scrollbars

This commit is contained in:
Will McGugan
2022-03-23 11:58:02 +00:00
parent 2dd362e10c
commit e8c8a5d966
10 changed files with 209 additions and 143 deletions

137
poetry.lock generated
View File

@@ -86,7 +86,7 @@ importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
name = "colorama"
version = "0.4.4"
description = "Cross-platform colored terminal text."
category = "main"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
@@ -148,7 +148,7 @@ dev = ["twine", "markdown", "flake8", "wheel"]
[[package]]
name = "identify"
version = "2.4.11"
version = "2.4.12"
description = "File identification library for Python"
category = "dev"
optional = false
@@ -159,7 +159,7 @@ license = ["ukkonen"]
[[package]]
name = "importlib-metadata"
version = "4.11.1"
version = "4.11.3"
description = "Read metadata from Python packages"
category = "dev"
optional = false
@@ -170,7 +170,7 @@ typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
zipp = ">=0.5"
[package.extras]
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
perf = ["ipython"]
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
@@ -212,7 +212,7 @@ testing = ["coverage", "pyyaml"]
[[package]]
name = "markupsafe"
version = "2.1.0"
version = "2.1.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "dev"
optional = false
@@ -251,15 +251,15 @@ i18n = ["babel (>=2.9.0)"]
[[package]]
name = "mkdocs-autorefs"
version = "0.3.1"
version = "0.4.1"
description = "Automatically link across pages in MkDocs."
category = "dev"
optional = false
python-versions = ">=3.6.2,<4.0.0"
python-versions = ">=3.7"
[package.dependencies]
Markdown = ">=3.3,<4.0"
mkdocs = ">=1.1,<2.0"
Markdown = ">=3.3"
mkdocs = ">=1.1"
[[package]]
name = "mkdocs-material"
@@ -417,7 +417,7 @@ python-versions = ">=3.5"
[[package]]
name = "pymdown-extensions"
version = "9.2"
version = "9.3"
description = "Extension pack for Python Markdown."
category = "dev"
optional = false
@@ -488,7 +488,7 @@ six = ">=1.5"
[[package]]
name = "pytkdocs"
version = "0.16.0"
version = "0.16.1"
description = "Load Python objects documentation."
category = "dev"
optional = false
@@ -523,14 +523,13 @@ pyyaml = "*"
[[package]]
name = "rich"
version = "11.2.0"
version = "12.0.1"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
category = "main"
optional = false
python-versions = ">=3.6.2,<4.0.0"
[package.dependencies]
colorama = ">=0.4.0,<0.5.0"
commonmark = ">=0.9.0,<0.10.0"
pygments = ">=2.6.0,<3.0.0"
typing-extensions = {version = ">=3.7.4,<5.0", markers = "python_version < \"3.8\""}
@@ -580,7 +579,7 @@ python-versions = "*"
[[package]]
name = "virtualenv"
version = "20.13.2"
version = "20.13.4"
description = "Virtual Python Environment builder"
category = "dev"
optional = false
@@ -623,7 +622,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-
[metadata]
lock-version = "1.1"
python-versions = "^3.7"
content-hash = "017cd9bd80c2432f3de493d190c162e98894d9bb1db0482502658e2bc9231887"
content-hash = "eedcff99ec01738d19c46511b2eac155bfdbf94796526565d14a5ef762108cfd"
[metadata.files]
astunparse = [
@@ -739,12 +738,12 @@ ghp-import = [
{file = "ghp_import-2.0.2-py3-none-any.whl", hash = "sha256:5f8962b30b20652cdffa9c5a9812f7de6bcb56ec475acac579807719bf242c46"},
]
identify = [
{file = "identify-2.4.11-py2.py3-none-any.whl", hash = "sha256:fd906823ed1db23c7a48f9b176a1d71cb8abede1e21ebe614bac7bdd688d9213"},
{file = "identify-2.4.11.tar.gz", hash = "sha256:2986942d3974c8f2e5019a190523b0b0e2a07cb8e89bf236727fb4b26f27f8fd"},
{file = "identify-2.4.12-py2.py3-none-any.whl", hash = "sha256:5f06b14366bd1facb88b00540a1de05b69b310cbc2654db3c7e07fa3a4339323"},
{file = "identify-2.4.12.tar.gz", hash = "sha256:3f3244a559290e7d3deb9e9adc7b33594c1bc85a9dd82e0f1be519bf12a1ec17"},
]
importlib-metadata = [
{file = "importlib_metadata-4.11.1-py3-none-any.whl", hash = "sha256:e0bc84ff355328a4adfc5240c4f211e0ab386f80aa640d1b11f0618a1d282094"},
{file = "importlib_metadata-4.11.1.tar.gz", hash = "sha256:175f4ee440a0317f6e8d81b7f8d4869f93316170a65ad2b007d2929186c8052c"},
{file = "importlib_metadata-4.11.3-py3-none-any.whl", hash = "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6"},
{file = "importlib_metadata-4.11.3.tar.gz", hash = "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"},
]
iniconfig = [
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
@@ -759,46 +758,46 @@ markdown = [
{file = "Markdown-3.3.6.tar.gz", hash = "sha256:76df8ae32294ec39dcf89340382882dfa12975f87f45c3ed1ecdb1e8cefc7006"},
]
markupsafe = [
{file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3028252424c72b2602a323f70fbf50aa80a5d3aa616ea6add4ba21ae9cc9da4c"},
{file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:290b02bab3c9e216da57c1d11d2ba73a9f73a614bbdcc027d299a60cdfabb11a"},
{file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e104c0c2b4cd765b4e83909cde7ec61a1e313f8a75775897db321450e928cce"},
{file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24c3be29abb6b34052fd26fc7a8e0a49b1ee9d282e3665e8ad09a0a68faee5b3"},
{file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204730fd5fe2fe3b1e9ccadb2bd18ba8712b111dcabce185af0b3b5285a7c989"},
{file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d3b64c65328cb4cd252c94f83e66e3d7acf8891e60ebf588d7b493a55a1dbf26"},
{file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:96de1932237abe0a13ba68b63e94113678c379dca45afa040a17b6e1ad7ed076"},
{file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75bb36f134883fdbe13d8e63b8675f5f12b80bb6627f7714c7d6c5becf22719f"},
{file = "MarkupSafe-2.1.0-cp310-cp310-win32.whl", hash = "sha256:4056f752015dfa9828dce3140dbadd543b555afb3252507348c493def166d454"},
{file = "MarkupSafe-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:d4e702eea4a2903441f2735799d217f4ac1b55f7d8ad96ab7d4e25417cb0827c"},
{file = "MarkupSafe-2.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f0eddfcabd6936558ec020130f932d479930581171368fd728efcfb6ef0dd357"},
{file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddea4c352a488b5e1069069f2f501006b1a4362cb906bee9a193ef1245a7a61"},
{file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09c86c9643cceb1d87ca08cdc30160d1b7ab49a8a21564868921959bd16441b8"},
{file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0a0abef2ca47b33fb615b491ce31b055ef2430de52c5b3fb19a4042dbc5cadb"},
{file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:736895a020e31b428b3382a7887bfea96102c529530299f426bf2e636aacec9e"},
{file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:679cbb78914ab212c49c67ba2c7396dc599a8479de51b9a87b174700abd9ea49"},
{file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:84ad5e29bf8bab3ad70fd707d3c05524862bddc54dc040982b0dbcff36481de7"},
{file = "MarkupSafe-2.1.0-cp37-cp37m-win32.whl", hash = "sha256:8da5924cb1f9064589767b0f3fc39d03e3d0fb5aa29e0cb21d43106519bd624a"},
{file = "MarkupSafe-2.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:454ffc1cbb75227d15667c09f164a0099159da0c1f3d2636aa648f12675491ad"},
{file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:142119fb14a1ef6d758912b25c4e803c3ff66920635c44078666fe7cc3f8f759"},
{file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b2a5a856019d2833c56a3dcac1b80fe795c95f401818ea963594b345929dffa7"},
{file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d1fb9b2eec3c9714dd936860850300b51dbaa37404209c8d4cb66547884b7ed"},
{file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62c0285e91414f5c8f621a17b69fc0088394ccdaa961ef469e833dbff64bd5ea"},
{file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc3150f85e2dbcf99e65238c842d1cfe69d3e7649b19864c1cc043213d9cd730"},
{file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f02cf7221d5cd915d7fa58ab64f7ee6dd0f6cddbb48683debf5d04ae9b1c2cc1"},
{file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5653619b3eb5cbd35bfba3c12d575db2a74d15e0e1c08bf1db788069d410ce8"},
{file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d2f5d97fcbd004c03df8d8fe2b973fe2b14e7bfeb2cfa012eaa8759ce9a762f"},
{file = "MarkupSafe-2.1.0-cp38-cp38-win32.whl", hash = "sha256:3cace1837bc84e63b3fd2dfce37f08f8c18aeb81ef5cf6bb9b51f625cb4e6cd8"},
{file = "MarkupSafe-2.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:fabbe18087c3d33c5824cb145ffca52eccd053061df1d79d4b66dafa5ad2a5ea"},
{file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:023af8c54fe63530545f70dd2a2a7eed18d07a9a77b94e8bf1e2ff7f252db9a3"},
{file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d66624f04de4af8bbf1c7f21cc06649c1c69a7f84109179add573ce35e46d448"},
{file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c532d5ab79be0199fa2658e24a02fce8542df196e60665dd322409a03db6a52c"},
{file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ec74fada3841b8c5f4c4f197bea916025cb9aa3fe5abf7d52b655d042f956"},
{file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c653fde75a6e5eb814d2a0a89378f83d1d3f502ab710904ee585c38888816c"},
{file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:961eb86e5be7d0973789f30ebcf6caab60b844203f4396ece27310295a6082c7"},
{file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:598b65d74615c021423bd45c2bc5e9b59539c875a9bdb7e5f2a6b92dfcfc268d"},
{file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:599941da468f2cf22bf90a84f6e2a65524e87be2fce844f96f2dd9a6c9d1e635"},
{file = "MarkupSafe-2.1.0-cp39-cp39-win32.whl", hash = "sha256:e6f7f3f41faffaea6596da86ecc2389672fa949bd035251eab26dc6697451d05"},
{file = "MarkupSafe-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:b8811d48078d1cf2a6863dafb896e68406c5f513048451cd2ded0473133473c7"},
{file = "MarkupSafe-2.1.0.tar.gz", hash = "sha256:80beaf63ddfbc64a0452b841d8036ca0611e049650e20afcb882f5d3c266d65f"},
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
{file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
{file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
{file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
{file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
{file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
{file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
{file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
]
mergedeep = [
{file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"},
@@ -809,8 +808,8 @@ mkdocs = [
{file = "mkdocs-1.2.3.tar.gz", hash = "sha256:89f5a094764381cda656af4298727c9f53dc3e602983087e1fe96ea1df24f4c1"},
]
mkdocs-autorefs = [
{file = "mkdocs-autorefs-0.3.1.tar.gz", hash = "sha256:12baad29359f468b44d980ed35b713715409097a1d8e3d0ef90962db95205eda"},
{file = "mkdocs_autorefs-0.3.1-py3-none-any.whl", hash = "sha256:f0fd7c115eaafda7fb16bf5ff5d70eda55d7c0599eac64f8b25eacf864312a85"},
{file = "mkdocs-autorefs-0.4.1.tar.gz", hash = "sha256:70748a7bd025f9ecd6d6feeba8ba63f8e891a1af55f48e366d6d6e78493aba84"},
{file = "mkdocs_autorefs-0.4.1-py3-none-any.whl", hash = "sha256:a2248a9501b29dc0cc8ba4c09f4f47ff121945f6ce33d760f145d6f89d313f5b"},
]
mkdocs-material = [
{file = "mkdocs-material-7.3.6.tar.gz", hash = "sha256:1b1dbd8ef2508b358d93af55a5c5db3f141c95667fad802301ec621c40c7c217"},
@@ -883,8 +882,8 @@ pygments = [
{file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"},
]
pymdown-extensions = [
{file = "pymdown-extensions-9.2.tar.gz", hash = "sha256:ed8f69a18bc158f00cbf03abc536b88b6e541b7e699156501e767c48f81d8850"},
{file = "pymdown_extensions-9.2-py3-none-any.whl", hash = "sha256:f2fa7d9317c672a419868c893c20a28fb7ed7fc60d4ec4774c35e01398ab330c"},
{file = "pymdown-extensions-9.3.tar.gz", hash = "sha256:a80553b243d3ed2d6c27723bcd64ca9887e560e6f4808baa96f36e93061eaf90"},
{file = "pymdown_extensions-9.3-py3-none-any.whl", hash = "sha256:b37461a181c1c8103cfe1660081726a0361a8294cbfda88e5b02cefe976f0546"},
]
pyparsing = [
{file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
@@ -903,8 +902,8 @@ python-dateutil = [
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
]
pytkdocs = [
{file = "pytkdocs-0.16.0-py3-none-any.whl", hash = "sha256:098405ff347797cfb887a4d78f161372109bfbfffa0f8ee8daa5e2b8a8caba4b"},
{file = "pytkdocs-0.16.0.tar.gz", hash = "sha256:274407bcefec58d7e411adb03b84da49120107912b1697d17d4a3aea0583f388"},
{file = "pytkdocs-0.16.1-py3-none-any.whl", hash = "sha256:a8c3f46ecef0b92864cc598e9101e9c4cf832ebbf228f50c84aa5dd850aac379"},
{file = "pytkdocs-0.16.1.tar.gz", hash = "sha256:e2ccf6dfe9dbbceb09818673f040f1a7c32ed0bffb2d709b06be6453c4026045"},
]
pyyaml = [
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
@@ -946,8 +945,8 @@ pyyaml-env-tag = [
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
]
rich = [
{file = "rich-11.2.0-py3-none-any.whl", hash = "sha256:d5f49ad91fb343efcae45a2b2df04a9755e863e50413623ab8c9e74f05aee52b"},
{file = "rich-11.2.0.tar.gz", hash = "sha256:1a6266a5738115017bb64a66c59c717e7aa047b3ae49a011ede4abdeffc6536e"},
{file = "rich-12.0.1-py3-none-any.whl", hash = "sha256:ce5c714e984a2d185399e4e1dd1f8b2feacb7cecfc576f1522425643a36a57ea"},
{file = "rich-12.0.1.tar.gz", hash = "sha256:3fba9dd15ebe048e2795a02ac19baee79dc12cc50b074ef70f2958cd651b59a9"},
]
six = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
@@ -993,8 +992,8 @@ typing-extensions = [
{file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"},
]
virtualenv = [
{file = "virtualenv-20.13.2-py2.py3-none-any.whl", hash = "sha256:e7b34c9474e6476ee208c43a4d9ac1510b041c68347eabfe9a9ea0c86aa0a46b"},
{file = "virtualenv-20.13.2.tar.gz", hash = "sha256:01f5f80744d24a3743ce61858123488e91cb2dd1d3bdf92adaf1bba39ffdedf0"},
{file = "virtualenv-20.13.4-py2.py3-none-any.whl", hash = "sha256:c3e01300fb8495bc00ed70741f5271fc95fed067eb7106297be73d30879af60c"},
{file = "virtualenv-20.13.4.tar.gz", hash = "sha256:ce8901d3bbf3b90393498187f2d56797a8a452fb2d0d7efc6fd837554d6f679c"},
]
watchdog = [
{file = "watchdog-2.1.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9693f35162dc6208d10b10ddf0458cc09ad70c30ba689d9206e02cd836ce28a3"},

View File

@@ -19,7 +19,7 @@ classifiers = [
[tool.poetry.dependencies]
python = "^3.7"
rich = "^11.2.0"
rich = "^12.0.0"
#rich = {git = "git@github.com:willmcgugan/rich", rev = "link-id"}
typing-extensions = { version = "^3.10.0", python = "<3.8" }

View File

@@ -3,7 +3,7 @@
layout: vertical;
text: on dark_green;
overflow: auto auto;
border: heavy white;
/*border: heavy white;*/
}
.list-item {

View File

@@ -26,7 +26,7 @@ class BasicApp(App):
Placeholder(id="child2", classes={"list-item"}),
Placeholder(id="child3", classes={"list-item"}),
Placeholder(classes={"list-item"}),
Placeholder(classes={"list-item"}),
# Placeholder(classes={"list-item"}),
# Placeholder(classes={"list-item"}),
# Placeholder(classes={"list-item"}),
# Placeholder(classes={"list-item"}),

View File

@@ -44,6 +44,7 @@ class RenderRegion(NamedTuple):
order: tuple[int, ...]
clip: Region
virtual_size: Size
container_size: Size
RenderRegionMap: TypeAlias = "dict[Widget, RenderRegion]"
@@ -155,7 +156,8 @@ class Compositor:
# Copy renders if the size hasn't changed
new_renders = {
widget: (region, clip) for widget, (region, _order, clip, _) in map.items()
widget: (region, clip)
for widget, (region, _order, clip, _, _) in map.items()
}
self.regions = new_renders
@@ -196,7 +198,6 @@ class Compositor:
) -> None:
widget.pre_render()
widgets.add(widget)
total_region = region
styles_offset = widget.styles.offset
layout_offset = (
styles_offset.resolve(region.size, clip.size)
@@ -210,7 +211,9 @@ class Compositor:
# Container region is minus border
container_region = region.shrink(widget.styles.gutter)
# The region that contains the content (container region minus scrollbars)
child_region = widget._arrange_container(container_region)
sub_clip = clip.intersection(child_region)
total_region = child_region.reset_origin
@@ -231,6 +234,14 @@ class Compositor:
sub_clip,
)
map[widget] = RenderRegion(
child_region + layout_offset,
order,
sub_clip,
total_region.size,
container_region.size,
)
for chrome_widget, chrome_region in widget._arrange_scrollbars(
container_region.size
):
@@ -239,11 +250,18 @@ class Compositor:
order,
clip,
chrome_region.size,
chrome_region.size,
)
map[widget] = RenderRegion(
region + layout_offset, order, clip, total_region.size
)
else:
map[widget] = RenderRegion(
region + layout_offset,
order,
clip,
region.size,
region.size,
)
add_widget(root, size.region, (), size.region)
@@ -252,11 +270,17 @@ class Compositor:
async def mount_all(self, screen: Screen) -> None:
screen.app.mount(*self.widgets)
def __iter__(self) -> Iterator[tuple[Widget, Region, Region, Size]]:
def __iter__(self) -> Iterator[tuple[Widget, Region, Region, Size, Size]]:
layers = sorted(self.map.items(), key=lambda item: item[1].order, reverse=True)
intersection = Region.intersection
for widget, (region, _order, clip, virtual_size) in layers:
yield widget, intersection(region, clip), region, virtual_size
for widget, (region, _order, clip, virtual_size, container_size) in layers:
yield (
widget,
intersection(region, clip),
region,
virtual_size,
container_size,
)
def get_offset(self, widget: Widget) -> Offset:
"""Get the offset of a widget."""
@@ -268,7 +292,7 @@ class Compositor:
def get_widget_at(self, x: int, y: int) -> tuple[Widget, Region]:
"""Get the widget under the given point or None."""
contains = Region.contains
for widget, cropped_region, region, _ in self:
for widget, cropped_region, region, *_ in self:
if contains(cropped_region, x, y):
return widget, region
raise errors.NoWidget(f"No widget under screen coordinate ({x}, {y})")
@@ -341,7 +365,7 @@ class Compositor:
intersection = Region.intersection
extend = list.extend
for region, order, clip, _ in self.map.values():
for region, order, clip, _, _ in self.map.values():
region = intersection(region, clip)
if region and (region in screen_region):
x, y, region_width, region_height = region
@@ -367,7 +391,7 @@ class Compositor:
widget_regions = sorted(
[
(widget, region, order, clip)
for widget, (region, order, clip, _) in self.map.items()
for widget, (region, order, clip, _, _) in self.map.items()
if widget.visible and not widget.is_transparent
],
key=itemgetter(2),
@@ -479,6 +503,7 @@ class Compositor:
render_lines = self._assemble_chops(chops[crop_y:crop_y2])
def width_view(line: list[Segment]) -> list[Segment]:
if line:
div_lines = list(divide(line, [crop_x, crop_x2]))
line = div_lines[1] if len(div_lines) > 1 else div_lines[0]

View File

@@ -90,7 +90,13 @@ class Resize(Event, verbosity=2, bubble=False):
__slots__ = ["size"]
size: Size
def __init__(self, sender: MessageTarget, size: Size, virtual_size: Size) -> None:
def __init__(
self,
sender: MessageTarget,
size: Size,
virtual_size: Size,
container_size: Size | None = None,
) -> None:
"""
Args:
sender (MessageTarget): Event sender.
@@ -99,6 +105,7 @@ class Resize(Event, verbosity=2, bubble=False):
"""
self.size = size
self.virtual_size = virtual_size
self.container_size = size if container_size is None else container_size
super().__init__(sender)
def can_replace(self, message: "Message") -> bool:
@@ -107,6 +114,7 @@ class Resize(Event, verbosity=2, bubble=False):
def __rich_repr__(self) -> rich.repr.Result:
yield "size", self.size
yield "virtual_size", self.virtual_size
yield "container_size", self.container_size, self.size
class Mount(Event, bubble=False):

View File

@@ -57,7 +57,7 @@ class Reactive(Generic[ReactiveType]):
computes.append(name)
self.name = name
self.internal_name = f"__{name}"
self.internal_name = f"_reactive_{name}"
setattr(owner, self.internal_name, self._default)
def __get__(self, obj: Reactable, obj_type: type[object]) -> ReactiveType:
@@ -85,7 +85,7 @@ class Reactive(Generic[ReactiveType]):
@classmethod
def check_watchers(cls, obj: Reactable, name: str, old_value: Any) -> None:
internal_name = f"__{name}"
internal_name = f"_reactive_{name}"
value = getattr(obj, internal_name)
async def update_watcher(

View File

@@ -100,11 +100,19 @@ class Screen(Widget):
send_resize = shown | resized
for widget, region, unclipped_region, virtual_size in self._compositor:
widget.size_updated(unclipped_region.size, virtual_size)
for (
widget,
region,
unclipped_region,
virtual_size,
container_size,
) in self._compositor:
widget.size_updated(unclipped_region.size, virtual_size, container_size)
if widget in send_resize:
widget.post_message_no_wait(
events.Resize(self, unclipped_region.size, virtual_size)
events.Resize(
self, unclipped_region.size, virtual_size, container_size
)
)
except Exception:
@@ -126,7 +134,7 @@ class Screen(Widget):
await self.refresh_layout()
async def on_resize(self, event: events.Resize) -> None:
self.size_updated(event.size, event.virtual_size)
self.size_updated(event.size, event.virtual_size, event.container_size)
await self.refresh_layout()
event.stop()

View File

@@ -80,6 +80,7 @@ class Widget(DOMNode):
self._size = Size(0, 0)
self._virtual_size = Size(0, 0)
self._container_size = Size(0, 0)
self._repaint_required = False
self._layout_required = False
self._animate: BoundAnimator | None = None
@@ -123,11 +124,11 @@ class Widget(DOMNode):
@property
def max_scroll_x(self) -> float:
return max(0, self.virtual_size.width - self.scroll_size.width)
return max(0, self.virtual_size.width - self.size.width)
@property
def max_scroll_y(self) -> float:
return max(0, self.virtual_size.height - self.scroll_size.height)
return max(0, self.virtual_size.height - self.size.height)
@property
def vscroll(self) -> ScrollBar:
@@ -168,33 +169,40 @@ class Widget(DOMNode):
"""Refresh scrollbar visibility."""
if not self.is_container:
return
styles = self.styles
overflow_x = styles.overflow_x
overflow_y = styles.overflow_y
width, height = self.scroll_size
width, height = self.container_size
show_horizontal = self.show_horizontal_scrollbar
if overflow_x == "hidden":
self.show_horizontal_scrollbar = False
elif overflow_x == "scroll":
self.show_horizontal_scrollbar = True
show_horizontal = False
if overflow_x == "scroll":
show_horizontal = True
elif overflow_x == "auto":
self.show_horizontal_scrollbar = self.virtual_size.width > width
# height -= self.show_horizontal_scrollbar
show_horizontal = self.virtual_size.width > width
show_vertical = self.show_vertical_scrollbar
if overflow_y == "hidden":
self.show_vertical_scrollbar = False
show_vertical = False
elif overflow_y == "scroll":
self.show_vertical_scrollbar = True
show_vertical = True
elif overflow_y == "auto":
self.show_vertical_scrollbar = self.virtual_size.height > height
show_vertical = self.virtual_size.height > height
self.show_horizontal_scrollbar = show_horizontal
self.show_vertical_scrollbar = show_vertical
self.log(
"REFRESH_SCROLLBARS",
self,
self.virtual_size,
self.scroll_size,
widget=self,
virtual_size=self.virtual_size,
size=self.size,
container_size=self.container_size,
)
# return changed
@property
def scrollbars_enabled(self) -> tuple[bool, bool]:
@@ -206,7 +214,10 @@ class Widget(DOMNode):
"""
if self.layout is None:
return False, False
return self.show_vertical_scrollbar, self.show_horizontal_scrollbar
enabled = self.show_vertical_scrollbar, self.show_horizontal_scrollbar
self.log(enabled)
return enabled
def scroll_to(
self,
@@ -266,20 +277,16 @@ class Widget(DOMNode):
self.scroll_to(y=self.scroll_target_y - 1.5, animate=animate)
def scroll_page_up(self, animate: bool = True) -> None:
self.scroll_to(
y=self.scroll_target_y - self.scroll_size.height, animate=animate
)
self.scroll_to(y=self.scroll_target_y - self.size.height, animate=animate)
def scroll_page_down(self, animate: bool = True) -> None:
self.scroll_to(
y=self.scroll_target_y + self.scroll_size.height, animate=animate
)
self.scroll_to(y=self.scroll_target_y + self.size.height, animate=animate)
def scroll_page_left(self, animate: bool = True) -> None:
self.scroll_to(x=self.scroll_target_x - self.scroll_size.width, animate=animate)
self.scroll_to(x=self.scroll_target_x - self.size.width, animate=animate)
def scroll_page_right(self, animate: bool = True) -> None:
self.scroll_to(x=self.scroll_target_x + self.scroll_size.width, animate=animate)
self.scroll_to(x=self.scroll_target_x + self.size.width, animate=animate)
def __init_subclass__(cls, can_focus: bool = True) -> None:
super().__init_subclass__()
@@ -296,21 +303,21 @@ class Widget(DOMNode):
yield "pseudo_classes", set(pseudo_classes)
def _arrange_container(self, region: Region) -> Region:
"""Adjusts the Windget region to accomodate scrollbars.
Args:
region (Region): A region for the widget.
Returns:
Region: The widget region minus scrollbars.
"""
show_vertical_scrollbar, show_horizontal_scrollbar = self.scrollbars_enabled
# self.log(self.styles.gutter)
# region = region.shrink(self.styles.gutter)
if show_horizontal_scrollbar and show_vertical_scrollbar:
(region, _, _, _) = region.split(-1, -1)
return region
elif show_vertical_scrollbar:
region, _ = region.split_vertical(-1)
return region
elif show_horizontal_scrollbar:
region, _ = region.split_horizontal(-1)
return region
return region
def _arrange_scrollbars(self, size: Size) -> Iterable[tuple[Widget, Region]]:
@@ -335,7 +342,6 @@ class Widget(DOMNode):
horizontal_scrollbar_region,
_,
) = region.split(-1, -1)
if vertical_scrollbar_region:
yield self.vscroll, vertical_scrollbar_region
if horizontal_scrollbar_region:
@@ -412,10 +418,8 @@ class Widget(DOMNode):
return self._size
@property
def scroll_size(self) -> Size:
scroll_size = self._size - self.styles.gutter.totals
scroll_size -= (self.show_vertical_scrollbar, self.show_horizontal_scrollbar)
return scroll_size
def container_size(self) -> Size:
return self._container_size
@property
def virtual_size(self) -> Size:
@@ -474,24 +478,32 @@ class Widget(DOMNode):
def on_style_change(self) -> None:
self.clear_render_cache()
def size_updated(self, size: Size, virtual_size: Size) -> None:
def size_updated(
self, size: Size, virtual_size: Size, container_size: Size
) -> None:
if self._size != size or self._virtual_size != virtual_size:
self._size = size
self._virtual_size = virtual_size
# self._refresh_scrollbars()
width, height = self.scroll_size
if self.show_vertical_scrollbar:
self.vscroll.window_virtual_size = virtual_size.height
self.vscroll.window_size = height
self.vscroll.refresh()
if self.show_horizontal_scrollbar:
self.hscroll.window_virtual_size = virtual_size.width
self.hscroll.window_size = width
self.hscroll.refresh()
self._container_size = container_size
self.scroll_to(self.scroll_x, self.scroll_y)
self.refresh()
self.call_later(self._refresh_scrollbars)
if self.is_container:
width, height = self.container_size
if self.show_vertical_scrollbar:
self.vscroll.window_virtual_size = virtual_size.height
self.vscroll.window_size = height
self.vscroll.refresh()
if self.show_horizontal_scrollbar:
self.hscroll.window_virtual_size = virtual_size.width
self.hscroll.window_size = width
self.hscroll.refresh()
# self.scroll_to(self.scroll_x, self.scroll_y)
self.refresh(layout=True)
self._refresh_scrollbars()
self.call_later(self.scroll_to, 0, 0)
# self.call_later(self._refresh_scrollbars)
else:
self.refresh()
def render_lines(self) -> None:
width, height = self.size
@@ -513,9 +525,11 @@ class Widget(DOMNode):
self.render_cache = None
def check_repaint(self) -> bool:
"""Check if a repaint has been requested."""
return self._repaint_required
def check_layout(self) -> bool:
"""Check if a layout has been requested."""
return self._layout_required
def reset_check_repaint(self) -> None:
@@ -580,10 +594,17 @@ class Widget(DOMNode):
return await super().post_message(message)
# async def on_resize(self, event: events.Resize) -> None:
# self.size_updated(event.size, event.virtual_size)
# self.size_updated(event.size, event.virtual_size, event.container_size)
async def on_idle(self, event: events.Idle) -> None:
"""Called when there are no more events on the queue.
Args:
event (events.Idle): Idle event.
"""
# Check if the styles have chained
repaint, layout = self.styles.check_refresh()
if layout or self.check_layout():
# self.render_cache = None
self.reset_check_repaint()

View File

@@ -7,13 +7,18 @@ from rich.panel import Panel
from rich.pretty import Pretty
import rich.repr
from logging import getLogger
from .. import log
from .. import events
from ..reactive import Reactive
from ..widget import Widget
log = getLogger("rich")
class TPanel(Panel):
def __rich_console__(self, console, options):
log("*", options)
return super().__rich_console__(console, options)
@rich.repr.auto(angular=False)
@@ -29,7 +34,7 @@ class Placeholder(Widget, can_focus=True):
yield "mouse_over", self.mouse_over, False
def render(self) -> RenderableType:
return Panel(
return TPanel(
Align.center(
Pretty(self, no_wrap=True, overflow="ellipsis"), vertical="middle"
),