streamlit 1.49.1__py3-none-any.whl → 1.51.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- streamlit/__init__.py +4 -1
- streamlit/column_config.py +2 -0
- streamlit/commands/navigation.py +7 -7
- streamlit/commands/page_config.py +4 -6
- streamlit/components/v1/custom_component.py +17 -42
- streamlit/components/v2/__init__.py +458 -0
- streamlit/components/v2/bidi_component/__init__.py +20 -0
- streamlit/components/v2/bidi_component/constants.py +29 -0
- streamlit/components/v2/bidi_component/main.py +386 -0
- streamlit/components/v2/bidi_component/serialization.py +265 -0
- streamlit/components/v2/bidi_component/state.py +92 -0
- streamlit/components/v2/component_definition_resolver.py +143 -0
- streamlit/components/v2/component_file_watcher.py +403 -0
- streamlit/components/v2/component_manager.py +431 -0
- streamlit/components/v2/component_manifest_handler.py +122 -0
- streamlit/components/v2/component_path_utils.py +245 -0
- streamlit/components/v2/component_registry.py +409 -0
- streamlit/components/v2/get_bidi_component_manager.py +51 -0
- streamlit/components/v2/manifest_scanner.py +615 -0
- streamlit/components/v2/presentation.py +198 -0
- streamlit/components/v2/types.py +324 -0
- streamlit/config.py +741 -32
- streamlit/config_option.py +4 -1
- streamlit/config_util.py +650 -1
- streamlit/connections/base_connection.py +4 -2
- streamlit/dataframe_util.py +18 -10
- streamlit/delta_generator.py +8 -7
- streamlit/delta_generator_singletons.py +3 -1
- streamlit/deprecation_util.py +17 -6
- streamlit/elements/arrow.py +90 -42
- streamlit/elements/deck_gl_json_chart.py +98 -39
- streamlit/elements/dialog_decorator.py +2 -1
- streamlit/elements/exception.py +3 -1
- streamlit/elements/form.py +6 -6
- streamlit/elements/graphviz_chart.py +24 -9
- streamlit/elements/heading.py +3 -5
- streamlit/elements/iframe.py +0 -2
- streamlit/elements/image.py +12 -13
- streamlit/elements/layouts.py +89 -22
- streamlit/elements/lib/built_in_chart_utils.py +95 -31
- streamlit/elements/lib/color_util.py +8 -18
- streamlit/elements/lib/column_config_utils.py +9 -8
- streamlit/elements/lib/column_types.py +595 -148
- streamlit/elements/lib/dialog.py +3 -2
- streamlit/elements/lib/image_utils.py +3 -5
- streamlit/elements/lib/layout_utils.py +50 -13
- streamlit/elements/lib/mutable_status_container.py +2 -2
- streamlit/elements/lib/options_selector_utils.py +2 -2
- streamlit/elements/lib/pandas_styler_utils.py +30 -14
- streamlit/elements/lib/utils.py +21 -9
- streamlit/elements/map.py +81 -40
- streamlit/elements/media.py +7 -7
- streamlit/elements/metric.py +11 -35
- streamlit/elements/pdf.py +2 -4
- streamlit/elements/plotly_chart.py +142 -26
- streamlit/elements/progress.py +2 -4
- streamlit/elements/pyplot.py +6 -6
- streamlit/elements/space.py +113 -0
- streamlit/elements/vega_charts.py +400 -143
- streamlit/elements/widgets/audio_input.py +52 -4
- streamlit/elements/widgets/button.py +29 -29
- streamlit/elements/widgets/button_group.py +33 -6
- streamlit/elements/widgets/camera_input.py +3 -4
- streamlit/elements/widgets/chat.py +7 -0
- streamlit/elements/widgets/checkbox.py +1 -0
- streamlit/elements/widgets/color_picker.py +1 -0
- streamlit/elements/widgets/data_editor.py +34 -29
- streamlit/elements/widgets/file_uploader.py +6 -10
- streamlit/elements/widgets/multiselect.py +14 -3
- streamlit/elements/widgets/number_input.py +5 -4
- streamlit/elements/widgets/radio.py +10 -2
- streamlit/elements/widgets/select_slider.py +8 -4
- streamlit/elements/widgets/selectbox.py +9 -2
- streamlit/elements/widgets/slider.py +38 -41
- streamlit/elements/widgets/text_widgets.py +6 -0
- streamlit/elements/widgets/time_widgets.py +15 -12
- streamlit/elements/write.py +28 -23
- streamlit/emojis.py +1 -1
- streamlit/errors.py +115 -0
- streamlit/git_util.py +65 -43
- streamlit/hello/hello.py +8 -0
- streamlit/hello/utils.py +2 -1
- streamlit/material_icon_names.py +1 -1
- streamlit/navigation/page.py +4 -1
- streamlit/proto/ArrowData_pb2.py +27 -0
- streamlit/proto/ArrowData_pb2.pyi +46 -0
- streamlit/proto/Arrow_pb2.py +10 -8
- streamlit/proto/Arrow_pb2.pyi +31 -2
- streamlit/proto/AudioInput_pb2.py +2 -2
- streamlit/proto/AudioInput_pb2.pyi +6 -2
- streamlit/proto/BidiComponent_pb2.py +34 -0
- streamlit/proto/BidiComponent_pb2.pyi +153 -0
- streamlit/proto/Block_pb2.py +11 -11
- streamlit/proto/Block_pb2.pyi +9 -1
- streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
- streamlit/proto/DeckGlJsonChart_pb2.pyi +9 -3
- streamlit/proto/Element_pb2.py +5 -3
- streamlit/proto/Element_pb2.pyi +14 -4
- streamlit/proto/HeightConfig_pb2.py +2 -2
- streamlit/proto/HeightConfig_pb2.pyi +6 -3
- streamlit/proto/NewSession_pb2.py +18 -16
- streamlit/proto/NewSession_pb2.pyi +158 -6
- streamlit/proto/PlotlyChart_pb2.py +8 -6
- streamlit/proto/PlotlyChart_pb2.pyi +3 -1
- streamlit/proto/Space_pb2.py +27 -0
- streamlit/proto/Space_pb2.pyi +42 -0
- streamlit/proto/WidgetStates_pb2.py +2 -2
- streamlit/proto/WidgetStates_pb2.pyi +13 -3
- streamlit/proto/WidthConfig_pb2.py +2 -2
- streamlit/proto/WidthConfig_pb2.pyi +6 -3
- streamlit/runtime/app_session.py +45 -6
- streamlit/runtime/caching/cache_data_api.py +4 -4
- streamlit/runtime/caching/cache_errors.py +4 -1
- streamlit/runtime/caching/cache_resource_api.py +3 -2
- streamlit/runtime/caching/cache_utils.py +2 -1
- streamlit/runtime/caching/cached_message_replay.py +3 -3
- streamlit/runtime/caching/hashing.py +3 -4
- streamlit/runtime/caching/legacy_cache_api.py +2 -1
- streamlit/runtime/connection_factory.py +1 -3
- streamlit/runtime/forward_msg_queue.py +4 -1
- streamlit/runtime/fragment.py +2 -1
- streamlit/runtime/memory_media_file_storage.py +1 -1
- streamlit/runtime/metrics_util.py +6 -2
- streamlit/runtime/runtime.py +14 -0
- streamlit/runtime/scriptrunner/exec_code.py +2 -1
- streamlit/runtime/scriptrunner/script_runner.py +2 -2
- streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
- streamlit/runtime/secrets.py +2 -4
- streamlit/runtime/session_manager.py +3 -1
- streamlit/runtime/state/common.py +30 -5
- streamlit/runtime/state/presentation.py +85 -0
- streamlit/runtime/state/safe_session_state.py +2 -2
- streamlit/runtime/state/session_state.py +220 -16
- streamlit/runtime/state/widgets.py +19 -3
- streamlit/runtime/theme_util.py +148 -0
- streamlit/runtime/websocket_session_manager.py +3 -1
- streamlit/source_util.py +2 -2
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +244 -227
- streamlit/static/static/css/{index.C8X8rNzw.css → index.BpABIXK9.css} +1 -1
- streamlit/static/static/css/index.DgR7E2CV.css +1 -0
- streamlit/static/static/js/{ErrorOutline.esm.DcGrhbBP.js → ErrorOutline.esm.YoJdlW1p.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.DgBvV6Pq.js → FileDownload.esm.Ddx8VEYy.js} +1 -1
- streamlit/static/static/js/{FileHelper.M6AAaeuA.js → FileHelper.90EtOmj9.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.DHh1GFzm.js → FormClearHelper.BB1Km6eP.js} +1 -1
- streamlit/static/static/js/InputInstructions.jhH15PqV.js +1 -0
- streamlit/static/static/js/{Particles.DDVT-6Qc.js → Particles.DUsputn1.js} +1 -1
- streamlit/static/static/js/{ProgressBar.BEY0cXXV.js → ProgressBar.DLY8H6nE.js} +2 -2
- streamlit/static/static/js/Toolbar.D8nHCkuz.js +1 -0
- streamlit/static/static/js/{base-input.CK3UVGp1.js → base-input.CJGiNqed.js} +3 -3
- streamlit/static/static/js/{checkbox.D8W881TL.js → checkbox.Cpdd482O.js} +1 -1
- streamlit/static/static/js/{createSuper.B6W-Dh9S.js → createSuper.CuQIogbW.js} +1 -1
- streamlit/static/static/js/data-grid-overlay-editor.2Ufgxc6y.js +1 -0
- streamlit/static/static/js/{downloader.DiKpuU_S.js → downloader.CN0K7xlu.js} +1 -1
- streamlit/static/static/js/{es6.B8zRNPZ-.js → es6.BJcsVXQ0.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.DIewJmmh.js → iframeResizer.contentWindow.XzUvQqcZ.js} +1 -1
- streamlit/static/static/js/index.B1ZQh4P1.js +1 -0
- streamlit/static/static/js/index.BKstZk0M.js +27 -0
- streamlit/static/static/js/{index.Bte_9Lyq.js → index.BMcFsUee.js} +1 -1
- streamlit/static/static/js/{index.qhs54UAB.js → index.BR-IdcTb.js} +1 -1
- streamlit/static/static/js/{index.CejBxbg1.js → index.B_dWA3vd.js} +1 -1
- streamlit/static/static/js/{index.D5naqx-J.js → index.BgnZEMVh.js} +1 -1
- streamlit/static/static/js/{index.C7fRKRs4.js → index.BohqXifI.js} +1 -1
- streamlit/static/static/js/{index.cnnXF7xQ.js → index.Br5nxKNj.js} +1 -1
- streamlit/static/static/js/index.BrIKVbNc.js +3 -0
- streamlit/static/static/js/index.BtWUPzle.js +1 -0
- streamlit/static/static/js/index.C0RLraek.js +1 -0
- streamlit/static/static/js/{index.CP5TD2z1.js → index.CAIjskgG.js} +1 -1
- streamlit/static/static/js/{index.CD8HuT3N.js → index.CAj-7vWz.js} +135 -162
- streamlit/static/static/js/{index.DtYN2x4k.js → index.CMtEit2O.js} +1 -1
- streamlit/static/static/js/index.CkRlykEE.js +12 -0
- streamlit/static/static/js/{index.Ts_0SdB9.js → index.CmN3FXfI.js} +2 -2
- streamlit/static/static/js/{index.BnEpvLEz.js → index.CwbFI1_-.js} +1 -1
- streamlit/static/static/js/{index.CcJf6BCU.js → index.CxIUUfab.js} +27 -27
- streamlit/static/static/js/index.D2KPNy7e.js +1 -0
- streamlit/static/static/js/{index.Ch7MBCx0.js → index.D3GPA5k4.js} +47 -47
- streamlit/static/static/js/{index.ho6NIXGl.js → index.DGAh7DMq.js} +1 -1
- streamlit/static/static/js/index.DKb_NvmG.js +197 -0
- streamlit/static/static/js/{index.CvYYtxD_.js → index.DMqgUYKq.js} +1 -1
- streamlit/static/static/js/{index.zecpGxtj.js → index.DOFlg3dS.js} +1 -1
- streamlit/static/static/js/{index.B9mjBcgE.js → index.DPUXkcQL.js} +1 -1
- streamlit/static/static/js/index.DX1xY89g.js +1 -0
- streamlit/static/static/js/index.DYATBCsq.js +2 -0
- streamlit/static/static/js/{index.D2-atlaQ.js → index.DaSmGJ76.js} +3 -3
- streamlit/static/static/js/index.Dd7bMeLP.js +1 -0
- streamlit/static/static/js/{index.4eF4NxG2.js → index.DjmmgI5U.js} +1 -1
- streamlit/static/static/js/index.Dq56CyM2.js +1 -0
- streamlit/static/static/js/index.DuiXaS5_.js +7 -0
- streamlit/static/static/js/index.DvFidMLe.js +2 -0
- streamlit/static/static/js/{index.452cqrrL.js → index.DwkhC5Pc.js} +1 -1
- streamlit/static/static/js/{index.Dk4C7X3i.js → index.Q-3sFn1v.js} +1 -1
- streamlit/static/static/js/{index.CjXWwH-y.js → index.QJ5QO9sJ.js} +1 -1
- streamlit/static/static/js/{index.B6U8LQo3.js → index.VwTaeety.js} +1 -1
- streamlit/static/static/js/index.YOqQbeX8.js +1 -0
- streamlit/static/static/js/{input.nzVJphXi.js → input.D4MN_FzN.js} +1 -1
- streamlit/static/static/js/{memory.CjCgTQz3.js → memory.DrZjtdGT.js} +1 -1
- streamlit/static/static/js/{number-overlay-editor.DaRFzZEO.js → number-overlay-editor.DRwAw1In.js} +1 -1
- streamlit/static/static/js/{possibleConstructorReturn.DgiPnZ9N.js → possibleConstructorReturn.exeeJQEP.js} +1 -1
- streamlit/static/static/js/record.B-tDciZb.js +1 -0
- streamlit/static/static/js/{sandbox.mithfq7Z.js → sandbox.ClO3IuUr.js} +1 -1
- streamlit/static/static/js/{timepicker.Dbl5KFh6.js → timepicker.DAhu-vcF.js} +4 -4
- streamlit/static/static/js/{toConsumableArray.D-Dx88BQ.js → toConsumableArray.DNbljYEC.js} +1 -1
- streamlit/static/static/js/{uniqueId.Bh26R_3S.js → uniqueId.oG4Gvj1v.js} +1 -1
- streamlit/static/static/js/{useBasicWidgetState.DeK-QJpD.js → useBasicWidgetState.D6sOH6oI.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.4iAdLWD-.js → useTextInputAutoExpand.4u3_GcuN.js} +2 -2
- streamlit/static/static/js/{useUpdateUiValue.CmT7_nJN.js → useUpdateUiValue.F2R3eTeR.js} +1 -1
- streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
- streamlit/static/static/js/withFullScreenWrapper.zothJIsI.js +1 -0
- streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
- streamlit/string_util.py +56 -1
- streamlit/testing/v1/app_test.py +2 -2
- streamlit/testing/v1/element_tree.py +23 -9
- streamlit/testing/v1/util.py +2 -2
- streamlit/type_util.py +3 -4
- streamlit/url_util.py +1 -3
- streamlit/user_info.py +1 -2
- streamlit/util.py +3 -1
- streamlit/watcher/event_based_path_watcher.py +23 -12
- streamlit/watcher/local_sources_watcher.py +11 -1
- streamlit/watcher/path_watcher.py +9 -6
- streamlit/watcher/polling_path_watcher.py +4 -1
- streamlit/watcher/util.py +2 -2
- streamlit/web/bootstrap.py +0 -31
- streamlit/web/cli.py +51 -22
- streamlit/web/server/bidi_component_request_handler.py +193 -0
- streamlit/web/server/component_file_utils.py +97 -0
- streamlit/web/server/component_request_handler.py +8 -21
- streamlit/web/server/oidc_mixin.py +3 -1
- streamlit/web/server/routes.py +18 -5
- streamlit/web/server/server.py +10 -0
- streamlit/web/server/server_util.py +3 -1
- streamlit/web/server/upload_file_request_handler.py +3 -1
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/METADATA +4 -5
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/RECORD +238 -209
- streamlit/static/static/css/index.COe1010n.css +0 -1
- streamlit/static/static/js/Hooks.DGu1od_L.js +0 -1
- streamlit/static/static/js/InputInstructions.z6sVgyYt.js +0 -1
- streamlit/static/static/js/Toolbar.DSnK1fUh.js +0 -1
- streamlit/static/static/js/data-grid-overlay-editor.DRTHOydk.js +0 -1
- streamlit/static/static/js/index.BXYmrqnf.js +0 -1
- streamlit/static/static/js/index.B_8AnktO.js +0 -1
- streamlit/static/static/js/index.Bl7zGQSh.js +0 -7
- streamlit/static/static/js/index.BnJIOYn9.js +0 -73
- streamlit/static/static/js/index.C1HcTl5K.js +0 -1
- streamlit/static/static/js/index.C7lSmSOP.js +0 -1
- streamlit/static/static/js/index.C_tmcx4B.js +0 -1
- streamlit/static/static/js/index.D3K5nOu9.js +0 -197
- streamlit/static/static/js/index.DkKT3LUI.js +0 -1
- streamlit/static/static/js/index.MTPPBDHk.js +0 -2
- streamlit/static/static/js/index.pqW9AMJD.js +0 -3
- streamlit/static/static/js/index.urHgTgMQ.js +0 -12
- streamlit/static/static/js/index.wzkv_11M.js +0 -1
- streamlit/static/static/js/index.yF5AncHY.js +0 -1
- streamlit/static/static/js/withFullScreenWrapper.DLp1ENGm.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.CBxVaFdk.woff2 +0 -0
- {streamlit-1.49.1.data → streamlit-1.51.0.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/WHEEL +0 -0
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/entry_points.txt +0 -0
- {streamlit-1.49.1.dist-info → streamlit-1.51.0.dist-info}/top_level.txt +0 -0
streamlit/__init__.py
CHANGED
|
@@ -165,6 +165,7 @@ audio_input = _main.audio_input
|
|
|
165
165
|
badge = _main.badge
|
|
166
166
|
balloons = _main.balloons
|
|
167
167
|
bar_chart = _main.bar_chart
|
|
168
|
+
_bidi_component = _main._bidi_component
|
|
168
169
|
bokeh_chart = _main.bokeh_chart
|
|
169
170
|
button = _main.button
|
|
170
171
|
caption = _main.caption
|
|
@@ -219,6 +220,7 @@ select_slider = _main.select_slider
|
|
|
219
220
|
segmented_control = _main.segmented_control
|
|
220
221
|
slider = _main.slider
|
|
221
222
|
snow = _main.snow
|
|
223
|
+
space = _main.space
|
|
222
224
|
subheader = _main.subheader
|
|
223
225
|
success = _main.success
|
|
224
226
|
table = _main.table
|
|
@@ -304,4 +306,5 @@ experimental_set_query_params = _deprecate_func_name(
|
|
|
304
306
|
# make it possible to call streamlit.components.v1.html etc. by importing it here
|
|
305
307
|
# import in the very end to avoid partially-initialized module import errors, because
|
|
306
308
|
# streamlit.components.v1 also uses some streamlit imports
|
|
307
|
-
import streamlit.components.v1
|
|
309
|
+
import streamlit.components.v1
|
|
310
|
+
import streamlit.components.v2 # noqa: F401
|
streamlit/column_config.py
CHANGED
|
@@ -30,6 +30,7 @@ __all__ = [
|
|
|
30
30
|
"LineChartColumn",
|
|
31
31
|
"LinkColumn",
|
|
32
32
|
"ListColumn",
|
|
33
|
+
"MultiselectColumn",
|
|
33
34
|
"NumberColumn",
|
|
34
35
|
"ProgressColumn",
|
|
35
36
|
"SelectboxColumn",
|
|
@@ -50,6 +51,7 @@ from streamlit.elements.lib.column_types import (
|
|
|
50
51
|
LineChartColumn,
|
|
51
52
|
LinkColumn,
|
|
52
53
|
ListColumn,
|
|
54
|
+
MultiselectColumn,
|
|
53
55
|
NumberColumn,
|
|
54
56
|
ProgressColumn,
|
|
55
57
|
SelectboxColumn,
|
streamlit/commands/navigation.py
CHANGED
|
@@ -14,11 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from collections.abc import Mapping, Sequence
|
|
17
|
+
from collections.abc import Callable, Mapping, Sequence
|
|
18
18
|
from pathlib import Path
|
|
19
|
-
from typing import TYPE_CHECKING,
|
|
20
|
-
|
|
21
|
-
from typing_extensions import TypeAlias
|
|
19
|
+
from typing import TYPE_CHECKING, Literal, TypeAlias
|
|
22
20
|
|
|
23
21
|
from streamlit import config
|
|
24
22
|
from streamlit.errors import StreamlitAPIException
|
|
@@ -37,7 +35,7 @@ if TYPE_CHECKING:
|
|
|
37
35
|
from streamlit.source_util import PageHash, PageInfo
|
|
38
36
|
|
|
39
37
|
SectionHeader: TypeAlias = str
|
|
40
|
-
PageType: TypeAlias =
|
|
38
|
+
PageType: TypeAlias = str | Path | Callable[[], None] | StreamlitPage
|
|
41
39
|
|
|
42
40
|
|
|
43
41
|
def convert_to_streamlit_page(
|
|
@@ -121,7 +119,9 @@ def navigation(
|
|
|
121
119
|
menu, ``pages`` must be a dictionary. Each key is the label of a
|
|
122
120
|
section and each value is the list of page-like objects for
|
|
123
121
|
that section. If you use ``position="top"``, each grouping will be a
|
|
124
|
-
collapsible item in the navigation menu.
|
|
122
|
+
collapsible item in the navigation menu. For top navigation, if you use
|
|
123
|
+
an empty string as a section header, the pages in that section will be
|
|
124
|
+
displayed at the beginning of the menu before the collapsible sections.
|
|
125
125
|
|
|
126
126
|
When you use a string or path as a page-like object, they are
|
|
127
127
|
internally passed to ``st.Page`` and converted to ``StreamlitPage``
|
|
@@ -316,7 +316,7 @@ def _navigation(
|
|
|
316
316
|
else:
|
|
317
317
|
nav_sections = {
|
|
318
318
|
section: [convert_to_streamlit_page(p) for p in section_pages]
|
|
319
|
-
for section, section_pages in pages.items()
|
|
319
|
+
for section, section_pages in pages.items()
|
|
320
320
|
}
|
|
321
321
|
page_list = pages_from_nav_sections(nav_sections)
|
|
322
322
|
|
|
@@ -18,9 +18,7 @@ import random
|
|
|
18
18
|
from collections.abc import Mapping
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
from textwrap import dedent
|
|
21
|
-
from typing import TYPE_CHECKING, Any, Final, Literal,
|
|
22
|
-
|
|
23
|
-
from typing_extensions import TypeAlias
|
|
21
|
+
from typing import TYPE_CHECKING, Any, Final, Literal, TypeAlias, cast
|
|
24
22
|
|
|
25
23
|
from streamlit.elements.lib.image_utils import AtomicImage, image_to_url
|
|
26
24
|
from streamlit.elements.lib.layout_utils import LayoutConfig
|
|
@@ -38,20 +36,20 @@ from streamlit.string_util import is_emoji, validate_material_icon
|
|
|
38
36
|
from streamlit.url_util import is_url
|
|
39
37
|
|
|
40
38
|
if TYPE_CHECKING:
|
|
41
|
-
from
|
|
39
|
+
from typing import TypeGuard
|
|
42
40
|
|
|
43
41
|
GET_HELP_KEY: Final = "get help"
|
|
44
42
|
REPORT_A_BUG_KEY: Final = "report a bug"
|
|
45
43
|
ABOUT_KEY: Final = "about"
|
|
46
44
|
|
|
47
|
-
PageIcon: TypeAlias =
|
|
45
|
+
PageIcon: TypeAlias = AtomicImage | str
|
|
48
46
|
Layout: TypeAlias = Literal["centered", "wide"]
|
|
49
47
|
InitialSideBarState: TypeAlias = Literal["auto", "expanded", "collapsed"]
|
|
50
48
|
_GetHelp: TypeAlias = Literal["Get help", "Get Help", "get help"]
|
|
51
49
|
_ReportABug: TypeAlias = Literal["Report a bug", "report a bug"]
|
|
52
50
|
_About: TypeAlias = Literal["About", "about"]
|
|
53
51
|
MenuKey: TypeAlias = Literal[_GetHelp, _ReportABug, _About]
|
|
54
|
-
MenuItems: TypeAlias = Mapping[MenuKey,
|
|
52
|
+
MenuItems: TypeAlias = Mapping[MenuKey, str | None]
|
|
55
53
|
|
|
56
54
|
RANDOM_EMOJIS: Final = list(
|
|
57
55
|
"🔥™🎉🚀🌌💣✨🌙🎆🎇💥🤩🤙🌛🤘⬆💡🤪🥂⚡💨🌠🎊🍿😛🔮🤟🌃🍃🍾💫▪🌴🎈🎬🌀🎄😝☔⛽🍂💃😎🍸🎨🥳☀😍🅱🌞😻🌟😜💦💅🦄😋😉👻🍁🤤👯🌻‼🌈👌🎃💛😚🔫🙌👽🍬🌅☁🍷👭☕🌚💁👅🥰🍜😌🎥🕺❕🧡☄💕🍻✅🌸🚬🤓🍹®☺💪😙☘🤠✊🤗🍵🤞😂💯😏📻🎂💗💜🌊❣🌝😘💆🤑🌿🦋😈⛄🚿😊🌹🥴😽💋😭🖤🙆👐⚪💟☃🙈🍭💻🥀🚗🤧🍝💎💓🤝💄💖🔞⁉⏰🕊🎧☠♥🌳🏾🙉⭐💊🍳🌎🙊💸❤🔪😆🌾✈📚💀🏠✌🏃🌵🚨💂🤫🤭😗😄🍒👏🙃🖖💞😅🎅🍄🆓👉💩🔊🤷⌚👸😇🚮💏👳🏽💘💿💉👠🎼🎶🎤👗❄🔐🎵🤒🍰👓🏄🌲🎮🙂📈🚙📍😵🗣❗🌺🙄👄🚘🥺🌍🏡♦💍🌱👑👙☑👾🍩🥶📣🏼🤣☯👵🍫➡🎀😃✋🍞🙇😹🙏👼🐝⚫🎁🍪🔨🌼👆👀😳🌏📖👃🎸👧💇🔒💙😞⛅🏻🍴😼🗿🍗♠🦁✔🤖☮🐢🐎💤😀🍺😁😴📺☹😲👍🎭💚🍆🍋🔵🏁🔴🔔🧐👰☎🏆🤡🐠📲🙋📌🐬✍🔑📱💰🐱💧🎓🍕👟🐣👫🍑😸🍦👁🆗🎯📢🚶🦅🐧💢🏀🚫💑🐟🌽🏊🍟💝💲🐍🍥🐸☝♣👊⚓❌🐯🏈📰🌧👿🐳💷🐺📞🆒🍀🤐🚲🍔👹🙍🌷🙎🐥💵🔝📸⚠❓🎩✂🍼😑⬇⚾🍎💔🐔⚽💭🏌🐷🍍✖🍇📝🍊🐙👋🤔🥊🗽🐑🐘🐰💐🐴♀🐦🍓✏👂🏴👇🆘😡🏉👩💌😺✝🐼🐒🐶👺🖕👬🍉🐻🐾⬅⏬▶👮🍌♂🔸👶🐮👪⛳🐐🎾🐕👴🐨🐊🔹©🎣👦👣👨👈💬⭕📹📷"
|
|
@@ -170,44 +170,22 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
|
|
|
170
170
|
if tab_index is not None:
|
|
171
171
|
element.component_instance.tab_index = tab_index
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
ctx = get_script_run_ctx()
|
|
191
|
-
|
|
192
|
-
if key is None:
|
|
193
|
-
marshall_element_args()
|
|
194
|
-
computed_id = compute_and_register_element_id(
|
|
195
|
-
"component_instance",
|
|
196
|
-
user_key=key,
|
|
197
|
-
dg=dg,
|
|
198
|
-
name=self.name,
|
|
199
|
-
url=self.url,
|
|
200
|
-
json_args=serialized_json_args,
|
|
201
|
-
special_args=special_args,
|
|
202
|
-
)
|
|
203
|
-
else:
|
|
204
|
-
computed_id = compute_and_register_element_id(
|
|
205
|
-
"component_instance",
|
|
206
|
-
user_key=key,
|
|
207
|
-
dg=dg,
|
|
208
|
-
name=self.name,
|
|
209
|
-
url=self.url,
|
|
210
|
-
)
|
|
173
|
+
element.component_instance.json_args = serialized_json_args
|
|
174
|
+
element.component_instance.special_args.extend(special_args)
|
|
175
|
+
|
|
176
|
+
computed_id = compute_and_register_element_id(
|
|
177
|
+
"component_instance",
|
|
178
|
+
user_key=key,
|
|
179
|
+
# Ensure that the component identity is kept stable when key is provided,
|
|
180
|
+
# Only the name and url are whitelisted to result in a new identity
|
|
181
|
+
# if they are changed.
|
|
182
|
+
key_as_main_identity={"name", "url"},
|
|
183
|
+
dg=dg,
|
|
184
|
+
name=self.name,
|
|
185
|
+
url=self.url,
|
|
186
|
+
json_args=serialized_json_args,
|
|
187
|
+
special_args=special_args,
|
|
188
|
+
)
|
|
211
189
|
element.component_instance.id = computed_id
|
|
212
190
|
|
|
213
191
|
def deserialize_component(ui_value: Any) -> Any:
|
|
@@ -218,15 +196,12 @@ And if you're using Streamlit Cloud, add "pyarrow" to your requirements.txt."""
|
|
|
218
196
|
element.component_instance.id,
|
|
219
197
|
deserializer=deserialize_component,
|
|
220
198
|
serializer=lambda x: x,
|
|
221
|
-
ctx=
|
|
199
|
+
ctx=get_script_run_ctx(),
|
|
222
200
|
on_change_handler=on_change,
|
|
223
201
|
value_type="json_value",
|
|
224
202
|
)
|
|
225
203
|
widget_value = component_state.value
|
|
226
204
|
|
|
227
|
-
if key is not None:
|
|
228
|
-
marshall_element_args()
|
|
229
|
-
|
|
230
205
|
if widget_value is None:
|
|
231
206
|
widget_value = default
|
|
232
207
|
elif isinstance(widget_value, ArrowTableProto):
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
"""Register the st.components.v2 API namespace."""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from typing import TYPE_CHECKING, Any
|
|
20
|
+
|
|
21
|
+
from streamlit.components.v2.component_definition_resolver import (
|
|
22
|
+
build_definition_with_validation,
|
|
23
|
+
)
|
|
24
|
+
from streamlit.components.v2.get_bidi_component_manager import (
|
|
25
|
+
get_bidi_component_manager,
|
|
26
|
+
)
|
|
27
|
+
from streamlit.errors import StreamlitAPIException
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from streamlit.components.v2.types import BidiComponentCallable
|
|
31
|
+
|
|
32
|
+
if TYPE_CHECKING:
|
|
33
|
+
from collections.abc import Callable
|
|
34
|
+
|
|
35
|
+
from streamlit.components.v2.bidi_component import BidiComponentResult
|
|
36
|
+
from streamlit.elements.lib.layout_utils import Height, Width
|
|
37
|
+
from streamlit.runtime.state.common import WidgetCallback
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _register_component(
|
|
41
|
+
name: str,
|
|
42
|
+
html: str | None = None,
|
|
43
|
+
css: str | None = None,
|
|
44
|
+
js: str | None = None,
|
|
45
|
+
) -> str:
|
|
46
|
+
"""Register a component and return its fully qualified key.
|
|
47
|
+
|
|
48
|
+
This shared function handles the component registration and constructing a
|
|
49
|
+
validated definition against any pre-registered components from
|
|
50
|
+
``pyproject.toml``.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
name : str
|
|
55
|
+
A short, descriptive identifier for the component.
|
|
56
|
+
html : str or None
|
|
57
|
+
Inline HTML markup for the component root.
|
|
58
|
+
css : str | None
|
|
59
|
+
Either inline CSS (string) or an asset-dir-relative path/glob to a
|
|
60
|
+
``.css`` file declared in the component's ``asset_dir``. Globs are
|
|
61
|
+
allowed and must resolve to exactly one file within ``asset_dir``.
|
|
62
|
+
js : str | None
|
|
63
|
+
Either inline JavaScript (string) or an asset-dir-relative path/glob to
|
|
64
|
+
a ``.js`` file declared in the component's ``asset_dir``. Globs are
|
|
65
|
+
allowed and must resolve to exactly one file within ``asset_dir``.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
str
|
|
70
|
+
The fully qualified component key in the form ``<module_name>.<n>``.
|
|
71
|
+
|
|
72
|
+
Raises
|
|
73
|
+
------
|
|
74
|
+
StreamlitAPIException
|
|
75
|
+
If ``css`` or ``js`` parameters are not strings or None.
|
|
76
|
+
"""
|
|
77
|
+
# Parameter type guards: only strings or None are supported for js/css
|
|
78
|
+
for _param_name, _param_value in (("css", css), ("js", js)):
|
|
79
|
+
if _param_value is not None and not isinstance(_param_value, str):
|
|
80
|
+
raise StreamlitAPIException(
|
|
81
|
+
f"{_param_name} parameter must be a string or None. Pass a string path or glob."
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
component_key = name
|
|
85
|
+
|
|
86
|
+
manager = get_bidi_component_manager()
|
|
87
|
+
manager.register(
|
|
88
|
+
build_definition_with_validation(
|
|
89
|
+
manager=manager,
|
|
90
|
+
component_key=component_key,
|
|
91
|
+
html=html,
|
|
92
|
+
css=css,
|
|
93
|
+
js=js,
|
|
94
|
+
)
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
# Record API inputs for future re-resolution on file changes
|
|
98
|
+
manager.record_api_inputs(component_key, css, js)
|
|
99
|
+
|
|
100
|
+
return component_key
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _create_component_callable(
|
|
104
|
+
name: str,
|
|
105
|
+
*,
|
|
106
|
+
html: str | None = None,
|
|
107
|
+
css: str | None = None,
|
|
108
|
+
js: str | None = None,
|
|
109
|
+
) -> Callable[..., Any]:
|
|
110
|
+
"""Create a component callable, handling both lookup and registration cases.
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
name : str
|
|
115
|
+
A short, descriptive identifier for the component.
|
|
116
|
+
html : str | None
|
|
117
|
+
Inline HTML markup for the component root.
|
|
118
|
+
css : str | None
|
|
119
|
+
Inline CSS (string) or a string path/glob to a file under ``asset_dir``;
|
|
120
|
+
see :func:`_register_component` for path validation semantics.
|
|
121
|
+
js : str | None
|
|
122
|
+
Inline JavaScript (string) or a string path/glob to a file under
|
|
123
|
+
``asset_dir``; see :func:`_register_component` for path validation semantics.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
Callable[..., Any]
|
|
128
|
+
A function that, when called inside a Streamlit script, mounts the
|
|
129
|
+
component and returns its state.
|
|
130
|
+
|
|
131
|
+
Raises
|
|
132
|
+
------
|
|
133
|
+
StreamlitAPIException
|
|
134
|
+
If a component is not found in the registry.
|
|
135
|
+
"""
|
|
136
|
+
component_key = _register_component(name=name, html=html, css=css, js=js)
|
|
137
|
+
|
|
138
|
+
# The inner callable that mounts the component.
|
|
139
|
+
def _mount_component(
|
|
140
|
+
*,
|
|
141
|
+
key: str | None = None,
|
|
142
|
+
data: Any | None = None,
|
|
143
|
+
default: dict[str, Any] | None = None,
|
|
144
|
+
width: Width = "stretch",
|
|
145
|
+
height: Height = "content",
|
|
146
|
+
isolate_styles: bool = True,
|
|
147
|
+
**on_callbacks: WidgetCallback | None,
|
|
148
|
+
) -> BidiComponentResult:
|
|
149
|
+
"""Mount the component.
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
key : str or None
|
|
154
|
+
An optional string to use as the unique key for the component.
|
|
155
|
+
data : Any or None
|
|
156
|
+
Data to pass to the component (JSON-serializable).
|
|
157
|
+
default : dict[str, Any] or None
|
|
158
|
+
A dictionary of default values for state properties. Keys must
|
|
159
|
+
correspond to valid state names (those with on_*_change callbacks).
|
|
160
|
+
width : Width
|
|
161
|
+
The width of the component.
|
|
162
|
+
height : Height
|
|
163
|
+
The height of the component.
|
|
164
|
+
isolate_styles : bool
|
|
165
|
+
Whether to sandbox the component styles in a shadow-root. Defaults to
|
|
166
|
+
True.
|
|
167
|
+
**on_callbacks : WidgetCallback
|
|
168
|
+
Callback functions for handling component events. Use pattern
|
|
169
|
+
on_{state_name}_change (e.g., on_click_change, on_value_change).
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
BidiComponentResult
|
|
174
|
+
Component state.
|
|
175
|
+
"""
|
|
176
|
+
import streamlit as st
|
|
177
|
+
|
|
178
|
+
return st._bidi_component(
|
|
179
|
+
component_key,
|
|
180
|
+
key=key,
|
|
181
|
+
isolate_styles=isolate_styles,
|
|
182
|
+
data=data,
|
|
183
|
+
default=default,
|
|
184
|
+
width=width,
|
|
185
|
+
height=height,
|
|
186
|
+
**on_callbacks,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Ensure the function remains compatible with the shared public callable type.
|
|
190
|
+
# Static type assertion to ensure the callable matches the shared signature
|
|
191
|
+
_typed_check_mount_component: BidiComponentCallable = _mount_component
|
|
192
|
+
|
|
193
|
+
return _mount_component
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def component(
|
|
197
|
+
name: str,
|
|
198
|
+
*,
|
|
199
|
+
html: str | None = None,
|
|
200
|
+
css: str | None = None,
|
|
201
|
+
js: str | None = None,
|
|
202
|
+
) -> BidiComponentCallable:
|
|
203
|
+
'''Register an ``st.components.v2`` component and return a callable to mount it.
|
|
204
|
+
|
|
205
|
+
A component must have HTML, JavaScript, or both. If you want a component
|
|
206
|
+
with only CSS, use ``st.html`` instead.
|
|
207
|
+
|
|
208
|
+
If your component is defined in an installed package, you can declare an
|
|
209
|
+
asset directory (``asset_dir``) through ``pyproject.toml`` files in the
|
|
210
|
+
package. This allows you to serve component assets and reference them by
|
|
211
|
+
path or glob in the ``html``, ``css``, and ``js`` parameters. Otherwise,
|
|
212
|
+
you must provide raw HTML, CSS, and/or JavaScript strings directly to these
|
|
213
|
+
parameters.
|
|
214
|
+
|
|
215
|
+
.. important::
|
|
216
|
+
When using paths or globs to define one or more component assets, the
|
|
217
|
+
paths must be relative to the component's ``asset_dir`` as declared in
|
|
218
|
+
the component manifest. This is only possible for installed components.
|
|
219
|
+
|
|
220
|
+
For security reasons, absolute paths and path traversals are rejected.
|
|
221
|
+
Because of runtime constraints, paths and globs must be provided as
|
|
222
|
+
strings and not ``Path`` objects.
|
|
223
|
+
|
|
224
|
+
Parameters
|
|
225
|
+
----------
|
|
226
|
+
name : str
|
|
227
|
+
A short, descriptive identifier for the component. This is used
|
|
228
|
+
internally by Streamlit to manage instances of the component.
|
|
229
|
+
|
|
230
|
+
Component names must be unique across an app. The names of imported
|
|
231
|
+
components are prefixed by their module name to avoid collisions.
|
|
232
|
+
|
|
233
|
+
If you register multiple components with the same name, a warning is
|
|
234
|
+
logged and the last-registered component is used. Because this can lead
|
|
235
|
+
to unexpected behavior, ensure that component names are unique. If you
|
|
236
|
+
intend to have multiple instances of a component in one app, avoid
|
|
237
|
+
wrapping a component definition together with its mounting command so
|
|
238
|
+
you don't re-register your component with each instance.
|
|
239
|
+
|
|
240
|
+
html : str or None
|
|
241
|
+
Inline HTML markup for the component root. This can be one of the
|
|
242
|
+
following strings:
|
|
243
|
+
|
|
244
|
+
- Raw HTML. This doesn't require any ``<html>``, ``<head>``, or
|
|
245
|
+
``<body>`` tags; just provide the inner HTML.
|
|
246
|
+
- A path or glob to an HTML file, relative to the component's
|
|
247
|
+
asset directory.
|
|
248
|
+
|
|
249
|
+
If any HTML depends on data passed at mount time, use a placeholder
|
|
250
|
+
element and populate it via JavaScript. Alternatively, you can append
|
|
251
|
+
a new element to the parent. For more information, see Example 2.
|
|
252
|
+
|
|
253
|
+
``html`` and ``js`` can't both be ``None``. At least one of them must
|
|
254
|
+
be provided.
|
|
255
|
+
|
|
256
|
+
css : str or None
|
|
257
|
+
Inline CSS. This can be one of the following strings:
|
|
258
|
+
|
|
259
|
+
- Raw CSS (without a ``<style>`` block).
|
|
260
|
+
- A path or glob to a CSS file, relative to the component's
|
|
261
|
+
asset directory.
|
|
262
|
+
|
|
263
|
+
js : str or None
|
|
264
|
+
Inline JavaScript. This can be one of the following strings:
|
|
265
|
+
|
|
266
|
+
- Raw JavaScript (without a ``<script>`` block).
|
|
267
|
+
- A path or glob to a JS file, relative to the component's
|
|
268
|
+
asset directory.
|
|
269
|
+
|
|
270
|
+
``html`` and ``js`` can't both be ``None``. At least one of them must
|
|
271
|
+
be provided.
|
|
272
|
+
|
|
273
|
+
Returns
|
|
274
|
+
-------
|
|
275
|
+
BidiComponentCallable
|
|
276
|
+
The component's mounting command.
|
|
277
|
+
|
|
278
|
+
This callable accepts the component parameters like ``key`` and
|
|
279
|
+
``data`` and returns a ``BidiComponentResult`` object with the
|
|
280
|
+
component's state. The mounting command can be included in a
|
|
281
|
+
user-friendly wrapper function to provide a simpler API. A mounting
|
|
282
|
+
command can be called multiple times in an app to create multiple
|
|
283
|
+
instances of the component.
|
|
284
|
+
|
|
285
|
+
Examples
|
|
286
|
+
--------
|
|
287
|
+
**Example 1: Create a JavaScript-only component that captures link clicks**
|
|
288
|
+
|
|
289
|
+
You can create a simple component that allows inline links to communicate
|
|
290
|
+
with Python. Normally, clicking links in a Streamlit app would start a new
|
|
291
|
+
session. This component captures link clicks and sends them to Python as
|
|
292
|
+
trigger values.
|
|
293
|
+
|
|
294
|
+
.. code-block:: python
|
|
295
|
+
|
|
296
|
+
import streamlit as st
|
|
297
|
+
|
|
298
|
+
JS = """
|
|
299
|
+
export default function(component) {
|
|
300
|
+
const { setTriggerValue } = component;
|
|
301
|
+
const links = document.querySelectorAll('a[href="#"]');
|
|
302
|
+
|
|
303
|
+
links.forEach((link) => {
|
|
304
|
+
link.onclick = (e) => {
|
|
305
|
+
setTriggerValue('clicked', link.innerHTML);
|
|
306
|
+
};
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
"""
|
|
310
|
+
|
|
311
|
+
my_component = st.components.v2.component(
|
|
312
|
+
"inline_links",
|
|
313
|
+
js=JS,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
result = my_component(on_clicked_change=lambda: None)
|
|
317
|
+
|
|
318
|
+
st.markdown(
|
|
319
|
+
"Components aren't [sandboxed](#), so you can write JS that [interacts](#) with the main [document](#)."
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
if result.clicked:
|
|
323
|
+
st.write(f"You clicked {result.clicked}!")
|
|
324
|
+
|
|
325
|
+
.. output ::
|
|
326
|
+
https://doc-components-markdown-links.streamlit.app/
|
|
327
|
+
height: 250px
|
|
328
|
+
|
|
329
|
+
**Example 2: Display a paragraph with custom inline links**
|
|
330
|
+
|
|
331
|
+
If you want to dynamically pass custom data from inline links, you can pass
|
|
332
|
+
HTML to the ``data`` parameter of the component's mount command. When a
|
|
333
|
+
link is clicked, the component sets a trigger value from the link's
|
|
334
|
+
``data-link`` HTML attribute.
|
|
335
|
+
|
|
336
|
+
.. warning::
|
|
337
|
+
|
|
338
|
+
If you directly modify the inner HTML of the parent element, you will
|
|
339
|
+
overwrite the HTML and CSS passed to the component. Instead, create a
|
|
340
|
+
new child element and set its inner HTML. You can create the
|
|
341
|
+
placeholder dynamically in JavaScript or include it in the ``html``
|
|
342
|
+
parameter.
|
|
343
|
+
|
|
344
|
+
.. code-block:: python
|
|
345
|
+
|
|
346
|
+
import streamlit as st
|
|
347
|
+
|
|
348
|
+
CSS = """
|
|
349
|
+
a {
|
|
350
|
+
color: var(--st-link-color);
|
|
351
|
+
}
|
|
352
|
+
"""
|
|
353
|
+
|
|
354
|
+
JS = """
|
|
355
|
+
export default function(component) {
|
|
356
|
+
const { data, setTriggerValue, parentElement } = component;
|
|
357
|
+
const newElement = document.createElement('div');
|
|
358
|
+
parentElement.appendChild(newElement);
|
|
359
|
+
newElement.innerHTML = data;
|
|
360
|
+
|
|
361
|
+
const links = newElement.querySelectorAll('a');
|
|
362
|
+
|
|
363
|
+
links.forEach((link) => {
|
|
364
|
+
link.onclick = (e) => {
|
|
365
|
+
setTriggerValue('clicked', link.getAttribute('data-link'));
|
|
366
|
+
};
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
my_component = st.components.v2.component(
|
|
372
|
+
"inline_links",
|
|
373
|
+
css=CSS,
|
|
374
|
+
js=JS,
|
|
375
|
+
)
|
|
376
|
+
|
|
377
|
+
paragraph_html = """
|
|
378
|
+
<p>This is an example paragraph with inline links. To see the response in
|
|
379
|
+
Python, click on the <a href="#" data-link="link_1">first link</a> or
|
|
380
|
+
<a href="#" data-link="link_2">second link</a>.</p>
|
|
381
|
+
"""
|
|
382
|
+
|
|
383
|
+
result = my_component(data=paragraph_html, on_clicked_change=lambda: None)
|
|
384
|
+
if result.clicked == "link_1":
|
|
385
|
+
st.write("You clicked the first link!")
|
|
386
|
+
elif result.clicked == "link_2":
|
|
387
|
+
st.write("You clicked the second link!")
|
|
388
|
+
|
|
389
|
+
.. output ::
|
|
390
|
+
https://doc-components-custom-anchors.streamlit.app/
|
|
391
|
+
height: 250px
|
|
392
|
+
|
|
393
|
+
**Example 3: Display an interactive SVG image**
|
|
394
|
+
|
|
395
|
+
You can create a component that displays an SVG image with clickable
|
|
396
|
+
shapes. When a shape is clicked, the component sends the shape type to
|
|
397
|
+
Python as a trigger value.
|
|
398
|
+
|
|
399
|
+
.. code-block:: python
|
|
400
|
+
|
|
401
|
+
import streamlit as st
|
|
402
|
+
|
|
403
|
+
HTML = """
|
|
404
|
+
<p>Click on the triangle, square, or circle to interact with the shapes:</p>
|
|
405
|
+
|
|
406
|
+
<svg width="400" height="300">
|
|
407
|
+
<polygon points="100,50 50,150 150,150" data-shape="triangle"></polygon>
|
|
408
|
+
<rect x="200" y="75" width="100" height="100" data-shape="square"></rect>
|
|
409
|
+
<circle cx="125" cy="225" r="40" data-shape="circle"></circle>
|
|
410
|
+
</svg>
|
|
411
|
+
"""
|
|
412
|
+
|
|
413
|
+
JS = """
|
|
414
|
+
export default function(component) {
|
|
415
|
+
const { setTriggerValue, parentElement } = component;
|
|
416
|
+
const shapes = parentElement.querySelectorAll('[data-shape]');
|
|
417
|
+
|
|
418
|
+
shapes.forEach((shape) => {
|
|
419
|
+
shape.onclick = (e) => {
|
|
420
|
+
setTriggerValue('clicked', shape.getAttribute('data-shape'));
|
|
421
|
+
};
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
"""
|
|
425
|
+
|
|
426
|
+
CSS = """
|
|
427
|
+
polygon, rect, circle {
|
|
428
|
+
stroke: var(--st-primary-color);
|
|
429
|
+
stroke-width: 2;
|
|
430
|
+
fill: transparent;
|
|
431
|
+
cursor: pointer;
|
|
432
|
+
}
|
|
433
|
+
polygon:hover, rect:hover, circle:hover {
|
|
434
|
+
fill: var(--st-secondary-background-color);
|
|
435
|
+
}
|
|
436
|
+
"""
|
|
437
|
+
|
|
438
|
+
my_component = st.components.v2.component(
|
|
439
|
+
"clickable_svg",
|
|
440
|
+
html=HTML,
|
|
441
|
+
css=CSS,
|
|
442
|
+
js=JS,
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
result = my_component(on_clicked_change=lambda: None)
|
|
446
|
+
result
|
|
447
|
+
|
|
448
|
+
.. output ::
|
|
449
|
+
https://doc-components-interactive-svg.streamlit.app/
|
|
450
|
+
height: 550px
|
|
451
|
+
|
|
452
|
+
'''
|
|
453
|
+
return _create_component_callable(name, html=html, css=css, js=js)
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
__all__ = [
|
|
457
|
+
"component",
|
|
458
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from streamlit.components.v2.bidi_component.main import BidiComponentMixin
|
|
18
|
+
from streamlit.components.v2.bidi_component.state import BidiComponentResult
|
|
19
|
+
|
|
20
|
+
__all__ = ["BidiComponentMixin", "BidiComponentResult"]
|