diff --git a/.gitattributes b/.gitattributes index 98fc73819ca8d0524895145efdd9df8b42516579..40d118c02a791c510167e54d609c8143afab3612 100644 --- a/.gitattributes +++ b/.gitattributes @@ -35,3 +35,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text MonsterUI/content/MonsterUI/docs/favicon.ico filter=lfs diff=lfs merge=lfs -text MonsterUI/content/MonsterUI/docs/MonsterUI.jpg filter=lfs diff=lfs merge=lfs -text +MonsterUI/docs/favicon.ico filter=lfs diff=lfs merge=lfs -text +MonsterUI/docs/MonsterUI.jpg filter=lfs diff=lfs merge=lfs -text diff --git a/MonsterUI/.cursorrules b/MonsterUI/.cursorrules new file mode 100644 index 0000000000000000000000000000000000000000..b9b43bfadddc061ef727187836ae64074ebbda9e --- /dev/null +++ b/MonsterUI/.cursorrules @@ -0,0 +1 @@ +I am trying to make the python code as consistent with tailwind as possible. For example `large` should be abbreviated `lg` like in tailwind. \ No newline at end of file diff --git a/MonsterUI/.gitattributes b/MonsterUI/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..753b249880d57c22306cf155601bff986622b1a0 --- /dev/null +++ b/MonsterUI/.gitattributes @@ -0,0 +1 @@ +*.ipynb merge=nbdev-merge diff --git a/MonsterUI/.gitconfig b/MonsterUI/.gitconfig new file mode 100644 index 0000000000000000000000000000000000000000..9054574f90b84d27e89a016d7c76d5bdf7e479a4 --- /dev/null +++ b/MonsterUI/.gitconfig @@ -0,0 +1,11 @@ +# Generated by nbdev_install_hooks +# +# If you need to disable this instrumentation do: +# git config --local --unset include.path +# +# To restore: +# git config --local include.path ../.gitconfig +# +[merge "nbdev-merge"] + name = resolve conflicts with nbdev_fix + driver = nbdev_merge %O %A %B %P diff --git a/MonsterUI/.gitignore b/MonsterUI/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..28e3c79aca8ec9a23bf2895a796d0996faa2daf9 --- /dev/null +++ b/MonsterUI/.gitignore @@ -0,0 +1,167 @@ +tags +.sesskey +docs/static +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class +_docs/* +_proc/* +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +uv.lock + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +.idea/ diff --git a/MonsterUI/CHANGELOG.bak b/MonsterUI/CHANGELOG.bak new file mode 100644 index 0000000000000000000000000000000000000000..2bbdba9ca0c2da2ba058bc770a7cd06673646bba --- /dev/null +++ b/MonsterUI/CHANGELOG.bak @@ -0,0 +1,222 @@ +# Release notes + + + +## 1.0.28 + +### New Features + +- allow optional renderer ([#134](https://github.com/AnswerDotAI/MonsterUI/pull/134)) + +### Bugs Squashed + +- `render_md` doesn't render images with data uris when `img_dir` is set ([#132](https://github.com/AnswerDotAI/MonsterUI/issues/132)) + + +## 1.0.26 + +### Bugs Squashed + +- fix `render_md` non http/s urls ([#133](https://github.com/AnswerDotAI/MonsterUI/pull/133)), thanks to [@comhar](https://github.com/comhar) + + +## 1.0.25 + +### Bugs Squashed + +- remove modal on close ([#130](https://github.com/AnswerDotAI/MonsterUI/pull/130)), thanks to [@comhar](https://github.com/comhar) +- Buttons not working in Modal added to the DOM by HTMX. ([#126](https://github.com/AnswerDotAI/MonsterUI/issues/126)) + + +## 1.0.24 + +### New Features + +- use uikit to initialise and open modals inserted with htmx ([#127](https://github.com/AnswerDotAI/MonsterUI/pull/127)), thanks to [@comhar](https://github.com/comhar) + + +## 1.0.23 + +### Bugs Squashed + +- fragment md parsing does not work ([#124](https://github.com/AnswerDotAI/MonsterUI/issues/124)) +- llms.txt showing "internal server" errors ([#122](https://github.com/AnswerDotAI/MonsterUI/issues/122)) + + +## 1.0.22 + +- Create custom themes + +### Bugs Squashed + +- Unicode strings with encoding declaration are not supported ([#123](https://github.com/AnswerDotAI/MonsterUI/issues/123)) +- Update DropDownNavContainer class to remove unnecessary width class ([#114](https://github.com/AnswerDotAI/MonsterUI/pull/114)), thanks to [@ndendic](https://github.com/ndendic) +- fix font weight ordering ([#113](https://github.com/AnswerDotAI/MonsterUI/pull/113)), thanks to [@comhar](https://github.com/comhar) +- FieldSet inputs in Form are misaligned when monsterui is active ([#87](https://github.com/AnswerDotAI/MonsterUI/issues/87)) + + +## 1.0.21 + +### New Features + +- The new `ApexChart` component can create line charts, pie charts and [more](https://monsterui.answer.ai/api_ref/docs_charts). ([#110](https://github.com/AnswerDotAI/MonsterUI/pull/110)), thanks to [@ndendic](https://github.com/ndendic) +- Toasts now disappear automatically after 5 seconds. You can adjust the duration by using the `dur` field (e.g. `Toast('My Toast', dur=10.0)`). ([#109](https://github.com/AnswerDotAI/MonsterUI/pull/109)), thanks to [@comhar](https://github.com/comhar) + +### Breaking Change + +- Katex is no longer included in the default headers. To include it set `katex=True` when calling `.headers`. (i.e. `Theme.slate.headers(katex=True)`). ([#105](https://github.com/AnswerDotAI/MonsterUI/pull/105)), thanks to [@comhar](https://github.com/comhar) + + +## 1.0.20 + +### New Features + +- Add `icon` header param to optionally not bring in icons js lib ([#99](https://github.com/AnswerDotAI/MonsterUI/issues/99)) + +### Bugs Squashed + +- added fh. to unqid ([#98](https://github.com/AnswerDotAI/MonsterUI/pull/98)), thanks to [@MorsCerta-crypto](https://github.com/MorsCerta-crypto) + + +## 1.0.19 + +### New Features + +- Add accordion component ([#94](https://github.com/AnswerDotAI/MonsterUI/pull/94)), thanks to [@MichlF](https://github.com/MichlF) +- Fix theme logic ([#93](https://github.com/AnswerDotAI/MonsterUI/pull/93)), thanks to [@curtis-allan](https://github.com/curtis-allan) + + +## 1.0.18 + +- Hotfix accidental deletion of label select :( + + +## 1.0.16 + +### Bugs Squashed + +- Select not properly checking presence of hx-trigger + +## 1.0.14 + +### New Features + +- Move CDN's to jsdelivr ([#88](https://github.com/AnswerDotAI/MonsterUI/pull/88)), thanks to [@curtis-allan](https://github.com/curtis-allan) + +### Bugs Squashed + +- Select htmx compatibility bug +- SVG Path Name Collision Issue in MonsterUI ([#85](https://github.com/AnswerDotAI/MonsterUI/issues/85)) + + +## 1.0.13 + +### Bugs Squashed + +- LabelCheckboxX ignores id set manually ([#80](https://github.com/AnswerDotAI/MonsterUI/issues/80)) +- Select sending multiple values to HTMX + + +## 1.0.10 + +### New Features + +- Cusom Themes support in ThemePicker ([#71](https://github.com/AnswerDotAI/MonsterUI/pull/71)), thanks to [@ndendic](https://github.com/ndendic) + + +## 1.0.8 + +- Add lightbox and Insertable select + +## 1.0.7 + +### New Features + +- Add select kwargs to Select and LabelSelect ([#70](https://github.com/AnswerDotAI/MonsterUI/issues/70)) + +### Bugs Squashed + +- Update component classes to align with Franken UI v2.0 ([#67](https://github.com/AnswerDotAI/MonsterUI/pull/67)), thanks to [@Zaseem-BIsquared](https://github.com/Zaseem-BIsquared) +- Updated ContainerT, CardT, and TableT class names to match the documented patterns from Franken UI v2.0 docs + +## 1.0.6 + + +### Bugs Squashed + +- Update component classes to align with Franken UI v2.0 ([#67](https://github.com/AnswerDotAI/MonsterUI/pull/67)), thanks to [@Zaseem-BIsquared](https://github.com/Zaseem-BIsquared) + + +## 1.0.5 + +- Add Center component + +## 1.0.4 + +### New Features + +- Bug fix to correct theming conflict in theme initialization + + +## 1.0.2 + +- Bug fix to add dark mode theme selector to TW config, thanks to [@curtis-allan](https://github.com/curtis-allan) + +## 1.0.1 + +- Theme bug fix not allowing theme changes to stick, thanks to [@zaseem-bisquared](https://github.com/Zaseem-BIsquared) +- Documentation bug fix on tutorial app, thanks to [@decherd](https://github.com/decherd) + + +## 1.0.0 + +### New Features + +- Migrated to use FrankenUI version 2.0 version + +- Brand new simplified NavBar api, including enhanced sticky and scrollspy options, thanks to [@ohmeow](https://github.com/ohmeow) and [@curtis-allan](https://github.com/curtis-allan) + +- Latex rendering enabled via katex ([#58](https://github.com/AnswerDotAI/MonsterUI/pull/58)), thanks to [@algal](https://github.com/algal) + +- Add API References and Guides to llms.txt ([#54](https://github.com/AnswerDotAI/MonsterUI/issues/54)) + +- New Range component, which includes min/max range + +- New center component thanks to inspiration from Carson of HTMX ([#52](https://github.com/AnswerDotAI/MonsterUI/issues/52)) + +- Better Theme Picker ([#51](https://github.com/AnswerDotAI/MonsterUI/issues/51)) + +- Upload Zone and Upload Button Components added ([#50](https://github.com/AnswerDotAI/MonsterUI/issues/50)) + +### Bugs Squashed + +- fix: correct PaddingT class naming for padding variants ([#55](https://github.com/AnswerDotAI/MonsterUI/pull/55)), thanks to [@Zaseem-BIsquared](https://github.com/Zaseem-BIsquared) + + +## 0.0.34 + + +### Bugs Squashed + +- Table markdown rendering bug fix ([#46](https://github.com/AnswerDotAI/MonsterUI/issues/46)) + + +## 0.0.33 + +### New Features + +- Add subtitle function for common semantic styling option ([#44](https://github.com/AnswerDotAI/MonsterUI/pull/44)) + +- Add semantic text styling to docs examples ([#42](https://github.com/AnswerDotAI/MonsterUI/pull/42)) + +- Created higher level Navbars function for auto-responsive collapse to mobile and easier interface ([#33](https://github.com/AnswerDotAI/MonsterUI/issues/33)), thanks to @curtis-allan + +- Added Scrollspy to Nav and NavBar and example that demonstrates it ([#31](https://github.com/AnswerDotAI/MonsterUI/issues/31)), thanks to @99ch + +- Added Highlight JS integration to headers ([#28](https://github.com/AnswerDotAI/MonsterUI/issues/28)), thanks to @99ch + +### Bugs Squashed + +- Improve defaults for Navbar when components are passed so it doesn't override styling specified toby user ([#43](https://github.com/AnswerDotAI/MonsterUI/pull/43)) + + diff --git a/MonsterUI/CHANGELOG.md b/MonsterUI/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..76c52c62bae254fd3bad420544ba2172ca2db015 --- /dev/null +++ b/MonsterUI/CHANGELOG.md @@ -0,0 +1,229 @@ +# Release notes + + + +## 1.0.29 + +### Bugs Squashed + +- `apply_classes` wraps some elements in html/body/head tags ([#135](https://github.com/AnswerDotAI/MonsterUI/issues/135)) + + +## 1.0.28 + +### New Features + +- allow optional renderer ([#134](https://github.com/AnswerDotAI/MonsterUI/pull/134)) + +### Bugs Squashed + +- `render_md` doesn't render images with data uris when `img_dir` is set ([#132](https://github.com/AnswerDotAI/MonsterUI/issues/132)) + + +## 1.0.26 + +### Bugs Squashed + +- fix `render_md` non http/s urls ([#133](https://github.com/AnswerDotAI/MonsterUI/pull/133)), thanks to [@comhar](https://github.com/comhar) + + +## 1.0.25 + +### Bugs Squashed + +- remove modal on close ([#130](https://github.com/AnswerDotAI/MonsterUI/pull/130)), thanks to [@comhar](https://github.com/comhar) +- Buttons not working in Modal added to the DOM by HTMX. ([#126](https://github.com/AnswerDotAI/MonsterUI/issues/126)) + + +## 1.0.24 + +### New Features + +- use uikit to initialise and open modals inserted with htmx ([#127](https://github.com/AnswerDotAI/MonsterUI/pull/127)), thanks to [@comhar](https://github.com/comhar) + + +## 1.0.23 + +### Bugs Squashed + +- fragment md parsing does not work ([#124](https://github.com/AnswerDotAI/MonsterUI/issues/124)) +- llms.txt showing "internal server" errors ([#122](https://github.com/AnswerDotAI/MonsterUI/issues/122)) + + +## 1.0.22 + +- Create custom themes + +### Bugs Squashed + +- Unicode strings with encoding declaration are not supported ([#123](https://github.com/AnswerDotAI/MonsterUI/issues/123)) +- Update DropDownNavContainer class to remove unnecessary width class ([#114](https://github.com/AnswerDotAI/MonsterUI/pull/114)), thanks to [@ndendic](https://github.com/ndendic) +- fix font weight ordering ([#113](https://github.com/AnswerDotAI/MonsterUI/pull/113)), thanks to [@comhar](https://github.com/comhar) +- FieldSet inputs in Form are misaligned when monsterui is active ([#87](https://github.com/AnswerDotAI/MonsterUI/issues/87)) + + +## 1.0.21 + +### New Features + +- The new `ApexChart` component can create line charts, pie charts and [more](https://monsterui.answer.ai/api_ref/docs_charts). ([#110](https://github.com/AnswerDotAI/MonsterUI/pull/110)), thanks to [@ndendic](https://github.com/ndendic) +- Toasts now disappear automatically after 5 seconds. You can adjust the duration by using the `dur` field (e.g. `Toast('My Toast', dur=10.0)`). ([#109](https://github.com/AnswerDotAI/MonsterUI/pull/109)), thanks to [@comhar](https://github.com/comhar) + +### Breaking Change + +- Katex is no longer included in the default headers. To include it set `katex=True` when calling `.headers`. (i.e. `Theme.slate.headers(katex=True)`). ([#105](https://github.com/AnswerDotAI/MonsterUI/pull/105)), thanks to [@comhar](https://github.com/comhar) + + +## 1.0.20 + +### New Features + +- Add `icon` header param to optionally not bring in icons js lib ([#99](https://github.com/AnswerDotAI/MonsterUI/issues/99)) + +### Bugs Squashed + +- added fh. to unqid ([#98](https://github.com/AnswerDotAI/MonsterUI/pull/98)), thanks to [@MorsCerta-crypto](https://github.com/MorsCerta-crypto) + + +## 1.0.19 + +### New Features + +- Add accordion component ([#94](https://github.com/AnswerDotAI/MonsterUI/pull/94)), thanks to [@MichlF](https://github.com/MichlF) +- Fix theme logic ([#93](https://github.com/AnswerDotAI/MonsterUI/pull/93)), thanks to [@curtis-allan](https://github.com/curtis-allan) + + +## 1.0.18 + +- Hotfix accidental deletion of label select :( + + +## 1.0.16 + +### Bugs Squashed + +- Select not properly checking presence of hx-trigger + +## 1.0.14 + +### New Features + +- Move CDN's to jsdelivr ([#88](https://github.com/AnswerDotAI/MonsterUI/pull/88)), thanks to [@curtis-allan](https://github.com/curtis-allan) + +### Bugs Squashed + +- Select htmx compatibility bug +- SVG Path Name Collision Issue in MonsterUI ([#85](https://github.com/AnswerDotAI/MonsterUI/issues/85)) + + +## 1.0.13 + +### Bugs Squashed + +- LabelCheckboxX ignores id set manually ([#80](https://github.com/AnswerDotAI/MonsterUI/issues/80)) +- Select sending multiple values to HTMX + + +## 1.0.10 + +### New Features + +- Cusom Themes support in ThemePicker ([#71](https://github.com/AnswerDotAI/MonsterUI/pull/71)), thanks to [@ndendic](https://github.com/ndendic) + + +## 1.0.8 + +- Add lightbox and Insertable select + +## 1.0.7 + +### New Features + +- Add select kwargs to Select and LabelSelect ([#70](https://github.com/AnswerDotAI/MonsterUI/issues/70)) + +### Bugs Squashed + +- Update component classes to align with Franken UI v2.0 ([#67](https://github.com/AnswerDotAI/MonsterUI/pull/67)), thanks to [@Zaseem-BIsquared](https://github.com/Zaseem-BIsquared) +- Updated ContainerT, CardT, and TableT class names to match the documented patterns from Franken UI v2.0 docs + +## 1.0.6 + + +### Bugs Squashed + +- Update component classes to align with Franken UI v2.0 ([#67](https://github.com/AnswerDotAI/MonsterUI/pull/67)), thanks to [@Zaseem-BIsquared](https://github.com/Zaseem-BIsquared) + + +## 1.0.5 + +- Add Center component + +## 1.0.4 + +### New Features + +- Bug fix to correct theming conflict in theme initialization + + +## 1.0.2 + +- Bug fix to add dark mode theme selector to TW config, thanks to [@curtis-allan](https://github.com/curtis-allan) + +## 1.0.1 + +- Theme bug fix not allowing theme changes to stick, thanks to [@zaseem-bisquared](https://github.com/Zaseem-BIsquared) +- Documentation bug fix on tutorial app, thanks to [@decherd](https://github.com/decherd) + + +## 1.0.0 + +### New Features + +- Migrated to use FrankenUI version 2.0 version + +- Brand new simplified NavBar api, including enhanced sticky and scrollspy options, thanks to [@ohmeow](https://github.com/ohmeow) and [@curtis-allan](https://github.com/curtis-allan) + +- Latex rendering enabled via katex ([#58](https://github.com/AnswerDotAI/MonsterUI/pull/58)), thanks to [@algal](https://github.com/algal) + +- Add API References and Guides to llms.txt ([#54](https://github.com/AnswerDotAI/MonsterUI/issues/54)) + +- New Range component, which includes min/max range + +- New center component thanks to inspiration from Carson of HTMX ([#52](https://github.com/AnswerDotAI/MonsterUI/issues/52)) + +- Better Theme Picker ([#51](https://github.com/AnswerDotAI/MonsterUI/issues/51)) + +- Upload Zone and Upload Button Components added ([#50](https://github.com/AnswerDotAI/MonsterUI/issues/50)) + +### Bugs Squashed + +- fix: correct PaddingT class naming for padding variants ([#55](https://github.com/AnswerDotAI/MonsterUI/pull/55)), thanks to [@Zaseem-BIsquared](https://github.com/Zaseem-BIsquared) + + +## 0.0.34 + + +### Bugs Squashed + +- Table markdown rendering bug fix ([#46](https://github.com/AnswerDotAI/MonsterUI/issues/46)) + + +## 0.0.33 + +### New Features + +- Add subtitle function for common semantic styling option ([#44](https://github.com/AnswerDotAI/MonsterUI/pull/44)) + +- Add semantic text styling to docs examples ([#42](https://github.com/AnswerDotAI/MonsterUI/pull/42)) + +- Created higher level Navbars function for auto-responsive collapse to mobile and easier interface ([#33](https://github.com/AnswerDotAI/MonsterUI/issues/33)), thanks to @curtis-allan + +- Added Scrollspy to Nav and NavBar and example that demonstrates it ([#31](https://github.com/AnswerDotAI/MonsterUI/issues/31)), thanks to @99ch + +- Added Highlight JS integration to headers ([#28](https://github.com/AnswerDotAI/MonsterUI/issues/28)), thanks to @99ch + +### Bugs Squashed + +- Improve defaults for Navbar when components are passed so it doesn't override styling specified toby user ([#43](https://github.com/AnswerDotAI/MonsterUI/pull/43)) + + diff --git a/MonsterUI/CONTRIBUTING.md b/MonsterUI/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..649dda863ae4345041ad9646771128639c30d739 --- /dev/null +++ b/MonsterUI/CONTRIBUTING.md @@ -0,0 +1,27 @@ +# CONTRIBUTING + +## Library Contributions + +> The code for all components in the library in the Jupyter notebooks (.ipynb files). Edit those, not the .py files. + +This is an [nbdev](https://nbdev.fast.ai/) library. The notebooks are located in `nbs`. + +### Exporting the Modules + +You can use `nbdev_export` to export the notebooks to the library directory, `monsterui`. + +### Cleaning NB metadad + +You can use `nbdev_clean` to clean the nb metadata from the .py files. + +## Docs Contributions + +The docs are run using [FastHTML](https://fastht.ml/) and can be run locally with: + +```bash +cd docs +pip install -r requirements.txt +python main.py +``` + +This will start up the MonsterUI documentation site, which is a FastHTML app. Then you can see the site locally at http://localhost:5001/ diff --git a/MonsterUI/LICENSE b/MonsterUI/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..3b106e87c0610102b42d042be9c79bc967c84503 --- /dev/null +++ b/MonsterUI/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022, fastai + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MonsterUI/MANIFEST.in b/MonsterUI/MANIFEST.in new file mode 100644 index 0000000000000000000000000000000000000000..5c0e7ced193cb35aee60cbadc3e022a1da0fd8cc --- /dev/null +++ b/MonsterUI/MANIFEST.in @@ -0,0 +1,5 @@ +include settings.ini +include LICENSE +include CONTRIBUTING.md +include README.md +recursive-exclude * __pycache__ diff --git a/MonsterUI/README.md b/MonsterUI/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f92a81ed69f3c89cabe4ee401bc30e9defd70a64 --- /dev/null +++ b/MonsterUI/README.md @@ -0,0 +1,99 @@ +# MonsterUI + +MonsterUI is a UI framework for FastHTML for building beautiful web interfaces with minimal code. It combines the simplicity of Python with the power of Tailwind. Perfect for data scientists, ML engineers, and developers who want to quickly turn their Python code into polished web apps without the complexity of traditional UI frameworks. Follows semantic HTML patterns when possible. + +MonsterUI adds the following Tailwind-based libraries [Franken UI](https://franken-ui.dev/) and [DaisyUI](https://daisyui.com/) to FastHTML, as well as Python's [Mistletoe](https://github.com/miyuchina/mistletoe) for Markdown, [HighlightJS](https://highlightjs.org/) for code highlighting, and [Katex](https://katex.org/) for latex support. + +# Getting Started + + +## Installation + +To install this library, uses + +`pip install MonsterUI` + +## Getting Started + +### TLDR + +Run `python file.py` on this to start: + +``` python +from fasthtml.common import * +from monsterui.all import * + +# Choose a theme color (blue, green, red, etc) +hdrs = Theme.blue.headers() + +# Create your app with the theme +app, rt = fast_app(hdrs=hdrs) + +@rt +def index(): + socials = (('github','https://github.com/AnswerDotAI/MonsterUI'), + ('twitter','https://twitter.com/isaac_flath/'), + ('linkedin','https://www.linkedin.com/in/isaacflath/')) + return Titled("Your First App", + Card( + H1("Welcome!"), + P("Your first MonsterUI app", cls=TextPresets.muted_sm), + P("I'm excited to see what you build with MonsterUI!"), + footer=DivLAligned(*[UkIconLink(icon,href=url) for icon,url in socials]))) + +serve() +``` + +## LLM context files + +Using LLMs for development is a best practice way to get started and +explore. While LLMs cannot code for you, they can be helpful assistants. +You must check, refactor, test, and vet any code any LLM generates for +you - but they are helpful productivity tools. Take a look inside the +`llms.txt` file to see links to particularly useful context files! + +- [llms.txt](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/llms.txt): Links to what is included +- [llms-ctx.txt](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/llms-ctx.txt): MonsterUI Documentation Pages +- [API list](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/apilist.txt): API list for MonsterUI (included in llms-ctx.txt) +- [llms-ctx-full.txt](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/llms-ctx-full.txt): Full context that includes all api reference pages as markdown + +In addition you can add `/md` (for markdown) to a url to get a markdown representation and `/rmd` for rendered markdown representation (nice for looking to see what would be put into context. + +### Step by Step + +To get started, check out: + +1. Start by importing the modules as follows: + +``` python +from fasthtml.common import * +from monsterui.all import * +``` + +2. Instantiate the app with the MonsterUI headers + +``` python +app = FastHTML(hdrs=Theme.blue.headers()) + +# Alternatively, using the fast_app method +app, rt = fast_app(hdrs=Theme.slate.headers()) +``` + +> *The color option can be any of the theme options available out of the +> box* + +> `katex` and `highlightjs` are not included by default. To include them set `katex=True` or `highlightjs=True` when calling `.headers`. (i.e. `Theme.slate.headers(katex=True)`)* + +From here, you can explore the API Reference & examples to see how to +implement the components. You can also check out these demo videos to as +a quick start guide: + +- MonsterUI [documentation page and Tutorial + app](https://monsterui.answer.ai/tutorial_app) +- Isaac & Hamel : [Building his website’s team + page](https://youtu.be/22Jn46-mmM0) +- Isaac & Audrey : [Building a blog](https://youtu.be/gVWAsywxLXE) +- Isaac : [Building a blog](https://youtu.be/22NJgfAqgko) + +More resources and improvements to the documentation will be added here +soon! diff --git a/MonsterUI/__pycache__/testnavbar.cpython-312.pyc b/MonsterUI/__pycache__/testnavbar.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9adc9a16db78bb292c00e8bf646e438f87baf119 Binary files /dev/null and b/MonsterUI/__pycache__/testnavbar.cpython-312.pyc differ diff --git a/MonsterUI/docs/.plash b/MonsterUI/docs/.plash new file mode 100644 index 0000000000000000000000000000000000000000..7a066597c5216af0373fba21d76fab2c38c49bf8 --- /dev/null +++ b/MonsterUI/docs/.plash @@ -0,0 +1 @@ +export PLASH_APP_NAME=monsterui.answer.ai diff --git a/MonsterUI/docs/MonsterUI.jpg b/MonsterUI/docs/MonsterUI.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eb5035155953aee57be89d5e38c12279c44e7c97 --- /dev/null +++ b/MonsterUI/docs/MonsterUI.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a18a9096a684140dade9be4e90b1cac0d65f395f04c9dc504502ed7d19735ac +size 717834 diff --git a/MonsterUI/docs/api_reference/api_reference.py b/MonsterUI/docs/api_reference/api_reference.py new file mode 100644 index 0000000000000000000000000000000000000000..57b3c330e48b79897d704d0c7dd62c989cf01652 --- /dev/null +++ b/MonsterUI/docs/api_reference/api_reference.py @@ -0,0 +1,1211 @@ +"""Reference to all FrankenUI Components""" + +from fasthtml.common import * +from monsterui.all import * +# from nbdev.showdoc import * +from utils import create_flippable_card, fn2code_string +from enum import EnumType +from collections.abc import Callable + +''' +Any variable starting with docs_ is a function that generates a section of the API reference. + +These are automatically added to the docs sidebar so you don't have to do anything other than add the function using create_doc_section. +''' +from inspect import signature, getdoc, getsourcefile, getsourcelines + +# Utilities +def get_github_url(func): + "Create GitHub URL for function, assuming AnswerDotAI/MonsterUI repo" + file = getsourcefile(func).split('MonsterUI/')[-1] + line = getsourcelines(func)[-1] + file = file.replace('/opt/venv/lib/python3.12/site-packages/','') + return f"https://github.com/AnswerDotAI/MonsterUI/blob/main/{file}#L{line}" + +def get_github_url(func): + "Create GitHub URL for function, assuming AnswerDotAI/MonsterUI repo" + try: + file = getsourcefile(func) + line = getsourcelines(func)[-1] + + # Get path after monsterui/ (case insensitive) + file = file.lower() + if 'monsterui/' in file: + file = file.split('monsterui/')[-1] + elif 'site-packages/' in file: + file = file.split('site-packages/')[-1] + + return f"https://github.com/AnswerDotAI/MonsterUI/blob/main/monsterui/{file}#L{line}" + except: + return None + +from fastcore.docments import docments, docstring, get_name +def show_doc(func) -> str: + "Convert a Google-style docstring to markdown" + params = docments(func, args_kwargs=True) + funcname = get_name(func) + doc = docstring(func) + par, ret = None, None + if params: + par = Div(Strong('Params'), + Ul(*[Li(render_md(f"`{name}` {desc if desc else ''}",class_map_mods={'p':'leading-relaxed'}), cls='') for name, desc in params.items() if name != 'return'], cls='uk-list-disc space-y-2 mb-6 ml-6')) + if 'return' in params and params['return']: ret = render_md(f"**Returns:** {params['return']}") + return Div( + DivFullySpaced( + render_md(f"### {funcname}"), + A("Source", href=get_github_url(func), cls='text-primary hover:text-primary-focus underline')), + Pre(Code(f"{funcname}{signature(func)}", + cls='hljs language-python px-1 block overflow-x-auto'), + cls='bg-base-200 rounded-lg p-4 mb-6'), + Div(Blockquote(render_md(doc), cls='pl-4 border-l-4 border-primary mb-6'), par, ret, cls='ml-10')) + +def enum_to_html_table(enum_class): + "Creates a compact multi-column table display for enum documentation" + items = list(enum_class.__members__.items()) + n_cols = min(4, max(2, round((len(items) ** 0.5)))) + + # Create header/cell pairs with borders + def make_pair(opt, val, i): + border = 'border-l border-base-300 pl-4' if i > 0 else '' + return [Th('Option', cls=border), Th('Value')] if opt == 'header' else [Td(opt, cls=border), Td(val)] + + # Build rows with padding for incomplete final row + rows = [] + for i in range(0, len(items), n_cols): + cells = [] + for j in range(n_cols): + name, val = items[i + j] if i + j < len(items) else ('', '') + cells.extend(make_pair(name, val.value if val else '', j)) + rows.append(Tr(*cells)) + + return Div( + Hr(cls='uk-divider-icon my-2'), + DivFullySpaced(H3(enum_class.__name__, cls='my-2'), P(I(enum_class.__doc__), cls='text-sm')), + Table( + Thead(Tr(*make_pair('header', '', 0) * n_cols)), + Tbody(*rows), + cls=(TableT.hover, 'uk-table-small uk-table-justify uk-table-middle'))) + +def render_content(c): + "Renders content by type" + if isinstance(c, str): return render_md(c) # Strings are rendered as markdown + elif isinstance(c, EnumType): return enum_to_html_table(c) # Enums are rendered as tables + elif isinstance(c, FT): return c # FastHTML tags are rendered as themselves + elif isinstance(c, tuple): # Tuples are rendered as cards with source and output that can be flipped + extra_cls = c[2] if len(tuple(c)) == 3 else None + return create_flippable_card(c[0], c[1], extra_cls) + elif isinstance(c, Callable): # Callables are rendered as documentation via show_doc + return show_doc(c) + # _html = show_doc(c, renderer=BasicHtmlRenderer)._repr_html_() + # return NotStr(apply_classes(_html, class_map_mods={"table":'uk-table uk-table-hover uk-table-small'})) + else: return c + +def create_doc_section(*content, title): + return lambda: Div(Container(*map(render_content, content))) + +def string2code_string(code: str) -> tuple: return eval(code), code + +# Sliders + +def ex_sliders_1(): + return Slider(*[Img(src=f'https://picsum.photos/200/200?random={i}') for i in range(10)]) + +def ex_sliders_2(): + def _card(i): return Card(H3(f'Card {i}'), P(f'Card {i} content')) + return Slider(*[_card(i) for i in range(10)]) + +def ex_sliders_3(): + def _card(i): return Card(H3(f'Card {i}'), P(f'Card {i} content')) + return Slider(*[_card(i) for i in range(10)], items_cls='gap-10', uk_slider='autoplay: true; autoplay-interval: 1000') + +docs_sliders = create_doc_section( + H1("Carousel Sliders API Reference"), + "Here is a simple example of a slider:", + fn2code_string(ex_sliders_1), + "Here is a slider with cards:", + fn2code_string(ex_sliders_2), + "Here is a slider with cards and autoplay:", + fn2code_string(ex_sliders_3), + "Typically you want to use the `Slider` component, but if you need more control you can use the `SliderContainer`, `SliderItems`, and `SliderNav` components.", + Slider, + SliderContainer, + SliderItems, + SliderNav, + title="Sliders") + +# Accordions + +def ex_accordion_1(): + return Div( + H2("Accordion Header"), + Accordion( + AccordionItem( + "Section 1", + P("Content for the first section."), + P("More content here."), + ), + AccordionItem( + "Section 2", + P("Content for the second section."), + Label("A label inside!"), + li_kwargs={"id": "section-2"}, + ), + AccordionItem( + "Section 3 - The last one!", P("Content for the third section.") + ), + multiple=False, + animation=True, + ), + ), + +def ex_accordion_2(): + return Div( + H2("Accordion Header"), + Accordion( + AccordionItem( + "Section 1", + P("Content for the first section."), + P("More content here."), + open=True, + ), + AccordionItem( + "Section 2", + P("Content for the second section."), + Label("A label inside!"), + li_kwargs={"id": "section-2"}, + ), + AccordionItem( + "Section 3 - The last one!", P("Content for the third section.") + ), + multiple=True, + animation=True, + ), + ), + +def ex_accordion_3(): + return Div( + H2("Accordion Header"), + Accordion( + AccordionItem( + "Section 1", + P("Content for the first section."), + P("More content here."), + ), + AccordionItem( + "Section 2", + P("Content for the second section."), + Label("A label inside!"), + li_kwargs={"id": "section-2"}, + ), + AccordionItem( + "Section 3 - The last one!", P("Content for the third section.") + ), + multiple=False, + animation=False, + ), + ), + +docs_accordion_link = create_doc_section( + H1("Accordion API Reference"), + Div(id='accordion'), # for linking to in release post + H3("Example Accordions"), + P("A simple accordion with fluid collapsing and expanding animation where only a single Section can be exanded at any time."), + fn2code_string(ex_accordion_1), + P("An accordion with fluid collapsing and expanding animation where one section is already expanded at startup and multiple section can be expanded at any time."), + fn2code_string(ex_accordion_2), + P("An accordion with no collapsing and expanding animation where only a single Section can be exanded at any time."), + fn2code_string(ex_accordion_3), + H3("API Reference"), + Accordion, + AccordionItem, + title="Accordion") + +# Buttons + +def ex_buttons(): + return Grid( + Button("Default"), + Button("Primary", cls=ButtonT.primary), + Button("Secondary", cls=ButtonT.secondary), + Button("Danger", cls=ButtonT.destructive), + Button("Text", cls=ButtonT.text), + Button("Link", cls=ButtonT.link), + Button("Ghost", cls=ButtonT.ghost), + ) + +def ex_links(): + return Div(cls='space-x-4')( + A('Default Link'), + A('Muted Link', cls=AT.muted), + A('Text Link', cls=AT.text), + A('Reset Link', cls=AT.reset), + A('Primary Link', cls=AT.primary), + A('Classic Link', cls=AT.classic),) + +docs_button_link = create_doc_section( + H1("Buttons & Links API Reference"), + Div(id='button'), # for linking to in release post + fn2code_string(ex_buttons), + fn2code_string(ex_links), + Button, + ButtonT, + AT, + title="Buttons & Links") + +# Theme + +def ex_theme_switcher(): + return ThemePicker() + +docs_theme_headers = create_doc_section( + H1("Theme and Headers API Reference"), + """ + To get headers with a default theme use `hdrs=Theme..headers()`. For example for the blue theme you would use `hdrs=Theme.blue.headers()`. The theme integrated together different frameworks and allows tailwind, FrankenUI, HighlighJS, and DaisyUI components to work well together. + + Tailwind, FrankenUI and DaisyUI are imported by default. You must use DaisyUI headers to use anything in the `daisy` module, and FrankenUI headers to use anything in the `franken` module. + + HighlightJS is not added by default, but you can add it by setting `highlightjs=True` in the headers function. The `render_md` function will use HighlightJS for code blocks. + + Theme options are:""", + Card(Grid(map(P,Theme)),cls='mb-8'), + H3("Theme Picker", id='theme'), + fn2code_string(ex_theme_switcher), + ThemePicker, + H3("Custom Themes"), + render_md(""" +1. You can use [this theme](https://github.com/AnswerDotAI/MonsterUI/blob/main/docs/custom_theme.css) as a starting point. +2. Add the theme to your headers as a link like this `Link(rel="stylesheet", href="/custom_theme.css", type="text/css")` +3. Then add the theme to the `ThemePicker` component. For example `ThemePicker(custom_themes=[('Grass', '#10b981')])` +"""), + "Themes are controlled with `bg-background text-foreground` classes on the `Body` tag. `fast_app` and `FastHTML` will do this for you automatically so you typically do not have to do anything", + fast_app, + FastHTML, + + Blockquote(P("Users have said ", A("this site", href="https://ui.jln.dev/"), " is helpful in creating your own themes.")), + + title="Headers") + +# Typography + +def ex_headings(): + return Div( + Titled("Titled"), + H1("Level 1 Heading (H1)"), + H2("Level 2 Heading (H2)"), + H3("Level 3 Heading (H3)"), + H4("Level 4 Heading (H4)"), + H5("Level 5 Heading (H5)"), + H6("Level 6 Heading (H6)"), + ) + + +def ex_semantic_elements(): + return Div( + H2("Semantic HTML Elements Demo"), + # Text formatting examples + P("Here's an example of ", Em("emphasized (Em)"), " and ", Strong("strong (Strong)"), " text."), + P("Some ", I("italic text (I)"), " and ", Small("smaller text (Small)"), " in a paragraph."), + P("You can ", Mark("highlight (Mark)"), " text, show ", Del("deleted (Del)"), " and ", + Ins("inserted (Ins)"), " content."), + P("Chemical formulas use ", Sub("subscripts (Sub)"), " and ", Sup("superscripts (Sup)"), + " like H", Sub("2"), "O."), + # Quote examples + Blockquote( + P("The only way to do great work is to love what you do."), + Cite("Steve Jobs (Cite)")), + P("As Shakespeare wrote, ", Q("All the world's a stage (Q)"), "."), + # Time and Address + P("Posted on ", Time("2024-01-29", datetime="2024-01-29")), + Address( + "Mozilla Foundation (Address)", + Br(), + "331 E Evelyn Ave (Address)", + Br(), + "Mountain View, CA 94041 (Address)", + Br(), + "USA (Address)"), + # Technical and definition examples + P( + Dfn("HTML (Dfn)"), " (", + Abbr("HyperText Markup Language (Abbr)", title="HyperText Markup Language"), + ") is the standard markup language for documents designed to be displayed in a web browser."), + P("Press ", Kbd("Ctrl (Kbd)"), " + ", Kbd("C (Kbd)"), " to copy."), + P("The command returned: ", Samp("Hello, World! (Samp)")), + P("Let ", Var("x (Var)"), " be the variable in the equation."), + # Figure with caption + Figure( + PicSumImg(), + Caption("Figure 1: An example image with caption (Caption)")), + # Interactive elements + Details( + Summary("Click to show more information (Summary)"), + P("This is the detailed content that is initially hidden (P)")), + # Data representation + P( + Data("123 (Data)", value="123"), " is a number, and here's a Meter showing progress: ", + Meter(value=0.6, min=0, max=1)), + P( + "Temperature: ", + Meter(value=-1, min=-10, max=40, low=0, high=30, optimum=21), + " (with low/high/optimum values)"), + P( + Data("€42.00", value="42"), + " - price example with semantic value"), + # Output example + P("Form calculation result: ", Output("The sum is 42 (Output)", form="calc-form", for_="num1 num2")), + # Meta information example + Section( + H3("Blog Post Title (H3)"), + Small("By John Doe • 5 min read (Small)"), + P("Article content here...")), + # Text decoration examples + P("This text has ",U("proper name annotation (U)"), " and this is ",S("outdated information (S)"), " that's been superseded."), + cls='space-y-4' + ) + + +def ex_textpresets(): + return Grid(*[Div(P(f"This is {preset.name} text", cls=preset.value)) for preset in TextPresets]) + +def ex_textt(): + return Grid(*[Div(P(f"This is {s.name} text", cls=s.value)) for s in TextT]) + +def ex_other(): + return Div( + CodeSpan("This is a CodeSpan element"), + Blockquote("This is a blockquote element"), + CodeBlock("#This is a CodeBlock element\n\ndef add(a,b): return a+b")) + +docs_typography = create_doc_section( + H1("Typography API Reference"), + P("Ready to go semantic options that cover most of what you need based on the HTML spec"), + fn2code_string(ex_headings), + fn2code_string(ex_semantic_elements), + fn2code_string(ex_other), + P("Styling text is possibly the most common style thing to do, so we have a couple of helpers for discoverability inside python. `TextPresets` is intended to be combinations are are widely applicable and used often, where `TextT` is intended to be more flexible options for you to combine together yourself."), + H5("TextPresets.*"), + fn2code_string(ex_textpresets), + H5("TextT.*"), + fn2code_string(ex_textt), + H3("API Reference"), + TextPresets, + TextT, + H1, H2, H3, H4, H5, H6, + CodeSpan, Blockquote, CodeBlock, + Em, Strong, I, Small, Mark, Sub, Sup, Del, Ins, + Dfn, Abbr, Q, Kbd, Samp, Var, + Figure, Caption, + Details, Summary, + Meter, Data, Output, + Address, Time, + title="Text Style") + + +# Notifications +def ex_alerts1(): return Alert("This is a plain alert") + +def ex_alerts2(): return Alert("Your purchase has been confirmed!", cls=AlertT.success) + +def ex_alerts3(): + return Alert( + DivLAligned(UkIcon('triangle-alert'), + P("Please enter a valid email.")), + cls=AlertT.error) + +def ex_toasts1(): + return Toast("First Example Toast", cls=(ToastHT.start, ToastVT.bottom), dur=300) + +def ex_toasts2(): + return Toast("Second Example Toast", alert_cls=AlertT.info, dur=300) + +docs_notifications = create_doc_section( + H1("Alerts & Toasts API Reference"), + H3("Alerts"), + P("The simplest alert is a div wrapped with a span:"), + fn2code_string(ex_alerts1), + P("Alert colors are defined by the alert styles:"), + fn2code_string(ex_alerts2), + P("It often looks nice to use icons in alerts: "), + fn2code_string(ex_alerts3), + Alert, AlertT, + DividerLine(), + H3("Toasts"), + P("To define a toast with a particular location, add horizontal or vertical toast type classes:"), + fn2code_string(ex_toasts1), + P("To define toast colors, set the class of the alert wrapped by the toast:"), + fn2code_string(ex_toasts2), + P("Toasts will disappear automatically after 5 seconds. To change the duration of the toast set the `dur` param like this `Toast('Content', dur=10)`."), + P("Here's a demo ", A("app", href="https://gallery.fastht.ml/split/dynamic_user_interface_(htmx)/toast", target="_blank", rel="noopener noreferrer", cls='underline'), " showing how to trigger a toast.", cls='mt-4'), + Toast, ToastHT, ToastVT, + title="Alerts & Toasts") + +# Containers + +def ex_articles(): + return Article( + ArticleTitle("Sample Article Title"), + Subtitle("By: John Doe"), + P('lorem ipsum dolor sit amet consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.')) + +def ex_containers(): + return Container( + "This is a sample container with custom styling.", + cls=ContainerT.xs, + style="background-color: #FFA500; color: #000000") + + +docs_containers = create_doc_section( + H1("Articles, Containers & Sections API Reference"), + ArticleMeta, + ArticleTitle, + Article, + fn2code_string(ex_articles), + Container, + ContainerT, + fn2code_string(ex_containers), + Section, + SectionT, + title="Articles, Containers & Sections" +) + +# Cards + +def ex_card(): + return Card( + Form(LabelInput("Input"), + LabelRange("Range")), + header=Div( + CardTitle("Header"), + P("A card with header and footer",cls=TextPresets.muted_sm)), + footer=DivLAligned(Button("Footer Submit Button"))) + + + +def Tags(cats): return Div(cls='space-x-2')(map(Label, cats)) + +def ex_card2_wide(): + def Tags(cats): return DivLAligned(map(Label, cats)) + + return Card( + DivLAligned( + A(Img(src="https://picsum.photos/200/200?random=12", style="width:200px"),href="#"), + Div(cls='space-y-3 uk-width-expand')( + H4("Creating Custom FastHTML Tags for Markdown Rendering"), + P("A step by step tutorial to rendering markdown in FastHTML using zero-md inside of DaisyUI chat bubbles"), + DivFullySpaced(map(Small, ["Isaac Flath", "20-October-2024"]), cls=TextT.muted), + DivFullySpaced( + Tags(["FastHTML", "HTMX", "Web Apps"]), + Button("Read", cls=(ButtonT.primary,'h-6'))))), + cls=CardT.hover) + +def ex_card2_tall(): + def Tags(cats): return DivLAligned(map(Label, cats)) + + return Card( + Div( + A(Img(src="https://picsum.photos/400/200?random=14"), href="#"), + Div(cls='space-y-3 uk-width-expand')( + H4("Creating Custom FastHTML Tags for Markdown Rendering"), + P("A step by step tutorial to rendering markdown in FastHTML using zero-md inside of DaisyUI chat bubbles"), + DivFullySpaced(map(Small, ["Isaac Flath", "20-October-2024"]), cls=TextT.muted), + DivFullySpaced( + Tags(["FastHTML", "HTMX", "Web Apps"]), + Button("Read", cls=(ButtonT.primary,'h-6'))))), + cls=CardT.hover) + +def ex_card3(): + def team_member(name, role, location="Remote"): + return Card( + DivLAligned( + DiceBearAvatar(name, h=24, w=24), + Div(H3(name), P(role))), + footer=DivFullySpaced( + DivHStacked(UkIcon("map-pin", height=16), P(location)), + DivHStacked(*(UkIconLink(icon, height=16) for icon in ("mail", "linkedin", "github"))))) + team = [ + team_member("Sarah Chen", "Engineering Lead", "San Francisco"), + team_member("James Wilson", "Senior Developer", "New York"), + team_member("Maria Garcia", "UX Designer", "London"), + team_member("Alex Kumar", "Product Manager", "Singapore"), + team_member("Emma Brown", "DevOps Engineer", "Toronto"), + team_member("Marcus Johnson", "Frontend Developer", "Berlin") + ] + return Grid(*team, cols_sm=1, cols_md=1, cols_lg=2, cols_xl=3) + +docs_cards = create_doc_section( + H1("Cards API Reference"), + H3("Example Usage"), + fn2code_string(ex_card), + (*fn2code_string(ex_card2_wide),'sm:block'), + (*fn2code_string(ex_card2_tall),'sm:hidden'), + fn2code_string(ex_card3), + H3("API Reference"), + Card, + CardTitle, + CardT, + P("The remainder of these are only needed if you're doing something really special. They are used in the `Card` function to generate the boilerplate for you.", cls='my-6'), + CardContainer, + CardHeader, + CardBody, + CardFooter, + title="Cards" +) + +# Lists + +def ex_lists(): + list_options = [(style,str(cls)) for style,cls in ListT.__members__.items()] + lists = [Div(H4(f"{style} List:"), Ul(Li("Item 1"), Li("Item 2"), cls=cls)) for style, cls in list_options] + return Grid(*lists) + +docs_lists = create_doc_section( + H1("Lists API Reference"), + fn2code_string(ex_lists), + ListT, + title="Lists") + +# Forms + +def ex_formlabel(): + return FormLabel("Form Label") + +def ex_input(): + return Div( + Input(placeholder="Enter text"), + LabelInput(label="Input", id='myid')) + +def ex_checkbox(): + return Div( + CheckboxX(), + LabelCheckboxX(label="Checkbox", id='checkbox1')) + +def ex_range(): + return Div( + Range(), + Range(label='kg', value="25,75", min=20, max=75), + LabelRange('Basic Range', value='50', min=0, max=100, step=1), + LabelRange('Range with Label', value='75', min=0, max=100, step=5, label_range=True), + LabelRange('Multiple Values', value='25,75', min=0, max=100, step=5, label_range=True), + LabelRange('Custom Range', value='500', min=0, max=1000, step=100, label_range=True) + ) + +def ex_switch(): + return Div( + Switch(id="switch"), + LabelSwitch(label="Switch", id='switch')) + +def ex_textarea(): + return Div( + TextArea(placeholder="Enter multiple lines of text"), + LabelTextArea(label="TextArea", id='myid')) + +def ex_radio(): + return Div( + Radio(name="radio-group", id="radio1"), + LabelRadio(label="Radio", id='radio1',cls='flex items-center space-x-4')) + +def ex_insertable_select1(): + fruit_opts = ['apple', 'orange', 'banana', 'mango'] + + return Grid( + Select(Option('Apple', value='apple'), + Option('Orange', value='orange'), + Option('Banana', value='banana'), + Option('Mango', value='mango'), + id="fruit", icon=True, insertable=True, placeholder="Choose a fruit..."), + + Select(Optgroup(label="Fruit")( + *map(lambda l: Option(l.capitalize(), value=l), sorted(fruit_opts))), + id="fruit", icon=True, insertable=True, placeholder="Choose a fruit...", + cls_custom="button: uk-input-fake justify-between w-full; dropdown: w-full")) + +def ex_select(): + return Div( + Select(map(Option, ["Option 1", "Option 2", "Option 3"])), + LabelSelect(map(Option, ["Option 1", "Option 2", "Option 3"]), label="Select", id='myid')) + +def ex_progress(): + return Progress(value=20, max=100) + +def ex_form(): + relationship = ["Parent",'Sibling', "Friend", "Spouse", "Significant Other", "Relative", "Child", "Other"] + return Div(cls='space-y-4')( + DivCentered( + H3("Emergency Contact Form"), + P("Please fill out the form completely", cls=TextPresets.muted_sm)), + Form(cls='space-y-4')( + Grid(LabelInput("First Name",id='fn'), LabelInput("Last Name",id='ln')), + Grid(LabelInput("Email", id='em'), LabelInput("Phone", id='ph')), + H3("Relationship to patient"), + Grid(*[LabelCheckboxX(o) for o in relationship], cols=4, cls='space-y-3'), + LabelInput("Address", id='ad'), + LabelInput("Address Line 2", id='ad2'), + Grid(LabelInput("City", id='ct'), LabelInput("State", id='st')), + LabelInput("Zip", id='zp'), + DivCentered(Button("Submit Form", cls=ButtonT.primary)))) + +def ex_upload(): + return Div(Upload("Upload Button!", id='upload1'), + UploadZone(DivCentered(Span("Upload Zone"), UkIcon("upload")), id='upload2'), + cls='space-y-4') + +docs_forms = create_doc_section( + H1("Forms and User Inputs API Reference"), + H3("Example Form"), + P(f"This form was live coded in a 5 minute video ", + A("here",href="https://www.loom.com/share/0916e8a95d524c43a4d100ee85157624?start_and_pause=1", + cls=AT.muted), cls=TextPresets.muted_sm), + fn2code_string(ex_form), + fn2code_string(ex_upload), + FormLabel, + fn2code_string(ex_formlabel), + Input, + fn2code_string(ex_input), + LabelInput, + LabelCheckboxX, + LabelSwitch, + LabelRange, + LabelTextArea, + LabelRadio, + LabelSelect, + Progress, + fn2code_string(ex_progress), + Radio, + fn2code_string(ex_radio), + CheckboxX, + fn2code_string(ex_checkbox), + Range, + fn2code_string(ex_range), + Switch, + fn2code_string(ex_switch), + TextArea, + fn2code_string(ex_textarea), + Select, + fn2code_string(ex_select), + H3("Example: Insertable Select"), + Caption("In a production app, the user-inserted option would be saved server-side (db, session etc.)"), + fn2code_string(ex_insertable_select1), + Legend, + Fieldset, + title="Forms") + + +# Lightbox + +def ex_lightbox1(): + return LightboxContainer( + LightboxItem(Button("Open"), href='https://picsum.photos/id/100/1280/720.webp', data_alt='A placeholder image to demonstrate the lightbox', data_caption='This is my super cool caption'), + ) +def ex_lightbox2(): + return LightboxContainer( + LightboxItem(Button("Open"), href='https://picsum.photos/id/100/1280/720.webp', data_alt='A placeholder image to demonstrate the lightbox', data_caption='Image 1'), + LightboxItem(href='https://picsum.photos/id/101/1280/720.webp', data_alt='A placeholder image to demonstrate the lightbox', data_caption='Image 2'), + LightboxItem(href='https://picsum.photos/id/102/1280/720.webp', data_alt='A placeholder image to demonstrate the lightbox', data_caption='Image 3'), + ) + +def ex_lightbox3(): + return LightboxContainer( + LightboxItem(Button("mp4"), href='https://yootheme.com/site/images/media/yootheme-pro.mp4'), + LightboxItem(Button("Youtube"), href='https://www.youtube.com/watch?v=c2pz2mlSfXA'), + LightboxItem(Button("Vimeo"), href='https://vimeo.com/1084537'), + LightboxItem(Button("Iframe"), data_type='iframe', href='https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d4740.819266853735!2d9.99008871708242!3d53.550454675412404!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x3f9d24afe84a0263!2sRathaus!5e0!3m2!1sde!2sde!4v1499675200938')) + +docs_lightbox = create_doc_section( + H1("Lightbox API Reference"), + fn2code_string(ex_lightbox1), + fn2code_string(ex_lightbox2), + fn2code_string(ex_lightbox3), + LightboxContainer, + LightboxItem, + title="Lightbox") + +# Modals + +def ex_modal(): + return Div( + Button("Open Modal",data_uk_toggle="target: #my-modal" ), + Modal(ModalTitle("Simple Test Modal"), + P("With some somewhat brief content to show that it works!", cls=TextPresets.muted_sm), + footer=ModalCloseButton("Close", cls=ButtonT.primary),id='my-modal')) + +docs_modals = create_doc_section( + H1("Modals API Reference"), + H3("Example Modal"), + fn2code_string(ex_modal), + Modal, + P("If you want to trigger a htmx event on close (like calling a route) you can use `hx_trigger='hidden'` to catch the close event."), + ModalCloseButton, + P("The remainder of the Modal functions below are used internally by the `Modal` function for you. You shouldn't need to use them unless you're doing something really special."), + ModalTitle, + ModalFooter, + ModalBody, + ModalHeader, + ModalDialog, + ModalContainer, + title="Modals") + +# Layout + +def ex_grid(): + return Grid( + Div( + P("Column 1 Item 1"), + P("Column 1 Item 2"), + P("Column 1 Item 3")), + Div( + P("Column 2 Item 1"), + P("Column 2 Item 2"), + P("Column 2 Item 3")), + Div( + P("Column 3 Item 1"), + P("Column 3 Item 2"), + P("Column 3 Item 3"))) + +def ex_product_grid(): + products = [ + {"name": "Laptop", "price": "$999", "img": "https://picsum.photos/200/100?random=1"}, + {"name": "Smartphone", "price": "$599", "img": "https://picsum.photos/200/100?random=2"}, + {"name": "Headphones", "price": "$199", "img": "https://picsum.photos/200/100?random=3"}, + {"name": "Smartwatch", "price": "$299", "img": "https://picsum.photos/200/100?random=4"}, + {"name": "Tablet", "price": "$449", "img": "https://picsum.photos/200/100?random=5"}, + {"name": "Camera", "price": "$799", "img": "https://picsum.photos/200/100?random=6"}, + ] + + product_cards = [ + Card( + Img(src=p["img"], alt=p["name"], style="width:100%; height:100px; object-fit:cover;"), + H4(p["name"], cls="mt-2"), + P(p["price"], cls=TextPresets.bold_sm), + Button("Add to Cart", cls=(ButtonT.primary, "mt-2")) + ) for p in products + ] + + return Grid(*product_cards, cols_lg=3) + +def ex_fully_spaced_div(): + return DivFullySpaced( + Button("Left", cls=ButtonT.primary), + Button("Center", cls=ButtonT.secondary), + Button("Right", cls=ButtonT.destructive) + ) + +def ex_centered_div(): + return DivCentered( + H3("Centered Title"), + P("This content is centered both horizontally and vertically.") + ) + +def ex_l_aligned_div(): + return DivLAligned( + Img(src="https://picsum.photos/100/100?random=1", style="max-width: 100px;"), + H4("Left Aligned Title"), + P("Some text that's left-aligned with the title and image.") + ) + +def ex_r_aligned_div(): + return DivRAligned( + Button("Action", cls=ButtonT.primary), + P("Right-aligned text"), + Img(src="https://picsum.photos/100/100?random=3", style="max-width: 100px;") + ) + +def ex_v_stacked_div(): + return DivVStacked( + H2("Vertical Stack"), + P("First paragraph in the stack"), + P("Second paragraph in the stack"), + Button("Action Button", cls=ButtonT.secondary) + ) + +def ex_h_stacked_div(): + return DivHStacked( + Div(H4("Column 1"), P("Content for column 1")), + Div(H4("Column 2"), P("Content for column 2")), + Div(H4("Column 3"), P("Content for column 3")) + ) + +docs_layout = create_doc_section( + H1("Layout (Flex and Grid) API Reference"), + P("This page covers `Grid`s, which are often used for general structure, `Flex` which is often used for layout of components that are not grid based, padding and positioning that can help you make your layout look good, and dividers that can help break up the page", cls=TextPresets.muted_sm), + H2("Grid"), + fn2code_string(ex_grid), + Grid, + H4("Practical Grid Example"), + fn2code_string(ex_product_grid), + H2("Flex"), + P("Play ", + A("Flex Box Froggy", href="https://flexboxfroggy.com/", cls=AT.muted), + " to get an understanding of flex box.", + cls=TextPresets.muted_sm), + DivFullySpaced, + fn2code_string(ex_fully_spaced_div), + DivCentered, + fn2code_string(ex_centered_div), + DivLAligned, + fn2code_string(ex_l_aligned_div), + DivRAligned, + fn2code_string(ex_r_aligned_div), + DivVStacked, + fn2code_string(ex_v_stacked_div), + DivHStacked, + fn2code_string(ex_h_stacked_div), + FlexT, + title="Layout") + +# Dividers + +def ex_dividers(): + return Div( + P("Small Divider"), + Divider(cls=DividerT.sm), + DivCentered( + P("Vertical Divider"), + Divider(cls=DividerT.vertical)), + DivCentered("Icon Divider"), + Divider(cls=DividerT.icon)) + +def ex_dividersplit(): + return DividerSplit(P("Or continue with", cls=TextPresets.muted_sm)) + +def ex_dividerline(): + return DividerLine() + +docs_dividers = create_doc_section( + H1("Dividers API Reference"), + Divider, + DividerT, + fn2code_string(ex_dividers), + DividerSplit, + fn2code_string(ex_dividersplit), + DividerLine, + fn2code_string(ex_dividerline), + title="Dividers") + +# Navigation + +def ex_nav1(): + mbrs1 = [Li(A('Option 1'), cls='uk-active'), Li(A('Option 2')), Li(A('Option 3'))] + return NavContainer(*mbrs1) + +def ex_nav2(): + mbrs1 = [Li(A('Option 1'), cls='uk-active'), Li(A('Option 2')), Li(A('Option 3'))] + mbrs2 = [Li(A('Child 1')), Li(A('Child 2')),Li(A('Child 3'))] + + return NavContainer( + NavHeaderLi("NavHeaderLi"), + *mbrs1, + Li(A(href='')(Div("Subtitle Ex",NavSubtitle("NavSubtitle text to be shown")))), + NavDividerLi(), + NavParentLi( + A('Parent Name'), + NavContainer(*mbrs2,parent=False), + ), + ) + +def ex_navbar1(): + return NavBar(A("Page1",href='/rt1'), + A("Page2",href='/rt2'), + A("Page3",href='/rt3'), + brand=H3('My Blog')) + +def ex_navbar2(): + return NavBar( + A(Input(placeholder='search')), + A(UkIcon("rocket")), + A('Page1',href='/rt1'), + A("Page2", href='/rt3'), + brand=DivLAligned(Img(src='/api_reference/logo.svg'),UkIcon('rocket',height=30,width=30))) + +def ex_navdrop(): + return Div( + Button("Open DropDown"), + DropDownNavContainer(Li(A("Item 1",href=''),Li(A("Item 2",href=''))))) + +def ex_tabs1(): + return Container( + TabContainer( + Li(A("Active",href='#', cls='uk-active')), + Li(A("Item",href='#')), + Li(A("Item",href='#')), + Li(A("Disabled",href='#', cls='uk-disabled')), + uk_switcher='connect: #component-nav; animation: uk-animation-fade', + alt=True), + Ul(id="component-nav", cls="uk-switcher")( + Li(H1("Tab 1")), + Li(H1("Tab 2")), + Li(H1("Tab 3")))) + +def ex_tabs2(): + return Container( + TabContainer( + Li(A("Active",href='javascript:void(0);', cls='uk-active')), + Li(A("Item",href='javascript:void(0);')), + Li(A("Item",href='javascript:void(0);')), + Li(A("Disabled", cls='uk-disabled')))) + +docs_navigation = create_doc_section( + H1("Navigation (Nav, NavBar, Tabs, etc.) API Reference"), + H1("Nav, NavBar, DowDownNav, and Tab examples"), + Divider(), + H2("Nav"), + fn2code_string(ex_nav1), + fn2code_string(ex_nav2), + H2("Navbars", id='navbars'), + "Fully responsive simple navbar using the high level API. This will collapse to a hamburger menu on mobile devices. See the Scrollspy example for a more complex navbar example.", + fn2code_string(ex_navbar1), + fn2code_string(ex_navbar2), + H2("Drop Down Navs"), + fn2code_string(ex_navdrop), + H2("Tabs"), + fn2code_string(ex_tabs2), + P("A tabs can use any method of navigation (htmx, or href). However, often these are use in conjunction with switchers do to this client side", cls=TextPresets.muted_sm), + fn2code_string(ex_tabs1), + H1("API Docs"), + NavBar, + TabContainer, + NavContainer, + NavT, + NavCloseLi, + NavSubtitle, + NavHeaderLi, + NavDividerLi, + NavParentLi, + DropDownNavContainer, + title="Navigation") + +# Steps + + +def ex_steps2(): + return Steps( + LiStep("Account Created", cls=StepT.primary), + LiStep("Profile Setup", cls=StepT.neutral), + LiStep("Verification", cls=StepT.neutral), + cls="w-full") +def ex_steps3(): + return Steps( + LiStep("Project Planning", cls=StepT.success, data_content="📝"), + LiStep("Design Phase", cls=StepT.success, data_content="💡"), + LiStep("Development", cls=StepT.primary, data_content="🛠️"), + LiStep("Testing", cls=StepT.neutral, data_content="🔎"), + LiStep("Deployment", cls=StepT.neutral, data_content="🚀"), + cls=(StepsT.vertical, "min-h-[400px]")) + +docs_steps = create_doc_section( + H1("Steps API Reference"), + fn2code_string(ex_steps2), + fn2code_string(ex_steps3), + H1("API Docs"), + Steps, + StepsT, + LiStep, + StepT, + title="Steps") +# Tables + +def ex_tables0(): + return Table( + Thead(Tr(Th('Name'), Th('Age'), Th('City'))), + Tbody(Tr(Td('Alice'), Td('25'), Td('New York')), + Tr(Td('Bob'), Td('30'), Td('San Francisco')), + Tr(Td('Charlie'), Td('35'), Td('London'))), + Tfoot(Tr(Td('Total'), Td('90')))) + +def ex_tables1(): + header = ['Name', 'Age', 'City'] + body = [['Alice', '25', 'New York'], + ['Bob', '30', 'San Francisco'], + ['Charlie', '35', 'London']] + footer = ['Total', '90'] + return TableFromLists(header, body, footer) + +def ex_tables2(): + def body_render(k, v): + match k.lower(): + case 'name': return Td(v, cls='font-bold') + case 'age': return Td(f"{v} years") + case _: return Td(v) + + header_data = ['Name', 'Age', 'City'] + body_data =[{'Name': 'Alice', 'Age': 30, 'City': 'New York'}, + {'Name': 'Bob', 'Age': 25, 'City': 'London'}] + + return TableFromDicts(header_data, body_data, + header_cell_render=lambda v: Th(v.upper()), + body_cell_render=body_render) + +docs_tables = create_doc_section( + H1("Tables API Reference"), + fn2code_string(ex_tables0), + fn2code_string(ex_tables1), + fn2code_string(ex_tables2), + Table, + TableFromLists, + TableFromDicts, + TableT, + Tbody, + Th, + Td, + title="Tables") + +# Icons + +def ex_dicebear(): + return DivLAligned( + DiceBearAvatar('Isaac Flath',10,10), + DiceBearAvatar('Aaliyah',10,10), + DiceBearAvatar('Alyssa',10,10)) + +def ex_picsum(): + return Grid(PicSumImg(100,100), PicSumImg(100,100, blur=6),PicSumImg(100,100, grayscale=True)) + +def ex_icon(): + return Grid( + UkIcon('chevrons-right', height=15, width=15), + UkIcon('bug', height=15, width=15), + UkIcon('phone-call', height=15, width=15), + UkIcon('maximize-2', height=15, width=15), + UkIcon('thumbs-up', height=15, width=15),) + +def ex_iconlink(): + return DivLAligned( + UkIconLink('chevrons-right'), + UkIconLink('chevrons-right', button=True, cls=ButtonT.primary)) + +docs_icons_images = create_doc_section( + H1("Icons & Images API Reference"), + H1("Avatars"), + fn2code_string(ex_dicebear), + DiceBearAvatar, + H1("PlaceHolder Images"), + fn2code_string(ex_picsum), + PicSumImg, + H1("Icons"), + P("Icons use Lucide icons - you can find a full list of icons in their docs.", cls=TextPresets.muted_sm), + fn2code_string(ex_icon), + UkIcon, + fn2code_string(ex_iconlink), + UkIconLink, + title="Icons") + +# Markdown + +def ex_markdown(): + md = '''# Example Markdown + ++ With **bold** and *italics* ++ With a [link](https://github.com) + +### And a subheading + +> This is a blockquote + +This supports inline latex: $e^{\\pi i} + 1 = 0$ as well as block latex thanks to Katex. + +$$ +\\frac{1}{2\\pi i} \\oint_C \\frac{f(z)}{z-z_0} dz +$$ + +And even syntax highlighting thanks to Highlight.js! (Just make sure you set `highlightjs=True` in the headers function) + +```python +def add(a, b): + return a + b +``` +''' + return render_md(md) + +def ex_markdown2(): + md = '''With custom **bold** style\n\n > But no extra quote style because class_map overrides all default styled''' + return render_md(md, class_map={'b': 'text-red-500'}) + +def ex_markdown3(): + md = '''With custom **bold** style\n\n > But default quote style because class_map_mods replaces sepecified styles and leaves the rest as default''' + return render_md(md, class_map_mods={'b': 'text-red-500'}) + +def ex_applyclasses(): + return apply_classes('

Hello, World!

This is a paragraph

') + +def ex_applyclasses2(): + from mistletoe import markdown, HTMLRenderer + md = markdown('# Hi\n[a link](www.google.com)', renderer=HTMLRenderer) + return Safe(apply_classes(md)) + +docs_markdown = create_doc_section( + H1("Markdown + automated HTML styling API Reference"), + fn2code_string(ex_markdown), + render_md("You can overwrite the default styling for markdown rendering with your own css classes with `class_map"), + fn2code_string(ex_markdown2), + render_md("You can modify the default styling for markdown rendering with your own css classes with `class_map_mods"), + fn2code_string(ex_markdown3), + render_md("This uses the `apply_classes` function, which can be used to apply classes to html strings. This is useful for applying styles to any html you get from an external source."), + fn2code_string(ex_applyclasses), + render_md("One common external source is a markdown renderer. MonsterUI uses tailwind css for styling so you don't get any styling without specifying classes, `apply_classes` can do that for you."), + fn2code_string(ex_applyclasses2), + apply_classes, + title="Markdown + HTML Frankification") + + +docs_html = create_doc_section( + H1("HTML Styling API Reference"), + fn2code_string(ex_applyclasses), + title="HTML Styling") + +def ex_loading1(): + return Loading() + +def ex_loading2(): + types = [LoadingT.spinner, LoadingT.dots, LoadingT.ring, LoadingT.ball, LoadingT.bars, LoadingT.infinity] + sizes = [LoadingT.xs, LoadingT.sm, LoadingT.md, LoadingT.lg] + rows = [Div(*[Loading((t,s)) for s in sizes], cls='flex gap-4') for t in types] + return Div(*rows, cls='flex flex-col gap-4') + +docs_loading = create_doc_section( + H1("Loading Indicators API Reference"), + fn2code_string(ex_loading1), + fn2code_string(ex_loading2), + Loading, + LoadingT, + title="Loading") + + +# Charts +def ex_line_chart(): + return ApexChart( + opts={ + "chart": {"type":"line", "zoom":{"enabled": False}, "toolbar":{"show":False}}, + "series": [{"name":"Desktops", "data": [186, 305, 237, 73, 209, 214, 355]}], + "xaxis": {"categories":["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"]} + }, + cls='max-w-md max-h-md' + ) + +def ex_pie_chart(): + return ApexChart( + opts={ + "chart": {"type":"pie", "zoom":{"enabled": False}, "toolbar":{"show":False}}, + "series": [186, 305, 237, 73, 209, 214, 355], + "labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"] + }, + cls='max-w-md max-h-md' + ) + +docs_charts = create_doc_section( + H1("Charts API Reference"), + P( + "MonsterUI supports ", A("ApexCharts", href="https://apexcharts.com/", cls='underline'), + ", a javascript library for rendering different charts like line and pie charts. ", + "See the full list of chart types ", A("here.", href="https://apexcharts.com/javascript-chart-demos/", cls='underline'), + ), + P("To render a chart you'll need to include the ApexChart js in your app headers like this"), + CodeSpan("app, rt = fast_app(hdrs=Theme.blue.headers(apex_charts=True))"), + P("Then create an " , CodeSpan("ApexChart"), " component as shown in the examples below."), + P("Generally, you should be able to take any chart from the ApexChart docs, convert the chart's options var to a python dict and plug it straight into MonsterUI's ApexChart component."), + H2("Example usage", cls="mt-4"), + H4("Line chart", cls="mt-4"), + fn2code_string(ex_line_chart), + H4("Pie chart", cls="mt-4"), + fn2code_string(ex_pie_chart), + ApexChart, + title="Charts" +) diff --git a/MonsterUI/docs/api_reference/logo.svg b/MonsterUI/docs/api_reference/logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..894ade8760968eba94089d83723962ef18660060 --- /dev/null +++ b/MonsterUI/docs/api_reference/logo.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonsterUI/docs/apilist.txt b/MonsterUI/docs/apilist.txt new file mode 100644 index 0000000000000000000000000000000000000000..dd97e9c0f7b977e51a67953184bb5d110daa6311 --- /dev/null +++ b/MonsterUI/docs/apilist.txt @@ -0,0 +1,520 @@ +# monsterui Module Documentation + +## monsterui.core + +- `class ThemeRadii(Enum)` + Members: none, sm, md, lg + + +- `class ThemeShadows` + +- `class ThemeFont` + +- `class Theme(Enum)` + Selector to choose theme and get all headers needed for app. Includes frankenui + tailwind + daisyui + highlight.js options + Members: slate, stone, gray, neutral, red, rose, orange, green, blue, yellow, violet, zinc + + - `headers(self, mode, icons, daisy, highlightjs, katex, apex_charts, radii, shadows, font)` + Create frankenui and tailwind cdns + + - `local_headers(self, mode, static_dir, icons, daisy, highlightjs, katex, apex_charts, radii, shadows, font)` + Create headers using local files downloaded from CDNs + + +## monsterui.daisy + +- `class AlertT(Enum)` + Alert styles from DaisyUI + Members: info, success, warning, error + + +- `def Alert(*c, **kwargs)` + Alert informs users about important events. + +- `class StepsT(Enum)` + Options for Steps + Members: vertical, horizonal + + +- `class StepT(Enum)` + Step styles for LiStep + Members: primary, secondary, accent, info, success, warning, error, neutral + + +- `def Steps(*li, **kwargs)` + Creates a steps container + +- `def LiStep(*c, **kwargs)` + Creates a step list item + +- `class LoadingT(Enum)` + Members: spinner, dots, ring, ball, bars, infinity, xs, sm, md, lg + + +- `def Loading(cls, htmx_indicator, **kwargs)` + Creates a loading animation component + +- `class ToastHT(Enum)` + Horizontal position for Toast + Members: start, center, end + + +- `class ToastVT(Enum)` + Vertical position for Toast + Members: top, middle, bottom + + +## monsterui.foundations + +> Data Structures and Utilties + +- `def stringify(o)` + Converts input types into strings that can be passed to FT components + +- `class VEnum(Enum)` + Members: + + - `__str__(self)` + - `__add__(self, other)` + - `__radd__(self, other)` + +## monsterui.franken + +- `class TextT(Enum)` + Text Styles from https://franken-ui.dev/docs/text + Members: paragraph, lead, meta, gray, italic, xs, sm, lg, xl, light, normal, medium, bold, extrabold, muted, primary, secondary, success, warning, error, info, left, right, center, justify, start, end, top, middle, bottom, truncate, break_, nowrap, underline, highlight + + +- `class TextPresets(Enum)` + Common Typography Presets + Members: muted_sm, muted_lg, bold_sm, bold_lg, md_weight_sm, md_weight_muted + + +- `def CodeSpan(*c, **kwargs)` + A CodeSpan with Styling + +- `def CodeBlock(*c, **kwargs)` + CodeBlock with Styling + +- `def H1(*c, **kwargs)` + H1 with styling and appropriate size + +- `def H2(*c, **kwargs)` + H2 with styling and appropriate size + +- `def H3(*c, **kwargs)` + H3 with styling and appropriate size + +- `def H4(*c, **kwargs)` + H4 with styling and appropriate size + +- `def H5(*c, **kwargs)` + H5 with styling and appropriate size + +- `def H6(*c, **kwargs)` + H6 with styling and appropriate size + +- `def Subtitle(*c, **kwargs)` + Styled muted_sm text designed to go under Headings and Titles + +- `def Q(*c, **kwargs)` + Styled quotation mark + +- `def Em(*c, **kwargs)` + Styled emphasis text + +- `def Strong(*c, **kwargs)` + Styled strong text + +- `def I(*c, **kwargs)` + Styled italic text + +- `def Small(*c, **kwargs)` + Styled small text + +- `def Mark(*c, **kwargs)` + Styled highlighted text + +- `def Del(*c, **kwargs)` + Styled deleted text + +- `def Ins(*c, **kwargs)` + Styled inserted text + +- `def Sub(*c, **kwargs)` + Styled subscript text + +- `def Sup(*c, **kwargs)` + Styled superscript text + +- `def Blockquote(*c, **kwargs)` + Blockquote with Styling + +- `def Caption(*c, **kwargs)` + Styled caption text + +- `def Cite(*c, **kwargs)` + Styled citation text + +- `def Time(*c, **kwargs)` + Styled time element + +- `def Address(*c, **kwargs)` + Styled address element + +- `def Abbr(*c, **kwargs)` + Styled abbreviation with dotted underline + +- `def Dfn(*c, **kwargs)` + Styled definition term with italic and medium weight + +- `def Kbd(*c, **kwargs)` + Styled keyboard input with subtle background + +- `def Samp(*c, **kwargs)` + Styled sample output with subtle background + +- `def Var(*c, **kwargs)` + Styled variable with italic monospace + +- `def Figure(*c, **kwargs)` + Styled figure container with card-like appearance + +- `def Details(*c, **kwargs)` + Styled details element + +- `def Summary(*c, **kwargs)` + Styled summary element + +- `def Data(*c, **kwargs)` + Styled data element + +- `def Meter(*c, **kwargs)` + Styled meter element + +- `def S(*c, **kwargs)` + Styled strikethrough text (different semantic meaning from Del) + +- `def U(*c, **kwargs)` + Styled underline (for proper names in Chinese, proper spelling etc) + +- `def Output(*c, **kwargs)` + Styled output element for form results + +- `def PicSumImg(h, w, id, grayscale, blur, **kwargs)` + Creates a placeholder image using https://picsum.photos/ + +- `def AccordionItem(title, *c)` + Creates a single item for use within an Accordion component, handling title, content, and open state. + +- `def Accordion(*c, **kwargs)` + Creates a styled Accordion container using accordion component. + +- `class ButtonT(Enum)` + Options for styling Buttons + Members: default, ghost, primary, secondary, destructive, text, link, xs, sm, lg, xl, icon + + +- `def Button(*c, **kwargs)` + Button with Styling (defaults to `submit` for form submission) + +- `class ContainerT(Enum)` + Max width container sizes from https://franken-ui.dev/docs/container + Members: xs, sm, lg, xl, expand + + +- `class BackgroundT(Enum)` + Members: muted, primary, secondary, default + + +- `def Container(*c, **kwargs)` + Div to be used as a container that often wraps large sections or a page of content + +- `def Titled(title, *c, **kwargs)` + Creates a standard page structure for titled page. Main(Container(title, content)) + +- `class DividerT(Enum)` + Divider Styles from https://franken-ui.dev/docs/divider + Members: icon, sm, vertical + + +- `def Divider(*c, **kwargs)` + Divider with default styling and margin + +- `def DividerSplit(*c)` + Creates a simple horizontal line divider with configurable thickness and vertical spacing + +- `def Article(*c, **kwargs)` + A styled article container for blog posts or similar content + +- `def ArticleTitle(*c, **kwargs)` + A title component for use within an Article + +- `def ArticleMeta(*c, **kwargs)` + A metadata component for use within an Article showing things like date, author etc + +- `class SectionT(Enum)` + Section styles from https://franken-ui.dev/docs/section + Members: default, muted, primary, secondary, xs, sm, lg, xl, remove_vertical + + +- `def Section(*c, **kwargs)` + Section with styling and margins + +- `def Form(*c, **kwargs)` + A Form with default spacing between form elements + +- `def Fieldset(*c, **kwargs)` + A Fieldset with default styling + +- `def Legend(*c, **kwargs)` + A Legend with default styling + +- `def Input(*c, **kwargs)` + An Input with default styling + +- `def Radio(*c, **kwargs)` + A Radio with default styling + +- `def CheckboxX(*c, **kwargs)` + A Checkbox with default styling + +- `def Range(*c, **kwargs)` + A Range with default styling + +- `def TextArea(*c, **kwargs)` + A Textarea with default styling + +- `def Switch(*c, **kwargs)` + A Switch with default styling + +- `def Upload(*c, **kwargs)` + A file upload component with default styling + +- `def UploadZone(*c, **kwargs)` + A file drop zone component with default styling + +- `def FormLabel(*c, **kwargs)` + A Label with default styling + +- `class LabelT(Enum)` + Members: primary, secondary, destructive + + +- `def Label(*c, **kwargs)` + FrankenUI labels, which look like pills + +- `def UkFormSection(title, description, *c)` + A form section with a title, description and optional button + +- `def GenericLabelInput(label, lbl_cls, input_cls, container, cls, id, input_fn, **kwargs)` + `Div(Label,Input)` component with Uk styling injected appropriately. Generally you should higher level API, such as `LabelInput` which is created for you in this library + +- `def LabelInput(label, lbl_cls, input_cls, cls, id, **kwargs)` + A `FormLabel` and `Input` pair that provides default spacing and links/names them based on id + +- `def LabelRadio(label, lbl_cls, input_cls, container, cls, id, **kwargs)` + A FormLabel and Radio pair that provides default spacing and links/names them based on id + +- `def LabelCheckboxX(label, lbl_cls, input_cls, container, cls, id, **kwargs)` + A FormLabel and CheckboxX pair that provides default spacing and links/names them based on id + +- `def Options(*c)` + Helper function to wrap things into `Option`s for use in `Select` + +- `def Select(*option, **kwargs)` + Creates a select dropdown with uk styling and option for adding a search box + +- `def LabelSelect(*option, **kwargs)` + A FormLabel and Select pair that provides default spacing and links/names them based on id + +- `@delegates(GenericLabelInput, but=['input_fn', 'cls']) def LabelRange(label, lbl_cls, input_cls, cls, id, value, min, max, step, label_range, **kwargs)` + A FormLabel and Range pair that provides default spacing and links/names them based on id + +- `class AT(Enum)` + Link styles from https://franken-ui.dev/docs/link + Members: muted, text, reset, primary, classic + + +- `class ListT(Enum)` + List styles using Tailwind CSS + Members: disc, circle, square, decimal, hyphen, bullet, divider, striped + + +- `def ModalContainer(*c, **kwargs)` + Creates a modal container that components go in + +- `def ModalDialog(*c, **kwargs)` + Creates a modal dialog + +- `def ModalHeader(*c, **kwargs)` + Creates a modal header + +- `def ModalBody(*c, **kwargs)` + Creates a modal body + +- `def ModalFooter(*c, **kwargs)` + Creates a modal footer + +- `def ModalTitle(*c, **kwargs)` + Creates a modal title + +- `def ModalCloseButton(*c, **kwargs)` + Creates a button that closes a modal with js + +- `def Modal(*c, **kwargs)` + Creates a modal with the appropriate classes to put the boilerplate in the appropriate places for you + +- `def Placeholder(*c, **kwargs)` + Creates a placeholder + +- `def Progress(*c, **kwargs)` + Creates a progress bar + +- `def UkIcon(icon, height, width, stroke_width, cls, **kwargs)` + Creates an icon using lucide icons + +- `def UkIconLink(icon, height, width, stroke_width, cls, button, **kwargs)` + Creates an icon link using lucide icons + +- `def DiceBearAvatar(seed_name, h, w)` + Creates an Avatar using https://dicebear.com/ + +- `def Center(*c, **kwargs)` + Centers contents both vertically and horizontally by default + +- `class FlexT(Enum)` + Flexbox modifiers using Tailwind CSS + Members: block, inline, left, center, right, between, around, stretch, top, middle, bottom, row, row_reverse, column, column_reverse, nowrap, wrap, wrap_reverse + + +- `def Grid(*div, **kwargs)` + Creates a responsive grid layout with smart defaults based on content + +- `def DivFullySpaced(*c, **kwargs)` + Creates a flex div with it's components having as much space between them as possible + +- `def DivCentered(*c, **kwargs)` + Creates a flex div with it's components centered in it + +- `def DivLAligned(*c, **kwargs)` + Creates a flex div with it's components aligned to the left + +- `def DivRAligned(*c, **kwargs)` + Creates a flex div with it's components aligned to the right + +- `def DivVStacked(*c, **kwargs)` + Creates a flex div with it's components stacked vertically + +- `def DivHStacked(*c, **kwargs)` + Creates a flex div with it's components stacked horizontally + +- `class NavT(Enum)` + Members: default, primary, secondary + + +- `def NavContainer(*li, **kwargs)` + Creates a navigation container (useful for creating a sidebar navigation). A Nav is a list (NavBar is something different) + +- `def NavParentLi(*nav_container, **kwargs)` + Creates a navigation list item with a parent nav for nesting + +- `def NavDividerLi(*c, **kwargs)` + Creates a navigation list item with a divider + +- `def NavHeaderLi(*c, **kwargs)` + Creates a navigation list item with a header + +- `def NavSubtitle(*c, **kwargs)` + Creates a navigation subtitle + +- `def NavCloseLi(*c, **kwargs)` + Creates a navigation list item with a close button + +- `class ScrollspyT(Enum)` + Members: underline, bold + + +- `def NavBar(*c)` + Creates a responsive navigation bar with mobile menu support + +- `def SliderContainer(*c, **kwargs)` + Creates a slider container + +- `def SliderItems(*c, **kwargs)` + Creates a slider items container + +- `def SliderNav(cls, prev_cls, next_cls, **kwargs)` + Navigation arrows for Slider component + +- `def Slider(*c, **kwargs)` + Creates a slider with optional navigation arrows + +- `def DropDownNavContainer(*li, **kwargs)` + A Nav that is part of a DropDown + +- `def TabContainer(*li, **kwargs)` + A TabContainer where children will be different tabs + +- `class CardT(Enum)` + Card styles from UIkit + Members: default, primary, secondary, destructive, hover + + +- `def CardTitle(*c, **kwargs)` + Creates a card title + +- `def CardHeader(*c, **kwargs)` + Creates a card header + +- `def CardBody(*c, **kwargs)` + Creates a card body + +- `def CardFooter(*c, **kwargs)` + Creates a card footer + +- `def CardContainer(*c, **kwargs)` + Creates a card container + +- `def Card(*c, **kwargs)` + Creates a Card with a header, body, and footer + +- `class TableT(Enum)` + Members: divider, striped, hover, sm, lg, justify, middle, responsive + + +- `def Table(*c, **kwargs)` + Creates a table + +- `def TableFromLists(header_data, body_data, footer_data, header_cell_render, body_cell_render, footer_cell_render, cls, sortable, **kwargs)` + Creates a Table from a list of header data and a list of lists of body data + +- `def TableFromDicts(header_data, body_data, footer_data, header_cell_render, body_cell_render, footer_cell_render, cls, sortable, **kwargs)` + Creates a Table from a list of header data and a list of dicts of body data + +- `def apply_classes(html_str, class_map, class_map_mods)` + Apply classes to html string + +- `class FrankenRenderer` + Custom renderer for Franken UI that handles image paths + + - `def __init__(self, *args, **kwargs)` + - `def render_image(self, token)` + Modify image paths if they're relative and self.img_dir is specified + + +- `def render_md(md_content, class_map, class_map_mods, img_dir, renderer)` + Renders markdown using mistletoe and lxml with custom image handling + +- `def ThemePicker(color, radii, shadows, font, mode, cls, custom_themes)` + Theme picker component with configurable sections + +- `def LightboxContainer(*lightboxitem, **kwargs)` + Lightbox container that will hold `LightboxItems` + +- `def LightboxItem(*c, **kwargs)` + Anchor tag with appropriate structure to go inside a `LightBoxContainer` + +- `def ApexChart(**kws)` + Apex chart component + diff --git a/MonsterUI/docs/cf_addns.py b/MonsterUI/docs/cf_addns.py new file mode 100644 index 0000000000000000000000000000000000000000..3e0878a6a983b0e2365bd6052149d6f1af0aa61f --- /dev/null +++ b/MonsterUI/docs/cf_addns.py @@ -0,0 +1,18 @@ + +# https://github.com/cloudflare/cloudflare-python/blob/main/api.md +from fastcore.script import * +from cloudflare import Cloudflare + +@call_parse +def add_dns_record( + record_type: str, # Type of DNS record (CNAME or A) + target: str, # Target IP address or domain name + record: str, # Record name (without the zone) + zone: str, # Zone name + proxied: bool_arg=True # Use CF proxy? +): + cf = Cloudflare() + zones = cf.zones.list(name=zone) + if not zones: raise ValueError(f"Zone '{zone}' not found") + zid = zones.result[0].id + cf.dns.records.create(zone_id=zid, type=record_type.upper(), name=f"{record}.{zone}", content=target, proxied=proxied) diff --git a/MonsterUI/docs/createllms.sh b/MonsterUI/docs/createllms.sh new file mode 100644 index 0000000000000000000000000000000000000000..16aba0da41096abd1052c01729ea1a35d4543680 --- /dev/null +++ b/MonsterUI/docs/createllms.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +from fastcore.utils import * +import httpx +import api_reference.api_reference as api_reference +def fname2title(ref_fn_name): return ref_fn_name[5:].replace('_',' | ').title() + +def create_llms_txt(): + # Get examples + base = "https://monsterui.answer.ai" + examples = [f for f in Path('examples').glob('*.py') if not f.name.startswith('__') and f.name.endswith('.py')] + example_links = [] + for f in examples: + content = httpx.get(f"{base}/{f.stem}/md").text + first_line = content.split('\n')[0].strip('# ').strip('"') + example_links.append(f"[{f.stem.title()}]({base}/{f.name[:-3]}/md): {first_line}") + + # Get reference files with their H1 headings + reference_fns = L([o for o in dir(api_reference) if o.startswith('docs_')]) + api_links = [] + for f in reference_fns: + content = httpx.get(f"{base}/api_ref/{f}/md").text + first_heading = content.split('\n')[0].strip('# ') + api_links.append(f"[{fname2title(f)}]({base}/api_ref/{f}/md): {first_heading}") + + # Create content + content = [ + "# MonsterUI Documentation", + ''' +> MonsterUI is a python library which brings styling to python for FastHTML apps. + +''' + "## API Reference", + '- [API List](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/apilist.txt): Complete API Reference', + "", + "## Examples", + *[f'- {a}' for a in example_links], + "", + "## Optional", + *[f'- {a}' for a in api_links], + "- [Layout](https://monsterui.answer.ai/tutorial_layout/md): MonsterUI Page Layout Guide", + "- [Spacing](https://monsterui.answer.ai/tutorial_spacing/md): Padding & Margin & Spacing, Oh my! (MonsterUI Spacing Guide)", + ] + + # Write to file + Path('llms.txt').write_text('\n'.join(content)) + +create_llms_txt() diff --git a/MonsterUI/docs/custom_theme.css b/MonsterUI/docs/custom_theme.css new file mode 100644 index 0000000000000000000000000000000000000000..92251a1d71775725b4e84c4b8718e550f5cce9ee --- /dev/null +++ b/MonsterUI/docs/custom_theme.css @@ -0,0 +1,56 @@ +/* custom_theme.css */ + +.uk-theme-grass { + --background: 78 47% 99%; + --foreground: 78 51% 0%; + --muted: 78 12% 85%; + --muted-foreground: 78 8% 38%; + --popover: 78 47% 99%; + --popover-foreground: 78 51% 0%; + --card: 78 47% 99%; + --card-foreground: 78 51% 0%; + --border: 78 2% 93%; + --input: 78 2% 93%; + --primary: 78 28% 60%; + --primary-foreground: 0 0% 0%; + --secondary: 78 8% 81%; + --secondary-foreground: 78 8% 21%; + --accent: 78 8% 81%; + --accent-foreground: 78 8% 21%; + --destructive: 17 86% 32%; + --destructive-foreground: 17 86% 92%; + --ring: 78 28% 60%; + --chart-1: 78 28% 60%; + --chart-2: 78 8% 81%; + --chart-3: 78 8% 81%; + --chart-4: 78 8% 84%; + --chart-5: 78 31% 60%; + --radius: 0.5rem; + } + + .dark.uk-theme-grass { + --background: 78 48% 2%; + --foreground: 78 24% 99%; + --muted: 78 12% 15%; + --muted-foreground: 78 8% 62%; + --popover: 78 48% 2%; + --popover-foreground: 78 24% 99%; + --card: 78 48% 2%; + --card-foreground: 78 24% 99%; + --border: 78 2% 14%; + --input: 78 2% 14%; + --primary: 78 28% 60%; + --primary-foreground: 0 0% 0%; + --secondary: 78 8% 14%; + --secondary-foreground: 78 8% 74%; + --accent: 78 8% 14%; + --accent-foreground: 78 8% 74%; + --destructive: 17 86% 60%; + --destructive-foreground: 17 86% 0%; + --ring: 78 28% 60%; + --chart-1: 78 28% 60%; + --chart-2: 78 8% 14%; + --chart-3: 78 8% 14%; + --chart-4: 78 8% 17%; + --chart-5: 78 31% 60%; + } \ No newline at end of file diff --git a/MonsterUI/docs/data_/mail.json b/MonsterUI/docs/data_/mail.json new file mode 100644 index 0000000000000000000000000000000000000000..63dc8872689abbb8eacd5a2db84c2cae9e7c909e --- /dev/null +++ b/MonsterUI/docs/data_/mail.json @@ -0,0 +1,206 @@ +[ + { + "id": "6c84fb90-12c4-11e1-840d-7b25c5ee775a", + "initial": "WS", + "name": "William Smith", + "email": "williamsmith@example.com", + "subject": "Meeting Tomorrow", + "text": "Hi, let's have a meeting tomorrow to discuss the project. I've been reviewing the project details and have some ideas I'd like to share. It's crucial that we align on our next steps to ensure the project's success.\n\nPlease come prepared with any questions or insights you may have. Looking forward to our meeting!\n\nBest regards, William", + "date": "2023-10-22T09:00:00", + "read": true, + "active": true, + "labels": ["meeting", "work", "important"] + }, + { + "id": "110e8400-e29b-11d4-a716-446655440000", + "initial": "AS", + "name": "Alice Smith", + "email": "alicesmith@example.com", + "subject": "Re: Project Update", + "text": "Thank you for the project update. It looks great! I've gone through the report, and the progress is impressive. The team has done a fantastic job, and I appreciate the hard work everyone has put in.\n\nI have a few minor suggestions that I'll include in the attached document.\n\nLet's discuss these during our next meeting. Keep up the excellent work!\n\nBest regards, Alice", + "date": "2023-10-22T10:30:00", + "read": true, + "active": false, + "labels": ["work", "important"] + }, + { + "id": "3e7c3f6d-bdf5-46ae-8d90-171300f27ae2", + "initial": "BJ", + "name": "Bob Johnson", + "email": "bobjohnson@example.com", + "subject": "Weekend Plans", + "text": "Any plans for the weekend? I was thinking of going hiking in the nearby mountains. It's been a while since we had some outdoor fun.\n\nIf you're interested, let me know, and we can plan the details. It'll be a great way to unwind and enjoy nature.\n\nLooking forward to your response!\n\nBest, Bob", + "date": "2023-04-10T11:45:00", + "read": true, + "active": false, + "labels": ["personal"] + }, + { + "id": "61c35085-72d7-42b4-8d62-738f700d4b92", + "initial": "ED", + "name": "Emily Davis", + "email": "emilydavis@example.com", + "subject": "Re: Question about Budget", + "text": "I have a question about the budget for the upcoming project. It seems like there's a discrepancy in the allocation of resources.\n\nI've reviewed the budget report and identified a few areas where we might be able to optimize our spending without compromising the project's quality.\n\nI've attached a detailed analysis for your reference. Let's discuss this further in our next meeting.\n\nThanks, Emily", + "date": "2023-03-25T13:15:00", + "read": false, + "active": false, + "labels": ["work", "budget"] + }, + { + "id": "8f7b5db9-d935-4e42-8e05-1f1d0a3dfb97", + "initial": "MW", + "name": "Michael Wilson", + "email": "michaelwilson@example.com", + "subject": "Important Announcement", + "text": "I have an important announcement to make during our team meeting. It pertains to a strategic shift in our approach to the upcoming product launch. We've received valuable feedback from our beta testers, and I believe it's time to make some adjustments to better meet our customers' needs.\n\nThis change is crucial to our success, and I look forward to discussing it with the team. Please be prepared to share your insights during the meeting.\n\nRegards, Michael", + "date": "2023-03-10T15:00:00", + "read": false, + "active": false, + "labels": ["meeting", "work", "important"] + }, + { + "id": "1f0f2c02-e299-40de-9b1d-86ef9e42126b", + "initial": "SB", + "name": "Sarah Brown", + "email": "sarahbrown@example.com", + "subject": "Re: Feedback on Proposal", + "text": "Thank you for your feedback on the proposal. It looks great! I'm pleased to hear that you found it promising. The team worked diligently to address all the key points you raised, and I believe we now have a strong foundation for the project.\n\nI've attached the revised proposal for your review.\n\nPlease let me know if you have any further comments or suggestions. Looking forward to your response.\n\nBest regards, Sarah", + "date": "2023-02-15T16:30:00", + "read": true, + "active": false, + "labels": ["work"] + }, + { + "id": "17c0a96d-4415-42b1-8b4f-764efab57f66", + "initial": "DL", + "name": "David Lee", + "email": "davidlee@example.com", + "subject": "New Project Idea", + "text": "I have an exciting new project idea to discuss with you. It involves expanding our services to target a niche market that has shown considerable growth in recent months.\n\nI've prepared a detailed proposal outlining the potential benefits and the strategy for execution.\n\nThis project has the potential to significantly impact our business positively. Let's set up a meeting to dive into the details and determine if it aligns with our current goals.\n\nBest regards, David", + "date": "2023-01-28T17:45:00", + "read": false, + "active": false, + "labels": ["meeting", "work", "important"] + }, + { + "id": "2f0130cb-39fc-44c4-bb3c-0a4337edaaab", + "initial": "OW", + "name": "Olivia Wilson", + "email": "oliviawilson@example.com", + "subject": "Vacation Plans", + "text": "Let's plan our vacation for next month. What do you think? I've been thinking of visiting a tropical paradise, and I've put together some destination options.\n\nI believe it's time for us to unwind and recharge. Please take a look at the options and let me know your preferences.\n\nWe can start making arrangements to ensure a smooth and enjoyable trip.\n\nExcited to hear your thoughts! Olivia", + "date": "2022-12-20T18:30:00", + "read": true, + "active": false, + "labels": ["personal"] + }, + { + "id": "de305d54-75b4-431b-adb2-eb6b9e546014", + "initial": "JM", + "name": "James Martin", + "email": "jamesmartin@example.com", + "subject": "Re: Conference Registration", + "text": "I've completed the registration for the conference next month. The event promises to be a great networking opportunity, and I'm looking forward to attending the various sessions and connecting with industry experts.\n\nI've also attached the conference schedule for your reference.\n\nIf there are any specific topics or sessions you'd like me to explore, please let me know. It's an exciting event, and I'll make the most of it.\n\nBest regards, James", + "date": "2022-11-30T19:15:00", + "read": true, + "active": false, + "labels": ["work", "conference"] + }, + { + "id": "7dd90c63-00f6-40f3-bd87-5060a24e8ee7", + "initial": "SW", + "name": "Sophia White", + "email": "sophiawhite@example.com", + "subject": "Team Dinner", + "text": "Let's have a team dinner next week to celebrate our success. We've achieved some significant milestones, and it's time to acknowledge our hard work and dedication.\n\nI've made reservations at a lovely restaurant, and I'm sure it'll be an enjoyable evening.\n\nPlease confirm your availability and any dietary preferences. Looking forward to a fun and memorable dinner with the team!\n\nBest, Sophia", + "date": "2022-11-05T20:30:00", + "read": false, + "active": false, + "labels": ["meeting", "work"] + }, + { + "id": "99a88f78-3eb4-4d87-87b7-7b15a49a0a05", + "initial": "DJ", + "name": "Daniel Johnson", + "email": "danieljohnson@example.com", + "subject": "Feedback Request", + "text": "I'd like your feedback on the latest project deliverables. We've made significant progress, and I value your input to ensure we're on the right track.\n\nI've attached the deliverables for your review, and I'm particularly interested in any areas where you think we can further enhance the quality or efficiency.\n\nYour feedback is invaluable, and I appreciate your time and expertise. Let's work together to make this project a success.\n\nRegards, Daniel", + "date": "2022-10-22T09:30:00", + "read": false, + "active": false, + "labels": ["work"] + }, + { + "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", + "initial": "AT", + "name": "Ava Taylor", + "email": "avataylor@example.com", + "subject": "Re: Meeting Agenda", + "text": "Here's the agenda for our meeting next week. I've included all the topics we need to cover, as well as time allocations for each.\n\nIf you have any additional items to discuss or any specific points to address, please let me know, and we can integrate them into the agenda.\n\nIt's essential that our meeting is productive and addresses all relevant matters.\n\nLooking forward to our meeting! Ava", + "date": "2022-10-10T10:45:00", + "read": true, + "active": false, + "labels": ["meeting", "work"] + }, + { + "id": "c1a0ecb4-2540-49c5-86f8-21e5ce79e4e6", + "initial": "WA", + "name": "William Anderson", + "email": "williamanderson@example.com", + "subject": "Product Launch Update", + "text": "The product launch is on track. I'll provide an update during our call. We've made substantial progress in the development and marketing of our new product.\n\nI'm excited to share the latest updates with you during our upcoming call. It's crucial that we coordinate our efforts to ensure a successful launch. Please come prepared with any questions or insights you may have.\n\nLet's make this product launch a resounding success!\n\nBest regards, William", + "date": "2022-09-20T12:00:00", + "read": false, + "active": false, + "labels": ["meeting", "work", "important"] + }, + { + "id": "ba54eefd-4097-4949-99f2-2a9ae4d1a836", + "initial": "MH", + "name": "Mia Harris", + "email": "miaharris@example.com", + "subject": "Re: Travel Itinerary", + "text": "I've received the travel itinerary. It looks great! Thank you for your prompt assistance in arranging the details. I've reviewed the schedule and the accommodations, and everything seems to be in order. I'm looking forward to the trip, and I'm confident it'll be a smooth and enjoyable experience.\n\nIf there are any specific activities or attractions you recommend at our destination, please feel free to share your suggestions.\n\nExcited for the trip! Mia", + "date": "2022-09-10T13:15:00", + "read": true, + "active": false, + "labels": ["personal", "travel"] + }, + { + "id": "df09b6ed-28bd-4e0c-85a9-9320ec5179aa", + "initial": "EC", + "name": "Ethan Clark", + "email": "ethanclark@example.com", + "subject": "Team Building Event", + "text": "Let's plan a team-building event for our department. Team cohesion and morale are vital to our success, and I believe a well-organized team-building event can be incredibly beneficial. I've done some research and have a few ideas for fun and engaging activities.\n\nPlease let me know your thoughts and availability. We want this event to be both enjoyable and productive.\n\nTogether, we'll strengthen our team and boost our performance.\n\nRegards, Ethan", + "date": "2022-08-25T15:30:00", + "read": false, + "active": false, + "labels": ["meeting", "work"] + }, + { + "id": "d67c1842-7f8b-4b4b-9be1-1b3b1ab4611d", + "initial": "CH", + "name": "Chloe Hall", + "email": "chloehall@example.com", + "subject": "Re: Budget Approval", + "text": "The budget has been approved. We can proceed with the project. I'm delighted to inform you that our budget proposal has received the green light from the finance department. This is a significant milestone, and it means we can move forward with the project as planned.\n\nI've attached the finalized budget for your reference. Let's ensure that we stay on track and deliver the project on time and within budget.\n\nIt's an exciting time for us! Chloe", + "date": "2022-08-10T16:45:00", + "read": true, + "active": false, + "labels": ["work", "budget"] + }, + { + "id": "6c9a7f94-8329-4d70-95d3-51f68c186ae1", + "initial": "ST", + "name": "Samuel Turner", + "email": "samuelturner@example.com", + "subject": "Weekend Hike", + "text": "Who's up for a weekend hike in the mountains? I've been craving some outdoor adventure, and a hike in the mountains sounds like the perfect escape. If you're up for the challenge, we can explore some scenic trails and enjoy the beauty of nature.\n\nI've done some research and have a few routes in mind.\n\nLet me know if you're interested, and we can plan the details.\n\nIt's sure to be a memorable experience! Samuel", + "date": "2022-07-28T17:30:00", + "read": false, + "active": false, + "labels": ["personal"] + } +] \ No newline at end of file diff --git a/MonsterUI/docs/data_/status_list.json b/MonsterUI/docs/data_/status_list.json new file mode 100644 index 0000000000000000000000000000000000000000..546f7919aed1f696bb3f2527e6a50238e477f02b --- /dev/null +++ b/MonsterUI/docs/data_/status_list.json @@ -0,0 +1 @@ +[{"selected": true, "id": "TASK-8782", "title": "You can't compress the program without quantifying the open-source SSD pixel!", "status": "progress", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-7878", "title": "Try to calculate the EXE feed, maybe it will index the multi-byte pixel!", "status": "backlog", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-7839", "title": "We need to bypass the neural TCP card!", "status": "todo", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-5562", "title": "The SAS interface is down, bypass the open-source pixel so we can back up the PNG bandwidth!", "status": "backlog", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-8686", "title": "I'll parse the wireless SSL protocol, that should driver the API panel!", "status": "cancelled", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-1280", "title": "Use the digital TLS panel, then you can transmit the haptic system!", "status": "done", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-7262", "title": "The UTF8 application is down, parse the neural bandwidth so we can back up the PNG firewall!", "status": "done", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-1138", "title": "Generating the driver won't do anything, we need to quantify the 1080p SMTP bandwidth!", "status": "progress", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-7184", "title": "We need to program the back-end THX pixel!", "status": "todo", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-5160", "title": "Calculating the bus won't do anything, we need to navigate the back-end JSON protocol!", "status": "progress", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-5618", "title": "Generating the driver won't do anything, we need to index the online SSL application!", "status": "done", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-6699", "title": "I'll transmit the wireless JBOD capacitor, that should hard drive the SSD feed!", "status": "backlog", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-2858", "title": "We need to override the online UDP bus!", "status": "backlog", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-9864", "title": "I'll reboot the 1080p FTP panel, that should matrix the HEX hard drive!", "status": "done", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-8404", "title": "We need to generate the virtual HEX alarm!", "status": "progress", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-5365", "title": "Backing up the pixel won't do anything, we need to transmit the primary IB array!", "status": "progress", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-1780", "title": "The CSS feed is down, index the bluetooth transmitter so we can compress the CLI protocol!", "status": "todo", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-6938", "title": "Use the redundant SCSI application, then you can hack the optical alarm!", "status": "todo", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-9885", "title": "We need to compress the auxiliary VGA driver!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-3216", "title": "Transmitting the transmitter won't do anything, we need to compress the virtual HDD sensor!", "status": "backlog", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-9285", "title": "The IP monitor is down, copy the haptic alarm so we can generate the HTTP transmitter!", "status": "todo", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-1024", "title": "Overriding the microchip won't do anything, we need to transmit the digital OCR transmitter!", "status": "progress", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-7068", "title": "You can't generate the capacitor without indexing the wireless HEX pixel!", "status": "cancelled", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-6502", "title": "Navigating the microchip won't do anything, we need to bypass the back-end SQL bus!", "status": "todo", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-5326", "title": "We need to hack the redundant UTF8 transmitter!", "status": "todo", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-6274", "title": "Use the virtual PCI circuit, then you can parse the bluetooth alarm!", "status": "cancelled", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-1571", "title": "I'll input the neural DRAM circuit, that should protocol the SMTP interface!", "status": "progress", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-9518", "title": "Compressing the interface won't do anything, we need to compress the online SDD matrix!", "status": "cancelled", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-5581", "title": "I'll synthesize the digital COM pixel, that should transmitter the UTF8 protocol!", "status": "backlog", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-2197", "title": "Parsing the feed won't do anything, we need to copy the bluetooth DRAM bus!", "status": "todo", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-8484", "title": "We need to parse the solid state UDP firewall!", "status": "progress", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-9892", "title": "If we back up the application, we can get to the UDP application through the multi-byte THX capacitor!", "status": "done", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-9616", "title": "We need to synthesize the cross-platform ASCII pixel!", "status": "progress", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-9744", "title": "Use the back-end IP card, then you can input the solid state hard drive!", "status": "done", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-1376", "title": "Generating the alarm won't do anything, we need to generate the mobile IP capacitor!", "status": "backlog", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-7382", "title": "If we back up the firewall, we can get to the RAM alarm through the primary UTF8 pixel!", "status": "todo", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-2290", "title": "I'll compress the virtual JSON panel, that should application the UTF8 bus!", "status": "cancelled", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-1533", "title": "You can't input the firewall without overriding the wireless TCP firewall!", "status": "done", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-4920", "title": "Bypassing the hard drive won't do anything, we need to input the bluetooth JSON program!", "status": "progress", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-5168", "title": "If we synthesize the bus, we can get to the IP panel through the virtual TLS array!", "status": "progress", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-7103", "title": "We need to parse the multi-byte EXE bandwidth!", "status": "cancelled", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-4314", "title": "If we compress the program, we can get to the XML alarm through the multi-byte COM matrix!", "status": "progress", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-3415", "title": "Use the cross-platform XML application, then you can quantify the solid state feed!", "status": "todo", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-8339", "title": "Try to calculate the DNS interface, maybe it will input the bluetooth capacitor!", "status": "progress", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-6995", "title": "Try to hack the XSS bandwidth, maybe it will override the bluetooth matrix!", "status": "todo", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-8053", "title": "If we connect the program, we can get to the UTF8 matrix through the digital UDP protocol!", "status": "todo", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-4336", "title": "If we synthesize the microchip, we can get to the SAS sensor through the optical UDP program!", "status": "todo", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-8790", "title": "I'll back up the optical COM alarm, that should alarm the RSS capacitor!", "status": "done", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-8980", "title": "Try to navigate the SQL transmitter, maybe it will back up the virtual firewall!", "status": "cancelled", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-7342", "title": "Use the neural CLI card, then you can parse the online port!", "status": "backlog", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-5608", "title": "I'll hack the haptic SSL program, that should bus the UDP transmitter!", "status": "cancelled", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-1606", "title": "I'll generate the bluetooth PNG firewall, that should pixel the SSL driver!", "status": "done", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-7872", "title": "Transmitting the circuit won't do anything, we need to reboot the 1080p RSS monitor!", "status": "cancelled", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-4167", "title": "Use the cross-platform SMS circuit, then you can synthesize the optical feed!", "status": "cancelled", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-9581", "title": "You can't index the port without hacking the cross-platform XSS monitor!", "status": "backlog", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-8806", "title": "We need to bypass the back-end SSL panel!", "status": "done", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-6542", "title": "Try to quantify the RSS firewall, maybe it will quantify the open-source system!", "status": "done", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-6806", "title": "The VGA protocol is down, reboot the back-end matrix so we can parse the CSS panel!", "status": "cancelled", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-9549", "title": "You can't bypass the bus without connecting the neural JBOD bus!", "status": "todo", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-1075", "title": "Backing up the driver won't do anything, we need to parse the redundant RAM pixel!", "status": "done", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-1427", "title": "Use the auxiliary PCI circuit, then you can calculate the cross-platform interface!", "status": "done", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-1907", "title": "Hacking the circuit won't do anything, we need to back up the online DRAM system!", "status": "todo", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-4309", "title": "If we generate the system, we can get to the TCP sensor through the optical GB pixel!", "status": "backlog", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-3973", "title": "I'll parse the back-end ADP array, that should bandwidth the RSS bandwidth!", "status": "todo", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-7962", "title": "Use the wireless RAM program, then you can hack the cross-platform feed!", "status": "cancelled", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-3360", "title": "You can't quantify the program without synthesizing the neural OCR interface!", "status": "done", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-9887", "title": "Use the auxiliary ASCII sensor, then you can connect the solid state port!", "status": "backlog", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-3649", "title": "I'll input the virtual USB system, that should circuit the DNS monitor!", "status": "progress", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-3586", "title": "If we quantify the circuit, we can get to the CLI feed through the mobile SMS hard drive!", "status": "progress", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-5150", "title": "I'll hack the wireless XSS port, that should transmitter the IP interface!", "status": "cancelled", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-3652", "title": "The SQL interface is down, override the optical bus so we can program the ASCII interface!", "status": "backlog", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-6884", "title": "Use the digital PCI circuit, then you can synthesize the multi-byte microchip!", "status": "cancelled", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-1591", "title": "We need to connect the mobile XSS driver!", "status": "progress", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-3802", "title": "Try to override the ASCII protocol, maybe it will parse the virtual matrix!", "status": "progress", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-7253", "title": "Programming the capacitor won't do anything, we need to bypass the neural IB hard drive!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-9739", "title": "We need to hack the multi-byte HDD bus!", "status": "done", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-4424", "title": "Try to hack the HEX alarm, maybe it will connect the optical pixel!", "status": "progress", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-3922", "title": "You can't back up the capacitor without generating the wireless PCI program!", "status": "backlog", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-4921", "title": "I'll index the open-source IP feed, that should system the GB application!", "status": "cancelled", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-5814", "title": "We need to calculate the 1080p AGP feed!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-2645", "title": "Synthesizing the system won't do anything, we need to navigate the multi-byte HDD firewall!", "status": "todo", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-4535", "title": "Try to copy the JSON circuit, maybe it will connect the wireless feed!", "status": "progress", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-4463", "title": "We need to copy the solid state AGP monitor!", "status": "done", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-9745", "title": "If we connect the protocol, we can get to the GB system through the bluetooth PCI microchip!", "status": "cancelled", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-2080", "title": "If we input the bus, we can get to the RAM matrix through the auxiliary RAM card!", "status": "todo", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-3838", "title": "I'll bypass the online TCP application, that should panel the AGP system!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-1340", "title": "We need to navigate the virtual PNG circuit!", "status": "todo", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-6665", "title": "If we parse the monitor, we can get to the SSD hard drive through the cross-platform AGP alarm!", "status": "cancelled", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-7585", "title": "If we calculate the hard drive, we can get to the SSL program through the multi-byte CSS microchip!", "status": "backlog", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-6319", "title": "We need to copy the multi-byte SCSI program!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-4369", "title": "Try to input the SCSI bus, maybe it will generate the 1080p pixel!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-9035", "title": "We need to override the solid state PNG array!", "status": "cancelled", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-3970", "title": "You can't index the transmitter without quantifying the haptic ASCII card!", "status": "todo", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-4473", "title": "You can't bypass the protocol without overriding the neural RSS program!", "status": "todo", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-4136", "title": "You can't hack the hard drive without hacking the primary JSON program!", "status": "cancelled", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-3939", "title": "Use the back-end SQL firewall, then you can connect the neural hard drive!", "status": "done", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-2007", "title": "I'll input the back-end USB protocol, that should bandwidth the PCI system!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-7516", "title": "Use the primary SQL program, then you can generate the auxiliary transmitter!", "status": "done", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-6906", "title": "Try to back up the DRAM system, maybe it will reboot the online transmitter!", "status": "done", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-5207", "title": "The SMS interface is down, copy the bluetooth bus so we can quantify the VGA card!", "status": "progress", "label": "bug", "priority": "low"}] \ No newline at end of file diff --git a/MonsterUI/docs/data_/statuses.json b/MonsterUI/docs/data_/statuses.json new file mode 100644 index 0000000000000000000000000000000000000000..bbfb93bcd0b90c2dbd5b9a1679a3981821ef28bc --- /dev/null +++ b/MonsterUI/docs/data_/statuses.json @@ -0,0 +1,22 @@ +{ + "backlog": { + "icon": "", + "text": "Backlog" + }, + "cancelled": { + "icon": "", + "text": "Cancelled" + }, + "done": { + "icon": "", + "text": "Done" + }, + "progress": { + "icon": "", + "text": "In Progress" + }, + "todo": { + "icon": "", + "text": "Todo" + } +} \ No newline at end of file diff --git a/MonsterUI/docs/examples/auth.py b/MonsterUI/docs/examples/auth.py new file mode 100644 index 0000000000000000000000000000000000000000..da11aa4efaeb4fa1018a5d4445916aad94a62c1b --- /dev/null +++ b/MonsterUI/docs/examples/auth.py @@ -0,0 +1,40 @@ +"""FrankenUI Auth Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +@rt +def index(): + left = Div(cls="col-span-1 hidden flex-col justify-between bg-zinc-900 p-8 text-white lg:flex")( + Div(cls=(TextT.bold))("Acme Inc"), + Blockquote(cls="space-y-2")( + P(cls=TextT.lg)('"This library has saved me countless hours of work and helped me deliver stunning designs to my clients faster than ever before."'), + Footer(cls=TextT.sm)("Sofia Davis"))) + + right = Div(cls="col-span-2 flex flex-col p-8 lg:col-span-1")( + DivRAligned(Button("Login", cls=ButtonT.ghost)), + DivCentered(cls='flex-1')( + Container( + DivVStacked( + H3("Create an account"), + Small("Enter your email below to create your account", cls=TextT.muted)), + Form( + Input(placeholder="name@example.com"), + Button(Span(cls="mr-2", uk_spinner="ratio: 0.54"), "Sign in with Email", cls=(ButtonT.primary, "w-full"), disabled=True), + DividerSplit(Small("Or continue with"),cls=TextT.muted), + Button(UkIcon('github',cls='mr-2'), "Github", cls=(ButtonT.default, "w-full")), + cls='space-y-6'), + DivVStacked(Small( + "By clicking continue, you agree to our ", + A(cls=AT.muted, href="#demo")("Terms of Service")," and ", + A(cls=AT.muted, href="#demo")("Privacy Policy"),".", + cls=(TextT.muted,"text-center"))), + cls="space-y-6"))) + + return Title("Auth Example"),Grid(left,right,cols=2, gap=0,cls='h-screen') + + +serve() diff --git a/MonsterUI/docs/examples/cards.py b/MonsterUI/docs/examples/cards.py new file mode 100644 index 0000000000000000000000000000000000000000..3245108bbe33e20c2b7791f57ed0b8c19bacbd18 --- /dev/null +++ b/MonsterUI/docs/examples/cards.py @@ -0,0 +1,141 @@ +"""FrankenUI Cards Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from fasthtml.components import Uk_input_tag +from fasthtml.svg import * +from monsterui.all import * +import calendar +from datetime import datetime + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +CreateAccount = Card( + Grid(Button(DivLAligned(UkIcon('github'),Div('Github'))),Button('Google')), + DividerSplit("OR CONTINUE WITH", text_cls=TextPresets.muted_sm), + LabelInput('Email', id='email', placeholder='m@example.com'), + LabelInput('Password', id='password',placeholder='Password', type='Password'), + header=(H3('Create an Account'),Subtitle('Enter your email below to create your account')), + footer=Button('Create Account',cls=(ButtonT.primary,'w-full'))) + +PaypalSVG_data = "M7.076 21.337H2.47a.641.641 0 0 1-.633-.74L4.944.901C5.026.382 5.474 0 5.998 0h7.46c2.57 0 4.578.543 5.69 1.81 1.01 1.15 1.304 2.42 1.012 4.287-.023.143-.047.288-.077.437-.983 5.05-4.349 6.797-8.647 6.797h-2.19c-.524 0-.968.382-1.05.9l-1.12 7.106zm14.146-14.42a3.35 3.35 0 0 0-.607-.541c-.013.076-.026.175-.041.254-.93 4.778-4.005 7.201-9.138 7.201h-2.19a.563.563 0 0 0-.556.479l-1.187 7.527h-.506l-.24 1.516a.56.56 0 0 0 .554.647h3.882c.46 0 .85-.334.922-.788.06-.26.76-4.852.816-5.09a.932.932 0 0 1 .923-.788h.58c3.76 0 6.705-1.528 7.565-5.946.36-1.847.174-3.388-.777-4.471z" +AppleSVG_data = "M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701" +Card1Svg = Svg(viewBox="0 0 24 24", fill="none", stroke="currentColor", stroke_linecap="round", stroke_linejoin="round", stroke_width="2", cls="h-6 w-6 mr-1")(Rect(width="20", height="14", x="2", y="5", rx="2"),Path(d="M2 10h20")) +PaypalSvg = Svg(role="img", viewBox="0 0 24 24", cls="h-6 w-6 mr-1")(Path(d=PaypalSVG_data, fill="currentColor")), +AppleSvg = Svg(role="img", viewBox="0 0 24 24", cls="h-6 w-6 mr-1")(Path(d=AppleSVG_data, fill="currentColor")) + +PaymentMethod = Card( + Grid(Button(DivCentered(Card1Svg, "Card"), cls='h-20 border-2 border-primary'), + Button(DivCentered(PaypalSvg, "PayPal"), cls='h-20'), + Button(DivCentered(AppleSvg, "Apple"), cls='h-20')), + Form(LabelInput('Name', id='name', placeholder='John Doe'), + LabelInput('Card Number', id='card_number', placeholder='m@example.com'), + Grid(LabelSelect(*Options(*calendar.month_name[1:],selected_idx=0),label='Expires',id='expire_month'), + LabelSelect(*Options(*range(2024,2030),selected_idx=0), label='Year', id='expire_year'), + LabelInput('CVV', id='cvv',placeholder='CVV', cls='mt-0'))), + header=(H3('Payment Method'),Subtitle('Add a new payment method to your account.'))) + +area_opts = ('Team','Billing','Account','Deployment','Support') +severity_opts = ('Severity 1 (Highest)', 'Severity 2', 'Severity 3', 'Severity 4 (Lowest)') +ReportIssue = Card( + Grid(Div(LabelSelect(*Options(*area_opts), label='Area', id='area')), + Div(LabelSelect(*Options(*severity_opts),label='Severity',id='area'))), + LabelInput( label='Subject', id='subject', placeholder='I need help with'), + LabelTextArea( label='Description', id='description',placeholder='Please include all information relevant to your issue'), + Div(FormLabel('Tags', fr='#tags'), + Uk_input_tag(name="Tags",state="danger", value="Spam,Invalid", uk_cloak=True, id='tags')), + header=(H3('Report Issue'),Subtitle('What area are you having problems with?')), + footer = DivFullySpaced(Button('Cancel'), Button(cls=ButtonT.primary)('Submit'))) + +monster_desc ="Python-first beautifully designed components because you deserve to focus on features that matter and your app deserves to be beautiful from day one." +MonsterUI = Card(H4("Monster UI"), + Subtitle(monster_desc), + DivLAligned( + Div("Python"), + DivLAligned(UkIcon('star'),Div("20k"), cls='space-x-1'), + Div(datetime.now().strftime("%B %d, %Y")), + cls=('space-x-4',TextPresets.muted_sm))) + +def CookieTableRow(heading, description, active=False): + return Tr(Td(H5(heading)), + Td(P(description, cls=TextPresets.muted_sm)), + Td(Switch(checked=active))) + +CookieSettings = Card( + Table(Tbody( + CookieTableRow('Strictly Necessary', 'These cookies are essential in order to use the website and use its features.', True), + CookieTableRow('Functional Cookies', 'These cookies allow the website to provide personalized functionality.'), + CookieTableRow('Performance Cookies', 'These cookies help to improve the performance of the website.'))), + header=(H4('Cookie Settings'),Subtitle('Manage your cookie settings here.')), + footer=Button('Save Preferences', cls=(ButtonT.primary, 'w-full'))) + +team_members = [("Sofia Davis", "m@example.com", "Owner"),("Jackson Lee", "p@example.com", "Member"),] +def TeamMemberRow(name, email, role): + return DivFullySpaced( + DivLAligned( + DiceBearAvatar(name, 10,10), + Div(P(name, cls=(TextT.sm, TextT.medium)), + P(email, cls=TextPresets.muted_sm))), + Button(role, UkIcon('chevron-down', cls='ml-4')), + DropDownNavContainer(map(NavCloseLi, [ + A(Div('Viewer', NavSubtitle('Can view and comment.'))), + A(Div('Developer', NavSubtitle('Can view, comment and edit.'))), + A(Div('Billing', NavSubtitle('Can view, comment and manage billing.'))), + A(Div('Owner', NavSubtitle('Admin-level access to all resources.')))]))) + +TeamMembers = Card(*[TeamMemberRow(*member) for member in team_members], + header = (H4('Team Members'),Subtitle('Invite your team members to collaborate.'))) + +access_roles = ("Read and write access", "Read-only access") +team_members = [("Olivia Martin", "m@example.com", "Read and write access"), + ("Isabella Nguyen", "b@example.com", "Read-only access"), + ("Sofia Davis", "p@example.com", "Read-only access")] + +def TeamMemberRow(name, email, role): + return DivFullySpaced( + DivLAligned(DiceBearAvatar(name, 10,10), + Div(P(name, cls=(TextT.sm, TextT.medium)), + P(email, cls=TextPresets.muted_sm))), + Select(*Options(*access_roles, selected_idx=access_roles.index(role)))) + +ShareDocument = Card( + DivLAligned(Input(value='http://example.com/link/to/document'),Button('Copy link', cls='whitespace-nowrap')), + Divider(), + H4('People with access', cls=TextPresets.bold_sm), + *[TeamMemberRow(*member) for member in team_members], + header = (H4('Share this document'),Subtitle('Anyone with the link can view this document.'))) + +DateCard = Card(Button('Jan 20, 2024 - Feb 09, 2024')) + +section_content =(('bell','Everything',"Email digest, mentions & all activity."), + ('user',"Available","Only mentions and comments"), + ('ban', "Ignoring","Turn of all notifications")) + +def NotificationRow(icon, name, desc): + return Li(cls='-mx-1')(A(DivLAligned(UkIcon(icon),Div(P(name),P(desc, cls=TextPresets.muted_sm))))) + +Notifications = Card( + NavContainer( + *[NotificationRow(*row) for row in section_content], + cls=NavT.secondary), + header = (H4('Notification'),Subtitle('Choose what you want to be notified about.')), + body_cls='pt-0') + +TeamCard = Card( + DivLAligned( + DiceBearAvatar("Isaac Flath", h=24, w=24), + Div(H3("Isaac Flath"), P("Library Creator"))), + footer=DivFullySpaced( + DivHStacked(UkIcon("map-pin", height=16), P("Alexandria, VA")), + DivHStacked(*(UkIconLink(icon, height=16) for icon in ("mail", "linkedin", "github")))), + cls=CardT.hover) + +@rt +def index(): + return Title("Cards Example"),Container(Grid( + *map(Div,( + Div(PaymentMethod,CreateAccount, TeamCard, cls='space-y-4'), + Div(TeamMembers, ShareDocument,DateCard,Notifications, cls='space-y-4'), + Div(ReportIssue,MonsterUI,CookieSettings, cls='space-y-4'))), + cols_md=1, cols_lg=2, cols_xl=3)) + +serve() diff --git a/MonsterUI/docs/examples/dashboard.py b/MonsterUI/docs/examples/dashboard.py new file mode 100644 index 0000000000000000000000000000000000000000..6fb2c627f01f8e86862b909cdd6548016d2a4273 --- /dev/null +++ b/MonsterUI/docs/examples/dashboard.py @@ -0,0 +1,106 @@ +"""FrankenUI Dashboard Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * # Bring in all of fasthtml +import fasthtml.common as fh # Used to get unstyled components +from monsterui.all import * # Bring in all of monsterui, including shadowing fasthtml components with styled components +from fasthtml.svg import * +import numpy as np +import plotly.express as px +import pandas as pd +import numpy as np + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def generate_chart(num_points=30): + df = pd.DataFrame({ + 'Date': pd.date_range('2024-01-01', periods=num_points), + 'Revenue': np.random.normal(100, 10, num_points).cumsum(), + 'Users': np.random.normal(80, 8, num_points).cumsum(), + 'Growth': np.random.normal(60, 6, num_points).cumsum()}) + + fig = px.line(df, x='Date', y=['Revenue', 'Users', 'Growth'], template='plotly_white', line_shape='spline') + + fig.update_traces(mode='lines+markers') + fig.update_layout( + margin=dict(l=20, r=20, t=20, b=20), hovermode='x unified', + showlegend=True, legend=dict(orientation='h', yanchor='bottom', y=1.02, xanchor='right', x=1), + plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', + xaxis=dict(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)'), + yaxis=dict(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)')) + + return fig.to_html(include_plotlyjs=True, full_html=False, config={'displayModeBar': False}) + +def InfoCard(title, value, change): return Card(H3(value),P(change, cls=TextPresets.muted_sm), header = H4(title)) + +rev = InfoCard("Total Revenue", "$45,231.89", "+20.1% from last month") +sub = InfoCard("Subscriptions", "+2350", "+180.1% from last month") +sal = InfoCard("Sales", "+12,234", "+19% from last month") +act = InfoCard("Active Now", "+573", "+201 since last hour") + +info_card_data = [("Total Revenue", "$45,231.89", "+20.1% from last month"), + ("Subscriptions", "+2350", "+180.1% from last month"), + ("Sales", "+12,234", "+19% from last month"), + ("Active Now", "+573", "+201 since last hour")] + +top_info_row = Grid(*[InfoCard(*row) for row in info_card_data]) + +def AvatarItem(name, email, amount): + return DivFullySpaced( + DivLAligned( + DiceBearAvatar(name, 9,9), + Div(Strong(name, cls=TextT.sm), + Address(A(email,href=f'mailto:{email}')))), + fh.Data(amount, cls="ml-auto font-medium", value=amount[2:])) + +recent_sales = Card( + Div(cls="space-y-8")( + *[AvatarItem(n,e,d) for (n,e,d) in ( + ("Olivia Martin", "olivia.martin@email.com", "+$1,999.00"), + ("Jackson Lee", "jackson.lee@email.com", "+$39.00"), + ("Isabella Nguyen", "isabella.nguyen@email.com", "+$299.00"), + ("William Kim", "will@email.com", "+$99.00"), + ("Sofia Davis", "sofia.davis@email.com", "+$39.00"))]), + header=Div(H3("Recent Sales"),Subtitle("You made 265 sales this month.")), + cls='col-span-3') + +teams = [["Alicia Koch"],['Acme Inc', 'Monster Inc.'],['Create a Team']] + +opt_hdrs = ["Personal", "Team", ""] + +team_dropdown = Select( + Optgroup(Option(A("Alicia Koch")), label="Personal Account"), + Optgroup(Option(A("Acme Inc")), Option(A("Monster Inc.")), label="Teams"), + Option(A("Create a Team")), + cls='flex items-center') + +hotkeys = [('Profile','⇧⌘P'),('Billing','⌘B'),('Settings','⌘S'),('New Team', ''), ('Logout', '')] + +def NavSpacedLi(t,s): return NavCloseLi(A(DivFullySpaced(P(t),P(s,cls=TextPresets.muted_sm)))) + +avatar_dropdown = Div( + DiceBearAvatar('Alicia Koch',8,8), + DropDownNavContainer( + NavHeaderLi('sveltecult',NavSubtitle("leader@sveltecult.com")), + *[NavSpacedLi(*hk) for hk in hotkeys],)) + +top_nav = NavBar( + team_dropdown, *map(A, ["Overview", "Customers", "Products", "Settings"]), + brand=DivLAligned(avatar_dropdown, Input(placeholder='Search'))) + +@rt +def index(): + return Title("Dashboard Example"), Container( + top_nav, + H2('Dashboard'), + TabContainer( + Li(A("Overview"),cls='uk-active'), + *map(lambda x: Li(A(x)), ["Analytics", "Reports", "Notifications"]), + alt=True), + top_info_row, + Grid( + Card(Safe(generate_chart(100)), cls='col-span-4'), + recent_sales, + gap=4,cols_xl=7,cols_lg=7,cols_md=1,cols_sm=1,cols_xs=1), + cls=('space-y-4', ContainerT.xl)) + +serve() diff --git a/MonsterUI/docs/examples/data/mail.json b/MonsterUI/docs/examples/data/mail.json new file mode 100644 index 0000000000000000000000000000000000000000..63dc8872689abbb8eacd5a2db84c2cae9e7c909e --- /dev/null +++ b/MonsterUI/docs/examples/data/mail.json @@ -0,0 +1,206 @@ +[ + { + "id": "6c84fb90-12c4-11e1-840d-7b25c5ee775a", + "initial": "WS", + "name": "William Smith", + "email": "williamsmith@example.com", + "subject": "Meeting Tomorrow", + "text": "Hi, let's have a meeting tomorrow to discuss the project. I've been reviewing the project details and have some ideas I'd like to share. It's crucial that we align on our next steps to ensure the project's success.\n\nPlease come prepared with any questions or insights you may have. Looking forward to our meeting!\n\nBest regards, William", + "date": "2023-10-22T09:00:00", + "read": true, + "active": true, + "labels": ["meeting", "work", "important"] + }, + { + "id": "110e8400-e29b-11d4-a716-446655440000", + "initial": "AS", + "name": "Alice Smith", + "email": "alicesmith@example.com", + "subject": "Re: Project Update", + "text": "Thank you for the project update. It looks great! I've gone through the report, and the progress is impressive. The team has done a fantastic job, and I appreciate the hard work everyone has put in.\n\nI have a few minor suggestions that I'll include in the attached document.\n\nLet's discuss these during our next meeting. Keep up the excellent work!\n\nBest regards, Alice", + "date": "2023-10-22T10:30:00", + "read": true, + "active": false, + "labels": ["work", "important"] + }, + { + "id": "3e7c3f6d-bdf5-46ae-8d90-171300f27ae2", + "initial": "BJ", + "name": "Bob Johnson", + "email": "bobjohnson@example.com", + "subject": "Weekend Plans", + "text": "Any plans for the weekend? I was thinking of going hiking in the nearby mountains. It's been a while since we had some outdoor fun.\n\nIf you're interested, let me know, and we can plan the details. It'll be a great way to unwind and enjoy nature.\n\nLooking forward to your response!\n\nBest, Bob", + "date": "2023-04-10T11:45:00", + "read": true, + "active": false, + "labels": ["personal"] + }, + { + "id": "61c35085-72d7-42b4-8d62-738f700d4b92", + "initial": "ED", + "name": "Emily Davis", + "email": "emilydavis@example.com", + "subject": "Re: Question about Budget", + "text": "I have a question about the budget for the upcoming project. It seems like there's a discrepancy in the allocation of resources.\n\nI've reviewed the budget report and identified a few areas where we might be able to optimize our spending without compromising the project's quality.\n\nI've attached a detailed analysis for your reference. Let's discuss this further in our next meeting.\n\nThanks, Emily", + "date": "2023-03-25T13:15:00", + "read": false, + "active": false, + "labels": ["work", "budget"] + }, + { + "id": "8f7b5db9-d935-4e42-8e05-1f1d0a3dfb97", + "initial": "MW", + "name": "Michael Wilson", + "email": "michaelwilson@example.com", + "subject": "Important Announcement", + "text": "I have an important announcement to make during our team meeting. It pertains to a strategic shift in our approach to the upcoming product launch. We've received valuable feedback from our beta testers, and I believe it's time to make some adjustments to better meet our customers' needs.\n\nThis change is crucial to our success, and I look forward to discussing it with the team. Please be prepared to share your insights during the meeting.\n\nRegards, Michael", + "date": "2023-03-10T15:00:00", + "read": false, + "active": false, + "labels": ["meeting", "work", "important"] + }, + { + "id": "1f0f2c02-e299-40de-9b1d-86ef9e42126b", + "initial": "SB", + "name": "Sarah Brown", + "email": "sarahbrown@example.com", + "subject": "Re: Feedback on Proposal", + "text": "Thank you for your feedback on the proposal. It looks great! I'm pleased to hear that you found it promising. The team worked diligently to address all the key points you raised, and I believe we now have a strong foundation for the project.\n\nI've attached the revised proposal for your review.\n\nPlease let me know if you have any further comments or suggestions. Looking forward to your response.\n\nBest regards, Sarah", + "date": "2023-02-15T16:30:00", + "read": true, + "active": false, + "labels": ["work"] + }, + { + "id": "17c0a96d-4415-42b1-8b4f-764efab57f66", + "initial": "DL", + "name": "David Lee", + "email": "davidlee@example.com", + "subject": "New Project Idea", + "text": "I have an exciting new project idea to discuss with you. It involves expanding our services to target a niche market that has shown considerable growth in recent months.\n\nI've prepared a detailed proposal outlining the potential benefits and the strategy for execution.\n\nThis project has the potential to significantly impact our business positively. Let's set up a meeting to dive into the details and determine if it aligns with our current goals.\n\nBest regards, David", + "date": "2023-01-28T17:45:00", + "read": false, + "active": false, + "labels": ["meeting", "work", "important"] + }, + { + "id": "2f0130cb-39fc-44c4-bb3c-0a4337edaaab", + "initial": "OW", + "name": "Olivia Wilson", + "email": "oliviawilson@example.com", + "subject": "Vacation Plans", + "text": "Let's plan our vacation for next month. What do you think? I've been thinking of visiting a tropical paradise, and I've put together some destination options.\n\nI believe it's time for us to unwind and recharge. Please take a look at the options and let me know your preferences.\n\nWe can start making arrangements to ensure a smooth and enjoyable trip.\n\nExcited to hear your thoughts! Olivia", + "date": "2022-12-20T18:30:00", + "read": true, + "active": false, + "labels": ["personal"] + }, + { + "id": "de305d54-75b4-431b-adb2-eb6b9e546014", + "initial": "JM", + "name": "James Martin", + "email": "jamesmartin@example.com", + "subject": "Re: Conference Registration", + "text": "I've completed the registration for the conference next month. The event promises to be a great networking opportunity, and I'm looking forward to attending the various sessions and connecting with industry experts.\n\nI've also attached the conference schedule for your reference.\n\nIf there are any specific topics or sessions you'd like me to explore, please let me know. It's an exciting event, and I'll make the most of it.\n\nBest regards, James", + "date": "2022-11-30T19:15:00", + "read": true, + "active": false, + "labels": ["work", "conference"] + }, + { + "id": "7dd90c63-00f6-40f3-bd87-5060a24e8ee7", + "initial": "SW", + "name": "Sophia White", + "email": "sophiawhite@example.com", + "subject": "Team Dinner", + "text": "Let's have a team dinner next week to celebrate our success. We've achieved some significant milestones, and it's time to acknowledge our hard work and dedication.\n\nI've made reservations at a lovely restaurant, and I'm sure it'll be an enjoyable evening.\n\nPlease confirm your availability and any dietary preferences. Looking forward to a fun and memorable dinner with the team!\n\nBest, Sophia", + "date": "2022-11-05T20:30:00", + "read": false, + "active": false, + "labels": ["meeting", "work"] + }, + { + "id": "99a88f78-3eb4-4d87-87b7-7b15a49a0a05", + "initial": "DJ", + "name": "Daniel Johnson", + "email": "danieljohnson@example.com", + "subject": "Feedback Request", + "text": "I'd like your feedback on the latest project deliverables. We've made significant progress, and I value your input to ensure we're on the right track.\n\nI've attached the deliverables for your review, and I'm particularly interested in any areas where you think we can further enhance the quality or efficiency.\n\nYour feedback is invaluable, and I appreciate your time and expertise. Let's work together to make this project a success.\n\nRegards, Daniel", + "date": "2022-10-22T09:30:00", + "read": false, + "active": false, + "labels": ["work"] + }, + { + "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", + "initial": "AT", + "name": "Ava Taylor", + "email": "avataylor@example.com", + "subject": "Re: Meeting Agenda", + "text": "Here's the agenda for our meeting next week. I've included all the topics we need to cover, as well as time allocations for each.\n\nIf you have any additional items to discuss or any specific points to address, please let me know, and we can integrate them into the agenda.\n\nIt's essential that our meeting is productive and addresses all relevant matters.\n\nLooking forward to our meeting! Ava", + "date": "2022-10-10T10:45:00", + "read": true, + "active": false, + "labels": ["meeting", "work"] + }, + { + "id": "c1a0ecb4-2540-49c5-86f8-21e5ce79e4e6", + "initial": "WA", + "name": "William Anderson", + "email": "williamanderson@example.com", + "subject": "Product Launch Update", + "text": "The product launch is on track. I'll provide an update during our call. We've made substantial progress in the development and marketing of our new product.\n\nI'm excited to share the latest updates with you during our upcoming call. It's crucial that we coordinate our efforts to ensure a successful launch. Please come prepared with any questions or insights you may have.\n\nLet's make this product launch a resounding success!\n\nBest regards, William", + "date": "2022-09-20T12:00:00", + "read": false, + "active": false, + "labels": ["meeting", "work", "important"] + }, + { + "id": "ba54eefd-4097-4949-99f2-2a9ae4d1a836", + "initial": "MH", + "name": "Mia Harris", + "email": "miaharris@example.com", + "subject": "Re: Travel Itinerary", + "text": "I've received the travel itinerary. It looks great! Thank you for your prompt assistance in arranging the details. I've reviewed the schedule and the accommodations, and everything seems to be in order. I'm looking forward to the trip, and I'm confident it'll be a smooth and enjoyable experience.\n\nIf there are any specific activities or attractions you recommend at our destination, please feel free to share your suggestions.\n\nExcited for the trip! Mia", + "date": "2022-09-10T13:15:00", + "read": true, + "active": false, + "labels": ["personal", "travel"] + }, + { + "id": "df09b6ed-28bd-4e0c-85a9-9320ec5179aa", + "initial": "EC", + "name": "Ethan Clark", + "email": "ethanclark@example.com", + "subject": "Team Building Event", + "text": "Let's plan a team-building event for our department. Team cohesion and morale are vital to our success, and I believe a well-organized team-building event can be incredibly beneficial. I've done some research and have a few ideas for fun and engaging activities.\n\nPlease let me know your thoughts and availability. We want this event to be both enjoyable and productive.\n\nTogether, we'll strengthen our team and boost our performance.\n\nRegards, Ethan", + "date": "2022-08-25T15:30:00", + "read": false, + "active": false, + "labels": ["meeting", "work"] + }, + { + "id": "d67c1842-7f8b-4b4b-9be1-1b3b1ab4611d", + "initial": "CH", + "name": "Chloe Hall", + "email": "chloehall@example.com", + "subject": "Re: Budget Approval", + "text": "The budget has been approved. We can proceed with the project. I'm delighted to inform you that our budget proposal has received the green light from the finance department. This is a significant milestone, and it means we can move forward with the project as planned.\n\nI've attached the finalized budget for your reference. Let's ensure that we stay on track and deliver the project on time and within budget.\n\nIt's an exciting time for us! Chloe", + "date": "2022-08-10T16:45:00", + "read": true, + "active": false, + "labels": ["work", "budget"] + }, + { + "id": "6c9a7f94-8329-4d70-95d3-51f68c186ae1", + "initial": "ST", + "name": "Samuel Turner", + "email": "samuelturner@example.com", + "subject": "Weekend Hike", + "text": "Who's up for a weekend hike in the mountains? I've been craving some outdoor adventure, and a hike in the mountains sounds like the perfect escape. If you're up for the challenge, we can explore some scenic trails and enjoy the beauty of nature.\n\nI've done some research and have a few routes in mind.\n\nLet me know if you're interested, and we can plan the details.\n\nIt's sure to be a memorable experience! Samuel", + "date": "2022-07-28T17:30:00", + "read": false, + "active": false, + "labels": ["personal"] + } +] \ No newline at end of file diff --git a/MonsterUI/docs/examples/data/status_list.json b/MonsterUI/docs/examples/data/status_list.json new file mode 100644 index 0000000000000000000000000000000000000000..546f7919aed1f696bb3f2527e6a50238e477f02b --- /dev/null +++ b/MonsterUI/docs/examples/data/status_list.json @@ -0,0 +1 @@ +[{"selected": true, "id": "TASK-8782", "title": "You can't compress the program without quantifying the open-source SSD pixel!", "status": "progress", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-7878", "title": "Try to calculate the EXE feed, maybe it will index the multi-byte pixel!", "status": "backlog", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-7839", "title": "We need to bypass the neural TCP card!", "status": "todo", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-5562", "title": "The SAS interface is down, bypass the open-source pixel so we can back up the PNG bandwidth!", "status": "backlog", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-8686", "title": "I'll parse the wireless SSL protocol, that should driver the API panel!", "status": "cancelled", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-1280", "title": "Use the digital TLS panel, then you can transmit the haptic system!", "status": "done", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-7262", "title": "The UTF8 application is down, parse the neural bandwidth so we can back up the PNG firewall!", "status": "done", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-1138", "title": "Generating the driver won't do anything, we need to quantify the 1080p SMTP bandwidth!", "status": "progress", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-7184", "title": "We need to program the back-end THX pixel!", "status": "todo", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-5160", "title": "Calculating the bus won't do anything, we need to navigate the back-end JSON protocol!", "status": "progress", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-5618", "title": "Generating the driver won't do anything, we need to index the online SSL application!", "status": "done", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-6699", "title": "I'll transmit the wireless JBOD capacitor, that should hard drive the SSD feed!", "status": "backlog", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-2858", "title": "We need to override the online UDP bus!", "status": "backlog", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-9864", "title": "I'll reboot the 1080p FTP panel, that should matrix the HEX hard drive!", "status": "done", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-8404", "title": "We need to generate the virtual HEX alarm!", "status": "progress", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-5365", "title": "Backing up the pixel won't do anything, we need to transmit the primary IB array!", "status": "progress", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-1780", "title": "The CSS feed is down, index the bluetooth transmitter so we can compress the CLI protocol!", "status": "todo", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-6938", "title": "Use the redundant SCSI application, then you can hack the optical alarm!", "status": "todo", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-9885", "title": "We need to compress the auxiliary VGA driver!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-3216", "title": "Transmitting the transmitter won't do anything, we need to compress the virtual HDD sensor!", "status": "backlog", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-9285", "title": "The IP monitor is down, copy the haptic alarm so we can generate the HTTP transmitter!", "status": "todo", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-1024", "title": "Overriding the microchip won't do anything, we need to transmit the digital OCR transmitter!", "status": "progress", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-7068", "title": "You can't generate the capacitor without indexing the wireless HEX pixel!", "status": "cancelled", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-6502", "title": "Navigating the microchip won't do anything, we need to bypass the back-end SQL bus!", "status": "todo", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-5326", "title": "We need to hack the redundant UTF8 transmitter!", "status": "todo", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-6274", "title": "Use the virtual PCI circuit, then you can parse the bluetooth alarm!", "status": "cancelled", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-1571", "title": "I'll input the neural DRAM circuit, that should protocol the SMTP interface!", "status": "progress", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-9518", "title": "Compressing the interface won't do anything, we need to compress the online SDD matrix!", "status": "cancelled", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-5581", "title": "I'll synthesize the digital COM pixel, that should transmitter the UTF8 protocol!", "status": "backlog", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-2197", "title": "Parsing the feed won't do anything, we need to copy the bluetooth DRAM bus!", "status": "todo", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-8484", "title": "We need to parse the solid state UDP firewall!", "status": "progress", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-9892", "title": "If we back up the application, we can get to the UDP application through the multi-byte THX capacitor!", "status": "done", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-9616", "title": "We need to synthesize the cross-platform ASCII pixel!", "status": "progress", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-9744", "title": "Use the back-end IP card, then you can input the solid state hard drive!", "status": "done", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-1376", "title": "Generating the alarm won't do anything, we need to generate the mobile IP capacitor!", "status": "backlog", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-7382", "title": "If we back up the firewall, we can get to the RAM alarm through the primary UTF8 pixel!", "status": "todo", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-2290", "title": "I'll compress the virtual JSON panel, that should application the UTF8 bus!", "status": "cancelled", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-1533", "title": "You can't input the firewall without overriding the wireless TCP firewall!", "status": "done", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-4920", "title": "Bypassing the hard drive won't do anything, we need to input the bluetooth JSON program!", "status": "progress", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-5168", "title": "If we synthesize the bus, we can get to the IP panel through the virtual TLS array!", "status": "progress", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-7103", "title": "We need to parse the multi-byte EXE bandwidth!", "status": "cancelled", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-4314", "title": "If we compress the program, we can get to the XML alarm through the multi-byte COM matrix!", "status": "progress", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-3415", "title": "Use the cross-platform XML application, then you can quantify the solid state feed!", "status": "todo", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-8339", "title": "Try to calculate the DNS interface, maybe it will input the bluetooth capacitor!", "status": "progress", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-6995", "title": "Try to hack the XSS bandwidth, maybe it will override the bluetooth matrix!", "status": "todo", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-8053", "title": "If we connect the program, we can get to the UTF8 matrix through the digital UDP protocol!", "status": "todo", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-4336", "title": "If we synthesize the microchip, we can get to the SAS sensor through the optical UDP program!", "status": "todo", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-8790", "title": "I'll back up the optical COM alarm, that should alarm the RSS capacitor!", "status": "done", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-8980", "title": "Try to navigate the SQL transmitter, maybe it will back up the virtual firewall!", "status": "cancelled", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-7342", "title": "Use the neural CLI card, then you can parse the online port!", "status": "backlog", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-5608", "title": "I'll hack the haptic SSL program, that should bus the UDP transmitter!", "status": "cancelled", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-1606", "title": "I'll generate the bluetooth PNG firewall, that should pixel the SSL driver!", "status": "done", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-7872", "title": "Transmitting the circuit won't do anything, we need to reboot the 1080p RSS monitor!", "status": "cancelled", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-4167", "title": "Use the cross-platform SMS circuit, then you can synthesize the optical feed!", "status": "cancelled", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-9581", "title": "You can't index the port without hacking the cross-platform XSS monitor!", "status": "backlog", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-8806", "title": "We need to bypass the back-end SSL panel!", "status": "done", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-6542", "title": "Try to quantify the RSS firewall, maybe it will quantify the open-source system!", "status": "done", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-6806", "title": "The VGA protocol is down, reboot the back-end matrix so we can parse the CSS panel!", "status": "cancelled", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-9549", "title": "You can't bypass the bus without connecting the neural JBOD bus!", "status": "todo", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-1075", "title": "Backing up the driver won't do anything, we need to parse the redundant RAM pixel!", "status": "done", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-1427", "title": "Use the auxiliary PCI circuit, then you can calculate the cross-platform interface!", "status": "done", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-1907", "title": "Hacking the circuit won't do anything, we need to back up the online DRAM system!", "status": "todo", "label": "documentation", "priority": "high"}, {"selected": false, "id": "TASK-4309", "title": "If we generate the system, we can get to the TCP sensor through the optical GB pixel!", "status": "backlog", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-3973", "title": "I'll parse the back-end ADP array, that should bandwidth the RSS bandwidth!", "status": "todo", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-7962", "title": "Use the wireless RAM program, then you can hack the cross-platform feed!", "status": "cancelled", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-3360", "title": "You can't quantify the program without synthesizing the neural OCR interface!", "status": "done", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-9887", "title": "Use the auxiliary ASCII sensor, then you can connect the solid state port!", "status": "backlog", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-3649", "title": "I'll input the virtual USB system, that should circuit the DNS monitor!", "status": "progress", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-3586", "title": "If we quantify the circuit, we can get to the CLI feed through the mobile SMS hard drive!", "status": "progress", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-5150", "title": "I'll hack the wireless XSS port, that should transmitter the IP interface!", "status": "cancelled", "label": "feature", "priority": "medium"}, {"selected": false, "id": "TASK-3652", "title": "The SQL interface is down, override the optical bus so we can program the ASCII interface!", "status": "backlog", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-6884", "title": "Use the digital PCI circuit, then you can synthesize the multi-byte microchip!", "status": "cancelled", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-1591", "title": "We need to connect the mobile XSS driver!", "status": "progress", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-3802", "title": "Try to override the ASCII protocol, maybe it will parse the virtual matrix!", "status": "progress", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-7253", "title": "Programming the capacitor won't do anything, we need to bypass the neural IB hard drive!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-9739", "title": "We need to hack the multi-byte HDD bus!", "status": "done", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-4424", "title": "Try to hack the HEX alarm, maybe it will connect the optical pixel!", "status": "progress", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-3922", "title": "You can't back up the capacitor without generating the wireless PCI program!", "status": "backlog", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-4921", "title": "I'll index the open-source IP feed, that should system the GB application!", "status": "cancelled", "label": "bug", "priority": "low"}, {"selected": false, "id": "TASK-5814", "title": "We need to calculate the 1080p AGP feed!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-2645", "title": "Synthesizing the system won't do anything, we need to navigate the multi-byte HDD firewall!", "status": "todo", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-4535", "title": "Try to copy the JSON circuit, maybe it will connect the wireless feed!", "status": "progress", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-4463", "title": "We need to copy the solid state AGP monitor!", "status": "done", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-9745", "title": "If we connect the protocol, we can get to the GB system through the bluetooth PCI microchip!", "status": "cancelled", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-2080", "title": "If we input the bus, we can get to the RAM matrix through the auxiliary RAM card!", "status": "todo", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-3838", "title": "I'll bypass the online TCP application, that should panel the AGP system!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-1340", "title": "We need to navigate the virtual PNG circuit!", "status": "todo", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-6665", "title": "If we parse the monitor, we can get to the SSD hard drive through the cross-platform AGP alarm!", "status": "cancelled", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-7585", "title": "If we calculate the hard drive, we can get to the SSL program through the multi-byte CSS microchip!", "status": "backlog", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-6319", "title": "We need to copy the multi-byte SCSI program!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-4369", "title": "Try to input the SCSI bus, maybe it will generate the 1080p pixel!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-9035", "title": "We need to override the solid state PNG array!", "status": "cancelled", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-3970", "title": "You can't index the transmitter without quantifying the haptic ASCII card!", "status": "todo", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-4473", "title": "You can't bypass the protocol without overriding the neural RSS program!", "status": "todo", "label": "documentation", "priority": "low"}, {"selected": false, "id": "TASK-4136", "title": "You can't hack the hard drive without hacking the primary JSON program!", "status": "cancelled", "label": "bug", "priority": "medium"}, {"selected": false, "id": "TASK-3939", "title": "Use the back-end SQL firewall, then you can connect the neural hard drive!", "status": "done", "label": "feature", "priority": "low"}, {"selected": false, "id": "TASK-2007", "title": "I'll input the back-end USB protocol, that should bandwidth the PCI system!", "status": "backlog", "label": "bug", "priority": "high"}, {"selected": false, "id": "TASK-7516", "title": "Use the primary SQL program, then you can generate the auxiliary transmitter!", "status": "done", "label": "documentation", "priority": "medium"}, {"selected": false, "id": "TASK-6906", "title": "Try to back up the DRAM system, maybe it will reboot the online transmitter!", "status": "done", "label": "feature", "priority": "high"}, {"selected": false, "id": "TASK-5207", "title": "The SMS interface is down, copy the bluetooth bus so we can quantify the VGA card!", "status": "progress", "label": "bug", "priority": "low"}] \ No newline at end of file diff --git a/MonsterUI/docs/examples/data/statuses.json b/MonsterUI/docs/examples/data/statuses.json new file mode 100644 index 0000000000000000000000000000000000000000..bbfb93bcd0b90c2dbd5b9a1679a3981821ef28bc --- /dev/null +++ b/MonsterUI/docs/examples/data/statuses.json @@ -0,0 +1,22 @@ +{ + "backlog": { + "icon": "", + "text": "Backlog" + }, + "cancelled": { + "icon": "", + "text": "Cancelled" + }, + "done": { + "icon": "", + "text": "Done" + }, + "progress": { + "icon": "", + "text": "In Progress" + }, + "todo": { + "icon": "", + "text": "Todo" + } +} \ No newline at end of file diff --git a/MonsterUI/docs/examples/forms.py b/MonsterUI/docs/examples/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..fa473bccb47b942b868e4a6cfee563131067fe3c --- /dev/null +++ b/MonsterUI/docs/examples/forms.py @@ -0,0 +1,150 @@ +"""FrankenUI Forms Example built with MonsterUI (original design by ShadCN)""" + + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def HelpText(c): return P(c,cls=TextPresets.muted_sm) + +def heading(): + return Div(cls="space-y-5")( + H2("Settings"), + Subtitle("Manage your account settings and set e-mail preferences."), + DividerSplit()) + + +sidebar = NavContainer( + *map(lambda x: Li(A(x)), ("Profile", "Account", "Appearance", "Notifications", "Display")), + uk_switcher="connect: #component-nav; animation: uk-animation-fade", + cls=(NavT.secondary,"space-y-4 p-4 w-1/5")) + + +def FormSectionDiv(*c, cls='space-y-2', **kwargs): return Div(*c, cls=cls, **kwargs) + +def FormLayout(title, subtitle, *content, cls='space-y-3 mt-4'): return Container(Div(H3(title), Subtitle(subtitle), DividerLine(), Form(*content, cls=cls))) + +def profile_form(): + content = (FormSectionDiv( + LabelInput("Username", placeholder='sveltecult', id='username'), + HelpText("This is your public display name. It can be your real name or a pseudonym. You can only change this once every 30 days.")), + FormSectionDiv( + LabelSelect( + Option("Select a verified email to display", value="", selected=True, disabled=True), + *[Option(o, value=o) for o in ('m@example.com', 'm@yahoo.com', 'm@cloud.com')], + label="Email", id="email"), + HelpText("You can manage verified email addresses in your email settings.")), + FormSectionDiv( + LabelTextArea("Bio", id="bio", placeholder="Tell us a little bit about yourself"), + HelpText("You can @mention other users and organizations to link to them."), + P("String must contain at least 4 character(s)", cls="text-destructive")), + FormSectionDiv( + FormLabel("URLs"), + HelpText("Add links to your website, blog, or social media profiles."), + Input(value="https://www.franken-ui.dev"), + Input(value="https://github.com/sveltecult/franken-ui"), + Button("Add URL")), + Button('Update profile', cls=ButtonT.primary)) + + return FormLayout('Profile', 'This is how others will see you on the site.', *content) + +def account_form(): + content = ( + FormSectionDiv( + LabelInput("Name", placeholder="Your name", id="name"), + HelpText("This is the name that will be displayed on your profile and in emails.")), + FormSectionDiv( + LabelInput("Date of Birth", type="date", placeholder="Pick a date", id="date_of_birth"), + HelpText("Your date of birth is used to calculate your age.")), + FormSectionDiv( + LabelSelect(*Options("Select a language", "English", "French", "German", "Spanish", "Portuguese", selected_idx=1, disabled_idxs={0}), + label='Language', id="language"), + HelpText("This is the language that will be used in the dashboard.")), + Button('Update profile', cls=ButtonT.primary)) + + return FormLayout('Account', 'Update your account settings. Set your preferred language and timezone.', *content) + +def appearance_form(): + def theme_item(bg_color, content_bg, text_bg): + common_content = f"space-y-2 rounded-md {content_bg} p-2 shadow-sm" + item_row = lambda: Div(cls=f"flex items-center space-x-2 {common_content}")( + Div(cls=f"h-4 w-4 rounded-full {text_bg}"), + Div(cls=f"h-2 w-[100px] rounded-lg {text_bg}")) + + return Div(cls=f"space-y-2 rounded-sm {bg_color} p-2")( + Div(cls=common_content)( + Div(cls=f"h-2 w-[80px] rounded-lg {text_bg}"), + Div(cls=f"h-2 w-[100px] rounded-lg {text_bg}")), + item_row(), + item_row()) + + common_toggle_cls = "block cursor-pointer items-center rounded-md border-2 border-muted p-1 ring-ring" + + content = ( + FormSectionDiv( + LabelSelect(*Options('Select a font family', 'Inter', 'Geist', 'Open Sans', selected_idx=2, disabled_idxs={0}), + label='Font Family', id='font_family'), + HelpText("Set the font you want to use in the dashboard.")), + FormSectionDiv( + FormLabel("Theme"), + HelpText("Select the theme for the dashboard."), + Grid( + A(id="theme-toggle-light", cls=common_toggle_cls)(theme_item("bg-[#ecedef]", "bg-white", "bg-[#ecedef]")), + A(id="theme-toggle-dark", cls=f"{common_toggle_cls} bg-popover")(theme_item("bg-slate-950", "bg-slate-800", "bg-slate-400")), + cols_max=2,cls=('max-w-md','gap-8'))), + Button('Update preferences', cls=ButtonT.primary)) + + return FormLayout('Appearance', 'Customize the appearance of the app. Automatically switch between day and night themes.', *content) + + +notification_items = [ + {"title": "Communication emails", "description": "Receive emails about your account activity.", "checked": False, "disabled": False}, + {"title": "Marketing emails", "description": "Receive emails about new products, features, and more.", "checked": False, "disabled": False}, + {"title": "Social emails", "description": "Receive emails for friend requests, follows, and more.", "checked": True, "disabled": False}, + {"title": "Security emails", "description": "Receive emails about your account activity and security.", "checked": True, "disabled": True}] + +def notifications_form(): + def RadioLabel(label): return DivLAligned(Radio(name="notification", checked=(label=="Nothing")), FormLabel(label)) + + def NotificationCard(item): + return Card( + Div(cls="space-y-0.5")( + FormLabel(Strong(item['title'], cls=TextT.sm), + HelpText(item['description'])))) + content = Div( + FormSectionDiv( + FormLabel("Notify me about"), + *map(RadioLabel, ["All new messages", "Direct messages and mentions", "Nothing"])), + Div( + H4("Email Notifications", cls="mb-4"), + Grid(*map(NotificationCard, notification_items), cols=1)), + LabelCheckboxX("Use different settings for my mobile devices", id="notification_mobile"), + HelpText("You can manage your mobile notifications in the mobile settings page."), + Button('Update notifications', cls=ButtonT.primary)) + + return FormLayout('Notifications', 'Configure how you receive notifications.', *content) + +def display_form(): + content = ( + Div(cls="space-y-2")( + Div(cls="mb-4")( + H5("Sidebar"), + Subtitle("Select the items you want to display in the sidebar.")), + *[Div(CheckboxX(id=f"display_{i}", checked=i in [0, 1, 2]),FormLabel(label)) + for i, label in enumerate(["Recents", "Home", "Applications", "Desktop", "Downloads", "Documents"])]), + Button('Update display', cls=ButtonT.primary)) + return FormLayout('Display', 'Turn items on or off to control what\'s displayed in the app.', *content) + +@rt +def index(): + return Title("Forms Example"),Container( + heading(), + Div(cls="flex gap-x-12")( + sidebar, + Ul(id="component-nav", cls="uk-switcher max-w-2xl")( + Li(cls="uk-active")(profile_form(), + *map(Li, [account_form(), appearance_form(), notifications_form(), display_form()]))))) + +serve() diff --git a/MonsterUI/docs/examples/mail.py b/MonsterUI/docs/examples/mail.py new file mode 100644 index 0000000000000000000000000000000000000000..eaa597b5c5ec9883b711dfd0dcbdb62ed883dc00 --- /dev/null +++ b/MonsterUI/docs/examples/mail.py @@ -0,0 +1,111 @@ +"""FrankenUI Mail Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * +import pathlib, json +from datetime import datetime + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +sidebar_group1 = (('home', 'Inbox', '128'), ('file-text', 'Drafts', '9'), (' arrow-up-right', 'Sent', ''), + ('ban', 'Junk', '23'), ('trash', 'Trash', ''), ('folder', 'Archive', '')) + +sidebar_group2 = (('globe','Social','972'),('info','Updates','342'),('messages-square','Forums','128'), + ('shopping-cart','Shopping','8'),('shopping-bag','Promotions','21'),) + +def MailSbLi(icon, title, cnt): + return Li(A(DivLAligned(Span(UkIcon(icon)),Span(title),P(cnt, cls=TextPresets.muted_sm)),href='#', cls='hover:bg-secondary p-4')) + +sidebar = NavContainer( + NavHeaderLi(H3("Email"), cls='p-3'), + Li(Select(map(Option, ('alicia@example.com','alicia@gmail.com', 'alicia@yahoo.com')))), + *[MailSbLi(i, t, c) for i, t, c in sidebar_group1], + Li(Hr()), + *[MailSbLi(i, t, c) for i, t, c in sidebar_group2], + cls='mt-3') + +mail_data = json.load(open(pathlib.Path('data_/mail.json'))) + +def format_date(date_str): + date_obj = datetime.fromisoformat(date_str) + return date_obj.strftime("%Y-%m-%d %I:%M %p") + +def MailItem(mail): + cls_base = 'relative rounded-lg border border-border p-3 text-sm hover:bg-secondary space-y-2' + cls = f"{cls_base} {'bg-muted' if mail == mail_data[0] else ''} {'tag-unread' if not mail['read'] else 'tag-mail'}" + + return Li( + DivFullySpaced( + DivLAligned( + Strong(mail['name']), + Span(cls='flex h-2 w-2 rounded-full bg-blue-600') if not mail['read'] else ''), + Time(format_date(mail['date']), cls='text-xs')), + Small(mail['subject'], href=f"#mail-{mail['id']}"), + Div(mail['text'][:100] + '...', cls=TextPresets.muted_sm), + DivLAligned( + *[Label(A(label, href='#'), cls='uk-label-primary' if label == 'work' else '') for label in mail['labels']]), + cls=cls) + +def MailList(mails): return Ul(cls='js-filter space-y-2 p-4 pt-0')(*[MailItem(mail) for mail in mails]) + +def MailContent(): + return Div(cls='flex flex-col',uk_filter="target: .js-filter")( + Div(cls='flex px-4 py-2 ')( + H3('Inbox'), + TabContainer(Li(A("All Mail",href='#', role='button'),cls='uk-active', uk_filter_control="filter: .tag-mail"), + Li(A("Unread",href='#', role='button'), uk_filter_control="filter: .tag-unread"), + alt=True, cls='ml-auto max-w-40', )), + Div(cls='flex flex-1 flex-col')( + Div(cls='p-4')( + Div(cls='uk-inline w-full')( + Span(cls='uk-form-icon text-muted-foreground')(UkIcon('search')), + Input(placeholder='Search'))), + Div(cls='flex-1 overflow-y-auto max-h-[600px]')(MailList(mail_data)))) + +def IconNavItem(*d): return [Li(A(UkIcon(o[0],uk_tooltip=o[1]))) for o in d] +def IconNav(*c,cls=''): return Ul(cls=f'uk-iconnav {cls}')(*c) + +def MailDetailView(mail): + top_icons = [('folder','Archive'), ('ban','Move to junk'), ('trash','Move to trash')] + reply_icons = [('reply','Reply'), ('reply','Reply all'), ('forward','Forward')] + dropdown_items = ['Mark as unread', 'Star read', 'Add Label', 'Mute Thread'] + + return Container( + DivFullySpaced( + DivLAligned( + DivLAligned(*[UkIcon(o[0],uk_tooltip=o[1]) for o in top_icons]), + Div(UkIcon('clock', uk_tooltip='Snooze'), cls='pl-2'), + cls='space-x-2 divide-x divide-border'), + DivLAligned( + *[UkIcon(o[0],uk_tooltip=o[1]) for o in reply_icons], + Div(UkIcon('ellipsis-vertical',button=True)), + DropDownNavContainer(*map(lambda x: Li(A(x)), dropdown_items)))), + DivLAligned( + Span(mail['name'][:2], cls='flex h-10 w-10 items-center justify-center rounded-full bg-muted'), + Div(Strong(mail['name']), + Div(mail['subject']), + DivLAligned(P('Reply-To:'), A(mail['email'], href=f"mailto:{mail['email']}"), cls='space-x-1'), + P(Time(format_date(mail['date']))), + cls='space-y-1'+TextT.sm), + cls='m-4 space-x-4'), + DividerLine(), + P(mail['text'], cls=TextT.sm +'p-4'), + DividerLine(), + Div(TextArea(id='message', placeholder=f"Reply {mail['name']}"), + DivFullySpaced( + LabelSwitch('Mute this thread',id='mute'), + Button('Send', cls=ButtonT.primary)), + cls='space-y-4')) + +@rt +def index(): + return Title("Mail Example"),Container( + Grid(Div(sidebar, cls='col-span-1'), + Div(MailContent(), cls='col-span-2'), + Div(MailDetailView(mail_data[0]), cls='col-span-2'), + cols_sm=1, cols_md=1, cols_lg=5, cols_xl=5, + gap=0, cls='flex-1'), + cls=('flex', ContainerT.xl)) + +serve() diff --git a/MonsterUI/docs/examples/music.py b/MonsterUI/docs/examples/music.py new file mode 100644 index 0000000000000000000000000000000000000000..5dfd3ef904052f161b99008400a090e70a354f7c --- /dev/null +++ b/MonsterUI/docs/examples/music.py @@ -0,0 +1,138 @@ +"""FrankenUI Music Example build with MonsterUI (Original design by ShadCN)""" + +from fasthtml.common import * + +from monsterui.all import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def MusicLi(t,hk=''): return Li(A(DivFullySpaced(t,P(hk,cls=TextPresets.muted_sm)))) + +music_items = [("About Music", "" ), + ("Preferences", "⌘" ), + ("Hide Music" , "⌘H" ), + ("Hide Others", "⇧⌘H"), + ("Quit Music" , "⌘Q" )] + +file_dd_items = [("New", ""), + ("Open Stream URL", "⌘U"), + ("Close Window", "⌘W"), + ("Library", ""), + ("Import", "⌘O"), + ("Burn Playlist to Disc", ""), + ("Show in Finder", "⇧⌘R"), + ("Convert", ""), + ("Page Setup", "Print")] + +edit_actions = [("Undo", "⌘Z"), + ("Redo", "⇧⌘Z"), + ("Cut", "⌘X"), + ("Copy", "⌘C"), + ("Paste", "⌘V"), + ("Select All", "⌘A"), + ("Deselect All", "⇧⌘A")] + +view_dd_data = ["Show Playing Next", "Show Lyrics", "Show Status Bar", "Hide Sidebar", "Enter Full Screen"] + + +music_headers = NavBar( + Button("Music", cls=ButtonT.ghost+TextT.gray),DropDownNavContainer(Li(A("Music"),NavContainer(map(lambda x: MusicLi(*x), music_items)))), + Button("File", cls=ButtonT.ghost+TextT.gray), DropDownNavContainer(Li(A("File"), NavContainer(map(lambda x: MusicLi(*x), file_dd_items)))), + Button("Edit", cls=ButtonT.ghost+TextT.gray), DropDownNavContainer(Li(A("Edit")),NavContainer( + *map(lambda x: MusicLi(*x), edit_actions), + Li(A(DivFullySpaced("Smart Dictation",UkIcon("mic")))), + Li(A(DivFullySpaced("Emojis & Symbols",UkIcon("globe")))))), + Button("View", cls=ButtonT.ghost+TextT.gray),DropDownNavContainer(Li(A("View"),NavContainer(map(lambda x: MusicLi(x), view_dd_data)))), + brand=DivLAligned(H2("Purrify")) + ) + + + + +# music_headers = NavBarContainer( +# NavBarLSide( +# NavBarNav( +# Li(A("Music"),NavBarNavContainer(map(lambda x: MusicLi(*x), music_items))), +# Li(A("File"), NavBarNavContainer(map(lambda x: MusicLi(*x), file_dd_items))), +# Li(A("Edit")), +# NavBarNavContainer( +# *map(lambda x: MusicLi(*x), edit_actions), +# Li(A(DivFullySpaced("Smart Dictation",UkIcon("mic")))), +# Li(A(DivFullySpaced("Emojis & Symbols",UkIcon("globe"))))), +# Li(A("View"), +# NavBarNavContainer(map(lambda x: MusicLi(x), view_dd_data))), +# Li(A("Account"), +# NavBarNavContainer( +# NavHeaderLi("Switch Account"), +# *map(MusicLi, ("Andy", "Benoit", "Luis", "Manage Family", "Add Account"))))))) + + +def Album(title,artist): + img_url = 'https://ucarecdn.com/e5607eaf-2b2a-43b9-ada9-330824b6afd7/music1.webp' + return Div( + Div(cls="overflow-hidden rounded-md")(Img(cls="transition-transform duration-200 hover:scale-105", src=img_url)), + Div(cls='space-y-1')(Strong(title),P(artist,cls=TextT.muted))) + +listen_now_albums = (("Roar", "Catty Perry"), ("Feline on a Prayer", "Cat Jovi"),("Fur Elise", "Ludwig van Beethovpurr"),("Purrple Rain", "Prince's Cat")) + +made_for_you_albums = [("Like a Feline", "Catdonna"), + ("Livin' La Vida Purrda", "Ricky Catin"), + ("Meow Meow Rocket", "Elton Cat"), + ("Rolling in the Purr", "Catdelle"), + ("Purrs of Silence", "Cat Garfunkel"), + ("Meow Me Maybe", "Carly Rae Purrsen"),] + +music_content = (Div(H3("Listen Now"), cls="mt-6 space-y-1"), + Subtitle("Top picks for you. Updated daily."), + DividerLine(), + Grid(*[Album(t,a) for t,a in listen_now_albums], cls='gap-8'), + Div(H3("Made for You"), cls="mt-6 space-y-1"), + Subtitle("Your personal playlists. Updated daily."), + DividerLine(), + Grid(*[Album(t,a) for t,a in made_for_you_albums], cols_xl=6)) + +tabs = TabContainer( + Li(A('Music', href='#'), cls='uk-active'), + Li(A('Podcasts', href='#')), + Li(A('Live', cls='opacity-50'), cls='uk-disabled'), + uk_switcher='connect: #component-nav; animation: uk-animation-fade', + alt=True) + +def podcast_tab(): + return Div( + Div(cls='space-y-3 mt-6')( + H3("New Episodes"), + Subtitle("Your favorite podcasts. Updated daily.")), + Div(cls="uk-placeholder flex h-[450px] items-center justify-center rounded-md mt-4",uk_placeholder=True)( + DivVStacked(cls="space-y-6")( + UkIcon("microphone", 3), + H4("No episodes added"), + Subtitle("You have not added any podcasts. Add one below."), + Button("Add Podcast", cls=ButtonT.primary)))) + +discoved_data = [("play-circle","Listen Now"), ("binoculars", "Browse"), ("rss","Radio")] +library_data = [("play-circle", "Playlists"), ("music", "Songs"), ("user", "Made for You"), ("users", "Artists"), ("bookmark", "Albums")] +playlists_data = [("library","Recently Added"), ("library","Recently Played")] + +def MusicSidebarLi(icon, text): return Li(A(DivLAligned(UkIcon(icon), P(text)))) +sidebar = NavContainer( + NavHeaderLi(H3("Discover")), *[MusicSidebarLi(*o) for o in discoved_data], + NavHeaderLi(H3("Library")), *[MusicSidebarLi(*o) for o in library_data], + NavHeaderLi(H3("Playlists")),*[MusicSidebarLi(*o) for o in playlists_data], + cls=(NavT.primary,'space-y-3','pl-8')) + +@rt +def index(): + return Title("Music Example"),Container(music_headers, DividerSplit(), + Grid(sidebar, + Div(cls="col-span-4 border-l border-border")( + Div(cls="px-8 py-6")( + DivFullySpaced( + Div(cls="max-w-80")(tabs), + Button(cls=ButtonT.primary)(DivLAligned(UkIcon('circle-plus')),Div("Add music"))), + Ul(id="component-nav", cls="uk-switcher")( + Li(*music_content), + Li(podcast_tab())))), + cols_sm=1, cols_md=1, cols_lg=5, cols_xl=5)) + +serve() diff --git a/MonsterUI/docs/examples/playground.py b/MonsterUI/docs/examples/playground.py new file mode 100644 index 0000000000000000000000000000000000000000..85597897583d0075102fc2893df34e8161c13045 --- /dev/null +++ b/MonsterUI/docs/examples/playground.py @@ -0,0 +1,69 @@ +"""FrankenUI Playground Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +preset_options = ["Grammatical Standard English", "Summarize for a 2nd grader", + "Text to command","Q&A","English to other languages","Parse unstructured data", + "Classification","Natural language to Python","Explain code","Chat","More examples"] + +def playground_navbar(): + save_modal = Modal( + ModalTitle("Save preset"), + P("This will save the current playground state as a preset which you can access later or share with others.",cls=("mt-1.5", TextPresets.muted_sm)), + LabelInput("Name", id="name"), + LabelInput("Description", id="description"), + ModalCloseButton("Save", cls=ButtonT.primary), + id="save") + + share_dd = Div(cls="space-y-6 p-4")( + H3("Share preset"), + P("Anyone who has this link and an OpenAI account will be able to view this.", cls=TextPresets.muted_sm), + Div(Input(value="https://platform.openai.com/playground/p/7bbKYQvsVkNmVb8NGcdUOLae?model=text-davinci-003", readonly=True), + Button(UkIcon('copy'), cls=(ButtonT.primary, "uk-drop-close",'mt-4')))) + + rnav = ( + Select(*Options(*preset_options), name='preset', optgroup_label="Examples", + placeholder='Load a preset', searchable=True, cls='h-9 w-[200px] lg:w-[300px]'), + Button("Save", cls=ButtonT.secondary, data_uk_toggle="#save"),save_modal, + Button("View Code", cls=ButtonT.secondary), + Button("Share", cls=ButtonT.secondary),DropDownNavContainer(share_dd), + Button(UkIcon(icon="ellipsis"), cls=ButtonT.secondary), + DropDownNavContainer( + Li(A("Content filter preferences")), + NavDividerLi(), + Li(A("Delete preset", cls="text-destructive")), + uk_dropdown="mode: click")) + + return NavBar(*rnav, brand=H4('Playground')) + +rsidebar = NavContainer( + Select( + Optgroup(map(Option,("text-davinci-003", "text-curie-001", "text-babbage-001", "text-ada-001")),label='GPT-3'), + Optgroup(map(Option,("code-davinci-002", "code-cushman-001")),label='Codex'), + label="Model", + searchable=True), + LabelRange(label='Temperature', value='12'), + LabelRange(label='Maximum Length', value='80'), + LabelRange(label='Top P', value='40'), + cls='space-y-6 mt-8') + +@rt +def index(): + navbar = playground_navbar() + main_content = Div( + Div(cls="flex-1")( + Textarea(cls="uk-textarea h-full p-4", placeholder="Write a tagline for an ice cream shop")), + cls="flex h-[700px] p-8 w-4/5") + + bottom_buttons = Div( + Button("Submit", cls=ButtonT.primary), + Button(UkIcon(icon="history"), cls=ButtonT.secondary), + cls="flex gap-x-2") + + return Title("Playground Example"),Div(navbar, Div(cls="flex w-full")(main_content, rsidebar), bottom_buttons) + +serve() diff --git a/MonsterUI/docs/examples/scrollspy.py b/MonsterUI/docs/examples/scrollspy.py new file mode 100644 index 0000000000000000000000000000000000000000..09cfa0895975bbc1bba980827507324b2aaf5a6d --- /dev/null +++ b/MonsterUI/docs/examples/scrollspy.py @@ -0,0 +1,125 @@ +"MonsterUI Scrollspy Example application" + +from fasthtml.common import * +from monsterui.all import * +import random + +# Using the "slate" theme with Highlight.js enabled +hdrs = Theme.slate.headers(highlightjs=True) +app, rt = fast_app(hdrs=hdrs) + +################################ +### Example Data and Content ### +################################ +products = [ + {"name": "Laptop", "price": "$999"}, + {"name": "Smartphone", "price": "$599"} +] + +code_example = """ +# Python Code Example +def greet(name): + return f"Hello, {name}!" + +print(greet("World")) +""" +testimonials = [ + {"name": "Alice", "feedback": "Great products and excellent customer service!"}, + {"name": "Bob", "feedback": "Fast shipping and amazing quality!"}, + {"name": "Charlie", "feedback": "Amazing experience! Will definitely buy again."}, + {"name": "Diana", "feedback": "Affordable prices and great variety!"}, + {"name": "Edward", "feedback": "Customer support was very helpful."}, + {"name": "Fiona", "feedback": "Loved the design and quality!"} +] + +# Team members +team = [ + {"name": "Isaac Flath", "role": "CEO"}, + {"name": "Benjamin Clavié", "role": "AI Researcher"}, + {"name": "Alexis Gallagher", "role": "ML Engineer"}, + {"name": "Hamel Husain", "role": "Data Scientist"}, + {"name": "Austin Huang", "role": "Software Engineer"}, + {"name": "Benjamin Warner", "role": "Product Manager"}, + {"name": "Jonathan Whitaker", "role": "UX Designer"}, + {"name": "Kerem Turgutlu", "role": "DevOps Engineer"}, + {"name": "Curtis Allan", "role": "DevOps Engineer"}, + {"name": "Audrey Roy Greenfeld", "role": "Security Analyst"}, + {"name": "Nathan Cooper", "role": "Full Stack Developer"}, + {"name": "Jeremy Howard", "role": "CTO"}, + {"name": "Wayde Gilliam", "role": "Cloud Architect"}, + {"name": "Daniel Roy Greenfeld", "role": "Blockchain Expert"}, + {"name": "Tommy Collins", "role": "AI Ethics Researcher"} +] + + +def ProductCard(p,img_id=1): + return Card( + PicSumImg(w=500, height=100, id=img_id), + DivFullySpaced(H4(p["name"]), P(Strong(p["price"], cls=TextT.sm))), + Button("Details", cls=(ButtonT.primary, "w-full"))) + +def TestimonialCard(t,img_id=1): + return Card( + DivLAligned(PicSumImg(w=50, h=50, cls='rounded-full', id=img_id), H4(t["name"])), + P(Q((t["feedback"])))) + + +def TeamCard(m,img_id=1): + return Card( + DivLAligned( + PicSumImg(w=50, h=50, cls='rounded-full', id=img_id), + Div(H4(m["name"]), P(m["role"]))), + DivRAligned( + UkIcon('twitter', cls='w-5 h-5'), + UkIcon('linkedin', cls='w-5 h-5'), + UkIcon('github', cls='w-5 h-5'), + cls=TextT.gray+'space-x-2' + ), + cls='p-3') + +################################ +### Navigation and Scrollspy ### +################################ + +scrollspy_links = ( + A("Welcome", href="#welcome-section"), + A("Products", href="#products-section"), + A("Testimonials", href="#testimonials-section"), + A("Team", href="#team-section"), + A("Code Example", href="#code-section")) +@rt +def index(): + def _Section(*c, **kwargs): return Section(*c, cls='space-y-3 my-48',**kwargs) + return Container( + NavBar( + *scrollspy_links, + brand=DivLAligned(H3("Scrollspy Demo!"),UkIcon('rocket',height=30,width=30)), + sticky=True, uk_scrollspy_nav=True, + scrollspy_cls=ScrollspyT.bold), + NavContainer( + *map(Li, scrollspy_links), + uk_scrollspy_nav=True, + sticky=True, + cls=(NavT.primary,'pt-20 px-5 pr-10')), + Container( + # Notice the ID of each section corresponds to the `scrollspy_links` dictionary + # So in scollspy `NavContainer` the `href` of each `Li` is the ID of the section + DivCentered( + H1("Welcome to the Store!"), + Subtitle("Explore our products and enjoy dynamic code examples."), + id="welcome-section"), + _Section(H2("Products"), + Grid(*[ProductCard(p,img_id=i) for i,p in enumerate(products)], cols_lg=2), + id="products-section"), + _Section(H2("Testimonials"), + Slider(*[TestimonialCard(t,img_id=i) for i,t in enumerate(testimonials)]), + id="testimonials-section"), + _Section(H2("Our Team"), + Grid(*[TeamCard(m,img_id=i) for i,m in enumerate(team)], cols_lg=2, cols_max=3), + id="team-section"), + _Section(H2("Code Example"), + CodeBlock(code_example, lang="python"), + id="code-section")), + cls=(ContainerT.xl,'uk-container-expand')) + +serve() diff --git a/MonsterUI/docs/examples/tasks.py b/MonsterUI/docs/examples/tasks.py new file mode 100644 index 0000000000000000000000000000000000000000..c057cfbdc67d702c80cf2be303672de2da7d9132 --- /dev/null +++ b/MonsterUI/docs/examples/tasks.py @@ -0,0 +1,118 @@ +"""FrankenUI Tasks Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * +import json + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def LAlignedCheckTxt(txt): return DivLAligned(UkIcon(icon='check'), P(txt, cls=TextPresets.muted_sm)) + +with open('data_/status_list.json', 'r') as f: data = json.load(f) +with open('data_/statuses.json', 'r') as f: statuses = json.load(f) + +def _create_tbl_data(d): + return {'Done': d['selected'], 'Task': d['id'], 'Title': d['title'], + 'Status' : d['status'], 'Priority': d['priority'] } + +data = [_create_tbl_data(d) for d in data] +page_size = 15 +current_page = 0 +paginated_data = data[current_page*page_size:(current_page+1)*page_size] + +priority_dd = [{'priority': "low", 'count': 36 }, {'priority': "medium", 'count': 33 }, {'priority': "high", 'count': 31 }] + +status_dd = [{'status': "backlog", 'count': 21 },{'status': "todo", 'count': 21 },{'status': "progress", 'count': 20 },{'status': "done",'count': 19 },{'status': "cancelled", 'count': 19 }] + +def create_hotkey_li(hotkey): return NavCloseLi(A(DivFullySpaced(hotkey[0], Span(hotkey[1], cls=TextPresets.muted_sm)))) + +hotkeys_a = (('Profile','⇧⌘P'),('Billing','⌘B'),('Settings','⌘S'),('New Team','')) +hotkeys_b = (('Logout',''), ) + +avatar_opts = DropDownNavContainer( + NavHeaderLi(P('sveltecult'),NavSubtitle('leader@sveltecult.com')), + NavDividerLi(), + *map(create_hotkey_li, hotkeys_a), + NavDividerLi(), + *map(create_hotkey_li, hotkeys_b),) + +def CreateTaskModal(): + return Modal( + Div(cls='p-6')( + ModalTitle('Create Task'), + P('Fill out the information below to create a new task', cls=TextPresets.muted_sm), + Br(), + Form(cls='space-y-6')( + Grid(Div(Select(*map(Option,('Documentation', 'Bug', 'Feature')), label='Task Type', id='task_type')), + Div(Select(*map(Option,('In Progress', 'Backlog', 'Todo', 'Cancelled', 'Done')), label='Status', id='task_status')), + Div(Select(*map(Option, ('Low', 'Medium', 'High')), label='Priority', id='task_priority'))), + TextArea(label='Title', placeholder='Please describe the task that needs to be completed'), + DivRAligned( + ModalCloseButton('Cancel', cls=ButtonT.ghost), + ModalCloseButton('Submit', cls=ButtonT.primary), + cls='space-x-5'))), + id='TaskForm') + +page_heading = DivFullySpaced(cls='space-y-2')( + Div(cls='space-y-2')( + H2('Welcome back!'),P("Here's a list of your tasks for this month!", cls=TextPresets.muted_sm)), + Div(DiceBearAvatar("sveltcult",8,8),avatar_opts)) + +table_controls =(Input(cls='w-[250px]',placeholder='Filter task'), + Button("Status"), + DropDownNavContainer(map(NavCloseLi,[A(DivFullySpaced(P(a['status']), P(a['count'])),cls='capitalize') for a in status_dd])), + Button("Priority"), + DropDownNavContainer(map(NavCloseLi,[A(DivFullySpaced(LAlignedCheckTxt(a['priority']), a['count']),cls='capitalize') for a in priority_dd])), + Button("View"), + DropDownNavContainer(map(NavCloseLi,[A(LAlignedCheckTxt(o)) for o in ['Title','Status','Priority']])), + Button('Create Task',cls=(ButtonT.primary, TextPresets.bold_sm), data_uk_toggle="target: #TaskForm")) + +def task_dropdown(): + return Div(Button(UkIcon('ellipsis')), + DropDownNavContainer( + map(NavCloseLi,[ + *map(A,('Edit', 'Make a copy', 'Favorite')), + A(DivFullySpaced(*[P(o, cls=TextPresets.muted_sm) for o in ('Delete', '⌘⌫')]))]))) +def header_render(col): + match col: + case "Done": return Th(CheckboxX(), shrink=True) + case 'Actions': return Th("", shrink=True) + case _: return Th(col, expand=True) + +def cell_render(col, val): + def _Td(*args,cls='', **kwargs): return Td(*args, cls=f'p-2 {cls}',**kwargs) + match col: + case "Done": return _Td(shrink=True)(CheckboxX(selected=val)) + case "Task": return _Td(val, cls='uk-visible@s') # Hide on small screens + case "Title": return _Td(val, cls='font-medium', expand=True) + case "Status" | "Priority": return _Td(cls='uk-visible@m uk-text-nowrap capitalize')(Span(val)) + case "Actions": return _Td(task_dropdown(), shrink=True) + case _: raise ValueError(f"Unknown column: {col}") + +task_columns = ["Done", 'Task', 'Title', 'Status', 'Priority', 'Actions'] + +tasks_table = Div(cls='mt-4')( + TableFromDicts( + header_data=task_columns, + body_data=paginated_data, + body_cell_render=cell_render, + header_cell_render=header_render, + sortable=True, + cls=(TableT.responsive, TableT.sm, TableT.divider))) + + +def footer(): + total_pages = (len(data) + page_size - 1) // page_size + return DivFullySpaced( + Div('1 of 100 row(s) selected.', cls=TextPresets.muted_sm), + DivLAligned( + DivCentered(f'Page {current_page + 1} of {total_pages}', cls=TextT.sm), + DivLAligned(*[UkIconLink(icon=i, button=True) for i in ('chevrons-left', 'chevron-left', 'chevron-right', 'chevrons-right')]))) + +tasks_ui = Div(DivFullySpaced(DivLAligned(table_controls), cls='mt-8'), tasks_table, footer()) + +@rt +def index(): return Container(page_heading, tasks_ui, CreateTaskModal()) + +serve() diff --git a/MonsterUI/docs/examples/ticket.py b/MonsterUI/docs/examples/ticket.py new file mode 100644 index 0000000000000000000000000000000000000000..4d86c0fdbee336f49f6690f48d9d8e30f0d83da4 --- /dev/null +++ b/MonsterUI/docs/examples/ticket.py @@ -0,0 +1,95 @@ +"""MonsterUI Help Desk Example - Professional Dashboard with DaisyUI components""" +from fasthtml.common import * +from monsterui.all import * +from datetime import datetime + +app, rt = fast_app(hdrs=Theme.blue.headers(daisy=True)) + +def TicketSteps(step): + return Steps( + LiStep("Submitted", data_content="📝", + cls=StepT.success if step > 0 else StepT.primary if step == 0 else StepT.neutral), + LiStep("In Review", data_content="🔎", + cls=StepT.success if step > 1 else StepT.primary if step == 1 else StepT.neutral), + LiStep("Processing", data_content="⚙️", + cls=StepT.success if step > 2 else StepT.primary if step == 2 else StepT.neutral), + LiStep("Resolved", data_content="✅", + cls=StepT.success if step > 3 else StepT.primary if step == 3 else StepT.neutral), + cls="w-full") + +def StatusBadge(status): + styles = {'high': AlertT.error, 'medium': AlertT.warning,'low': AlertT.info} + alert_type = styles.get(status, AlertT.info) + return Alert(f"{status.title()} Priority", cls=(alert_type,"w-32 shadow-sm")) + +def TicketCard(id, title, description, status, step, department): + return Card( + CardHeader( + DivFullySpaced( + Div(H3(f"#{id}", cls=TextT.muted), + H4(title), + cls='space-y-2'), + StatusBadge(status))), + CardBody( + P(description, cls=(TextT.muted, "mb-6")), + DividerSplit(cls="my-6"), + TicketSteps(step), + DividerSplit(cls="my-6"), + DivFullySpaced( + Div(Strong("Department"), + P(department), + cls=('space-y-3', TextPresets.muted_sm)), + Div(Strong("Last Updated"), + P(Time(datetime.now().strftime('%b %d, %H:%M'))), + cls=('space-y-3', TextPresets.muted_sm)), + Button("View Details", cls=ButtonT.primary), + cls='mt-6')), + cls=CardT.hover) + +def NewTicketModal(): + return Modal( + ModalHeader(H3("Create New Support Ticket")), + ModalBody( + Alert( + DivLAligned(UkIcon("info"), Span("Please provide as much detail as possible to help us assist you quickly.")), + cls=(AlertT.info,"mb-4")), + Form( + Grid(LabelInput("Title", id="title", placeholder="Brief description of your issue"), + LabelSelect(Options("IT Support", "HR", "Facilities", "Finance"), label="Department", id="department")), + LabelSelect(Options("Low", "Medium", "High"), label="Priority Level", id="priority"), + LabelTextArea("Description", id="description", placeholder="Please provide detailed information about your issue"), + DivRAligned( + Button("Cancel", cls=ButtonT.ghost, data_uk_toggle="target: #new-ticket"), + Button(Loading(cls=LoadingT.spinner), "Submit Ticket", cls=ButtonT.primary, data_uk_toggle="target: #success-toast; target: #new-ticket")), + cls='space-y-8')), + id="new-ticket") + +@rt +def index(): + tickets = [ + {'id': "TK-1001", 'title': "Cloud Storage Access Error", + 'description': "Unable to access cloud storage with persistent authorization errors. Multiple users affected across marketing department.", + 'status': 'high', 'step': 2, 'department': 'IT Support'}, + {'id': "TK-1002", 'title': "Email Integration Issue", + 'description': "Exchange server not syncing with mobile devices. Affecting external client communications.", + 'status': 'medium', 'step': 1, 'department': 'IT Support'}, + {'id': "TK-1003", 'title': "Office Equipment Setup", + 'description': "New department printer needs configuration and network integration. Required for upcoming client presentation.", + 'status': 'low', 'step': 0, 'department': 'Facilities'} + ] + + return Title("Help Desk Dashboard"), Container( + Section( + DivFullySpaced( + H2("Active Tickets"), + Button(UkIcon("plus-circle", cls="mr-2"), "New Ticket", cls=ButtonT.primary, data_uk_toggle="target: #new-ticket"), + cls='mb-8'), + Grid(*[TicketCard(**ticket) for ticket in tickets], cols=1), + cls="my-6"), + NewTicketModal(), + Toast(DivLAligned(UkIcon('check-circle', cls='mr-2'), "Ticket submitted successfully! Our team will review it shortly."), id="success-toast", alert_cls=AlertT.success, cls=(ToastHT.end, ToastVT.bottom)), + Loading(htmx_indicator=True, type=LoadingT.dots, cls="fixed top-0 right-0 m-4"), + cls="mx-auto max-w-7xl" + ) + +serve() \ No newline at end of file diff --git a/MonsterUI/docs/favicon.ico b/MonsterUI/docs/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..713a1d6faf8c590b8411b60efee511e278fe7325 --- /dev/null +++ b/MonsterUI/docs/favicon.ico @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f07da47ab7b8723e505f2f614213ca0202ee44c5368a62fc563bb3c4eedaa76e +size 270398 diff --git a/MonsterUI/docs/getting_started/GettingStarted.md b/MonsterUI/docs/getting_started/GettingStarted.md new file mode 100644 index 0000000000000000000000000000000000000000..8724fd1c26efdcb349c4f39b3d26bce0e44743ff --- /dev/null +++ b/MonsterUI/docs/getting_started/GettingStarted.md @@ -0,0 +1,98 @@ +# MonsterUI + +MonsterUI is a UI framework for FastHTML for building beautiful web interfaces with minimal code. It combines the simplicity of Python with the power of Tailwind. Perfect for data scientists, ML engineers, and developers who want to quickly turn their Python code into polished web apps without the complexity of traditional UI frameworks. Follows semantic HTML patterns when possible. + +MonsterUI adds the following Tailwind-based libraries [Franken UI](https://franken-ui.dev/) and [DaisyUI](https://daisyui.com/) to FastHTML, as well as Python's [Mistletoe](https://github.com/miyuchina/mistletoe) for Markdown, [HighlightJS](https://highlightjs.org/) for code highlighting, and [Katex](https://katex.org/) for latex support. + +# Getting Started + +## Installation + +To install this library, uses + +`pip install MonsterUI` + +## Getting Started + +### TLDR + +Run `python file.py` on this to start: + +``` python +from fasthtml.common import * +from monsterui.all import * + +# Choose a theme color (blue, green, red, etc) +hdrs = Theme.blue.headers() + +# Create your app with the theme +app, rt = fast_app(hdrs=hdrs) + +@rt +def index(): + socials = (('github','https://github.com/AnswerDotAI/MonsterUI'), + ('twitter','https://twitter.com/isaac_flath/'), + ('linkedin','https://www.linkedin.com/in/isaacflath/')) + return Titled("Your First App", + Card( + H1("Welcome!"), + P("Your first MonsterUI app", cls=TextPresets.muted_sm), + P("I'm excited to see what you build with MonsterUI!"), + footer=DivLAligned(*[UkIconLink(icon,href=url) for icon,url in socials]))) + +serve() +``` + +## LLM context files + +Using LLMs for development is a best practice way to get started and +explore. While LLMs cannot code for you, they can be helpful assistants. +You must check, refactor, test, and vet any code any LLM generates for +you - but they are helpful productivity tools. Take a look inside the +`llms.txt` file to see links to particularly useful context files! + +- [llms.txt](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/llms.txt): Links to what is included +- [llms-ctx.txt](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/llms-ctx.txt): MonsterUI Documentation Pages +- [API list](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/apilist.txt): API list for MonsterUI (included in llms-ctx.txt) +- [llms-ctx-full.txt](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/llms-ctx-full.txt): Full context that includes all api reference pages as markdown + +In addition you can add `/md` (for markdown) to a url to get a markdown representation and `/rmd` for rendered markdown representation (nice for looking to see what would be put into context. + +### Step by Step + +To get started, check out: + +1. Start by importing the modules as follows: + +``` python +from fasthtml.common import * +from monsterui.all import * +``` + +2. Instantiate the app with the MonsterUI headers + +``` python +app = FastHTML(hdrs=Theme.blue.headers()) + +# Alternatively, using the fast_app method +app, rt = fast_app(hdrs=Theme.slate.headers()) +``` + +> *The color option can be any of the theme options available out of the +> box* + +> `katex` and `highlightjs` are not included by default. To include them set `katex=True` or `highlightjs=True` when calling `.headers`. (i.e. `Theme.slate.headers(katex=True)`)* + +From here, you can explore the API Reference & examples to see how to +implement the components. You can also check out these demo videos to as +a quick start guide: + +- MonsterUI [documentation page and Tutorial + app](https://monsterui.answer.ai/tutorial_app) +- Isaac & Hamel : [Building his website’s team + page](https://youtu.be/22Jn46-mmM0) +- Isaac & Audrey : [Building a blog](https://youtu.be/gVWAsywxLXE) +- Isaac : [Building a blog](https://youtu.be/22NJgfAqgko) + +More resources and improvements to the documentation will be added here +soon! diff --git a/MonsterUI/docs/getting_started/StylingRulesOfThumb.py b/MonsterUI/docs/getting_started/StylingRulesOfThumb.py new file mode 100644 index 0000000000000000000000000000000000000000..7aa28655a9d6dc8d566aa57f5cefd60090c4ec92 --- /dev/null +++ b/MonsterUI/docs/getting_started/StylingRulesOfThumb.py @@ -0,0 +1,110 @@ +from fasthtml.common import * +from monsterui.all import * +from utils import create_flippable_card, fn2code_string + +def prerequisites(): + return Section( + H2("Prerequisites"), + P("""The MonsterUI library automatically handles a lot of styling for you, but it assumes you structure your page with HTML. + If you aren't familiar with the basics of HTML, check out the """, + A("W3 Schools HTML references", href="https://www.w3schools.com/html", cls=AT.muted), + " to learn more about the basics of HTML."), + cls='my-4 py-4' + ) + +def next_steps(): + return Section( + H2("Next Steps"), + P("""Once you have a good grasp of HTML, you can reference the following resources to continue to expand your capabilities. Instead of trying to learn all of these, focus on the ones that are relevant to something specific you want to do."""), + List(map(Li, [ + A("Improving Aesthetics with Spacing", href="https://frankenui.fasthtml.io/docs/getting_started/SpacingTutorial", cls=AT.muted), + A("Manipulating Page and Element Layout", href="https://frankenui.fasthtml.io/docs/getting_started/LayoutTutorial", cls=AT.muted), + A("FlexBox Froggy", href="https://flexboxfroggy.com/", cls=AT.muted), + A("Accessibility", href="https://frankenui.fasthtml.io/docs/getting_started/Accessibility", cls=AT.muted), + ]), cls=ListT.bullet), + cls='my-4 py-4' + ) + +def page(): + return Article( + ArticleTitle("Styling Rules of Thumb"), + ArticleMeta("A guide to making a pretty good looking website in a hurry"), + prerequisites(), + next_steps(), + # button_section(), + # typography_section(), + ) + + +def accessibility_section(): + # TODO: Alt tags + # TODO: Aria labels + # TODO: High contrast + # TODO: Prefers reduced motion + pass + +def further_reading(): + # TODO: Tailwind CSS + # TODO: FlexBox Froggy + # TODO: Accessibility + pass + +def button_section(): + def _ex_buttons(): + return Form( + Grid(LabelInput("Email"), + LabelInput("Name"), + cols=2), + Grid(Button("Submit Information", cls=ButtonT.primary), + Button("Delete Information", cls=ButtonT.destructive), + Button("Cancel"), + cols=3) + ) + + return Section( + H2("Pick button styles based on desired behavior"), + Blockquote("The aethetic of a button should match the desired behavior",cls='uk-blockquote mb-8'), + Strong("What to do:"), + List( + Li("Use ButtonT.primary for the most important actions (ie add to card, checkout, etc.)"), + Li("Use ButtonT.secondary for actions that are important but not the primary action (ie save, etc.)"), + Li("Use ButtonT.destructive for destructive actions"), + Li("Use default styling for UX actions (ie go cancel, close etc.)"), + cls=ListT.bullet + ), + create_flippable_card(*fn2code_string(_ex_buttons)), + cls='my-4 py-4' + ) + +def typography_section(): + def _ex_typography(): + return Div(cls='space-y-5')( + Div(cls='space-y-3')( + H1("The main heading"), + Blockquote("A section describing easy ways to make generally good looking text"), + ), + Div(cls='space-y-3')( + H2("My First Section"), + P("A short description of what's in this section", cls=TextPresets.muted_sm), + P("""Now I can write the main content of the page with a normal P tag. + We can use this for longer text like paragraphs. + It's ideal because this text is highly readable. + I can write longer sentences and paragraphs without is being really hard to read with highly styled text. + Often if you aren't careful with styling you can make the text hard to read, especially if you aren't thinking about light vs dark backgrounds. + """)) + ) + + + return Section( + H2("Use consistent typography"), + Blockquote("Consistency is key to a polished user experience",cls='uk-blockquote mb-8'), + Strong("What to do:"), + List( + Li("Use H1-4 for headings"), + Li("Use P with cls=TextPresets.muted_sm subheadings like "), + Li("Use P for most body text"), + cls=ListT.bullet), + create_flippable_card(*fn2code_string(_ex_typography)), + cls='my-4 py-4' + ) + diff --git a/MonsterUI/docs/getting_started/app_product_gallery.py b/MonsterUI/docs/getting_started/app_product_gallery.py new file mode 100644 index 0000000000000000000000000000000000000000..110a048cf8b99de27f76433c5ebdc78e187a87cc --- /dev/null +++ b/MonsterUI/docs/getting_started/app_product_gallery.py @@ -0,0 +1,96 @@ +from fasthtml.common import * +# MonsterUI shadows fasthtml components with the same name +from monsterui.all import * +# If you don't want shadowing behavior, you use import monsterui.core as ... style instead + +# Get frankenui and tailwind headers via CDN using Theme.blue.headers() +hdrs = Theme.blue.headers() + +# fast_app is shadowed by MonsterUI to make it default to no Pico, and add body classes +# needed for frankenui theme styling +app, rt = fast_app(hdrs=hdrs) + +# Examples Product Data to render in the gallery and detail pages   +products = [ + {"name": "Laptop", "price": "$999", "img": "https://picsum.photos/400/100?random=1"}, + {"name": "Smartphone", "price": "$599", "img": "https://picsum.photos/400/100?random=2"}, + {"name": "Headphones", "price": "$199", "img": "https://picsum.photos/400/100?random=3"}, + {"name": "Smartwatch", "price": "$299", "img": "https://picsum.photos/400/100?random=4"}, + {"name": "Tablet", "price": "$449", "img": "https://picsum.photos/400/100?random=5"}, + {"name": "Camera", "price": "$799", "img": "https://picsum.photos/400/100?random=6"},] + +def ProductCard(p): + # Card does lots of boilerplate classes so you can just pass in the content + return Card( + # width:100% makes the image take the full width so we are guarenteed that we won't + # have the image cut off or not large enough. Because all our images are a consistent + # size we do not need to worry about stretching or skewing the image, this is ideal. + # If you have images of different sizes, you will need to use object-fit:cover and/or + # height to either strech, shrink, or crop the image. It is much better to adjust your + # images to be a consistent size upfront so you don't have to handle edge cases of + # different images skeweing/stretching differently. + Img(src=p["img"], alt=p["name"], style="width:100%"), + # All components can take a cls argument to add additional styling - `mt-2` adds margin + # to the top (see spacing tutorial for details on spacing). + # + # Often adding space makes a site look more put together - usually the 2 - 5 range is a + # good choice + H4(p["name"], cls="mt-2"), + # There are helpful Enums, such as TextPresetsT, ButtonT, ContainerT, etc that allow for easy + # discoverability of class options. + # bold_sm is helpful for things that you want to look like regular text, but stand out + # visually for emphasis. + P(p["price"], cls=TextPresets.bold_sm), + # ButtonT.primary is useful for actions you really want the user to take (like adding + # something to the card) - these stand out visually. For dangerous actions (like + # deleting something) you generally would want to use ButtonT.destructive. For UX actions + # that aren't a goal of the page (like cancelling something that hasn't been submitted) + # you generally want the default styling. + Button("Click me!", cls=(ButtonT.primary, "mt-2"), + # HTMX can be used as normal on any component + hx_get=product_detail.to(product_name=p['name']), + hx_push_url='true', + hx_target='body')) + +@rt +def index(): + # Titled using a H1 title, sets the page title, and wraps contents in Main(Container(...)) using + # frankenui styles. Generally you will want to use Titled for all of your pages + return Titled("Example Store Front!", + Grid(*[ProductCard(p) for p in products], cols_lg=3)) + +example_product_description = """\n +This is a sample detailed description of the {product_name}. You can see when clicking on the card +from the gallery you can: + ++ Have a detailed description of the product on the page ++ Have an order form to fill out and submit ++ Anything else you want! +""" + +@rt +def product_detail(product_name:str): + return Titled("Product Detail", + # Grid lays out its children in a responsive grid + Grid( + Div( + H1(product_name), + # render_md is a helper that renders markdown into HTML using frankenui styles. + render_md(example_product_description.format(product_name=product_name))), + Div( + H3("Order Form"), + # Form automatically has a class of 'space-y-3' for a margin between each child. + Form( + # LabelInput is a convience wrapper for a label and input that links them. + LabelInput("Name", id='name'), + LabelInput("Email", id='email'), + LabelInput("Quantity", id='quantity'), + # ButtonT.primary because this is the primary action of the page! + Button("Submit", cls=ButtonT.primary)) + + ), + # Grid has defaults and args for cols at different breakpoints, but you can pass in + # your own to customize responsiveness. + cols_lg=2)) + +serve() diff --git a/MonsterUI/docs/guides/Layout.ipynb b/MonsterUI/docs/guides/Layout.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..526d6948bb9af0dc8b364f9a038c53ac449e17f0 --- /dev/null +++ b/MonsterUI/docs/guides/Layout.ipynb @@ -0,0 +1,591 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "09a2b6fa", + "metadata": {}, + "source": [ + "# MonterUI Page Layout Guide \n", + "\n", + "This guide will discuss 3 tools for laying out your app pages, Grid, Flexbox, and Columns. This page will discuss the strengths and when to use each individually, and then a section for how to combine them for more complex layouts at the end.\n", + "\n", + "> Note: This guide is designed to get you started building layouts quickly, not to teach you all the details needed to build every possible custom layout with pixel-perfect control. To get more detailed and lower-level control, explore the tailwind docs.\n", + "\n", + "\n", + "This guide is for creating flexible layouts you envision, but does not discuss responsiveness to make different layouts that are both mobile and desktop friendly. Stay tunes for a responsiveness guide that will help with that!" + ] + }, + { + "cell_type": "markdown", + "id": "3bdf365b", + "metadata": {}, + "source": [ + "# Grid\n", + "\n", + "Grids are best for regular predictable layouts with lots of the same shape of things that may need to change a lot for different screen sizes. I think the best way to see what it can do is to see a bunch of examples, so here they are!" + ] + }, + { + "cell_type": "markdown", + "id": "7d1bc6e0", + "metadata": {}, + "source": [ + "## Minimal Image Cards\n", + "\n", + "This is a minimal example of a grid that just shows image and text. This is the foundation for many more complex layouts so make sure to understand what's going on here first before moving on!\n", + "\n", + "A grid lays things out in a...grid. As you can see, we have evenly sized cards by default." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "8b6ef3ea", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "def picsum_img(seed): return Img(src=f'https://picsum.photos/300/200?random={seed}')\n", + " \n", + "Grid(*[Card(picsum_img(i),P(f\"Image {i}\")) for i in range(6)])" + ] + }, + { + "cell_type": "markdown", + "id": "c35376e2", + "metadata": {}, + "source": [ + "## Dashboard Example" + ] + }, + { + "cell_type": "markdown", + "id": "a7c9149c", + "metadata": {}, + "source": [ + "However, they don't have to be evenly sized! By providing `row-span-{int}` and `col-span-{int}` we can control how many rows or columns specific grid elements take up. By doing this, we can create a grid that has lots of different shapes and types of elements.\n", + "\n", + "Let's look at a dashboard layout at an examples of this." + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "5abd8bd1", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def StatCard(title, value, color='primary'):\n", + " \"A card with a statistics. Since there is no row/col span class it will take up 1 slot\"\n", + " return Card(P(title, cls=TextPresets.muted_sm), H3(value, cls=f'text-{color}'),)\n", + "\n", + "stats = [StatCard(*data) for data in [\n", + " (\"Total Users\", \"1,234\", \"blue-600\"),\n", + " (\"Active Now\", \"342\", \"green-600\"),\n", + " (\"Revenue\", \"$45,678\", \"purple-600\"),\n", + " (\"Conversion\", \"2.4%\", \"amber-600\")]]\n", + "\n", + "def ChartCard(title): \n", + " \"A card for a chart. col-span-2 means it will take up 2 columns\"\n", + " return Div(cls=\"col-span-2\")( \n", + " Card(H3(title),Div(\"Chart Goes Here\", cls=\"h-64 uk-background-muted\")))\n", + "chart_cards = [ChartCard(title) for title in (\"Monthly Revenue\", \"User Growth\")]\n", + "\n", + "\n", + "sidebar = Form(\n", + " H3(\"SideBar\"),\n", + " LabelRange(\"Range For Filters\", min=0, max=100),\n", + " LabelInput(\"A search Bar\"),\n", + " LabelSelect(map(Option, [\"Product Line A\", \"Product Line B\", \"Product Line C\", \"Product Line D\"]),\n", + " label=\"Choose Product Line\"),\n", + " LabelCheckboxX(\"Include Inactive Users\"),\n", + " LabelCheckboxX(\"Include Users without order\"),\n", + " LabelCheckboxX(\"Include Users without email\"),\n", + " # This sidebar will take up 2 rows b/c of row-span-2\n", + " cls='row-span-2 space-y-5'\n", + ")\n", + "\n", + "Container(Grid(sidebar, *stats, *chart_cards, cols=5))" + ] + }, + { + "cell_type": "markdown", + "id": "cc9bb132", + "metadata": {}, + "source": [ + "# Flexbox" + ] + }, + { + "cell_type": "markdown", + "id": "1dcb8075", + "metadata": {}, + "source": [ + "Using Grid for the overall layout, and flex for the individual elements is a powerful pattern. With `MonsterUI` you can do quite a bit without knowing anything about flexbox, which is what will be taught here. \n", + "\n", + "However, flexbox is well worth learning about it in more detail. You will run into situations where you need more flexbox knowledge than is covered here to build your vision. Thankfully you can get that knowledge by playing a [fantastic tutorial game called FlexBox Froggy](https://flexboxfroggy.com/)!" + ] + }, + { + "cell_type": "markdown", + "id": "d10557e5", + "metadata": {}, + "source": [ + "## Forms\n", + "\n", + "Often you want to stack things horizontally. You can use the `DivHStacked` component to do this.\n", + "\n", + "`DivHStacked` is a helper function for flexbox and creates a div with these classes by default `cls=(FlexT.block, FlexT.row, FlexT.middle, 'space-x-4')`. " + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "eaa39f3a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": 71, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def InputGroup(label, placeholder='', button_text='Submit', cls=''):\n", + " # Div H Stacked makes the label and input show up on the same row instead of putting the input on a newline\n", + " return DivHStacked(\n", + " FormLabel(label, cls='whitespace-nowrap'),\n", + " Input(placeholder=placeholder))\n", + "\n", + "Container(\n", + " H3(\"Form with Input Groups\"),\n", + " Form(cls='space-y-4')(\n", + " InputGroup(\"Search Users\", \"Enter username...\"),\n", + " InputGroup(\"Filter Tags\", \"Add tags...\", \"Add\"),\n", + " InputGroup(\"Email List\", \"Enter email...\", \"Subscribe\"),\n", + " Div(*( Button(UkIcon(icon, cls='mr-2'), text) for icon, text in [(\"rocket\", \"Submit\"), (\"circle-x\", \"Cancel\")]), cls='space-x-4')))" + ] + }, + { + "cell_type": "markdown", + "id": "c4afd0d0", + "metadata": {}, + "source": [ + "## Avatar " + ] + }, + { + "cell_type": "markdown", + "id": "9154ae8f", + "metadata": {}, + "source": [ + "You can use this same `DivHStacked` to align things like text next to images. And you can use `DivVStacked` to stack things vertically to create design structures you like. `DivVStacked` works by using `cls=(FlexT.block,FlexT.column,FlexT.middle)`" + ] + }, + { + "cell_type": "code", + "execution_count": 170, + "id": "f782c6ca", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "\"Avatar\"
\n", + "

John Doe

\n", + "

john@example.com

\n", + "

+1-123-456-7890

\n", + "
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((span((img((),{'alt': 'Avatar', 'loading': 'lazy', 'src': 'https://api.dicebear.com/8.x/lorelei/svg?seed=user', 'class': 'aspect-square h-20 w-20'}),),{'class': 'relative flex h-20 w-20 shrink-0 overflow-hidden rounded-full bg-accent'}), div((p(('John Doe',),{'class': 'uk-text-large '}), p(('john@example.com',),{'class': 'uk-text-muted '}), p(('+1-123-456-7890',),{'class': 'uk-text-muted '})),{'class': 'uk-flex uk-flex-column uk-flex-middle '})),{'class': 'uk-flex uk-flex-row uk-flex-middle space-x-4'})" + ] + }, + "execution_count": 170, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# DivHStacked makes the a single row so text is to on same line as avatar\n", + "DivHStacked(\n", + " DiceBearAvatar(\"user\"), \n", + " # DivVStacked stacks things vertically together and centers it with flex\n", + " DivVStacked(\n", + " P(\"John Doe\", cls=TextT.lg),\n", + " P(\"john@example.com\", cls=TextT.muted), \n", + " P(\"+1-123-456-7890\"), cls=TextT.muted))" + ] + }, + { + "cell_type": "markdown", + "id": "6234fdf8", + "metadata": {}, + "source": [ + "## Pricing Card\n", + "\n", + "These can be combined with icons and other styling to create larger components like a pricing card." + ] + }, + { + "cell_type": "code", + "execution_count": 165, + "id": "f1846dc1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

Pro Plan

\n", + "

$99

\n", + "

per month

\n", + "
\n", + "
    \n", + "
    \n", + "
  • Unlimited users
  • \n", + "
    \n", + "
    \n", + "
  • 24/7 priority support
  • \n", + "
    \n", + "
    \n", + "
  • Custom branding options
  • \n", + "
    \n", + "
    \n", + "
  • Advanced analytics dashboard
  • \n", + "
    \n", + "
    \n", + "
  • Full API access
  • \n", + "
    \n", + "
    \n", + "
  • Priority request queue
  • \n", + "
    \n", + "
\n", + "
\n", + "
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((div((div((div((h2(('Pro Plan',),{'class': 'uk-h2 '}), h3(('$99',),{'class': 'uk-h3 text-primary'}), p(('per month',),{'class': 'uk-text-muted '})),{'class': 'uk-flex uk-flex-column uk-flex-middle space-y-1'}), ul((div((uk-icon((),{'icon': 'check', 'class': 'text-green-500 mr-2'}), li(('Unlimited users',),{})),{'class': 'uk-flex uk-flex-row uk-flex-middle space-x-4'}), div((uk-icon((),{'icon': 'check', 'class': 'text-green-500 mr-2'}), li(('24/7 priority support',),{})),{'class': 'uk-flex uk-flex-row uk-flex-middle space-x-4'}), div((uk-icon((),{'icon': 'check', 'class': 'text-green-500 mr-2'}), li(('Custom branding options',),{})),{'class': 'uk-flex uk-flex-row uk-flex-middle space-x-4'}), div((uk-icon((),{'icon': 'check', 'class': 'text-green-500 mr-2'}), li(('Advanced analytics dashboard',),{})),{'class': 'uk-flex uk-flex-row uk-flex-middle space-x-4'}), div((uk-icon((),{'icon': 'check', 'class': 'text-green-500 mr-2'}), li(('Full API access',),{})),{'class': 'uk-flex uk-flex-row uk-flex-middle space-x-4'}), div((uk-icon((),{'icon': 'check', 'class': 'text-green-500 mr-2'}), li(('Priority request queue',),{})),{'class': 'uk-flex uk-flex-row uk-flex-middle space-x-4'})),{'class': 'space-y-4'}), button(('Subscribe Now',),{'type': 'submit', 'class': 'uk-btn uk-btn-primary w-full'})),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}),),{'class': 'uk-flex uk-flex-column uk-flex-middle space-y-4'})" + ] + }, + "execution_count": 165, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "features = [\n", + " \"Unlimited users\",\n", + " \"24/7 priority support\",\n", + " \"Custom branding options\", \n", + " \"Advanced analytics dashboard\",\n", + " \"Full API access\",\n", + " \"Priority request queue\"\n", + "]\n", + "\n", + "\n", + "def PricingCard(plan, price, features):\n", + " \"Create a polished pricing card with consistent styling\"\n", + " return Card(\n", + " DivVStacked( # Center and veritcally stack the plan name and price\n", + " H2(plan),\n", + " H3(price, cls='text-primary'),\n", + " P('per month',cls=TextT.muted),\n", + " cls='space-y-1'),\n", + " # DivHStacked makes green check and feature Li show up on same row instead of newline\n", + " Ul(*[DivHStacked(UkIcon('check', cls='text-green-500 mr-2'), Li(feature)) for feature in features], \n", + " cls='space-y-4'),\n", + " Button(\"Subscribe Now\", cls=(ButtonT.primary, 'w-full')))\n", + "\n", + "DivVStacked(PricingCard(\"Pro Plan\", \"$99\", features))" + ] + }, + { + "cell_type": "markdown", + "id": "ddf9cf78", + "metadata": {}, + "source": [ + "## Footer\n", + "\n", + "Or you can combine things to make advanced footers that have titles, organized links, and icons!\n", + "\n", + "In this example we add another flex helper function, `DivFullySpaced`. `DivFullySpaced` is a flex class that puts as much space between items as possible" + ] + }, + { + "cell_type": "code", + "execution_count": 176, + "id": "ee79e8cf", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "
\n", + "

Company Name

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

Company

\n", + "AboutBlogCareersPress Kit
\n", + " \n", + " \n", + "
\n", + "

© 2024 Company Name. All rights reserved.

\n", + "
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((div((div((h3(('Company Name',),{'class': 'uk-h3 '}), div((uk-icon((),{'icon': 'twitter', 'class': }), uk-icon((),{'icon': 'facebook', 'class': }), uk-icon((),{'icon': 'github', 'class': }), uk-icon((),{'icon': 'linkedin', 'class': })),{'class': 'uk-flex uk-flex-row uk-flex-middle space-x-4'})),{'class': 'uk-flex uk-flex-between uk-flex-middle w-full'}), hr((),{'class': 'my-4 h-[2px] w-full bg-secondary'}), div((div((h4(('Company',),{'class': 'uk-h4 '}), a(('About',),{'href': '#about', 'class': }), a(('Blog',),{'href': '#blog', 'class': }), a(('Careers',),{'href': '#careers', 'class': }), a(('Press Kit',),{'href': '#press-kit', 'class': })),{'class': 'uk-flex uk-flex-column uk-flex-middle space-y-4'}), div((h4(('Resources',),{'class': 'uk-h4 '}), a(('Documentation',),{'href': '#documentation', 'class': }), a(('Help Center',),{'href': '#help-center', 'class': }), a(('Status',),{'href': '#status', 'class': }), a(('Contact Sales',),{'href': '#contact-sales', 'class': })),{'class': 'uk-flex uk-flex-column uk-flex-middle space-y-4'}), div((h4(('Legal',),{'class': 'uk-h4 '}), a(('Terms of Service',),{'href': '#terms-of-service', 'class': }), a(('Privacy Policy',),{'href': '#privacy-policy', 'class': }), a(('Cookie Settings',),{'href': '#cookie-settings', 'class': }), a(('Accessibility',),{'href': '#accessibility', 'class': })),{'class': 'uk-flex uk-flex-column uk-flex-middle space-y-4'})),{'class': 'uk-flex uk-flex-between uk-flex-middle w-full'}), hr((),{'class': 'my-4 h-[2px] w-full bg-secondary'}), p(('© 2024 Company Name. All rights reserved.',),{'class': 'uk-text-small uk-text-lead'})),{'class': 'space-y-8'}),),{'class': 'uk-container bg-gray-50 py-12'})" + ] + }, + "execution_count": 176, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def FooterLinkGroup(title, links):\n", + " # DivVStacked centers and makes title and each link stack vertically\n", + " return DivVStacked(\n", + " H4(title),\n", + " *[A(text, href=f\"#{text.lower().replace(' ', '-')}\", cls=TextT.muted) for text in links])\n", + "\n", + "company = [\"About\", \"Blog\", \"Careers\", \"Press Kit\"]\n", + "resource = [\"Documentation\", \"Help Center\", \"Status\", \"Contact Sales\"]\n", + "legal = [\"Terms of Service\", \"Privacy Policy\", \"Cookie Settings\", \"Accessibility\"]\n", + "\n", + "Container(cls='uk-background-muted py-12')(Div(\n", + " # Company Name and social icons will be on the same row with as much sapce between as possible\n", + " DivFullySpaced( \n", + " H3(\"Company Name\"),\n", + " # DivHStacked makes the icons be on the same row in a group\n", + " DivHStacked(*[UkIcon(icon, cls=TextT.lead) for icon in \n", + " ['twitter', 'facebook', 'github', 'linkedin']])),\n", + " DividerLine(),\n", + " DivFullySpaced( # Each child will be spread out as much as possible based on number of children\n", + " FooterLinkGroup(\"Company\", company),\n", + " FooterLinkGroup(\"Resources\", resource),\n", + " FooterLinkGroup(\"Legal\", legal)), \n", + " DividerLine(),\n", + " P(\"© 2024 Company Name. All rights reserved.\", cls=TextT.lead+TextT.sm),\n", + " cls='space-y-8 p-8'))" + ] + }, + { + "cell_type": "markdown", + "id": "bb311899", + "metadata": {}, + "source": [ + "## Dashboard" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "1e29f9de", + "metadata": {}, + "outputs": [], + "source": [ + "def StatsCard(label, value, change):\n", + " color = 'green' if change[0] == '+' else 'red'\n", + " return Card(DivVStacked( # Stacks vertically and centers all elements\n", + " P(label, cls=TextPresets.muted_sm),\n", + " H3(value),\n", + " P(f\"{change}% from last month\", cls=f\"text-{color}-600 text-sm\")))\n", + " \n", + "def RecentActivity(user, action, time):\n", + " return DivHStacked( # Makes Avatar and text be on same row\n", + " DiceBearAvatar(user, h=8, w=8),\n", + " P(f\"{user} {action}\", cls=\"flex-1\"),\n", + " P(time, cls=TextPresets.muted_sm))\n", + " \n", + "DivVStacked( # Centers the entire dashboard layout\n", + " # Page header\n", + " DivVStacked( # Stacks vertically and centers the title/subtitle\n", + " H2(\"Welcome back, Isaac!\"),\n", + " P(\"Here's what's happening with your projects today.\",cls=TextT.muted)),\n", + "\n", + " # DivHStacked puts all the stats cards on the same row\n", + " DivHStacked(*(StatsCard(label, value, change)\n", + " for label, value, change in [\n", + " (\"Total Projects\", \"12\", \"+2.5\"),\n", + " (\"Hours Logged\", \"164\", \"+12.3\"),\n", + " (\"Tasks Complete\", \"64%\", \"-4.1\"),\n", + " (\"Team Velocity\", \"23\", \"+8.4\")]\n", + " )),\n", + "\n", + " # Recent activity\n", + " Card(*(RecentActivity(user, action, time) \n", + " for user, action, time in [\n", + " (\"Sarah Chen\", \"completed Project Alpha deployment\", \"2h ago\"),\n", + " (\"James Wilson\", \"commented on Project Beta\", \"4h ago\"),\n", + " (\"Maria Garcia\", \"uploaded new design files\", \"6h ago\"),\n", + " (\"Alex Kumar\", \"started Sprint Planning\", \"8h ago\")]),\n", + " header=H3(\"Recent Activity\"),\n", + " ),\n", + " cls=\"space-y-6\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "edd8dc07", + "metadata": {}, + "source": [ + "## Columns\n", + "\n", + "Columns are a great for sections that have a lot of text." + ] + }, + { + "cell_type": "code", + "execution_count": 181, + "id": "6dfbd634", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "

Lorem Ipsum

\n", + "
\n", + "

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do \n", + " eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad \n", + " minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip \n", + " ex ea commodo consequat.

\n", + "
\n", + "

Duis aute irure dolor in reprehenderit in voluptate velit esse \n", + " cillum dolore eu fugiat nulla pariatur.

\n", + "
\n", + "

Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \n", + " officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde \n", + " omnis iste natus error sit voluptatem accusantium doloremque laudantium.

\n", + "

Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit \n", + " aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem \n", + " sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor.

\n", + "
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((h1(('Lorem Ipsum',),{'class': 'uk-h1 text-center mb-8'}), div((p(('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do \\n eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad \\n minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip \\n ex ea commodo consequat.',),{'class': 'uk-paragraph '}), div((p(('Duis aute irure dolor in reprehenderit in voluptate velit esse \\n cillum dolore eu fugiat nulla pariatur.',),{'class': 'uk-text-large uk-text-bold uk-text-center uk-text-italic text-primary'}),),{'class': 'uk-flex uk-flex-column uk-flex-middle uk-flex-center mt-8'}), p(('Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \\n officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde \\n omnis iste natus error sit voluptatem accusantium doloremque laudantium.',),{'class': 'uk-paragraph '}), p(('Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit \\n aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem \\n sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor.',),{'class': 'uk-paragraph '})),{'class': 'columns-2 gap-12'})),{'class': 'uk-container mt-5 uk-container-xlarge'})" + ] + }, + "execution_count": 181, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Container(\n", + " H1(\"Lorem Ipsum\", cls=\"text-center mb-8\"),\n", + "\n", + " # Use 2 columns for the main content\n", + " Div(cls=\"columns-2 gap-12\")(\n", + " P(\"\"\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do \n", + " eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad \n", + " minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip \n", + " ex ea commodo consequat.\"\"\"),\n", + "\n", + " DivCentered(cls='mt-8')(\n", + " P(\"\"\"Duis aute irure dolor in reprehenderit in voluptate velit esse \n", + " cillum dolore eu fugiat nulla pariatur.\"\"\", \n", + " cls=(TextT.lg, TextT.bold, TextT.center, TextT.italic, \"text-primary\"))),\n", + "\n", + " P(\"\"\"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \n", + " officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde \n", + " omnis iste natus error sit voluptatem accusantium doloremque laudantium.\"\"\"),\n", + "\n", + " P(\"\"\"Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit \n", + " aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem \n", + " sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor.\"\"\")))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/MonsterUI/docs/guides/Spacing.ipynb b/MonsterUI/docs/guides/Spacing.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..f5e770467107c2626785ae2710bd66f7f4538f56 --- /dev/null +++ b/MonsterUI/docs/guides/Spacing.ipynb @@ -0,0 +1,482 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ce15239f", + "metadata": {}, + "source": [ + "# Padding & Margin & Spacing, Oh my! (MonsterUI Spacing Guide)\n", + "\n", + "This guide will cover some essentials about how to properly space apps and what the differences are between:\n", + "\n", + "- Padding\n", + "- Margin\n", + "- Spacing\n", + "- Gap\n", + "\n", + "Manipulating the space between components can make a huge difference to the percieved quality of the page. Being able to tweak the spacing can have a big impact!\n", + "\n", + "> Tip: I find it works best to get everything on the page without adjusting spacing much, and adjusting spacing at the end. \n", + "\n", + "## Abreviations:\n", + "\n", + "First a few abbreviations that are helpful to know with tailwind (and a convention we follow in `MonsterUI`).\n", + "\n", + "- `t`, `b`, `l`, `r` = top, bottom, left, right\n", + "- `p`, `m` = padding, margin\n", + "- `x`, `y` = horizontal, vertical\n", + "\n", + "That means:\n", + "\n", + "- `mt` means margin on top of the element\n", + "- `px` means padding on the x axis (both left and right)\n", + "- `space-y` means apply spacing on the y axis (both top and bottom)\n", + "\n", + "## Padding vs Margin\n", + "\n", + "Margin applies space to the left of the component, and padding applies space on the left inside of the component. \n", + "\n", + "Please reference the example with cards below:\n", + "\n", + "- `ml-20` applies space to the left of the card (outside the card)\n", + "- `pl-20` applies space on the left inside of the card (inside the card)\n", + "\n", + "This means that if you want to move the whole thing but keep the actual container unchanged, use margin. If you want to change the container by adding space inside of it, use padding." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "aef6844a", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card with ml-20

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card with pl-20

\n", + "
\n", + "
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((div((div((h4(('A Simple Card with ml-20',),{'class': 'uk-h4 ', 'style': 'background-color: red'}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card ml-20'}), div((div((h4(('A Simple Card with pl-20',),{'class': 'uk-h4 ', 'style': 'background-color: red'}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card pl-20'})),{'class': 'grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 gap-4'})" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Grid(\n", + " Card(H4(\"A Simple Card with ml-20\",style='background-color: red'), \n", + " cls='ml-20'),\n", + " Card(H4(\"A Simple Card with pl-20\", style='background-color: red'),\n", + " cls='pl-20'))" + ] + }, + { + "cell_type": "markdown", + "id": "59ed6d0d", + "metadata": {}, + "source": [ + "## Space vs gap\n", + "\n", + "Spacing and gap are both about setting the space between components.\n", + "\n", + "+ Spacing applies margin to every element except for the first element in a group. \n", + "+ Gap creates a gap between every element in flexbox elements and grids.\n", + "\n", + ">Rule of thumb: Use Gap when using grids.\n", + "\n", + "Let's take a look at some grid examples." + ] + }, + { + "cell_type": "markdown", + "id": "22ad2226", + "metadata": {}, + "source": [ + "#### Grid" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "a296d044", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '})),{'class': 'grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 '})" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Grid(\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " cls='')" + ] + }, + { + "cell_type": "markdown", + "id": "286c245f", + "metadata": {}, + "source": [ + "#### Grid with gap" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ed24f5d3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '})),{'class': 'grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 gap-4'})" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Grid(\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " cls='gap-4')" + ] + }, + { + "cell_type": "markdown", + "id": "7bb43e6d", + "metadata": {}, + "source": [ + "#### Grid with space" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "44130942", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "
\n", + "

A Simple Card

\n", + "
\n", + "
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '}), div((div((h4(('A Simple Card',),{'class': 'uk-h4 '}),),{'class': 'uk-card-body space-y-6'}),),{'class': 'uk-card '})),{'class': 'grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-3 space-x-4 space-y-4'})" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Grid(\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " Card(H4(\"A Simple Card\")),\n", + " cls='space-x-4 space-y-4')" + ] + }, + { + "cell_type": "markdown", + "id": "50c48f82", + "metadata": {}, + "source": [ + "### Grid with no gap or space\n", + "\n", + "The first example has no gap or not space applied. As expected this means the cards are flush with each other. Often this is not what you want, because a little space between cards looks much nicer.\n", + "\n", + "### Grid with gap\n", + "\n", + "The second example has the same grid but with gap applied. As youc an see, this gives constent space between all elements of the grid looks great!\n", + "\n", + "### Grid with space\n", + "\n", + "The third example has the same grid but with space applied. As you can see, it's not really what we want. However it's a really good illustration of how space works so let's notice a few things about it:\n", + "\n", + "**X Axis**\n", + "\n", + "- The first card is flush with the left side of the page (no margin)\n", + "- The card below it isn't flush with the left side of the page (has margin)\n", + "\n", + "**Y Axis**\n", + "\n", + "- The first card is flush with the heading immediately above it (no margin)\n", + "- The card top it's right isn't flush with the heading above it (has margin)\n", + "\n", + "So `space` applies margin to every element except for the first element in a group!\n", + "\n", + "> Tip: Use your browser developer tools to inspect the examples\n", + "\n", + "Next, let's look at a form example where `gap` isn't a good choice but `space` works beautifully!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36d1949c", + "metadata": {}, + "outputs": [], + "source": [ + "Form(DivCentered(H3(\"My Form\")),\n", + " LabelInput(\"Name\"),\n", + " Grid(LabelInput(\"Phone\"), LabelInput(\"Email\"), cols=2),\n", + " cls='')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8c5d280", + "metadata": {}, + "outputs": [], + "source": [ + "Form(DivCentered(H3(\"My Form with gap\")),\n", + " LabelInput(\"Name\"),\n", + " Grid(LabelInput(\"Phone\"), LabelInput(\"Email\"), cols=2),\n", + " cls='gap-y-5')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "b2566530", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "

My Form with Spacing

\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "```" + ], + "text/plain": [ + "form((div((h3(('My Form with Spacing',),{'class': 'uk-h3 '}),),{'class': 'uk-flex uk-flex-column uk-flex-middle uk-flex-center space-y-4'}), div((label(('Name',),{'for': '', 'class': 'uk-form-label '}), input((),{'id': '', 'class': 'uk-input '})),{'class': 'space-y-2'}), div((div((label(('Phone',),{'for': '', 'class': 'uk-form-label '}), input((),{'id': '', 'class': 'uk-input '})),{'class': 'space-y-2'}), div((label(('Email',),{'for': '', 'class': 'uk-form-label '}), input((),{'id': '', 'class': 'uk-input '})),{'class': 'space-y-2'})),{'class': 'grid grid-cols-2 sm:grid-cols-2 md:grid-cols-2 lg:grid-cols-2 gap-4'})),{'enctype': 'multipart/form-data', 'class': 'space-y-5'})" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Form(DivCentered(H3(\"My Form with Spacing\")),\n", + " LabelInput(\"Name\"),\n", + " Grid(LabelInput(\"Phone\"), LabelInput(\"Email\"), cols=2),\n", + " cls='space-y-5')" + ] + }, + { + "cell_type": "markdown", + "id": "85e821ad", + "metadata": {}, + "source": [ + "### Form with no gap or space\n", + "\n", + "The top form looks a bit scrunched with defaults, but it's certainly passable. There is a bit of a space between the label and it's associated input because of the defaults in MonsterUI.\n", + "\n", + "### Form with gap\n", + "\n", + "The second form with gap is identical to the first. Because we're not in a flex element or a grid, it doesn't do anything at all!\n", + "\n", + "### Form with space\n", + "\n", + "`Space-y-5` adds vertical space between each child which really spreads out the form for a nice aesthetic. If you recall from the grid example, it does not apply this margin to the first element - but in this situation (and many others) we do not want the spacing above the top element (heading) to be the same as the spacing between the form elements.\n", + "\n", + "> Tip: Use your browser developer tools to inspect the examples\n" + ] + }, + { + "cell_type": "markdown", + "id": "83d0f4ea", + "metadata": {}, + "source": [ + "# Further reading\n", + "\n", + "For further reading, check out the [Tailwind CSS guide](https://tailwindcss.com/docs/margin#adding-margin-to-a-single-side), which other users have found to be a useful as an additional guide." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/MonsterUI/docs/htmxindicator.py b/MonsterUI/docs/htmxindicator.py new file mode 100644 index 0000000000000000000000000000000000000000..ebcef847be62fdf5d0543a4746d7377fa2c8efa2 --- /dev/null +++ b/MonsterUI/docs/htmxindicator.py @@ -0,0 +1,25 @@ +from fasthtml.common import * +from monsterui.all import * +import time +from fasthtml.components import Uk_theme_switcher + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +@rt +def index(): + return Titled("Loading Demo", + Button("Load", id='load', + hx_get=load, hx_target='#content', hx_swap='beforeend', + hx_indicator='#loading'), + Div(id='content'), + Loading(id='loading', htmx_indicator=True)) + +@rt +def load(): + time.sleep(1) + return P("Loading Demo") + +@rt +def theme(): return Uk_theme_switcher() + +serve() diff --git a/MonsterUI/docs/llms-ctx-full.txt b/MonsterUI/docs/llms-ctx-full.txt new file mode 100644 index 0000000000000000000000000000000000000000..ce85d1f966dfe12d430acc113eb563d68db52508 --- /dev/null +++ b/MonsterUI/docs/llms-ctx-full.txt @@ -0,0 +1,7633 @@ +> MonsterUI is a python library which brings styling to python for FastHTML apps.# monsterui Module Documentation + +## monsterui.core + +- `class ThemeRadii(Enum)` + Members: none, sm, md, lg + + +- `class ThemeShadows` + +- `class ThemeFont` + +- `class Theme(Enum)` + Selector to choose theme and get all headers needed for app. Includes frankenui + tailwind + daisyui + highlight.js options + Members: slate, stone, gray, neutral, red, rose, orange, green, blue, yellow, violet, zinc + + - `headers(self, mode, icons, daisy, highlightjs, katex, apex_charts, radii, shadows, font)` + Create frankenui and tailwind cdns + + - `local_headers(self, mode, static_dir, icons, daisy, highlightjs, katex, apex_charts, radii, shadows, font)` + Create headers using local files downloaded from CDNs + + +## monsterui.daisy + +- `class AlertT(Enum)` + Alert styles from DaisyUI + Members: info, success, warning, error + + +- `def Alert(*c, **kwargs)` + Alert informs users about important events. + +- `class StepsT(Enum)` + Options for Steps + Members: vertical, horizonal + + +- `class StepT(Enum)` + Step styles for LiStep + Members: primary, secondary, accent, info, success, warning, error, neutral + + +- `def Steps(*li, **kwargs)` + Creates a steps container + +- `def LiStep(*c, **kwargs)` + Creates a step list item + +- `class LoadingT(Enum)` + Members: spinner, dots, ring, ball, bars, infinity, xs, sm, md, lg + + +- `def Loading(cls, htmx_indicator, **kwargs)` + Creates a loading animation component + +- `class ToastHT(Enum)` + Horizontal position for Toast + Members: start, center, end + + +- `class ToastVT(Enum)` + Vertical position for Toast + Members: top, middle, bottom + + +## monsterui.foundations + +> Data Structures and Utilties + +- `def stringify(o)` + Converts input types into strings that can be passed to FT components + +- `class VEnum(Enum)` + Members: + + - `__str__(self)` + - `__add__(self, other)` + - `__radd__(self, other)` + +## monsterui.franken + +- `class TextT(Enum)` + Text Styles from https://franken-ui.dev/docs/text + Members: paragraph, lead, meta, gray, italic, xs, sm, lg, xl, light, normal, medium, bold, extrabold, muted, primary, secondary, success, warning, error, info, left, right, center, justify, start, end, top, middle, bottom, truncate, break_, nowrap, underline, highlight + + +- `class TextPresets(Enum)` + Common Typography Presets + Members: muted_sm, muted_lg, bold_sm, bold_lg, md_weight_sm, md_weight_muted + + +- `def CodeSpan(*c, **kwargs)` + A CodeSpan with Styling + +- `def CodeBlock(*c, **kwargs)` + CodeBlock with Styling + +- `def H1(*c, **kwargs)` + H1 with styling and appropriate size + +- `def H2(*c, **kwargs)` + H2 with styling and appropriate size + +- `def H3(*c, **kwargs)` + H3 with styling and appropriate size + +- `def H4(*c, **kwargs)` + H4 with styling and appropriate size + +- `def H5(*c, **kwargs)` + H5 with styling and appropriate size + +- `def H6(*c, **kwargs)` + H6 with styling and appropriate size + +- `def Subtitle(*c, **kwargs)` + Styled muted_sm text designed to go under Headings and Titles + +- `def Q(*c, **kwargs)` + Styled quotation mark + +- `def Em(*c, **kwargs)` + Styled emphasis text + +- `def Strong(*c, **kwargs)` + Styled strong text + +- `def I(*c, **kwargs)` + Styled italic text + +- `def Small(*c, **kwargs)` + Styled small text + +- `def Mark(*c, **kwargs)` + Styled highlighted text + +- `def Del(*c, **kwargs)` + Styled deleted text + +- `def Ins(*c, **kwargs)` + Styled inserted text + +- `def Sub(*c, **kwargs)` + Styled subscript text + +- `def Sup(*c, **kwargs)` + Styled superscript text + +- `def Blockquote(*c, **kwargs)` + Blockquote with Styling + +- `def Caption(*c, **kwargs)` + Styled caption text + +- `def Cite(*c, **kwargs)` + Styled citation text + +- `def Time(*c, **kwargs)` + Styled time element + +- `def Address(*c, **kwargs)` + Styled address element + +- `def Abbr(*c, **kwargs)` + Styled abbreviation with dotted underline + +- `def Dfn(*c, **kwargs)` + Styled definition term with italic and medium weight + +- `def Kbd(*c, **kwargs)` + Styled keyboard input with subtle background + +- `def Samp(*c, **kwargs)` + Styled sample output with subtle background + +- `def Var(*c, **kwargs)` + Styled variable with italic monospace + +- `def Figure(*c, **kwargs)` + Styled figure container with card-like appearance + +- `def Details(*c, **kwargs)` + Styled details element + +- `def Summary(*c, **kwargs)` + Styled summary element + +- `def Data(*c, **kwargs)` + Styled data element + +- `def Meter(*c, **kwargs)` + Styled meter element + +- `def S(*c, **kwargs)` + Styled strikethrough text (different semantic meaning from Del) + +- `def U(*c, **kwargs)` + Styled underline (for proper names in Chinese, proper spelling etc) + +- `def Output(*c, **kwargs)` + Styled output element for form results + +- `def PicSumImg(h, w, id, grayscale, blur, **kwargs)` + Creates a placeholder image using https://picsum.photos/ + +- `def AccordionItem(title, *c)` + Creates a single item for use within an Accordion component, handling title, content, and open state. + +- `def Accordion(*c, **kwargs)` + Creates a styled Accordion container using accordion component. + +- `class ButtonT(Enum)` + Options for styling Buttons + Members: default, ghost, primary, secondary, destructive, text, link, xs, sm, lg, xl, icon + + +- `def Button(*c, **kwargs)` + Button with Styling (defaults to `submit` for form submission) + +- `class ContainerT(Enum)` + Max width container sizes from https://franken-ui.dev/docs/container + Members: xs, sm, lg, xl, expand + + +- `class BackgroundT(Enum)` + Members: muted, primary, secondary, default + + +- `def Container(*c, **kwargs)` + Div to be used as a container that often wraps large sections or a page of content + +- `def Titled(title, *c, **kwargs)` + Creates a standard page structure for titled page. Main(Container(title, content)) + +- `class DividerT(Enum)` + Divider Styles from https://franken-ui.dev/docs/divider + Members: icon, sm, vertical + + +- `def Divider(*c, **kwargs)` + Divider with default styling and margin + +- `def DividerSplit(*c)` + Creates a simple horizontal line divider with configurable thickness and vertical spacing + +- `def Article(*c, **kwargs)` + A styled article container for blog posts or similar content + +- `def ArticleTitle(*c, **kwargs)` + A title component for use within an Article + +- `def ArticleMeta(*c, **kwargs)` + A metadata component for use within an Article showing things like date, author etc + +- `class SectionT(Enum)` + Section styles from https://franken-ui.dev/docs/section + Members: default, muted, primary, secondary, xs, sm, lg, xl, remove_vertical + + +- `def Section(*c, **kwargs)` + Section with styling and margins + +- `def Form(*c, **kwargs)` + A Form with default spacing between form elements + +- `def Fieldset(*c, **kwargs)` + A Fieldset with default styling + +- `def Legend(*c, **kwargs)` + A Legend with default styling + +- `def Input(*c, **kwargs)` + An Input with default styling + +- `def Radio(*c, **kwargs)` + A Radio with default styling + +- `def CheckboxX(*c, **kwargs)` + A Checkbox with default styling + +- `def Range(*c, **kwargs)` + A Range with default styling + +- `def TextArea(*c, **kwargs)` + A Textarea with default styling + +- `def Switch(*c, **kwargs)` + A Switch with default styling + +- `def Upload(*c, **kwargs)` + A file upload component with default styling + +- `def UploadZone(*c, **kwargs)` + A file drop zone component with default styling + +- `def FormLabel(*c, **kwargs)` + A Label with default styling + +- `class LabelT(Enum)` + Members: primary, secondary, destructive + + +- `def Label(*c, **kwargs)` + FrankenUI labels, which look like pills + +- `def UkFormSection(title, description, *c)` + A form section with a title, description and optional button + +- `def GenericLabelInput(label, lbl_cls, input_cls, container, cls, id, input_fn, **kwargs)` + `Div(Label,Input)` component with Uk styling injected appropriately. Generally you should higher level API, such as `LabelInput` which is created for you in this library + +- `def LabelInput(label, lbl_cls, input_cls, cls, id, **kwargs)` + A `FormLabel` and `Input` pair that provides default spacing and links/names them based on id + +- `def LabelRadio(label, lbl_cls, input_cls, container, cls, id, **kwargs)` + A FormLabel and Radio pair that provides default spacing and links/names them based on id + +- `def LabelCheckboxX(label, lbl_cls, input_cls, container, cls, id, **kwargs)` + A FormLabel and CheckboxX pair that provides default spacing and links/names them based on id + +- `def Options(*c)` + Helper function to wrap things into `Option`s for use in `Select` + +- `def Select(*option, **kwargs)` + Creates a select dropdown with uk styling and option for adding a search box + +- `def LabelSelect(*option, **kwargs)` + A FormLabel and Select pair that provides default spacing and links/names them based on id + +- `@delegates(GenericLabelInput, but=['input_fn', 'cls']) def LabelRange(label, lbl_cls, input_cls, cls, id, value, min, max, step, label_range, **kwargs)` + A FormLabel and Range pair that provides default spacing and links/names them based on id + +- `class AT(Enum)` + Link styles from https://franken-ui.dev/docs/link + Members: muted, text, reset, primary, classic + + +- `class ListT(Enum)` + List styles using Tailwind CSS + Members: disc, circle, square, decimal, hyphen, bullet, divider, striped + + +- `def ModalContainer(*c, **kwargs)` + Creates a modal container that components go in + +- `def ModalDialog(*c, **kwargs)` + Creates a modal dialog + +- `def ModalHeader(*c, **kwargs)` + Creates a modal header + +- `def ModalBody(*c, **kwargs)` + Creates a modal body + +- `def ModalFooter(*c, **kwargs)` + Creates a modal footer + +- `def ModalTitle(*c, **kwargs)` + Creates a modal title + +- `def ModalCloseButton(*c, **kwargs)` + Creates a button that closes a modal with js + +- `def Modal(*c, **kwargs)` + Creates a modal with the appropriate classes to put the boilerplate in the appropriate places for you + +- `def Placeholder(*c, **kwargs)` + Creates a placeholder + +- `def Progress(*c, **kwargs)` + Creates a progress bar + +- `def UkIcon(icon, height, width, stroke_width, cls, **kwargs)` + Creates an icon using lucide icons + +- `def UkIconLink(icon, height, width, stroke_width, cls, button, **kwargs)` + Creates an icon link using lucide icons + +- `def DiceBearAvatar(seed_name, h, w)` + Creates an Avatar using https://dicebear.com/ + +- `def Center(*c, **kwargs)` + Centers contents both vertically and horizontally by default + +- `class FlexT(Enum)` + Flexbox modifiers using Tailwind CSS + Members: block, inline, left, center, right, between, around, stretch, top, middle, bottom, row, row_reverse, column, column_reverse, nowrap, wrap, wrap_reverse + + +- `def Grid(*div, **kwargs)` + Creates a responsive grid layout with smart defaults based on content + +- `def DivFullySpaced(*c, **kwargs)` + Creates a flex div with it's components having as much space between them as possible + +- `def DivCentered(*c, **kwargs)` + Creates a flex div with it's components centered in it + +- `def DivLAligned(*c, **kwargs)` + Creates a flex div with it's components aligned to the left + +- `def DivRAligned(*c, **kwargs)` + Creates a flex div with it's components aligned to the right + +- `def DivVStacked(*c, **kwargs)` + Creates a flex div with it's components stacked vertically + +- `def DivHStacked(*c, **kwargs)` + Creates a flex div with it's components stacked horizontally + +- `class NavT(Enum)` + Members: default, primary, secondary + + +- `def NavContainer(*li, **kwargs)` + Creates a navigation container (useful for creating a sidebar navigation). A Nav is a list (NavBar is something different) + +- `def NavParentLi(*nav_container, **kwargs)` + Creates a navigation list item with a parent nav for nesting + +- `def NavDividerLi(*c, **kwargs)` + Creates a navigation list item with a divider + +- `def NavHeaderLi(*c, **kwargs)` + Creates a navigation list item with a header + +- `def NavSubtitle(*c, **kwargs)` + Creates a navigation subtitle + +- `def NavCloseLi(*c, **kwargs)` + Creates a navigation list item with a close button + +- `class ScrollspyT(Enum)` + Members: underline, bold + + +- `def NavBar(*c)` + Creates a responsive navigation bar with mobile menu support + +- `def SliderContainer(*c, **kwargs)` + Creates a slider container + +- `def SliderItems(*c, **kwargs)` + Creates a slider items container + +- `def SliderNav(cls, prev_cls, next_cls, **kwargs)` + Navigation arrows for Slider component + +- `def Slider(*c, **kwargs)` + Creates a slider with optional navigation arrows + +- `def DropDownNavContainer(*li, **kwargs)` + A Nav that is part of a DropDown + +- `def TabContainer(*li, **kwargs)` + A TabContainer where children will be different tabs + +- `class CardT(Enum)` + Card styles from UIkit + Members: default, primary, secondary, destructive, hover + + +- `def CardTitle(*c, **kwargs)` + Creates a card title + +- `def CardHeader(*c, **kwargs)` + Creates a card header + +- `def CardBody(*c, **kwargs)` + Creates a card body + +- `def CardFooter(*c, **kwargs)` + Creates a card footer + +- `def CardContainer(*c, **kwargs)` + Creates a card container + +- `def Card(*c, **kwargs)` + Creates a Card with a header, body, and footer + +- `class TableT(Enum)` + Members: divider, striped, hover, sm, lg, justify, middle, responsive + + +- `def Table(*c, **kwargs)` + Creates a table + +- `def TableFromLists(header_data, body_data, footer_data, header_cell_render, body_cell_render, footer_cell_render, cls, sortable, **kwargs)` + Creates a Table from a list of header data and a list of lists of body data + +- `def TableFromDicts(header_data, body_data, footer_data, header_cell_render, body_cell_render, footer_cell_render, cls, sortable, **kwargs)` + Creates a Table from a list of header data and a list of dicts of body data + +- `def apply_classes(html_str, class_map, class_map_mods)` + Apply classes to html string + +- `class FrankenRenderer` + Custom renderer for Franken UI that handles image paths + + - `def __init__(self, *args, **kwargs)` + - `def render_image(self, token)` + Modify image paths if they're relative and self.img_dir is specified + + +- `def render_md(md_content, class_map, class_map_mods, img_dir, renderer)` + Renders markdown using mistletoe and lxml with custom image handling + +- `def ThemePicker(color, radii, shadows, font, mode, cls, custom_themes)` + Theme picker component with configurable sections + +- `def LightboxContainer(*lightboxitem, **kwargs)` + Lightbox container that will hold `LightboxItems` + +- `def LightboxItem(*c, **kwargs)` + Anchor tag with appropriate structure to go inside a `LightBoxContainer` + +- `def ApexChart(**kws)` + Apex chart component +"""FrankenUI Cards Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from fasthtml.components import Uk_input_tag +from fasthtml.svg import * +from monsterui.all import * +import calendar +from datetime import datetime + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +CreateAccount = Card( + Grid(Button(DivLAligned(UkIcon('github'),Div('Github'))),Button('Google')), + DividerSplit("OR CONTINUE WITH", text_cls=TextPresets.muted_sm), + LabelInput('Email', id='email', placeholder='m@example.com'), + LabelInput('Password', id='password',placeholder='Password', type='Password'), + header=(H3('Create an Account'),Subtitle('Enter your email below to create your account')), + footer=Button('Create Account',cls=(ButtonT.primary,'w-full'))) + +PaypalSVG_data = "M7.076 21.337H2.47a.641.641 0 0 1-.633-.74L4.944.901C5.026.382 5.474 0 5.998 0h7.46c2.57 0 4.578.543 5.69 1.81 1.01 1.15 1.304 2.42 1.012 4.287-.023.143-.047.288-.077.437-.983 5.05-4.349 6.797-8.647 6.797h-2.19c-.524 0-.968.382-1.05.9l-1.12 7.106zm14.146-14.42a3.35 3.35 0 0 0-.607-.541c-.013.076-.026.175-.041.254-.93 4.778-4.005 7.201-9.138 7.201h-2.19a.563.563 0 0 0-.556.479l-1.187 7.527h-.506l-.24 1.516a.56.56 0 0 0 .554.647h3.882c.46 0 .85-.334.922-.788.06-.26.76-4.852.816-5.09a.932.932 0 0 1 .923-.788h.58c3.76 0 6.705-1.528 7.565-5.946.36-1.847.174-3.388-.777-4.471z" +AppleSVG_data = "M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701" +Card1Svg = Svg(viewBox="0 0 24 24", fill="none", stroke="currentColor", stroke_linecap="round", stroke_linejoin="round", stroke_width="2", cls="h-6 w-6 mr-1")(Rect(width="20", height="14", x="2", y="5", rx="2"),Path(d="M2 10h20")) +PaypalSvg = Svg(role="img", viewBox="0 0 24 24", cls="h-6 w-6 mr-1")(Path(d=PaypalSVG_data, fill="currentColor")), +AppleSvg = Svg(role="img", viewBox="0 0 24 24", cls="h-6 w-6 mr-1")(Path(d=AppleSVG_data, fill="currentColor")) + +PaymentMethod = Card( + Grid(Button(DivCentered(Card1Svg, "Card"), cls='h-20 border-2 border-primary'), + Button(DivCentered(PaypalSvg, "PayPal"), cls='h-20'), + Button(DivCentered(AppleSvg, "Apple"), cls='h-20')), + Form(LabelInput('Name', id='name', placeholder='John Doe'), + LabelInput('Card Number', id='card_number', placeholder='m@example.com'), + Grid(LabelSelect(*Options(*calendar.month_name[1:],selected_idx=0),label='Expires',id='expire_month'), + LabelSelect(*Options(*range(2024,2030),selected_idx=0), label='Year', id='expire_year'), + LabelInput('CVV', id='cvv',placeholder='CVV', cls='mt-0'))), + header=(H3('Payment Method'),Subtitle('Add a new payment method to your account.'))) + +area_opts = ('Team','Billing','Account','Deployment','Support') +severity_opts = ('Severity 1 (Highest)', 'Severity 2', 'Severity 3', 'Severity 4 (Lowest)') +ReportIssue = Card( + Grid(Div(LabelSelect(*Options(*area_opts), label='Area', id='area')), + Div(LabelSelect(*Options(*severity_opts),label='Severity',id='area'))), + LabelInput( label='Subject', id='subject', placeholder='I need help with'), + LabelTextArea( label='Description', id='description',placeholder='Please include all information relevant to your issue'), + Div(FormLabel('Tags', fr='#tags'), + Uk_input_tag(name="Tags",state="danger", value="Spam,Invalid", uk_cloak=True, id='tags')), + header=(H3('Report Issue'),Subtitle('What area are you having problems with?')), + footer = DivFullySpaced(Button('Cancel'), Button(cls=ButtonT.primary)('Submit'))) + +monster_desc ="Python-first beautifully designed components because you deserve to focus on features that matter and your app deserves to be beautiful from day one." +MonsterUI = Card(H4("Monster UI"), + Subtitle(monster_desc), + DivLAligned( + Div("Python"), + DivLAligned(UkIcon('star'),Div("20k"), cls='space-x-1'), + Div(datetime.now().strftime("%B %d, %Y")), + cls=('space-x-4',TextPresets.muted_sm))) + +def CookieTableRow(heading, description, active=False): + return Tr(Td(H5(heading)), + Td(P(description, cls=TextPresets.muted_sm)), + Td(Switch(checked=active))) + +CookieSettings = Card( + Table(Tbody( + CookieTableRow('Strictly Necessary', 'These cookies are essential in order to use the website and use its features.', True), + CookieTableRow('Functional Cookies', 'These cookies allow the website to provide personalized functionality.'), + CookieTableRow('Performance Cookies', 'These cookies help to improve the performance of the website.'))), + header=(H4('Cookie Settings'),Subtitle('Manage your cookie settings here.')), + footer=Button('Save Preferences', cls=(ButtonT.primary, 'w-full'))) + +team_members = [("Sofia Davis", "m@example.com", "Owner"),("Jackson Lee", "p@example.com", "Member"),] +def TeamMemberRow(name, email, role): + return DivFullySpaced( + DivLAligned( + DiceBearAvatar(name, 10,10), + Div(P(name, cls=(TextT.sm, TextT.medium)), + P(email, cls=TextPresets.muted_sm))), + Button(role, UkIcon('chevron-down', cls='ml-4')), + DropDownNavContainer(map(NavCloseLi, [ + A(Div('Viewer', NavSubtitle('Can view and comment.'))), + A(Div('Developer', NavSubtitle('Can view, comment and edit.'))), + A(Div('Billing', NavSubtitle('Can view, comment and manage billing.'))), + A(Div('Owner', NavSubtitle('Admin-level access to all resources.')))]))) + +TeamMembers = Card(*[TeamMemberRow(*member) for member in team_members], + header = (H4('Team Members'),Subtitle('Invite your team members to collaborate.'))) + +access_roles = ("Read and write access", "Read-only access") +team_members = [("Olivia Martin", "m@example.com", "Read and write access"), + ("Isabella Nguyen", "b@example.com", "Read-only access"), + ("Sofia Davis", "p@example.com", "Read-only access")] + +def TeamMemberRow(name, email, role): + return DivFullySpaced( + DivLAligned(DiceBearAvatar(name, 10,10), + Div(P(name, cls=(TextT.sm, TextT.medium)), + P(email, cls=TextPresets.muted_sm))), + Select(*Options(*access_roles, selected_idx=access_roles.index(role)))) + +ShareDocument = Card( + DivLAligned(Input(value='http://example.com/link/to/document'),Button('Copy link', cls='whitespace-nowrap')), + Divider(), + H4('People with access', cls=TextPresets.bold_sm), + *[TeamMemberRow(*member) for member in team_members], + header = (H4('Share this document'),Subtitle('Anyone with the link can view this document.'))) + +DateCard = Card(Button('Jan 20, 2024 - Feb 09, 2024')) + +section_content =(('bell','Everything',"Email digest, mentions & all activity."), + ('user',"Available","Only mentions and comments"), + ('ban', "Ignoring","Turn of all notifications")) + +def NotificationRow(icon, name, desc): + return Li(cls='-mx-1')(A(DivLAligned(UkIcon(icon),Div(P(name),P(desc, cls=TextPresets.muted_sm))))) + +Notifications = Card( + NavContainer( + *[NotificationRow(*row) for row in section_content], + cls=NavT.secondary), + header = (H4('Notification'),Subtitle('Choose what you want to be notified about.')), + body_cls='pt-0') + +TeamCard = Card( + DivLAligned( + DiceBearAvatar("Isaac Flath", h=24, w=24), + Div(H3("Isaac Flath"), P("Library Creator"))), + footer=DivFullySpaced( + DivHStacked(UkIcon("map-pin", height=16), P("Alexandria, VA")), + DivHStacked(*(UkIconLink(icon, height=16) for icon in ("mail", "linkedin", "github")))), + cls=CardT.hover) + +@rt +def index(): + return Title("Cards Example"),Container(Grid( + *map(Div,( + Div(PaymentMethod,CreateAccount, TeamCard, cls='space-y-4'), + Div(TeamMembers, ShareDocument,DateCard,Notifications, cls='space-y-4'), + Div(ReportIssue,MonsterUI,CookieSettings, cls='space-y-4'))), + cols_md=1, cols_lg=2, cols_xl=3)) + +serve()"""FrankenUI Dashboard Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * # Bring in all of fasthtml +import fasthtml.common as fh # Used to get unstyled components +from monsterui.all import * # Bring in all of monsterui, including shadowing fasthtml components with styled components +from fasthtml.svg import * +import numpy as np +import plotly.express as px +import pandas as pd +import numpy as np + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def generate_chart(num_points=30): + df = pd.DataFrame({ + 'Date': pd.date_range('2024-01-01', periods=num_points), + 'Revenue': np.random.normal(100, 10, num_points).cumsum(), + 'Users': np.random.normal(80, 8, num_points).cumsum(), + 'Growth': np.random.normal(60, 6, num_points).cumsum()}) + + fig = px.line(df, x='Date', y=['Revenue', 'Users', 'Growth'], template='plotly_white', line_shape='spline') + + fig.update_traces(mode='lines+markers') + fig.update_layout( + margin=dict(l=20, r=20, t=20, b=20), hovermode='x unified', + showlegend=True, legend=dict(orientation='h', yanchor='bottom', y=1.02, xanchor='right', x=1), + plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', + xaxis=dict(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)'), + yaxis=dict(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)')) + + return fig.to_html(include_plotlyjs=True, full_html=False, config={'displayModeBar': False}) + +def InfoCard(title, value, change): return Card(H3(value),P(change, cls=TextPresets.muted_sm), header = H4(title)) + +rev = InfoCard("Total Revenue", "$45,231.89", "+20.1% from last month") +sub = InfoCard("Subscriptions", "+2350", "+180.1% from last month") +sal = InfoCard("Sales", "+12,234", "+19% from last month") +act = InfoCard("Active Now", "+573", "+201 since last hour") + +info_card_data = [("Total Revenue", "$45,231.89", "+20.1% from last month"), + ("Subscriptions", "+2350", "+180.1% from last month"), + ("Sales", "+12,234", "+19% from last month"), + ("Active Now", "+573", "+201 since last hour")] + +top_info_row = Grid(*[InfoCard(*row) for row in info_card_data]) + +def AvatarItem(name, email, amount): + return DivFullySpaced( + DivLAligned( + DiceBearAvatar(name, 9,9), + Div(Strong(name, cls=TextT.sm), + Address(A(email,href=f'mailto:{email}')))), + fh.Data(amount, cls="ml-auto font-medium", value=amount[2:])) + +recent_sales = Card( + Div(cls="space-y-8")( + *[AvatarItem(n,e,d) for (n,e,d) in ( + ("Olivia Martin", "olivia.martin@email.com", "+$1,999.00"), + ("Jackson Lee", "jackson.lee@email.com", "+$39.00"), + ("Isabella Nguyen", "isabella.nguyen@email.com", "+$299.00"), + ("William Kim", "will@email.com", "+$99.00"), + ("Sofia Davis", "sofia.davis@email.com", "+$39.00"))]), + header=Div(H3("Recent Sales"),Subtitle("You made 265 sales this month.")), + cls='col-span-3') + +teams = [["Alicia Koch"],['Acme Inc', 'Monster Inc.'],['Create a Team']] + +opt_hdrs = ["Personal", "Team", ""] + +team_dropdown = Select( + Optgroup(Option(A("Alicia Koch")), label="Personal Account"), + Optgroup(Option(A("Acme Inc")), Option(A("Monster Inc.")), label="Teams"), + Option(A("Create a Team")), + cls='flex items-center') + +hotkeys = [('Profile','⇧⌘P'),('Billing','⌘B'),('Settings','⌘S'),('New Team', ''), ('Logout', '')] + +def NavSpacedLi(t,s): return NavCloseLi(A(DivFullySpaced(P(t),P(s,cls=TextPresets.muted_sm)))) + +avatar_dropdown = Div( + DiceBearAvatar('Alicia Koch',8,8), + DropDownNavContainer( + NavHeaderLi('sveltecult',NavSubtitle("leader@sveltecult.com")), + *[NavSpacedLi(*hk) for hk in hotkeys],)) + +top_nav = NavBar( + team_dropdown, *map(A, ["Overview", "Customers", "Products", "Settings"]), + brand=DivLAligned(avatar_dropdown, Input(placeholder='Search'))) + +@rt +def index(): + return Title("Dashboard Example"), Container( + top_nav, + H2('Dashboard'), + TabContainer( + Li(A("Overview"),cls='uk-active'), + *map(lambda x: Li(A(x)), ["Analytics", "Reports", "Notifications"]), + alt=True), + top_info_row, + Grid( + Card(Safe(generate_chart(100)), cls='col-span-4'), + recent_sales, + gap=4,cols_xl=7,cols_lg=7,cols_md=1,cols_sm=1,cols_xs=1), + cls=('space-y-4', ContainerT.xl)) + +serve()"""FrankenUI Forms Example built with MonsterUI (original design by ShadCN)""" + + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def HelpText(c): return P(c,cls=TextPresets.muted_sm) + +def heading(): + return Div(cls="space-y-5")( + H2("Settings"), + Subtitle("Manage your account settings and set e-mail preferences."), + DividerSplit()) + + +sidebar = NavContainer( + *map(lambda x: Li(A(x)), ("Profile", "Account", "Appearance", "Notifications", "Display")), + uk_switcher="connect: #component-nav; animation: uk-animation-fade", + cls=(NavT.secondary,"space-y-4 p-4 w-1/5")) + + +def FormSectionDiv(*c, cls='space-y-2', **kwargs): return Div(*c, cls=cls, **kwargs) + +def FormLayout(title, subtitle, *content, cls='space-y-3 mt-4'): return Container(Div(H3(title), Subtitle(subtitle), DividerLine(), Form(*content, cls=cls))) + +def profile_form(): + content = (FormSectionDiv( + LabelInput("Username", placeholder='sveltecult', id='username'), + HelpText("This is your public display name. It can be your real name or a pseudonym. You can only change this once every 30 days.")), + FormSectionDiv( + LabelSelect( + Option("Select a verified email to display", value="", selected=True, disabled=True), + *[Option(o, value=o) for o in ('m@example.com', 'm@yahoo.com', 'm@cloud.com')], + label="Email", id="email"), + HelpText("You can manage verified email addresses in your email settings.")), + FormSectionDiv( + LabelTextArea("Bio", id="bio", placeholder="Tell us a little bit about yourself"), + HelpText("You can @mention other users and organizations to link to them."), + P("String must contain at least 4 character(s)", cls="text-destructive")), + FormSectionDiv( + FormLabel("URLs"), + HelpText("Add links to your website, blog, or social media profiles."), + Input(value="https://www.franken-ui.dev"), + Input(value="https://github.com/sveltecult/franken-ui"), + Button("Add URL")), + Button('Update profile', cls=ButtonT.primary)) + + return FormLayout('Profile', 'This is how others will see you on the site.', *content) + +def account_form(): + content = ( + FormSectionDiv( + LabelInput("Name", placeholder="Your name", id="name"), + HelpText("This is the name that will be displayed on your profile and in emails.")), + FormSectionDiv( + LabelInput("Date of Birth", type="date", placeholder="Pick a date", id="date_of_birth"), + HelpText("Your date of birth is used to calculate your age.")), + FormSectionDiv( + LabelSelect(*Options("Select a language", "English", "French", "German", "Spanish", "Portuguese", selected_idx=1, disabled_idxs={0}), + label='Language', id="language"), + HelpText("This is the language that will be used in the dashboard.")), + Button('Update profile', cls=ButtonT.primary)) + + return FormLayout('Account', 'Update your account settings. Set your preferred language and timezone.', *content) + +def appearance_form(): + def theme_item(bg_color, content_bg, text_bg): + common_content = f"space-y-2 rounded-md {content_bg} p-2 shadow-sm" + item_row = lambda: Div(cls=f"flex items-center space-x-2 {common_content}")( + Div(cls=f"h-4 w-4 rounded-full {text_bg}"), + Div(cls=f"h-2 w-[100px] rounded-lg {text_bg}")) + + return Div(cls=f"space-y-2 rounded-sm {bg_color} p-2")( + Div(cls=common_content)( + Div(cls=f"h-2 w-[80px] rounded-lg {text_bg}"), + Div(cls=f"h-2 w-[100px] rounded-lg {text_bg}")), + item_row(), + item_row()) + + common_toggle_cls = "block cursor-pointer items-center rounded-md border-2 border-muted p-1 ring-ring" + + content = ( + FormSectionDiv( + LabelSelect(*Options('Select a font family', 'Inter', 'Geist', 'Open Sans', selected_idx=2, disabled_idxs={0}), + label='Font Family', id='font_family'), + HelpText("Set the font you want to use in the dashboard.")), + FormSectionDiv( + FormLabel("Theme"), + HelpText("Select the theme for the dashboard."), + Grid( + A(id="theme-toggle-light", cls=common_toggle_cls)(theme_item("bg-[#ecedef]", "bg-white", "bg-[#ecedef]")), + A(id="theme-toggle-dark", cls=f"{common_toggle_cls} bg-popover")(theme_item("bg-slate-950", "bg-slate-800", "bg-slate-400")), + cols_max=2,cls=('max-w-md','gap-8'))), + Button('Update preferences', cls=ButtonT.primary)) + + return FormLayout('Appearance', 'Customize the appearance of the app. Automatically switch between day and night themes.', *content) + + +notification_items = [ + {"title": "Communication emails", "description": "Receive emails about your account activity.", "checked": False, "disabled": False}, + {"title": "Marketing emails", "description": "Receive emails about new products, features, and more.", "checked": False, "disabled": False}, + {"title": "Social emails", "description": "Receive emails for friend requests, follows, and more.", "checked": True, "disabled": False}, + {"title": "Security emails", "description": "Receive emails about your account activity and security.", "checked": True, "disabled": True}] + +def notifications_form(): + def RadioLabel(label): return DivLAligned(Radio(name="notification", checked=(label=="Nothing")), FormLabel(label)) + + def NotificationCard(item): + return Card( + Div(cls="space-y-0.5")( + FormLabel(Strong(item['title'], cls=TextT.sm), + HelpText(item['description'])))) + content = Div( + FormSectionDiv( + FormLabel("Notify me about"), + *map(RadioLabel, ["All new messages", "Direct messages and mentions", "Nothing"])), + Div( + H4("Email Notifications", cls="mb-4"), + Grid(*map(NotificationCard, notification_items), cols=1)), + LabelCheckboxX("Use different settings for my mobile devices", id="notification_mobile"), + HelpText("You can manage your mobile notifications in the mobile settings page."), + Button('Update notifications', cls=ButtonT.primary)) + + return FormLayout('Notifications', 'Configure how you receive notifications.', *content) + +def display_form(): + content = ( + Div(cls="space-y-2")( + Div(cls="mb-4")( + H5("Sidebar"), + Subtitle("Select the items you want to display in the sidebar.")), + *[Div(CheckboxX(id=f"display_{i}", checked=i in [0, 1, 2]),FormLabel(label)) + for i, label in enumerate(["Recents", "Home", "Applications", "Desktop", "Downloads", "Documents"])]), + Button('Update display', cls=ButtonT.primary)) + return FormLayout('Display', 'Turn items on or off to control what\'s displayed in the app.', *content) + +@rt +def index(): + return Title("Forms Example"),Container( + heading(), + Div(cls="flex gap-x-12")( + sidebar, + Ul(id="component-nav", cls="uk-switcher max-w-2xl")( + Li(cls="uk-active")(profile_form(), + *map(Li, [account_form(), appearance_form(), notifications_form(), display_form()]))))) + +serve()"MonsterUI Scrollspy Example application" + +from fasthtml.common import * +from monsterui.all import * +import random + +# Using the "slate" theme with Highlight.js enabled +hdrs = Theme.slate.headers(highlightjs=True) +app, rt = fast_app(hdrs=hdrs) + +################################ +### Example Data and Content ### +################################ +products = [ + {"name": "Laptop", "price": "$999"}, + {"name": "Smartphone", "price": "$599"} +] + +code_example = """ +# Python Code Example +def greet(name): + return f"Hello, {name}!" + +print(greet("World")) +""" +testimonials = [ + {"name": "Alice", "feedback": "Great products and excellent customer service!"}, + {"name": "Bob", "feedback": "Fast shipping and amazing quality!"}, + {"name": "Charlie", "feedback": "Amazing experience! Will definitely buy again."}, + {"name": "Diana", "feedback": "Affordable prices and great variety!"}, + {"name": "Edward", "feedback": "Customer support was very helpful."}, + {"name": "Fiona", "feedback": "Loved the design and quality!"} +] + +# Team members +team = [ + {"name": "Isaac Flath", "role": "CEO"}, + {"name": "Benjamin Clavié", "role": "AI Researcher"}, + {"name": "Alexis Gallagher", "role": "ML Engineer"}, + {"name": "Hamel Husain", "role": "Data Scientist"}, + {"name": "Austin Huang", "role": "Software Engineer"}, + {"name": "Benjamin Warner", "role": "Product Manager"}, + {"name": "Jonathan Whitaker", "role": "UX Designer"}, + {"name": "Kerem Turgutlu", "role": "DevOps Engineer"}, + {"name": "Curtis Allan", "role": "DevOps Engineer"}, + {"name": "Audrey Roy Greenfeld", "role": "Security Analyst"}, + {"name": "Nathan Cooper", "role": "Full Stack Developer"}, + {"name": "Jeremy Howard", "role": "CTO"}, + {"name": "Wayde Gilliam", "role": "Cloud Architect"}, + {"name": "Daniel Roy Greenfeld", "role": "Blockchain Expert"}, + {"name": "Tommy Collins", "role": "AI Ethics Researcher"} +] + + +def ProductCard(p,img_id=1): + return Card( + PicSumImg(w=500, height=100, id=img_id), + DivFullySpaced(H4(p["name"]), P(Strong(p["price"], cls=TextT.sm))), + Button("Details", cls=(ButtonT.primary, "w-full"))) + +def TestimonialCard(t,img_id=1): + return Card( + DivLAligned(PicSumImg(w=50, h=50, cls='rounded-full', id=img_id), H4(t["name"])), + P(Q((t["feedback"])))) + + +def TeamCard(m,img_id=1): + return Card( + DivLAligned( + PicSumImg(w=50, h=50, cls='rounded-full', id=img_id), + Div(H4(m["name"]), P(m["role"]))), + DivRAligned( + UkIcon('twitter', cls='w-5 h-5'), + UkIcon('linkedin', cls='w-5 h-5'), + UkIcon('github', cls='w-5 h-5'), + cls=TextT.gray+'space-x-2' + ), + cls='p-3') + +################################ +### Navigation and Scrollspy ### +################################ + +scrollspy_links = ( + A("Welcome", href="#welcome-section"), + A("Products", href="#products-section"), + A("Testimonials", href="#testimonials-section"), + A("Team", href="#team-section"), + A("Code Example", href="#code-section")) +@rt +def index(): + def _Section(*c, **kwargs): return Section(*c, cls='space-y-3 my-48',**kwargs) + return Container( + NavBar( + *scrollspy_links, + brand=DivLAligned(H3("Scrollspy Demo!"),UkIcon('rocket',height=30,width=30)), + sticky=True, uk_scrollspy_nav=True, + scrollspy_cls=ScrollspyT.bold), + NavContainer( + *map(Li, scrollspy_links), + uk_scrollspy_nav=True, + sticky=True, + cls=(NavT.primary,'pt-20 px-5 pr-10')), + Container( + # Notice the ID of each section corresponds to the `scrollspy_links` dictionary + # So in scollspy `NavContainer` the `href` of each `Li` is the ID of the section + DivCentered( + H1("Welcome to the Store!"), + Subtitle("Explore our products and enjoy dynamic code examples."), + id="welcome-section"), + _Section(H2("Products"), + Grid(*[ProductCard(p,img_id=i) for i,p in enumerate(products)], cols_lg=2), + id="products-section"), + _Section(H2("Testimonials"), + Slider(*[TestimonialCard(t,img_id=i) for i,t in enumerate(testimonials)]), + id="testimonials-section"), + _Section(H2("Our Team"), + Grid(*[TeamCard(m,img_id=i) for i,m in enumerate(team)], cols_lg=2, cols_max=3), + id="team-section"), + _Section(H2("Code Example"), + CodeBlock(code_example, lang="python"), + id="code-section")), + cls=(ContainerT.xl,'uk-container-expand')) + +serve()"""MonsterUI Help Desk Example - Professional Dashboard with DaisyUI components""" +from fasthtml.common import * +from monsterui.all import * +from datetime import datetime + +app, rt = fast_app(hdrs=Theme.blue.headers(daisy=True)) + +def TicketSteps(step): + return Steps( + LiStep("Submitted", data_content="📝", + cls=StepT.success if step > 0 else StepT.primary if step == 0 else StepT.neutral), + LiStep("In Review", data_content="🔎", + cls=StepT.success if step > 1 else StepT.primary if step == 1 else StepT.neutral), + LiStep("Processing", data_content="⚙️", + cls=StepT.success if step > 2 else StepT.primary if step == 2 else StepT.neutral), + LiStep("Resolved", data_content="✅", + cls=StepT.success if step > 3 else StepT.primary if step == 3 else StepT.neutral), + cls="w-full") + +def StatusBadge(status): + styles = {'high': AlertT.error, 'medium': AlertT.warning,'low': AlertT.info} + alert_type = styles.get(status, AlertT.info) + return Alert(f"{status.title()} Priority", cls=(alert_type,"w-32 shadow-sm")) + +def TicketCard(id, title, description, status, step, department): + return Card( + CardHeader( + DivFullySpaced( + Div(H3(f"#{id}", cls=TextT.muted), + H4(title), + cls='space-y-2'), + StatusBadge(status))), + CardBody( + P(description, cls=(TextT.muted, "mb-6")), + DividerSplit(cls="my-6"), + TicketSteps(step), + DividerSplit(cls="my-6"), + DivFullySpaced( + Div(Strong("Department"), + P(department), + cls=('space-y-3', TextPresets.muted_sm)), + Div(Strong("Last Updated"), + P(Time(datetime.now().strftime('%b %d, %H:%M'))), + cls=('space-y-3', TextPresets.muted_sm)), + Button("View Details", cls=ButtonT.primary), + cls='mt-6')), + cls=CardT.hover) + +def NewTicketModal(): + return Modal( + ModalHeader(H3("Create New Support Ticket")), + ModalBody( + Alert( + DivLAligned(UkIcon("info"), Span("Please provide as much detail as possible to help us assist you quickly.")), + cls=(AlertT.info,"mb-4")), + Form( + Grid(LabelInput("Title", id="title", placeholder="Brief description of your issue"), + LabelSelect(Options("IT Support", "HR", "Facilities", "Finance"), label="Department", id="department")), + LabelSelect(Options("Low", "Medium", "High"), label="Priority Level", id="priority"), + LabelTextArea("Description", id="description", placeholder="Please provide detailed information about your issue"), + DivRAligned( + Button("Cancel", cls=ButtonT.ghost, data_uk_toggle="target: #new-ticket"), + Button(Loading(cls=LoadingT.spinner), "Submit Ticket", cls=ButtonT.primary, data_uk_toggle="target: #success-toast; target: #new-ticket")), + cls='space-y-8')), + id="new-ticket") + +@rt +def index(): + tickets = [ + {'id': "TK-1001", 'title': "Cloud Storage Access Error", + 'description': "Unable to access cloud storage with persistent authorization errors. Multiple users affected across marketing department.", + 'status': 'high', 'step': 2, 'department': 'IT Support'}, + {'id': "TK-1002", 'title': "Email Integration Issue", + 'description': "Exchange server not syncing with mobile devices. Affecting external client communications.", + 'status': 'medium', 'step': 1, 'department': 'IT Support'}, + {'id': "TK-1003", 'title': "Office Equipment Setup", + 'description': "New department printer needs configuration and network integration. Required for upcoming client presentation.", + 'status': 'low', 'step': 0, 'department': 'Facilities'} + ] + + return Title("Help Desk Dashboard"), Container( + Section( + DivFullySpaced( + H2("Active Tickets"), + Button(UkIcon("plus-circle", cls="mr-2"), "New Ticket", cls=ButtonT.primary, data_uk_toggle="target: #new-ticket"), + cls='mb-8'), + Grid(*[TicketCard(**ticket) for ticket in tickets], cols=1), + cls="my-6"), + NewTicketModal(), + Toast(DivLAligned(UkIcon('check-circle', cls='mr-2'), "Ticket submitted successfully! Our team will review it shortly."), id="success-toast", alert_cls=AlertT.success, cls=(ToastHT.end, ToastVT.bottom)), + Loading(htmx_indicator=True, type=LoadingT.dots, cls="fixed top-0 right-0 m-4"), + cls="mx-auto max-w-7xl" + ) + +serve()"""FrankenUI Playground Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +preset_options = ["Grammatical Standard English", "Summarize for a 2nd grader", + "Text to command","Q&A","English to other languages","Parse unstructured data", + "Classification","Natural language to Python","Explain code","Chat","More examples"] + +def playground_navbar(): + save_modal = Modal( + ModalTitle("Save preset"), + P("This will save the current playground state as a preset which you can access later or share with others.",cls=("mt-1.5", TextPresets.muted_sm)), + LabelInput("Name", id="name"), + LabelInput("Description", id="description"), + ModalCloseButton("Save", cls=ButtonT.primary), + id="save") + + share_dd = Div(cls="space-y-6 p-4")( + H3("Share preset"), + P("Anyone who has this link and an OpenAI account will be able to view this.", cls=TextPresets.muted_sm), + Div(Input(value="https://platform.openai.com/playground/p/7bbKYQvsVkNmVb8NGcdUOLae?model=text-davinci-003", readonly=True), + Button(UkIcon('copy'), cls=(ButtonT.primary, "uk-drop-close",'mt-4')))) + + rnav = ( + Select(*Options(*preset_options), name='preset', optgroup_label="Examples", + placeholder='Load a preset', searchable=True, cls='h-9 w-[200px] lg:w-[300px]'), + Button("Save", cls=ButtonT.secondary, data_uk_toggle="#save"),save_modal, + Button("View Code", cls=ButtonT.secondary), + Button("Share", cls=ButtonT.secondary),DropDownNavContainer(share_dd), + Button(UkIcon(icon="ellipsis"), cls=ButtonT.secondary), + DropDownNavContainer( + Li(A("Content filter preferences")), + NavDividerLi(), + Li(A("Delete preset", cls="text-destructive")), + uk_dropdown="mode: click")) + + return NavBar(*rnav, brand=H4('Playground')) + +rsidebar = NavContainer( + Select( + Optgroup(map(Option,("text-davinci-003", "text-curie-001", "text-babbage-001", "text-ada-001")),label='GPT-3'), + Optgroup(map(Option,("code-davinci-002", "code-cushman-001")),label='Codex'), + label="Model", + searchable=True), + LabelRange(label='Temperature', value='12'), + LabelRange(label='Maximum Length', value='80'), + LabelRange(label='Top P', value='40'), + cls='space-y-6 mt-8') + +@rt +def index(): + navbar = playground_navbar() + main_content = Div( + Div(cls="flex-1")( + Textarea(cls="uk-textarea h-full p-4", placeholder="Write a tagline for an ice cream shop")), + cls="flex h-[700px] p-8 w-4/5") + + bottom_buttons = Div( + Button("Submit", cls=ButtonT.primary), + Button(UkIcon(icon="history"), cls=ButtonT.secondary), + cls="flex gap-x-2") + + return Title("Playground Example"),Div(navbar, Div(cls="flex w-full")(main_content, rsidebar), bottom_buttons) + +serve()"""FrankenUI Mail Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * +import pathlib, json +from datetime import datetime + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +sidebar_group1 = (('home', 'Inbox', '128'), ('file-text', 'Drafts', '9'), (' arrow-up-right', 'Sent', ''), + ('ban', 'Junk', '23'), ('trash', 'Trash', ''), ('folder', 'Archive', '')) + +sidebar_group2 = (('globe','Social','972'),('info','Updates','342'),('messages-square','Forums','128'), + ('shopping-cart','Shopping','8'),('shopping-bag','Promotions','21'),) + +def MailSbLi(icon, title, cnt): + return Li(A(DivLAligned(Span(UkIcon(icon)),Span(title),P(cnt, cls=TextPresets.muted_sm)),href='#', cls='hover:bg-secondary p-4')) + +sidebar = NavContainer( + NavHeaderLi(H3("Email"), cls='p-3'), + Li(Select(map(Option, ('alicia@example.com','alicia@gmail.com', 'alicia@yahoo.com')))), + *[MailSbLi(i, t, c) for i, t, c in sidebar_group1], + Li(Hr()), + *[MailSbLi(i, t, c) for i, t, c in sidebar_group2], + cls='mt-3') + +mail_data = json.load(open(pathlib.Path('data_/mail.json'))) + +def format_date(date_str): + date_obj = datetime.fromisoformat(date_str) + return date_obj.strftime("%Y-%m-%d %I:%M %p") + +def MailItem(mail): + cls_base = 'relative rounded-lg border border-border p-3 text-sm hover:bg-secondary space-y-2' + cls = f"{cls_base} {'bg-muted' if mail == mail_data[0] else ''} {'tag-unread' if not mail['read'] else 'tag-mail'}" + + return Li( + DivFullySpaced( + DivLAligned( + Strong(mail['name']), + Span(cls='flex h-2 w-2 rounded-full bg-blue-600') if not mail['read'] else ''), + Time(format_date(mail['date']), cls='text-xs')), + Small(mail['subject'], href=f"#mail-{mail['id']}"), + Div(mail['text'][:100] + '...', cls=TextPresets.muted_sm), + DivLAligned( + *[Label(A(label, href='#'), cls='uk-label-primary' if label == 'work' else '') for label in mail['labels']]), + cls=cls) + +def MailList(mails): return Ul(cls='js-filter space-y-2 p-4 pt-0')(*[MailItem(mail) for mail in mails]) + +def MailContent(): + return Div(cls='flex flex-col',uk_filter="target: .js-filter")( + Div(cls='flex px-4 py-2 ')( + H3('Inbox'), + TabContainer(Li(A("All Mail",href='#', role='button'),cls='uk-active', uk_filter_control="filter: .tag-mail"), + Li(A("Unread",href='#', role='button'), uk_filter_control="filter: .tag-unread"), + alt=True, cls='ml-auto max-w-40', )), + Div(cls='flex flex-1 flex-col')( + Div(cls='p-4')( + Div(cls='uk-inline w-full')( + Span(cls='uk-form-icon text-muted-foreground')(UkIcon('search')), + Input(placeholder='Search'))), + Div(cls='flex-1 overflow-y-auto max-h-[600px]')(MailList(mail_data)))) + +def IconNavItem(*d): return [Li(A(UkIcon(o[0],uk_tooltip=o[1]))) for o in d] +def IconNav(*c,cls=''): return Ul(cls=f'uk-iconnav {cls}')(*c) + +def MailDetailView(mail): + top_icons = [('folder','Archive'), ('ban','Move to junk'), ('trash','Move to trash')] + reply_icons = [('reply','Reply'), ('reply','Reply all'), ('forward','Forward')] + dropdown_items = ['Mark as unread', 'Star read', 'Add Label', 'Mute Thread'] + + return Container( + DivFullySpaced( + DivLAligned( + DivLAligned(*[UkIcon(o[0],uk_tooltip=o[1]) for o in top_icons]), + Div(UkIcon('clock', uk_tooltip='Snooze'), cls='pl-2'), + cls='space-x-2 divide-x divide-border'), + DivLAligned( + *[UkIcon(o[0],uk_tooltip=o[1]) for o in reply_icons], + Div(UkIcon('ellipsis-vertical',button=True)), + DropDownNavContainer(*map(lambda x: Li(A(x)), dropdown_items)))), + DivLAligned( + Span(mail['name'][:2], cls='flex h-10 w-10 items-center justify-center rounded-full bg-muted'), + Div(Strong(mail['name']), + Div(mail['subject']), + DivLAligned(P('Reply-To:'), A(mail['email'], href=f"mailto:{mail['email']}"), cls='space-x-1'), + P(Time(format_date(mail['date']))), + cls='space-y-1'+TextT.sm), + cls='m-4 space-x-4'), + DividerLine(), + P(mail['text'], cls=TextT.sm +'p-4'), + DividerLine(), + Div(TextArea(id='message', placeholder=f"Reply {mail['name']}"), + DivFullySpaced( + LabelSwitch('Mute this thread',id='mute'), + Button('Send', cls=ButtonT.primary)), + cls='space-y-4')) + +@rt +def index(): + return Title("Mail Example"),Container( + Grid(Div(sidebar, cls='col-span-1'), + Div(MailContent(), cls='col-span-2'), + Div(MailDetailView(mail_data[0]), cls='col-span-2'), + cols_sm=1, cols_md=1, cols_lg=5, cols_xl=5, + gap=0, cls='flex-1'), + cls=('flex', ContainerT.xl)) + +serve()"""FrankenUI Tasks Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * +import json + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def LAlignedCheckTxt(txt): return DivLAligned(UkIcon(icon='check'), P(txt, cls=TextPresets.muted_sm)) + +with open('data_/status_list.json', 'r') as f: data = json.load(f) +with open('data_/statuses.json', 'r') as f: statuses = json.load(f) + +def _create_tbl_data(d): + return {'Done': d['selected'], 'Task': d['id'], 'Title': d['title'], + 'Status' : d['status'], 'Priority': d['priority'] } + +data = [_create_tbl_data(d) for d in data] +page_size = 15 +current_page = 0 +paginated_data = data[current_page*page_size:(current_page+1)*page_size] + +priority_dd = [{'priority': "low", 'count': 36 }, {'priority': "medium", 'count': 33 }, {'priority': "high", 'count': 31 }] + +status_dd = [{'status': "backlog", 'count': 21 },{'status': "todo", 'count': 21 },{'status': "progress", 'count': 20 },{'status': "done",'count': 19 },{'status': "cancelled", 'count': 19 }] + +def create_hotkey_li(hotkey): return NavCloseLi(A(DivFullySpaced(hotkey[0], Span(hotkey[1], cls=TextPresets.muted_sm)))) + +hotkeys_a = (('Profile','⇧⌘P'),('Billing','⌘B'),('Settings','⌘S'),('New Team','')) +hotkeys_b = (('Logout',''), ) + +avatar_opts = DropDownNavContainer( + NavHeaderLi(P('sveltecult'),NavSubtitle('leader@sveltecult.com')), + NavDividerLi(), + *map(create_hotkey_li, hotkeys_a), + NavDividerLi(), + *map(create_hotkey_li, hotkeys_b),) + +def CreateTaskModal(): + return Modal( + Div(cls='p-6')( + ModalTitle('Create Task'), + P('Fill out the information below to create a new task', cls=TextPresets.muted_sm), + Br(), + Form(cls='space-y-6')( + Grid(Div(Select(*map(Option,('Documentation', 'Bug', 'Feature')), label='Task Type', id='task_type')), + Div(Select(*map(Option,('In Progress', 'Backlog', 'Todo', 'Cancelled', 'Done')), label='Status', id='task_status')), + Div(Select(*map(Option, ('Low', 'Medium', 'High')), label='Priority', id='task_priority'))), + TextArea(label='Title', placeholder='Please describe the task that needs to be completed'), + DivRAligned( + ModalCloseButton('Cancel', cls=ButtonT.ghost), + ModalCloseButton('Submit', cls=ButtonT.primary), + cls='space-x-5'))), + id='TaskForm') + +page_heading = DivFullySpaced(cls='space-y-2')( + Div(cls='space-y-2')( + H2('Welcome back!'),P("Here's a list of your tasks for this month!", cls=TextPresets.muted_sm)), + Div(DiceBearAvatar("sveltcult",8,8),avatar_opts)) + +table_controls =(Input(cls='w-[250px]',placeholder='Filter task'), + Button("Status"), + DropDownNavContainer(map(NavCloseLi,[A(DivFullySpaced(P(a['status']), P(a['count'])),cls='capitalize') for a in status_dd])), + Button("Priority"), + DropDownNavContainer(map(NavCloseLi,[A(DivFullySpaced(LAlignedCheckTxt(a['priority']), a['count']),cls='capitalize') for a in priority_dd])), + Button("View"), + DropDownNavContainer(map(NavCloseLi,[A(LAlignedCheckTxt(o)) for o in ['Title','Status','Priority']])), + Button('Create Task',cls=(ButtonT.primary, TextPresets.bold_sm), data_uk_toggle="target: #TaskForm")) + +def task_dropdown(): + return Div(Button(UkIcon('ellipsis')), + DropDownNavContainer( + map(NavCloseLi,[ + *map(A,('Edit', 'Make a copy', 'Favorite')), + A(DivFullySpaced(*[P(o, cls=TextPresets.muted_sm) for o in ('Delete', '⌘⌫')]))]))) +def header_render(col): + match col: + case "Done": return Th(CheckboxX(), shrink=True) + case 'Actions': return Th("", shrink=True) + case _: return Th(col, expand=True) + +def cell_render(col, val): + def _Td(*args,cls='', **kwargs): return Td(*args, cls=f'p-2 {cls}',**kwargs) + match col: + case "Done": return _Td(shrink=True)(CheckboxX(selected=val)) + case "Task": return _Td(val, cls='uk-visible@s') # Hide on small screens + case "Title": return _Td(val, cls='font-medium', expand=True) + case "Status" | "Priority": return _Td(cls='uk-visible@m uk-text-nowrap capitalize')(Span(val)) + case "Actions": return _Td(task_dropdown(), shrink=True) + case _: raise ValueError(f"Unknown column: {col}") + +task_columns = ["Done", 'Task', 'Title', 'Status', 'Priority', 'Actions'] + +tasks_table = Div(cls='mt-4')( + TableFromDicts( + header_data=task_columns, + body_data=paginated_data, + body_cell_render=cell_render, + header_cell_render=header_render, + sortable=True, + cls=(TableT.responsive, TableT.sm, TableT.divider))) + + +def footer(): + total_pages = (len(data) + page_size - 1) // page_size + return DivFullySpaced( + Div('1 of 100 row(s) selected.', cls=TextPresets.muted_sm), + DivLAligned( + DivCentered(f'Page {current_page + 1} of {total_pages}', cls=TextT.sm), + DivLAligned(*[UkIconLink(icon=i, button=True) for i in ('chevrons-left', 'chevron-left', 'chevron-right', 'chevrons-right')]))) + +tasks_ui = Div(DivFullySpaced(DivLAligned(table_controls), cls='mt-8'), tasks_table, footer()) + +@rt +def index(): return Container(page_heading, tasks_ui, CreateTaskModal()) + +serve()"""FrankenUI Music Example build with MonsterUI (Original design by ShadCN)""" + +from fasthtml.common import * + +from monsterui.all import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def MusicLi(t,hk=''): return Li(A(DivFullySpaced(t,P(hk,cls=TextPresets.muted_sm)))) + +music_items = [("About Music", "" ), + ("Preferences", "⌘" ), + ("Hide Music" , "⌘H" ), + ("Hide Others", "⇧⌘H"), + ("Quit Music" , "⌘Q" )] + +file_dd_items = [("New", ""), + ("Open Stream URL", "⌘U"), + ("Close Window", "⌘W"), + ("Library", ""), + ("Import", "⌘O"), + ("Burn Playlist to Disc", ""), + ("Show in Finder", "⇧⌘R"), + ("Convert", ""), + ("Page Setup", "Print")] + +edit_actions = [("Undo", "⌘Z"), + ("Redo", "⇧⌘Z"), + ("Cut", "⌘X"), + ("Copy", "⌘C"), + ("Paste", "⌘V"), + ("Select All", "⌘A"), + ("Deselect All", "⇧⌘A")] + +view_dd_data = ["Show Playing Next", "Show Lyrics", "Show Status Bar", "Hide Sidebar", "Enter Full Screen"] + + +music_headers = NavBar( + Button("Music", cls=ButtonT.ghost+TextT.gray),DropDownNavContainer(Li(A("Music"),NavContainer(map(lambda x: MusicLi(*x), music_items)))), + Button("File", cls=ButtonT.ghost+TextT.gray), DropDownNavContainer(Li(A("File"), NavContainer(map(lambda x: MusicLi(*x), file_dd_items)))), + Button("Edit", cls=ButtonT.ghost+TextT.gray), DropDownNavContainer(Li(A("Edit")),NavContainer( + *map(lambda x: MusicLi(*x), edit_actions), + Li(A(DivFullySpaced("Smart Dictation",UkIcon("mic")))), + Li(A(DivFullySpaced("Emojis & Symbols",UkIcon("globe")))))), + Button("View", cls=ButtonT.ghost+TextT.gray),DropDownNavContainer(Li(A("View"),NavContainer(map(lambda x: MusicLi(x), view_dd_data)))), + brand=DivLAligned(H2("Purrify")) + ) + + + + +# music_headers = NavBarContainer( +# NavBarLSide( +# NavBarNav( +# Li(A("Music"),NavBarNavContainer(map(lambda x: MusicLi(*x), music_items))), +# Li(A("File"), NavBarNavContainer(map(lambda x: MusicLi(*x), file_dd_items))), +# Li(A("Edit")), +# NavBarNavContainer( +# *map(lambda x: MusicLi(*x), edit_actions), +# Li(A(DivFullySpaced("Smart Dictation",UkIcon("mic")))), +# Li(A(DivFullySpaced("Emojis & Symbols",UkIcon("globe"))))), +# Li(A("View"), +# NavBarNavContainer(map(lambda x: MusicLi(x), view_dd_data))), +# Li(A("Account"), +# NavBarNavContainer( +# NavHeaderLi("Switch Account"), +# *map(MusicLi, ("Andy", "Benoit", "Luis", "Manage Family", "Add Account"))))))) + + +def Album(title,artist): + img_url = 'https://ucarecdn.com/e5607eaf-2b2a-43b9-ada9-330824b6afd7/music1.webp' + return Div( + Div(cls="overflow-hidden rounded-md")(Img(cls="transition-transform duration-200 hover:scale-105", src=img_url)), + Div(cls='space-y-1')(Strong(title),P(artist,cls=TextT.muted))) + +listen_now_albums = (("Roar", "Catty Perry"), ("Feline on a Prayer", "Cat Jovi"),("Fur Elise", "Ludwig van Beethovpurr"),("Purrple Rain", "Prince's Cat")) + +made_for_you_albums = [("Like a Feline", "Catdonna"), + ("Livin' La Vida Purrda", "Ricky Catin"), + ("Meow Meow Rocket", "Elton Cat"), + ("Rolling in the Purr", "Catdelle"), + ("Purrs of Silence", "Cat Garfunkel"), + ("Meow Me Maybe", "Carly Rae Purrsen"),] + +music_content = (Div(H3("Listen Now"), cls="mt-6 space-y-1"), + Subtitle("Top picks for you. Updated daily."), + DividerLine(), + Grid(*[Album(t,a) for t,a in listen_now_albums], cls='gap-8'), + Div(H3("Made for You"), cls="mt-6 space-y-1"), + Subtitle("Your personal playlists. Updated daily."), + DividerLine(), + Grid(*[Album(t,a) for t,a in made_for_you_albums], cols_xl=6)) + +tabs = TabContainer( + Li(A('Music', href='#'), cls='uk-active'), + Li(A('Podcasts', href='#')), + Li(A('Live', cls='opacity-50'), cls='uk-disabled'), + uk_switcher='connect: #component-nav; animation: uk-animation-fade', + alt=True) + +def podcast_tab(): + return Div( + Div(cls='space-y-3 mt-6')( + H3("New Episodes"), + Subtitle("Your favorite podcasts. Updated daily.")), + Div(cls="uk-placeholder flex h-[450px] items-center justify-center rounded-md mt-4",uk_placeholder=True)( + DivVStacked(cls="space-y-6")( + UkIcon("microphone", 3), + H4("No episodes added"), + Subtitle("You have not added any podcasts. Add one below."), + Button("Add Podcast", cls=ButtonT.primary)))) + +discoved_data = [("play-circle","Listen Now"), ("binoculars", "Browse"), ("rss","Radio")] +library_data = [("play-circle", "Playlists"), ("music", "Songs"), ("user", "Made for You"), ("users", "Artists"), ("bookmark", "Albums")] +playlists_data = [("library","Recently Added"), ("library","Recently Played")] + +def MusicSidebarLi(icon, text): return Li(A(DivLAligned(UkIcon(icon), P(text)))) +sidebar = NavContainer( + NavHeaderLi(H3("Discover")), *[MusicSidebarLi(*o) for o in discoved_data], + NavHeaderLi(H3("Library")), *[MusicSidebarLi(*o) for o in library_data], + NavHeaderLi(H3("Playlists")),*[MusicSidebarLi(*o) for o in playlists_data], + cls=(NavT.primary,'space-y-3','pl-8')) + +@rt +def index(): + return Title("Music Example"),Container(music_headers, DividerSplit(), + Grid(sidebar, + Div(cls="col-span-4 border-l border-border")( + Div(cls="px-8 py-6")( + DivFullySpaced( + Div(cls="max-w-80")(tabs), + Button(cls=ButtonT.primary)(DivLAligned(UkIcon('circle-plus')),Div("Add music"))), + Ul(id="component-nav", cls="uk-switcher")( + Li(*music_content), + Li(podcast_tab())))), + cols_sm=1, cols_md=1, cols_lg=5, cols_xl=5)) + +serve()"""FrankenUI Auth Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +@rt +def index(): + left = Div(cls="col-span-1 hidden flex-col justify-between bg-zinc-900 p-8 text-white lg:flex")( + Div(cls=(TextT.bold))("Acme Inc"), + Blockquote(cls="space-y-2")( + P(cls=TextT.lg)('"This library has saved me countless hours of work and helped me deliver stunning designs to my clients faster than ever before."'), + Footer(cls=TextT.sm)("Sofia Davis"))) + + right = Div(cls="col-span-2 flex flex-col p-8 lg:col-span-1")( + DivRAligned(Button("Login", cls=ButtonT.ghost)), + DivCentered(cls='flex-1')( + Container( + DivVStacked( + H3("Create an account"), + Small("Enter your email below to create your account", cls=TextT.muted)), + Form( + Input(placeholder="name@example.com"), + Button(Span(cls="mr-2", uk_spinner="ratio: 0.54"), "Sign in with Email", cls=(ButtonT.primary, "w-full"), disabled=True), + DividerSplit(Small("Or continue with"),cls=TextT.muted), + Button(UkIcon('github',cls='mr-2'), "Github", cls=(ButtonT.default, "w-full")), + cls='space-y-6'), + DivVStacked(Small( + "By clicking continue, you agree to our ", + A(cls=AT.muted, href="#demo")("Terms of Service")," and ", + A(cls=AT.muted, href="#demo")("Privacy Policy"),".", + cls=(TextT.muted,"text-center"))), + cls="space-y-6"))) + + return Title("Auth Example"),Grid(left,right,cols=2, gap=0,cls='h-screen') + + +serve()# Accordion API Reference + +### Example Accordions + +A simple accordion with fluid collapsing and expanding animation where only a single Section can be exanded at any time. + +See Source + +See Output + +## Accordion Header + + * Section 1 + +Content for the first section. + +More content here. + + * Section 2 + +Content for the second section. + +A label inside! + + * Section 3 - The last one! + +Content for the third section. + +[code] + + def ex_accordion_1(): + return Div( + H2("Accordion Header"), + Accordion( + AccordionItem( + "Section 1", + P("Content for the first section."), + P("More content here."), + ), + AccordionItem( + "Section 2", + P("Content for the second section."), + Label("A label inside!"), + li_kwargs={"id": "section-2"}, + ), + AccordionItem( + "Section 3 - The last one!", P("Content for the third section.") + ), + multiple=False, + animation=True, + ), + ), + +[/code] + +An accordion with fluid collapsing and expanding animation where one section is already expanded at startup and multiple section can be expanded at any time. + +See Source + +See Output + +## Accordion Header + + * Section 1 + +Content for the first section. + +More content here. + + * Section 2 + +Content for the second section. + +A label inside! + + * Section 3 - The last one! + +Content for the third section. + +[code] + + def ex_accordion_2(): + return Div( + H2("Accordion Header"), + Accordion( + AccordionItem( + "Section 1", + P("Content for the first section."), + P("More content here."), + open=True, + ), + AccordionItem( + "Section 2", + P("Content for the second section."), + Label("A label inside!"), + li_kwargs={"id": "section-2"}, + ), + AccordionItem( + "Section 3 - The last one!", P("Content for the third section.") + ), + multiple=True, + animation=True, + ), + ), + +[/code] + +An accordion with no collapsing and expanding animation where only a single Section can be exanded at any time. + +See Source + +See Output + +## Accordion Header + + * Section 1 + +Content for the first section. + +More content here. + + * Section 2 + +Content for the second section. + +A label inside! + + * Section 3 - The last one! + +Content for the third section. + +[code] + + def ex_accordion_3(): + return Div( + H2("Accordion Header"), + Accordion( + AccordionItem( + "Section 1", + P("Content for the first section."), + P("More content here."), + ), + AccordionItem( + "Section 2", + P("Content for the second section."), + Label("A label inside!"), + li_kwargs={"id": "section-2"}, + ), + AccordionItem( + "Section 3 - The last one!", P("Content for the third section.") + ), + multiple=False, + animation=False, + ), + ), + +[/code] + +### API Reference + +### Accordion + +Source + +[code] + + Accordion(*c: 'AccordionItem', cls: Union[str, enum.Enum, tuple] = (), multiple: Optional[bool] = None, collapsible: Optional[bool] = None, animation: Optional[bool] = None, duration: Optional[int] = None, active: Optional[int] = None, transition: Optional[str] = None, tag: str = 'ul', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a styled Accordion container using accordion component. + +**Params** + + * `c` One or more `AccordionItem` components + + * `cls` Additional classes for the container (`Ul` or `Div`) + + * `multiple` Allow multiple items to be open simultaneously (UIkit option) + + * `collapsible` Allow all items to be closed (UIkit option, default True) + + * `animation` Enable/disable animation (UIkit option, default True) + + * `duration` Animation duration in ms (UIkit option, default 200) + + * `active` Index (0-based) of the item to be open by default (UIkit option) + + * `transition` Animation transition timing function (UIkit option, e.g., 'ease-out') + + * `tag` HTML tag for the container ('ul' or 'div') + + * `kwargs` + +**Returns:** Ul(*items...) or Div(*items...) + +### AccordionItem + +Source + +[code] + + AccordionItem(title: Union[str, fastcore.xml.FT], *c: fastcore.xml.FT, cls: Union[str, enum.Enum, tuple] = (), title_cls: Union[str, enum.Enum, tuple] = ('flex justify-between items-center w-full',), content_cls: Union[str, enum.Enum, tuple] = (), open: bool = False, li_kwargs: Optional[Dict] = None, a_kwargs: Optional[Dict] = None, div_kwargs: Optional[Dict] = None) -> fastcore.xml.FT +[/code] + +> Creates a single item for use within an Accordion component, handling title, content, and open state. + +**Params** + + * `title` Content for the accordion item title + + * `c` Content to display when the item is open + + * `cls` Additional classes for the outer `Li` container + + * `title_cls` Additional classes for the title `A` tag + + * `content_cls` Additional classes for the content `Div` + + * `open` Whether this item should be open by default + + * `li_kwargs` Additional attributes for the outer `Li` tag + + * `a_kwargs` Additional attributes for the title `A` tag + + * `div_kwargs` Additional attributes for the content `Div` tag + +**Returns:** Li(A(title, Span(Icon, Icon)), Div(content)) +# Buttons & Links API Reference + +See Source + +See Output + +DefaultPrimarySecondaryDangerTextLinkGhost + +[code] + + def ex_buttons(): + return Grid( + Button("Default"), + Button("Primary", cls=ButtonT.primary), + Button("Secondary", cls=ButtonT.secondary), + Button("Danger", cls=ButtonT.destructive), + Button("Text", cls=ButtonT.text), + Button("Link", cls=ButtonT.link), + Button("Ghost", cls=ButtonT.ghost), + ) + +[/code] + +See Source + +See Output + +Default LinkMuted LinkText LinkReset LinkPrimary LinkClassic Link + +[code] + + def ex_links(): + return Div(cls='space-x-4')( + A('Default Link'), + A('Muted Link', cls=AT.muted), + A('Text Link', cls=AT.text), + A('Reset Link', cls=AT.reset), + A('Primary Link', cls=AT.primary), + A('Classic Link', cls=AT.classic),) + +[/code] + +### Button + +Source + +[code] + + Button(*c: Union[str, fastcore.xml.FT], cls: Union[str, enum.Enum] = , submit=True, **kwargs) -> fastcore.xml.FT +[/code] + +> Button with Styling (defaults to `submit` for form submission) + +**Params** + + * `c` Contents of `Button` tag (often text) + + * `cls` Classes in addition to `Button` styling (use `ButtonT` for built in styles) + + * `submit` Whether the button should submit a form + + * `kwargs` + +**Returns:** Button(..., cls='uk-btn') + +* * * + +### ButtonT + +_Options for styling Buttons_ + +Option | Value | Option | Value | Option | Value +---|---|---|---|---|--- +default | uk-btn-default | ghost | uk-btn-ghost | primary | uk-btn-primary +secondary | uk-btn-secondary | destructive | uk-btn-destructive | text | uk-btn-text +link | uk-btn-link | xs | uk-btn-xs | sm | uk-btn-sm +lg | uk-btn-lg | xl | uk-btn-xl | icon | uk-btn-icon + +* * * + +### AT + +_Link styles from https://franken-ui.dev/docs/link_ + +Option | Value | Option | Value +---|---|---|--- +muted | uk-link-muted | text | uk-link-text +reset | uk-link-reset | primary | uk-link text-primary hover:text-primary-focus underline +classic | text-blue-600 hover:text-blue-800 underline | | +# Cards API Reference + +### Example Usage + +See Source + +See Output + +Header + +A card with header and footer + +Input + +Range + +Footer Submit Button + +[code] + + def ex_card(): + return Card( + Form(LabelInput("Input"), + LabelRange("Range")), + header=Div( + CardTitle("Header"), + P("A card with header and footer",cls=TextPresets.muted_sm)), + footer=DivLAligned(Button("Footer Submit Button"))) + +[/code] + +See Source + +See Output + +#### Creating Custom FastHTML Tags for Markdown Rendering + +A step by step tutorial to rendering markdown in FastHTML using zero-md inside of DaisyUI chat bubbles + +Isaac Flath20-October-2024 + +FastHTMLHTMXWeb Apps + +Read + +[code] + + def ex_card2_wide(): + def Tags(cats): return DivLAligned(map(Label, cats)) + + return Card( + DivLAligned( + A(Img(src="https://picsum.photos/200/200?random=12", style="width:200px"),href="#"), + Div(cls='space-y-3 uk-width-expand')( + H4("Creating Custom FastHTML Tags for Markdown Rendering"), + P("A step by step tutorial to rendering markdown in FastHTML using zero-md inside of DaisyUI chat bubbles"), + DivFullySpaced(map(Small, ["Isaac Flath", "20-October-2024"]), cls=TextT.muted), + DivFullySpaced( + Tags(["FastHTML", "HTMX", "Web Apps"]), + Button("Read", cls=(ButtonT.primary,'h-6'))))), + cls=CardT.hover) + +[/code] + +See Source + +See Output + +#### Creating Custom FastHTML Tags for Markdown Rendering + +A step by step tutorial to rendering markdown in FastHTML using zero-md inside of DaisyUI chat bubbles + +Isaac Flath20-October-2024 + +FastHTMLHTMXWeb Apps + +Read + +[code] + + def ex_card2_tall(): + def Tags(cats): return DivLAligned(map(Label, cats)) + + return Card( + Div( + A(Img(src="https://picsum.photos/400/200?random=14"), href="#"), + Div(cls='space-y-3 uk-width-expand')( + H4("Creating Custom FastHTML Tags for Markdown Rendering"), + P("A step by step tutorial to rendering markdown in FastHTML using zero-md inside of DaisyUI chat bubbles"), + DivFullySpaced(map(Small, ["Isaac Flath", "20-October-2024"]), cls=TextT.muted), + DivFullySpaced( + Tags(["FastHTML", "HTMX", "Web Apps"]), + Button("Read", cls=(ButtonT.primary,'h-6'))))), + cls=CardT.hover) + +[/code] + +See Source + +See Output + +### Sarah Chen + +Engineering Lead + +San Francisco + +### James Wilson + +Senior Developer + +New York + +### Maria Garcia + +UX Designer + +London + +### Alex Kumar + +Product Manager + +Singapore + +### Emma Brown + +DevOps Engineer + +Toronto + +### Marcus Johnson + +Frontend Developer + +Berlin + +[code] + + def ex_card3(): + def team_member(name, role, location="Remote"): + return Card( + DivLAligned( + DiceBearAvatar(name, h=24, w=24), + Div(H3(name), P(role))), + footer=DivFullySpaced( + DivHStacked(UkIcon("map-pin", height=16), P(location)), + DivHStacked(*(UkIconLink(icon, height=16) for icon in ("mail", "linkedin", "github"))))) + team = [ + team_member("Sarah Chen", "Engineering Lead", "San Francisco"), + team_member("James Wilson", "Senior Developer", "New York"), + team_member("Maria Garcia", "UX Designer", "London"), + team_member("Alex Kumar", "Product Manager", "Singapore"), + team_member("Emma Brown", "DevOps Engineer", "Toronto"), + team_member("Marcus Johnson", "Frontend Developer", "Berlin") + ] + return Grid(*team, cols_sm=1, cols_md=1, cols_lg=2, cols_xl=3) + +[/code] + +### API Reference + +### Card + +Source + +[code] + + Card(*c, header: Union[fastcore.xml.FT, Iterable[fastcore.xml.FT]] = None, footer: Union[fastcore.xml.FT, Iterable[fastcore.xml.FT]] = None, body_cls='space-y-6', header_cls=(), footer_cls=(), cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a Card with a header, body, and footer + +**Params** + + * `c` Components that go in the body (Main content of the card such as a form, and image, a signin form, etc.) + + * `header` Component(s) that goes in the header (often a `ModalTitle` and a subtitle) + + * `footer` Component(s) that goes in the footer (often a `ModalCloseButton`) + + * `body_cls` classes for the body + + * `header_cls` classes for the header + + * `footer_cls` classes for the footer + + * `cls` class for outermost component + + * `kwargs` + +**Returns:** Card component + +### CardTitle + +Source + +[code] + + CardTitle(*c, cls=(), **kwargs) +[/code] + +> Creates a card title + +**Params** + + * `c` Components (often a string) + + * `cls` Additional classes on the div + + * `kwargs` + +* * * + +### CardT + +_Card styles from UIkit_ + +Option | Value | Option | Value +---|---|---|--- +default | uk-card-default | primary | uk-card-primary +secondary | uk-card-secondary | destructive | uk-card-destructive +hover | uk-card hover:shadow-lg hover:-translate-y-1 transition-all duration-200 | | + +The remainder of these are only needed if you're doing something really special. They are used in the `Card` function to generate the boilerplate for you. + +### CardContainer + +Source + +[code] + + CardContainer(*c, cls=, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a card container + +**Params** + + * `c` Components (typically `CardHeader`, `CardBody`, `CardFooter`) + + * `cls` Additional classes on the div + + * `kwargs` + +**Returns:** Container for a card + +### CardHeader + +Source + +[code] + + CardHeader(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a card header + +**Params** + + * `c` Components that goes in the header (often a `ModalTitle` and description) + + * `cls` Additional classes on the div + + * `kwargs` + +**Returns:** Container for the header of a card + +### CardBody + +Source + +[code] + + CardBody(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a card body + +**Params** + + * `c` Components that go in the body (Main content of the card such as a form, and image, a signin form, etc.) + + * `cls` Additional classes on the div + + * `kwargs` + +**Returns:** Container for the body of a card + +### CardFooter + +Source + +[code] + + CardFooter(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a card footer + +**Params** + + * `c` Components that go in the footer (often a `ModalCloseButton`) + + * `cls` Additional classes on the div + + * `kwargs` + +**Returns:** Container for the footer of a card +# Charts API Reference + +MonsterUI supports ApexCharts, a javascript library for rendering different charts like line and pie charts. See the full list of chart types here. + +To render a chart you'll need to include the ApexChart js in your app headers like this + +`app, rt = fast_app(hdrs=Theme.blue.headers(apex_charts=True))` + +Then create an `ApexChart` component as shown in the examples below. + +Generally, you should be able to take any chart from the ApexChart docs, convert the chart's options var to a python dict and plug it straight into MonsterUI's ApexChart component. + +## Example usage + +#### Line chart + +See Source + +See Output + +[code] + + def ex_line_chart(): + return ApexChart( + opts={ + "chart": {"type":"line", "zoom":{"enabled": False}, "toolbar":{"show":False}}, + "series": [{"name":"Desktops", "data": [186, 305, 237, 73, 209, 214, 355]}], + "xaxis": {"categories":["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"]} + }, + cls='max-w-md max-h-md' + ) + +[/code] + +#### Pie chart + +See Source + +See Output + +[code] + + def ex_pie_chart(): + return ApexChart( + opts={ + "chart": {"type":"pie", "zoom":{"enabled": False}, "toolbar":{"show":False}}, + "series": [186, 305, 237, 73, 209, 214, 355], + "labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"] + }, + cls='max-w-md max-h-md' + ) + +[/code] + +### ApexChart + +Source + +[code] + + ApexChart(*, opts: Dict, cls: enum.Enum | str | tuple = (), **kws) -> fastcore.xml.FT +[/code] + +> Apex chart component + +**Params** + + * `opts` ApexChart options used to render your chart (e.g. {"chart":{"type":"line"}, ...}) + + * `cls` Classes for the outer container + + * `kws` + +**Returns:** Div(Uk_chart(Script(...))) +# Articles, Containers & Sections API Reference + +### ArticleMeta + +Source + +[code] + + ArticleMeta(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A metadata component for use within an Article showing things like date, author etc + +**Params** + + * `c` contents of ArticleMeta tag (often other tags) + + * `cls` Classes in addition to ArticleMeta styling + + * `kwargs` + +**Returns:** P(..., cls='uk-article-meta') + +### ArticleTitle + +Source + +[code] + + ArticleTitle(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A title component for use within an Article + +**Params** + + * `c` contents of ArticleTitle tag (often other tags) + + * `cls` Classes in addition to ArticleTitle styling + + * `kwargs` + +**Returns:** H1(..., cls='uk-article-title') + +### Article + +Source + +[code] + + Article(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A styled article container for blog posts or similar content + +**Params** + + * `c` contents of Article tag (often other tags) + + * `cls` Classes in addition to Article styling + + * `kwargs` + +**Returns:** Article(..., cls='uk-article') + +See Source + +See Output + +# Sample Article Title + +By: John Doe + +lorem ipsum dolor sit amet consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + +[code] + + def ex_articles(): + return Article( + ArticleTitle("Sample Article Title"), + Subtitle("By: John Doe"), + P('lorem ipsum dolor sit amet consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.')) + +[/code] + +### Container + +Source + +[code] + + Container(*c, cls=('mt-5', ), **kwargs) -> fastcore.xml.FT +[/code] + +> Div to be used as a container that often wraps large sections or a page of content + +**Params** + + * `c` Contents of Container tag (often other FT Components) + + * `cls` Classes in addition to Container styling + + * `kwargs` + +**Returns:** Container(..., cls='uk-container') + +* * * + +### ContainerT + +_Max width container sizes from https://franken-ui.dev/docs/container_ + +Option | Value | Option | Value +---|---|---|--- +xs | uk-container-xs | sm | uk-container-sm +lg | uk-container-lg | xl | uk-container-xl +expand | uk-container-expand | | + +See Source + +See Output + +This is a sample container with custom styling. + +[code] + + def ex_containers(): + return Container( + "This is a sample container with custom styling.", + cls=ContainerT.xs, + style="background-color: #FFA500; color: #000000") + +[/code] + +### Section + +Source + +[code] + + Section(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Section with styling and margins + +**Params** + + * `c` contents of Section tag (often other tags) + + * `cls` Classes in addition to Section styling + + * `kwargs` + +**Returns:** Div(..., cls='uk-section') + +* * * + +### SectionT + +_Section styles from https://franken-ui.dev/docs/section_ + +Option | Value | Option | Value | Option | Value +---|---|---|---|---|--- +default | uk-section-default | muted | uk-section-muted | primary | uk-section-primary +secondary | uk-section-secondary | xs | uk-section-xsmall | sm | uk-section-small +lg | uk-section-large | xl | uk-section-xlarge | remove_vertical | uk-section-remove-vertical +# Dividers API Reference + +### Divider + +Source + +[code] + + Divider(*c, cls=('my-4', ), **kwargs) -> fastcore.xml.FT +[/code] + +> Divider with default styling and margin + +**Params** + + * `c` contents of Divider tag (often nothing) + + * `cls` Classes in addition to Divider styling + + * `kwargs` + +**Returns:** Hr(..., cls='uk-divider-icon') or Div(..., cls='uk-divider-vertical') + +* * * + +### DividerT + +_Divider Styles from https://franken-ui.dev/docs/divider_ + +Option | Value | Option | Value +---|---|---|--- +icon | uk-divider-icon | sm | uk-divider-sm +vertical | uk-divider-vertical | | + +See Source + +See Output + +Small Divider + +* * * + +Vertical Divider + +Icon Divider + +* * * +[code] + + def ex_dividers(): + return Div( + P("Small Divider"), + Divider(cls=DividerT.sm), + DivCentered( + P("Vertical Divider"), + Divider(cls=DividerT.vertical)), + DivCentered("Icon Divider"), + Divider(cls=DividerT.icon)) + +[/code] + +### DividerSplit + +Source + +[code] + + DividerSplit(*c, cls=(), line_cls=(), text_cls=()) +[/code] + +> Creates a simple horizontal line divider with configurable thickness and vertical spacing + +**Params** + + * `c` + + * `cls` + + * `line_cls` + + * `text_cls` + +See Source + +See Output + +Or continue with + +[code] + + def ex_dividersplit(): + return DividerSplit(P("Or continue with", cls=TextPresets.muted_sm)) + +[/code] + +### DividerLine + +Source + +[code] + + DividerLine(lwidth=2, y_space=4) +[/code] + +> **Params** + + * `lwidth` + + * `y_space` + +See Source + +See Output + +* * * +[code] + + def ex_dividerline(): + return DividerLine() + +[/code] +# Forms and User Inputs API Reference + +### Example Form + +This form was live coded in a 5 minute video here + +See Source + +See Output + +### Emergency Contact Form + +Please fill out the form completely + +First Name + +Last Name + +Email + +Phone + +### Relationship to patient + +Parent + +Sibling + +Friend + +Spouse + +Significant Other + +Relative + +Child + +Other + +Address + +Address Line 2 + +City + +State + +Zip + +Submit Form + +[code] + + def ex_form(): + relationship = ["Parent",'Sibling', "Friend", "Spouse", "Significant Other", "Relative", "Child", "Other"] + return Div(cls='space-y-4')( + DivCentered( + H3("Emergency Contact Form"), + P("Please fill out the form completely", cls=TextPresets.muted_sm)), + Form(cls='space-y-4')( + Grid(LabelInput("First Name",id='fn'), LabelInput("Last Name",id='ln')), + Grid(LabelInput("Email", id='em'), LabelInput("Phone", id='ph')), + H3("Relationship to patient"), + Grid(*[LabelCheckboxX(o) for o in relationship], cols=4, cls='space-y-3'), + LabelInput("Address", id='ad'), + LabelInput("Address Line 2", id='ad2'), + Grid(LabelInput("City", id='ct'), LabelInput("State", id='st')), + LabelInput("Zip", id='zp'), + DivCentered(Button("Submit Form", cls=ButtonT.primary)))) + +[/code] + +See Source + +See Output + +Upload Button! + +Upload Zone + +[code] + + def ex_upload(): + return Div(Upload("Upload Button!", id='upload1'), + UploadZone(DivCentered(Span("Upload Zone"), UkIcon("upload")), id='upload2'), + cls='space-y-4') + +[/code] + +### FormLabel + +Source + +[code] + + FormLabel(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A Label with default styling + +**Params** + + * `c` contents of FormLabel tag (often text) + + * `cls` Classes in addition to FormLabel styling + + * `kwargs` + +**Returns:** Label(..., cls='uk-form-label') + +See Source + +See Output + +Form Label + +[code] + + def ex_formlabel(): + return FormLabel("Form Label") + +[/code] + +### Input + +Source + +[code] + + Input(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> An Input with default styling + +**Params** + + * `c` contents of Input tag (often nothing) + + * `cls` Classes in addition to Input styling + + * `kwargs` + +**Returns:** Input(..., cls='uk-input') + +See Source + +See Output + +Input + +[code] + + def ex_input(): + return Div( + Input(placeholder="Enter text"), + LabelInput(label="Input", id='myid')) + +[/code] + +### LabelInput + +Source + +[code] + + LabelInput(label: str | fastcore.xml.FT, lbl_cls='', input_cls='', cls='space-y-2', id='', **kwargs) -> fastcore.xml.FT +[/code] + +> A `FormLabel` and `Input` pair that provides default spacing and links/names them based on id + +**Params** + + * `label` FormLabel content (often text) + + * `lbl_cls` Additional classes for `FormLabel` + + * `input_cls` Additional classes for `Input` + + * `cls` Classes on container (default is `'space-y-2'` to prevent scrunched up form elements) + + * `id` id for `FormLabel` and `Input` (`id`, `name` and `for` attributes are set to this value) + + * `kwargs` + +**Returns:** Div(cls='space-y-2')(`FormLabel`, `Input`) + +### LabelCheckboxX + +Source + +[code] + + LabelCheckboxX(label: str | fastcore.xml.FT, lbl_cls='', input_cls='', container=functools.partial(, 'div', void_=False), cls='flex items-center space-x-2', id='', **kwargs) -> fastcore.xml.FT +[/code] + +> A FormLabel and CheckboxX pair that provides default spacing and links/names them based on id + +**Params** + + * `label` FormLabel content (often text) + + * `lbl_cls` Additional classes for `FormLabel` + + * `input_cls` Additional classes for `CheckboxX` + + * `container` Container to wrap label and input in (default is Div) + + * `cls` Classes on container (default is 'flex items-center space-x-2') + + * `id` id for `FormLabel` and `CheckboxX` (`id`, `name` and `for` attributes are set to this value) + + * `kwargs` + +**Returns:** Div(cls='flex items-center space-x-2')(`FormLabel`, `CheckboxX`) + +### LabelSwitch + +Source + +[code] + + LabelSwitch(label: str | fastcore.xml.FT, lbl_cls='', input_cls='', cls='space-x-2', id='', *, container=functools.partial(, 'div', void_=False)) -> fastcore.xml.FT +[/code] + +> **Params** + + * `label` FormLabel content (often text) + + * `lbl_cls` Additional classes for `FormLabel` + + * `input_cls` Additional classes for `Switch` + + * `container` Container to wrap label and input in (default is Div) + + * `cls` Classes on container (default is `'space-x-2'` to prevent scrunched up form elements) + + * `id` id for `FormLabel` and `Switch` (`id`, `name` and `for` attributes are set to this value) + +**Returns:** Div(cls='space-y-2')(`FormLabel`, `Switch`) + +### LabelRange + +Source + +[code] + + LabelRange(label: str | fastcore.xml.FT, lbl_cls='', input_cls='', cls='space-y-6', id='', value='', min=None, max=None, step=None, label_range=True, *, container=functools.partial(, 'div', void_=False)) -> fastcore.xml.FT +[/code] + +> A FormLabel and Range pair that provides default spacing and links/names them based on id + +**Params** + + * `label` FormLabel content (often text) + + * `lbl_cls` Additional classes for `FormLabel` + + * `input_cls` Additional classes for `Range` + + * `container` Container to wrap label and input in (default is Div) + + * `cls` Classes on container (default is `'space-y-2'` to prevent scrunched up form elements) + + * `id` id for `FormLabel` and `Range` (`id`, `name` and `for` attributes are set to this value) + + * `value` Value for the range input + + * `min` Minimum value + + * `max` Maximum value + + * `step` Step size + + * `label_range` Whether to show the range value label (label for the `Range` component) + +**Returns:** Div(cls='space-y-2')(`FormLabel`, `Range`) + +### LabelTextArea + +Source + +[code] + + LabelTextArea(label: str | fastcore.xml.FT, value='', lbl_cls='', input_cls='', cls='space-y-2', id='', **kwargs) -> fastcore.xml.FT +[/code] + +> **Params** + + * `label` FormLabel content (often text) + + * `value` Value for the textarea + + * `lbl_cls` Additional classes for `FormLabel` + + * `input_cls` Additional classes for `TextArea` + + * `cls` Classes on container (default is `'space-y-2'` to prevent scrunched up form elements) + + * `id` id for `FormLabel` and `TextArea` (`id`, `name` and `for` attributes are set to this value) + + * `kwargs` + +**Returns:** Div(cls='space-y-2')(`FormLabel`, `TextArea`) + +### LabelRadio + +Source + +[code] + + LabelRadio(label: str | fastcore.xml.FT, lbl_cls='', input_cls='', container=functools.partial(, 'div', void_=False), cls='flex items-center space-x-2', id='', **kwargs) -> fastcore.xml.FT +[/code] + +> A FormLabel and Radio pair that provides default spacing and links/names them based on id + +**Params** + + * `label` FormLabel content (often text) + + * `lbl_cls` Additional classes for `FormLabel` + + * `input_cls` Additional classes for `Radio` + + * `container` Container to wrap label and input in (default is Div) + + * `cls` Classes on container (default is 'flex items-center space-x-2') + + * `id` id for `FormLabel` and `Radio` (`id`, `name` and `for` attributes are set to this value) + + * `kwargs` + +**Returns:** Div(cls='flex items-center space-x-2')(`FormLabel`, `Radio`) + +### LabelSelect + +Source + +[code] + + LabelSelect(*option, label=(), lbl_cls=(), inp_cls=(), cls=('space-y-2',), id='', name='', placeholder='', searchable=False, select_kwargs=None, **kwargs) +[/code] + +> A FormLabel and Select pair that provides default spacing and links/names them based on id + +**Params** + + * `option` Options for the select dropdown (can use `Options` helper function to create) + + * `label` String or FT component for the label + + * `lbl_cls` Additional classes for the label + + * `inp_cls` Additional classes for the select input + + * `cls` Classes for the outer div + + * `id` ID for the select input + + * `name` Name attribute for the select input + + * `placeholder` Placeholder text for the select input + + * `searchable` Whether the select should be searchable + + * `select_kwargs` Additional Arguments passed to Select + + * `kwargs` + +### Progress + +Source + +[code] + + Progress(*c, cls=(), value='', max='100', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a progress bar + +**Params** + + * `c` Components to put in the progress bar (often nothing) + + * `cls` Additional classes on the progress bar + + * `value` Value of the progress bar + + * `max` Max value of the progress bar (defaults to 100 for percentage) + + * `kwargs` + +**Returns:** Progress(..., cls='uk-progress') + +See Source + +See Output + +[code] + + def ex_progress(): + return Progress(value=20, max=100) + +[/code] + +### Radio + +Source + +[code] + + Radio(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A Radio with default styling + +**Params** + + * `c` contents of Radio tag (often nothing) + + * `cls` Classes in addition to Radio styling + + * `kwargs` + +**Returns:** Input(..., cls='uk-radio', type='radio') + +See Source + +See Output + +Radio + +[code] + + def ex_radio(): + return Div( + Radio(name="radio-group", id="radio1"), + LabelRadio(label="Radio", id='radio1',cls='flex items-center space-x-4')) + +[/code] + +### CheckboxX + +Source + +[code] + + CheckboxX(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A Checkbox with default styling + +**Params** + + * `c` contents of CheckboxX tag (often nothing) + + * `cls` Classes in addition to CheckboxX styling + + * `kwargs` + +**Returns:** Input(..., cls='uk-checkbox', type='checkbox') + +See Source + +See Output + +Checkbox + +[code] + + def ex_checkbox(): + return Div( + CheckboxX(), + LabelCheckboxX(label="Checkbox", id='checkbox1')) + +[/code] + +### Range + +Source + +[code] + + Range(*c, value='', label=True, min=None, max=None, step=None, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A Range with default styling + +**Params** + + * `c` contents of Range tag (often nothing) + + * `value` + + * `label` + + * `min` + + * `max` + + * `step` + + * `cls` Classes in addition to Range styling + + * `kwargs` + +**Returns:** Input(..., cls='uk-range', type='range') + +See Source + +See Output + +Basic Range + +Range with Label + +Multiple Values + +Custom Range + +[code] + + def ex_range(): + return Div( + Range(), + Range(label='kg', value="25,75", min=20, max=75), + LabelRange('Basic Range', value='50', min=0, max=100, step=1), + LabelRange('Range with Label', value='75', min=0, max=100, step=5, label_range=True), + LabelRange('Multiple Values', value='25,75', min=0, max=100, step=5, label_range=True), + LabelRange('Custom Range', value='500', min=0, max=1000, step=100, label_range=True) + ) + +[/code] + +### Switch + +Source + +[code] + + Switch(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A Switch with default styling + +**Params** + + * `c` contents of Switch tag (often nothing) + + * `cls` Classes in addition to Switch styling + + * `kwargs` + +**Returns:** Input(..., cls='uk-toggle-switch uk-toggle-switch-primary min-w-9', type='checkbox') + +See Source + +See Output + +Switch + +[code] + + def ex_switch(): + return Div( + Switch(id="switch"), + LabelSwitch(label="Switch", id='switch')) + +[/code] + +### TextArea + +Source + +[code] + + TextArea(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A Textarea with default styling + +**Params** + + * `c` contents of TextArea tag (often text) + + * `cls` Classes in addition to TextArea styling + + * `kwargs` + +**Returns:** TextArea(..., cls='uk-textarea') + +See Source + +See Output + +TextArea + +[code] + + def ex_textarea(): + return Div( + TextArea(placeholder="Enter multiple lines of text"), + LabelTextArea(label="TextArea", id='myid')) + +[/code] + +### Select + +Source + +[code] + + Select(*option, inp_cls=(), cls=('h-10',), cls_custom='button: uk-input-fake dropdown: w-full', id='', name='', placeholder='', searchable=False, insertable=False, select_kwargs=None, **kwargs) +[/code] + +> Creates a select dropdown with uk styling and option for adding a search box + +**Params** + + * `option` Options for the select dropdown (can use `Options` helper function to create) + + * `inp_cls` Additional classes for the select input + + * `cls` Classes for the outer div (default h-10 for consistent height) + + * `cls_custom` Classes for the Uk_Select web component + + * `id` ID for the select input + + * `name` Name attribute for the select input + + * `placeholder` Placeholder text for the select input + + * `searchable` Whether the select should be searchable + + * `insertable` Whether to allow user-defined options to be added + + * `select_kwargs` Additional Arguments passed to Select + + * `kwargs` + +See Source + +See Output + +Option 1Option 2Option 3 + +Select + +Option 1Option 2Option 3 + +[code] + + def ex_select(): + return Div( + Select(map(Option, ["Option 1", "Option 2", "Option 3"])), + LabelSelect(map(Option, ["Option 1", "Option 2", "Option 3"]), label="Select", id='myid')) + +[/code] + +### Example: Insertable Select + +In a production app, the user-inserted option would be saved server-side (db, session etc.) + +See Source + +See Output + +AppleOrangeBananaMango + +AppleBananaMangoOrange + +[code] + + def ex_insertable_select1(): + fruit_opts = ['apple', 'orange', 'banana', 'mango'] + + return Grid( + Select(Option('Apple', value='apple'), + Option('Orange', value='orange'), + Option('Banana', value='banana'), + Option('Mango', value='mango'), + id="fruit", icon=True, insertable=True, placeholder="Choose a fruit..."), + + Select(Optgroup(label="Fruit")( + *map(lambda l: Option(l.capitalize(), value=l), sorted(fruit_opts))), + id="fruit", icon=True, insertable=True, placeholder="Choose a fruit...", + cls_custom="button: uk-input-fake justify-between w-full; dropdown: w-full")) + +[/code] + +### Legend + +Source + +[code] + + Legend(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A Legend with default styling + +**Params** + + * `c` contents of Legend tag (often other tags) + + * `cls` Classes in addition to Legend styling + + * `kwargs` + +**Returns:** Legend(..., cls='uk-legend') + +### Fieldset + +Source + +[code] + + Fieldset(*c, cls='flex', **kwargs) -> fastcore.xml.FT +[/code] + +> A Fieldset with default styling + +**Params** + + * `c` contents of Fieldset tag (often other tags) + + * `cls` Classes in addition to Fieldset styling + + * `kwargs` + +**Returns:** Fieldset(..., cls='uk-fieldset') +# HTML Styling API Reference + +See Source + +See Output + +

Hello, World!

This is a paragraph

+ +[code] + + def ex_applyclasses(): + return apply_classes('

Hello, World!

This is a paragraph

') + +[/code] +
# Icons & Images API Reference + +# Avatars + +See Source + +See Output + +[code] + + def ex_dicebear(): + return DivLAligned( + DiceBearAvatar('Isaac Flath',10,10), + DiceBearAvatar('Aaliyah',10,10), + DiceBearAvatar('Alyssa',10,10)) + +[/code] + +### DiceBearAvatar + +Source + +[code] + + DiceBearAvatar(seed_name: str, h: int = 20, w: int = 20) +[/code] + +> Creates an Avatar using https://dicebear.com/ + +**Params** + + * `seed_name` Seed name (ie 'Isaac Flath') + + * `h` Height + + * `w` Width + +# PlaceHolder Images + +See Source + +See Output + +[code] + + def ex_picsum(): + return Grid(PicSumImg(100,100), PicSumImg(100,100, blur=6),PicSumImg(100,100, grayscale=True)) + +[/code] + +### PicSumImg + +Source + +[code] + + PicSumImg(h: int = 200, w: int = 200, id: int = None, grayscale: bool = False, blur: int = None, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a placeholder image using https://picsum.photos/ + +**Params** + + * `h` Height in pixels + + * `w` Width in pixels + + * `id` Optional specific image ID to use + + * `grayscale` Whether to return grayscale version + + * `blur` Optional blur amount (1-10) + + * `kwargs` + +**Returns:** Img tag with picsum image + +# Icons + +Icons use Lucide icons - you can find a full list of icons in their docs. + +See Source + +See Output + +[code] + + def ex_icon(): + return Grid( + UkIcon('chevrons-right', height=15, width=15), + UkIcon('bug', height=15, width=15), + UkIcon('phone-call', height=15, width=15), + UkIcon('maximize-2', height=15, width=15), + UkIcon('thumbs-up', height=15, width=15),) + +[/code] + +### UkIcon + +Source + +[code] + + UkIcon(icon: str, height: int = None, width: int = None, stroke_width: int = None, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates an icon using lucide icons + +**Params** + + * `icon` Icon name from lucide icons + + * `height` + + * `width` + + * `stroke_width` Thickness of lines + + * `cls` Additional classes on the `Uk_icon` tag + + * `kwargs` + +**Returns:** a lucide icon of the specified size + +See Source + +See Output + +[code] + + def ex_iconlink(): + return DivLAligned( + UkIconLink('chevrons-right'), + UkIconLink('chevrons-right', button=True, cls=ButtonT.primary)) + +[/code] + +### UkIconLink + +Source + +[code] + + UkIconLink(icon: str, height: int = None, width: int = None, stroke_width: int = None, cls=(), button: bool = False, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates an icon link using lucide icons + +**Params** + + * `icon` Icon name from lucide icons + + * `height` + + * `width` + + * `stroke_width` Thickness of lines + + * `cls` Additional classes on the icon + + * `button` Whether to use a button (defaults to a link) + + * `kwargs` + +**Returns:** a lucide icon button or link of the specified size +# Layout (Flex and Grid) API Reference + +This page covers `Grid`s, which are often used for general structure, `Flex` which is often used for layout of components that are not grid based, padding and positioning that can help you make your layout look good, and dividers that can help break up the page + +## Grid + +See Source + +See Output + +Column 1 Item 1 + +Column 1 Item 2 + +Column 1 Item 3 + +Column 2 Item 1 + +Column 2 Item 2 + +Column 2 Item 3 + +Column 3 Item 1 + +Column 3 Item 2 + +Column 3 Item 3 + +[code] + + def ex_grid(): + return Grid( + Div( + P("Column 1 Item 1"), + P("Column 1 Item 2"), + P("Column 1 Item 3")), + Div( + P("Column 2 Item 1"), + P("Column 2 Item 2"), + P("Column 2 Item 3")), + Div( + P("Column 3 Item 1"), + P("Column 3 Item 2"), + P("Column 3 Item 3"))) + +[/code] + +### Grid + +Source + +[code] + + Grid(*div, cols_min: int = 1, cols_max: int = 4, cols_sm: int = None, cols_md: int = None, cols_lg: int = None, cols_xl: int = None, cols: int = None, cls='gap-4', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a responsive grid layout with smart defaults based on content + +**Params** + + * `div` `Div` components to put in the grid + + * `cols_min` Minimum number of columns at any screen size + + * `cols_max` Maximum number of columns allowed at any screen size + + * `cols_sm` Number of columns on small screens + + * `cols_md` Number of columns on medium screens + + * `cols_lg` Number of columns on large screens + + * `cols_xl` Number of columns on extra large screens + + * `cols` Number of columns on all screens + + * `cls` Additional classes on the grid (tip: `gap` provides spacing for grids) + + * `kwargs` + +**Returns:** Responsive grid component + +#### Practical Grid Example + +See Source + +See Output + +#### Laptop + +$999 + +Add to Cart + +#### Smartphone + +$599 + +Add to Cart + +#### Headphones + +$199 + +Add to Cart + +#### Smartwatch + +$299 + +Add to Cart + +#### Tablet + +$449 + +Add to Cart + +#### Camera + +$799 + +Add to Cart + +[code] + + def ex_product_grid(): + products = [ + {"name": "Laptop", "price": "$999", "img": "https://picsum.photos/200/100?random=1"}, + {"name": "Smartphone", "price": "$599", "img": "https://picsum.photos/200/100?random=2"}, + {"name": "Headphones", "price": "$199", "img": "https://picsum.photos/200/100?random=3"}, + {"name": "Smartwatch", "price": "$299", "img": "https://picsum.photos/200/100?random=4"}, + {"name": "Tablet", "price": "$449", "img": "https://picsum.photos/200/100?random=5"}, + {"name": "Camera", "price": "$799", "img": "https://picsum.photos/200/100?random=6"}, + ] + + product_cards = [ + Card( + Img(src=p["img"], alt=p["name"], style="width:100%; height:100px; object-fit:cover;"), + H4(p["name"], cls="mt-2"), + P(p["price"], cls=TextPresets.bold_sm), + Button("Add to Cart", cls=(ButtonT.primary, "mt-2")) + ) for p in products + ] + + return Grid(*product_cards, cols_lg=3) + +[/code] + +## Flex + +Play Flex Box Froggy to get an understanding of flex box. + +### DivFullySpaced + +Source + +[code] + + DivFullySpaced(*c, cls='w-full', **kwargs) +[/code] + +> Creates a flex div with it's components having as much space between them as possible + +**Params** + + * `c` Components + + * `cls` Classes for outer div (`w-full` makes it use all available width) + + * `kwargs` + +See Source + +See Output + +LeftCenterRight + +[code] + + def ex_fully_spaced_div(): + return DivFullySpaced( + Button("Left", cls=ButtonT.primary), + Button("Center", cls=ButtonT.secondary), + Button("Right", cls=ButtonT.destructive) + ) + +[/code] + +### DivCentered + +Source + +[code] + + DivCentered(*c, cls='space-y-4', vstack=True, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a flex div with it's components centered in it + +**Params** + + * `c` Components + + * `cls` Classes for outer div (`space-y-4` provides spacing between components) + + * `vstack` Whether to stack the components vertically + + * `kwargs` + +**Returns:** Div with components centered in it + +See Source + +See Output + +### Centered Title + +This content is centered both horizontally and vertically. + +[code] + + def ex_centered_div(): + return DivCentered( + H3("Centered Title"), + P("This content is centered both horizontally and vertically.") + ) + +[/code] + +### DivLAligned + +Source + +[code] + + DivLAligned(*c, cls='space-x-4', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a flex div with it's components aligned to the left + +**Params** + + * `c` Components + + * `cls` Classes for outer div + + * `kwargs` + +**Returns:** Div with components aligned to the left + +See Source + +See Output + +#### Left Aligned Title + +Some text that's left-aligned with the title and image. + +[code] + + def ex_l_aligned_div(): + return DivLAligned( + Img(src="https://picsum.photos/100/100?random=1", style="max-width: 100px;"), + H4("Left Aligned Title"), + P("Some text that's left-aligned with the title and image.") + ) + +[/code] + +### DivRAligned + +Source + +[code] + + DivRAligned(*c, cls='space-x-4', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a flex div with it's components aligned to the right + +**Params** + + * `c` Components + + * `cls` Classes for outer div + + * `kwargs` + +**Returns:** Div with components aligned to the right + +See Source + +See Output + +Action + +Right-aligned text + +[code] + + def ex_r_aligned_div(): + return DivRAligned( + Button("Action", cls=ButtonT.primary), + P("Right-aligned text"), + Img(src="https://picsum.photos/100/100?random=3", style="max-width: 100px;") + ) + +[/code] + +### DivVStacked + +Source + +[code] + + DivVStacked(*c, cls='space-y-4', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a flex div with it's components stacked vertically + +**Params** + + * `c` Components + + * `cls` Additional classes on the div (tip: `space-y-4` provides spacing between components) + + * `kwargs` + +**Returns:** Div with components stacked vertically + +See Source + +See Output + +## Vertical Stack + +First paragraph in the stack + +Second paragraph in the stack + +Action Button + +[code] + + def ex_v_stacked_div(): + return DivVStacked( + H2("Vertical Stack"), + P("First paragraph in the stack"), + P("Second paragraph in the stack"), + Button("Action Button", cls=ButtonT.secondary) + ) + +[/code] + +### DivHStacked + +Source + +[code] + + DivHStacked(*c, cls='space-x-4', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a flex div with it's components stacked horizontally + +**Params** + + * `c` Components + + * `cls` Additional classes on the div (`space-x-4` provides spacing between components) + + * `kwargs` + +**Returns:** Div with components stacked horizontally + +See Source + +See Output + +#### Column 1 + +Content for column 1 + +#### Column 2 + +Content for column 2 + +#### Column 3 + +Content for column 3 + +[code] + + def ex_h_stacked_div(): + return DivHStacked( + Div(H4("Column 1"), P("Content for column 1")), + Div(H4("Column 2"), P("Content for column 2")), + Div(H4("Column 3"), P("Content for column 3")) + ) + +[/code] + +* * * + +### FlexT + +_Flexbox modifiers using Tailwind CSS_ + +Option | Value | Option | Value | Option | Value | Option | Value +---|---|---|---|---|---|---|--- +block | flex | inline | inline-flex | left | justify-start | center | justify-center +right | justify-end | between | justify-between | around | justify-around | stretch | items-stretch +top | items-start | middle | items-center | bottom | items-end | row | flex-row +row_reverse | flex-row-reverse | column | flex-col | column_reverse | flex-col-reverse | nowrap | flex-nowrap +wrap | flex-wrap | wrap_reverse | flex-wrap-reverse | | | | +# Lightbox API Reference + +See Source + +See Output + +Open + +[code] + + def ex_lightbox1(): + return LightboxContainer( + LightboxItem(Button("Open"), href='https://picsum.photos/id/100/1280/720.webp', data_alt='A placeholder image to demonstrate the lightbox', data_caption='This is my super cool caption'), + ) + +[/code] + +See Source + +See Output + +Open + +[code] + + def ex_lightbox2(): + return LightboxContainer( + LightboxItem(Button("Open"), href='https://picsum.photos/id/100/1280/720.webp', data_alt='A placeholder image to demonstrate the lightbox', data_caption='Image 1'), + LightboxItem(href='https://picsum.photos/id/101/1280/720.webp', data_alt='A placeholder image to demonstrate the lightbox', data_caption='Image 2'), + LightboxItem(href='https://picsum.photos/id/102/1280/720.webp', data_alt='A placeholder image to demonstrate the lightbox', data_caption='Image 3'), + ) + +[/code] + +See Source + +See Output + +mp4YoutubeVimeoIframe + +[code] + + def ex_lightbox3(): + return LightboxContainer( + LightboxItem(Button("mp4"), href='https://yootheme.com/site/images/media/yootheme-pro.mp4'), + LightboxItem(Button("Youtube"), href='https://www.youtube.com/watch?v=c2pz2mlSfXA'), + LightboxItem(Button("Vimeo"), href='https://vimeo.com/1084537'), + LightboxItem(Button("Iframe"), data_type='iframe', href='https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d4740.819266853735!2d9.99008871708242!3d53.550454675412404!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x3f9d24afe84a0263!2sRathaus!5e0!3m2!1sde!2sde!4v1499675200938')) + +[/code] + +### LightboxContainer + +Source + +[code] + + LightboxContainer(*lightboxitem, data_uk_lightbox='counter: true', **kwargs) -> fastcore.xml.FT +[/code] + +> Lightbox container that will hold `LightboxItems` + +**Params** + + * `lightboxitem` `LightBoxItem`s that will be inside lightbox + + * `data_uk_lightbox` See https://franken-ui.dev/docs/2.0/lightbox for advanced options + + * `kwargs` + +**Returns:** Lightbox + +### LightboxItem + +Source + +[code] + + LightboxItem(*c, href, data_alt=None, data_caption=None, cls='', **kwargs) -> fastcore.xml.FT +[/code] + +> Anchor tag with appropriate structure to go inside a `LightBoxContainer` + +**Params** + + * `c` Component that when clicked will open the lightbox (often a button) + + * `href` Href to image, youtube video, vimeo, google maps, etc. + + * `data_alt` Alt text for the lightbox item/image + + * `data_caption` Caption for the item that shows below it + + * `cls` Class for the A tag (often nothing or `uk-btn`) + + * `kwargs` + +**Returns:** A(... href, data_alt, cls., ...) +# Lists API Reference + +See Source + +See Output + +#### disc List: + + * Item 1 + * Item 2 + +#### circle List: + + * Item 1 + * Item 2 + +#### square List: + + * Item 1 + * Item 2 + +#### decimal List: + + * Item 1 + * Item 2 + +#### hyphen List: + + * Item 1 + * Item 2 + +#### bullet List: + + * Item 1 + * Item 2 + +#### divider List: + + * Item 1 + * Item 2 + +#### striped List: + + * Item 1 + * Item 2 + +[code] + + def ex_lists(): + list_options = [(style,str(cls)) for style,cls in ListT.__members__.items()] + lists = [Div(H4(f"{style} List:"), Ul(Li("Item 1"), Li("Item 2"), cls=cls)) for style, cls in list_options] + return Grid(*lists) + +[/code] + +* * * + +### ListT + +_List styles using Tailwind CSS_ + +Option | Value | Option | Value | Option | Value +---|---|---|---|---|--- +disc | list-disc list-inside | circle | list-[circle] list-inside | square | list-[square] list-inside +decimal | uk-list uk-list-decimal | hyphen | uk-list uk-list-hyphen | bullet | uk-list uk-list-bullet +divider | uk-list uk-list-divider | striped | uk-list uk-list-striped | | +# Loading Indicators API Reference + +See Source + +See Output + +[code] + + def ex_loading1(): + return Loading() + +[/code] + +See Source + +See Output + +[code] + + def ex_loading2(): + types = [LoadingT.spinner, LoadingT.dots, LoadingT.ring, LoadingT.ball, LoadingT.bars, LoadingT.infinity] + sizes = [LoadingT.xs, LoadingT.sm, LoadingT.md, LoadingT.lg] + rows = [Div(*[Loading((t,s)) for s in sizes], cls='flex gap-4') for t in types] + return Div(*rows, cls='flex flex-col gap-4') + +[/code] + +### Loading + +Source + +[code] + + Loading(cls=(, ), htmx_indicator=False, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a loading animation component + +**Params** + + * `cls` Classes for indicator (generally `LoadingT` options) + + * `htmx_indicator` Add htmx-indicator class + + * `kwargs` + +**Returns:** Span(cls=...) + +* * * + +### LoadingT + +__ + +Option | Value | Option | Value | Option | Value +---|---|---|---|---|--- +spinner | loading-spinner | dots | loading-dots | ring | loading-ring +ball | loading-ball | bars | loading-bars | infinity | loading-infinity +xs | loading-xsmall | sm | loading-small | md | loading-medium +lg | loading-large | | | | +# Markdown + automated HTML styling API Reference + +See Source + +See Output + +# Example Markdown + + * With **bold** and _italics_ + * With a link + +### And a subheading + +> This is a blockquote + +This supports inline latex: $e^{\pi i} + 1 = 0$ as well as block latex thanks to Katex. + +$$ \frac{1}{2\pi i} \oint_C \frac{f(z)}{z-z_0} dz $$ + +And even syntax highlighting thanks to Highlight.js! (Just make sure you set `highlightjs=True` in the headers function) + +[code] + + def add(a, b): + return a + b + +[/code] + +[code] + + def ex_markdown(): + md = '''# Example Markdown + + + With **bold** and *italics* + + With a [link](https://github.com) + + ### And a subheading + + > This is a blockquote + + This supports inline latex: $e^{\\pi i} + 1 = 0$ as well as block latex thanks to Katex. + + $$ + \\frac{1}{2\\pi i} \\oint_C \\frac{f(z)}{z-z_0} dz + $$ + + And even syntax highlighting thanks to Highlight.js! (Just make sure you set `highlightjs=True` in the headers function) + + ```python + def add(a, b): + return a + b + ``` + ''' + return render_md(md) + +[/code] + +You can overwrite the default styling for markdown rendering with your own css classes with `class_map + +See Source + +See Output + +With custom **bold** style + +> But no extra quote style because class_map overrides all default styled +[code] + + def ex_markdown2(): + md = '''With custom **bold** style\n\n > But no extra quote style because class_map overrides all default styled''' + return render_md(md, class_map={'b': 'text-red-500'}) + +[/code] + +You can modify the default styling for markdown rendering with your own css classes with `class_map_mods + +See Source + +See Output + +With custom **bold** style + +> But default quote style because class_map_mods replaces sepecified styles and leaves the rest as default +[code] + + def ex_markdown3(): + md = '''With custom **bold** style\n\n > But default quote style because class_map_mods replaces sepecified styles and leaves the rest as default''' + return render_md(md, class_map_mods={'b': 'text-red-500'}) + +[/code] + +This uses the `apply_classes` function, which can be used to apply classes to html strings. This is useful for applying styles to any html you get from an external source. + +See Source + +See Output + +

Hello, World!

This is a paragraph

+ +[code] + + def ex_applyclasses(): + return apply_classes('

Hello, World!

This is a paragraph

') + +[/code] + +One common external source is a markdown renderer. MonsterUI uses tailwind css for styling so you don't get any styling without specifying classes, `apply_classes` can do that for you. + +See Source + +See Output + +# Hi + +a link + +[code] + + def ex_applyclasses2(): + from mistletoe import markdown, HTMLRenderer + md = markdown('# Hi\n[a link](www.google.com)', renderer=HTMLRenderer) + return Safe(apply_classes(md)) + +[/code] + +### apply_classes + +Source + +[code] + + apply_classes(html_str: str, class_map=None, class_map_mods=None) -> str +[/code] + +> Apply classes to html string + +**Params** + + * `html_str` Html string + + * `class_map` Class map + + * `class_map_mods` Class map that will modify the class map map (for small changes to base map) + +**Returns:** Html string with classes applied +
# Modals API Reference + +### Example Modal + +See Source + +See Output + +Open Modal + +## Simple Test Modal + +With some somewhat brief content to show that it works! + +Close + +[code] + + def ex_modal(): + return Div( + Button("Open Modal",data_uk_toggle="target: #my-modal" ), + Modal(ModalTitle("Simple Test Modal"), + P("With some somewhat brief content to show that it works!", cls=TextPresets.muted_sm), + footer=ModalCloseButton("Close", cls=ButtonT.primary),id='my-modal')) + +[/code] + +### Modal + +Source + +[code] + + Modal(*c, header=None, footer=None, cls=(), dialog_cls=(), header_cls='p-6', body_cls='space-y-6', footer_cls=(), id='', open=False, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a modal with the appropriate classes to put the boilerplate in the appropriate places for you + +**Params** + + * `c` Components to put in the `ModalBody` (often forms, sign in buttons, images, etc.) + + * `header` Components that go in the `ModalHeader` (often a `ModalTitle`) + + * `footer` Components that go in the `ModalFooter` (often a `ModalCloseButton`) + + * `cls` Additional classes on the outermost `ModalContainer` + + * `dialog_cls` Additional classes on the `ModalDialog` + + * `header_cls` Additional classes on the `ModalHeader` + + * `body_cls` Additional classes on the `ModalBody` + + * `footer_cls` Additional classes on the `ModalFooter` + + * `id` id for the outermost container + + * `open` Whether the modal is open (typically used for HTMX controlled modals) + + * `kwargs` + +**Returns:** Fully styled modal FT Component + +### ModalCloseButton + +Source + +[code] + + ModalCloseButton(*c, cls='absolute top-3 right-3', htmx=False, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a button that closes a modal with js + +**Params** + + * `c` Components to put in the button (often text and/or an icon) + + * `cls` Additional classes on the button + + * `htmx` Whether to use HTMX to close the modal (must add hx_get to a route that closes the modal) + + * `kwargs` + +**Returns:** Button(..., cls='uk-modal-close') + `hx_target` and `hx_swap` if htmx is True + +The remainder of the Modal functions below are used internally by the `Modal` function for you. You shouldn't need to use them unless you're doing something really special. + +### ModalTitle + +Source + +[code] + + ModalTitle(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a modal title + +**Params** + + * `c` Components to put in the `ModalTitle` (often text) + + * `cls` Additional classes on the `ModalTitle` + + * `kwargs` + +**Returns:** H2(..., cls='uk-modal-title') + +### ModalFooter + +Source + +[code] + + ModalFooter(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a modal footer + +**Params** + + * `c` Components to put in the `ModalFooter` (often buttons) + + * `cls` Additional classes on the `ModalFooter` + + * `kwargs` + +**Returns:** Div(..., cls='uk-modal-footer') + +### ModalBody + +Source + +[code] + + ModalBody(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a modal body + +**Params** + + * `c` Components to put in the `ModalBody` (often forms, sign in buttons, images, etc.) + + * `cls` Additional classes on the `ModalBody` + + * `kwargs` + +**Returns:** Div(..., cls='uk-modal-body') + +### ModalHeader + +Source + +[code] + + ModalHeader(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a modal header + +**Params** + + * `c` Components to put in the `ModalHeader` + + * `cls` Additional classes on the `ModalHeader` + + * `kwargs` + +**Returns:** Div(..., cls='uk-modal-header') + +### ModalDialog + +Source + +[code] + + ModalDialog(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a modal dialog + +**Params** + + * `c` Components to put in the `ModalDialog` (often `ModalBody`, `ModalHeader`, etc) + + * `cls` Additional classes on the `ModalDialog` + + * `kwargs` + +**Returns:** Div(..., cls='uk-modal-dialog') + +### ModalContainer + +Source + +[code] + + ModalContainer(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a modal container that components go in + +**Params** + + * `c` Components to put in the modal (often `ModalDialog`) + + * `cls` Additional classes on the `ModalContainer` + + * `kwargs` + +**Returns:** Div(..., cls='uk-modal uk-modal-container') +# Navigation (Nav, NavBar, Tabs, etc.) API Reference + +# Nav, NavBar, DowDownNav, and Tab examples + +* * * + +## Nav + +See Source + +See Output + + * Option 1 + * Option 2 + * Option 3 + +[code] + + def ex_nav1(): + mbrs1 = [Li(A('Option 1'), cls='uk-active'), Li(A('Option 2')), Li(A('Option 3'))] + return NavContainer(*mbrs1) + +[/code] + +See Source + +See Output + + * NavHeaderLi + * Option 1 + * Option 2 + * Option 3 + * Subtitle Ex + +NavSubtitle text to be shown + + * * Parent Name + * Child 1 + * Child 2 + * Child 3 + +[code] + + def ex_nav2(): + mbrs1 = [Li(A('Option 1'), cls='uk-active'), Li(A('Option 2')), Li(A('Option 3'))] + mbrs2 = [Li(A('Child 1')), Li(A('Child 2')),Li(A('Child 3'))] + + return NavContainer( + NavHeaderLi("NavHeaderLi"), + *mbrs1, + Li(A(href='')(Div("Subtitle Ex",NavSubtitle("NavSubtitle text to be shown")))), + NavDividerLi(), + NavParentLi( + A('Parent Name'), + NavContainer(*mbrs2,parent=False), + ), + ) + +[/code] + +## Navbars + +Fully responsive simple navbar using the high level API. This will collapse to a hamburger menu on mobile devices. See the Scrollspy example for a more complex navbar example. + +See Source + +See Output + +### My Blog + +Page1Page2Page3 + +Page1Page2Page3 + +[code] + + def ex_navbar1(): + return NavBar(A("Page1",href='/rt1'), + A("Page2",href='/rt2'), + A("Page3",href='/rt3'), + brand=H3('My Blog')) + +[/code] + +See Source + +See Output + +Page1Page2 + +Page1Page2 + +[code] + + def ex_navbar2(): + return NavBar( + A(Input(placeholder='search')), + A(UkIcon("rocket")), + A('Page1',href='/rt1'), + A("Page2", href='/rt3'), + brand=DivLAligned(Img(src='/api_reference/logo.svg'),UkIcon('rocket',height=30,width=30))) + +[/code] + +## Drop Down Navs + +See Source + +See Output + +Open DropDown + + * Item 1 + * Item 2 + +[code] + + def ex_navdrop(): + return Div( + Button("Open DropDown"), + DropDownNavContainer(Li(A("Item 1",href=''),Li(A("Item 2",href=''))))) + +[/code] + +## Tabs + +See Source + +See Output + + * Active + * Item + * Item + * Disabled + +[code] + + def ex_tabs2(): + return Container( + TabContainer( + Li(A("Active",href='javascript:void(0);', cls='uk-active')), + Li(A("Item",href='javascript:void(0);')), + Li(A("Item",href='javascript:void(0);')), + Li(A("Disabled", cls='uk-disabled')))) + +[/code] + +A tabs can use any method of navigation (htmx, or href). However, often these are use in conjunction with switchers do to this client side + +See Source + +See Output + + * Active + * Item + * Item + * Disabled + + * # Tab 1 + + * # Tab 2 + + * # Tab 3 + +[code] + + def ex_tabs1(): + return Container( + TabContainer( + Li(A("Active",href='#', cls='uk-active')), + Li(A("Item",href='#')), + Li(A("Item",href='#')), + Li(A("Disabled",href='#', cls='uk-disabled')), + uk_switcher='connect: #component-nav; animation: uk-animation-fade', + alt=True), + Ul(id="component-nav", cls="uk-switcher")( + Li(H1("Tab 1")), + Li(H1("Tab 2")), + Li(H1("Tab 3")))) + +[/code] + +# API Docs + +### NavBar + +Source + +[code] + + NavBar(*c, brand=h3(('Title',),{'class': 'uk-h3 '}), right_cls='items-center space-x-4', mobile_cls='space-y-4', sticky: bool = False, uk_scrollspy_nav: bool | str = False, cls='p-4', scrollspy_cls=, menu_id=None) -> fastcore.xml.FT +[/code] + +> Creates a responsive navigation bar with mobile menu support + +**Params** + + * `c` Component for right side of navbar (Often A tag links) + + * `brand` Brand/logo component for left side + + * `right_cls` Spacing for desktop links + + * `mobile_cls` Spacing for mobile links + + * `sticky` Whether to stick to the top of the page while scrolling + + * `uk_scrollspy_nav` Whether to use scrollspy for navigation + + * `cls` Classes for navbar + + * `scrollspy_cls` Scrollspy class (usually ScrollspyT.*) + + * `menu_id` ID for menu container (used for mobile toggle) + +**Returns:** Responsive NavBar + +### TabContainer + +Source + +[code] + + TabContainer(*li, cls='', alt=False, **kwargs) -> fastcore.xml.FT +[/code] + +> A TabContainer where children will be different tabs + +**Params** + + * `li` Components + + * `cls` Additional classes on the `Ul` + + * `alt` Whether to use an alternative tab style + + * `kwargs` + +**Returns:** Tab container + +### NavContainer + +Source + +[code] + + NavContainer(*li, cls=, parent=True, uk_nav=False, uk_scrollspy_nav=False, sticky=False, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a navigation container (useful for creating a sidebar navigation). A Nav is a list (NavBar is something different) + +**Params** + + * `li` List items are navigation elements (Special `Li` such as `NavParentLi`, `NavDividerLi`, `NavHeaderLi`, `NavSubtitle`, `NavCloseLi` can also be used) + + * `cls` Additional classes on the nav + + * `parent` Whether this nav is a _parent_ or _sub_ nav + + * `uk_nav` True for default collapsible behavior, see frankenui docs for more advanced options + + * `uk_scrollspy_nav` Activates scrollspy linking each item `A` tags `href` to content's `id` attribute + + * `sticky` Whether to stick to the top of the page while scrolling + + * `kwargs` + +**Returns:** FT Component that is a list of `Li` styled for a sidebar navigation menu + +* * * + +### NavT + +__ + +Option | Value | Option | Value +---|---|---|--- +default | uk-nav-default | primary | uk-nav-primary +secondary | uk-nav-secondary | | + +### NavCloseLi + +Source + +[code] + + NavCloseLi(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a navigation list item with a close button + +**Params** + + * `c` Components + + * `cls` Additional classes on the li + + * `kwargs` + +**Returns:** Navigation list item with a close button + +### NavSubtitle + +Source + +[code] + + NavSubtitle(*c, cls=, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a navigation subtitle + +**Params** + + * `c` Components + + * `cls` Additional classes on the div + + * `kwargs` + +**Returns:** Navigation subtitle + +### NavHeaderLi + +Source + +[code] + + NavHeaderLi(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a navigation list item with a header + +**Params** + + * `c` Components + + * `cls` Additional classes on the li + + * `kwargs` + +**Returns:** Navigation list item with a header + +### NavDividerLi + +Source + +[code] + + NavDividerLi(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a navigation list item with a divider + +**Params** + + * `c` Components + + * `cls` Additional classes on the li + + * `kwargs` + +**Returns:** Navigation list item with a divider + +### NavParentLi + +Source + +[code] + + NavParentLi(*nav_container, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a navigation list item with a parent nav for nesting + +**Params** + + * `nav_container` `NavContainer` container for a nested nav with `parent=False`) + + * `cls` Additional classes on the li + + * `kwargs` + +**Returns:** Navigation list item + +### DropDownNavContainer + +Source + +[code] + + DropDownNavContainer(*li, cls=, parent=True, uk_nav=False, uk_dropdown=True, **kwargs) -> fastcore.xml.FT +[/code] + +> A Nav that is part of a DropDown + +**Params** + + * `li` Components + + * `cls` Additional classes on the nav + + * `parent` Whether to use a parent nav + + * `uk_nav` True for default collapsible behavior, see https://franken-ui.dev/docs/nav#component-options for more advanced options + + * `uk_dropdown` Whether to use a dropdown + + * `kwargs` + +**Returns:** DropDown nav container +# Alerts & Toasts API Reference + +### Alerts + +The simplest alert is a div wrapped with a span: + +See Source + +See Output + +This is a plain alert + +[code] + + def ex_alerts1(): return Alert("This is a plain alert") + +[/code] + +Alert colors are defined by the alert styles: + +See Source + +See Output + +Your purchase has been confirmed! + +[code] + + def ex_alerts2(): return Alert("Your purchase has been confirmed!", cls=AlertT.success) + +[/code] + +It often looks nice to use icons in alerts: + +See Source + +See Output + +Please enter a valid email. + +[code] + + def ex_alerts3(): + return Alert( + DivLAligned(UkIcon('triangle-alert'), + P("Please enter a valid email.")), + cls=AlertT.error) + +[/code] + +### Alert + +Source + +[code] + + Alert(*c, cls='', **kwargs) -> fastcore.xml.FT +[/code] + +> Alert informs users about important events. + +**Params** + + * `c` Content for Alert (often text and/or icon) + + * `cls` Class for the alert (often an `AlertT` option) + + * `kwargs` + +**Returns:** Div(Span(...), cls='alert', role='alert') + +* * * + +### AlertT + +_Alert styles from DaisyUI_ + +Option | Value | Option | Value +---|---|---|--- +info | alert-info | success | alert-success +warning | alert-warning | error | alert-error + +* * * + +### Toasts + +To define a toast with a particular location, add horizontal or vertical toast type classes: + +See Source + +See Output + +First Example Toast + +[code] + + def ex_toasts1(): + return Toast("First Example Toast", cls=(ToastHT.start, ToastVT.bottom), dur=300) + +[/code] + +To define toast colors, set the class of the alert wrapped by the toast: + +See Source + +See Output + +Second Example Toast + +[code] + + def ex_toasts2(): + return Toast("Second Example Toast", alert_cls=AlertT.info, dur=300) + +[/code] + +Toasts will disappear automatically after 5 seconds. To change the duration of the toast set the `dur` param like this `Toast('Content', dur=10)`. + +Here's a demo app showing how to trigger a toast. + +### Toast + +Source + +[code] + + Toast(*c, cls='', alert_cls='', dur=5.0, **kwargs) -> fastcore.xml.FT +[/code] + +> Toasts are stacked announcements, positioned on the corner of page. + +**Params** + + * `c` Content for toast (often test) + + * `cls` Classes for toast (often `ToastHT` and `ToastVT` options) + + * `alert_cls` classes for altert (often `AlertT` options) + + * `dur` no. of seconds before the toast disappears + + * `kwargs` + +**Returns:** Div(Alert(...), cls='toast') + +* * * + +### ToastHT + +_Horizontal position for Toast_ + +Option | Value | Option | Value +---|---|---|--- +start | toast-start | center | toast-center +end | toast-end | | + +* * * + +### ToastVT + +_Vertical position for Toast_ + +Option | Value | Option | Value +---|---|---|--- +top | toast-top | middle | toast-middle +bottom | toast-bottom | | +# Carousel Sliders API Reference + +Here is a simple example of a slider: + +See Source + +See Output + +[code] + + def ex_sliders_1(): + return Slider(*[Img(src=f'https://picsum.photos/200/200?random={i}') for i in range(10)]) + +[/code] + +Here is a slider with cards: + +See Source + +See Output + +### Card 0 + +Card 0 content + +### Card 1 + +Card 1 content + +### Card 2 + +Card 2 content + +### Card 3 + +Card 3 content + +### Card 4 + +Card 4 content + +### Card 5 + +Card 5 content + +### Card 6 + +Card 6 content + +### Card 7 + +Card 7 content + +### Card 8 + +Card 8 content + +### Card 9 + +Card 9 content + +[code] + + def ex_sliders_2(): + def _card(i): return Card(H3(f'Card {i}'), P(f'Card {i} content')) + return Slider(*[_card(i) for i in range(10)]) + +[/code] + +Here is a slider with cards and autoplay: + +See Source + +See Output + +### Card 0 + +Card 0 content + +### Card 1 + +Card 1 content + +### Card 2 + +Card 2 content + +### Card 3 + +Card 3 content + +### Card 4 + +Card 4 content + +### Card 5 + +Card 5 content + +### Card 6 + +Card 6 content + +### Card 7 + +Card 7 content + +### Card 8 + +Card 8 content + +### Card 9 + +Card 9 content + +[code] + + def ex_sliders_3(): + def _card(i): return Card(H3(f'Card {i}'), P(f'Card {i} content')) + return Slider(*[_card(i) for i in range(10)], items_cls='gap-10', uk_slider='autoplay: true; autoplay-interval: 1000') + +[/code] + +Typically you want to use the `Slider` component, but if you need more control you can use the `SliderContainer`, `SliderItems`, and `SliderNav` components. + +### Slider + +Source + +[code] + + Slider(*c, cls='', items_cls='gap-4', nav=True, nav_cls='', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a slider with optional navigation arrows + +**Params** + + * `c` Items to show in slider + + * `cls` Classes for slider container + + * `items_cls` Classes for items container + + * `nav` Whether to show navigation arrows + + * `nav_cls` Classes for navigation arrows + + * `kwargs` + +**Returns:** SliderContainer(SliderItems(..., cls='gap-4'), SliderNav?) + +### SliderContainer + +Source + +[code] + + SliderContainer(*c, cls='', uk_slider=True, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a slider container + +**Params** + + * `c` Components + + * `cls` Additional classes on the container + + * `uk_slider` See FrankenUI Slider docs for more options + + * `kwargs` + +**Returns:** Div(..., cls='relative', uk_slider=True, ...) + +### SliderItems + +Source + +[code] + + SliderItems(*c, cls='', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a slider items container + +**Params** + + * `c` Components + + * `cls` Additional classes for the items + + * `kwargs` + +**Returns:** Div(..., cls='uk-slider-items uk-grid', ...) + +### SliderNav + +Source + +[code] + + SliderNav(cls='uk-position-small uk-hidden-hover', prev_cls='absolute left-0 top-1/2 -translate-y-1/2', next_cls='absolute right-0 top-1/2 -translate-y-1/2', **kwargs) -> fastcore.xml.FT +[/code] + +> Navigation arrows for Slider component + +**Params** + + * `cls` Additional classes for the navigation + + * `prev_cls` Additional classes for the previous navigation + + * `next_cls` Additional classes for the next navigation + + * `kwargs` + +**Returns:** Left and right navigation arrows for Slider component +# Steps API Reference + +See Source + +See Output + + * Account Created + * Profile Setup + * Verification + +[code] + + def ex_steps2(): + return Steps( + LiStep("Account Created", cls=StepT.primary), + LiStep("Profile Setup", cls=StepT.neutral), + LiStep("Verification", cls=StepT.neutral), + cls="w-full") + +[/code] + +See Source + +See Output + + * Project Planning + * Design Phase + * Development + * Testing + * Deployment + +[code] + + def ex_steps3(): + return Steps( + LiStep("Project Planning", cls=StepT.success, data_content="📝"), + LiStep("Design Phase", cls=StepT.success, data_content="💡"), + LiStep("Development", cls=StepT.primary, data_content="🛠️"), + LiStep("Testing", cls=StepT.neutral, data_content="🔎"), + LiStep("Deployment", cls=StepT.neutral, data_content="🚀"), + cls=(StepsT.vertical, "min-h-[400px]")) + +[/code] + +# API Docs + +### Steps + +Source + +[code] + + Steps(*li, cls='', **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a steps container + +**Params** + + * `li` Each `Li` represent a step (generally use `LiStep`) + + * `cls` class for Steps (generally a `StepsT` option) + + * `kwargs` + +**Returns:** Ul(..., cls='steps') + +* * * + +### StepsT + +_Options for Steps_ + +Option | Value | Option | Value +---|---|---|--- +vertical | steps-vertical | horizonal | steps-horizonal + +### LiStep + +Source + +[code] + + LiStep(*c, cls='', data_content=None, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a step list item + +**Params** + + * `c` Description for Step that goes next to bubble (often text) + + * `cls` Additional step classes (generally a `StepT` component) + + * `data_content` Content for inside bubble (defaults to number, often an emoji) + + * `kwargs` + +**Returns:** Li(..., cls='step') + +* * * + +### StepT + +_Step styles for LiStep_ + +Option | Value | Option | Value | Option | Value +---|---|---|---|---|--- +primary | step-primary | secondary | step-secondary | accent | step-accent +info | step-info | success | step-success | warning | step-warning +error | step-error | neutral | step-neutral | | +# Tables API Reference + +See Source + +See Output + +Name | Age | City +---|---|--- +Alice | 25 | New York +Bob | 30 | San Francisco +Charlie | 35 | London +Total | 90 +[code] + + def ex_tables0(): + return Table( + Thead(Tr(Th('Name'), Th('Age'), Th('City'))), + Tbody(Tr(Td('Alice'), Td('25'), Td('New York')), + Tr(Td('Bob'), Td('30'), Td('San Francisco')), + Tr(Td('Charlie'), Td('35'), Td('London'))), + Tfoot(Tr(Td('Total'), Td('90')))) + +[/code] + +See Source + +See Output + +Name | Age | City +---|---|--- +Alice | 25 | New York +Bob | 30 | San Francisco +Charlie | 35 | London +Total | 90 +[code] + + def ex_tables1(): + header = ['Name', 'Age', 'City'] + body = [['Alice', '25', 'New York'], + ['Bob', '30', 'San Francisco'], + ['Charlie', '35', 'London']] + footer = ['Total', '90'] + return TableFromLists(header, body, footer) + +[/code] + +See Source + +See Output + +NAME | AGE | CITY +---|---|--- +Alice | 30 years | New York +Bob | 25 years | London +[code] + + def ex_tables2(): + def body_render(k, v): + match k.lower(): + case 'name': return Td(v, cls='font-bold') + case 'age': return Td(f"{v} years") + case _: return Td(v) + + header_data = ['Name', 'Age', 'City'] + body_data =[{'Name': 'Alice', 'Age': 30, 'City': 'New York'}, + {'Name': 'Bob', 'Age': 25, 'City': 'London'}] + + return TableFromDicts(header_data, body_data, + header_cell_render=lambda v: Th(v.upper()), + body_cell_render=body_render) + +[/code] + +### Table + +Source + +[code] + + Table(*c, cls=(, , , ), **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a table + +**Params** + + * `c` Components (typically `Thead`, `Tbody`, `Tfoot`) + + * `cls` Additional classes on the table + + * `kwargs` + +**Returns:** Table component + +### TableFromLists + +Source + +[code] + + TableFromLists(header_data: Sequence, body_data: Sequence[Sequence], footer_data=None, header_cell_render=, body_cell_render=, footer_cell_render=, cls=(, , , ), sortable=False, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a Table from a list of header data and a list of lists of body data + +**Params** + + * `header_data` List of header data + + * `body_data` List of lists of body data + + * `footer_data` List of footer data + + * `header_cell_render` Function(content) -> FT that renders header cells + + * `body_cell_render` Function(key, content) -> FT that renders body cells + + * `footer_cell_render` Function(key, content) -> FT that renders footer cells + + * `cls` Additional classes on the table + + * `sortable` Whether to use sortable table + + * `kwargs` + +**Returns:** Table from lists + +### TableFromDicts + +Source + +[code] + + TableFromDicts(header_data: Sequence, body_data: Sequence[dict], footer_data=None, header_cell_render=, body_cell_render= at 0x752645f85b20>, footer_cell_render= at 0x752645f85bc0>, cls=(, , , ), sortable=False, **kwargs) -> fastcore.xml.FT +[/code] + +> Creates a Table from a list of header data and a list of dicts of body data + +**Params** + + * `header_data` List of header data + + * `body_data` List of dicts of body data + + * `footer_data` List of footer data + + * `header_cell_render` Function(content) -> FT that renders header cells + + * `body_cell_render` Function(key, content) -> FT that renders body cells + + * `footer_cell_render` Function(key, content) -> FT that renders footer cells + + * `cls` Additional classes on the table + + * `sortable` Whether to use sortable table + + * `kwargs` + +**Returns:** Styled Table + +* * * + +### TableT + +__ + +Option | Value | Option | Value | Option | Value +---|---|---|---|---|--- +divider | uk-table-divider | striped | uk-table-striped | hover | uk-table-hover +sm | uk-table-sm | lg | uk-table-lg | justify | uk-table-justify +middle | uk-table-middle | responsive | uk-table-responsive | | + +### Tbody + +Source + +[code] + + Tbody(*rows, cls=(), sortable=False, **kwargs) +[/code] + +> **Params** + + * `rows` + + * `cls` + + * `sortable` + + * `kwargs` + +### Th + +Source + +[code] + + Th(*c, cls=(), shrink=False, expand=False, small=False) +[/code] + +> **Params** + + * `c` Components that go in the cell + + * `cls` Additional classes on the cell container + + * `shrink` Whether to shrink the cell + + * `expand` Whether to expand the cell + + * `small` Whether to use a small table + +**Returns:** Table cell + +### Td + +Source + +[code] + + Td(*c, cls=(), shrink=False, expand=False, small=False) +[/code] + +> **Params** + + * `c` Components that go in the cell + + * `cls` Additional classes on the cell container + + * `shrink` Whether to shrink the cell + + * `expand` Whether to expand the cell + + * `small` Whether to use a small table + +**Returns:** Table cell +# Theme and Headers API Reference + +To get headers with a default theme use `hdrs=Theme..headers()`. For example for the blue theme you would use `hdrs=Theme.blue.headers()`. The theme integrated together different frameworks and allows tailwind, FrankenUI, HighlighJS, and DaisyUI components to work well together. + +Tailwind, FrankenUI and DaisyUI are imported by default. You must use DaisyUI headers to use anything in the `daisy` module, and FrankenUI headers to use anything in the `franken` module. + +HighlightJS is not added by default, but you can add it by setting `highlightjs=True` in the headers function. The `render_md` function will use HighlightJS for code blocks. + +Theme options are: + +Theme.slate + +Theme.stone + +Theme.gray + +Theme.neutral + +Theme.red + +Theme.rose + +Theme.orange + +Theme.green + +Theme.blue + +Theme.yellow + +Theme.violet + +Theme.zinc + +### Theme Picker + +See Source + +See Output + +ZincSlateStoneGrayNeutralRedRoseOrangeGreenBlueYellowVioletNoneSmallMediumLargeNoneSmallMediumLargeSmallDefaultLightDark + +[code] + + def ex_theme_switcher(): + return ThemePicker() + +[/code] + +### ThemePicker + +Source + +[code] + + ThemePicker(color=True, radii=True, shadows=True, font=True, mode=True, cls='p-4', custom_themes=[]) +[/code] + +> Theme picker component with configurable sections + +**Params** + + * `color` + + * `radii` + + * `shadows` + + * `font` + + * `mode` + + * `cls` + + * `custom_themes` + +### Custom Themes + + 1. You can use this theme as a starting point. + 2. Add the theme to your headers as a link like this `Link(rel="stylesheet", href="/custom_theme.css", type="text/css")` + 3. Then add the theme to the `ThemePicker` component. For example `ThemePicker(custom_themes=[('Grass', '#10b981')])` + +Themes are controlled with `bg-background text-foreground` classes on the `Body` tag. `fast_app` and `FastHTML` will do this for you automatically so you typically do not have to do anything + +### fast_app + +Source + +[code] + + fast_app(*args, pico=False, db_file: Optional[str] = None, render: Optional[] = None, hdrs: Optional[tuple] = None, ftrs: Optional[tuple] = None, tbls: Optional[dict] = None, before: Union[tuple, NoneType, fasthtml.core.Beforeware] = None, middleware: Optional[tuple] = None, live: bool = False, debug: bool = False, title: str = 'FastHTML page', routes: Optional[tuple] = None, exception_handlers: Optional[dict] = None, on_startup: Optional[] = None, on_shutdown: Optional[] = None, lifespan: Optional[] = None, default_hdrs=True, surreal: Optional[bool] = True, htmx: Optional[bool] = True, exts: Union[list, str, NoneType] = None, canonical: bool = True, secret_key: Optional[str] = None, key_fname: str = '.sesskey', session_cookie: str = 'session_', max_age: int = 31536000, sess_path: str = '/', same_site: str = 'lax', sess_https_only: bool = False, sess_domain: Optional[str] = None, htmlkw: Optional[dict] = None, bodykw: Optional[dict] = None, reload_attempts: Optional[int] = 1, reload_interval: Optional[int] = 1000, static_path: str = '.', body_wrap: = , nb_hdrs: bool = False) +[/code] + +> Create a FastHTML or FastHTMLWithLiveReload app with `bg-background text-foreground` to bodykw for frankenui themes + +**Params** + + * `db_file` Database file name, if needed + + * `render` Function used to render default database class + + * `hdrs` Additional FT elements to add to + + * `ftrs` Additional FT elements to add to end of + + * `tbls` Experimental mapping from DB table names to dict table definitions + + * `before` Functions to call prior to calling handler + + * `middleware` Standard Starlette middleware + + * `live` Enable live reloading + + * `debug` Passed to Starlette, indicating if debug tracebacks should be returned on errors + + * `title` Default page title + + * `routes` Passed to Starlette + + * `exception_handlers` Passed to Starlette + + * `on_startup` Passed to Starlette + + * `on_shutdown` Passed to Starlette + + * `lifespan` Passed to Starlette + + * `default_hdrs` Include default FastHTML headers such as HTMX script? + + * `pico` Include PicoCSS header? + + * `surreal` Include surreal.js/scope headers? + + * `htmx` Include HTMX header? + + * `exts` HTMX extension names to include + + * `canonical` Automatically include canonical link? + + * `secret_key` Signing key for sessions + + * `key_fname` Session cookie signing key file name + + * `session_cookie` Session cookie name + + * `max_age` Session cookie expiry time + + * `sess_path` Session cookie path + + * `same_site` Session cookie same site policy + + * `sess_https_only` Session cookie HTTPS only? + + * `sess_domain` Session cookie domain + + * `htmlkw` Attrs to add to the HTML tag + + * `bodykw` Attrs to add to the Body tag + + * `reload_attempts` Number of reload attempts when live reloading + + * `reload_interval` Time between reload attempts in ms + + * `static_path` Where the static file route points to, defaults to root dir + + * `body_wrap` FT wrapper for body contents + + * `nb_hdrs` If in notebook include headers inject headers in notebook DOM? + + * `args` + +### FastHTML + +Source + +[code] + + FastHTML(*args, pico=False, debug=False, routes=None, middleware=None, title: str = 'FastHTML page', exception_handlers=None, on_startup=None, on_shutdown=None, lifespan=None, hdrs=None, ftrs=None, exts=None, before=None, after=None, surreal=True, htmx=True, default_hdrs=True, sess_cls=, secret_key=None, session_cookie='session_', max_age=31536000, sess_path='/', same_site='lax', sess_https_only=False, sess_domain=None, key_fname='.sesskey', body_wrap=, htmlkw=None, nb_hdrs=False, canonical=True) +[/code] + +> Create a FastHTML app and adds `bg-background text-foreground` to bodykw for frankenui themes + +**Params** + + * `debug` + + * `routes` + + * `middleware` + + * `title` + + * `exception_handlers` + + * `on_startup` + + * `on_shutdown` + + * `lifespan` + + * `hdrs` + + * `ftrs` + + * `exts` + + * `before` + + * `after` + + * `surreal` + + * `htmx` + + * `default_hdrs` + + * `sess_cls` + + * `secret_key` + + * `session_cookie` + + * `max_age` + + * `sess_path` + + * `same_site` + + * `sess_https_only` + + * `sess_domain` + + * `key_fname` + + * `body_wrap` + + * `htmlkw` + + * `nb_hdrs` + + * `canonical` + + * `args` + + * `pico` + +> Users have said this site is helpful in creating your own themes. +# Typography API Reference + +Ready to go semantic options that cover most of what you need based on the HTML spec + +See Source + +See Output + +Titled + +# Titled + +# Level 1 Heading (H1) + +## Level 2 Heading (H2) + +### Level 3 Heading (H3) + +#### Level 4 Heading (H4) + +##### Level 5 Heading (H5) + +###### Level 6 Heading (H6) + +[code] + + def ex_headings(): + return Div( + Titled("Titled"), + H1("Level 1 Heading (H1)"), + H2("Level 2 Heading (H2)"), + H3("Level 3 Heading (H3)"), + H4("Level 4 Heading (H4)"), + H5("Level 5 Heading (H5)"), + H6("Level 6 Heading (H6)"), + ) + +[/code] + +See Source + +See Output + +## Semantic HTML Elements Demo + +Here's an example of _emphasized (Em)_ and **strong (Strong)** text. + +Some _italic text (I)_ and smaller text (Small) in a paragraph. + +You can highlight (Mark) text, show ~~deleted (Del)~~ and inserted (Ins) content. + +Chemical formulas use subscripts (Sub) and superscripts (Sup) like H2O. + +> The only way to do great work is to love what you do. +> +> Steve Jobs (Cite) + +As Shakespeare wrote, "All the world's a stage (Q)". + +Posted on 2024-01-29 + +Mozilla Foundation (Address) +331 E Evelyn Ave (Address) +Mountain View, CA 94041 (Address) +USA (Address) + +HTML (Dfn) (HyperText Markup Language (Abbr)) is the standard markup language for documents designed to be displayed in a web browser. + +Press `Ctrl (Kbd)` \+ `C (Kbd)` to copy. + +The command returned: Hello, World! (Samp) + +Let x (Var) be the variable in the equation. + +Figure 1: An example image with caption (Caption)Click to show more information (Summary) + +This is the detailed content that is initially hidden (P) + +123 (Data) is a number, and here's a Meter showing progress: + +Temperature: (with low/high/optimum values) + +€42.00 \- price example with semantic value + +Form calculation result: The sum is 42 (Output) + +### Blog Post Title (H3) + +By John Doe • 5 min read (Small) + +Article content here... + +This text has _proper name annotation (U)_ and this is ~~outdated information (S)~~ that's been superseded. + +[code] + + def ex_semantic_elements(): + return Div( + H2("Semantic HTML Elements Demo"), + # Text formatting examples + P("Here's an example of ", Em("emphasized (Em)"), " and ", Strong("strong (Strong)"), " text."), + P("Some ", I("italic text (I)"), " and ", Small("smaller text (Small)"), " in a paragraph."), + P("You can ", Mark("highlight (Mark)"), " text, show ", Del("deleted (Del)"), " and ", + Ins("inserted (Ins)"), " content."), + P("Chemical formulas use ", Sub("subscripts (Sub)"), " and ", Sup("superscripts (Sup)"), + " like H", Sub("2"), "O."), + # Quote examples + Blockquote( + P("The only way to do great work is to love what you do."), + Cite("Steve Jobs (Cite)")), + P("As Shakespeare wrote, ", Q("All the world's a stage (Q)"), "."), + # Time and Address + P("Posted on ", Time("2024-01-29", datetime="2024-01-29")), + Address( + "Mozilla Foundation (Address)", + Br(), + "331 E Evelyn Ave (Address)", + Br(), + "Mountain View, CA 94041 (Address)", + Br(), + "USA (Address)"), + # Technical and definition examples + P( + Dfn("HTML (Dfn)"), " (", + Abbr("HyperText Markup Language (Abbr)", title="HyperText Markup Language"), + ") is the standard markup language for documents designed to be displayed in a web browser."), + P("Press ", Kbd("Ctrl (Kbd)"), " + ", Kbd("C (Kbd)"), " to copy."), + P("The command returned: ", Samp("Hello, World! (Samp)")), + P("Let ", Var("x (Var)"), " be the variable in the equation."), + # Figure with caption + Figure( + PicSumImg(), + Caption("Figure 1: An example image with caption (Caption)")), + # Interactive elements + Details( + Summary("Click to show more information (Summary)"), + P("This is the detailed content that is initially hidden (P)")), + # Data representation + P( + Data("123 (Data)", value="123"), " is a number, and here's a Meter showing progress: ", + Meter(value=0.6, min=0, max=1)), + P( + "Temperature: ", + Meter(value=-1, min=-10, max=40, low=0, high=30, optimum=21), + " (with low/high/optimum values)"), + P( + Data("€42.00", value="42"), + " - price example with semantic value"), + # Output example + P("Form calculation result: ", Output("The sum is 42 (Output)", form="calc-form", for_="num1 num2")), + # Meta information example + Section( + H3("Blog Post Title (H3)"), + Small("By John Doe • 5 min read (Small)"), + P("Article content here...")), + # Text decoration examples + P("This text has ",U("proper name annotation (U)"), " and this is ",S("outdated information (S)"), " that's been superseded."), + cls='space-y-4' + ) + +[/code] + +See Source + +See Output + +`This is a CodeSpan element` + +> This is a blockquote element +[code] + + #This is a CodeBlock element + + def add(a,b): return a+b +[/code] + +[code] + + def ex_other(): + return Div( + CodeSpan("This is a CodeSpan element"), + Blockquote("This is a blockquote element"), + CodeBlock("#This is a CodeBlock element\n\ndef add(a,b): return a+b")) + +[/code] + +Styling text is possibly the most common style thing to do, so we have a couple of helpers for discoverability inside python. `TextPresets` is intended to be combinations are are widely applicable and used often, where `TextT` is intended to be more flexible options for you to combine together yourself. + +##### TextPresets.* + +See Source + +See Output + +This is muted_sm text + +This is muted_lg text + +This is bold_sm text + +This is bold_lg text + +This is md_weight_sm text + +This is md_weight_muted text + +[code] + + def ex_textpresets(): + return Grid(*[Div(P(f"This is {preset.name} text", cls=preset.value)) for preset in TextPresets]) + +[/code] + +##### TextT.* + +See Source + +See Output + +This is paragraph text + +This is lead text + +This is meta text + +This is gray text + +This is italic text + +This is xs text + +This is sm text + +This is lg text + +This is xl text + +This is light text + +This is normal text + +This is medium text + +This is bold text + +This is extrabold text + +This is primary text + +This is secondary text + +This is success text + +This is warning text + +This is error text + +This is info text + +This is left text + +This is right text + +This is center text + +This is justify text + +This is start text + +This is end text + +This is top text + +This is middle text + +This is bottom text + +This is truncate text + +This is break_ text + +This is nowrap text + +This is underline text + +This is highlight text + +[code] + + def ex_textt(): + return Grid(*[Div(P(f"This is {s.name} text", cls=s.value)) for s in TextT]) + +[/code] + +### API Reference + +* * * + +### TextPresets + +_Common Typography Presets_ + +Option | Value | Option | Value +---|---|---|--- +muted_sm | text-gray-500 dark:text-gray-200 text-sm | muted_lg | text-gray-500 dark:text-gray-200 text-lg +bold_sm | font-bold text-sm | bold_lg | font-bold text-lg +md_weight_sm | text-sm font-medium | md_weight_muted | font-medium text-gray-500 dark:text-gray-200 + +* * * + +### TextT + +_Text Styles from https://franken-ui.dev/docs/text_ + +Option | Value | Option | Value | Option | Value | Option | Value +---|---|---|---|---|---|---|--- +paragraph | uk-paragraph | lead | uk-text-lead | meta | uk-text-meta | gray | text-gray-500 dark:text-gray-200 +italic | italic | xs | text-xs | sm | text-sm | lg | text-lg +xl | text-xl | light | font-light | normal | font-normal | medium | font-medium +bold | font-bold | extrabold | font-extrabold | muted | text-gray-500 dark:text-gray-200 | primary | text-primary +secondary | text-secondary | success | text-success | warning | text-warning | error | text-error +info | text-info | left | text-left | right | text-right | center | text-center +justify | text-justify | start | text-start | end | text-end | top | align-top +middle | align-middle | bottom | align-bottom | truncate | uk-text-truncate | break_ | uk-text-break +nowrap | uk-text-nowrap | underline | underline | highlight | bg-yellow-200 dark:bg-yellow-800 text-black | | + +### H1 + +Source + +[code] + + H1(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> H1 with styling and appropriate size + +**Params** + + * `c` Contents of H1 tag (often text) + + * `cls` Classes in addition to H1 styling + + * `kwargs` + +**Returns:** H1(..., cls='uk-h1') + +### H2 + +Source + +[code] + + H2(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> H2 with styling and appropriate size + +**Params** + + * `c` Contents of H2 tag (often text) + + * `cls` Classes in addition to H2 styling + + * `kwargs` + +**Returns:** H2(..., cls='uk-h2') + +### H3 + +Source + +[code] + + H3(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> H3 with styling and appropriate size + +**Params** + + * `c` Contents of H3 tag (often text) + + * `cls` Classes in addition to H3 styling + + * `kwargs` + +**Returns:** H3(..., cls='uk-h3') + +### H4 + +Source + +[code] + + H4(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> H4 with styling and appropriate size + +**Params** + + * `c` Contents of H4 tag (often text) + + * `cls` Classes in addition to H4 styling + + * `kwargs` + +**Returns:** H4(..., cls='uk-h4') + +### H5 + +Source + +[code] + + H5(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> H5 with styling and appropriate size + +**Params** + + * `c` Contents of H5 tag (often text) + + * `cls` Classes in addition to H5 styling + + * `kwargs` + +**Returns:** H5(..., cls='text-lg font-semibold') + +### H6 + +Source + +[code] + + H6(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> H6 with styling and appropriate size + +**Params** + + * `c` Contents of H6 tag (often text) + + * `cls` Classes in addition to H6 styling + + * `kwargs` + +**Returns:** H6(..., cls='text-base font-semibold') + +### CodeSpan + +Source + +[code] + + CodeSpan(*c, cls=(), **kwargs) -> fastcore.xml.FT +[/code] + +> A CodeSpan with Styling + +**Params** + + * `c` Contents of CodeSpan tag (inline text code snippets) + + * `cls` Classes in addition to CodeSpan styling + + * `kwargs` + +**Returns:** Code(..., cls='uk-codespan') + +### Blockquote + +Source + +[code] + + Blockquote(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Blockquote with Styling + +**Params** + + * `c` Contents of Blockquote tag (often text) + + * `cls` Classes in addition to Blockquote styling + + * `kwargs` + +**Returns:** Blockquote(..., cls='uk-blockquote') + +### CodeBlock + +Source + +[code] + + CodeBlock(*c: str, cls: enum.Enum | str | tuple = (), code_cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> CodeBlock with Styling + +**Params** + + * `c` Contents of Code tag (often text) + + * `cls` Classes for the outer container + + * `code_cls` Classes for the code tag + + * `kwargs` + +**Returns:** Div(Pre(Code(..., cls='uk-codeblock), cls='multiple tailwind styles'), cls='uk-block') + +### Em + +Source + +[code] + + Em(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled emphasis text + +**Params** + + * `c` Contents of Em tag (emphasis) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Em tag + +### Strong + +Source + +[code] + + Strong(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled strong text + +**Params** + + * `c` Contents of Strong tag + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Strong tag + +### I + +Source + +[code] + + I(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled italic text + +**Params** + + * `c` Contents of I tag (italics) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for I tag + +### Small + +Source + +[code] + + Small(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled small text + +**Params** + + * `c` Contents of Small tag + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Small tag + +### Mark + +Source + +[code] + + Mark(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled highlighted text + +**Params** + + * `c` Contents of Mark tag (highlighted text) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Mark tag + +### Sub + +Source + +[code] + + Sub(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled subscript text + +**Params** + + * `c` Contents of Sub tag (subscript) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Sub tag + +### Sup + +Source + +[code] + + Sup(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled superscript text + +**Params** + + * `c` Contents of Sup tag (superscript) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Sup tag + +### Del + +Source + +[code] + + Del(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled deleted text + +**Params** + + * `c` Contents of Del tag (deleted text) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Del tag + +### Ins + +Source + +[code] + + Ins(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled inserted text + +**Params** + + * `c` Contents of Ins tag (inserted text) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Ins tag + +### Dfn + +Source + +[code] + + Dfn(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled definition term with italic and medium weight + +**Params** + + * `c` Contents of Dfn tag (definition) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Dfn tag + +### Abbr + +Source + +[code] + + Abbr(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), title: str = None, **kwargs) -> fastcore.xml.FT +[/code] + +> Styled abbreviation with dotted underline + +**Params** + + * `c` Contents of Abbr tag + + * `cls` Additional classes + + * `title` Title attribute for abbreviation + + * `kwargs` + +**Returns:** Additional args for Abbr tag + +### Q + +Source + +[code] + + Q(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled quotation mark + +**Params** + + * `c` Contents of Q tag (quote) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Q tag + +### Kbd + +Source + +[code] + + Kbd(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled keyboard input with subtle background + +**Params** + + * `c` Contents of Kbd tag (keyboard input) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Kbd tag + +### Samp + +Source + +[code] + + Samp(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled sample output with subtle background + +**Params** + + * `c` Contents of Samp tag (sample output) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Samp tag + +### Var + +Source + +[code] + + Var(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled variable with italic monospace + +**Params** + + * `c` Contents of Var tag (variable) + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Var tag + +### Figure + +Source + +[code] + + Figure(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled figure container with card-like appearance + +**Params** + + * `c` Contents of Figure tag + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Figure tag + +### Caption + +Source + +[code] + + Caption(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled caption text + +**Params** + + * `c` + + * `cls` + + * `kwargs` + +### Details + +Source + +[code] + + Details(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled details element + +**Params** + + * `c` Contents of Details tag + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Details tag + +### Summary + +Source + +[code] + + Summary(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled summary element + +**Params** + + * `c` Contents of Summary tag + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Summary tag + +### Meter + +Source + +[code] + + Meter(*c: fastcore.xml.FT | str, value: float = None, min: float = None, max: float = None, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled meter element + +**Params** + + * `c` Contents of Meter tag + + * `value` Current value + + * `min` Minimum value + + * `max` Maximum value + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Meter tag + +### Data + +Source + +[code] + + Data(*c: fastcore.xml.FT | str, value: str = None, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled data element + +**Params** + + * `c` Contents of Data tag + + * `value` Value attribute + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Data tag + +### Output + +Source + +[code] + + Output(*c: fastcore.xml.FT | str, form: str = None, for_: str = None, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled output element for form results + +**Params** + + * `c` Contents of Output tag + + * `form` ID of form this output belongs to + + * `for_` IDs of elements this output is for + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Output tag + +### Address + +Source + +[code] + + Address(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), **kwargs) -> fastcore.xml.FT +[/code] + +> Styled address element + +**Params** + + * `c` Contents of Address tag + + * `cls` Additional classes + + * `kwargs` + +**Returns:** Additional args for Address tag + +### Time + +Source + +[code] + + Time(*c: fastcore.xml.FT | str, cls: enum.Enum | str | tuple = (), datetime: str = None, **kwargs) -> fastcore.xml.FT +[/code] + +> Styled time element + +**Params** + + * `c` Contents of Time tag + + * `cls` Additional classes + + * `datetime` datetime attribute + + * `kwargs` + +**Returns:** Additional args for Time tag + + *[HyperText Markup Language (Abbr)]: HyperText Markup Language +# MonterUI Page Layout Guide + +This guide will discuss 3 tools for laying out your app pages, Grid, Flexbox, and Columns. This page will discuss the strengths and when to use each individually, and then a section for how to combine them for more complex layouts at the end. + +> Note: This guide is designed to get you started building layouts quickly, not to teach you all the details needed to build every possible custom layout with pixel-perfect control. To get more detailed and lower-level control, explore the tailwind docs. + +This guide is for creating flexible layouts you envision, but does not discuss responsiveness to make different layouts that are both mobile and desktop friendly. Stay tunes for a responsiveness guide that will help with that! + +# Grid + +Grids are best for regular predictable layouts with lots of the same shape of things that may need to change a lot for different screen sizes. I think the best way to see what it can do is to see a bunch of examples, so here they are! + +## Minimal Image Cards + +This is a minimal example of a grid that just shows image and text. This is the foundation for many more complex layouts so make sure to understand what's going on here first before moving on! + +A grid lays things out in a...grid. As you can see, we have evenly sized cards by default. + +See Source + +See Output + +Image 0 + +Image 1 + +Image 2 + +Image 3 + +Image 4 + +Image 5 + +[code] + + def picsum_img(seed): return Img(src=f'https://picsum.photos/300/200?random={seed}') + + Grid(*[Card(picsum_img(i),P(f"Image {i}")) for i in range(6)]) +[/code] + +## Dashboard Example + +However, they don't have to be evenly sized! By providing `row-span-{int}` and `col-span-{int}` we can control how many rows or columns specific grid elements take up. By doing this, we can create a grid that has lots of different shapes and types of elements. + +Let's look at a dashboard layout at an examples of this. + +See Source + +See Output + +### SideBar + +Range For Filters + +A search Bar + +Choose Product Line + +Product Line AProduct Line BProduct Line CProduct Line D + +Include Inactive Users + +Include Users without order + +Include Users without email + +Total Users + +### 1,234 + +Active Now + +### 342 + +Revenue + +### $45,678 + +Conversion + +### 2.4% + +### Monthly Revenue + +Chart Goes Here + +### User Growth + +Chart Goes Here + +[code] + + def StatCard(title, value, color='primary'): + "A card with a statistics. Since there is no row/col span class it will take up 1 slot" + return Card(P(title, cls=TextPresets.muted_sm), H3(value, cls=f'text-{color}'),) + + stats = [StatCard(*data) for data in [ + ("Total Users", "1,234", "blue-600"), + ("Active Now", "342", "green-600"), + ("Revenue", "$45,678", "purple-600"), + ("Conversion", "2.4%", "amber-600")]] + + def ChartCard(title): + "A card for a chart. col-span-2 means it will take up 2 columns" + return Div(cls="col-span-2")( + Card(H3(title),Div("Chart Goes Here", cls="h-64 uk-background-muted"))) + chart_cards = [ChartCard(title) for title in ("Monthly Revenue", "User Growth")] + + + sidebar = Form( + H3("SideBar"), + LabelRange("Range For Filters", min=0, max=100), + LabelInput("A search Bar"), + LabelSelect(map(Option, ["Product Line A", "Product Line B", "Product Line C", "Product Line D"]), + label="Choose Product Line"), + LabelCheckboxX("Include Inactive Users"), + LabelCheckboxX("Include Users without order"), + LabelCheckboxX("Include Users without email"), + # This sidebar will take up 2 rows b/c of row-span-2 + cls='row-span-2 space-y-5' + ) + + Container(Grid(sidebar, *stats, *chart_cards, cols=5)) +[/code] + +# Flexbox + +Using Grid for the overall layout, and flex for the individual elements is a powerful pattern. With `MonsterUI` you can do quite a bit without knowing anything about flexbox, which is what will be taught here. + +However, flexbox is well worth learning about it in more detail. You will run into situations where you need more flexbox knowledge than is covered here to build your vision. Thankfully you can get that knowledge by playing a fantastic tutorial game called FlexBox Froggy! + +## Forms + +Often you want to stack things horizontally. You can use the `DivHStacked` component to do this. + +`DivHStacked` is a helper function for flexbox and creates a div with these classes by default `cls=(FlexT.block, FlexT.row, FlexT.middle, 'space-x-4')`. + +See Source + +See Output + +### Form with Input Groups + +Search Users + +Filter Tags + +Email List + +SubmitCancel + +[code] + + def InputGroup(label, placeholder='', button_text='Submit', cls=''): + # Div H Stacked makes the label and input show up on the same row instead of putting the input on a newline + return DivHStacked( + FormLabel(label, cls='whitespace-nowrap'), + Input(placeholder=placeholder)) + + Container( + H3("Form with Input Groups"), + Form(cls='space-y-4')( + InputGroup("Search Users", "Enter username..."), + InputGroup("Filter Tags", "Add tags...", "Add"), + InputGroup("Email List", "Enter email...", "Subscribe"), + Div(*( Button(UkIcon(icon, cls='mr-2'), text) for icon, text in [("rocket", "Submit"), ("circle-x", "Cancel")]), cls='space-x-4'))) +[/code] + +## Avatar + +You can use this same `DivHStacked` to align things like text next to images. And you can use `DivVStacked` to stack things vertically to create design structures you like. `DivVStacked` works by using `cls=(FlexT.block,FlexT.column,FlexT.middle)` + +See Source + +See Output + +John Doe + +[email protected] + ++1-123-456-7890 + +[code] + + # DivHStacked makes the a single row so text is to on same line as avatar + DivHStacked( + DiceBearAvatar("user"), + # DivVStacked stacks things vertically together and centers it with flex + DivVStacked( + P("John Doe", cls=TextT.lg), + P("[email protected]", cls=TextT.muted), + P("+1-123-456-7890"), cls=TextT.muted)) +[/code] + +## Pricing Card + +These can be combined with icons and other styling to create larger components like a pricing card. + +See Source + +See Output + +## Pro Plan + +### $99 + +per month + + * Unlimited users + + * 24/7 priority support + + * Custom branding options + + * Advanced analytics dashboard + + * Full API access + + * Priority request queue + +Subscribe Now + +[code] + + features = [ + "Unlimited users", + "24/7 priority support", + "Custom branding options", + "Advanced analytics dashboard", + "Full API access", + "Priority request queue" + ] + + + def PricingCard(plan, price, features): + "Create a polished pricing card with consistent styling" + return Card( + DivVStacked( # Center and veritcally stack the plan name and price + H2(plan), + H3(price, cls='text-primary'), + P('per month',cls=TextT.muted), + cls='space-y-1'), + # DivHStacked makes green check and feature Li show up on same row instead of newline + Ul(*[DivHStacked(UkIcon('check', cls='text-green-500 mr-2'), Li(feature)) for feature in features], + cls='space-y-4'), + Button("Subscribe Now", cls=(ButtonT.primary, 'w-full'))) + + DivVStacked(PricingCard("Pro Plan", "$99", features)) +[/code] + +## Footer + +Or you can combine things to make advanced footers that have titles, organized links, and icons! + +In this example we add another flex helper function, `DivFullySpaced`. `DivFullySpaced` is a flex class that puts as much space between items as possible + +See Source + +See Output + +### Company Name + +* * * + +#### Company + +AboutBlogCareersPress Kit + +#### Resources + +DocumentationHelp CenterStatusContact Sales + +#### Legal + +Terms of ServicePrivacy PolicyCookie SettingsAccessibility + +* * * + +© 2024 Company Name. All rights reserved. + +[code] + + def FooterLinkGroup(title, links): + # DivVStacked centers and makes title and each link stack vertically + return DivVStacked( + H4(title), + *[A(text, href=f"#{text.lower().replace(' ', '-')}", cls=TextT.muted) for text in links]) + + company = ["About", "Blog", "Careers", "Press Kit"] + resource = ["Documentation", "Help Center", "Status", "Contact Sales"] + legal = ["Terms of Service", "Privacy Policy", "Cookie Settings", "Accessibility"] + + Container(cls='uk-background-muted py-12')(Div( + # Company Name and social icons will be on the same row with as much sapce between as possible + DivFullySpaced( + H3("Company Name"), + # DivHStacked makes the icons be on the same row in a group + DivHStacked(*[UkIcon(icon, cls=TextT.lead) for icon in + ['twitter', 'facebook', 'github', 'linkedin']])), + DividerLine(), + DivFullySpaced( # Each child will be spread out as much as possible based on number of children + FooterLinkGroup("Company", company), + FooterLinkGroup("Resources", resource), + FooterLinkGroup("Legal", legal)), + DividerLine(), + P("© 2024 Company Name. All rights reserved.", cls=TextT.lead+TextT.sm), + cls='space-y-8 p-8')) +[/code] + +## Dashboard + +See Source + +See Output + +## Welcome back, Isaac! + +Here's what's happening with your projects today. + +Total Projects + +### 12 + ++2.5% from last month + +Hours Logged + +### 164 + ++12.3% from last month + +Tasks Complete + +### 64% + +-4.1% from last month + +Team Velocity + +### 23 + ++8.4% from last month + +### Recent Activity + +Sarah Chen completed Project Alpha deployment + +2h ago + +James Wilson commented on Project Beta + +4h ago + +Maria Garcia uploaded new design files + +6h ago + +Alex Kumar started Sprint Planning + +8h ago + +[code] + + def StatsCard(label, value, change): + color = 'green' if change[0] == '+' else 'red' + return Card(DivVStacked( # Stacks vertically and centers all elements + P(label, cls=TextPresets.muted_sm), + H3(value), + P(f"{change}% from last month", cls=f"text-{color}-600 text-sm"))) + + def RecentActivity(user, action, time): + return DivHStacked( # Makes Avatar and text be on same row + DiceBearAvatar(user, h=8, w=8), + P(f"{user} {action}", cls="flex-1"), + P(time, cls=TextPresets.muted_sm)) + + DivVStacked( # Centers the entire dashboard layout + # Page header + DivVStacked( # Stacks vertically and centers the title/subtitle + H2("Welcome back, Isaac!"), + P("Here's what's happening with your projects today.",cls=TextT.muted)), + + # DivHStacked puts all the stats cards on the same row + DivHStacked(*(StatsCard(label, value, change) + for label, value, change in [ + ("Total Projects", "12", "+2.5"), + ("Hours Logged", "164", "+12.3"), + ("Tasks Complete", "64%", "-4.1"), + ("Team Velocity", "23", "+8.4")] + )), + + # Recent activity + Card(*(RecentActivity(user, action, time) + for user, action, time in [ + ("Sarah Chen", "completed Project Alpha deployment", "2h ago"), + ("James Wilson", "commented on Project Beta", "4h ago"), + ("Maria Garcia", "uploaded new design files", "6h ago"), + ("Alex Kumar", "started Sprint Planning", "8h ago")]), + header=H3("Recent Activity"), + ), + cls="space-y-6" + ) +[/code] + +## Columns + +Columns are a great for sections that have a lot of text. + +See Source + +See Output + +# Lorem Ipsum + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + +Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + +Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium. + +Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor. + +[code] + + Container( + H1("Lorem Ipsum", cls="text-center mb-8"), + + # Use 2 columns for the main content + Div(cls="columns-2 gap-12")( + P("""Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip + ex ea commodo consequat."""), + + DivCentered(cls='mt-8')( + P("""Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur.""", + cls=(TextT.lg, TextT.bold, TextT.center, TextT.italic, "text-primary"))), + + P("""Excepteur sint occaecat cupidatat non proident, sunt in culpa qui + officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde + omnis iste natus error sit voluptatem accusantium doloremque laudantium."""), + + P("""Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit + aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem + sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor."""))) +[/code] +# Padding & Margin & Spacing, Oh my! (MonsterUI Spacing Guide) + +This guide will cover some essentials about how to properly space apps and what the differences are between: + + * Padding + * Margin + * Spacing + * Gap + +Manipulating the space between components can make a huge difference to the percieved quality of the page. Being able to tweak the spacing can have a big impact! + +> Tip: I find it works best to get everything on the page without adjusting spacing much, and adjusting spacing at the end. + +## Abreviations: + +First a few abbreviations that are helpful to know with tailwind (and a convention we follow in `MonsterUI`). + + * `t`, `b`, `l`, `r` = top, bottom, left, right + * `p`, `m` = padding, margin + * `x`, `y` = horizontal, vertical + +That means: + + * `mt` means margin on top of the element + * `px` means padding on the x axis (both left and right) + * `space-y` means apply spacing on the y axis (both top and bottom) + +## Padding vs Margin + +Margin applies space to the left of the component, and padding applies space on the left inside of the component. + +Please reference the example with cards below: + + * `ml-20` applies space to the left of the card (outside the card) + * `pl-20` applies space on the left inside of the card (inside the card) + +This means that if you want to move the whole thing but keep the actual container unchanged, use margin. If you want to change the container by adding space inside of it, use padding. + +See Source + +See Output + +#### A Simple Card with ml-20 + +#### A Simple Card with pl-20 + +[code] + + Grid( + Card(H4("A Simple Card with ml-20",style='background-color: red'), + cls='ml-20'), + Card(H4("A Simple Card with pl-20", style='background-color: red'), + cls='pl-20')) +[/code] + +## Space vs gap + +Spacing and gap are both about setting the space between components. + + * Spacing applies margin to every element except for the first element in a group. + * Gap creates a gap between every element in flexbox elements and grids. + +> Rule of thumb: Use Gap when using grids. + +Let's take a look at some grid examples. + +#### Grid + +See Source + +See Output + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +[code] + + Grid( + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + cls='') +[/code] + +#### Grid with gap + +See Source + +See Output + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +[code] + + Grid( + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + cls='gap-4') +[/code] + +#### Grid with space + +See Source + +See Output + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +#### A Simple Card + +[code] + + Grid( + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + Card(H4("A Simple Card")), + cls='space-x-4 space-y-4') +[/code] + +### Grid with no gap or space + +The first example has no gap or not space applied. As expected this means the cards are flush with each other. Often this is not what you want, because a little space between cards looks much nicer. + +### Grid with gap + +The second example has the same grid but with gap applied. As youc an see, this gives constent space between all elements of the grid looks great! + +### Grid with space + +The third example has the same grid but with space applied. As you can see, it's not really what we want. However it's a really good illustration of how space works so let's notice a few things about it: + +**X Axis** + + * The first card is flush with the left side of the page (no margin) + * The card below it isn't flush with the left side of the page (has margin) + +**Y Axis** + + * The first card is flush with the heading immediately above it (no margin) + * The card top it's right isn't flush with the heading above it (has margin) + +So `space` applies margin to every element except for the first element in a group! + +> Tip: Use your browser developer tools to inspect the examples + +Next, let's look at a form example where `gap` isn't a good choice but `space` works beautifully! + +See Source + +See Output + +### My Form + +Name + +Phone + +Email + +[code] + + Form(DivCentered(H3("My Form")), + LabelInput("Name"), + Grid(LabelInput("Phone"), LabelInput("Email"), cols=2), + cls='') +[/code] + +See Source + +See Output + +### My Form with gap + +Name + +Phone + +Email + +[code] + + Form(DivCentered(H3("My Form with gap")), + LabelInput("Name"), + Grid(LabelInput("Phone"), LabelInput("Email"), cols=2), + cls='gap-y-5') +[/code] + +See Source + +See Output + +### My Form with Spacing + +Name + +Phone + +Email + +[code] + + Form(DivCentered(H3("My Form with Spacing")), + LabelInput("Name"), + Grid(LabelInput("Phone"), LabelInput("Email"), cols=2), + cls='space-y-5') +[/code] + +### Form with no gap or space + +The top form looks a bit scrunched with defaults, but it's certainly passable. There is a bit of a space between the label and it's associated input because of the defaults in MonsterUI. + +### Form with gap + +The second form with gap is identical to the first. Because we're not in a flex element or a grid, it doesn't do anything at all! + +### Form with space + +`Space-y-5` adds vertical space between each child which really spreads out the form for a nice aesthetic. If you recall from the grid example, it does not apply this margin to the first element - but in this situation (and many others) we do not want the spacing above the top element (heading) to be the same as the spacing between the form elements. + +> Tip: Use your browser developer tools to inspect the examples + +# Further reading + +For further reading, check out the Tailwind CSS guide, which other users have found to be a useful as an additional guide. +
diff --git a/MonsterUI/docs/llms-ctx.txt b/MonsterUI/docs/llms-ctx.txt new file mode 100644 index 0000000000000000000000000000000000000000..ce4cf13e7864cee127e271a9b6a51f29185c81d1 --- /dev/null +++ b/MonsterUI/docs/llms-ctx.txt @@ -0,0 +1,1603 @@ +> MonsterUI is a python library which brings styling to python for FastHTML apps.# monsterui Module Documentation + +## monsterui.core + +- `class ThemeRadii(Enum)` + Members: none, sm, md, lg + + +- `class ThemeShadows` + +- `class ThemeFont` + +- `class Theme(Enum)` + Selector to choose theme and get all headers needed for app. Includes frankenui + tailwind + daisyui + highlight.js options + Members: slate, stone, gray, neutral, red, rose, orange, green, blue, yellow, violet, zinc + + - `headers(self, mode, icons, daisy, highlightjs, katex, apex_charts, radii, shadows, font)` + Create frankenui and tailwind cdns + + - `local_headers(self, mode, static_dir, icons, daisy, highlightjs, katex, apex_charts, radii, shadows, font)` + Create headers using local files downloaded from CDNs + + +## monsterui.daisy + +- `class AlertT(Enum)` + Alert styles from DaisyUI + Members: info, success, warning, error + + +- `def Alert(*c, **kwargs)` + Alert informs users about important events. + +- `class StepsT(Enum)` + Options for Steps + Members: vertical, horizonal + + +- `class StepT(Enum)` + Step styles for LiStep + Members: primary, secondary, accent, info, success, warning, error, neutral + + +- `def Steps(*li, **kwargs)` + Creates a steps container + +- `def LiStep(*c, **kwargs)` + Creates a step list item + +- `class LoadingT(Enum)` + Members: spinner, dots, ring, ball, bars, infinity, xs, sm, md, lg + + +- `def Loading(cls, htmx_indicator, **kwargs)` + Creates a loading animation component + +- `class ToastHT(Enum)` + Horizontal position for Toast + Members: start, center, end + + +- `class ToastVT(Enum)` + Vertical position for Toast + Members: top, middle, bottom + + +## monsterui.foundations + +> Data Structures and Utilties + +- `def stringify(o)` + Converts input types into strings that can be passed to FT components + +- `class VEnum(Enum)` + Members: + + - `__str__(self)` + - `__add__(self, other)` + - `__radd__(self, other)` + +## monsterui.franken + +- `class TextT(Enum)` + Text Styles from https://franken-ui.dev/docs/text + Members: paragraph, lead, meta, gray, italic, xs, sm, lg, xl, light, normal, medium, bold, extrabold, muted, primary, secondary, success, warning, error, info, left, right, center, justify, start, end, top, middle, bottom, truncate, break_, nowrap, underline, highlight + + +- `class TextPresets(Enum)` + Common Typography Presets + Members: muted_sm, muted_lg, bold_sm, bold_lg, md_weight_sm, md_weight_muted + + +- `def CodeSpan(*c, **kwargs)` + A CodeSpan with Styling + +- `def CodeBlock(*c, **kwargs)` + CodeBlock with Styling + +- `def H1(*c, **kwargs)` + H1 with styling and appropriate size + +- `def H2(*c, **kwargs)` + H2 with styling and appropriate size + +- `def H3(*c, **kwargs)` + H3 with styling and appropriate size + +- `def H4(*c, **kwargs)` + H4 with styling and appropriate size + +- `def H5(*c, **kwargs)` + H5 with styling and appropriate size + +- `def H6(*c, **kwargs)` + H6 with styling and appropriate size + +- `def Subtitle(*c, **kwargs)` + Styled muted_sm text designed to go under Headings and Titles + +- `def Q(*c, **kwargs)` + Styled quotation mark + +- `def Em(*c, **kwargs)` + Styled emphasis text + +- `def Strong(*c, **kwargs)` + Styled strong text + +- `def I(*c, **kwargs)` + Styled italic text + +- `def Small(*c, **kwargs)` + Styled small text + +- `def Mark(*c, **kwargs)` + Styled highlighted text + +- `def Del(*c, **kwargs)` + Styled deleted text + +- `def Ins(*c, **kwargs)` + Styled inserted text + +- `def Sub(*c, **kwargs)` + Styled subscript text + +- `def Sup(*c, **kwargs)` + Styled superscript text + +- `def Blockquote(*c, **kwargs)` + Blockquote with Styling + +- `def Caption(*c, **kwargs)` + Styled caption text + +- `def Cite(*c, **kwargs)` + Styled citation text + +- `def Time(*c, **kwargs)` + Styled time element + +- `def Address(*c, **kwargs)` + Styled address element + +- `def Abbr(*c, **kwargs)` + Styled abbreviation with dotted underline + +- `def Dfn(*c, **kwargs)` + Styled definition term with italic and medium weight + +- `def Kbd(*c, **kwargs)` + Styled keyboard input with subtle background + +- `def Samp(*c, **kwargs)` + Styled sample output with subtle background + +- `def Var(*c, **kwargs)` + Styled variable with italic monospace + +- `def Figure(*c, **kwargs)` + Styled figure container with card-like appearance + +- `def Details(*c, **kwargs)` + Styled details element + +- `def Summary(*c, **kwargs)` + Styled summary element + +- `def Data(*c, **kwargs)` + Styled data element + +- `def Meter(*c, **kwargs)` + Styled meter element + +- `def S(*c, **kwargs)` + Styled strikethrough text (different semantic meaning from Del) + +- `def U(*c, **kwargs)` + Styled underline (for proper names in Chinese, proper spelling etc) + +- `def Output(*c, **kwargs)` + Styled output element for form results + +- `def PicSumImg(h, w, id, grayscale, blur, **kwargs)` + Creates a placeholder image using https://picsum.photos/ + +- `def AccordionItem(title, *c)` + Creates a single item for use within an Accordion component, handling title, content, and open state. + +- `def Accordion(*c, **kwargs)` + Creates a styled Accordion container using accordion component. + +- `class ButtonT(Enum)` + Options for styling Buttons + Members: default, ghost, primary, secondary, destructive, text, link, xs, sm, lg, xl, icon + + +- `def Button(*c, **kwargs)` + Button with Styling (defaults to `submit` for form submission) + +- `class ContainerT(Enum)` + Max width container sizes from https://franken-ui.dev/docs/container + Members: xs, sm, lg, xl, expand + + +- `class BackgroundT(Enum)` + Members: muted, primary, secondary, default + + +- `def Container(*c, **kwargs)` + Div to be used as a container that often wraps large sections or a page of content + +- `def Titled(title, *c, **kwargs)` + Creates a standard page structure for titled page. Main(Container(title, content)) + +- `class DividerT(Enum)` + Divider Styles from https://franken-ui.dev/docs/divider + Members: icon, sm, vertical + + +- `def Divider(*c, **kwargs)` + Divider with default styling and margin + +- `def DividerSplit(*c)` + Creates a simple horizontal line divider with configurable thickness and vertical spacing + +- `def Article(*c, **kwargs)` + A styled article container for blog posts or similar content + +- `def ArticleTitle(*c, **kwargs)` + A title component for use within an Article + +- `def ArticleMeta(*c, **kwargs)` + A metadata component for use within an Article showing things like date, author etc + +- `class SectionT(Enum)` + Section styles from https://franken-ui.dev/docs/section + Members: default, muted, primary, secondary, xs, sm, lg, xl, remove_vertical + + +- `def Section(*c, **kwargs)` + Section with styling and margins + +- `def Form(*c, **kwargs)` + A Form with default spacing between form elements + +- `def Fieldset(*c, **kwargs)` + A Fieldset with default styling + +- `def Legend(*c, **kwargs)` + A Legend with default styling + +- `def Input(*c, **kwargs)` + An Input with default styling + +- `def Radio(*c, **kwargs)` + A Radio with default styling + +- `def CheckboxX(*c, **kwargs)` + A Checkbox with default styling + +- `def Range(*c, **kwargs)` + A Range with default styling + +- `def TextArea(*c, **kwargs)` + A Textarea with default styling + +- `def Switch(*c, **kwargs)` + A Switch with default styling + +- `def Upload(*c, **kwargs)` + A file upload component with default styling + +- `def UploadZone(*c, **kwargs)` + A file drop zone component with default styling + +- `def FormLabel(*c, **kwargs)` + A Label with default styling + +- `class LabelT(Enum)` + Members: primary, secondary, destructive + + +- `def Label(*c, **kwargs)` + FrankenUI labels, which look like pills + +- `def UkFormSection(title, description, *c)` + A form section with a title, description and optional button + +- `def GenericLabelInput(label, lbl_cls, input_cls, container, cls, id, input_fn, **kwargs)` + `Div(Label,Input)` component with Uk styling injected appropriately. Generally you should higher level API, such as `LabelInput` which is created for you in this library + +- `def LabelInput(label, lbl_cls, input_cls, cls, id, **kwargs)` + A `FormLabel` and `Input` pair that provides default spacing and links/names them based on id + +- `def LabelRadio(label, lbl_cls, input_cls, container, cls, id, **kwargs)` + A FormLabel and Radio pair that provides default spacing and links/names them based on id + +- `def LabelCheckboxX(label, lbl_cls, input_cls, container, cls, id, **kwargs)` + A FormLabel and CheckboxX pair that provides default spacing and links/names them based on id + +- `def Options(*c)` + Helper function to wrap things into `Option`s for use in `Select` + +- `def Select(*option, **kwargs)` + Creates a select dropdown with uk styling and option for adding a search box + +- `def LabelSelect(*option, **kwargs)` + A FormLabel and Select pair that provides default spacing and links/names them based on id + +- `@delegates(GenericLabelInput, but=['input_fn', 'cls']) def LabelRange(label, lbl_cls, input_cls, cls, id, value, min, max, step, label_range, **kwargs)` + A FormLabel and Range pair that provides default spacing and links/names them based on id + +- `class AT(Enum)` + Link styles from https://franken-ui.dev/docs/link + Members: muted, text, reset, primary, classic + + +- `class ListT(Enum)` + List styles using Tailwind CSS + Members: disc, circle, square, decimal, hyphen, bullet, divider, striped + + +- `def ModalContainer(*c, **kwargs)` + Creates a modal container that components go in + +- `def ModalDialog(*c, **kwargs)` + Creates a modal dialog + +- `def ModalHeader(*c, **kwargs)` + Creates a modal header + +- `def ModalBody(*c, **kwargs)` + Creates a modal body + +- `def ModalFooter(*c, **kwargs)` + Creates a modal footer + +- `def ModalTitle(*c, **kwargs)` + Creates a modal title + +- `def ModalCloseButton(*c, **kwargs)` + Creates a button that closes a modal with js + +- `def Modal(*c, **kwargs)` + Creates a modal with the appropriate classes to put the boilerplate in the appropriate places for you + +- `def Placeholder(*c, **kwargs)` + Creates a placeholder + +- `def Progress(*c, **kwargs)` + Creates a progress bar + +- `def UkIcon(icon, height, width, stroke_width, cls, **kwargs)` + Creates an icon using lucide icons + +- `def UkIconLink(icon, height, width, stroke_width, cls, button, **kwargs)` + Creates an icon link using lucide icons + +- `def DiceBearAvatar(seed_name, h, w)` + Creates an Avatar using https://dicebear.com/ + +- `def Center(*c, **kwargs)` + Centers contents both vertically and horizontally by default + +- `class FlexT(Enum)` + Flexbox modifiers using Tailwind CSS + Members: block, inline, left, center, right, between, around, stretch, top, middle, bottom, row, row_reverse, column, column_reverse, nowrap, wrap, wrap_reverse + + +- `def Grid(*div, **kwargs)` + Creates a responsive grid layout with smart defaults based on content + +- `def DivFullySpaced(*c, **kwargs)` + Creates a flex div with it's components having as much space between them as possible + +- `def DivCentered(*c, **kwargs)` + Creates a flex div with it's components centered in it + +- `def DivLAligned(*c, **kwargs)` + Creates a flex div with it's components aligned to the left + +- `def DivRAligned(*c, **kwargs)` + Creates a flex div with it's components aligned to the right + +- `def DivVStacked(*c, **kwargs)` + Creates a flex div with it's components stacked vertically + +- `def DivHStacked(*c, **kwargs)` + Creates a flex div with it's components stacked horizontally + +- `class NavT(Enum)` + Members: default, primary, secondary + + +- `def NavContainer(*li, **kwargs)` + Creates a navigation container (useful for creating a sidebar navigation). A Nav is a list (NavBar is something different) + +- `def NavParentLi(*nav_container, **kwargs)` + Creates a navigation list item with a parent nav for nesting + +- `def NavDividerLi(*c, **kwargs)` + Creates a navigation list item with a divider + +- `def NavHeaderLi(*c, **kwargs)` + Creates a navigation list item with a header + +- `def NavSubtitle(*c, **kwargs)` + Creates a navigation subtitle + +- `def NavCloseLi(*c, **kwargs)` + Creates a navigation list item with a close button + +- `class ScrollspyT(Enum)` + Members: underline, bold + + +- `def NavBar(*c)` + Creates a responsive navigation bar with mobile menu support + +- `def SliderContainer(*c, **kwargs)` + Creates a slider container + +- `def SliderItems(*c, **kwargs)` + Creates a slider items container + +- `def SliderNav(cls, prev_cls, next_cls, **kwargs)` + Navigation arrows for Slider component + +- `def Slider(*c, **kwargs)` + Creates a slider with optional navigation arrows + +- `def DropDownNavContainer(*li, **kwargs)` + A Nav that is part of a DropDown + +- `def TabContainer(*li, **kwargs)` + A TabContainer where children will be different tabs + +- `class CardT(Enum)` + Card styles from UIkit + Members: default, primary, secondary, destructive, hover + + +- `def CardTitle(*c, **kwargs)` + Creates a card title + +- `def CardHeader(*c, **kwargs)` + Creates a card header + +- `def CardBody(*c, **kwargs)` + Creates a card body + +- `def CardFooter(*c, **kwargs)` + Creates a card footer + +- `def CardContainer(*c, **kwargs)` + Creates a card container + +- `def Card(*c, **kwargs)` + Creates a Card with a header, body, and footer + +- `class TableT(Enum)` + Members: divider, striped, hover, sm, lg, justify, middle, responsive + + +- `def Table(*c, **kwargs)` + Creates a table + +- `def TableFromLists(header_data, body_data, footer_data, header_cell_render, body_cell_render, footer_cell_render, cls, sortable, **kwargs)` + Creates a Table from a list of header data and a list of lists of body data + +- `def TableFromDicts(header_data, body_data, footer_data, header_cell_render, body_cell_render, footer_cell_render, cls, sortable, **kwargs)` + Creates a Table from a list of header data and a list of dicts of body data + +- `def apply_classes(html_str, class_map, class_map_mods)` + Apply classes to html string + +- `class FrankenRenderer` + Custom renderer for Franken UI that handles image paths + + - `def __init__(self, *args, **kwargs)` + - `def render_image(self, token)` + Modify image paths if they're relative and self.img_dir is specified + + +- `def render_md(md_content, class_map, class_map_mods, img_dir, renderer)` + Renders markdown using mistletoe and lxml with custom image handling + +- `def ThemePicker(color, radii, shadows, font, mode, cls, custom_themes)` + Theme picker component with configurable sections + +- `def LightboxContainer(*lightboxitem, **kwargs)` + Lightbox container that will hold `LightboxItems` + +- `def LightboxItem(*c, **kwargs)` + Anchor tag with appropriate structure to go inside a `LightBoxContainer` + +- `def ApexChart(**kws)` + Apex chart component +"""FrankenUI Cards Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from fasthtml.components import Uk_input_tag +from fasthtml.svg import * +from monsterui.all import * +import calendar +from datetime import datetime + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +CreateAccount = Card( + Grid(Button(DivLAligned(UkIcon('github'),Div('Github'))),Button('Google')), + DividerSplit("OR CONTINUE WITH", text_cls=TextPresets.muted_sm), + LabelInput('Email', id='email', placeholder='m@example.com'), + LabelInput('Password', id='password',placeholder='Password', type='Password'), + header=(H3('Create an Account'),Subtitle('Enter your email below to create your account')), + footer=Button('Create Account',cls=(ButtonT.primary,'w-full'))) + +PaypalSVG_data = "M7.076 21.337H2.47a.641.641 0 0 1-.633-.74L4.944.901C5.026.382 5.474 0 5.998 0h7.46c2.57 0 4.578.543 5.69 1.81 1.01 1.15 1.304 2.42 1.012 4.287-.023.143-.047.288-.077.437-.983 5.05-4.349 6.797-8.647 6.797h-2.19c-.524 0-.968.382-1.05.9l-1.12 7.106zm14.146-14.42a3.35 3.35 0 0 0-.607-.541c-.013.076-.026.175-.041.254-.93 4.778-4.005 7.201-9.138 7.201h-2.19a.563.563 0 0 0-.556.479l-1.187 7.527h-.506l-.24 1.516a.56.56 0 0 0 .554.647h3.882c.46 0 .85-.334.922-.788.06-.26.76-4.852.816-5.09a.932.932 0 0 1 .923-.788h.58c3.76 0 6.705-1.528 7.565-5.946.36-1.847.174-3.388-.777-4.471z" +AppleSVG_data = "M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701" +Card1Svg = Svg(viewBox="0 0 24 24", fill="none", stroke="currentColor", stroke_linecap="round", stroke_linejoin="round", stroke_width="2", cls="h-6 w-6 mr-1")(Rect(width="20", height="14", x="2", y="5", rx="2"),Path(d="M2 10h20")) +PaypalSvg = Svg(role="img", viewBox="0 0 24 24", cls="h-6 w-6 mr-1")(Path(d=PaypalSVG_data, fill="currentColor")), +AppleSvg = Svg(role="img", viewBox="0 0 24 24", cls="h-6 w-6 mr-1")(Path(d=AppleSVG_data, fill="currentColor")) + +PaymentMethod = Card( + Grid(Button(DivCentered(Card1Svg, "Card"), cls='h-20 border-2 border-primary'), + Button(DivCentered(PaypalSvg, "PayPal"), cls='h-20'), + Button(DivCentered(AppleSvg, "Apple"), cls='h-20')), + Form(LabelInput('Name', id='name', placeholder='John Doe'), + LabelInput('Card Number', id='card_number', placeholder='m@example.com'), + Grid(LabelSelect(*Options(*calendar.month_name[1:],selected_idx=0),label='Expires',id='expire_month'), + LabelSelect(*Options(*range(2024,2030),selected_idx=0), label='Year', id='expire_year'), + LabelInput('CVV', id='cvv',placeholder='CVV', cls='mt-0'))), + header=(H3('Payment Method'),Subtitle('Add a new payment method to your account.'))) + +area_opts = ('Team','Billing','Account','Deployment','Support') +severity_opts = ('Severity 1 (Highest)', 'Severity 2', 'Severity 3', 'Severity 4 (Lowest)') +ReportIssue = Card( + Grid(Div(LabelSelect(*Options(*area_opts), label='Area', id='area')), + Div(LabelSelect(*Options(*severity_opts),label='Severity',id='area'))), + LabelInput( label='Subject', id='subject', placeholder='I need help with'), + LabelTextArea( label='Description', id='description',placeholder='Please include all information relevant to your issue'), + Div(FormLabel('Tags', fr='#tags'), + Uk_input_tag(name="Tags",state="danger", value="Spam,Invalid", uk_cloak=True, id='tags')), + header=(H3('Report Issue'),Subtitle('What area are you having problems with?')), + footer = DivFullySpaced(Button('Cancel'), Button(cls=ButtonT.primary)('Submit'))) + +monster_desc ="Python-first beautifully designed components because you deserve to focus on features that matter and your app deserves to be beautiful from day one." +MonsterUI = Card(H4("Monster UI"), + Subtitle(monster_desc), + DivLAligned( + Div("Python"), + DivLAligned(UkIcon('star'),Div("20k"), cls='space-x-1'), + Div(datetime.now().strftime("%B %d, %Y")), + cls=('space-x-4',TextPresets.muted_sm))) + +def CookieTableRow(heading, description, active=False): + return Tr(Td(H5(heading)), + Td(P(description, cls=TextPresets.muted_sm)), + Td(Switch(checked=active))) + +CookieSettings = Card( + Table(Tbody( + CookieTableRow('Strictly Necessary', 'These cookies are essential in order to use the website and use its features.', True), + CookieTableRow('Functional Cookies', 'These cookies allow the website to provide personalized functionality.'), + CookieTableRow('Performance Cookies', 'These cookies help to improve the performance of the website.'))), + header=(H4('Cookie Settings'),Subtitle('Manage your cookie settings here.')), + footer=Button('Save Preferences', cls=(ButtonT.primary, 'w-full'))) + +team_members = [("Sofia Davis", "m@example.com", "Owner"),("Jackson Lee", "p@example.com", "Member"),] +def TeamMemberRow(name, email, role): + return DivFullySpaced( + DivLAligned( + DiceBearAvatar(name, 10,10), + Div(P(name, cls=(TextT.sm, TextT.medium)), + P(email, cls=TextPresets.muted_sm))), + Button(role, UkIcon('chevron-down', cls='ml-4')), + DropDownNavContainer(map(NavCloseLi, [ + A(Div('Viewer', NavSubtitle('Can view and comment.'))), + A(Div('Developer', NavSubtitle('Can view, comment and edit.'))), + A(Div('Billing', NavSubtitle('Can view, comment and manage billing.'))), + A(Div('Owner', NavSubtitle('Admin-level access to all resources.')))]))) + +TeamMembers = Card(*[TeamMemberRow(*member) for member in team_members], + header = (H4('Team Members'),Subtitle('Invite your team members to collaborate.'))) + +access_roles = ("Read and write access", "Read-only access") +team_members = [("Olivia Martin", "m@example.com", "Read and write access"), + ("Isabella Nguyen", "b@example.com", "Read-only access"), + ("Sofia Davis", "p@example.com", "Read-only access")] + +def TeamMemberRow(name, email, role): + return DivFullySpaced( + DivLAligned(DiceBearAvatar(name, 10,10), + Div(P(name, cls=(TextT.sm, TextT.medium)), + P(email, cls=TextPresets.muted_sm))), + Select(*Options(*access_roles, selected_idx=access_roles.index(role)))) + +ShareDocument = Card( + DivLAligned(Input(value='http://example.com/link/to/document'),Button('Copy link', cls='whitespace-nowrap')), + Divider(), + H4('People with access', cls=TextPresets.bold_sm), + *[TeamMemberRow(*member) for member in team_members], + header = (H4('Share this document'),Subtitle('Anyone with the link can view this document.'))) + +DateCard = Card(Button('Jan 20, 2024 - Feb 09, 2024')) + +section_content =(('bell','Everything',"Email digest, mentions & all activity."), + ('user',"Available","Only mentions and comments"), + ('ban', "Ignoring","Turn of all notifications")) + +def NotificationRow(icon, name, desc): + return Li(cls='-mx-1')(A(DivLAligned(UkIcon(icon),Div(P(name),P(desc, cls=TextPresets.muted_sm))))) + +Notifications = Card( + NavContainer( + *[NotificationRow(*row) for row in section_content], + cls=NavT.secondary), + header = (H4('Notification'),Subtitle('Choose what you want to be notified about.')), + body_cls='pt-0') + +TeamCard = Card( + DivLAligned( + DiceBearAvatar("Isaac Flath", h=24, w=24), + Div(H3("Isaac Flath"), P("Library Creator"))), + footer=DivFullySpaced( + DivHStacked(UkIcon("map-pin", height=16), P("Alexandria, VA")), + DivHStacked(*(UkIconLink(icon, height=16) for icon in ("mail", "linkedin", "github")))), + cls=CardT.hover) + +@rt +def index(): + return Title("Cards Example"),Container(Grid( + *map(Div,( + Div(PaymentMethod,CreateAccount, TeamCard, cls='space-y-4'), + Div(TeamMembers, ShareDocument,DateCard,Notifications, cls='space-y-4'), + Div(ReportIssue,MonsterUI,CookieSettings, cls='space-y-4'))), + cols_md=1, cols_lg=2, cols_xl=3)) + +serve()"""FrankenUI Dashboard Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * # Bring in all of fasthtml +import fasthtml.common as fh # Used to get unstyled components +from monsterui.all import * # Bring in all of monsterui, including shadowing fasthtml components with styled components +from fasthtml.svg import * +import numpy as np +import plotly.express as px +import pandas as pd +import numpy as np + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def generate_chart(num_points=30): + df = pd.DataFrame({ + 'Date': pd.date_range('2024-01-01', periods=num_points), + 'Revenue': np.random.normal(100, 10, num_points).cumsum(), + 'Users': np.random.normal(80, 8, num_points).cumsum(), + 'Growth': np.random.normal(60, 6, num_points).cumsum()}) + + fig = px.line(df, x='Date', y=['Revenue', 'Users', 'Growth'], template='plotly_white', line_shape='spline') + + fig.update_traces(mode='lines+markers') + fig.update_layout( + margin=dict(l=20, r=20, t=20, b=20), hovermode='x unified', + showlegend=True, legend=dict(orientation='h', yanchor='bottom', y=1.02, xanchor='right', x=1), + plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)', + xaxis=dict(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)'), + yaxis=dict(showgrid=True, gridwidth=1, gridcolor='rgba(0,0,0,0.1)')) + + return fig.to_html(include_plotlyjs=True, full_html=False, config={'displayModeBar': False}) + +def InfoCard(title, value, change): return Card(H3(value),P(change, cls=TextPresets.muted_sm), header = H4(title)) + +rev = InfoCard("Total Revenue", "$45,231.89", "+20.1% from last month") +sub = InfoCard("Subscriptions", "+2350", "+180.1% from last month") +sal = InfoCard("Sales", "+12,234", "+19% from last month") +act = InfoCard("Active Now", "+573", "+201 since last hour") + +info_card_data = [("Total Revenue", "$45,231.89", "+20.1% from last month"), + ("Subscriptions", "+2350", "+180.1% from last month"), + ("Sales", "+12,234", "+19% from last month"), + ("Active Now", "+573", "+201 since last hour")] + +top_info_row = Grid(*[InfoCard(*row) for row in info_card_data]) + +def AvatarItem(name, email, amount): + return DivFullySpaced( + DivLAligned( + DiceBearAvatar(name, 9,9), + Div(Strong(name, cls=TextT.sm), + Address(A(email,href=f'mailto:{email}')))), + fh.Data(amount, cls="ml-auto font-medium", value=amount[2:])) + +recent_sales = Card( + Div(cls="space-y-8")( + *[AvatarItem(n,e,d) for (n,e,d) in ( + ("Olivia Martin", "olivia.martin@email.com", "+$1,999.00"), + ("Jackson Lee", "jackson.lee@email.com", "+$39.00"), + ("Isabella Nguyen", "isabella.nguyen@email.com", "+$299.00"), + ("William Kim", "will@email.com", "+$99.00"), + ("Sofia Davis", "sofia.davis@email.com", "+$39.00"))]), + header=Div(H3("Recent Sales"),Subtitle("You made 265 sales this month.")), + cls='col-span-3') + +teams = [["Alicia Koch"],['Acme Inc', 'Monster Inc.'],['Create a Team']] + +opt_hdrs = ["Personal", "Team", ""] + +team_dropdown = Select( + Optgroup(Option(A("Alicia Koch")), label="Personal Account"), + Optgroup(Option(A("Acme Inc")), Option(A("Monster Inc.")), label="Teams"), + Option(A("Create a Team")), + cls='flex items-center') + +hotkeys = [('Profile','⇧⌘P'),('Billing','⌘B'),('Settings','⌘S'),('New Team', ''), ('Logout', '')] + +def NavSpacedLi(t,s): return NavCloseLi(A(DivFullySpaced(P(t),P(s,cls=TextPresets.muted_sm)))) + +avatar_dropdown = Div( + DiceBearAvatar('Alicia Koch',8,8), + DropDownNavContainer( + NavHeaderLi('sveltecult',NavSubtitle("leader@sveltecult.com")), + *[NavSpacedLi(*hk) for hk in hotkeys],)) + +top_nav = NavBar( + team_dropdown, *map(A, ["Overview", "Customers", "Products", "Settings"]), + brand=DivLAligned(avatar_dropdown, Input(placeholder='Search'))) + +@rt +def index(): + return Title("Dashboard Example"), Container( + top_nav, + H2('Dashboard'), + TabContainer( + Li(A("Overview"),cls='uk-active'), + *map(lambda x: Li(A(x)), ["Analytics", "Reports", "Notifications"]), + alt=True), + top_info_row, + Grid( + Card(Safe(generate_chart(100)), cls='col-span-4'), + recent_sales, + gap=4,cols_xl=7,cols_lg=7,cols_md=1,cols_sm=1,cols_xs=1), + cls=('space-y-4', ContainerT.xl)) + +serve()"""FrankenUI Forms Example built with MonsterUI (original design by ShadCN)""" + + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def HelpText(c): return P(c,cls=TextPresets.muted_sm) + +def heading(): + return Div(cls="space-y-5")( + H2("Settings"), + Subtitle("Manage your account settings and set e-mail preferences."), + DividerSplit()) + + +sidebar = NavContainer( + *map(lambda x: Li(A(x)), ("Profile", "Account", "Appearance", "Notifications", "Display")), + uk_switcher="connect: #component-nav; animation: uk-animation-fade", + cls=(NavT.secondary,"space-y-4 p-4 w-1/5")) + + +def FormSectionDiv(*c, cls='space-y-2', **kwargs): return Div(*c, cls=cls, **kwargs) + +def FormLayout(title, subtitle, *content, cls='space-y-3 mt-4'): return Container(Div(H3(title), Subtitle(subtitle), DividerLine(), Form(*content, cls=cls))) + +def profile_form(): + content = (FormSectionDiv( + LabelInput("Username", placeholder='sveltecult', id='username'), + HelpText("This is your public display name. It can be your real name or a pseudonym. You can only change this once every 30 days.")), + FormSectionDiv( + LabelSelect( + Option("Select a verified email to display", value="", selected=True, disabled=True), + *[Option(o, value=o) for o in ('m@example.com', 'm@yahoo.com', 'm@cloud.com')], + label="Email", id="email"), + HelpText("You can manage verified email addresses in your email settings.")), + FormSectionDiv( + LabelTextArea("Bio", id="bio", placeholder="Tell us a little bit about yourself"), + HelpText("You can @mention other users and organizations to link to them."), + P("String must contain at least 4 character(s)", cls="text-destructive")), + FormSectionDiv( + FormLabel("URLs"), + HelpText("Add links to your website, blog, or social media profiles."), + Input(value="https://www.franken-ui.dev"), + Input(value="https://github.com/sveltecult/franken-ui"), + Button("Add URL")), + Button('Update profile', cls=ButtonT.primary)) + + return FormLayout('Profile', 'This is how others will see you on the site.', *content) + +def account_form(): + content = ( + FormSectionDiv( + LabelInput("Name", placeholder="Your name", id="name"), + HelpText("This is the name that will be displayed on your profile and in emails.")), + FormSectionDiv( + LabelInput("Date of Birth", type="date", placeholder="Pick a date", id="date_of_birth"), + HelpText("Your date of birth is used to calculate your age.")), + FormSectionDiv( + LabelSelect(*Options("Select a language", "English", "French", "German", "Spanish", "Portuguese", selected_idx=1, disabled_idxs={0}), + label='Language', id="language"), + HelpText("This is the language that will be used in the dashboard.")), + Button('Update profile', cls=ButtonT.primary)) + + return FormLayout('Account', 'Update your account settings. Set your preferred language and timezone.', *content) + +def appearance_form(): + def theme_item(bg_color, content_bg, text_bg): + common_content = f"space-y-2 rounded-md {content_bg} p-2 shadow-sm" + item_row = lambda: Div(cls=f"flex items-center space-x-2 {common_content}")( + Div(cls=f"h-4 w-4 rounded-full {text_bg}"), + Div(cls=f"h-2 w-[100px] rounded-lg {text_bg}")) + + return Div(cls=f"space-y-2 rounded-sm {bg_color} p-2")( + Div(cls=common_content)( + Div(cls=f"h-2 w-[80px] rounded-lg {text_bg}"), + Div(cls=f"h-2 w-[100px] rounded-lg {text_bg}")), + item_row(), + item_row()) + + common_toggle_cls = "block cursor-pointer items-center rounded-md border-2 border-muted p-1 ring-ring" + + content = ( + FormSectionDiv( + LabelSelect(*Options('Select a font family', 'Inter', 'Geist', 'Open Sans', selected_idx=2, disabled_idxs={0}), + label='Font Family', id='font_family'), + HelpText("Set the font you want to use in the dashboard.")), + FormSectionDiv( + FormLabel("Theme"), + HelpText("Select the theme for the dashboard."), + Grid( + A(id="theme-toggle-light", cls=common_toggle_cls)(theme_item("bg-[#ecedef]", "bg-white", "bg-[#ecedef]")), + A(id="theme-toggle-dark", cls=f"{common_toggle_cls} bg-popover")(theme_item("bg-slate-950", "bg-slate-800", "bg-slate-400")), + cols_max=2,cls=('max-w-md','gap-8'))), + Button('Update preferences', cls=ButtonT.primary)) + + return FormLayout('Appearance', 'Customize the appearance of the app. Automatically switch between day and night themes.', *content) + + +notification_items = [ + {"title": "Communication emails", "description": "Receive emails about your account activity.", "checked": False, "disabled": False}, + {"title": "Marketing emails", "description": "Receive emails about new products, features, and more.", "checked": False, "disabled": False}, + {"title": "Social emails", "description": "Receive emails for friend requests, follows, and more.", "checked": True, "disabled": False}, + {"title": "Security emails", "description": "Receive emails about your account activity and security.", "checked": True, "disabled": True}] + +def notifications_form(): + def RadioLabel(label): return DivLAligned(Radio(name="notification", checked=(label=="Nothing")), FormLabel(label)) + + def NotificationCard(item): + return Card( + Div(cls="space-y-0.5")( + FormLabel(Strong(item['title'], cls=TextT.sm), + HelpText(item['description'])))) + content = Div( + FormSectionDiv( + FormLabel("Notify me about"), + *map(RadioLabel, ["All new messages", "Direct messages and mentions", "Nothing"])), + Div( + H4("Email Notifications", cls="mb-4"), + Grid(*map(NotificationCard, notification_items), cols=1)), + LabelCheckboxX("Use different settings for my mobile devices", id="notification_mobile"), + HelpText("You can manage your mobile notifications in the mobile settings page."), + Button('Update notifications', cls=ButtonT.primary)) + + return FormLayout('Notifications', 'Configure how you receive notifications.', *content) + +def display_form(): + content = ( + Div(cls="space-y-2")( + Div(cls="mb-4")( + H5("Sidebar"), + Subtitle("Select the items you want to display in the sidebar.")), + *[Div(CheckboxX(id=f"display_{i}", checked=i in [0, 1, 2]),FormLabel(label)) + for i, label in enumerate(["Recents", "Home", "Applications", "Desktop", "Downloads", "Documents"])]), + Button('Update display', cls=ButtonT.primary)) + return FormLayout('Display', 'Turn items on or off to control what\'s displayed in the app.', *content) + +@rt +def index(): + return Title("Forms Example"),Container( + heading(), + Div(cls="flex gap-x-12")( + sidebar, + Ul(id="component-nav", cls="uk-switcher max-w-2xl")( + Li(cls="uk-active")(profile_form(), + *map(Li, [account_form(), appearance_form(), notifications_form(), display_form()]))))) + +serve()"MonsterUI Scrollspy Example application" + +from fasthtml.common import * +from monsterui.all import * +import random + +# Using the "slate" theme with Highlight.js enabled +hdrs = Theme.slate.headers(highlightjs=True) +app, rt = fast_app(hdrs=hdrs) + +################################ +### Example Data and Content ### +################################ +products = [ + {"name": "Laptop", "price": "$999"}, + {"name": "Smartphone", "price": "$599"} +] + +code_example = """ +# Python Code Example +def greet(name): + return f"Hello, {name}!" + +print(greet("World")) +""" +testimonials = [ + {"name": "Alice", "feedback": "Great products and excellent customer service!"}, + {"name": "Bob", "feedback": "Fast shipping and amazing quality!"}, + {"name": "Charlie", "feedback": "Amazing experience! Will definitely buy again."}, + {"name": "Diana", "feedback": "Affordable prices and great variety!"}, + {"name": "Edward", "feedback": "Customer support was very helpful."}, + {"name": "Fiona", "feedback": "Loved the design and quality!"} +] + +# Team members +team = [ + {"name": "Isaac Flath", "role": "CEO"}, + {"name": "Benjamin Clavié", "role": "AI Researcher"}, + {"name": "Alexis Gallagher", "role": "ML Engineer"}, + {"name": "Hamel Husain", "role": "Data Scientist"}, + {"name": "Austin Huang", "role": "Software Engineer"}, + {"name": "Benjamin Warner", "role": "Product Manager"}, + {"name": "Jonathan Whitaker", "role": "UX Designer"}, + {"name": "Kerem Turgutlu", "role": "DevOps Engineer"}, + {"name": "Curtis Allan", "role": "DevOps Engineer"}, + {"name": "Audrey Roy Greenfeld", "role": "Security Analyst"}, + {"name": "Nathan Cooper", "role": "Full Stack Developer"}, + {"name": "Jeremy Howard", "role": "CTO"}, + {"name": "Wayde Gilliam", "role": "Cloud Architect"}, + {"name": "Daniel Roy Greenfeld", "role": "Blockchain Expert"}, + {"name": "Tommy Collins", "role": "AI Ethics Researcher"} +] + + +def ProductCard(p,img_id=1): + return Card( + PicSumImg(w=500, height=100, id=img_id), + DivFullySpaced(H4(p["name"]), P(Strong(p["price"], cls=TextT.sm))), + Button("Details", cls=(ButtonT.primary, "w-full"))) + +def TestimonialCard(t,img_id=1): + return Card( + DivLAligned(PicSumImg(w=50, h=50, cls='rounded-full', id=img_id), H4(t["name"])), + P(Q((t["feedback"])))) + + +def TeamCard(m,img_id=1): + return Card( + DivLAligned( + PicSumImg(w=50, h=50, cls='rounded-full', id=img_id), + Div(H4(m["name"]), P(m["role"]))), + DivRAligned( + UkIcon('twitter', cls='w-5 h-5'), + UkIcon('linkedin', cls='w-5 h-5'), + UkIcon('github', cls='w-5 h-5'), + cls=TextT.gray+'space-x-2' + ), + cls='p-3') + +################################ +### Navigation and Scrollspy ### +################################ + +scrollspy_links = ( + A("Welcome", href="#welcome-section"), + A("Products", href="#products-section"), + A("Testimonials", href="#testimonials-section"), + A("Team", href="#team-section"), + A("Code Example", href="#code-section")) +@rt +def index(): + def _Section(*c, **kwargs): return Section(*c, cls='space-y-3 my-48',**kwargs) + return Container( + NavBar( + *scrollspy_links, + brand=DivLAligned(H3("Scrollspy Demo!"),UkIcon('rocket',height=30,width=30)), + sticky=True, uk_scrollspy_nav=True, + scrollspy_cls=ScrollspyT.bold), + NavContainer( + *map(Li, scrollspy_links), + uk_scrollspy_nav=True, + sticky=True, + cls=(NavT.primary,'pt-20 px-5 pr-10')), + Container( + # Notice the ID of each section corresponds to the `scrollspy_links` dictionary + # So in scollspy `NavContainer` the `href` of each `Li` is the ID of the section + DivCentered( + H1("Welcome to the Store!"), + Subtitle("Explore our products and enjoy dynamic code examples."), + id="welcome-section"), + _Section(H2("Products"), + Grid(*[ProductCard(p,img_id=i) for i,p in enumerate(products)], cols_lg=2), + id="products-section"), + _Section(H2("Testimonials"), + Slider(*[TestimonialCard(t,img_id=i) for i,t in enumerate(testimonials)]), + id="testimonials-section"), + _Section(H2("Our Team"), + Grid(*[TeamCard(m,img_id=i) for i,m in enumerate(team)], cols_lg=2, cols_max=3), + id="team-section"), + _Section(H2("Code Example"), + CodeBlock(code_example, lang="python"), + id="code-section")), + cls=(ContainerT.xl,'uk-container-expand')) + +serve()"""MonsterUI Help Desk Example - Professional Dashboard with DaisyUI components""" +from fasthtml.common import * +from monsterui.all import * +from datetime import datetime + +app, rt = fast_app(hdrs=Theme.blue.headers(daisy=True)) + +def TicketSteps(step): + return Steps( + LiStep("Submitted", data_content="📝", + cls=StepT.success if step > 0 else StepT.primary if step == 0 else StepT.neutral), + LiStep("In Review", data_content="🔎", + cls=StepT.success if step > 1 else StepT.primary if step == 1 else StepT.neutral), + LiStep("Processing", data_content="⚙️", + cls=StepT.success if step > 2 else StepT.primary if step == 2 else StepT.neutral), + LiStep("Resolved", data_content="✅", + cls=StepT.success if step > 3 else StepT.primary if step == 3 else StepT.neutral), + cls="w-full") + +def StatusBadge(status): + styles = {'high': AlertT.error, 'medium': AlertT.warning,'low': AlertT.info} + alert_type = styles.get(status, AlertT.info) + return Alert(f"{status.title()} Priority", cls=(alert_type,"w-32 shadow-sm")) + +def TicketCard(id, title, description, status, step, department): + return Card( + CardHeader( + DivFullySpaced( + Div(H3(f"#{id}", cls=TextT.muted), + H4(title), + cls='space-y-2'), + StatusBadge(status))), + CardBody( + P(description, cls=(TextT.muted, "mb-6")), + DividerSplit(cls="my-6"), + TicketSteps(step), + DividerSplit(cls="my-6"), + DivFullySpaced( + Div(Strong("Department"), + P(department), + cls=('space-y-3', TextPresets.muted_sm)), + Div(Strong("Last Updated"), + P(Time(datetime.now().strftime('%b %d, %H:%M'))), + cls=('space-y-3', TextPresets.muted_sm)), + Button("View Details", cls=ButtonT.primary), + cls='mt-6')), + cls=CardT.hover) + +def NewTicketModal(): + return Modal( + ModalHeader(H3("Create New Support Ticket")), + ModalBody( + Alert( + DivLAligned(UkIcon("info"), Span("Please provide as much detail as possible to help us assist you quickly.")), + cls=(AlertT.info,"mb-4")), + Form( + Grid(LabelInput("Title", id="title", placeholder="Brief description of your issue"), + LabelSelect(Options("IT Support", "HR", "Facilities", "Finance"), label="Department", id="department")), + LabelSelect(Options("Low", "Medium", "High"), label="Priority Level", id="priority"), + LabelTextArea("Description", id="description", placeholder="Please provide detailed information about your issue"), + DivRAligned( + Button("Cancel", cls=ButtonT.ghost, data_uk_toggle="target: #new-ticket"), + Button(Loading(cls=LoadingT.spinner), "Submit Ticket", cls=ButtonT.primary, data_uk_toggle="target: #success-toast; target: #new-ticket")), + cls='space-y-8')), + id="new-ticket") + +@rt +def index(): + tickets = [ + {'id': "TK-1001", 'title': "Cloud Storage Access Error", + 'description': "Unable to access cloud storage with persistent authorization errors. Multiple users affected across marketing department.", + 'status': 'high', 'step': 2, 'department': 'IT Support'}, + {'id': "TK-1002", 'title': "Email Integration Issue", + 'description': "Exchange server not syncing with mobile devices. Affecting external client communications.", + 'status': 'medium', 'step': 1, 'department': 'IT Support'}, + {'id': "TK-1003", 'title': "Office Equipment Setup", + 'description': "New department printer needs configuration and network integration. Required for upcoming client presentation.", + 'status': 'low', 'step': 0, 'department': 'Facilities'} + ] + + return Title("Help Desk Dashboard"), Container( + Section( + DivFullySpaced( + H2("Active Tickets"), + Button(UkIcon("plus-circle", cls="mr-2"), "New Ticket", cls=ButtonT.primary, data_uk_toggle="target: #new-ticket"), + cls='mb-8'), + Grid(*[TicketCard(**ticket) for ticket in tickets], cols=1), + cls="my-6"), + NewTicketModal(), + Toast(DivLAligned(UkIcon('check-circle', cls='mr-2'), "Ticket submitted successfully! Our team will review it shortly."), id="success-toast", alert_cls=AlertT.success, cls=(ToastHT.end, ToastVT.bottom)), + Loading(htmx_indicator=True, type=LoadingT.dots, cls="fixed top-0 right-0 m-4"), + cls="mx-auto max-w-7xl" + ) + +serve()"""FrankenUI Playground Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +preset_options = ["Grammatical Standard English", "Summarize for a 2nd grader", + "Text to command","Q&A","English to other languages","Parse unstructured data", + "Classification","Natural language to Python","Explain code","Chat","More examples"] + +def playground_navbar(): + save_modal = Modal( + ModalTitle("Save preset"), + P("This will save the current playground state as a preset which you can access later or share with others.",cls=("mt-1.5", TextPresets.muted_sm)), + LabelInput("Name", id="name"), + LabelInput("Description", id="description"), + ModalCloseButton("Save", cls=ButtonT.primary), + id="save") + + share_dd = Div(cls="space-y-6 p-4")( + H3("Share preset"), + P("Anyone who has this link and an OpenAI account will be able to view this.", cls=TextPresets.muted_sm), + Div(Input(value="https://platform.openai.com/playground/p/7bbKYQvsVkNmVb8NGcdUOLae?model=text-davinci-003", readonly=True), + Button(UkIcon('copy'), cls=(ButtonT.primary, "uk-drop-close",'mt-4')))) + + rnav = ( + Select(*Options(*preset_options), name='preset', optgroup_label="Examples", + placeholder='Load a preset', searchable=True, cls='h-9 w-[200px] lg:w-[300px]'), + Button("Save", cls=ButtonT.secondary, data_uk_toggle="#save"),save_modal, + Button("View Code", cls=ButtonT.secondary), + Button("Share", cls=ButtonT.secondary),DropDownNavContainer(share_dd), + Button(UkIcon(icon="ellipsis"), cls=ButtonT.secondary), + DropDownNavContainer( + Li(A("Content filter preferences")), + NavDividerLi(), + Li(A("Delete preset", cls="text-destructive")), + uk_dropdown="mode: click")) + + return NavBar(*rnav, brand=H4('Playground')) + +rsidebar = NavContainer( + Select( + Optgroup(map(Option,("text-davinci-003", "text-curie-001", "text-babbage-001", "text-ada-001")),label='GPT-3'), + Optgroup(map(Option,("code-davinci-002", "code-cushman-001")),label='Codex'), + label="Model", + searchable=True), + LabelRange(label='Temperature', value='12'), + LabelRange(label='Maximum Length', value='80'), + LabelRange(label='Top P', value='40'), + cls='space-y-6 mt-8') + +@rt +def index(): + navbar = playground_navbar() + main_content = Div( + Div(cls="flex-1")( + Textarea(cls="uk-textarea h-full p-4", placeholder="Write a tagline for an ice cream shop")), + cls="flex h-[700px] p-8 w-4/5") + + bottom_buttons = Div( + Button("Submit", cls=ButtonT.primary), + Button(UkIcon(icon="history"), cls=ButtonT.secondary), + cls="flex gap-x-2") + + return Title("Playground Example"),Div(navbar, Div(cls="flex w-full")(main_content, rsidebar), bottom_buttons) + +serve()"""FrankenUI Mail Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * +import pathlib, json +from datetime import datetime + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +sidebar_group1 = (('home', 'Inbox', '128'), ('file-text', 'Drafts', '9'), (' arrow-up-right', 'Sent', ''), + ('ban', 'Junk', '23'), ('trash', 'Trash', ''), ('folder', 'Archive', '')) + +sidebar_group2 = (('globe','Social','972'),('info','Updates','342'),('messages-square','Forums','128'), + ('shopping-cart','Shopping','8'),('shopping-bag','Promotions','21'),) + +def MailSbLi(icon, title, cnt): + return Li(A(DivLAligned(Span(UkIcon(icon)),Span(title),P(cnt, cls=TextPresets.muted_sm)),href='#', cls='hover:bg-secondary p-4')) + +sidebar = NavContainer( + NavHeaderLi(H3("Email"), cls='p-3'), + Li(Select(map(Option, ('alicia@example.com','alicia@gmail.com', 'alicia@yahoo.com')))), + *[MailSbLi(i, t, c) for i, t, c in sidebar_group1], + Li(Hr()), + *[MailSbLi(i, t, c) for i, t, c in sidebar_group2], + cls='mt-3') + +mail_data = json.load(open(pathlib.Path('data_/mail.json'))) + +def format_date(date_str): + date_obj = datetime.fromisoformat(date_str) + return date_obj.strftime("%Y-%m-%d %I:%M %p") + +def MailItem(mail): + cls_base = 'relative rounded-lg border border-border p-3 text-sm hover:bg-secondary space-y-2' + cls = f"{cls_base} {'bg-muted' if mail == mail_data[0] else ''} {'tag-unread' if not mail['read'] else 'tag-mail'}" + + return Li( + DivFullySpaced( + DivLAligned( + Strong(mail['name']), + Span(cls='flex h-2 w-2 rounded-full bg-blue-600') if not mail['read'] else ''), + Time(format_date(mail['date']), cls='text-xs')), + Small(mail['subject'], href=f"#mail-{mail['id']}"), + Div(mail['text'][:100] + '...', cls=TextPresets.muted_sm), + DivLAligned( + *[Label(A(label, href='#'), cls='uk-label-primary' if label == 'work' else '') for label in mail['labels']]), + cls=cls) + +def MailList(mails): return Ul(cls='js-filter space-y-2 p-4 pt-0')(*[MailItem(mail) for mail in mails]) + +def MailContent(): + return Div(cls='flex flex-col',uk_filter="target: .js-filter")( + Div(cls='flex px-4 py-2 ')( + H3('Inbox'), + TabContainer(Li(A("All Mail",href='#', role='button'),cls='uk-active', uk_filter_control="filter: .tag-mail"), + Li(A("Unread",href='#', role='button'), uk_filter_control="filter: .tag-unread"), + alt=True, cls='ml-auto max-w-40', )), + Div(cls='flex flex-1 flex-col')( + Div(cls='p-4')( + Div(cls='uk-inline w-full')( + Span(cls='uk-form-icon text-muted-foreground')(UkIcon('search')), + Input(placeholder='Search'))), + Div(cls='flex-1 overflow-y-auto max-h-[600px]')(MailList(mail_data)))) + +def IconNavItem(*d): return [Li(A(UkIcon(o[0],uk_tooltip=o[1]))) for o in d] +def IconNav(*c,cls=''): return Ul(cls=f'uk-iconnav {cls}')(*c) + +def MailDetailView(mail): + top_icons = [('folder','Archive'), ('ban','Move to junk'), ('trash','Move to trash')] + reply_icons = [('reply','Reply'), ('reply','Reply all'), ('forward','Forward')] + dropdown_items = ['Mark as unread', 'Star read', 'Add Label', 'Mute Thread'] + + return Container( + DivFullySpaced( + DivLAligned( + DivLAligned(*[UkIcon(o[0],uk_tooltip=o[1]) for o in top_icons]), + Div(UkIcon('clock', uk_tooltip='Snooze'), cls='pl-2'), + cls='space-x-2 divide-x divide-border'), + DivLAligned( + *[UkIcon(o[0],uk_tooltip=o[1]) for o in reply_icons], + Div(UkIcon('ellipsis-vertical',button=True)), + DropDownNavContainer(*map(lambda x: Li(A(x)), dropdown_items)))), + DivLAligned( + Span(mail['name'][:2], cls='flex h-10 w-10 items-center justify-center rounded-full bg-muted'), + Div(Strong(mail['name']), + Div(mail['subject']), + DivLAligned(P('Reply-To:'), A(mail['email'], href=f"mailto:{mail['email']}"), cls='space-x-1'), + P(Time(format_date(mail['date']))), + cls='space-y-1'+TextT.sm), + cls='m-4 space-x-4'), + DividerLine(), + P(mail['text'], cls=TextT.sm +'p-4'), + DividerLine(), + Div(TextArea(id='message', placeholder=f"Reply {mail['name']}"), + DivFullySpaced( + LabelSwitch('Mute this thread',id='mute'), + Button('Send', cls=ButtonT.primary)), + cls='space-y-4')) + +@rt +def index(): + return Title("Mail Example"),Container( + Grid(Div(sidebar, cls='col-span-1'), + Div(MailContent(), cls='col-span-2'), + Div(MailDetailView(mail_data[0]), cls='col-span-2'), + cols_sm=1, cols_md=1, cols_lg=5, cols_xl=5, + gap=0, cls='flex-1'), + cls=('flex', ContainerT.xl)) + +serve()"""FrankenUI Tasks Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * +import json + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def LAlignedCheckTxt(txt): return DivLAligned(UkIcon(icon='check'), P(txt, cls=TextPresets.muted_sm)) + +with open('data_/status_list.json', 'r') as f: data = json.load(f) +with open('data_/statuses.json', 'r') as f: statuses = json.load(f) + +def _create_tbl_data(d): + return {'Done': d['selected'], 'Task': d['id'], 'Title': d['title'], + 'Status' : d['status'], 'Priority': d['priority'] } + +data = [_create_tbl_data(d) for d in data] +page_size = 15 +current_page = 0 +paginated_data = data[current_page*page_size:(current_page+1)*page_size] + +priority_dd = [{'priority': "low", 'count': 36 }, {'priority': "medium", 'count': 33 }, {'priority': "high", 'count': 31 }] + +status_dd = [{'status': "backlog", 'count': 21 },{'status': "todo", 'count': 21 },{'status': "progress", 'count': 20 },{'status': "done",'count': 19 },{'status': "cancelled", 'count': 19 }] + +def create_hotkey_li(hotkey): return NavCloseLi(A(DivFullySpaced(hotkey[0], Span(hotkey[1], cls=TextPresets.muted_sm)))) + +hotkeys_a = (('Profile','⇧⌘P'),('Billing','⌘B'),('Settings','⌘S'),('New Team','')) +hotkeys_b = (('Logout',''), ) + +avatar_opts = DropDownNavContainer( + NavHeaderLi(P('sveltecult'),NavSubtitle('leader@sveltecult.com')), + NavDividerLi(), + *map(create_hotkey_li, hotkeys_a), + NavDividerLi(), + *map(create_hotkey_li, hotkeys_b),) + +def CreateTaskModal(): + return Modal( + Div(cls='p-6')( + ModalTitle('Create Task'), + P('Fill out the information below to create a new task', cls=TextPresets.muted_sm), + Br(), + Form(cls='space-y-6')( + Grid(Div(Select(*map(Option,('Documentation', 'Bug', 'Feature')), label='Task Type', id='task_type')), + Div(Select(*map(Option,('In Progress', 'Backlog', 'Todo', 'Cancelled', 'Done')), label='Status', id='task_status')), + Div(Select(*map(Option, ('Low', 'Medium', 'High')), label='Priority', id='task_priority'))), + TextArea(label='Title', placeholder='Please describe the task that needs to be completed'), + DivRAligned( + ModalCloseButton('Cancel', cls=ButtonT.ghost), + ModalCloseButton('Submit', cls=ButtonT.primary), + cls='space-x-5'))), + id='TaskForm') + +page_heading = DivFullySpaced(cls='space-y-2')( + Div(cls='space-y-2')( + H2('Welcome back!'),P("Here's a list of your tasks for this month!", cls=TextPresets.muted_sm)), + Div(DiceBearAvatar("sveltcult",8,8),avatar_opts)) + +table_controls =(Input(cls='w-[250px]',placeholder='Filter task'), + Button("Status"), + DropDownNavContainer(map(NavCloseLi,[A(DivFullySpaced(P(a['status']), P(a['count'])),cls='capitalize') for a in status_dd])), + Button("Priority"), + DropDownNavContainer(map(NavCloseLi,[A(DivFullySpaced(LAlignedCheckTxt(a['priority']), a['count']),cls='capitalize') for a in priority_dd])), + Button("View"), + DropDownNavContainer(map(NavCloseLi,[A(LAlignedCheckTxt(o)) for o in ['Title','Status','Priority']])), + Button('Create Task',cls=(ButtonT.primary, TextPresets.bold_sm), data_uk_toggle="target: #TaskForm")) + +def task_dropdown(): + return Div(Button(UkIcon('ellipsis')), + DropDownNavContainer( + map(NavCloseLi,[ + *map(A,('Edit', 'Make a copy', 'Favorite')), + A(DivFullySpaced(*[P(o, cls=TextPresets.muted_sm) for o in ('Delete', '⌘⌫')]))]))) +def header_render(col): + match col: + case "Done": return Th(CheckboxX(), shrink=True) + case 'Actions': return Th("", shrink=True) + case _: return Th(col, expand=True) + +def cell_render(col, val): + def _Td(*args,cls='', **kwargs): return Td(*args, cls=f'p-2 {cls}',**kwargs) + match col: + case "Done": return _Td(shrink=True)(CheckboxX(selected=val)) + case "Task": return _Td(val, cls='uk-visible@s') # Hide on small screens + case "Title": return _Td(val, cls='font-medium', expand=True) + case "Status" | "Priority": return _Td(cls='uk-visible@m uk-text-nowrap capitalize')(Span(val)) + case "Actions": return _Td(task_dropdown(), shrink=True) + case _: raise ValueError(f"Unknown column: {col}") + +task_columns = ["Done", 'Task', 'Title', 'Status', 'Priority', 'Actions'] + +tasks_table = Div(cls='mt-4')( + TableFromDicts( + header_data=task_columns, + body_data=paginated_data, + body_cell_render=cell_render, + header_cell_render=header_render, + sortable=True, + cls=(TableT.responsive, TableT.sm, TableT.divider))) + + +def footer(): + total_pages = (len(data) + page_size - 1) // page_size + return DivFullySpaced( + Div('1 of 100 row(s) selected.', cls=TextPresets.muted_sm), + DivLAligned( + DivCentered(f'Page {current_page + 1} of {total_pages}', cls=TextT.sm), + DivLAligned(*[UkIconLink(icon=i, button=True) for i in ('chevrons-left', 'chevron-left', 'chevron-right', 'chevrons-right')]))) + +tasks_ui = Div(DivFullySpaced(DivLAligned(table_controls), cls='mt-8'), tasks_table, footer()) + +@rt +def index(): return Container(page_heading, tasks_ui, CreateTaskModal()) + +serve()"""FrankenUI Music Example build with MonsterUI (Original design by ShadCN)""" + +from fasthtml.common import * + +from monsterui.all import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +def MusicLi(t,hk=''): return Li(A(DivFullySpaced(t,P(hk,cls=TextPresets.muted_sm)))) + +music_items = [("About Music", "" ), + ("Preferences", "⌘" ), + ("Hide Music" , "⌘H" ), + ("Hide Others", "⇧⌘H"), + ("Quit Music" , "⌘Q" )] + +file_dd_items = [("New", ""), + ("Open Stream URL", "⌘U"), + ("Close Window", "⌘W"), + ("Library", ""), + ("Import", "⌘O"), + ("Burn Playlist to Disc", ""), + ("Show in Finder", "⇧⌘R"), + ("Convert", ""), + ("Page Setup", "Print")] + +edit_actions = [("Undo", "⌘Z"), + ("Redo", "⇧⌘Z"), + ("Cut", "⌘X"), + ("Copy", "⌘C"), + ("Paste", "⌘V"), + ("Select All", "⌘A"), + ("Deselect All", "⇧⌘A")] + +view_dd_data = ["Show Playing Next", "Show Lyrics", "Show Status Bar", "Hide Sidebar", "Enter Full Screen"] + + +music_headers = NavBar( + Button("Music", cls=ButtonT.ghost+TextT.gray),DropDownNavContainer(Li(A("Music"),NavContainer(map(lambda x: MusicLi(*x), music_items)))), + Button("File", cls=ButtonT.ghost+TextT.gray), DropDownNavContainer(Li(A("File"), NavContainer(map(lambda x: MusicLi(*x), file_dd_items)))), + Button("Edit", cls=ButtonT.ghost+TextT.gray), DropDownNavContainer(Li(A("Edit")),NavContainer( + *map(lambda x: MusicLi(*x), edit_actions), + Li(A(DivFullySpaced("Smart Dictation",UkIcon("mic")))), + Li(A(DivFullySpaced("Emojis & Symbols",UkIcon("globe")))))), + Button("View", cls=ButtonT.ghost+TextT.gray),DropDownNavContainer(Li(A("View"),NavContainer(map(lambda x: MusicLi(x), view_dd_data)))), + brand=DivLAligned(H2("Purrify")) + ) + + + + +# music_headers = NavBarContainer( +# NavBarLSide( +# NavBarNav( +# Li(A("Music"),NavBarNavContainer(map(lambda x: MusicLi(*x), music_items))), +# Li(A("File"), NavBarNavContainer(map(lambda x: MusicLi(*x), file_dd_items))), +# Li(A("Edit")), +# NavBarNavContainer( +# *map(lambda x: MusicLi(*x), edit_actions), +# Li(A(DivFullySpaced("Smart Dictation",UkIcon("mic")))), +# Li(A(DivFullySpaced("Emojis & Symbols",UkIcon("globe"))))), +# Li(A("View"), +# NavBarNavContainer(map(lambda x: MusicLi(x), view_dd_data))), +# Li(A("Account"), +# NavBarNavContainer( +# NavHeaderLi("Switch Account"), +# *map(MusicLi, ("Andy", "Benoit", "Luis", "Manage Family", "Add Account"))))))) + + +def Album(title,artist): + img_url = 'https://ucarecdn.com/e5607eaf-2b2a-43b9-ada9-330824b6afd7/music1.webp' + return Div( + Div(cls="overflow-hidden rounded-md")(Img(cls="transition-transform duration-200 hover:scale-105", src=img_url)), + Div(cls='space-y-1')(Strong(title),P(artist,cls=TextT.muted))) + +listen_now_albums = (("Roar", "Catty Perry"), ("Feline on a Prayer", "Cat Jovi"),("Fur Elise", "Ludwig van Beethovpurr"),("Purrple Rain", "Prince's Cat")) + +made_for_you_albums = [("Like a Feline", "Catdonna"), + ("Livin' La Vida Purrda", "Ricky Catin"), + ("Meow Meow Rocket", "Elton Cat"), + ("Rolling in the Purr", "Catdelle"), + ("Purrs of Silence", "Cat Garfunkel"), + ("Meow Me Maybe", "Carly Rae Purrsen"),] + +music_content = (Div(H3("Listen Now"), cls="mt-6 space-y-1"), + Subtitle("Top picks for you. Updated daily."), + DividerLine(), + Grid(*[Album(t,a) for t,a in listen_now_albums], cls='gap-8'), + Div(H3("Made for You"), cls="mt-6 space-y-1"), + Subtitle("Your personal playlists. Updated daily."), + DividerLine(), + Grid(*[Album(t,a) for t,a in made_for_you_albums], cols_xl=6)) + +tabs = TabContainer( + Li(A('Music', href='#'), cls='uk-active'), + Li(A('Podcasts', href='#')), + Li(A('Live', cls='opacity-50'), cls='uk-disabled'), + uk_switcher='connect: #component-nav; animation: uk-animation-fade', + alt=True) + +def podcast_tab(): + return Div( + Div(cls='space-y-3 mt-6')( + H3("New Episodes"), + Subtitle("Your favorite podcasts. Updated daily.")), + Div(cls="uk-placeholder flex h-[450px] items-center justify-center rounded-md mt-4",uk_placeholder=True)( + DivVStacked(cls="space-y-6")( + UkIcon("microphone", 3), + H4("No episodes added"), + Subtitle("You have not added any podcasts. Add one below."), + Button("Add Podcast", cls=ButtonT.primary)))) + +discoved_data = [("play-circle","Listen Now"), ("binoculars", "Browse"), ("rss","Radio")] +library_data = [("play-circle", "Playlists"), ("music", "Songs"), ("user", "Made for You"), ("users", "Artists"), ("bookmark", "Albums")] +playlists_data = [("library","Recently Added"), ("library","Recently Played")] + +def MusicSidebarLi(icon, text): return Li(A(DivLAligned(UkIcon(icon), P(text)))) +sidebar = NavContainer( + NavHeaderLi(H3("Discover")), *[MusicSidebarLi(*o) for o in discoved_data], + NavHeaderLi(H3("Library")), *[MusicSidebarLi(*o) for o in library_data], + NavHeaderLi(H3("Playlists")),*[MusicSidebarLi(*o) for o in playlists_data], + cls=(NavT.primary,'space-y-3','pl-8')) + +@rt +def index(): + return Title("Music Example"),Container(music_headers, DividerSplit(), + Grid(sidebar, + Div(cls="col-span-4 border-l border-border")( + Div(cls="px-8 py-6")( + DivFullySpaced( + Div(cls="max-w-80")(tabs), + Button(cls=ButtonT.primary)(DivLAligned(UkIcon('circle-plus')),Div("Add music"))), + Ul(id="component-nav", cls="uk-switcher")( + Li(*music_content), + Li(podcast_tab())))), + cols_sm=1, cols_md=1, cols_lg=5, cols_xl=5)) + +serve()"""FrankenUI Auth Example built with MonsterUI (original design by ShadCN)""" + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.svg import * + +app, rt = fast_app(hdrs=Theme.blue.headers()) + +@rt +def index(): + left = Div(cls="col-span-1 hidden flex-col justify-between bg-zinc-900 p-8 text-white lg:flex")( + Div(cls=(TextT.bold))("Acme Inc"), + Blockquote(cls="space-y-2")( + P(cls=TextT.lg)('"This library has saved me countless hours of work and helped me deliver stunning designs to my clients faster than ever before."'), + Footer(cls=TextT.sm)("Sofia Davis"))) + + right = Div(cls="col-span-2 flex flex-col p-8 lg:col-span-1")( + DivRAligned(Button("Login", cls=ButtonT.ghost)), + DivCentered(cls='flex-1')( + Container( + DivVStacked( + H3("Create an account"), + Small("Enter your email below to create your account", cls=TextT.muted)), + Form( + Input(placeholder="name@example.com"), + Button(Span(cls="mr-2", uk_spinner="ratio: 0.54"), "Sign in with Email", cls=(ButtonT.primary, "w-full"), disabled=True), + DividerSplit(Small("Or continue with"),cls=TextT.muted), + Button(UkIcon('github',cls='mr-2'), "Github", cls=(ButtonT.default, "w-full")), + cls='space-y-6'), + DivVStacked(Small( + "By clicking continue, you agree to our ", + A(cls=AT.muted, href="#demo")("Terms of Service")," and ", + A(cls=AT.muted, href="#demo")("Privacy Policy"),".", + cls=(TextT.muted,"text-center"))), + cls="space-y-6"))) + + return Title("Auth Example"),Grid(left,right,cols=2, gap=0,cls='h-screen') + + +serve() diff --git a/MonsterUI/docs/llms.txt b/MonsterUI/docs/llms.txt new file mode 100644 index 0000000000000000000000000000000000000000..e97811a766fd681a74290b557cf0b2e72200d828 --- /dev/null +++ b/MonsterUI/docs/llms.txt @@ -0,0 +1,44 @@ +# MonsterUI Documentation + +> MonsterUI is a python library which brings styling to python for FastHTML apps. + +## API Reference +- [API List](https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/apilist.txt): Complete API Reference + +## Examples +- [Cards](https://monsterui.answer.ai/cards/md): FrankenUI Cards Example built with MonsterUI (original design by ShadCN) +- [Dashboard](https://monsterui.answer.ai/dashboard/md): FrankenUI Dashboard Example built with MonsterUI (original design by ShadCN) +- [Forms](https://monsterui.answer.ai/forms/md): FrankenUI Forms Example built with MonsterUI (original design by ShadCN) +- [Scrollspy](https://monsterui.answer.ai/scrollspy/md): MonsterUI Scrollspy Example application +- [Ticket](https://monsterui.answer.ai/ticket/md): MonsterUI Help Desk Example - Professional Dashboard with DaisyUI components +- [Playground](https://monsterui.answer.ai/playground/md): FrankenUI Playground Example built with MonsterUI (original design by ShadCN) +- [Mail](https://monsterui.answer.ai/mail/md): FrankenUI Mail Example built with MonsterUI (original design by ShadCN) +- [Tasks](https://monsterui.answer.ai/tasks/md): FrankenUI Tasks Example built with MonsterUI (original design by ShadCN) +- [Music](https://monsterui.answer.ai/music/md): FrankenUI Music Example build with MonsterUI (Original design by ShadCN) +- [Auth](https://monsterui.answer.ai/auth/md): FrankenUI Auth Example built with MonsterUI (original design by ShadCN) + +## Optional +- [Accordion | Link](https://monsterui.answer.ai/api_ref/docs_accordion_link/md): Accordion API Reference +- [Button | Link](https://monsterui.answer.ai/api_ref/docs_button_link/md): Buttons & Links API Reference +- [Cards](https://monsterui.answer.ai/api_ref/docs_cards/md): Cards API Reference +- [Charts](https://monsterui.answer.ai/api_ref/docs_charts/md): Charts API Reference +- [Containers](https://monsterui.answer.ai/api_ref/docs_containers/md): Articles, Containers & Sections API Reference +- [Dividers](https://monsterui.answer.ai/api_ref/docs_dividers/md): Dividers API Reference +- [Forms](https://monsterui.answer.ai/api_ref/docs_forms/md): Forms and User Inputs API Reference +- [Html](https://monsterui.answer.ai/api_ref/docs_html/md): HTML Styling API Reference +- [Icons | Images](https://monsterui.answer.ai/api_ref/docs_icons_images/md): Icons & Images API Reference +- [Layout](https://monsterui.answer.ai/api_ref/docs_layout/md): Layout (Flex and Grid) API Reference +- [Lightbox](https://monsterui.answer.ai/api_ref/docs_lightbox/md): Lightbox API Reference +- [Lists](https://monsterui.answer.ai/api_ref/docs_lists/md): Lists API Reference +- [Loading](https://monsterui.answer.ai/api_ref/docs_loading/md): Loading Indicators API Reference +- [Markdown](https://monsterui.answer.ai/api_ref/docs_markdown/md): Markdown + automated HTML styling API Reference +- [Modals](https://monsterui.answer.ai/api_ref/docs_modals/md): Modals API Reference +- [Navigation](https://monsterui.answer.ai/api_ref/docs_navigation/md): Navigation (Nav, NavBar, Tabs, etc.) API Reference +- [Notifications](https://monsterui.answer.ai/api_ref/docs_notifications/md): Alerts & Toasts API Reference +- [Sliders](https://monsterui.answer.ai/api_ref/docs_sliders/md): Carousel Sliders API Reference +- [Steps](https://monsterui.answer.ai/api_ref/docs_steps/md): Steps API Reference +- [Tables](https://monsterui.answer.ai/api_ref/docs_tables/md): Tables API Reference +- [Theme | Headers](https://monsterui.answer.ai/api_ref/docs_theme_headers/md): Theme and Headers API Reference +- [Typography](https://monsterui.answer.ai/api_ref/docs_typography/md): Typography API Reference +- [Layout](https://monsterui.answer.ai/tutorial_layout/md): MonsterUI Page Layout Guide +- [Spacing](https://monsterui.answer.ai/tutorial_spacing/md): Padding & Margin & Spacing, Oh my! (MonsterUI Spacing Guide) \ No newline at end of file diff --git a/MonsterUI/docs/main.py b/MonsterUI/docs/main.py new file mode 100644 index 0000000000000000000000000000000000000000..8c45f99350026b80c870ad8762139dbadf9913a1 --- /dev/null +++ b/MonsterUI/docs/main.py @@ -0,0 +1,266 @@ +from fasthtml.common import * +from functools import partial +from monsterui.all import * +from fasthtml.components import Uk_theme_switcher +from utils import render_nb +from pathlib import Path +from toolslm.download import read_html,html2md +from starlette.responses import PlainTextResponse +import httpx + +def _not_found(req, exc): + _path = req.url.path.rstrip('/') + if _path.endswith('.md') or _path.endswith('.rmd'): + url = f'https://monsterui.answer.ai{_path[:-3].rstrip("/").rstrip(".")}'.rstrip("/").rstrip(".") + try: + r = httpx.head(url, follow_redirects=True, timeout=1.0) + if r.status_code < 400: # Accept 2xx and 3xx status codes + if _path.endswith('.rmd') or _path.endswith('/rmd'): return Container(render_md(read_html(url, sel='#content'))) + elif _path.endswith('.md') or _path.endswith('/md'): return PlainTextResponse(read_html(url, sel='#content')) + except (httpx.TimeoutException, httpx.NetworkError): pass + return _create_page( + Container(Card(CardBody(H1("404 - Page Not Found"), P("The page you're looking for doesn't exist.")))), + req, + None) + + +app,rt = fast_app(exception_handlers={404:_not_found}, pico=False, + hdrs=(*Theme.blue.headers(highlightjs=True,apex_charts=True), Link(rel="icon", type="image/x-icon", href="/favicon.ico"), + Link(rel="stylesheet", href="/custom_theme.css", type="text/css")), + ) + +def is_htmx(request=None): + "Check if the request is an HTMX request" + return request and 'hx-request' in request.headers + +def _create_page(content, # The content to display (without the layout/sidebar) + request, # Request object to determine if HTMX request + sidebar_section, # The open section on the sidebar + ): + "Makes page load sidebar if direct request, otherwise loads content only via HTMX" + if is_htmx(request): return content + else: return with_layout(sidebar_section, content) + +def with_layout(sidebar_section, content): + "Puts the sidebar and content into a layout" + return Title(f"MonsterUI"), Div(cls="flex flex-col md:flex-row w-full")( + Button(UkIcon("menu",50,50,cls='mt-4'), cls="md:hidden mb-4", data_uk_toggle="target: #mobile-sidebar"), + Div(sidebar(sidebar_section), id='mobile-sidebar', hidden=True), + Div(cls="md:flex w-full")( + Div(sidebar(sidebar_section), cls="hidden md:block w-1/5 max-w-52"), + Div(content, cls='md:w-4/5 w-full mr-5', id="content", ))) + + +### +# Build the Example Pages +### + +from examples.tasks import index as tasks_homepage +from examples.cards import index as cards_homepage +from examples.dashboard import index as dashboard_homepage +from examples.forms import index as forms_homepage +from examples.music import index as music_homepage +from examples.auth import index as auth_homepage +from examples.playground import index as playground_homepage +from examples.mail import index as mail_homepage +from examples.scrollspy import index as scrollspy_homepage +from examples.ticket import index as ticket_homepage +def _example_route(name, homepage, o:str, request=None): + match o: + case 'code' | 'rmd': return Div(render_md(f'''```python\n\n{open(f'examples/{name}.py').read()}\n\n```''')) + case 'md': return PlainTextResponse(open(f'examples/{name}.py').read()) + case _: return _create_example_page(homepage, request) + +_create_example_page = partial(_create_page, sidebar_section='Examples') + +@rt('/scrollspy') +@rt('/scrollspy/{o}') +def scrollspy(o:str='', request=None): return _example_route('scrollspy', Div(DivRAligned(A("See Code",href='/scrollspy/code',cls='m-4 uk-btn'+ButtonT.default)),scrollspy_homepage()), o, request) + +@rt('/ticket') +@rt('/ticket/{o}') +def ticket(o:str='', request=None): return _example_route('ticket', Div(DivRAligned(A("See Code",href='/ticket/code',cls='m-4 uk-btn'+ButtonT.default)),ticket_homepage()), o, request) + +@rt('/tasks') +@rt('/tasks/{o}') +def tasks(o:str='', request=None): return _example_route('tasks', Div(DivRAligned(A("See Code",href='/tasks/code',cls='m-4 uk-btn'+ButtonT.default)),tasks_homepage()), o, request) + +@rt('/cards') +@rt('/cards/{o}') +def cards(o:str, request=None): return _example_route('cards', Div(DivRAligned(A("See Code",href='/cards/code',cls='m-4 uk-btn'+ButtonT.default)),cards_homepage()), o, request) + +@rt('/dashboard') +@rt('/dashboard/{o}') +def dashboard(o:str, request=None): return _example_route('dashboard', Div(DivRAligned(A("See Code",href='/dashboard/code',cls='m-4 uk-btn'+ButtonT.default)),dashboard_homepage()), o, request) + +@rt('/forms') +@rt('/forms/{o}') +def forms(o:str, request=None): return _example_route('forms', Div(DivRAligned(A("See Code",href='/forms/code',cls='m-4 uk-btn'+ButtonT.default)),forms_homepage()), o, request) + +@rt('/music') +@rt('/music/{o}') +def music(o:str, request=None): return _example_route('music', Div(DivRAligned(A("See Code",href='/music/code',cls='m-4 uk-btn'+ButtonT.default)),music_homepage()), o, request) + +@rt('/auth') +@rt('/auth/{o}') +def auth(o:str, request=None): return _example_route('auth', Div(DivRAligned(A("See Code",href='/auth/code',cls='m-4 uk-btn'+ButtonT.default)),auth_homepage()), o, request) + +@rt('/playground') +@rt('/playground/{o}') +def playground(o:str, request=None): return _example_route('playground', Div(DivRAligned(A("See Code",href='/playground/code',cls='m-4 uk-btn'+ButtonT.default)),playground_homepage()), o, request) + +@rt('/mail') +@rt('/mail/{o}') +def mail(o:str, request=None): return _example_route('mail', Div(DivRAligned(A("See Code",href='/mail/code',cls='m-4 uk-btn'+ButtonT.default)),mail_homepage()), o, request) + +### +# Build the API Reference Pages +### + +import api_reference.api_reference as api_reference +def fname2title(ref_fn_name): return ref_fn_name[5:].replace('_',' | ').title() + +reference_fns = L([o for o in dir(api_reference) if o.startswith('docs_')]) +@rt('/api_ref/{o}') +def api_route(request, o:str): + if o not in reference_fns: raise HTTPException(404) + content = getattr(api_reference, o)() + return _create_page(Container(content), request=request, sidebar_section='API Reference') + +@rt('/api_ref/{o}/md') +def api_route_md(request, o:str): + if o not in reference_fns: raise HTTPException(404) + content = getattr(api_reference, o)() + return PlainTextResponse(html2md(to_xml(content))) + +@rt('/api_ref/{o}rmd') +def api_route_md(request, o:str): + if o not in reference_fns: raise HTTPException(404) + content = getattr(api_reference, o)() + return Div(render_md(html2md(to_xml(content)))) + +### +# Build the Guides Pages +### +@rt('/tutorial_spacing') +@rt('/tutorial_spacing/{o}') +def tutorial_spacing(o:str='', request=None): + if o=='md': return PlainTextResponse(read_html(f'https://monsterui.answer.ai/tutorial_spacing', sel='#content')) + if o=='rmd': return Div(render_md(read_html(f'https://monsterui.answer.ai/tutorial_spacing', sel='#content'))) + return _create_page(render_nb('guides/Spacing.ipynb'), request, 'Guides') +@rt('/tutorial_layout') +@rt('/tutorial_layout/{o}') +def tutorial_layout(o:str='', request=None): + if o=='md': return PlainTextResponse(read_html(f'https://monsterui.answer.ai/tutorial_layout', sel='#content')) + if o=='rmd': return Div(render_md(read_html(f'https://monsterui.answer.ai/tutorial_layout', sel='#content'))) + return _create_page(render_nb('guides/Layout.ipynb'), request, 'Guides',) + +### +# Build the Theme Switcher Page +### + +@rt +def theme_switcher(request): + return _create_page(Div(ThemePicker(custom_themes=[("Grass", "#10b981")]),cls="p-12"), request, None) + +### +# Build the Getting Started Pages +### + +gs_path = Path('getting_started') + +@rt('/tutorial_app') +@rt('/tutorial_app/{o}') +def tutorial_app(o:str='', request=None): + pass + if o=='md': return PlainTextResponse(read_html(f'https://monsterui.answer.ai/tutorial_app', sel='#content')) + if o=='rmd': return Div(render_md(read_html(f'https://monsterui.answer.ai/tutorial_app', sel='#content'))) + app_code = open(gs_path/'app_product_gallery.py').read() + app_rendered = Div(Pre(Code(app_code))) + content = Container(cls='space-y-4')( + H1("Tutorial App"), + render_md("""This is a heavily commented example of a product gallery app built with MonsterUI for those that like to learn by example. \ + This tutorial app assumes you have some familiarity with fasthtml apps already, so focuses on what MonsterUI adds on top of fasthtml. + To make the most out of this tutorial, you should follow these steps:"""), + Ol( + Li("Briefly read through this to get an overview of what is happening, without focusing on any details"), + Li("Install fasthtml and MonsterUI"), + Li("Copy the code into your own project locally and run it using `python app.py`"), + Li("Go through the code in detail to understand how it works by experimenting with changing things"), + cls=ListT.decimal+TextT.lg + ), + render_md("""> Tip: Try adding `import fasthtml.common as fh`, so you can replace things with the base fasthtml components to see what happens! +For example, try replacing `H4` with `fh.H4` or `Button` with `fh.Button`."""), + Divider(), + app_rendered) + return _create_page(content, request, 'Getting Started') + +@rt('/') +@rt('/{o}') +def index(o:str='', request=None): + if o=='md': return PlainTextResponse(read_html(f'https://monsterui.answer.ai/getting_started', sel='#content')) + if o=='rmd': return Div(render_md(read_html(f'https://monsterui.answer.ai/getting_started', sel='#content'))) + content = Container(render_md(open(gs_path/'GettingStarted.md').read())) + return _create_page(content, request, 'Getting Started') + +### +# Build the Sidebar +### + +def sidebar(open_section): + def create_li(title, href): + return Li(A(title,hx_target="#content", hx_get=href, hx_push_url='true')) + + return NavContainer( + NavParentLi( + A(DivFullySpaced("Getting Started", )), + NavContainer(create_li("Getting Started", index), + create_li("Tutorial App", tutorial_app), + parent=False), + cls='uk-open' if open_section=='Getting Started' else '' + ), + NavParentLi( + A(DivFullySpaced("API Reference", )), + NavContainer( + *[create_li(fname2title(o), f"/api_ref/{o}") for o in reference_fns], + parent=False, + ), + cls='uk-open' if open_section=='API Reference' else '' + ), + NavParentLi( + A(DivFullySpaced('Guides', )), + NavContainer( + *[create_li(title, href) for title, href in [ + ('Spacing', tutorial_spacing), + ('Layout', tutorial_layout), + ]], + parent=False + ), + cls='uk-open' if open_section=='Guides' else '' + ), + + NavParentLi( + A(DivFullySpaced('Examples', )), + NavContainer( + *[create_li(title, href) for title, href in [ + ('Task', '/tasks/'), + ('Card', '/cards/'), + ('Dashboard', '/dashboard/'), + ('Form', '/forms/'), + ('Music', '/music/'), + ('Auth', '/auth/'), + ('Playground', '/playground/'), + ('Mail', '/mail/'), + ('Ticket', '/ticket/'), + ('Scrollspy', '/scrollspy/'), + ]], + parent=False + ), + cls='uk-open' if open_section=='Examples' else '' + ), + create_li("Theme", theme_switcher), + uk_nav=True, + cls=(NavT.primary, "space-y-4 p-4 w-full md:w-full") + ) + +serve() diff --git a/MonsterUI/docs/requirements.txt b/MonsterUI/docs/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..2d4a29298bc262a6fa37d0f9ec89cb1b8a2df3be --- /dev/null +++ b/MonsterUI/docs/requirements.txt @@ -0,0 +1,13 @@ +toolslm +python-fasthtml +pandas +plotly +monsterui @ git+https://github.com/AnswerDotAI/monsterui +fastcore +fh_matplotlib +numpy +matplotlib +pysymbol_llm @ git+https://github.com/AnswerDotAI/pysymbol-llm.git +mistletoe +lxml +html2text diff --git a/MonsterUI/docs/updatellms.sh b/MonsterUI/docs/updatellms.sh new file mode 100644 index 0000000000000000000000000000000000000000..9d29c8c7235ec9146ad9ac08ed829660f5ba6916 --- /dev/null +++ b/MonsterUI/docs/updatellms.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +./createllms.sh +pysym2md --output_file apilist.txt monsterui +llms_txt2ctx llms.txt >llms-ctx.txt +llms_txt2ctx llms.txt --optional True > llms-ctx-full.txt diff --git a/MonsterUI/docs/utils.py b/MonsterUI/docs/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..24694a449a46aff6c0dd2236798a980e87a0bbc0 --- /dev/null +++ b/MonsterUI/docs/utils.py @@ -0,0 +1,60 @@ +"""Utilities for building the docs page that don't belong anywhere else""" + + +__all__ = ['hjs', 'HShow', 'create_server'] + +from fasthtml.common import * +from monsterui.all import * +from fasthtml.jupyter import * +from collections.abc import Callable +import inspect +import ast +def get_last_statement(code): return ast.unparse(ast.parse(code).body[-1]) +import json +from pathlib import Path + + +def create_flippable_card(content, source_code, extra_cls=None): + "Creates a card that flips between content and source code" + _id = 'f'+str(unqid()) + _card = Card( + Button( + DivFullySpaced(UkIcon('corner-down-right', 20, 20, 3),"See Source"), + data_uk_toggle=f"target: #{_id}", id=_id, cls=ButtonT.primary), + Button( + DivFullySpaced(UkIcon('corner-down-right', 20, 20, 3),"See Output"), + data_uk_toggle=f"target: #{_id}", id=_id, cls=ButtonT.primary, hidden=True), + Div(content, id=_id), + Div(Pre(Code(source_code, cls="hljs language-python")), id=_id, hidden=True), + cls='my-8') + return Div(_card, cls=extra_cls) if extra_cls else _card + +def fn2code_string(fn: Callable) -> tuple: return fn(), inspect.getsource(fn) + + +def render_nb(path): + "Renders a Jupyter notebook with markdown cells and flippable code cards" + namespace = globals().copy() + # Read and parse the notebook + nb_content = json.loads(Path(path).read_text()) + cells = nb_content['cells'] + + # Convert cells to appropriate HTML elements + rendered_cells = [] + for cell in cells: + if cell['cell_type'] == 'markdown': + # Combine all markdown lines and render + md_content = ''.join(cell['source']) + rendered_cells.append(render_md(md_content)) + elif cell['cell_type'] == 'code': + # Skip empty code cells + if not ''.join(cell['source']).strip(): continue + # Create flippable card for code + code_content = ''.join(cell['source']) + exec(code_content, namespace) + result = eval(get_last_statement(code_content), namespace) + + rendered_cells.append(create_flippable_card(result, code_content)) + + # Return all cells wrapped in a container with vertical spacing + return Container(cls='space-y-4')(*rendered_cells) diff --git a/MonsterUI/monsterui/__init__.py b/MonsterUI/monsterui/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..02edba9ff8523bfc57c083f8bd85f25a0f4d3e7a --- /dev/null +++ b/MonsterUI/monsterui/__init__.py @@ -0,0 +1 @@ +__version__ = "1.0.30" \ No newline at end of file diff --git a/MonsterUI/monsterui/__pycache__/__init__.cpython-312.pyc b/MonsterUI/monsterui/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3eeb23bf9f8c8cfbfe9e70e877ab2286ccc01bf5 Binary files /dev/null and b/MonsterUI/monsterui/__pycache__/__init__.cpython-312.pyc differ diff --git a/MonsterUI/monsterui/__pycache__/all.cpython-312.pyc b/MonsterUI/monsterui/__pycache__/all.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d84f8b8044d66b4e7daa40b4d8d5d6b8aceaf8a1 Binary files /dev/null and b/MonsterUI/monsterui/__pycache__/all.cpython-312.pyc differ diff --git a/MonsterUI/monsterui/__pycache__/core.cpython-312.pyc b/MonsterUI/monsterui/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e1f4b9e9b7fa1c1f5d68ea4aa4ce67f107e972f6 Binary files /dev/null and b/MonsterUI/monsterui/__pycache__/core.cpython-312.pyc differ diff --git a/MonsterUI/monsterui/__pycache__/daisy.cpython-312.pyc b/MonsterUI/monsterui/__pycache__/daisy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff2d9b6e9f082a143a686b4ac5fa9d5f6df29cf2 Binary files /dev/null and b/MonsterUI/monsterui/__pycache__/daisy.cpython-312.pyc differ diff --git a/MonsterUI/monsterui/__pycache__/foundations.cpython-312.pyc b/MonsterUI/monsterui/__pycache__/foundations.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6f8aa30ec6bfc948c005ba0897b59814cd5364a2 Binary files /dev/null and b/MonsterUI/monsterui/__pycache__/foundations.cpython-312.pyc differ diff --git a/MonsterUI/monsterui/__pycache__/franken.cpython-312.pyc b/MonsterUI/monsterui/__pycache__/franken.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..589957bcf50c39781a889ecc5c5952720fa42edc Binary files /dev/null and b/MonsterUI/monsterui/__pycache__/franken.cpython-312.pyc differ diff --git a/MonsterUI/monsterui/_modidx.py b/MonsterUI/monsterui/_modidx.py new file mode 100644 index 0000000000000000000000000000000000000000..ac14255d3fa604a90e008f149f043477525ecb0e --- /dev/null +++ b/MonsterUI/monsterui/_modidx.py @@ -0,0 +1,222 @@ +# Autogenerated by nbdev + +d = { 'settings': { 'branch': 'main', + 'doc_baseurl': '/MonsterUI', + 'doc_host': 'https://monsterui.answer.ai', + 'git_url': 'https://github.com/AnswerDotAI/MonsterUI', + 'lib_path': 'monsterui'}, + 'syms': { 'monsterui.all': {}, + 'monsterui.core': { 'monsterui.core.FastHTML': ('core.html#fasthtml', 'monsterui/core.py'), + 'monsterui.core.Theme': ('core.html#theme', 'monsterui/core.py'), + 'monsterui.core.Theme._create_headers': ('core.html#theme._create_headers', 'monsterui/core.py'), + 'monsterui.core.Theme._generate_next_value_': ( 'core.html#theme._generate_next_value_', + 'monsterui/core.py'), + 'monsterui.core.Theme.headers': ('core.html#theme.headers', 'monsterui/core.py'), + 'monsterui.core.Theme.local_headers': ('core.html#theme.local_headers', 'monsterui/core.py'), + 'monsterui.core.ThemeFont': ('core.html#themefont', 'monsterui/core.py'), + 'monsterui.core.ThemeRadii': ('core.html#themeradii', 'monsterui/core.py'), + 'monsterui.core.ThemeShadows': ('core.html#themeshadows', 'monsterui/core.py'), + 'monsterui.core._download_resource': ('core.html#_download_resource', 'monsterui/core.py'), + 'monsterui.core._headers_theme': ('core.html#_headers_theme', 'monsterui/core.py'), + 'monsterui.core.fast_app': ('core.html#fast_app', 'monsterui/core.py')}, + 'monsterui.daisy': { 'monsterui.daisy.Alert': ('daisy.html#alert', 'monsterui/daisy.py'), + 'monsterui.daisy.AlertT': ('daisy.html#alertt', 'monsterui/daisy.py'), + 'monsterui.daisy.AlertT._generate_next_value_': ( 'daisy.html#alertt._generate_next_value_', + 'monsterui/daisy.py'), + 'monsterui.daisy.LiStep': ('daisy.html#listep', 'monsterui/daisy.py'), + 'monsterui.daisy.Loading': ('daisy.html#loading', 'monsterui/daisy.py'), + 'monsterui.daisy.LoadingT': ('daisy.html#loadingt', 'monsterui/daisy.py'), + 'monsterui.daisy.LoadingT._generate_next_value_': ( 'daisy.html#loadingt._generate_next_value_', + 'monsterui/daisy.py'), + 'monsterui.daisy.StepT': ('daisy.html#stept', 'monsterui/daisy.py'), + 'monsterui.daisy.StepT._generate_next_value_': ( 'daisy.html#stept._generate_next_value_', + 'monsterui/daisy.py'), + 'monsterui.daisy.Steps': ('daisy.html#steps', 'monsterui/daisy.py'), + 'monsterui.daisy.StepsT': ('daisy.html#stepst', 'monsterui/daisy.py'), + 'monsterui.daisy.StepsT._generate_next_value_': ( 'daisy.html#stepst._generate_next_value_', + 'monsterui/daisy.py'), + 'monsterui.daisy.Toast': ('daisy.html#toast', 'monsterui/daisy.py'), + 'monsterui.daisy.ToastHT': ('daisy.html#toastht', 'monsterui/daisy.py'), + 'monsterui.daisy.ToastHT._generate_next_value_': ( 'daisy.html#toastht._generate_next_value_', + 'monsterui/daisy.py'), + 'monsterui.daisy.ToastVT': ('daisy.html#toastvt', 'monsterui/daisy.py'), + 'monsterui.daisy.ToastVT._generate_next_value_': ( 'daisy.html#toastvt._generate_next_value_', + 'monsterui/daisy.py')}, + 'monsterui.foundations': { 'monsterui.foundations.VEnum': ('foundation.html#venum', 'monsterui/foundations.py'), + 'monsterui.foundations.VEnum.__add__': ('foundation.html#venum.__add__', 'monsterui/foundations.py'), + 'monsterui.foundations.VEnum.__radd__': ( 'foundation.html#venum.__radd__', + 'monsterui/foundations.py'), + 'monsterui.foundations.VEnum.__str__': ('foundation.html#venum.__str__', 'monsterui/foundations.py'), + 'monsterui.foundations.str2ukcls': ('foundation.html#str2ukcls', 'monsterui/foundations.py'), + 'monsterui.foundations.stringify': ('foundation.html#stringify', 'monsterui/foundations.py')}, + 'monsterui.franken': { 'monsterui.franken.AT': ('franken.html#at', 'monsterui/franken.py'), + 'monsterui.franken.AT._generate_next_value_': ( 'franken.html#at._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.Abbr': ('franken.html#abbr', 'monsterui/franken.py'), + 'monsterui.franken.Accordion': ('franken.html#accordion', 'monsterui/franken.py'), + 'monsterui.franken.AccordionItem': ('franken.html#accordionitem', 'monsterui/franken.py'), + 'monsterui.franken.Address': ('franken.html#address', 'monsterui/franken.py'), + 'monsterui.franken.ApexChart': ('franken.html#apexchart', 'monsterui/franken.py'), + 'monsterui.franken.Article': ('franken.html#article', 'monsterui/franken.py'), + 'monsterui.franken.ArticleMeta': ('franken.html#articlemeta', 'monsterui/franken.py'), + 'monsterui.franken.ArticleTitle': ('franken.html#articletitle', 'monsterui/franken.py'), + 'monsterui.franken.BackgroundT': ('franken.html#backgroundt', 'monsterui/franken.py'), + 'monsterui.franken.BackgroundT._generate_next_value_': ( 'franken.html#backgroundt._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.Blockquote': ('franken.html#blockquote', 'monsterui/franken.py'), + 'monsterui.franken.Button': ('franken.html#button', 'monsterui/franken.py'), + 'monsterui.franken.ButtonT': ('franken.html#buttont', 'monsterui/franken.py'), + 'monsterui.franken.ButtonT._generate_next_value_': ( 'franken.html#buttont._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.Caption': ('franken.html#caption', 'monsterui/franken.py'), + 'monsterui.franken.Card': ('franken.html#card', 'monsterui/franken.py'), + 'monsterui.franken.CardBody': ('franken.html#cardbody', 'monsterui/franken.py'), + 'monsterui.franken.CardContainer': ('franken.html#cardcontainer', 'monsterui/franken.py'), + 'monsterui.franken.CardFooter': ('franken.html#cardfooter', 'monsterui/franken.py'), + 'monsterui.franken.CardHeader': ('franken.html#cardheader', 'monsterui/franken.py'), + 'monsterui.franken.CardT': ('franken.html#cardt', 'monsterui/franken.py'), + 'monsterui.franken.CardT._generate_next_value_': ( 'franken.html#cardt._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.CardTitle': ('franken.html#cardtitle', 'monsterui/franken.py'), + 'monsterui.franken.Center': ('franken.html#center', 'monsterui/franken.py'), + 'monsterui.franken.CheckboxX': ('franken.html#checkboxx', 'monsterui/franken.py'), + 'monsterui.franken.Cite': ('franken.html#cite', 'monsterui/franken.py'), + 'monsterui.franken.CodeBlock': ('franken.html#codeblock', 'monsterui/franken.py'), + 'monsterui.franken.CodeSpan': ('franken.html#codespan', 'monsterui/franken.py'), + 'monsterui.franken.Container': ('franken.html#container', 'monsterui/franken.py'), + 'monsterui.franken.ContainerT': ('franken.html#containert', 'monsterui/franken.py'), + 'monsterui.franken.ContainerT._generate_next_value_': ( 'franken.html#containert._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.Data': ('franken.html#data', 'monsterui/franken.py'), + 'monsterui.franken.Del': ('franken.html#del', 'monsterui/franken.py'), + 'monsterui.franken.Details': ('franken.html#details', 'monsterui/franken.py'), + 'monsterui.franken.Dfn': ('franken.html#dfn', 'monsterui/franken.py'), + 'monsterui.franken.DiceBearAvatar': ('franken.html#dicebearavatar', 'monsterui/franken.py'), + 'monsterui.franken.DivCentered': ('franken.html#divcentered', 'monsterui/franken.py'), + 'monsterui.franken.DivFullySpaced': ('franken.html#divfullyspaced', 'monsterui/franken.py'), + 'monsterui.franken.DivHStacked': ('franken.html#divhstacked', 'monsterui/franken.py'), + 'monsterui.franken.DivLAligned': ('franken.html#divlaligned', 'monsterui/franken.py'), + 'monsterui.franken.DivRAligned': ('franken.html#divraligned', 'monsterui/franken.py'), + 'monsterui.franken.DivVStacked': ('franken.html#divvstacked', 'monsterui/franken.py'), + 'monsterui.franken.Divider': ('franken.html#divider', 'monsterui/franken.py'), + 'monsterui.franken.DividerLine': ('franken.html#dividerline', 'monsterui/franken.py'), + 'monsterui.franken.DividerSplit': ('franken.html#dividersplit', 'monsterui/franken.py'), + 'monsterui.franken.DividerT': ('franken.html#dividert', 'monsterui/franken.py'), + 'monsterui.franken.DividerT._generate_next_value_': ( 'franken.html#dividert._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.DropDownNavContainer': ('franken.html#dropdownnavcontainer', 'monsterui/franken.py'), + 'monsterui.franken.Em': ('franken.html#em', 'monsterui/franken.py'), + 'monsterui.franken.Fieldset': ('franken.html#fieldset', 'monsterui/franken.py'), + 'monsterui.franken.Figure': ('franken.html#figure', 'monsterui/franken.py'), + 'monsterui.franken.FlexT': ('franken.html#flext', 'monsterui/franken.py'), + 'monsterui.franken.FlexT._generate_next_value_': ( 'franken.html#flext._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.Form': ('franken.html#form', 'monsterui/franken.py'), + 'monsterui.franken.FormLabel': ('franken.html#formlabel', 'monsterui/franken.py'), + 'monsterui.franken.FrankenRenderer': ('franken.html#frankenrenderer', 'monsterui/franken.py'), + 'monsterui.franken.FrankenRenderer.__init__': ( 'franken.html#frankenrenderer.__init__', + 'monsterui/franken.py'), + 'monsterui.franken.FrankenRenderer.render_image': ( 'franken.html#frankenrenderer.render_image', + 'monsterui/franken.py'), + 'monsterui.franken.GenericLabelInput': ('franken.html#genericlabelinput', 'monsterui/franken.py'), + 'monsterui.franken.Grid': ('franken.html#grid', 'monsterui/franken.py'), + 'monsterui.franken.H1': ('franken.html#h1', 'monsterui/franken.py'), + 'monsterui.franken.H2': ('franken.html#h2', 'monsterui/franken.py'), + 'monsterui.franken.H3': ('franken.html#h3', 'monsterui/franken.py'), + 'monsterui.franken.H4': ('franken.html#h4', 'monsterui/franken.py'), + 'monsterui.franken.H5': ('franken.html#h5', 'monsterui/franken.py'), + 'monsterui.franken.H6': ('franken.html#h6', 'monsterui/franken.py'), + 'monsterui.franken.I': ('franken.html#i', 'monsterui/franken.py'), + 'monsterui.franken.Input': ('franken.html#input', 'monsterui/franken.py'), + 'monsterui.franken.Ins': ('franken.html#ins', 'monsterui/franken.py'), + 'monsterui.franken.Kbd': ('franken.html#kbd', 'monsterui/franken.py'), + 'monsterui.franken.Label': ('franken.html#label', 'monsterui/franken.py'), + 'monsterui.franken.LabelCheckboxX': ('franken.html#labelcheckboxx', 'monsterui/franken.py'), + 'monsterui.franken.LabelInput': ('franken.html#labelinput', 'monsterui/franken.py'), + 'monsterui.franken.LabelRadio': ('franken.html#labelradio', 'monsterui/franken.py'), + 'monsterui.franken.LabelRange': ('franken.html#labelrange', 'monsterui/franken.py'), + 'monsterui.franken.LabelSelect': ('franken.html#labelselect', 'monsterui/franken.py'), + 'monsterui.franken.LabelSwitch': ('franken.html#labelswitch', 'monsterui/franken.py'), + 'monsterui.franken.LabelT': ('franken.html#labelt', 'monsterui/franken.py'), + 'monsterui.franken.LabelT._generate_next_value_': ( 'franken.html#labelt._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.LabelTextArea': ('franken.html#labeltextarea', 'monsterui/franken.py'), + 'monsterui.franken.Legend': ('franken.html#legend', 'monsterui/franken.py'), + 'monsterui.franken.LightboxContainer': ('franken.html#lightboxcontainer', 'monsterui/franken.py'), + 'monsterui.franken.LightboxItem': ('franken.html#lightboxitem', 'monsterui/franken.py'), + 'monsterui.franken.ListT': ('franken.html#listt', 'monsterui/franken.py'), + 'monsterui.franken.Mark': ('franken.html#mark', 'monsterui/franken.py'), + 'monsterui.franken.Meter': ('franken.html#meter', 'monsterui/franken.py'), + 'monsterui.franken.Modal': ('franken.html#modal', 'monsterui/franken.py'), + 'monsterui.franken.ModalBody': ('franken.html#modalbody', 'monsterui/franken.py'), + 'monsterui.franken.ModalCloseButton': ('franken.html#modalclosebutton', 'monsterui/franken.py'), + 'monsterui.franken.ModalContainer': ('franken.html#modalcontainer', 'monsterui/franken.py'), + 'monsterui.franken.ModalDialog': ('franken.html#modaldialog', 'monsterui/franken.py'), + 'monsterui.franken.ModalFooter': ('franken.html#modalfooter', 'monsterui/franken.py'), + 'monsterui.franken.ModalHeader': ('franken.html#modalheader', 'monsterui/franken.py'), + 'monsterui.franken.ModalTitle': ('franken.html#modaltitle', 'monsterui/franken.py'), + 'monsterui.franken.NavBar': ('franken.html#navbar', 'monsterui/franken.py'), + 'monsterui.franken.NavCloseLi': ('franken.html#navcloseli', 'monsterui/franken.py'), + 'monsterui.franken.NavContainer': ('franken.html#navcontainer', 'monsterui/franken.py'), + 'monsterui.franken.NavDividerLi': ('franken.html#navdividerli', 'monsterui/franken.py'), + 'monsterui.franken.NavHeaderLi': ('franken.html#navheaderli', 'monsterui/franken.py'), + 'monsterui.franken.NavParentLi': ('franken.html#navparentli', 'monsterui/franken.py'), + 'monsterui.franken.NavSubtitle': ('franken.html#navsubtitle', 'monsterui/franken.py'), + 'monsterui.franken.NavT': ('franken.html#navt', 'monsterui/franken.py'), + 'monsterui.franken.NavT._generate_next_value_': ( 'franken.html#navt._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.Options': ('franken.html#options', 'monsterui/franken.py'), + 'monsterui.franken.Output': ('franken.html#output', 'monsterui/franken.py'), + 'monsterui.franken.PicSumImg': ('franken.html#picsumimg', 'monsterui/franken.py'), + 'monsterui.franken.Placeholder': ('franken.html#placeholder', 'monsterui/franken.py'), + 'monsterui.franken.Progress': ('franken.html#progress', 'monsterui/franken.py'), + 'monsterui.franken.Q': ('franken.html#q', 'monsterui/franken.py'), + 'monsterui.franken.Radio': ('franken.html#radio', 'monsterui/franken.py'), + 'monsterui.franken.Range': ('franken.html#range', 'monsterui/franken.py'), + 'monsterui.franken.S': ('franken.html#s', 'monsterui/franken.py'), + 'monsterui.franken.Samp': ('franken.html#samp', 'monsterui/franken.py'), + 'monsterui.franken.ScrollspyT': ('franken.html#scrollspyt', 'monsterui/franken.py'), + 'monsterui.franken.Section': ('franken.html#section', 'monsterui/franken.py'), + 'monsterui.franken.SectionT': ('franken.html#sectiont', 'monsterui/franken.py'), + 'monsterui.franken.SectionT._generate_next_value_': ( 'franken.html#sectiont._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.Select': ('franken.html#select', 'monsterui/franken.py'), + 'monsterui.franken.Slider': ('franken.html#slider', 'monsterui/franken.py'), + 'monsterui.franken.SliderContainer': ('franken.html#slidercontainer', 'monsterui/franken.py'), + 'monsterui.franken.SliderItems': ('franken.html#slideritems', 'monsterui/franken.py'), + 'monsterui.franken.SliderNav': ('franken.html#slidernav', 'monsterui/franken.py'), + 'monsterui.franken.Small': ('franken.html#small', 'monsterui/franken.py'), + 'monsterui.franken.Strong': ('franken.html#strong', 'monsterui/franken.py'), + 'monsterui.franken.Sub': ('franken.html#sub', 'monsterui/franken.py'), + 'monsterui.franken.Subtitle': ('franken.html#subtitle', 'monsterui/franken.py'), + 'monsterui.franken.Summary': ('franken.html#summary', 'monsterui/franken.py'), + 'monsterui.franken.Sup': ('franken.html#sup', 'monsterui/franken.py'), + 'monsterui.franken.Switch': ('franken.html#switch', 'monsterui/franken.py'), + 'monsterui.franken.TabContainer': ('franken.html#tabcontainer', 'monsterui/franken.py'), + 'monsterui.franken.Table': ('franken.html#table', 'monsterui/franken.py'), + 'monsterui.franken.TableFromDicts': ('franken.html#tablefromdicts', 'monsterui/franken.py'), + 'monsterui.franken.TableFromLists': ('franken.html#tablefromlists', 'monsterui/franken.py'), + 'monsterui.franken.TableT': ('franken.html#tablet', 'monsterui/franken.py'), + 'monsterui.franken.TableT._generate_next_value_': ( 'franken.html#tablet._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.Tbody': ('franken.html#tbody', 'monsterui/franken.py'), + 'monsterui.franken.Td': ('franken.html#td', 'monsterui/franken.py'), + 'monsterui.franken.TextArea': ('franken.html#textarea', 'monsterui/franken.py'), + 'monsterui.franken.TextPresets': ('franken.html#textpresets', 'monsterui/franken.py'), + 'monsterui.franken.TextT': ('franken.html#textt', 'monsterui/franken.py'), + 'monsterui.franken.TextT._generate_next_value_': ( 'franken.html#textt._generate_next_value_', + 'monsterui/franken.py'), + 'monsterui.franken.Th': ('franken.html#th', 'monsterui/franken.py'), + 'monsterui.franken.ThemePicker': ('franken.html#themepicker', 'monsterui/franken.py'), + 'monsterui.franken.Time': ('franken.html#time', 'monsterui/franken.py'), + 'monsterui.franken.Titled': ('franken.html#titled', 'monsterui/franken.py'), + 'monsterui.franken.U': ('franken.html#u', 'monsterui/franken.py'), + 'monsterui.franken.UkFormSection': ('franken.html#ukformsection', 'monsterui/franken.py'), + 'monsterui.franken.UkIcon': ('franken.html#ukicon', 'monsterui/franken.py'), + 'monsterui.franken.UkIconLink': ('franken.html#ukiconlink', 'monsterui/franken.py'), + 'monsterui.franken.Upload': ('franken.html#upload', 'monsterui/franken.py'), + 'monsterui.franken.UploadZone': ('franken.html#uploadzone', 'monsterui/franken.py'), + 'monsterui.franken.Var': ('franken.html#var', 'monsterui/franken.py'), + 'monsterui.franken._TableCell': ('franken.html#_tablecell', 'monsterui/franken.py'), + 'monsterui.franken.apply_classes': ('franken.html#apply_classes', 'monsterui/franken.py'), + 'monsterui.franken.render_md': ('franken.html#render_md', 'monsterui/franken.py')}}} diff --git a/MonsterUI/monsterui/all.py b/MonsterUI/monsterui/all.py new file mode 100644 index 0000000000000000000000000000000000000000..0c8810a03ccc578700d90a184cb29523d2224383 --- /dev/null +++ b/MonsterUI/monsterui/all.py @@ -0,0 +1,3 @@ +from .core import * +from .franken import * +from .daisy import * diff --git a/MonsterUI/monsterui/core.py b/MonsterUI/monsterui/core.py new file mode 100644 index 0000000000000000000000000000000000000000..6b1d97284617decd2c19ad82ea0aa93a934d5660 --- /dev/null +++ b/MonsterUI/monsterui/core.py @@ -0,0 +1,264 @@ +# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/01_core.ipynb. + +# %% auto 0 +__all__ = ['HEADER_URLS', 'daisy_styles', 'scrollspy_style', 'fast_app', 'FastHTML', 'ThemeRadii', 'ThemeShadows', 'ThemeFont', + 'Theme'] + +# %% ../nbs/01_core.ipynb +import fasthtml.common as fh +from .foundations import * +from fasthtml.common import FastHTML, fast_app +from enum import Enum, auto +from fastcore.all import * +import httpx +from pathlib import Path + +# %% ../nbs/01_core.ipynb +@delegates(fh.fast_app, but=['pico']) +def fast_app(*args, pico=False, **kwargs): + "Create a FastHTML or FastHTMLWithLiveReload app with `bg-background text-foreground` to bodykw for frankenui themes" + if 'bodykw' not in kwargs: kwargs['bodykw'] = {} + if 'class' not in kwargs['bodykw']: kwargs['bodykw']['class'] = '' + kwargs['bodykw']['class'] = stringify((kwargs['bodykw']['class'],'bg-background text-foreground')) + return fh.fast_app(*args, pico=pico, **kwargs) + +# %% ../nbs/01_core.ipynb +@delegates(fh.FastHTML, but=['pico']) +def FastHTML(*args, pico=False, **kwargs): + "Create a FastHTML app and adds `bg-background text-foreground` to bodykw for frankenui themes" + if 'bodykw' not in kwargs: kwargs['bodykw'] = {} + if 'class' not in kwargs['bodykw']: kwargs['bodykw']['class'] = '' + kwargs['bodykw']['class'] = stringify((kwargs['bodykw']['class'],'bg-background text-foreground')) + bodykw = kwargs.pop('bodykw',{}) + return fh.FastHTML(*args, pico=pico, **bodykw, **kwargs) + +# %% ../nbs/01_core.ipynb +class ThemeRadii(VEnum): + none = 'uk-radii-none' + sm = 'uk-radii-sm' + md = 'uk-radii-md' + lg = 'uk-radii-lg' + +class ThemeShadows: + none = 'uk-shadows-none' + sm = 'uk-shadows-sm' + md = 'uk-shadows-md' + lg = 'uk-shadows-lg' + +class ThemeFont: + sm = 'uk-font-sm' + default = 'uk-font-base' + +# %% ../nbs/01_core.ipynb +def _headers_theme(color, mode='auto', radii=ThemeRadii.sm, shadows=ThemeShadows.sm, font=ThemeFont.sm): + franken_init = ''' + const __FRANKEN__ = JSON.parse(localStorage.getItem("__FRANKEN__") || "{}"); + ''' + + mode_script = { + 'auto': f''' + {franken_init} + if ( + __FRANKEN__.mode === "dark" || + (!__FRANKEN__.mode && + window.matchMedia("(prefers-color-scheme: dark)").matches) + ) {{ + htmlElement.classList.add("dark"); + }} else {{ + htmlElement.classList.remove("dark"); + }} + ''', + 'light': f'{franken_init}\nhtmlElement.classList.remove("dark");', + 'dark': f'{franken_init}\nhtmlElement.classList.add("dark");' + } + + return fh.Script(f''' + const htmlElement = document.documentElement; + {mode_script[mode]} + htmlElement.classList.add(__FRANKEN__.theme || "uk-theme-{color}"); + htmlElement.classList.add(__FRANKEN__.radii || "{radii}"); + htmlElement.classList.add(__FRANKEN__.shadows || "{shadows}"); + htmlElement.classList.add(__FRANKEN__.font || "{font}"); + ''') + +# %% ../nbs/01_core.ipynb +HEADER_URLS = { + 'franken_css': "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/css/core.min.css", + 'franken_js_core': "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/core.iife.js", + 'franken_icons': "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/icon.iife.js", + 'tailwind': "https://cdn.tailwindcss.com/3.4.16", + 'daisyui': "https://cdn.jsdelivr.net/npm/daisyui@4.12.24/dist/full.min.css", + 'apex_charts': "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/chart.iife.js", + 'highlight_js': "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js", + 'highlight_python': "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/python.min.js", + 'highlight_light_css': "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/atom-one-light.css", + 'highlight_dark_css': "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/atom-one-dark.css", + 'highlight_copy': "https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js", + 'highlight_copy_css': "https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css", +} + +def _download_resource(url, static_dir): + "Download a single resource and return its local path" + static = Path(static_dir) + fname = static/f"{url[0]}.{'js' if 'js' in url[1] else 'css'}" + content = httpx.get(url[1], follow_redirects=True).content + fname.write_bytes(content) + return (url[0], f"/{static_dir}/{fname.name}") + +# %% ../nbs/01_core.ipynb +daisy_styles = Style(""" +:root { + --b1: from hsl(var(--background)) l c h; + --bc: from hsl(var(--foreground)) l c h; + --m: from hsl(var(--muted)) l c h; + --mc: from hsl(var(--muted-foreground)) l c h; + --po: from hsl(var(--popover)) l c h; + --poc: from hsl(var(--popover-foreground)) l c h; + --b2: from hsl(var(--card)) l c h; + --b2c: from hsl(var(--card-foreground)) l c h; + --br: from hsl(var(--border)) l c h; + --in: from hsl(var(--input)) l c h; + --p: from hsl(var(--primary)) l c h; + --pc: from hsl(var(--primary-foreground)) l c h; + --s: from hsl(var(--secondary)) l c h; + --sc: from hsl(var(--secondary-foreground)) l c h; + --a: from hsl(var(--accent)) l c h; + --ac: from hsl(var(--accent-foreground)) l c h; + --er: from hsl(var(--destructive)) l c h; + --erc: from hsl(var(--destructive-foreground)) l c h; + --b3: from hsl(var(--ring)) l c h; + --ch1: from hsl(var(--chart-1)) l c h; + --ch2: from hsl(var(--chart-2)) l c h; + --ch3: from hsl(var(--chart-3)) l c h; + --ch4: from hsl(var(--chart-4)) l c h; + --ch5: from hsl(var(--chart-5)) l c h; + --rd: var(--radius); +} +""") + + +# %% ../nbs/01_core.ipynb +scrollspy_style= Style(''' +.monster-navbar.navbar-bold a { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} +.monster-navbar.navbar-bold a.uk-active { + transform: scale(1.15) ; + font-weight: bold; + text-shadow: 0 0 12px rgba(var(--p-rgb), 0.4); + letter-spacing: 0.02em; + color: hsl(var(--p) / 1); +} +.monster-navbar.navbar-underline a.uk-active { position: relative; } +.monster-navbar.navbar-underline a.uk-active::after { + content: ''; + position: absolute; + left: 0; + bottom: -2px; + width: 100%; + height: 2px; + background: currentColor; + animation: slideIn 0.3s ease forwards; +} +@keyframes slideIn { + from { transform: scaleX(0); } + to { transform: scaleX(1); } +} +''') + +# %% ../nbs/01_core.ipynb +class Theme(Enum): + "Selector to choose theme and get all headers needed for app. Includes frankenui + tailwind + daisyui + highlight.js options" + def _generate_next_value_(name, start, count, last_values): return name + slate = auto() + stone = auto() + gray = auto() + neutral = auto() + red = auto() + rose = auto() + orange = auto() + green = auto() + blue = auto() + yellow = auto() + violet = auto() + zinc = auto() + + def _create_headers(self, urls, mode='auto', icons=True, daisy=True, highlightjs=False, katex=False, apex_charts=False, radii=ThemeRadii.sm, shadows=ThemeShadows.sm, font=ThemeFont.sm): + "Create header elements with given URLs" + hdrs = [ + fh.Link(rel="stylesheet", href=urls['franken_css']), + fh.Script(type="module", src=urls['franken_js_core']), + fh.Script(src=urls['tailwind']), + fh.Script(""" + tailwind.config = { + darkMode: 'selector', + } + """), + _headers_theme(self.value, mode=mode, radii=radii, shadows=shadows, font=font), + scrollspy_style] + + if icons: hdrs.append(fh.Script(type="module", src=urls['franken_icons'])) + if daisy: hdrs += [fh.Link(rel="stylesheet", href=urls['daisyui']), daisy_styles] + if apex_charts: hdrs += [fh.Script(type='module', src=urls['apex_charts'])] + + if highlightjs: + hdrs += [ + fh.Script(src=urls['highlight_js']), + fh.Script(src=urls['highlight_python']), + fh.Link(rel="stylesheet", href=urls['highlight_light_css'], id='hljs-light'), + fh.Link(rel="stylesheet", href=urls['highlight_dark_css'], id='hljs-dark'), + fh.Script(src=urls['highlight_copy']), + fh.Link(rel="stylesheet", href=urls['highlight_copy_css']), + fh.Script(''' + hljs.addPlugin(new CopyButtonPlugin()); + hljs.configure({ + cssSelector: 'pre code', + languages: ['python'], + ignoreUnescapedHTML: true + }); + function updateTheme() { + const isDark = document.documentElement.classList.contains('dark'); + document.getElementById('hljs-dark').disabled = !isDark; + document.getElementById('hljs-light').disabled = isDark; + } + new MutationObserver(mutations => + mutations.forEach(m => m.target.tagName === 'HTML' && + m.attributeName === 'class' && updateTheme()) + ).observe(document.documentElement, { attributes: true }); + updateTheme(); + htmx.onLoad(hljs.highlightAll); + ''', type='module'), + ] + + if katex: + hdrs += [ + fh.Link(rel="stylesheet", + href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css"), + fh.Script(""" + import katex from 'https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.mjs'; + import autoRender from 'https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/contrib/auto-render.mjs'; + const options = { + delimiters: [ + {left: '$$', right: '$$', display: true}, + {left: '$', right: '$', display: false} + ], + ignoredClasses: ['nomath'] + }; + + document.addEventListener('htmx:load', evt => { + const element = evt.detail.elt || document.body; + autoRender(element,options); + }); + """,type="module"), + ] + return hdrs + + def headers(self, mode='auto', icons=True, daisy=True, highlightjs=False, katex=False, apex_charts=False, radii=ThemeRadii.sm, shadows=ThemeShadows.sm, font=ThemeFont.sm ): + "Create frankenui and tailwind cdns" + return self._create_headers(HEADER_URLS, mode=mode, icons=icons, daisy=daisy, highlightjs=highlightjs, katex=katex, apex_charts=apex_charts, radii=radii, shadows=shadows, font=font) + + def local_headers(self, mode='auto', static_dir='static', icons=True, daisy=True, highlightjs=False, katex=False, apex_charts=False, radii='md', shadows='sm', font='sm'): + "Create headers using local files downloaded from CDNs" + Path(static_dir).mkdir(exist_ok=True) + local_urls = dict([_download_resource(url, static_dir) for url in HEADER_URLS.items()]) + return self._create_headers(local_urls, mode=mode, icons=icons, daisy=daisy, highlightjs=highlightjs, katex=katex, apex_charts=apex_charts, radii=radii, shadows=shadows, font=font) diff --git a/MonsterUI/monsterui/daisy.py b/MonsterUI/monsterui/daisy.py new file mode 100644 index 0000000000000000000000000000000000000000..48137085940cc1bcbcc8a9bb5c49b8b23a7da7f3 --- /dev/null +++ b/MonsterUI/monsterui/daisy.py @@ -0,0 +1,119 @@ +# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/03_daisy.ipynb. + +# %% auto 0 +__all__ = ['AlertT', 'Alert', 'StepsT', 'StepT', 'Steps', 'LiStep', 'LoadingT', 'Loading', 'ToastHT', 'ToastVT', 'Toast'] + +# %% ../nbs/03_daisy.ipynb +import fasthtml.common as fh +from .foundations import * +from fasthtml.common import Div, Span, FT +from fasthtml.svg import * +from enum import auto +from fastcore.all import * + + +# %% ../nbs/03_daisy.ipynb +class AlertT(VEnum): + "Alert styles from DaisyUI" + def _generate_next_value_(name, start, count, last_values): return f"alert-{name}" + info = auto() + success = auto() + warning = auto() + error = auto() + +# %% ../nbs/03_daisy.ipynb +def Alert(*c, # Content for Alert (often text and/or icon) + cls='', # Class for the alert (often an `AlertT` option) + **kwargs # Additional arguments for outer Div + )->FT: # Div(Span(...), cls='alert', role='alert') + "Alert informs users about important events." + return Div(Span(*c), cls=('alert', stringify(cls)), role='alert', **kwargs) + +# %% ../nbs/03_daisy.ipynb +class StepsT(VEnum): + "Options for Steps" + def _generate_next_value_(name, start, count, last_values): return f'steps-{name}' + vertical = auto() + horizonal = auto() + +# %% ../nbs/03_daisy.ipynb +class StepT(VEnum): + 'Step styles for LiStep' + def _generate_next_value_(name, start, count, last_values): return f'step-{name}' + primary = auto() + secondary = auto() + accent = auto() + info = auto() + success = auto() + warning = auto() + error = auto() + neutral = auto() + +# %% ../nbs/03_daisy.ipynb +def Steps(*li, # Each `Li` represent a step (generally use `LiStep`) + cls='', # class for Steps (generally a `StepsT` option) + **kwargs # Additional args for outer wrapper (`Ul` component) + )->FT: # Ul(..., cls='steps') + "Creates a steps container" + return Ul(*li, cls=('steps',stringify(cls)), **kwargs) + +def LiStep(*c, # Description for Step that goes next to bubble (often text) + cls='', # Additional step classes (generally a `StepT` component) + data_content=None, # Content for inside bubble (defaults to number, often an emoji) + **kwargs # Aditional arguments for the step (`Li` component) + )->FT: # Li(..., cls='step') + "Creates a step list item" + return Li(*c, cls=('step', stringify(cls)), data_content=data_content, **kwargs) + +# %% ../nbs/03_daisy.ipynb +class LoadingT(VEnum): + def _generate_next_value_(name, start, count, last_values): return f'loading-{name}' + spinner = auto() + dots = auto() + ring = auto() + ball = auto() + bars = auto() + infinity = auto() + + xs = 'loading-xsmall' + sm = 'loading-small' + md = 'loading-medium' + lg = 'loading-large' + +# %% ../nbs/03_daisy.ipynb +def Loading(cls=(LoadingT.bars, LoadingT.lg), # Classes for indicator (generally `LoadingT` options) + htmx_indicator=False, # Add htmx-indicator class + **kwargs # additional args for outer conainter (`Span`) + )->FT: # Span(cls=...) + "Creates a loading animation component" + classes = ['loading', stringify(cls)] + if htmx_indicator: classes.append('htmx-indicator') + return Span(cls=classes, **kwargs) + +# %% ../nbs/03_daisy.ipynb +class ToastHT(VEnum): + "Horizontal position for Toast" + def _generate_next_value_(name, start, count, last_values): return f'toast-{name}' + start = auto() + center = auto() + end = auto() + +class ToastVT(VEnum): + "Vertical position for Toast" + def _generate_next_value_(name, start, count, last_values): return f'toast-{name}' + top = auto() + middle = auto() + bottom = auto() + +# %% ../nbs/03_daisy.ipynb +def Toast(*c, # Content for toast (often test) + cls='', # Classes for toast (often `ToastHT` and `ToastVT` options) + alert_cls='', # classes for altert (often `AlertT` options) + dur=5.0, # no. of seconds before the toast disappears + **kwargs # Additional args for outer container (`Div` tag) + )->FT: # Div(Alert(...), cls='toast') + "Toasts are stacked announcements, positioned on the corner of page." + a = Alert(*c, cls=alert_cls) + _id = fh.unqid() + js = '''(() => setTimeout(() => document.querySelector('[data-mui="%s"]').remove(),%s))()'''%(_id,dur*1000) + return Div(a, NotStr(f""), data_mui=_id, cls=('toast', stringify(cls)), **kwargs) diff --git a/MonsterUI/monsterui/foundations.py b/MonsterUI/monsterui/foundations.py new file mode 100644 index 0000000000000000000000000000000000000000..7c9749b8eae265a563c7b321a26c7720fe2ae2c1 --- /dev/null +++ b/MonsterUI/monsterui/foundations.py @@ -0,0 +1,27 @@ +"""Data Structures and Utilties""" + +# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_foundation.ipynb. + +# %% auto 0 +__all__ = ['stringify', 'str2ukcls', 'VEnum'] + +# %% ../nbs/00_foundation.ipynb +from enum import Enum, auto +from fastcore.all import * + +# %% ../nbs/00_foundation.ipynb +# need a better name, stringify might be too general for what it does +def stringify(o # String, Tuple, or Enum options we want stringified + ): # String that can be passed FT comp args (such as `cls=`) + "Converts input types into strings that can be passed to FT components" + if is_listy(o): return ' '.join(map(str,o)) if o else "" + return o.__str__() + +# %% ../nbs/00_foundation.ipynb +def str2ukcls(base, txt): return f"uk-{base}-{txt.replace('_', '-')}".strip('-') + +# %% ../nbs/00_foundation.ipynb +class VEnum(Enum): + def __str__(self): return self.value + def __add__(self, other): return stringify((self,other)) + def __radd__(self, other): return stringify((other,self)) diff --git a/MonsterUI/monsterui/franken.py b/MonsterUI/monsterui/franken.py new file mode 100644 index 0000000000000000000000000000000000000000..a775286f4851259eb2c553e109de09f2c6e158b1 --- /dev/null +++ b/MonsterUI/monsterui/franken.py @@ -0,0 +1,1628 @@ +# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/02_franken.ipynb. + +# %% auto 0 +__all__ = ['franken_class_map', 'TextT', 'TextPresets', 'CodeSpan', 'CodeBlock', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Subtitle', + 'Q', 'Em', 'Strong', 'I', 'Small', 'Mark', 'Del', 'Ins', 'Sub', 'Sup', 'Blockquote', 'Caption', 'Cite', + 'Time', 'Address', 'Abbr', 'Dfn', 'Kbd', 'Samp', 'Var', 'Figure', 'Details', 'Summary', 'Data', 'Meter', 'S', + 'U', 'Output', 'PicSumImg', 'AccordionItem', 'Accordion', 'ButtonT', 'Button', 'ContainerT', 'BackgroundT', + 'Container', 'Titled', 'DividerT', 'Divider', 'DividerSplit', 'DividerLine', 'Article', 'ArticleTitle', + 'ArticleMeta', 'SectionT', 'Section', 'Form', 'Fieldset', 'Legend', 'Input', 'Radio', 'CheckboxX', 'Range', + 'TextArea', 'Switch', 'Upload', 'UploadZone', 'FormLabel', 'LabelT', 'Label', 'UkFormSection', + 'GenericLabelInput', 'LabelInput', 'LabelTextArea', 'LabelSwitch', 'LabelRadio', 'LabelCheckboxX', 'Options', + 'Select', 'LabelSelect', 'LabelRange', 'AT', 'ListT', 'ModalContainer', 'ModalDialog', 'ModalHeader', + 'ModalBody', 'ModalFooter', 'ModalTitle', 'ModalCloseButton', 'Modal', 'Placeholder', 'Progress', 'UkIcon', + 'UkIconLink', 'DiceBearAvatar', 'Center', 'FlexT', 'Grid', 'DivFullySpaced', 'DivCentered', 'DivLAligned', + 'DivRAligned', 'DivVStacked', 'DivHStacked', 'NavT', 'NavContainer', 'NavParentLi', 'NavDividerLi', + 'NavHeaderLi', 'NavSubtitle', 'NavCloseLi', 'ScrollspyT', 'NavBar', 'SliderContainer', 'SliderItems', + 'SliderNav', 'Slider', 'DropDownNavContainer', 'TabContainer', 'CardT', 'CardTitle', 'CardHeader', + 'CardBody', 'CardFooter', 'CardContainer', 'Card', 'TableT', 'Table', 'Td', 'Th', 'Tbody', 'TableFromLists', + 'TableFromDicts', 'apply_classes', 'FrankenRenderer', 'render_md', 'ThemePicker', 'LightboxContainer', + 'LightboxItem', 'ApexChart'] + +# %% ../nbs/02_franken.ipynb +import fasthtml.common as fh +from .foundations import * +from fasthtml.common import Div, P, Span, FT +from enum import Enum, auto +from fasthtml.components import Uk_select,Uk_input_tag,Uk_icon,Uk_input_range, Uk_chart +from functools import partial +from itertools import zip_longest +from typing import Union, Tuple, Optional, Sequence +from fastcore.all import * +import copy, re, httpx, os +import pathlib +from mistletoe.html_renderer import HTMLRenderer +from mistletoe.span_token import Image +import mistletoe +from lxml import html, etree +import fasthtml.components as fh_comp +import json + +# %% ../nbs/02_franken.ipynb +class TextT(VEnum): + 'Text Styles from https://franken-ui.dev/docs/text' + def _generate_next_value_(name, start, count, last_values): + return str2ukcls('text', name) + + paragraph = "uk-paragraph" + # Text Style + lead,meta, gray, italic= auto(), auto(), 'text-gray-500 dark:text-gray-200', 'italic' + # Text Size + xs, sm, lg, xl = 'text-xs', 'text-sm', 'text-lg', 'text-xl' + # Text Weight + light, normal, medium, bold, extrabold = 'font-light','font-normal','font-medium','font-bold','font-extrabold' + # Text Color + muted,primary,secondary = 'text-gray-500 dark:text-gray-200', 'text-primary', 'text-secondary' + success,warning, error, info = 'text-success', 'text-warning', 'text-error', 'text-info' + # Text Alignment + left, right,center = "text-left","text-right","text-center" + justify, start, end = "text-justify","text-start","text-end" + # Vertical Alignment + top,middle,bottom = 'align-top','align-middle','align-bottom' + # Text Wrapping + truncate,break_,nowrap = 'uk-text-truncate','uk-text-break', 'uk-text-nowrap' + # other + underline = 'underline' + highlight = 'bg-yellow-200 dark:bg-yellow-800 text-black' +class TextPresets(VEnum): + 'Common Typography Presets' + muted_sm = TextT.muted+TextT.sm + muted_lg = TextT.muted+TextT.lg + + bold_sm = TextT.bold+TextT.sm + bold_lg = TextT.bold+TextT.lg + + md_weight_sm = stringify((TextT.sm, TextT.medium)) + md_weight_muted = stringify((TextT.medium, TextT.muted)) + +# %% ../nbs/02_franken.ipynb +def CodeSpan(*c, # Contents of CodeSpan tag (inline text code snippets) + cls=(), # Classes in addition to CodeSpan styling + **kwargs # Additional args for CodeSpan tag + )->FT: # Code(..., cls='uk-codespan') + "A CodeSpan with Styling" + return fh.Code(*c, cls=('uk-codespan', stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def CodeBlock(*c: str, # Contents of Code tag (often text) + cls: Enum | str | tuple = (), # Classes for the outer container + code_cls: Enum | str | tuple = (), # Classes for the code tag + **kwargs # Additional args for Code tag + ) -> FT: # Div(Pre(Code(..., cls='uk-codeblock), cls='multiple tailwind styles'), cls='uk-block') + "CodeBlock with Styling" + return Div( + Pre(Code(*c, cls=('uk-codeblock', stringify(code_cls)), **kwargs), + cls=(f'bg-gray-100 dark:bg-gray-800 {TextT.gray} p-0.4 rounded text-sm font-mono')), +# cls=('bg-gray-100 dark:bg-gray-800 dark:text-gray-200 p-0.4 rounded text-sm font-mono')), + cls=('uk-block', stringify(cls))) + +# %% ../nbs/02_franken.ipynb +def H1(*c:FT|str, # Contents of H1 tag (often text) + cls:Enum|str|tuple=(), # Classes in addition to H1 styling + **kwargs # Additional args for H1 tag + )->FT: # H1(..., cls='uk-h1') + "H1 with styling and appropriate size" + return fh.H1(*c, cls=('uk-h1',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def H2(*c:FT|str, # Contents of H2 tag (often text) + cls:Enum|str|tuple=(), # Classes in addition to H2 styling + **kwargs # Additional args for H2 tag + )->FT: # H2(..., cls='uk-h2') + "H2 with styling and appropriate size" + return fh.H2(*c, cls=('uk-h2',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def H3(*c:FT|str, # Contents of H3 tag (often text) + cls:Enum|str|tuple=(), # Classes in addition to H3 styling + **kwargs # Additional args for H3 tag + )->FT: # H3(..., cls='uk-h3') + "H3 with styling and appropriate size" + return fh.H3(*c, cls=('uk-h3',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def H4(*c:FT|str, # Contents of H4 tag (often text) + cls:Enum|str|tuple=(), # Classes in addition to H4 styling + **kwargs # Additional args for H4 tag + )->FT: # H4(..., cls='uk-h4') + "H4 with styling and appropriate size" + return fh.H4(*c, cls=('uk-h4',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def H5(*c:FT|str, # Contents of H5 tag (often text) + cls:Enum|str|tuple=(), # Classes in addition to H5 styling + **kwargs # Additional args for H5 tag + )->FT: # H5(..., cls='text-lg font-semibold') + "H5 with styling and appropriate size" + return fh.H5(*c, cls=('text-lg font-semibold',stringify(cls)), **kwargs) + +def H6(*c:FT|str, # Contents of H6 tag (often text) + cls:Enum|str|tuple=(), # Classes in addition to H6 styling + **kwargs # Additional args for H6 tag + )->FT: # H6(..., cls='text-base font-semibold') + "H6 with styling and appropriate size" + return fh.H6(*c, cls=('text-base font-semibold',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Subtitle(*c:FT|str, # Contents of P tag (often text) + cls:Enum|str|tuple='mt-1.5', # Additional classes + **kwargs # Additional args for P tag + )->FT: + "Styled muted_sm text designed to go under Headings and Titles" + return fh.P(*c, cls=(TextPresets.muted_sm, stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Q(*c:FT|str, # Contents of Q tag (quote) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Q tag + )->FT: + "Styled quotation mark" + return fh.Q(*c, cls=(TextT.italic,TextT.lg, stringify(cls)), **kwargs) + +def Em(*c:FT|str, # Contents of Em tag (emphasis) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Em tag + )->FT: + "Styled emphasis text" + return fh.Em(*c, cls=(TextT.medium, stringify(cls)), **kwargs) + +def Strong(*c:FT|str, # Contents of Strong tag + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Strong tag + )->FT: + "Styled strong text" + return fh.Strong(*c, cls=(TextT.bold, stringify(cls)), **kwargs) + +def I(*c:FT|str, # Contents of I tag (italics) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for I tag + )->FT: + "Styled italic text" + return fh.I(*c, cls=(TextT.italic, stringify(cls)), **kwargs) + +def Small(*c:FT|str, # Contents of Small tag + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Small tag + )->FT: + "Styled small text" + return fh.Small(*c, cls=(TextT.sm, stringify(cls)), **kwargs) + +def Mark(*c:FT|str, # Contents of Mark tag (highlighted text) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Mark tag + )->FT: + "Styled highlighted text" + return fh.Mark(*c, cls=(TextT.highlight, stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Del(*c:FT|str, # Contents of Del tag (deleted text) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Del tag + )->FT: + "Styled deleted text" + return fh.Del(*c, cls=('line-through', TextT.gray, stringify(cls)), **kwargs) + +def Ins(*c:FT|str, # Contents of Ins tag (inserted text) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Ins tag + )->FT: + "Styled inserted text" + return fh.Ins(*c, cls=(TextT.underline+' text-green-600', stringify(cls)), **kwargs) + +def Sub(*c:FT|str, # Contents of Sub tag (subscript) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Sub tag + )->FT: + "Styled subscript text" + return fh.Sub(*c, cls=(TextT.sm+' -bottom-1 relative', stringify(cls)), **kwargs) + +def Sup(*c:FT|str, # Contents of Sup tag (superscript) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Sup tag + )->FT: + "Styled superscript text" + return fh.Sup(*c, cls=(TextT.sm+' -top-1 relative', stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Blockquote(*c:FT|str, # Contents of Blockquote tag (often text) + cls:Enum|str|tuple=(), # Classes in addition to Blockquote styling + **kwargs # Additional args for Blockquote tag + )->FT: # Blockquote(..., cls='uk-blockquote') + "Blockquote with Styling" + return fh.Blockquote(*c, cls=('uk-blockquote',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Caption(*c:FT|str, cls:Enum|str|tuple=(), **kwargs)->FT: + "Styled caption text" + return fh.Caption( + Span(*c, cls=(TextT.gray, TextT.sm, stringify(cls))), + **kwargs) + +# %% ../nbs/02_franken.ipynb +def Cite(*c:FT|str, # Contents of Cite tag + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Cite tag + )->FT: + "Styled citation text" + return fh.Cite(*c, cls=(TextT.italic, TextT.gray, stringify(cls)), **kwargs) + +def Time(*c:FT|str, # Contents of Time tag + cls:Enum|str|tuple=(), # Additional classes + datetime:str=None, # datetime attribute + **kwargs # Additional args for Time tag + )->FT: + "Styled time element" + if datetime: kwargs['datetime'] = datetime + return fh.Time(*c, cls=(TextT.gray, stringify(cls)), **kwargs) + +def Address(*c:FT|str, # Contents of Address tag + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Address tag + )->FT: + "Styled address element" + return fh.Address(*c, cls=(TextT.italic, stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Abbr(*c:FT|str, # Contents of Abbr tag + cls:Enum|str|tuple=(), # Additional classes + title:str=None, # Title attribute for abbreviation + **kwargs # Additional args for Abbr tag + )->FT: + "Styled abbreviation with dotted underline" + if title: kwargs['title'] = title + return fh.Abbr(*c, cls=('border-b border-dotted border-secondary hover:cursor-help', stringify(cls)), **kwargs) + +def Dfn(*c:FT|str, # Contents of Dfn tag (definition) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Dfn tag + )->FT: + "Styled definition term with italic and medium weight" + return fh.Dfn(*c, cls=(TextT.medium + TextT.italic + TextT.gray, stringify(cls)), **kwargs) + +def Kbd(*c:FT|str, # Contents of Kbd tag (keyboard input) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Kbd tag + )->FT: + "Styled keyboard input with subtle background" + return fh.Kbd(*c, cls=('font-mono px-1.5 py-0.5 text-sm bg-secondary border border-gray-300 dark:border-gray-600 rounded shadow-sm', stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Samp(*c:FT|str, # Contents of Samp tag (sample output) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Samp tag + )->FT: + "Styled sample output with subtle background" + return fh.Samp(*c, cls=('font-mono bg-secondary px-1 rounded', TextT.gray, stringify(cls)), **kwargs) + +def Var(*c:FT|str, # Contents of Var tag (variable) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Var tag + )->FT: + "Styled variable with italic monospace" + return fh.Var(*c, cls=('font-mono',TextT.italic + TextT.gray, stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Figure(*c:FT|str, # Contents of Figure tag + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Figure tag + )->FT: + "Styled figure container with card-like appearance" + return fh.Figure(*c, cls=('p-4 my-4 border border-gray-200 dark:border-gray-800 rounded-lg shadow-sm bg-card', stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Details(*c:FT|str, # Contents of Details tag + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Details tag + )->FT: + "Styled details element" + return fh.Details(*c, cls=('border border-secondary rounded-lg', stringify(cls)), **kwargs) + +def Summary(*c:FT|str, # Contents of Summary tag + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Summary tag + )->FT: + "Styled summary element" + return fh.Summary(*c, cls=(TextT.medium + ' p-3 hover:bg-secondary cursor-pointer', stringify(cls)), **kwargs) + +def Data(*c:FT|str, # Contents of Data tag + value:str=None, # Value attribute + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Data tag + )->FT: + "Styled data element" + if value: kwargs['value'] = value + return fh.Data(*c, cls=('font-mono text-sm bg-secondary px-1 rounded', stringify(cls)), **kwargs) + +def Meter(*c:FT|str, # Contents of Meter tag + value:float=None, # Current value + min:float=None, # Minimum value + max:float=None, # Maximum value + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Meter tag + )->FT: + "Styled meter element" + if value is not None: kwargs['value'] = value + if min is not None: kwargs['min'] = min + if max is not None: kwargs['max'] = max + return fh.Meter(*c, cls=('w-full h-2 bg-secondary rounded', stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def S(*c:FT|str, # Contents of S tag (strikethrough) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for S tag + )->FT: + "Styled strikethrough text (different semantic meaning from Del)" + return fh.S(*c, cls=('line-through', TextT.gray, stringify(cls)), **kwargs) + +def U(*c:FT|str, # Contents of U tag (unarticulated annotation) + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for U tag + )->FT: + "Styled underline (for proper names in Chinese, proper spelling etc)" + return fh.U(*c, cls=(TextT.underline, stringify(cls)), **kwargs) + +def Output(*c:FT|str, # Contents of Output tag + form:str=None, # ID of form this output belongs to + for_:str=None, # IDs of elements this output is for + cls:Enum|str|tuple=(), # Additional classes + **kwargs # Additional args for Output tag + )->FT: + "Styled output element for form results" + if form: kwargs['form'] = form + if for_: kwargs['for'] = for_ # Note: 'for' is reserved in Python + return fh.Output(*c, cls=('font-mono bg-secondary px-2 py-1 rounded', + stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def PicSumImg(h:int=200, # Height in pixels + w:int=200, # Width in pixels + id:int=None, # Optional specific image ID to use + grayscale:bool=False, # Whether to return grayscale version + blur:int=None, # Optional blur amount (1-10) + **kwargs # Additional args for Img tag + )->FT: # Img tag with picsum image + "Creates a placeholder image using https://picsum.photos/" + url = f"https://picsum.photos" + if id is not None: url = f"{url}/id/{id}" + url = f"{url}/{w}/{h}" + if grayscale: url = f"{url}?grayscale" + if blur is not None: + url = f"{url}{'?' if not grayscale else '&'}blur={max(1,min(10,blur))}" + return fh.Img(src=url, loading="lazy", **kwargs) + +# %% ../nbs/02_franken.ipynb +def AccordionItem(title: Union[str, FT], # Content for the accordion item title + *c: FT, # Content to display when the item is open + cls: Union[str, Enum, tuple] = (), # Additional classes for the outer `Li` container + title_cls: Union[str, Enum, tuple] = ('flex justify-between items-center w-full',), # Additional classes for the title `A` tag + content_cls: Union[str, Enum, tuple] = (), # Additional classes for the content `Div` + open: bool = False, # Whether this item should be open by default + li_kwargs: Optional[Dict] = None, # Additional attributes for the outer `Li` tag + a_kwargs: Optional[Dict] = None, # Additional attributes for the title `A` tag + div_kwargs: Optional[Dict] = None # Additional attributes for the content `Div` tag + ) -> FT: # Li(A(title, Span(Icon, Icon)), Div(content)) + "Creates a single item for use within an Accordion component, handling title, content, and open state." + li_attrs, a_attrs, div_attrs = li_kwargs or {}, a_kwargs or {}, div_kwargs or {} + li_classes = ['group', stringify(cls)] + if open: li_classes.append('uk-open') + final_li_cls = stringify(li_classes) + combined_title_cls = stringify(('uk-accordion-title', stringify(title_cls))) + content_classes = stringify(('uk-accordion-content', stringify(content_cls))) + if 'href' not in a_attrs: a_attrs['href'] = '#' + icon_container = Span( + UkIcon("chevron-down", cls="block group-[.uk-open]:hidden h-5 w-5"), + UkIcon("chevron-up", cls="hidden group-[.uk-open]:block h-5 w-5") + ) + return fh.Li( + fh.A(title, icon_container, cls=combined_title_cls, **a_attrs), + fh.Div(*c, cls=content_classes, **div_attrs), + cls=final_li_cls, + **li_attrs + ) + +# %% ../nbs/02_franken.ipynb +def Accordion(*c: 'AccordionItem', # One or more `AccordionItem` components + cls: Union[str, Enum, tuple] = (), # Additional classes for the container (`Ul` or `Div`) + multiple: Optional[bool] = None, # Allow multiple items to be open simultaneously (UIkit option) + collapsible: Optional[bool] = None, # Allow all items to be closed (UIkit option, default True) + animation: Optional[bool] = None, # Enable/disable animation (UIkit option, default True) + duration: Optional[int] = None, # Animation duration in ms (UIkit option, default 200) + active: Optional[int] = None, # Index (0-based) of the item to be open by default (UIkit option) + transition: Optional[str] = None, # Animation transition timing function (UIkit option, e.g., 'ease-out') + tag: str = 'ul', # HTML tag for the container ('ul' or 'div') + **kwargs # Additional attributes for the container tag (e.g., id) + ) -> FT: # Ul(*items...) or Div(*items...) + """ + Creates a styled Accordion container using accordion component. + """ + opts = [] + if multiple is not None: opts.append(f"multiple: {str(multiple).lower()}") + if collapsible is not None: opts.append(f"collapsible: {str(collapsible).lower()}") + if animation is not None: opts.append(f"animation: {str(animation).lower()}") + if duration is not None: opts.append(f"duration: {duration}") + if active is not None: opts.append(f"active: {active}") + if transition is not None: opts.append(f"transition: {transition}") + uk_attr_val = "; ".join(opts) if opts else "" + kwargs['uk-accordion'] = uk_attr_val + container_tag = fh.Ul if tag.lower() == 'ul' else fh.Div + final_cls = stringify(cls) + return container_tag(*c, cls=final_cls, **kwargs) + +# %% ../nbs/02_franken.ipynb +class ButtonT(VEnum): + "Options for styling Buttons" + def _generate_next_value_(name, start, count, last_values): return str2ukcls('btn', name) + default, ghost, primary = auto(),auto(),auto() + secondary, destructive = auto(), auto() + text, link = auto(), auto() + xs, sm, lg, xl = auto(), auto(), auto(), auto() + icon = auto() + +# %% ../nbs/02_franken.ipynb +def Button(*c: Union[str, FT], # Contents of `Button` tag (often text) + cls: Union[str, Enum]=ButtonT.default, # Classes in addition to `Button` styling (use `ButtonT` for built in styles) + submit=True, # Whether the button should submit a form + **kwargs # Additional args for `Button` tag + ) -> FT: # Button(..., cls='uk-btn') + "Button with Styling (defaults to `submit` for form submission)" + if 'type' not in kwargs: kwargs['type'] = 'submit' if submit else 'button' + return fh.Button(*c, cls=('uk-btn', stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +class ContainerT(VEnum): + 'Max width container sizes from https://franken-ui.dev/docs/container' + def _generate_next_value_(name, start, count, last_values): return str2ukcls('container', name) + xs = auto() + sm = auto() + lg = auto() + xl = auto() + expand = auto() + +# %% ../nbs/02_franken.ipynb +class BackgroundT(VEnum): + def _generate_next_value_(name, start, count, last_values): return str2ukcls('background', name) + muted = auto() + primary = auto() + secondary = auto() + default = auto() + +# %% ../nbs/02_franken.ipynb +def Container(*c, # Contents of Container tag (often other FT Components) + cls=('mt-5', ContainerT.xl), # Classes in addition to Container styling + **kwargs # Additional args for Container (`Div` tag) + )->FT: # Container(..., cls='uk-container') + "Div to be used as a container that often wraps large sections or a page of content" + return Div(*c, cls=('uk-container',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Titled(title:str="FastHTML app", # Title of the page + *c, # Contents of the page (often other tags) + cls=ContainerT.xl, # Classes in addition to Container styling + **kwargs # Additional args for Container (`Div` tag) + )->FT: # Title, Main(Container(H1(title), content)) + "Creates a standard page structure for titled page. Main(Container(title, content))" + return fh.Title(title), fh.Main(Container(H1(title), *c, cls=cls, **kwargs)) + +# %% ../nbs/02_franken.ipynb +class DividerT(VEnum): + "Divider Styles from https://franken-ui.dev/docs/divider" + def _generate_next_value_(name, start, count, last_values): return str2ukcls('divider', name) + icon=auto() + sm=auto() + vertical=auto() + +# %% ../nbs/02_franken.ipynb +def Divider(*c, # contents of Divider tag (often nothing) + cls=('my-4', DividerT.icon), # Classes in addition to Divider styling + **kwargs # Additional args for Divider tag + )->FT: # Hr(..., cls='uk-divider-icon') or Div(..., cls='uk-divider-vertical') + "Divider with default styling and margin" + cls = stringify(cls) + container = Div if 'uk-divider-vertical' in cls else Hr + return container(*c, cls=cls, **kwargs) + +# %% ../nbs/02_franken.ipynb +def DividerSplit(*c, cls=(), line_cls=(), text_cls=()): + "Creates a simple horizontal line divider with configurable thickness and vertical spacing" + cls, line_cls, text_cls = map(stringify,(cls, line_cls, text_cls)) + return Div(cls='relative ' + cls)( + Div(cls="absolute inset-0 flex items-center " + line_cls)(Span(cls="w-full border-t border-border")), + Div(cls="relative flex justify-center " + text_cls)(Span(cls="bg-background px-2 ")(*c))) + +# %% ../nbs/02_franken.ipynb +def DividerLine(lwidth=2, y_space=4): return Hr(cls=f"my-{y_space} h-[{lwidth}px] w-full bg-secondary") + +# %% ../nbs/02_franken.ipynb +def Article(*c, # contents of Article tag (often other tags) + cls=(), # Classes in addition to Article styling + **kwargs # Additional args for Article tag + )->FT: # Article(..., cls='uk-article') + "A styled article container for blog posts or similar content" + return fh.Article(*c, cls=('uk-article',stringify(cls)), **kwargs) + +def ArticleTitle(*c, # contents of ArticleTitle tag (often other tags) + cls=(), # Classes in addition to ArticleTitle styling + **kwargs # Additional args for ArticleTitle tag + )->FT: # H1(..., cls='uk-article-title') + "A title component for use within an Article" + return H1(*c, cls=('uk-article-title',stringify(cls)), **kwargs) + +def ArticleMeta(*c, # contents of ArticleMeta tag (often other tags) + cls=(), # Classes in addition to ArticleMeta styling + **kwargs # Additional args for ArticleMeta tag + )->FT: # P(..., cls='uk-article-meta') + "A metadata component for use within an Article showing things like date, author etc" + return P(*c, cls=('uk-article-meta',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +class SectionT(VEnum): + 'Section styles from https://franken-ui.dev/docs/section' + def _generate_next_value_(name, start, count, last_values): return str2ukcls('section', name) + default = auto() + muted = auto() + primary = auto() + secondary = auto() + xs = 'uk-section-xsmall' + sm = 'uk-section-small' + lg = 'uk-section-large' + xl = 'uk-section-xlarge' + remove_vertical = auto() + +# %% ../nbs/02_franken.ipynb +def Section(*c, # contents of Section tag (often other tags) + cls=(), # Classes in addition to Section styling + **kwargs # Additional args for Section tag + )->FT: # Div(..., cls='uk-section') + "Section with styling and margins" + return fh.Div(*c, cls=('uk-section',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Form(*c, # contents of Form tag (often Buttons, FormLabels, and LabelInputs) + cls='space-y-3', # Classes in addition to Form styling (default is 'space-y-3' to prevent scrunched up form elements) + **kwargs # Additional args for Form tag + )->FT: # Form(..., cls='space-y-3') + "A Form with default spacing between form elements" + return fh.Form(*c, cls=stringify(cls), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Fieldset(*c, # contents of Fieldset tag (often other tags) + cls='flex', # Classes in addition to Fieldset styling + **kwargs # Additional args for Fieldset tag + )->FT: # Fieldset(..., cls='uk-fieldset') + "A Fieldset with default styling" + return fh.Fieldset(*c, cls=('uk-fieldset',stringify(cls)), **kwargs) + +def Legend(*c, # contents of Legend tag (often other tags) + cls=(), # Classes in addition to Legend styling + **kwargs # Additional args for Legend tag + )->FT: # Legend(..., cls='uk-legend') + "A Legend with default styling" + return fh.Legend(*c, cls=('uk-legend',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Input(*c, # contents of Input tag (often nothing) + cls=(), # Classes in addition to Input styling + **kwargs # Additional args for Input tag + )->FT: # Input(..., cls='uk-input') + "An Input with default styling" + return fh.Input(*c, cls=('uk-input',stringify(cls)), **kwargs) + +def Radio(*c, # contents of Radio tag (often nothing) + cls=(), # Classes in addition to Radio styling + **kwargs # Additional args for Radio tag + )->FT: # Input(..., cls='uk-radio', type='radio') + "A Radio with default styling" + return fh.Input(*c, cls=('uk-radio',stringify(cls)), type='radio', **kwargs) +def CheckboxX(*c, # contents of CheckboxX tag (often nothing) + cls=(), # Classes in addition to CheckboxX styling + **kwargs # Additional args for CheckboxX tag + )->FT: # Input(..., cls='uk-checkbox', type='checkbox') + "A Checkbox with default styling" + return fh.Input(*c, cls=('uk-checkbox',stringify(cls)), type='checkbox', **kwargs) + +# %% ../nbs/02_franken.ipynb +def Range(*c, # contents of Range tag (often nothing) + value='', + label=True, + min=None, + max=None, + step=None, + cls=(), # Classes in addition to Range styling + **kwargs # Additional args for Range tag + )->FT: # Input(..., cls='uk-range', type='range') + "A Range with default styling" + return Uk_input_range(*c, min=min, label=label, max=max, value=value, step=step, multiple=len(value.split(','))>1, cls=('uk-range',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def TextArea(*c, # contents of TextArea tag (often text) + cls=(), # Classes in addition to TextArea styling + **kwargs # Additional args for TextArea tag + )->FT: # TextArea(..., cls='uk-textarea') + "A Textarea with default styling" + return fh.Textarea(*c, cls=('uk-textarea',stringify(cls)), **kwargs) +def Switch(*c, # contents of Switch tag (often nothing) + cls=(), # Classes in addition to Switch styling + **kwargs # Additional args for Switch tag + )->FT: # Input(..., cls='uk-toggle-switch uk-toggle-switch-primary min-w-9', type='checkbox') + "A Switch with default styling" + return fh.Input(*c, cls=('uk-toggle-switch uk-toggle-switch-primary min-w-9',stringify(cls)), type='checkbox', **kwargs) + +# %% ../nbs/02_franken.ipynb +def Upload(*c, # Contents of Upload tag button (often text) + cls=(), # Classes in addition to Upload styling + multiple=False, # Whether to allow multiple file selection + accept=None, # File types to accept (e.g. 'image/*') + button_cls=ButtonT.default, # Classes for the button + id=None, # ID for the file input + name=None, # Name for the file input + **kwargs # Additional args for the outer div + )->FT: # Div(Input(type='file'), Button(...)) + "A file upload component with default styling" + input_kwargs = {'type': 'file', 'multiple': multiple} + if accept: input_kwargs['accept'] = accept + if id: input_kwargs['id'] = id + if name: input_kwargs['name'] = name + return Div( + fh.Input(**input_kwargs), + Button(*c, cls=button_cls, submit=False, tabindex="-1"), + cls=('w-full js-upload', stringify(cls)), + uk_form_custom=True) + +def UploadZone(*c, # Contents of UploadZone tag (often text or other tags) + cls=(), # Classes in addition to UploadZone styling + multiple=False, # Whether to allow multiple file selection + accept=None, # File types to accept (e.g. 'image/*') + id=None, # ID for the file input + name=None, # Name for the file input + **kwargs # Additional args for the outer div + )->FT: + "A file drop zone component with default styling" + input_kwargs = {'type': 'file', 'multiple': multiple} + if accept: input_kwargs['accept'] = accept + if id: input_kwargs['id'] = id + if name: input_kwargs['name'] = name + return Div( + Div(fh.Input(**input_kwargs), + Span(*c), + uk_form_custom=True, + cls='w-full'), + cls=('js-upload uk-placeholder uk-text-center', stringify(cls)), + **kwargs) + +# %% ../nbs/02_franken.ipynb +def FormLabel(*c, # contents of FormLabel tag (often text) + cls=(), # Classes in addition to FormLabel styling + **kwargs # Additional args for FormLabel tag + )->FT: # Label(..., cls='uk-form-label') + "A Label with default styling" + return fh.Label(*c, cls=('uk-form-label',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +class LabelT(VEnum): + def _generate_next_value_(name, start, count, last_values): return str2ukcls('label', name) + primary = auto() + secondary = auto() + destructive = auto() + +# %% ../nbs/02_franken.ipynb +def Label(*c, # contents of Label tag (often text) + cls=(), # Classes in addition to Label styling + **kwargs # Additional args for Label tag + )->FT: # Label(..., cls='uk-label') + "FrankenUI labels, which look like pills" + return fh.Label(*c, cls=('uk-label',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def UkFormSection(title, description, *c, button_txt='Update', outer_margin=6, inner_margin=6): + "A form section with a title, description and optional button" + return Div(cls=f'space-y-{inner_margin} py-{outer_margin}')( + Div(H3(title), P(description, cls=TextPresets.muted_sm)), + DividerSplit(), *c, + Div(Button(button_txt, cls=ButtonT.primary)) if button_txt else None) + +# %% ../nbs/02_franken.ipynb +def GenericLabelInput( + label:str|FT, # FormLabel content (often text) + lbl_cls='', # Additional classes for FormLabel + input_cls='', # Additional classes for user input (Input, Select, etc) + container=Div, # Container to wrap label and input in (default is Div) + cls='', # Classes on container (default is '') + id=None, # id for label and input (`id`, `name` and `for` attributes are set to this value). If `label` is str, this defaults to `label.lower()` + input_fn=noop, # User input FT component + **kwargs # Additional args for user input + ): + "`Div(Label,Input)` component with Uk styling injected appropriately. Generally you should higher level API, such as `LabelInput` which is created for you in this library" + if not id and isinstance(label, str): id = label.lower() + if isinstance(label, str) or label.tag != 'label': + label = FormLabel(cls=stringify(lbl_cls), fr=id)(label) + inp = input_fn(id=id, cls=stringify(input_cls), **kwargs) + if container: return container(label, inp, cls=stringify(cls)) + return label, inp + +# %% ../nbs/02_franken.ipynb +def LabelInput(label:str|FT, # FormLabel content (often text) + lbl_cls='', # Additional classes for `FormLabel` + input_cls='', # Additional classes for `Input` + cls='space-y-2', # Classes on container (default is `'space-y-2'` to prevent scrunched up form elements) + id='', # id for `FormLabel` and `Input` (`id`, `name` and `for` attributes are set to this value) + **kwargs # Additional args for `Input` + )->FT: # Div(cls='space-y-2')(`FormLabel`, `Input`) + "A `FormLabel` and `Input` pair that provides default spacing and links/names them based on id" + return GenericLabelInput(label=label, lbl_cls=lbl_cls, input_cls=input_cls, + container=Div, cls=cls, id=id, input_fn=Input, **kwargs) + +# %% ../nbs/02_franken.ipynb +def LabelTextArea(label:str|FT, # FormLabel content (often text) + value='', # Value for the textarea + lbl_cls='', # Additional classes for `FormLabel` + input_cls='', # Additional classes for `TextArea` + cls='space-y-2', # Classes on container (default is `'space-y-2'` to prevent scrunched up form elements) + id='', # id for `FormLabel` and `TextArea` (`id`, `name` and `for` attributes are set to this value) + **kwargs # Additional args for `TextArea` + )->FT: # Div(cls='space-y-2')(`FormLabel`, `TextArea`) + def text_area_with_value(**kw): return TextArea(value, **kw) + return GenericLabelInput(label=label, lbl_cls=lbl_cls, input_cls=input_cls, + container=Div, cls=cls, id=id, input_fn=text_area_with_value, **kwargs) + +# %% ../nbs/02_franken.ipynb +@delegates(GenericLabelInput, but=['input_fn','cls']) +def LabelSwitch(label:str|FT, # FormLabel content (often text) + lbl_cls='', # Additional classes for `FormLabel` + input_cls='', # Additional classes for `Switch` + cls='space-x-2', # Classes on container (default is `'space-x-2'` to prevent scrunched up form elements) + id='', # id for `FormLabel` and `Switch` (`id`, `name` and `for` attributes are set to this value) + **kwargs # Additional args for `Switch` + )->FT: # Div(cls='space-y-2')(`FormLabel`, `Switch`) + return GenericLabelInput(label=label, lbl_cls=lbl_cls, input_cls=input_cls, + container=Div, cls=cls, id=id, input_fn=Switch, **kwargs) + +# %% ../nbs/02_franken.ipynb +def LabelRadio(label:str|FT, # FormLabel content (often text) + lbl_cls='', # Additional classes for `FormLabel` + input_cls='', # Additional classes for `Radio` + container=Div, # Container to wrap label and input in (default is Div) + cls='flex items-center space-x-2', # Classes on container (default is 'flex items-center space-x-2') + id='', # id for `FormLabel` and `Radio` (`id`, `name` and `for` attributes are set to this value) + **kwargs # Additional args for `Radio` + )->FT: # Div(cls='flex items-center space-x-2')(`FormLabel`, `Radio`) + "A FormLabel and Radio pair that provides default spacing and links/names them based on id" + if isinstance(label, str) or label.tag != 'label': + label = FormLabel(cls=stringify(lbl_cls), fr=id)(label) + inp = Radio(id=id, cls=stringify(input_cls), **kwargs) + if container: return container(inp, label, cls=stringify(cls)) + return inp, label + +# %% ../nbs/02_franken.ipynb +def LabelCheckboxX(label:str|FT, # FormLabel content (often text) + lbl_cls='', # Additional classes for `FormLabel` + input_cls='', # Additional classes for `CheckboxX` + container=Div, # Container to wrap label and input in (default is Div) + cls='flex items-center space-x-2', # Classes on container (default is 'flex items-center space-x-2') + id='', # id for `FormLabel` and `CheckboxX` (`id`, `name` and `for` attributes are set to this value) + **kwargs # Additional args for `CheckboxX` + )->FT: # Div(cls='flex items-center space-x-2')(`FormLabel`, `CheckboxX`) + "A FormLabel and CheckboxX pair that provides default spacing and links/names them based on id" + if not id: id = fh.unqid() + if isinstance(label, str) or label.tag != 'label': + label = FormLabel(cls=stringify(lbl_cls), fr=id)(label) + inp = CheckboxX(id=id, cls=stringify(input_cls), **kwargs) + if container: return container(inp, label, cls=stringify(cls)) + return inp, label + +# %% ../nbs/02_franken.ipynb +def Options(*c, # Content for an `Option` + selected_idx:int=None, # Index location of selected `Option` + disabled_idxs:set=None # Idex locations of disabled `Options` + ): + "Helper function to wrap things into `Option`s for use in `Select`" + return [fh.Option(o,selected=i==selected_idx, disabled=disabled_idxs and i in disabled_idxs) for i,o in enumerate(c)] + +# %% ../nbs/02_franken.ipynb +def Select(*option, # Options for the select dropdown (can use `Options` helper function to create) + inp_cls=(), # Additional classes for the select input + cls=('h-10',), # Classes for the outer div (default h-10 for consistent height) + cls_custom='button: uk-input-fake; dropdown: w-full', # Classes for the Uk_Select web component + id="", # ID for the select input + name="", # Name attribute for the select input + placeholder="", # Placeholder text for the select input + searchable=False, # Whether the select should be searchable + insertable=False, # Whether to allow user-defined options to be added + select_kwargs=None, # Additional Arguments passed to Select + + **kwargs # Additional arguments passed to Uk_select + ): + "Creates a select dropdown with uk styling and option for adding a search box" + inp_cls, cls, cls_custom= map(stringify, (inp_cls, cls, cls_custom)) + select_kwargs = ifnone(select_kwargs, {}) + + if 'hx_trigger' not in kwargs: kwargs['hx_trigger']='' + if 'change' in kwargs['hx_trigger']: + if not id: id = fh.unqid() + kwargs['hx_trigger'] = kwargs['hx_trigger'].replace('changed', f'uk-select:input from:#{id}') + kwargs['hx_trigger'] = kwargs['hx_trigger'].replace('change', f'uk-select:input from:#{id}') + + if 'delay' not in kwargs['hx_trigger']: + kwargs['hx_trigger'] += ' delay:100ms' + + if 'hx_include' not in kwargs: kwargs['hx_include']='' + kwargs['hx_include'] += ' this' + kwargs['hx_include'] = kwargs['hx_include'].strip() + + if id and not name: name = id + + uk_select = Uk_select(fh.Select(*option, hidden=True, + **select_kwargs, + + ), + cls_custom=cls_custom, + searchable=searchable, + placeholder=placeholder, + insertable=insertable, + cls=inp_cls, + id=id, + name=name, + **kwargs + ) + + return Div(cls=cls)(uk_select) + +# %% ../nbs/02_franken.ipynb +def LabelSelect(*option, # Options for the select dropdown (can use `Options` helper function to create) + label=(), # String or FT component for the label + lbl_cls=(), # Additional classes for the label + inp_cls=(), # Additional classes for the select input + cls=('space-y-2',), # Classes for the outer div + id="", # ID for the select input + name="", # Name attribute for the select input + placeholder="", # Placeholder text for the select input + searchable=False, # Whether the select should be searchable + select_kwargs=None, # Additional Arguments passed to Select + **kwargs): # Additional arguments passed to Select + "A FormLabel and Select pair that provides default spacing and links/names them based on id" + lbl_cls, inp_cls, cls = map(stringify, (lbl_cls, inp_cls, cls)) + select_kwargs = ifnone(select_kwargs, {}) + if label: + lbl = FormLabel(cls=f'{lbl_cls}', fr=id)(label) + select = Select(*option, inp_cls=inp_cls, id=id, name=name if name else id, + placeholder=placeholder, searchable=searchable, select_kwargs=select_kwargs, **kwargs) + return Div(cls=cls)(lbl, select) if label else Div(cls=cls)(select) + +# %% ../nbs/02_franken.ipynb +@delegates(GenericLabelInput, but=['input_fn','cls']) +def LabelRange(label:str|FT, # FormLabel content (often text) + lbl_cls='', # Additional classes for `FormLabel` + input_cls='', # Additional classes for `Range` + cls='space-y-6', # Classes on container (default is `'space-y-2'` to prevent scrunched up form elements) + id='', # id for `FormLabel` and `Range` (`id`, `name` and `for` attributes are set to this value) + value='', # Value for the range input + min=None, # Minimum value + max=None, # Maximum value + step=None, # Step size + label_range=True, # Whether to show the range value label (label for the `Range` component) + **kwargs # Additional args for `Range` + )->FT: # Div(cls='space-y-2')(`FormLabel`, `Range`) + "A FormLabel and Range pair that provides default spacing and links/names them based on id" + def range_with_value(**kw): + return Div(Range(value=value, min=min, max=max, step=step, label=label_range, **kw)) + return GenericLabelInput(label=label, lbl_cls=lbl_cls, input_cls=input_cls, + container=Div, cls=cls, id=id, input_fn=range_with_value, **kwargs) + +# %% ../nbs/02_franken.ipynb +class AT(VEnum): + 'Link styles from https://franken-ui.dev/docs/link' + def _generate_next_value_(name, start, count, last_values): return str2ukcls('link', name) + muted = auto() + text = auto() + reset = auto() + primary = 'uk-link text-primary hover:text-primary-focus underline' + classic = 'text-blue-600 hover:text-blue-800 underline' + +# %% ../nbs/02_franken.ipynb +class ListT(VEnum): + 'List styles using Tailwind CSS' + disc = 'list-disc list-inside' + circle = 'list-[circle] list-inside' + square = 'list-[square] list-inside' + decimal = 'uk-list uk-list-decimal' + hyphen = 'uk-list uk-list-hyphen' + bullet = 'uk-list uk-list-bullet' + divider = 'uk-list uk-list-divider' + striped = 'uk-list uk-list-striped' + +# %% ../nbs/02_franken.ipynb +def ModalContainer(*c, # Components to put in the modal (often `ModalDialog`) + cls=(), # Additional classes on the `ModalContainer` + **kwargs # Additional args for `Div` tag + )->FT: # Div(..., cls='uk-modal uk-modal-container') + "Creates a modal container that components go in" + return fh.Div(*c, cls=('uk-modal uk-modal-container',stringify(cls)), data_uk_modal=True, **kwargs) +def ModalDialog(*c, # Components to put in the `ModalDialog` (often `ModalBody`, `ModalHeader`, etc) + cls=(), # Additional classes on the `ModalDialog` + **kwargs # Additional args for `Div` tag + )->FT: # Div(..., cls='uk-modal-dialog') + "Creates a modal dialog" + return fh.Div(*c, cls=('uk-modal-dialog', stringify(cls)), **kwargs) +def ModalHeader(*c, # Components to put in the `ModalHeader` + cls=(), # Additional classes on the `ModalHeader` + **kwargs # Additional args for `Div` tag + )->FT: # Div(..., cls='uk-modal-header') + "Creates a modal header" + return fh.Div(*c, cls=('uk-modal-header', stringify(cls)), **kwargs) +def ModalBody(*c, # Components to put in the `ModalBody` (often forms, sign in buttons, images, etc.) + cls=(), # Additional classes on the `ModalBody` + **kwargs # Additional args for `Div` tag + )->FT: # Div(..., cls='uk-modal-body') + "Creates a modal body" + return fh.Div(*c, cls=('uk-modal-body', stringify(cls)), **kwargs) +def ModalFooter(*c, # Components to put in the `ModalFooter` (often buttons) + cls=(), # Additional classes on the `ModalFooter` + **kwargs # Additional args for `Div` tag + )->FT: # Div(..., cls='uk-modal-footer') + "Creates a modal footer" + return fh.Div(*c, cls=('uk-modal-footer', stringify(cls)), **kwargs) +def ModalTitle(*c, # Components to put in the `ModalTitle` (often text) + cls=(), # Additional classes on the `ModalTitle` + **kwargs # Additional args for `H2` tag + )->FT: # H2(..., cls='uk-modal-title') + "Creates a modal title" + return fh.H2(*c, cls=('uk-modal-title', stringify(cls)), **kwargs) +def ModalCloseButton(*c, # Components to put in the button (often text and/or an icon) + cls="absolute top-3 right-3", # Additional classes on the button + **kwargs # Additional args for `Button` tag + )->FT: # Button(..., cls='uk-modal-close') + "Creates a button that closes a modal with js" + cls = (stringify(cls), 'uk-modal-close') + kwargs['data-uk-close'] = True + return Button(*c, cls=(stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Modal(*c, # Components to put in the `ModalBody` (often forms, sign in buttons, images, etc.) + header=None, # Components that go in the `ModalHeader` (often a `ModalTitle`) + footer=None, # Components that go in the `ModalFooter` (often a `ModalCloseButton`) + cls=(), # Additional classes on the outermost `ModalContainer` + dialog_cls=(), # Additional classes on the `ModalDialog` + header_cls='p-6', # Additional classes on the `ModalHeader` + body_cls='space-y-6', # Additional classes on the `ModalBody` + footer_cls=(), # Additional classes on the `ModalFooter` + id='', # id for the outermost container + hx_init=False, # Initialize modal with UIKit on load (used for modals added to the DOM by HTMX) + hx_open=False, # Open modal on load (used for modals added to the DOM by HTMX) + **kwargs # Additional args for the outermost `Div` tag + )->FT: # Fully styled modal FT Component + "Creates a modal with the appropriate classes to put the boilerplate in the appropriate places for you" + if not id: id = fh.unqid() + if hx_open: kwargs["hx_on__load"] = f"UIkit.modal('#{id}').show()" + if hx_init and not hx_open: kwargs["hx_on__load"] = f"UIkit.modal('#{id}')" + if hx_open or hx_init: kwargs["hx-on:hidden"] = "this.remove()" + cls, dialog_cls, header_cls, body_cls, footer_cls = map(stringify, (cls, dialog_cls, header_cls, body_cls, footer_cls)) + res = [] + if header: res.append(ModalHeader(cls=header_cls)(header)) + res.append(ModalBody(cls=body_cls)(*c)) + if footer: res.append(ModalFooter(cls=footer_cls)(footer)) + return ModalContainer(ModalDialog(*res, cls=dialog_cls), cls=cls, id=id, **kwargs) + +# %% ../nbs/02_franken.ipynb +def Placeholder(*c, # Components to put in the placeholder + cls=(), # Additional classes on the placeholder + **kwargs # Additional args for `Div` tag + )->FT: # Div(..., cls='uk-placeholder') + "Creates a placeholder" + return fh.Div(*c, cls=('uk-placeholder',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Progress(*c, # Components to put in the progress bar (often nothing) + cls=(), # Additional classes on the progress bar + value="", # Value of the progress bar + max="100", # Max value of the progress bar (defaults to 100 for percentage) + **kwargs # Additional args for `Progress` tag + )->FT: # Progress(..., cls='uk-progress') + "Creates a progress bar" + return fh.Progress(*c, value=value, max=max, cls=('uk-progress',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def UkIcon(icon:str, # Icon name from [lucide icons](https://lucide.dev/icons/) + height:int=None, + width:int=None, + stroke_width:int=None, # Thickness of lines + cls=(), # Additional classes on the `Uk_icon` tag + **kwargs # Additional args for `Uk_icon` tag + )->FT: # a lucide icon of the specified size + "Creates an icon using lucide icons" + return Uk_icon(icon=icon, height=height, width=width, stroke_width=stroke_width, cls=cls, **kwargs) + +# %% ../nbs/02_franken.ipynb +def UkIconLink(icon:str, # Icon name from [lucide icons](https://lucide.dev/icons/) + height:int=None, + width:int=None, + stroke_width:int=None, # Thickness of lines + cls=(), # Additional classes on the icon + button:bool=False, # Whether to use a button (defaults to a link) + **kwargs # Additional args for `A` or `Button` tag + )->FT: # a lucide icon button or link of the specified size + "Creates an icon link using lucide icons" + fn = fh.Button if button else fh.A + return fn(cls=(f"uk-icon-{'button' if button else 'link'}", stringify(cls)), **kwargs)( + UkIcon(icon=icon, height=height, width=width, stroke_width=stroke_width)) + +# %% ../nbs/02_franken.ipynb +def DiceBearAvatar(seed_name:str, # Seed name (ie 'Isaac Flath') + h:int=20, # Height + w:int=20, # Width + ): # Span with Avatar + "Creates an Avatar using https://dicebear.com/" + url = 'https://api.dicebear.com/8.x/lorelei/svg?seed=' + return Span(cls=f"relative flex h-{h} w-{w} shrink-0 overflow-hidden rounded-full bg-secondary")( + fh.Img(cls=f"aspect-square h-{h} w-{w}", alt="Avatar", loading="lazy", src=f"{url}{seed_name}")) + +# %% ../nbs/02_franken.ipynb +def Center(*c, # Components to center + vertical:bool=True, # Whether to center vertically + horizontal:bool=True, # Whether to center horizontally + cls=(), # Additional classes + **kwargs # Additional args for container div + )->FT: # Div with centered contents + "Centers contents both vertically and horizontally by default" + classes = ['flex'] + if vertical: classes.append('items-center min-h-full') + if horizontal: classes.append('justify-center min-w-full') + return fh_comp.Center(*c, cls=(stringify(classes), stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +class FlexT(VEnum): + 'Flexbox modifiers using Tailwind CSS' + def _generate_next_value_(name, start, count, last_values): return name + + # Display + block = 'flex' + inline = 'inline-flex' + + # Horizontal Alignment + left = 'justify-start' + center = 'justify-center' + right = 'justify-end' + between = 'justify-between' + around = 'justify-around' + + # Vertical Alignment + stretch = 'items-stretch' + top = 'items-start' + middle = 'items-center' + bottom = 'items-end' + + # Direction + row = 'flex-row' + row_reverse = 'flex-row-reverse' + column = 'flex-col' + column_reverse = 'flex-col-reverse' + + # Wrap + nowrap = 'flex-nowrap' + wrap = 'flex-wrap' + wrap_reverse = 'flex-wrap-reverse' + +# %% ../nbs/02_franken.ipynb +def Grid(*div, # `Div` components to put in the grid + cols_min:int=1, # Minimum number of columns at any screen size + cols_max:int=4, # Maximum number of columns allowed at any screen size + cols_sm:int=None, # Number of columns on small screens + cols_md:int=None, # Number of columns on medium screens + cols_lg:int=None, # Number of columns on large screens + cols_xl:int=None, # Number of columns on extra large screens + cols:int=None, # Number of columns on all screens + cls='gap-4', # Additional classes on the grid (tip: `gap` provides spacing for grids) + **kwargs # Additional args for `Div` tag + )->FT: # Responsive grid component + "Creates a responsive grid layout with smart defaults based on content" + if cols: cols_min = cols_sm = cols_md = cols_lg = cols_xl = cols + else: + n = len(div) + cols_max = min(n, cols_max) + cols_sm = cols_sm or min(n, cols_min, cols_max) + cols_md = cols_md or min(n, cols_min+1, cols_max) + cols_lg = cols_lg or min(n, cols_min+2, cols_max) + cols_xl = cols_xl or cols_max + return Div(cls=(f'grid grid-cols-{cols_min} sm:grid-cols-{cols_sm} md:grid-cols-{cols_md} lg:grid-cols-{cols_lg} xl:grid-cols-{cols_xl}', stringify(cls)), **kwargs)(*div) + +# %% ../nbs/02_franken.ipynb +def DivFullySpaced(*c, # Components + cls='w-full',# Classes for outer div (`w-full` makes it use all available width) + **kwargs # Additional args for outer div + ): # Div with spaced components via flex classes + "Creates a flex div with it's components having as much space between them as possible" + cls = stringify(cls) + return Div(cls=(FlexT.block,FlexT.between,FlexT.middle,cls), **kwargs)(*c) + +# %% ../nbs/02_franken.ipynb +def DivCentered(*c, # Components + cls='space-y-4', # Classes for outer div (`space-y-4` provides spacing between components) + vstack=True, # Whether to stack the components vertically + **kwargs # Additional args for outer div + )->FT: # Div with components centered in it + "Creates a flex div with it's components centered in it" + cls=stringify(cls) + return Div(cls=(FlexT.block,(FlexT.column if vstack else FlexT.row),FlexT.middle,FlexT.center,cls),**kwargs)(*c) + +# %% ../nbs/02_franken.ipynb +def DivLAligned(*c, # Components + cls='space-x-4', # Classes for outer div + **kwargs # Additional args for outer div + )->FT: # Div with components aligned to the left + "Creates a flex div with it's components aligned to the left" + cls=stringify(cls) + return Div(cls=(FlexT.block,FlexT.left,FlexT.middle,cls), **kwargs)(*c) + +# %% ../nbs/02_franken.ipynb +def DivRAligned(*c, # Components + cls='space-x-4', # Classes for outer div + **kwargs # Additional args for outer div + )->FT: # Div with components aligned to the right + "Creates a flex div with it's components aligned to the right" + cls=stringify(cls) + return Div(cls=(FlexT.block,FlexT.right,FlexT.middle,cls), **kwargs)(*c) + +# %% ../nbs/02_franken.ipynb +def DivVStacked(*c, # Components + cls='space-y-4', # Additional classes on the div (tip: `space-y-4` provides spacing between components) + **kwargs # Additional args for the div + )->FT: # Div with components stacked vertically + "Creates a flex div with it's components stacked vertically" + cls=stringify(cls) + return Div(cls=(FlexT.block,FlexT.column,FlexT.middle,cls), **kwargs)(*c) + +# %% ../nbs/02_franken.ipynb +def DivHStacked(*c, # Components + cls='space-x-4', # Additional classes on the div (`space-x-4` provides spacing between components) + **kwargs # Additional args for the div + )->FT: # Div with components stacked horizontally + "Creates a flex div with it's components stacked horizontally" + cls=stringify(cls) + return Div(cls=(FlexT.block,FlexT.row,FlexT.middle,cls), **kwargs)(*c) + +# %% ../nbs/02_franken.ipynb +class NavT(VEnum): + def _generate_next_value_(name, start, count, last_values): return str2ukcls('nav', name) + default = auto() + primary = auto() + secondary = auto() + +# %% ../nbs/02_franken.ipynb +def NavContainer(*li, # List items are navigation elements (Special `Li` such as `NavParentLi`, `NavDividerLi`, `NavHeaderLi`, `NavSubtitle`, `NavCloseLi` can also be used) + cls=NavT.primary, # Additional classes on the nav + parent=True, # Whether this nav is a *parent* or *sub* nav + uk_nav=False, #True for default collapsible behavior, see [frankenui docs](https://franken-ui.dev/docs/nav#component-options) for more advanced options + uk_scrollspy_nav=False, # Activates scrollspy linking each item `A` tags `href` to content's `id` attribute + sticky=False, # Whether to stick to the top of the page while scrolling + **kwargs # Additional args + )->FT: # FT Component that is a list of `Li` styled for a sidebar navigation menu + "Creates a navigation container (useful for creating a sidebar navigation). A Nav is a list (NavBar is something different)" + _uk_scrollspy_nav = False + if uk_scrollspy_nav: + if isinstance(uk_scrollspy_nav, bool): _uk_scrollspy_nav = 'closest: li; scroll: true' if uk_scrollspy_nav else False + else: _uk_scrollspy_nav = uk_scrollspy_nav + _sticky = 'float-left sticky top-4 hidden md:block' if sticky else '' + return fh.Ul(*li, uk_nav=uk_nav, cls=(f"uk-nav{'' if parent else '-sub'}", stringify(cls), _sticky), uk_scrollspy_nav=_uk_scrollspy_nav, **kwargs) + +# %% ../nbs/02_franken.ipynb +def NavParentLi(*nav_container, # `NavContainer` container for a nested nav with `parent=False`) + cls=(), # Additional classes on the li + **kwargs # Additional args for the li + )->FT: # Navigation list item + "Creates a navigation list item with a parent nav for nesting" + return fh.Li(*nav_container, cls=('uk-parent', stringify(cls)),**kwargs) +def NavDividerLi(*c, # Components + cls=(), # Additional classes on the li + **kwargs # Additional args for the li + )->FT: # Navigation list item with a divider + "Creates a navigation list item with a divider" + return fh.Li(*c, cls=('uk-nav-divider', stringify(cls)),**kwargs) +def NavHeaderLi(*c, # Components + cls=(), # Additional classes on the li + **kwargs # Additional args for the li + )->FT: # Navigation list item with a header + "Creates a navigation list item with a header" + return fh.Li(*c, cls=('uk-nav-header', stringify(cls)),**kwargs) +def NavSubtitle(*c, # Components + cls=TextPresets.muted_sm, # Additional classes on the div + **kwargs # Additional args for the div + )->FT: # Navigation subtitle + "Creates a navigation subtitle" + return fh.Div(*c, cls=('uk-nav-subtitle', stringify(cls)),**kwargs) +def NavCloseLi(*c, # Components + cls=(), # Additional classes on the li + **kwargs # Additional args for the li + )->FT: # Navigation list item with a close button + "Creates a navigation list item with a close button" + return fh.Li(*c, cls=('uk-drop-close', stringify(cls)),**kwargs) + +# %% ../nbs/02_franken.ipynb +class ScrollspyT(VEnum): + underline = 'navbar-underline' + bold = 'navbar-bold' + +# %% ../nbs/02_franken.ipynb +def NavBar(*c, # Component for right side of navbar (Often A tag links) + brand=H3("Title"), # Brand/logo component for left side + right_cls='items-center space-x-4', # Spacing for desktop links + mobile_cls='space-y-4', # Spacing for mobile links + sticky:bool=False, # Whether to stick to the top of the page while scrolling + uk_scrollspy_nav:bool|str=False, # Whether to use scrollspy for navigation + cls='p-4', # Classes for navbar + scrollspy_cls=ScrollspyT.underline, # Scrollspy class (usually ScrollspyT.*) + menu_id=None, # ID for menu container (used for mobile toggle) + )->FT: # Responsive NavBar + "Creates a responsive navigation bar with mobile menu support" + if menu_id is None: menu_id = fh.unqid() + sticky_cls = 'sticky top-4 bg-base-100/80 backdrop-blur-sm z-50' if sticky else '' + if uk_scrollspy_nav == True: uk_scrollspy_nav = 'closest: a; scroll: true' + + mobile_icon = A(UkIcon("menu", width=30, height=30), cls="md:hidden", data_uk_toggle=f"target: #{menu_id}; cls: hidden") + return Div( + Div( + DivFullySpaced( + brand, # Brand/logo component for left side + mobile_icon, # Hamburger menu icon + Div(*c,cls=(stringify(right_cls),'hidden md:flex'), uk_scrollspy_nav=uk_scrollspy_nav)),# Desktop Navbar (right side) + cls=('monster-navbar', stringify(cls), stringify(scrollspy_cls)) + ), + DivCentered(*c, + cls=(stringify(mobile_cls),stringify(cls), stringify(scrollspy_cls), + 'hidden md:hidden monster-navbar'), + id=menu_id, uk_scrollspy_nav=uk_scrollspy_nav), + cls=sticky_cls) + +# %% ../nbs/02_franken.ipynb +def SliderContainer( + *c, # Components + cls='', # Additional classes on the container + uk_slider=True, # See FrankenUI Slider docs for more options + **kwargs # Additional args for the container + ) -> FT: # Div(..., cls='relative', uk_slider=True, ...) + "Creates a slider container" + return Div(*c, cls=('relative', stringify(cls)), uk_slider=uk_slider, **kwargs) + +# %% ../nbs/02_franken.ipynb +def SliderItems( + *c, # Components + cls='', # Additional classes for the items + **kwargs # Additional args for the items + ) -> FT: # Div(..., cls='uk-slider-items uk-grid', ...) + "Creates a slider items container" + return Div(*c, cls=('uk-slider-items uk-grid', stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def SliderNav( + cls='uk-position-small uk-hidden-hover', # Additional classes for the navigation + prev_cls='absolute left-0 top-1/2 -translate-y-1/2', # Additional classes for the previous navigation + next_cls='absolute right-0 top-1/2 -translate-y-1/2', # Additional classes for the next navigation + **kwargs # Additional args for the navigation + ) -> FT: # Left and right navigation arrows for Slider component + "Navigation arrows for Slider component" + return ( + fh.A(cls=(prev_cls, stringify(cls)), href='', + uk_slidenav_previous=True, uk_slider_item='previous', **kwargs), + fh.A(cls=(next_cls, stringify(cls)), href='', + uk_slidenav_next=True, uk_slider_item='next', **kwargs) + ) + +# %% ../nbs/02_franken.ipynb +def Slider(*c, # Items to show in slider + cls='', # Classes for slider container + items_cls='gap-4', # Classes for items container + nav=True, # Whether to show navigation arrows + nav_cls='', # Classes for navigation arrows + **kwargs # Additional args for slider container + ) -> FT: # SliderContainer(SliderItems(..., cls='gap-4'), SliderNav?) + "Creates a slider with optional navigation arrows" + nav_comp = SliderNav(cls=nav_cls) if nav else () + return SliderContainer( + SliderItems(*c, cls=items_cls), + *nav_comp, + cls=cls, + **kwargs + ) + +# %% ../nbs/02_franken.ipynb +def DropDownNavContainer(*li, # Components + cls=NavT.primary, # Additional classes on the nav + parent=True, # Whether to use a parent nav + uk_nav=False, #True for default collapsible behavior, see https://franken-ui.dev/docs/nav#component-options for more advanced options + uk_dropdown=True, # Whether to use a dropdown + **kwargs # Additional args for the nav + )->FT: # DropDown nav container + "A Nav that is part of a DropDown" + return Div(cls = 'uk-drop uk-dropdown',uk_dropdown=uk_dropdown)(NavContainer(*li, cls=('uk-dropdown-nav',stringify(cls)), uk_nav=uk_nav, parent=parent, **kwargs)) + +# %% ../nbs/02_franken.ipynb +def TabContainer(*li, # Components + cls='', # Additional classes on the `Ul` + alt=False, # Whether to use an alternative tab style + **kwargs # Additional args for the `Ul` + )->FT: # Tab container + "A TabContainer where children will be different tabs" + cls = stringify(cls) + return Ul(cls=(f"uk-tab{'-alt' if alt else ''}",stringify(cls)),**kwargs)(*li) + +# %% ../nbs/02_franken.ipynb +class CardT(VEnum): + 'Card styles from UIkit' + def _generate_next_value_(name, start, count, last_values): return str2ukcls('card', name) + default = auto() + primary = auto() + secondary = auto() + destructive = auto() + hover = 'uk-card hover:shadow-lg hover:-translate-y-1 transition-all duration-200' + +# %% ../nbs/02_franken.ipynb +def CardTitle(*c, # Components (often a string) + cls=(), # Additional classes on the div + **kwargs # Additional args for the div + ): + "Creates a card title" + return fh.Div(*c, cls=('uk-card-title',stringify(cls)), **kwargs) + +def CardHeader(*c, # Components that goes in the header (often a `ModalTitle` and description) + cls=(), # Additional classes on the div + **kwargs # Additional args for the div + )->FT: # Container for the header of a card + "Creates a card header" + return fh.Div(*c, cls=('uk-card-header',stringify(cls)), **kwargs) + +def CardBody(*c, # Components that go in the body (Main content of the card such as a form, and image, a signin form, etc.) + cls=(), # Additional classes on the div + **kwargs # Additional args for the div + )->FT: # Container for the body of a card + "Creates a card body" + return fh.Div(*c, cls=('uk-card-body',stringify(cls)), **kwargs) + +def CardFooter(*c, # Components that go in the footer (often a `ModalCloseButton`) + cls=(), # Additional classes on the div + **kwargs # Additional args for the div + )->FT: # Container for the footer of a card + "Creates a card footer" + return fh.Div(*c, cls=('uk-card-footer',stringify(cls)), **kwargs) + +def CardContainer(*c, # Components (typically `CardHeader`, `CardBody`, `CardFooter`) + cls=CardT.default, # Additional classes on the div + **kwargs # Additional args for the div + )->FT: # Container for a card + "Creates a card container" + return fh.Div(*c, cls=('uk-card',stringify(cls)), **kwargs) + +# %% ../nbs/02_franken.ipynb +def Card(*c, # Components that go in the body (Main content of the card such as a form, and image, a signin form, etc.) + header:FT|Iterable[FT]=None, # Component(s) that goes in the header (often a `ModalTitle` and a subtitle) + footer:FT|Iterable[FT]=None, # Component(s) that goes in the footer (often a `ModalCloseButton`) + body_cls='space-y-6', # classes for the body + header_cls=(), # classes for the header + footer_cls=(), # classes for the footer + cls=(), #class for outermost component + **kwargs # additional arguments for the `CardContainer` + )->FT: # Card component + "Creates a Card with a header, body, and footer" + header_cls, footer_cls, body_cls, cls = map(stringify, (header_cls, footer_cls, body_cls, cls)) + res = [] + if header: res.append(CardHeader(cls=header_cls)(header)) + res.append(CardBody(cls=body_cls)(*c)) + if footer: res.append(CardFooter(cls=footer_cls)(footer)) + return CardContainer(cls=cls, **kwargs)(*res) + +# %% ../nbs/02_franken.ipynb +class TableT(VEnum): + def _generate_next_value_(name, start, count, last_values): return str2ukcls('table', name) + divider = auto() + striped = auto() + hover = auto() + sm = auto() + lg = auto() + justify = auto() + middle = auto() + responsive = auto() + +# %% ../nbs/02_franken.ipynb +def Table(*c, # Components (typically `Thead`, `Tbody`, `Tfoot`) + cls=(TableT.middle, TableT.divider, TableT.hover, TableT.sm), # Additional classes on the table + **kwargs # Additional args for the table + )->FT: # Table component + "Creates a table" + return fh.Table(cls=('uk-table', stringify(cls)), *c, **kwargs) + +# %% ../nbs/02_franken.ipynb +def _TableCell(Component, + *c, # Components that go in the cell + cls=(), # Additional classes on the cell container + shrink=False, # Whether to shrink the cell + expand=False, # Whether to expand the cell + small=False, # Whether to use a small table + **kwargs # Additional args for the cell + )->FT: # Table cell + "Creates a table cell" + cls = stringify(cls) + if shrink: cls += ' uk-table-shrink' + if expand: cls += ' uk-table-expand' + if small: cls += ' uk-table-small' + return Component(*c,cls=cls, **kwargs) + +@delegates(_TableCell, but=['Component']) +def Td(*c,**kwargs): return _TableCell(fh.Td, *c, **kwargs) +@delegates(_TableCell, but=['Component']) +def Th(*c,**kwargs): return _TableCell(fh.Th, *c, **kwargs) + +def Tbody(*rows, cls=(), sortable=False, **kwargs): return fh.Tbody(*rows, cls=stringify(cls), uk_sortable=sortable, **kwargs) + +# %% ../nbs/02_franken.ipynb +def TableFromLists(header_data:Sequence, # List of header data + body_data:Sequence[Sequence], # List of lists of body data + footer_data=None, # List of footer data + header_cell_render=Th, # Function(content) -> FT that renders header cells + body_cell_render=Td, # Function(key, content) -> FT that renders body cells + footer_cell_render=Td, # Function(key, content) -> FT that renders footer cells + cls=(TableT.middle, TableT.divider, TableT.hover, TableT.sm), # Additional classes on the table + sortable=False, # Whether to use sortable table + **kwargs # Additional args for the table + )->FT: # Table from lists + "Creates a Table from a list of header data and a list of lists of body data" + return Table( + Thead(Tr(*map(header_cell_render, header_data))), + Tbody(*[Tr(*map(body_cell_render, r)) for r in body_data], sortable=sortable), + Tfoot(Tr(*map(footer_cell_render, footer_data))) if footer_data else '', + cls=stringify(cls), + **kwargs) + +# %% ../nbs/02_franken.ipynb +def TableFromDicts(header_data:Sequence, # List of header data + body_data:Sequence[dict], # List of dicts of body data + footer_data=None, # List of footer data + header_cell_render=Th, # Function(content) -> FT that renders header cells + body_cell_render=lambda k,v : Td(v), # Function(key, content) -> FT that renders body cells + footer_cell_render=lambda k,v : Td(v), # Function(key, content) -> FT that renders footer cells + cls=(TableT.middle, TableT.divider, TableT.hover, TableT.sm), # Additional classes on the table + sortable=False, # Whether to use sortable table + **kwargs # Additional args for the table + )->FT: # Styled Table + "Creates a Table from a list of header data and a list of dicts of body data" + return Table( + Thead(Tr(*[header_cell_render(h) for h in header_data])), + Tbody(*[Tr(*[body_cell_render(k, r.get(k, '')) for k in header_data]) for r in body_data], sortable=sortable), + Tfoot(Tr(*[footer_cell_render(k, footer_data.get(k.lower(), '')) for k in header_data])) if footer_data else '', + cls=stringify(cls), + **kwargs + ) + +# %% ../nbs/02_franken.ipynb +franken_class_map = { + 'h1': 'uk-h1 text-4xl font-bold mt-12 mb-6', + 'h2': 'uk-h2 text-3xl font-bold mt-10 mb-5', + 'h3': 'uk-h3 text-2xl font-semibold mt-8 mb-4', + 'h4': 'uk-h4 text-xl font-semibold mt-6 mb-3', + + # Body text and links + 'p': 'text-lg leading-relaxed mb-6', + 'a': 'uk-link text-primary hover:text-primary-focus underline', + + # Lists with proper spacing + 'ul': 'uk-list uk-list-bullet space-y-2 mb-6 ml-6 text-lg', + 'ol': 'uk-list uk-list-decimal space-y-2 mb-6 ml-6 text-lg', + 'li': 'leading-relaxed', + + # Code and quotes + 'pre': 'bg-base-200 rounded-lg p-4 mb-6', + 'code': 'uk-codespan px-1', + 'pre code': 'uk-codespan px-1 block overflow-x-auto', + 'blockquote': 'uk-blockquote pl-4 border-l-4 border-primary italic mb-6', + + # Tables + 'table': 'uk-table uk-table-divider uk-table-hover uk-table-small w-full mb-6', + 'th': '!text-left p-2 font-semibold', + 'td': 'p-2', + + # Other elements + 'hr': 'uk-divider-icon my-8', + 'img': 'max-w-full h-auto rounded-lg mb-6' +} + +# %% ../nbs/02_franken.ipynb +def apply_classes(html_str:str, # Html string + class_map=None, # Class map + class_map_mods=None # Class map that will modify the class map map (for small changes to base map) + )->str: # Html string with classes applied + "Apply classes to html string" + if not html_str: return html_str + # Handles "Unicode strings with encoding declaration are not supported": + if html_str[:100].lstrip().startswith('', 1)[1].strip() + class_map = ifnone(class_map, franken_class_map) + if class_map_mods: class_map = {**class_map, **class_map_mods} + try: + html_str = html.fragment_fromstring(html_str, create_parent=True) + for selector, classes in class_map.items(): + # Handle descendant selectors (e.g., 'pre code') + xpath = '//' + '/descendant::'.join(selector.split()) + for element in html_str.xpath(xpath): + existing_class = element.get('class', '') + new_class = f"{existing_class} {classes}".strip() + element.set('class', new_class) + return ''.join(etree.tostring(c, encoding='unicode', method='html') for c in html_str) + except (etree.ParserError,ValueError): return html_str + +# %% ../nbs/02_franken.ipynb +class FrankenRenderer(HTMLRenderer): + "Custom renderer for Franken UI that handles image paths" + def __init__(self, *args, img_dir=None, **kwargs): + super().__init__(*args, **kwargs) + self.img_dir = img_dir + + def render_image(self, token): + "Modify image paths if they're relative and self.img_dir is specified" + template = '{}' + title = f' title="{token.title}"' if hasattr(token, 'title') else '' + src = token.src + if self.img_dir and not src.startswith(('http://', 'https://', '/', 'attachment:', 'blob:', 'data:')): + src = f'{pathlib.Path(self.img_dir)}/{src}' + return template.format(src, token.children[0].content if token.children else '', title) + +# %% ../nbs/02_franken.ipynb +def render_md(md_content:str, # Markdown content + class_map=None, # Class map + class_map_mods=None, # Additional class map + img_dir:str=None, # Directory containing images + renderer=FrankenRenderer # custom renderer + )->FT: # Rendered markdown + "Renders markdown using mistletoe and lxml with custom image handling" + if md_content=='': return md_content + html_content = mistletoe.markdown(md_content, partial(renderer, img_dir=img_dir)) + return NotStr(apply_classes(html_content, class_map, class_map_mods)) + +# %% ../nbs/02_franken.ipynb +def ThemePicker(color=True, radii=True, shadows=True, font=True, mode=True, cls='p-4', custom_themes=[]): + "Theme picker component with configurable sections" + def _opt(val, txt, **kwargs): return Option(txt, value=val, **kwargs) + def _optgrp(key, lbl, opts): return fh.Optgroup(data_key=key, label=lbl)(*opts) + + groups = [] + if color: groups.append(_optgrp('theme', 'Theme', [ + _opt('uk-theme-zinc', 'Zinc', data_hex='#52525b', selected=True), + *[_opt(f'uk-theme-{c.lower()}', c, data_hex=h) for c,h in + [('Slate','#64748b'),('Stone','#78716c'),('Gray','#6b7280'), + ('Neutral','#737373'),('Red','#dc2626'),('Rose','#e11d48'), + ('Orange','#f97316'),('Green','#16a34a'),('Blue','#2563eb'), + ('Yellow','#facc15'),('Violet','#7c3aed'),*custom_themes]]])) + if radii: groups.append(_optgrp('radii', 'Radii', [ + _opt('uk-radii-none','None'), _opt('uk-radii-sm','Small'), + _opt('uk-radii-md','Medium',selected=True), _opt('uk-radii-lg','Large')])) + if shadows: groups.append(_optgrp('shadows', 'Shadows', [ + _opt('uk-shadows-none','None'), _opt('uk-shadows-sm','Small',selected=True), + _opt('uk-shadows-md','Medium'), _opt('uk-shadows-lg','Large')])) + if font: groups.append(_optgrp('font', 'Font', [ + _opt('uk-font-sm','Small',selected=True), _opt('uk-font-base','Default')])) + if mode: groups.append(_optgrp('mode', 'Mode', [ + _opt('light','Light',data_icon='sun'), _opt('dark','Dark',data_icon='moon')])) + from fasthtml.components import Uk_theme_switcher + return Div(Uk_theme_switcher(fh.Select(*groups, hidden=True), id="theme-switcher"), cls=stringify(cls)) + +# %% ../nbs/02_franken.ipynb +def LightboxContainer(*lightboxitem, # `LightBoxItem`s that will be inside lightbox + data_uk_lightbox='counter: true', # See https://franken-ui.dev/docs/2.0/lightbox for advanced options + **kwargs # Additional options for outer container + )->FT: # Lightbox + "Lightbox container that will hold `LightboxItems`" + return fh.Div(*lightboxitem, data_uk_lightbox=data_uk_lightbox, **kwargs) + +# %% ../nbs/02_franken.ipynb +def LightboxItem(*c, # Component that when clicked will open the lightbox (often a button) + href, # Href to image, youtube video, vimeo, google maps, etc. + data_alt=None, # Alt text for the lightbox item/image + data_caption=None, # Caption for the item that shows below it + cls='', # Class for the A tag (often nothing or `uk-btn`) + **kwargs # Additional args for the `A` tag + )->FT: # A(... href, data_alt, cls., ...) + "Anchor tag with appropriate structure to go inside a `LightBoxContainer`" + return fh.A(*c, href=href, data_alt=data_alt, cls=stringify(cls), **kwargs) + +# %% ../nbs/02_franken.ipynb +def ApexChart(*, + opts:Dict, # ApexChart options used to render your chart (e.g. {"chart":{"type":"line"}, ...}) + cls: Enum | str | tuple = (), # Classes for the outer container + **kws, # Additional args for the outer container + )->FT: # Div(Uk_chart(Script(...))) + "Apex chart component" + js=NotStr(f"") + return Div(Uk_chart(js), cls=stringify(cls), **kws) diff --git a/MonsterUI/monsterui/icon.iife.js b/MonsterUI/monsterui/icon.iife.js new file mode 100644 index 0000000000000000000000000000000000000000..e01b228b72d625fc9866feda861abbeeb623976b --- /dev/null +++ b/MonsterUI/monsterui/icon.iife.js @@ -0,0 +1,4 @@ +var FRANKENUIICON=function(M,Py,r){"use strict";const E0=(t,p,h=[])=>{const c=document.createElementNS("http://www.w3.org/2000/svg",t);return Object.keys(p).forEach(d=>{c.setAttribute(d,String(p[d]))}),h.length&&h.forEach(d=>{const s=E0(...d);c.appendChild(s)}),c};var I0=([t,p,h])=>E0(t,p,h);const ky=t=>Array.from(t.attributes).reduce((p,h)=>(p[h.name]=h.value,p),{}),zy=t=>typeof t=="string"?t:!t||!t.class?"":t.class&&typeof t.class=="string"?t.class.split(" "):t.class&&Array.isArray(t.class)?t.class:"",By=t=>t.flatMap(zy).map(h=>h.trim()).filter(Boolean).filter((h,c,d)=>d.indexOf(h)===c).join(" "),Fy=t=>t.replace(/(\w)(\w*)(_|-|\s*)/g,(p,h,c)=>h.toUpperCase()+c.toLowerCase()),G0=(t,{nameAttr:p,icons:h,attrs:c})=>{var Zy;const d=t.getAttribute(p);if(d==null)return;const s=Fy(d),i=h[s];if(!i)return console.warn(`${t.outerHTML} icon name was not found in the provided icons object.`);const Ly=ky(t),[Ty,Uy,Oy]=i,Sy={...Uy,"data-lucide":d,...c,...Ly},fy=By(["lucide",`lucide-${d}`,Ly,c]);fy&&Object.assign(Sy,{class:fy});const Iy=I0([Ty,Sy,Oy]);return(Zy=t.parentNode)==null?void 0:Zy.replaceChild(Iy,t)};const a={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":2,"stroke-linecap":"round","stroke-linejoin":"round"};const W0=["svg",a,[["path",{d:"M3.5 13h6"}],["path",{d:"m2 16 4.5-9 4.5 9"}],["path",{d:"M18 7v9"}],["path",{d:"m14 12 4 4 4-4"}]]];const X0=["svg",a,[["path",{d:"M3.5 13h6"}],["path",{d:"m2 16 4.5-9 4.5 9"}],["path",{d:"M18 16V7"}],["path",{d:"m14 11 4-4 4 4"}]]];const N0=["svg",a,[["path",{d:"M21 14h-5"}],["path",{d:"M16 16v-3.5a2.5 2.5 0 0 1 5 0V16"}],["path",{d:"M4.5 13h6"}],["path",{d:"m3 16 4.5-9 4.5 9"}]]];const K0=["svg",a,[["circle",{cx:"16",cy:"4",r:"1"}],["path",{d:"m18 19 1-7-6 1"}],["path",{d:"m5 8 3-3 5.5 3-2.36 3.5"}],["path",{d:"M4.24 14.5a5 5 0 0 0 6.88 6"}],["path",{d:"M13.76 17.5a5 5 0 0 0-6.88-6"}]]];const J0=["svg",a,[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"}]]];const j0=["svg",a,[["path",{d:"M6 12H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"}],["path",{d:"M6 8h12"}],["path",{d:"M18.3 17.7a2.5 2.5 0 0 1-3.16 3.83 2.53 2.53 0 0 1-1.14-2V12"}],["path",{d:"M6.6 15.6A2 2 0 1 0 10 17v-5"}]]];const Q0=["svg",a,[["path",{d:"M5 17H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-1"}],["path",{d:"m12 15 5 6H7Z"}]]];const l=["svg",a,[["circle",{cx:"12",cy:"13",r:"8"}],["path",{d:"M5 3 2 6"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.38 18.7 4 21"}],["path",{d:"M17.64 18.67 20 21"}],["path",{d:"m9 13 2 2 4-4"}]]];const g=["svg",a,[["circle",{cx:"12",cy:"13",r:"8"}],["path",{d:"M5 3 2 6"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.38 18.7 4 21"}],["path",{d:"M17.64 18.67 20 21"}],["path",{d:"M9 13h6"}]]];const _0=["svg",a,[["path",{d:"M6.87 6.87a8 8 0 1 0 11.26 11.26"}],["path",{d:"M19.9 14.25a8 8 0 0 0-9.15-9.15"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.26 18.67 4 21"}],["path",{d:"m2 2 20 20"}],["path",{d:"M4 4 2 6"}]]];const x=["svg",a,[["circle",{cx:"12",cy:"13",r:"8"}],["path",{d:"M5 3 2 6"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.38 18.7 4 21"}],["path",{d:"M17.64 18.67 20 21"}],["path",{d:"M12 10v6"}],["path",{d:"M9 13h6"}]]];const Y0=["svg",a,[["circle",{cx:"12",cy:"13",r:"8"}],["path",{d:"M12 9v4l2 2"}],["path",{d:"M5 3 2 6"}],["path",{d:"m22 6-3-3"}],["path",{d:"M6.38 18.7 4 21"}],["path",{d:"M17.64 18.67 20 21"}]]];const $0=["svg",a,[["path",{d:"M11 21c0-2.5 2-2.5 2-5"}],["path",{d:"M16 21c0-2.5 2-2.5 2-5"}],["path",{d:"m19 8-.8 3a1.25 1.25 0 0 1-1.2 1H7a1.25 1.25 0 0 1-1.2-1L5 8"}],["path",{d:"M21 3a1 1 0 0 1 1 1v2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4a1 1 0 0 1 1-1z"}],["path",{d:"M6 21c0-2.5 2-2.5 2-5"}]]];const aa=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["polyline",{points:"11 3 11 11 14 8 17 11 17 3"}]]];const ta=["svg",a,[["path",{d:"M2 12h20"}],["path",{d:"M10 16v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-4"}],["path",{d:"M10 8V4a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v4"}],["path",{d:"M20 16v1a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2v-1"}],["path",{d:"M14 8V7c0-1.1.9-2 2-2h2a2 2 0 0 1 2 2v1"}]]];const ha=["svg",a,[["path",{d:"M12 2v20"}],["path",{d:"M8 10H4a2 2 0 0 1-2-2V6c0-1.1.9-2 2-2h4"}],["path",{d:"M16 10h4a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-4"}],["path",{d:"M8 20H7a2 2 0 0 1-2-2v-2c0-1.1.9-2 2-2h1"}],["path",{d:"M16 14h1a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2h-1"}]]];const da=["svg",a,[["line",{x1:"21",x2:"3",y1:"6",y2:"6"}],["line",{x1:"17",x2:"7",y1:"12",y2:"12"}],["line",{x1:"19",x2:"5",y1:"18",y2:"18"}]]];const pa=["svg",a,[["rect",{width:"6",height:"16",x:"4",y:"2",rx:"2"}],["rect",{width:"6",height:"9",x:"14",y:"9",rx:"2"}],["path",{d:"M22 22H2"}]]];const ca=["svg",a,[["rect",{width:"16",height:"6",x:"2",y:"4",rx:"2"}],["rect",{width:"9",height:"6",x:"9",y:"14",rx:"2"}],["path",{d:"M22 22V2"}]]];const Ma=["svg",a,[["rect",{width:"6",height:"14",x:"4",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"14",y:"7",rx:"2"}],["path",{d:"M17 22v-5"}],["path",{d:"M17 7V2"}],["path",{d:"M7 22v-3"}],["path",{d:"M7 5V2"}]]];const sa=["svg",a,[["rect",{width:"6",height:"14",x:"4",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"14",y:"7",rx:"2"}],["path",{d:"M10 2v20"}],["path",{d:"M20 2v20"}]]];const ea=["svg",a,[["rect",{width:"6",height:"14",x:"4",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"14",y:"7",rx:"2"}],["path",{d:"M4 2v20"}],["path",{d:"M14 2v20"}]]];const ra=["svg",a,[["rect",{width:"6",height:"14",x:"2",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"16",y:"7",rx:"2"}],["path",{d:"M12 2v20"}]]];const va=["svg",a,[["rect",{width:"6",height:"14",x:"2",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"12",y:"7",rx:"2"}],["path",{d:"M22 2v20"}]]];const na=["svg",a,[["rect",{width:"6",height:"14",x:"6",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"16",y:"7",rx:"2"}],["path",{d:"M2 2v20"}]]];const oa=["svg",a,[["rect",{width:"6",height:"10",x:"9",y:"7",rx:"2"}],["path",{d:"M4 22V2"}],["path",{d:"M20 22V2"}]]];const ia=["svg",a,[["rect",{width:"6",height:"14",x:"3",y:"5",rx:"2"}],["rect",{width:"6",height:"10",x:"15",y:"7",rx:"2"}],["path",{d:"M3 2v20"}],["path",{d:"M21 2v20"}]]];const la=["svg",a,[["line",{x1:"3",x2:"21",y1:"6",y2:"6"}],["line",{x1:"3",x2:"21",y1:"12",y2:"12"}],["line",{x1:"3",x2:"21",y1:"18",y2:"18"}]]];const ga=["svg",a,[["line",{x1:"21",x2:"3",y1:"6",y2:"6"}],["line",{x1:"15",x2:"3",y1:"12",y2:"12"}],["line",{x1:"17",x2:"3",y1:"18",y2:"18"}]]];const xa=["svg",a,[["line",{x1:"21",x2:"3",y1:"6",y2:"6"}],["line",{x1:"21",x2:"9",y1:"12",y2:"12"}],["line",{x1:"21",x2:"7",y1:"18",y2:"18"}]]];const ya=["svg",a,[["rect",{width:"6",height:"16",x:"4",y:"6",rx:"2"}],["rect",{width:"6",height:"9",x:"14",y:"6",rx:"2"}],["path",{d:"M22 2H2"}]]];const ma=["svg",a,[["rect",{width:"9",height:"6",x:"6",y:"14",rx:"2"}],["rect",{width:"16",height:"6",x:"6",y:"4",rx:"2"}],["path",{d:"M2 2v20"}]]];const Ha=["svg",a,[["path",{d:"M22 17h-3"}],["path",{d:"M22 7h-5"}],["path",{d:"M5 17H2"}],["path",{d:"M7 7H2"}],["rect",{x:"5",y:"14",width:"14",height:"6",rx:"2"}],["rect",{x:"7",y:"4",width:"10",height:"6",rx:"2"}]]];const Va=["svg",a,[["rect",{width:"14",height:"6",x:"5",y:"14",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"4",rx:"2"}],["path",{d:"M2 20h20"}],["path",{d:"M2 10h20"}]]];const Ca=["svg",a,[["rect",{width:"14",height:"6",x:"5",y:"14",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"4",rx:"2"}],["path",{d:"M2 14h20"}],["path",{d:"M2 4h20"}]]];const wa=["svg",a,[["rect",{width:"14",height:"6",x:"5",y:"16",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"2",rx:"2"}],["path",{d:"M2 12h20"}]]];const ua=["svg",a,[["rect",{width:"14",height:"6",x:"5",y:"12",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"2",rx:"2"}],["path",{d:"M2 22h20"}]]];const Aa=["svg",a,[["rect",{width:"14",height:"6",x:"5",y:"16",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"6",rx:"2"}],["path",{d:"M2 2h20"}]]];const La=["svg",a,[["rect",{width:"10",height:"6",x:"7",y:"9",rx:"2"}],["path",{d:"M22 20H2"}],["path",{d:"M22 4H2"}]]];const Sa=["svg",a,[["rect",{width:"14",height:"6",x:"5",y:"15",rx:"2"}],["rect",{width:"10",height:"6",x:"7",y:"3",rx:"2"}],["path",{d:"M2 21h20"}],["path",{d:"M2 3h20"}]]];const fa=["svg",a,[["path",{d:"M10 10H6"}],["path",{d:"M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2"}],["path",{d:"M19 18h2a1 1 0 0 0 1-1v-3.28a1 1 0 0 0-.684-.948l-1.923-.641a1 1 0 0 1-.578-.502l-1.539-3.076A1 1 0 0 0 16.382 8H14"}],["path",{d:"M8 8v4"}],["path",{d:"M9 18h6"}],["circle",{cx:"17",cy:"18",r:"2"}],["circle",{cx:"7",cy:"18",r:"2"}]]];const Za=["svg",a,[["path",{d:"M17.5 12c0 4.4-3.6 8-8 8A4.5 4.5 0 0 1 5 15.5c0-6 8-4 8-8.5a3 3 0 1 0-6 0c0 3 2.5 8.5 12 13"}],["path",{d:"M16 12h3"}]]];const Pa=["svg",a,[["path",{d:"M10 17c-5-3-7-7-7-9a2 2 0 0 1 4 0c0 2.5-5 2.5-5 6 0 1.7 1.3 3 3 3 2.8 0 5-2.2 5-5"}],["path",{d:"M22 17c-5-3-7-7-7-9a2 2 0 0 1 4 0c0 2.5-5 2.5-5 6 0 1.7 1.3 3 3 3 2.8 0 5-2.2 5-5"}]]];const ka=["svg",a,[["path",{d:"M10 2v5.632c0 .424-.272.795-.653.982A6 6 0 0 0 6 14c.006 4 3 7 5 8"}],["path",{d:"M10 5H8a2 2 0 0 0 0 4h.68"}],["path",{d:"M14 2v5.632c0 .424.272.795.652.982A6 6 0 0 1 18 14c0 4-3 7-5 8"}],["path",{d:"M14 5h2a2 2 0 0 1 0 4h-.68"}],["path",{d:"M18 22H6"}],["path",{d:"M9 2h6"}]]];const za=["svg",a,[["path",{d:"M12 22V8"}],["path",{d:"M5 12H2a10 10 0 0 0 20 0h-3"}],["circle",{cx:"12",cy:"5",r:"3"}]]];const Ba=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M16 16s-1.5-2-4-2-4 2-4 2"}],["path",{d:"M7.5 8 10 9"}],["path",{d:"m14 9 2.5-1"}],["path",{d:"M9 10h.01"}],["path",{d:"M15 10h.01"}]]];const Fa=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 15h8"}],["path",{d:"M8 9h2"}],["path",{d:"M14 9h2"}]]];const Da=["svg",a,[["path",{d:"M2 12 7 2"}],["path",{d:"m7 12 5-10"}],["path",{d:"m12 12 5-10"}],["path",{d:"m17 12 5-10"}],["path",{d:"M4.5 7h15"}],["path",{d:"M12 16v6"}]]];const qa=["svg",a,[["path",{d:"M7 10H6a4 4 0 0 1-4-4 1 1 0 0 1 1-1h4"}],["path",{d:"M7 5a1 1 0 0 1 1-1h13a1 1 0 0 1 1 1 7 7 0 0 1-7 7H8a1 1 0 0 1-1-1z"}],["path",{d:"M9 12v5"}],["path",{d:"M15 12v5"}],["path",{d:"M5 20a3 3 0 0 1 3-3h8a3 3 0 0 1 3 3 1 1 0 0 1-1 1H6a1 1 0 0 1-1-1"}]]];const Ra=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m14.31 8 5.74 9.94"}],["path",{d:"M9.69 8h11.48"}],["path",{d:"m7.38 12 5.74-9.94"}],["path",{d:"M9.69 16 3.95 6.06"}],["path",{d:"M14.31 16H2.83"}],["path",{d:"m16.62 12-5.74 9.94"}]]];const ba=["svg",a,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M6 8h.01"}],["path",{d:"M10 8h.01"}],["path",{d:"M14 8h.01"}]]];const Ta=["svg",a,[["rect",{x:"2",y:"4",width:"20",height:"16",rx:"2"}],["path",{d:"M10 4v4"}],["path",{d:"M2 8h20"}],["path",{d:"M6 4v4"}]]];const Ua=["svg",a,[["path",{d:"M12 20.94c1.5 0 2.75 1.06 4 1.06 3 0 6-8 6-12.22A4.91 4.91 0 0 0 17 5c-2.22 0-4 1.44-5 2-1-.56-2.78-2-5-2a4.9 4.9 0 0 0-5 4.78C2 14 5 22 8 22c1.25 0 2.5-1.06 4-1.06Z"}],["path",{d:"M10 2c1 .5 2 2 2 5"}]]];const Oa=["svg",a,[["rect",{width:"20",height:"5",x:"2",y:"3",rx:"1"}],["path",{d:"M4 8v11a2 2 0 0 0 2 2h2"}],["path",{d:"M20 8v11a2 2 0 0 1-2 2h-2"}],["path",{d:"m9 15 3-3 3 3"}],["path",{d:"M12 12v9"}]]];const Ia=["svg",a,[["rect",{width:"20",height:"5",x:"2",y:"3",rx:"1"}],["path",{d:"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"}],["path",{d:"m9.5 17 5-5"}],["path",{d:"m9.5 12 5 5"}]]];const Ea=["svg",a,[["rect",{width:"20",height:"5",x:"2",y:"3",rx:"1"}],["path",{d:"M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8"}],["path",{d:"M10 12h4"}]]];const Ga=["svg",a,[["path",{d:"M19 9V6a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v3"}],["path",{d:"M3 16a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5a2 2 0 0 0-4 0v1.5a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5V11a2 2 0 0 0-4 0z"}],["path",{d:"M5 18v2"}],["path",{d:"M19 18v2"}]]];const Wa=["svg",a,[["path",{d:"M15 5H9"}],["path",{d:"M15 9v3h4l-7 7-7-7h4V9z"}]]];const Xa=["svg",a,[["path",{d:"M15 6v6h4l-7 7-7-7h4V6h6z"}]]];const Na=["svg",a,[["path",{d:"M19 15V9"}],["path",{d:"M15 15h-3v4l-7-7 7-7v4h3v6z"}]]];const Ka=["svg",a,[["path",{d:"M18 15h-6v4l-7-7 7-7v4h6v6z"}]]];const Ja=["svg",a,[["path",{d:"M5 9v6"}],["path",{d:"M9 9h3V5l7 7-7 7v-4H9V9z"}]]];const ja=["svg",a,[["path",{d:"M6 9h6V5l7 7-7 7v-4H6V9z"}]]];const Qa=["svg",a,[["path",{d:"M9 19h6"}],["path",{d:"M9 15v-3H5l7-7 7 7h-4v3H9z"}]]];const _a=["svg",a,[["path",{d:"M9 18v-6H5l7-7 7 7h-4v6H9z"}]]];const Ya=["svg",a,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["rect",{x:"15",y:"4",width:"4",height:"6",ry:"2"}],["path",{d:"M17 20v-6h-2"}],["path",{d:"M15 20h4"}]]];const $a=["svg",a,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"M17 10V4h-2"}],["path",{d:"M15 10h4"}],["rect",{x:"15",y:"14",width:"4",height:"6",ry:"2"}]]];const y=["svg",a,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"M20 8h-5"}],["path",{d:"M15 10V6.5a2.5 2.5 0 0 1 5 0V10"}],["path",{d:"M15 14h5l-5 6h5"}]]];const at=["svg",a,[["path",{d:"M19 3H5"}],["path",{d:"M12 21V7"}],["path",{d:"m6 15 6 6 6-6"}]]];const tt=["svg",a,[["path",{d:"M17 7 7 17"}],["path",{d:"M17 17H7V7"}]]];const ht=["svg",a,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"M11 4h4"}],["path",{d:"M11 8h7"}],["path",{d:"M11 12h10"}]]];const dt=["svg",a,[["path",{d:"m7 7 10 10"}],["path",{d:"M17 7v10H7"}]]];const pt=["svg",a,[["path",{d:"M12 2v14"}],["path",{d:"m19 9-7 7-7-7"}],["circle",{cx:"12",cy:"21",r:"1"}]]];const ct=["svg",a,[["path",{d:"M12 17V3"}],["path",{d:"m6 11 6 6 6-6"}],["path",{d:"M19 21H5"}]]];const Mt=["svg",a,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"m21 8-4-4-4 4"}],["path",{d:"M17 4v16"}]]];const m=["svg",a,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 20V4"}],["path",{d:"M11 4h10"}],["path",{d:"M11 8h7"}],["path",{d:"M11 12h4"}]]];const H=["svg",a,[["path",{d:"m3 16 4 4 4-4"}],["path",{d:"M7 4v16"}],["path",{d:"M15 4h5l-5 6h5"}],["path",{d:"M15 20v-3.5a2.5 2.5 0 0 1 5 0V20"}],["path",{d:"M20 18h-5"}]]];const st=["svg",a,[["path",{d:"M12 5v14"}],["path",{d:"m19 12-7 7-7-7"}]]];const et=["svg",a,[["path",{d:"m9 6-6 6 6 6"}],["path",{d:"M3 12h14"}],["path",{d:"M21 19V5"}]]];const rt=["svg",a,[["path",{d:"M8 3 4 7l4 4"}],["path",{d:"M4 7h16"}],["path",{d:"m16 21 4-4-4-4"}],["path",{d:"M20 17H4"}]]];const vt=["svg",a,[["path",{d:"M3 19V5"}],["path",{d:"m13 6-6 6 6 6"}],["path",{d:"M7 12h14"}]]];const nt=["svg",a,[["path",{d:"m12 19-7-7 7-7"}],["path",{d:"M19 12H5"}]]];const ot=["svg",a,[["path",{d:"M3 5v14"}],["path",{d:"M21 12H7"}],["path",{d:"m15 18 6-6-6-6"}]]];const it=["svg",a,[["path",{d:"m16 3 4 4-4 4"}],["path",{d:"M20 7H4"}],["path",{d:"m8 21-4-4 4-4"}],["path",{d:"M4 17h16"}]]];const lt=["svg",a,[["path",{d:"M17 12H3"}],["path",{d:"m11 18 6-6-6-6"}],["path",{d:"M21 5v14"}]]];const gt=["svg",a,[["path",{d:"M5 12h14"}],["path",{d:"m12 5 7 7-7 7"}]]];const xt=["svg",a,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["rect",{x:"15",y:"4",width:"4",height:"6",ry:"2"}],["path",{d:"M17 20v-6h-2"}],["path",{d:"M15 20h4"}]]];const yt=["svg",a,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M17 10V4h-2"}],["path",{d:"M15 10h4"}],["rect",{x:"15",y:"14",width:"4",height:"6",ry:"2"}]]];const V=["svg",a,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M20 8h-5"}],["path",{d:"M15 10V6.5a2.5 2.5 0 0 1 5 0V10"}],["path",{d:"M15 14h5l-5 6h5"}]]];const mt=["svg",a,[["path",{d:"m21 16-4 4-4-4"}],["path",{d:"M17 20V4"}],["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}]]];const Ht=["svg",a,[["path",{d:"m5 9 7-7 7 7"}],["path",{d:"M12 16V2"}],["circle",{cx:"12",cy:"21",r:"1"}]]];const Vt=["svg",a,[["path",{d:"m18 9-6-6-6 6"}],["path",{d:"M12 3v14"}],["path",{d:"M5 21h14"}]]];const Ct=["svg",a,[["path",{d:"M7 17V7h10"}],["path",{d:"M17 17 7 7"}]]];const C=["svg",a,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M11 12h4"}],["path",{d:"M11 16h7"}],["path",{d:"M11 20h10"}]]];const wt=["svg",a,[["path",{d:"M7 7h10v10"}],["path",{d:"M7 17 17 7"}]]];const ut=["svg",a,[["path",{d:"M5 3h14"}],["path",{d:"m18 13-6-6-6 6"}],["path",{d:"M12 7v14"}]]];const At=["svg",a,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M11 12h10"}],["path",{d:"M11 16h7"}],["path",{d:"M11 20h4"}]]];const w=["svg",a,[["path",{d:"m3 8 4-4 4 4"}],["path",{d:"M7 4v16"}],["path",{d:"M15 4h5l-5 6h5"}],["path",{d:"M15 20v-3.5a2.5 2.5 0 0 1 5 0V20"}],["path",{d:"M20 18h-5"}]]];const Lt=["svg",a,[["path",{d:"m5 12 7-7 7 7"}],["path",{d:"M12 19V5"}]]];const St=["svg",a,[["path",{d:"m4 6 3-3 3 3"}],["path",{d:"M7 17V3"}],["path",{d:"m14 6 3-3 3 3"}],["path",{d:"M17 17V3"}],["path",{d:"M4 21h16"}]]];const ft=["svg",a,[["path",{d:"M12 6v12"}],["path",{d:"M17.196 9 6.804 15"}],["path",{d:"m6.804 9 10.392 6"}]]];const Zt=["svg",a,[["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8"}]]];const Pt=["svg",a,[["circle",{cx:"12",cy:"12",r:"1"}],["path",{d:"M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z"}],["path",{d:"M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z"}]]];const kt=["svg",a,[["path",{d:"M2 10v3"}],["path",{d:"M6 6v11"}],["path",{d:"M10 3v18"}],["path",{d:"M14 8v7"}],["path",{d:"M18 5v13"}],["path",{d:"M22 10v3"}]]];const zt=["svg",a,[["path",{d:"M2 13a2 2 0 0 0 2-2V7a2 2 0 0 1 4 0v13a2 2 0 0 0 4 0V4a2 2 0 0 1 4 0v13a2 2 0 0 0 4 0v-4a2 2 0 0 1 2-2"}]]];const Bt=["svg",a,[["path",{d:"m15.477 12.89 1.515 8.526a.5.5 0 0 1-.81.47l-3.58-2.687a1 1 0 0 0-1.197 0l-3.586 2.686a.5.5 0 0 1-.81-.469l1.514-8.526"}],["circle",{cx:"12",cy:"8",r:"6"}]]];const Ft=["svg",a,[["path",{d:"m14 12-8.5 8.5a2.12 2.12 0 1 1-3-3L11 9"}],["path",{d:"M15 13 9 7l4-4 6 6h3a8 8 0 0 1-7 7z"}]]];const u=["svg",a,[["path",{d:"M4 4v16h16"}],["path",{d:"m4 20 7-7"}]]];const Dt=["svg",a,[["path",{d:"M9 12h.01"}],["path",{d:"M15 12h.01"}],["path",{d:"M10 16c.5.3 1.2.5 2 .5s1.5-.2 2-.5"}],["path",{d:"M19 6.3a9 9 0 0 1 1.8 3.9 2 2 0 0 1 0 3.6 9 9 0 0 1-17.6 0 2 2 0 0 1 0-3.6A9 9 0 0 1 12 3c2 0 3.5 1.1 3.5 2.5s-.9 2.5-2 2.5c-.8 0-1.5-.4-1.5-1"}]]];const qt=["svg",a,[["path",{d:"M4 10a4 4 0 0 1 4-4h8a4 4 0 0 1 4 4v10a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2Z"}],["path",{d:"M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2"}],["path",{d:"M8 21v-5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v5"}],["path",{d:"M8 10h8"}],["path",{d:"M8 18h8"}]]];const Rt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16"}]]];const bt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M12 7v10"}],["path",{d:"M15.4 10a4 4 0 1 0 0 4"}]]];const A=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"m9 12 2 2 4-4"}]]];const Tt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"}],["path",{d:"M12 18V6"}]]];const Ut=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M7 12h5"}],["path",{d:"M15 9.4a4 4 0 1 0 0 5.2"}]]];const Ot=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"}],["line",{x1:"12",x2:"12.01",y1:"17",y2:"17"}]]];const It=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M8 8h8"}],["path",{d:"M8 12h8"}],["path",{d:"m13 17-5-1h1a4 4 0 0 0 0-8"}]]];const Et=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"12",x2:"12",y1:"16",y2:"12"}],["line",{x1:"12",x2:"12.01",y1:"8",y2:"8"}]]];const Gt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"m9 8 3 3v7"}],["path",{d:"m12 11 3-3"}],["path",{d:"M9 12h6"}],["path",{d:"M9 16h6"}]]];const Wt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12"}]]];const Xt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"m15 9-6 6"}],["path",{d:"M9 9h.01"}],["path",{d:"M15 15h.01"}]]];const Nt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"12",x2:"12",y1:"8",y2:"16"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12"}]]];const Kt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M8 12h4"}],["path",{d:"M10 16V9.5a2.5 2.5 0 0 1 5 0"}],["path",{d:"M8 16h7"}]]];const Jt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M9 16h5"}],["path",{d:"M9 12h5a2 2 0 1 0 0-4h-3v9"}]]];const jt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["path",{d:"M11 17V8h4"}],["path",{d:"M11 12h3"}],["path",{d:"M9 16h4"}]]];const Qt=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}],["line",{x1:"15",x2:"9",y1:"9",y2:"15"}],["line",{x1:"9",x2:"15",y1:"9",y2:"15"}]]];const _t=["svg",a,[["path",{d:"M3.85 8.62a4 4 0 0 1 4.78-4.77 4 4 0 0 1 6.74 0 4 4 0 0 1 4.78 4.78 4 4 0 0 1 0 6.74 4 4 0 0 1-4.77 4.78 4 4 0 0 1-6.75 0 4 4 0 0 1-4.78-4.77 4 4 0 0 1 0-6.76Z"}]]];const Yt=["svg",a,[["path",{d:"M22 18H6a2 2 0 0 1-2-2V7a2 2 0 0 0-2-2"}],["path",{d:"M17 14V4a2 2 0 0 0-2-2h-1a2 2 0 0 0-2 2v10"}],["rect",{width:"13",height:"8",x:"8",y:"6",rx:"1"}],["circle",{cx:"18",cy:"20",r:"2"}],["circle",{cx:"9",cy:"20",r:"2"}]]];const $t=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m4.9 4.9 14.2 14.2"}]]];const ah=["svg",a,[["path",{d:"M4 13c3.5-2 8-2 10 2a5.5 5.5 0 0 1 8 5"}],["path",{d:"M5.15 17.89c5.52-1.52 8.65-6.89 7-12C11.55 4 11.5 2 13 2c3.22 0 5 5.5 5 8 0 6.5-4.2 12-10.49 12C5.11 22 2 22 2 20c0-1.5 1.14-1.55 3.15-2.11Z"}]]];const th=["svg",a,[["path",{d:"M10 10.01h.01"}],["path",{d:"M10 14.01h.01"}],["path",{d:"M14 10.01h.01"}],["path",{d:"M14 14.01h.01"}],["path",{d:"M18 6v11.5"}],["path",{d:"M6 6v12"}],["rect",{x:"2",y:"6",width:"20",height:"12",rx:"2"}]]];const hh=["svg",a,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M6 12h.01M18 12h.01"}]]];const dh=["svg",a,[["path",{d:"M3 5v14"}],["path",{d:"M8 5v14"}],["path",{d:"M12 5v14"}],["path",{d:"M17 5v14"}],["path",{d:"M21 5v14"}]]];const ph=["svg",a,[["path",{d:"M4 20h16"}],["path",{d:"m6 16 6-12 6 12"}],["path",{d:"M8 12h8"}]]];const ch=["svg",a,[["path",{d:"M9 6 6.5 3.5a1.5 1.5 0 0 0-1-.5C4.683 3 4 3.683 4 4.5V17a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-5"}],["line",{x1:"10",x2:"8",y1:"5",y2:"7"}],["line",{x1:"2",x2:"22",y1:"12",y2:"12"}],["line",{x1:"7",x2:"7",y1:"19",y2:"21"}],["line",{x1:"17",x2:"17",y1:"19",y2:"21"}]]];const Mh=["svg",a,[["path",{d:"M15 7h1a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2h-2"}],["path",{d:"M6 7H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h1"}],["path",{d:"m11 7-3 5h4l-3 5"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}]]];const sh=["svg",a,[["rect",{width:"16",height:"10",x:"2",y:"7",rx:"2",ry:"2"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}],["line",{x1:"6",x2:"6",y1:"11",y2:"13"}],["line",{x1:"10",x2:"10",y1:"11",y2:"13"}],["line",{x1:"14",x2:"14",y1:"11",y2:"13"}]]];const eh=["svg",a,[["rect",{width:"16",height:"10",x:"2",y:"7",rx:"2",ry:"2"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}],["line",{x1:"6",x2:"6",y1:"11",y2:"13"}]]];const rh=["svg",a,[["rect",{width:"16",height:"10",x:"2",y:"7",rx:"2",ry:"2"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}],["line",{x1:"6",x2:"6",y1:"11",y2:"13"}],["line",{x1:"10",x2:"10",y1:"11",y2:"13"}]]];const vh=["svg",a,[["path",{d:"M14 7h2a2 2 0 0 1 2 2v6c0 1-1 2-2 2h-2"}],["path",{d:"M6 7H4a2 2 0 0 0-2 2v6c0 1 1 2 2 2h2"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}],["line",{x1:"10",x2:"10",y1:"7",y2:"13"}],["line",{x1:"10",x2:"10",y1:"17",y2:"17.01"}]]];const nh=["svg",a,[["rect",{width:"16",height:"10",x:"2",y:"7",rx:"2",ry:"2"}],["line",{x1:"22",x2:"22",y1:"11",y2:"13"}]]];const oh=["svg",a,[["path",{d:"M4.5 3h15"}],["path",{d:"M6 3v16a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V3"}],["path",{d:"M6 14h12"}]]];const ih=["svg",a,[["path",{d:"M9 9c-.64.64-1.521.954-2.402 1.165A6 6 0 0 0 8 22a13.96 13.96 0 0 0 9.9-4.1"}],["path",{d:"M10.75 5.093A6 6 0 0 1 22 8c0 2.411-.61 4.68-1.683 6.66"}],["path",{d:"M5.341 10.62a4 4 0 0 0 6.487 1.208M10.62 5.341a4.015 4.015 0 0 1 2.039 2.04"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const lh=["svg",a,[["path",{d:"M10.165 6.598C9.954 7.478 9.64 8.36 9 9c-.64.64-1.521.954-2.402 1.165A6 6 0 0 0 8 22c7.732 0 14-6.268 14-14a6 6 0 0 0-11.835-1.402Z"}],["path",{d:"M5.341 10.62a4 4 0 1 0 5.279-5.28"}]]];const gh=["svg",a,[["path",{d:"M2 20v-8a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v8"}],["path",{d:"M4 10V6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v4"}],["path",{d:"M12 4v6"}],["path",{d:"M2 18h20"}]]];const xh=["svg",a,[["path",{d:"M3 20v-8a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v8"}],["path",{d:"M5 10V6a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v4"}],["path",{d:"M3 18h18"}]]];const yh=["svg",a,[["path",{d:"M2 4v16"}],["path",{d:"M2 8h18a2 2 0 0 1 2 2v10"}],["path",{d:"M2 17h20"}],["path",{d:"M6 8v9"}]]];const mh=["svg",a,[["circle",{cx:"12.5",cy:"8.5",r:"2.5"}],["path",{d:"M12.5 2a6.5 6.5 0 0 0-6.22 4.6c-1.1 3.13-.78 3.9-3.18 6.08A3 3 0 0 0 5 18c4 0 8.4-1.8 11.4-4.3A6.5 6.5 0 0 0 12.5 2Z"}],["path",{d:"m18.5 6 2.19 4.5a6.48 6.48 0 0 1 .31 2 6.49 6.49 0 0 1-2.6 5.2C15.4 20.2 11 22 7 22a3 3 0 0 1-2.68-1.66L2.4 16.5"}]]];const Hh=["svg",a,[["path",{d:"M13 13v5"}],["path",{d:"M17 11.47V8"}],["path",{d:"M17 11h1a3 3 0 0 1 2.745 4.211"}],["path",{d:"m2 2 20 20"}],["path",{d:"M5 8v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2v-3"}],["path",{d:"M7.536 7.535C6.766 7.649 6.154 8 5.5 8a2.5 2.5 0 0 1-1.768-4.268"}],["path",{d:"M8.727 3.204C9.306 2.767 9.885 2 11 2c1.56 0 2 1.5 3 1.5s1.72-.5 2.5-.5a1 1 0 1 1 0 5c-.78 0-1.5-.5-2.5-.5a3.149 3.149 0 0 0-.842.12"}],["path",{d:"M9 14.6V18"}]]];const Vh=["svg",a,[["path",{d:"M17 11h1a3 3 0 0 1 0 6h-1"}],["path",{d:"M9 12v6"}],["path",{d:"M13 12v6"}],["path",{d:"M14 7.5c-1 0-1.44.5-3 .5s-2-.5-3-.5-1.72.5-2.5.5a2.5 2.5 0 0 1 0-5c.78 0 1.57.5 2.5.5S9.44 2 11 2s2 1.5 3 1.5 1.72-.5 2.5-.5a2.5 2.5 0 0 1 0 5c-.78 0-1.5-.5-2.5-.5Z"}],["path",{d:"M5 8v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8"}]]];const Ch=["svg",a,[["path",{d:"M19.4 14.9C20.2 16.4 21 17 21 17H3s3-2 3-9c0-3.3 2.7-6 6-6 .7 0 1.3.1 1.9.3"}],["path",{d:"M10.3 21a1.94 1.94 0 0 0 3.4 0"}],["circle",{cx:"18",cy:"8",r:"3"}]]];const wh=["svg",a,[["path",{d:"M18.8 4A6.3 8.7 0 0 1 20 9"}],["path",{d:"M9 9h.01"}],["circle",{cx:"9",cy:"9",r:"7"}],["rect",{width:"10",height:"6",x:"4",y:"16",rx:"2"}],["path",{d:"M14 19c3 0 4.6-1.6 4.6-1.6"}],["circle",{cx:"20",cy:"16",r:"2"}]]];const uh=["svg",a,[["path",{d:"M18.4 12c.8 3.8 2.6 5 2.6 5H3s3-2 3-9c0-3.3 2.7-6 6-6 1.8 0 3.4.8 4.5 2"}],["path",{d:"M10.3 21a1.94 1.94 0 0 0 3.4 0"}],["path",{d:"M15 8h6"}]]];const Ah=["svg",a,[["path",{d:"M8.7 3A6 6 0 0 1 18 8a21.3 21.3 0 0 0 .6 5"}],["path",{d:"M17 17H3s3-2 3-9a4.67 4.67 0 0 1 .3-1.7"}],["path",{d:"M10.3 21a1.94 1.94 0 0 0 3.4 0"}],["path",{d:"m2 2 20 20"}]]];const Lh=["svg",a,[["path",{d:"M19.3 14.8C20.1 16.4 21 17 21 17H3s3-2 3-9c0-3.3 2.7-6 6-6 1 0 1.9.2 2.8.7"}],["path",{d:"M10.3 21a1.94 1.94 0 0 0 3.4 0"}],["path",{d:"M15 8h6"}],["path",{d:"M18 5v6"}]]];const Sh=["svg",a,[["path",{d:"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"}],["path",{d:"M10.3 21a1.94 1.94 0 0 0 3.4 0"}],["path",{d:"M4 2C2.8 3.7 2 5.7 2 8"}],["path",{d:"M22 8c0-2.3-.8-4.3-2-6"}]]];const fh=["svg",a,[["path",{d:"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"}],["path",{d:"M10.3 21a1.94 1.94 0 0 0 3.4 0"}]]];const L=["svg",a,[["rect",{width:"13",height:"7",x:"3",y:"3",rx:"1"}],["path",{d:"m22 15-3-3 3-3"}],["rect",{width:"13",height:"7",x:"3",y:"14",rx:"1"}]]];const S=["svg",a,[["rect",{width:"13",height:"7",x:"8",y:"3",rx:"1"}],["path",{d:"m2 9 3 3-3 3"}],["rect",{width:"13",height:"7",x:"8",y:"14",rx:"1"}]]];const Zh=["svg",a,[["rect",{width:"7",height:"13",x:"3",y:"3",rx:"1"}],["path",{d:"m9 22 3-3 3 3"}],["rect",{width:"7",height:"13",x:"14",y:"3",rx:"1"}]]];const Ph=["svg",a,[["rect",{width:"7",height:"13",x:"3",y:"8",rx:"1"}],["path",{d:"m15 2-3 3-3-3"}],["rect",{width:"7",height:"13",x:"14",y:"8",rx:"1"}]]];const kh=["svg",a,[["path",{d:"M12.409 13.017A5 5 0 0 1 22 15c0 3.866-4 7-9 7-4.077 0-8.153-.82-10.371-2.462-.426-.316-.631-.832-.62-1.362C2.118 12.723 2.627 2 10 2a3 3 0 0 1 3 3 2 2 0 0 1-2 2c-1.105 0-1.64-.444-2-1"}],["path",{d:"M15 14a5 5 0 0 0-7.584 2"}],["path",{d:"M9.964 6.825C8.019 7.977 9.5 13 8 15"}]]];const zh=["svg",a,[["circle",{cx:"18.5",cy:"17.5",r:"3.5"}],["circle",{cx:"5.5",cy:"17.5",r:"3.5"}],["circle",{cx:"15",cy:"5",r:"1"}],["path",{d:"M12 17.5V14l-3-3 4-3 2 3h2"}]]];const Bh=["svg",a,[["rect",{x:"14",y:"14",width:"4",height:"6",rx:"2"}],["rect",{x:"6",y:"4",width:"4",height:"6",rx:"2"}],["path",{d:"M6 20h4"}],["path",{d:"M14 10h4"}],["path",{d:"M6 14h2v6"}],["path",{d:"M14 4h2v6"}]]];const Fh=["svg",a,[["path",{d:"M10 10h4"}],["path",{d:"M19 7V4a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v3"}],["path",{d:"M20 21a2 2 0 0 0 2-2v-3.851c0-1.39-2-2.962-2-4.829V8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v11a2 2 0 0 0 2 2z"}],["path",{d:"M 22 16 L 2 16"}],["path",{d:"M4 21a2 2 0 0 1-2-2v-3.851c0-1.39 2-2.962 2-4.829V8a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v11a2 2 0 0 1-2 2z"}],["path",{d:"M9 7V4a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1v3"}]]];const Dh=["svg",a,[["circle",{cx:"12",cy:"11.9",r:"2"}],["path",{d:"M6.7 3.4c-.9 2.5 0 5.2 2.2 6.7C6.5 9 3.7 9.6 2 11.6"}],["path",{d:"m8.9 10.1 1.4.8"}],["path",{d:"M17.3 3.4c.9 2.5 0 5.2-2.2 6.7 2.4-1.2 5.2-.6 6.9 1.5"}],["path",{d:"m15.1 10.1-1.4.8"}],["path",{d:"M16.7 20.8c-2.6-.4-4.6-2.6-4.7-5.3-.2 2.6-2.1 4.8-4.7 5.2"}],["path",{d:"M12 13.9v1.6"}],["path",{d:"M13.5 5.4c-1-.2-2-.2-3 0"}],["path",{d:"M17 16.4c.7-.7 1.2-1.6 1.5-2.5"}],["path",{d:"M5.5 13.9c.3.9.8 1.8 1.5 2.5"}]]];const qh=["svg",a,[["path",{d:"M16 7h.01"}],["path",{d:"M3.4 18H12a8 8 0 0 0 8-8V7a4 4 0 0 0-7.28-2.3L2 20"}],["path",{d:"m20 7 2 .5-2 .5"}],["path",{d:"M10 18v3"}],["path",{d:"M14 17.75V21"}],["path",{d:"M7 18a6 6 0 0 0 3.84-10.61"}]]];const Rh=["svg",a,[["path",{d:"M11.767 19.089c4.924.868 6.14-6.025 1.216-6.894m-1.216 6.894L5.86 18.047m5.908 1.042-.347 1.97m1.563-8.864c4.924.869 6.14-6.025 1.215-6.893m-1.215 6.893-3.94-.694m5.155-6.2L8.29 4.26m5.908 1.042.348-1.97M7.48 20.364l3.126-17.727"}]]];const bh=["svg",a,[["circle",{cx:"9",cy:"9",r:"7"}],["circle",{cx:"15",cy:"15",r:"7"}]]];const Th=["svg",a,[["path",{d:"M3 3h18"}],["path",{d:"M20 7H8"}],["path",{d:"M20 11H8"}],["path",{d:"M10 19h10"}],["path",{d:"M8 15h12"}],["path",{d:"M4 3v14"}],["circle",{cx:"4",cy:"19",r:"2"}]]];const Uh=["svg",a,[["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1"}],["path",{d:"M10 21V8a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H3"}]]];const Oh=["svg",a,[["path",{d:"m7 7 10 10-5 5V2l5 5L7 17"}],["line",{x1:"18",x2:"21",y1:"12",y2:"12"}],["line",{x1:"3",x2:"6",y1:"12",y2:"12"}]]];const Ih=["svg",a,[["path",{d:"m17 17-5 5V12l-5 5"}],["path",{d:"m2 2 20 20"}],["path",{d:"M14.5 9.5 17 7l-5-5v4.5"}]]];const Eh=["svg",a,[["path",{d:"m7 7 10 10-5 5V2l5 5L7 17"}],["path",{d:"M20.83 14.83a4 4 0 0 0 0-5.66"}],["path",{d:"M18 12h.01"}]]];const Gh=["svg",a,[["path",{d:"m7 7 10 10-5 5V2l5 5L7 17"}]]];const Wh=["svg",a,[["path",{d:"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8"}]]];const Xh=["svg",a,[["path",{d:"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"}],["circle",{cx:"12",cy:"12",r:"4"}]]];const Nh=["svg",a,[["circle",{cx:"11",cy:"13",r:"9"}],["path",{d:"M14.35 4.65 16.3 2.7a2.41 2.41 0 0 1 3.4 0l1.6 1.6a2.4 2.4 0 0 1 0 3.4l-1.95 1.95"}],["path",{d:"m22 2-1.5 1.5"}]]];const Kh=["svg",a,[["path",{d:"M17 10c.7-.7 1.69 0 2.5 0a2.5 2.5 0 1 0 0-5 .5.5 0 0 1-.5-.5 2.5 2.5 0 1 0-5 0c0 .81.7 1.8 0 2.5l-7 7c-.7.7-1.69 0-2.5 0a2.5 2.5 0 0 0 0 5c.28 0 .5.22.5.5a2.5 2.5 0 1 0 5 0c0-.81-.7-1.8 0-2.5Z"}]]];const Jh=["svg",a,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m8 13 4-7 4 7"}],["path",{d:"M9.1 11h5.7"}]]];const jh=["svg",a,[["path",{d:"M12 6v7"}],["path",{d:"M16 8v3"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M8 8v3"}]]];const Qh=["svg",a,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m9 9.5 2 2 4-4"}]]];const _h=["svg",a,[["path",{d:"M2 16V4a2 2 0 0 1 2-2h11"}],["path",{d:"M22 18H11a2 2 0 1 0 0 4h10.5a.5.5 0 0 0 .5-.5v-15a.5.5 0 0 0-.5-.5H11a2 2 0 0 0-2 2v12"}],["path",{d:"M5 14H4a2 2 0 1 0 0 4h1"}]]];const f=["svg",a,[["path",{d:"M12 17h2"}],["path",{d:"M12 22h2"}],["path",{d:"M12 2h2"}],["path",{d:"M18 22h1a1 1 0 0 0 1-1"}],["path",{d:"M18 2h1a1 1 0 0 1 1 1v1"}],["path",{d:"M20 15v2h-2"}],["path",{d:"M20 8v3"}],["path",{d:"M4 11V9"}],["path",{d:"M4 19.5V15"}],["path",{d:"M4 5v-.5A2.5 2.5 0 0 1 6.5 2H8"}],["path",{d:"M8 22H6.5a1 1 0 0 1 0-5H8"}]]];const Yh=["svg",a,[["path",{d:"M12 13V7"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m9 10 3 3 3-3"}]]];const $h=["svg",a,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M8 12v-2a4 4 0 0 1 8 0v2"}],["circle",{cx:"15",cy:"12",r:"1"}],["circle",{cx:"9",cy:"12",r:"1"}]]];const a4=["svg",a,[["path",{d:"M16 8.2A2.22 2.22 0 0 0 13.8 6c-.8 0-1.4.3-1.8.9-.4-.6-1-.9-1.8-.9A2.22 2.22 0 0 0 8 8.2c0 .6.3 1.2.7 1.6A226.652 226.652 0 0 0 12 13a404 404 0 0 0 3.3-3.1 2.413 2.413 0 0 0 .7-1.7"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}]]];const t4=["svg",a,[["path",{d:"m20 13.7-2.1-2.1a2 2 0 0 0-2.8 0L9.7 17"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["circle",{cx:"10",cy:"8",r:"2"}]]];const h4=["svg",a,[["path",{d:"m19 3 1 1"}],["path",{d:"m20 2-4.5 4.5"}],["path",{d:"M20 8v13a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H14"}],["circle",{cx:"14",cy:"8",r:"2"}]]];const d4=["svg",a,[["path",{d:"M18 6V4a2 2 0 1 0-4 0v2"}],["path",{d:"M20 15v6a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H10"}],["rect",{x:"12",y:"6",width:"8",height:"5",rx:"1"}]]];const p4=["svg",a,[["path",{d:"M10 2v8l3-3 3 3V2"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}]]];const c4=["svg",a,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M9 10h6"}]]];const M4=["svg",a,[["path",{d:"M8 3H2v15h7c1.7 0 3 1.3 3 3V7c0-2.2-1.8-4-4-4Z"}],["path",{d:"m16 12 2 2 4-4"}],["path",{d:"M22 6V3h-6c-2.2 0-4 1.8-4 4v14c0-1.7 1.3-3 3-3h7v-2.3"}]]];const s4=["svg",a,[["path",{d:"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"}],["path",{d:"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"}],["path",{d:"M6 8h2"}],["path",{d:"M6 12h2"}],["path",{d:"M16 8h2"}],["path",{d:"M16 12h2"}]]];const e4=["svg",a,[["path",{d:"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"}],["path",{d:"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"}]]];const r4=["svg",a,[["path",{d:"M12 7v6"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M9 10h6"}]]];const v4=["svg",a,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M8 11h8"}],["path",{d:"M8 7h6"}]]];const n4=["svg",a,[["path",{d:"M10 13h4"}],["path",{d:"M12 6v7"}],["path",{d:"M16 8V6H8v2"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}]]];const o4=["svg",a,[["path",{d:"M12 13V7"}],["path",{d:"M18 2h1a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2"}],["path",{d:"m9 10 3-3 3 3"}],["path",{d:"m9 5 3-3 3 3"}]]];const i4=["svg",a,[["path",{d:"M12 13V7"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m9 10 3-3 3 3"}]]];const l4=["svg",a,[["path",{d:"M15 13a3 3 0 1 0-6 0"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["circle",{cx:"12",cy:"8",r:"2"}]]];const g4=["svg",a,[["path",{d:"m14.5 7-5 5"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}],["path",{d:"m9.5 7 5 5"}]]];const x4=["svg",a,[["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20"}]]];const y4=["svg",a,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2Z"}],["path",{d:"m9 10 2 2 4-4"}]]];const m4=["svg",a,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"}],["line",{x1:"15",x2:"9",y1:"10",y2:"10"}]]];const H4=["svg",a,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"}],["line",{x1:"12",x2:"12",y1:"7",y2:"13"}],["line",{x1:"15",x2:"9",y1:"10",y2:"10"}]]];const V4=["svg",a,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2Z"}],["path",{d:"m14.5 7.5-5 5"}],["path",{d:"m9.5 7.5 5 5"}]]];const C4=["svg",a,[["path",{d:"m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"}]]];const w4=["svg",a,[["path",{d:"M4 9V5a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v4"}],["path",{d:"M8 8v1"}],["path",{d:"M12 8v1"}],["path",{d:"M16 8v1"}],["rect",{width:"20",height:"12",x:"2",y:"9",rx:"2"}],["circle",{cx:"8",cy:"15",r:"2"}],["circle",{cx:"16",cy:"15",r:"2"}]]];const u4=["svg",a,[["path",{d:"M12 6V2H8"}],["path",{d:"m8 18-4 4V8a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2Z"}],["path",{d:"M2 12h2"}],["path",{d:"M9 11v2"}],["path",{d:"M15 11v2"}],["path",{d:"M20 12h2"}]]];const A4=["svg",a,[["path",{d:"M13.67 8H18a2 2 0 0 1 2 2v4.33"}],["path",{d:"M2 14h2"}],["path",{d:"M20 14h2"}],["path",{d:"M22 22 2 2"}],["path",{d:"M8 8H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 1.414-.586"}],["path",{d:"M9 13v2"}],["path",{d:"M9.67 4H12v2.33"}]]];const L4=["svg",a,[["path",{d:"M12 8V4H8"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}],["path",{d:"M2 14h2"}],["path",{d:"M20 14h2"}],["path",{d:"M15 13v2"}],["path",{d:"M9 13v2"}]]];const S4=["svg",a,[["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M21 19a2 2 0 0 1-2 2"}],["path",{d:"M5 21a2 2 0 0 1-2-2"}],["path",{d:"M9 3h1"}],["path",{d:"M9 21h1"}],["path",{d:"M14 3h1"}],["path",{d:"M14 21h1"}],["path",{d:"M3 9v1"}],["path",{d:"M21 9v1"}],["path",{d:"M3 14v1"}],["path",{d:"M21 14v1"}]]];const f4=["svg",a,[["path",{d:"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"}],["path",{d:"m3.3 7 8.7 5 8.7-5"}],["path",{d:"M12 22V12"}]]];const Z4=["svg",a,[["path",{d:"M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z"}],["path",{d:"m7 16.5-4.74-2.85"}],["path",{d:"m7 16.5 5-3"}],["path",{d:"M7 16.5v5.17"}],["path",{d:"M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z"}],["path",{d:"m17 16.5-5-3"}],["path",{d:"m17 16.5 4.74-2.85"}],["path",{d:"M17 16.5v5.17"}],["path",{d:"M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z"}],["path",{d:"M12 8 7.26 5.15"}],["path",{d:"m12 8 4.74-2.85"}],["path",{d:"M12 13.5V8"}]]];const Z=["svg",a,[["path",{d:"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1"}],["path",{d:"M16 21h1a2 2 0 0 0 2-2v-5c0-1.1.9-2 2-2a2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1"}]]];const P4=["svg",a,[["path",{d:"M16 3h3v18h-3"}],["path",{d:"M8 21H5V3h3"}]]];const k4=["svg",a,[["path",{d:"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"}],["path",{d:"M9 13a4.5 4.5 0 0 0 3-4"}],["path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5"}],["path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396"}],["path",{d:"M6 18a4 4 0 0 1-1.967-.516"}],["path",{d:"M12 13h4"}],["path",{d:"M12 18h6a2 2 0 0 1 2 2v1"}],["path",{d:"M12 8h8"}],["path",{d:"M16 8V5a2 2 0 0 1 2-2"}],["circle",{cx:"16",cy:"13",r:".5"}],["circle",{cx:"18",cy:"3",r:".5"}],["circle",{cx:"20",cy:"21",r:".5"}],["circle",{cx:"20",cy:"8",r:".5"}]]];const z4=["svg",a,[["path",{d:"M12 5a3 3 0 1 0-5.997.142 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588 4 4 0 0 0 7.636 2.106 3.2 3.2 0 0 0 .164-.546c.028-.13.306-.13.335 0a3.2 3.2 0 0 0 .163.546 4 4 0 0 0 7.636-2.106 4 4 0 0 0 .556-6.588 4 4 0 0 0-2.526-5.77A3 3 0 1 0 12 5"}],["path",{d:"M17.599 6.5a3 3 0 0 0 .399-1.375"}],["path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5"}],["path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396"}],["path",{d:"M19.938 10.5a4 4 0 0 1 .585.396"}],["path",{d:"M6 18a4 4 0 0 1-1.967-.516"}],["path",{d:"M19.967 17.484A4 4 0 0 1 18 18"}],["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"m15.7 10.4-.9.4"}],["path",{d:"m9.2 13.2-.9.4"}],["path",{d:"m13.6 15.7-.4-.9"}],["path",{d:"m10.8 9.2-.4-.9"}],["path",{d:"m15.7 13.5-.9-.4"}],["path",{d:"m9.2 10.9-.9-.4"}],["path",{d:"m10.5 15.7.4-.9"}],["path",{d:"m13.1 9.2.4-.9"}]]];const B4=["svg",a,[["path",{d:"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"}],["path",{d:"M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"}],["path",{d:"M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"}],["path",{d:"M17.599 6.5a3 3 0 0 0 .399-1.375"}],["path",{d:"M6.003 5.125A3 3 0 0 0 6.401 6.5"}],["path",{d:"M3.477 10.896a4 4 0 0 1 .585-.396"}],["path",{d:"M19.938 10.5a4 4 0 0 1 .585.396"}],["path",{d:"M6 18a4 4 0 0 1-1.967-.516"}],["path",{d:"M19.967 17.484A4 4 0 0 1 18 18"}]]];const F4=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 9v6"}],["path",{d:"M16 15v6"}],["path",{d:"M16 3v6"}],["path",{d:"M3 15h18"}],["path",{d:"M3 9h18"}],["path",{d:"M8 15v6"}],["path",{d:"M8 3v6"}]]];const D4=["svg",a,[["path",{d:"M12 12h.01"}],["path",{d:"M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"}],["path",{d:"M22 13a18.15 18.15 0 0 1-20 0"}],["rect",{width:"20",height:"14",x:"2",y:"6",rx:"2"}]]];const q4=["svg",a,[["path",{d:"M12 11v4"}],["path",{d:"M14 13h-4"}],["path",{d:"M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"}],["path",{d:"M18 6v14"}],["path",{d:"M6 6v14"}],["rect",{width:"20",height:"14",x:"2",y:"6",rx:"2"}]]];const R4=["svg",a,[["path",{d:"M16 20V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"}],["rect",{width:"20",height:"14",x:"2",y:"6",rx:"2"}]]];const b4=["svg",a,[["rect",{x:"8",y:"8",width:"8",height:"8",rx:"2"}],["path",{d:"M4 10a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2"}],["path",{d:"M14 20a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2"}]]];const T4=["svg",a,[["path",{d:"m9.06 11.9 8.07-8.06a2.85 2.85 0 1 1 4.03 4.03l-8.06 8.08"}],["path",{d:"M7.07 14.94c-1.66 0-3 1.35-3 3.02 0 1.33-2.5 1.52-2 2.02 1.08 1.1 2.49 2.02 4 2.02 2.2 0 4-1.8 4-4.04a3.01 3.01 0 0 0-3-3.02z"}]]];const U4=["svg",a,[["path",{d:"M15 7.13V6a3 3 0 0 0-5.14-2.1L8 2"}],["path",{d:"M14.12 3.88 16 2"}],["path",{d:"M22 13h-4v-2a4 4 0 0 0-4-4h-1.3"}],["path",{d:"M20.97 5c0 2.1-1.6 3.8-3.5 4"}],["path",{d:"m2 2 20 20"}],["path",{d:"M7.7 7.7A4 4 0 0 0 6 11v3a6 6 0 0 0 11.13 3.13"}],["path",{d:"M12 20v-8"}],["path",{d:"M6 13H2"}],["path",{d:"M3 21c0-2.1 1.7-3.9 3.8-4"}]]];const O4=["svg",a,[["path",{d:"M12.765 21.522a.5.5 0 0 1-.765-.424v-8.196a.5.5 0 0 1 .765-.424l5.878 3.674a1 1 0 0 1 0 1.696z"}],["path",{d:"M14.12 3.88 16 2"}],["path",{d:"M18 11a4 4 0 0 0-4-4h-4a4 4 0 0 0-4 4v3a6.1 6.1 0 0 0 2 4.5"}],["path",{d:"M20.97 5c0 2.1-1.6 3.8-3.5 4"}],["path",{d:"M3 21c0-2.1 1.7-3.9 3.8-4"}],["path",{d:"M6 13H2"}],["path",{d:"M6.53 9C4.6 8.8 3 7.1 3 5"}],["path",{d:"m8 2 1.88 1.88"}],["path",{d:"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"}]]];const I4=["svg",a,[["path",{d:"m8 2 1.88 1.88"}],["path",{d:"M14.12 3.88 16 2"}],["path",{d:"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"}],["path",{d:"M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6"}],["path",{d:"M12 20v-9"}],["path",{d:"M6.53 9C4.6 8.8 3 7.1 3 5"}],["path",{d:"M6 13H2"}],["path",{d:"M3 21c0-2.1 1.7-3.9 3.8-4"}],["path",{d:"M20.97 5c0 2.1-1.6 3.8-3.5 4"}],["path",{d:"M22 13h-4"}],["path",{d:"M17.2 17c2.1.1 3.8 1.9 3.8 4"}]]];const E4=["svg",a,[["path",{d:"M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z"}],["path",{d:"M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2"}],["path",{d:"M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2"}],["path",{d:"M10 6h4"}],["path",{d:"M10 10h4"}],["path",{d:"M10 14h4"}],["path",{d:"M10 18h4"}]]];const G4=["svg",a,[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2",ry:"2"}],["path",{d:"M9 22v-4h6v4"}],["path",{d:"M8 6h.01"}],["path",{d:"M16 6h.01"}],["path",{d:"M12 6h.01"}],["path",{d:"M12 10h.01"}],["path",{d:"M12 14h.01"}],["path",{d:"M16 10h.01"}],["path",{d:"M16 14h.01"}],["path",{d:"M8 10h.01"}],["path",{d:"M8 14h.01"}]]];const W4=["svg",a,[["path",{d:"M4 6 2 7"}],["path",{d:"M10 6h4"}],["path",{d:"m22 7-2-1"}],["rect",{width:"16",height:"16",x:"4",y:"3",rx:"2"}],["path",{d:"M4 11h16"}],["path",{d:"M8 15h.01"}],["path",{d:"M16 15h.01"}],["path",{d:"M6 19v2"}],["path",{d:"M18 21v-2"}]]];const X4=["svg",a,[["path",{d:"M8 6v6"}],["path",{d:"M15 6v6"}],["path",{d:"M2 12h19.6"}],["path",{d:"M18 18h3s.5-1.7.8-2.8c.1-.4.2-.8.2-1.2 0-.4-.1-.8-.2-1.2l-1.4-5C20.1 6.8 19.1 6 18 6H4a2 2 0 0 0-2 2v10h3"}],["circle",{cx:"7",cy:"18",r:"2"}],["path",{d:"M9 18h5"}],["circle",{cx:"16",cy:"18",r:"2"}]]];const N4=["svg",a,[["path",{d:"M10 3h.01"}],["path",{d:"M14 2h.01"}],["path",{d:"m2 9 20-5"}],["path",{d:"M12 12V6.5"}],["rect",{width:"16",height:"10",x:"4",y:"12",rx:"3"}],["path",{d:"M9 12v5"}],["path",{d:"M15 12v5"}],["path",{d:"M4 17h16"}]]];const K4=["svg",a,[["path",{d:"M17 21v-2a1 1 0 0 1-1-1v-1a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1"}],["path",{d:"M19 15V6.5a1 1 0 0 0-7 0v11a1 1 0 0 1-7 0V9"}],["path",{d:"M21 21v-2h-4"}],["path",{d:"M3 5h4V3"}],["path",{d:"M7 5a1 1 0 0 1 1 1v1a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a1 1 0 0 1 1-1V3"}]]];const J4=["svg",a,[["circle",{cx:"9",cy:"7",r:"2"}],["path",{d:"M7.2 7.9 3 11v9c0 .6.4 1 1 1h16c.6 0 1-.4 1-1v-9c0-2-3-6-7-8l-3.6 2.6"}],["path",{d:"M16 13H3"}],["path",{d:"M16 17H3"}]]];const j4=["svg",a,[["path",{d:"M20 21v-8a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8"}],["path",{d:"M4 16s.5-1 2-1 2.5 2 4 2 2.5-2 4-2 2.5 2 4 2 2-1 2-1"}],["path",{d:"M2 21h20"}],["path",{d:"M7 8v3"}],["path",{d:"M12 8v3"}],["path",{d:"M17 8v3"}],["path",{d:"M7 4h.01"}],["path",{d:"M12 4h.01"}],["path",{d:"M17 4h.01"}]]];const Q4=["svg",a,[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["line",{x1:"8",x2:"16",y1:"6",y2:"6"}],["line",{x1:"16",x2:"16",y1:"14",y2:"18"}],["path",{d:"M16 10h.01"}],["path",{d:"M12 10h.01"}],["path",{d:"M8 10h.01"}],["path",{d:"M12 14h.01"}],["path",{d:"M8 14h.01"}],["path",{d:"M12 18h.01"}],["path",{d:"M8 18h.01"}]]];const _4=["svg",a,[["path",{d:"m14 18 4 4 4-4"}],["path",{d:"M16 2v4"}],["path",{d:"M18 14v8"}],["path",{d:"M21 11.354V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7.343"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}]]];const Y4=["svg",a,[["path",{d:"m14 18 4-4 4 4"}],["path",{d:"M16 2v4"}],["path",{d:"M18 22v-8"}],["path",{d:"M21 11.343V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h9"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}]]];const $4=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21 14V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8"}],["path",{d:"M3 10h18"}],["path",{d:"m16 20 2 2 4-4"}]]];const a5=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"m9 16 2 2 4-4"}]]];const t5=["svg",a,[["path",{d:"M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5"}],["path",{d:"M16 2v4"}],["path",{d:"M8 2v4"}],["path",{d:"M3 10h5"}],["path",{d:"M17.5 17.5 16 16.3V14"}],["circle",{cx:"16",cy:"16",r:"6"}]]];const h5=["svg",a,[["path",{d:"m15.2 16.9-.9-.4"}],["path",{d:"m15.2 19.1-.9.4"}],["path",{d:"M16 2v4"}],["path",{d:"m16.9 15.2-.4-.9"}],["path",{d:"m16.9 20.8-.4.9"}],["path",{d:"m19.5 14.3-.4.9"}],["path",{d:"m19.5 21.7-.4-.9"}],["path",{d:"M21 10.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6"}],["path",{d:"m21.7 16.5-.9.4"}],["path",{d:"m21.7 19.5-.9-.4"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}],["circle",{cx:"18",cy:"18",r:"3"}]]];const d5=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"M8 14h.01"}],["path",{d:"M12 14h.01"}],["path",{d:"M16 14h.01"}],["path",{d:"M8 18h.01"}],["path",{d:"M12 18h.01"}],["path",{d:"M16 18h.01"}]]];const p5=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21 17V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11Z"}],["path",{d:"M3 10h18"}],["path",{d:"M15 22v-4a2 2 0 0 1 2-2h4"}]]];const c5=["svg",a,[["path",{d:"M3 10h18V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7"}],["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21.29 14.7a2.43 2.43 0 0 0-2.65-.52c-.3.12-.57.3-.8.53l-.34.34-.35-.34a2.43 2.43 0 0 0-2.65-.53c-.3.12-.56.3-.79.53-.95.94-1 2.53.2 3.74L17.5 22l3.6-3.55c1.2-1.21 1.14-2.8.19-3.74Z"}]]];const M5=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"M10 16h4"}]]];const s5=["svg",a,[["path",{d:"M16 19h6"}],["path",{d:"M16 2v4"}],["path",{d:"M21 15V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8.5"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}]]];const e5=["svg",a,[["path",{d:"M4.2 4.2A2 2 0 0 0 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 1.82-1.18"}],["path",{d:"M21 15.5V6a2 2 0 0 0-2-2H9.5"}],["path",{d:"M16 2v4"}],["path",{d:"M3 10h7"}],["path",{d:"M21 10h-5.5"}],["path",{d:"m2 2 20 20"}]]];const r5=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"M10 16h4"}],["path",{d:"M12 14v4"}]]];const v5=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21 13V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8"}],["path",{d:"M3 10h18"}],["path",{d:"M16 19h6"}],["path",{d:"M19 16v6"}]]];const n5=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M16 2v4"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}],["path",{d:"M17 14h-6"}],["path",{d:"M13 18H7"}],["path",{d:"M7 14h.01"}],["path",{d:"M17 18h.01"}]]];const o5=["svg",a,[["path",{d:"M16 2v4"}],["path",{d:"M21 11.75V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h7.25"}],["path",{d:"m22 22-1.875-1.875"}],["path",{d:"M3 10h18"}],["path",{d:"M8 2v4"}],["circle",{cx:"18",cy:"18",r:"3"}]]];const i5=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M21 13V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8"}],["path",{d:"M3 10h18"}],["path",{d:"m17 22 5-5"}],["path",{d:"m17 17 5 5"}]]];const l5=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}],["path",{d:"m14 14-4 4"}],["path",{d:"m10 14 4 4"}]]];const g5=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["path",{d:"M3 10h18"}]]];const x5=["svg",a,[["line",{x1:"2",x2:"22",y1:"2",y2:"22"}],["path",{d:"M7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16"}],["path",{d:"M9.5 4h5L17 7h3a2 2 0 0 1 2 2v7.5"}],["path",{d:"M14.121 15.121A3 3 0 1 1 9.88 10.88"}]]];const y5=["svg",a,[["path",{d:"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"}],["circle",{cx:"12",cy:"13",r:"3"}]]];const m5=["svg",a,[["path",{d:"M5.7 21a2 2 0 0 1-3.5-2l8.6-14a6 6 0 0 1 10.4 6 2 2 0 1 1-3.464-2 2 2 0 1 0-3.464-2Z"}],["path",{d:"M17.75 7 15 2.1"}],["path",{d:"M10.9 4.8 13 9"}],["path",{d:"m7.9 9.7 2 4.4"}],["path",{d:"M4.9 14.7 7 18.9"}]]];const H5=["svg",a,[["path",{d:"m8.5 8.5-1 1a4.95 4.95 0 0 0 7 7l1-1"}],["path",{d:"M11.843 6.187A4.947 4.947 0 0 1 16.5 7.5a4.947 4.947 0 0 1 1.313 4.657"}],["path",{d:"M14 16.5V14"}],["path",{d:"M14 6.5v1.843"}],["path",{d:"M10 10v7.5"}],["path",{d:"m16 7 1-5 1.367.683A3 3 0 0 0 19.708 3H21v1.292a3 3 0 0 0 .317 1.341L22 7l-5 1"}],["path",{d:"m8 17-1 5-1.367-.683A3 3 0 0 0 4.292 21H3v-1.292a3 3 0 0 0-.317-1.341L2 17l5-1"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const V5=["svg",a,[["path",{d:"m9.5 7.5-2 2a4.95 4.95 0 1 0 7 7l2-2a4.95 4.95 0 1 0-7-7Z"}],["path",{d:"M14 6.5v10"}],["path",{d:"M10 7.5v10"}],["path",{d:"m16 7 1-5 1.37.68A3 3 0 0 0 19.7 3H21v1.3c0 .46.1.92.32 1.33L22 7l-5 1"}],["path",{d:"m8 17-1 5-1.37-.68A3 3 0 0 0 4.3 21H3v-1.3a3 3 0 0 0-.32-1.33L2 17l5-1"}]]];const C5=["svg",a,[["path",{d:"M12 22v-4"}],["path",{d:"M7 12c-1.5 0-4.5 1.5-5 3 3.5 1.5 6 1 6 1-1.5 1.5-2 3.5-2 5 2.5 0 4.5-1.5 6-3 1.5 1.5 3.5 3 6 3 0-1.5-.5-3.5-2-5 0 0 2.5.5 6-1-.5-1.5-3.5-3-5-3 1.5-1 4-4 4-6-2.5 0-5.5 1.5-7 3 0-2.5-.5-5-2-7-1.5 2-2 4.5-2 7-1.5-1.5-4.5-3-7-3 0 2 2.5 5 4 6"}]]];const w5=["svg",a,[["path",{d:"M10.5 5H19a2 2 0 0 1 2 2v8.5"}],["path",{d:"M17 11h-.5"}],["path",{d:"M19 19H5a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2"}],["path",{d:"m2 2 20 20"}],["path",{d:"M7 11h4"}],["path",{d:"M7 15h2.5"}]]];const P=["svg",a,[["rect",{width:"18",height:"14",x:"3",y:"5",rx:"2",ry:"2"}],["path",{d:"M7 15h4M15 15h2M7 11h2M13 11h4"}]]];const u5=["svg",a,[["path",{d:"m21 8-2 2-1.5-3.7A2 2 0 0 0 15.646 5H8.4a2 2 0 0 0-1.903 1.257L5 10 3 8"}],["path",{d:"M7 14h.01"}],["path",{d:"M17 14h.01"}],["rect",{width:"18",height:"8",x:"3",y:"10",rx:"2"}],["path",{d:"M5 18v2"}],["path",{d:"M19 18v2"}]]];const A5=["svg",a,[["path",{d:"M10 2h4"}],["path",{d:"m21 8-2 2-1.5-3.7A2 2 0 0 0 15.646 5H8.4a2 2 0 0 0-1.903 1.257L5 10 3 8"}],["path",{d:"M7 14h.01"}],["path",{d:"M17 14h.01"}],["rect",{width:"18",height:"8",x:"3",y:"10",rx:"2"}],["path",{d:"M5 18v2"}],["path",{d:"M19 18v2"}]]];const L5=["svg",a,[["path",{d:"M19 17h2c.6 0 1-.4 1-1v-3c0-.9-.7-1.7-1.5-1.9C18.7 10.6 16 10 16 10s-1.3-1.4-2.2-2.3c-.5-.4-1.1-.7-1.8-.7H5c-.6 0-1.1.4-1.4.9l-1.4 2.9A3.7 3.7 0 0 0 2 12v4c0 .6.4 1 1 1h2"}],["circle",{cx:"7",cy:"17",r:"2"}],["path",{d:"M9 17h6"}],["circle",{cx:"17",cy:"17",r:"2"}]]];const S5=["svg",a,[["rect",{width:"4",height:"4",x:"2",y:"9"}],["rect",{width:"4",height:"10",x:"10",y:"9"}],["path",{d:"M18 19V9a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v8a2 2 0 0 0 2 2h2"}],["circle",{cx:"8",cy:"19",r:"2"}],["path",{d:"M10 19h12v-2"}]]];const f5=["svg",a,[["path",{d:"M2.27 21.7s9.87-3.5 12.73-6.36a4.5 4.5 0 0 0-6.36-6.37C5.77 11.84 2.27 21.7 2.27 21.7zM8.64 14l-2.05-2.04M15.34 15l-2.46-2.46"}],["path",{d:"M22 9s-1.33-2-3.5-2C16.86 7 15 9 15 9s1.33 2 3.5 2S22 9 22 9z"}],["path",{d:"M15 2s-2 1.33-2 3.5S15 9 15 9s2-1.84 2-3.5C17 3.33 15 2 15 2z"}]]];const Z5=["svg",a,[["circle",{cx:"7",cy:"12",r:"3"}],["path",{d:"M10 9v6"}],["circle",{cx:"17",cy:"12",r:"3"}],["path",{d:"M14 7v8"}]]];const P5=["svg",a,[["path",{d:"m3 15 4-8 4 8"}],["path",{d:"M4 13h6"}],["circle",{cx:"18",cy:"12",r:"3"}],["path",{d:"M21 9v6"}]]];const k5=["svg",a,[["path",{d:"m3 15 4-8 4 8"}],["path",{d:"M4 13h6"}],["path",{d:"M15 11h4.5a2 2 0 0 1 0 4H15V7h4a2 2 0 0 1 0 4"}]]];const z5=["svg",a,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["circle",{cx:"8",cy:"10",r:"2"}],["path",{d:"M8 12h8"}],["circle",{cx:"16",cy:"10",r:"2"}],["path",{d:"m6 20 .7-2.9A1.4 1.4 0 0 1 8.1 16h7.8a1.4 1.4 0 0 1 1.4 1l.7 3"}]]];const B5=["svg",a,[["path",{d:"M2 8V6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6"}],["path",{d:"M2 12a9 9 0 0 1 8 8"}],["path",{d:"M2 16a5 5 0 0 1 4 4"}],["line",{x1:"2",x2:"2.01",y1:"20",y2:"20"}]]];const F5=["svg",a,[["path",{d:"M22 20v-9H2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2Z"}],["path",{d:"M18 11V4H6v7"}],["path",{d:"M15 22v-4a3 3 0 0 0-3-3a3 3 0 0 0-3 3v4"}],["path",{d:"M22 11V9"}],["path",{d:"M2 11V9"}],["path",{d:"M6 4V2"}],["path",{d:"M18 4V2"}],["path",{d:"M10 4V2"}],["path",{d:"M14 4V2"}]]];const D5=["svg",a,[["path",{d:"M12 5c.67 0 1.35.09 2 .26 1.78-2 5.03-2.84 6.42-2.26 1.4.58-.42 7-.42 7 .57 1.07 1 2.24 1 3.44C21 17.9 16.97 21 12 21s-9-3-9-7.56c0-1.25.5-2.4 1-3.44 0 0-1.89-6.42-.5-7 1.39-.58 4.72.23 6.5 2.23A9.04 9.04 0 0 1 12 5Z"}],["path",{d:"M8 14v.5"}],["path",{d:"M16 14v.5"}],["path",{d:"M11.25 16.25h1.5L12 17l-.75-.75Z"}]]];const q5=["svg",a,[["path",{d:"M16.75 12h3.632a1 1 0 0 1 .894 1.447l-2.034 4.069a1 1 0 0 1-1.708.134l-2.124-2.97"}],["path",{d:"M17.106 9.053a1 1 0 0 1 .447 1.341l-3.106 6.211a1 1 0 0 1-1.342.447L3.61 12.3a2.92 2.92 0 0 1-1.3-3.91L3.69 5.6a2.92 2.92 0 0 1 3.92-1.3z"}],["path",{d:"M2 19h3.76a2 2 0 0 0 1.8-1.1L9 15"}],["path",{d:"M2 21v-4"}],["path",{d:"M7 9h.01"}]]];const k=["svg",a,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 11.207a.5.5 0 0 1 .146-.353l2-2a.5.5 0 0 1 .708 0l3.292 3.292a.5.5 0 0 0 .708 0l4.292-4.292a.5.5 0 0 1 .854.353V16a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1z"}]]];const z=["svg",a,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["rect",{x:"7",y:"13",width:"9",height:"4",rx:"1"}],["rect",{x:"7",y:"5",width:"12",height:"4",rx:"1"}]]];const R5=["svg",a,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 11h8"}],["path",{d:"M7 16h3"}],["path",{d:"M7 6h12"}]]];const b5=["svg",a,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 11h8"}],["path",{d:"M7 16h12"}],["path",{d:"M7 6h3"}]]];const T5=["svg",a,[["path",{d:"M11 13v4"}],["path",{d:"M15 5v4"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["rect",{x:"7",y:"13",width:"9",height:"4",rx:"1"}],["rect",{x:"7",y:"5",width:"12",height:"4",rx:"1"}]]];const B=["svg",a,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 16h8"}],["path",{d:"M7 11h12"}],["path",{d:"M7 6h3"}]]];const F=["svg",a,[["path",{d:"M9 5v4"}],["rect",{width:"4",height:"6",x:"7",y:"9",rx:"1"}],["path",{d:"M9 15v2"}],["path",{d:"M17 3v2"}],["rect",{width:"4",height:"8",x:"15",y:"5",rx:"1"}],["path",{d:"M17 13v3"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}]]];const D=["svg",a,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["rect",{x:"15",y:"5",width:"4",height:"12",rx:"1"}],["rect",{x:"7",y:"8",width:"4",height:"9",rx:"1"}]]];const U5=["svg",a,[["path",{d:"M13 17V9"}],["path",{d:"M18 17v-3"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M8 17V5"}]]];const q=["svg",a,[["path",{d:"M13 17V9"}],["path",{d:"M18 17V5"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M8 17v-3"}]]];const O5=["svg",a,[["path",{d:"M11 13H7"}],["path",{d:"M19 9h-4"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["rect",{x:"15",y:"5",width:"4",height:"12",rx:"1"}],["rect",{x:"7",y:"8",width:"4",height:"9",rx:"1"}]]];const R=["svg",a,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M18 17V9"}],["path",{d:"M13 17V5"}],["path",{d:"M8 17v-3"}]]];const b=["svg",a,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"m19 9-5 5-4-4-3 3"}]]];const I5=["svg",a,[["path",{d:"m13.11 7.664 1.78 2.672"}],["path",{d:"m14.162 12.788-3.324 1.424"}],["path",{d:"m20 4-6.06 1.515"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["circle",{cx:"12",cy:"6",r:"2"}],["circle",{cx:"16",cy:"12",r:"2"}],["circle",{cx:"9",cy:"15",r:"2"}]]];const E5=["svg",a,[["path",{d:"M12 20V10"}],["path",{d:"M18 20v-4"}],["path",{d:"M6 20V4"}]]];const T=["svg",a,[["line",{x1:"12",x2:"12",y1:"20",y2:"10"}],["line",{x1:"18",x2:"18",y1:"20",y2:"4"}],["line",{x1:"6",x2:"6",y1:"20",y2:"16"}]]];const U=["svg",a,[["line",{x1:"18",x2:"18",y1:"20",y2:"10"}],["line",{x1:"12",x2:"12",y1:"20",y2:"4"}],["line",{x1:"6",x2:"6",y1:"20",y2:"14"}]]];const G5=["svg",a,[["path",{d:"M12 16v5"}],["path",{d:"M16 14v7"}],["path",{d:"M20 10v11"}],["path",{d:"m22 3-8.646 8.646a.5.5 0 0 1-.708 0L9.354 8.354a.5.5 0 0 0-.707 0L2 15"}],["path",{d:"M4 18v3"}],["path",{d:"M8 14v7"}]]];const O=["svg",a,[["path",{d:"M8 6h10"}],["path",{d:"M6 12h9"}],["path",{d:"M11 18h7"}]]];const I=["svg",a,[["path",{d:"M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z"}],["path",{d:"M21.21 15.89A10 10 0 1 1 8 2.83"}]]];const E=["svg",a,[["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor"}],["circle",{cx:"18.5",cy:"5.5",r:".5",fill:"currentColor"}],["circle",{cx:"11.5",cy:"11.5",r:".5",fill:"currentColor"}],["circle",{cx:"7.5",cy:"16.5",r:".5",fill:"currentColor"}],["circle",{cx:"17.5",cy:"14.5",r:".5",fill:"currentColor"}],["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}]]];const W5=["svg",a,[["path",{d:"M3 3v16a2 2 0 0 0 2 2h16"}],["path",{d:"M7 16c.5-2 1.5-7 4-7 2 0 2 3 4 3 2.5 0 4.5-5 5-7"}]]];const X5=["svg",a,[["path",{d:"M18 6 7 17l-5-5"}],["path",{d:"m22 10-7.5 7.5L13 16"}]]];const N5=["svg",a,[["path",{d:"M20 6 9 17l-5-5"}]]];const K5=["svg",a,[["path",{d:"M17 21a1 1 0 0 0 1-1v-5.35c0-.457.316-.844.727-1.041a4 4 0 0 0-2.134-7.589 5 5 0 0 0-9.186 0 4 4 0 0 0-2.134 7.588c.411.198.727.585.727 1.041V20a1 1 0 0 0 1 1Z"}],["path",{d:"M6 17h12"}]]];const J5=["svg",a,[["path",{d:"M2 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z"}],["path",{d:"M12 17a5 5 0 0 0 10 0c0-2.76-2.5-5-5-3-2.5-2-5 .24-5 3Z"}],["path",{d:"M7 14c3.22-2.91 4.29-8.75 5-12 1.66 2.38 4.94 9 5 12"}],["path",{d:"M22 9c-4.29 0-7.14-2.33-10-7 5.71 0 10 4.67 10 7Z"}]]];const j5=["svg",a,[["path",{d:"m6 9 6 6 6-6"}]]];const Q5=["svg",a,[["path",{d:"m17 18-6-6 6-6"}],["path",{d:"M7 6v12"}]]];const _5=["svg",a,[["path",{d:"m7 18 6-6-6-6"}],["path",{d:"M17 6v12"}]]];const Y5=["svg",a,[["path",{d:"m15 18-6-6 6-6"}]]];const $5=["svg",a,[["path",{d:"m9 18 6-6-6-6"}]]];const a3=["svg",a,[["path",{d:"m18 15-6-6-6 6"}]]];const t3=["svg",a,[["path",{d:"m7 20 5-5 5 5"}],["path",{d:"m7 4 5 5 5-5"}]]];const h3=["svg",a,[["path",{d:"m7 6 5 5 5-5"}],["path",{d:"m7 13 5 5 5-5"}]]];const d3=["svg",a,[["path",{d:"m18 8 4 4-4 4"}],["path",{d:"m6 8-4 4 4 4"}],["path",{d:"M8 12h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M16 12h.01"}]]];const p3=["svg",a,[["path",{d:"m9 7-5 5 5 5"}],["path",{d:"m15 7 5 5-5 5"}]]];const c3=["svg",a,[["path",{d:"m11 17-5-5 5-5"}],["path",{d:"m18 17-5-5 5-5"}]]];const M3=["svg",a,[["path",{d:"m20 17-5-5 5-5"}],["path",{d:"m4 17 5-5-5-5"}]]];const s3=["svg",a,[["path",{d:"m6 17 5-5-5-5"}],["path",{d:"m13 17 5-5-5-5"}]]];const e3=["svg",a,[["path",{d:"m7 15 5 5 5-5"}],["path",{d:"m7 9 5-5 5 5"}]]];const r3=["svg",a,[["path",{d:"m17 11-5-5-5 5"}],["path",{d:"m17 18-5-5-5 5"}]]];const v3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"4"}],["line",{x1:"21.17",x2:"12",y1:"8",y2:"8"}],["line",{x1:"3.95",x2:"8.54",y1:"6.06",y2:"14"}],["line",{x1:"10.88",x2:"15.46",y1:"21.94",y2:"14"}]]];const n3=["svg",a,[["path",{d:"M10 9h4"}],["path",{d:"M12 7v5"}],["path",{d:"M14 22v-4a2 2 0 0 0-4 0v4"}],["path",{d:"M18 22V5.618a1 1 0 0 0-.553-.894l-4.553-2.277a2 2 0 0 0-1.788 0L6.553 4.724A1 1 0 0 0 6 5.618V22"}],["path",{d:"m18 7 3.447 1.724a1 1 0 0 1 .553.894V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9.618a1 1 0 0 1 .553-.894L6 7"}]]];const o3=["svg",a,[["path",{d:"M12 12H3a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h13"}],["path",{d:"M18 8c0-2.5-2-2.5-2-5"}],["path",{d:"m2 2 20 20"}],["path",{d:"M21 12a1 1 0 0 1 1 1v2a1 1 0 0 1-.5.866"}],["path",{d:"M22 8c0-2.5-2-2.5-2-5"}],["path",{d:"M7 12v4"}]]];const i3=["svg",a,[["path",{d:"M17 12H3a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h14"}],["path",{d:"M18 8c0-2.5-2-2.5-2-5"}],["path",{d:"M21 16a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1"}],["path",{d:"M22 8c0-2.5-2-2.5-2-5"}],["path",{d:"M7 12v4"}]]];const G=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16"}]]];const W=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 8v8"}],["path",{d:"m8 12 4 4 4-4"}]]];const X=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M16 12H8"}],["path",{d:"m12 8-4 4 4 4"}]]];const N=["svg",a,[["path",{d:"M2 12a10 10 0 1 1 10 10"}],["path",{d:"m2 22 10-10"}],["path",{d:"M8 22H2v-6"}]]];const K=["svg",a,[["path",{d:"M12 22a10 10 0 1 1 10-10"}],["path",{d:"M22 22 12 12"}],["path",{d:"M22 16v6h-6"}]]];const J=["svg",a,[["path",{d:"M2 8V2h6"}],["path",{d:"m2 2 10 10"}],["path",{d:"M12 2A10 10 0 1 1 2 12"}]]];const j=["svg",a,[["path",{d:"M22 12A10 10 0 1 1 12 2"}],["path",{d:"M22 2 12 12"}],["path",{d:"M16 2h6v6"}]]];const Q=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 12h8"}],["path",{d:"m12 16 4-4-4-4"}]]];const _=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m16 12-4-4-4 4"}],["path",{d:"M12 16V8"}]]];const Y=["svg",a,[["path",{d:"M21.801 10A10 10 0 1 1 17 3.335"}],["path",{d:"m9 11 3 3L22 4"}]]];const $=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m9 12 2 2 4-4"}]]];const a1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m16 10-4 4-4-4"}]]];const t1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m14 16-4-4 4-4"}]]];const h1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m10 8 4 4-4 4"}]]];const d1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m8 14 4-4 4 4"}]]];const l3=["svg",a,[["path",{d:"M10.1 2.182a10 10 0 0 1 3.8 0"}],["path",{d:"M13.9 21.818a10 10 0 0 1-3.8 0"}],["path",{d:"M17.609 3.721a10 10 0 0 1 2.69 2.7"}],["path",{d:"M2.182 13.9a10 10 0 0 1 0-3.8"}],["path",{d:"M20.279 17.609a10 10 0 0 1-2.7 2.69"}],["path",{d:"M21.818 10.1a10 10 0 0 1 0 3.8"}],["path",{d:"M3.721 6.391a10 10 0 0 1 2.7-2.69"}],["path",{d:"M6.391 20.279a10 10 0 0 1-2.69-2.7"}]]];const p1=["svg",a,[["line",{x1:"8",x2:"16",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"16",y2:"16"}],["line",{x1:"12",x2:"12",y1:"8",y2:"8"}],["circle",{cx:"12",cy:"12",r:"10"}]]];const g3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"}],["path",{d:"M12 18V6"}]]];const x3=["svg",a,[["path",{d:"M10.1 2.18a9.93 9.93 0 0 1 3.8 0"}],["path",{d:"M17.6 3.71a9.95 9.95 0 0 1 2.69 2.7"}],["path",{d:"M21.82 10.1a9.93 9.93 0 0 1 0 3.8"}],["path",{d:"M20.29 17.6a9.95 9.95 0 0 1-2.7 2.69"}],["path",{d:"M13.9 21.82a9.94 9.94 0 0 1-3.8 0"}],["path",{d:"M6.4 20.29a9.95 9.95 0 0 1-2.69-2.7"}],["path",{d:"M2.18 13.9a9.93 9.93 0 0 1 0-3.8"}],["path",{d:"M3.71 6.4a9.95 9.95 0 0 1 2.7-2.69"}],["circle",{cx:"12",cy:"12",r:"1"}]]];const y3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"1"}]]];const m3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M17 12h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M7 12h.01"}]]];const H3=["svg",a,[["path",{d:"M7 10h10"}],["path",{d:"M7 14h10"}],["circle",{cx:"12",cy:"12",r:"10"}]]];const V3=["svg",a,[["path",{d:"M12 2a10 10 0 0 1 7.38 16.75"}],["path",{d:"m16 12-4-4-4 4"}],["path",{d:"M12 16V8"}],["path",{d:"M2.5 8.875a10 10 0 0 0-.5 3"}],["path",{d:"M2.83 16a10 10 0 0 0 2.43 3.4"}],["path",{d:"M4.636 5.235a10 10 0 0 1 .891-.857"}],["path",{d:"M8.644 21.42a10 10 0 0 0 7.631-.38"}]]];const C3=["svg",a,[["path",{d:"M12 2a10 10 0 0 1 7.38 16.75"}],["path",{d:"M12 8v8"}],["path",{d:"M16 12H8"}],["path",{d:"M2.5 8.875a10 10 0 0 0-.5 3"}],["path",{d:"M2.83 16a10 10 0 0 0 2.43 3.4"}],["path",{d:"M4.636 5.235a10 10 0 0 1 .891-.857"}],["path",{d:"M8.644 21.42a10 10 0 0 0 7.631-.38"}]]];const c1=["svg",a,[["path",{d:"M15.6 2.7a10 10 0 1 0 5.7 5.7"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M13.4 10.6 19 5"}]]];const M1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"}],["path",{d:"M12 17h.01"}]]];const s1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 12h8"}]]];const w3=["svg",a,[["path",{d:"m2 2 20 20"}],["path",{d:"M8.35 2.69A10 10 0 0 1 21.3 15.65"}],["path",{d:"M19.08 19.08A10 10 0 1 1 4.92 4.92"}]]];const e1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m5 5 14 14"}],["path",{d:"M13 13a3 3 0 1 0 0-6H9v2"}],["path",{d:"M9 17v-2.34"}]]];const r1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M9 17V7h4a3 3 0 0 1 0 6H9"}]]];const v1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"10",x2:"10",y1:"15",y2:"9"}],["line",{x1:"14",x2:"14",y1:"15",y2:"9"}]]];const n1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m15 9-6 6"}],["path",{d:"M9 9h.01"}],["path",{d:"M15 15h.01"}]]];const o1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polygon",{points:"10 8 16 12 10 16 10 8"}]]];const i1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 12h8"}],["path",{d:"M12 8v8"}]]];const l1=["svg",a,[["path",{d:"M12 7v4"}],["path",{d:"M7.998 9.003a5 5 0 1 0 8-.005"}],["circle",{cx:"12",cy:"12",r:"10"}]]];const g1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M22 2 2 22"}]]];const u3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"9",x2:"15",y1:"15",y2:"9"}]]];const x1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["rect",{width:"6",height:"6",x:"9",y:"9"}]]];const y1=["svg",a,[["path",{d:"M18 20a6 6 0 0 0-12 0"}],["circle",{cx:"12",cy:"10",r:"4"}],["circle",{cx:"12",cy:"12",r:"10"}]]];const m1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M7 20.662V19a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v1.662"}]]];const H1=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m15 9-6 6"}],["path",{d:"m9 9 6 6"}]]];const A3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}]]];const L3=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M11 9h4a2 2 0 0 0 2-2V3"}],["circle",{cx:"9",cy:"9",r:"2"}],["path",{d:"M7 21v-4a2 2 0 0 1 2-2h4"}],["circle",{cx:"15",cy:"15",r:"2"}]]];const S3=["svg",a,[["path",{d:"M21.66 17.67a1.08 1.08 0 0 1-.04 1.6A12 12 0 0 1 4.73 2.38a1.1 1.1 0 0 1 1.61-.04z"}],["path",{d:"M19.65 15.66A8 8 0 0 1 8.35 4.34"}],["path",{d:"m14 10-5.5 5.5"}],["path",{d:"M14 17.85V10H6.15"}]]];const f3=["svg",a,[["path",{d:"M20.2 6 3 11l-.9-2.4c-.3-1.1.3-2.2 1.3-2.5l13.5-4c1.1-.3 2.2.3 2.5 1.3Z"}],["path",{d:"m6.2 5.3 3.1 3.9"}],["path",{d:"m12.4 3.4 3.1 4"}],["path",{d:"M3 11h18v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z"}]]];const Z3=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"m9 14 2 2 4-4"}]]];const P3=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v4"}],["path",{d:"M21 14H11"}],["path",{d:"m15 10-4 4 4 4"}]]];const k3=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"M12 11h4"}],["path",{d:"M12 16h4"}],["path",{d:"M8 11h.01"}],["path",{d:"M8 16h.01"}]]];const z3=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"M9 14h6"}]]];const B3=["svg",a,[["path",{d:"M15 2H9a1 1 0 0 0-1 1v2c0 .6.4 1 1 1h6c.6 0 1-.4 1-1V3c0-.6-.4-1-1-1Z"}],["path",{d:"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2M16 4h2a2 2 0 0 1 2 2v2M11 14h10"}],["path",{d:"m17 10 4 4-4 4"}]]];const V1=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1"}],["path",{d:"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-.5"}],["path",{d:"M16 4h2a2 2 0 0 1 1.73 1"}],["path",{d:"M8 18h1"}],["path",{d:"M21.378 12.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]];const C1=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-5.5"}],["path",{d:"M4 13.5V6a2 2 0 0 1 2-2h2"}],["path",{d:"M13.378 15.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]];const F3=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"M9 14h6"}],["path",{d:"M12 17v-6"}]]];const D3=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"M9 12v-1h6v1"}],["path",{d:"M11 17h2"}],["path",{d:"M12 11v6"}]]];const q3=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}],["path",{d:"m15 11-6 6"}],["path",{d:"m9 11 6 6"}]]];const R3=["svg",a,[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"}]]];const b3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 14.5 8"}]]];const T3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 8 10"}]]];const U3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 9.5 8"}]]];const O3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12"}]]];const I3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 16 10"}]]];const E3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 16.5 12"}]]];const G3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 16 14"}]]];const W3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 14.5 16"}]]];const X3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 12 16.5"}]]];const N3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 9.5 16"}]]];const K3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 8 14"}]]];const J3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 7.5 12"}]]];const j3=["svg",a,[["path",{d:"M12.338 21.994A10 10 0 1 1 21.925 13.227"}],["path",{d:"M12 6v6l2 1"}],["path",{d:"m14 18 4 4 4-4"}],["path",{d:"M18 14v8"}]]];const Q3=["svg",a,[["path",{d:"M13.228 21.925A10 10 0 1 1 21.994 12.338"}],["path",{d:"M12 6v6l1.562.781"}],["path",{d:"m14 18 4-4 4 4"}],["path",{d:"M18 22v-8"}]]];const _3=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["polyline",{points:"12 6 12 12 16 14"}]]];const Y3=["svg",a,[["circle",{cx:"12",cy:"17",r:"3"}],["path",{d:"M4.2 15.1A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.2"}],["path",{d:"m15.7 18.4-.9-.3"}],["path",{d:"m9.2 15.9-.9-.3"}],["path",{d:"m10.6 20.7.3-.9"}],["path",{d:"m13.1 14.2.3-.9"}],["path",{d:"m13.6 20.7-.4-1"}],["path",{d:"m10.8 14.3-.4-1"}],["path",{d:"m8.3 18.6 1-.4"}],["path",{d:"m14.7 15.8 1-.4"}]]];const w1=["svg",a,[["path",{d:"M12 13v8l-4-4"}],["path",{d:"m12 21 4-4"}],["path",{d:"M4.393 15.269A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.436 8.284"}]]];const $3=["svg",a,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M8 19v1"}],["path",{d:"M8 14v1"}],["path",{d:"M16 19v1"}],["path",{d:"M16 14v1"}],["path",{d:"M12 21v1"}],["path",{d:"M12 16v1"}]]];const ad=["svg",a,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M16 17H7"}],["path",{d:"M17 21H9"}]]];const td=["svg",a,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M16 14v2"}],["path",{d:"M8 14v2"}],["path",{d:"M16 20h.01"}],["path",{d:"M8 20h.01"}],["path",{d:"M12 16v2"}],["path",{d:"M12 22h.01"}]]];const hd=["svg",a,[["path",{d:"M6 16.326A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 .5 8.973"}],["path",{d:"m13 12-3 5h4l-3 5"}]]];const dd=["svg",a,[["path",{d:"M10.188 8.5A6 6 0 0 1 16 4a1 1 0 0 0 6 6 6 6 0 0 1-3 5.197"}],["path",{d:"M11 20v2"}],["path",{d:"M3 20a5 5 0 1 1 8.9-4H13a3 3 0 0 1 2 5.24"}],["path",{d:"M7 19v2"}]]];const pd=["svg",a,[["path",{d:"M10.188 8.5A6 6 0 0 1 16 4a1 1 0 0 0 6 6 6 6 0 0 1-3 5.197"}],["path",{d:"M13 16a3 3 0 1 1 0 6H7a5 5 0 1 1 4.9-6Z"}]]];const cd=["svg",a,[["path",{d:"m2 2 20 20"}],["path",{d:"M5.782 5.782A7 7 0 0 0 9 19h8.5a4.5 4.5 0 0 0 1.307-.193"}],["path",{d:"M21.532 16.5A4.5 4.5 0 0 0 17.5 10h-1.79A7.008 7.008 0 0 0 10 5.07"}]]];const Md=["svg",a,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"m9.2 22 3-7"}],["path",{d:"m9 13-3 7"}],["path",{d:"m17 13-3 7"}]]];const sd=["svg",a,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M16 14v6"}],["path",{d:"M8 14v6"}],["path",{d:"M12 16v6"}]]];const ed=["svg",a,[["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"M8 15h.01"}],["path",{d:"M8 19h.01"}],["path",{d:"M12 17h.01"}],["path",{d:"M12 21h.01"}],["path",{d:"M16 15h.01"}],["path",{d:"M16 19h.01"}]]];const rd=["svg",a,[["path",{d:"M12 2v2"}],["path",{d:"m4.93 4.93 1.41 1.41"}],["path",{d:"M20 12h2"}],["path",{d:"m19.07 4.93-1.41 1.41"}],["path",{d:"M15.947 12.65a4 4 0 0 0-5.925-4.128"}],["path",{d:"M3 20a5 5 0 1 1 8.9-4H13a3 3 0 0 1 2 5.24"}],["path",{d:"M11 20v2"}],["path",{d:"M7 19v2"}]]];const vd=["svg",a,[["path",{d:"M12 2v2"}],["path",{d:"m4.93 4.93 1.41 1.41"}],["path",{d:"M20 12h2"}],["path",{d:"m19.07 4.93-1.41 1.41"}],["path",{d:"M15.947 12.65a4 4 0 0 0-5.925-4.128"}],["path",{d:"M13 22H7a5 5 0 1 1 4.9-6H13a3 3 0 0 1 0 6Z"}]]];const u1=["svg",a,[["path",{d:"M12 13v8"}],["path",{d:"M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242"}],["path",{d:"m8 17 4-4 4 4"}]]];const nd=["svg",a,[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"}]]];const od=["svg",a,[["path",{d:"M17.5 21H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"}],["path",{d:"M22 10a3 3 0 0 0-3-3h-2.207a5.502 5.502 0 0 0-10.702.5"}]]];const id=["svg",a,[["path",{d:"M16.17 7.83 2 22"}],["path",{d:"M4.02 12a2.827 2.827 0 1 1 3.81-4.17A2.827 2.827 0 1 1 12 4.02a2.827 2.827 0 1 1 4.17 3.81A2.827 2.827 0 1 1 19.98 12a2.827 2.827 0 1 1-3.81 4.17A2.827 2.827 0 1 1 12 19.98a2.827 2.827 0 1 1-4.17-3.81A1 1 0 1 1 4 12"}],["path",{d:"m7.83 7.83 8.34 8.34"}]]];const ld=["svg",a,[["path",{d:"M17.28 9.05a5.5 5.5 0 1 0-10.56 0A5.5 5.5 0 1 0 12 17.66a5.5 5.5 0 1 0 5.28-8.6Z"}],["path",{d:"M12 17.66L12 22"}]]];const A1=["svg",a,[["path",{d:"m18 16 4-4-4-4"}],["path",{d:"m6 8-4 4 4 4"}],["path",{d:"m14.5 4-5 16"}]]];const gd=["svg",a,[["polyline",{points:"16 18 22 12 16 6"}],["polyline",{points:"8 6 2 12 8 18"}]]];const xd=["svg",a,[["polygon",{points:"12 2 22 8.5 22 15.5 12 22 2 15.5 2 8.5 12 2"}],["line",{x1:"12",x2:"12",y1:"22",y2:"15.5"}],["polyline",{points:"22 8.5 12 15.5 2 8.5"}],["polyline",{points:"2 15.5 12 8.5 22 15.5"}],["line",{x1:"12",x2:"12",y1:"2",y2:"8.5"}]]];const yd=["svg",a,[["path",{d:"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"}],["polyline",{points:"7.5 4.21 12 6.81 16.5 4.21"}],["polyline",{points:"7.5 19.79 7.5 14.6 3 12"}],["polyline",{points:"21 12 16.5 14.6 16.5 19.79"}],["polyline",{points:"3.27 6.96 12 12.01 20.73 6.96"}],["line",{x1:"12",x2:"12",y1:"22.08",y2:"12"}]]];const md=["svg",a,[["path",{d:"M10 2v2"}],["path",{d:"M14 2v2"}],["path",{d:"M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1"}],["path",{d:"M6 2v2"}]]];const Hd=["svg",a,[["path",{d:"M12 20a8 8 0 1 0 0-16 8 8 0 0 0 0 16Z"}],["path",{d:"M12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z"}],["path",{d:"M12 2v2"}],["path",{d:"M12 22v-2"}],["path",{d:"m17 20.66-1-1.73"}],["path",{d:"M11 10.27 7 3.34"}],["path",{d:"m20.66 17-1.73-1"}],["path",{d:"m3.34 7 1.73 1"}],["path",{d:"M14 12h8"}],["path",{d:"M2 12h2"}],["path",{d:"m20.66 7-1.73 1"}],["path",{d:"m3.34 17 1.73-1"}],["path",{d:"m17 3.34-1 1.73"}],["path",{d:"m11 13.73-4 6.93"}]]];const Vd=["svg",a,[["circle",{cx:"8",cy:"8",r:"6"}],["path",{d:"M18.09 10.37A6 6 0 1 1 10.34 18"}],["path",{d:"M7 6h1v4"}],["path",{d:"m16.71 13.88.7.71-2.82 2.82"}]]];const L1=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 3v18"}]]];const S1=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}],["path",{d:"M15 3v18"}]]];const Cd=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7.5 3v18"}],["path",{d:"M12 3v18"}],["path",{d:"M16.5 3v18"}]]];const wd=["svg",a,[["rect",{width:"8",height:"8",x:"2",y:"2",rx:"2"}],["path",{d:"M14 2c1.1 0 2 .9 2 2v4c0 1.1-.9 2-2 2"}],["path",{d:"M20 2c1.1 0 2 .9 2 2v4c0 1.1-.9 2-2 2"}],["path",{d:"M10 18H5c-1.7 0-3-1.3-3-3v-1"}],["polyline",{points:"7 21 10 18 7 15"}],["rect",{width:"8",height:"8",x:"14",y:"14",rx:"2"}]]];const ud=["svg",a,[["path",{d:"M15 6v12a3 3 0 1 0 3-3H6a3 3 0 1 0 3 3V6a3 3 0 1 0-3 3h12a3 3 0 1 0-3-3"}]]];const Ad=["svg",a,[["path",{d:"m16.24 7.76-1.804 5.411a2 2 0 0 1-1.265 1.265L7.76 16.24l1.804-5.411a2 2 0 0 1 1.265-1.265z"}],["circle",{cx:"12",cy:"12",r:"10"}]]];const Ld=["svg",a,[["path",{d:"M5.5 8.5 9 12l-3.5 3.5L2 12l3.5-3.5Z"}],["path",{d:"m12 2 3.5 3.5L12 9 8.5 5.5 12 2Z"}],["path",{d:"M18.5 8.5 22 12l-3.5 3.5L15 12l3.5-3.5Z"}],["path",{d:"m12 15 3.5 3.5L12 22l-3.5-3.5L12 15Z"}]]];const Sd=["svg",a,[["rect",{width:"14",height:"8",x:"5",y:"2",rx:"2"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2"}],["path",{d:"M6 18h2"}],["path",{d:"M12 18h6"}]]];const fd=["svg",a,[["path",{d:"M3 20a1 1 0 0 1-1-1v-1a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1a1 1 0 0 1-1 1Z"}],["path",{d:"M20 16a8 8 0 1 0-16 0"}],["path",{d:"M12 4v4"}],["path",{d:"M10 4h4"}]]];const Zd=["svg",a,[["path",{d:"m20.9 18.55-8-15.98a1 1 0 0 0-1.8 0l-8 15.98"}],["ellipse",{cx:"12",cy:"19",rx:"9",ry:"3"}]]];const Pd=["svg",a,[["rect",{x:"2",y:"6",width:"20",height:"8",rx:"1"}],["path",{d:"M17 14v7"}],["path",{d:"M7 14v7"}],["path",{d:"M17 3v3"}],["path",{d:"M7 3v3"}],["path",{d:"M10 14 2.3 6.3"}],["path",{d:"m14 6 7.7 7.7"}],["path",{d:"m8 6 8 8"}]]];const f1=["svg",a,[["path",{d:"M16 18a4 4 0 0 0-8 0"}],["circle",{cx:"12",cy:"11",r:"3"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["line",{x1:"8",x2:"8",y1:"2",y2:"4"}],["line",{x1:"16",x2:"16",y1:"2",y2:"4"}]]];const kd=["svg",a,[["path",{d:"M17 18a2 2 0 0 0-2-2H9a2 2 0 0 0-2 2"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2"}],["circle",{cx:"12",cy:"10",r:"2"}],["line",{x1:"8",x2:"8",y1:"2",y2:"4"}],["line",{x1:"16",x2:"16",y1:"2",y2:"4"}]]];const zd=["svg",a,[["path",{d:"M22 7.7c0-.6-.4-1.2-.8-1.5l-6.3-3.9a1.72 1.72 0 0 0-1.7 0l-10.3 6c-.5.2-.9.8-.9 1.4v6.6c0 .5.4 1.2.8 1.5l6.3 3.9a1.72 1.72 0 0 0 1.7 0l10.3-6c.5-.3.9-1 .9-1.5Z"}],["path",{d:"M10 21.9V14L2.1 9.1"}],["path",{d:"m10 14 11.9-6.9"}],["path",{d:"M14 19.8v-8.1"}],["path",{d:"M18 17.5V9.4"}]]];const Bd=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 18a6 6 0 0 0 0-12v12z"}]]];const Fd=["svg",a,[["path",{d:"M12 2a10 10 0 1 0 10 10 4 4 0 0 1-5-5 4 4 0 0 1-5-5"}],["path",{d:"M8.5 8.5v.01"}],["path",{d:"M16 15.5v.01"}],["path",{d:"M12 12v.01"}],["path",{d:"M11 17v.01"}],["path",{d:"M7 14v.01"}]]];const Dd=["svg",a,[["path",{d:"M2 12h20"}],["path",{d:"M20 12v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-8"}],["path",{d:"m4 8 16-4"}],["path",{d:"m8.86 6.78-.45-1.81a2 2 0 0 1 1.45-2.43l1.94-.48a2 2 0 0 1 2.43 1.46l.45 1.8"}]]];const qd=["svg",a,[["path",{d:"m12 15 2 2 4-4"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]];const Rd=["svg",a,[["line",{x1:"12",x2:"18",y1:"15",y2:"15"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]];const bd=["svg",a,[["line",{x1:"15",x2:"15",y1:"12",y2:"18"}],["line",{x1:"12",x2:"18",y1:"15",y2:"15"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]];const Td=["svg",a,[["line",{x1:"12",x2:"18",y1:"18",y2:"12"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]];const Ud=["svg",a,[["line",{x1:"12",x2:"18",y1:"12",y2:"18"}],["line",{x1:"12",x2:"18",y1:"18",y2:"12"}],["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]];const Od=["svg",a,[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]]];const Id=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M9.17 14.83a4 4 0 1 0 0-5.66"}]]];const Ed=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M14.83 14.83a4 4 0 1 1 0-5.66"}]]];const Gd=["svg",a,[["polyline",{points:"9 10 4 15 9 20"}],["path",{d:"M20 4v7a4 4 0 0 1-4 4H4"}]]];const Wd=["svg",a,[["polyline",{points:"15 10 20 15 15 20"}],["path",{d:"M4 4v7a4 4 0 0 0 4 4h12"}]]];const Xd=["svg",a,[["polyline",{points:"14 15 9 20 4 15"}],["path",{d:"M20 4h-7a4 4 0 0 0-4 4v12"}]]];const Nd=["svg",a,[["polyline",{points:"14 9 9 4 4 9"}],["path",{d:"M20 20h-7a4 4 0 0 1-4-4V4"}]]];const Kd=["svg",a,[["polyline",{points:"10 15 15 20 20 15"}],["path",{d:"M4 4h7a4 4 0 0 1 4 4v12"}]]];const Jd=["svg",a,[["polyline",{points:"10 9 15 4 20 9"}],["path",{d:"M4 20h7a4 4 0 0 0 4-4V4"}]]];const jd=["svg",a,[["polyline",{points:"9 14 4 9 9 4"}],["path",{d:"M20 20v-7a4 4 0 0 0-4-4H4"}]]];const Qd=["svg",a,[["polyline",{points:"15 14 20 9 15 4"}],["path",{d:"M4 20v-7a4 4 0 0 1 4-4h12"}]]];const _d=["svg",a,[["rect",{width:"16",height:"16",x:"4",y:"4",rx:"2"}],["rect",{width:"6",height:"6",x:"9",y:"9",rx:"1"}],["path",{d:"M15 2v2"}],["path",{d:"M15 20v2"}],["path",{d:"M2 15h2"}],["path",{d:"M2 9h2"}],["path",{d:"M20 15h2"}],["path",{d:"M20 9h2"}],["path",{d:"M9 2v2"}],["path",{d:"M9 20v2"}]]];const Yd=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M10 9.3a2.8 2.8 0 0 0-3.5 1 3.1 3.1 0 0 0 0 3.4 2.7 2.7 0 0 0 3.5 1"}],["path",{d:"M17 9.3a2.8 2.8 0 0 0-3.5 1 3.1 3.1 0 0 0 0 3.4 2.7 2.7 0 0 0 3.5 1"}]]];const $d=["svg",a,[["rect",{width:"20",height:"14",x:"2",y:"5",rx:"2"}],["line",{x1:"2",x2:"22",y1:"10",y2:"10"}]]];const ap=["svg",a,[["path",{d:"m4.6 13.11 5.79-3.21c1.89-1.05 4.79 1.78 3.71 3.71l-3.22 5.81C8.8 23.16.79 15.23 4.6 13.11Z"}],["path",{d:"m10.5 9.5-1-2.29C9.2 6.48 8.8 6 8 6H4.5C2.79 6 2 6.5 2 8.5a7.71 7.71 0 0 0 2 4.83"}],["path",{d:"M8 6c0-1.55.24-4-2-4-2 0-2.5 2.17-2.5 4"}],["path",{d:"m14.5 13.5 2.29 1c.73.3 1.21.7 1.21 1.5v3.5c0 1.71-.5 2.5-2.5 2.5a7.71 7.71 0 0 1-4.83-2"}],["path",{d:"M18 16c1.55 0 4-.24 4 2 0 2-2.17 2.5-4 2.5"}]]];const tp=["svg",a,[["path",{d:"M6 2v14a2 2 0 0 0 2 2h14"}],["path",{d:"M18 22V8a2 2 0 0 0-2-2H2"}]]];const hp=["svg",a,[["path",{d:"M11 2a2 2 0 0 0-2 2v5H4a2 2 0 0 0-2 2v2c0 1.1.9 2 2 2h5v5c0 1.1.9 2 2 2h2a2 2 0 0 0 2-2v-5h5a2 2 0 0 0 2-2v-2a2 2 0 0 0-2-2h-5V4a2 2 0 0 0-2-2h-2z"}]]];const dp=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"22",x2:"18",y1:"12",y2:"12"}],["line",{x1:"6",x2:"2",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"6",y2:"2"}],["line",{x1:"12",x2:"12",y1:"22",y2:"18"}]]];const pp=["svg",a,[["path",{d:"M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z"}],["path",{d:"M5 21h14"}]]];const cp=["svg",a,[["path",{d:"m21.12 6.4-6.05-4.06a2 2 0 0 0-2.17-.05L2.95 8.41a2 2 0 0 0-.95 1.7v5.82a2 2 0 0 0 .88 1.66l6.05 4.07a2 2 0 0 0 2.17.05l9.95-6.12a2 2 0 0 0 .95-1.7V8.06a2 2 0 0 0-.88-1.66Z"}],["path",{d:"M10 22v-8L2.25 9.15"}],["path",{d:"m10 14 11.77-6.87"}]]];const Mp=["svg",a,[["path",{d:"m6 8 1.75 12.28a2 2 0 0 0 2 1.72h4.54a2 2 0 0 0 2-1.72L18 8"}],["path",{d:"M5 8h14"}],["path",{d:"M7 15a6.47 6.47 0 0 1 5 0 6.47 6.47 0 0 0 5 0"}],["path",{d:"m12 8 1-6h2"}]]];const sp=["svg",a,[["circle",{cx:"12",cy:"12",r:"8"}],["line",{x1:"3",x2:"6",y1:"3",y2:"6"}],["line",{x1:"21",x2:"18",y1:"3",y2:"6"}],["line",{x1:"3",x2:"6",y1:"21",y2:"18"}],["line",{x1:"21",x2:"18",y1:"21",y2:"18"}]]];const ep=["svg",a,[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}],["path",{d:"M3 5v14a9 3 0 0 0 18 0V5"}]]];const rp=["svg",a,[["path",{d:"M11 11.31c1.17.56 1.54 1.69 3.5 1.69 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M11.75 18c.35.5 1.45 1 2.75 1 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["path",{d:"M2 6h4"}],["path",{d:"M7 3a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1L10 4a1 1 0 0 0-1-1z"}]]];const vp=["svg",a,[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}],["path",{d:"M3 12a9 3 0 0 0 5 2.69"}],["path",{d:"M21 9.3V5"}],["path",{d:"M3 5v14a9 3 0 0 0 6.47 2.88"}],["path",{d:"M12 12v4h4"}],["path",{d:"M13 20a5 5 0 0 0 9-3 4.5 4.5 0 0 0-4.5-4.5c-1.33 0-2.54.54-3.41 1.41L12 16"}]]];const np=["svg",a,[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}],["path",{d:"M3 5V19A9 3 0 0 0 15 21.84"}],["path",{d:"M21 5V8"}],["path",{d:"M21 12L18 17H22L19 22"}],["path",{d:"M3 12A9 3 0 0 0 14.59 14.87"}]]];const op=["svg",a,[["ellipse",{cx:"12",cy:"5",rx:"9",ry:"3"}],["path",{d:"M3 5V19A9 3 0 0 0 21 19V5"}],["path",{d:"M3 12A9 3 0 0 0 21 12"}]]];const ip=["svg",a,[["path",{d:"M10 5a2 2 0 0 0-1.344.519l-6.328 5.74a1 1 0 0 0 0 1.481l6.328 5.741A2 2 0 0 0 10 19h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2z"}],["path",{d:"m12 9 6 6"}],["path",{d:"m18 9-6 6"}]]];const lp=["svg",a,[["circle",{cx:"12",cy:"4",r:"2"}],["path",{d:"M10.2 3.2C5.5 4 2 8.1 2 13a2 2 0 0 0 4 0v-1a2 2 0 0 1 4 0v4a2 2 0 0 0 4 0v-4a2 2 0 0 1 4 0v1a2 2 0 0 0 4 0c0-4.9-3.5-9-8.2-9.8"}],["path",{d:"M3.2 14.8a9 9 0 0 0 17.6 0"}]]];const gp=["svg",a,[["circle",{cx:"19",cy:"19",r:"2"}],["circle",{cx:"5",cy:"5",r:"2"}],["path",{d:"M6.48 3.66a10 10 0 0 1 13.86 13.86"}],["path",{d:"m6.41 6.41 11.18 11.18"}],["path",{d:"M3.66 6.48a10 10 0 0 0 13.86 13.86"}]]];const xp=["svg",a,[["path",{d:"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0z"}],["path",{d:"M8 12h8"}]]];const Z1=["svg",a,[["path",{d:"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0Z"}],["path",{d:"M9.2 9.2h.01"}],["path",{d:"m14.5 9.5-5 5"}],["path",{d:"M14.7 14.8h.01"}]]];const yp=["svg",a,[["path",{d:"M12 8v8"}],["path",{d:"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0z"}],["path",{d:"M8 12h8"}]]];const mp=["svg",a,[["path",{d:"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41l-7.59-7.59a2.41 2.41 0 0 0-3.41 0Z"}]]];const Hp=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M12 12h.01"}]]];const Vp=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M15 9h.01"}],["path",{d:"M9 15h.01"}]]];const Cp=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M16 8h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M8 16h.01"}]]];const wp=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M16 8h.01"}],["path",{d:"M8 8h.01"}],["path",{d:"M8 16h.01"}],["path",{d:"M16 16h.01"}]]];const up=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M16 8h.01"}],["path",{d:"M8 8h.01"}],["path",{d:"M8 16h.01"}],["path",{d:"M16 16h.01"}],["path",{d:"M12 12h.01"}]]];const Ap=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M16 8h.01"}],["path",{d:"M16 12h.01"}],["path",{d:"M16 16h.01"}],["path",{d:"M8 8h.01"}],["path",{d:"M8 12h.01"}],["path",{d:"M8 16h.01"}]]];const Lp=["svg",a,[["rect",{width:"12",height:"12",x:"2",y:"10",rx:"2",ry:"2"}],["path",{d:"m17.92 14 3.5-3.5a2.24 2.24 0 0 0 0-3l-5-4.92a2.24 2.24 0 0 0-3 0L10 6"}],["path",{d:"M6 18h.01"}],["path",{d:"M10 14h.01"}],["path",{d:"M15 6h.01"}],["path",{d:"M18 9h.01"}]]];const Sp=["svg",a,[["path",{d:"M12 3v14"}],["path",{d:"M5 10h14"}],["path",{d:"M5 21h14"}]]];const fp=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M12 12h.01"}]]];const Zp=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M6 12c0-1.7.7-3.2 1.8-4.2"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M18 12c0 1.7-.7 3.2-1.8 4.2"}]]];const Pp=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["circle",{cx:"12",cy:"12",r:"5"}],["path",{d:"M12 12h.01"}]]];const kp=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"2"}]]];const zp=["svg",a,[["circle",{cx:"12",cy:"6",r:"1"}],["line",{x1:"5",x2:"19",y1:"12",y2:"12"}],["circle",{cx:"12",cy:"18",r:"1"}]]];const Bp=["svg",a,[["path",{d:"M15 2c-1.35 1.5-2.092 3-2.5 4.5L14 8"}],["path",{d:"m17 6-2.891-2.891"}],["path",{d:"M2 15c3.333-3 6.667-3 10-3"}],["path",{d:"m2 2 20 20"}],["path",{d:"m20 9 .891.891"}],["path",{d:"M22 9c-1.5 1.35-3 2.092-4.5 2.5l-1-1"}],["path",{d:"M3.109 14.109 4 15"}],["path",{d:"m6.5 12.5 1 1"}],["path",{d:"m7 18 2.891 2.891"}],["path",{d:"M9 22c1.35-1.5 2.092-3 2.5-4.5L10 16"}]]];const Fp=["svg",a,[["path",{d:"m10 16 1.5 1.5"}],["path",{d:"m14 8-1.5-1.5"}],["path",{d:"M15 2c-1.798 1.998-2.518 3.995-2.807 5.993"}],["path",{d:"m16.5 10.5 1 1"}],["path",{d:"m17 6-2.891-2.891"}],["path",{d:"M2 15c6.667-6 13.333 0 20-6"}],["path",{d:"m20 9 .891.891"}],["path",{d:"M3.109 14.109 4 15"}],["path",{d:"m6.5 12.5 1 1"}],["path",{d:"m7 18 2.891 2.891"}],["path",{d:"M9 22c1.798-1.998 2.518-3.995 2.807-5.993"}]]];const Dp=["svg",a,[["path",{d:"M2 8h20"}],["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M6 16h12"}]]];const qp=["svg",a,[["path",{d:"M11.25 16.25h1.5L12 17z"}],["path",{d:"M16 14v.5"}],["path",{d:"M4.42 11.247A13.152 13.152 0 0 0 4 14.556C4 18.728 7.582 21 12 21s8-2.272 8-6.444a11.702 11.702 0 0 0-.493-3.309"}],["path",{d:"M8 14v.5"}],["path",{d:"M8.5 8.5c-.384 1.05-1.083 2.028-2.344 2.5-1.931.722-3.576-.297-3.656-1-.113-.994 1.177-6.53 4-7 1.923-.321 3.651.845 3.651 2.235A7.497 7.497 0 0 1 14 5.277c0-1.39 1.844-2.598 3.767-2.277 2.823.47 4.113 6.006 4 7-.08.703-1.725 1.722-3.656 1-1.261-.472-1.855-1.45-2.239-2.5"}]]];const Rp=["svg",a,[["line",{x1:"12",x2:"12",y1:"2",y2:"22"}],["path",{d:"M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"}]]];const bp=["svg",a,[["path",{d:"M20.5 10a2.5 2.5 0 0 1-2.4-3H18a2.95 2.95 0 0 1-2.6-4.4 10 10 0 1 0 6.3 7.1c-.3.2-.8.3-1.2.3"}],["circle",{cx:"12",cy:"12",r:"3"}]]];const Tp=["svg",a,[["path",{d:"M18 20V6a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v14"}],["path",{d:"M2 20h20"}],["path",{d:"M14 12v.01"}]]];const Up=["svg",a,[["path",{d:"M13 4h3a2 2 0 0 1 2 2v14"}],["path",{d:"M2 20h3"}],["path",{d:"M13 20h9"}],["path",{d:"M10 12v.01"}],["path",{d:"M13 4.562v16.157a1 1 0 0 1-1.242.97L5 20V5.562a2 2 0 0 1 1.515-1.94l4-1A2 2 0 0 1 13 4.561Z"}]]];const Op=["svg",a,[["circle",{cx:"12.1",cy:"12.1",r:"1"}]]];const Ip=["svg",a,[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"}],["polyline",{points:"7 10 12 15 17 10"}],["line",{x1:"12",x2:"12",y1:"15",y2:"3"}]]];const Ep=["svg",a,[["path",{d:"m12.99 6.74 1.93 3.44"}],["path",{d:"M19.136 12a10 10 0 0 1-14.271 0"}],["path",{d:"m21 21-2.16-3.84"}],["path",{d:"m3 21 8.02-14.26"}],["circle",{cx:"12",cy:"5",r:"2"}]]];const Gp=["svg",a,[["path",{d:"M10 11h.01"}],["path",{d:"M14 6h.01"}],["path",{d:"M18 6h.01"}],["path",{d:"M6.5 13.1h.01"}],["path",{d:"M22 5c0 9-4 12-6 12s-6-3-6-12c0-2 2-3 6-3s6 1 6 3"}],["path",{d:"M17.4 9.9c-.8.8-2 .8-2.8 0"}],["path",{d:"M10.1 7.1C9 7.2 7.7 7.7 6 8.6c-3.5 2-4.7 3.9-3.7 5.6 4.5 7.8 9.5 8.4 11.2 7.4.9-.5 1.9-2.1 1.9-4.7"}],["path",{d:"M9.1 16.5c.3-1.1 1.4-1.7 2.4-1.4"}]]];const Wp=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M19.13 5.09C15.22 9.14 10 10.44 2.25 10.94"}],["path",{d:"M21.75 12.84c-6.62-1.41-12.14 1-16.38 6.32"}],["path",{d:"M8.56 2.75c4.37 6 6 9.42 8 17.72"}]]];const Xp=["svg",a,[["path",{d:"M14 9c0 .6-.4 1-1 1H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9c.6 0 1 .4 1 1Z"}],["path",{d:"M18 6h4"}],["path",{d:"M14 4h3a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-3"}],["path",{d:"m5 10-2 8"}],["path",{d:"M12 10v3c0 .6-.4 1-1 1H8"}],["path",{d:"m7 18 2-8"}],["path",{d:"M5 22c-1.7 0-3-1.3-3-3 0-.6.4-1 1-1h7c.6 0 1 .4 1 1v2c0 .6-.4 1-1 1Z"}]]];const Np=["svg",a,[["path",{d:"M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z"}]]];const Kp=["svg",a,[["path",{d:"M7 16.3c2.2 0 4-1.83 4-4.05 0-1.16-.57-2.26-1.71-3.19S7.29 6.75 7 5.3c-.29 1.45-1.14 2.84-2.29 3.76S3 11.1 3 12.25c0 2.22 1.8 4.05 4 4.05z"}],["path",{d:"M12.56 6.6A10.97 10.97 0 0 0 14 3.02c.5 2.5 2 4.9 4 6.5s3 3.5 3 5.5a6.98 6.98 0 0 1-11.91 4.97"}]]];const Jp=["svg",a,[["path",{d:"m2 2 8 8"}],["path",{d:"m22 2-8 8"}],["ellipse",{cx:"12",cy:"9",rx:"10",ry:"5"}],["path",{d:"M7 13.4v7.9"}],["path",{d:"M12 14v8"}],["path",{d:"M17 13.4v7.9"}],["path",{d:"M2 9v8a10 5 0 0 0 20 0V9"}]]];const jp=["svg",a,[["path",{d:"M15.4 15.63a7.875 6 135 1 1 6.23-6.23 4.5 3.43 135 0 0-6.23 6.23"}],["path",{d:"m8.29 12.71-2.6 2.6a2.5 2.5 0 1 0-1.65 4.65A2.5 2.5 0 1 0 8.7 18.3l2.59-2.59"}]]];const Qp=["svg",a,[["path",{d:"M14.4 14.4 9.6 9.6"}],["path",{d:"M18.657 21.485a2 2 0 1 1-2.829-2.828l-1.767 1.768a2 2 0 1 1-2.829-2.829l6.364-6.364a2 2 0 1 1 2.829 2.829l-1.768 1.767a2 2 0 1 1 2.828 2.829z"}],["path",{d:"m21.5 21.5-1.4-1.4"}],["path",{d:"M3.9 3.9 2.5 2.5"}],["path",{d:"M6.404 12.768a2 2 0 1 1-2.829-2.829l1.768-1.767a2 2 0 1 1-2.828-2.829l2.828-2.828a2 2 0 1 1 2.829 2.828l1.767-1.768a2 2 0 1 1 2.829 2.829z"}]]];const _p=["svg",a,[["path",{d:"M6 18.5a3.5 3.5 0 1 0 7 0c0-1.57.92-2.52 2.04-3.46"}],["path",{d:"M6 8.5c0-.75.13-1.47.36-2.14"}],["path",{d:"M8.8 3.15A6.5 6.5 0 0 1 19 8.5c0 1.63-.44 2.81-1.09 3.76"}],["path",{d:"M12.5 6A2.5 2.5 0 0 1 15 8.5M10 13a2 2 0 0 0 1.82-1.18"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const Yp=["svg",a,[["path",{d:"M6 8.5a6.5 6.5 0 1 1 13 0c0 6-6 6-6 10a3.5 3.5 0 1 1-7 0"}],["path",{d:"M15 8.5a2.5 2.5 0 0 0-5 0v1a2 2 0 1 1 0 4"}]]];const $p=["svg",a,[["path",{d:"M7 3.34V5a3 3 0 0 0 3 3"}],["path",{d:"M11 21.95V18a2 2 0 0 0-2-2 2 2 0 0 1-2-2v-1a2 2 0 0 0-2-2H2.05"}],["path",{d:"M21.54 15H17a2 2 0 0 0-2 2v4.54"}],["path",{d:"M12 2a10 10 0 1 0 9.54 13"}],["path",{d:"M20 6V4a2 2 0 1 0-4 0v2"}],["rect",{width:"8",height:"5",x:"14",y:"6",rx:"1"}]]];const P1=["svg",a,[["path",{d:"M21.54 15H17a2 2 0 0 0-2 2v4.54"}],["path",{d:"M7 3.34V5a3 3 0 0 0 3 3a2 2 0 0 1 2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2c0-1.1.9-2 2-2h3.17"}],["path",{d:"M11 21.95V18a2 2 0 0 0-2-2a2 2 0 0 1-2-2v-1a2 2 0 0 0-2-2H2.05"}],["circle",{cx:"12",cy:"12",r:"10"}]]];const a6=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 2a7 7 0 1 0 10 10"}]]];const t6=["svg",a,[["circle",{cx:"11.5",cy:"12.5",r:"3.5"}],["path",{d:"M3 8c0-3.5 2.5-6 6.5-6 5 0 4.83 3 7.5 5s5 2 5 6c0 4.5-2.5 6.5-7 6.5-2.5 0-2.5 2.5-6 2.5s-7-2-7-5.5c0-3 1.5-3 1.5-5C3.5 10 3 9 3 8Z"}]]];const h6=["svg",a,[["path",{d:"M6.399 6.399C5.362 8.157 4.65 10.189 4.5 12c-.37 4.43 1.27 9.95 7.5 10 3.256-.026 5.259-1.547 6.375-3.625"}],["path",{d:"M19.532 13.875A14.07 14.07 0 0 0 19.5 12c-.36-4.34-3.95-9.96-7.5-10-1.04.012-2.082.502-3.046 1.297"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const d6=["svg",a,[["path",{d:"M12 22c6.23-.05 7.87-5.57 7.5-10-.36-4.34-3.95-9.96-7.5-10-3.55.04-7.14 5.66-7.5 10-.37 4.43 1.27 9.95 7.5 10z"}]]];const k1=["svg",a,[["circle",{cx:"12",cy:"12",r:"1"}],["circle",{cx:"12",cy:"5",r:"1"}],["circle",{cx:"12",cy:"19",r:"1"}]]];const z1=["svg",a,[["circle",{cx:"12",cy:"12",r:"1"}],["circle",{cx:"19",cy:"12",r:"1"}],["circle",{cx:"5",cy:"12",r:"1"}]]];const p6=["svg",a,[["line",{x1:"5",x2:"19",y1:"9",y2:"9"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15"}],["line",{x1:"19",x2:"5",y1:"5",y2:"19"}]]];const c6=["svg",a,[["line",{x1:"5",x2:"19",y1:"9",y2:"9"}],["line",{x1:"5",x2:"19",y1:"15",y2:"15"}]]];const M6=["svg",a,[["path",{d:"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21"}],["path",{d:"M22 21H7"}],["path",{d:"m5 11 9 9"}]]];const s6=["svg",a,[["path",{d:"m15 20 3-3h2a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h2l3 3z"}],["path",{d:"M6 8v1"}],["path",{d:"M10 8v1"}],["path",{d:"M14 8v1"}],["path",{d:"M18 8v1"}]]];const e6=["svg",a,[["path",{d:"M4 10h12"}],["path",{d:"M4 14h9"}],["path",{d:"M19 6a7.7 7.7 0 0 0-5.2-2A7.9 7.9 0 0 0 6 12c0 4.4 3.5 8 7.8 8 2 0 3.8-.8 5.2-2"}]]];const r6=["svg",a,[["path",{d:"m21 21-6-6m6 6v-4.8m0 4.8h-4.8"}],["path",{d:"M3 16.2V21m0 0h4.8M3 21l6-6"}],["path",{d:"M21 7.8V3m0 0h-4.8M21 3l-6 6"}],["path",{d:"M3 7.8V3m0 0h4.8M3 3l6 6"}]]];const v6=["svg",a,[["path",{d:"M15 3h6v6"}],["path",{d:"M10 14 21 3"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"}]]];const n6=["svg",a,[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"}],["path",{d:"m2 2 20 20"}]]];const o6=["svg",a,[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"}],["circle",{cx:"12",cy:"12",r:"3"}]]];const i6=["svg",a,[["path",{d:"M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"}]]];const l6=["svg",a,[["path",{d:"M2 20a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8l-7 5V8l-7 5V4a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M17 18h1"}],["path",{d:"M12 18h1"}],["path",{d:"M7 18h1"}]]];const g6=["svg",a,[["path",{d:"M10.827 16.379a6.082 6.082 0 0 1-8.618-7.002l5.412 1.45a6.082 6.082 0 0 1 7.002-8.618l-1.45 5.412a6.082 6.082 0 0 1 8.618 7.002l-5.412-1.45a6.082 6.082 0 0 1-7.002 8.618l1.45-5.412Z"}],["path",{d:"M12 12v.01"}]]];const x6=["svg",a,[["polygon",{points:"13 19 22 12 13 5 13 19"}],["polygon",{points:"2 19 11 12 2 5 2 19"}]]];const y6=["svg",a,[["path",{d:"M12.67 19a2 2 0 0 0 1.416-.588l6.154-6.172a6 6 0 0 0-8.49-8.49L5.586 9.914A2 2 0 0 0 5 11.328V18a1 1 0 0 0 1 1z"}],["path",{d:"M16 8 2 22"}],["path",{d:"M17.5 15H9"}]]];const m6=["svg",a,[["path",{d:"M4 3 2 5v15c0 .6.4 1 1 1h2c.6 0 1-.4 1-1V5Z"}],["path",{d:"M6 8h4"}],["path",{d:"M6 18h4"}],["path",{d:"m12 3-2 2v15c0 .6.4 1 1 1h2c.6 0 1-.4 1-1V5Z"}],["path",{d:"M14 8h4"}],["path",{d:"M14 18h4"}],["path",{d:"m20 3-2 2v15c0 .6.4 1 1 1h2c.6 0 1-.4 1-1V5Z"}]]];const H6=["svg",a,[["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M12 2v4"}],["path",{d:"m6.8 15-3.5 2"}],["path",{d:"m20.7 7-3.5 2"}],["path",{d:"M6.8 9 3.3 7"}],["path",{d:"m20.7 17-3.5-2"}],["path",{d:"m9 22 3-8 3 8"}],["path",{d:"M8 22h8"}],["path",{d:"M18 18.7a9 9 0 1 0-12 0"}]]];const V6=["svg",a,[["path",{d:"M5 5.5A3.5 3.5 0 0 1 8.5 2H12v7H8.5A3.5 3.5 0 0 1 5 5.5z"}],["path",{d:"M12 2h3.5a3.5 3.5 0 1 1 0 7H12V2z"}],["path",{d:"M12 12.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 1 1-7 0z"}],["path",{d:"M5 19.5A3.5 3.5 0 0 1 8.5 16H12v3.5a3.5 3.5 0 1 1-7 0z"}],["path",{d:"M5 12.5A3.5 3.5 0 0 1 8.5 9H12v7H8.5A3.5 3.5 0 0 1 5 12.5z"}]]];const C6=["svg",a,[["path",{d:"M10 12v-1"}],["path",{d:"M10 18v-2"}],["path",{d:"M10 7V6"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M15.5 22H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v16a2 2 0 0 0 .274 1.01"}],["circle",{cx:"10",cy:"20",r:"2"}]]];const w6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v2"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"3",cy:"17",r:"1"}],["path",{d:"M2 17v-3a4 4 0 0 1 8 0v3"}],["circle",{cx:"9",cy:"17",r:"1"}]]];const u6=["svg",a,[["path",{d:"M17.5 22h.5a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M2 19a2 2 0 1 1 4 0v1a2 2 0 1 1-4 0v-4a6 6 0 0 1 12 0v4a2 2 0 1 1-4 0v-1a2 2 0 1 1 4 0"}]]];const B1=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m8 18 4-4"}],["path",{d:"M8 10v8h8"}]]];const A6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m14 12.5 1 5.5-3-1-3 1 1-5.5"}]]];const L6=["svg",a,[["path",{d:"M12 22h6a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M5 17a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"}],["path",{d:"M7 16.5 8 22l-3-1-3 1 1-5.5"}]]];const S6=["svg",a,[["path",{d:"M14.5 22H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M3 13.1a2 2 0 0 0-1 1.76v3.24a2 2 0 0 0 .97 1.78L6 21.7a2 2 0 0 0 2.03.01L11 19.9a2 2 0 0 0 1-1.76V14.9a2 2 0 0 0-.97-1.78L8 11.3a2 2 0 0 0-2.03-.01Z"}],["path",{d:"M7 17v5"}],["path",{d:"M11.7 14.2 7 17l-4.7-2.8"}]]];const F1=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 18v-2"}],["path",{d:"M12 18v-4"}],["path",{d:"M16 18v-6"}]]];const D1=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 18v-1"}],["path",{d:"M12 18v-6"}],["path",{d:"M16 18v-3"}]]];const q1=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m16 13-3.5 3.5-2-2L8 17"}]]];const R1=["svg",a,[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3.5"}],["path",{d:"M4.017 11.512a6 6 0 1 0 8.466 8.475"}],["path",{d:"M9 16a1 1 0 0 1-1-1v-4c0-.552.45-1.008.995-.917a6 6 0 0 1 4.922 4.922c.091.544-.365.995-.917.995z"}]]];const f6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m3 15 2 2 4-4"}]]];const Z6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m9 15 2 2 4-4"}]]];const P6=["svg",a,[["path",{d:"M16 22h2a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"8",cy:"16",r:"6"}],["path",{d:"M9.5 17.5 8 16.25V14"}]]];const k6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m5 12-3 3 3 3"}],["path",{d:"m9 18 3-3-3-3"}]]];const z6=["svg",a,[["path",{d:"M10 12.5 8 15l2 2.5"}],["path",{d:"m14 12.5 2 2.5-2 2.5"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"}]]];const b1=["svg",a,[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m3.2 12.9-.9-.4"}],["path",{d:"m3.2 15.1-.9.4"}],["path",{d:"M4.677 21.5a2 2 0 0 0 1.313.5H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v2.5"}],["path",{d:"m4.9 11.2-.4-.9"}],["path",{d:"m4.9 16.8-.4.9"}],["path",{d:"m7.5 10.3-.4.9"}],["path",{d:"m7.5 17.7-.4-.9"}],["path",{d:"m9.7 12.5-.9.4"}],["path",{d:"m9.7 15.5-.9-.4"}],["circle",{cx:"6",cy:"14",r:"3"}]]];const B6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M9 10h6"}],["path",{d:"M12 13V7"}],["path",{d:"M9 17h6"}]]];const F6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["rect",{width:"4",height:"6",x:"2",y:"12",rx:"2"}],["path",{d:"M10 12h2v6"}],["path",{d:"M10 18h4"}]]];const D6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M12 18v-6"}],["path",{d:"m9 15 3 3 3-3"}]]];const q6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v2"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M10.29 10.7a2.43 2.43 0 0 0-2.66-.52c-.29.12-.56.3-.78.53l-.35.34-.35-.34a2.43 2.43 0 0 0-2.65-.53c-.3.12-.56.3-.79.53-.95.94-1 2.53.2 3.74L6.5 18l3.6-3.55c1.2-1.21 1.14-2.8.19-3.74Z"}]]];const R6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"10",cy:"12",r:"2"}],["path",{d:"m20 17-1.296-1.296a2.41 2.41 0 0 0-3.408 0L9 22"}]]];const b6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M2 15h10"}],["path",{d:"m9 18 3-3-3-3"}]]];const T6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1"}],["path",{d:"M8 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1"}]]];const U6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M10 12a1 1 0 0 0-1 1v1a1 1 0 0 1-1 1 1 1 0 0 1 1 1v1a1 1 0 0 0 1 1"}],["path",{d:"M14 18a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1 1 1 0 0 1-1-1v-1a1 1 0 0 0-1-1"}]]];const O6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v6"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"4",cy:"16",r:"2"}],["path",{d:"m10 10-4.5 4.5"}],["path",{d:"m9 11 1 1"}]]];const I6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["circle",{cx:"10",cy:"16",r:"2"}],["path",{d:"m16 10-4.5 4.5"}],["path",{d:"m15 11 1 1"}]]];const E6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v1"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["rect",{width:"8",height:"5",x:"2",y:"13",rx:"1"}],["path",{d:"M8 13v-2a2 2 0 1 0-4 0v2"}]]];const G6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["rect",{width:"8",height:"6",x:"8",y:"12",rx:"1"}],["path",{d:"M10 12v-2a2 2 0 1 1 4 0v2"}]]];const W6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M3 15h6"}]]];const X6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M9 15h6"}]]];const N6=["svg",a,[["circle",{cx:"14",cy:"16",r:"2"}],["circle",{cx:"6",cy:"18",r:"2"}],["path",{d:"M4 12.4V4a2 2 0 0 1 2-2h8.5L20 7.5V20a2 2 0 0 1-2 2h-7.5"}],["path",{d:"M8 18v-7.7L16 9v7"}]]];const K6=["svg",a,[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4 7V4a2 2 0 0 1 2-2 2 2 0 0 0-2 2"}],["path",{d:"M4.063 20.999a2 2 0 0 0 2 1L18 22a2 2 0 0 0 2-2V7l-5-5H6"}],["path",{d:"m5 11-3 3"}],["path",{d:"m5 17-3-3h10"}]]];const T1=["svg",a,[["path",{d:"m18 5-2.414-2.414A2 2 0 0 0 14.172 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2"}],["path",{d:"M21.378 12.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}],["path",{d:"M8 18h1"}]]];const U1=["svg",a,[["path",{d:"M12.5 22H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v9.5"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M13.378 15.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]];const J6=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M3 15h6"}],["path",{d:"M6 12v6"}]]];const j6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M9 15h6"}],["path",{d:"M12 18v-6"}]]];const Q6=["svg",a,[["path",{d:"M12 17h.01"}],["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"}],["path",{d:"M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3"}]]];const _6=["svg",a,[["path",{d:"M20 10V7l-5-5H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M16 14a2 2 0 0 0-2 2"}],["path",{d:"M20 14a2 2 0 0 1 2 2"}],["path",{d:"M20 22a2 2 0 0 0 2-2"}],["path",{d:"M16 22a2 2 0 0 1-2-2"}]]];const Y6=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["circle",{cx:"11.5",cy:"14.5",r:"2.5"}],["path",{d:"M13.3 16.3 15 18"}]]];const $6=["svg",a,[["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4.268 21a2 2 0 0 0 1.727 1H18a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"}],["path",{d:"m9 18-1.5-1.5"}],["circle",{cx:"5",cy:"14",r:"3"}]]];const ac=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 12h8"}],["path",{d:"M10 11v2"}],["path",{d:"M8 17h8"}],["path",{d:"M14 16v2"}]]];const tc=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 13h2"}],["path",{d:"M14 13h2"}],["path",{d:"M8 17h2"}],["path",{d:"M14 17h2"}]]];const hc=["svg",a,[["path",{d:"M21 7h-3a2 2 0 0 1-2-2V2"}],["path",{d:"M21 6v6.5c0 .8-.7 1.5-1.5 1.5h-7c-.8 0-1.5-.7-1.5-1.5v-9c0-.8.7-1.5 1.5-1.5H17Z"}],["path",{d:"M7 8v8.8c0 .3.2.6.4.8.2.2.5.4.8.4H15"}],["path",{d:"M3 12v8.8c0 .3.2.6.4.8.2.2.5.4.8.4H11"}]]];const dc=["svg",a,[["path",{d:"m10 18 3-3-3-3"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4 11V4a2 2 0 0 1 2-2h9l5 5v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h7"}]]];const pc=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m8 16 2-2-2-2"}],["path",{d:"M12 18h4"}]]];const cc=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M10 9H8"}],["path",{d:"M16 13H8"}],["path",{d:"M16 17H8"}]]];const Mc=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M2 13v-1h6v1"}],["path",{d:"M5 12v6"}],["path",{d:"M4 18h2"}]]];const sc=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M9 13v-1h6v1"}],["path",{d:"M12 12v6"}],["path",{d:"M11 18h2"}]]];const ec=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M12 12v6"}],["path",{d:"m15 15-3-3-3 3"}]]];const rc=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["rect",{width:"8",height:"6",x:"2",y:"12",rx:"1"}],["path",{d:"m10 15.5 4 2.5v-6l-4 2.5"}]]];const vc=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m10 11 5 3-5 3v-6Z"}]]];const nc=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 15h.01"}],["path",{d:"M11.5 13.5a2.5 2.5 0 0 1 0 3"}],["path",{d:"M15 12a5 5 0 0 1 0 6"}]]];const oc=["svg",a,[["path",{d:"M11 11a5 5 0 0 1 0 6"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"M4.268 21A2 2 0 0 0 6 22h12a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v3"}],["path",{d:"m7 10-3 2H2v4h2l3 2z"}]]];const ic=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M12 9v4"}],["path",{d:"M12 17h.01"}]]];const lc=["svg",a,[["path",{d:"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m8 12.5-5 5"}],["path",{d:"m3 12.5 5 5"}]]];const gc=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}],["path",{d:"m14.5 12.5-5 5"}],["path",{d:"m9.5 12.5 5 5"}]]];const xc=["svg",a,[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}]]];const yc=["svg",a,[["path",{d:"M20 7h-3a2 2 0 0 1-2-2V2"}],["path",{d:"M9 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h7l4 4v10a2 2 0 0 1-2 2Z"}],["path",{d:"M3 7.6v12.8A1.6 1.6 0 0 0 4.6 22h9.8"}]]];const mc=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 3v18"}],["path",{d:"M3 7.5h4"}],["path",{d:"M3 12h18"}],["path",{d:"M3 16.5h4"}],["path",{d:"M17 3v18"}],["path",{d:"M17 7.5h4"}],["path",{d:"M17 16.5h4"}]]];const Hc=["svg",a,[["path",{d:"M13.013 3H2l8 9.46V19l4 2v-8.54l.9-1.055"}],["path",{d:"m22 3-5 5"}],["path",{d:"m17 3 5 5"}]]];const Vc=["svg",a,[["polygon",{points:"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"}]]];const Cc=["svg",a,[["path",{d:"M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4"}],["path",{d:"M14 13.12c0 2.38 0 6.38-1 8.88"}],["path",{d:"M17.29 21.02c.12-.6.43-2.3.5-3.02"}],["path",{d:"M2 12a10 10 0 0 1 18-6"}],["path",{d:"M2 16h.01"}],["path",{d:"M21.8 16c.2-2 .131-5.354 0-6"}],["path",{d:"M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2"}],["path",{d:"M8.65 22c.21-.66.45-1.32.57-2"}],["path",{d:"M9 6.8a6 6 0 0 1 9 5.2v2"}]]];const wc=["svg",a,[["path",{d:"M15 6.5V3a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v3.5"}],["path",{d:"M9 18h8"}],["path",{d:"M18 3h-3"}],["path",{d:"M11 3a6 6 0 0 0-6 6v11"}],["path",{d:"M5 13h4"}],["path",{d:"M17 10a4 4 0 0 0-8 0v10a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2Z"}]]];const uc=["svg",a,[["path",{d:"M18 12.47v.03m0-.5v.47m-.475 5.056A6.744 6.744 0 0 1 15 18c-3.56 0-7.56-2.53-8.5-6 .348-1.28 1.114-2.433 2.121-3.38m3.444-2.088A8.802 8.802 0 0 1 15 6c3.56 0 6.06 2.54 7 6-.309 1.14-.786 2.177-1.413 3.058"}],["path",{d:"M7 10.67C7 8 5.58 5.97 2.73 5.5c-1 1.5-1 5 .23 6.5-1.24 1.5-1.24 5-.23 6.5C5.58 18.03 7 16 7 13.33m7.48-4.372A9.77 9.77 0 0 1 16 6.07m0 11.86a9.77 9.77 0 0 1-1.728-3.618"}],["path",{d:"m16.01 17.93-.23 1.4A2 2 0 0 1 13.8 21H9.5a5.96 5.96 0 0 0 1.49-3.98M8.53 3h5.27a2 2 0 0 1 1.98 1.67l.23 1.4M2 2l20 20"}]]];const Ac=["svg",a,[["path",{d:"M2 16s9-15 20-4C11 23 2 8 2 8"}]]];const Lc=["svg",a,[["path",{d:"M6.5 12c.94-3.46 4.94-6 8.5-6 3.56 0 6.06 2.54 7 6-.94 3.47-3.44 6-7 6s-7.56-2.53-8.5-6Z"}],["path",{d:"M18 12v.5"}],["path",{d:"M16 17.93a9.77 9.77 0 0 1 0-11.86"}],["path",{d:"M7 10.67C7 8 5.58 5.97 2.73 5.5c-1 1.5-1 5 .23 6.5-1.24 1.5-1.24 5-.23 6.5C5.58 18.03 7 16 7 13.33"}],["path",{d:"M10.46 7.26C10.2 5.88 9.17 4.24 8 3h5.8a2 2 0 0 1 1.98 1.67l.23 1.4"}],["path",{d:"m16.01 17.93-.23 1.4A2 2 0 0 1 13.8 21H9.5a5.96 5.96 0 0 0 1.49-3.98"}]]];const Sc=["svg",a,[["path",{d:"M8 2c3 0 5 2 8 2s4-1 4-1v11"}],["path",{d:"M4 22V4"}],["path",{d:"M4 15s1-1 4-1 5 2 8 2"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const fc=["svg",a,[["path",{d:"M17 22V2L7 7l10 5"}]]];const Zc=["svg",a,[["path",{d:"M7 22V2l10 5-10 5"}]]];const Pc=["svg",a,[["path",{d:"M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"}],["line",{x1:"4",x2:"4",y1:"22",y2:"15"}]]];const kc=["svg",a,[["path",{d:"M12 2c1 3 2.5 3.5 3.5 4.5A5 5 0 0 1 17 10a5 5 0 1 1-10 0c0-.3 0-.6.1-.9a2 2 0 1 0 3.3-2C8 4.5 11 2 12 2Z"}],["path",{d:"m5 22 14-4"}],["path",{d:"m5 18 14 4"}]]];const zc=["svg",a,[["path",{d:"M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z"}]]];const Bc=["svg",a,[["path",{d:"M16 16v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2V10c0-2-2-2-2-4"}],["path",{d:"M7 2h11v4c0 2-2 2-2 4v1"}],["line",{x1:"11",x2:"18",y1:"6",y2:"6"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const Fc=["svg",a,[["path",{d:"M18 6c0 2-2 2-2 4v10a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2V10c0-2-2-2-2-4V2h12z"}],["line",{x1:"6",x2:"18",y1:"6",y2:"6"}],["line",{x1:"12",x2:"12",y1:"12",y2:"12"}]]];const Dc=["svg",a,[["path",{d:"M10 10 4.72 20.55a1 1 0 0 0 .9 1.45h12.76a1 1 0 0 0 .9-1.45l-1.272-2.542"}],["path",{d:"M10 2v2.343"}],["path",{d:"M14 2v6.343"}],["path",{d:"M8.5 2h7"}],["path",{d:"M7 16h9"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const qc=["svg",a,[["path",{d:"M10 2v7.527a2 2 0 0 1-.211.896L4.72 20.55a1 1 0 0 0 .9 1.45h12.76a1 1 0 0 0 .9-1.45l-5.069-10.127A2 2 0 0 1 14 9.527V2"}],["path",{d:"M8.5 2h7"}],["path",{d:"M7 16h10"}]]];const Rc=["svg",a,[["path",{d:"M10 2v7.31"}],["path",{d:"M14 9.3V1.99"}],["path",{d:"M8.5 2h7"}],["path",{d:"M14 9.3a6.5 6.5 0 1 1-4 0"}],["path",{d:"M5.52 16h12.96"}]]];const bc=["svg",a,[["path",{d:"m3 7 5 5-5 5V7"}],["path",{d:"m21 7-5 5 5 5V7"}],["path",{d:"M12 20v2"}],["path",{d:"M12 14v2"}],["path",{d:"M12 8v2"}],["path",{d:"M12 2v2"}]]];const Tc=["svg",a,[["path",{d:"M8 3H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h3"}],["path",{d:"M16 3h3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-3"}],["path",{d:"M12 20v2"}],["path",{d:"M12 14v2"}],["path",{d:"M12 8v2"}],["path",{d:"M12 2v2"}]]];const Uc=["svg",a,[["path",{d:"m17 3-5 5-5-5h10"}],["path",{d:"m17 21-5-5-5 5h10"}],["path",{d:"M4 12H2"}],["path",{d:"M10 12H8"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}]]];const Oc=["svg",a,[["path",{d:"M21 8V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v3"}],["path",{d:"M21 16v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-3"}],["path",{d:"M4 12H2"}],["path",{d:"M10 12H8"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}]]];const Ic=["svg",a,[["path",{d:"M12 5a3 3 0 1 1 3 3m-3-3a3 3 0 1 0-3 3m3-3v1M9 8a3 3 0 1 0 3 3M9 8h1m5 0a3 3 0 1 1-3 3m3-3h-1m-2 3v-1"}],["circle",{cx:"12",cy:"8",r:"2"}],["path",{d:"M12 10v12"}],["path",{d:"M12 22c4.2 0 7-1.667 7-5-4.2 0-7 1.667-7 5Z"}],["path",{d:"M12 22c-4.2 0-7-1.667-7-5 4.2 0 7 1.667 7 5Z"}]]];const Ec=["svg",a,[["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"M12 16.5A4.5 4.5 0 1 1 7.5 12 4.5 4.5 0 1 1 12 7.5a4.5 4.5 0 1 1 4.5 4.5 4.5 4.5 0 1 1-4.5 4.5"}],["path",{d:"M12 7.5V9"}],["path",{d:"M7.5 12H9"}],["path",{d:"M16.5 12H15"}],["path",{d:"M12 16.5V15"}],["path",{d:"m8 8 1.88 1.88"}],["path",{d:"M14.12 9.88 16 8"}],["path",{d:"m8 16 1.88-1.88"}],["path",{d:"M14.12 14.12 16 16"}]]];const Gc=["svg",a,[["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}]]];const Wc=["svg",a,[["path",{d:"M2 12h6"}],["path",{d:"M22 12h-6"}],["path",{d:"M12 2v2"}],["path",{d:"M12 8v2"}],["path",{d:"M12 14v2"}],["path",{d:"M12 20v2"}],["path",{d:"m19 9-3 3 3 3"}],["path",{d:"m5 15 3-3-3-3"}]]];const Xc=["svg",a,[["path",{d:"M12 22v-6"}],["path",{d:"M12 8V2"}],["path",{d:"M4 12H2"}],["path",{d:"M10 12H8"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}],["path",{d:"m15 19-3-3-3 3"}],["path",{d:"m15 5-3 3-3-3"}]]];const Nc=["svg",a,[["circle",{cx:"15",cy:"19",r:"2"}],["path",{d:"M20.9 19.8A2 2 0 0 0 22 18V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h5.1"}],["path",{d:"M15 11v-1"}],["path",{d:"M15 17v-2"}]]];const Kc=["svg",a,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"m9 13 2 2 4-4"}]]];const Jc=["svg",a,[["circle",{cx:"16",cy:"16",r:"6"}],["path",{d:"M7 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2"}],["path",{d:"M16 14v2l1 1"}]]];const jc=["svg",a,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M2 10h20"}]]];const Qc=["svg",a,[["path",{d:"M10 10.5 8 13l2 2.5"}],["path",{d:"m14 10.5 2 2.5-2 2.5"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z"}]]];const O1=["svg",a,[["circle",{cx:"18",cy:"18",r:"3"}],["path",{d:"M10.3 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v3.3"}],["path",{d:"m21.7 19.4-.9-.3"}],["path",{d:"m15.2 16.9-.9-.3"}],["path",{d:"m16.6 21.7.3-.9"}],["path",{d:"m19.1 15.2.3-.9"}],["path",{d:"m19.6 21.7-.4-1"}],["path",{d:"m16.8 15.3-.4-1"}],["path",{d:"m14.3 19.6 1-.4"}],["path",{d:"m20.7 16.8 1-.4"}]]];const _c=["svg",a,[["path",{d:"M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"}],["circle",{cx:"12",cy:"13",r:"1"}]]];const Yc=["svg",a,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M12 10v6"}],["path",{d:"m15 13-3 3-3-3"}]]];const $c=["svg",a,[["path",{d:"M9 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v5"}],["circle",{cx:"13",cy:"12",r:"2"}],["path",{d:"M18 19c-2.8 0-5-2.2-5-5v8"}],["circle",{cx:"20",cy:"19",r:"2"}]]];const a8=["svg",a,[["circle",{cx:"12",cy:"13",r:"2"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M14 13h3"}],["path",{d:"M7 13h3"}]]];const t8=["svg",a,[["path",{d:"M11 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v1.5"}],["path",{d:"M13.9 17.45c-1.2-1.2-1.14-2.8-.2-3.73a2.43 2.43 0 0 1 3.44 0l.36.34.34-.34a2.43 2.43 0 0 1 3.45-.01c.95.95 1 2.53-.2 3.74L17.5 21Z"}]]];const h8=["svg",a,[["path",{d:"M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1"}],["path",{d:"M2 13h10"}],["path",{d:"m9 16 3-3-3-3"}]]];const d8=["svg",a,[["path",{d:"M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"}],["path",{d:"M8 10v4"}],["path",{d:"M12 10v2"}],["path",{d:"M16 10v6"}]]];const p8=["svg",a,[["circle",{cx:"16",cy:"20",r:"2"}],["path",{d:"M10 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v2"}],["path",{d:"m22 14-4.5 4.5"}],["path",{d:"m21 15 1 1"}]]];const c8=["svg",a,[["rect",{width:"8",height:"5",x:"14",y:"17",rx:"1"}],["path",{d:"M10 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v2.5"}],["path",{d:"M20 17v-2a2 2 0 1 0-4 0v2"}]]];const M8=["svg",a,[["path",{d:"M9 13h6"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}]]];const s8=["svg",a,[["path",{d:"m6 14 1.45-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.55 6a2 2 0 0 1-1.94 1.5H4a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2h3.93a2 2 0 0 1 1.66.9l.82 1.2a2 2 0 0 0 1.66.9H18a2 2 0 0 1 2 2v2"}],["circle",{cx:"14",cy:"15",r:"1"}]]];const e8=["svg",a,[["path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2"}]]];const r8=["svg",a,[["path",{d:"M2 7.5V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-1.5"}],["path",{d:"M2 13h10"}],["path",{d:"m5 10-3 3 3 3"}]]];const I1=["svg",a,[["path",{d:"M2 11.5V5a2 2 0 0 1 2-2h3.9c.7 0 1.3.3 1.7.9l.8 1.2c.4.6 1 .9 1.7.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-9.5"}],["path",{d:"M11.378 13.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]];const v8=["svg",a,[["path",{d:"M12 10v6"}],["path",{d:"M9 13h6"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}]]];const n8=["svg",a,[["path",{d:"M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"}],["circle",{cx:"12",cy:"13",r:"2"}],["path",{d:"M12 15v5"}]]];const o8=["svg",a,[["circle",{cx:"11.5",cy:"12.5",r:"2.5"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M13.3 14.3 15 16"}]]];const i8=["svg",a,[["path",{d:"M10.7 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v4.1"}],["path",{d:"m21 21-1.9-1.9"}],["circle",{cx:"17",cy:"17",r:"3"}]]];const l8=["svg",a,[["path",{d:"M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h7"}],["path",{d:"m8 16 3-3-3-3"}]]];const g8=["svg",a,[["path",{d:"M9 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v.5"}],["path",{d:"M12 10v4h4"}],["path",{d:"m12 14 1.535-1.605a5 5 0 0 1 8 1.5"}],["path",{d:"M22 22v-4h-4"}],["path",{d:"m22 18-1.535 1.605a5 5 0 0 1-8-1.5"}]]];const x8=["svg",a,[["path",{d:"M20 10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2.5a1 1 0 0 1-.8-.4l-.9-1.2A1 1 0 0 0 15 3h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z"}],["path",{d:"M20 21a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-2.9a1 1 0 0 1-.88-.55l-.42-.85a1 1 0 0 0-.92-.6H13a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z"}],["path",{d:"M3 5a2 2 0 0 0 2 2h3"}],["path",{d:"M3 3v13a2 2 0 0 0 2 2h3"}]]];const y8=["svg",a,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"M12 10v6"}],["path",{d:"m9 13 3-3 3 3"}]]];const m8=["svg",a,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}],["path",{d:"m9.5 10.5 5 5"}],["path",{d:"m14.5 10.5-5 5"}]]];const H8=["svg",a,[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}]]];const V8=["svg",a,[["path",{d:"M20 17a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3.9a2 2 0 0 1-1.69-.9l-.81-1.2a2 2 0 0 0-1.67-.9H8a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2Z"}],["path",{d:"M2 8v11a2 2 0 0 0 2 2h14"}]]];const C8=["svg",a,[["path",{d:"M4 16v-2.38C4 11.5 2.97 10.5 3 8c.03-2.72 1.49-6 4.5-6C9.37 2 10 3.8 10 5.5c0 3.11-2 5.66-2 8.68V16a2 2 0 1 1-4 0Z"}],["path",{d:"M20 20v-2.38c0-2.12 1.03-3.12 1-5.62-.03-2.72-1.49-6-4.5-6C14.63 6 14 7.8 14 9.5c0 3.11 2 5.66 2 8.68V20a2 2 0 1 0 4 0Z"}],["path",{d:"M16 17h4"}],["path",{d:"M4 13h4"}]]];const w8=["svg",a,[["path",{d:"M12 12H5a2 2 0 0 0-2 2v5"}],["circle",{cx:"13",cy:"19",r:"2"}],["circle",{cx:"5",cy:"19",r:"2"}],["path",{d:"M8 19h3m5-17v17h6M6 12V7c0-1.1.9-2 2-2h3l5 5"}]]];const u8=["svg",a,[["polyline",{points:"15 17 20 12 15 7"}],["path",{d:"M4 18v-2a4 4 0 0 1 4-4h12"}]]];const A8=["svg",a,[["line",{x1:"22",x2:"2",y1:"6",y2:"6"}],["line",{x1:"22",x2:"2",y1:"18",y2:"18"}],["line",{x1:"6",x2:"6",y1:"2",y2:"22"}],["line",{x1:"18",x2:"18",y1:"2",y2:"22"}]]];const L8=["svg",a,[["path",{d:"M5 16V9h14V2H5l14 14h-7m-7 0 7 7v-7m-7 0h7"}]]];const S8=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M16 16s-1.5-2-4-2-4 2-4 2"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}]]];const f8=["svg",a,[["line",{x1:"3",x2:"15",y1:"22",y2:"22"}],["line",{x1:"4",x2:"14",y1:"9",y2:"9"}],["path",{d:"M14 22V4a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v18"}],["path",{d:"M14 13h2a2 2 0 0 1 2 2v2a2 2 0 0 0 2 2a2 2 0 0 0 2-2V9.83a2 2 0 0 0-.59-1.42L18 5"}]]];const Z8=["svg",a,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["rect",{width:"10",height:"8",x:"7",y:"8",rx:"1"}]]];const P8=["svg",a,[["path",{d:"M2 7v10"}],["path",{d:"M6 5v14"}],["rect",{width:"12",height:"18",x:"10",y:"3",rx:"2"}]]];const k8=["svg",a,[["path",{d:"M2 3v18"}],["rect",{width:"12",height:"18",x:"6",y:"3",rx:"2"}],["path",{d:"M22 3v18"}]]];const z8=["svg",a,[["rect",{width:"18",height:"14",x:"3",y:"3",rx:"2"}],["path",{d:"M4 21h1"}],["path",{d:"M9 21h1"}],["path",{d:"M14 21h1"}],["path",{d:"M19 21h1"}]]];const B8=["svg",a,[["path",{d:"M7 2h10"}],["path",{d:"M5 6h14"}],["rect",{width:"18",height:"12",x:"3",y:"10",rx:"2"}]]];const F8=["svg",a,[["path",{d:"M3 2h18"}],["rect",{width:"18",height:"12",x:"3",y:"6",rx:"2"}],["path",{d:"M3 22h18"}]]];const D8=["svg",a,[["line",{x1:"6",x2:"10",y1:"11",y2:"11"}],["line",{x1:"8",x2:"8",y1:"9",y2:"13"}],["line",{x1:"15",x2:"15.01",y1:"12",y2:"12"}],["line",{x1:"18",x2:"18.01",y1:"10",y2:"10"}],["path",{d:"M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z"}]]];const q8=["svg",a,[["line",{x1:"6",x2:"10",y1:"12",y2:"12"}],["line",{x1:"8",x2:"8",y1:"10",y2:"14"}],["line",{x1:"15",x2:"15.01",y1:"13",y2:"13"}],["line",{x1:"18",x2:"18.01",y1:"11",y2:"11"}],["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}]]];const R8=["svg",a,[["path",{d:"m12 14 4-4"}],["path",{d:"M3.34 19a10 10 0 1 1 17.32 0"}]]];const b8=["svg",a,[["path",{d:"m14.5 12.5-8 8a2.119 2.119 0 1 1-3-3l8-8"}],["path",{d:"m16 16 6-6"}],["path",{d:"m8 8 6-6"}],["path",{d:"m9 7 8 8"}],["path",{d:"m21 11-8-8"}]]];const T8=["svg",a,[["path",{d:"M6 3h12l4 6-10 13L2 9Z"}],["path",{d:"M11 3 8 9l4 13 4-13-3-6"}],["path",{d:"M2 9h20"}]]];const U8=["svg",a,[["path",{d:"M9 10h.01"}],["path",{d:"M15 10h.01"}],["path",{d:"M12 2a8 8 0 0 0-8 8v12l3-3 2.5 2.5L12 19l2.5 2.5L17 19l3 3V10a8 8 0 0 0-8-8z"}]]];const O8=["svg",a,[["rect",{x:"3",y:"8",width:"18",height:"4",rx:"1"}],["path",{d:"M12 8v13"}],["path",{d:"M19 12v7a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-7"}],["path",{d:"M7.5 8a2.5 2.5 0 0 1 0-5A4.8 8 0 0 1 12 8a4.8 8 0 0 1 4.5-5 2.5 2.5 0 0 1 0 5"}]]];const I8=["svg",a,[["path",{d:"M6 3v12"}],["path",{d:"M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"}],["path",{d:"M6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"}],["path",{d:"M15 6a9 9 0 0 0-9 9"}],["path",{d:"M18 15v6"}],["path",{d:"M21 18h-6"}]]];const E8=["svg",a,[["line",{x1:"6",x2:"6",y1:"3",y2:"15"}],["circle",{cx:"18",cy:"6",r:"3"}],["circle",{cx:"6",cy:"18",r:"3"}],["path",{d:"M18 9a9 9 0 0 1-9 9"}]]];const E1=["svg",a,[["circle",{cx:"12",cy:"12",r:"3"}],["line",{x1:"3",x2:"9",y1:"12",y2:"12"}],["line",{x1:"15",x2:"21",y1:"12",y2:"12"}]]];const G8=["svg",a,[["path",{d:"M12 3v6"}],["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"M12 15v6"}]]];const W8=["svg",a,[["circle",{cx:"5",cy:"6",r:"3"}],["path",{d:"M12 6h5a2 2 0 0 1 2 2v7"}],["path",{d:"m15 9-3-3 3-3"}],["circle",{cx:"19",cy:"18",r:"3"}],["path",{d:"M12 18H7a2 2 0 0 1-2-2V9"}],["path",{d:"m9 15 3 3-3 3"}]]];const X8=["svg",a,[["circle",{cx:"18",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M13 6h3a2 2 0 0 1 2 2v7"}],["path",{d:"M11 18H8a2 2 0 0 1-2-2V9"}]]];const N8=["svg",a,[["circle",{cx:"12",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["circle",{cx:"18",cy:"6",r:"3"}],["path",{d:"M18 9v2c0 .6-.4 1-1 1H7c-.6 0-1-.4-1-1V9"}],["path",{d:"M12 12v3"}]]];const K8=["svg",a,[["circle",{cx:"5",cy:"6",r:"3"}],["path",{d:"M5 9v6"}],["circle",{cx:"5",cy:"18",r:"3"}],["path",{d:"M12 3v18"}],["circle",{cx:"19",cy:"6",r:"3"}],["path",{d:"M16 15.7A9 9 0 0 0 19 9"}]]];const J8=["svg",a,[["circle",{cx:"18",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M6 21V9a9 9 0 0 0 9 9"}]]];const j8=["svg",a,[["circle",{cx:"5",cy:"6",r:"3"}],["path",{d:"M5 9v12"}],["circle",{cx:"19",cy:"18",r:"3"}],["path",{d:"m15 9-3-3 3-3"}],["path",{d:"M12 6h5a2 2 0 0 1 2 2v7"}]]];const Q8=["svg",a,[["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M6 9v12"}],["path",{d:"m21 3-6 6"}],["path",{d:"m21 9-6-6"}],["path",{d:"M18 11.5V15"}],["circle",{cx:"18",cy:"18",r:"3"}]]];const _8=["svg",a,[["circle",{cx:"5",cy:"6",r:"3"}],["path",{d:"M5 9v12"}],["path",{d:"m15 9-3-3 3-3"}],["path",{d:"M12 6h5a2 2 0 0 1 2 2v3"}],["path",{d:"M19 15v6"}],["path",{d:"M22 18h-6"}]]];const Y8=["svg",a,[["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M6 9v12"}],["path",{d:"M13 6h3a2 2 0 0 1 2 2v3"}],["path",{d:"M18 15v6"}],["path",{d:"M21 18h-6"}]]];const $8=["svg",a,[["circle",{cx:"18",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M18 6V5"}],["path",{d:"M18 11v-1"}],["line",{x1:"6",x2:"6",y1:"9",y2:"21"}]]];const a7=["svg",a,[["circle",{cx:"18",cy:"18",r:"3"}],["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M13 6h3a2 2 0 0 1 2 2v7"}],["line",{x1:"6",x2:"6",y1:"9",y2:"21"}]]];const t7=["svg",a,[["path",{d:"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"}],["path",{d:"M9 18c-4.51 2-5-2-7-2"}]]];const h7=["svg",a,[["path",{d:"m22 13.29-3.33-10a.42.42 0 0 0-.14-.18.38.38 0 0 0-.22-.11.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18l-2.26 6.67H8.32L6.1 3.26a.42.42 0 0 0-.1-.18.38.38 0 0 0-.26-.08.39.39 0 0 0-.23.07.42.42 0 0 0-.14.18L2 13.29a.74.74 0 0 0 .27.83L12 21l9.69-6.88a.71.71 0 0 0 .31-.83Z"}]]];const d7=["svg",a,[["path",{d:"M15.2 22H8.8a2 2 0 0 1-2-1.79L5 3h14l-1.81 17.21A2 2 0 0 1 15.2 22Z"}],["path",{d:"M6 12a5 5 0 0 1 6 0 5 5 0 0 0 6 0"}]]];const p7=["svg",a,[["circle",{cx:"6",cy:"15",r:"4"}],["circle",{cx:"18",cy:"15",r:"4"}],["path",{d:"M14 15a2 2 0 0 0-2-2 2 2 0 0 0-2 2"}],["path",{d:"M2.5 13 5 7c.7-1.3 1.4-2 3-2"}],["path",{d:"M21.5 13 19 7c-.7-1.3-1.5-2-3-2"}]]];const c7=["svg",a,[["path",{d:"M15.686 15A14.5 14.5 0 0 1 12 22a14.5 14.5 0 0 1 0-20 10 10 0 1 0 9.542 13"}],["path",{d:"M2 12h8.5"}],["path",{d:"M20 6V4a2 2 0 1 0-4 0v2"}],["rect",{width:"8",height:"5",x:"14",y:"6",rx:"1"}]]];const M7=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"}],["path",{d:"M2 12h20"}]]];const s7=["svg",a,[["path",{d:"M12 13V2l8 4-8 4"}],["path",{d:"M20.561 10.222a9 9 0 1 1-12.55-5.29"}],["path",{d:"M8.002 9.997a5 5 0 1 0 8.9 2.02"}]]];const e7=["svg",a,[["path",{d:"M18 11.5V9a2 2 0 0 0-2-2a2 2 0 0 0-2 2v1.4"}],["path",{d:"M14 10V8a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2"}],["path",{d:"M10 9.9V9a2 2 0 0 0-2-2a2 2 0 0 0-2 2v5"}],["path",{d:"M6 14a2 2 0 0 0-2-2a2 2 0 0 0-2 2"}],["path",{d:"M18 11a2 2 0 1 1 4 0v3a8 8 0 0 1-8 8h-4a8 8 0 0 1-8-8 2 2 0 1 1 4 0"}]]];const r7=["svg",a,[["path",{d:"M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z"}],["path",{d:"M22 10v6"}],["path",{d:"M6 12.5V16a6 3 0 0 0 12 0v-3.5"}]]];const v7=["svg",a,[["path",{d:"M22 5V2l-5.89 5.89"}],["circle",{cx:"16.6",cy:"15.89",r:"3"}],["circle",{cx:"8.11",cy:"7.4",r:"3"}],["circle",{cx:"12.35",cy:"11.65",r:"3"}],["circle",{cx:"13.91",cy:"5.85",r:"3"}],["circle",{cx:"18.15",cy:"10.09",r:"3"}],["circle",{cx:"6.56",cy:"13.2",r:"3"}],["circle",{cx:"10.8",cy:"17.44",r:"3"}],["circle",{cx:"5",cy:"19",r:"3"}]]];const n7=["svg",a,[["path",{d:"M12 3v17a1 1 0 0 1-1 1H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6a1 1 0 0 1-1 1H3"}],["path",{d:"m16 19 2 2 4-4"}]]];const o7=["svg",a,[["path",{d:"M12 3v17a1 1 0 0 1-1 1H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6a1 1 0 0 1-1 1H3"}],["path",{d:"m16 16 5 5"}],["path",{d:"m16 21 5-5"}]]];const G1=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 12h18"}],["path",{d:"M12 3v18"}]]];const v=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"M3 15h18"}],["path",{d:"M9 3v18"}],["path",{d:"M15 3v18"}]]];const i7=["svg",a,[["circle",{cx:"12",cy:"9",r:"1"}],["circle",{cx:"19",cy:"9",r:"1"}],["circle",{cx:"5",cy:"9",r:"1"}],["circle",{cx:"12",cy:"15",r:"1"}],["circle",{cx:"19",cy:"15",r:"1"}],["circle",{cx:"5",cy:"15",r:"1"}]]];const l7=["svg",a,[["circle",{cx:"9",cy:"12",r:"1"}],["circle",{cx:"9",cy:"5",r:"1"}],["circle",{cx:"9",cy:"19",r:"1"}],["circle",{cx:"15",cy:"12",r:"1"}],["circle",{cx:"15",cy:"5",r:"1"}],["circle",{cx:"15",cy:"19",r:"1"}]]];const g7=["svg",a,[["circle",{cx:"12",cy:"5",r:"1"}],["circle",{cx:"19",cy:"5",r:"1"}],["circle",{cx:"5",cy:"5",r:"1"}],["circle",{cx:"12",cy:"12",r:"1"}],["circle",{cx:"19",cy:"12",r:"1"}],["circle",{cx:"5",cy:"12",r:"1"}],["circle",{cx:"12",cy:"19",r:"1"}],["circle",{cx:"19",cy:"19",r:"1"}],["circle",{cx:"5",cy:"19",r:"1"}]]];const x7=["svg",a,[["path",{d:"M3 7V5c0-1.1.9-2 2-2h2"}],["path",{d:"M17 3h2c1.1 0 2 .9 2 2v2"}],["path",{d:"M21 17v2c0 1.1-.9 2-2 2h-2"}],["path",{d:"M7 21H5c-1.1 0-2-.9-2-2v-2"}],["rect",{width:"7",height:"5",x:"7",y:"7",rx:"1"}],["rect",{width:"7",height:"5",x:"10",y:"12",rx:"1"}]]];const y7=["svg",a,[["path",{d:"m11.9 12.1 4.514-4.514"}],["path",{d:"M20.1 2.3a1 1 0 0 0-1.4 0l-1.114 1.114A2 2 0 0 0 17 4.828v1.344a2 2 0 0 1-.586 1.414A2 2 0 0 1 17.828 7h1.344a2 2 0 0 0 1.414-.586L21.7 5.3a1 1 0 0 0 0-1.4z"}],["path",{d:"m6 16 2 2"}],["path",{d:"M8.2 9.9C8.7 8.8 9.8 8 11 8c2.8 0 5 2.2 5 5 0 1.2-.8 2.3-1.9 2.8l-.9.4A2 2 0 0 0 12 18a4 4 0 0 1-4 4c-3.3 0-6-2.7-6-6a4 4 0 0 1 4-4 2 2 0 0 0 1.8-1.2z"}],["circle",{cx:"11.5",cy:"12.5",r:".5",fill:"currentColor"}]]];const m7=["svg",a,[["path",{d:"M13.144 21.144A7.274 10.445 45 1 0 2.856 10.856"}],["path",{d:"M13.144 21.144A7.274 4.365 45 0 0 2.856 10.856a7.274 4.365 45 0 0 10.288 10.288"}],["path",{d:"M16.565 10.435 18.6 8.4a2.501 2.501 0 1 0 1.65-4.65 2.5 2.5 0 1 0-4.66 1.66l-2.024 2.025"}],["path",{d:"m8.5 16.5-1-1"}]]];const H7=["svg",a,[["path",{d:"m15 12-8.373 8.373a1 1 0 1 1-3-3L12 9"}],["path",{d:"m18 15 4-4"}],["path",{d:"m21.5 11.5-1.914-1.914A2 2 0 0 1 19 8.172V7l-2.26-2.26a6 6 0 0 0-4.202-1.756L9 2.96l.92.82A6.18 6.18 0 0 1 12 8.4V10l2 2h1.172a2 2 0 0 1 1.414.586L18.5 14.5"}]]];const V7=["svg",a,[["path",{d:"M11 15h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 17"}],["path",{d:"m7 21 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"}],["path",{d:"m2 16 6 6"}],["circle",{cx:"16",cy:"9",r:"2.9"}],["circle",{cx:"6",cy:"5",r:"3"}]]];const C7=["svg",a,[["path",{d:"M11 14h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 16"}],["path",{d:"m7 20 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"}],["path",{d:"m2 15 6 6"}],["path",{d:"M19.5 8.5c.7-.7 1.5-1.6 1.5-2.7A2.73 2.73 0 0 0 16 4a2.78 2.78 0 0 0-5 1.8c0 1.2.8 2 1.5 2.8L16 12Z"}]]];const W1=["svg",a,[["path",{d:"M11 12h2a2 2 0 1 0 0-4h-3c-.6 0-1.1.2-1.4.6L3 14"}],["path",{d:"m7 18 1.6-1.4c.3-.4.8-.6 1.4-.6h4c1.1 0 2.1-.4 2.8-1.2l4.6-4.4a2 2 0 0 0-2.75-2.91l-4.2 3.9"}],["path",{d:"m2 13 6 6"}]]];const w7=["svg",a,[["path",{d:"M18 12.5V10a2 2 0 0 0-2-2a2 2 0 0 0-2 2v1.4"}],["path",{d:"M14 11V9a2 2 0 1 0-4 0v2"}],["path",{d:"M10 10.5V5a2 2 0 1 0-4 0v9"}],["path",{d:"m7 15-1.76-1.76a2 2 0 0 0-2.83 2.82l3.6 3.6C7.5 21.14 9.2 22 12 22h2a8 8 0 0 0 8-8V7a2 2 0 1 0-4 0v5"}]]];const u7=["svg",a,[["path",{d:"M12 3V2"}],["path",{d:"M5 10a7.1 7.1 0 0 1 14 0"}],["path",{d:"M4 10h16"}],["path",{d:"M2 14h12a2 2 0 1 1 0 4h-2"}],["path",{d:"m15.4 17.4 3.2-2.8a2 2 0 0 1 2.8 2.9l-3.6 3.3c-.7.8-1.7 1.2-2.8 1.2h-4c-1.1 0-2.1-.4-2.8-1.2L5 18"}],["path",{d:"M5 14v7H2"}]]];const A7=["svg",a,[["path",{d:"M18 11V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2"}],["path",{d:"M14 10V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v2"}],["path",{d:"M10 10.5V6a2 2 0 0 0-2-2a2 2 0 0 0-2 2v8"}],["path",{d:"M18 8a2 2 0 1 1 4 0v6a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15"}]]];const L7=["svg",a,[["path",{d:"m11 17 2 2a1 1 0 1 0 3-3"}],["path",{d:"m14 14 2.5 2.5a1 1 0 1 0 3-3l-3.88-3.88a3 3 0 0 0-4.24 0l-.88.88a1 1 0 1 1-3-3l2.81-2.81a5.79 5.79 0 0 1 7.06-.87l.47.28a2 2 0 0 0 1.42.25L21 4"}],["path",{d:"m21 3 1 11h-2"}],["path",{d:"M3 3 2 14l6.5 6.5a1 1 0 1 0 3-3"}],["path",{d:"M3 4h8"}]]];const S7=["svg",a,[["path",{d:"M12 2v8"}],["path",{d:"m16 6-4 4-4-4"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2"}],["path",{d:"M6 18h.01"}],["path",{d:"M10 18h.01"}]]];const f7=["svg",a,[["path",{d:"m16 6-4-4-4 4"}],["path",{d:"M12 2v8"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2"}],["path",{d:"M6 18h.01"}],["path",{d:"M10 18h.01"}]]];const Z7=["svg",a,[["line",{x1:"22",x2:"2",y1:"12",y2:"12"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"}],["line",{x1:"6",x2:"6.01",y1:"16",y2:"16"}],["line",{x1:"10",x2:"10.01",y1:"16",y2:"16"}]]];const P7=["svg",a,[["path",{d:"M2 18a1 1 0 0 0 1 1h18a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v2z"}],["path",{d:"M10 10V5a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v5"}],["path",{d:"M4 15v-3a6 6 0 0 1 6-6"}],["path",{d:"M14 6a6 6 0 0 1 6 6v3"}]]];const k7=["svg",a,[["line",{x1:"4",x2:"20",y1:"9",y2:"9"}],["line",{x1:"4",x2:"20",y1:"15",y2:"15"}],["line",{x1:"10",x2:"8",y1:"3",y2:"21"}],["line",{x1:"16",x2:"14",y1:"3",y2:"21"}]]];const z7=["svg",a,[["path",{d:"m5.2 6.2 1.4 1.4"}],["path",{d:"M2 13h2"}],["path",{d:"M20 13h2"}],["path",{d:"m17.4 7.6 1.4-1.4"}],["path",{d:"M22 17H2"}],["path",{d:"M22 21H2"}],["path",{d:"M16 13a4 4 0 0 0-8 0"}],["path",{d:"M12 5V2.5"}]]];const B7=["svg",a,[["path",{d:"M22 9a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h1l2 2h12l2-2h1a1 1 0 0 0 1-1Z"}],["path",{d:"M7.5 12h9"}]]];const F7=["svg",a,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["path",{d:"m17 12 3-2v8"}]]];const D7=["svg",a,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["path",{d:"M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1"}]]];const q7=["svg",a,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["path",{d:"M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2"}],["path",{d:"M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2"}]]];const R7=["svg",a,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["path",{d:"M17 10v4h4"}],["path",{d:"M21 10v8"}]]];const b7=["svg",a,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["path",{d:"M17 13v-3h4"}],["path",{d:"M17 17.7c.4.2.8.3 1.3.3 1.5 0 2.7-1.1 2.7-2.5S19.8 13 18.3 13H17"}]]];const T7=["svg",a,[["path",{d:"M4 12h8"}],["path",{d:"M4 18V6"}],["path",{d:"M12 18V6"}],["circle",{cx:"19",cy:"16",r:"2"}],["path",{d:"M20 10c-2 2-3 3.5-3 6"}]]];const U7=["svg",a,[["path",{d:"M6 12h12"}],["path",{d:"M6 20V4"}],["path",{d:"M18 20V4"}]]];const O7=["svg",a,[["path",{d:"M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3"}]]];const I7=["svg",a,[["path",{d:"M3 11h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Zm0 0a9 9 0 1 1 18 0m0 0v5a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3Z"}],["path",{d:"M21 16v2a4 4 0 0 1-4 4h-5"}]]];const E7=["svg",a,[["path",{d:"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"}],["path",{d:"m12 13-1-1 2-2-3-3 2-2"}]]];const G7=["svg",a,[["path",{d:"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"}],["path",{d:"M12 5 9.04 7.96a2.17 2.17 0 0 0 0 3.08c.82.82 2.13.85 3 .07l2.07-1.9a2.82 2.82 0 0 1 3.79 0l2.96 2.66"}],["path",{d:"m18 15-2-2"}],["path",{d:"m15 18-2-2"}]]];const W7=["svg",a,[["line",{x1:"2",y1:"2",x2:"22",y2:"22"}],["path",{d:"M16.5 16.5 12 21l-7-7c-1.5-1.45-3-3.2-3-5.5a5.5 5.5 0 0 1 2.14-4.35"}],["path",{d:"M8.76 3.1c1.15.22 2.13.78 3.24 1.9 1.5-1.5 2.74-2 4.5-2A5.5 5.5 0 0 1 22 8.5c0 2.12-1.3 3.78-2.67 5.17"}]]];const X7=["svg",a,[["path",{d:"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"}],["path",{d:"M3.22 12H9.5l.5-1 2 4.5 2-7 1.5 3.5h5.27"}]]];const N7=["svg",a,[["path",{d:"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"}]]];const K7=["svg",a,[["path",{d:"M11 8c2-3-2-3 0-6"}],["path",{d:"M15.5 8c2-3-2-3 0-6"}],["path",{d:"M6 10h.01"}],["path",{d:"M6 14h.01"}],["path",{d:"M10 16v-4"}],["path",{d:"M14 16v-4"}],["path",{d:"M18 16v-4"}],["path",{d:"M20 6a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h3"}],["path",{d:"M5 20v2"}],["path",{d:"M19 20v2"}]]];const J7=["svg",a,[["path",{d:"M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"}]]];const j7=["svg",a,[["path",{d:"m9 11-6 6v3h9l3-3"}],["path",{d:"m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4"}]]];const Q7=["svg",a,[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"}],["path",{d:"M3 3v5h5"}],["path",{d:"M12 7v5l4 2"}]]];const _7=["svg",a,[["path",{d:"M10.82 16.12c1.69.6 3.91.79 5.18.85.28.01.53-.09.7-.27"}],["path",{d:"M11.14 20.57c.52.24 2.44 1.12 4.08 1.37.46.06.86-.25.9-.71.12-1.52-.3-3.43-.5-4.28"}],["path",{d:"M16.13 21.05c1.65.63 3.68.84 4.87.91a.9.9 0 0 0 .7-.26"}],["path",{d:"M17.99 5.52a20.83 20.83 0 0 1 3.15 4.5.8.8 0 0 1-.68 1.13c-1.17.1-2.5.02-3.9-.25"}],["path",{d:"M20.57 11.14c.24.52 1.12 2.44 1.37 4.08.04.3-.08.59-.31.75"}],["path",{d:"M4.93 4.93a10 10 0 0 0-.67 13.4c.35.43.96.4 1.17-.12.69-1.71 1.07-5.07 1.07-6.71 1.34.45 3.1.9 4.88.62a.85.85 0 0 0 .48-.24"}],["path",{d:"M5.52 17.99c1.05.95 2.91 2.42 4.5 3.15a.8.8 0 0 0 1.13-.68c.2-2.34-.33-5.3-1.57-8.28"}],["path",{d:"M8.35 2.68a10 10 0 0 1 9.98 1.58c.43.35.4.96-.12 1.17-1.5.6-4.3.98-6.07 1.05"}],["path",{d:"m2 2 20 20"}]]];const Y7=["svg",a,[["path",{d:"M10.82 16.12c1.69.6 3.91.79 5.18.85.55.03 1-.42.97-.97-.06-1.27-.26-3.5-.85-5.18"}],["path",{d:"M11.5 6.5c1.64 0 5-.38 6.71-1.07.52-.2.55-.82.12-1.17A10 10 0 0 0 4.26 18.33c.35.43.96.4 1.17-.12.69-1.71 1.07-5.07 1.07-6.71 1.34.45 3.1.9 4.88.62a.88.88 0 0 0 .73-.74c.3-2.14-.15-3.5-.61-4.88"}],["path",{d:"M15.62 16.95c.2.85.62 2.76.5 4.28a.77.77 0 0 1-.9.7 16.64 16.64 0 0 1-4.08-1.36"}],["path",{d:"M16.13 21.05c1.65.63 3.68.84 4.87.91a.9.9 0 0 0 .96-.96 17.68 17.68 0 0 0-.9-4.87"}],["path",{d:"M16.94 15.62c.86.2 2.77.62 4.29.5a.77.77 0 0 0 .7-.9 16.64 16.64 0 0 0-1.36-4.08"}],["path",{d:"M17.99 5.52a20.82 20.82 0 0 1 3.15 4.5.8.8 0 0 1-.68 1.13c-2.33.2-5.3-.32-8.27-1.57"}],["path",{d:"M4.93 4.93 3 3a.7.7 0 0 1 0-1"}],["path",{d:"M9.58 12.18c1.24 2.98 1.77 5.95 1.57 8.28a.8.8 0 0 1-1.13.68 20.82 20.82 0 0 1-4.5-3.15"}]]];const $7=["svg",a,[["path",{d:"M12 6v4"}],["path",{d:"M14 14h-4"}],["path",{d:"M14 18h-4"}],["path",{d:"M14 8h-4"}],["path",{d:"M18 12h2a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2h2"}],["path",{d:"M18 22V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v18"}]]];const aM=["svg",a,[["path",{d:"M10 22v-6.57"}],["path",{d:"M12 11h.01"}],["path",{d:"M12 7h.01"}],["path",{d:"M14 15.43V22"}],["path",{d:"M15 16a5 5 0 0 0-6 0"}],["path",{d:"M16 11h.01"}],["path",{d:"M16 7h.01"}],["path",{d:"M8 11h.01"}],["path",{d:"M8 7h.01"}],["rect",{x:"4",y:"2",width:"16",height:"20",rx:"2"}]]];const tM=["svg",a,[["path",{d:"M5 22h14"}],["path",{d:"M5 2h14"}],["path",{d:"M17 22v-4.172a2 2 0 0 0-.586-1.414L12 12l-4.414 4.414A2 2 0 0 0 7 17.828V22"}],["path",{d:"M7 2v4.172a2 2 0 0 0 .586 1.414L12 12l4.414-4.414A2 2 0 0 0 17 6.172V2"}]]];const hM=["svg",a,[["path",{d:"M10 12V8.964"}],["path",{d:"M14 12V8.964"}],["path",{d:"M15 12a1 1 0 0 1 1 1v2a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-2a1 1 0 0 1 1-1z"}],["path",{d:"M8.5 21H5a2 2 0 0 1-2-2v-9a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-2"}]]];const dM=["svg",a,[["path",{d:"M13.22 2.416a2 2 0 0 0-2.511.057l-7 5.999A2 2 0 0 0 3 10v9a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7.354"}],["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"}],["path",{d:"M15 6h6"}],["path",{d:"M18 3v6"}]]];const X1=["svg",a,[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"}]]];const N1=["svg",a,[["path",{d:"M12 17c5 0 8-2.69 8-6H4c0 3.31 3 6 8 6m-4 4h8m-4-3v3M5.14 11a3.5 3.5 0 1 1 6.71 0"}],["path",{d:"M12.14 11a3.5 3.5 0 1 1 6.71 0"}],["path",{d:"M15.5 6.5a3.5 3.5 0 1 0-7 0"}]]];const K1=["svg",a,[["path",{d:"m7 11 4.08 10.35a1 1 0 0 0 1.84 0L17 11"}],["path",{d:"M17 7A5 5 0 0 0 7 7"}],["path",{d:"M17 7a2 2 0 0 1 0 4H7a2 2 0 0 1 0-4"}]]];const pM=["svg",a,[["path",{d:"M16 10h2"}],["path",{d:"M16 14h2"}],["path",{d:"M6.17 15a3 3 0 0 1 5.66 0"}],["circle",{cx:"9",cy:"11",r:"2"}],["rect",{x:"2",y:"5",width:"20",height:"14",rx:"2"}]]];const cM=["svg",a,[["path",{d:"M10.3 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10l-3.1-3.1a2 2 0 0 0-2.814.014L6 21"}],["path",{d:"m14 19 3 3v-5.5"}],["path",{d:"m17 22 3-3"}],["circle",{cx:"9",cy:"9",r:"2"}]]];const MM=["svg",a,[["path",{d:"M21 9v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"}],["line",{x1:"16",x2:"22",y1:"5",y2:"5"}],["circle",{cx:"9",cy:"9",r:"2"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"}]]];const sM=["svg",a,[["line",{x1:"2",x2:"22",y1:"2",y2:"22"}],["path",{d:"M10.41 10.41a2 2 0 1 1-2.83-2.83"}],["line",{x1:"13.5",x2:"6",y1:"13.5",y2:"21"}],["line",{x1:"18",x2:"21",y1:"12",y2:"15"}],["path",{d:"M3.59 3.59A1.99 1.99 0 0 0 3 5v14a2 2 0 0 0 2 2h14c.55 0 1.052-.22 1.41-.59"}],["path",{d:"M21 15V5a2 2 0 0 0-2-2H9"}]]];const eM=["svg",a,[["path",{d:"m11 16-5 5"}],["path",{d:"M11 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v6.5"}],["path",{d:"M15.765 22a.5.5 0 0 1-.765-.424V13.38a.5.5 0 0 1 .765-.424l5.878 3.674a1 1 0 0 1 0 1.696z"}],["circle",{cx:"9",cy:"9",r:"2"}]]];const rM=["svg",a,[["path",{d:"M16 5h6"}],["path",{d:"M19 2v6"}],["path",{d:"M21 11.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7.5"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"}],["circle",{cx:"9",cy:"9",r:"2"}]]];const vM=["svg",a,[["path",{d:"M10.3 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10l-3.1-3.1a2 2 0 0 0-2.814.014L6 21"}],["path",{d:"m14 19.5 3-3 3 3"}],["path",{d:"M17 22v-5.5"}],["circle",{cx:"9",cy:"9",r:"2"}]]];const nM=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["circle",{cx:"9",cy:"9",r:"2"}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"}]]];const oM=["svg",a,[["path",{d:"M18 22H4a2 2 0 0 1-2-2V6"}],["path",{d:"m22 13-1.296-1.296a2.41 2.41 0 0 0-3.408 0L11 18"}],["circle",{cx:"12",cy:"8",r:"2"}],["rect",{width:"16",height:"16",x:"6",y:"2",rx:"2"}]]];const iM=["svg",a,[["path",{d:"M12 3v12"}],["path",{d:"m8 11 4 4 4-4"}],["path",{d:"M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4"}]]];const lM=["svg",a,[["polyline",{points:"22 12 16 12 14 15 10 15 8 12 2 12"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"}]]];const J1=["svg",a,[["polyline",{points:"7 8 3 12 7 16"}],["line",{x1:"21",x2:"11",y1:"12",y2:"12"}],["line",{x1:"21",x2:"11",y1:"6",y2:"6"}],["line",{x1:"21",x2:"11",y1:"18",y2:"18"}]]];const j1=["svg",a,[["polyline",{points:"3 8 7 12 3 16"}],["line",{x1:"21",x2:"11",y1:"12",y2:"12"}],["line",{x1:"21",x2:"11",y1:"6",y2:"6"}],["line",{x1:"21",x2:"11",y1:"18",y2:"18"}]]];const gM=["svg",a,[["path",{d:"M6 3h12"}],["path",{d:"M6 8h12"}],["path",{d:"m6 13 8.5 8"}],["path",{d:"M6 13h3"}],["path",{d:"M9 13c6.667 0 6.667-10 0-10"}]]];const xM=["svg",a,[["path",{d:"M12 12c-2-2.67-4-4-6-4a4 4 0 1 0 0 8c2 0 4-1.33 6-4Zm0 0c2 2.67 4 4 6 4a4 4 0 0 0 0-8c-2 0-4 1.33-6 4Z"}]]];const yM=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M12 16v-4"}],["path",{d:"M12 8h.01"}]]];const mM=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 7h.01"}],["path",{d:"M17 7h.01"}],["path",{d:"M7 17h.01"}],["path",{d:"M17 17h.01"}]]];const HM=["svg",a,[["rect",{width:"20",height:"20",x:"2",y:"2",rx:"5",ry:"5"}],["path",{d:"M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"}],["line",{x1:"17.5",x2:"17.51",y1:"6.5",y2:"6.5"}]]];const VM=["svg",a,[["line",{x1:"19",x2:"10",y1:"4",y2:"4"}],["line",{x1:"14",x2:"5",y1:"20",y2:"20"}],["line",{x1:"15",x2:"9",y1:"4",y2:"20"}]]];const CM=["svg",a,[["path",{d:"M20 10c0-4.4-3.6-8-8-8s-8 3.6-8 8 3.6 8 8 8h8"}],["polyline",{points:"16 14 20 18 16 22"}]]];const wM=["svg",a,[["path",{d:"M4 10c0-4.4 3.6-8 8-8s8 3.6 8 8-3.6 8-8 8H4"}],["polyline",{points:"8 22 4 18 8 14"}]]];const uM=["svg",a,[["path",{d:"M12 9.5V21m0-11.5L6 3m6 6.5L18 3"}],["path",{d:"M6 15h12"}],["path",{d:"M6 11h12"}]]];const AM=["svg",a,[["path",{d:"M21 17a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-2Z"}],["path",{d:"M6 15v-2"}],["path",{d:"M12 15V9"}],["circle",{cx:"12",cy:"6",r:"3"}]]];const LM=["svg",a,[["path",{d:"M6 5v11"}],["path",{d:"M12 5v6"}],["path",{d:"M18 5v14"}]]];const SM=["svg",a,[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor"}]]];const fM=["svg",a,[["path",{d:"M12.4 2.7a2.5 2.5 0 0 1 3.4 0l5.5 5.5a2.5 2.5 0 0 1 0 3.4l-3.7 3.7a2.5 2.5 0 0 1-3.4 0L8.7 9.8a2.5 2.5 0 0 1 0-3.4z"}],["path",{d:"m14 7 3 3"}],["path",{d:"m9.4 10.6-6.814 6.814A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814"}]]];const ZM=["svg",a,[["path",{d:"m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4"}],["path",{d:"m21 2-9.6 9.6"}],["circle",{cx:"7.5",cy:"15.5",r:"5.5"}]]];const PM=["svg",a,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M6 8h4"}],["path",{d:"M14 8h.01"}],["path",{d:"M18 8h.01"}],["path",{d:"M2 12h20"}],["path",{d:"M6 12v4"}],["path",{d:"M10 12v4"}],["path",{d:"M14 12v4"}],["path",{d:"M18 12v4"}]]];const kM=["svg",a,[["path",{d:"M 20 4 A2 2 0 0 1 22 6"}],["path",{d:"M 22 6 L 22 16.41"}],["path",{d:"M 7 16 L 16 16"}],["path",{d:"M 9.69 4 L 20 4"}],["path",{d:"M14 8h.01"}],["path",{d:"M18 8h.01"}],["path",{d:"m2 2 20 20"}],["path",{d:"M20 20H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2"}],["path",{d:"M6 8h.01"}],["path",{d:"M8 12h.01"}]]];const zM=["svg",a,[["path",{d:"M10 8h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M14 8h.01"}],["path",{d:"M16 12h.01"}],["path",{d:"M18 8h.01"}],["path",{d:"M6 8h.01"}],["path",{d:"M7 16h10"}],["path",{d:"M8 12h.01"}],["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}]]];const BM=["svg",a,[["path",{d:"M12 2v5"}],["path",{d:"M6 7h12l4 9H2l4-9Z"}],["path",{d:"M9.17 16a3 3 0 1 0 5.66 0"}]]];const FM=["svg",a,[["path",{d:"m14 5-3 3 2 7 8-8-7-2Z"}],["path",{d:"m14 5-3 3-3-3 3-3 3 3Z"}],["path",{d:"M9.5 6.5 4 12l3 6"}],["path",{d:"M3 22v-2c0-1.1.9-2 2-2h4a2 2 0 0 1 2 2v2H3Z"}]]];const DM=["svg",a,[["path",{d:"M9 2h6l3 7H6l3-7Z"}],["path",{d:"M12 9v13"}],["path",{d:"M9 22h6"}]]];const qM=["svg",a,[["path",{d:"M11 13h6l3 7H8l3-7Z"}],["path",{d:"M14 13V8a2 2 0 0 0-2-2H8"}],["path",{d:"M4 9h2a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H4v6Z"}]]];const RM=["svg",a,[["path",{d:"M11 4h6l3 7H8l3-7Z"}],["path",{d:"M14 11v5a2 2 0 0 1-2 2H8"}],["path",{d:"M4 15h2a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H4v-6Z"}]]];const bM=["svg",a,[["path",{d:"M8 2h8l4 10H4L8 2Z"}],["path",{d:"M12 12v6"}],["path",{d:"M8 22v-2c0-1.1.9-2 2-2h4a2 2 0 0 1 2 2v2H8Z"}]]];const TM=["svg",a,[["path",{d:"m12 8 6-3-6-3v10"}],["path",{d:"m8 11.99-5.5 3.14a1 1 0 0 0 0 1.74l8.5 4.86a2 2 0 0 0 2 0l8.5-4.86a1 1 0 0 0 0-1.74L16 12"}],["path",{d:"m6.49 12.85 11.02 6.3"}],["path",{d:"M17.51 12.85 6.5 19.15"}]]];const UM=["svg",a,[["line",{x1:"3",x2:"21",y1:"22",y2:"22"}],["line",{x1:"6",x2:"6",y1:"18",y2:"11"}],["line",{x1:"10",x2:"10",y1:"18",y2:"11"}],["line",{x1:"14",x2:"14",y1:"18",y2:"11"}],["line",{x1:"18",x2:"18",y1:"18",y2:"11"}],["polygon",{points:"12 2 20 7 4 7"}]]];const OM=["svg",a,[["path",{d:"m5 8 6 6"}],["path",{d:"m4 14 6-6 2-3"}],["path",{d:"M2 5h12"}],["path",{d:"M7 2h1"}],["path",{d:"m22 22-5-10-5 10"}],["path",{d:"M14 18h6"}]]];const Q1=["svg",a,[["rect",{width:"18",height:"12",x:"3",y:"4",rx:"2",ry:"2"}],["line",{x1:"2",x2:"22",y1:"20",y2:"20"}]]];const IM=["svg",a,[["path",{d:"M20 16V7a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v9m16 0H4m16 0 1.28 2.55a1 1 0 0 1-.9 1.45H3.62a1 1 0 0 1-.9-1.45L4 16"}]]];const EM=["svg",a,[["path",{d:"M7 22a5 5 0 0 1-2-4"}],["path",{d:"M7 16.93c.96.43 1.96.74 2.99.91"}],["path",{d:"M3.34 14A6.8 6.8 0 0 1 2 10c0-4.42 4.48-8 10-8s10 3.58 10 8a7.19 7.19 0 0 1-.33 2"}],["path",{d:"M5 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"}],["path",{d:"M14.33 22h-.09a.35.35 0 0 1-.24-.32v-10a.34.34 0 0 1 .33-.34c.08 0 .15.03.21.08l7.34 6a.33.33 0 0 1-.21.59h-4.49l-2.57 3.85a.35.35 0 0 1-.28.14z"}]]];const GM=["svg",a,[["path",{d:"M7 22a5 5 0 0 1-2-4"}],["path",{d:"M3.3 14A6.8 6.8 0 0 1 2 10c0-4.4 4.5-8 10-8s10 3.6 10 8-4.5 8-10 8a12 12 0 0 1-5-1"}],["path",{d:"M5 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"}]]];const WM=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M18 13a6 6 0 0 1-6 5 6 6 0 0 1-6-5h12Z"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}]]];const XM=["svg",a,[["path",{d:"m16.02 12 5.48 3.13a1 1 0 0 1 0 1.74L13 21.74a2 2 0 0 1-2 0l-8.5-4.87a1 1 0 0 1 0-1.74L7.98 12"}],["path",{d:"M13 13.74a2 2 0 0 1-2 0L2.5 8.87a1 1 0 0 1 0-1.74L11 2.26a2 2 0 0 1 2 0l8.5 4.87a1 1 0 0 1 0 1.74Z"}]]];const NM=["svg",a,[["path",{d:"m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"}],["path",{d:"m6.08 9.5-3.5 1.6a1 1 0 0 0 0 1.81l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9a1 1 0 0 0 0-1.83l-3.5-1.59"}],["path",{d:"m6.08 14.5-3.5 1.6a1 1 0 0 0 0 1.81l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9a1 1 0 0 0 0-1.83l-3.5-1.59"}]]];const KM=["svg",a,[["path",{d:"m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"}],["path",{d:"m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"}],["path",{d:"m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"}]]];const JM=["svg",a,[["rect",{width:"7",height:"9",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"5",x:"14",y:"3",rx:"1"}],["rect",{width:"7",height:"9",x:"14",y:"12",rx:"1"}],["rect",{width:"7",height:"5",x:"3",y:"16",rx:"1"}]]];const jM=["svg",a,[["rect",{width:"7",height:"7",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1"}]]];const QM=["svg",a,[["rect",{width:"7",height:"7",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1"}],["path",{d:"M14 4h7"}],["path",{d:"M14 9h7"}],["path",{d:"M14 15h7"}],["path",{d:"M14 20h7"}]]];const _M=["svg",a,[["rect",{width:"7",height:"18",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1"}]]];const YM=["svg",a,[["rect",{width:"18",height:"7",x:"3",y:"3",rx:"1"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1"}]]];const $M=["svg",a,[["rect",{width:"18",height:"7",x:"3",y:"3",rx:"1"}],["rect",{width:"9",height:"7",x:"3",y:"14",rx:"1"}],["rect",{width:"5",height:"7",x:"16",y:"14",rx:"1"}]]];const as=["svg",a,[["path",{d:"M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z"}],["path",{d:"M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12"}]]];const ts=["svg",a,[["path",{d:"M2 22c1.25-.987 2.27-1.975 3.9-2.2a5.56 5.56 0 0 1 3.8 1.5 4 4 0 0 0 6.187-2.353 3.5 3.5 0 0 0 3.69-5.116A3.5 3.5 0 0 0 20.95 8 3.5 3.5 0 1 0 16 3.05a3.5 3.5 0 0 0-5.831 1.373 3.5 3.5 0 0 0-5.116 3.69 4 4 0 0 0-2.348 6.155C3.499 15.42 4.409 16.712 4.2 18.1 3.926 19.743 3.014 20.732 2 22"}],["path",{d:"M2 22 17 7"}]]];const hs=["svg",a,[["path",{d:"M16 12h3a2 2 0 0 0 1.902-1.38l1.056-3.333A1 1 0 0 0 21 6H3a1 1 0 0 0-.958 1.287l1.056 3.334A2 2 0 0 0 5 12h3"}],["path",{d:"M18 6V3a1 1 0 0 0-1-1h-3"}],["rect",{width:"8",height:"12",x:"8",y:"10",rx:"1"}]]];const ds=["svg",a,[["path",{d:"M15 12h6"}],["path",{d:"M15 6h6"}],["path",{d:"m3 13 3.553-7.724a.5.5 0 0 1 .894 0L11 13"}],["path",{d:"M3 18h18"}],["path",{d:"M4 11h6"}]]];const ps=["svg",a,[["rect",{width:"8",height:"18",x:"3",y:"3",rx:"1"}],["path",{d:"M7 3v18"}],["path",{d:"M20.4 18.9c.2.5-.1 1.1-.6 1.3l-1.9.7c-.5.2-1.1-.1-1.3-.6L11.1 5.1c-.2-.5.1-1.1.6-1.3l1.9-.7c.5-.2 1.1.1 1.3.6Z"}]]];const cs=["svg",a,[["path",{d:"m16 6 4 14"}],["path",{d:"M12 6v14"}],["path",{d:"M8 8v12"}],["path",{d:"M4 4v16"}]]];const Ms=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"m4.93 4.93 4.24 4.24"}],["path",{d:"m14.83 9.17 4.24-4.24"}],["path",{d:"m14.83 14.83 4.24 4.24"}],["path",{d:"m9.17 14.83-4.24 4.24"}],["circle",{cx:"12",cy:"12",r:"4"}]]];const ss=["svg",a,[["path",{d:"M8 20V8c0-2.2 1.8-4 4-4 1.5 0 2.8.8 3.5 2"}],["path",{d:"M6 12h4"}],["path",{d:"M14 12h2v8"}],["path",{d:"M6 20h4"}],["path",{d:"M14 20h4"}]]];const es=["svg",a,[["path",{d:"M16.8 11.2c.8-.9 1.2-2 1.2-3.2a6 6 0 0 0-9.3-5"}],["path",{d:"m2 2 20 20"}],["path",{d:"M6.3 6.3a4.67 4.67 0 0 0 1.2 5.2c.7.7 1.3 1.5 1.5 2.5"}],["path",{d:"M9 18h6"}],["path",{d:"M10 22h4"}]]];const rs=["svg",a,[["path",{d:"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"}],["path",{d:"M9 18h6"}],["path",{d:"M10 22h4"}]]];const vs=["svg",a,[["path",{d:"M9 17H7A5 5 0 0 1 7 7"}],["path",{d:"M15 7h2a5 5 0 0 1 4 8"}],["line",{x1:"8",x2:"12",y1:"12",y2:"12"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const ns=["svg",a,[["path",{d:"M9 17H7A5 5 0 0 1 7 7h2"}],["path",{d:"M15 7h2a5 5 0 1 1 0 10h-2"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12"}]]];const os=["svg",a,[["path",{d:"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"}],["path",{d:"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"}]]];const is=["svg",a,[["path",{d:"M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"}],["rect",{width:"4",height:"12",x:"2",y:"9"}],["circle",{cx:"4",cy:"4",r:"2"}]]];const ls=["svg",a,[["path",{d:"M11 18H3"}],["path",{d:"m15 18 2 2 4-4"}],["path",{d:"M16 12H3"}],["path",{d:"M16 6H3"}]]];const gs=["svg",a,[["path",{d:"m3 17 2 2 4-4"}],["path",{d:"m3 7 2 2 4-4"}],["path",{d:"M13 6h8"}],["path",{d:"M13 12h8"}],["path",{d:"M13 18h8"}]]];const xs=["svg",a,[["path",{d:"m3 10 2.5-2.5L3 5"}],["path",{d:"m3 19 2.5-2.5L3 14"}],["path",{d:"M10 6h11"}],["path",{d:"M10 12h11"}],["path",{d:"M10 18h11"}]]];const ys=["svg",a,[["path",{d:"M16 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M10 18H3"}],["path",{d:"M21 6v10a2 2 0 0 1-2 2h-5"}],["path",{d:"m16 16-2 2 2 2"}]]];const ms=["svg",a,[["path",{d:"M3 6h18"}],["path",{d:"M7 12h10"}],["path",{d:"M10 18h4"}]]];const Hs=["svg",a,[["path",{d:"M11 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M16 18H3"}],["path",{d:"M21 12h-6"}]]];const Vs=["svg",a,[["path",{d:"M21 15V6"}],["path",{d:"M18.5 18a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z"}],["path",{d:"M12 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M12 18H3"}]]];const Cs=["svg",a,[["line",{x1:"10",x2:"21",y1:"6",y2:"6"}],["line",{x1:"10",x2:"21",y1:"12",y2:"12"}],["line",{x1:"10",x2:"21",y1:"18",y2:"18"}],["path",{d:"M4 6h1v4"}],["path",{d:"M4 10h2"}],["path",{d:"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"}]]];const ws=["svg",a,[["path",{d:"M11 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M16 18H3"}],["path",{d:"M18 9v6"}],["path",{d:"M21 12h-6"}]]];const us=["svg",a,[["path",{d:"M21 6H3"}],["path",{d:"M7 12H3"}],["path",{d:"M7 18H3"}],["path",{d:"M12 18a5 5 0 0 0 9-3 4.5 4.5 0 0 0-4.5-4.5c-1.33 0-2.54.54-3.41 1.41L11 14"}],["path",{d:"M11 10v4h4"}]]];const As=["svg",a,[["path",{d:"M16 12H3"}],["path",{d:"M16 18H3"}],["path",{d:"M10 6H3"}],["path",{d:"M21 18V8a2 2 0 0 0-2-2h-5"}],["path",{d:"m16 8-2-2 2-2"}]]];const Ls=["svg",a,[["rect",{x:"3",y:"5",width:"6",height:"6",rx:"1"}],["path",{d:"m3 17 2 2 4-4"}],["path",{d:"M13 6h8"}],["path",{d:"M13 12h8"}],["path",{d:"M13 18h8"}]]];const Ss=["svg",a,[["path",{d:"M21 12h-8"}],["path",{d:"M21 6H8"}],["path",{d:"M21 18h-8"}],["path",{d:"M3 6v4c0 1.1.9 2 2 2h3"}],["path",{d:"M3 10v6c0 1.1.9 2 2 2h3"}]]];const fs=["svg",a,[["path",{d:"M12 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M12 18H3"}],["path",{d:"m16 12 5 3-5 3v-6Z"}]]];const Zs=["svg",a,[["path",{d:"M11 12H3"}],["path",{d:"M16 6H3"}],["path",{d:"M16 18H3"}],["path",{d:"m19 10-4 4"}],["path",{d:"m15 10 4 4"}]]];const Ps=["svg",a,[["line",{x1:"8",x2:"21",y1:"6",y2:"6"}],["line",{x1:"8",x2:"21",y1:"12",y2:"12"}],["line",{x1:"8",x2:"21",y1:"18",y2:"18"}],["line",{x1:"3",x2:"3.01",y1:"6",y2:"6"}],["line",{x1:"3",x2:"3.01",y1:"12",y2:"12"}],["line",{x1:"3",x2:"3.01",y1:"18",y2:"18"}]]];const _1=["svg",a,[["path",{d:"M21 12a9 9 0 1 1-6.219-8.56"}]]];const ks=["svg",a,[["path",{d:"M2 12c0-2.8 2.2-5 5-5s5 2.2 5 5 2.2 5 5 5 5-2.2 5-5"}],["path",{d:"M7 20.7a1 1 0 1 1 5-8.7 1 1 0 1 0 5-8.6"}],["path",{d:"M7 3.3a1 1 0 1 1 5 8.6 1 1 0 1 0 5 8.6"}],["circle",{cx:"12",cy:"12",r:"10"}]]];const zs=["svg",a,[["path",{d:"M12 2v4"}],["path",{d:"m16.2 7.8 2.9-2.9"}],["path",{d:"M18 12h4"}],["path",{d:"m16.2 16.2 2.9 2.9"}],["path",{d:"M12 18v4"}],["path",{d:"m4.9 19.1 2.9-2.9"}],["path",{d:"M2 12h4"}],["path",{d:"m4.9 4.9 2.9 2.9"}]]];const Bs=["svg",a,[["line",{x1:"2",x2:"5",y1:"12",y2:"12"}],["line",{x1:"19",x2:"22",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"2",y2:"5"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}],["circle",{cx:"12",cy:"12",r:"7"}],["circle",{cx:"12",cy:"12",r:"3"}]]];const Fs=["svg",a,[["line",{x1:"2",x2:"5",y1:"12",y2:"12"}],["line",{x1:"19",x2:"22",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"2",y2:"5"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}],["path",{d:"M7.11 7.11C5.83 8.39 5 10.1 5 12c0 3.87 3.13 7 7 7 1.9 0 3.61-.83 4.89-2.11"}],["path",{d:"M18.71 13.96c.19-.63.29-1.29.29-1.96 0-3.87-3.13-7-7-7-.67 0-1.33.1-1.96.29"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const Ds=["svg",a,[["line",{x1:"2",x2:"5",y1:"12",y2:"12"}],["line",{x1:"19",x2:"22",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"2",y2:"5"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}],["circle",{cx:"12",cy:"12",r:"7"}]]];const Y1=["svg",a,[["circle",{cx:"12",cy:"16",r:"1"}],["rect",{width:"18",height:"12",x:"3",y:"10",rx:"2"}],["path",{d:"M7 10V7a5 5 0 0 1 9.33-2.5"}]]];const qs=["svg",a,[["circle",{cx:"12",cy:"16",r:"1"}],["rect",{x:"3",y:"10",width:"18",height:"12",rx:"2"}],["path",{d:"M7 10V7a5 5 0 0 1 10 0v3"}]]];const $1=["svg",a,[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2"}],["path",{d:"M7 11V7a5 5 0 0 1 9.9-1"}]]];const Rs=["svg",a,[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4"}]]];const bs=["svg",a,[["path",{d:"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"}],["polyline",{points:"10 17 15 12 10 7"}],["line",{x1:"15",x2:"3",y1:"12",y2:"12"}]]];const Ts=["svg",a,[["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"}],["polyline",{points:"16 17 21 12 16 7"}],["line",{x1:"21",x2:"9",y1:"12",y2:"12"}]]];const Us=["svg",a,[["path",{d:"M13 12h8"}],["path",{d:"M13 18h8"}],["path",{d:"M13 6h8"}],["path",{d:"M3 12h1"}],["path",{d:"M3 18h1"}],["path",{d:"M3 6h1"}],["path",{d:"M8 12h1"}],["path",{d:"M8 18h1"}],["path",{d:"M8 6h1"}]]];const Os=["svg",a,[["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}],["path",{d:"M11 11a2 2 0 0 0 4 0 4 4 0 0 0-8 0 6 6 0 0 0 12 0"}]]];const Is=["svg",a,[["path",{d:"M6 20a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2"}],["path",{d:"M8 18V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v14"}],["path",{d:"M10 20h4"}],["circle",{cx:"16",cy:"20",r:"2"}],["circle",{cx:"8",cy:"20",r:"2"}]]];const Es=["svg",a,[["path",{d:"m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15"}],["path",{d:"m5 8 4 4"}],["path",{d:"m12 15 4 4"}]]];const Gs=["svg",a,[["path",{d:"M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"m16 19 2 2 4-4"}]]];const Ws=["svg",a,[["path",{d:"M22 15V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M16 19h6"}]]];const Xs=["svg",a,[["path",{d:"M21.2 8.4c.5.38.8.97.8 1.6v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V10a2 2 0 0 1 .8-1.6l8-6a2 2 0 0 1 2.4 0l8 6Z"}],["path",{d:"m22 10-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 10"}]]];const Ns=["svg",a,[["path",{d:"M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h8"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M19 16v6"}],["path",{d:"M16 19h6"}]]];const Ks=["svg",a,[["path",{d:"M22 10.5V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h12.5"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M18 15.28c.2-.4.5-.8.9-1a2.1 2.1 0 0 1 2.6.4c.3.4.5.8.5 1.3 0 1.3-2 2-2 2"}],["path",{d:"M20 22v.01"}]]];const Js=["svg",a,[["path",{d:"M22 12.5V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h7.5"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M18 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"}],["circle",{cx:"18",cy:"18",r:"3"}],["path",{d:"m22 22-1.5-1.5"}]]];const js=["svg",a,[["path",{d:"M22 10.5V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h12.5"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"M20 14v4"}],["path",{d:"M20 22v.01"}]]];const Qs=["svg",a,[["path",{d:"M22 13V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h9"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}],["path",{d:"m17 17 4 4"}],["path",{d:"m21 17-4 4"}]]];const _s=["svg",a,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"}]]];const Ys=["svg",a,[["path",{d:"M22 17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9.5C2 7 4 5 6.5 5H18c2.2 0 4 1.8 4 4v8Z"}],["polyline",{points:"15,9 18,9 18,11"}],["path",{d:"M6.5 5C9 5 11 7 11 9.5V17a2 2 0 0 1-2 2"}],["line",{x1:"6",x2:"7",y1:"10",y2:"10"}]]];const $s=["svg",a,[["rect",{width:"16",height:"13",x:"6",y:"4",rx:"2"}],["path",{d:"m22 7-7.1 3.78c-.57.3-1.23.3-1.8 0L6 7"}],["path",{d:"M2 8v11c0 1.1.9 2 2 2h14"}]]];const ae=["svg",a,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["path",{d:"m9 10 2 2 4-4"}]]];const te=["svg",a,[["path",{d:"M19.43 12.935c.357-.967.57-1.955.57-2.935a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 1.202 0 32.197 32.197 0 0 0 .813-.728"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"m16 18 2 2 4-4"}]]];const he=["svg",a,[["path",{d:"M15 22a1 1 0 0 1-1-1v-4a1 1 0 0 1 .445-.832l3-2a1 1 0 0 1 1.11 0l3 2A1 1 0 0 1 22 17v4a1 1 0 0 1-1 1z"}],["path",{d:"M18 10a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 .601.2"}],["path",{d:"M18 22v-3"}],["circle",{cx:"10",cy:"10",r:"3"}]]];const de=["svg",a,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["path",{d:"M9 10h6"}]]];const pe=["svg",a,[["path",{d:"M18.977 14C19.6 12.701 20 11.343 20 10a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 1.202 0 32 32 0 0 0 .824-.738"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M16 18h6"}]]];const ce=["svg",a,[["path",{d:"M12.75 7.09a3 3 0 0 1 2.16 2.16"}],["path",{d:"M17.072 17.072c-1.634 2.17-3.527 3.912-4.471 4.727a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 1.432-4.568"}],["path",{d:"m2 2 20 20"}],["path",{d:"M8.475 2.818A8 8 0 0 1 20 10c0 1.183-.31 2.377-.81 3.533"}],["path",{d:"M9.13 9.13a3 3 0 0 0 3.74 3.74"}]]];const Me=["svg",a,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["path",{d:"M12 7v6"}],["path",{d:"M9 10h6"}]]];const se=["svg",a,[["path",{d:"M19.914 11.105A7.298 7.298 0 0 0 20 10a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 1.202 0 32 32 0 0 0 .824-.738"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M16 18h6"}],["path",{d:"M19 15v6"}]]];const ee=["svg",a,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["path",{d:"m14.5 7.5-5 5"}],["path",{d:"m9.5 7.5 5 5"}]]];const re=["svg",a,[["path",{d:"M19.752 11.901A7.78 7.78 0 0 0 20 10a8 8 0 0 0-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 0 0 1.202 0 19 19 0 0 0 .09-.077"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"m21.5 15.5-5 5"}],["path",{d:"m21.5 20.5-5-5"}]]];const ve=["svg",a,[["path",{d:"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"}],["circle",{cx:"12",cy:"10",r:"3"}]]];const ne=["svg",a,[["path",{d:"M18 8c0 3.613-3.869 7.429-5.393 8.795a1 1 0 0 1-1.214 0C9.87 15.429 6 11.613 6 8a6 6 0 0 1 12 0"}],["circle",{cx:"12",cy:"8",r:"2"}],["path",{d:"M8.714 14h-3.71a1 1 0 0 0-.948.683l-2.004 6A1 1 0 0 0 3 22h18a1 1 0 0 0 .948-1.316l-2-6a1 1 0 0 0-.949-.684h-3.712"}]]];const oe=["svg",a,[["path",{d:"M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z"}],["path",{d:"M15 5.764v15"}],["path",{d:"M9 3.236v15"}]]];const ie=["svg",a,[["path",{d:"M8 22h8"}],["path",{d:"M12 11v11"}],["path",{d:"m19 3-7 8-7-8Z"}]]];const le=["svg",a,[["polyline",{points:"15 3 21 3 21 9"}],["polyline",{points:"9 21 3 21 3 15"}],["line",{x1:"21",x2:"14",y1:"3",y2:"10"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14"}]]];const ge=["svg",a,[["path",{d:"M8 3H5a2 2 0 0 0-2 2v3"}],["path",{d:"M21 8V5a2 2 0 0 0-2-2h-3"}],["path",{d:"M3 16v3a2 2 0 0 0 2 2h3"}],["path",{d:"M16 21h3a2 2 0 0 0 2-2v-3"}]]];const xe=["svg",a,[["path",{d:"M7.21 15 2.66 7.14a2 2 0 0 1 .13-2.2L4.4 2.8A2 2 0 0 1 6 2h12a2 2 0 0 1 1.6.8l1.6 2.14a2 2 0 0 1 .14 2.2L16.79 15"}],["path",{d:"M11 12 5.12 2.2"}],["path",{d:"m13 12 5.88-9.8"}],["path",{d:"M8 7h8"}],["circle",{cx:"12",cy:"17",r:"5"}],["path",{d:"M12 18v-2h-.5"}]]];const ye=["svg",a,[["path",{d:"M9.26 9.26 3 11v3l14.14 3.14"}],["path",{d:"M21 15.34V6l-7.31 2.03"}],["path",{d:"M11.6 16.8a3 3 0 1 1-5.8-1.6"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const me=["svg",a,[["path",{d:"m3 11 18-5v12L3 14v-3z"}],["path",{d:"M11.6 16.8a3 3 0 1 1-5.8-1.6"}]]];const He=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["line",{x1:"8",x2:"16",y1:"15",y2:"15"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}]]];const Ve=["svg",a,[["path",{d:"M6 19v-3"}],["path",{d:"M10 19v-3"}],["path",{d:"M14 19v-3"}],["path",{d:"M18 19v-3"}],["path",{d:"M8 11V9"}],["path",{d:"M16 11V9"}],["path",{d:"M12 11V9"}],["path",{d:"M2 15h20"}],["path",{d:"M2 7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v1.1a2 2 0 0 0 0 3.837V17a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-5.1a2 2 0 0 0 0-3.837Z"}]]];const Ce=["svg",a,[["line",{x1:"4",x2:"20",y1:"12",y2:"12"}],["line",{x1:"4",x2:"20",y1:"6",y2:"6"}],["line",{x1:"4",x2:"20",y1:"18",y2:"18"}]]];const we=["svg",a,[["path",{d:"m8 6 4-4 4 4"}],["path",{d:"M12 2v10.3a4 4 0 0 1-1.172 2.872L4 22"}],["path",{d:"m20 22-5-5"}]]];const ue=["svg",a,[["path",{d:"M10 9.5 8 12l2 2.5"}],["path",{d:"m14 9.5 2 2.5-2 2.5"}],["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22z"}]]];const Ae=["svg",a,[["path",{d:"M13.5 3.1c-.5 0-1-.1-1.5-.1s-1 .1-1.5.1"}],["path",{d:"M19.3 6.8a10.45 10.45 0 0 0-2.1-2.1"}],["path",{d:"M20.9 13.5c.1-.5.1-1 .1-1.5s-.1-1-.1-1.5"}],["path",{d:"M17.2 19.3a10.45 10.45 0 0 0 2.1-2.1"}],["path",{d:"M10.5 20.9c.5.1 1 .1 1.5.1s1-.1 1.5-.1"}],["path",{d:"M3.5 17.5 2 22l4.5-1.5"}],["path",{d:"M3.1 10.5c0 .5-.1 1-.1 1.5s.1 1 .1 1.5"}],["path",{d:"M6.8 4.7a10.45 10.45 0 0 0-2.1 2.1"}]]];const Le=["svg",a,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M15.8 9.2a2.5 2.5 0 0 0-3.5 0l-.3.4-.35-.3a2.42 2.42 0 1 0-3.2 3.6l3.6 3.5 3.6-3.5c1.2-1.2 1.1-2.7.2-3.7"}]]];const Se=["svg",a,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M8 12h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M16 12h.01"}]]];const fe=["svg",a,[["path",{d:"M20.5 14.9A9 9 0 0 0 9.1 3.5"}],["path",{d:"m2 2 20 20"}],["path",{d:"M5.6 5.6C3 8.3 2.2 12.5 4 16l-2 6 6-2c3.4 1.8 7.6 1.1 10.3-1.7"}]]];const Ze=["svg",a,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M8 12h8"}],["path",{d:"M12 8v8"}]]];const Pe=["svg",a,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"}],["path",{d:"M12 17h.01"}]]];const ke=["svg",a,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"m10 15-3-3 3-3"}],["path",{d:"M7 12h7a2 2 0 0 1 2 2v1"}]]];const ze=["svg",a,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"M12 8v4"}],["path",{d:"M12 16h.01"}]]];const Be=["svg",a,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}],["path",{d:"m15 9-6 6"}],["path",{d:"m9 9 6 6"}]]];const Fe=["svg",a,[["path",{d:"M7.9 20A9 9 0 1 0 4 16.1L2 22Z"}]]];const De=["svg",a,[["path",{d:"M10 7.5 8 10l2 2.5"}],["path",{d:"m14 7.5 2 2.5-2 2.5"}],["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}]]];const qe=["svg",a,[["path",{d:"M3 6V5c0-1.1.9-2 2-2h2"}],["path",{d:"M11 3h3"}],["path",{d:"M18 3h1c1.1 0 2 .9 2 2"}],["path",{d:"M21 9v2"}],["path",{d:"M21 15c0 1.1-.9 2-2 2h-1"}],["path",{d:"M14 17h-3"}],["path",{d:"m7 17-4 4v-5"}],["path",{d:"M3 12v-2"}]]];const Re=["svg",a,[["path",{d:"m5 19-2 2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2"}],["path",{d:"M9 10h6"}],["path",{d:"M12 7v6"}],["path",{d:"M9 17h6"}]]];const be=["svg",a,[["path",{d:"M11.7 3H5a2 2 0 0 0-2 2v16l4-4h12a2 2 0 0 0 2-2v-2.7"}],["circle",{cx:"18",cy:"6",r:"3"}]]];const Te=["svg",a,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M14.8 7.5a1.84 1.84 0 0 0-2.6 0l-.2.3-.3-.3a1.84 1.84 0 1 0-2.4 2.8L12 13l2.7-2.7c.9-.9.8-2.1.1-2.8"}]]];const Ue=["svg",a,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M8 10h.01"}],["path",{d:"M12 10h.01"}],["path",{d:"M16 10h.01"}]]];const Oe=["svg",a,[["path",{d:"M21 15V5a2 2 0 0 0-2-2H9"}],["path",{d:"m2 2 20 20"}],["path",{d:"M3.6 3.6c-.4.3-.6.8-.6 1.4v16l4-4h10"}]]];const Ie=["svg",a,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M12 7v6"}],["path",{d:"M9 10h6"}]]];const Ee=["svg",a,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M8 12a2 2 0 0 0 2-2V8H8"}],["path",{d:"M14 12a2 2 0 0 0 2-2V8h-2"}]]];const Ge=["svg",a,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"m10 7-3 3 3 3"}],["path",{d:"M17 13v-1a2 2 0 0 0-2-2H7"}]]];const We=["svg",a,[["path",{d:"M21 12v3a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h7"}],["path",{d:"M16 3h5v5"}],["path",{d:"m16 8 5-5"}]]];const Xe=["svg",a,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M13 8H7"}],["path",{d:"M17 12H7"}]]];const Ne=["svg",a,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"M12 7v2"}],["path",{d:"M12 13h.01"}]]];const Ke=["svg",a,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}],["path",{d:"m14.5 7.5-5 5"}],["path",{d:"m9.5 7.5 5 5"}]]];const Je=["svg",a,[["path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"}]]];const je=["svg",a,[["path",{d:"M14 9a2 2 0 0 1-2 2H6l-4 4V4c0-1.1.9-2 2-2h8a2 2 0 0 1 2 2z"}],["path",{d:"M18 9h2a2 2 0 0 1 2 2v11l-4-4h-6a2 2 0 0 1-2-2v-1"}]]];const Qe=["svg",a,[["line",{x1:"2",x2:"22",y1:"2",y2:"22"}],["path",{d:"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2"}],["path",{d:"M5 10v2a7 7 0 0 0 12 5"}],["path",{d:"M15 9.34V5a3 3 0 0 0-5.68-1.33"}],["path",{d:"M9 9v3a3 3 0 0 0 5.12 2.12"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}]]];const a2=["svg",a,[["path",{d:"m11 7.601-5.994 8.19a1 1 0 0 0 .1 1.298l.817.818a1 1 0 0 0 1.314.087L15.09 12"}],["path",{d:"M16.5 21.174C15.5 20.5 14.372 20 13 20c-2.058 0-3.928 2.356-6 2-2.072-.356-2.775-3.369-1.5-4.5"}],["circle",{cx:"16",cy:"7",r:"5"}]]];const _e=["svg",a,[["path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"}],["path",{d:"M19 10v2a7 7 0 0 1-14 0v-2"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22"}]]];const Ye=["svg",a,[["path",{d:"M18 12h2"}],["path",{d:"M18 16h2"}],["path",{d:"M18 20h2"}],["path",{d:"M18 4h2"}],["path",{d:"M18 8h2"}],["path",{d:"M4 12h2"}],["path",{d:"M4 16h2"}],["path",{d:"M4 20h2"}],["path",{d:"M4 4h2"}],["path",{d:"M4 8h2"}],["path",{d:"M8 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-1.5c-.276 0-.494.227-.562.495a2 2 0 0 1-3.876 0C9.994 2.227 9.776 2 9.5 2z"}]]];const $e=["svg",a,[["path",{d:"M6 18h8"}],["path",{d:"M3 22h18"}],["path",{d:"M14 22a7 7 0 1 0 0-14h-1"}],["path",{d:"M9 14h2"}],["path",{d:"M9 12a2 2 0 0 1-2-2V6h6v4a2 2 0 0 1-2 2Z"}],["path",{d:"M12 6V3a1 1 0 0 0-1-1H9a1 1 0 0 0-1 1v3"}]]];const a9=["svg",a,[["rect",{width:"20",height:"15",x:"2",y:"4",rx:"2"}],["rect",{width:"8",height:"7",x:"6",y:"8",rx:"1"}],["path",{d:"M18 8v7"}],["path",{d:"M6 19v2"}],["path",{d:"M18 19v2"}]]];const t9=["svg",a,[["path",{d:"M18 6H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h13l4-3.5L18 6Z"}],["path",{d:"M12 13v8"}],["path",{d:"M12 3v3"}]]];const h9=["svg",a,[["path",{d:"M8 2h8"}],["path",{d:"M9 2v1.343M15 2v2.789a4 4 0 0 0 .672 2.219l.656.984a4 4 0 0 1 .672 2.22v1.131M7.8 7.8l-.128.192A4 4 0 0 0 7 10.212V20a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2v-3"}],["path",{d:"M7 15a6.47 6.47 0 0 1 5 0 6.472 6.472 0 0 0 3.435.435"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const d9=["svg",a,[["path",{d:"M8 2h8"}],["path",{d:"M9 2v2.789a4 4 0 0 1-.672 2.219l-.656.984A4 4 0 0 0 7 10.212V20a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2v-9.789a4 4 0 0 0-.672-2.219l-.656-.984A4 4 0 0 1 15 4.788V2"}],["path",{d:"M7 15a6.472 6.472 0 0 1 5 0 6.47 6.47 0 0 0 5 0"}]]];const p9=["svg",a,[["polyline",{points:"4 14 10 14 10 20"}],["polyline",{points:"20 10 14 10 14 4"}],["line",{x1:"14",x2:"21",y1:"10",y2:"3"}],["line",{x1:"3",x2:"10",y1:"21",y2:"14"}]]];const c9=["svg",a,[["path",{d:"M8 3v3a2 2 0 0 1-2 2H3"}],["path",{d:"M21 8h-3a2 2 0 0 1-2-2V3"}],["path",{d:"M3 16h3a2 2 0 0 1 2 2v3"}],["path",{d:"M16 21v-3a2 2 0 0 1 2-2h3"}]]];const M9=["svg",a,[["path",{d:"M5 12h14"}]]];const s9=["svg",a,[["path",{d:"m9 10 2 2 4-4"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]];const e9=["svg",a,[["path",{d:"M12 17v4"}],["path",{d:"m15.2 4.9-.9-.4"}],["path",{d:"m15.2 7.1-.9.4"}],["path",{d:"m16.9 3.2-.4-.9"}],["path",{d:"m16.9 8.8-.4.9"}],["path",{d:"m19.5 2.3-.4.9"}],["path",{d:"m19.5 9.7-.4-.9"}],["path",{d:"m21.7 4.5-.9.4"}],["path",{d:"m21.7 7.5-.9-.4"}],["path",{d:"M22 13v2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"}],["path",{d:"M8 21h8"}],["circle",{cx:"18",cy:"6",r:"3"}]]];const r9=["svg",a,[["circle",{cx:"19",cy:"6",r:"3"}],["path",{d:"M22 12v3a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h9"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]];const v9=["svg",a,[["path",{d:"M12 13V7"}],["path",{d:"m15 10-3 3-3-3"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]];const n9=["svg",a,[["path",{d:"M17 17H4a2 2 0 0 1-2-2V5c0-1.5 1-2 1-2"}],["path",{d:"M22 15V5a2 2 0 0 0-2-2H9"}],["path",{d:"M8 21h8"}],["path",{d:"M12 17v4"}],["path",{d:"m2 2 20 20"}]]];const o9=["svg",a,[["path",{d:"M10 13V7"}],["path",{d:"M14 13V7"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]];const i9=["svg",a,[["path",{d:"M10 7.75a.75.75 0 0 1 1.142-.638l3.664 2.249a.75.75 0 0 1 0 1.278l-3.664 2.25a.75.75 0 0 1-1.142-.64z"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}],["rect",{x:"2",y:"3",width:"20",height:"14",rx:"2"}]]];const l9=["svg",a,[["path",{d:"M18 8V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h8"}],["path",{d:"M10 19v-3.96 3.15"}],["path",{d:"M7 19h5"}],["rect",{width:"6",height:"10",x:"16",y:"12",rx:"2"}]]];const g9=["svg",a,[["path",{d:"M5.5 20H8"}],["path",{d:"M17 9h.01"}],["rect",{width:"10",height:"16",x:"12",y:"4",rx:"2"}],["path",{d:"M8 6H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h4"}],["circle",{cx:"17",cy:"15",r:"1"}]]];const x9=["svg",a,[["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}],["rect",{x:"2",y:"3",width:"20",height:"14",rx:"2"}],["rect",{x:"9",y:"7",width:"6",height:"6",rx:"1"}]]];const y9=["svg",a,[["path",{d:"m9 10 3-3 3 3"}],["path",{d:"M12 13V7"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]];const m9=["svg",a,[["path",{d:"m14.5 12.5-5-5"}],["path",{d:"m9.5 12.5 5-5"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["path",{d:"M12 17v4"}],["path",{d:"M8 21h8"}]]];const H9=["svg",a,[["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}],["line",{x1:"8",x2:"16",y1:"21",y2:"21"}],["line",{x1:"12",x2:"12",y1:"17",y2:"21"}]]];const V9=["svg",a,[["path",{d:"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9"}],["path",{d:"M20 3v4"}],["path",{d:"M22 5h-4"}]]];const C9=["svg",a,[["path",{d:"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"}]]];const w9=["svg",a,[["path",{d:"m8 3 4 8 5-5 5 15H2L8 3z"}],["path",{d:"M4.14 15.08c2.62-1.57 5.24-1.43 7.86.42 2.74 1.94 5.49 2 8.23.19"}]]];const u9=["svg",a,[["path",{d:"m8 3 4 8 5-5 5 15H2L8 3z"}]]];const A9=["svg",a,[["path",{d:"M12 6v.343"}],["path",{d:"M18.218 18.218A7 7 0 0 1 5 15V9a7 7 0 0 1 .782-3.218"}],["path",{d:"M19 13.343V9A7 7 0 0 0 8.56 2.902"}],["path",{d:"M22 22 2 2"}]]];const L9=["svg",a,[["path",{d:"M4.037 4.688a.495.495 0 0 1 .651-.651l16 6.5a.5.5 0 0 1-.063.947l-6.124 1.58a2 2 0 0 0-1.438 1.435l-1.579 6.126a.5.5 0 0 1-.947.063z"}]]];const S9=["svg",a,[["path",{d:"M2.034 2.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.944L8.204 7.545a1 1 0 0 0-.66.66l-1.066 3.443a.5.5 0 0 1-.944.033z"}],["circle",{cx:"16",cy:"16",r:"6"}],["path",{d:"m11.8 11.8 8.4 8.4"}]]];const f9=["svg",a,[["path",{d:"M14 4.1 12 6"}],["path",{d:"m5.1 8-2.9-.8"}],["path",{d:"m6 12-1.9 2"}],["path",{d:"M7.2 2.2 8 5.1"}],["path",{d:"M9.037 9.69a.498.498 0 0 1 .653-.653l11 4.5a.5.5 0 0 1-.074.949l-4.349 1.041a1 1 0 0 0-.74.739l-1.04 4.35a.5.5 0 0 1-.95.074z"}]]];const Z9=["svg",a,[["path",{d:"M12.586 12.586 19 19"}],["path",{d:"M3.688 3.037a.497.497 0 0 0-.651.651l6.5 15.999a.501.501 0 0 0 .947-.062l1.569-6.083a2 2 0 0 1 1.448-1.479l6.124-1.579a.5.5 0 0 0 .063-.947z"}]]];const P9=["svg",a,[["rect",{x:"5",y:"2",width:"14",height:"20",rx:"7"}],["path",{d:"M12 6v4"}]]];const t2=["svg",a,[["path",{d:"M5 3v16h16"}],["path",{d:"m5 19 6-6"}],["path",{d:"m2 6 3-3 3 3"}],["path",{d:"m18 16 3 3-3 3"}]]];const k9=["svg",a,[["polyline",{points:"5 11 5 5 11 5"}],["polyline",{points:"19 13 19 19 13 19"}],["line",{x1:"5",x2:"19",y1:"5",y2:"19"}]]];const z9=["svg",a,[["polyline",{points:"13 5 19 5 19 11"}],["polyline",{points:"11 19 5 19 5 13"}],["line",{x1:"19",x2:"5",y1:"5",y2:"19"}]]];const B9=["svg",a,[["path",{d:"M11 19H5V13"}],["path",{d:"M19 5L5 19"}]]];const F9=["svg",a,[["path",{d:"M19 13V19H13"}],["path",{d:"M5 5L19 19"}]]];const D9=["svg",a,[["path",{d:"M8 18L12 22L16 18"}],["path",{d:"M12 2V22"}]]];const q9=["svg",a,[["polyline",{points:"18 8 22 12 18 16"}],["polyline",{points:"6 8 2 12 6 16"}],["line",{x1:"2",x2:"22",y1:"12",y2:"12"}]]];const R9=["svg",a,[["path",{d:"M6 8L2 12L6 16"}],["path",{d:"M2 12H22"}]]];const b9=["svg",a,[["path",{d:"M18 8L22 12L18 16"}],["path",{d:"M2 12H22"}]]];const T9=["svg",a,[["path",{d:"M5 11V5H11"}],["path",{d:"M5 5L19 19"}]]];const U9=["svg",a,[["path",{d:"M13 5H19V11"}],["path",{d:"M19 5L5 19"}]]];const O9=["svg",a,[["path",{d:"M8 6L12 2L16 6"}],["path",{d:"M12 2V22"}]]];const I9=["svg",a,[["polyline",{points:"8 18 12 22 16 18"}],["polyline",{points:"8 6 12 2 16 6"}],["line",{x1:"12",x2:"12",y1:"2",y2:"22"}]]];const E9=["svg",a,[["polyline",{points:"5 9 2 12 5 15"}],["polyline",{points:"9 5 12 2 15 5"}],["polyline",{points:"15 19 12 22 9 19"}],["polyline",{points:"19 9 22 12 19 15"}],["line",{x1:"2",x2:"22",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"2",y2:"22"}]]];const G9=["svg",a,[["circle",{cx:"8",cy:"18",r:"4"}],["path",{d:"M12 18V2l7 4"}]]];const W9=["svg",a,[["circle",{cx:"12",cy:"18",r:"4"}],["path",{d:"M16 18V2"}]]];const X9=["svg",a,[["path",{d:"M9 18V5l12-2v13"}],["path",{d:"m9 9 12-2"}],["circle",{cx:"6",cy:"18",r:"3"}],["circle",{cx:"18",cy:"16",r:"3"}]]];const N9=["svg",a,[["path",{d:"M9 18V5l12-2v13"}],["circle",{cx:"6",cy:"18",r:"3"}],["circle",{cx:"18",cy:"16",r:"3"}]]];const K9=["svg",a,[["path",{d:"M9.31 9.31 5 21l7-4 7 4-1.17-3.17"}],["path",{d:"M14.53 8.88 12 2l-1.17 3.17"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const J9=["svg",a,[["polygon",{points:"12 2 19 21 12 17 5 21 12 2"}]]];const j9=["svg",a,[["path",{d:"M8.43 8.43 3 11l8 2 2 8 2.57-5.43"}],["path",{d:"M17.39 11.73 22 2l-9.73 4.61"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const Q9=["svg",a,[["polygon",{points:"3 11 22 2 13 21 11 13 3 11"}]]];const _9=["svg",a,[["rect",{x:"16",y:"16",width:"6",height:"6",rx:"1"}],["rect",{x:"2",y:"16",width:"6",height:"6",rx:"1"}],["rect",{x:"9",y:"2",width:"6",height:"6",rx:"1"}],["path",{d:"M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"}],["path",{d:"M12 12V8"}]]];const Y9=["svg",a,[["path",{d:"M4 22h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-2 2Zm0 0a2 2 0 0 1-2-2v-9c0-1.1.9-2 2-2h2"}],["path",{d:"M18 14h-8"}],["path",{d:"M15 18h-5"}],["path",{d:"M10 6h8v4h-8V6Z"}]]];const $9=["svg",a,[["path",{d:"M6 8.32a7.43 7.43 0 0 1 0 7.36"}],["path",{d:"M9.46 6.21a11.76 11.76 0 0 1 0 11.58"}],["path",{d:"M12.91 4.1a15.91 15.91 0 0 1 .01 15.8"}],["path",{d:"M16.37 2a20.16 20.16 0 0 1 0 20"}]]];const ar=["svg",a,[["path",{d:"M13.4 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.4"}],["path",{d:"M2 6h4"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["path",{d:"M21.378 5.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}]]];const tr=["svg",a,[["path",{d:"M2 6h4"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["path",{d:"M15 2v20"}],["path",{d:"M15 7h5"}],["path",{d:"M15 12h5"}],["path",{d:"M15 17h5"}]]];const hr=["svg",a,[["path",{d:"M2 6h4"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["path",{d:"M9.5 8h5"}],["path",{d:"M9.5 12H16"}],["path",{d:"M9.5 16H14"}]]];const dr=["svg",a,[["path",{d:"M2 6h4"}],["path",{d:"M2 10h4"}],["path",{d:"M2 14h4"}],["path",{d:"M2 18h4"}],["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["path",{d:"M16 2v20"}]]];const pr=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M12 2v4"}],["path",{d:"M16 2v4"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v2"}],["path",{d:"M20 12v2"}],["path",{d:"M20 18v2a2 2 0 0 1-2 2h-1"}],["path",{d:"M13 22h-2"}],["path",{d:"M7 22H6a2 2 0 0 1-2-2v-2"}],["path",{d:"M4 14v-2"}],["path",{d:"M4 8V6a2 2 0 0 1 2-2h2"}],["path",{d:"M8 10h6"}],["path",{d:"M8 14h8"}],["path",{d:"M8 18h5"}]]];const cr=["svg",a,[["path",{d:"M8 2v4"}],["path",{d:"M12 2v4"}],["path",{d:"M16 2v4"}],["rect",{width:"16",height:"18",x:"4",y:"4",rx:"2"}],["path",{d:"M8 10h6"}],["path",{d:"M8 14h8"}],["path",{d:"M8 18h5"}]]];const Mr=["svg",a,[["path",{d:"M12 4V2"}],["path",{d:"M5 10v4a7.004 7.004 0 0 0 5.277 6.787c.412.104.802.292 1.102.592L12 22l.621-.621c.3-.3.69-.488 1.102-.592a7.01 7.01 0 0 0 4.125-2.939"}],["path",{d:"M19 10v3.343"}],["path",{d:"M12 12c-1.349-.573-1.905-1.005-2.5-2-.546.902-1.048 1.353-2.5 2-1.018-.644-1.46-1.08-2-2-1.028.71-1.69.918-3 1 1.081-1.048 1.757-2.03 2-3 .194-.776.84-1.551 1.79-2.21m11.654 5.997c.887-.457 1.28-.891 1.556-1.787 1.032.916 1.683 1.157 3 1-1.297-1.036-1.758-2.03-2-3-.5-2-4-4-8-4-.74 0-1.461.068-2.15.192"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const sr=["svg",a,[["path",{d:"M12 4V2"}],["path",{d:"M5 10v4a7.004 7.004 0 0 0 5.277 6.787c.412.104.802.292 1.102.592L12 22l.621-.621c.3-.3.69-.488 1.102-.592A7.003 7.003 0 0 0 19 14v-4"}],["path",{d:"M12 4C8 4 4.5 6 4 8c-.243.97-.919 1.952-2 3 1.31-.082 1.972-.29 3-1 .54.92.982 1.356 2 2 1.452-.647 1.954-1.098 2.5-2 .595.995 1.151 1.427 2.5 2 1.31-.621 1.862-1.058 2.5-2 .629.977 1.162 1.423 2.5 2 1.209-.548 1.68-.967 2-2 1.032.916 1.683 1.157 3 1-1.297-1.036-1.758-2.03-2-3-.5-2-4-4-8-4Z"}]]];const h2=["svg",a,[["path",{d:"M12 16h.01"}],["path",{d:"M12 8v4"}],["path",{d:"M15.312 2a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z"}]]];const d2=["svg",a,[["path",{d:"M10 15V9"}],["path",{d:"M14 15V9"}],["path",{d:"M2.586 16.872A2 2 0 0 1 2 15.458V8.542a2 2 0 0 1 .586-1.414l4.542-4.542A2 2 0 0 1 8.542 2h6.916a2 2 0 0 1 1.414.586l4.542 4.542A2 2 0 0 1 22 8.542v6.916a2 2 0 0 1-.586 1.414l-4.542 4.542a2 2 0 0 1-1.414.586H8.542a2 2 0 0 1-1.414-.586z"}]]];const p2=["svg",a,[["path",{d:"m15 9-6 6"}],["path",{d:"M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z"}],["path",{d:"m9 9 6 6"}]]];const er=["svg",a,[["path",{d:"M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z"}]]];const rr=["svg",a,[["path",{d:"M3 20h4.5a.5.5 0 0 0 .5-.5v-.282a.52.52 0 0 0-.247-.437 8 8 0 1 1 8.494-.001.52.52 0 0 0-.247.438v.282a.5.5 0 0 0 .5.5H21"}]]];const vr=["svg",a,[["path",{d:"M3 3h6l6 18h6"}],["path",{d:"M14 3h7"}]]];const nr=["svg",a,[["circle",{cx:"12",cy:"12",r:"3"}],["circle",{cx:"19",cy:"5",r:"2"}],["circle",{cx:"5",cy:"19",r:"2"}],["path",{d:"M10.4 21.9a10 10 0 0 0 9.941-15.416"}],["path",{d:"M13.5 2.1a10 10 0 0 0-9.841 15.416"}]]];const or=["svg",a,[["path",{d:"M12 12V4a1 1 0 0 1 1-1h6.297a1 1 0 0 1 .651 1.759l-4.696 4.025"}],["path",{d:"m12 21-7.414-7.414A2 2 0 0 1 4 12.172V6.415a1.002 1.002 0 0 1 1.707-.707L20 20.009"}],["path",{d:"m12.214 3.381 8.414 14.966a1 1 0 0 1-.167 1.199l-1.168 1.163a1 1 0 0 1-.706.291H6.351a1 1 0 0 1-.625-.219L3.25 18.8a1 1 0 0 1 .631-1.781l4.165.027"}]]];const ir=["svg",a,[["path",{d:"M3 9h18v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9Z"}],["path",{d:"m3 9 2.45-4.9A2 2 0 0 1 7.24 3h9.52a2 2 0 0 1 1.8 1.1L21 9"}],["path",{d:"M12 3v6"}]]];const lr=["svg",a,[["path",{d:"m16 16 2 2 4-4"}],["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}]]];const gr=["svg",a,[["path",{d:"M16 16h6"}],["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}]]];const xr=["svg",a,[["path",{d:"M12 22v-9"}],["path",{d:"M15.17 2.21a1.67 1.67 0 0 1 1.63 0L21 4.57a1.93 1.93 0 0 1 0 3.36L8.82 14.79a1.655 1.655 0 0 1-1.64 0L3 12.43a1.93 1.93 0 0 1 0-3.36z"}],["path",{d:"M20 13v3.87a2.06 2.06 0 0 1-1.11 1.83l-6 3.08a1.93 1.93 0 0 1-1.78 0l-6-3.08A2.06 2.06 0 0 1 4 16.87V13"}],["path",{d:"M21 12.43a1.93 1.93 0 0 0 0-3.36L8.83 2.2a1.64 1.64 0 0 0-1.63 0L3 4.57a1.93 1.93 0 0 0 0 3.36l12.18 6.86a1.636 1.636 0 0 0 1.63 0z"}]]];const yr=["svg",a,[["path",{d:"M16 16h6"}],["path",{d:"M19 13v6"}],["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}]]];const mr=["svg",a,[["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}],["circle",{cx:"18.5",cy:"15.5",r:"2.5"}],["path",{d:"M20.27 17.27 22 19"}]]];const Hr=["svg",a,[["path",{d:"M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"}],["path",{d:"m7.5 4.27 9 5.15"}],["polyline",{points:"3.29 7 12 12 20.71 7"}],["line",{x1:"12",x2:"12",y1:"22",y2:"12"}],["path",{d:"m17 13 5 5m-5 0 5-5"}]]];const Vr=["svg",a,[["path",{d:"m7.5 4.27 9 5.15"}],["path",{d:"M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"}],["path",{d:"m3.3 7 8.7 5 8.7-5"}],["path",{d:"M12 22V12"}]]];const Cr=["svg",a,[["path",{d:"m19 11-8-8-8.6 8.6a2 2 0 0 0 0 2.8l5.2 5.2c.8.8 2 .8 2.8 0L19 11Z"}],["path",{d:"m5 2 5 5"}],["path",{d:"M2 13h15"}],["path",{d:"M22 20a2 2 0 1 1-4 0c0-1.6 1.7-2.4 2-4 .3 1.6 2 2.4 2 4Z"}]]];const wr=["svg",a,[["rect",{width:"16",height:"6",x:"2",y:"2",rx:"2"}],["path",{d:"M10 16v-2a2 2 0 0 1 2-2h8a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2"}],["rect",{width:"4",height:"6",x:"8",y:"16",rx:"1"}]]];const c2=["svg",a,[["path",{d:"M10 2v2"}],["path",{d:"M14 2v4"}],["path",{d:"M17 2a1 1 0 0 1 1 1v9H6V3a1 1 0 0 1 1-1z"}],["path",{d:"M6 12a1 1 0 0 0-1 1v1a2 2 0 0 0 2 2h2a1 1 0 0 1 1 1v2.9a2 2 0 1 0 4 0V17a1 1 0 0 1 1-1h2a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1"}]]];const ur=["svg",a,[["path",{d:"m14.622 17.897-10.68-2.913"}],["path",{d:"M18.376 2.622a1 1 0 1 1 3.002 3.002L17.36 9.643a.5.5 0 0 0 0 .707l.944.944a2.41 2.41 0 0 1 0 3.408l-.944.944a.5.5 0 0 1-.707 0L8.354 7.348a.5.5 0 0 1 0-.707l.944-.944a2.41 2.41 0 0 1 3.408 0l.944.944a.5.5 0 0 0 .707 0z"}],["path",{d:"M9 8c-1.804 2.71-3.97 3.46-6.583 3.948a.507.507 0 0 0-.302.819l7.32 8.883a1 1 0 0 0 1.185.204C12.735 20.405 16 16.792 16 15"}]]];const Ar=["svg",a,[["circle",{cx:"13.5",cy:"6.5",r:".5",fill:"currentColor"}],["circle",{cx:"17.5",cy:"10.5",r:".5",fill:"currentColor"}],["circle",{cx:"8.5",cy:"7.5",r:".5",fill:"currentColor"}],["circle",{cx:"6.5",cy:"12.5",r:".5",fill:"currentColor"}],["path",{d:"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z"}]]];const Lr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 15h18"}],["path",{d:"m15 8-3 3-3-3"}]]];const M2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M14 15h1"}],["path",{d:"M19 15h2"}],["path",{d:"M3 15h2"}],["path",{d:"M9 15h1"}]]];const Sr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 15h18"}],["path",{d:"m9 10 3-3 3 3"}]]];const fr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 15h18"}]]];const s2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}],["path",{d:"m16 15-3-3 3-3"}]]];const e2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 14v1"}],["path",{d:"M9 19v2"}],["path",{d:"M9 3v2"}],["path",{d:"M9 9v1"}]]];const r2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}],["path",{d:"m14 9 3 3-3 3"}]]];const v2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}]]];const Zr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M15 3v18"}],["path",{d:"m8 9 3 3-3 3"}]]];const n2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M15 14v1"}],["path",{d:"M15 19v2"}],["path",{d:"M15 3v2"}],["path",{d:"M15 9v1"}]]];const Pr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M15 3v18"}],["path",{d:"m10 15-3-3 3-3"}]]];const kr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M15 3v18"}]]];const zr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"m9 16 3-3 3 3"}]]];const o2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M14 9h1"}],["path",{d:"M19 9h2"}],["path",{d:"M3 9h2"}],["path",{d:"M9 9h1"}]]];const Br=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"m15 14-3 3-3-3"}]]];const Fr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}]]];const Dr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 3v18"}],["path",{d:"M9 15h12"}]]];const qr=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 15h12"}],["path",{d:"M15 3v18"}]]];const i2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"M9 21V9"}]]];const Rr=["svg",a,[["path",{d:"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"}]]];const br=["svg",a,[["path",{d:"M8 21s-4-3-4-9 4-9 4-9"}],["path",{d:"M16 3s4 3 4 9-4 9-4 9"}]]];const Tr=["svg",a,[["path",{d:"M9 9a3 3 0 1 1 6 0"}],["path",{d:"M12 12v3"}],["path",{d:"M11 15h2"}],["path",{d:"M19 9a7 7 0 1 0-13.6 2.3C6.4 14.4 8 19 8 19h8s1.6-4.6 2.6-7.7c.3-.8.4-1.5.4-2.3"}],["path",{d:"M12 19v3"}]]];const Ur=["svg",a,[["path",{d:"M5.8 11.3 2 22l10.7-3.79"}],["path",{d:"M4 3h.01"}],["path",{d:"M22 8h.01"}],["path",{d:"M15 2h.01"}],["path",{d:"M22 20h.01"}],["path",{d:"m22 2-2.24.75a2.9 2.9 0 0 0-1.96 3.12c.1.86-.57 1.63-1.45 1.63h-.38c-.86 0-1.6.6-1.76 1.44L14 10"}],["path",{d:"m22 13-.82-.33c-.86-.34-1.82.2-1.98 1.11c-.11.7-.72 1.22-1.43 1.22H17"}],["path",{d:"m11 2 .33.82c.34.86-.2 1.82-1.11 1.98C9.52 4.9 9 5.52 9 6.23V7"}],["path",{d:"M11 13c1.93 1.93 2.83 4.17 2 5-.83.83-3.07-.07-5-2-1.93-1.93-2.83-4.17-2-5 .83-.83 3.07.07 5 2Z"}]]];const Or=["svg",a,[["rect",{x:"14",y:"4",width:"4",height:"16",rx:"1"}],["rect",{x:"6",y:"4",width:"4",height:"16",rx:"1"}]]];const Ir=["svg",a,[["circle",{cx:"11",cy:"4",r:"2"}],["circle",{cx:"18",cy:"8",r:"2"}],["circle",{cx:"20",cy:"16",r:"2"}],["path",{d:"M9 10a5 5 0 0 1 5 5v3.5a3.5 3.5 0 0 1-6.84 1.045Q6.52 17.48 4.46 16.84A3.5 3.5 0 0 1 5.5 10Z"}]]];const Er=["svg",a,[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2"}],["path",{d:"M15 14h.01"}],["path",{d:"M9 6h6"}],["path",{d:"M9 10h6"}]]];const l2=["svg",a,[["path",{d:"M12 20h9"}],["path",{d:"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z"}]]];const Gr=["svg",a,[["path",{d:"m10 10-6.157 6.162a2 2 0 0 0-.5.833l-1.322 4.36a.5.5 0 0 0 .622.624l4.358-1.323a2 2 0 0 0 .83-.5L14 13.982"}],["path",{d:"m12.829 7.172 4.359-4.346a1 1 0 1 1 3.986 3.986l-4.353 4.353"}],["path",{d:"m2 2 20 20"}]]];const Wr=["svg",a,[["path",{d:"M15.707 21.293a1 1 0 0 1-1.414 0l-1.586-1.586a1 1 0 0 1 0-1.414l5.586-5.586a1 1 0 0 1 1.414 0l1.586 1.586a1 1 0 0 1 0 1.414z"}],["path",{d:"m18 13-1.375-6.874a1 1 0 0 0-.746-.776L3.235 2.028a1 1 0 0 0-1.207 1.207L5.35 15.879a1 1 0 0 0 .776.746L13 18"}],["path",{d:"m2.3 2.3 7.286 7.286"}],["circle",{cx:"11",cy:"11",r:"2"}]]];const g2=["svg",a,[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"}]]];const Xr=["svg",a,[["path",{d:"M12 20h9"}],["path",{d:"M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z"}],["path",{d:"m15 5 3 3"}]]];const Nr=["svg",a,[["path",{d:"m10 10-6.157 6.162a2 2 0 0 0-.5.833l-1.322 4.36a.5.5 0 0 0 .622.624l4.358-1.323a2 2 0 0 0 .83-.5L14 13.982"}],["path",{d:"m12.829 7.172 4.359-4.346a1 1 0 1 1 3.986 3.986l-4.353 4.353"}],["path",{d:"m15 5 4 4"}],["path",{d:"m2 2 20 20"}]]];const Kr=["svg",a,[["path",{d:"M13 7 8.7 2.7a2.41 2.41 0 0 0-3.4 0L2.7 5.3a2.41 2.41 0 0 0 0 3.4L7 13"}],["path",{d:"m8 6 2-2"}],["path",{d:"m18 16 2-2"}],["path",{d:"m17 11 4.3 4.3c.94.94.94 2.46 0 3.4l-2.6 2.6c-.94.94-2.46.94-3.4 0L11 17"}],["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"}],["path",{d:"m15 5 4 4"}]]];const Jr=["svg",a,[["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"}],["path",{d:"m15 5 4 4"}]]];const jr=["svg",a,[["path",{d:"M10.83 2.38a2 2 0 0 1 2.34 0l8 5.74a2 2 0 0 1 .73 2.25l-3.04 9.26a2 2 0 0 1-1.9 1.37H7.04a2 2 0 0 1-1.9-1.37L2.1 10.37a2 2 0 0 1 .73-2.25z"}]]];const Qr=["svg",a,[["line",{x1:"19",x2:"5",y1:"5",y2:"19"}],["circle",{cx:"6.5",cy:"6.5",r:"2.5"}],["circle",{cx:"17.5",cy:"17.5",r:"2.5"}]]];const _r=["svg",a,[["circle",{cx:"12",cy:"5",r:"1"}],["path",{d:"m9 20 3-6 3 6"}],["path",{d:"m6 8 6 2 6-2"}],["path",{d:"M12 10v4"}]]];const Yr=["svg",a,[["path",{d:"M20 11H4"}],["path",{d:"M20 7H4"}],["path",{d:"M7 21V4a1 1 0 0 1 1-1h4a1 1 0 0 1 0 12H7"}]]];const $r=["svg",a,[["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}],["path",{d:"M14.05 2a9 9 0 0 1 8 7.94"}],["path",{d:"M14.05 6A5 5 0 0 1 18 10"}]]];const av=["svg",a,[["polyline",{points:"18 2 22 6 18 10"}],["line",{x1:"14",x2:"22",y1:"6",y2:"6"}],["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]];const tv=["svg",a,[["polyline",{points:"16 2 16 8 22 8"}],["line",{x1:"22",x2:"16",y1:"2",y2:"8"}],["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]];const hv=["svg",a,[["line",{x1:"22",x2:"16",y1:"2",y2:"8"}],["line",{x1:"16",x2:"22",y1:"2",y2:"8"}],["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]];const dv=["svg",a,[["path",{d:"M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-3.33-2.67m-2.67-3.34a19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91"}],["line",{x1:"22",x2:"2",y1:"2",y2:"22"}]]];const pv=["svg",a,[["polyline",{points:"22 8 22 2 16 2"}],["line",{x1:"16",x2:"22",y1:"8",y2:"2"}],["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]];const cv=["svg",a,[["path",{d:"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"}]]];const Mv=["svg",a,[["line",{x1:"9",x2:"9",y1:"4",y2:"20"}],["path",{d:"M4 7c0-1.7 1.3-3 3-3h13"}],["path",{d:"M18 20c-1.7 0-3-1.3-3-3V4"}]]];const sv=["svg",a,[["path",{d:"M18.5 8c-1.4 0-2.6-.8-3.2-2A6.87 6.87 0 0 0 2 9v11a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-8.5C22 9.6 20.4 8 18.5 8"}],["path",{d:"M2 14h20"}],["path",{d:"M6 14v4"}],["path",{d:"M10 14v4"}],["path",{d:"M14 14v4"}],["path",{d:"M18 14v4"}]]];const ev=["svg",a,[["path",{d:"M14.531 12.469 6.619 20.38a1 1 0 1 1-3-3l7.912-7.912"}],["path",{d:"M15.686 4.314A12.5 12.5 0 0 0 5.461 2.958 1 1 0 0 0 5.58 4.71a22 22 0 0 1 6.318 3.393"}],["path",{d:"M17.7 3.7a1 1 0 0 0-1.4 0l-4.6 4.6a1 1 0 0 0 0 1.4l2.6 2.6a1 1 0 0 0 1.4 0l4.6-4.6a1 1 0 0 0 0-1.4z"}],["path",{d:"M19.686 8.314a12.501 12.501 0 0 1 1.356 10.225 1 1 0 0 1-1.751-.119 22 22 0 0 0-3.393-6.319"}]]];const rv=["svg",a,[["path",{d:"M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4"}],["rect",{width:"10",height:"7",x:"12",y:"13",rx:"2"}]]];const vv=["svg",a,[["path",{d:"M8 4.5v5H3m-1-6 6 6m13 0v-3c0-1.16-.84-2-2-2h-7m-9 9v2c0 1.05.95 2 2 2h3"}],["rect",{width:"10",height:"7",x:"12",y:"13.5",ry:"2"}]]];const nv=["svg",a,[["path",{d:"M19 5c-1.5 0-2.8 1.4-3 2-3.5-1.5-11-.3-11 5 0 1.8 0 3 2 4.5V20h4v-2h3v2h4v-4c1-.5 1.7-1 2-2h2v-4h-2c0-1-.5-1.5-1-2V5z"}],["path",{d:"M2 9v1c0 1.1.9 2 2 2h1"}],["path",{d:"M16 11h.01"}]]];const ov=["svg",a,[["path",{d:"M14 3v11"}],["path",{d:"M14 9h-3a3 3 0 0 1 0-6h9"}],["path",{d:"M18 3v11"}],["path",{d:"M22 18H2l4-4"}],["path",{d:"m6 22-4-4"}]]];const iv=["svg",a,[["path",{d:"M10 3v11"}],["path",{d:"M10 9H7a1 1 0 0 1 0-6h8"}],["path",{d:"M14 3v11"}],["path",{d:"m18 14 4 4H2"}],["path",{d:"m22 18-4 4"}]]];const lv=["svg",a,[["path",{d:"M13 4v16"}],["path",{d:"M17 4v16"}],["path",{d:"M19 4H9.5a4.5 4.5 0 0 0 0 9H13"}]]];const gv=["svg",a,[["path",{d:"M18 11h-4a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h4"}],["path",{d:"M6 7v13a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7"}],["rect",{width:"16",height:"5",x:"4",y:"2",rx:"1"}]]];const xv=["svg",a,[["path",{d:"m10.5 20.5 10-10a4.95 4.95 0 1 0-7-7l-10 10a4.95 4.95 0 1 0 7 7Z"}],["path",{d:"m8.5 8.5 7 7"}]]];const yv=["svg",a,[["path",{d:"M12 17v5"}],["path",{d:"M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89"}],["path",{d:"m2 2 20 20"}],["path",{d:"M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11"}]]];const mv=["svg",a,[["path",{d:"M12 17v5"}],["path",{d:"M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"}]]];const Hv=["svg",a,[["path",{d:"m2 22 1-1h3l9-9"}],["path",{d:"M3 21v-3l9-9"}],["path",{d:"m15 6 3.4-3.4a2.1 2.1 0 1 1 3 3L18 9l.4.4a2.1 2.1 0 1 1-3 3l-3.8-3.8a2.1 2.1 0 1 1 3-3l.4.4Z"}]]];const Vv=["svg",a,[["path",{d:"M15 11h.01"}],["path",{d:"M11 15h.01"}],["path",{d:"M16 16h.01"}],["path",{d:"m2 16 20 6-6-20A20 20 0 0 0 2 16"}],["path",{d:"M5.71 17.11a17.04 17.04 0 0 1 11.4-11.4"}]]];const Cv=["svg",a,[["path",{d:"M2 22h20"}],["path",{d:"M3.77 10.77 2 9l2-4.5 1.1.55c.55.28.9.84.9 1.45s.35 1.17.9 1.45L8 8.5l3-6 1.05.53a2 2 0 0 1 1.09 1.52l.72 5.4a2 2 0 0 0 1.09 1.52l4.4 2.2c.42.22.78.55 1.01.96l.6 1.03c.49.88-.06 1.98-1.06 2.1l-1.18.15c-.47.06-.95-.02-1.37-.24L4.29 11.15a2 2 0 0 1-.52-.38Z"}]]];const wv=["svg",a,[["path",{d:"M2 22h20"}],["path",{d:"M6.36 17.4 4 17l-2-4 1.1-.55a2 2 0 0 1 1.8 0l.17.1a2 2 0 0 0 1.8 0L8 12 5 6l.9-.45a2 2 0 0 1 2.09.2l4.02 3a2 2 0 0 0 2.1.2l4.19-2.06a2.41 2.41 0 0 1 1.73-.17L21 7a1.4 1.4 0 0 1 .87 1.99l-.38.76c-.23.46-.6.84-1.07 1.08L7.58 17.2a2 2 0 0 1-1.22.18Z"}]]];const uv=["svg",a,[["path",{d:"M17.8 19.2 16 11l3.5-3.5C21 6 21.5 4 21 3c-1-.5-3 0-4.5 1.5L13 8 4.8 6.2c-.5-.1-.9.1-1.1.5l-.3.5c-.2.5-.1 1 .3 1.3L9 12l-2 3H4l-1 1 3 2 2 3 1-1v-3l3-2 3.5 5.3c.3.4.8.5 1.3.3l.5-.2c.4-.3.6-.7.5-1.2z"}]]];const Av=["svg",a,[["polygon",{points:"6 3 20 12 6 21 6 3"}]]];const Lv=["svg",a,[["path",{d:"M9 2v6"}],["path",{d:"M15 2v6"}],["path",{d:"M12 17v5"}],["path",{d:"M5 8h14"}],["path",{d:"M6 11V8h12v3a6 6 0 1 1-12 0Z"}]]];const x2=["svg",a,[["path",{d:"M6.3 20.3a2.4 2.4 0 0 0 3.4 0L12 18l-6-6-2.3 2.3a2.4 2.4 0 0 0 0 3.4Z"}],["path",{d:"m2 22 3-3"}],["path",{d:"M7.5 13.5 10 11"}],["path",{d:"M10.5 16.5 13 14"}],["path",{d:"m18 3-4 4h6l-4 4"}]]];const Sv=["svg",a,[["path",{d:"M12 22v-5"}],["path",{d:"M9 8V2"}],["path",{d:"M15 8V2"}],["path",{d:"M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"}]]];const fv=["svg",a,[["path",{d:"M5 12h14"}],["path",{d:"M12 5v14"}]]];const Zv=["svg",a,[["path",{d:"M3 2v1c0 1 2 1 2 2S3 6 3 7s2 1 2 2-2 1-2 2 2 1 2 2"}],["path",{d:"M18 6h.01"}],["path",{d:"M6 18h.01"}],["path",{d:"M20.83 8.83a4 4 0 0 0-5.66-5.66l-12 12a4 4 0 1 0 5.66 5.66Z"}],["path",{d:"M18 11.66V22a4 4 0 0 0 4-4V6"}]]];const Pv=["svg",a,[["path",{d:"M4 3h16a2 2 0 0 1 2 2v6a10 10 0 0 1-10 10A10 10 0 0 1 2 11V5a2 2 0 0 1 2-2z"}],["polyline",{points:"8 10 12 14 16 10"}]]];const kv=["svg",a,[["path",{d:"M16.85 18.58a9 9 0 1 0-9.7 0"}],["path",{d:"M8 14a5 5 0 1 1 8 0"}],["circle",{cx:"12",cy:"11",r:"1"}],["path",{d:"M13 17a1 1 0 1 0-2 0l.5 4.5a.5.5 0 1 0 1 0Z"}]]];const zv=["svg",a,[["path",{d:"M10 4.5V4a2 2 0 0 0-2.41-1.957"}],["path",{d:"M13.9 8.4a2 2 0 0 0-1.26-1.295"}],["path",{d:"M21.7 16.2A8 8 0 0 0 22 14v-3a2 2 0 1 0-4 0v-1a2 2 0 0 0-3.63-1.158"}],["path",{d:"m7 15-1.8-1.8a2 2 0 0 0-2.79 2.86L6 19.7a7.74 7.74 0 0 0 6 2.3h2a8 8 0 0 0 5.657-2.343"}],["path",{d:"M6 6v8"}],["path",{d:"m2 2 20 20"}]]];const Bv=["svg",a,[["path",{d:"M22 14a8 8 0 0 1-8 8"}],["path",{d:"M18 11v-1a2 2 0 0 0-2-2a2 2 0 0 0-2 2"}],["path",{d:"M14 10V9a2 2 0 0 0-2-2a2 2 0 0 0-2 2v1"}],["path",{d:"M10 9.5V4a2 2 0 0 0-2-2a2 2 0 0 0-2 2v10"}],["path",{d:"M18 11a2 2 0 1 1 4 0v3a8 8 0 0 1-8 8h-2c-2.8 0-4.5-.86-5.99-2.34l-3.6-3.6a2 2 0 0 1 2.83-2.82L7 15"}]]];const Fv=["svg",a,[["path",{d:"M18 8a2 2 0 0 0 0-4 2 2 0 0 0-4 0 2 2 0 0 0-4 0 2 2 0 0 0-4 0 2 2 0 0 0 0 4"}],["path",{d:"M10 22 9 8"}],["path",{d:"m14 22 1-14"}],["path",{d:"M20 8c.5 0 .9.4.8 1l-2.6 12c-.1.5-.7 1-1.2 1H7c-.6 0-1.1-.4-1.2-1L3.2 9c-.1-.6.3-1 .8-1Z"}]]];const Dv=["svg",a,[["path",{d:"M18.6 14.4c.8-.8.8-2 0-2.8l-8.1-8.1a4.95 4.95 0 1 0-7.1 7.1l8.1 8.1c.9.7 2.1.7 2.9-.1Z"}],["path",{d:"m22 22-5.5-5.5"}]]];const qv=["svg",a,[["path",{d:"M18 7c0-5.333-8-5.333-8 0"}],["path",{d:"M10 7v14"}],["path",{d:"M6 21h12"}],["path",{d:"M6 13h10"}]]];const Rv=["svg",a,[["path",{d:"M18.36 6.64A9 9 0 0 1 20.77 15"}],["path",{d:"M6.16 6.16a9 9 0 1 0 12.68 12.68"}],["path",{d:"M12 2v4"}],["path",{d:"m2 2 20 20"}]]];const bv=["svg",a,[["path",{d:"M12 2v10"}],["path",{d:"M18.4 6.6a9 9 0 1 1-12.77.04"}]]];const Tv=["svg",a,[["path",{d:"M2 3h20"}],["path",{d:"M21 3v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V3"}],["path",{d:"m7 21 5-5 5 5"}]]];const Uv=["svg",a,[["path",{d:"M13.5 22H7a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v.5"}],["path",{d:"m16 19 2 2 4-4"}],["path",{d:"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v2"}],["path",{d:"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6"}]]];const Ov=["svg",a,[["path",{d:"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"}],["path",{d:"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6"}],["rect",{x:"6",y:"14",width:"12",height:"8",rx:"1"}]]];const Iv=["svg",a,[["path",{d:"M5 7 3 5"}],["path",{d:"M9 6V3"}],["path",{d:"m13 7 2-2"}],["circle",{cx:"9",cy:"13",r:"3"}],["path",{d:"M11.83 12H20a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h2.17"}],["path",{d:"M16 16h2"}]]];const Ev=["svg",a,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M12 9v11"}],["path",{d:"M2 9h13a2 2 0 0 1 2 2v9"}]]];const Gv=["svg",a,[["path",{d:"M19.439 7.85c-.049.322.059.648.289.878l1.568 1.568c.47.47.706 1.087.706 1.704s-.235 1.233-.706 1.704l-1.611 1.611a.98.98 0 0 1-.837.276c-.47-.07-.802-.48-.968-.925a2.501 2.501 0 1 0-3.214 3.214c.446.166.855.497.925.968a.979.979 0 0 1-.276.837l-1.61 1.61a2.404 2.404 0 0 1-1.705.707 2.402 2.402 0 0 1-1.704-.706l-1.568-1.568a1.026 1.026 0 0 0-.877-.29c-.493.074-.84.504-1.02.968a2.5 2.5 0 1 1-3.237-3.237c.464-.18.894-.527.967-1.02a1.026 1.026 0 0 0-.289-.877l-1.568-1.568A2.402 2.402 0 0 1 1.998 12c0-.617.236-1.234.706-1.704L4.23 8.77c.24-.24.581-.353.917-.303.515.077.877.528 1.073 1.01a2.5 2.5 0 1 0 3.259-3.259c-.482-.196-.933-.558-1.01-1.073-.05-.336.062-.676.303-.917l1.525-1.525A2.402 2.402 0 0 1 12 1.998c.617 0 1.234.236 1.704.706l1.568 1.568c.23.23.556.338.877.29.493-.074.84-.504 1.02-.968a2.5 2.5 0 1 1 3.237 3.237c-.464.18-.894.527-.967 1.02Z"}]]];const Wv=["svg",a,[["path",{d:"M2.5 16.88a1 1 0 0 1-.32-1.43l9-13.02a1 1 0 0 1 1.64 0l9 13.01a1 1 0 0 1-.32 1.44l-8.51 4.86a2 2 0 0 1-1.98 0Z"}],["path",{d:"M12 2v20"}]]];const Xv=["svg",a,[["rect",{width:"5",height:"5",x:"3",y:"3",rx:"1"}],["rect",{width:"5",height:"5",x:"16",y:"3",rx:"1"}],["rect",{width:"5",height:"5",x:"3",y:"16",rx:"1"}],["path",{d:"M21 16h-3a2 2 0 0 0-2 2v3"}],["path",{d:"M21 21v.01"}],["path",{d:"M12 7v3a2 2 0 0 1-2 2H7"}],["path",{d:"M3 12h.01"}],["path",{d:"M12 3h.01"}],["path",{d:"M12 16v.01"}],["path",{d:"M16 12h1"}],["path",{d:"M21 12v.01"}],["path",{d:"M12 21v-1"}]]];const Nv=["svg",a,[["path",{d:"M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"}],["path",{d:"M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z"}]]];const Kv=["svg",a,[["path",{d:"M13 16a3 3 0 0 1 2.24 5"}],["path",{d:"M18 12h.01"}],["path",{d:"M18 21h-8a4 4 0 0 1-4-4 7 7 0 0 1 7-7h.2L9.6 6.4a1 1 0 1 1 2.8-2.8L15.8 7h.2c3.3 0 6 2.7 6 6v1a2 2 0 0 1-2 2h-1a3 3 0 0 0-3 3"}],["path",{d:"M20 8.54V4a2 2 0 1 0-4 0v3"}],["path",{d:"M7.612 12.524a3 3 0 1 0-1.6 4.3"}]]];const Jv=["svg",a,[["path",{d:"M19.07 4.93A10 10 0 0 0 6.99 3.34"}],["path",{d:"M4 6h.01"}],["path",{d:"M2.29 9.62A10 10 0 1 0 21.31 8.35"}],["path",{d:"M16.24 7.76A6 6 0 1 0 8.23 16.67"}],["path",{d:"M12 18h.01"}],["path",{d:"M17.99 11.66A6 6 0 0 1 15.77 16.67"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"m13.41 10.59 5.66-5.66"}]]];const jv=["svg",a,[["path",{d:"M12 12h.01"}],["path",{d:"M7.5 4.2c-.3-.5-.9-.7-1.3-.4C3.9 5.5 2.3 8.1 2 11c-.1.5.4 1 1 1h5c0-1.5.8-2.8 2-3.4-1.1-1.9-2-3.5-2.5-4.4z"}],["path",{d:"M21 12c.6 0 1-.4 1-1-.3-2.9-1.8-5.5-4.1-7.1-.4-.3-1.1-.2-1.3.3-.6.9-1.5 2.5-2.6 4.3 1.2.7 2 2 2 3.5h5z"}],["path",{d:"M7.5 19.8c-.3.5-.1 1.1.4 1.3 2.6 1.2 5.6 1.2 8.2 0 .5-.2.7-.8.4-1.3-.5-.9-1.4-2.5-2.5-4.3-1.2.7-2.8.7-4 0-1.1 1.8-2 3.4-2.5 4.3z"}]]];const Qv=["svg",a,[["path",{d:"M3 12h3.28a1 1 0 0 1 .948.684l2.298 7.934a.5.5 0 0 0 .96-.044L13.82 4.771A1 1 0 0 1 14.792 4H21"}]]];const _v=["svg",a,[["path",{d:"M5 16v2"}],["path",{d:"M19 16v2"}],["rect",{width:"20",height:"8",x:"2",y:"8",rx:"2"}],["path",{d:"M18 12h.01"}]]];const Yv=["svg",a,[["path",{d:"M4.9 16.1C1 12.2 1 5.8 4.9 1.9"}],["path",{d:"M7.8 4.7a6.14 6.14 0 0 0-.8 7.5"}],["circle",{cx:"12",cy:"9",r:"2"}],["path",{d:"M16.2 4.8c2 2 2.26 5.11.8 7.47"}],["path",{d:"M19.1 1.9a9.96 9.96 0 0 1 0 14.1"}],["path",{d:"M9.5 18h5"}],["path",{d:"m8 22 4-11 4 11"}]]];const $v=["svg",a,[["path",{d:"M4.9 19.1C1 15.2 1 8.8 4.9 4.9"}],["path",{d:"M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5"}],["circle",{cx:"12",cy:"12",r:"2"}],["path",{d:"M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5"}],["path",{d:"M19.1 4.9C23 8.8 23 15.1 19.1 19"}]]];const an=["svg",a,[["path",{d:"M20.34 17.52a10 10 0 1 0-2.82 2.82"}],["circle",{cx:"19",cy:"19",r:"2"}],["path",{d:"m13.41 13.41 4.18 4.18"}],["circle",{cx:"12",cy:"12",r:"2"}]]];const tn=["svg",a,[["path",{d:"M5 15h14"}],["path",{d:"M5 9h14"}],["path",{d:"m14 20-5-5 6-6-5-5"}]]];const hn=["svg",a,[["path",{d:"M22 17a10 10 0 0 0-20 0"}],["path",{d:"M6 17a6 6 0 0 1 12 0"}],["path",{d:"M10 17a2 2 0 0 1 4 0"}]]];const dn=["svg",a,[["path",{d:"M17 5c0-1.7-1.3-3-3-3s-3 1.3-3 3c0 .8.3 1.5.8 2H11c-3.9 0-7 3.1-7 7c0 2.2 1.8 4 4 4"}],["path",{d:"M16.8 3.9c.3-.3.6-.5 1-.7 1.5-.6 3.3.1 3.9 1.6.6 1.5-.1 3.3-1.6 3.9l1.6 2.8c.2.3.2.7.2 1-.2.8-.9 1.2-1.7 1.1 0 0-1.6-.3-2.7-.6H17c-1.7 0-3 1.3-3 3"}],["path",{d:"M13.2 18a3 3 0 0 0-2.2-5"}],["path",{d:"M13 22H4a2 2 0 0 1 0-4h12"}],["path",{d:"M16 9h.01"}]]];const pn=["svg",a,[["rect",{width:"12",height:"20",x:"6",y:"2",rx:"2"}],["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}]]];const cn=["svg",a,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M12 6.5v11"}],["path",{d:"M15 9.4a4 4 0 1 0 0 5.2"}]]];const Mn=["svg",a,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M8 12h5"}],["path",{d:"M16 9.5a4 4 0 1 0 0 5.2"}]]];const sn=["svg",a,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M8 7h8"}],["path",{d:"M12 17.5 8 15h1a4 4 0 0 0 0-8"}],["path",{d:"M8 11h8"}]]];const en=["svg",a,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"m12 10 3-3"}],["path",{d:"m9 7 3 3v7.5"}],["path",{d:"M9 11h6"}],["path",{d:"M9 15h6"}]]];const rn=["svg",a,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M8 13h5"}],["path",{d:"M10 17V9.5a2.5 2.5 0 0 1 5 0"}],["path",{d:"M8 17h7"}]]];const vn=["svg",a,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M8 15h5"}],["path",{d:"M8 11h5a2 2 0 1 0 0-4h-3v10"}]]];const nn=["svg",a,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M10 17V7h5"}],["path",{d:"M10 11h4"}],["path",{d:"M8 15h5"}]]];const on=["svg",a,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M14 8H8"}],["path",{d:"M16 12H8"}],["path",{d:"M13 16H8"}]]];const ln=["svg",a,[["path",{d:"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"}],["path",{d:"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"}],["path",{d:"M12 17.5v-11"}]]];const y2=["svg",a,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}],["path",{d:"M12 12h.01"}],["path",{d:"M17 12h.01"}],["path",{d:"M7 12h.01"}]]];const gn=["svg",a,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"2"}]]];const xn=["svg",a,[["rect",{width:"12",height:"20",x:"6",y:"2",rx:"2"}]]];const yn=["svg",a,[["path",{d:"M7 19H4.815a1.83 1.83 0 0 1-1.57-.881 1.785 1.785 0 0 1-.004-1.784L7.196 9.5"}],["path",{d:"M11 19h8.203a1.83 1.83 0 0 0 1.556-.89 1.784 1.784 0 0 0 0-1.775l-1.226-2.12"}],["path",{d:"m14 16-3 3 3 3"}],["path",{d:"M8.293 13.596 7.196 9.5 3.1 10.598"}],["path",{d:"m9.344 5.811 1.093-1.892A1.83 1.83 0 0 1 11.985 3a1.784 1.784 0 0 1 1.546.888l3.943 6.843"}],["path",{d:"m13.378 9.633 4.096 1.098 1.097-4.096"}]]];const mn=["svg",a,[["path",{d:"m15 14 5-5-5-5"}],["path",{d:"M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13"}]]];const Hn=["svg",a,[["circle",{cx:"12",cy:"17",r:"1"}],["path",{d:"M21 7v6h-6"}],["path",{d:"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7"}]]];const Vn=["svg",a,[["path",{d:"M21 7v6h-6"}],["path",{d:"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7"}]]];const Cn=["svg",a,[["path",{d:"M3 2v6h6"}],["path",{d:"M21 12A9 9 0 0 0 6 5.3L3 8"}],["path",{d:"M21 22v-6h-6"}],["path",{d:"M3 12a9 9 0 0 0 15 6.7l3-2.7"}],["circle",{cx:"12",cy:"12",r:"1"}]]];const wn=["svg",a,[["path",{d:"M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"}],["path",{d:"M3 3v5h5"}],["path",{d:"M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16"}],["path",{d:"M16 16h5v5"}]]];const un=["svg",a,[["path",{d:"M21 8L18.74 5.74A9.75 9.75 0 0 0 12 3C11 3 10.03 3.16 9.13 3.47"}],["path",{d:"M8 16H3v5"}],["path",{d:"M3 12C3 9.51 4 7.26 5.64 5.64"}],["path",{d:"m3 16 2.26 2.26A9.75 9.75 0 0 0 12 21c2.49 0 4.74-1 6.36-2.64"}],["path",{d:"M21 12c0 1-.16 1.97-.47 2.87"}],["path",{d:"M21 3v5h-5"}],["path",{d:"M22 22 2 2"}]]];const An=["svg",a,[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}],["path",{d:"M21 3v5h-5"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}],["path",{d:"M8 16H3v5"}]]];const Ln=["svg",a,[["path",{d:"M5 6a4 4 0 0 1 4-4h6a4 4 0 0 1 4 4v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6Z"}],["path",{d:"M5 10h14"}],["path",{d:"M15 7v6"}]]];const Sn=["svg",a,[["path",{d:"M17 3v10"}],["path",{d:"m12.67 5.5 8.66 5"}],["path",{d:"m12.67 10.5 8.66-5"}],["path",{d:"M9 17a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v2a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-2z"}]]];const fn=["svg",a,[["path",{d:"M4 7V4h16v3"}],["path",{d:"M5 20h6"}],["path",{d:"M13 4 8 20"}],["path",{d:"m15 15 5 5"}],["path",{d:"m20 15-5 5"}]]];const Zn=["svg",a,[["path",{d:"m17 2 4 4-4 4"}],["path",{d:"M3 11v-1a4 4 0 0 1 4-4h14"}],["path",{d:"m7 22-4-4 4-4"}],["path",{d:"M21 13v1a4 4 0 0 1-4 4H3"}],["path",{d:"M11 10h1v4"}]]];const Pn=["svg",a,[["path",{d:"m2 9 3-3 3 3"}],["path",{d:"M13 18H7a2 2 0 0 1-2-2V6"}],["path",{d:"m22 15-3 3-3-3"}],["path",{d:"M11 6h6a2 2 0 0 1 2 2v10"}]]];const kn=["svg",a,[["path",{d:"m17 2 4 4-4 4"}],["path",{d:"M3 11v-1a4 4 0 0 1 4-4h14"}],["path",{d:"m7 22-4-4 4-4"}],["path",{d:"M21 13v1a4 4 0 0 1-4 4H3"}]]];const zn=["svg",a,[["path",{d:"M14 14a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2"}],["path",{d:"M14 4a2 2 0 0 1 2-2"}],["path",{d:"M16 10a2 2 0 0 1-2-2"}],["path",{d:"M20 14a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2"}],["path",{d:"M20 2a2 2 0 0 1 2 2"}],["path",{d:"M22 8a2 2 0 0 1-2 2"}],["path",{d:"m3 7 3 3 3-3"}],["path",{d:"M6 10V5a 3 3 0 0 1 3-3h1"}],["rect",{x:"2",y:"14",width:"8",height:"8",rx:"2"}]]];const Bn=["svg",a,[["path",{d:"M14 4a2 2 0 0 1 2-2"}],["path",{d:"M16 10a2 2 0 0 1-2-2"}],["path",{d:"M20 2a2 2 0 0 1 2 2"}],["path",{d:"M22 8a2 2 0 0 1-2 2"}],["path",{d:"m3 7 3 3 3-3"}],["path",{d:"M6 10V5a3 3 0 0 1 3-3h1"}],["rect",{x:"2",y:"14",width:"8",height:"8",rx:"2"}]]];const Fn=["svg",a,[["polyline",{points:"7 17 2 12 7 7"}],["polyline",{points:"12 17 7 12 12 7"}],["path",{d:"M22 18v-2a4 4 0 0 0-4-4H7"}]]];const Dn=["svg",a,[["polyline",{points:"9 17 4 12 9 7"}],["path",{d:"M20 18v-2a4 4 0 0 0-4-4H4"}]]];const qn=["svg",a,[["polygon",{points:"11 19 2 12 11 5 11 19"}],["polygon",{points:"22 19 13 12 22 5 22 19"}]]];const Rn=["svg",a,[["path",{d:"M12 11.22C11 9.997 10 9 10 8a2 2 0 0 1 4 0c0 1-.998 2.002-2.01 3.22"}],["path",{d:"m12 18 2.57-3.5"}],["path",{d:"M6.243 9.016a7 7 0 0 1 11.507-.009"}],["path",{d:"M9.35 14.53 12 11.22"}],["path",{d:"M9.35 14.53C7.728 12.246 6 10.221 6 7a6 5 0 0 1 12 0c-.005 3.22-1.778 5.235-3.43 7.5l3.557 4.527a1 1 0 0 1-.203 1.43l-1.894 1.36a1 1 0 0 1-1.384-.215L12 18l-2.679 3.593a1 1 0 0 1-1.39.213l-1.865-1.353a1 1 0 0 1-.203-1.422z"}]]];const bn=["svg",a,[["path",{d:"M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"}],["path",{d:"m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"}],["path",{d:"M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"}],["path",{d:"M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"}]]];const Tn=["svg",a,[["polyline",{points:"3.5 2 6.5 12.5 18 12.5"}],["line",{x1:"9.5",x2:"5.5",y1:"12.5",y2:"20"}],["line",{x1:"15",x2:"18.5",y1:"12.5",y2:"20"}],["path",{d:"M2.75 18a13 13 0 0 0 18.5 0"}]]];const Un=["svg",a,[["path",{d:"M6 19V5"}],["path",{d:"M10 19V6.8"}],["path",{d:"M14 19v-7.8"}],["path",{d:"M18 5v4"}],["path",{d:"M18 19v-6"}],["path",{d:"M22 19V9"}],["path",{d:"M2 19V9a4 4 0 0 1 4-4c2 0 4 1.33 6 4s4 4 6 4a4 4 0 1 0-3-6.65"}]]];const m2=["svg",a,[["path",{d:"M16.466 7.5C15.643 4.237 13.952 2 12 2 9.239 2 7 6.477 7 12s2.239 10 5 10c.342 0 .677-.069 1-.2"}],["path",{d:"m15.194 13.707 3.814 1.86-1.86 3.814"}],["path",{d:"M19 15.57c-1.804.885-4.274 1.43-7 1.43-5.523 0-10-2.239-10-5s4.477-5 10-5c4.838 0 8.873 1.718 9.8 4"}]]];const On=["svg",a,[["path",{d:"M20 9V7a2 2 0 0 0-2-2h-6"}],["path",{d:"m15 2-3 3 3 3"}],["path",{d:"M20 13v5a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h2"}]]];const In=["svg",a,[["path",{d:"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"}],["path",{d:"M3 3v5h5"}]]];const En=["svg",a,[["path",{d:"M12 5H6a2 2 0 0 0-2 2v3"}],["path",{d:"m9 8 3-3-3-3"}],["path",{d:"M4 14v4a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2"}]]];const Gn=["svg",a,[["path",{d:"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8"}],["path",{d:"M21 3v5h-5"}]]];const Wn=["svg",a,[["circle",{cx:"6",cy:"19",r:"3"}],["path",{d:"M9 19h8.5c.4 0 .9-.1 1.3-.2"}],["path",{d:"M5.2 5.2A3.5 3.53 0 0 0 6.5 12H12"}],["path",{d:"m2 2 20 20"}],["path",{d:"M21 15.3a3.5 3.5 0 0 0-3.3-3.3"}],["path",{d:"M15 5h-4.3"}],["circle",{cx:"18",cy:"5",r:"3"}]]];const Xn=["svg",a,[["circle",{cx:"6",cy:"19",r:"3"}],["path",{d:"M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15"}],["circle",{cx:"18",cy:"5",r:"3"}]]];const Nn=["svg",a,[["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2"}],["path",{d:"M6.01 18H6"}],["path",{d:"M10.01 18H10"}],["path",{d:"M15 10v4"}],["path",{d:"M17.84 7.17a4 4 0 0 0-5.66 0"}],["path",{d:"M20.66 4.34a8 8 0 0 0-11.31 0"}]]];const H2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 12h18"}]]];const V2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M21 9H3"}],["path",{d:"M21 15H3"}]]];const Kn=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M21 7.5H3"}],["path",{d:"M21 12H3"}],["path",{d:"M21 16.5H3"}]]];const Jn=["svg",a,[["path",{d:"M4 11a9 9 0 0 1 9 9"}],["path",{d:"M4 4a16 16 0 0 1 16 16"}],["circle",{cx:"5",cy:"19",r:"1"}]]];const jn=["svg",a,[["path",{d:"M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z"}],["path",{d:"m14.5 12.5 2-2"}],["path",{d:"m11.5 9.5 2-2"}],["path",{d:"m8.5 6.5 2-2"}],["path",{d:"m17.5 15.5 2-2"}]]];const Qn=["svg",a,[["path",{d:"M6 11h8a4 4 0 0 0 0-8H9v18"}],["path",{d:"M6 15h8"}]]];const _n=["svg",a,[["path",{d:"M22 18H2a4 4 0 0 0 4 4h12a4 4 0 0 0 4-4Z"}],["path",{d:"M21 14 10 2 3 14h18Z"}],["path",{d:"M10 2v16"}]]];const Yn=["svg",a,[["path",{d:"M7 21h10"}],["path",{d:"M12 21a9 9 0 0 0 9-9H3a9 9 0 0 0 9 9Z"}],["path",{d:"M11.38 12a2.4 2.4 0 0 1-.4-4.77 2.4 2.4 0 0 1 3.2-2.77 2.4 2.4 0 0 1 3.47-.63 2.4 2.4 0 0 1 3.37 3.37 2.4 2.4 0 0 1-1.1 3.7 2.51 2.51 0 0 1 .03 1.1"}],["path",{d:"m13 12 4-4"}],["path",{d:"M10.9 7.25A3.99 3.99 0 0 0 4 10c0 .73.2 1.41.54 2"}]]];const $n=["svg",a,[["path",{d:"M3 11v3a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1v-3"}],["path",{d:"M12 19H4a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-3.83"}],["path",{d:"m3 11 7.77-6.04a2 2 0 0 1 2.46 0L21 11H3Z"}],["path",{d:"M12.97 19.77 7 15h12.5l-3.75 4.5a2 2 0 0 1-2.78.27Z"}]]];const ao=["svg",a,[["path",{d:"M4 10a7.31 7.31 0 0 0 10 10Z"}],["path",{d:"m9 15 3-3"}],["path",{d:"M17 13a6 6 0 0 0-6-6"}],["path",{d:"M21 13A10 10 0 0 0 11 3"}]]];const to=["svg",a,[["path",{d:"M13 7 9 3 5 7l4 4"}],["path",{d:"m17 11 4 4-4 4-4-4"}],["path",{d:"m8 12 4 4 6-6-4-4Z"}],["path",{d:"m16 8 3-3"}],["path",{d:"M9 21a6 6 0 0 0-6-6"}]]];const ho=["svg",a,[["path",{d:"M10 2v3a1 1 0 0 0 1 1h5"}],["path",{d:"M18 18v-6a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6"}],["path",{d:"M18 22H4a2 2 0 0 1-2-2V6"}],["path",{d:"M8 18a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9.172a2 2 0 0 1 1.414.586l2.828 2.828A2 2 0 0 1 22 6.828V16a2 2 0 0 1-2.01 2z"}]]];const po=["svg",a,[["path",{d:"M13 13H8a1 1 0 0 0-1 1v7"}],["path",{d:"M14 8h1"}],["path",{d:"M17 21v-4"}],["path",{d:"m2 2 20 20"}],["path",{d:"M20.41 20.41A2 2 0 0 1 19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 .59-1.41"}],["path",{d:"M29.5 11.5s5 5 4 5"}],["path",{d:"M9 3h6.2a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V15"}]]];const co=["svg",a,[["path",{d:"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"}],["path",{d:"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7"}],["path",{d:"M7 3v4a1 1 0 0 0 1 1h7"}]]];const C2=["svg",a,[["circle",{cx:"19",cy:"19",r:"2"}],["circle",{cx:"5",cy:"5",r:"2"}],["path",{d:"M5 7v12h12"}],["path",{d:"m5 19 6-6"}]]];const Mo=["svg",a,[["path",{d:"m16 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z"}],["path",{d:"m2 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z"}],["path",{d:"M7 21h10"}],["path",{d:"M12 3v18"}],["path",{d:"M3 7h2c2 0 5-1 7-2 2 1 5 2 7 2h2"}]]];const so=["svg",a,[["path",{d:"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"}],["path",{d:"M14 15H9v-5"}],["path",{d:"M16 3h5v5"}],["path",{d:"M21 3 9 15"}]]];const eo=["svg",a,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M8 7v10"}],["path",{d:"M12 7v10"}],["path",{d:"M17 7v10"}]]];const ro=["svg",a,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["circle",{cx:"12",cy:"12",r:"1"}],["path",{d:"M18.944 12.33a1 1 0 0 0 0-.66 7.5 7.5 0 0 0-13.888 0 1 1 0 0 0 0 .66 7.5 7.5 0 0 0 13.888 0"}]]];const vo=["svg",a,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M8 14s1.5 2 4 2 4-2 4-2"}],["path",{d:"M9 9h.01"}],["path",{d:"M15 9h.01"}]]];const no=["svg",a,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M7 12h10"}]]];const oo=["svg",a,[["path",{d:"M17 12v4a1 1 0 0 1-1 1h-4"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M17 8V7"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M7 17h.01"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["rect",{x:"7",y:"7",width:"5",height:"5",rx:"1"}]]];const io=["svg",a,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"m16 16-1.9-1.9"}]]];const lo=["svg",a,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M7 8h8"}],["path",{d:"M7 12h10"}],["path",{d:"M7 16h6"}]]];const go=["svg",a,[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2"}]]];const xo=["svg",a,[["path",{d:"M14 22v-4a2 2 0 1 0-4 0v4"}],["path",{d:"m18 10 4 2v8a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-8l4-2"}],["path",{d:"M18 5v17"}],["path",{d:"m4 6 8-4 8 4"}],["path",{d:"M6 5v17"}],["circle",{cx:"12",cy:"9",r:"2"}]]];const yo=["svg",a,[["path",{d:"M5.42 9.42 8 12"}],["circle",{cx:"4",cy:"8",r:"2"}],["path",{d:"m14 6-8.58 8.58"}],["circle",{cx:"4",cy:"16",r:"2"}],["path",{d:"M10.8 14.8 14 18"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}]]];const mo=["svg",a,[["circle",{cx:"6",cy:"6",r:"3"}],["path",{d:"M8.12 8.12 12 12"}],["path",{d:"M20 4 8.12 15.88"}],["circle",{cx:"6",cy:"18",r:"3"}],["path",{d:"M14.8 14.8 20 20"}]]];const Ho=["svg",a,[["path",{d:"M13 3H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-3"}],["path",{d:"M8 21h8"}],["path",{d:"M12 17v4"}],["path",{d:"m22 3-5 5"}],["path",{d:"m17 3 5 5"}]]];const Vo=["svg",a,[["path",{d:"M13 3H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-3"}],["path",{d:"M8 21h8"}],["path",{d:"M12 17v4"}],["path",{d:"m17 8 5-5"}],["path",{d:"M17 3h5v5"}]]];const Co=["svg",a,[["path",{d:"M15 12h-5"}],["path",{d:"M15 8h-5"}],["path",{d:"M19 17V5a2 2 0 0 0-2-2H4"}],["path",{d:"M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3"}]]];const wo=["svg",a,[["path",{d:"M19 17V5a2 2 0 0 0-2-2H4"}],["path",{d:"M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3"}]]];const uo=["svg",a,[["path",{d:"m8 11 2 2 4-4"}],["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}]]];const Ao=["svg",a,[["path",{d:"m13 13.5 2-2.5-2-2.5"}],["path",{d:"m21 21-4.3-4.3"}],["path",{d:"M9 8.5 7 11l2 2.5"}],["circle",{cx:"11",cy:"11",r:"8"}]]];const Lo=["svg",a,[["path",{d:"m13.5 8.5-5 5"}],["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}]]];const So=["svg",a,[["path",{d:"m13.5 8.5-5 5"}],["path",{d:"m8.5 8.5 5 5"}],["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}]]];const fo=["svg",a,[["circle",{cx:"11",cy:"11",r:"8"}],["path",{d:"m21 21-4.3-4.3"}]]];const Zo=["svg",a,[["path",{d:"M16 5a4 3 0 0 0-8 0c0 4 8 3 8 7a4 3 0 0 1-8 0"}],["path",{d:"M8 19a4 3 0 0 0 8 0c0-4-8-3-8-7a4 3 0 0 1 8 0"}]]];const w2=["svg",a,[["path",{d:"m3 3 3 9-3 9 19-9Z"}],["path",{d:"M6 12h16"}]]];const Po=["svg",a,[["rect",{x:"14",y:"14",width:"8",height:"8",rx:"2"}],["rect",{x:"2",y:"2",width:"8",height:"8",rx:"2"}],["path",{d:"M7 14v1a2 2 0 0 0 2 2h1"}],["path",{d:"M14 7h1a2 2 0 0 1 2 2v1"}]]];const ko=["svg",a,[["path",{d:"m22 2-7 20-4-9-9-4Z"}],["path",{d:"M22 2 11 13"}]]];const zo=["svg",a,[["line",{x1:"3",x2:"21",y1:"12",y2:"12"}],["polyline",{points:"8 8 12 4 16 8"}],["polyline",{points:"16 16 12 20 8 16"}]]];const Bo=["svg",a,[["line",{x1:"12",x2:"12",y1:"3",y2:"21"}],["polyline",{points:"8 8 4 12 8 16"}],["polyline",{points:"16 16 20 12 16 8"}]]];const Fo=["svg",a,[["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"M4.5 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-.5"}],["path",{d:"M4.5 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-.5"}],["path",{d:"M6 6h.01"}],["path",{d:"M6 18h.01"}],["path",{d:"m15.7 13.4-.9-.3"}],["path",{d:"m9.2 10.9-.9-.3"}],["path",{d:"m10.6 15.7.3-.9"}],["path",{d:"m13.6 15.7-.4-1"}],["path",{d:"m10.8 9.3-.4-1"}],["path",{d:"m8.3 13.6 1-.4"}],["path",{d:"m14.7 10.8 1-.4"}],["path",{d:"m13.4 8.3-.3.9"}]]];const Do=["svg",a,[["path",{d:"M6 10H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-2"}],["path",{d:"M6 14H4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-2"}],["path",{d:"M6 6h.01"}],["path",{d:"M6 18h.01"}],["path",{d:"m13 6-4 6h6l-4 6"}]]];const qo=["svg",a,[["path",{d:"M7 2h13a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-5"}],["path",{d:"M10 10 2.5 2.5C2 2 2 2.5 2 5v3a2 2 0 0 0 2 2h6z"}],["path",{d:"M22 17v-1a2 2 0 0 0-2-2h-1"}],["path",{d:"M4 14a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h16.5l1-.5.5.5-8-8H4z"}],["path",{d:"M6 18h.01"}],["path",{d:"m2 2 20 20"}]]];const Ro=["svg",a,[["rect",{width:"20",height:"8",x:"2",y:"2",rx:"2",ry:"2"}],["rect",{width:"20",height:"8",x:"2",y:"14",rx:"2",ry:"2"}],["line",{x1:"6",x2:"6.01",y1:"6",y2:"6"}],["line",{x1:"6",x2:"6.01",y1:"18",y2:"18"}]]];const bo=["svg",a,[["path",{d:"M20 7h-9"}],["path",{d:"M14 17H5"}],["circle",{cx:"17",cy:"17",r:"3"}],["circle",{cx:"7",cy:"7",r:"3"}]]];const To=["svg",a,[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"}],["circle",{cx:"12",cy:"12",r:"3"}]]];const Uo=["svg",a,[["path",{d:"M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z"}],["rect",{x:"3",y:"14",width:"7",height:"7",rx:"1"}],["circle",{cx:"17.5",cy:"17.5",r:"3.5"}]]];const Oo=["svg",a,[["circle",{cx:"18",cy:"5",r:"3"}],["circle",{cx:"6",cy:"12",r:"3"}],["circle",{cx:"18",cy:"19",r:"3"}],["line",{x1:"8.59",x2:"15.42",y1:"13.51",y2:"17.49"}],["line",{x1:"15.41",x2:"8.59",y1:"6.51",y2:"10.49"}]]];const Io=["svg",a,[["path",{d:"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"}],["polyline",{points:"16 6 12 2 8 6"}],["line",{x1:"12",x2:"12",y1:"2",y2:"15"}]]];const Eo=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["line",{x1:"3",x2:"21",y1:"9",y2:"9"}],["line",{x1:"3",x2:"21",y1:"15",y2:"15"}],["line",{x1:"9",x2:"9",y1:"9",y2:"21"}],["line",{x1:"15",x2:"15",y1:"9",y2:"21"}]]];const Go=["svg",a,[["path",{d:"M14 11a2 2 0 1 1-4 0 4 4 0 0 1 8 0 6 6 0 0 1-12 0 8 8 0 0 1 16 0 10 10 0 1 1-20 0 11.93 11.93 0 0 1 2.42-7.22 2 2 0 1 1 3.16 2.44"}]]];const Wo=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M12 8v4"}],["path",{d:"M12 16h.01"}]]];const Xo=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"m4.243 5.21 14.39 12.472"}]]];const No=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"m9 12 2 2 4-4"}]]];const Ko=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M8 12h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M16 12h.01"}]]];const Jo=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M12 22V2"}]]];const jo=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M9 12h6"}]]];const Qo=["svg",a,[["path",{d:"m2 2 20 20"}],["path",{d:"M5 5a1 1 0 0 0-1 1v7c0 5 3.5 7.5 7.67 8.94a1 1 0 0 0 .67.01c2.35-.82 4.48-1.97 5.9-3.71"}],["path",{d:"M9.309 3.652A12.252 12.252 0 0 0 11.24 2.28a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1v7a9.784 9.784 0 0 1-.08 1.264"}]]];const _o=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M9 12h6"}],["path",{d:"M12 9v6"}]]];const Yo=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3"}],["path",{d:"M12 17h.01"}]]];const u2=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}],["path",{d:"m14.5 9.5-5 5"}],["path",{d:"m9.5 9.5 5 5"}]]];const $o=["svg",a,[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"}]]];const ai=["svg",a,[["circle",{cx:"12",cy:"12",r:"8"}],["path",{d:"M12 2v7.5"}],["path",{d:"m19 5-5.23 5.23"}],["path",{d:"M22 12h-7.5"}],["path",{d:"m19 19-5.23-5.23"}],["path",{d:"M12 14.5V22"}],["path",{d:"M10.23 13.77 5 19"}],["path",{d:"M9.5 12H2"}],["path",{d:"M10.23 10.23 5 5"}],["circle",{cx:"12",cy:"12",r:"2.5"}]]];const ti=["svg",a,[["path",{d:"M2 21c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1 .6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M19.38 20A11.6 11.6 0 0 0 21 14l-9-4-9 4c0 2.9.94 5.34 2.81 7.76"}],["path",{d:"M19 13V7a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v6"}],["path",{d:"M12 10v4"}],["path",{d:"M12 2v3"}]]];const hi=["svg",a,[["path",{d:"M20.38 3.46 16 2a4 4 0 0 1-8 0L3.62 3.46a2 2 0 0 0-1.34 2.23l.58 3.47a1 1 0 0 0 .99.84H6v10c0 1.1.9 2 2 2h8a2 2 0 0 0 2-2V10h2.15a1 1 0 0 0 .99-.84l.58-3.47a2 2 0 0 0-1.34-2.23z"}]]];const di=["svg",a,[["path",{d:"M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z"}],["path",{d:"M3 6h18"}],["path",{d:"M16 10a4 4 0 0 1-8 0"}]]];const pi=["svg",a,[["path",{d:"m15 11-1 9"}],["path",{d:"m19 11-4-7"}],["path",{d:"M2 11h20"}],["path",{d:"m3.5 11 1.6 7.4a2 2 0 0 0 2 1.6h9.8a2 2 0 0 0 2-1.6l1.7-7.4"}],["path",{d:"M4.5 15.5h15"}],["path",{d:"m5 11 4-7"}],["path",{d:"m9 11 1 9"}]]];const ci=["svg",a,[["circle",{cx:"8",cy:"21",r:"1"}],["circle",{cx:"19",cy:"21",r:"1"}],["path",{d:"M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12"}]]];const Mi=["svg",a,[["path",{d:"M2 22v-5l5-5 5 5-5 5z"}],["path",{d:"M9.5 14.5 16 8"}],["path",{d:"m17 2 5 5-.5.5a3.53 3.53 0 0 1-5 0s0 0 0 0a3.53 3.53 0 0 1 0-5L17 2"}]]];const si=["svg",a,[["path",{d:"m4 4 2.5 2.5"}],["path",{d:"M13.5 6.5a4.95 4.95 0 0 0-7 7"}],["path",{d:"M15 5 5 15"}],["path",{d:"M14 17v.01"}],["path",{d:"M10 16v.01"}],["path",{d:"M13 13v.01"}],["path",{d:"M16 10v.01"}],["path",{d:"M11 20v.01"}],["path",{d:"M17 14v.01"}],["path",{d:"M20 11v.01"}]]];const ei=["svg",a,[["path",{d:"m15 15 6 6m-6-6v4.8m0-4.8h4.8"}],["path",{d:"M9 19.8V15m0 0H4.2M9 15l-6 6"}],["path",{d:"M15 4.2V9m0 0h4.8M15 9l6-6"}],["path",{d:"M9 4.2V9m0 0H4.2M9 9 3 3"}]]];const ri=["svg",a,[["path",{d:"M12 22v-7l-2-2"}],["path",{d:"M17 8v.8A6 6 0 0 1 13.8 20H10A6.5 6.5 0 0 1 7 8a5 5 0 0 1 10 0Z"}],["path",{d:"m14 14-2 2"}]]];const vi=["svg",a,[["path",{d:"M2 18h1.4c1.3 0 2.5-.6 3.3-1.7l6.1-8.6c.7-1.1 2-1.7 3.3-1.7H22"}],["path",{d:"m18 2 4 4-4 4"}],["path",{d:"M2 6h1.9c1.5 0 2.9.9 3.6 2.2"}],["path",{d:"M22 18h-5.9c-1.3 0-2.6-.7-3.3-1.8l-.5-.8"}],["path",{d:"m18 14 4 4-4 4"}]]];const ni=["svg",a,[["path",{d:"M18 7V5a1 1 0 0 0-1-1H6.5a.5.5 0 0 0-.4.8l4.5 6a2 2 0 0 1 0 2.4l-4.5 6a.5.5 0 0 0 .4.8H17a1 1 0 0 0 1-1v-2"}]]];const oi=["svg",a,[["path",{d:"M2 20h.01"}],["path",{d:"M7 20v-4"}],["path",{d:"M12 20v-8"}],["path",{d:"M17 20V8"}]]];const ii=["svg",a,[["path",{d:"M2 20h.01"}],["path",{d:"M7 20v-4"}]]];const li=["svg",a,[["path",{d:"M2 20h.01"}],["path",{d:"M7 20v-4"}],["path",{d:"M12 20v-8"}]]];const gi=["svg",a,[["path",{d:"M2 20h.01"}]]];const xi=["svg",a,[["path",{d:"M2 20h.01"}],["path",{d:"M7 20v-4"}],["path",{d:"M12 20v-8"}],["path",{d:"M17 20V8"}],["path",{d:"M22 4v16"}]]];const yi=["svg",a,[["path",{d:"m21 17-2.156-1.868A.5.5 0 0 0 18 15.5v.5a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1c0-2.545-3.991-3.97-8.5-4a1 1 0 0 0 0 5c4.153 0 4.745-11.295 5.708-13.5a2.5 2.5 0 1 1 3.31 3.284"}],["path",{d:"M3 21h18"}]]];const mi=["svg",a,[["path",{d:"M10 9H4L2 7l2-2h6"}],["path",{d:"M14 5h6l2 2-2 2h-6"}],["path",{d:"M10 22V4a2 2 0 1 1 4 0v18"}],["path",{d:"M8 22h8"}]]];const Hi=["svg",a,[["path",{d:"M12 13v8"}],["path",{d:"M12 3v3"}],["path",{d:"M18 6a2 2 0 0 1 1.414.586l2.293 2.207a1 1 0 0 1 0 1.414l-2.27 2.184a2 2 0 0 1-1.742.586L6 13a2 2 0 0 1-1.414-.586l-2.293-2.207a1 1 0 0 1 0-1.414l2.293-2.207A2 2 0 0 1 6 6z"}]]];const Vi=["svg",a,[["path",{d:"M7 18v-6a5 5 0 1 1 10 0v6"}],["path",{d:"M5 21a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-1a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2z"}],["path",{d:"M21 12h1"}],["path",{d:"M18.5 4.5 18 5"}],["path",{d:"M2 12h1"}],["path",{d:"M12 2v1"}],["path",{d:"m4.929 4.929.707.707"}],["path",{d:"M12 12v6"}]]];const Ci=["svg",a,[["polygon",{points:"19 20 9 12 19 4 19 20"}],["line",{x1:"5",x2:"5",y1:"19",y2:"5"}]]];const wi=["svg",a,[["polygon",{points:"5 4 15 12 5 20 5 4"}],["line",{x1:"19",x2:"19",y1:"5",y2:"19"}]]];const ui=["svg",a,[["path",{d:"m12.5 17-.5-1-.5 1h1z"}],["path",{d:"M15 22a1 1 0 0 0 1-1v-1a2 2 0 0 0 1.56-3.25 8 8 0 1 0-11.12 0A2 2 0 0 0 8 20v1a1 1 0 0 0 1 1z"}],["circle",{cx:"15",cy:"12",r:"1"}],["circle",{cx:"9",cy:"12",r:"1"}]]];const Ai=["svg",a,[["rect",{width:"3",height:"8",x:"13",y:"2",rx:"1.5"}],["path",{d:"M19 8.5V10h1.5A1.5 1.5 0 1 0 19 8.5"}],["rect",{width:"3",height:"8",x:"8",y:"14",rx:"1.5"}],["path",{d:"M5 15.5V14H3.5A1.5 1.5 0 1 0 5 15.5"}],["rect",{width:"8",height:"3",x:"14",y:"13",rx:"1.5"}],["path",{d:"M15.5 19H14v1.5a1.5 1.5 0 1 0 1.5-1.5"}],["rect",{width:"8",height:"3",x:"2",y:"8",rx:"1.5"}],["path",{d:"M8.5 5H10V3.5A1.5 1.5 0 1 0 8.5 5"}]]];const Li=["svg",a,[["path",{d:"M22 2 2 22"}]]];const Si=["svg",a,[["path",{d:"m8 14-6 6h9v-3"}],["path",{d:"M18.37 3.63 8 14l3 3L21.37 6.63a2.12 2.12 0 1 0-3-3Z"}]]];const fi=["svg",a,[["line",{x1:"21",x2:"14",y1:"4",y2:"4"}],["line",{x1:"10",x2:"3",y1:"4",y2:"4"}],["line",{x1:"21",x2:"12",y1:"12",y2:"12"}],["line",{x1:"8",x2:"3",y1:"12",y2:"12"}],["line",{x1:"21",x2:"16",y1:"20",y2:"20"}],["line",{x1:"12",x2:"3",y1:"20",y2:"20"}],["line",{x1:"14",x2:"14",y1:"2",y2:"6"}],["line",{x1:"8",x2:"8",y1:"10",y2:"14"}],["line",{x1:"16",x2:"16",y1:"18",y2:"22"}]]];const A2=["svg",a,[["line",{x1:"4",x2:"4",y1:"21",y2:"14"}],["line",{x1:"4",x2:"4",y1:"10",y2:"3"}],["line",{x1:"12",x2:"12",y1:"21",y2:"12"}],["line",{x1:"12",x2:"12",y1:"8",y2:"3"}],["line",{x1:"20",x2:"20",y1:"21",y2:"16"}],["line",{x1:"20",x2:"20",y1:"12",y2:"3"}],["line",{x1:"2",x2:"6",y1:"14",y2:"14"}],["line",{x1:"10",x2:"14",y1:"8",y2:"8"}],["line",{x1:"18",x2:"22",y1:"16",y2:"16"}]]];const Zi=["svg",a,[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2"}],["path",{d:"M12.667 8 10 12h4l-2.667 4"}]]];const Pi=["svg",a,[["rect",{width:"7",height:"12",x:"2",y:"6",rx:"1"}],["path",{d:"M13 8.32a7.43 7.43 0 0 1 0 7.36"}],["path",{d:"M16.46 6.21a11.76 11.76 0 0 1 0 11.58"}],["path",{d:"M19.91 4.1a15.91 15.91 0 0 1 .01 15.8"}]]];const ki=["svg",a,[["rect",{width:"14",height:"20",x:"5",y:"2",rx:"2",ry:"2"}],["path",{d:"M12 18h.01"}]]];const zi=["svg",a,[["path",{d:"M22 11v1a10 10 0 1 1-9-10"}],["path",{d:"M8 14s1.5 2 4 2 4-2 4-2"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}],["path",{d:"M16 5h6"}],["path",{d:"M19 2v6"}]]];const Bi=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["path",{d:"M8 14s1.5 2 4 2 4-2 4-2"}],["line",{x1:"9",x2:"9.01",y1:"9",y2:"9"}],["line",{x1:"15",x2:"15.01",y1:"9",y2:"9"}]]];const Fi=["svg",a,[["path",{d:"M2 13a6 6 0 1 0 12 0 4 4 0 1 0-8 0 2 2 0 0 0 4 0"}],["circle",{cx:"10",cy:"13",r:"8"}],["path",{d:"M2 21h12c4.4 0 8-3.6 8-8V7a2 2 0 1 0-4 0v6"}],["path",{d:"M18 3 19.1 5.2"}],["path",{d:"M22 3 20.9 5.2"}]]];const Di=["svg",a,[["line",{x1:"2",x2:"22",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"2",y2:"22"}],["path",{d:"m20 16-4-4 4-4"}],["path",{d:"m4 8 4 4-4 4"}],["path",{d:"m16 4-4 4-4-4"}],["path",{d:"m8 20 4-4 4 4"}]]];const qi=["svg",a,[["path",{d:"M20 9V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v3"}],["path",{d:"M2 16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5a2 2 0 0 0-4 0v1.5a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5V11a2 2 0 0 0-4 0z"}],["path",{d:"M4 18v2"}],["path",{d:"M20 18v2"}],["path",{d:"M12 4v9"}]]];const Ri=["svg",a,[["path",{d:"M12 21a9 9 0 0 0 9-9H3a9 9 0 0 0 9 9Z"}],["path",{d:"M7 21h10"}],["path",{d:"M19.5 12 22 6"}],["path",{d:"M16.25 3c.27.1.8.53.75 1.36-.06.83-.93 1.2-1 2.02-.05.78.34 1.24.73 1.62"}],["path",{d:"M11.25 3c.27.1.8.53.74 1.36-.05.83-.93 1.2-.98 2.02-.06.78.33 1.24.72 1.62"}],["path",{d:"M6.25 3c.27.1.8.53.75 1.36-.06.83-.93 1.2-1 2.02-.05.78.34 1.24.74 1.62"}]]];const bi=["svg",a,[["path",{d:"M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1"}]]];const Ti=["svg",a,[["path",{d:"M5 9c-1.5 1.5-3 3.2-3 5.5A5.5 5.5 0 0 0 7.5 20c1.8 0 3-.5 4.5-2 1.5 1.5 2.7 2 4.5 2a5.5 5.5 0 0 0 5.5-5.5c0-2.3-1.5-4-3-5.5l-7-7-7 7Z"}],["path",{d:"M12 18v4"}]]];const Ui=["svg",a,[["path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"}]]];const L2=["svg",a,[["path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"}],["path",{d:"M20 3v4"}],["path",{d:"M22 5h-4"}],["path",{d:"M4 17v2"}],["path",{d:"M5 18H3"}]]];const Oi=["svg",a,[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2"}],["path",{d:"M12 6h.01"}],["circle",{cx:"12",cy:"14",r:"4"}],["path",{d:"M12 14h.01"}]]];const Ii=["svg",a,[["path",{d:"M8.8 20v-4.1l1.9.2a2.3 2.3 0 0 0 2.164-2.1V8.3A5.37 5.37 0 0 0 2 8.25c0 2.8.656 3.054 1 4.55a5.77 5.77 0 0 1 .029 2.758L2 20"}],["path",{d:"M19.8 17.8a7.5 7.5 0 0 0 .003-10.603"}],["path",{d:"M17 15a3.5 3.5 0 0 0-.025-4.975"}]]];const Ei=["svg",a,[["path",{d:"m6 16 6-12 6 12"}],["path",{d:"M8 12h8"}],["path",{d:"M4 21c1.1 0 1.1-1 2.3-1s1.1 1 2.3 1c1.1 0 1.1-1 2.3-1 1.1 0 1.1 1 2.3 1 1.1 0 1.1-1 2.3-1 1.1 0 1.1 1 2.3 1 1.1 0 1.1-1 2.3-1"}]]];const Gi=["svg",a,[["path",{d:"m6 16 6-12 6 12"}],["path",{d:"M8 12h8"}],["path",{d:"m16 20 2 2 4-4"}]]];const Wi=["svg",a,[["circle",{cx:"19",cy:"5",r:"2"}],["circle",{cx:"5",cy:"19",r:"2"}],["path",{d:"M5 17A12 12 0 0 1 17 5"}]]];const Xi=["svg",a,[["path",{d:"M16 3h5v5"}],["path",{d:"M8 3H3v5"}],["path",{d:"M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3"}],["path",{d:"m15 9 6-6"}]]];const Ni=["svg",a,[["path",{d:"M3 3h.01"}],["path",{d:"M7 5h.01"}],["path",{d:"M11 7h.01"}],["path",{d:"M3 7h.01"}],["path",{d:"M7 9h.01"}],["path",{d:"M3 11h.01"}],["rect",{width:"4",height:"4",x:"15",y:"5"}],["path",{d:"m19 9 2 2v10c0 .6-.4 1-1 1h-6c-.6 0-1-.4-1-1V11l2-2"}],["path",{d:"m13 14 8-2"}],["path",{d:"m13 19 8-2"}]]];const Ki=["svg",a,[["path",{d:"M7 20h10"}],["path",{d:"M10 20c5.5-2.5.8-6.4 3-10"}],["path",{d:"M9.5 9.4c1.1.8 1.8 2.2 2.3 3.7-2 .4-3.5.4-4.8-.3-1.2-.6-2.3-1.9-3-4.2 2.8-.5 4.4 0 5.5.8z"}],["path",{d:"M14.1 6a7 7 0 0 0-1.1 4c1.9-.1 3.3-.6 4.3-1.4 1-1 1.6-2.3 1.7-4.6-2.7.1-4 1-4.9 2z"}]]];const S2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M17 12h-2l-2 5-2-10-2 5H7"}]]];const f2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m16 8-8 8"}],["path",{d:"M16 16H8V8"}]]];const Z2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m8 8 8 8"}],["path",{d:"M16 8v8H8"}]]];const P2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 8v8"}],["path",{d:"m8 12 4 4 4-4"}]]];const k2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m12 8-4 4 4 4"}],["path",{d:"M16 12H8"}]]];const z2=["svg",a,[["path",{d:"M13 21h6a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v6"}],["path",{d:"m3 21 9-9"}],["path",{d:"M9 21H3v-6"}]]];const B2=["svg",a,[["path",{d:"M21 11V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6"}],["path",{d:"m21 21-9-9"}],["path",{d:"M21 15v6h-6"}]]];const F2=["svg",a,[["path",{d:"M13 3h6a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-6"}],["path",{d:"m3 3 9 9"}],["path",{d:"M3 9V3h6"}]]];const D2=["svg",a,[["path",{d:"M21 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h6"}],["path",{d:"m21 3-9 9"}],["path",{d:"M15 3h6v6"}]]];const q2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 12h8"}],["path",{d:"m12 16 4-4-4-4"}]]];const R2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 16V8h8"}],["path",{d:"M16 16 8 8"}]]];const b2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 8h8v8"}],["path",{d:"m8 16 8-8"}]]];const T2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m16 12-4-4-4 4"}],["path",{d:"M12 16V8"}]]];const U2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 8v8"}],["path",{d:"m8.5 14 7-4"}],["path",{d:"m8.5 10 7 4"}]]];const O2=["svg",a,[["path",{d:"M4 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2"}],["path",{d:"M10 22H8"}],["path",{d:"M16 22h-2"}],["circle",{cx:"8",cy:"8",r:"2"}],["path",{d:"M9.414 9.414 12 12"}],["path",{d:"M14.8 14.8 18 18"}],["circle",{cx:"8",cy:"16",r:"2"}],["path",{d:"m18 6-8.586 8.586"}]]];const n=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 8h7"}],["path",{d:"M8 12h6"}],["path",{d:"M11 16h5"}]]];const I2=["svg",a,[["path",{d:"M21 10.5V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h12.5"}],["path",{d:"m9 11 3 3L22 4"}]]];const E2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m9 12 2 2 4-4"}]]];const G2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m16 10-4 4-4-4"}]]];const W2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m14 16-4-4 4-4"}]]];const X2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m10 8 4 4-4 4"}]]];const N2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m8 14 4-4 4 4"}]]];const K2=["svg",a,[["path",{d:"M10 9.5 8 12l2 2.5"}],["path",{d:"m14 9.5 2 2.5-2 2.5"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]];const Ji=["svg",a,[["path",{d:"M10 9.5 8 12l2 2.5"}],["path",{d:"M14 21h1"}],["path",{d:"m14 9.5 2 2.5-2 2.5"}],["path",{d:"M5 21a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2"}],["path",{d:"M9 21h1"}]]];const ji=["svg",a,[["path",{d:"M5 21a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2"}],["path",{d:"M9 21h1"}],["path",{d:"M14 21h1"}]]];const J2=["svg",a,[["path",{d:"M8 7v7"}],["path",{d:"M12 7v4"}],["path",{d:"M16 7v9"}],["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M9 3h1"}],["path",{d:"M14 3h1"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M21 9v1"}],["path",{d:"M21 14v1"}],["path",{d:"M21 19a2 2 0 0 1-2 2"}],["path",{d:"M14 21h1"}],["path",{d:"M9 21h1"}],["path",{d:"M5 21a2 2 0 0 1-2-2"}],["path",{d:"M3 14v1"}],["path",{d:"M3 9v1"}]]];const j2=["svg",a,[["path",{d:"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.943l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.943.033z"}],["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M5 21a2 2 0 0 1-2-2"}],["path",{d:"M9 3h1"}],["path",{d:"M9 21h2"}],["path",{d:"M14 3h1"}],["path",{d:"M3 9v1"}],["path",{d:"M21 9v2"}],["path",{d:"M3 14v1"}]]];const Q2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["line",{x1:"8",x2:"16",y1:"12",y2:"12"}],["line",{x1:"12",x2:"12",y1:"16",y2:"16"}],["line",{x1:"12",x2:"12",y1:"8",y2:"8"}]]];const _2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["circle",{cx:"12",cy:"12",r:"1"}]]];const Y2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 10h10"}],["path",{d:"M7 14h10"}]]];const $2=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"M9 17c2 0 2.8-1 2.8-2.8V10c0-2 1-3.3 3.2-3"}],["path",{d:"M9 11.2h5.7"}]]];const a0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 7v7"}],["path",{d:"M12 7v4"}],["path",{d:"M16 7v9"}]]];const t0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 7v10"}],["path",{d:"M11 7v10"}],["path",{d:"m15 7 2 10"}]]];const h0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 16V8l4 4 4-4v8"}]]];const d0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 8h10"}],["path",{d:"M7 12h10"}],["path",{d:"M7 16h10"}]]];const p0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 12h8"}]]];const c0=["svg",a,[["path",{d:"M12.034 12.681a.498.498 0 0 1 .647-.647l9 3.5a.5.5 0 0 1-.033.943l-3.444 1.068a1 1 0 0 0-.66.66l-1.067 3.443a.5.5 0 0 1-.943.033z"}],["path",{d:"M21 11V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h6"}]]];const M0=["svg",a,[["path",{d:"M3.6 3.6A2 2 0 0 1 5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-.59 1.41"}],["path",{d:"M3 8.7V19a2 2 0 0 0 2 2h10.3"}],["path",{d:"m2 2 20 20"}],["path",{d:"M13 13a3 3 0 1 0 0-6H9v2"}],["path",{d:"M9 17v-2.3"}]]];const s0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M9 17V7h4a3 3 0 0 1 0 6H9"}]]];const e=["svg",a,[["path",{d:"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"}],["path",{d:"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z"}]]];const e0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m15 9-6 6"}],["path",{d:"M9 9h.01"}],["path",{d:"M15 15h.01"}]]];const r0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M7 7h10"}],["path",{d:"M10 7v10"}],["path",{d:"M16 17a2 2 0 0 1-2-2V7"}]]];const v0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M12 12H9.5a2.5 2.5 0 0 1 0-5H17"}],["path",{d:"M12 7v10"}],["path",{d:"M16 7v10"}]]];const n0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"m9 8 6 4-6 4Z"}]]];const o0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M8 12h8"}],["path",{d:"M12 8v8"}]]];const i0=["svg",a,[["path",{d:"M12 7v4"}],["path",{d:"M7.998 9.003a5 5 0 1 0 8-.005"}],["rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}]]];const Qi=["svg",a,[["path",{d:"M7 12h2l2 5 2-10h4"}],["rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}]]];const l0=["svg",a,[["rect",{width:"20",height:"20",x:"2",y:"2",rx:"2"}],["circle",{cx:"8",cy:"8",r:"2"}],["path",{d:"M9.414 9.414 12 12"}],["path",{d:"M14.8 14.8 18 18"}],["circle",{cx:"8",cy:"16",r:"2"}],["path",{d:"m18 6-8.586 8.586"}]]];const g0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M16 8.9V7H8l4 5-4 5h8v-1.9"}]]];const x0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["line",{x1:"9",x2:"15",y1:"15",y2:"9"}]]];const y0=["svg",a,[["path",{d:"M8 19H5c-1 0-2-1-2-2V7c0-1 1-2 2-2h3"}],["path",{d:"M16 5h3c1 0 2 1 2 2v10c0 1-1 2-2 2h-3"}],["line",{x1:"12",x2:"12",y1:"4",y2:"20"}]]];const m0=["svg",a,[["path",{d:"M5 8V5c0-1 1-2 2-2h10c1 0 2 1 2 2v3"}],["path",{d:"M19 16v3c0 1-1 2-2 2H7c-1 0-2-1-2-2v-3"}],["line",{x1:"4",x2:"20",y1:"12",y2:"12"}]]];const _i=["svg",a,[["rect",{x:"3",y:"3",width:"18",height:"18",rx:"2"}],["rect",{x:"8",y:"8",width:"8",height:"8",rx:"1"}]]];const Yi=["svg",a,[["path",{d:"M4 10c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h4c1.1 0 2 .9 2 2"}],["path",{d:"M10 16c-1.1 0-2-.9-2-2v-4c0-1.1.9-2 2-2h4c1.1 0 2 .9 2 2"}],["rect",{width:"8",height:"8",x:"14",y:"14",rx:"2"}]]];const H0=["svg",a,[["path",{d:"m7 11 2-2-2-2"}],["path",{d:"M11 13h4"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}]]];const V0=["svg",a,[["path",{d:"M18 21a6 6 0 0 0-12 0"}],["circle",{cx:"12",cy:"11",r:"4"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]];const C0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M7 21v-2a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v2"}]]];const w0=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["path",{d:"m15 9-6 6"}],["path",{d:"m9 9 6 6"}]]];const $i=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]];const al=["svg",a,[["path",{d:"M12 3c7.2 0 9 1.8 9 9s-1.8 9-9 9-9-1.8-9-9 1.8-9 9-9"}]]];const tl=["svg",a,[["path",{d:"M15.236 22a3 3 0 0 0-2.2-5"}],["path",{d:"M16 20a3 3 0 0 1 3-3h1a2 2 0 0 0 2-2v-2a4 4 0 0 0-4-4V4"}],["path",{d:"M18 13h.01"}],["path",{d:"M18 6a4 4 0 0 0-4 4 7 7 0 0 0-7 7c0-5 4-5 4-10.5a4.5 4.5 0 1 0-9 0 2.5 2.5 0 0 0 5 0C7 10 3 11 3 17c0 2.8 2.2 5 5 5h10"}]]];const hl=["svg",a,[["path",{d:"M5 22h14"}],["path",{d:"M19.27 13.73A2.5 2.5 0 0 0 17.5 13h-11A2.5 2.5 0 0 0 4 15.5V17a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-1.5c0-.66-.26-1.3-.73-1.77Z"}],["path",{d:"M14 13V8.5C14 7 15 7 15 5a3 3 0 0 0-3-3c-1.66 0-3 1-3 3s1 2 1 3.5V13"}]]];const dl=["svg",a,[["path",{d:"M12 17.8 5.8 21 7 14.1 2 9.3l7-1L12 2"}]]];const pl=["svg",a,[["path",{d:"M8.34 8.34 2 9.27l5 4.87L5.82 21 12 17.77 18.18 21l-.59-3.43"}],["path",{d:"M18.42 12.76 22 9.27l-6.91-1L12 2l-1.44 2.91"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const cl=["svg",a,[["polygon",{points:"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"}]]];const Ml=["svg",a,[["line",{x1:"18",x2:"18",y1:"20",y2:"4"}],["polygon",{points:"14,20 4,12 14,4"}]]];const sl=["svg",a,[["line",{x1:"6",x2:"6",y1:"4",y2:"20"}],["polygon",{points:"10,4 20,12 10,20"}]]];const el=["svg",a,[["path",{d:"M4.8 2.3A.3.3 0 1 0 5 2H4a2 2 0 0 0-2 2v5a6 6 0 0 0 6 6a6 6 0 0 0 6-6V4a2 2 0 0 0-2-2h-1a.2.2 0 1 0 .3.3"}],["path",{d:"M8 15v1a6 6 0 0 0 6 6a6 6 0 0 0 6-6v-4"}],["circle",{cx:"20",cy:"10",r:"2"}]]];const rl=["svg",a,[["path",{d:"M15.5 3H5a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2V8.5L15.5 3Z"}],["path",{d:"M14 3v4a2 2 0 0 0 2 2h4"}],["path",{d:"M8 13h.01"}],["path",{d:"M16 13h.01"}],["path",{d:"M10 16s.8 1 2 1c1.3 0 2-1 2-1"}]]];const vl=["svg",a,[["path",{d:"M16 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8Z"}],["path",{d:"M15 3v4a2 2 0 0 0 2 2h4"}]]];const nl=["svg",a,[["path",{d:"m2 7 4.41-4.41A2 2 0 0 1 7.83 2h8.34a2 2 0 0 1 1.42.59L22 7"}],["path",{d:"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"}],["path",{d:"M15 22v-4a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4"}],["path",{d:"M2 7h20"}],["path",{d:"M22 7v3a2 2 0 0 1-2 2a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 16 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 12 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 8 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 4 12a2 2 0 0 1-2-2V7"}]]];const ol=["svg",a,[["rect",{width:"20",height:"6",x:"2",y:"4",rx:"2"}],["rect",{width:"20",height:"6",x:"2",y:"14",rx:"2"}]]];const il=["svg",a,[["rect",{width:"6",height:"20",x:"4",y:"2",rx:"2"}],["rect",{width:"6",height:"20",x:"14",y:"2",rx:"2"}]]];const ll=["svg",a,[["path",{d:"M16 4H9a3 3 0 0 0-2.83 4"}],["path",{d:"M14 12a4 4 0 0 1 0 8H6"}],["line",{x1:"4",x2:"20",y1:"12",y2:"12"}]]];const gl=["svg",a,[["path",{d:"m4 5 8 8"}],["path",{d:"m12 5-8 8"}],["path",{d:"M20 19h-4c0-1.5.44-2 1.5-2.5S20 15.33 20 14c0-.47-.17-.93-.48-1.29a2.11 2.11 0 0 0-2.62-.44c-.42.24-.74.62-.9 1.07"}]]];const xl=["svg",a,[["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M12 4h.01"}],["path",{d:"M20 12h.01"}],["path",{d:"M12 20h.01"}],["path",{d:"M4 12h.01"}],["path",{d:"M17.657 6.343h.01"}],["path",{d:"M17.657 17.657h.01"}],["path",{d:"M6.343 17.657h.01"}],["path",{d:"M6.343 6.343h.01"}]]];const yl=["svg",a,[["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M12 3v1"}],["path",{d:"M12 20v1"}],["path",{d:"M3 12h1"}],["path",{d:"M20 12h1"}],["path",{d:"m18.364 5.636-.707.707"}],["path",{d:"m6.343 17.657-.707.707"}],["path",{d:"m5.636 5.636.707.707"}],["path",{d:"m17.657 17.657.707.707"}]]];const ml=["svg",a,[["path",{d:"M12 8a2.83 2.83 0 0 0 4 4 4 4 0 1 1-4-4"}],["path",{d:"M12 2v2"}],["path",{d:"M12 20v2"}],["path",{d:"m4.9 4.9 1.4 1.4"}],["path",{d:"m17.7 17.7 1.4 1.4"}],["path",{d:"M2 12h2"}],["path",{d:"M20 12h2"}],["path",{d:"m6.3 17.7-1.4 1.4"}],["path",{d:"m19.1 4.9-1.4 1.4"}]]];const Hl=["svg",a,[["path",{d:"M10 9a3 3 0 1 0 0 6"}],["path",{d:"M2 12h1"}],["path",{d:"M14 21V3"}],["path",{d:"M10 4V3"}],["path",{d:"M10 21v-1"}],["path",{d:"m3.64 18.36.7-.7"}],["path",{d:"m4.34 6.34-.7-.7"}],["path",{d:"M14 12h8"}],["path",{d:"m17 4-3 3"}],["path",{d:"m14 17 3 3"}],["path",{d:"m21 15-3-3 3-3"}]]];const Vl=["svg",a,[["circle",{cx:"12",cy:"12",r:"4"}],["path",{d:"M12 2v2"}],["path",{d:"M12 20v2"}],["path",{d:"m4.93 4.93 1.41 1.41"}],["path",{d:"m17.66 17.66 1.41 1.41"}],["path",{d:"M2 12h2"}],["path",{d:"M20 12h2"}],["path",{d:"m6.34 17.66-1.41 1.41"}],["path",{d:"m19.07 4.93-1.41 1.41"}]]];const Cl=["svg",a,[["path",{d:"M12 2v8"}],["path",{d:"m4.93 10.93 1.41 1.41"}],["path",{d:"M2 18h2"}],["path",{d:"M20 18h2"}],["path",{d:"m19.07 10.93-1.41 1.41"}],["path",{d:"M22 22H2"}],["path",{d:"m8 6 4-4 4 4"}],["path",{d:"M16 18a4 4 0 0 0-8 0"}]]];const wl=["svg",a,[["path",{d:"M12 10V2"}],["path",{d:"m4.93 10.93 1.41 1.41"}],["path",{d:"M2 18h2"}],["path",{d:"M20 18h2"}],["path",{d:"m19.07 10.93-1.41 1.41"}],["path",{d:"M22 22H2"}],["path",{d:"m16 6-4 4-4-4"}],["path",{d:"M16 18a4 4 0 0 0-8 0"}]]];const ul=["svg",a,[["path",{d:"m4 19 8-8"}],["path",{d:"m12 19-8-8"}],["path",{d:"M20 12h-4c0-1.5.442-2 1.5-2.5S20 8.334 20 7.002c0-.472-.17-.93-.484-1.29a2.105 2.105 0 0 0-2.617-.436c-.42.239-.738.614-.899 1.06"}]]];const Al=["svg",a,[["path",{d:"M11 17a4 4 0 0 1-8 0V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2Z"}],["path",{d:"M16.7 13H19a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H7"}],["path",{d:"M 7 17h.01"}],["path",{d:"m11 8 2.3-2.3a2.4 2.4 0 0 1 3.404.004L18.6 7.6a2.4 2.4 0 0 1 .026 3.434L9.9 19.8"}]]];const Ll=["svg",a,[["path",{d:"M10 21V3h8"}],["path",{d:"M6 16h9"}],["path",{d:"M10 9.5h7"}]]];const Sl=["svg",a,[["path",{d:"M11 19H4a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h5"}],["path",{d:"M13 5h7a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2h-5"}],["circle",{cx:"12",cy:"12",r:"3"}],["path",{d:"m18 22-3-3 3-3"}],["path",{d:"m6 2 3 3-3 3"}]]];const fl=["svg",a,[["polyline",{points:"14.5 17.5 3 6 3 3 6 3 17.5 14.5"}],["line",{x1:"13",x2:"19",y1:"19",y2:"13"}],["line",{x1:"16",x2:"20",y1:"16",y2:"20"}],["line",{x1:"19",x2:"21",y1:"21",y2:"19"}]]];const Zl=["svg",a,[["polyline",{points:"14.5 17.5 3 6 3 3 6 3 17.5 14.5"}],["line",{x1:"13",x2:"19",y1:"19",y2:"13"}],["line",{x1:"16",x2:"20",y1:"16",y2:"20"}],["line",{x1:"19",x2:"21",y1:"21",y2:"19"}],["polyline",{points:"14.5 6.5 18 3 21 3 21 6 17.5 9.5"}],["line",{x1:"5",x2:"9",y1:"14",y2:"18"}],["line",{x1:"7",x2:"4",y1:"17",y2:"20"}],["line",{x1:"3",x2:"5",y1:"19",y2:"21"}]]];const Pl=["svg",a,[["path",{d:"m18 2 4 4"}],["path",{d:"m17 7 3-3"}],["path",{d:"M19 9 8.7 19.3c-1 1-2.5 1-3.4 0l-.6-.6c-1-1-1-2.5 0-3.4L15 5"}],["path",{d:"m9 11 4 4"}],["path",{d:"m5 19-3 3"}],["path",{d:"m14 4 6 6"}]]];const kl=["svg",a,[["path",{d:"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18"}]]];const zl=["svg",a,[["path",{d:"M12 21v-6"}],["path",{d:"M12 9V3"}],["path",{d:"M3 15h18"}],["path",{d:"M3 9h18"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]];const Bl=["svg",a,[["path",{d:"M12 15V9"}],["path",{d:"M3 15h18"}],["path",{d:"M3 9h18"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]]];const Fl=["svg",a,[["path",{d:"M14 14v2"}],["path",{d:"M14 20v2"}],["path",{d:"M14 2v2"}],["path",{d:"M14 8v2"}],["path",{d:"M2 15h8"}],["path",{d:"M2 3h6a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H2"}],["path",{d:"M2 9h8"}],["path",{d:"M22 15h-4"}],["path",{d:"M22 3h-2a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h2"}],["path",{d:"M22 9h-4"}],["path",{d:"M5 3v18"}]]];const Dl=["svg",a,[["path",{d:"M16 12H3"}],["path",{d:"M16 18H3"}],["path",{d:"M16 6H3"}],["path",{d:"M21 12h.01"}],["path",{d:"M21 18h.01"}],["path",{d:"M21 6h.01"}]]];const ql=["svg",a,[["path",{d:"M15 3v18"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M21 9H3"}],["path",{d:"M21 15H3"}]]];const Rl=["svg",a,[["path",{d:"M14 10h2"}],["path",{d:"M15 22v-8"}],["path",{d:"M15 2v4"}],["path",{d:"M2 10h2"}],["path",{d:"M20 10h2"}],["path",{d:"M3 19h18"}],["path",{d:"M3 22v-6a2 2 135 0 1 2-2h14a2 2 45 0 1 2 2v6"}],["path",{d:"M3 2v2a2 2 45 0 0 2 2h14a2 2 135 0 0 2-2V2"}],["path",{d:"M8 10h2"}],["path",{d:"M9 22v-8"}],["path",{d:"M9 2v4"}]]];const bl=["svg",a,[["path",{d:"M12 3v18"}],["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9h18"}],["path",{d:"M3 15h18"}]]];const Tl=["svg",a,[["rect",{width:"10",height:"14",x:"3",y:"8",rx:"2"}],["path",{d:"M5 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v16a2 2 0 0 1-2 2h-2.4"}],["path",{d:"M8 18h.01"}]]];const Ul=["svg",a,[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2",ry:"2"}],["line",{x1:"12",x2:"12.01",y1:"18",y2:"18"}]]];const Ol=["svg",a,[["circle",{cx:"7",cy:"7",r:"5"}],["circle",{cx:"17",cy:"17",r:"5"}],["path",{d:"M12 17h10"}],["path",{d:"m3.46 10.54 7.08-7.08"}]]];const Il=["svg",a,[["path",{d:"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"}],["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor"}]]];const El=["svg",a,[["path",{d:"m15 5 6.3 6.3a2.4 2.4 0 0 1 0 3.4L17 19"}],["path",{d:"M9.586 5.586A2 2 0 0 0 8.172 5H3a1 1 0 0 0-1 1v5.172a2 2 0 0 0 .586 1.414L8.29 18.29a2.426 2.426 0 0 0 3.42 0l3.58-3.58a2.426 2.426 0 0 0 0-3.42z"}],["circle",{cx:"6.5",cy:"9.5",r:".5",fill:"currentColor"}]]];const Gl=["svg",a,[["path",{d:"M4 4v16"}]]];const Wl=["svg",a,[["path",{d:"M4 4v16"}],["path",{d:"M9 4v16"}]]];const Xl=["svg",a,[["path",{d:"M4 4v16"}],["path",{d:"M9 4v16"}],["path",{d:"M14 4v16"}]]];const Nl=["svg",a,[["path",{d:"M4 4v16"}],["path",{d:"M9 4v16"}],["path",{d:"M14 4v16"}],["path",{d:"M19 4v16"}]]];const Kl=["svg",a,[["path",{d:"M4 4v16"}],["path",{d:"M9 4v16"}],["path",{d:"M14 4v16"}],["path",{d:"M19 4v16"}],["path",{d:"M22 6 2 18"}]]];const Jl=["svg",a,[["circle",{cx:"17",cy:"4",r:"2"}],["path",{d:"M15.59 5.41 5.41 15.59"}],["circle",{cx:"4",cy:"17",r:"2"}],["path",{d:"M12 22s-4-9-1.5-11.5S22 12 22 12"}]]];const jl=["svg",a,[["circle",{cx:"12",cy:"12",r:"10"}],["circle",{cx:"12",cy:"12",r:"6"}],["circle",{cx:"12",cy:"12",r:"2"}]]];const Ql=["svg",a,[["path",{d:"m10.065 12.493-6.18 1.318a.934.934 0 0 1-1.108-.702l-.537-2.15a1.07 1.07 0 0 1 .691-1.265l13.504-4.44"}],["path",{d:"m13.56 11.747 4.332-.924"}],["path",{d:"m16 21-3.105-6.21"}],["path",{d:"M16.485 5.94a2 2 0 0 1 1.455-2.425l1.09-.272a1 1 0 0 1 1.212.727l1.515 6.06a1 1 0 0 1-.727 1.213l-1.09.272a2 2 0 0 1-2.425-1.455z"}],["path",{d:"m6.158 8.633 1.114 4.456"}],["path",{d:"m8 21 3.105-6.21"}],["circle",{cx:"12",cy:"13",r:"2"}]]];const _l=["svg",a,[["circle",{cx:"4",cy:"4",r:"2"}],["path",{d:"m14 5 3-3 3 3"}],["path",{d:"m14 10 3-3 3 3"}],["path",{d:"M17 14V2"}],["path",{d:"M17 14H7l-5 8h20Z"}],["path",{d:"M8 14v8"}],["path",{d:"m9 14 5 8"}]]];const Yl=["svg",a,[["path",{d:"M3.5 21 14 3"}],["path",{d:"M20.5 21 10 3"}],["path",{d:"M15.5 21 12 15l-3.5 6"}],["path",{d:"M2 21h20"}]]];const $l=["svg",a,[["polyline",{points:"4 17 10 11 4 5"}],["line",{x1:"12",x2:"20",y1:"19",y2:"19"}]]];const u0=["svg",a,[["path",{d:"M21 7 6.82 21.18a2.83 2.83 0 0 1-3.99-.01a2.83 2.83 0 0 1 0-4L17 3"}],["path",{d:"m16 2 6 6"}],["path",{d:"M12 16H4"}]]];const ag=["svg",a,[["path",{d:"M14.5 2v17.5c0 1.4-1.1 2.5-2.5 2.5c-1.4 0-2.5-1.1-2.5-2.5V2"}],["path",{d:"M8.5 2h7"}],["path",{d:"M14.5 16h-5"}]]];const tg=["svg",a,[["path",{d:"M9 2v17.5A2.5 2.5 0 0 1 6.5 22A2.5 2.5 0 0 1 4 19.5V2"}],["path",{d:"M20 2v17.5a2.5 2.5 0 0 1-2.5 2.5a2.5 2.5 0 0 1-2.5-2.5V2"}],["path",{d:"M3 2h7"}],["path",{d:"M14 2h7"}],["path",{d:"M9 16H4"}],["path",{d:"M20 16h-5"}]]];const hg=["svg",a,[["path",{d:"M5 4h1a3 3 0 0 1 3 3 3 3 0 0 1 3-3h1"}],["path",{d:"M13 20h-1a3 3 0 0 1-3-3 3 3 0 0 1-3 3H5"}],["path",{d:"M5 16H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h1"}],["path",{d:"M13 8h7a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-7"}],["path",{d:"M9 7v10"}]]];const dg=["svg",a,[["path",{d:"M17 22h-1a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h1"}],["path",{d:"M7 22h1a4 4 0 0 0 4-4v-1"}],["path",{d:"M7 2h1a4 4 0 0 1 4 4v1"}]]];const pg=["svg",a,[["path",{d:"M17 6H3"}],["path",{d:"M21 12H8"}],["path",{d:"M21 18H8"}],["path",{d:"M3 12v6"}]]];const cg=["svg",a,[["path",{d:"M21 6H3"}],["path",{d:"M10 12H3"}],["path",{d:"M10 18H3"}],["circle",{cx:"17",cy:"15",r:"3"}],["path",{d:"m21 19-1.9-1.9"}]]];const A0=["svg",a,[["path",{d:"M5 3a2 2 0 0 0-2 2"}],["path",{d:"M19 3a2 2 0 0 1 2 2"}],["path",{d:"M21 19a2 2 0 0 1-2 2"}],["path",{d:"M5 21a2 2 0 0 1-2-2"}],["path",{d:"M9 3h1"}],["path",{d:"M9 21h1"}],["path",{d:"M14 3h1"}],["path",{d:"M14 21h1"}],["path",{d:"M3 9v1"}],["path",{d:"M21 9v1"}],["path",{d:"M3 14v1"}],["path",{d:"M21 14v1"}],["line",{x1:"7",x2:"15",y1:"8",y2:"8"}],["line",{x1:"7",x2:"17",y1:"12",y2:"12"}],["line",{x1:"7",x2:"13",y1:"16",y2:"16"}]]];const Mg=["svg",a,[["path",{d:"M17 6.1H3"}],["path",{d:"M21 12.1H3"}],["path",{d:"M15.1 18H3"}]]];const sg=["svg",a,[["path",{d:"M2 10s3-3 3-8"}],["path",{d:"M22 10s-3-3-3-8"}],["path",{d:"M10 2c0 4.4-3.6 8-8 8"}],["path",{d:"M14 2c0 4.4 3.6 8 8 8"}],["path",{d:"M2 10s2 2 2 5"}],["path",{d:"M22 10s-2 2-2 5"}],["path",{d:"M8 15h8"}],["path",{d:"M2 22v-1a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1"}],["path",{d:"M14 22v-1a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v1"}]]];const eg=["svg",a,[["path",{d:"M2 12h10"}],["path",{d:"M9 4v16"}],["path",{d:"m3 9 3 3-3 3"}],["path",{d:"M12 6 9 9 6 6"}],["path",{d:"m6 18 3-3 1.5 1.5"}],["path",{d:"M20 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z"}]]];const rg=["svg",a,[["path",{d:"M12 9a4 4 0 0 0-2 7.5"}],["path",{d:"M12 3v2"}],["path",{d:"m6.6 18.4-1.4 1.4"}],["path",{d:"M20 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z"}],["path",{d:"M4 13H2"}],["path",{d:"M6.34 7.34 4.93 5.93"}]]];const vg=["svg",a,[["path",{d:"M14 4v10.54a4 4 0 1 1-4 0V4a2 2 0 0 1 4 0Z"}]]];const ng=["svg",a,[["path",{d:"M17 14V2"}],["path",{d:"M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22a3.13 3.13 0 0 1-3-3.88Z"}]]];const og=["svg",a,[["path",{d:"M7 10v12"}],["path",{d:"M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z"}]]];const ig=["svg",a,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"m9 12 2 2 4-4"}]]];const lg=["svg",a,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M9 12h6"}]]];const gg=["svg",a,[["path",{d:"M2 9a3 3 0 1 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 1 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M9 9h.01"}],["path",{d:"m15 9-6 6"}],["path",{d:"M15 15h.01"}]]];const xg=["svg",a,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M9 12h6"}],["path",{d:"M12 9v6"}]]];const yg=["svg",a,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"m9.5 14.5 5-5"}]]];const mg=["svg",a,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"m9.5 14.5 5-5"}],["path",{d:"m9.5 9.5 5 5"}]]];const Hg=["svg",a,[["path",{d:"M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z"}],["path",{d:"M13 5v2"}],["path",{d:"M13 17v2"}],["path",{d:"M13 11v2"}]]];const Vg=["svg",a,[["path",{d:"M10.5 17h1.227a2 2 0 0 0 1.345-.52L18 12"}],["path",{d:"m12 13.5 3.75.5"}],["path",{d:"m4.5 8 10.58-5.06a1 1 0 0 1 1.342.488L18.5 8"}],["path",{d:"M6 10V8"}],["path",{d:"M6 14v1"}],["path",{d:"M6 19v2"}],["rect",{x:"2",y:"8",width:"20",height:"13",rx:"2"}]]];const Cg=["svg",a,[["path",{d:"m4.5 8 10.58-5.06a1 1 0 0 1 1.342.488L18.5 8"}],["path",{d:"M6 10V8"}],["path",{d:"M6 14v1"}],["path",{d:"M6 19v2"}],["rect",{x:"2",y:"8",width:"20",height:"13",rx:"2"}]]];const wg=["svg",a,[["path",{d:"M10 2h4"}],["path",{d:"M4.6 11a8 8 0 0 0 1.7 8.7 8 8 0 0 0 8.7 1.7"}],["path",{d:"M7.4 7.4a8 8 0 0 1 10.3 1 8 8 0 0 1 .9 10.2"}],["path",{d:"m2 2 20 20"}],["path",{d:"M12 12v-2"}]]];const ug=["svg",a,[["path",{d:"M10 2h4"}],["path",{d:"M12 14v-4"}],["path",{d:"M4 13a8 8 0 0 1 8-7 8 8 0 1 1-5.3 14L4 17.6"}],["path",{d:"M9 17H4v5"}]]];const Ag=["svg",a,[["line",{x1:"10",x2:"14",y1:"2",y2:"2"}],["line",{x1:"12",x2:"15",y1:"14",y2:"11"}],["circle",{cx:"12",cy:"14",r:"8"}]]];const Lg=["svg",a,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"6",ry:"6"}],["circle",{cx:"8",cy:"12",r:"2"}]]];const Sg=["svg",a,[["rect",{width:"20",height:"12",x:"2",y:"6",rx:"6",ry:"6"}],["circle",{cx:"16",cy:"12",r:"2"}]]];const fg=["svg",a,[["path",{d:"M21 4H3"}],["path",{d:"M18 8H6"}],["path",{d:"M19 12H9"}],["path",{d:"M16 16h-6"}],["path",{d:"M11 20H9"}]]];const Zg=["svg",a,[["ellipse",{cx:"12",cy:"11",rx:"3",ry:"2"}],["ellipse",{cx:"12",cy:"12.5",rx:"10",ry:"8.5"}]]];const Pg=["svg",a,[["path",{d:"M4 4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16"}],["path",{d:"M2 14h12"}],["path",{d:"M22 14h-2"}],["path",{d:"M12 20v-6"}],["path",{d:"m2 2 20 20"}],["path",{d:"M22 16V6a2 2 0 0 0-2-2H10"}]]];const kg=["svg",a,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M2 14h20"}],["path",{d:"M12 20v-6"}]]];const zg=["svg",a,[["path",{d:"M18.2 12.27 20 6H4l1.8 6.27a1 1 0 0 0 .95.73h10.5a1 1 0 0 0 .96-.73Z"}],["path",{d:"M8 13v9"}],["path",{d:"M16 22v-9"}],["path",{d:"m9 6 1 7"}],["path",{d:"m15 6-1 7"}],["path",{d:"M12 6V2"}],["path",{d:"M13 2h-2"}]]];const Bg=["svg",a,[["rect",{width:"18",height:"12",x:"3",y:"8",rx:"1"}],["path",{d:"M10 8V5c0-.6-.4-1-1-1H6a1 1 0 0 0-1 1v3"}],["path",{d:"M19 8V5c0-.6-.4-1-1-1h-3a1 1 0 0 0-1 1v3"}]]];const Fg=["svg",a,[["path",{d:"m10 11 11 .9a1 1 0 0 1 .8 1.1l-.665 4.158a1 1 0 0 1-.988.842H20"}],["path",{d:"M16 18h-5"}],["path",{d:"M18 5a1 1 0 0 0-1 1v5.573"}],["path",{d:"M3 4h8.129a1 1 0 0 1 .99.863L13 11.246"}],["path",{d:"M4 11V4"}],["path",{d:"M7 15h.01"}],["path",{d:"M8 10.1V4"}],["circle",{cx:"18",cy:"18",r:"2"}],["circle",{cx:"7",cy:"15",r:"5"}]]];const Dg=["svg",a,[["path",{d:"M9.3 6.2a4.55 4.55 0 0 0 5.4 0"}],["path",{d:"M7.9 10.7c.9.8 2.4 1.3 4.1 1.3s3.2-.5 4.1-1.3"}],["path",{d:"M13.9 3.5a1.93 1.93 0 0 0-3.8-.1l-3 10c-.1.2-.1.4-.1.6 0 1.7 2.2 3 5 3s5-1.3 5-3c0-.2 0-.4-.1-.5Z"}],["path",{d:"m7.5 12.2-4.7 2.7c-.5.3-.8.7-.8 1.1s.3.8.8 1.1l7.6 4.5c.9.5 2.1.5 3 0l7.6-4.5c.7-.3 1-.7 1-1.1s-.3-.8-.8-1.1l-4.7-2.8"}]]];const qg=["svg",a,[["path",{d:"M2 22V12a10 10 0 1 1 20 0v10"}],["path",{d:"M15 6.8v1.4a3 2.8 0 1 1-6 0V6.8"}],["path",{d:"M10 15h.01"}],["path",{d:"M14 15h.01"}],["path",{d:"M10 19a4 4 0 0 1-4-4v-3a6 6 0 1 1 12 0v3a4 4 0 0 1-4 4Z"}],["path",{d:"m9 19-2 3"}],["path",{d:"m15 19 2 3"}]]];const Rg=["svg",a,[["path",{d:"M8 3.1V7a4 4 0 0 0 8 0V3.1"}],["path",{d:"m9 15-1-1"}],["path",{d:"m15 15 1-1"}],["path",{d:"M9 19c-2.8 0-5-2.2-5-5v-4a8 8 0 0 1 16 0v4c0 2.8-2.2 5-5 5Z"}],["path",{d:"m8 19-2 3"}],["path",{d:"m16 19 2 3"}]]];const bg=["svg",a,[["path",{d:"M2 17 17 2"}],["path",{d:"m2 14 8 8"}],["path",{d:"m5 11 8 8"}],["path",{d:"m8 8 8 8"}],["path",{d:"m11 5 8 8"}],["path",{d:"m14 2 8 8"}],["path",{d:"M7 22 22 7"}]]];const L0=["svg",a,[["rect",{width:"16",height:"16",x:"4",y:"3",rx:"2"}],["path",{d:"M4 11h16"}],["path",{d:"M12 3v8"}],["path",{d:"m8 19-2 3"}],["path",{d:"m18 22-2-3"}],["path",{d:"M8 15h.01"}],["path",{d:"M16 15h.01"}]]];const Tg=["svg",a,[["path",{d:"M3 6h18"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"}],["line",{x1:"10",x2:"10",y1:"11",y2:"17"}],["line",{x1:"14",x2:"14",y1:"11",y2:"17"}]]];const Ug=["svg",a,[["path",{d:"M3 6h18"}],["path",{d:"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"}],["path",{d:"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"}]]];const Og=["svg",a,[["path",{d:"M8 19a4 4 0 0 1-2.24-7.32A3.5 3.5 0 0 1 9 6.03V6a3 3 0 1 1 6 0v.04a3.5 3.5 0 0 1 3.24 5.65A4 4 0 0 1 16 19Z"}],["path",{d:"M12 19v3"}]]];const S0=["svg",a,[["path",{d:"M13 8c0-2.76-2.46-5-5.5-5S2 5.24 2 8h2l1-1 1 1h4"}],["path",{d:"M13 7.14A5.82 5.82 0 0 1 16.5 6c3.04 0 5.5 2.24 5.5 5h-3l-1-1-1 1h-3"}],["path",{d:"M5.89 9.71c-2.15 2.15-2.3 5.47-.35 7.43l4.24-4.25.7-.7.71-.71 2.12-2.12c-1.95-1.96-5.27-1.8-7.42.35"}],["path",{d:"M11 15.5c.5 2.5-.17 4.5-1 6.5h4c2-5.5-.5-12-1-14"}]]];const Ig=["svg",a,[["path",{d:"m17 14 3 3.3a1 1 0 0 1-.7 1.7H4.7a1 1 0 0 1-.7-1.7L7 14h-.3a1 1 0 0 1-.7-1.7L9 9h-.2A1 1 0 0 1 8 7.3L12 3l4 4.3a1 1 0 0 1-.8 1.7H15l3 3.3a1 1 0 0 1-.7 1.7H17Z"}],["path",{d:"M12 22v-3"}]]];const Eg=["svg",a,[["path",{d:"M10 10v.2A3 3 0 0 1 8.9 16H5a3 3 0 0 1-1-5.8V10a3 3 0 0 1 6 0Z"}],["path",{d:"M7 16v6"}],["path",{d:"M13 19v3"}],["path",{d:"M12 19h8.3a1 1 0 0 0 .7-1.7L18 14h.3a1 1 0 0 0 .7-1.7L16 9h.2a1 1 0 0 0 .8-1.7L13 3l-1.4 1.5"}]]];const Gg=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}],["rect",{width:"3",height:"9",x:"7",y:"7"}],["rect",{width:"3",height:"5",x:"14",y:"7"}]]];const Wg=["svg",a,[["polyline",{points:"22 17 13.5 8.5 8.5 13.5 2 7"}],["polyline",{points:"16 17 22 17 22 11"}]]];const Xg=["svg",a,[["polyline",{points:"22 7 13.5 15.5 8.5 10.5 2 17"}],["polyline",{points:"16 7 22 7 22 13"}]]];const f0=["svg",a,[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"}],["path",{d:"M12 9v4"}],["path",{d:"M12 17h.01"}]]];const Ng=["svg",a,[["path",{d:"M22 18a2 2 0 0 1-2 2H3c-1.1 0-1.3-.6-.4-1.3L20.4 4.3c.9-.7 1.6-.4 1.6.7Z"}]]];const Kg=["svg",a,[["path",{d:"M13.73 4a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"}]]];const Jg=["svg",a,[["path",{d:"M6 9H4.5a2.5 2.5 0 0 1 0-5H6"}],["path",{d:"M18 9h1.5a2.5 2.5 0 0 0 0-5H18"}],["path",{d:"M4 22h16"}],["path",{d:"M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"}],["path",{d:"M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"}],["path",{d:"M18 2H6v7a6 6 0 0 0 12 0V2Z"}]]];const jg=["svg",a,[["path",{d:"M14 18V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v11a1 1 0 0 0 1 1h2"}],["path",{d:"M15 18H9"}],["path",{d:"M19 18h2a1 1 0 0 0 1-1v-3.65a1 1 0 0 0-.22-.624l-3.48-4.35A1 1 0 0 0 17.52 8H14"}],["circle",{cx:"17",cy:"18",r:"2"}],["circle",{cx:"7",cy:"18",r:"2"}]]];const Qg=["svg",a,[["path",{d:"m12 10 2 4v3a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-3a8 8 0 1 0-16 0v3a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-3l2-4h4Z"}],["path",{d:"M4.82 7.9 8 10"}],["path",{d:"M15.18 7.9 12 10"}],["path",{d:"M16.93 10H20a2 2 0 0 1 0 4H2"}]]];const _g=["svg",a,[["path",{d:"M10 7.75a.75.75 0 0 1 1.142-.638l3.664 2.249a.75.75 0 0 1 0 1.278l-3.664 2.25a.75.75 0 0 1-1.142-.64z"}],["path",{d:"M7 21h10"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}]]];const Z0=["svg",a,[["path",{d:"M7 21h10"}],["rect",{width:"20",height:"14",x:"2",y:"3",rx:"2"}]]];const Yg=["svg",a,[["rect",{width:"20",height:"15",x:"2",y:"7",rx:"2",ry:"2"}],["polyline",{points:"17 2 12 7 7 2"}]]];const $g=["svg",a,[["path",{d:"M21 2H3v16h5v4l4-4h5l4-4V2zm-10 9V7m5 4V7"}]]];const ax=["svg",a,[["path",{d:"M22 4s-.7 2.1-2 3.4c1.6 10-9.4 17.3-18 11.6 2.2.1 4.4-.6 6-2C3 15.5.5 9.6 3 5c2.2 2.6 5.6 4.1 9 4-.9-4.2 4-6.6 7-3.8 1.1 0 3-1.2 3-1.2z"}]]];const tx=["svg",a,[["path",{d:"M14 16.5a.5.5 0 0 0 .5.5h.5a2 2 0 0 1 0 4H9a2 2 0 0 1 0-4h.5a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5V8a2 2 0 0 1-4 0V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v3a2 2 0 0 1-4 0v-.5a.5.5 0 0 0-.5-.5h-3a.5.5 0 0 0-.5.5Z"}]]];const hx=["svg",a,[["polyline",{points:"4 7 4 4 20 4 20 7"}],["line",{x1:"9",x2:"15",y1:"20",y2:"20"}],["line",{x1:"12",x2:"12",y1:"4",y2:"20"}]]];const dx=["svg",a,[["path",{d:"M12 2v1"}],["path",{d:"M15.5 21a1.85 1.85 0 0 1-3.5-1v-8H2a10 10 0 0 1 3.428-6.575"}],["path",{d:"M17.5 12H22A10 10 0 0 0 9.004 3.455"}],["path",{d:"m2 2 20 20"}]]];const px=["svg",a,[["path",{d:"M22 12a10.06 10.06 1 0 0-20 0Z"}],["path",{d:"M12 12v8a2 2 0 0 0 4 0"}],["path",{d:"M12 2v1"}]]];const cx=["svg",a,[["path",{d:"M6 4v6a6 6 0 0 0 12 0V4"}],["line",{x1:"4",x2:"20",y1:"20",y2:"20"}]]];const Mx=["svg",a,[["path",{d:"M9 14 4 9l5-5"}],["path",{d:"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11"}]]];const sx=["svg",a,[["circle",{cx:"12",cy:"17",r:"1"}],["path",{d:"M3 7v6h6"}],["path",{d:"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"}]]];const ex=["svg",a,[["path",{d:"M3 7v6h6"}],["path",{d:"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"}]]];const rx=["svg",a,[["path",{d:"M16 12h6"}],["path",{d:"M8 12H2"}],["path",{d:"M12 2v2"}],["path",{d:"M12 8v2"}],["path",{d:"M12 14v2"}],["path",{d:"M12 20v2"}],["path",{d:"m19 15 3-3-3-3"}],["path",{d:"m5 9-3 3 3 3"}]]];const vx=["svg",a,[["path",{d:"M12 22v-6"}],["path",{d:"M12 8V2"}],["path",{d:"M4 12H2"}],["path",{d:"M10 12H8"}],["path",{d:"M16 12h-2"}],["path",{d:"M22 12h-2"}],["path",{d:"m15 19-3 3-3-3"}],["path",{d:"m15 5-3-3-3 3"}]]];const nx=["svg",a,[["rect",{width:"8",height:"6",x:"5",y:"4",rx:"1"}],["rect",{width:"8",height:"6",x:"11",y:"14",rx:"1"}]]];const P0=["svg",a,[["circle",{cx:"12",cy:"10",r:"1"}],["path",{d:"M22 20V8h-4l-6-4-6 4H2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2"}],["path",{d:"M6 17v.01"}],["path",{d:"M6 13v.01"}],["path",{d:"M18 17v.01"}],["path",{d:"M18 13v.01"}],["path",{d:"M14 22v-5a2 2 0 0 0-2-2a2 2 0 0 0-2 2v5"}]]];const ox=["svg",a,[["path",{d:"M15 7h2a5 5 0 0 1 0 10h-2m-6 0H7A5 5 0 0 1 7 7h2"}]]];const ix=["svg",a,[["path",{d:"m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71"}],["path",{d:"m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71"}],["line",{x1:"8",x2:"8",y1:"2",y2:"5"}],["line",{x1:"2",x2:"5",y1:"8",y2:"8"}],["line",{x1:"16",x2:"16",y1:"19",y2:"22"}],["line",{x1:"19",x2:"22",y1:"16",y2:"16"}]]];const lx=["svg",a,[["path",{d:"m19 5 3-3"}],["path",{d:"m2 22 3-3"}],["path",{d:"M6.3 20.3a2.4 2.4 0 0 0 3.4 0L12 18l-6-6-2.3 2.3a2.4 2.4 0 0 0 0 3.4Z"}],["path",{d:"M7.5 13.5 10 11"}],["path",{d:"M10.5 16.5 13 14"}],["path",{d:"m12 6 6 6 2.3-2.3a2.4 2.4 0 0 0 0-3.4l-2.6-2.6a2.4 2.4 0 0 0-3.4 0Z"}]]];const gx=["svg",a,[["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"}],["polyline",{points:"17 8 12 3 7 8"}],["line",{x1:"12",x2:"12",y1:"3",y2:"15"}]]];const xx=["svg",a,[["circle",{cx:"10",cy:"7",r:"1"}],["circle",{cx:"4",cy:"20",r:"1"}],["path",{d:"M4.7 19.3 19 5"}],["path",{d:"m21 3-3 1 2 2Z"}],["path",{d:"M9.26 7.68 5 12l2 5"}],["path",{d:"m10 14 5 2 3.5-3.5"}],["path",{d:"m18 12 1-1 1 1-1 1Z"}]]];const yx=["svg",a,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["polyline",{points:"16 11 18 13 22 9"}]]];const mx=["svg",a,[["circle",{cx:"18",cy:"15",r:"3"}],["circle",{cx:"9",cy:"7",r:"4"}],["path",{d:"M10 15H6a4 4 0 0 0-4 4v2"}],["path",{d:"m21.7 16.4-.9-.3"}],["path",{d:"m15.2 13.9-.9-.3"}],["path",{d:"m16.6 18.7.3-.9"}],["path",{d:"m19.1 12.2.3-.9"}],["path",{d:"m19.6 18.7-.4-1"}],["path",{d:"m16.8 12.3-.4-1"}],["path",{d:"m14.3 16.6 1-.4"}],["path",{d:"m20.7 13.8 1-.4"}]]];const Hx=["svg",a,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11"}]]];const Vx=["svg",a,[["path",{d:"M11.5 15H7a4 4 0 0 0-4 4v2"}],["path",{d:"M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}],["circle",{cx:"10",cy:"7",r:"4"}]]];const Cx=["svg",a,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["line",{x1:"19",x2:"19",y1:"8",y2:"14"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11"}]]];const k0=["svg",a,[["path",{d:"M2 21a8 8 0 0 1 13.292-6"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"m16 19 2 2 4-4"}]]];const z0=["svg",a,[["path",{d:"M2 21a8 8 0 0 1 10.434-7.62"}],["circle",{cx:"10",cy:"8",r:"5"}],["circle",{cx:"18",cy:"18",r:"3"}],["path",{d:"m19.5 14.3-.4.9"}],["path",{d:"m16.9 20.8-.4.9"}],["path",{d:"m21.7 19.5-.9-.4"}],["path",{d:"m15.2 16.9-.9-.4"}],["path",{d:"m21.7 16.5-.9.4"}],["path",{d:"m15.2 19.1-.9.4"}],["path",{d:"m19.5 21.7-.4-.9"}],["path",{d:"m16.9 15.2-.4-.9"}]]];const B0=["svg",a,[["path",{d:"M2 21a8 8 0 0 1 13.292-6"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"M22 19h-6"}]]];const wx=["svg",a,[["path",{d:"M2 21a8 8 0 0 1 10.821-7.487"}],["path",{d:"M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"}],["circle",{cx:"10",cy:"8",r:"5"}]]];const F0=["svg",a,[["path",{d:"M2 21a8 8 0 0 1 13.292-6"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"M19 16v6"}],["path",{d:"M22 19h-6"}]]];const ux=["svg",a,[["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"M2 21a8 8 0 0 1 10.434-7.62"}],["circle",{cx:"18",cy:"18",r:"3"}],["path",{d:"m22 22-1.9-1.9"}]]];const D0=["svg",a,[["path",{d:"M2 21a8 8 0 0 1 11.873-7"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"m17 17 5 5"}],["path",{d:"m22 17-5 5"}]]];const q0=["svg",a,[["circle",{cx:"12",cy:"8",r:"5"}],["path",{d:"M20 21a8 8 0 0 0-16 0"}]]];const Ax=["svg",a,[["circle",{cx:"10",cy:"7",r:"4"}],["path",{d:"M10.3 15H7a4 4 0 0 0-4 4v2"}],["circle",{cx:"17",cy:"17",r:"3"}],["path",{d:"m21 21-1.9-1.9"}]]];const Lx=["svg",a,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["line",{x1:"17",x2:"22",y1:"8",y2:"13"}],["line",{x1:"22",x2:"17",y1:"8",y2:"13"}]]];const Sx=["svg",a,[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"}],["circle",{cx:"12",cy:"7",r:"4"}]]];const R0=["svg",a,[["path",{d:"M18 21a8 8 0 0 0-16 0"}],["circle",{cx:"10",cy:"8",r:"5"}],["path",{d:"M22 20c0-3.37-2-6.5-4-8a5 5 0 0 0-.45-8.3"}]]];const fx=["svg",a,[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}],["circle",{cx:"9",cy:"7",r:"4"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87"}],["path",{d:"M16 3.13a4 4 0 0 1 0 7.75"}]]];const b0=["svg",a,[["path",{d:"m16 2-2.3 2.3a3 3 0 0 0 0 4.2l1.8 1.8a3 3 0 0 0 4.2 0L22 8"}],["path",{d:"M15 15 3.3 3.3a4.2 4.2 0 0 0 0 6l7.3 7.3c.7.7 2 .7 2.8 0L15 15Zm0 0 7 7"}],["path",{d:"m2.1 21.8 6.4-6.3"}],["path",{d:"m19 5-7 7"}]]];const T0=["svg",a,[["path",{d:"M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2"}],["path",{d:"M7 2v20"}],["path",{d:"M21 15V2a5 5 0 0 0-5 5v6c0 1.1.9 2 2 2h3Zm0 0v7"}]]];const Zx=["svg",a,[["path",{d:"M12 2v20"}],["path",{d:"M2 5h20"}],["path",{d:"M3 3v2"}],["path",{d:"M7 3v2"}],["path",{d:"M17 3v2"}],["path",{d:"M21 3v2"}],["path",{d:"m19 5-7 7-7-7"}]]];const Px=["svg",a,[["path",{d:"M8 21s-4-3-4-9 4-9 4-9"}],["path",{d:"M16 3s4 3 4 9-4 9-4 9"}],["line",{x1:"15",x2:"9",y1:"9",y2:"15"}],["line",{x1:"9",x2:"15",y1:"9",y2:"15"}]]];const kx=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["circle",{cx:"7.5",cy:"7.5",r:".5",fill:"currentColor"}],["path",{d:"m7.9 7.9 2.7 2.7"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor"}],["path",{d:"m13.4 10.6 2.7-2.7"}],["circle",{cx:"7.5",cy:"16.5",r:".5",fill:"currentColor"}],["path",{d:"m7.9 16.1 2.7-2.7"}],["circle",{cx:"16.5",cy:"16.5",r:".5",fill:"currentColor"}],["path",{d:"m13.4 13.4 2.7 2.7"}],["circle",{cx:"12",cy:"12",r:"2"}]]];const zx=["svg",a,[["path",{d:"M2 2a26.6 26.6 0 0 1 10 20c.9-6.82 1.5-9.5 4-14"}],["path",{d:"M16 8c4 0 6-2 6-6-4 0-6 2-6 6"}],["path",{d:"M17.41 3.6a10 10 0 1 0 3 3"}]]];const Bx=["svg",a,[["path",{d:"M2 12a5 5 0 0 0 5 5 8 8 0 0 1 5 2 8 8 0 0 1 5-2 5 5 0 0 0 5-5V7h-5a8 8 0 0 0-5 2 8 8 0 0 0-5-2H2Z"}],["path",{d:"M6 11c1.5 0 3 .5 3 2-2 0-3 0-3-2Z"}],["path",{d:"M18 11c-1.5 0-3 .5-3 2 2 0 3 0 3-2Z"}]]];const Fx=["svg",a,[["path",{d:"m2 8 2 2-2 2 2 2-2 2"}],["path",{d:"m22 8-2 2 2 2-2 2 2 2"}],["path",{d:"M8 8v10c0 .55.45 1 1 1h6c.55 0 1-.45 1-1v-2"}],["path",{d:"M16 10.34V6c0-.55-.45-1-1-1h-4.34"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const Dx=["svg",a,[["path",{d:"m2 8 2 2-2 2 2 2-2 2"}],["path",{d:"m22 8-2 2 2 2-2 2 2 2"}],["rect",{width:"8",height:"14",x:"8",y:"5",rx:"1"}]]];const qx=["svg",a,[["path",{d:"M10.66 6H14a2 2 0 0 1 2 2v2.5l5.248-3.062A.5.5 0 0 1 22 7.87v8.196"}],["path",{d:"M16 16a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h2"}],["path",{d:"m2 2 20 20"}]]];const Rx=["svg",a,[["path",{d:"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5"}],["rect",{x:"2",y:"6",width:"14",height:"12",rx:"2"}]]];const bx=["svg",a,[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2"}],["path",{d:"M2 8h20"}],["circle",{cx:"8",cy:"14",r:"2"}],["path",{d:"M8 12h8"}],["circle",{cx:"16",cy:"14",r:"2"}]]];const Tx=["svg",a,[["path",{d:"M21 17v2a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-2"}],["path",{d:"M21 7V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v2"}],["circle",{cx:"12",cy:"12",r:"1"}],["path",{d:"M18.944 12.33a1 1 0 0 0 0-.66 7.5 7.5 0 0 0-13.888 0 1 1 0 0 0 0 .66 7.5 7.5 0 0 0 13.888 0"}]]];const Ux=["svg",a,[["circle",{cx:"6",cy:"12",r:"4"}],["circle",{cx:"18",cy:"12",r:"4"}],["line",{x1:"6",x2:"18",y1:"16",y2:"16"}]]];const Ox=["svg",a,[["polygon",{points:"11 5 6 9 2 9 2 15 6 15 11 19 11 5"}],["path",{d:"M15.54 8.46a5 5 0 0 1 0 7.07"}]]];const Ix=["svg",a,[["polygon",{points:"11 5 6 9 2 9 2 15 6 15 11 19 11 5"}],["path",{d:"M15.54 8.46a5 5 0 0 1 0 7.07"}],["path",{d:"M19.07 4.93a10 10 0 0 1 0 14.14"}]]];const Ex=["svg",a,[["polygon",{points:"11 5 6 9 2 9 2 15 6 15 11 19 11 5"}],["line",{x1:"22",x2:"16",y1:"9",y2:"15"}],["line",{x1:"16",x2:"22",y1:"9",y2:"15"}]]];const Gx=["svg",a,[["polygon",{points:"11 5 6 9 2 9 2 15 6 15 11 19 11 5"}]]];const Wx=["svg",a,[["path",{d:"m9 12 2 2 4-4"}],["path",{d:"M5 7c0-1.1.9-2 2-2h10a2 2 0 0 1 2 2v12H5V7Z"}],["path",{d:"M22 19H2"}]]];const Xx=["svg",a,[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}],["path",{d:"M3 9a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2"}],["path",{d:"M3 11h3c.8 0 1.6.3 2.1.9l1.1.9c1.6 1.6 4.1 1.6 5.7 0l1.1-.9c.5-.5 1.3-.9 2.1-.9H21"}]]];const U0=["svg",a,[["path",{d:"M17 14h.01"}],["path",{d:"M7 7h12a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14"}]]];const Nx=["svg",a,[["path",{d:"M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1"}],["path",{d:"M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4"}]]];const Kx=["svg",a,[["circle",{cx:"8",cy:"9",r:"2"}],["path",{d:"m9 17 6.1-6.1a2 2 0 0 1 2.81.01L22 15V5a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2"}],["path",{d:"M8 21h8"}],["path",{d:"M12 17v4"}]]];const O0=["svg",a,[["path",{d:"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72"}],["path",{d:"m14 7 3 3"}],["path",{d:"M5 6v4"}],["path",{d:"M19 14v4"}],["path",{d:"M10 2v2"}],["path",{d:"M7 8H3"}],["path",{d:"M21 16h-4"}],["path",{d:"M11 3H9"}]]];const Jx=["svg",a,[["path",{d:"M15 4V2"}],["path",{d:"M15 16v-2"}],["path",{d:"M8 9h2"}],["path",{d:"M20 9h2"}],["path",{d:"M17.8 11.8 19 13"}],["path",{d:"M15 9h.01"}],["path",{d:"M17.8 6.2 19 5"}],["path",{d:"m3 21 9-9"}],["path",{d:"M12.2 6.2 11 5"}]]];const jx=["svg",a,[["path",{d:"M22 8.35V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V8.35A2 2 0 0 1 3.26 6.5l8-3.2a2 2 0 0 1 1.48 0l8 3.2A2 2 0 0 1 22 8.35Z"}],["path",{d:"M6 18h12"}],["path",{d:"M6 14h12"}],["rect",{width:"12",height:"12",x:"6",y:"10"}]]];const Qx=["svg",a,[["path",{d:"M3 6h3"}],["path",{d:"M17 6h.01"}],["rect",{width:"18",height:"20",x:"3",y:"2",rx:"2"}],["circle",{cx:"12",cy:"13",r:"5"}],["path",{d:"M12 18a2.5 2.5 0 0 0 0-5 2.5 2.5 0 0 1 0-5"}]]];const _x=["svg",a,[["circle",{cx:"12",cy:"12",r:"6"}],["polyline",{points:"12 10 12 12 13 13"}],["path",{d:"m16.13 7.66-.81-4.05a2 2 0 0 0-2-1.61h-2.68a2 2 0 0 0-2 1.61l-.78 4.05"}],["path",{d:"m7.88 16.36.8 4a2 2 0 0 0 2 1.61h2.72a2 2 0 0 0 2-1.61l.81-4.05"}]]];const Yx=["svg",a,[["path",{d:"M2 6c.6.5 1.2 1 2.5 1C7 7 7 5 9.5 5c2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M2 12c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}],["path",{d:"M2 18c.6.5 1.2 1 2.5 1 2.5 0 2.5-2 5-2 2.6 0 2.4 2 5 2 2.5 0 2.5-2 5-2 1.3 0 1.9.5 2.5 1"}]]];const $x=["svg",a,[["circle",{cx:"12",cy:"4.5",r:"2.5"}],["path",{d:"m10.2 6.3-3.9 3.9"}],["circle",{cx:"4.5",cy:"12",r:"2.5"}],["path",{d:"M7 12h10"}],["circle",{cx:"19.5",cy:"12",r:"2.5"}],["path",{d:"m13.8 17.7 3.9-3.9"}],["circle",{cx:"12",cy:"19.5",r:"2.5"}]]];const ay=["svg",a,[["circle",{cx:"12",cy:"10",r:"8"}],["circle",{cx:"12",cy:"10",r:"3"}],["path",{d:"M7 22h10"}],["path",{d:"M12 22v-4"}]]];const ty=["svg",a,[["path",{d:"M17 17h-5c-1.09-.02-1.94.92-2.5 1.9A3 3 0 1 1 2.57 15"}],["path",{d:"M9 3.4a4 4 0 0 1 6.52.66"}],["path",{d:"m6 17 3.1-5.8a2.5 2.5 0 0 0 .057-2.05"}],["path",{d:"M20.3 20.3a4 4 0 0 1-2.3.7"}],["path",{d:"M18.6 13a4 4 0 0 1 3.357 3.414"}],["path",{d:"m12 6 .6 1"}],["path",{d:"m2 2 20 20"}]]];const hy=["svg",a,[["path",{d:"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2"}],["path",{d:"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06"}],["path",{d:"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8"}]]];const dy=["svg",a,[["circle",{cx:"12",cy:"5",r:"3"}],["path",{d:"M6.5 8a2 2 0 0 0-1.905 1.46L2.1 18.5A2 2 0 0 0 4 21h16a2 2 0 0 0 1.925-2.54L19.4 9.5A2 2 0 0 0 17.48 8Z"}]]];const py=["svg",a,[["path",{d:"m2 22 10-10"}],["path",{d:"m16 8-1.17 1.17"}],["path",{d:"M3.47 12.53 5 11l1.53 1.53a3.5 3.5 0 0 1 0 4.94L5 19l-1.53-1.53a3.5 3.5 0 0 1 0-4.94Z"}],["path",{d:"m8 8-.53.53a3.5 3.5 0 0 0 0 4.94L9 15l1.53-1.53c.55-.55.88-1.25.98-1.97"}],["path",{d:"M10.91 5.26c.15-.26.34-.51.56-.73L13 3l1.53 1.53a3.5 3.5 0 0 1 .28 4.62"}],["path",{d:"M20 2h2v2a4 4 0 0 1-4 4h-2V6a4 4 0 0 1 4-4Z"}],["path",{d:"M11.47 17.47 13 19l-1.53 1.53a3.5 3.5 0 0 1-4.94 0L5 19l1.53-1.53a3.5 3.5 0 0 1 4.94 0Z"}],["path",{d:"m16 16-.53.53a3.5 3.5 0 0 1-4.94 0L9 15l1.53-1.53a3.49 3.49 0 0 1 1.97-.98"}],["path",{d:"M18.74 13.09c.26-.15.51-.34.73-.56L21 11l-1.53-1.53a3.5 3.5 0 0 0-4.62-.28"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const cy=["svg",a,[["path",{d:"M2 22 16 8"}],["path",{d:"M3.47 12.53 5 11l1.53 1.53a3.5 3.5 0 0 1 0 4.94L5 19l-1.53-1.53a3.5 3.5 0 0 1 0-4.94Z"}],["path",{d:"M7.47 8.53 9 7l1.53 1.53a3.5 3.5 0 0 1 0 4.94L9 15l-1.53-1.53a3.5 3.5 0 0 1 0-4.94Z"}],["path",{d:"M11.47 4.53 13 3l1.53 1.53a3.5 3.5 0 0 1 0 4.94L13 11l-1.53-1.53a3.5 3.5 0 0 1 0-4.94Z"}],["path",{d:"M20 2h2v2a4 4 0 0 1-4 4h-2V6a4 4 0 0 1 4-4Z"}],["path",{d:"M11.47 17.47 13 19l-1.53 1.53a3.5 3.5 0 0 1-4.94 0L5 19l1.53-1.53a3.5 3.5 0 0 1 4.94 0Z"}],["path",{d:"M15.47 13.47 17 15l-1.53 1.53a3.5 3.5 0 0 1-4.94 0L9 15l1.53-1.53a3.5 3.5 0 0 1 4.94 0Z"}],["path",{d:"M19.47 9.47 21 11l-1.53 1.53a3.5 3.5 0 0 1-4.94 0L13 11l1.53-1.53a3.5 3.5 0 0 1 4.94 0Z"}]]];const My=["svg",a,[["circle",{cx:"7",cy:"12",r:"3"}],["path",{d:"M10 9v6"}],["circle",{cx:"17",cy:"12",r:"3"}],["path",{d:"M14 7v8"}],["path",{d:"M22 17v1c0 .5-.5 1-1 1H3c-.5 0-1-.5-1-1v-1"}]]];const sy=["svg",a,[["path",{d:"M12 20h.01"}],["path",{d:"M5 12.859a10 10 0 0 1 14 0"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0"}]]];const ey=["svg",a,[["path",{d:"M12 20h.01"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0"}]]];const ry=["svg",a,[["path",{d:"M12 20h.01"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0"}],["path",{d:"M5 12.859a10 10 0 0 1 5.17-2.69"}],["path",{d:"M19 12.859a10 10 0 0 0-2.007-1.523"}],["path",{d:"M2 8.82a15 15 0 0 1 4.177-2.643"}],["path",{d:"M22 8.82a15 15 0 0 0-11.288-3.764"}],["path",{d:"m2 2 20 20"}]]];const vy=["svg",a,[["path",{d:"M12 20h.01"}]]];const ny=["svg",a,[["path",{d:"M12 20h.01"}],["path",{d:"M2 8.82a15 15 0 0 1 20 0"}],["path",{d:"M5 12.859a10 10 0 0 1 14 0"}],["path",{d:"M8.5 16.429a5 5 0 0 1 7 0"}]]];const oy=["svg",a,[["path",{d:"M17.7 7.7a2.5 2.5 0 1 1 1.8 4.3H2"}],["path",{d:"M9.6 4.6A2 2 0 1 1 11 8H2"}],["path",{d:"M12.6 19.4A2 2 0 1 0 14 16H2"}]]];const iy=["svg",a,[["path",{d:"M8 22h8"}],["path",{d:"M7 10h3m7 0h-1.343"}],["path",{d:"M12 15v7"}],["path",{d:"M7.307 7.307A12.33 12.33 0 0 0 7 10a5 5 0 0 0 7.391 4.391M8.638 2.981C8.75 2.668 8.872 2.34 9 2h6c1.5 4 2 6 2 8 0 .407-.05.809-.145 1.198"}],["line",{x1:"2",x2:"22",y1:"2",y2:"22"}]]];const ly=["svg",a,[["path",{d:"M8 22h8"}],["path",{d:"M7 10h10"}],["path",{d:"M12 15v7"}],["path",{d:"M12 15a5 5 0 0 0 5-5c0-2-.5-4-2-8H9c-1.5 4-2 6-2 8a5 5 0 0 0 5 5Z"}]]];const gy=["svg",a,[["rect",{width:"8",height:"8",x:"3",y:"3",rx:"2"}],["path",{d:"M7 11v4a2 2 0 0 0 2 2h4"}],["rect",{width:"8",height:"8",x:"13",y:"13",rx:"2"}]]];const xy=["svg",a,[["path",{d:"m19 12-1.5 3"}],["path",{d:"M19.63 18.81 22 20"}],["path",{d:"M6.47 8.23a1.68 1.68 0 0 1 2.44 1.93l-.64 2.08a6.76 6.76 0 0 0 10.16 7.67l.42-.27a1 1 0 1 0-2.73-4.21l-.42.27a1.76 1.76 0 0 1-2.63-1.99l.64-2.08A6.66 6.66 0 0 0 3.94 3.9l-.7.4a1 1 0 1 0 2.55 4.34z"}]]];const yy=["svg",a,[["line",{x1:"3",x2:"21",y1:"6",y2:"6"}],["path",{d:"M3 12h15a3 3 0 1 1 0 6h-4"}],["polyline",{points:"16 16 14 18 16 20"}],["line",{x1:"3",x2:"10",y1:"18",y2:"18"}]]];const my=["svg",a,[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"}]]];const Hy=["svg",a,[["path",{d:"M18 6 6 18"}],["path",{d:"m6 6 12 12"}]]];const Vy=["svg",a,[["path",{d:"M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17"}],["path",{d:"m10 15 5-3-5-3z"}]]];const Cy=["svg",a,[["path",{d:"M10.513 4.856 13.12 2.17a.5.5 0 0 1 .86.46l-1.377 4.317"}],["path",{d:"M15.656 10H20a1 1 0 0 1 .78 1.63l-1.72 1.773"}],["path",{d:"M16.273 16.273 10.88 21.83a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14H4a1 1 0 0 1-.78-1.63l4.507-4.643"}],["path",{d:"m2 2 20 20"}]]];const wy=["svg",a,[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"}]]];const uy=["svg",a,[["circle",{cx:"11",cy:"11",r:"8"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65"}],["line",{x1:"11",x2:"11",y1:"8",y2:"14"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11"}]]];const Ay=["svg",a,[["circle",{cx:"11",cy:"11",r:"8"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11"}]]];const Dy=Object.freeze(Object.defineProperty({__proto__:null,AArrowDown:W0,AArrowUp:X0,ALargeSmall:N0,Accessibility:K0,Activity:J0,ActivitySquare:S2,AirVent:j0,Airplay:Q0,AlarmCheck:l,AlarmClock:Y0,AlarmClockCheck:l,AlarmClockMinus:g,AlarmClockOff:_0,AlarmClockPlus:x,AlarmMinus:g,AlarmPlus:x,AlarmSmoke:$0,Album:aa,AlertCircle:G,AlertOctagon:h2,AlertTriangle:f0,AlignCenter:da,AlignCenterHorizontal:ta,AlignCenterVertical:ha,AlignEndHorizontal:pa,AlignEndVertical:ca,AlignHorizontalDistributeCenter:Ma,AlignHorizontalDistributeEnd:sa,AlignHorizontalDistributeStart:ea,AlignHorizontalJustifyCenter:ra,AlignHorizontalJustifyEnd:va,AlignHorizontalJustifyStart:na,AlignHorizontalSpaceAround:oa,AlignHorizontalSpaceBetween:ia,AlignJustify:la,AlignLeft:ga,AlignRight:xa,AlignStartHorizontal:ya,AlignStartVertical:ma,AlignVerticalDistributeCenter:Ha,AlignVerticalDistributeEnd:Va,AlignVerticalDistributeStart:Ca,AlignVerticalJustifyCenter:wa,AlignVerticalJustifyEnd:ua,AlignVerticalJustifyStart:Aa,AlignVerticalSpaceAround:La,AlignVerticalSpaceBetween:Sa,Ambulance:fa,Ampersand:Za,Ampersands:Pa,Amphora:ka,Anchor:za,Angry:Ba,Annoyed:Fa,Antenna:Da,Anvil:qa,Aperture:Ra,AppWindow:Ta,AppWindowMac:ba,Apple:Ua,Archive:Ea,ArchiveRestore:Oa,ArchiveX:Ia,AreaChart:k,Armchair:Ga,ArrowBigDown:Xa,ArrowBigDownDash:Wa,ArrowBigLeft:Ka,ArrowBigLeftDash:Na,ArrowBigRight:ja,ArrowBigRightDash:Ja,ArrowBigUp:_a,ArrowBigUpDash:Qa,ArrowDown:st,ArrowDown01:Ya,ArrowDown10:$a,ArrowDownAZ:y,ArrowDownAz:y,ArrowDownCircle:W,ArrowDownFromLine:at,ArrowDownLeft:tt,ArrowDownLeftFromCircle:N,ArrowDownLeftFromSquare:z2,ArrowDownLeftSquare:f2,ArrowDownNarrowWide:ht,ArrowDownRight:dt,ArrowDownRightFromCircle:K,ArrowDownRightFromSquare:B2,ArrowDownRightSquare:Z2,ArrowDownSquare:P2,ArrowDownToDot:pt,ArrowDownToLine:ct,ArrowDownUp:Mt,ArrowDownWideNarrow:m,ArrowDownZA:H,ArrowDownZa:H,ArrowLeft:nt,ArrowLeftCircle:X,ArrowLeftFromLine:et,ArrowLeftRight:rt,ArrowLeftSquare:k2,ArrowLeftToLine:vt,ArrowRight:gt,ArrowRightCircle:Q,ArrowRightFromLine:ot,ArrowRightLeft:it,ArrowRightSquare:q2,ArrowRightToLine:lt,ArrowUp:Lt,ArrowUp01:xt,ArrowUp10:yt,ArrowUpAZ:V,ArrowUpAz:V,ArrowUpCircle:_,ArrowUpDown:mt,ArrowUpFromDot:Ht,ArrowUpFromLine:Vt,ArrowUpLeft:Ct,ArrowUpLeftFromCircle:J,ArrowUpLeftFromSquare:F2,ArrowUpLeftSquare:R2,ArrowUpNarrowWide:C,ArrowUpRight:wt,ArrowUpRightFromCircle:j,ArrowUpRightFromSquare:D2,ArrowUpRightSquare:b2,ArrowUpSquare:T2,ArrowUpToLine:ut,ArrowUpWideNarrow:At,ArrowUpZA:w,ArrowUpZa:w,ArrowsUpFromLine:St,Asterisk:ft,AsteriskSquare:U2,AtSign:Zt,Atom:Pt,AudioLines:kt,AudioWaveform:zt,Award:Bt,Axe:Ft,Axis3D:u,Axis3d:u,Baby:Dt,Backpack:qt,Badge:_t,BadgeAlert:Rt,BadgeCent:bt,BadgeCheck:A,BadgeDollarSign:Tt,BadgeEuro:Ut,BadgeHelp:Ot,BadgeIndianRupee:It,BadgeInfo:Et,BadgeJapaneseYen:Gt,BadgeMinus:Wt,BadgePercent:Xt,BadgePlus:Nt,BadgePoundSterling:Kt,BadgeRussianRuble:Jt,BadgeSwissFranc:jt,BadgeX:Qt,BaggageClaim:Yt,Ban:$t,Banana:ah,Bandage:th,Banknote:hh,BarChart:T,BarChart2:U,BarChart3:R,BarChart4:q,BarChartBig:D,BarChartHorizontal:B,BarChartHorizontalBig:z,Barcode:dh,Baseline:ph,Bath:ch,Battery:nh,BatteryCharging:Mh,BatteryFull:sh,BatteryLow:eh,BatteryMedium:rh,BatteryWarning:vh,Beaker:oh,Bean:lh,BeanOff:ih,Bed:yh,BedDouble:gh,BedSingle:xh,Beef:mh,Beer:Vh,BeerOff:Hh,Bell:fh,BellDot:Ch,BellElectric:wh,BellMinus:uh,BellOff:Ah,BellPlus:Lh,BellRing:Sh,BetweenHorizonalEnd:L,BetweenHorizonalStart:S,BetweenHorizontalEnd:L,BetweenHorizontalStart:S,BetweenVerticalEnd:Zh,BetweenVerticalStart:Ph,BicepsFlexed:kh,Bike:zh,Binary:Bh,Binoculars:Fh,Biohazard:Dh,Bird:qh,Bitcoin:Rh,Blend:bh,Blinds:Th,Blocks:Uh,Bluetooth:Gh,BluetoothConnected:Oh,BluetoothOff:Ih,BluetoothSearching:Eh,Bold:Wh,Bolt:Xh,Bomb:Nh,Bone:Kh,Book:x4,BookA:Jh,BookAudio:jh,BookCheck:Qh,BookCopy:_h,BookDashed:f,BookDown:Yh,BookHeadphones:$h,BookHeart:a4,BookImage:t4,BookKey:h4,BookLock:d4,BookMarked:p4,BookMinus:c4,BookOpen:e4,BookOpenCheck:M4,BookOpenText:s4,BookPlus:r4,BookTemplate:f,BookText:v4,BookType:n4,BookUp:i4,BookUp2:o4,BookUser:l4,BookX:g4,Bookmark:C4,BookmarkCheck:y4,BookmarkMinus:m4,BookmarkPlus:H4,BookmarkX:V4,BoomBox:w4,Bot:L4,BotMessageSquare:u4,BotOff:A4,Box:f4,BoxSelect:S4,Boxes:Z4,Braces:Z,Brackets:P4,Brain:B4,BrainCircuit:k4,BrainCog:z4,BrickWall:F4,Briefcase:R4,BriefcaseBusiness:D4,BriefcaseMedical:q4,BringToFront:b4,Brush:T4,Bug:I4,BugOff:U4,BugPlay:O4,Building:G4,Building2:E4,Bus:X4,BusFront:W4,Cable:K4,CableCar:N4,Cake:j4,CakeSlice:J4,Calculator:Q4,Calendar:g5,CalendarArrowDown:_4,CalendarArrowUp:Y4,CalendarCheck:a5,CalendarCheck2:$4,CalendarClock:t5,CalendarCog:h5,CalendarDays:d5,CalendarFold:p5,CalendarHeart:c5,CalendarMinus:s5,CalendarMinus2:M5,CalendarOff:e5,CalendarPlus:v5,CalendarPlus2:r5,CalendarRange:n5,CalendarSearch:o5,CalendarX:l5,CalendarX2:i5,Camera:y5,CameraOff:x5,CandlestickChart:F,Candy:V5,CandyCane:m5,CandyOff:H5,Cannabis:C5,Captions:P,CaptionsOff:w5,Car:L5,CarFront:u5,CarTaxiFront:A5,Caravan:S5,Carrot:f5,CaseLower:Z5,CaseSensitive:P5,CaseUpper:k5,CassetteTape:z5,Cast:B5,Castle:F5,Cat:D5,Cctv:q5,ChartArea:k,ChartBar:B,ChartBarBig:z,ChartBarDecreasing:R5,ChartBarIncreasing:b5,ChartBarStacked:T5,ChartCandlestick:F,ChartColumn:R,ChartColumnBig:D,ChartColumnDecreasing:U5,ChartColumnIncreasing:q,ChartColumnStacked:O5,ChartLine:b,ChartNetwork:I5,ChartNoAxesColumn:U,ChartNoAxesColumnDecreasing:E5,ChartNoAxesColumnIncreasing:T,ChartNoAxesCombined:G5,ChartNoAxesGantt:O,ChartPie:I,ChartScatter:E,ChartSpline:W5,Check:N5,CheckCheck:X5,CheckCircle:Y,CheckCircle2:$,CheckSquare:I2,CheckSquare2:E2,ChefHat:K5,Cherry:J5,ChevronDown:j5,ChevronDownCircle:a1,ChevronDownSquare:G2,ChevronFirst:Q5,ChevronLast:_5,ChevronLeft:Y5,ChevronLeftCircle:t1,ChevronLeftSquare:W2,ChevronRight:$5,ChevronRightCircle:h1,ChevronRightSquare:X2,ChevronUp:a3,ChevronUpCircle:d1,ChevronUpSquare:N2,ChevronsDown:h3,ChevronsDownUp:t3,ChevronsLeft:c3,ChevronsLeftRight:p3,ChevronsLeftRightEllipsis:d3,ChevronsRight:s3,ChevronsRightLeft:M3,ChevronsUp:r3,ChevronsUpDown:e3,Chrome:v3,Church:n3,Cigarette:i3,CigaretteOff:o3,Circle:A3,CircleAlert:G,CircleArrowDown:W,CircleArrowLeft:X,CircleArrowOutDownLeft:N,CircleArrowOutDownRight:K,CircleArrowOutUpLeft:J,CircleArrowOutUpRight:j,CircleArrowRight:Q,CircleArrowUp:_,CircleCheck:$,CircleCheckBig:Y,CircleChevronDown:a1,CircleChevronLeft:t1,CircleChevronRight:h1,CircleChevronUp:d1,CircleDashed:l3,CircleDivide:p1,CircleDollarSign:g3,CircleDot:y3,CircleDotDashed:x3,CircleEllipsis:m3,CircleEqual:H3,CircleFadingArrowUp:V3,CircleFadingPlus:C3,CircleGauge:c1,CircleHelp:M1,CircleMinus:s1,CircleOff:w3,CircleParking:r1,CircleParkingOff:e1,CirclePause:v1,CirclePercent:n1,CirclePlay:o1,CirclePlus:i1,CirclePower:l1,CircleSlash:u3,CircleSlash2:g1,CircleSlashed:g1,CircleStop:x1,CircleUser:m1,CircleUserRound:y1,CircleX:H1,CircuitBoard:L3,Citrus:S3,Clapperboard:f3,Clipboard:R3,ClipboardCheck:Z3,ClipboardCopy:P3,ClipboardEdit:C1,ClipboardList:k3,ClipboardMinus:z3,ClipboardPaste:B3,ClipboardPen:C1,ClipboardPenLine:V1,ClipboardPlus:F3,ClipboardSignature:V1,ClipboardType:D3,ClipboardX:q3,Clock:_3,Clock1:b3,Clock10:T3,Clock11:U3,Clock12:O3,Clock2:I3,Clock3:E3,Clock4:G3,Clock5:W3,Clock6:X3,Clock7:N3,Clock8:K3,Clock9:J3,ClockArrowDown:j3,ClockArrowUp:Q3,Cloud:nd,CloudCog:Y3,CloudDownload:w1,CloudDrizzle:$3,CloudFog:ad,CloudHail:td,CloudLightning:hd,CloudMoon:pd,CloudMoonRain:dd,CloudOff:cd,CloudRain:sd,CloudRainWind:Md,CloudSnow:ed,CloudSun:vd,CloudSunRain:rd,CloudUpload:u1,Cloudy:od,Clover:id,Club:ld,Code:gd,Code2:A1,CodeSquare:K2,CodeXml:A1,Codepen:xd,Codesandbox:yd,Coffee:md,Cog:Hd,Coins:Vd,Columns:L1,Columns2:L1,Columns3:S1,Columns4:Cd,Combine:wd,Command:ud,Compass:Ad,Component:Ld,Computer:Sd,ConciergeBell:fd,Cone:Zd,Construction:Pd,Contact:kd,Contact2:f1,ContactRound:f1,Container:zd,Contrast:Bd,Cookie:Fd,CookingPot:Dd,Copy:Od,CopyCheck:qd,CopyMinus:Rd,CopyPlus:bd,CopySlash:Td,CopyX:Ud,Copyleft:Id,Copyright:Ed,CornerDownLeft:Gd,CornerDownRight:Wd,CornerLeftDown:Xd,CornerLeftUp:Nd,CornerRightDown:Kd,CornerRightUp:Jd,CornerUpLeft:jd,CornerUpRight:Qd,Cpu:_d,CreativeCommons:Yd,CreditCard:$d,Croissant:ap,Crop:tp,Cross:hp,Crosshair:dp,Crown:pp,Cuboid:cp,CupSoda:Mp,CurlyBraces:Z,Currency:sp,Cylinder:ep,Dam:rp,Database:op,DatabaseBackup:vp,DatabaseZap:np,Delete:ip,Dessert:lp,Diameter:gp,Diamond:mp,DiamondMinus:xp,DiamondPercent:Z1,DiamondPlus:yp,Dice1:Hp,Dice2:Vp,Dice3:Cp,Dice4:wp,Dice5:up,Dice6:Ap,Dices:Lp,Diff:Sp,Disc:kp,Disc2:fp,Disc3:Zp,DiscAlbum:Pp,Divide:zp,DivideCircle:p1,DivideSquare:Q2,Dna:Fp,DnaOff:Bp,Dock:Dp,Dog:qp,DollarSign:Rp,Donut:bp,DoorClosed:Tp,DoorOpen:Up,Dot:Op,DotSquare:_2,Download:Ip,DownloadCloud:w1,DraftingCompass:Ep,Drama:Gp,Dribbble:Wp,Drill:Xp,Droplet:Np,Droplets:Kp,Drum:Jp,Drumstick:jp,Dumbbell:Qp,Ear:Yp,EarOff:_p,Earth:P1,EarthLock:$p,Eclipse:a6,Edit:e,Edit2:g2,Edit3:l2,Egg:d6,EggFried:t6,EggOff:h6,Ellipsis:z1,EllipsisVertical:k1,Equal:c6,EqualNot:p6,EqualSquare:Y2,Eraser:M6,EthernetPort:s6,Euro:e6,Expand:r6,ExternalLink:v6,Eye:o6,EyeOff:n6,Facebook:i6,Factory:l6,Fan:g6,FastForward:x6,Feather:y6,Fence:m6,FerrisWheel:H6,Figma:V6,File:xc,FileArchive:C6,FileAudio:u6,FileAudio2:w6,FileAxis3D:B1,FileAxis3d:B1,FileBadge:L6,FileBadge2:A6,FileBarChart:F1,FileBarChart2:D1,FileBox:S6,FileChartColumn:D1,FileChartColumnIncreasing:F1,FileChartLine:q1,FileChartPie:R1,FileCheck:Z6,FileCheck2:f6,FileClock:P6,FileCode:z6,FileCode2:k6,FileCog:b1,FileCog2:b1,FileDiff:B6,FileDigit:F6,FileDown:D6,FileEdit:U1,FileHeart:q6,FileImage:R6,FileInput:b6,FileJson:U6,FileJson2:T6,FileKey:I6,FileKey2:O6,FileLineChart:q1,FileLock:G6,FileLock2:E6,FileMinus:X6,FileMinus2:W6,FileMusic:N6,FileOutput:K6,FilePen:U1,FilePenLine:T1,FilePieChart:R1,FilePlus:j6,FilePlus2:J6,FileQuestion:Q6,FileScan:_6,FileSearch:$6,FileSearch2:Y6,FileSignature:T1,FileSliders:ac,FileSpreadsheet:tc,FileStack:hc,FileSymlink:dc,FileTerminal:pc,FileText:cc,FileType:sc,FileType2:Mc,FileUp:ec,FileVideo:vc,FileVideo2:rc,FileVolume:oc,FileVolume2:nc,FileWarning:ic,FileX:gc,FileX2:lc,Files:yc,Film:mc,Filter:Vc,FilterX:Hc,Fingerprint:Cc,FireExtinguisher:wc,Fish:Lc,FishOff:uc,FishSymbol:Ac,Flag:Pc,FlagOff:Sc,FlagTriangleLeft:fc,FlagTriangleRight:Zc,Flame:zc,FlameKindling:kc,Flashlight:Fc,FlashlightOff:Bc,FlaskConical:qc,FlaskConicalOff:Dc,FlaskRound:Rc,FlipHorizontal:Tc,FlipHorizontal2:bc,FlipVertical:Oc,FlipVertical2:Uc,Flower:Ec,Flower2:Ic,Focus:Gc,FoldHorizontal:Wc,FoldVertical:Xc,Folder:H8,FolderArchive:Nc,FolderCheck:Kc,FolderClock:Jc,FolderClosed:jc,FolderCode:Qc,FolderCog:O1,FolderCog2:O1,FolderDot:_c,FolderDown:Yc,FolderEdit:I1,FolderGit:a8,FolderGit2:$c,FolderHeart:t8,FolderInput:h8,FolderKanban:d8,FolderKey:p8,FolderLock:c8,FolderMinus:M8,FolderOpen:e8,FolderOpenDot:s8,FolderOutput:r8,FolderPen:I1,FolderPlus:v8,FolderRoot:n8,FolderSearch:i8,FolderSearch2:o8,FolderSymlink:l8,FolderSync:g8,FolderTree:x8,FolderUp:y8,FolderX:m8,Folders:V8,Footprints:C8,ForkKnife:T0,ForkKnifeCrossed:b0,Forklift:w8,FormInput:y2,Forward:u8,Frame:A8,Framer:L8,Frown:S8,Fuel:f8,Fullscreen:Z8,FunctionSquare:$2,GalleryHorizontal:k8,GalleryHorizontalEnd:P8,GalleryThumbnails:z8,GalleryVertical:F8,GalleryVerticalEnd:B8,Gamepad:q8,Gamepad2:D8,GanttChart:O,GanttChartSquare:n,Gauge:R8,GaugeCircle:c1,Gavel:b8,Gem:T8,Ghost:U8,Gift:O8,GitBranch:E8,GitBranchPlus:I8,GitCommit:E1,GitCommitHorizontal:E1,GitCommitVertical:G8,GitCompare:X8,GitCompareArrows:W8,GitFork:N8,GitGraph:K8,GitMerge:J8,GitPullRequest:a7,GitPullRequestArrow:j8,GitPullRequestClosed:Q8,GitPullRequestCreate:Y8,GitPullRequestCreateArrow:_8,GitPullRequestDraft:$8,Github:t7,Gitlab:h7,GlassWater:d7,Glasses:p7,Globe:M7,Globe2:P1,GlobeLock:c7,Goal:s7,Grab:e7,GraduationCap:r7,Grape:v7,Grid:v,Grid2X2:G1,Grid2x2:G1,Grid2x2Check:n7,Grid2x2X:o7,Grid3X3:v,Grid3x3:v,Grip:g7,GripHorizontal:i7,GripVertical:l7,Group:x7,Guitar:y7,Ham:m7,Hammer:H7,Hand:A7,HandCoins:V7,HandHeart:C7,HandHelping:W1,HandMetal:w7,HandPlatter:u7,Handshake:L7,HardDrive:Z7,HardDriveDownload:S7,HardDriveUpload:f7,HardHat:P7,Hash:k7,Haze:z7,HdmiPort:B7,Heading:U7,Heading1:F7,Heading2:D7,Heading3:q7,Heading4:R7,Heading5:b7,Heading6:T7,Headphones:O7,Headset:I7,Heart:N7,HeartCrack:E7,HeartHandshake:G7,HeartOff:W7,HeartPulse:X7,Heater:K7,HelpCircle:M1,HelpingHand:W1,Hexagon:J7,Highlighter:j7,History:Q7,Home:X1,Hop:Y7,HopOff:_7,Hospital:$7,Hotel:aM,Hourglass:tM,House:X1,HousePlug:hM,HousePlus:dM,IceCream:K1,IceCream2:N1,IceCreamBowl:N1,IceCreamCone:K1,IdCard:pM,Image:nM,ImageDown:cM,ImageMinus:MM,ImageOff:sM,ImagePlay:eM,ImagePlus:rM,ImageUp:vM,Images:oM,Import:iM,Inbox:lM,Indent:j1,IndentDecrease:J1,IndentIncrease:j1,IndianRupee:gM,Infinity:xM,Info:yM,Inspect:c0,InspectionPanel:mM,Instagram:HM,Italic:VM,IterationCcw:CM,IterationCw:wM,JapaneseYen:uM,Joystick:AM,Kanban:LM,KanbanSquare:a0,KanbanSquareDashed:J2,Key:ZM,KeyRound:SM,KeySquare:fM,Keyboard:zM,KeyboardMusic:PM,KeyboardOff:kM,Lamp:bM,LampCeiling:BM,LampDesk:FM,LampFloor:DM,LampWallDown:qM,LampWallUp:RM,LandPlot:TM,Landmark:UM,Languages:OM,Laptop:IM,Laptop2:Q1,LaptopMinimal:Q1,Lasso:GM,LassoSelect:EM,Laugh:WM,Layers:KM,Layers2:XM,Layers3:NM,Layout:i2,LayoutDashboard:JM,LayoutGrid:jM,LayoutList:QM,LayoutPanelLeft:_M,LayoutPanelTop:YM,LayoutTemplate:$M,Leaf:as,LeafyGreen:ts,Lectern:hs,LetterText:ds,Library:cs,LibraryBig:ps,LibrarySquare:t0,LifeBuoy:Ms,Ligature:ss,Lightbulb:rs,LightbulbOff:es,LineChart:b,Link:os,Link2:ns,Link2Off:vs,Linkedin:is,List:Ps,ListCheck:ls,ListChecks:gs,ListCollapse:xs,ListEnd:ys,ListFilter:ms,ListMinus:Hs,ListMusic:Vs,ListOrdered:Cs,ListPlus:ws,ListRestart:us,ListStart:As,ListTodo:Ls,ListTree:Ss,ListVideo:fs,ListX:Zs,Loader:zs,Loader2:_1,LoaderCircle:_1,LoaderPinwheel:ks,Locate:Ds,LocateFixed:Bs,LocateOff:Fs,Lock:Rs,LockKeyhole:qs,LockKeyholeOpen:Y1,LockOpen:$1,LogIn:bs,LogOut:Ts,Logs:Us,Lollipop:Os,Luggage:Is,MSquare:h0,Magnet:Es,Mail:_s,MailCheck:Gs,MailMinus:Ws,MailOpen:Xs,MailPlus:Ns,MailQuestion:Ks,MailSearch:Js,MailWarning:js,MailX:Qs,Mailbox:Ys,Mails:$s,Map:oe,MapPin:ve,MapPinCheck:te,MapPinCheckInside:ae,MapPinHouse:he,MapPinMinus:pe,MapPinMinusInside:de,MapPinOff:ce,MapPinPlus:se,MapPinPlusInside:Me,MapPinX:re,MapPinXInside:ee,MapPinned:ne,Martini:ie,Maximize:ge,Maximize2:le,Medal:xe,Megaphone:me,MegaphoneOff:ye,Meh:He,MemoryStick:Ve,Menu:Ce,MenuSquare:d0,Merge:we,MessageCircle:Fe,MessageCircleCode:ue,MessageCircleDashed:Ae,MessageCircleHeart:Le,MessageCircleMore:Se,MessageCircleOff:fe,MessageCirclePlus:Ze,MessageCircleQuestion:Pe,MessageCircleReply:ke,MessageCircleWarning:ze,MessageCircleX:Be,MessageSquare:Je,MessageSquareCode:De,MessageSquareDashed:qe,MessageSquareDiff:Re,MessageSquareDot:be,MessageSquareHeart:Te,MessageSquareMore:Ue,MessageSquareOff:Oe,MessageSquarePlus:Ie,MessageSquareQuote:Ee,MessageSquareReply:Ge,MessageSquareShare:We,MessageSquareText:Xe,MessageSquareWarning:Ne,MessageSquareX:Ke,MessagesSquare:je,Mic:_e,Mic2:a2,MicOff:Qe,MicVocal:a2,Microchip:Ye,Microscope:$e,Microwave:a9,Milestone:t9,Milk:d9,MilkOff:h9,Minimize:c9,Minimize2:p9,Minus:M9,MinusCircle:s1,MinusSquare:p0,Monitor:H9,MonitorCheck:s9,MonitorCog:e9,MonitorDot:r9,MonitorDown:v9,MonitorOff:n9,MonitorPause:o9,MonitorPlay:i9,MonitorSmartphone:l9,MonitorSpeaker:g9,MonitorStop:x9,MonitorUp:y9,MonitorX:m9,Moon:C9,MoonStar:V9,MoreHorizontal:z1,MoreVertical:k1,Mountain:u9,MountainSnow:w9,Mouse:P9,MouseOff:A9,MousePointer:Z9,MousePointer2:L9,MousePointerBan:S9,MousePointerClick:f9,MousePointerSquareDashed:j2,Move:E9,Move3D:t2,Move3d:t2,MoveDiagonal:z9,MoveDiagonal2:k9,MoveDown:D9,MoveDownLeft:B9,MoveDownRight:F9,MoveHorizontal:q9,MoveLeft:R9,MoveRight:b9,MoveUp:O9,MoveUpLeft:T9,MoveUpRight:U9,MoveVertical:I9,Music:N9,Music2:G9,Music3:W9,Music4:X9,Navigation:Q9,Navigation2:J9,Navigation2Off:K9,NavigationOff:j9,Network:_9,Newspaper:Y9,Nfc:$9,Notebook:dr,NotebookPen:ar,NotebookTabs:tr,NotebookText:hr,NotepadText:cr,NotepadTextDashed:pr,Nut:sr,NutOff:Mr,Octagon:er,OctagonAlert:h2,OctagonPause:d2,OctagonX:p2,Omega:rr,Option:vr,Orbit:nr,Origami:or,Outdent:J1,Package:Vr,Package2:ir,PackageCheck:lr,PackageMinus:gr,PackageOpen:xr,PackagePlus:yr,PackageSearch:mr,PackageX:Hr,PaintBucket:Cr,PaintRoller:wr,Paintbrush:ur,Paintbrush2:c2,PaintbrushVertical:c2,Palette:Ar,Palmtree:S0,PanelBottom:fr,PanelBottomClose:Lr,PanelBottomDashed:M2,PanelBottomInactive:M2,PanelBottomOpen:Sr,PanelLeft:v2,PanelLeftClose:s2,PanelLeftDashed:e2,PanelLeftInactive:e2,PanelLeftOpen:r2,PanelRight:kr,PanelRightClose:Zr,PanelRightDashed:n2,PanelRightInactive:n2,PanelRightOpen:Pr,PanelTop:Fr,PanelTopClose:zr,PanelTopDashed:o2,PanelTopInactive:o2,PanelTopOpen:Br,PanelsLeftBottom:Dr,PanelsLeftRight:S1,PanelsRightBottom:qr,PanelsTopBottom:V2,PanelsTopLeft:i2,Paperclip:Rr,Parentheses:br,ParkingCircle:r1,ParkingCircleOff:e1,ParkingMeter:Tr,ParkingSquare:s0,ParkingSquareOff:M0,PartyPopper:Ur,Pause:Or,PauseCircle:v1,PauseOctagon:d2,PawPrint:Ir,PcCase:Er,Pen:g2,PenBox:e,PenLine:l2,PenOff:Gr,PenSquare:e,PenTool:Wr,Pencil:Jr,PencilLine:Xr,PencilOff:Nr,PencilRuler:Kr,Pentagon:jr,Percent:Qr,PercentCircle:n1,PercentDiamond:Z1,PercentSquare:e0,PersonStanding:_r,PhilippinePeso:Yr,Phone:cv,PhoneCall:$r,PhoneForwarded:av,PhoneIncoming:tv,PhoneMissed:hv,PhoneOff:dv,PhoneOutgoing:pv,Pi:Mv,PiSquare:r0,Piano:sv,Pickaxe:ev,PictureInPicture:vv,PictureInPicture2:rv,PieChart:I,PiggyBank:nv,Pilcrow:lv,PilcrowLeft:ov,PilcrowRight:iv,PilcrowSquare:v0,Pill:xv,PillBottle:gv,Pin:mv,PinOff:yv,Pipette:Hv,Pizza:Vv,Plane:uv,PlaneLanding:Cv,PlaneTakeoff:wv,Play:Av,PlayCircle:o1,PlaySquare:n0,Plug:Sv,Plug2:Lv,PlugZap:x2,PlugZap2:x2,Plus:fv,PlusCircle:i1,PlusSquare:o0,Pocket:Pv,PocketKnife:Zv,Podcast:kv,Pointer:Bv,PointerOff:zv,Popcorn:Fv,Popsicle:Dv,PoundSterling:qv,Power:bv,PowerCircle:l1,PowerOff:Rv,PowerSquare:i0,Presentation:Tv,Printer:Ov,PrinterCheck:Uv,Projector:Iv,Proportions:Ev,Puzzle:Gv,Pyramid:Wv,QrCode:Xv,Quote:Nv,Rabbit:Kv,Radar:Jv,Radiation:jv,Radical:Qv,Radio:$v,RadioReceiver:_v,RadioTower:Yv,Radius:an,RailSymbol:tn,Rainbow:hn,Rat:dn,Ratio:pn,Receipt:ln,ReceiptCent:cn,ReceiptEuro:Mn,ReceiptIndianRupee:sn,ReceiptJapaneseYen:en,ReceiptPoundSterling:rn,ReceiptRussianRuble:vn,ReceiptSwissFranc:nn,ReceiptText:on,RectangleEllipsis:y2,RectangleHorizontal:gn,RectangleVertical:xn,Recycle:yn,Redo:Vn,Redo2:mn,RedoDot:Hn,RefreshCcw:wn,RefreshCcwDot:Cn,RefreshCw:An,RefreshCwOff:un,Refrigerator:Ln,Regex:Sn,RemoveFormatting:fn,Repeat:kn,Repeat1:Zn,Repeat2:Pn,Replace:Bn,ReplaceAll:zn,Reply:Dn,ReplyAll:Fn,Rewind:qn,Ribbon:Rn,Rocket:bn,RockingChair:Tn,RollerCoaster:Un,Rotate3D:m2,Rotate3d:m2,RotateCcw:In,RotateCcwSquare:On,RotateCw:Gn,RotateCwSquare:En,Route:Xn,RouteOff:Wn,Router:Nn,Rows:H2,Rows2:H2,Rows3:V2,Rows4:Kn,Rss:Jn,Ruler:jn,RussianRuble:Qn,Sailboat:_n,Salad:Yn,Sandwich:$n,Satellite:to,SatelliteDish:ao,Save:co,SaveAll:ho,SaveOff:po,Scale:Mo,Scale3D:C2,Scale3d:C2,Scaling:so,Scan:go,ScanBarcode:eo,ScanEye:ro,ScanFace:vo,ScanLine:no,ScanQrCode:oo,ScanSearch:io,ScanText:lo,ScatterChart:E,School:xo,School2:P0,Scissors:mo,ScissorsLineDashed:yo,ScissorsSquare:l0,ScissorsSquareDashedBottom:O2,ScreenShare:Vo,ScreenShareOff:Ho,Scroll:wo,ScrollText:Co,Search:fo,SearchCheck:uo,SearchCode:Ao,SearchSlash:Lo,SearchX:So,Section:Zo,Send:ko,SendHorizonal:w2,SendHorizontal:w2,SendToBack:Po,SeparatorHorizontal:zo,SeparatorVertical:Bo,Server:Ro,ServerCog:Fo,ServerCrash:Do,ServerOff:qo,Settings:To,Settings2:bo,Shapes:Uo,Share:Io,Share2:Oo,Sheet:Eo,Shell:Go,Shield:$o,ShieldAlert:Wo,ShieldBan:Xo,ShieldCheck:No,ShieldClose:u2,ShieldEllipsis:Ko,ShieldHalf:Jo,ShieldMinus:jo,ShieldOff:Qo,ShieldPlus:_o,ShieldQuestion:Yo,ShieldX:u2,Ship:ti,ShipWheel:ai,Shirt:hi,ShoppingBag:di,ShoppingBasket:pi,ShoppingCart:ci,Shovel:Mi,ShowerHead:si,Shrink:ei,Shrub:ri,Shuffle:vi,Sidebar:v2,SidebarClose:s2,SidebarOpen:r2,Sigma:ni,SigmaSquare:g0,Signal:xi,SignalHigh:oi,SignalLow:ii,SignalMedium:li,SignalZero:gi,Signature:yi,Signpost:Hi,SignpostBig:mi,Siren:Vi,SkipBack:Ci,SkipForward:wi,Skull:ui,Slack:Ai,Slash:Li,SlashSquare:x0,Slice:Si,Sliders:A2,SlidersHorizontal:fi,SlidersVertical:A2,Smartphone:ki,SmartphoneCharging:Zi,SmartphoneNfc:Pi,Smile:Bi,SmilePlus:zi,Snail:Fi,Snowflake:Di,Sofa:qi,SortAsc:C,SortDesc:m,Soup:Ri,Space:bi,Spade:Ti,Sparkle:Ui,Sparkles:L2,Speaker:Oi,Speech:Ii,SpellCheck:Gi,SpellCheck2:Ei,Spline:Wi,Split:Xi,SplitSquareHorizontal:y0,SplitSquareVertical:m0,SprayCan:Ni,Sprout:Ki,Square:$i,SquareActivity:S2,SquareArrowDown:P2,SquareArrowDownLeft:f2,SquareArrowDownRight:Z2,SquareArrowLeft:k2,SquareArrowOutDownLeft:z2,SquareArrowOutDownRight:B2,SquareArrowOutUpLeft:F2,SquareArrowOutUpRight:D2,SquareArrowRight:q2,SquareArrowUp:T2,SquareArrowUpLeft:R2,SquareArrowUpRight:b2,SquareAsterisk:U2,SquareBottomDashedScissors:O2,SquareChartGantt:n,SquareCheck:E2,SquareCheckBig:I2,SquareChevronDown:G2,SquareChevronLeft:W2,SquareChevronRight:X2,SquareChevronUp:N2,SquareCode:K2,SquareDashedBottom:ji,SquareDashedBottomCode:Ji,SquareDashedKanban:J2,SquareDashedMousePointer:j2,SquareDivide:Q2,SquareDot:_2,SquareEqual:Y2,SquareFunction:$2,SquareGanttChart:n,SquareKanban:a0,SquareLibrary:t0,SquareM:h0,SquareMenu:d0,SquareMinus:p0,SquareMousePointer:c0,SquareParking:s0,SquareParkingOff:M0,SquarePen:e,SquarePercent:e0,SquarePi:r0,SquarePilcrow:v0,SquarePlay:n0,SquarePlus:o0,SquarePower:i0,SquareRadical:Qi,SquareScissors:l0,SquareSigma:g0,SquareSlash:x0,SquareSplitHorizontal:y0,SquareSplitVertical:m0,SquareSquare:_i,SquareStack:Yi,SquareTerminal:H0,SquareUser:C0,SquareUserRound:V0,SquareX:w0,Squircle:al,Squirrel:tl,Stamp:hl,Star:cl,StarHalf:dl,StarOff:pl,Stars:L2,StepBack:Ml,StepForward:sl,Stethoscope:el,Sticker:rl,StickyNote:vl,StopCircle:x1,Store:nl,StretchHorizontal:ol,StretchVertical:il,Strikethrough:ll,Subscript:gl,Subtitles:P,Sun:Vl,SunDim:xl,SunMedium:yl,SunMoon:ml,SunSnow:Hl,Sunrise:Cl,Sunset:wl,Superscript:ul,SwatchBook:Al,SwissFranc:Ll,SwitchCamera:Sl,Sword:fl,Swords:Zl,Syringe:Pl,Table:bl,Table2:kl,TableCellsMerge:zl,TableCellsSplit:Bl,TableColumnsSplit:Fl,TableOfContents:Dl,TableProperties:ql,TableRowsSplit:Rl,Tablet:Ul,TabletSmartphone:Tl,Tablets:Ol,Tag:Il,Tags:El,Tally1:Gl,Tally2:Wl,Tally3:Xl,Tally4:Nl,Tally5:Kl,Tangent:Jl,Target:jl,Telescope:Ql,Tent:Yl,TentTree:_l,Terminal:$l,TerminalSquare:H0,TestTube:ag,TestTube2:u0,TestTubeDiagonal:u0,TestTubes:tg,Text:Mg,TextCursor:dg,TextCursorInput:hg,TextQuote:pg,TextSearch:cg,TextSelect:A0,TextSelection:A0,Theater:sg,Thermometer:vg,ThermometerSnowflake:eg,ThermometerSun:rg,ThumbsDown:ng,ThumbsUp:og,Ticket:Hg,TicketCheck:ig,TicketMinus:lg,TicketPercent:gg,TicketPlus:xg,TicketSlash:yg,TicketX:mg,Tickets:Cg,TicketsPlane:Vg,Timer:Ag,TimerOff:wg,TimerReset:ug,ToggleLeft:Lg,ToggleRight:Sg,Tornado:fg,Torus:Zg,Touchpad:kg,TouchpadOff:Pg,TowerControl:zg,ToyBrick:Bg,Tractor:Fg,TrafficCone:Dg,Train:L0,TrainFront:Rg,TrainFrontTunnel:qg,TrainTrack:bg,TramFront:L0,Trash:Ug,Trash2:Tg,TreeDeciduous:Og,TreePalm:S0,TreePine:Ig,Trees:Eg,Trello:Gg,TrendingDown:Wg,TrendingUp:Xg,Triangle:Kg,TriangleAlert:f0,TriangleRight:Ng,Trophy:Jg,Truck:jg,Turtle:Qg,Tv:Yg,Tv2:Z0,TvMinimal:Z0,TvMinimalPlay:_g,Twitch:$g,Twitter:ax,Type:hx,TypeOutline:tx,Umbrella:px,UmbrellaOff:dx,Underline:cx,Undo:ex,Undo2:Mx,UndoDot:sx,UnfoldHorizontal:rx,UnfoldVertical:vx,Ungroup:nx,University:P0,Unlink:ix,Unlink2:ox,Unlock:$1,UnlockKeyhole:Y1,Unplug:lx,Upload:gx,UploadCloud:u1,Usb:xx,User:Sx,User2:q0,UserCheck:yx,UserCheck2:k0,UserCircle:m1,UserCircle2:y1,UserCog:mx,UserCog2:z0,UserMinus:Hx,UserMinus2:B0,UserPen:Vx,UserPlus:Cx,UserPlus2:F0,UserRound:q0,UserRoundCheck:k0,UserRoundCog:z0,UserRoundMinus:B0,UserRoundPen:wx,UserRoundPlus:F0,UserRoundSearch:ux,UserRoundX:D0,UserSearch:Ax,UserSquare:C0,UserSquare2:V0,UserX:Lx,UserX2:D0,Users:fx,Users2:R0,UsersRound:R0,Utensils:T0,UtensilsCrossed:b0,UtilityPole:Zx,Variable:Px,Vault:kx,Vegan:zx,VenetianMask:Bx,Verified:A,Vibrate:Dx,VibrateOff:Fx,Video:Rx,VideoOff:qx,Videotape:bx,View:Tx,Voicemail:Ux,Volume:Gx,Volume1:Ox,Volume2:Ix,VolumeX:Ex,Vote:Wx,Wallet:Nx,Wallet2:U0,WalletCards:Xx,WalletMinimal:U0,Wallpaper:Kx,Wand:Jx,Wand2:O0,WandSparkles:O0,Warehouse:jx,WashingMachine:Qx,Watch:_x,Waves:Yx,Waypoints:$x,Webcam:ay,Webhook:hy,WebhookOff:ty,Weight:dy,Wheat:cy,WheatOff:py,WholeWord:My,Wifi:ny,WifiHigh:sy,WifiLow:ey,WifiOff:ry,WifiZero:vy,Wind:oy,Wine:ly,WineOff:iy,Workflow:gy,Worm:xy,WrapText:yy,Wrench:my,X:Hy,XCircle:H1,XOctagon:p2,XSquare:w0,Youtube:Vy,Zap:wy,ZapOff:Cy,ZoomIn:uy,ZoomOut:Ay},Symbol.toStringTag,{value:"Module"}));const qy=Object.freeze(Object.defineProperty({__proto__:null,AArrowDown:W0,AArrowUp:X0,ALargeSmall:N0,Accessibility:K0,Activity:J0,ActivitySquare:S2,AirVent:j0,Airplay:Q0,AlarmCheck:l,AlarmClock:Y0,AlarmClockCheck:l,AlarmClockMinus:g,AlarmClockOff:_0,AlarmClockPlus:x,AlarmMinus:g,AlarmPlus:x,AlarmSmoke:$0,Album:aa,AlertCircle:G,AlertOctagon:h2,AlertTriangle:f0,AlignCenter:da,AlignCenterHorizontal:ta,AlignCenterVertical:ha,AlignEndHorizontal:pa,AlignEndVertical:ca,AlignHorizontalDistributeCenter:Ma,AlignHorizontalDistributeEnd:sa,AlignHorizontalDistributeStart:ea,AlignHorizontalJustifyCenter:ra,AlignHorizontalJustifyEnd:va,AlignHorizontalJustifyStart:na,AlignHorizontalSpaceAround:oa,AlignHorizontalSpaceBetween:ia,AlignJustify:la,AlignLeft:ga,AlignRight:xa,AlignStartHorizontal:ya,AlignStartVertical:ma,AlignVerticalDistributeCenter:Ha,AlignVerticalDistributeEnd:Va,AlignVerticalDistributeStart:Ca,AlignVerticalJustifyCenter:wa,AlignVerticalJustifyEnd:ua,AlignVerticalJustifyStart:Aa,AlignVerticalSpaceAround:La,AlignVerticalSpaceBetween:Sa,Ambulance:fa,Ampersand:Za,Ampersands:Pa,Amphora:ka,Anchor:za,Angry:Ba,Annoyed:Fa,Antenna:Da,Anvil:qa,Aperture:Ra,AppWindow:Ta,AppWindowMac:ba,Apple:Ua,Archive:Ea,ArchiveRestore:Oa,ArchiveX:Ia,AreaChart:k,Armchair:Ga,ArrowBigDown:Xa,ArrowBigDownDash:Wa,ArrowBigLeft:Ka,ArrowBigLeftDash:Na,ArrowBigRight:ja,ArrowBigRightDash:Ja,ArrowBigUp:_a,ArrowBigUpDash:Qa,ArrowDown:st,ArrowDown01:Ya,ArrowDown10:$a,ArrowDownAZ:y,ArrowDownAz:y,ArrowDownCircle:W,ArrowDownFromLine:at,ArrowDownLeft:tt,ArrowDownLeftFromCircle:N,ArrowDownLeftFromSquare:z2,ArrowDownLeftSquare:f2,ArrowDownNarrowWide:ht,ArrowDownRight:dt,ArrowDownRightFromCircle:K,ArrowDownRightFromSquare:B2,ArrowDownRightSquare:Z2,ArrowDownSquare:P2,ArrowDownToDot:pt,ArrowDownToLine:ct,ArrowDownUp:Mt,ArrowDownWideNarrow:m,ArrowDownZA:H,ArrowDownZa:H,ArrowLeft:nt,ArrowLeftCircle:X,ArrowLeftFromLine:et,ArrowLeftRight:rt,ArrowLeftSquare:k2,ArrowLeftToLine:vt,ArrowRight:gt,ArrowRightCircle:Q,ArrowRightFromLine:ot,ArrowRightLeft:it,ArrowRightSquare:q2,ArrowRightToLine:lt,ArrowUp:Lt,ArrowUp01:xt,ArrowUp10:yt,ArrowUpAZ:V,ArrowUpAz:V,ArrowUpCircle:_,ArrowUpDown:mt,ArrowUpFromDot:Ht,ArrowUpFromLine:Vt,ArrowUpLeft:Ct,ArrowUpLeftFromCircle:J,ArrowUpLeftFromSquare:F2,ArrowUpLeftSquare:R2,ArrowUpNarrowWide:C,ArrowUpRight:wt,ArrowUpRightFromCircle:j,ArrowUpRightFromSquare:D2,ArrowUpRightSquare:b2,ArrowUpSquare:T2,ArrowUpToLine:ut,ArrowUpWideNarrow:At,ArrowUpZA:w,ArrowUpZa:w,ArrowsUpFromLine:St,Asterisk:ft,AsteriskSquare:U2,AtSign:Zt,Atom:Pt,AudioLines:kt,AudioWaveform:zt,Award:Bt,Axe:Ft,Axis3D:u,Axis3d:u,Baby:Dt,Backpack:qt,Badge:_t,BadgeAlert:Rt,BadgeCent:bt,BadgeCheck:A,BadgeDollarSign:Tt,BadgeEuro:Ut,BadgeHelp:Ot,BadgeIndianRupee:It,BadgeInfo:Et,BadgeJapaneseYen:Gt,BadgeMinus:Wt,BadgePercent:Xt,BadgePlus:Nt,BadgePoundSterling:Kt,BadgeRussianRuble:Jt,BadgeSwissFranc:jt,BadgeX:Qt,BaggageClaim:Yt,Ban:$t,Banana:ah,Bandage:th,Banknote:hh,BarChart:T,BarChart2:U,BarChart3:R,BarChart4:q,BarChartBig:D,BarChartHorizontal:B,BarChartHorizontalBig:z,Barcode:dh,Baseline:ph,Bath:ch,Battery:nh,BatteryCharging:Mh,BatteryFull:sh,BatteryLow:eh,BatteryMedium:rh,BatteryWarning:vh,Beaker:oh,Bean:lh,BeanOff:ih,Bed:yh,BedDouble:gh,BedSingle:xh,Beef:mh,Beer:Vh,BeerOff:Hh,Bell:fh,BellDot:Ch,BellElectric:wh,BellMinus:uh,BellOff:Ah,BellPlus:Lh,BellRing:Sh,BetweenHorizonalEnd:L,BetweenHorizonalStart:S,BetweenHorizontalEnd:L,BetweenHorizontalStart:S,BetweenVerticalEnd:Zh,BetweenVerticalStart:Ph,BicepsFlexed:kh,Bike:zh,Binary:Bh,Binoculars:Fh,Biohazard:Dh,Bird:qh,Bitcoin:Rh,Blend:bh,Blinds:Th,Blocks:Uh,Bluetooth:Gh,BluetoothConnected:Oh,BluetoothOff:Ih,BluetoothSearching:Eh,Bold:Wh,Bolt:Xh,Bomb:Nh,Bone:Kh,Book:x4,BookA:Jh,BookAudio:jh,BookCheck:Qh,BookCopy:_h,BookDashed:f,BookDown:Yh,BookHeadphones:$h,BookHeart:a4,BookImage:t4,BookKey:h4,BookLock:d4,BookMarked:p4,BookMinus:c4,BookOpen:e4,BookOpenCheck:M4,BookOpenText:s4,BookPlus:r4,BookTemplate:f,BookText:v4,BookType:n4,BookUp:i4,BookUp2:o4,BookUser:l4,BookX:g4,Bookmark:C4,BookmarkCheck:y4,BookmarkMinus:m4,BookmarkPlus:H4,BookmarkX:V4,BoomBox:w4,Bot:L4,BotMessageSquare:u4,BotOff:A4,Box:f4,BoxSelect:S4,Boxes:Z4,Braces:Z,Brackets:P4,Brain:B4,BrainCircuit:k4,BrainCog:z4,BrickWall:F4,Briefcase:R4,BriefcaseBusiness:D4,BriefcaseMedical:q4,BringToFront:b4,Brush:T4,Bug:I4,BugOff:U4,BugPlay:O4,Building:G4,Building2:E4,Bus:X4,BusFront:W4,Cable:K4,CableCar:N4,Cake:j4,CakeSlice:J4,Calculator:Q4,Calendar:g5,CalendarArrowDown:_4,CalendarArrowUp:Y4,CalendarCheck:a5,CalendarCheck2:$4,CalendarClock:t5,CalendarCog:h5,CalendarDays:d5,CalendarFold:p5,CalendarHeart:c5,CalendarMinus:s5,CalendarMinus2:M5,CalendarOff:e5,CalendarPlus:v5,CalendarPlus2:r5,CalendarRange:n5,CalendarSearch:o5,CalendarX:l5,CalendarX2:i5,Camera:y5,CameraOff:x5,CandlestickChart:F,Candy:V5,CandyCane:m5,CandyOff:H5,Cannabis:C5,Captions:P,CaptionsOff:w5,Car:L5,CarFront:u5,CarTaxiFront:A5,Caravan:S5,Carrot:f5,CaseLower:Z5,CaseSensitive:P5,CaseUpper:k5,CassetteTape:z5,Cast:B5,Castle:F5,Cat:D5,Cctv:q5,ChartArea:k,ChartBar:B,ChartBarBig:z,ChartBarDecreasing:R5,ChartBarIncreasing:b5,ChartBarStacked:T5,ChartCandlestick:F,ChartColumn:R,ChartColumnBig:D,ChartColumnDecreasing:U5,ChartColumnIncreasing:q,ChartColumnStacked:O5,ChartLine:b,ChartNetwork:I5,ChartNoAxesColumn:U,ChartNoAxesColumnDecreasing:E5,ChartNoAxesColumnIncreasing:T,ChartNoAxesCombined:G5,ChartNoAxesGantt:O,ChartPie:I,ChartScatter:E,ChartSpline:W5,Check:N5,CheckCheck:X5,CheckCircle:Y,CheckCircle2:$,CheckSquare:I2,CheckSquare2:E2,ChefHat:K5,Cherry:J5,ChevronDown:j5,ChevronDownCircle:a1,ChevronDownSquare:G2,ChevronFirst:Q5,ChevronLast:_5,ChevronLeft:Y5,ChevronLeftCircle:t1,ChevronLeftSquare:W2,ChevronRight:$5,ChevronRightCircle:h1,ChevronRightSquare:X2,ChevronUp:a3,ChevronUpCircle:d1,ChevronUpSquare:N2,ChevronsDown:h3,ChevronsDownUp:t3,ChevronsLeft:c3,ChevronsLeftRight:p3,ChevronsLeftRightEllipsis:d3,ChevronsRight:s3,ChevronsRightLeft:M3,ChevronsUp:r3,ChevronsUpDown:e3,Chrome:v3,Church:n3,Cigarette:i3,CigaretteOff:o3,Circle:A3,CircleAlert:G,CircleArrowDown:W,CircleArrowLeft:X,CircleArrowOutDownLeft:N,CircleArrowOutDownRight:K,CircleArrowOutUpLeft:J,CircleArrowOutUpRight:j,CircleArrowRight:Q,CircleArrowUp:_,CircleCheck:$,CircleCheckBig:Y,CircleChevronDown:a1,CircleChevronLeft:t1,CircleChevronRight:h1,CircleChevronUp:d1,CircleDashed:l3,CircleDivide:p1,CircleDollarSign:g3,CircleDot:y3,CircleDotDashed:x3,CircleEllipsis:m3,CircleEqual:H3,CircleFadingArrowUp:V3,CircleFadingPlus:C3,CircleGauge:c1,CircleHelp:M1,CircleMinus:s1,CircleOff:w3,CircleParking:r1,CircleParkingOff:e1,CirclePause:v1,CirclePercent:n1,CirclePlay:o1,CirclePlus:i1,CirclePower:l1,CircleSlash:u3,CircleSlash2:g1,CircleSlashed:g1,CircleStop:x1,CircleUser:m1,CircleUserRound:y1,CircleX:H1,CircuitBoard:L3,Citrus:S3,Clapperboard:f3,Clipboard:R3,ClipboardCheck:Z3,ClipboardCopy:P3,ClipboardEdit:C1,ClipboardList:k3,ClipboardMinus:z3,ClipboardPaste:B3,ClipboardPen:C1,ClipboardPenLine:V1,ClipboardPlus:F3,ClipboardSignature:V1,ClipboardType:D3,ClipboardX:q3,Clock:_3,Clock1:b3,Clock10:T3,Clock11:U3,Clock12:O3,Clock2:I3,Clock3:E3,Clock4:G3,Clock5:W3,Clock6:X3,Clock7:N3,Clock8:K3,Clock9:J3,ClockArrowDown:j3,ClockArrowUp:Q3,Cloud:nd,CloudCog:Y3,CloudDownload:w1,CloudDrizzle:$3,CloudFog:ad,CloudHail:td,CloudLightning:hd,CloudMoon:pd,CloudMoonRain:dd,CloudOff:cd,CloudRain:sd,CloudRainWind:Md,CloudSnow:ed,CloudSun:vd,CloudSunRain:rd,CloudUpload:u1,Cloudy:od,Clover:id,Club:ld,Code:gd,Code2:A1,CodeSquare:K2,CodeXml:A1,Codepen:xd,Codesandbox:yd,Coffee:md,Cog:Hd,Coins:Vd,Columns:L1,Columns2:L1,Columns3:S1,Columns4:Cd,Combine:wd,Command:ud,Compass:Ad,Component:Ld,Computer:Sd,ConciergeBell:fd,Cone:Zd,Construction:Pd,Contact:kd,Contact2:f1,ContactRound:f1,Container:zd,Contrast:Bd,Cookie:Fd,CookingPot:Dd,Copy:Od,CopyCheck:qd,CopyMinus:Rd,CopyPlus:bd,CopySlash:Td,CopyX:Ud,Copyleft:Id,Copyright:Ed,CornerDownLeft:Gd,CornerDownRight:Wd,CornerLeftDown:Xd,CornerLeftUp:Nd,CornerRightDown:Kd,CornerRightUp:Jd,CornerUpLeft:jd,CornerUpRight:Qd,Cpu:_d,CreativeCommons:Yd,CreditCard:$d,Croissant:ap,Crop:tp,Cross:hp,Crosshair:dp,Crown:pp,Cuboid:cp,CupSoda:Mp,CurlyBraces:Z,Currency:sp,Cylinder:ep,Dam:rp,Database:op,DatabaseBackup:vp,DatabaseZap:np,Delete:ip,Dessert:lp,Diameter:gp,Diamond:mp,DiamondMinus:xp,DiamondPercent:Z1,DiamondPlus:yp,Dice1:Hp,Dice2:Vp,Dice3:Cp,Dice4:wp,Dice5:up,Dice6:Ap,Dices:Lp,Diff:Sp,Disc:kp,Disc2:fp,Disc3:Zp,DiscAlbum:Pp,Divide:zp,DivideCircle:p1,DivideSquare:Q2,Dna:Fp,DnaOff:Bp,Dock:Dp,Dog:qp,DollarSign:Rp,Donut:bp,DoorClosed:Tp,DoorOpen:Up,Dot:Op,DotSquare:_2,Download:Ip,DownloadCloud:w1,DraftingCompass:Ep,Drama:Gp,Dribbble:Wp,Drill:Xp,Droplet:Np,Droplets:Kp,Drum:Jp,Drumstick:jp,Dumbbell:Qp,Ear:Yp,EarOff:_p,Earth:P1,EarthLock:$p,Eclipse:a6,Edit:e,Edit2:g2,Edit3:l2,Egg:d6,EggFried:t6,EggOff:h6,Ellipsis:z1,EllipsisVertical:k1,Equal:c6,EqualNot:p6,EqualSquare:Y2,Eraser:M6,EthernetPort:s6,Euro:e6,Expand:r6,ExternalLink:v6,Eye:o6,EyeOff:n6,Facebook:i6,Factory:l6,Fan:g6,FastForward:x6,Feather:y6,Fence:m6,FerrisWheel:H6,Figma:V6,File:xc,FileArchive:C6,FileAudio:u6,FileAudio2:w6,FileAxis3D:B1,FileAxis3d:B1,FileBadge:L6,FileBadge2:A6,FileBarChart:F1,FileBarChart2:D1,FileBox:S6,FileChartColumn:D1,FileChartColumnIncreasing:F1,FileChartLine:q1,FileChartPie:R1,FileCheck:Z6,FileCheck2:f6,FileClock:P6,FileCode:z6,FileCode2:k6,FileCog:b1,FileCog2:b1,FileDiff:B6,FileDigit:F6,FileDown:D6,FileEdit:U1,FileHeart:q6,FileImage:R6,FileInput:b6,FileJson:U6,FileJson2:T6,FileKey:I6,FileKey2:O6,FileLineChart:q1,FileLock:G6,FileLock2:E6,FileMinus:X6,FileMinus2:W6,FileMusic:N6,FileOutput:K6,FilePen:U1,FilePenLine:T1,FilePieChart:R1,FilePlus:j6,FilePlus2:J6,FileQuestion:Q6,FileScan:_6,FileSearch:$6,FileSearch2:Y6,FileSignature:T1,FileSliders:ac,FileSpreadsheet:tc,FileStack:hc,FileSymlink:dc,FileTerminal:pc,FileText:cc,FileType:sc,FileType2:Mc,FileUp:ec,FileVideo:vc,FileVideo2:rc,FileVolume:oc,FileVolume2:nc,FileWarning:ic,FileX:gc,FileX2:lc,Files:yc,Film:mc,Filter:Vc,FilterX:Hc,Fingerprint:Cc,FireExtinguisher:wc,Fish:Lc,FishOff:uc,FishSymbol:Ac,Flag:Pc,FlagOff:Sc,FlagTriangleLeft:fc,FlagTriangleRight:Zc,Flame:zc,FlameKindling:kc,Flashlight:Fc,FlashlightOff:Bc,FlaskConical:qc,FlaskConicalOff:Dc,FlaskRound:Rc,FlipHorizontal:Tc,FlipHorizontal2:bc,FlipVertical:Oc,FlipVertical2:Uc,Flower:Ec,Flower2:Ic,Focus:Gc,FoldHorizontal:Wc,FoldVertical:Xc,Folder:H8,FolderArchive:Nc,FolderCheck:Kc,FolderClock:Jc,FolderClosed:jc,FolderCode:Qc,FolderCog:O1,FolderCog2:O1,FolderDot:_c,FolderDown:Yc,FolderEdit:I1,FolderGit:a8,FolderGit2:$c,FolderHeart:t8,FolderInput:h8,FolderKanban:d8,FolderKey:p8,FolderLock:c8,FolderMinus:M8,FolderOpen:e8,FolderOpenDot:s8,FolderOutput:r8,FolderPen:I1,FolderPlus:v8,FolderRoot:n8,FolderSearch:i8,FolderSearch2:o8,FolderSymlink:l8,FolderSync:g8,FolderTree:x8,FolderUp:y8,FolderX:m8,Folders:V8,Footprints:C8,ForkKnife:T0,ForkKnifeCrossed:b0,Forklift:w8,FormInput:y2,Forward:u8,Frame:A8,Framer:L8,Frown:S8,Fuel:f8,Fullscreen:Z8,FunctionSquare:$2,GalleryHorizontal:k8,GalleryHorizontalEnd:P8,GalleryThumbnails:z8,GalleryVertical:F8,GalleryVerticalEnd:B8,Gamepad:q8,Gamepad2:D8,GanttChart:O,GanttChartSquare:n,Gauge:R8,GaugeCircle:c1,Gavel:b8,Gem:T8,Ghost:U8,Gift:O8,GitBranch:E8,GitBranchPlus:I8,GitCommit:E1,GitCommitHorizontal:E1,GitCommitVertical:G8,GitCompare:X8,GitCompareArrows:W8,GitFork:N8,GitGraph:K8,GitMerge:J8,GitPullRequest:a7,GitPullRequestArrow:j8,GitPullRequestClosed:Q8,GitPullRequestCreate:Y8,GitPullRequestCreateArrow:_8,GitPullRequestDraft:$8,Github:t7,Gitlab:h7,GlassWater:d7,Glasses:p7,Globe:M7,Globe2:P1,GlobeLock:c7,Goal:s7,Grab:e7,GraduationCap:r7,Grape:v7,Grid:v,Grid2X2:G1,Grid2x2:G1,Grid2x2Check:n7,Grid2x2X:o7,Grid3X3:v,Grid3x3:v,Grip:g7,GripHorizontal:i7,GripVertical:l7,Group:x7,Guitar:y7,Ham:m7,Hammer:H7,Hand:A7,HandCoins:V7,HandHeart:C7,HandHelping:W1,HandMetal:w7,HandPlatter:u7,Handshake:L7,HardDrive:Z7,HardDriveDownload:S7,HardDriveUpload:f7,HardHat:P7,Hash:k7,Haze:z7,HdmiPort:B7,Heading:U7,Heading1:F7,Heading2:D7,Heading3:q7,Heading4:R7,Heading5:b7,Heading6:T7,Headphones:O7,Headset:I7,Heart:N7,HeartCrack:E7,HeartHandshake:G7,HeartOff:W7,HeartPulse:X7,Heater:K7,HelpCircle:M1,HelpingHand:W1,Hexagon:J7,Highlighter:j7,History:Q7,Home:X1,Hop:Y7,HopOff:_7,Hospital:$7,Hotel:aM,Hourglass:tM,House:X1,HousePlug:hM,HousePlus:dM,IceCream:K1,IceCream2:N1,IceCreamBowl:N1,IceCreamCone:K1,IdCard:pM,Image:nM,ImageDown:cM,ImageMinus:MM,ImageOff:sM,ImagePlay:eM,ImagePlus:rM,ImageUp:vM,Images:oM,Import:iM,Inbox:lM,Indent:j1,IndentDecrease:J1,IndentIncrease:j1,IndianRupee:gM,Infinity:xM,Info:yM,Inspect:c0,InspectionPanel:mM,Instagram:HM,Italic:VM,IterationCcw:CM,IterationCw:wM,JapaneseYen:uM,Joystick:AM,Kanban:LM,KanbanSquare:a0,KanbanSquareDashed:J2,Key:ZM,KeyRound:SM,KeySquare:fM,Keyboard:zM,KeyboardMusic:PM,KeyboardOff:kM,Lamp:bM,LampCeiling:BM,LampDesk:FM,LampFloor:DM,LampWallDown:qM,LampWallUp:RM,LandPlot:TM,Landmark:UM,Languages:OM,Laptop:IM,Laptop2:Q1,LaptopMinimal:Q1,Lasso:GM,LassoSelect:EM,Laugh:WM,Layers:KM,Layers2:XM,Layers3:NM,Layout:i2,LayoutDashboard:JM,LayoutGrid:jM,LayoutList:QM,LayoutPanelLeft:_M,LayoutPanelTop:YM,LayoutTemplate:$M,Leaf:as,LeafyGreen:ts,Lectern:hs,LetterText:ds,Library:cs,LibraryBig:ps,LibrarySquare:t0,LifeBuoy:Ms,Ligature:ss,Lightbulb:rs,LightbulbOff:es,LineChart:b,Link:os,Link2:ns,Link2Off:vs,Linkedin:is,List:Ps,ListCheck:ls,ListChecks:gs,ListCollapse:xs,ListEnd:ys,ListFilter:ms,ListMinus:Hs,ListMusic:Vs,ListOrdered:Cs,ListPlus:ws,ListRestart:us,ListStart:As,ListTodo:Ls,ListTree:Ss,ListVideo:fs,ListX:Zs,Loader:zs,Loader2:_1,LoaderCircle:_1,LoaderPinwheel:ks,Locate:Ds,LocateFixed:Bs,LocateOff:Fs,Lock:Rs,LockKeyhole:qs,LockKeyholeOpen:Y1,LockOpen:$1,LogIn:bs,LogOut:Ts,Logs:Us,Lollipop:Os,Luggage:Is,MSquare:h0,Magnet:Es,Mail:_s,MailCheck:Gs,MailMinus:Ws,MailOpen:Xs,MailPlus:Ns,MailQuestion:Ks,MailSearch:Js,MailWarning:js,MailX:Qs,Mailbox:Ys,Mails:$s,Map:oe,MapPin:ve,MapPinCheck:te,MapPinCheckInside:ae,MapPinHouse:he,MapPinMinus:pe,MapPinMinusInside:de,MapPinOff:ce,MapPinPlus:se,MapPinPlusInside:Me,MapPinX:re,MapPinXInside:ee,MapPinned:ne,Martini:ie,Maximize:ge,Maximize2:le,Medal:xe,Megaphone:me,MegaphoneOff:ye,Meh:He,MemoryStick:Ve,Menu:Ce,MenuSquare:d0,Merge:we,MessageCircle:Fe,MessageCircleCode:ue,MessageCircleDashed:Ae,MessageCircleHeart:Le,MessageCircleMore:Se,MessageCircleOff:fe,MessageCirclePlus:Ze,MessageCircleQuestion:Pe,MessageCircleReply:ke,MessageCircleWarning:ze,MessageCircleX:Be,MessageSquare:Je,MessageSquareCode:De,MessageSquareDashed:qe,MessageSquareDiff:Re,MessageSquareDot:be,MessageSquareHeart:Te,MessageSquareMore:Ue,MessageSquareOff:Oe,MessageSquarePlus:Ie,MessageSquareQuote:Ee,MessageSquareReply:Ge,MessageSquareShare:We,MessageSquareText:Xe,MessageSquareWarning:Ne,MessageSquareX:Ke,MessagesSquare:je,Mic:_e,Mic2:a2,MicOff:Qe,MicVocal:a2,Microchip:Ye,Microscope:$e,Microwave:a9,Milestone:t9,Milk:d9,MilkOff:h9,Minimize:c9,Minimize2:p9,Minus:M9,MinusCircle:s1,MinusSquare:p0,Monitor:H9,MonitorCheck:s9,MonitorCog:e9,MonitorDot:r9,MonitorDown:v9,MonitorOff:n9,MonitorPause:o9,MonitorPlay:i9,MonitorSmartphone:l9,MonitorSpeaker:g9,MonitorStop:x9,MonitorUp:y9,MonitorX:m9,Moon:C9,MoonStar:V9,MoreHorizontal:z1,MoreVertical:k1,Mountain:u9,MountainSnow:w9,Mouse:P9,MouseOff:A9,MousePointer:Z9,MousePointer2:L9,MousePointerBan:S9,MousePointerClick:f9,MousePointerSquareDashed:j2,Move:E9,Move3D:t2,Move3d:t2,MoveDiagonal:z9,MoveDiagonal2:k9,MoveDown:D9,MoveDownLeft:B9,MoveDownRight:F9,MoveHorizontal:q9,MoveLeft:R9,MoveRight:b9,MoveUp:O9,MoveUpLeft:T9,MoveUpRight:U9,MoveVertical:I9,Music:N9,Music2:G9,Music3:W9,Music4:X9,Navigation:Q9,Navigation2:J9,Navigation2Off:K9,NavigationOff:j9,Network:_9,Newspaper:Y9,Nfc:$9,Notebook:dr,NotebookPen:ar,NotebookTabs:tr,NotebookText:hr,NotepadText:cr,NotepadTextDashed:pr,Nut:sr,NutOff:Mr,Octagon:er,OctagonAlert:h2,OctagonPause:d2,OctagonX:p2,Omega:rr,Option:vr,Orbit:nr,Origami:or,Outdent:J1,Package:Vr,Package2:ir,PackageCheck:lr,PackageMinus:gr,PackageOpen:xr,PackagePlus:yr,PackageSearch:mr,PackageX:Hr,PaintBucket:Cr,PaintRoller:wr,Paintbrush:ur,Paintbrush2:c2,PaintbrushVertical:c2,Palette:Ar,Palmtree:S0,PanelBottom:fr,PanelBottomClose:Lr,PanelBottomDashed:M2,PanelBottomInactive:M2,PanelBottomOpen:Sr,PanelLeft:v2,PanelLeftClose:s2,PanelLeftDashed:e2,PanelLeftInactive:e2,PanelLeftOpen:r2,PanelRight:kr,PanelRightClose:Zr,PanelRightDashed:n2,PanelRightInactive:n2,PanelRightOpen:Pr,PanelTop:Fr,PanelTopClose:zr,PanelTopDashed:o2,PanelTopInactive:o2,PanelTopOpen:Br,PanelsLeftBottom:Dr,PanelsLeftRight:S1,PanelsRightBottom:qr,PanelsTopBottom:V2,PanelsTopLeft:i2,Paperclip:Rr,Parentheses:br,ParkingCircle:r1,ParkingCircleOff:e1,ParkingMeter:Tr,ParkingSquare:s0,ParkingSquareOff:M0,PartyPopper:Ur,Pause:Or,PauseCircle:v1,PauseOctagon:d2,PawPrint:Ir,PcCase:Er,Pen:g2,PenBox:e,PenLine:l2,PenOff:Gr,PenSquare:e,PenTool:Wr,Pencil:Jr,PencilLine:Xr,PencilOff:Nr,PencilRuler:Kr,Pentagon:jr,Percent:Qr,PercentCircle:n1,PercentDiamond:Z1,PercentSquare:e0,PersonStanding:_r,PhilippinePeso:Yr,Phone:cv,PhoneCall:$r,PhoneForwarded:av,PhoneIncoming:tv,PhoneMissed:hv,PhoneOff:dv,PhoneOutgoing:pv,Pi:Mv,PiSquare:r0,Piano:sv,Pickaxe:ev,PictureInPicture:vv,PictureInPicture2:rv,PieChart:I,PiggyBank:nv,Pilcrow:lv,PilcrowLeft:ov,PilcrowRight:iv,PilcrowSquare:v0,Pill:xv,PillBottle:gv,Pin:mv,PinOff:yv,Pipette:Hv,Pizza:Vv,Plane:uv,PlaneLanding:Cv,PlaneTakeoff:wv,Play:Av,PlayCircle:o1,PlaySquare:n0,Plug:Sv,Plug2:Lv,PlugZap:x2,PlugZap2:x2,Plus:fv,PlusCircle:i1,PlusSquare:o0,Pocket:Pv,PocketKnife:Zv,Podcast:kv,Pointer:Bv,PointerOff:zv,Popcorn:Fv,Popsicle:Dv,PoundSterling:qv,Power:bv,PowerCircle:l1,PowerOff:Rv,PowerSquare:i0,Presentation:Tv,Printer:Ov,PrinterCheck:Uv,Projector:Iv,Proportions:Ev,Puzzle:Gv,Pyramid:Wv,QrCode:Xv,Quote:Nv,Rabbit:Kv,Radar:Jv,Radiation:jv,Radical:Qv,Radio:$v,RadioReceiver:_v,RadioTower:Yv,Radius:an,RailSymbol:tn,Rainbow:hn,Rat:dn,Ratio:pn,Receipt:ln,ReceiptCent:cn,ReceiptEuro:Mn,ReceiptIndianRupee:sn,ReceiptJapaneseYen:en,ReceiptPoundSterling:rn,ReceiptRussianRuble:vn,ReceiptSwissFranc:nn,ReceiptText:on,RectangleEllipsis:y2,RectangleHorizontal:gn,RectangleVertical:xn,Recycle:yn,Redo:Vn,Redo2:mn,RedoDot:Hn,RefreshCcw:wn,RefreshCcwDot:Cn,RefreshCw:An,RefreshCwOff:un,Refrigerator:Ln,Regex:Sn,RemoveFormatting:fn,Repeat:kn,Repeat1:Zn,Repeat2:Pn,Replace:Bn,ReplaceAll:zn,Reply:Dn,ReplyAll:Fn,Rewind:qn,Ribbon:Rn,Rocket:bn,RockingChair:Tn,RollerCoaster:Un,Rotate3D:m2,Rotate3d:m2,RotateCcw:In,RotateCcwSquare:On,RotateCw:Gn,RotateCwSquare:En,Route:Xn,RouteOff:Wn,Router:Nn,Rows:H2,Rows2:H2,Rows3:V2,Rows4:Kn,Rss:Jn,Ruler:jn,RussianRuble:Qn,Sailboat:_n,Salad:Yn,Sandwich:$n,Satellite:to,SatelliteDish:ao,Save:co,SaveAll:ho,SaveOff:po,Scale:Mo,Scale3D:C2,Scale3d:C2,Scaling:so,Scan:go,ScanBarcode:eo,ScanEye:ro,ScanFace:vo,ScanLine:no,ScanQrCode:oo,ScanSearch:io,ScanText:lo,ScatterChart:E,School:xo,School2:P0,Scissors:mo,ScissorsLineDashed:yo,ScissorsSquare:l0,ScissorsSquareDashedBottom:O2,ScreenShare:Vo,ScreenShareOff:Ho,Scroll:wo,ScrollText:Co,Search:fo,SearchCheck:uo,SearchCode:Ao,SearchSlash:Lo,SearchX:So,Section:Zo,Send:ko,SendHorizonal:w2,SendHorizontal:w2,SendToBack:Po,SeparatorHorizontal:zo,SeparatorVertical:Bo,Server:Ro,ServerCog:Fo,ServerCrash:Do,ServerOff:qo,Settings:To,Settings2:bo,Shapes:Uo,Share:Io,Share2:Oo,Sheet:Eo,Shell:Go,Shield:$o,ShieldAlert:Wo,ShieldBan:Xo,ShieldCheck:No,ShieldClose:u2,ShieldEllipsis:Ko,ShieldHalf:Jo,ShieldMinus:jo,ShieldOff:Qo,ShieldPlus:_o,ShieldQuestion:Yo,ShieldX:u2,Ship:ti,ShipWheel:ai,Shirt:hi,ShoppingBag:di,ShoppingBasket:pi,ShoppingCart:ci,Shovel:Mi,ShowerHead:si,Shrink:ei,Shrub:ri,Shuffle:vi,Sidebar:v2,SidebarClose:s2,SidebarOpen:r2,Sigma:ni,SigmaSquare:g0,Signal:xi,SignalHigh:oi,SignalLow:ii,SignalMedium:li,SignalZero:gi,Signature:yi,Signpost:Hi,SignpostBig:mi,Siren:Vi,SkipBack:Ci,SkipForward:wi,Skull:ui,Slack:Ai,Slash:Li,SlashSquare:x0,Slice:Si,Sliders:A2,SlidersHorizontal:fi,SlidersVertical:A2,Smartphone:ki,SmartphoneCharging:Zi,SmartphoneNfc:Pi,Smile:Bi,SmilePlus:zi,Snail:Fi,Snowflake:Di,Sofa:qi,SortAsc:C,SortDesc:m,Soup:Ri,Space:bi,Spade:Ti,Sparkle:Ui,Sparkles:L2,Speaker:Oi,Speech:Ii,SpellCheck:Gi,SpellCheck2:Ei,Spline:Wi,Split:Xi,SplitSquareHorizontal:y0,SplitSquareVertical:m0,SprayCan:Ni,Sprout:Ki,Square:$i,SquareActivity:S2,SquareArrowDown:P2,SquareArrowDownLeft:f2,SquareArrowDownRight:Z2,SquareArrowLeft:k2,SquareArrowOutDownLeft:z2,SquareArrowOutDownRight:B2,SquareArrowOutUpLeft:F2,SquareArrowOutUpRight:D2,SquareArrowRight:q2,SquareArrowUp:T2,SquareArrowUpLeft:R2,SquareArrowUpRight:b2,SquareAsterisk:U2,SquareBottomDashedScissors:O2,SquareChartGantt:n,SquareCheck:E2,SquareCheckBig:I2,SquareChevronDown:G2,SquareChevronLeft:W2,SquareChevronRight:X2,SquareChevronUp:N2,SquareCode:K2,SquareDashedBottom:ji,SquareDashedBottomCode:Ji,SquareDashedKanban:J2,SquareDashedMousePointer:j2,SquareDivide:Q2,SquareDot:_2,SquareEqual:Y2,SquareFunction:$2,SquareGanttChart:n,SquareKanban:a0,SquareLibrary:t0,SquareM:h0,SquareMenu:d0,SquareMinus:p0,SquareMousePointer:c0,SquareParking:s0,SquareParkingOff:M0,SquarePen:e,SquarePercent:e0,SquarePi:r0,SquarePilcrow:v0,SquarePlay:n0,SquarePlus:o0,SquarePower:i0,SquareRadical:Qi,SquareScissors:l0,SquareSigma:g0,SquareSlash:x0,SquareSplitHorizontal:y0,SquareSplitVertical:m0,SquareSquare:_i,SquareStack:Yi,SquareTerminal:H0,SquareUser:C0,SquareUserRound:V0,SquareX:w0,Squircle:al,Squirrel:tl,Stamp:hl,Star:cl,StarHalf:dl,StarOff:pl,Stars:L2,StepBack:Ml,StepForward:sl,Stethoscope:el,Sticker:rl,StickyNote:vl,StopCircle:x1,Store:nl,StretchHorizontal:ol,StretchVertical:il,Strikethrough:ll,Subscript:gl,Subtitles:P,Sun:Vl,SunDim:xl,SunMedium:yl,SunMoon:ml,SunSnow:Hl,Sunrise:Cl,Sunset:wl,Superscript:ul,SwatchBook:Al,SwissFranc:Ll,SwitchCamera:Sl,Sword:fl,Swords:Zl,Syringe:Pl,Table:bl,Table2:kl,TableCellsMerge:zl,TableCellsSplit:Bl,TableColumnsSplit:Fl,TableOfContents:Dl,TableProperties:ql,TableRowsSplit:Rl,Tablet:Ul,TabletSmartphone:Tl,Tablets:Ol,Tag:Il,Tags:El,Tally1:Gl,Tally2:Wl,Tally3:Xl,Tally4:Nl,Tally5:Kl,Tangent:Jl,Target:jl,Telescope:Ql,Tent:Yl,TentTree:_l,Terminal:$l,TerminalSquare:H0,TestTube:ag,TestTube2:u0,TestTubeDiagonal:u0,TestTubes:tg,Text:Mg,TextCursor:dg,TextCursorInput:hg,TextQuote:pg,TextSearch:cg,TextSelect:A0,TextSelection:A0,Theater:sg,Thermometer:vg,ThermometerSnowflake:eg,ThermometerSun:rg,ThumbsDown:ng,ThumbsUp:og,Ticket:Hg,TicketCheck:ig,TicketMinus:lg,TicketPercent:gg,TicketPlus:xg,TicketSlash:yg,TicketX:mg,Tickets:Cg,TicketsPlane:Vg,Timer:Ag,TimerOff:wg,TimerReset:ug,ToggleLeft:Lg,ToggleRight:Sg,Tornado:fg,Torus:Zg,Touchpad:kg,TouchpadOff:Pg,TowerControl:zg,ToyBrick:Bg,Tractor:Fg,TrafficCone:Dg,Train:L0,TrainFront:Rg,TrainFrontTunnel:qg,TrainTrack:bg,TramFront:L0,Trash:Ug,Trash2:Tg,TreeDeciduous:Og,TreePalm:S0,TreePine:Ig,Trees:Eg,Trello:Gg,TrendingDown:Wg,TrendingUp:Xg,Triangle:Kg,TriangleAlert:f0,TriangleRight:Ng,Trophy:Jg,Truck:jg,Turtle:Qg,Tv:Yg,Tv2:Z0,TvMinimal:Z0,TvMinimalPlay:_g,Twitch:$g,Twitter:ax,Type:hx,TypeOutline:tx,Umbrella:px,UmbrellaOff:dx,Underline:cx,Undo:ex,Undo2:Mx,UndoDot:sx,UnfoldHorizontal:rx,UnfoldVertical:vx,Ungroup:nx,University:P0,Unlink:ix,Unlink2:ox,Unlock:$1,UnlockKeyhole:Y1,Unplug:lx,Upload:gx,UploadCloud:u1,Usb:xx,User:Sx,User2:q0,UserCheck:yx,UserCheck2:k0,UserCircle:m1,UserCircle2:y1,UserCog:mx,UserCog2:z0,UserMinus:Hx,UserMinus2:B0,UserPen:Vx,UserPlus:Cx,UserPlus2:F0,UserRound:q0,UserRoundCheck:k0,UserRoundCog:z0,UserRoundMinus:B0,UserRoundPen:wx,UserRoundPlus:F0,UserRoundSearch:ux,UserRoundX:D0,UserSearch:Ax,UserSquare:C0,UserSquare2:V0,UserX:Lx,UserX2:D0,Users:fx,Users2:R0,UsersRound:R0,Utensils:T0,UtensilsCrossed:b0,UtilityPole:Zx,Variable:Px,Vault:kx,Vegan:zx,VenetianMask:Bx,Verified:A,Vibrate:Dx,VibrateOff:Fx,Video:Rx,VideoOff:qx,Videotape:bx,View:Tx,Voicemail:Ux,Volume:Gx,Volume1:Ox,Volume2:Ix,VolumeX:Ex,Vote:Wx,Wallet:Nx,Wallet2:U0,WalletCards:Xx,WalletMinimal:U0,Wallpaper:Kx,Wand:Jx,Wand2:O0,WandSparkles:O0,Warehouse:jx,WashingMachine:Qx,Watch:_x,Waves:Yx,Waypoints:$x,Webcam:ay,Webhook:hy,WebhookOff:ty,Weight:dy,Wheat:cy,WheatOff:py,WholeWord:My,Wifi:ny,WifiHigh:sy,WifiLow:ey,WifiOff:ry,WifiZero:vy,Wind:oy,Wine:ly,WineOff:iy,Workflow:gy,Worm:xy,WrapText:yy,Wrench:my,X:Hy,XCircle:H1,XOctagon:p2,XSquare:w0,Youtube:Vy,Zap:wy,ZapOff:Cy,ZoomIn:uy,ZoomOut:Ay,createElement:I0,createIcons:({icons:t={},nameAttr:p="data-lucide",attrs:h={}}={})=>{if(!Object.values(t).length)throw new Error(`Please provide an icons object. +If you want to use all the icons you can import it like: + \`import { createIcons, icons } from 'lucide'; +lucide.createIcons({icons});\``);if(typeof document>"u")throw new Error("`createIcons()` only works in a browser environment.");const c=document.querySelectorAll(`[${p}]`);if(Array.from(c).forEach(d=>G0(d,{nameAttr:p,icons:t,attrs:h})),p==="data-lucide"){const d=document.querySelectorAll("[icon-name]");d.length>0&&(console.warn("[Lucide] Some icons were found with the now deprecated icon-name attribute. These will still be replaced for backwards compatibility, but will no longer be supported in v1.0 and you should switch to data-lucide"),Array.from(d).forEach(s=>G0(s,{nameAttr:"icon-name",icons:t,attrs:h})))}},icons:Dy},Symbol.toStringTag,{value:"Module"}));var Ry=Object.defineProperty,by=Object.getOwnPropertyDescriptor,o=(t,p,h,c)=>{for(var d=c>1?void 0:c?by(p,h):p,s=t.length-1,i;s>=0;s--)(i=t[s])&&(d=(c?i(p,h,d):i(d))||d);return c&&d&&Ry(p,h,d),d};return M.Icon=class extends Py.LitElement{constructor(){super(),this["custom-class"]="",this.icon="",this["stroke-width"]="2",this.height="16",this.width="16"}connectedCallback(){super.connectedCallback(),this.removeAttribute("uk-cloak")}createRenderRoot(){return this}render(){const p=this.icon.trim().split("-").map(h=>h.charAt(0).toUpperCase()+h.slice(1)).join("");try{const h=I0(qy[p]);if(h.setAttribute("class",this["custom-class"]),h.setAttribute("height",this.height),h.setAttribute("stroke-width",this["stroke-width"]),h.setAttribute("width",this.width),this.renderRoot.children.length===0)return h}catch{}}},o([r.property({type:String})],M.Icon.prototype,"custom-class",2),o([r.property({type:String})],M.Icon.prototype,"icon",2),o([r.property({type:String})],M.Icon.prototype,"stroke-width",2),o([r.property({type:String})],M.Icon.prototype,"height",2),o([r.property({type:String})],M.Icon.prototype,"width",2),M.Icon=o([r.customElement("uk-icon")],M.Icon),Object.defineProperty(M,Symbol.toStringTag,{value:"Module"}),M}({},Lit,LitDecorators); diff --git a/MonsterUI/nbs/.!32603!screenshot_cropped.png b/MonsterUI/nbs/.!32603!screenshot_cropped.png new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/MonsterUI/nbs/.last_checked b/MonsterUI/nbs/.last_checked new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/MonsterUI/nbs/00_foundation.ipynb b/MonsterUI/nbs/00_foundation.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..a299d74dcded8fc55cc5cdfa5690d7f8d8b44f27 --- /dev/null +++ b/MonsterUI/nbs/00_foundation.ipynb @@ -0,0 +1,184 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Foundation\n", + "\n", + "> Data Structures and Utilties" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| default_exp foundations" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "#| export\n", + "from enum import Enum, auto\n", + "from fastcore.all import *" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "from nbdev.showdoc import show_doc" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "show_doc = partial(show_doc, title_level=4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Stringification" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "# need a better name, stringify might be too general for what it does \n", + "def stringify(o # String, Tuple, or Enum options we want stringified\n", + " ): # String that can be passed FT comp args (such as `cls=`)\n", + " \"Converts input types into strings that can be passed to FT components\" \n", + " if is_listy(o): return ' '.join(map(str,o)) if o else \"\"\n", + " return o.__str__()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "assert stringify('abc') == 'abc'\n", + "assert stringify(('abc','def')) == 'abc def'\n", + "assert 'uk-input ' + stringify(()) == 'uk-input '\n", + "assert 'uk-input ' + stringify(\"\") == 'uk-input '" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Enum Utilities" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def str2ukcls(base, txt): return f\"uk-{base}-{txt.replace('_', '-')}\".strip('-')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class VEnum(Enum):\n", + " def __str__(self): return self.value\n", + " def __add__(self, other): return stringify((self,other))\n", + " def __radd__(self, other): return stringify((other,self))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class TextT(VEnum):\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('text', name)\n", + " \n", + " foo = '1234'\n", + " red = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "assert TextT.foo + TextT.red == '1234 uk-text-red'\n", + "assert TextT.red + TextT.foo == 'uk-text-red 1234'\n", + "assert 'uk-text-red' + TextT.foo == 'uk-text-red 1234'\n", + "assert TextT.red + '1234' == 'uk-text-red 1234'\n", + "assert stringify((TextT.red,TextT.foo)) == 'uk-text-red 1234'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "import nbdev; nbdev.nbdev_export()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "python3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/MonsterUI/nbs/01_core.ipynb b/MonsterUI/nbs/01_core.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..13e83be4f0d6baad77c923ed736693966fd220a3 --- /dev/null +++ b/MonsterUI/nbs/01_core.ipynb @@ -0,0 +1,537 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Core\n", + "\n", + "> The building blocks to the UI" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| default_exp core" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "import fasthtml.common as fh\n", + "from monsterui.foundations import *\n", + "from fasthtml.common import FastHTML, fast_app\n", + "from enum import Enum, auto\n", + "from fastcore.all import *\n", + "import httpx\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from fasthtml.jupyter import *\n", + "from functools import partial" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from nbdev.showdoc import *" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## App" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "@delegates(fh.fast_app, but=['pico'])\n", + "def fast_app(*args, pico=False, **kwargs):\n", + " \"Create a FastHTML or FastHTMLWithLiveReload app with `bg-background text-foreground` to bodykw for frankenui themes\"\n", + " if 'bodykw' not in kwargs: kwargs['bodykw'] = {}\n", + " if 'class' not in kwargs['bodykw']: kwargs['bodykw']['class'] = ''\n", + " kwargs['bodykw']['class'] = stringify((kwargs['bodykw']['class'],'bg-background text-foreground'))\n", + " return fh.fast_app(*args, pico=pico, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "assert fast_app(bodykw={'something':'test'})[0].bodykw == {'something': 'test', 'class': ' bg-background text-foreground'}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "@delegates(fh.FastHTML, but=['pico'])\n", + "def FastHTML(*args, pico=False, **kwargs):\n", + " \"Create a FastHTML app and adds `bg-background text-foreground` to bodykw for frankenui themes\"\n", + " if 'bodykw' not in kwargs: kwargs['bodykw'] = {}\n", + " if 'class' not in kwargs['bodykw']: kwargs['bodykw']['class'] = ''\n", + " kwargs['bodykw']['class'] = stringify((kwargs['bodykw']['class'],'bg-background text-foreground'))\n", + " bodykw = kwargs.pop('bodykw',{})\n", + " return fh.FastHTML(*args, pico=pico, **bodykw, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'pico': False, 'something': 'test', 'class': ' bg-background text-foreground'}" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "FastHTML(bodykw={'something':'test'}).bodykw" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Theme / Headers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can select a theme color to and get all the headers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class ThemeRadii(VEnum):\n", + " none = 'uk-radii-none'\n", + " sm = 'uk-radii-sm'\n", + " md = 'uk-radii-md'\n", + " lg = 'uk-radii-lg'\n", + "\n", + "class ThemeShadows:\n", + " none = 'uk-shadows-none'\n", + " sm = 'uk-shadows-sm'\n", + " md = 'uk-shadows-md'\n", + " lg = 'uk-shadows-lg'\n", + "\n", + "class ThemeFont:\n", + " sm = 'uk-font-sm'\n", + " default = 'uk-font-base'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def _headers_theme(color, mode='auto', radii=ThemeRadii.sm, shadows=ThemeShadows.sm, font=ThemeFont.sm):\n", + " franken_init = '''\n", + " const __FRANKEN__ = JSON.parse(localStorage.getItem(\"__FRANKEN__\") || \"{}\");\n", + " '''\n", + " \n", + " mode_script = {\n", + " 'auto': f'''\n", + " {franken_init}\n", + " if (\n", + " __FRANKEN__.mode === \"dark\" ||\n", + " (!__FRANKEN__.mode &&\n", + " window.matchMedia(\"(prefers-color-scheme: dark)\").matches)\n", + " ) {{\n", + " htmlElement.classList.add(\"dark\");\n", + " }} else {{\n", + " htmlElement.classList.remove(\"dark\");\n", + " }}\n", + " ''',\n", + " 'light': f'{franken_init}\\nhtmlElement.classList.remove(\"dark\");',\n", + " 'dark': f'{franken_init}\\nhtmlElement.classList.add(\"dark\");'\n", + " }\n", + " \n", + " return fh.Script(f'''\n", + " const htmlElement = document.documentElement;\n", + " {mode_script[mode]}\n", + " htmlElement.classList.add(__FRANKEN__.theme || \"uk-theme-{color}\");\n", + " htmlElement.classList.add(__FRANKEN__.radii || \"{radii}\");\n", + " htmlElement.classList.add(__FRANKEN__.shadows || \"{shadows}\");\n", + " htmlElement.classList.add(__FRANKEN__.font || \"{font}\");\n", + " ''')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "HEADER_URLS = {\n", + " 'franken_css': \"https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/css/core.min.css\",\n", + " 'franken_js_core': \"https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/core.iife.js\",\n", + " 'franken_icons': \"https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/icon.iife.js\",\n", + " 'tailwind': \"https://cdn.tailwindcss.com/3.4.16\",\n", + " 'daisyui': \"https://cdn.jsdelivr.net/npm/daisyui@4.12.24/dist/full.min.css\",\n", + " 'apex_charts': \"https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/chart.iife.js\",\n", + " 'highlight_js': \"https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js\",\n", + " 'highlight_python': \"https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/python.min.js\",\n", + " 'highlight_light_css': \"https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/atom-one-light.css\",\n", + " 'highlight_dark_css': \"https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/atom-one-dark.css\",\n", + " 'highlight_copy': \"https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js\",\n", + " 'highlight_copy_css': \"https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css\",\n", + "}\n", + "\n", + "def _download_resource(url, static_dir):\n", + " \"Download a single resource and return its local path\"\n", + " static = Path(static_dir)\n", + " fname = static/f\"{url[0]}.{'js' if 'js' in url[1] else 'css'}\"\n", + " content = httpx.get(url[1], follow_redirects=True).content\n", + " fname.write_bytes(content)\n", + " return (url[0], f\"/{static_dir}/{fname.name}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "daisy_styles = Style(\"\"\"\n", + ":root {\n", + " --b1: from hsl(var(--background)) l c h;\n", + " --bc: from hsl(var(--foreground)) l c h;\n", + " --m: from hsl(var(--muted)) l c h;\n", + " --mc: from hsl(var(--muted-foreground)) l c h;\n", + " --po: from hsl(var(--popover)) l c h;\n", + " --poc: from hsl(var(--popover-foreground)) l c h;\n", + " --b2: from hsl(var(--card)) l c h;\n", + " --b2c: from hsl(var(--card-foreground)) l c h;\n", + " --br: from hsl(var(--border)) l c h;\n", + " --in: from hsl(var(--input)) l c h;\n", + " --p: from hsl(var(--primary)) l c h;\n", + " --pc: from hsl(var(--primary-foreground)) l c h;\n", + " --s: from hsl(var(--secondary)) l c h;\n", + " --sc: from hsl(var(--secondary-foreground)) l c h;\n", + " --a: from hsl(var(--accent)) l c h;\n", + " --ac: from hsl(var(--accent-foreground)) l c h;\n", + " --er: from hsl(var(--destructive)) l c h;\n", + " --erc: from hsl(var(--destructive-foreground)) l c h;\n", + " --b3: from hsl(var(--ring)) l c h;\n", + " --ch1: from hsl(var(--chart-1)) l c h;\n", + " --ch2: from hsl(var(--chart-2)) l c h;\n", + " --ch3: from hsl(var(--chart-3)) l c h;\n", + " --ch4: from hsl(var(--chart-4)) l c h;\n", + " --ch5: from hsl(var(--chart-5)) l c h;\n", + " --rd: var(--radius);\n", + "}\n", + "\"\"\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "scrollspy_style= Style('''\n", + ".monster-navbar.navbar-bold a {\n", + " transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n", + "}\n", + ".monster-navbar.navbar-bold a.uk-active {\n", + " transform: scale(1.15) ;\n", + " font-weight: bold;\n", + " text-shadow: 0 0 12px rgba(var(--p-rgb), 0.4);\n", + " letter-spacing: 0.02em;\n", + " color: hsl(var(--p) / 1);\n", + "}\n", + ".monster-navbar.navbar-underline a.uk-active { position: relative; }\n", + ".monster-navbar.navbar-underline a.uk-active::after {\n", + " content: '';\n", + " position: absolute;\n", + " left: 0;\n", + " bottom: -2px;\n", + " width: 100%;\n", + " height: 2px;\n", + " background: currentColor;\n", + " animation: slideIn 0.3s ease forwards;\n", + "}\n", + "@keyframes slideIn {\n", + " from { transform: scaleX(0); }\n", + " to { transform: scaleX(1); }\n", + "}\n", + "''')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class Theme(Enum):\n", + " \"Selector to choose theme and get all headers needed for app. Includes frankenui + tailwind + daisyui + highlight.js options\"\n", + " def _generate_next_value_(name, start, count, last_values): return name\n", + " slate = auto()\n", + " stone = auto()\n", + " gray = auto()\n", + " neutral = auto()\n", + " red = auto()\n", + " rose = auto()\n", + " orange = auto()\n", + " green = auto()\n", + " blue = auto()\n", + " yellow = auto()\n", + " violet = auto()\n", + " zinc = auto()\n", + "\n", + " def _create_headers(self, urls, mode='auto', icons=True, daisy=True, highlightjs=False, katex=False, apex_charts=False, radii=ThemeRadii.sm, shadows=ThemeShadows.sm, font=ThemeFont.sm):\n", + " \"Create header elements with given URLs\"\n", + " hdrs = [\n", + " fh.Link(rel=\"stylesheet\", href=urls['franken_css']),\n", + " fh.Script(type=\"module\", src=urls['franken_js_core']),\n", + " fh.Script(src=urls['tailwind']),\n", + " fh.Script(\"\"\"\n", + " tailwind.config = {\n", + " darkMode: 'selector',\n", + " }\n", + " \"\"\"),\n", + " _headers_theme(self.value, mode=mode, radii=radii, shadows=shadows, font=font),\n", + " scrollspy_style]\n", + "\n", + " if icons: hdrs.append(fh.Script(type=\"module\", src=urls['franken_icons']))\n", + " if daisy: hdrs += [fh.Link(rel=\"stylesheet\", href=urls['daisyui']), daisy_styles]\n", + " if apex_charts: hdrs += [fh.Script(type='module', src=urls['apex_charts'])]\n", + " \n", + " if highlightjs:\n", + " hdrs += [\n", + " fh.Script(src=urls['highlight_js']),\n", + " fh.Script(src=urls['highlight_python']),\n", + " fh.Link(rel=\"stylesheet\", href=urls['highlight_light_css'], id='hljs-light'),\n", + " fh.Link(rel=\"stylesheet\", href=urls['highlight_dark_css'], id='hljs-dark'),\n", + " fh.Script(src=urls['highlight_copy']),\n", + " fh.Link(rel=\"stylesheet\", href=urls['highlight_copy_css']),\n", + " fh.Script('''\n", + " hljs.addPlugin(new CopyButtonPlugin());\n", + " hljs.configure({\n", + " cssSelector: 'pre code',\n", + " languages: ['python'],\n", + " ignoreUnescapedHTML: true\n", + " });\n", + " function updateTheme() {\n", + " const isDark = document.documentElement.classList.contains('dark');\n", + " document.getElementById('hljs-dark').disabled = !isDark;\n", + " document.getElementById('hljs-light').disabled = isDark;\n", + " }\n", + " new MutationObserver(mutations =>\n", + " mutations.forEach(m => m.target.tagName === 'HTML' &&\n", + " m.attributeName === 'class' && updateTheme())\n", + " ).observe(document.documentElement, { attributes: true });\n", + " updateTheme();\n", + " htmx.onLoad(hljs.highlightAll);\n", + " ''', type='module'),\n", + " ]\n", + "\n", + " if katex:\n", + " hdrs += [\n", + " fh.Link(rel=\"stylesheet\",\n", + " href=\"https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css\"),\n", + " fh.Script(\"\"\"\n", + " import katex from 'https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.mjs';\n", + " import autoRender from 'https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/contrib/auto-render.mjs';\n", + " const options = {\n", + " delimiters: [\n", + " {left: '$$', right: '$$', display: true},\n", + " {left: '$', right: '$', display: false}\n", + " ],\n", + " ignoredClasses: ['nomath']\n", + " };\n", + "\n", + " document.addEventListener('htmx:load', evt => {\n", + " const element = evt.detail.elt || document.body;\n", + " autoRender(element,options);\n", + " });\n", + " \"\"\",type=\"module\"),\n", + " ]\n", + " return hdrs\n", + "\n", + " def headers(self, mode='auto', icons=True, daisy=True, highlightjs=False, katex=False, apex_charts=False, radii=ThemeRadii.sm, shadows=ThemeShadows.sm, font=ThemeFont.sm ):\n", + " \"Create frankenui and tailwind cdns\"\n", + " return self._create_headers(HEADER_URLS, mode=mode, icons=icons, daisy=daisy, highlightjs=highlightjs, katex=katex, apex_charts=apex_charts, radii=radii, shadows=shadows, font=font) \n", + " \n", + " def local_headers(self, mode='auto', static_dir='static', icons=True, daisy=True, highlightjs=False, katex=False, apex_charts=False, radii='md', shadows='sm', font='sm'):\n", + " \"Create headers using local files downloaded from CDNs\"\n", + " Path(static_dir).mkdir(exist_ok=True)\n", + " local_urls = dict([_download_resource(url, static_dir) for url in HEADER_URLS.items()])\n", + " return self._create_headers(local_urls, mode=mode, icons=icons, daisy=daisy, highlightjs=highlightjs, katex=katex, apex_charts=apex_charts, radii=radii, shadows=shadows, font=font)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/css/core.min.css\n", + "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/core.iife.js\n", + "https://cdn.tailwindcss.com/3.4.16\n", + "inline\n", + "inline\n", + "inline\n", + "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/icon.iife.js\n", + "https://cdn.jsdelivr.net/npm/daisyui@4.12.24/dist/full.min.css\n", + "inline\n" + ] + } + ], + "source": [ + "for h in Theme.blue.headers(): print(h.href or h.src or \"inline\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`katex` and `highlightjs` are not included by default. To include them set `katex=True` or `highlightjs=True` when calling `.headers`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/css/core.min.css\n", + "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/core.iife.js\n", + "https://cdn.tailwindcss.com/3.4.16\n", + "inline\n", + "inline\n", + "inline\n", + "https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/icon.iife.js\n", + "https://cdn.jsdelivr.net/npm/daisyui@4.12.24/dist/full.min.css\n", + "inline\n", + "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js\n", + "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/python.min.js\n", + "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/atom-one-light.css\n", + "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/atom-one-dark.css\n", + "https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js\n", + "https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css\n", + "inline\n", + "https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css\n", + "inline\n" + ] + } + ], + "source": [ + "for h in Theme.blue.headers(katex=True, highlightjs=True): print(h.href or h.src or \"inline\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app = FastHTML(hdrs=Theme.blue.headers())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "app, rt = fast_app(hdrs=Theme.blue.headers())\n", + "Show = partial(HTMX, app=app)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## export -" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "import nbdev; nbdev.nbdev_export()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "python", + "language": "python", + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/MonsterUI/nbs/02_franken.ipynb b/MonsterUI/nbs/02_franken.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..3b3959efd0f3d7f27e480a25b306af4259a4c29d --- /dev/null +++ b/MonsterUI/nbs/02_franken.ipynb @@ -0,0 +1,3680 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5bfbea37", + "metadata": {}, + "source": [ + "## Frankenui UI\n", + "\n", + "> Helpers and components for DaisyUI style stuff" + ] + }, + { + "cell_type": "markdown", + "id": "5fef8136", + "metadata": {}, + "source": [ + "Based on the minimal context shown, FrankenUI appears to be a collection of helper utilities and components designed to work with DaisyUI styling. DaisyUI is a popular plugin for Tailwind CSS that provides pre-built components and utility classes.\n", + "\n", + "However, I don't see enough context to provide specific details about what FrankenUI actually includes or implements. Would you like me to help explore its specific features or implementation?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e3b2231", + "metadata": {}, + "outputs": [], + "source": [ + "#| default_exp franken" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a9b7e605", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "import fasthtml.common as fh\n", + "from monsterui.foundations import *\n", + "from fasthtml.common import Div, P, Span, FT\n", + "from enum import Enum, auto\n", + "from fasthtml.components import Uk_select,Uk_input_tag,Uk_icon,Uk_input_range, Uk_chart\n", + "from functools import partial\n", + "from itertools import zip_longest\n", + "from typing import Union, Tuple, Optional, Sequence\n", + "from fastcore.all import *\n", + "import copy, re, httpx, os\n", + "import pathlib\n", + "from mistletoe.html_renderer import HTMLRenderer\n", + "from mistletoe.span_token import Image\n", + "import mistletoe\n", + "from lxml import html, etree\n", + "import fasthtml.components as fh_comp\n", + "import json" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e5ef9de1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#| hide\n", + "from fasthtml.jupyter import *\n", + "from IPython.display import HTML, Markdown, Image\n", + "from monsterui.core import Theme\n", + "\n", + "if 'server' in globals(): server.stop()\n", + "#| export\n", + "app,rt = fh.fast_app(pico=False, hdrs=(Theme.violet.headers()),\n", + " static_path=os.path.abspath('.'), nb_hdrs=False,\n", + " bodykw={\"class\":\"uk-overflow-auto min-h-screen\"})\n", + "server = JupyUvi(app)\n", + "Show = partial(HTMX, app=app)" + ] + }, + { + "cell_type": "markdown", + "id": "4d6b7aca", + "metadata": {}, + "source": [ + "## Text Style" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "777a9672", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class TextT(VEnum):\n", + " 'Text Styles from https://franken-ui.dev/docs/text'\n", + " def _generate_next_value_(name, start, count, last_values):\n", + " return str2ukcls('text', name)\n", + " \n", + " paragraph = \"uk-paragraph\"\n", + " # Text Style\n", + " lead,meta, gray, italic= auto(), auto(), 'text-gray-500 dark:text-gray-200', 'italic'\n", + " # Text Size\n", + " xs, sm, lg, xl = 'text-xs', 'text-sm', 'text-lg', 'text-xl'\n", + " # Text Weight\n", + " light, normal, medium, bold, extrabold = 'font-light','font-normal','font-medium','font-bold','font-extrabold'\n", + " # Text Color\n", + " muted,primary,secondary = 'text-gray-500 dark:text-gray-200', 'text-primary', 'text-secondary'\n", + " success,warning, error, info = 'text-success', 'text-warning', 'text-error', 'text-info'\n", + " # Text Alignment\n", + " left, right,center = \"text-left\",\"text-right\",\"text-center\"\n", + " justify, start, end = \"text-justify\",\"text-start\",\"text-end\"\n", + " # Vertical Alignment\n", + " top,middle,bottom = 'align-top','align-middle','align-bottom'\n", + " # Text Wrapping\n", + " truncate,break_,nowrap = 'uk-text-truncate','uk-text-break', 'uk-text-nowrap' \n", + " # other\n", + " underline = 'underline'\n", + " highlight = 'bg-yellow-200 dark:bg-yellow-800 text-black'\n", + "class TextPresets(VEnum):\n", + " 'Common Typography Presets'\n", + " muted_sm = TextT.muted+TextT.sm\n", + " muted_lg = TextT.muted+TextT.lg\n", + " \n", + " bold_sm = TextT.bold+TextT.sm\n", + " bold_lg = TextT.bold+TextT.lg\n", + " \n", + " md_weight_sm = stringify((TextT.sm, TextT.medium))\n", + " md_weight_muted = stringify((TextT.medium, TextT.muted))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67c88a05", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def CodeSpan(*c, # Contents of CodeSpan tag (inline text code snippets)\n", + " cls=(), # Classes in addition to CodeSpan styling\n", + " **kwargs # Additional args for CodeSpan tag\n", + " )->FT: # Code(..., cls='uk-codespan')\n", + " \"A CodeSpan with Styling\"\n", + " return fh.Code(*c, cls=('uk-codespan', stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ecdd881a", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def CodeBlock(*c: str, # Contents of Code tag (often text)\n", + " cls: Enum | str | tuple = (), # Classes for the outer container\n", + " code_cls: Enum | str | tuple = (), # Classes for the code tag\n", + " **kwargs # Additional args for Code tag\n", + " ) -> FT: # Div(Pre(Code(..., cls='uk-codeblock), cls='multiple tailwind styles'), cls='uk-block')\n", + " \"CodeBlock with Styling\"\n", + " return Div(\n", + " Pre(Code(*c, cls=('uk-codeblock', stringify(code_cls)), **kwargs),\n", + " cls=(f'bg-gray-100 dark:bg-gray-800 {TextT.gray} p-0.4 rounded text-sm font-mono')),\n", + "# cls=('bg-gray-100 dark:bg-gray-800 dark:text-gray-200 p-0.4 rounded text-sm font-mono')),\n", + " cls=('uk-block', stringify(cls)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e0c2ec91", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def H1(*c:FT|str, # Contents of H1 tag (often text)\n", + " cls:Enum|str|tuple=(), # Classes in addition to H1 styling\n", + " **kwargs # Additional args for H1 tag\n", + " )->FT: # H1(..., cls='uk-h1')\n", + " \"H1 with styling and appropriate size\"\n", + " return fh.H1(*c, cls=('uk-h1',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4c29aff7", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def H2(*c:FT|str, # Contents of H2 tag (often text)\n", + " cls:Enum|str|tuple=(), # Classes in addition to H2 styling\n", + " **kwargs # Additional args for H2 tag\n", + " )->FT: # H2(..., cls='uk-h2')\n", + " \"H2 with styling and appropriate size\"\n", + " return fh.H2(*c, cls=('uk-h2',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da456b99", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def H3(*c:FT|str, # Contents of H3 tag (often text)\n", + " cls:Enum|str|tuple=(), # Classes in addition to H3 styling\n", + " **kwargs # Additional args for H3 tag\n", + " )->FT: # H3(..., cls='uk-h3')\n", + " \"H3 with styling and appropriate size\"\n", + " return fh.H3(*c, cls=('uk-h3',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5bd78f89", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def H4(*c:FT|str, # Contents of H4 tag (often text)\n", + " cls:Enum|str|tuple=(), # Classes in addition to H4 styling\n", + " **kwargs # Additional args for H4 tag\n", + " )->FT: # H4(..., cls='uk-h4')\n", + " \"H4 with styling and appropriate size\"\n", + " return fh.H4(*c, cls=('uk-h4',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d1fd94dd", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def H5(*c:FT|str, # Contents of H5 tag (often text)\n", + " cls:Enum|str|tuple=(), # Classes in addition to H5 styling\n", + " **kwargs # Additional args for H5 tag\n", + " )->FT: # H5(..., cls='text-lg font-semibold')\n", + " \"H5 with styling and appropriate size\"\n", + " return fh.H5(*c, cls=('text-lg font-semibold',stringify(cls)), **kwargs)\n", + "\n", + "def H6(*c:FT|str, # Contents of H6 tag (often text)\n", + " cls:Enum|str|tuple=(), # Classes in addition to H6 styling\n", + " **kwargs # Additional args for H6 tag\n", + " )->FT: # H6(..., cls='text-base font-semibold')\n", + " \"H6 with styling and appropriate size\"\n", + " return fh.H6(*c, cls=('text-base font-semibold',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2724ebf9", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Subtitle(*c:FT|str, # Contents of P tag (often text)\n", + " cls:Enum|str|tuple='mt-1.5', # Additional classes\n", + " **kwargs # Additional args for P tag\n", + " )->FT:\n", + " \"Styled muted_sm text designed to go under Headings and Titles\"\n", + " return fh.P(*c, cls=(TextPresets.muted_sm, stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "af39f723", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Q(*c:FT|str, # Contents of Q tag (quote)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Q tag\n", + " )->FT:\n", + " \"Styled quotation mark\"\n", + " return fh.Q(*c, cls=(TextT.italic,TextT.lg, stringify(cls)), **kwargs)\n", + "\n", + "def Em(*c:FT|str, # Contents of Em tag (emphasis)\n", + " cls:Enum|str|tuple=(), # Additional classes \n", + " **kwargs # Additional args for Em tag\n", + " )->FT:\n", + " \"Styled emphasis text\"\n", + " return fh.Em(*c, cls=(TextT.medium, stringify(cls)), **kwargs)\n", + "\n", + "def Strong(*c:FT|str, # Contents of Strong tag\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Strong tag\n", + " )->FT:\n", + " \"Styled strong text\" \n", + " return fh.Strong(*c, cls=(TextT.bold, stringify(cls)), **kwargs)\n", + "\n", + "def I(*c:FT|str, # Contents of I tag (italics)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for I tag\n", + " )->FT:\n", + " \"Styled italic text\"\n", + " return fh.I(*c, cls=(TextT.italic, stringify(cls)), **kwargs)\n", + "\n", + "def Small(*c:FT|str, # Contents of Small tag\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Small tag\n", + " )->FT:\n", + " \"Styled small text\"\n", + " return fh.Small(*c, cls=(TextT.sm, stringify(cls)), **kwargs)\n", + "\n", + "def Mark(*c:FT|str, # Contents of Mark tag (highlighted text)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Mark tag\n", + " )->FT:\n", + " \"Styled highlighted text\"\n", + " return fh.Mark(*c, cls=(TextT.highlight, stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c07710b0", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Del(*c:FT|str, # Contents of Del tag (deleted text)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Del tag\n", + " )->FT:\n", + " \"Styled deleted text\"\n", + " return fh.Del(*c, cls=('line-through', TextT.gray, stringify(cls)), **kwargs)\n", + "\n", + "def Ins(*c:FT|str, # Contents of Ins tag (inserted text)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Ins tag\n", + " )->FT:\n", + " \"Styled inserted text\"\n", + " return fh.Ins(*c, cls=(TextT.underline+' text-green-600', stringify(cls)), **kwargs)\n", + "\n", + "def Sub(*c:FT|str, # Contents of Sub tag (subscript)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Sub tag\n", + " )->FT:\n", + " \"Styled subscript text\"\n", + " return fh.Sub(*c, cls=(TextT.sm+' -bottom-1 relative', stringify(cls)), **kwargs)\n", + "\n", + "def Sup(*c:FT|str, # Contents of Sup tag (superscript) \n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Sup tag\n", + " )->FT:\n", + " \"Styled superscript text\"\n", + " return fh.Sup(*c, cls=(TextT.sm+' -top-1 relative', stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b99103f", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Blockquote(*c:FT|str, # Contents of Blockquote tag (often text)\n", + " cls:Enum|str|tuple=(), # Classes in addition to Blockquote styling\n", + " **kwargs # Additional args for Blockquote tag\n", + " )->FT: # Blockquote(..., cls='uk-blockquote')\n", + " \"Blockquote with Styling\"\n", + " return fh.Blockquote(*c, cls=('uk-blockquote',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df406d73", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Caption(*c:FT|str, cls:Enum|str|tuple=(), **kwargs)->FT:\n", + " \"Styled caption text\"\n", + " return fh.Caption(\n", + " Span(*c, cls=(TextT.gray, TextT.sm, stringify(cls))),\n", + " **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d12d83f5", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Cite(*c:FT|str, # Contents of Cite tag\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Cite tag\n", + " )->FT:\n", + " \"Styled citation text\"\n", + " return fh.Cite(*c, cls=(TextT.italic, TextT.gray, stringify(cls)), **kwargs)\n", + "\n", + "def Time(*c:FT|str, # Contents of Time tag\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " datetime:str=None, # datetime attribute\n", + " **kwargs # Additional args for Time tag\n", + " )->FT:\n", + " \"Styled time element\"\n", + " if datetime: kwargs['datetime'] = datetime\n", + " return fh.Time(*c, cls=(TextT.gray, stringify(cls)), **kwargs)\n", + "\n", + "def Address(*c:FT|str, # Contents of Address tag\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Address tag\n", + " )->FT:\n", + " \"Styled address element\"\n", + " return fh.Address(*c, cls=(TextT.italic, stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c7fee69", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "demo = Div(\n", + " H1(\"MonsterUI's Semantic Text\"),\n", + " P(\n", + " Strong(\"MonsterUI\"), \" brings the power of semantic HTML to life with \",\n", + " Em(\"beautiful styling\"), \" and \", Mark(\"zero configuration\"), \".\"\n", + " ),\n", + " Blockquote(\n", + " P(\"Write semantic HTML in pure Python, get modern styling for free.\"),\n", + " Cite(\"MonsterUI Team\")\n", + " ),\n", + " footer=Meta(\"Released February 2025\"),\n", + " )\n", + "\n", + "Show(demo)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "baeb05f4", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Abbr(*c:FT|str, # Contents of Abbr tag\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " title:str=None, # Title attribute for abbreviation\n", + " **kwargs # Additional args for Abbr tag\n", + " )->FT:\n", + " \"Styled abbreviation with dotted underline\"\n", + " if title: kwargs['title'] = title\n", + " return fh.Abbr(*c, cls=('border-b border-dotted border-secondary hover:cursor-help', stringify(cls)), **kwargs)\n", + "\n", + "def Dfn(*c:FT|str, # Contents of Dfn tag (definition)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Dfn tag\n", + " )->FT:\n", + " \"Styled definition term with italic and medium weight\"\n", + " return fh.Dfn(*c, cls=(TextT.medium + TextT.italic + TextT.gray, stringify(cls)), **kwargs)\n", + "\n", + "def Kbd(*c:FT|str, # Contents of Kbd tag (keyboard input)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Kbd tag\n", + " )->FT:\n", + " \"Styled keyboard input with subtle background\"\n", + " return fh.Kbd(*c, cls=('font-mono px-1.5 py-0.5 text-sm bg-secondary border border-gray-300 dark:border-gray-600 rounded shadow-sm', stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "64be65c1", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Samp(*c:FT|str, # Contents of Samp tag (sample output)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Samp tag\n", + " )->FT:\n", + " \"Styled sample output with subtle background\"\n", + " return fh.Samp(*c, cls=('font-mono bg-secondary px-1 rounded', TextT.gray, stringify(cls)), **kwargs)\n", + "\n", + "def Var(*c:FT|str, # Contents of Var tag (variable)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Var tag\n", + " )->FT:\n", + " \"Styled variable with italic monospace\"\n", + " return fh.Var(*c, cls=('font-mono',TextT.italic + TextT.gray, stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dba6517b", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Figure(*c:FT|str, # Contents of Figure tag\n", + " cls:Enum|str|tuple=(), # Additional classes \n", + " **kwargs # Additional args for Figure tag\n", + " )->FT:\n", + " \"Styled figure container with card-like appearance\"\n", + " return fh.Figure(*c, cls=('p-4 my-4 border border-gray-200 dark:border-gray-800 rounded-lg shadow-sm bg-card', stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2faaf0d4", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Details(*c:FT|str, # Contents of Details tag\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Details tag\n", + " )->FT:\n", + " \"Styled details element\"\n", + " return fh.Details(*c, cls=('border border-secondary rounded-lg', stringify(cls)), **kwargs)\n", + "\n", + "def Summary(*c:FT|str, # Contents of Summary tag\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Summary tag\n", + " )->FT:\n", + " \"Styled summary element\"\n", + " return fh.Summary(*c, cls=(TextT.medium + ' p-3 hover:bg-secondary cursor-pointer', stringify(cls)), **kwargs)\n", + "\n", + "def Data(*c:FT|str, # Contents of Data tag\n", + " value:str=None, # Value attribute\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Data tag\n", + " )->FT:\n", + " \"Styled data element\"\n", + " if value: kwargs['value'] = value\n", + " return fh.Data(*c, cls=('font-mono text-sm bg-secondary px-1 rounded', stringify(cls)), **kwargs)\n", + "\n", + "def Meter(*c:FT|str, # Contents of Meter tag\n", + " value:float=None, # Current value\n", + " min:float=None, # Minimum value\n", + " max:float=None, # Maximum value\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Meter tag\n", + " )->FT:\n", + " \"Styled meter element\"\n", + " if value is not None: kwargs['value'] = value\n", + " if min is not None: kwargs['min'] = min\n", + " if max is not None: kwargs['max'] = max\n", + " return fh.Meter(*c, cls=('w-full h-2 bg-secondary rounded', stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "000abe38", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def S(*c:FT|str, # Contents of S tag (strikethrough)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for S tag\n", + " )->FT:\n", + " \"Styled strikethrough text (different semantic meaning from Del)\"\n", + " return fh.S(*c, cls=('line-through', TextT.gray, stringify(cls)), **kwargs)\n", + "\n", + "def U(*c:FT|str, # Contents of U tag (unarticulated annotation)\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for U tag\n", + " )->FT:\n", + " \"Styled underline (for proper names in Chinese, proper spelling etc)\"\n", + " return fh.U(*c, cls=(TextT.underline, stringify(cls)), **kwargs)\n", + "\n", + "def Output(*c:FT|str, # Contents of Output tag\n", + " form:str=None, # ID of form this output belongs to\n", + " for_:str=None, # IDs of elements this output is for\n", + " cls:Enum|str|tuple=(), # Additional classes\n", + " **kwargs # Additional args for Output tag\n", + " )->FT:\n", + " \"Styled output element for form results\"\n", + " if form: kwargs['form'] = form\n", + " if for_: kwargs['for'] = for_ # Note: 'for' is reserved in Python\n", + " return fh.Output(*c, cls=('font-mono bg-secondary px-2 py-1 rounded', \n", + " stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a161f997", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def PicSumImg(h:int=200, # Height in pixels\n", + " w:int=200, # Width in pixels\n", + " id:int=None, # Optional specific image ID to use\n", + " grayscale:bool=False, # Whether to return grayscale version\n", + " blur:int=None, # Optional blur amount (1-10)\n", + " **kwargs # Additional args for Img tag\n", + " )->FT: # Img tag with picsum image\n", + " \"Creates a placeholder image using https://picsum.photos/\"\n", + " url = f\"https://picsum.photos\"\n", + " if id is not None: url = f\"{url}/id/{id}\"\n", + " url = f\"{url}/{w}/{h}\"\n", + " if grayscale: url = f\"{url}?grayscale\"\n", + " if blur is not None: \n", + " url = f\"{url}{'?' if not grayscale else '&'}blur={max(1,min(10,blur))}\"\n", + " return fh.Img(src=url, loading=\"lazy\", **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "caf685b3", + "metadata": {}, + "source": [ + "## Accordion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d672f295", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def AccordionItem(title: Union[str, FT], # Content for the accordion item title\n", + " *c: FT, # Content to display when the item is open\n", + " cls: Union[str, Enum, tuple] = (), # Additional classes for the outer `Li` container\n", + " title_cls: Union[str, Enum, tuple] = ('flex justify-between items-center w-full',), # Additional classes for the title `A` tag\n", + " content_cls: Union[str, Enum, tuple] = (), # Additional classes for the content `Div`\n", + " open: bool = False, # Whether this item should be open by default\n", + " li_kwargs: Optional[Dict] = None, # Additional attributes for the outer `Li` tag\n", + " a_kwargs: Optional[Dict] = None, # Additional attributes for the title `A` tag\n", + " div_kwargs: Optional[Dict] = None # Additional attributes for the content `Div` tag\n", + " ) -> FT: # Li(A(title, Span(Icon, Icon)), Div(content))\n", + " \"Creates a single item for use within an Accordion component, handling title, content, and open state.\"\n", + " li_attrs, a_attrs, div_attrs = li_kwargs or {}, a_kwargs or {}, div_kwargs or {}\n", + " li_classes = ['group', stringify(cls)]\n", + " if open: li_classes.append('uk-open')\n", + " final_li_cls = stringify(li_classes)\n", + " combined_title_cls = stringify(('uk-accordion-title', stringify(title_cls)))\n", + " content_classes = stringify(('uk-accordion-content', stringify(content_cls)))\n", + " if 'href' not in a_attrs: a_attrs['href'] = '#'\n", + " icon_container = Span(\n", + " UkIcon(\"chevron-down\", cls=\"block group-[.uk-open]:hidden h-5 w-5\"),\n", + " UkIcon(\"chevron-up\", cls=\"hidden group-[.uk-open]:block h-5 w-5\")\n", + " )\n", + " return fh.Li(\n", + " fh.A(title, icon_container, cls=combined_title_cls, **a_attrs),\n", + " fh.Div(*c, cls=content_classes, **div_attrs),\n", + " cls=final_li_cls,\n", + " **li_attrs\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a19bf8be", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Accordion(*c: 'AccordionItem', # One or more `AccordionItem` components\n", + " cls: Union[str, Enum, tuple] = (), # Additional classes for the container (`Ul` or `Div`)\n", + " multiple: Optional[bool] = None, # Allow multiple items to be open simultaneously (UIkit option)\n", + " collapsible: Optional[bool] = None, # Allow all items to be closed (UIkit option, default True)\n", + " animation: Optional[bool] = None, # Enable/disable animation (UIkit option, default True)\n", + " duration: Optional[int] = None, # Animation duration in ms (UIkit option, default 200)\n", + " active: Optional[int] = None, # Index (0-based) of the item to be open by default (UIkit option)\n", + " transition: Optional[str] = None, # Animation transition timing function (UIkit option, e.g., 'ease-out')\n", + " tag: str = 'ul', # HTML tag for the container ('ul' or 'div')\n", + " **kwargs # Additional attributes for the container tag (e.g., id)\n", + " ) -> FT: # Ul(*items...) or Div(*items...)\n", + " \"\"\"\n", + " Creates a styled Accordion container using accordion component.\n", + " \"\"\"\n", + " opts = []\n", + " if multiple is not None: opts.append(f\"multiple: {str(multiple).lower()}\")\n", + " if collapsible is not None: opts.append(f\"collapsible: {str(collapsible).lower()}\")\n", + " if animation is not None: opts.append(f\"animation: {str(animation).lower()}\")\n", + " if duration is not None: opts.append(f\"duration: {duration}\")\n", + " if active is not None: opts.append(f\"active: {active}\")\n", + " if transition is not None: opts.append(f\"transition: {transition}\")\n", + " uk_attr_val = \"; \".join(opts) if opts else \"\"\n", + " kwargs['uk-accordion'] = uk_attr_val\n", + " container_tag = fh.Ul if tag.lower() == 'ul' else fh.Div\n", + " final_cls = stringify(cls)\n", + " return container_tag(*c, cls=final_cls, **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "d818104f", + "metadata": {}, + "source": [ + "## Button" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f914a2c", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class ButtonT(VEnum):\n", + " \"Options for styling Buttons\"\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('btn', name)\n", + " default, ghost, primary = auto(),auto(),auto()\n", + " secondary, destructive = auto(), auto()\n", + " text, link = auto(), auto()\n", + " xs, sm, lg, xl = auto(), auto(), auto(), auto()\n", + " icon = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "680b16c1", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Button(*c: Union[str, FT], # Contents of `Button` tag (often text)\n", + " cls: Union[str, Enum]=ButtonT.default, # Classes in addition to `Button` styling (use `ButtonT` for built in styles)\n", + " submit=True, # Whether the button should submit a form\n", + " **kwargs # Additional args for `Button` tag\n", + " ) -> FT: # Button(..., cls='uk-btn')\n", + " \"Button with Styling (defaults to `submit` for form submission)\"\n", + " if 'type' not in kwargs: kwargs['type'] = 'submit' if submit else 'button'\n", + " return fh.Button(*c, cls=('uk-btn', stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "021bab4c", + "metadata": {}, + "source": [ + "## Headings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b28c2acd", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class ContainerT(VEnum):\n", + " 'Max width container sizes from https://franken-ui.dev/docs/container'\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('container', name)\n", + " xs = auto()\n", + " sm = auto()\n", + " lg = auto()\n", + " xl = auto()\n", + " expand = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f665556f", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class BackgroundT(VEnum):\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('background', name)\n", + " muted = auto()\n", + " primary = auto()\n", + " secondary = auto()\n", + " default = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4356199a", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Container(*c, # Contents of Container tag (often other FT Components)\n", + " cls=('mt-5', ContainerT.xl), # Classes in addition to Container styling\n", + " **kwargs # Additional args for Container (`Div` tag)\n", + " )->FT: # Container(..., cls='uk-container')\n", + " \"Div to be used as a container that often wraps large sections or a page of content\"\n", + " return Div(*c, cls=('uk-container',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cf4d85dc", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Titled(title:str=\"FastHTML app\", # Title of the page\n", + " *c, # Contents of the page (often other tags)\n", + " cls=ContainerT.xl, # Classes in addition to Container styling\n", + " **kwargs # Additional args for Container (`Div` tag)\n", + " )->FT: # Title, Main(Container(H1(title), content))\n", + " \"Creates a standard page structure for titled page. Main(Container(title, content))\"\n", + " return fh.Title(title), fh.Main(Container(H1(title), *c, cls=cls, **kwargs))" + ] + }, + { + "cell_type": "markdown", + "id": "be7cf579", + "metadata": {}, + "source": [ + "## Dividers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a2e515f", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class DividerT(VEnum):\n", + " \"Divider Styles from https://franken-ui.dev/docs/divider\"\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('divider', name)\n", + " icon=auto()\n", + " sm=auto()\n", + " vertical=auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa142350", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Divider(*c, # contents of Divider tag (often nothing)\n", + " cls=('my-4', DividerT.icon), # Classes in addition to Divider styling\n", + " **kwargs # Additional args for Divider tag\n", + " )->FT: # Hr(..., cls='uk-divider-icon') or Div(..., cls='uk-divider-vertical')\n", + " \"Divider with default styling and margin\"\n", + " cls = stringify(cls)\n", + " container = Div if 'uk-divider-vertical' in cls else Hr\n", + " return container(*c, cls=cls, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1549197f", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DividerSplit(*c, cls=(), line_cls=(), text_cls=()):\n", + " \"Creates a simple horizontal line divider with configurable thickness and vertical spacing\"\n", + " cls, line_cls, text_cls = map(stringify,(cls, line_cls, text_cls))\n", + " return Div(cls='relative ' + cls)(\n", + " Div(cls=\"absolute inset-0 flex items-center \" + line_cls)(Span(cls=\"w-full border-t border-border\")),\n", + " Div(cls=\"relative flex justify-center \" + text_cls)(Span(cls=\"bg-background px-2 \")(*c)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "753a1497", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DividerLine(lwidth=2, y_space=4): return Hr(cls=f\"my-{y_space} h-[{lwidth}px] w-full bg-secondary\")" + ] + }, + { + "cell_type": "markdown", + "id": "ca9d872c", + "metadata": {}, + "source": [ + "## Articles & Containers & Sections" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c9a2956", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Article(*c, # contents of Article tag (often other tags)\n", + " cls=(), # Classes in addition to Article styling\n", + " **kwargs # Additional args for Article tag\n", + " )->FT: # Article(..., cls='uk-article')\n", + " \"A styled article container for blog posts or similar content\"\n", + " return fh.Article(*c, cls=('uk-article',stringify(cls)), **kwargs)\n", + "\n", + "def ArticleTitle(*c, # contents of ArticleTitle tag (often other tags)\n", + " cls=(), # Classes in addition to ArticleTitle styling\n", + " **kwargs # Additional args for ArticleTitle tag\n", + " )->FT: # H1(..., cls='uk-article-title')\n", + " \"A title component for use within an Article\"\n", + " return H1(*c, cls=('uk-article-title',stringify(cls)), **kwargs)\n", + "\n", + "def ArticleMeta(*c, # contents of ArticleMeta tag (often other tags)\n", + " cls=(), # Classes in addition to ArticleMeta styling\n", + " **kwargs # Additional args for ArticleMeta tag\n", + " )->FT: # P(..., cls='uk-article-meta')\n", + " \"A metadata component for use within an Article showing things like date, author etc\"\n", + " return P(*c, cls=('uk-article-meta',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2b0abaa", + "metadata": {}, + "outputs": [], + "source": [ + "# Article(ArticleTitle(\"Article Title\"), ArticleMeta(\"By: John Doe\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "22609bb2", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class SectionT(VEnum):\n", + " 'Section styles from https://franken-ui.dev/docs/section'\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('section', name)\n", + " default = auto()\n", + " muted = auto()\n", + " primary = auto()\n", + " secondary = auto()\n", + " xs = 'uk-section-xsmall'\n", + " sm = 'uk-section-small'\n", + " lg = 'uk-section-large'\n", + " xl = 'uk-section-xlarge'\n", + " remove_vertical = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb0244e9", + "metadata": {}, + "outputs": [], + "source": [ + "# Markdown(enum_to_markdown_table(SectionT))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "18bb39ed", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Section(*c, # contents of Section tag (often other tags)\n", + " cls=(), # Classes in addition to Section styling\n", + " **kwargs # Additional args for Section tag\n", + " )->FT: # Div(..., cls='uk-section')\n", + " \"Section with styling and margins\"\n", + " return fh.Div(*c, cls=('uk-section',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "c70c8aab", + "metadata": {}, + "source": [ + "## Forms & Inputs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd2fd2ad", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Form(*c, # contents of Form tag (often Buttons, FormLabels, and LabelInputs)\n", + " cls='space-y-3', # Classes in addition to Form styling (default is 'space-y-3' to prevent scrunched up form elements)\n", + " **kwargs # Additional args for Form tag\n", + " )->FT: # Form(..., cls='space-y-3')\n", + " \"A Form with default spacing between form elements\"\n", + " return fh.Form(*c, cls=stringify(cls), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "23618919", + "metadata": {}, + "outputs": [], + "source": [ + "#|export\n", + "def Fieldset(*c, # contents of Fieldset tag (often other tags)\n", + " cls='flex', # Classes in addition to Fieldset styling\n", + " **kwargs # Additional args for Fieldset tag\n", + " )->FT: # Fieldset(..., cls='uk-fieldset')\n", + " \"A Fieldset with default styling\"\n", + " return fh.Fieldset(*c, cls=('uk-fieldset',stringify(cls)), **kwargs)\n", + "\n", + "def Legend(*c, # contents of Legend tag (often other tags)\n", + " cls=(), # Classes in addition to Legend styling\n", + " **kwargs # Additional args for Legend tag\n", + " )->FT: # Legend(..., cls='uk-legend')\n", + " \"A Legend with default styling\"\n", + " return fh.Legend(*c, cls=('uk-legend',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "866006f3", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Input(*c, # contents of Input tag (often nothing)\n", + " cls=(), # Classes in addition to Input styling\n", + " **kwargs # Additional args for Input tag\n", + " )->FT: # Input(..., cls='uk-input')\n", + " \"An Input with default styling\"\n", + " return fh.Input(*c, cls=('uk-input',stringify(cls)), **kwargs)\n", + "\n", + "def Radio(*c, # contents of Radio tag (often nothing)\n", + " cls=(), # Classes in addition to Radio styling\n", + " **kwargs # Additional args for Radio tag\n", + " )->FT: # Input(..., cls='uk-radio', type='radio')\n", + " \"A Radio with default styling\"\n", + " return fh.Input(*c, cls=('uk-radio',stringify(cls)), type='radio', **kwargs)\n", + "def CheckboxX(*c, # contents of CheckboxX tag (often nothing)\n", + " cls=(), # Classes in addition to CheckboxX styling\n", + " **kwargs # Additional args for CheckboxX tag\n", + " )->FT: # Input(..., cls='uk-checkbox', type='checkbox')\n", + " \"A Checkbox with default styling\"\n", + " return fh.Input(*c, cls=('uk-checkbox',stringify(cls)), type='checkbox', **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "210222f5", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aee199c9", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Range(*c, # contents of Range tag (often nothing)\n", + " value='',\n", + " label=True,\n", + " min=None,\n", + " max=None,\n", + " step=None,\n", + " cls=(), # Classes in addition to Range styling\n", + " **kwargs # Additional args for Range tag\n", + " )->FT: # Input(..., cls='uk-range', type='range')\n", + " \"A Range with default styling\"\n", + " return Uk_input_range(*c, min=min, label=label, max=max, value=value, step=step, multiple=len(value.split(','))>1, cls=('uk-range',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1999cbd1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "\n", + "```" + ], + "text/plain": [ + "uk-input-range((),{'label': 'kg', 'value': '25,75', 'multiple': True, 'class': 'uk-range '})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Range(label='kg', value=\"25,75\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7a1efbc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "Open in new tab" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "Show(Range(label='kg', value=\"25,75\"), link=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ad1ad1ba", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def TextArea(*c, # contents of TextArea tag (often text)\n", + " cls=(), # Classes in addition to TextArea styling\n", + " **kwargs # Additional args for TextArea tag\n", + " )->FT: # TextArea(..., cls='uk-textarea')\n", + " \"A Textarea with default styling\"\n", + " return fh.Textarea(*c, cls=('uk-textarea',stringify(cls)), **kwargs)\n", + "def Switch(*c, # contents of Switch tag (often nothing)\n", + " cls=(), # Classes in addition to Switch styling\n", + " **kwargs # Additional args for Switch tag\n", + " )->FT: # Input(..., cls='uk-toggle-switch uk-toggle-switch-primary min-w-9', type='checkbox')\n", + " \"A Switch with default styling\"\n", + " return fh.Input(*c, cls=('uk-toggle-switch uk-toggle-switch-primary min-w-9',stringify(cls)), type='checkbox', **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6d644ea", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Upload(*c, # Contents of Upload tag button (often text)\n", + " cls=(), # Classes in addition to Upload styling\n", + " multiple=False, # Whether to allow multiple file selection\n", + " accept=None, # File types to accept (e.g. 'image/*')\n", + " button_cls=ButtonT.default, # Classes for the button\n", + " id=None, # ID for the file input\n", + " name=None, # Name for the file input\n", + " **kwargs # Additional args for the outer div\n", + " )->FT: # Div(Input(type='file'), Button(...))\n", + " \"A file upload component with default styling\"\n", + " input_kwargs = {'type': 'file', 'multiple': multiple}\n", + " if accept: input_kwargs['accept'] = accept\n", + " if id: input_kwargs['id'] = id\n", + " if name: input_kwargs['name'] = name\n", + " return Div(\n", + " fh.Input(**input_kwargs),\n", + " Button(*c, cls=button_cls, submit=False, tabindex=\"-1\"),\n", + " cls=('w-full js-upload', stringify(cls)),\n", + " uk_form_custom=True)\n", + "\n", + "def UploadZone(*c, # Contents of UploadZone tag (often text or other tags)\n", + " cls=(), # Classes in addition to UploadZone styling\n", + " multiple=False, # Whether to allow multiple file selection\n", + " accept=None, # File types to accept (e.g. 'image/*')\n", + " id=None, # ID for the file input\n", + " name=None, # Name for the file input\n", + " **kwargs # Additional args for the outer div\n", + " )->FT:\n", + " \"A file drop zone component with default styling\"\n", + " input_kwargs = {'type': 'file', 'multiple': multiple}\n", + " if accept: input_kwargs['accept'] = accept \n", + " if id: input_kwargs['id'] = id\n", + " if name: input_kwargs['name'] = name\n", + " return Div(\n", + " Div(fh.Input(**input_kwargs),\n", + " Span(*c),\n", + " uk_form_custom=True, \n", + " cls='w-full'),\n", + " cls=('js-upload uk-placeholder uk-text-center', stringify(cls)),\n", + " **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "25914646", + "metadata": {}, + "outputs": [], + "source": [ + "#|export\n", + "def FormLabel(*c, # contents of FormLabel tag (often text)\n", + " cls=(), # Classes in addition to FormLabel styling\n", + " **kwargs # Additional args for FormLabel tag\n", + " )->FT: # Label(..., cls='uk-form-label')\n", + " \"A Label with default styling\"\n", + " return fh.Label(*c, cls=('uk-form-label',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "698f63d6", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class LabelT(VEnum):\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('label', name)\n", + " primary = auto()\n", + " secondary = auto()\n", + " destructive = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eaa2043b", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Label(*c, # contents of Label tag (often text)\n", + " cls=(), # Classes in addition to Label styling\n", + " **kwargs # Additional args for Label tag\n", + " )->FT: # Label(..., cls='uk-label')\n", + " \"FrankenUI labels, which look like pills\"\n", + " return fh.Label(*c, cls=('uk-label',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "04248315", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def UkFormSection(title, description, *c, button_txt='Update', outer_margin=6, inner_margin=6):\n", + " \"A form section with a title, description and optional button\"\n", + " return Div(cls=f'space-y-{inner_margin} py-{outer_margin}')(\n", + " Div(H3(title), P(description, cls=TextPresets.muted_sm)),\n", + " DividerSplit(), *c,\n", + " Div(Button(button_txt, cls=ButtonT.primary)) if button_txt else None)" + ] + }, + { + "cell_type": "markdown", + "id": "0e1c120a", + "metadata": {}, + "source": [ + "## Labeled Inputs" + ] + }, + { + "cell_type": "markdown", + "id": "9a8f8c66", + "metadata": {}, + "source": [ + "Inputs of various types often go with a label. Because of this we created functions to do this for you along with properly linking the `for` attribute from the lable to the input. We also have some nice defaults, such as putting a little spacing between the label and the input" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56e7ca16", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def GenericLabelInput(\n", + " label:str|FT, # FormLabel content (often text)\n", + " lbl_cls='', # Additional classes for FormLabel\n", + " input_cls='', # Additional classes for user input (Input, Select, etc)\n", + " container=Div, # Container to wrap label and input in (default is Div)\n", + " cls='', # Classes on container (default is '')\n", + " id=None, # id for label and input (`id`, `name` and `for` attributes are set to this value). If `label` is str, this defaults to `label.lower()`\n", + " input_fn=noop, # User input FT component \n", + " **kwargs # Additional args for user input\n", + " ): \n", + " \"`Div(Label,Input)` component with Uk styling injected appropriately. Generally you should higher level API, such as `LabelInput` which is created for you in this library\"\n", + " if not id and isinstance(label, str): id = label.lower()\n", + " if isinstance(label, str) or label.tag != 'label': \n", + " label = FormLabel(cls=stringify(lbl_cls), fr=id)(label)\n", + " inp = input_fn(id=id, cls=stringify(input_cls), **kwargs) \n", + " if container: return container(label, inp, cls=stringify(cls))\n", + " return label, inp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b878694f", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def LabelInput(label:str|FT, # FormLabel content (often text)\n", + " lbl_cls='', # Additional classes for `FormLabel`\n", + " input_cls='', # Additional classes for `Input`\n", + " cls='space-y-2', # Classes on container (default is `'space-y-2'` to prevent scrunched up form elements)\n", + " id='', # id for `FormLabel` and `Input` (`id`, `name` and `for` attributes are set to this value)\n", + " **kwargs # Additional args for `Input`\n", + " )->FT: # Div(cls='space-y-2')(`FormLabel`, `Input`)\n", + " \"A `FormLabel` and `Input` pair that provides default spacing and links/names them based on id\"\n", + " return GenericLabelInput(label=label, lbl_cls=lbl_cls, input_cls=input_cls,\n", + " container=Div, cls=cls, id=id, input_fn=Input, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea4c8a92", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def LabelTextArea(label:str|FT, # FormLabel content (often text)\n", + " value='', # Value for the textarea\n", + " lbl_cls='', # Additional classes for `FormLabel`\n", + " input_cls='', # Additional classes for `TextArea`\n", + " cls='space-y-2', # Classes on container (default is `'space-y-2'` to prevent scrunched up form elements)\n", + " id='', # id for `FormLabel` and `TextArea` (`id`, `name` and `for` attributes are set to this value)\n", + " **kwargs # Additional args for `TextArea`\n", + " )->FT: # Div(cls='space-y-2')(`FormLabel`, `TextArea`)\n", + " def text_area_with_value(**kw): return TextArea(value, **kw)\n", + " return GenericLabelInput(label=label, lbl_cls=lbl_cls, input_cls=input_cls,\n", + " container=Div, cls=cls, id=id, input_fn=text_area_with_value, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c5809ab0", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "@delegates(GenericLabelInput, but=['input_fn','cls'])\n", + "def LabelSwitch(label:str|FT, # FormLabel content (often text)\n", + " lbl_cls='', # Additional classes for `FormLabel`\n", + " input_cls='', # Additional classes for `Switch`\n", + " cls='space-x-2', # Classes on container (default is `'space-x-2'` to prevent scrunched up form elements)\n", + " id='', # id for `FormLabel` and `Switch` (`id`, `name` and `for` attributes are set to this value)\n", + " **kwargs # Additional args for `Switch`\n", + " )->FT: # Div(cls='space-y-2')(`FormLabel`, `Switch`)\n", + " return GenericLabelInput(label=label, lbl_cls=lbl_cls, input_cls=input_cls,\n", + " container=Div, cls=cls, id=id, input_fn=Switch, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9fdc52d0", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def LabelRadio(label:str|FT, # FormLabel content (often text)\n", + " lbl_cls='', # Additional classes for `FormLabel`\n", + " input_cls='', # Additional classes for `Radio`\n", + " container=Div, # Container to wrap label and input in (default is Div)\n", + " cls='flex items-center space-x-2', # Classes on container (default is 'flex items-center space-x-2')\n", + " id='', # id for `FormLabel` and `Radio` (`id`, `name` and `for` attributes are set to this value)\n", + " **kwargs # Additional args for `Radio`\n", + " )->FT: # Div(cls='flex items-center space-x-2')(`FormLabel`, `Radio`)\n", + " \"A FormLabel and Radio pair that provides default spacing and links/names them based on id\"\n", + " if isinstance(label, str) or label.tag != 'label': \n", + " label = FormLabel(cls=stringify(lbl_cls), fr=id)(label)\n", + " inp = Radio(id=id, cls=stringify(input_cls), **kwargs) \n", + " if container: return container(inp, label, cls=stringify(cls))\n", + " return inp, label" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "914769f7", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def LabelCheckboxX(label:str|FT, # FormLabel content (often text)\n", + " lbl_cls='', # Additional classes for `FormLabel`\n", + " input_cls='', # Additional classes for `CheckboxX`\n", + " container=Div, # Container to wrap label and input in (default is Div)\n", + " cls='flex items-center space-x-2', # Classes on container (default is 'flex items-center space-x-2')\n", + " id='', # id for `FormLabel` and `CheckboxX` (`id`, `name` and `for` attributes are set to this value)\n", + " **kwargs # Additional args for `CheckboxX`\n", + " )->FT: # Div(cls='flex items-center space-x-2')(`FormLabel`, `CheckboxX`)\n", + " \"A FormLabel and CheckboxX pair that provides default spacing and links/names them based on id\"\n", + " if not id: id = fh.unqid()\n", + " if isinstance(label, str) or label.tag != 'label': \n", + " label = FormLabel(cls=stringify(lbl_cls), fr=id)(label)\n", + " inp = CheckboxX(id=id, cls=stringify(input_cls), **kwargs) \n", + " if container: return container(inp, label, cls=stringify(cls))\n", + " return inp, label" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "138d303a", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Options(*c, # Content for an `Option`\n", + " selected_idx:int=None, # Index location of selected `Option`\n", + " disabled_idxs:set=None # Idex locations of disabled `Options`\n", + " ):\n", + " \"Helper function to wrap things into `Option`s for use in `Select`\"\n", + " return [fh.Option(o,selected=i==selected_idx, disabled=disabled_idxs and i in disabled_idxs) for i,o in enumerate(c)]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "477a3c8e", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Select(*option, # Options for the select dropdown (can use `Options` helper function to create)\n", + " inp_cls=(), # Additional classes for the select input\n", + " cls=('h-10',), # Classes for the outer div (default h-10 for consistent height)\n", + " cls_custom='button: uk-input-fake; dropdown: w-full', # Classes for the Uk_Select web component\n", + " id=\"\", # ID for the select input\n", + " name=\"\", # Name attribute for the select input\n", + " placeholder=\"\", # Placeholder text for the select input\n", + " searchable=False, # Whether the select should be searchable\n", + " insertable=False, # Whether to allow user-defined options to be added\n", + " select_kwargs=None, # Additional Arguments passed to Select\n", + " \n", + " **kwargs # Additional arguments passed to Uk_select\n", + " ): \n", + " \"Creates a select dropdown with uk styling and option for adding a search box\"\n", + " inp_cls, cls, cls_custom= map(stringify, (inp_cls, cls, cls_custom))\n", + " select_kwargs = ifnone(select_kwargs, {})\n", + "\n", + " if 'hx_trigger' not in kwargs: kwargs['hx_trigger']=''\n", + " if 'change' in kwargs['hx_trigger']:\n", + " if not id: id = fh.unqid()\n", + " kwargs['hx_trigger'] = kwargs['hx_trigger'].replace('changed', f'uk-select:input from:#{id}')\n", + " kwargs['hx_trigger'] = kwargs['hx_trigger'].replace('change', f'uk-select:input from:#{id}')\n", + " \n", + " if 'delay' not in kwargs['hx_trigger']:\n", + " kwargs['hx_trigger'] += ' delay:100ms'\n", + " \n", + " if 'hx_include' not in kwargs: kwargs['hx_include']=''\n", + " kwargs['hx_include'] += ' this'\n", + " kwargs['hx_include'] = kwargs['hx_include'].strip()\n", + " \n", + " if id and not name: name = id\n", + "\n", + " uk_select = Uk_select(fh.Select(*option, hidden=True, \n", + " **select_kwargs, \n", + " \n", + " ),\n", + " cls_custom=cls_custom,\n", + " searchable=searchable,\n", + " placeholder=placeholder,\n", + " insertable=insertable,\n", + " cls=inp_cls,\n", + " id=id,\n", + " name=name,\n", + " **kwargs\n", + " )\n", + " \n", + " return Div(cls=cls)(uk_select)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b50363e", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def LabelSelect(*option, # Options for the select dropdown (can use `Options` helper function to create) \n", + " label=(), # String or FT component for the label\n", + " lbl_cls=(), # Additional classes for the label\n", + " inp_cls=(), # Additional classes for the select input\n", + " cls=('space-y-2',), # Classes for the outer div\n", + " id=\"\", # ID for the select input\n", + " name=\"\", # Name attribute for the select input\n", + " placeholder=\"\", # Placeholder text for the select input\n", + " searchable=False, # Whether the select should be searchable\n", + " select_kwargs=None, # Additional Arguments passed to Select\n", + " **kwargs): # Additional arguments passed to Select\n", + " \"A FormLabel and Select pair that provides default spacing and links/names them based on id\"\n", + " lbl_cls, inp_cls, cls = map(stringify, (lbl_cls, inp_cls, cls))\n", + " select_kwargs = ifnone(select_kwargs, {})\n", + " if label:\n", + " lbl = FormLabel(cls=f'{lbl_cls}', fr=id)(label)\n", + " select = Select(*option, inp_cls=inp_cls, id=id, name=name if name else id, \n", + " placeholder=placeholder, searchable=searchable, select_kwargs=select_kwargs, **kwargs)\n", + " return Div(cls=cls)(lbl, select) if label else Div(cls=cls)(select)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79c17d86", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Show(\n", + " Div(cls='h-48')(LabelSelect(\n", + " Option(\"Select a verified email to display\", value=\"\", selected=True, disabled=True),\n", + " *[Option(o, value=o) for o in ('m@example.com', 'm@yahoo.com', 'm@cloud.com')], \n", + " label=\"Email\", id=\"email\",\n", + " searchable=True)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "443e2641", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "@delegates(GenericLabelInput, but=['input_fn','cls'])\n", + "def LabelRange(label:str|FT, # FormLabel content (often text)\n", + " lbl_cls='', # Additional classes for `FormLabel`\n", + " input_cls='', # Additional classes for `Range`\n", + " cls='space-y-6', # Classes on container (default is `'space-y-2'` to prevent scrunched up form elements)\n", + " id='', # id for `FormLabel` and `Range` (`id`, `name` and `for` attributes are set to this value)\n", + " value='', # Value for the range input\n", + " min=None, # Minimum value\n", + " max=None, # Maximum value\n", + " step=None, # Step size\n", + " label_range=True, # Whether to show the range value label (label for the `Range` component)\n", + " **kwargs # Additional args for `Range`\n", + " )->FT: # Div(cls='space-y-2')(`FormLabel`, `Range`)\n", + " \"A FormLabel and Range pair that provides default spacing and links/names them based on id\"\n", + " def range_with_value(**kw): \n", + " return Div(Range(value=value, min=min, max=max, step=step, label=label_range, **kw))\n", + " return GenericLabelInput(label=label, lbl_cls=lbl_cls, input_cls=input_cls,\n", + " container=Div, cls=cls, id=id, input_fn=range_with_value, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cdaf2fdd", + "metadata": {}, + "outputs": [], + "source": [ + "# Show(Div(cls='space-y-6')(\n", + "# LabelRange('Basic Range', value='50', min=0, max=100, step=1),\n", + "# LabelRange('Range with Label', value='75', min=0, max=100, step=5, label_range=True),\n", + "# LabelRange('Multiple Values', value='25,75', min=0, max=100, step=5, label_range=True),\n", + "# LabelRange('Custom Range', value='500', min=0, max=1000, step=100, label_range=True)\n", + "# ))" + ] + }, + { + "cell_type": "markdown", + "id": "a51be92e", + "metadata": {}, + "source": [ + "## Links" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2301e943", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class AT(VEnum):\n", + " 'Link styles from https://franken-ui.dev/docs/link'\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('link', name)\n", + " muted = auto()\n", + " text = auto()\n", + " reset = auto()\n", + " primary = 'uk-link text-primary hover:text-primary-focus underline'\n", + " classic = 'text-blue-600 hover:text-blue-800 underline'" + ] + }, + { + "cell_type": "markdown", + "id": "214f2635", + "metadata": {}, + "source": [ + "## Lists" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6faf97f9", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class ListT(VEnum):\n", + " 'List styles using Tailwind CSS'\n", + " disc = 'list-disc list-inside'\n", + " circle = 'list-[circle] list-inside' \n", + " square = 'list-[square] list-inside'\n", + " decimal = 'uk-list uk-list-decimal'\n", + " hyphen = 'uk-list uk-list-hyphen'\n", + " bullet = 'uk-list uk-list-bullet'\n", + " divider = 'uk-list uk-list-divider'\n", + " striped = 'uk-list uk-list-striped'" + ] + }, + { + "cell_type": "markdown", + "id": "973d656e", + "metadata": {}, + "source": [ + "## Modal" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "86708593", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def ModalContainer(*c, # Components to put in the modal (often `ModalDialog`)\n", + " cls=(), # Additional classes on the `ModalContainer`\n", + " **kwargs # Additional args for `Div` tag\n", + " )->FT: # Div(..., cls='uk-modal uk-modal-container')\n", + " \"Creates a modal container that components go in\"\n", + " return fh.Div(*c, cls=('uk-modal uk-modal-container',stringify(cls)), data_uk_modal=True, **kwargs)\n", + "def ModalDialog(*c, # Components to put in the `ModalDialog` (often `ModalBody`, `ModalHeader`, etc)\n", + " cls=(), # Additional classes on the `ModalDialog`\n", + " **kwargs # Additional args for `Div` tag\n", + " )->FT: # Div(..., cls='uk-modal-dialog')\n", + " \"Creates a modal dialog\"\n", + " return fh.Div(*c, cls=('uk-modal-dialog', stringify(cls)), **kwargs)\n", + "def ModalHeader(*c, # Components to put in the `ModalHeader`\n", + " cls=(), # Additional classes on the `ModalHeader`\n", + " **kwargs # Additional args for `Div` tag\n", + " )->FT: # Div(..., cls='uk-modal-header')\n", + " \"Creates a modal header\"\n", + " return fh.Div(*c, cls=('uk-modal-header', stringify(cls)), **kwargs)\n", + "def ModalBody(*c, # Components to put in the `ModalBody` (often forms, sign in buttons, images, etc.)\n", + " cls=(), # Additional classes on the `ModalBody`\n", + " **kwargs # Additional args for `Div` tag\n", + " )->FT: # Div(..., cls='uk-modal-body')\n", + " \"Creates a modal body\"\n", + " return fh.Div(*c, cls=('uk-modal-body', stringify(cls)), **kwargs)\n", + "def ModalFooter(*c, # Components to put in the `ModalFooter` (often buttons)\n", + " cls=(), # Additional classes on the `ModalFooter`\n", + " **kwargs # Additional args for `Div` tag\n", + " )->FT: # Div(..., cls='uk-modal-footer')\n", + " \"Creates a modal footer\"\n", + " return fh.Div(*c, cls=('uk-modal-footer', stringify(cls)), **kwargs)\n", + "def ModalTitle(*c, # Components to put in the `ModalTitle` (often text)\n", + " cls=(), # Additional classes on the `ModalTitle`\n", + " **kwargs # Additional args for `H2` tag\n", + " )->FT: # H2(..., cls='uk-modal-title')\n", + " \"Creates a modal title\"\n", + " return fh.H2(*c, cls=('uk-modal-title', stringify(cls)), **kwargs)\n", + "def ModalCloseButton(*c, # Components to put in the button (often text and/or an icon)\n", + " cls=\"absolute top-3 right-3\", # Additional classes on the button\n", + " **kwargs # Additional args for `Button` tag\n", + " )->FT: # Button(..., cls='uk-modal-close')\n", + " \"Creates a button that closes a modal with js\"\n", + " cls = (stringify(cls), 'uk-modal-close')\n", + " kwargs['data-uk-close'] = True\n", + " return Button(*c, cls=(stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "962cb933", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Modal(*c, # Components to put in the `ModalBody` (often forms, sign in buttons, images, etc.)\n", + " header=None, # Components that go in the `ModalHeader` (often a `ModalTitle`)\n", + " footer=None, # Components that go in the `ModalFooter` (often a `ModalCloseButton`)\n", + " cls=(), # Additional classes on the outermost `ModalContainer` \n", + " dialog_cls=(), # Additional classes on the `ModalDialog` \n", + " header_cls='p-6', # Additional classes on the `ModalHeader`\n", + " body_cls='space-y-6', # Additional classes on the `ModalBody`\n", + " footer_cls=(), # Additional classes on the `ModalFooter`\n", + " id='', # id for the outermost container\n", + " hx_init=False, # Initialize modal with UIKit on load (used for modals added to the DOM by HTMX)\n", + " hx_open=False, # Open modal on load (used for modals added to the DOM by HTMX)\n", + " **kwargs # Additional args for the outermost `Div` tag\n", + " )->FT: # Fully styled modal FT Component\n", + " \"Creates a modal with the appropriate classes to put the boilerplate in the appropriate places for you\"\n", + " if not id: id = fh.unqid()\n", + " if hx_open: kwargs[\"hx_on__load\"] = f\"UIkit.modal('#{id}').show()\"\n", + " if hx_init and not hx_open: kwargs[\"hx_on__load\"] = f\"UIkit.modal('#{id}')\"\n", + " if hx_open or hx_init: kwargs[\"hx-on:hidden\"] = \"this.remove()\"\n", + " cls, dialog_cls, header_cls, body_cls, footer_cls = map(stringify, (cls, dialog_cls, header_cls, body_cls, footer_cls))\n", + " res = []\n", + " if header: res.append(ModalHeader(cls=header_cls)(header))\n", + " res.append(ModalBody(cls=body_cls)(*c))\n", + " if footer: res.append(ModalFooter(cls=footer_cls)(footer))\n", + " return ModalContainer(ModalDialog(*res, cls=dialog_cls), cls=cls, id=id, **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "4136c713", + "metadata": {}, + "source": [ + "## Exploring modals:" + ] + }, + { + "cell_type": "markdown", + "id": "4b4740c3", + "metadata": {}, + "source": [ + "**Idea**\n", + "\n", + "> Possible add dual functionality to the modal by default - adding an option for HTMX or pure Javascript? Already have the htmx kwarg, maybe just clean it up so both work well" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8116c952", + "metadata": {}, + "outputs": [], + "source": [ + "test_modal = Modal(Caption(\"This is a test modal\"), header=Span(ModalTitle(\"Modal Heading\"), ModalCloseButton(htmx=True)), footer=P(\"Modal Footer\"), id=\"mymodal\", open=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2188fc85", + "metadata": {}, + "outputs": [], + "source": [ + "@rt\n", + "def _modal(): return test_modal" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d59ff966", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Show(Container(Button(\"Open\", hx_get=_modal, hx_swap=\"beforeend\", hx_target='body')), height=500)" + ] + }, + { + "cell_type": "markdown", + "id": "f7b1880d", + "metadata": {}, + "source": [ + "## Other" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "062e2c65", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Placeholder(*c, # Components to put in the placeholder\n", + " cls=(), # Additional classes on the placeholder\n", + " **kwargs # Additional args for `Div` tag\n", + " )->FT: # Div(..., cls='uk-placeholder')\n", + " \"Creates a placeholder\"\n", + " return fh.Div(*c, cls=('uk-placeholder',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0aaf6a63", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Progress(*c, # Components to put in the progress bar (often nothing)\n", + " cls=(), # Additional classes on the progress bar\n", + " value=\"\", # Value of the progress bar\n", + " max=\"100\", # Max value of the progress bar (defaults to 100 for percentage)\n", + " **kwargs # Additional args for `Progress` tag\n", + " )->FT: # Progress(..., cls='uk-progress')\n", + " \"Creates a progress bar\"\n", + " return fh.Progress(*c, value=value, max=max, cls=('uk-progress',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "4509a22a", + "metadata": {}, + "source": [ + "## Icons and Avatars" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e0ea901", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def UkIcon(icon:str, # Icon name from [lucide icons](https://lucide.dev/icons/)\n", + " height:int=None, \n", + " width:int=None, \n", + " stroke_width:int=None, # Thickness of lines\n", + " cls=(), # Additional classes on the `Uk_icon` tag\n", + " **kwargs # Additional args for `Uk_icon` tag\n", + " )->FT: # a lucide icon of the specified size \n", + " \"Creates an icon using lucide icons\"\n", + " return Uk_icon(icon=icon, height=height, width=width, stroke_width=stroke_width, cls=cls, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ffb2568c", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def UkIconLink(icon:str, # Icon name from [lucide icons](https://lucide.dev/icons/)\n", + " height:int=None, \n", + " width:int=None, \n", + " stroke_width:int=None, # Thickness of lines\n", + " cls=(), # Additional classes on the icon\n", + " button:bool=False, # Whether to use a button (defaults to a link)\n", + " **kwargs # Additional args for `A` or `Button` tag\n", + " )->FT: # a lucide icon button or link of the specified size\n", + " \"Creates an icon link using lucide icons\"\n", + " fn = fh.Button if button else fh.A\n", + " return fn(cls=(f\"uk-icon-{'button' if button else 'link'}\", stringify(cls)), **kwargs)(\n", + " UkIcon(icon=icon, height=height, width=width, stroke_width=stroke_width))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8ed62dbf", + "metadata": {}, + "outputs": [], + "source": [ + "class IconButtonT(VEnum):\n", + " xs = 'uk-icon-button-xsmall'\n", + " sm = 'uk-icon-button-small'\n", + " outline= 'uk-icon-button-outline'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "052b0814", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DiceBearAvatar(seed_name:str, # Seed name (ie 'Isaac Flath')\n", + " h:int=20, # Height \n", + " w:int=20, # Width\n", + " ): # Span with Avatar\n", + " \"Creates an Avatar using https://dicebear.com/\"\n", + " url = 'https://api.dicebear.com/8.x/lorelei/svg?seed='\n", + " return Span(cls=f\"relative flex h-{h} w-{w} shrink-0 overflow-hidden rounded-full bg-secondary\")(\n", + " fh.Img(cls=f\"aspect-square h-{h} w-{w}\", alt=\"Avatar\", loading=\"lazy\", src=f\"{url}{seed_name}\"))" + ] + }, + { + "cell_type": "markdown", + "id": "01cc7f66", + "metadata": {}, + "source": [ + "## Flexbox | Grid" + ] + }, + { + "cell_type": "markdown", + "id": "93285680", + "metadata": {}, + "source": [ + "The most common pattern for spacing it to organize the general high level page layout with a `Grid`, and smaller components with `Flex`.\n", + "\n", + ":::{.callout-tip}\n", + "Play [Flex Box Froggy](https://flexboxfroggy.com/) to get an understanding of flex box.\n", + ":::" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d97ba141", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Center(*c, # Components to center\n", + " vertical:bool=True, # Whether to center vertically\n", + " horizontal:bool=True, # Whether to center horizontally \n", + " cls=(), # Additional classes\n", + " **kwargs # Additional args for container div\n", + " )->FT: # Div with centered contents\n", + " \"Centers contents both vertically and horizontally by default\"\n", + " classes = ['flex']\n", + " if vertical: classes.append('items-center min-h-full') \n", + " if horizontal: classes.append('justify-center min-w-full')\n", + " return fh_comp.Center(*c, cls=(stringify(classes), stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "81e07739", + "metadata": {}, + "outputs": [], + "source": [ + "# Show(Div(\n", + "# H2(\"All centered (default)\"),\n", + "# Div(cls='h-48')(Center(H1(\"Center()\"), cls='bg-secondary')),\n", + "# H2(\"Only vertically centered\"),\n", + "# Div(cls='h-48')(Center(H1(\"Center(horizontal=False)\"), horizontal=False, cls='bg-secondary')),\n", + "# H2(\"Only horizontally centered\"),\n", + "# Div(cls='h-48')(Center(H1(\"Center(vertical=False)\"), vertical=False, cls='bg-secondary')),\n", + "# H2(\"Not centered\"),\n", + "# Div(cls='h-48')(Center(H1(\"Center(vertical=False, horizontal=False)\"), vertical=False, horizontal=False, cls='bg-secondary')),\n", + "# cls='space-y-4'\n", + "# ))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6580e01", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from fasthtml.jupyter import *\n", + "from monsterui.all import *\n", + "from functools import partial\n", + "app, rt = fast_app(hdrs=Theme.blue.headers(apex_charts=True))\n", + "server = JupyUvi(app, port=8008)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5f789304", + "metadata": {}, + "outputs": [], + "source": [ + "Show = partial(HTMX, app=app, port = 8008)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4648ad79", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class FlexT(VEnum):\n", + " 'Flexbox modifiers using Tailwind CSS'\n", + " def _generate_next_value_(name, start, count, last_values): return name\n", + " \n", + " # Display\n", + " block = 'flex'\n", + " inline = 'inline-flex'\n", + " \n", + " # Horizontal Alignment\n", + " left = 'justify-start' \n", + " center = 'justify-center'\n", + " right = 'justify-end'\n", + " between = 'justify-between'\n", + " around = 'justify-around'\n", + " \n", + " # Vertical Alignment\n", + " stretch = 'items-stretch'\n", + " top = 'items-start'\n", + " middle = 'items-center' \n", + " bottom = 'items-end'\n", + " \n", + " # Direction\n", + " row = 'flex-row'\n", + " row_reverse = 'flex-row-reverse'\n", + " column = 'flex-col'\n", + " column_reverse = 'flex-col-reverse'\n", + " \n", + " # Wrap\n", + " nowrap = 'flex-nowrap'\n", + " wrap = 'flex-wrap'\n", + " wrap_reverse = 'flex-wrap-reverse'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a2f0a89", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "edb685b5", + "metadata": {}, + "outputs": [], + "source": [ + "#|export\n", + "def Grid(*div, # `Div` components to put in the grid\n", + " cols_min:int=1, # Minimum number of columns at any screen size\n", + " cols_max:int=4, # Maximum number of columns allowed at any screen size\n", + " cols_sm:int=None, # Number of columns on small screens\n", + " cols_md:int=None, # Number of columns on medium screens\n", + " cols_lg:int=None, # Number of columns on large screens\n", + " cols_xl:int=None, # Number of columns on extra large screens\n", + " cols:int=None, # Number of columns on all screens\n", + " cls='gap-4', # Additional classes on the grid (tip: `gap` provides spacing for grids)\n", + " **kwargs # Additional args for `Div` tag\n", + " )->FT: # Responsive grid component\n", + " \"Creates a responsive grid layout with smart defaults based on content\"\n", + " if cols: cols_min = cols_sm = cols_md = cols_lg = cols_xl = cols\n", + " else:\n", + " n = len(div)\n", + " cols_max = min(n, cols_max)\n", + " cols_sm = cols_sm or min(n, cols_min, cols_max)\n", + " cols_md = cols_md or min(n, cols_min+1, cols_max) \n", + " cols_lg = cols_lg or min(n, cols_min+2, cols_max) \n", + " cols_xl = cols_xl or cols_max\n", + " return Div(cls=(f'grid grid-cols-{cols_min} sm:grid-cols-{cols_sm} md:grid-cols-{cols_md} lg:grid-cols-{cols_lg} xl:grid-cols-{cols_xl}', stringify(cls)), **kwargs)(*div)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11e1d241", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DivFullySpaced(*c, # Components\n", + " cls='w-full',# Classes for outer div (`w-full` makes it use all available width)\n", + " **kwargs # Additional args for outer div\n", + " ): # Div with spaced components via flex classes\n", + " \"Creates a flex div with it's components having as much space between them as possible\"\n", + " cls = stringify(cls)\n", + " return Div(cls=(FlexT.block,FlexT.between,FlexT.middle,cls), **kwargs)(*c)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f01fe37c", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DivCentered(*c, # Components\n", + " cls='space-y-4', # Classes for outer div (`space-y-4` provides spacing between components)\n", + " vstack=True, # Whether to stack the components vertically\n", + " **kwargs # Additional args for outer div\n", + " )->FT: # Div with components centered in it\n", + " \"Creates a flex div with it's components centered in it\"\n", + " cls=stringify(cls)\n", + " return Div(cls=(FlexT.block,(FlexT.column if vstack else FlexT.row),FlexT.middle,FlexT.center,cls),**kwargs)(*c)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c38c8af", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DivLAligned(*c, # Components\n", + " cls='space-x-4', # Classes for outer div\n", + " **kwargs # Additional args for outer div\n", + " )->FT: # Div with components aligned to the left\n", + " \"Creates a flex div with it's components aligned to the left\"\n", + " cls=stringify(cls)\n", + " return Div(cls=(FlexT.block,FlexT.left,FlexT.middle,cls), **kwargs)(*c)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0209ff32", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DivRAligned(*c, # Components\n", + " cls='space-x-4', # Classes for outer div\n", + " **kwargs # Additional args for outer div\n", + " )->FT: # Div with components aligned to the right\n", + " \"Creates a flex div with it's components aligned to the right\"\n", + " cls=stringify(cls)\n", + " return Div(cls=(FlexT.block,FlexT.right,FlexT.middle,cls), **kwargs)(*c)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "130f5b56", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DivVStacked(*c, # Components\n", + " cls='space-y-4', # Additional classes on the div (tip: `space-y-4` provides spacing between components)\n", + " **kwargs # Additional args for the div\n", + " )->FT: # Div with components stacked vertically\n", + " \"Creates a flex div with it's components stacked vertically\"\n", + " cls=stringify(cls)\n", + " return Div(cls=(FlexT.block,FlexT.column,FlexT.middle,cls), **kwargs)(*c)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a583eefe", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DivHStacked(*c, # Components\n", + " cls='space-x-4', # Additional classes on the div (`space-x-4` provides spacing between components)\n", + " **kwargs # Additional args for the div\n", + " )->FT: # Div with components stacked horizontally\n", + " \"Creates a flex div with it's components stacked horizontally\"\n", + " cls=stringify(cls)\n", + " return Div(cls=(FlexT.block,FlexT.row,FlexT.middle,cls), **kwargs)(*c)" + ] + }, + { + "cell_type": "markdown", + "id": "293f142a", + "metadata": {}, + "source": [ + "## Nav" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "505ca979", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class NavT(VEnum):\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('nav', name)\n", + " default = auto()\n", + " primary = auto()\n", + " secondary = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d99a277f", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def NavContainer(*li, # List items are navigation elements (Special `Li` such as `NavParentLi`, `NavDividerLi`, `NavHeaderLi`, `NavSubtitle`, `NavCloseLi` can also be used)\n", + " cls=NavT.primary, # Additional classes on the nav\n", + " parent=True, # Whether this nav is a *parent* or *sub* nav\n", + " uk_nav=False, #True for default collapsible behavior, see [frankenui docs](https://franken-ui.dev/docs/nav#component-options) for more advanced options\n", + " uk_scrollspy_nav=False, # Activates scrollspy linking each item `A` tags `href` to content's `id` attribute\n", + " sticky=False, # Whether to stick to the top of the page while scrolling\n", + " **kwargs # Additional args\n", + " )->FT: # FT Component that is a list of `Li` styled for a sidebar navigation menu\n", + " \"Creates a navigation container (useful for creating a sidebar navigation). A Nav is a list (NavBar is something different)\"\n", + " _uk_scrollspy_nav = False\n", + " if uk_scrollspy_nav:\n", + " if isinstance(uk_scrollspy_nav, bool): _uk_scrollspy_nav = 'closest: li; scroll: true' if uk_scrollspy_nav else False\n", + " else: _uk_scrollspy_nav = uk_scrollspy_nav\n", + " _sticky = 'float-left sticky top-4 hidden md:block' if sticky else ''\n", + " return fh.Ul(*li, uk_nav=uk_nav, cls=(f\"uk-nav{'' if parent else '-sub'}\", stringify(cls), _sticky), uk_scrollspy_nav=_uk_scrollspy_nav, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0539b25a", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def NavParentLi(*nav_container, # `NavContainer` container for a nested nav with `parent=False`)\n", + " cls=(), # Additional classes on the li\n", + " **kwargs # Additional args for the li\n", + " )->FT: # Navigation list item\n", + " \"Creates a navigation list item with a parent nav for nesting\"\n", + " return fh.Li(*nav_container, cls=('uk-parent', stringify(cls)),**kwargs)\n", + "def NavDividerLi(*c, # Components\n", + " cls=(), # Additional classes on the li\n", + " **kwargs # Additional args for the li\n", + " )->FT: # Navigation list item with a divider\n", + " \"Creates a navigation list item with a divider\"\n", + " return fh.Li(*c, cls=('uk-nav-divider', stringify(cls)),**kwargs)\n", + "def NavHeaderLi(*c, # Components\n", + " cls=(), # Additional classes on the li\n", + " **kwargs # Additional args for the li\n", + " )->FT: # Navigation list item with a header\n", + " \"Creates a navigation list item with a header\"\n", + " return fh.Li(*c, cls=('uk-nav-header', stringify(cls)),**kwargs)\n", + "def NavSubtitle(*c, # Components\n", + " cls=TextPresets.muted_sm, # Additional classes on the div\n", + " **kwargs # Additional args for the div\n", + " )->FT: # Navigation subtitle\n", + " \"Creates a navigation subtitle\"\n", + " return fh.Div(*c, cls=('uk-nav-subtitle', stringify(cls)),**kwargs)\n", + "def NavCloseLi(*c, # Components\n", + " cls=(), # Additional classes on the li\n", + " **kwargs # Additional args for the li\n", + " )->FT: # Navigation list item with a close button\n", + " \"Creates a navigation list item with a close button\"\n", + " return fh.Li(*c, cls=('uk-drop-close', stringify(cls)),**kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee713a6e", + "metadata": {}, + "outputs": [], + "source": [ + "def NavParentIcon(): return Span(uk_nav_parent_icon=True)" + ] + }, + { + "cell_type": "markdown", + "id": "331a69a0", + "metadata": {}, + "source": [ + "## Navbar" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df4312e3", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class ScrollspyT(VEnum):\n", + " underline = 'navbar-underline'\n", + " bold = 'navbar-bold'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "398e8988", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def NavBar(*c, # Component for right side of navbar (Often A tag links)\n", + " brand=H3(\"Title\"), # Brand/logo component for left side\n", + " right_cls='items-center space-x-4', # Spacing for desktop links\n", + " mobile_cls='space-y-4', # Spacing for mobile links\n", + " sticky:bool=False, # Whether to stick to the top of the page while scrolling\n", + " uk_scrollspy_nav:bool|str=False, # Whether to use scrollspy for navigation\n", + " cls='p-4', # Classes for navbar\n", + " scrollspy_cls=ScrollspyT.underline, # Scrollspy class (usually ScrollspyT.*)\n", + " menu_id=None, # ID for menu container (used for mobile toggle)\n", + " )->FT: # Responsive NavBar\n", + " \"Creates a responsive navigation bar with mobile menu support\"\n", + " if menu_id is None: menu_id = fh.unqid()\n", + " sticky_cls = 'sticky top-4 bg-base-100/80 backdrop-blur-sm z-50' if sticky else ''\n", + " if uk_scrollspy_nav == True: uk_scrollspy_nav = 'closest: a; scroll: true'\n", + "\n", + " mobile_icon = A(UkIcon(\"menu\", width=30, height=30), cls=\"md:hidden\", data_uk_toggle=f\"target: #{menu_id}; cls: hidden\")\n", + " return Div(\n", + " Div(\n", + " DivFullySpaced(\n", + " brand, # Brand/logo component for left side\n", + " mobile_icon, # Hamburger menu icon\n", + " Div(*c,cls=(stringify(right_cls),'hidden md:flex'), uk_scrollspy_nav=uk_scrollspy_nav)),# Desktop Navbar (right side)\n", + " cls=('monster-navbar', stringify(cls), stringify(scrollspy_cls))\n", + " ),\n", + " DivCentered(*c, \n", + " cls=(stringify(mobile_cls),stringify(cls), stringify(scrollspy_cls),\n", + " 'hidden md:hidden monster-navbar'), \n", + " id=menu_id, uk_scrollspy_nav=uk_scrollspy_nav),\n", + " cls=sticky_cls)" + ] + }, + { + "cell_type": "markdown", + "id": "332e3968", + "metadata": {}, + "source": [ + "## Slider" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6ea2c0e", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def SliderContainer(\n", + " *c, # Components\n", + " cls='', # Additional classes on the container\n", + " uk_slider=True, # See FrankenUI Slider docs for more options\n", + " **kwargs # Additional args for the container\n", + " ) -> FT: # Div(..., cls='relative', uk_slider=True, ...)\n", + " \"Creates a slider container\"\n", + " return Div(*c, cls=('relative', stringify(cls)), uk_slider=uk_slider, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da2f1202", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def SliderItems(\n", + " *c, # Components\n", + " cls='', # Additional classes for the items\n", + " **kwargs # Additional args for the items\n", + " ) -> FT: # Div(..., cls='uk-slider-items uk-grid', ...)\n", + " \"Creates a slider items container\"\n", + " return Div(*c, cls=('uk-slider-items uk-grid', stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e25bfae7", + "metadata": {}, + "outputs": [], + "source": [ + "# Show(SliderContainer(SliderItems(*[Img(src=f'https://picsum.photos/200/200?random={i}', style='width:200px') for i in range(5)])))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7edf26f7", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def SliderNav(\n", + " cls='uk-position-small uk-hidden-hover', # Additional classes for the navigation\n", + " prev_cls='absolute left-0 top-1/2 -translate-y-1/2', # Additional classes for the previous navigation\n", + " next_cls='absolute right-0 top-1/2 -translate-y-1/2', # Additional classes for the next navigation\n", + " **kwargs # Additional args for the navigation\n", + " ) -> FT: # Left and right navigation arrows for Slider component\n", + " \"Navigation arrows for Slider component\"\n", + " return (\n", + " fh.A(cls=(prev_cls, stringify(cls)), href='',\n", + " uk_slidenav_previous=True, uk_slider_item='previous', **kwargs),\n", + " fh.A(cls=(next_cls, stringify(cls)), href='',\n", + " uk_slidenav_next=True, uk_slider_item='next', **kwargs)\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5aae8c03", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Slider(*c, # Items to show in slider\n", + " cls='', # Classes for slider container\n", + " items_cls='gap-4', # Classes for items container\n", + " nav=True, # Whether to show navigation arrows\n", + " nav_cls='', # Classes for navigation arrows\n", + " **kwargs # Additional args for slider container\n", + " ) -> FT: # SliderContainer(SliderItems(..., cls='gap-4'), SliderNav?)\n", + " \"Creates a slider with optional navigation arrows\"\n", + " nav_comp = SliderNav(cls=nav_cls) if nav else ()\n", + " return SliderContainer(\n", + " SliderItems(*c, cls=items_cls),\n", + " *nav_comp,\n", + " cls=cls,\n", + " **kwargs\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "706f6ccc", + "metadata": {}, + "outputs": [], + "source": [ + "# Show(Slider(*[Div(Img(src=f'https://picsum.photos/200/200?random={i}'))\n", + "# for i in range(5)]), link=True)" + ] + }, + { + "cell_type": "markdown", + "id": "f0fa7a22", + "metadata": {}, + "source": [ + "## DropDown" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34747040", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def DropDownNavContainer(*li, # Components\n", + " cls=NavT.primary, # Additional classes on the nav\n", + " parent=True, # Whether to use a parent nav\n", + " uk_nav=False, #True for default collapsible behavior, see https://franken-ui.dev/docs/nav#component-options for more advanced options\n", + " uk_dropdown=True, # Whether to use a dropdown\n", + " **kwargs # Additional args for the nav\n", + " )->FT: # DropDown nav container\n", + " \"A Nav that is part of a DropDown\"\n", + " return Div(cls = 'uk-drop uk-dropdown',uk_dropdown=uk_dropdown)(NavContainer(*li, cls=('uk-dropdown-nav',stringify(cls)), uk_nav=uk_nav, parent=parent, **kwargs))" + ] + }, + { + "cell_type": "markdown", + "id": "ac27bf48", + "metadata": {}, + "source": [ + "## Tabs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "553f4a81", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def TabContainer(*li, # Components\n", + " cls='', # Additional classes on the `Ul`\n", + " alt=False, # Whether to use an alternative tab style\n", + " **kwargs # Additional args for the `Ul`\n", + " )->FT: # Tab container\n", + " \"A TabContainer where children will be different tabs\"\n", + " cls = stringify(cls)\n", + " return Ul(cls=(f\"uk-tab{'-alt' if alt else ''}\",stringify(cls)),**kwargs)(*li)" + ] + }, + { + "cell_type": "markdown", + "id": "6348c5f3", + "metadata": {}, + "source": [ + "## Cards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "759a0de3", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class CardT(VEnum):\n", + " 'Card styles from UIkit'\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('card', name)\n", + " default = auto()\n", + " primary = auto()\n", + " secondary = auto()\n", + " destructive = auto()\n", + " hover = 'uk-card hover:shadow-lg hover:-translate-y-1 transition-all duration-200'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c165a0a6", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def CardTitle(*c, # Components (often a string)\n", + " cls=(), # Additional classes on the div\n", + " **kwargs # Additional args for the div\n", + " ): \n", + " \"Creates a card title\"\n", + " return fh.Div(*c, cls=('uk-card-title',stringify(cls)), **kwargs)\n", + "\n", + "def CardHeader(*c, # Components that goes in the header (often a `ModalTitle` and description)\n", + " cls=(), # Additional classes on the div\n", + " **kwargs # Additional args for the div\n", + " )->FT: # Container for the header of a card\n", + " \"Creates a card header\"\n", + " return fh.Div(*c, cls=('uk-card-header',stringify(cls)), **kwargs)\n", + "\n", + "def CardBody(*c, # Components that go in the body (Main content of the card such as a form, and image, a signin form, etc.)\n", + " cls=(), # Additional classes on the div\n", + " **kwargs # Additional args for the div\n", + " )->FT: # Container for the body of a card\n", + " \"Creates a card body\"\n", + " return fh.Div(*c, cls=('uk-card-body',stringify(cls)), **kwargs)\n", + "\n", + "def CardFooter(*c, # Components that go in the footer (often a `ModalCloseButton`)\n", + " cls=(), # Additional classes on the div\n", + " **kwargs # Additional args for the div\n", + " )->FT: # Container for the footer of a card\n", + " \"Creates a card footer\"\n", + " return fh.Div(*c, cls=('uk-card-footer',stringify(cls)), **kwargs)\n", + "\n", + "def CardContainer(*c, # Components (typically `CardHeader`, `CardBody`, `CardFooter`)\n", + " cls=CardT.default, # Additional classes on the div\n", + " **kwargs # Additional args for the div\n", + " )->FT: # Container for a card\n", + " \"Creates a card container\"\n", + " return fh.Div(*c, cls=('uk-card',stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cd8a16e4", + "metadata": {}, + "outputs": [], + "source": [ + "#|export\n", + "def Card(*c, # Components that go in the body (Main content of the card such as a form, and image, a signin form, etc.)\n", + " header:FT|Iterable[FT]=None, # Component(s) that goes in the header (often a `ModalTitle` and a subtitle)\n", + " footer:FT|Iterable[FT]=None, # Component(s) that goes in the footer (often a `ModalCloseButton`)\n", + " body_cls='space-y-6', # classes for the body\n", + " header_cls=(), # classes for the header\n", + " footer_cls=(), # classes for the footer\n", + " cls=(), #class for outermost component\n", + " **kwargs # additional arguments for the `CardContainer`\n", + " )->FT: # Card component\n", + " \"Creates a Card with a header, body, and footer\"\n", + " header_cls, footer_cls, body_cls, cls = map(stringify, (header_cls, footer_cls, body_cls, cls))\n", + " res = []\n", + " if header: res.append(CardHeader(cls=header_cls)(header))\n", + " res.append(CardBody(cls=body_cls)(*c))\n", + " if footer: res.append(CardFooter(cls=footer_cls)(footer))\n", + " return CardContainer(cls=cls, **kwargs)(*res)" + ] + }, + { + "cell_type": "markdown", + "id": "e86be034", + "metadata": {}, + "source": [ + "## Tables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d0038f9", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class TableT(VEnum):\n", + " def _generate_next_value_(name, start, count, last_values): return str2ukcls('table', name)\n", + " divider = auto()\n", + " striped = auto()\n", + " hover = auto()\n", + " sm = auto()\n", + " lg = auto()\n", + " justify = auto()\n", + " middle = auto()\n", + " responsive = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e942edd1", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Table(*c, # Components (typically `Thead`, `Tbody`, `Tfoot`)\n", + " cls=(TableT.middle, TableT.divider, TableT.hover, TableT.sm), # Additional classes on the table\n", + " **kwargs # Additional args for the table\n", + " )->FT: # Table component\n", + " \"Creates a table\"\n", + " return fh.Table(cls=('uk-table', stringify(cls)), *c, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30bbdbed", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def _TableCell(Component, \n", + " *c, # Components that go in the cell\n", + " cls=(), # Additional classes on the cell container\n", + " shrink=False, # Whether to shrink the cell\n", + " expand=False, # Whether to expand the cell\n", + " small=False, # Whether to use a small table\n", + " **kwargs # Additional args for the cell\n", + " )->FT: # Table cell\n", + " \"Creates a table cell\"\n", + " cls = stringify(cls)\n", + " if shrink: cls += ' uk-table-shrink'\n", + " if expand: cls += ' uk-table-expand'\n", + " if small: cls += ' uk-table-small'\n", + " return Component(*c,cls=cls, **kwargs)\n", + "\n", + "@delegates(_TableCell, but=['Component'])\n", + "def Td(*c,**kwargs): return _TableCell(fh.Td, *c, **kwargs)\n", + "@delegates(_TableCell, but=['Component'])\n", + "def Th(*c,**kwargs): return _TableCell(fh.Th, *c, **kwargs)\n", + "\n", + "def Tbody(*rows, cls=(), sortable=False, **kwargs): return fh.Tbody(*rows, cls=stringify(cls), uk_sortable=sortable, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2cd41ae7", + "metadata": {}, + "outputs": [], + "source": [ + "#|export\n", + "def TableFromLists(header_data:Sequence, # List of header data\n", + " body_data:Sequence[Sequence], # List of lists of body data\n", + " footer_data=None, # List of footer data\n", + " header_cell_render=Th, # Function(content) -> FT that renders header cells\n", + " body_cell_render=Td, # Function(key, content) -> FT that renders body cells\n", + " footer_cell_render=Td, # Function(key, content) -> FT that renders footer cells\n", + " cls=(TableT.middle, TableT.divider, TableT.hover, TableT.sm), # Additional classes on the table\n", + " sortable=False, # Whether to use sortable table\n", + " **kwargs # Additional args for the table\n", + " )->FT: # Table from lists\n", + " \"Creates a Table from a list of header data and a list of lists of body data\"\n", + " return Table(\n", + " Thead(Tr(*map(header_cell_render, header_data))),\n", + " Tbody(*[Tr(*map(body_cell_render, r)) for r in body_data], sortable=sortable),\n", + " Tfoot(Tr(*map(footer_cell_render, footer_data))) if footer_data else '',\n", + " cls=stringify(cls), \n", + " **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa3eebd7", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def TableFromDicts(header_data:Sequence, # List of header data\n", + " body_data:Sequence[dict], # List of dicts of body data\n", + " footer_data=None, # List of footer data\n", + " header_cell_render=Th, # Function(content) -> FT that renders header cells\n", + " body_cell_render=lambda k,v : Td(v), # Function(key, content) -> FT that renders body cells\n", + " footer_cell_render=lambda k,v : Td(v), # Function(key, content) -> FT that renders footer cells\n", + " cls=(TableT.middle, TableT.divider, TableT.hover, TableT.sm), # Additional classes on the table\n", + " sortable=False, # Whether to use sortable table\n", + " **kwargs # Additional args for the table\n", + " )->FT: # Styled Table\n", + " \"Creates a Table from a list of header data and a list of dicts of body data\"\n", + " return Table(\n", + " Thead(Tr(*[header_cell_render(h) for h in header_data])),\n", + " Tbody(*[Tr(*[body_cell_render(k, r.get(k, '')) for k in header_data]) for r in body_data], sortable=sortable),\n", + " Tfoot(Tr(*[footer_cell_render(k, footer_data.get(k.lower(), '')) for k in header_data])) if footer_data else '',\n", + " cls=stringify(cls), \n", + " **kwargs\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "ff42d2d8", + "metadata": {}, + "source": [ + "## Calendar, Date, Time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a3004b07", + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import datetime\n", + "\n", + "#| export\n", + "def CalendarInput(\n", + " cls = \"\", # Additional classes\n", + " today: bool = False, # Automatically sets today as the active date.\n", + " jumpable: bool = False, # Allow month and year selection\n", + " starts_with: int = 0, # First day of the week (0 for Sunday, 1 for Monday)\n", + " disabled_dates: str | list[str] = None, # A comma-separated list of dates to disable (YYYY-MM-DD)\n", + " marked_dates: str | list[str] = None, # A comma-separated list of dates to add an indicator (YYYY-MM-DD)\n", + " view_date: str = None, # Sets the initial view date of the calendar (YYYY-MM-DD)\n", + " min_date: str = None, # Sets the minimum date that can be selected (YYYY-MM-DD)\n", + " max_date: str = None, # Sets the maximum date that can be selected (YYYY-MM-DD)\n", + " selected_date: str = None, # Sets the current value of the calendar (YYYY-MM-DD)\n", + " hidden_name: str = None, # Sets the hidden name input field\n", + " i18n: str = None, # Enables internationalization\n", + " **kwargs # Additional arguments\n", + ") -> str:\n", + " \"\"\"Creates a UIkit calendar component.\"\"\"\n", + " \n", + " # Validation bits for attributes that require YYYY-MM-DD formats\n", + " def _validate_date(date_value):\n", + " \"\"\"Validates if a given date string follows the YYYY-MM-DD format.\"\"\"\n", + " if isinstance(date_value, str):\n", + " try:\n", + " datetime.strptime(date_value, \"%Y-%m-%d\")\n", + " return True\n", + " except ValueError:\n", + " return False\n", + " return False\n", + " \n", + " validation_errors = []\n", + " date_attrs = {\n", + " \"view_date\": [view_date] if view_date else [],\n", + " \"min_date\": [min_date] if min_date else [],\n", + " \"max_date\": [max_date] if max_date else [],\n", + " \"disabled_dates\": disabled_dates.split(',') if isinstance(disabled_dates, str) else (disabled_dates if disabled_dates else []),\n", + " \"marked_dates\": marked_dates.split(',') if isinstance(marked_dates, str) else (marked_dates if marked_dates else []),\n", + " }\n", + " \n", + " for attr_name, attr_values in date_attrs.items():\n", + " if attr_values:\n", + " invalid_dates = [date for date in attr_values if date and not _validate_date(date)]\n", + " if invalid_dates:\n", + " validation_errors.append(f\"{attr_name} contains invalid dates: {', '.join(invalid_dates)}\")\n", + " \n", + " if validation_errors:\n", + " raise ValueError(\"\\n\".join(validation_errors))\n", + " \n", + " # Set the tag attributes\n", + " attrs = {\n", + " \"today\": today,\n", + " \"jumpable\": jumpable,\n", + " \"starts-with\": starts_with,\n", + " \"disabled-dates\": \",\".join(date_attrs[\"disabled_dates\"]) if date_attrs[\"disabled_dates\"] else None,\n", + " \"marked-dates\": \",\".join(date_attrs[\"marked_dates\"]) if date_attrs[\"marked_dates\"] else None,\n", + " \"view-date\": view_date,\n", + " \"min\": min_date,\n", + " \"max\": max_date,\n", + " \"value\": selected_date,\n", + " \"name\": hidden_name,\n", + " \"i18n\": i18n,\n", + " }\n", + " \n", + " attrs = {k: v for k, v in attrs.items() if v is not None}\n", + " \n", + " # Return the fastHTML web component\n", + " return fh.ft_html(\"uk-calendar\", cls=stringify(cls), **{**attrs, **kwargs})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10f8a6cf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "\n", + "```" + ], + "text/plain": [ + "uk-calendar((),{'today': True, 'jumpable': True, 'starts-with': 1, 'disabled-dates': '2025-02-10,2025-02-05', 'marked-dates': '2025-02-10,2025-02-05', 'min': '2025-02-01', 'max': '2025-02-15', 'class': ''})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ci = CalendarInput(\n", + " today=True, \n", + " jumpable=True, \n", + " starts_with=1, \n", + " min_date='2025-02-01', \n", + " max_date='2025-02-15',\n", + " disabled_dates='2025-02-10,2025-02-05',\n", + " marked_dates='2025-02-10,2025-02-05',\n", + ")\n", + "ci" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4980c063", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Show(ci)" + ] + }, + { + "cell_type": "markdown", + "id": "b91b0b27", + "metadata": {}, + "source": [ + "## Markdown" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7dd39c6", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "franken_class_map = {\n", + " 'h1': 'uk-h1 text-4xl font-bold mt-12 mb-6',\n", + " 'h2': 'uk-h2 text-3xl font-bold mt-10 mb-5', \n", + " 'h3': 'uk-h3 text-2xl font-semibold mt-8 mb-4',\n", + " 'h4': 'uk-h4 text-xl font-semibold mt-6 mb-3',\n", + " \n", + " # Body text and links\n", + " 'p': 'text-lg leading-relaxed mb-6',\n", + " 'a': 'uk-link text-primary hover:text-primary-focus underline',\n", + " \n", + " # Lists with proper spacing\n", + " 'ul': 'uk-list uk-list-bullet space-y-2 mb-6 ml-6 text-lg',\n", + " 'ol': 'uk-list uk-list-decimal space-y-2 mb-6 ml-6 text-lg',\n", + " 'li': 'leading-relaxed',\n", + " \n", + " # Code and quotes\n", + " 'pre': 'bg-base-200 rounded-lg p-4 mb-6',\n", + " 'code': 'uk-codespan px-1',\n", + " 'pre code': 'uk-codespan px-1 block overflow-x-auto',\n", + " 'blockquote': 'uk-blockquote pl-4 border-l-4 border-primary italic mb-6',\n", + " \n", + " # Tables\n", + " 'table': 'uk-table uk-table-divider uk-table-hover uk-table-small w-full mb-6',\n", + " 'th': '!text-left p-2 font-semibold',\n", + " 'td': 'p-2',\n", + " \n", + " # Other elements\n", + " 'hr': 'uk-divider-icon my-8',\n", + " 'img': 'max-w-full h-auto rounded-lg mb-6'\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b4bcb8c6", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def apply_classes(html_str:str, # Html string\n", + " class_map=None, # Class map\n", + " class_map_mods=None # Class map that will modify the class map map (for small changes to base map)\n", + " )->str: # Html string with classes applied\n", + " \"Apply classes to html string\"\n", + " if not html_str: return html_str\n", + " # Handles \"Unicode strings with encoding declaration are not supported\":\n", + " if html_str[:100].lstrip().startswith('', 1)[1].strip()\n", + " class_map = ifnone(class_map, franken_class_map)\n", + " if class_map_mods: class_map = {**class_map, **class_map_mods}\n", + " try:\n", + " html_str = html.fragment_fromstring(html_str, create_parent=True)\n", + " for selector, classes in class_map.items():\n", + " # Handle descendant selectors (e.g., 'pre code')\n", + " xpath = '//' + '/descendant::'.join(selector.split())\n", + " for element in html_str.xpath(xpath):\n", + " existing_class = element.get('class', '')\n", + " new_class = f\"{existing_class} {classes}\".strip()\n", + " element.set('class', new_class)\n", + " return ''.join(etree.tostring(c, encoding='unicode', method='html') for c in html_str)\n", + " except (etree.ParserError,ValueError): return html_str" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7d943f5f", + "metadata": {}, + "outputs": [], + "source": [ + "_test = apply_classes(\"

Hello, world!

\", class_map_mods={'h1': 'uk-h1 my-4 mb-4'})\n", + "assert _test == '

Hello, world!

'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f973ca3", + "metadata": {}, + "outputs": [], + "source": [ + "_test = apply_classes(\"\", class_map_mods={'h1': 'uk-h1 my-4 mb-4'})\n", + "assert _test == ''" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0cf074d0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\n'" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "apply_classes(mistletoe.markdown(''), franken_class_map, None)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a2417a54", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class FrankenRenderer(HTMLRenderer):\n", + " \"Custom renderer for Franken UI that handles image paths\"\n", + " def __init__(self, *args, img_dir=None, **kwargs):\n", + " super().__init__(*args, **kwargs)\n", + " self.img_dir = img_dir\n", + "\n", + " def render_image(self, token):\n", + " \"Modify image paths if they're relative and self.img_dir is specified\"\n", + " template = '\"{}\"{}'\n", + " title = f' title=\"{token.title}\"' if hasattr(token, 'title') else ''\n", + " src = token.src\n", + " if self.img_dir and not src.startswith(('http://', 'https://', '/', 'attachment:', 'blob:', 'data:')):\n", + " src = f'{pathlib.Path(self.img_dir)}/{src}'\n", + " return template.format(src, token.children[0].content if token.children else '', title)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b31876df", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def render_md(md_content:str, # Markdown content\n", + " class_map=None, # Class map\n", + " class_map_mods=None, # Additional class map\n", + " img_dir:str=None, # Directory containing images\n", + " renderer=FrankenRenderer # custom renderer\n", + " )->FT: # Rendered markdown\n", + " \"Renders markdown using mistletoe and lxml with custom image handling\"\n", + " if md_content=='': return md_content\n", + " html_content = mistletoe.markdown(md_content, partial(renderer, img_dir=img_dir))\n", + " return NotStr(apply_classes(html_content, class_map, class_map_mods))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00cc5859", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "

\"test\"

\n", + "\n", + "

\"test\"

\n", + "\n", + "

\"test\"

\n", + "\n", + "

\"test\"

\n", + "\n" + ] + } + ], + "source": [ + "print(render_md('![test](/users/isaac-flath/my_image.png)', img_dir='static'))\n", + "print(render_md('![test](my_image.png)', img_dir='static'))\n", + "print(render_md('![test](https://example.com/img.png)', img_dir='static'))\n", + "print(render_md('![test](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiB)', img_dir='static'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a69f18f", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def ThemePicker(color=True, radii=True, shadows=True, font=True, mode=True, cls='p-4', custom_themes=[]):\n", + " \"Theme picker component with configurable sections\"\n", + " def _opt(val, txt, **kwargs): return Option(txt, value=val, **kwargs)\n", + " def _optgrp(key, lbl, opts): return fh.Optgroup(data_key=key, label=lbl)(*opts)\n", + " \n", + " groups = []\n", + " if color: groups.append(_optgrp('theme', 'Theme', [\n", + " _opt('uk-theme-zinc', 'Zinc', data_hex='#52525b', selected=True),\n", + " *[_opt(f'uk-theme-{c.lower()}', c, data_hex=h) for c,h in \n", + " [('Slate','#64748b'),('Stone','#78716c'),('Gray','#6b7280'),\n", + " ('Neutral','#737373'),('Red','#dc2626'),('Rose','#e11d48'),\n", + " ('Orange','#f97316'),('Green','#16a34a'),('Blue','#2563eb'),\n", + " ('Yellow','#facc15'),('Violet','#7c3aed'),*custom_themes]]]))\n", + " if radii: groups.append(_optgrp('radii', 'Radii', [\n", + " _opt('uk-radii-none','None'), _opt('uk-radii-sm','Small'),\n", + " _opt('uk-radii-md','Medium',selected=True), _opt('uk-radii-lg','Large')]))\n", + " if shadows: groups.append(_optgrp('shadows', 'Shadows', [\n", + " _opt('uk-shadows-none','None'), _opt('uk-shadows-sm','Small',selected=True),\n", + " _opt('uk-shadows-md','Medium'), _opt('uk-shadows-lg','Large')]))\n", + " if font: groups.append(_optgrp('font', 'Font', [\n", + " _opt('uk-font-sm','Small',selected=True), _opt('uk-font-base','Default')]))\n", + " if mode: groups.append(_optgrp('mode', 'Mode', [\n", + " _opt('light','Light',data_icon='sun'), _opt('dark','Dark',data_icon='moon')]))\n", + " from fasthtml.components import Uk_theme_switcher\n", + " return Div(Uk_theme_switcher(fh.Select(*groups, hidden=True), id=\"theme-switcher\"), cls=stringify(cls))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f10bf966", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Show(ThemePicker())" + ] + }, + { + "cell_type": "markdown", + "id": "55cb49c1", + "metadata": {}, + "source": [ + "### Insertable Select" + ] + }, + { + "cell_type": "markdown", + "id": "1e931722", + "metadata": {}, + "source": [ + "> Since the `LabelSelect()` component already exists, we will simply add the `insertable=True` param and test it's viability with htmx:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a6af684a", + "metadata": {}, + "outputs": [], + "source": [ + "@rt\n", + "def test_form(email:str):\n", + " return Span('Server Received: ', Output(email), cls=\"border-b p-2\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e767c812", + "metadata": {}, + "outputs": [], + "source": [ + "select = Form(LabelSelect(\n", + " Option(\"Select a verified email to display\", value=\"\", selected=True, disabled=True),\n", + " *[Option(o, value=o) for o in ('m@example.com', 'm@yahoo.com', 'm@cloud.com')], \n", + " label=\"Email\", id=\"email\", name=\"email\",\n", + " insertable=True), Button('Submit', cls=ButtonT.primary+' uk-btn'), hx_post=test_form, hx_swap=\"beforeend\", cls='grid gap-3 mx-auto mt-4 w-1/2')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "959cc162", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Show(select, height=350)" + ] + }, + { + "cell_type": "markdown", + "id": "9162d6b0", + "metadata": {}, + "source": [ + "### Persist client option on submit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7d00ca6", + "metadata": {}, + "outputs": [], + "source": [ + "@rt\n", + "def submit_fruit(sess, fruit:str):\n", + " if not fruit: return\n", + " if fruit not in sess['options']: sess['options'].append(fruit.lower())\n", + " return Span('Server Received: ', Output(fruit.capitalize()))\n", + "\n", + "@rt\n", + "def refresh(sess, clear:bool):\n", + " if clear: sess.clear()\n", + " return select2(sess)" + ] + }, + { + "cell_type": "markdown", + "id": "6b7a43c5", + "metadata": {}, + "source": [ + "> Using `` for option label" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6ae03388", + "metadata": {}, + "outputs": [], + "source": [ + "@rt\n", + "def select2(sess):\n", + " if not sess.get('options', ''):\n", + " sess['options'] = ['apple', 'orange', 'banana', 'mango']\n", + " btns = DivHStacked(cls=\"w-full justify-between\")(\n", + " Button('Clear (Persist)', hx_post=refresh.to(sess=sess, clear=False), hx_target=\"closest form\", hx_swap=\"outerHTML\", cls=ButtonT.default),\n", + " Button('Clear (Refresh)', hx_post=refresh.to(sess=sess, clear=True), hx_target=\"closest form\", hx_swap=\"outerHTML\", cls=ButtonT.default),\n", + " Button('Submit', cls=ButtonT.primary))\n", + " \n", + " return Form(LabelSelect(\n", + " fh.Optgroup(label=\"Fruit\")(\n", + " *map(lambda l: Option(l.capitalize(), value=l), sorted(sess['options']))\n", + " ),\n", + " label=\"Fruit picker\", id=\"fruit\", name=\"fruit\",\n", + " icon=True, insertable=\"true\", placeholder=\"Choose a fruit...\",\n", + " cls_custom=\"button: uk-input-fake justify-between w-full; dropdown: w-full\"),\n", + " btns,hx_post=submit_fruit, hx_swap=\"beforeend\",\n", + " cls='grid gap-2 mx-auto mt-4 w-1/2')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed0e86b3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Show(select2, height=350)" + ] + }, + { + "cell_type": "markdown", + "id": "3d822070", + "metadata": {}, + "source": [ + "### Light Box" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a0b3bef", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def LightboxContainer(*lightboxitem, # `LightBoxItem`s that will be inside lightbox\n", + " data_uk_lightbox='counter: true', # See https://franken-ui.dev/docs/2.0/lightbox for advanced options\n", + " **kwargs # Additional options for outer container\n", + " )->FT: # Lightbox\n", + " \"Lightbox container that will hold `LightboxItems`\"\n", + " return fh.Div(*lightboxitem, data_uk_lightbox=data_uk_lightbox, **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "285ec264", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def LightboxItem(*c, # Component that when clicked will open the lightbox (often a button)\n", + " href, # Href to image, youtube video, vimeo, google maps, etc.\n", + " data_alt=None, # Alt text for the lightbox item/image\n", + " data_caption=None, # Caption for the item that shows below it\n", + " cls='', # Class for the A tag (often nothing or `uk-btn`)\n", + " **kwargs # Additional args for the `A` tag\n", + " )->FT: # A(... href, data_alt, cls., ...)\n", + " \"Anchor tag with appropriate structure to go inside a `LightBoxContainer`\"\n", + " return fh.A(*c, href=href, data_alt=data_alt, cls=stringify(cls), **kwargs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "904b3eaa", + "metadata": {}, + "outputs": [], + "source": [ + "# Show(\n", + "# LightboxContainer(\n", + "# LightboxItem(Button(\"Open\"), href='https://picsum.photos/id/100/1280/720.webp', data_alt='alt text stuff', data_caption='my caption'),\n", + "# ),\n", + "# height=400\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "11058ff9", + "metadata": {}, + "outputs": [], + "source": [ + "# Show(\n", + "# LightboxContainer(\n", + "# LightboxItem(Button(\"Open\"), href='https://picsum.photos/id/100/1280/720.webp', data_alt='alt text stuff', data_caption='my caption'),\n", + "# LightboxItem(href='https://picsum.photos/id/101/1280/720.webp', data_alt='alt text stuff', data_caption='my caption'),\n", + "# LightboxItem(href='https://picsum.photos/id/102/1280/720.webp', data_alt='alt text stuff', data_caption='my caption'),\n", + "# ),\n", + "# height=400\n", + "# )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c6448f8", + "metadata": {}, + "outputs": [], + "source": [ + "# Show(\n", + "# LightboxContainer(\n", + "# LightboxItem(Button(\"Open\"), href='https://yootheme.com/site/images/media/yootheme-pro.mp4'),\n", + "# LightboxItem(Button(\"Open\"), href='https://www.youtube.com/watch?v=c2pz2mlSfXA'),\n", + "# LightboxItem(Button(\"Open\"), href='https://vimeo.com/1084537'),\n", + "# LightboxItem(Button(\"Open\"), data_type='iframe', href='https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d4740.819266853735!2d9.99008871708242!3d53.550454675412404!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x3f9d24afe84a0263!2sRathaus!5e0!3m2!1sde!2sde!4v1499675200938')\n", + "# ),\n", + "# height=400\n", + "# )" + ] + }, + { + "cell_type": "markdown", + "id": "b50d8270", + "metadata": {}, + "source": [ + "### Apex Charts" + ] + }, + { + "cell_type": "markdown", + "id": "626d7354", + "metadata": {}, + "source": [ + "FrankenUI supports [ApexCharts](https://franken-ui.dev/docs/2.0/chart-introduction) which is a javascript [library](https://apexcharts.com/) for rendering charts. \n", + "\n", + "ApexCharts supports many different chart types like line charts, scatter plots and bar charts. See the full list [here](https://apexcharts.com/javascript-chart-demos/).\n", + "\n", + "To render a simple line chart we need to include the ApexChart [js](https://cdn.jsdelivr.net/npm/franken-ui@2.0.0/dist/js/chart.iife.js) in our app headers and then generate the following html.\n", + "\n", + "```html\n", + "
\n", + " \n", + " \n", + " \n", + "
\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "4cab7bd6", + "metadata": {}, + "source": [ + "Let's create a simple component that will take a dictionary that describes the chart and create the html shown above." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "124849e8", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def ApexChart(*, \n", + " opts:Dict, # ApexChart options used to render your chart (e.g. {\"chart\":{\"type\":\"line\"}, ...})\n", + " cls: Enum | str | tuple = (), # Classes for the outer container\n", + " **kws, # Additional args for the outer container\n", + " )->FT: # Div(Uk_chart(Script(...)))\n", + " \"Apex chart component\"\n", + " js=NotStr(f\"\")\n", + " return Div(Uk_chart(js), cls=stringify(cls), **kws)" + ] + }, + { + "cell_type": "markdown", + "id": "4bf68297", + "metadata": {}, + "source": [ + "Let's render a simple line chart example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "08c8c968", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((uk-chart(('',),{}),),{'class': 'max-w-md max-h-md'})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "chart = ApexChart(\n", + " opts={\n", + " \"chart\": {\"type\": \"line\", \"zoom\": {\"enabled\": False}, \"toolbar\": {\"show\": False}},\n", + " \"series\":[{\"name\": \"Desktops\", \"data\": [186, 305, 237, 73, 209, 214, 355]}],\n", + " \"xaxis\": {\"categories\":[\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\"]}\n", + " },\n", + " cls='max-w-md max-h-md'\n", + ")\n", + "chart" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1158ce84", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + " " + ], + "text/plain": [ + "" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Show(chart)" + ] + }, + { + "cell_type": "markdown", + "id": "36e36f28", + "metadata": {}, + "source": [ + "To include the ApexChart js in your app headers set `apex_charts=True` like this\n", + "\n", + "`app, rt = fast_app(hdrs=Theme.blue.headers(apex_charts=True))`" + ] + }, + { + "cell_type": "markdown", + "id": "e05a5ad6", + "metadata": {}, + "source": [ + "## export -" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "909c1b2f", + "metadata": {}, + "outputs": [], + "source": [ + "#|hide\n", + "from nbdev import nbdev_export\n", + "nbdev_export()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de35d138", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "python3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/MonsterUI/nbs/03_daisy.ipynb b/MonsterUI/nbs/03_daisy.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..79e351aa7a081b64a41de33480fe7c2a34c0a987 --- /dev/null +++ b/MonsterUI/nbs/03_daisy.ipynb @@ -0,0 +1,501 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "5bfbea37", + "metadata": {}, + "source": [ + "## Daisy UI\n", + "\n", + "> Helpers and components for DaisyUI style stuff" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e3b2231", + "metadata": {}, + "outputs": [], + "source": [ + "#| default_exp daisy" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d623c13c", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "import fasthtml.common as fh\n", + "from monsterui.foundations import *\n", + "from fasthtml.common import Div, Span, FT\n", + "from fasthtml.svg import *\n", + "from enum import auto\n", + "from fastcore.all import *\n" + ] + }, + { + "cell_type": "markdown", + "id": "1c836adc", + "metadata": {}, + "source": [ + "## Alerts" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60694dc8", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class AlertT(VEnum):\n", + " \"Alert styles from DaisyUI\"\n", + " def _generate_next_value_(name, start, count, last_values): return f\"alert-{name}\"\n", + " info = auto()\n", + " success = auto()\n", + " warning = auto()\n", + " error = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2109995", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Alert(*c, # Content for Alert (often text and/or icon)\n", + " cls='', # Class for the alert (often an `AlertT` option)\n", + " **kwargs # Additional arguments for outer Div\n", + " )->FT: # Div(Span(...), cls='alert', role='alert')\n", + " \"Alert informs users about important events.\"\n", + " return Div(Span(*c), cls=('alert', stringify(cls)), role='alert', **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "d9c6a3c1", + "metadata": {}, + "source": [ + "The simplest alert is a div wrapped with a span:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b454c4c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "Hi
\n", + "\n", + "```" + ], + "text/plain": [ + "div((span(('Hi',),{}),),{'class': 'alert ', 'role': 'alert'})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Alert(\"Hi\")" + ] + }, + { + "cell_type": "markdown", + "id": "61fcb532", + "metadata": {}, + "source": [ + "Alert colors are defined by the alert styles:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d82437b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "Hi
\n", + "\n", + "```" + ], + "text/plain": [ + "div((span(('Hi',),{}),),{'class': 'alert alert-info', 'role': 'alert'})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Alert(\"Hi\", cls=AlertT.info)" + ] + }, + { + "cell_type": "markdown", + "id": "b7679070", + "metadata": {}, + "source": [ + "## Steps" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f043eaf", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class StepsT(VEnum):\n", + " \"Options for Steps\"\n", + " def _generate_next_value_(name, start, count, last_values): return f'steps-{name}'\n", + " vertical = auto()\n", + " horizonal = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c37ed9f9", + "metadata": {}, + "outputs": [], + "source": [ + "#| export \n", + "class StepT(VEnum):\n", + " 'Step styles for LiStep'\n", + " def _generate_next_value_(name, start, count, last_values): return f'step-{name}'\n", + " primary = auto()\n", + " secondary = auto()\n", + " accent = auto() \n", + " info = auto()\n", + " success = auto()\n", + " warning = auto()\n", + " error = auto()\n", + " neutral = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21a7d741", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Steps(*li, # Each `Li` represent a step (generally use `LiStep`)\n", + " cls='', # class for Steps (generally a `StepsT` option)\n", + " **kwargs # Additional args for outer wrapper (`Ul` component)\n", + " )->FT: # Ul(..., cls='steps')\n", + " \"Creates a steps container\"\n", + " return Ul(*li, cls=('steps',stringify(cls)), **kwargs)\n", + "\n", + "def LiStep(*c, # Description for Step that goes next to bubble (often text)\n", + " cls='', # Additional step classes (generally a `StepT` component)\n", + " data_content=None, # Content for inside bubble (defaults to number, often an emoji)\n", + " **kwargs # Aditional arguments for the step (`Li` component)\n", + " )->FT: # Li(..., cls='step')\n", + " \"Creates a step list item\"\n", + " return Li(*c, cls=('step', stringify(cls)), data_content=data_content, **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "28b13d70", + "metadata": {}, + "source": [ + "To create a list of steps in a process:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b89e2ef", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
    \n", + "
  • Register
  • \n", + "
  • Choose Plan
  • \n", + "
  • Purchase
  • \n", + "
  • Receive Product
  • \n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "ul((li(('Register',),{'class': 'step primary'}), li(('Choose Plan',),{'class': 'step primary'}), li(('Purchase',),{'class': 'step '}), li(('Receive Product',),{'class': 'step '})),{'class': 'steps '})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Steps(\n", + " *[LiStep(o, cls=\"primary\") for o in (\"Register\", \"Choose Plan\")],\n", + " *[LiStep(o) for o in (\"Purchase\", \"Receive Product\")]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "ff7822be", + "metadata": {}, + "source": [ + "# Loading" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5e8838cf", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class LoadingT(VEnum):\n", + " def _generate_next_value_(name, start, count, last_values): return f'loading-{name}'\n", + " spinner = auto()\n", + " dots = auto()\n", + " ring = auto()\n", + " ball = auto()\n", + " bars = auto()\n", + " infinity = auto()\n", + " \n", + " xs = 'loading-xsmall'\n", + " sm = 'loading-small'\n", + " md = 'loading-medium'\n", + " lg = 'loading-large'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7902bff", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Loading(cls=(LoadingT.bars, LoadingT.lg), # Classes for indicator (generally `LoadingT` options)\n", + " htmx_indicator=False, # Add htmx-indicator class\n", + " **kwargs # additional args for outer conainter (`Span`)\n", + " )->FT: # Span(cls=...)\n", + " \"Creates a loading animation component\"\n", + " classes = ['loading', stringify(cls)]\n", + " if htmx_indicator: classes.append('htmx-indicator')\n", + " return Span(cls=classes, **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "a7680d3b", + "metadata": {}, + "source": [ + "## Toasts" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a2c99d2e", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class ToastHT(VEnum):\n", + " \"Horizontal position for Toast\"\n", + " def _generate_next_value_(name, start, count, last_values): return f'toast-{name}'\n", + " start = auto()\n", + " center = auto()\n", + " end = auto()\n", + "\n", + "class ToastVT(VEnum):\n", + " \"Vertical position for Toast\"\n", + " def _generate_next_value_(name, start, count, last_values): return f'toast-{name}'\n", + " top = auto()\n", + " middle = auto()\n", + " bottom = auto()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c57bac21", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "def Toast(*c, # Content for toast (often test)\n", + " cls='', # Classes for toast (often `ToastHT` and `ToastVT` options)\n", + " alert_cls='', # classes for altert (often `AlertT` options)\n", + " dur=5.0, # no. of seconds before the toast disappears\n", + " **kwargs # Additional args for outer container (`Div` tag)\n", + " )->FT: # Div(Alert(...), cls='toast')\n", + " \"Toasts are stacked announcements, positioned on the corner of page.\"\n", + " a = Alert(*c, cls=alert_cls)\n", + " _id = fh.unqid()\n", + " js = '''(() => setTimeout(() => document.querySelector('[data-mui=\"%s\"]').remove(),%s))()'''%(_id,dur*1000)\n", + " return Div(a, NotStr(f\"\"), data_mui=_id, cls=('toast', stringify(cls)), **kwargs)" + ] + }, + { + "cell_type": "markdown", + "id": "2323f7ff", + "metadata": {}, + "source": [ + "*Note: We use `NotStr(f\"\")` instead of `Script(js)` to prevent the js from being escaped.*" + ] + }, + { + "cell_type": "markdown", + "id": "2ef57fd9", + "metadata": {}, + "source": [ + "To define a toast with a particular location, add horizontal or vertical toast type classes:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3747ef4b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "New message arrived.
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((div((span(('New message arrived.',),{}),),{'class': 'alert ', 'role': 'alert'}), ''),{'data-mui': '_6Hhof295QJm6E7-LMKS9BA', 'class': 'toast toast-start toast-middle'})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Toast(\"New message arrived.\", cls=(ToastHT.start, ToastVT.middle))" + ] + }, + { + "cell_type": "markdown", + "id": "cdbac191", + "metadata": {}, + "source": [ + "To define toast colors, set the class of the alert wrapped by the toast:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "824df9df", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "New message arrived.
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((div((span(('New message arrived.',),{}),),{'class': 'alert alert-info', 'role': 'alert'}), ''),{'data-mui': '_vq6iBLofRF2Rz0Z7Qqvyfg', 'class': 'toast '})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Toast(\"New message arrived.\", alert_cls=AlertT.info)" + ] + }, + { + "cell_type": "markdown", + "id": "b380807d", + "metadata": {}, + "source": [ + "Set the Toast duration to 10 seconds." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "180451d1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "```html\n", + "
\n", + "
\n", + "New message arrived.
\n", + "
\n", + "\n", + "```" + ], + "text/plain": [ + "div((div((span(('New message arrived.',),{}),),{'class': 'alert alert-info', 'role': 'alert'}), ''),{'data-mui': '_vbVi8KJdR9SQntA85v9FDw', 'class': 'toast '})" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Toast(\"New message arrived.\", alert_cls=AlertT.info, dur=10.0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1523f5e2", + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "import nbdev; nbdev.nbdev_export()" + ] + } + ], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/MonsterUI/nbs/_quarto.yml b/MonsterUI/nbs/_quarto.yml new file mode 100644 index 0000000000000000000000000000000000000000..0f069c638702d4f86459d98190cf55b22e14da20 --- /dev/null +++ b/MonsterUI/nbs/_quarto.yml @@ -0,0 +1,24 @@ +project: + type: website + resources: + - "*txt" + +format: + html: + theme: cosmo + css: styles.css + toc: true + keep-md: true + commonmark: default + +website: + twitter-card: true + open-graph: true + repo-actions: [issue] + navbar: + background: primary + search: true + sidebar: + style: floating + +metadata-files: [nbdev.yml, sidebar.yml] diff --git a/MonsterUI/nbs/logo.svg b/MonsterUI/nbs/logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..894ade8760968eba94089d83723962ef18660060 --- /dev/null +++ b/MonsterUI/nbs/logo.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MonsterUI/nbs/nbdev.yml b/MonsterUI/nbs/nbdev.yml new file mode 100644 index 0000000000000000000000000000000000000000..feee02fe4dcfbbcdfea1d30cf71b55a2ff2182df --- /dev/null +++ b/MonsterUI/nbs/nbdev.yml @@ -0,0 +1,9 @@ +project: + output-dir: _docs + +website: + title: "MonsterUI" + site-url: "https://Isaac-Flath.github.io/MonsterUI" + description: "The simplicity of FastHTML with the power of Tailwind" + repo-branch: main + repo-url: "https://github.com/Isaac-Flath/MonsterUI" diff --git a/MonsterUI/nbs/screenshot.png b/MonsterUI/nbs/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..997984e69a5ef6afa6fa58845c0f3a7ef69e731f Binary files /dev/null and b/MonsterUI/nbs/screenshot.png differ diff --git a/MonsterUI/nbs/screenshot_cropped.png b/MonsterUI/nbs/screenshot_cropped.png new file mode 100644 index 0000000000000000000000000000000000000000..7a1be618204fcc6c5a62e9a2b49dda4b4cd8692f Binary files /dev/null and b/MonsterUI/nbs/screenshot_cropped.png differ diff --git a/MonsterUI/nbs/sidebar.yml b/MonsterUI/nbs/sidebar.yml new file mode 100644 index 0000000000000000000000000000000000000000..6bb24ed0cb8c34fd288112de83078a076a9b5ec5 --- /dev/null +++ b/MonsterUI/nbs/sidebar.yml @@ -0,0 +1,7 @@ +website: + sidebar: + contents: + - index.ipynb + - 00_foundation.ipynb + - 01_core.ipynb + - 02_components.ipynb diff --git a/MonsterUI/nbs/styles.css b/MonsterUI/nbs/styles.css new file mode 100644 index 0000000000000000000000000000000000000000..66ccc49ee8f0e73901dac02dc4e9224b7d1b2c78 --- /dev/null +++ b/MonsterUI/nbs/styles.css @@ -0,0 +1,37 @@ +.cell { + margin-bottom: 1rem; +} + +.cell > .sourceCode { + margin-bottom: 0; +} + +.cell-output > pre { + margin-bottom: 0; +} + +.cell-output > pre, .cell-output > .sourceCode > pre, .cell-output-stdout > pre { + margin-left: 0.8rem; + margin-top: 0; + background: none; + border-left: 2px solid lightsalmon; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.cell-output > .sourceCode { + border: none; +} + +.cell-output > .sourceCode { + background: none; + margin-top: 0; +} + +div.description { + padding-left: 2px; + padding-top: 5px; + font-style: italic; + font-size: 135%; + opacity: 70%; +} diff --git a/MonsterUI/pyproject.toml b/MonsterUI/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..e4ad55e5d99281660373ce790e86fce2a9ba0170 --- /dev/null +++ b/MonsterUI/pyproject.toml @@ -0,0 +1,11 @@ +[build-system] +requires = ["setuptools>=64.0"] +build-backend = "setuptools.build_meta" + +[project] +name="monsterui" +requires-python=">=3.10" +dynamic = [ "keywords", "description", "version", "dependencies", "optional-dependencies", "readme", "license", "authors", "classifiers", "entry-points", "scripts", "urls"] + +[tool.uv] +cache-keys = [{ file = "pyproject.toml" }, { file = "settings.ini" }, { file = "setup.py" }] diff --git a/MonsterUI/requirements.txt b/MonsterUI/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..edc227c983306945e78578ba8a5d109c8d9c4abb --- /dev/null +++ b/MonsterUI/requirements.txt @@ -0,0 +1,3 @@ +git+https://github.com/AnswerDotAI/fasthtml.git +monsterui +uvicorn diff --git a/MonsterUI/settings.ini b/MonsterUI/settings.ini new file mode 100644 index 0000000000000000000000000000000000000000..d9806486824960a7287fb9e096b43ecaa0b13a95 --- /dev/null +++ b/MonsterUI/settings.ini @@ -0,0 +1,40 @@ +[DEFAULT] +repo = MonsterUI +lib_name = monsterui +version = 1.0.30 +min_python = 3.10 +license = apache2 +black_formatting = False +lib_path = monsterui +nbs_path = nbs +recursive = True +tst_flags = notest +put_version_in_init = True +cell_number = False +branch = main +custom_sidebar = False +doc_host = https://monsterui.answer.ai +doc_baseurl = /MonsterUI +title = MonsterUI +git_url = https://github.com/AnswerDotAI/MonsterUI +user = AnswerDotAI +audience = Developers +author = isaac flath +author_email = isaac.flath@gmail.com +copyright = 2024 onwards, isaac flath +description = The simplicity of FastHTML with the power of Tailwind +keywords = nbdev jupyter notebook python +language = English +status = 3 +requirements = python-fasthtml fastcore lxml mistletoe +dev_requirements = pandas jinja2 llms-txt pysymbol_llm +doc_path = _docs +readme_nb = index.ipynb +allowed_metadata_keys = +allowed_cell_metadata_keys = +jupyter_hooks = False +clean_ids = True +clear_all = False +skip_procs = +update_pyproject = True + diff --git a/MonsterUI/setup.py b/MonsterUI/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..e3281ae9bd7b98568e77014dba1b7b353d409205 --- /dev/null +++ b/MonsterUI/setup.py @@ -0,0 +1,57 @@ +from pkg_resources import parse_version +from configparser import ConfigParser +import setuptools, shlex +assert parse_version(setuptools.__version__)>=parse_version('36.2') + +# note: all settings are in settings.ini; edit there, not here +config = ConfigParser(delimiters=['=']) +config.read('settings.ini', encoding='utf-8') +cfg = config['DEFAULT'] + +cfg_keys = 'version description keywords author author_email'.split() +expected = cfg_keys + "lib_name user branch license status min_python audience language".split() +for o in expected: assert o in cfg, "missing expected setting: {}".format(o) +setup_cfg = {o:cfg[o] for o in cfg_keys} + +licenses = { + 'apache2': ('Apache Software License 2.0','OSI Approved :: Apache Software License'), + 'mit': ('MIT License', 'OSI Approved :: MIT License'), + 'gpl2': ('GNU General Public License v2', 'OSI Approved :: GNU General Public License v2 (GPLv2)'), + 'gpl3': ('GNU General Public License v3', 'OSI Approved :: GNU General Public License v3 (GPLv3)'), + 'bsd3': ('BSD License', 'OSI Approved :: BSD License'), +} +statuses = [ '1 - Planning', '2 - Pre-Alpha', '3 - Alpha', + '4 - Beta', '5 - Production/Stable', '6 - Mature', '7 - Inactive' ] +py_versions = '3.6 3.7 3.8 3.9 3.10'.split() + +requirements = shlex.split(cfg.get('requirements', '')) +if cfg.get('pip_requirements'): requirements += shlex.split(cfg.get('pip_requirements', '')) +min_python = cfg['min_python'] +lic = licenses.get(cfg['license'].lower(), (cfg['license'], None)) +dev_requirements = (cfg.get('dev_requirements') or '').split() + +setuptools.setup( + name = cfg['lib_name'], + license = lic[0], + classifiers = [ + 'Development Status :: ' + statuses[int(cfg['status'])], + 'Intended Audience :: ' + cfg['audience'].title(), + 'Natural Language :: ' + cfg['language'].title(), + ] + ['Programming Language :: Python :: '+o for o in py_versions[py_versions.index(min_python):]] + (['License :: ' + lic[1] ] if lic[1] else []), + url = cfg['git_url'], + packages = setuptools.find_packages(), + include_package_data = True, + install_requires = requirements, + extras_require={ 'dev': dev_requirements }, + dependency_links = cfg.get('dep_links','').split(), + python_requires = '>=' + cfg['min_python'], + long_description = open('README.md', encoding='utf-8').read(), + long_description_content_type = 'text/markdown', + zip_safe = False, + entry_points = { + 'console_scripts': cfg.get('console_scripts','').split(), + 'nbdev': [f'{cfg.get("lib_path")}={cfg.get("lib_path")}._modidx:d'] + }, + **setup_cfg) + + diff --git a/MonsterUI/testnavbar.py b/MonsterUI/testnavbar.py new file mode 100644 index 0000000000000000000000000000000000000000..42f7c6a7d2f5daa2610037a2da5413e3aedd67ac --- /dev/null +++ b/MonsterUI/testnavbar.py @@ -0,0 +1,15 @@ +from fasthtml.common import * +from monsterui.all import * +hdrs = Theme.blue.headers(mode='light') +app, rt = fast_app(hdrs=hdrs, live=True) +@rt +def index(): + return Title('Hello World'), Container( + H2(A('Pretty URL', href='', cls=AT.primary)), + P('I love monsterui!'), + A('Go to Google', href='https://google.com', cls=AT.classic), + Card('A Fancy Card :)') + ) + + +serve() \ No newline at end of file