Box 1
+This is the content for box 1.
+Box 2
+This is the content for box 2.
+Box 3
+This is the content for box 3.
+diff --git a/Dockerfile b/Dockerfile index 8dc8d02ece8f3e90685e76e6642625fe0b0a72c4..15913fd209baf09c441cef89bdd7ee31755868fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.10.14-bullseye +FROM python:3.10.15-bullseye RUN apt-get update && \ apt-get install -y \ diff --git a/__pycache__/autocomplete.cpython-310.pyc b/__pycache__/autocomplete.cpython-310.pyc index 33303752d306e05a45bcc5b93e1e72ac62ac94a9..bfccee199477353cec4a8b146a1884c08713d063 100644 Binary files a/__pycache__/autocomplete.cpython-310.pyc and b/__pycache__/autocomplete.cpython-310.pyc differ diff --git a/__pycache__/bootstrap.cpython-310.pyc b/__pycache__/bootstrap.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..01e81277e470fb4a2810cd5d6e789e6e91d4f136 Binary files /dev/null and b/__pycache__/bootstrap.cpython-310.pyc differ diff --git a/__pycache__/button_toggle.cpython-310.pyc b/__pycache__/button_toggle.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..835764024ea7b5fe873a7bfa4f1f652629afd50f Binary files /dev/null and b/__pycache__/button_toggle.cpython-310.pyc differ diff --git a/__pycache__/card.cpython-310.pyc b/__pycache__/card.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..11f40d73fe98549284dfea1050c605a34af3fecf Binary files /dev/null and b/__pycache__/card.cpython-310.pyc differ diff --git a/__pycache__/chat.cpython-310.pyc b/__pycache__/chat.cpython-310.pyc index b47712fa389324cf4dd5cb7bd7b487850ada04f0..49f3df2a9e3a9e79200134a843a4a0782a40a71d 100644 Binary files a/__pycache__/chat.cpython-310.pyc and b/__pycache__/chat.cpython-310.pyc differ diff --git a/__pycache__/date_picker.cpython-310.pyc b/__pycache__/date_picker.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d482bb209ae8de29af2bd25e20bfff68f4e379c2 Binary files /dev/null and b/__pycache__/date_picker.cpython-310.pyc differ diff --git a/__pycache__/date_range_picker.cpython-310.pyc b/__pycache__/date_range_picker.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6588ef07f6b20daf538e5c0c74243f39a89da14d Binary files /dev/null and b/__pycache__/date_range_picker.cpython-310.pyc differ diff --git a/__pycache__/expansion_panel.cpython-310.pyc b/__pycache__/expansion_panel.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4bf80faa121108d9d1df1fd271e1a1e5785b2e74 Binary files /dev/null and b/__pycache__/expansion_panel.cpython-310.pyc differ diff --git a/__pycache__/grid_table.cpython-310.pyc b/__pycache__/grid_table.cpython-310.pyc index 5734efb63840e0b5cf26531960363c53d214109b..8498670c460392759d43d0051aafc67953baddb8 100644 Binary files a/__pycache__/grid_table.cpython-310.pyc and b/__pycache__/grid_table.cpython-310.pyc differ diff --git a/__pycache__/input.cpython-310.pyc b/__pycache__/input.cpython-310.pyc index 80fd6b6cdaf7e8e673e4eb723fc325762d17e1da..69d829b62f376f96bd96aeb6d90e797b51771794 100644 Binary files a/__pycache__/input.cpython-310.pyc and b/__pycache__/input.cpython-310.pyc differ diff --git a/__pycache__/llm_rewriter.cpython-310.pyc b/__pycache__/llm_rewriter.cpython-310.pyc index 4b53c362be4bfd3e9a5223e58709f1283ef07346..bda41763da426abc2eea09d8e3b9f8e2de1cc8a6 100644 Binary files a/__pycache__/llm_rewriter.cpython-310.pyc and b/__pycache__/llm_rewriter.cpython-310.pyc differ diff --git a/__pycache__/main.cpython-310.pyc b/__pycache__/main.cpython-310.pyc index 4ce10055951209669edbf992d6ac6feb2bfe50aa..760162cade85b6d271806030cdf5e3a2a5381820 100644 Binary files a/__pycache__/main.cpython-310.pyc and b/__pycache__/main.cpython-310.pyc differ diff --git a/__pycache__/markdown_demo.cpython-310.pyc b/__pycache__/markdown_demo.cpython-310.pyc index edbd09658b94c12612c1b8a857d56fbfbf9fe5df..ed88572435c7b725b7128bfd0984ebb848b93513 100644 Binary files a/__pycache__/markdown_demo.cpython-310.pyc and b/__pycache__/markdown_demo.cpython-310.pyc differ diff --git a/__pycache__/select_demo.cpython-310.pyc b/__pycache__/select_demo.cpython-310.pyc index b6b9aec8b47211bbea34825a80a0bfb70c2f5863..29fc78a77fc32dd1e3fadcc76644545f8847cdd9 100644 Binary files a/__pycache__/select_demo.cpython-310.pyc and b/__pycache__/select_demo.cpython-310.pyc differ diff --git a/__pycache__/sidenav.cpython-310.pyc b/__pycache__/sidenav.cpython-310.pyc index e8264e285d7c6dae4e959ba2c23fa3af40aabae1..badf7dfe9b343571a79968663821d9aff0b146de 100644 Binary files a/__pycache__/sidenav.cpython-310.pyc and b/__pycache__/sidenav.cpython-310.pyc differ diff --git a/__pycache__/tailwind.cpython-310.pyc b/__pycache__/tailwind.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a5f4b140766a7a7ed53e39bd0ead2ae1a1d4c852 Binary files /dev/null and b/__pycache__/tailwind.cpython-310.pyc differ diff --git a/__pycache__/text.cpython-310.pyc b/__pycache__/text.cpython-310.pyc index d55c2b4b6c6483b58a799d929731bc27b32e7e4c..adef4deecb7866cda6c73c0a3150942266b83dc8 100644 Binary files a/__pycache__/text.cpython-310.pyc and b/__pycache__/text.cpython-310.pyc differ diff --git a/__pycache__/text_to_image.cpython-310.pyc b/__pycache__/text_to_image.cpython-310.pyc index e46dfdc168989c24c1dad99e864b7025a2de63b1..cc0a3f41fe3196de8bddea14c5b6282da7bd9cd4 100644 Binary files a/__pycache__/text_to_image.cpython-310.pyc and b/__pycache__/text_to_image.cpython-310.pyc differ diff --git a/__pycache__/text_to_text.cpython-310.pyc b/__pycache__/text_to_text.cpython-310.pyc index 3d54a1db953af274787594cca8904545ef0d9d46..ed9da1399691739cac81f4117ee78470945e1317 100644 Binary files a/__pycache__/text_to_text.cpython-310.pyc and b/__pycache__/text_to_text.cpython-310.pyc differ diff --git a/__pycache__/textarea.cpython-310.pyc b/__pycache__/textarea.cpython-310.pyc index 73f7dedd3e326274460e6d3f69c0232b9a4e9540..86aed0cd5ab3770bc811531c19d7e9d609565329 100644 Binary files a/__pycache__/textarea.cpython-310.pyc and b/__pycache__/textarea.cpython-310.pyc differ diff --git a/__pycache__/uploader.cpython-310.pyc b/__pycache__/uploader.cpython-310.pyc index 0b34e35eb73f95fa3ef84c92add4a259789f2165..5659832ecab1470b508fb39aa8926ec843d06d4a 100644 Binary files a/__pycache__/uploader.cpython-310.pyc and b/__pycache__/uploader.cpython-310.pyc differ diff --git a/autocomplete.py b/autocomplete.py index 77b0c83f321d78f1df9e7cf1f4e0bb8f740f6f1b..010705f337ea718f0204d11bb89b6bbafced9f39 100644 --- a/autocomplete.py +++ b/autocomplete.py @@ -29,6 +29,7 @@ def app(): on_selection_change=on_value_change, on_enter=on_value_change, on_input=on_input, + appearance="outline", ) if state.selected_value: diff --git a/bootstrap.py b/bootstrap.py new file mode 100644 index 0000000000000000000000000000000000000000..e05f6db6a58d389c0d1391300f87667e1df788b8 --- /dev/null +++ b/bootstrap.py @@ -0,0 +1,78 @@ +import mesop as me + + +@me.page( + security_policy=me.SecurityPolicy( + allowed_iframe_parents=["https://google.github.io", "https://huggingface.co."] + ), + stylesheets=[ + "https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css", + ], + path="/bootstrap", +) +def page(): + with me.box(classes="container"): + with me.box( + classes="d-flex flex-wrap justify-content-between py-3 mb-4 border-bottom", + ): + with me.box( + classes="d-flex align-items-center mb-3 mb-md-0 me-md-auto link-body-emphasis text-decoration-none fs-4", + ): + me.text("Mesop") + + with me.box(classes="nav nav-pills"): + with me.box(classes="nav-item"): + with me.box(classes="nav-link active"): + me.text("Features") + with me.box(classes="nav-item"): + with me.box(classes="nav-link"): + me.text("About") + + with me.box(classes="container px-4 py-5"): + with me.box(classes="pb-2 border-bottom"): + me.text("Columns", type="headline-5") + + with me.box(classes="row g-4 py-5 row-cols-1 row-cols-lg-3"): + with me.box(classes="feature col"): + with me.box(classes="fs-2 text-body-emphasis"): + me.text("Featured title") + me.text( + "Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words." + ) + me.link(text="Call to action", url="/#") + + with me.box(classes="feature col"): + with me.box(classes="fs-2 text-body-emphasis"): + me.text("Featured title") + me.text( + "Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words." + ) + me.link(text="Call to action", url="/#") + + with me.box(classes="feature col"): + with me.box(classes="fs-2 text-body-emphasis"): + me.text("Featured title") + me.text( + "Paragraph of text beneath the heading to explain the heading. We'll add onto it with another sentence and probably just keep going until we run out of words." + ) + me.link(text="Call to action", url="/#") + + with me.box( + classes="d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top" + ): + with me.box(classes="col-md-4 mb-0 text-body-secondary"): + me.text("Copyright 2024 Mesop") + + with me.box(classes="nav col-md-4 justify-content-end"): + with me.box(classes="nav-item"): + with me.box(classes="nav-link px-2 text-body-secondary"): + me.text("Home") + with me.box(classes="nav-item"): + with me.box(classes="nav-link px-2 text-body-secondary"): + me.text("Features") + with me.box(classes="nav-item"): + with me.box(classes="nav-link px-2 text-body-secondary"): + me.text("FAQs") + with me.box(classes="nav-item"): + with me.box(classes="nav-link px-2 text-body-secondary"): + me.text("About") diff --git a/button_toggle.py b/button_toggle.py new file mode 100644 index 0000000000000000000000000000000000000000..514f9128ff50780bcdb807ace2be6efa6db8a54f --- /dev/null +++ b/button_toggle.py @@ -0,0 +1,41 @@ +from dataclasses import field + +import mesop as me + + +@me.stateclass +class State: + selected_values: list[str] = field( + default_factory=lambda: ["bold", "underline"] + ) + + +def load(e: me.LoadEvent): + me.set_theme_mode("system") + + +@me.page(on_load=load, path="/button_toggle") +def app(): + state = me.state(State) + + with me.box(style=me.Style(margin=me.Margin.all(15))): + me.button_toggle( + value=state.selected_values, + buttons=[ + me.ButtonToggleButton(label="Bold", value="bold"), + me.ButtonToggleButton(label="Italic", value="italic"), + me.ButtonToggleButton(label="Underline", value="underline"), + ], + multiple=True, + hide_selection_indicator=False, + disabled=False, + on_change=on_change, + style=me.Style(margin=me.Margin(bottom=20)), + ) + + me.text("Select buttons: " + " ".join(state.selected_values)) + + +def on_change(e: me.ButtonToggleChangeEvent): + state = me.state(State) + state.selected_values = e.values diff --git a/card.py b/card.py new file mode 100644 index 0000000000000000000000000000000000000000..c166381522f070f5ed6b9d619cf246e9dd2c2954 --- /dev/null +++ b/card.py @@ -0,0 +1,103 @@ +import mesop as me + + +def load(e: me.LoadEvent): + me.set_theme_mode("system") + + +@me.page( + on_load=load, + security_policy=me.SecurityPolicy( + allowed_iframe_parents=["https://google.github.io", "https://huggingface.co."], + ), + path="/card", +) +def app(): + with me.box( + style=me.Style( + display="flex", + flex_direction="column", + gap=15, + margin=me.Margin.all(15), + max_width=500, + ) + ): + with me.card(appearance="outlined"): + me.card_header( + title="Grapefruit", + subtitle="Kind of fruit", + image="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg", + ) + me.image( + style=me.Style( + width="100%", + ), + src="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg", + ) + with me.card_content(): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + with me.card_actions(align="end"): + me.button(label="Add to cart") + me.button(label="Buy") + + with me.card(appearance="raised"): + me.card_header( + title="Grapefruit", + subtitle="Kind of fruit", + image="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg", + image_type="small", + ) + + with me.card_content(): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + with me.card_actions(align="start"): + me.button(label="Add to cart") + me.button(label="Buy") + + with me.card(appearance="outlined"): + me.card_header( + title="Grapefruit", + subtitle="Kind of fruit", + image="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg", + image_type="medium", + ) + + with me.card_content(): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + with me.card_actions(align="start"): + me.button(label="Add to cart") + me.button(label="Buy") + + me.card_header( + title="Grapefruit", + image="https://interactive-examples.mdn.mozilla.net/media/cc0-images/grapefruit-slice-332-332.jpg", + image_type="large", + ) + + with me.card_content(): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + with me.card_actions(align="end"): + me.button(label="Add to cart") + me.button(label="Buy") + + me.card_header( + title="Grapefruit", + image_type="large", + ) + + with me.card_content(): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) diff --git a/date_picker.py b/date_picker.py new file mode 100644 index 0000000000000000000000000000000000000000..c023f7c8248de752c6cd9aa34644e3d0b630c9fb --- /dev/null +++ b/date_picker.py @@ -0,0 +1,52 @@ +from dataclasses import field +from datetime import date + +import mesop as me + + +@me.stateclass +class State: + picked_date: date | None = field(default_factory=lambda: date(2024, 10, 1)) + + +def on_load(e: me.LoadEvent): + me.set_theme_mode("system") + + +@me.page(path="/date_picker", on_load=on_load) +def app(): + state = me.state(State) + with me.box( + style=me.Style( + display="flex", + flex_direction="column", + gap=15, + padding=me.Padding.all(15), + ) + ): + me.date_picker( + label="Date", + disabled=False, + placeholder="9/1/2024", + required=True, + value=state.picked_date, + readonly=False, + hide_required_marker=False, + color="accent", + float_label="always", + appearance="outline", + on_change=on_date_change, + ) + + me.text("Selected date: " + _render_date(state.picked_date)) + + +def on_date_change(e: me.DatePickerChangeEvent): + state = me.state(State) + state.picked_date = e.date + + +def _render_date(maybe_date: date | None) -> str: + if maybe_date: + return maybe_date.strftime("%Y-%m-%d") + return "None" diff --git a/date_range_picker.py b/date_range_picker.py new file mode 100644 index 0000000000000000000000000000000000000000..f9281ac6e16b3657d64e75db22c964cdb96c26cc --- /dev/null +++ b/date_range_picker.py @@ -0,0 +1,61 @@ +from dataclasses import field +from datetime import date + +import mesop as me + + +@me.stateclass +class State: + picked_start_date: date | None = field( + default_factory=lambda: date(2024, 10, 1) + ) + picked_end_date: date | None = field( + default_factory=lambda: date(2024, 11, 1) + ) + + +def on_load(e: me.LoadEvent): + me.set_theme_mode("system") + + +@me.page(path="/date_range_picker", on_load=on_load) +def app(): + state = me.state(State) + with me.box( + style=me.Style( + display="flex", + flex_direction="column", + gap=15, + padding=me.Padding.all(15), + ) + ): + me.date_range_picker( + label="Date Range", + disabled=False, + placeholder_start_date="9/1/2024", + placeholder_end_date="10/1/2024", + required=True, + start_date=state.picked_start_date, + end_date=state.picked_end_date, + readonly=False, + hide_required_marker=False, + color="accent", + float_label="always", + appearance="outline", + on_change=on_date_range_change, + ) + + me.text("Start date: " + _render_date(state.picked_start_date)) + me.text("End date: " + _render_date(state.picked_end_date)) + + +def on_date_range_change(e: me.DateRangePickerChangeEvent): + state = me.state(State) + state.picked_start_date = e.start_date + state.picked_end_date = e.end_date + + +def _render_date(maybe_date: date | None) -> str: + if maybe_date: + return maybe_date.strftime("%Y-%m-%d") + return "None" diff --git a/expansion_panel.py b/expansion_panel.py new file mode 100644 index 0000000000000000000000000000000000000000..bff919499bcb9fd605eb17b9a23d008d38cdb20c --- /dev/null +++ b/expansion_panel.py @@ -0,0 +1,165 @@ +from dataclasses import field + +import mesop as me + + +@me.stateclass +class State: + normal_accordion: dict[str, bool] = field( + default_factory=lambda: {"pie": True, "donut": False, "icecream": False} + ) + multi_accordion: dict[str, bool] = field( + default_factory=lambda: {"pie": False, "donut": False, "icecream": False} + ) + + +def load(e: me.LoadEvent): + me.set_theme_mode("system") + + +@me.page( + on_load=load, + security_policy=me.SecurityPolicy( + allowed_iframe_parents=["https://google.github.io", "https://huggingface.co."] + ), + path="/expansion_panel", +) +def app(): + state = me.state(State) + with me.box( + style=me.Style( + display="flex", + flex_direction="column", + gap=15, + margin=me.Margin.all(15), + max_width=500, + ) + ): + me.text("Normal Accordion", type="headline-5") + with me.accordion(): + with me.expansion_panel( + key="pie", + title="Pie", + description="Type of snack", + icon="pie_chart", + disabled=False, + expanded=state.normal_accordion["pie"], + hide_toggle=False, + on_toggle=on_accordion_toggle, + ): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + with me.expansion_panel( + key="donut", + title="Donut", + description="Type of breakfast", + icon="donut_large", + disabled=False, + expanded=state.normal_accordion["donut"], + hide_toggle=False, + on_toggle=on_accordion_toggle, + ): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + with me.expansion_panel( + key="icecream", + title="Ice cream", + description="Type of dessert", + icon="icecream", + disabled=False, + expanded=state.normal_accordion["icecream"], + hide_toggle=False, + on_toggle=on_accordion_toggle, + ): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + me.text("Multi Accordion", type="headline-5") + with me.box( + style=me.Style(display="flex", gap=20, margin=me.Margin(bottom=15)), + ): + me.button( + label="Open All", type="flat", on_click=on_multi_accordion_open_all + ) + me.button( + label="Close All", type="flat", on_click=on_multi_accordion_close_all + ) + + with me.accordion(): + with me.expansion_panel( + key="pie", + title="Pie", + description="Type of snack", + icon="pie_chart", + expanded=state.multi_accordion["pie"], + on_toggle=on_multi_accordion_toggle, + ): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + with me.expansion_panel( + key="donut", + title="Donut", + description="Type of breakfast", + icon="donut_large", + expanded=state.multi_accordion["donut"], + on_toggle=on_multi_accordion_toggle, + ): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + with me.expansion_panel( + key="icecream", + title="Ice cream", + description="Type of dessert", + icon="icecream", + expanded=state.multi_accordion["icecream"], + on_toggle=on_multi_accordion_toggle, + ): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + me.text("Expansion Panel", type="headline-5") + + with me.expansion_panel( + key="pie", + title="Pie", + description="Type of snack", + icon="pie_chart", + ): + me.text( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla sed augue ultricies, laoreet nunc eget, ultricies augue. In ornare bibendum mauris vel sodales. Donec ut interdum felis. Nulla facilisi. Morbi a laoreet turpis, sed posuere arcu. Nam nisi neque, molestie vitae euismod eu, sollicitudin eu lectus. Pellentesque orci metus, finibus id faucibus et, ultrices quis dui. Duis in augue ac metus tristique lacinia." + ) + + +def on_accordion_toggle(e: me.ExpansionPanelToggleEvent): + """Implements accordion behavior where only one panel can be open at a time""" + state = me.state(State) + state.normal_accordion = {"pie": False, "donut": False, "icecream": False} + state.normal_accordion[e.key] = e.opened + + +def on_multi_accordion_toggle(e: me.ExpansionPanelToggleEvent): + """Implements accordion behavior where multiple panels can be open at a time""" + state = me.state(State) + state.multi_accordion[e.key] = e.opened + + +def on_multi_accordion_open_all(e: me.ClickEvent): + state = me.state(State) + for key in state.multi_accordion: + state.multi_accordion[key] = True + + +def on_multi_accordion_close_all(e: me.ClickEvent): + state = me.state(State) + for key in state.multi_accordion: + state.multi_accordion[key] = False diff --git a/grid_table.py b/grid_table.py index 01e174eb5eb0cdf0d94b7fc98f89b05270c37a3d..e9b0cfe4ded1de8ec2ef25ece8f2f28474c063d6 100644 --- a/grid_table.py +++ b/grid_table.py @@ -22,7 +22,7 @@ TODOs: from dataclasses import dataclass, field from datetime import datetime -from typing import Any, Callable, Literal, Protocol +from typing import Any, Callable, Literal import pandas as pd @@ -57,7 +57,12 @@ class State: theme: str = "light" +def load(e: me.LoadEvent): + me.set_theme_mode("system") + + @me.page( + on_load=load, security_policy=me.SecurityPolicy( allowed_iframe_parents=["https://google.github.io", "https://huggingface.co."] ), @@ -108,17 +113,15 @@ def app(): ), sort_column=state.sort_column, sort_direction=state.sort_direction, - theme=GridTableThemeLight(striped=True) - if state.theme == "light" - else GridTableThemeDark(striped=True), + theme=GridTableTheme(striped=True), ) # Used for demonstrating "table button" click example. if state.string_output: with me.box( style=me.Style( - background="#ececec", - color="#333", + background=me.theme_var("surface-container-high"), + color=me.theme_var("on-surface"), margin=me.Margin(top=20), padding=me.Padding.all(15), ) @@ -206,30 +209,16 @@ class GridTableCellMeta: value: Any -class GridTableTheme(Protocol): - """Interface for theming the grid table""" - - def header(self, sortable: bool = False) -> me.Style: - return me.Style() +class GridTableTheme: + """This default theme utilizes Mesop's built in dark mode to toggle between dark/light themes.""" - def sort_icon(self, current_column: str, sort_column: str) -> me.Style: - return me.Style() - - def cell(self, cell_meta: GridTableCellMeta) -> me.Style: - return me.Style() - - def expander(self, df_row_index: int) -> me.Style: - return me.Style() - - -class GridTableThemeDark(GridTableTheme): - _HEADER_BG: str = "#28313e" - _CELL_BG: str = "#141d2c" - _CELL_BG_ALT: str = "#02060c" - _COLOR: str = "#fff" + _HEADER_BG: str = me.theme_var("surface-container-highest") + _CELL_BG: str = me.theme_var("surface-container-low") + _CELL_BG_ALT: str = me.theme_var("surface-container-lowest") + _COLOR: str = me.theme_var("on-surface-variant") _PADDING: me.Padding = me.Padding.all(10) _BORDER: me.Border = me.Border.all( - me.BorderSide(width=1, style="solid", color="rgba(255, 255, 255, 0.16)") + me.BorderSide(width=1, style="solid", color=me.theme_var("outline-variant")) ) def __init__(self, striped: bool = False): @@ -246,9 +235,9 @@ class GridTableThemeDark(GridTableTheme): def sort_icon(self, current_column: str, sort_column: str) -> me.Style: return me.Style( - color="rgba(255, 255, 255, .8)" + color=me.theme_var("outline") if sort_column == current_column - else "rgba(255, 255, 255, .4)", + else me.theme_var("outline-variant"), # Hack to make the icon align correctly. Will break if user changes the # font size with custom styles. height=16, @@ -273,61 +262,6 @@ class GridTableThemeDark(GridTableTheme): ) -class GridTableThemeLight(GridTableTheme): - _HEADER_BG: str = "#fff" - _CELL_BG: str = "#fff" - _CELL_BG_ALT: str = "#f6f6f6" - _COLOR: str = "#000" - _PADDING: me.Padding = me.Padding.all(10) - _HEADER_BORDER: me.Border = me.Border( - bottom=me.BorderSide(width=1, style="solid", color="#b2b2b2") - ) - _CELL_BORDER: me.Border = me.Border( - bottom=me.BorderSide(width=1, style="solid", color="#d9d9d9") - ) - - def __init__(self, striped: bool = False): - self.striped = striped - - def header(self, sortable: bool = False) -> me.Style: - return me.Style( - background=self._HEADER_BG, - color=self._COLOR, - cursor="pointer" if sortable else "default", - font_weight="bold", - padding=self._PADDING, - border=self._HEADER_BORDER, - ) - - def sort_icon(self, current_column: str, sort_column: str) -> me.Style: - return me.Style( - color="rgba(0, 0, 0, .8)" - if sort_column == current_column - else "rgba(0, 0, 0, .4)", - # Hack to make the icon align correctly. Will break if user changes the - # font size with custom styles. - height=18, - ) - - def cell(self, cell_meta: GridTableCellMeta) -> me.Style: - return me.Style( - background=self._CELL_BG_ALT - if self.striped and cell_meta.row_index % 2 - else self._CELL_BG, - color=self._COLOR, - padding=self._PADDING, - border=self._CELL_BORDER, - ) - - def expander(self, df_row_index: int) -> me.Style: - return me.Style( - background=self._CELL_BG, - color=self._COLOR, - padding=self._PADDING, - border=self._CELL_BORDER, - ) - - def get_data_frame(): """Helper function to get a sorted/filtered version of the main data frame. @@ -357,6 +291,7 @@ def on_theme_changed(e: me.SelectSelectionChangeEvent): """Changes the theme of the grid table""" state = me.state(State) state.theme = e.value + me.set_theme_mode(state.theme) # type: ignore def on_filter_by_strings(e: me.InputBlurEvent | me.InputEnterEvent): @@ -432,12 +367,14 @@ def strings_component(meta: GridTableCellMeta): on_click=on_click_strings, style=me.Style( border_radius=3, - background="#334053", + background=me.theme_var("primary-container"), border=me.Border.all( - me.BorderSide(width=1, style="solid", color="rgba(255, 255, 255, 0.16)") + me.BorderSide( + width=1, style="solid", color=me.theme_var("primary-fixed-dim") + ) ), font_weight="bold", - color="#fff", + color=me.theme_var("on-primary-container"), ), ) @@ -506,7 +443,7 @@ def grid_table( grid_template_columns=f"repeat({len(data.columns)}, 1fr)", ) ): - _theme: GridTableTheme = GridTableThemeLight() + _theme: GridTableTheme = GridTableTheme() if theme: _theme = theme diff --git a/input.py b/input.py index 60da20dca6dee74141fdbe7bc5f0f557d16ce1a2..ce65560fcbb1d361f9282ef420a7d16dea1dab49 100644 --- a/input.py +++ b/input.py @@ -23,6 +23,7 @@ def load(e: me.LoadEvent): path="/input", ) def app(): - s = me.state(State) - me.input(label="Basic input", on_blur=on_blur) - me.text(text=s.input) + with me.box(style=me.Style(margin=me.Margin.all(15))): + s = me.state(State) + me.input(label="Basic input", appearance="outline", on_blur=on_blur) + me.text(text=s.input) diff --git a/llm_rewriter.py b/llm_rewriter.py index 32280693576c9eebd078ce0106438bf94bdd0c23..40d01ac119d0e7ef017af3a37fca95f4e029f2b3 100644 --- a/llm_rewriter.py +++ b/llm_rewriter.py @@ -30,7 +30,7 @@ class State: def load(e: me.LoadEvent): - me.set_theme_mode("light") + me.set_theme_mode("system") @me.page( diff --git a/main.py b/main.py index 99e7d016f0a875fba6b45da71daf3e5de8e3f841..387e9e29042953de56034c06c21383dd743703ad 100644 --- a/main.py +++ b/main.py @@ -24,16 +24,22 @@ import audio as audio import autocomplete as autocomplete import badge as badge import basic_animation as basic_animation +import bootstrap as bootstrap import box as box import button as button +import button_toggle as button_toggle +import card as card import chat as chat import chat_inputs as chat_inputs import checkbox as checkbox import code_demo as code_demo # cannot call it code due to python library naming conflict +import date_picker as date_picker +import date_range_picker as date_range_picker import density as density import dialog as dialog import divider as divider import embed as embed +import expansion_panel as expansion_panel import fancy_chat as fancy_chat import feedback as feedback import form_billing as form_billing @@ -59,6 +65,7 @@ import slide_toggle as slide_toggle import slider as slider import snackbar as snackbar import table as table +import tailwind as tailwind import text as text import text_to_image as text_to_image import text_to_text as text_to_text @@ -123,6 +130,13 @@ FIRST_SECTIONS = [ Example(name="feedback"), ], ), + Section( + name="Integrations", + examples=[ + Example(name="bootstrap"), + Example(name="tailwind"), + ], + ), ] COMPONENTS_SECTIONS = [ @@ -154,7 +168,10 @@ COMPONENTS_SECTIONS = [ examples=[ Example(name="autocomplete"), Example(name="button"), + Example(name="button_toggle"), Example(name="checkbox"), + Example(name="date_picker"), + Example(name="date_range_picker"), Example(name="input"), Example(name="textarea"), Example(name="radio"), @@ -168,7 +185,9 @@ COMPONENTS_SECTIONS = [ name="Visual", examples=[ Example(name="badge"), + Example(name="card"), Example(name="divider"), + Example(name="expansion_panel"), Example(name="icon"), Example(name="progress_bar"), Example(name="progress_spinner"), diff --git a/requirements.txt b/requirements.txt index 29bbe8f85db142602bf08ef6f8ccc8fc62bb534a..6bab7c7d033a9c5f106066249e49e04c743dd8b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ -mesop>=0.10.0 +mesop>=0.13.0 Flask==3.0.0 gunicorn==22.0.0 -Werkzeug==3.0.1 +Werkzeug==3.0.6 # For examples: matplotlib numpy diff --git a/screenshots/autocomplete.png b/screenshots/autocomplete.png index 01ccb80181755aa36f3dd63ac13013459ef06b48..2603f270a838e2a89e60963ee8c68d5688fc2c45 100644 Binary files a/screenshots/autocomplete.png and b/screenshots/autocomplete.png differ diff --git a/screenshots/autocomplete.webp b/screenshots/autocomplete.webp index 8f7196bece25986d98a57eb638a7af3a0ae36c82..1824c7df199ceed2be3792b3cc392c3dbf8dbdca 100644 Binary files a/screenshots/autocomplete.webp and b/screenshots/autocomplete.webp differ diff --git a/screenshots/bootstrap.png b/screenshots/bootstrap.png new file mode 100644 index 0000000000000000000000000000000000000000..0fe5871fc7e14d0018cd7d27b47e034fcccee29d Binary files /dev/null and b/screenshots/bootstrap.png differ diff --git a/screenshots/bootstrap.webp b/screenshots/bootstrap.webp new file mode 100644 index 0000000000000000000000000000000000000000..4a841a752020d9132d3ab8fc9f1ddf76865b03a7 Binary files /dev/null and b/screenshots/bootstrap.webp differ diff --git a/screenshots/button_toggle.png b/screenshots/button_toggle.png new file mode 100644 index 0000000000000000000000000000000000000000..8544a40e25740f59e12b14cb557cc0f6f5722c83 Binary files /dev/null and b/screenshots/button_toggle.png differ diff --git a/screenshots/button_toggle.webp b/screenshots/button_toggle.webp new file mode 100644 index 0000000000000000000000000000000000000000..003c74ed95888b473cd02c39949f0c3ad20e3152 Binary files /dev/null and b/screenshots/button_toggle.webp differ diff --git a/screenshots/card.png b/screenshots/card.png new file mode 100644 index 0000000000000000000000000000000000000000..89d68cd70b3fecc3cf80b36a1ca304bca271174c Binary files /dev/null and b/screenshots/card.png differ diff --git a/screenshots/card.webp b/screenshots/card.webp new file mode 100644 index 0000000000000000000000000000000000000000..446018d12d3ef96719b3f167d0fe3d78f79c8eef Binary files /dev/null and b/screenshots/card.webp differ diff --git a/screenshots/date_picker.png b/screenshots/date_picker.png new file mode 100644 index 0000000000000000000000000000000000000000..71385f51df7a2b5fc44850d9f84c83973de0043e Binary files /dev/null and b/screenshots/date_picker.png differ diff --git a/screenshots/date_picker.webp b/screenshots/date_picker.webp new file mode 100644 index 0000000000000000000000000000000000000000..d4f8bfd1bb4da9c5ec9d6f34b943b5f724906f83 Binary files /dev/null and b/screenshots/date_picker.webp differ diff --git a/screenshots/date_range_picker.png b/screenshots/date_range_picker.png new file mode 100644 index 0000000000000000000000000000000000000000..fee9e11fe12ad6c01547dec0dfec02f2e682a3e5 Binary files /dev/null and b/screenshots/date_range_picker.png differ diff --git a/screenshots/date_range_picker.webp b/screenshots/date_range_picker.webp new file mode 100644 index 0000000000000000000000000000000000000000..664962e1589284a32dbdfc48bd8995780dbed508 Binary files /dev/null and b/screenshots/date_range_picker.webp differ diff --git a/screenshots/embed.png b/screenshots/embed.png index 21e43bdecca8b9b2ff49b424eb6f6a40bd4c57de..fdb9dbb15dd3b025e8ae567a6f89334fde67011b 100644 Binary files a/screenshots/embed.png and b/screenshots/embed.png differ diff --git a/screenshots/embed.webp b/screenshots/embed.webp index e4ce9011181432708b6675079fce0ad00d4d1134..6494144ae6a93c72641df2791215099fb3ef97cb 100644 Binary files a/screenshots/embed.webp and b/screenshots/embed.webp differ diff --git a/screenshots/expansion_panel.png b/screenshots/expansion_panel.png new file mode 100644 index 0000000000000000000000000000000000000000..c31fcaf860dff09645a80f82e597ea5e92be4f14 Binary files /dev/null and b/screenshots/expansion_panel.png differ diff --git a/screenshots/expansion_panel.webp b/screenshots/expansion_panel.webp new file mode 100644 index 0000000000000000000000000000000000000000..a16195845ef6c706be8d8bbe208596dcfcc861d7 Binary files /dev/null and b/screenshots/expansion_panel.webp differ diff --git a/screenshots/grid_table.png b/screenshots/grid_table.png index aaccb0b39d6ae0c17699aae29cc003891c0b31aa..d71690497ad270825197c39f8f399446b0f38024 100644 Binary files a/screenshots/grid_table.png and b/screenshots/grid_table.png differ diff --git a/screenshots/grid_table.webp b/screenshots/grid_table.webp index 834c3e968d6e351021d17ec8bee669bd3482501f..882d6ba6fe8d89117838cdf63fac5cb42d53872c 100644 Binary files a/screenshots/grid_table.webp and b/screenshots/grid_table.webp differ diff --git a/screenshots/input.png b/screenshots/input.png index 43cef51e404698381085a85b33580fbdb7d88ac5..a077514276a8e41c653d0a751cd4f06704bc9b97 100644 Binary files a/screenshots/input.png and b/screenshots/input.png differ diff --git a/screenshots/input.webp b/screenshots/input.webp index 52e66db7a9f4ab23e4976838802d022db9655eed..965796f4bc98d7e4dad0f90cca0f7909f227cea9 100644 Binary files a/screenshots/input.webp and b/screenshots/input.webp differ diff --git a/screenshots/main.png b/screenshots/main.png index 2e849b23a1567aa6a8f68759a59d900df0c4476c..36538453688e3ee25127750622ba24883606fc04 100644 Binary files a/screenshots/main.png and b/screenshots/main.png differ diff --git a/screenshots/main.webp b/screenshots/main.webp index 3243831584237884dab92b945cde29611b4994d8..b4fb1c0b3ea47c62ec702603a9e0c1f908f4bf6c 100644 Binary files a/screenshots/main.webp and b/screenshots/main.webp differ diff --git a/screenshots/progress_bar.png b/screenshots/progress_bar.png index 9139972894e14b434100c3965863de65337ce67e..d28f296cf24854f6f0b61a38d382065051de5814 100644 Binary files a/screenshots/progress_bar.png and b/screenshots/progress_bar.png differ diff --git a/screenshots/progress_bar.webp b/screenshots/progress_bar.webp index 18ef8e586f79ec517bed53a7ed5c462e1fcda763..b6b70f5e032f3d36a461dab4a8994e42659d3bfa 100644 Binary files a/screenshots/progress_bar.webp and b/screenshots/progress_bar.webp differ diff --git a/screenshots/progress_spinner.png b/screenshots/progress_spinner.png index 6b7a461b5bdab61379d6b87751289404d482faa8..e09eb48a752129487fb64e250900b14e801f4938 100644 Binary files a/screenshots/progress_spinner.png and b/screenshots/progress_spinner.png differ diff --git a/screenshots/progress_spinner.webp b/screenshots/progress_spinner.webp index aeb7ec55ecc4eddc4af1a19954bc9f51c1beabd8..d2cc3fd30cf1da35ddd01c20d27200e1e3ccd7c4 100644 Binary files a/screenshots/progress_spinner.webp and b/screenshots/progress_spinner.webp differ diff --git a/screenshots/select_demo.png b/screenshots/select_demo.png index 6d6610337adaab693b041ff41159db39c1d21f1c..f29ea9f5bc682a7e5689c49defbdd17540bdce5e 100644 Binary files a/screenshots/select_demo.png and b/screenshots/select_demo.png differ diff --git a/screenshots/select_demo.webp b/screenshots/select_demo.webp index 264009ba97b147e56966239f3741c3fc20af296e..ffe6e6c0d1e763e67ecb7d13e42c5f909ffe14c0 100644 Binary files a/screenshots/select_demo.webp and b/screenshots/select_demo.webp differ diff --git a/screenshots/sidenav.png b/screenshots/sidenav.png index 41a723fc5404730b320684c258a38003f151bc26..f41669388ed847942085e37c3f2c4bac9e0d0c2e 100644 Binary files a/screenshots/sidenav.png and b/screenshots/sidenav.png differ diff --git a/screenshots/sidenav.webp b/screenshots/sidenav.webp index 010df721545497df517f7a9b6fbc5dd37983cb2c..dcc09fc4ff3624e65caa32e5def1841de515d62a 100644 Binary files a/screenshots/sidenav.webp and b/screenshots/sidenav.webp differ diff --git a/screenshots/tailwind.png b/screenshots/tailwind.png new file mode 100644 index 0000000000000000000000000000000000000000..627a83483ce2e7307e0bb61d2aac0dd633dc26ea Binary files /dev/null and b/screenshots/tailwind.png differ diff --git a/screenshots/tailwind.webp b/screenshots/tailwind.webp new file mode 100644 index 0000000000000000000000000000000000000000..f60a1e7b6a6e1c6fe4583563efce2756cd9e5e14 Binary files /dev/null and b/screenshots/tailwind.webp differ diff --git a/screenshots/textarea.png b/screenshots/textarea.png index 5e15844672590f5e301a6096d109631e5fc09a76..40f5c4c1223add6d1d6e8dc9ca30e967653c7c1d 100644 Binary files a/screenshots/textarea.png and b/screenshots/textarea.png differ diff --git a/screenshots/textarea.webp b/screenshots/textarea.webp index cbb229bf1ffee30982bd16a9334efca8fa0be4ac..0ddceb3466484a2a14089f0b173c8ea94aebd1d2 100644 Binary files a/screenshots/textarea.webp and b/screenshots/textarea.webp differ diff --git a/screenshots/uploader.png b/screenshots/uploader.png index fbbc0fec6954fd8bf11e554f68bc461e1f1d84df..ec899edc3d140b2e83f15ab6c395bee9bf32c825 100644 Binary files a/screenshots/uploader.png and b/screenshots/uploader.png differ diff --git a/screenshots/uploader.webp b/screenshots/uploader.webp index e75945100e2e2a85b649b430bfd83da987cde497..c14f408227599bb6a020149ce24ade66127704b2 100644 Binary files a/screenshots/uploader.webp and b/screenshots/uploader.webp differ diff --git a/screenshots/video.png b/screenshots/video.png index 0e41fa7f12f667bdd54bfc92d0d8b989a39b4844..33798d3a708d83b4f0a6830d983a67756684cb34 100644 Binary files a/screenshots/video.png and b/screenshots/video.png differ diff --git a/screenshots/video.webp b/screenshots/video.webp index 05ed719614cdbdc912bbd4e917189acaa5dd442c..85c435f187b361ccf36a6c12917d1ad0fbacfd42 100644 Binary files a/screenshots/video.webp and b/screenshots/video.webp differ diff --git a/select_demo.py b/select_demo.py index 859e75c208459cf579d018214cc2b2a0bd1195c5..7a21b9072f01b2970b737d69ae86c2b80429614e 100644 --- a/select_demo.py +++ b/select_demo.py @@ -1,14 +1,24 @@ +from dataclasses import field + import mesop as me @me.stateclass class State: - selected_values: list[str] + selected_values_1: list[str] = field( + default_factory=lambda: ["value1", "value2"] + ) + selected_values_2: str = "value1" + + +def on_selection_change_1(e: me.SelectSelectionChangeEvent): + s = me.state(State) + s.selected_values_1 = e.values -def on_selection_change(e: me.SelectSelectionChangeEvent): +def on_selection_change_2(e: me.SelectSelectionChangeEvent): s = me.state(State) - s.selected_values = e.values + s.selected_values_2 = e.value def load(e: me.LoadEvent): @@ -23,18 +33,36 @@ def load(e: me.LoadEvent): path="/select_demo", ) def app(): + state = me.state(State) with me.box(style=me.Style(margin=me.Margin.all(15))): - me.text(text="Select") me.select( - label="Select", + label="Select multiple", options=[ me.SelectOption(label="label 1", value="value1"), me.SelectOption(label="label 2", value="value2"), me.SelectOption(label="label 3", value="value3"), ], - on_selection_change=on_selection_change, + on_selection_change=on_selection_change_1, style=me.Style(width=500), multiple=True, + appearance="outline", + value=state.selected_values_1, + ) + me.text( + text="Selected values (multiple): " + ", ".join(state.selected_values_1) + ) + + me.select( + label="Select single", + options=[ + me.SelectOption(label="label 1", value="value1"), + me.SelectOption(label="label 2", value="value2"), + me.SelectOption(label="label 3", value="value3"), + ], + on_selection_change=on_selection_change_2, + style=me.Style(width=500, margin=me.Margin(top=40)), + multiple=False, + appearance="outline", + value=state.selected_values_2, ) - s = me.state(State) - me.text(text="Selected values: " + ", ".join(s.selected_values)) + me.text(text="Selected values (single): " + state.selected_values_2) diff --git a/sidenav.py b/sidenav.py index eeb6048c7963d529ced8446ed5f9ed425294e5f2..5ee9fb1df8399288b8601010398153d4c4a08a13 100644 --- a/sidenav.py +++ b/sidenav.py @@ -1,5 +1,7 @@ import mesop as me +SIDENAV_WIDTH = 200 + @me.stateclass class State: @@ -11,7 +13,9 @@ def on_click(e: me.ClickEvent): s.sidenav_open = not s.sidenav_open -SIDENAV_WIDTH = 200 +def opened_changed(e: me.SidenavOpenedChangedEvent): + s = me.state(State) + s.sidenav_open = e.opened def load(e: me.LoadEvent): @@ -28,13 +32,22 @@ def load(e: me.LoadEvent): def app(): state = me.state(State) with me.sidenav( - opened=state.sidenav_open, style=me.Style(width=SIDENAV_WIDTH) + opened=state.sidenav_open, + disable_close=False, + on_opened_changed=opened_changed, + style=me.Style( + border_radius=0, + width=SIDENAV_WIDTH, + background=me.theme_var("surface-container-low"), + padding=me.Padding.all(15), + ), ): me.text("Inside sidenav") with me.box( style=me.Style( margin=me.Margin(left=SIDENAV_WIDTH if state.sidenav_open else 0), + padding=me.Padding.all(15), ), ): with me.content_button(on_click=on_click): diff --git a/static/tailwind.css b/static/tailwind.css new file mode 100644 index 0000000000000000000000000000000000000000..8d38afe0d9442ae8e4340f61afbd80437d62c1e7 --- /dev/null +++ b/static/tailwind.css @@ -0,0 +1,756 @@ +/* +MIT License + +Copyright (c) Tailwind Labs, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +*, +::before, +::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +/* +! tailwindcss v3.4.14 | MIT License | https://tailwindcss.com +*/ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e5e7eb; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ + -webkit-tap-highlight-color: transparent; + /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, + 'Liberation Mono', 'Courier New', monospace; + /* 1 */ + font-feature-settings: normal; + /* 2 */ + font-variation-settings: normal; + /* 3 */ + font-size: 1em; + /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-feature-settings: inherit; + /* 1 */ + font-variation-settings: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + letter-spacing: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, +textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #9ca3af; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role='button'] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden]:where(:not([hidden='until-found'])) { + display: none; +} + +.container { + width: 100%; +} + +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.block { + display: block; +} + +.flex { + display: flex; +} + +.grid { + display: grid; +} + +.min-h-screen { + min-height: 100vh; +} + +.w-64 { + width: 16rem; +} + +.flex-1 { + flex: 1 1 0%; +} + +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + +.flex-col { + flex-direction: column; +} + +.gap-4 { + gap: 1rem; +} + +.rounded { + border-radius: 0.25rem; +} + +.bg-gray-100 { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + +.bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); +} + +.bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.p-4 { + padding: 1rem; +} + +.p-6 { + padding: 1.5rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.py-4 { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + +.font-bold { + font-weight: 700; +} + +.font-semibold { + font-weight: 600; +} + +.text-gray-700 { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} + +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.shadow { + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), + 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), + var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +@media (min-width: 768px) { + .md\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} diff --git a/tailwind.py b/tailwind.py new file mode 100644 index 0000000000000000000000000000000000000000..4fa0e63805814df614e416215f80ff64b9dab9db --- /dev/null +++ b/tailwind.py @@ -0,0 +1,133 @@ +""" +Example Tailwind command: + +``` +npx tailwindcss -i ./tailwind_input.css -o ./tailwind.css +``` + +Example tailwind_input.css + +``` +@tailwind base; +@tailwind components; +@tailwind utilities; +``` + +Example Tailwind config: + +``` +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["main.py"], + theme: { + extend: {}, + }, + plugins: [], + safelist: [], +}; +``` + +Original HTML mark up: + +``` + +
+ + +This is the content for box 1.
+This is the content for box 2.
+This is the content for box 3.
+