streamlit 1.48.1__py3-none-any.whl → 1.49.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 +3 -10
- streamlit/commands/logo.py +4 -3
- streamlit/commands/navigation.py +1 -1
- streamlit/commands/page_config.py +4 -1
- streamlit/components/v1/custom_component.py +2 -2
- streamlit/config.py +82 -1
- streamlit/connections/snowflake_connection.py +3 -1
- streamlit/delta_generator.py +3 -0
- streamlit/elements/arrow.py +155 -70
- streamlit/elements/bokeh_chart.py +13 -3
- streamlit/elements/deck_gl_json_chart.py +0 -1
- streamlit/elements/dialog_decorator.py +7 -59
- streamlit/elements/form.py +10 -1
- streamlit/elements/graphviz_chart.py +57 -6
- streamlit/elements/heading.py +17 -16
- streamlit/elements/image.py +64 -37
- streamlit/elements/layouts.py +2 -2
- streamlit/elements/lib/built_in_chart_utils.py +2 -5
- streamlit/elements/lib/column_config_utils.py +18 -4
- streamlit/elements/lib/column_types.py +75 -30
- streamlit/elements/lib/dialog.py +3 -3
- streamlit/elements/lib/image_utils.py +19 -11
- streamlit/elements/lib/layout_utils.py +15 -2
- streamlit/elements/lib/utils.py +20 -41
- streamlit/elements/markdown.py +7 -6
- streamlit/elements/media.py +6 -13
- streamlit/elements/metric.py +78 -1
- streamlit/elements/pdf.py +192 -0
- streamlit/elements/plotly_chart.py +3 -2
- streamlit/elements/pyplot.py +53 -11
- streamlit/elements/toast.py +81 -5
- streamlit/elements/vega_charts.py +3 -8
- streamlit/elements/widgets/audio_input.py +0 -1
- streamlit/elements/widgets/button.py +0 -4
- streamlit/elements/widgets/button_group.py +5 -4
- streamlit/elements/widgets/camera_input.py +0 -1
- streamlit/elements/widgets/chat.py +11 -13
- streamlit/elements/widgets/checkbox.py +0 -1
- streamlit/elements/widgets/color_picker.py +0 -1
- streamlit/elements/widgets/data_editor.py +142 -62
- streamlit/elements/widgets/file_uploader.py +74 -37
- streamlit/elements/widgets/multiselect.py +0 -1
- streamlit/elements/widgets/number_input.py +0 -1
- streamlit/elements/widgets/radio.py +0 -1
- streamlit/elements/widgets/select_slider.py +0 -1
- streamlit/elements/widgets/selectbox.py +0 -1
- streamlit/elements/widgets/slider.py +0 -1
- streamlit/elements/widgets/text_widgets.py +0 -2
- streamlit/elements/widgets/time_widgets.py +0 -2
- streamlit/errors.py +11 -0
- streamlit/material_icon_names.py +1 -1
- streamlit/proto/Arrow_pb2.py +14 -8
- streamlit/proto/Arrow_pb2.pyi +11 -3
- streamlit/proto/Block_pb2.py +16 -16
- streamlit/proto/Block_pb2.pyi +2 -0
- streamlit/proto/ChatInput_pb2.py +3 -3
- streamlit/proto/ChatInput_pb2.pyi +2 -0
- streamlit/proto/FileUploader_pb2.py +2 -2
- streamlit/proto/FileUploader_pb2.pyi +5 -1
- streamlit/proto/GraphVizChart_pb2.py +4 -2
- streamlit/proto/GraphVizChart_pb2.pyi +1 -1
- streamlit/proto/Image_pb2.py +4 -2
- streamlit/proto/Image_pb2.pyi +1 -10
- streamlit/proto/Metric_pb2.py +8 -6
- streamlit/proto/Metric_pb2.pyi +34 -10
- streamlit/proto/Toast_pb2.py +2 -2
- streamlit/proto/Toast_pb2.pyi +10 -1
- streamlit/runtime/caching/__init__.py +14 -2
- streamlit/runtime/caching/cache_data_api.py +0 -17
- streamlit/runtime/caching/cache_resource_api.py +0 -16
- streamlit/runtime/caching/cached_message_replay.py +8 -20
- streamlit/runtime/caching/hashing.py +31 -1
- streamlit/runtime/credentials.py +4 -4
- streamlit/runtime/fragment.py +0 -42
- streamlit/runtime/websocket_session_manager.py +1 -1
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +224 -252
- streamlit/static/static/css/{index.CJVRHjQZ.css → index.C8X8rNzw.css} +1 -1
- streamlit/static/static/css/index.COe1010n.css +1 -0
- streamlit/static/static/js/{ErrorOutline.esm.DjObtx4K.js → ErrorOutline.esm.u9XvzxL8.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.Bz9nxNC5.js → FileDownload.esm.CaRyZ-b2.js} +1 -1
- streamlit/static/static/js/FileHelper.Dk2SwIi3.js +5 -0
- streamlit/static/static/js/FormClearHelper.l_UPPvkg.js +1 -0
- streamlit/static/static/js/{Hooks.DEoLCfOE.js → Hooks.BxrVEftw.js} +1 -1
- streamlit/static/static/js/InputInstructions.C254RU9X.js +1 -0
- streamlit/static/static/js/Particles.DkY6FDnc.js +1 -0
- streamlit/static/static/js/ProgressBar.BPtSM82n.js +2 -0
- streamlit/static/static/js/Toolbar.BO_3WBaS.js +1 -0
- streamlit/static/static/js/{base-input.BmvSaPd2.js → base-input.egUI4LjJ.js} +4 -4
- streamlit/static/static/js/{checkbox.Cgxgc0et.js → checkbox.ButpszcE.js} +2 -2
- streamlit/static/static/js/createSuper.DYJA5xa6.js +1 -0
- streamlit/static/static/js/data-grid-overlay-editor.C9gQLEnU.js +1 -0
- streamlit/static/static/js/{downloader.M6jQeNDf.js → downloader.B3TjsSPZ.js} +1 -1
- streamlit/static/static/js/es6.BYSNuG4D.js +2 -0
- streamlit/static/static/js/iframeResizer.contentWindow.CNPHJsF2.js +1 -0
- streamlit/static/static/js/index.0tDq1WXk.js +1 -0
- streamlit/static/static/js/index.BBnWuh07.js +976 -0
- streamlit/static/static/js/index.BDZorv41.js +1 -0
- streamlit/static/static/js/{index.CbdWnLqS.js → index.BH79B25f.js} +3 -3
- streamlit/static/static/js/index.BeTC4Yl-.js +197 -0
- streamlit/static/static/js/index.BnOd05Ko.js +2 -0
- streamlit/static/static/js/index.BoJaJReB.js +1 -0
- streamlit/static/static/js/index.Bp1Of6L8.js +1 -0
- streamlit/static/static/js/index.Bpe4-O2W.js +1 -0
- streamlit/static/static/js/index.BrD9sbpx.js +1 -0
- streamlit/static/static/js/index.C1qCS-sd.js +1 -0
- streamlit/static/static/js/index.C3EXAI-u.js +1 -0
- streamlit/static/static/js/index.C77g9sAQ.js +3 -0
- streamlit/static/static/js/{index.BXDq9dj4.js → index.CFePF7s4.js} +1 -1
- streamlit/static/static/js/index.CFjU0x00.js +1 -0
- streamlit/static/static/js/index.Ca3y4ztK.js +1 -0
- streamlit/static/static/js/{index.CgZDfhN4.js → index.Cb9gN2T2.js} +2 -2
- streamlit/static/static/js/{index.tsvTLdio.js → index.CbwuUwu4.js} +9 -9
- streamlit/static/static/js/index.CeXLlclc.js +1 -0
- streamlit/static/static/js/index.CfiZGqj3.js +3 -0
- streamlit/static/static/js/index.CjQnYKID.js +1 -0
- streamlit/static/static/js/index.Cl_966eE.js +3858 -0
- streamlit/static/static/js/{index.Cqa4gqqN.js → index.CqSRo6zQ.js} +1 -1
- streamlit/static/static/js/index.CuEFSQ-o.js +1 -0
- streamlit/static/static/js/index.D4jR1m1z.js +1 -0
- streamlit/static/static/js/index.DGcW849X.js +1 -0
- streamlit/static/static/js/index.DKb-BAE2.js +1 -0
- streamlit/static/static/js/index.DP1rDFP0.js +1 -0
- streamlit/static/static/js/{index.D1EayrNh.js → index.DStzYLqM.js} +2 -2
- streamlit/static/static/js/index.DVKQKDLu.js +1 -0
- streamlit/static/static/js/index.DWedOrkQ.js +1 -0
- streamlit/static/static/js/index.DYbRPmVF.js +1 -0
- streamlit/static/static/js/index.DgpIMUsr.js +1 -0
- streamlit/static/static/js/index.DtwkPJs5.js +5367 -0
- streamlit/static/static/js/{index.D1jHqUJq.js → index.MQLQLR5Z.js} +1 -1
- streamlit/static/static/js/index.uInpwWAP.js +1 -0
- streamlit/static/static/js/index.z992t-BQ.js +7 -0
- streamlit/static/static/js/{input.DZd6EQlV.js → input.CbP5ZuQ7.js} +2 -2
- streamlit/static/static/js/{memory.ptkfuI71.js → memory.BuacVo2L.js} +1 -1
- streamlit/static/static/js/number-overlay-editor.BZb9zRl_.js +9 -0
- streamlit/static/static/js/{possibleConstructorReturn.Bd4ImlQ9.js → possibleConstructorReturn.DSM84rOS.js} +1 -1
- streamlit/static/static/js/{sandbox.DsH8LuID.js → sandbox.C480llMG.js} +1 -1
- streamlit/static/static/js/{timepicker.QVekV78C.js → timepicker.BunxCVp7.js} +4 -4
- streamlit/static/static/js/{toConsumableArray.BJvaP8gb.js → toConsumableArray.B4o8rEx1.js} +3 -3
- streamlit/static/static/js/uniqueId.tii0yosY.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.DB3vMS9V.js → useBasicWidgetState.Bnm4FD6K.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.CBkGkaRt.js → useTextInputAutoExpand.Dgtwc1m0.js} +2 -2
- streamlit/static/static/js/useUpdateUiValue.DjXdMFGw.js +1 -0
- streamlit/static/static/js/withFullScreenWrapper.0cy2pVf5.js +1 -0
- streamlit/static/static/media/MaterialSymbols-Rounded.CBxVaFdk.woff2 +0 -0
- streamlit/user_info.py +3 -1
- streamlit/web/server/browser_websocket_handler.py +15 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/METADATA +4 -2
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/RECORD +153 -156
- streamlit/static/static/css/index.CQt5TjGB.css +0 -1
- streamlit/static/static/js/FileHelper.BrQvUXVD.js +0 -5
- streamlit/static/static/js/FormClearHelper.DF4gFAOO.js +0 -1
- streamlit/static/static/js/InputInstructions.D8zoMog9.js +0 -1
- streamlit/static/static/js/Particles.CCFySwdL.js +0 -1
- streamlit/static/static/js/ProgressBar.COK9j1l0.js +0 -2
- streamlit/static/static/js/Toolbar.Dt4jIKlY.js +0 -1
- streamlit/static/static/js/createSuper.siQeagI2.js +0 -1
- streamlit/static/static/js/data-grid-overlay-editor.Ct51iCb_.js +0 -1
- streamlit/static/static/js/es6.CMaUdEZ5.js +0 -2
- streamlit/static/static/js/iframeResizer.contentWindow.C33BryyP.js +0 -1
- streamlit/static/static/js/index.8GJD0eeD.js +0 -1
- streamlit/static/static/js/index.8QEYHMQD.js +0 -1
- streamlit/static/static/js/index.Ay41Wnu9.js +0 -1
- streamlit/static/static/js/index.BLiKiJ7_.js +0 -1
- streamlit/static/static/js/index.BT78cJmU.js +0 -1
- streamlit/static/static/js/index.BdGvnhlM.js +0 -1
- streamlit/static/static/js/index.BfasrT0d.js +0 -1
- streamlit/static/static/js/index.CCdtFMFG.js +0 -1
- streamlit/static/static/js/index.CFRGZDz1.js +0 -1
- streamlit/static/static/js/index.CFSFYiPA.js +0 -5366
- streamlit/static/static/js/index.CeiIiXap.js +0 -1
- streamlit/static/static/js/index.CzX2xpyc.js +0 -1
- streamlit/static/static/js/index.D1ErX5go.js +0 -2
- streamlit/static/static/js/index.D5gweoL5.js +0 -7
- streamlit/static/static/js/index.DByVKZgq.js +0 -1
- streamlit/static/static/js/index.DEND45D1.js +0 -3
- streamlit/static/static/js/index.DKN5MVff.js +0 -781
- streamlit/static/static/js/index.DfoxW1gP.js +0 -3855
- streamlit/static/static/js/index.Dtf1Ac0x.js +0 -1
- streamlit/static/static/js/index.DxrLhpeO.js +0 -1
- streamlit/static/static/js/index.J7o-_HIh.js +0 -1
- streamlit/static/static/js/index.LU8juINp.js +0 -197
- streamlit/static/static/js/index.L_N2iylt.js +0 -1
- streamlit/static/static/js/index.PZUX2kRz.js +0 -3
- streamlit/static/static/js/index.ROjU6K0k.js +0 -1
- streamlit/static/static/js/index.WSNLkF94.js +0 -1
- streamlit/static/static/js/index.X5W3gJLn.js +0 -1
- streamlit/static/static/js/index.k9LYqfSL.js +0 -1
- streamlit/static/static/js/index.pnHtHv_c.js +0 -203
- streamlit/static/static/js/index.tPUXqsfW.js +0 -1
- streamlit/static/static/js/mergeWith.GRNk8iwv.js +0 -1
- streamlit/static/static/js/number-overlay-editor.DXS2qb1U.js +0 -9
- streamlit/static/static/js/threshold.DjX0wlsa.js +0 -1
- streamlit/static/static/js/timer.CAwTRJ_g.js +0 -1
- streamlit/static/static/js/uniqueId.D_5M8Dgf.js +0 -1
- streamlit/static/static/js/useUpdateUiValue.C7ZKpLQK.js +0 -1
- streamlit/static/static/js/value.CgPGBV_l.js +0 -1
- streamlit/static/static/js/withFullScreenWrapper.C-gXt0Rl.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.DsbC8sYI.woff2 +0 -0
- {streamlit-1.48.1.data → streamlit-1.49.0.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/WHEEL +0 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/entry_points.txt +0 -0
- {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/top_level.txt +0 -0
streamlit/elements/metric.py
CHANGED
|
@@ -20,6 +20,7 @@ from typing import TYPE_CHECKING, Any, Literal, Union, cast
|
|
|
20
20
|
|
|
21
21
|
from typing_extensions import TypeAlias
|
|
22
22
|
|
|
23
|
+
from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
|
|
23
24
|
from streamlit.elements.lib.layout_utils import (
|
|
24
25
|
Height,
|
|
25
26
|
LayoutConfig,
|
|
@@ -62,11 +63,14 @@ class MetricMixin:
|
|
|
62
63
|
value: Value,
|
|
63
64
|
delta: Delta = None,
|
|
64
65
|
delta_color: DeltaColor = "normal",
|
|
66
|
+
*,
|
|
65
67
|
help: str | None = None,
|
|
66
68
|
label_visibility: LabelVisibility = "visible",
|
|
67
69
|
border: bool = False,
|
|
68
70
|
width: Width = "stretch",
|
|
69
71
|
height: Height = "content",
|
|
72
|
+
chart_data: OptionSequence[Any] | None = None,
|
|
73
|
+
chart_type: Literal["line", "bar", "area"] = "line",
|
|
70
74
|
) -> DeltaGenerator:
|
|
71
75
|
r"""Display a metric in big bold font, with an optional indicator of how the metric changed.
|
|
72
76
|
|
|
@@ -156,6 +160,22 @@ class MetricMixin:
|
|
|
156
160
|
the parent container, the width of the element matches the width
|
|
157
161
|
of the parent container.
|
|
158
162
|
|
|
163
|
+
chart_data : Iterable or None
|
|
164
|
+
A sequence of numeric values to display as a sparkline chart. If
|
|
165
|
+
this is ``None`` (default), no chart is displayed. The sequence can
|
|
166
|
+
be anything supported by ``st.dataframe``, including a ``list`` or
|
|
167
|
+
``set``. If the sequence is dataframe-like, the first column will
|
|
168
|
+
be used. Each value will be cast to ``float`` internally by
|
|
169
|
+
default.
|
|
170
|
+
|
|
171
|
+
chart_type : "line", "bar", or "area"
|
|
172
|
+
The type of sparkline chart to display. This can be one of the
|
|
173
|
+
following:
|
|
174
|
+
|
|
175
|
+
- ``"line"`` (default): A simple sparkline.
|
|
176
|
+
- ``"area"``: A sparkline with area shading.
|
|
177
|
+
- ``"bar"``: A bar chart.
|
|
178
|
+
|
|
159
179
|
Examples
|
|
160
180
|
--------
|
|
161
181
|
**Example 1: Show a metric**
|
|
@@ -192,7 +212,10 @@ class MetricMixin:
|
|
|
192
212
|
>>> st.metric(label="Gas price", value=4, delta=-0.5, delta_color="inverse")
|
|
193
213
|
>>>
|
|
194
214
|
>>> st.metric(
|
|
195
|
-
... label="Active developers",
|
|
215
|
+
... label="Active developers",
|
|
216
|
+
... value=123,
|
|
217
|
+
... delta=123,
|
|
218
|
+
... delta_color="off",
|
|
196
219
|
... )
|
|
197
220
|
|
|
198
221
|
.. output::
|
|
@@ -218,6 +241,33 @@ class MetricMixin:
|
|
|
218
241
|
https://doc-metric-example4.streamlit.app/
|
|
219
242
|
height: 350px
|
|
220
243
|
|
|
244
|
+
**Example 5: Show sparklines**
|
|
245
|
+
|
|
246
|
+
To show trends over time, add sparklines.
|
|
247
|
+
|
|
248
|
+
>>> import streamlit as st
|
|
249
|
+
>>> from numpy.random import default_rng as rng
|
|
250
|
+
>>>
|
|
251
|
+
>>> changes = list(rng(4).standard_normal(20))
|
|
252
|
+
>>> data = [sum(changes[:i]) for i in range(20)]
|
|
253
|
+
>>> delta = round(data[-1], 2)
|
|
254
|
+
>>>
|
|
255
|
+
>>> row = st.container(horizontal=True)
|
|
256
|
+
>>> with row:
|
|
257
|
+
>>> st.metric(
|
|
258
|
+
... "Line", 10, delta, chart_data=data, chart_type="line", border=True
|
|
259
|
+
... )
|
|
260
|
+
>>> st.metric(
|
|
261
|
+
... "Area", 10, delta, chart_data=data, chart_type="area", border=True
|
|
262
|
+
... )
|
|
263
|
+
>>> st.metric(
|
|
264
|
+
... "Bar", 10, delta, chart_data=data, chart_type="bar", border=True
|
|
265
|
+
... )
|
|
266
|
+
|
|
267
|
+
.. output::
|
|
268
|
+
https://doc-metric-example5.streamlit.app/
|
|
269
|
+
height: 300px
|
|
270
|
+
|
|
221
271
|
"""
|
|
222
272
|
maybe_raise_label_warnings(label, label_visibility)
|
|
223
273
|
|
|
@@ -238,6 +288,22 @@ class MetricMixin:
|
|
|
238
288
|
label_visibility
|
|
239
289
|
)
|
|
240
290
|
|
|
291
|
+
if chart_data is not None:
|
|
292
|
+
prepared_data: list[float] = []
|
|
293
|
+
for val in convert_anything_to_list(chart_data):
|
|
294
|
+
try:
|
|
295
|
+
prepared_data.append(float(val))
|
|
296
|
+
except Exception as ex: # noqa: PERF203
|
|
297
|
+
raise StreamlitAPIException(
|
|
298
|
+
"Only numeric values are supported for chart data sequence. The "
|
|
299
|
+
f"value '{val}' is of type {type(val)} and "
|
|
300
|
+
"cannot be converted to float."
|
|
301
|
+
) from ex
|
|
302
|
+
if len(prepared_data) > 0:
|
|
303
|
+
metric_proto.chart_data.extend(prepared_data)
|
|
304
|
+
|
|
305
|
+
metric_proto.chart_type = _parse_chart_type(chart_type)
|
|
306
|
+
|
|
241
307
|
validate_height(height, allow_content=True)
|
|
242
308
|
validate_width(width, allow_content=True)
|
|
243
309
|
layout_config = LayoutConfig(width=width, height=height)
|
|
@@ -249,6 +315,17 @@ class MetricMixin:
|
|
|
249
315
|
return cast("DeltaGenerator", self)
|
|
250
316
|
|
|
251
317
|
|
|
318
|
+
def _parse_chart_type(
|
|
319
|
+
chart_type: Literal["line", "bar", "area"],
|
|
320
|
+
) -> MetricProto.ChartType.ValueType:
|
|
321
|
+
if chart_type == "bar":
|
|
322
|
+
return MetricProto.ChartType.BAR
|
|
323
|
+
if chart_type == "area":
|
|
324
|
+
return MetricProto.ChartType.AREA
|
|
325
|
+
# Use line as default chart:
|
|
326
|
+
return MetricProto.ChartType.LINE
|
|
327
|
+
|
|
328
|
+
|
|
252
329
|
def _parse_label(label: str) -> str:
|
|
253
330
|
if not isinstance(label, str):
|
|
254
331
|
raise TypeError(
|
|
@@ -0,0 +1,192 @@
|
|
|
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
|
+
import io
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import TYPE_CHECKING, Any, Union, cast
|
|
20
|
+
|
|
21
|
+
from typing_extensions import TypeAlias
|
|
22
|
+
|
|
23
|
+
from streamlit import url_util
|
|
24
|
+
from streamlit.elements.lib.layout_utils import validate_height
|
|
25
|
+
from streamlit.errors import StreamlitAPIException
|
|
26
|
+
from streamlit.runtime.metrics_util import gather_metrics
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from streamlit.delta_generator import DeltaGenerator
|
|
30
|
+
from streamlit.elements.lib.layout_utils import HeightWithoutContent
|
|
31
|
+
|
|
32
|
+
PdfData: TypeAlias = Union[str, Path, bytes, io.BytesIO]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _get_pdf_component() -> Any | None:
|
|
36
|
+
"""Get the PDF custom component if available.
|
|
37
|
+
|
|
38
|
+
Returns
|
|
39
|
+
-------
|
|
40
|
+
Any | None
|
|
41
|
+
The pdf_viewer function if the streamlit-pdf component is available,
|
|
42
|
+
None otherwise.
|
|
43
|
+
"""
|
|
44
|
+
try:
|
|
45
|
+
import streamlit_pdf # type: ignore
|
|
46
|
+
|
|
47
|
+
return streamlit_pdf.pdf_viewer
|
|
48
|
+
except ImportError:
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class PdfMixin:
|
|
53
|
+
@gather_metrics("pdf")
|
|
54
|
+
def pdf(
|
|
55
|
+
self,
|
|
56
|
+
data: PdfData,
|
|
57
|
+
*,
|
|
58
|
+
height: HeightWithoutContent = 500,
|
|
59
|
+
key: str | None = None,
|
|
60
|
+
) -> DeltaGenerator:
|
|
61
|
+
"""Display a PDF viewer.
|
|
62
|
+
|
|
63
|
+
.. Important::
|
|
64
|
+
|
|
65
|
+
You must install |streamlit-pdf|_ to use this command. You can
|
|
66
|
+
install it as an extra with Streamlit:
|
|
67
|
+
|
|
68
|
+
.. code-block:: shell
|
|
69
|
+
|
|
70
|
+
pip install streamlit[pdf]
|
|
71
|
+
|
|
72
|
+
.. |streamlit-pdf| replace:: ``streamlit-pdf``
|
|
73
|
+
.. _streamlit-pdf: https://github.com/streamlit/streamlit-pdf
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
data : str, Path, BytesIO, or bytes
|
|
78
|
+
The PDF file to show. This can be one of the following:
|
|
79
|
+
|
|
80
|
+
- A URL (string) for a hosted PDF file.
|
|
81
|
+
- A path to a local PDF file. If you use a relative path, it must
|
|
82
|
+
be relative to the current working directory.
|
|
83
|
+
- A file-like object. For example, this can be an ``UploadedFile``
|
|
84
|
+
from ``st.file_uploader``, or this can be a local file opened
|
|
85
|
+
with ``open()``.
|
|
86
|
+
- Raw bytes data.
|
|
87
|
+
|
|
88
|
+
height : int or "stretch"
|
|
89
|
+
The height of the PDF viewer. This can be one of the following:
|
|
90
|
+
|
|
91
|
+
- An integer specifying the height in pixels: The viewer has a
|
|
92
|
+
fixed height. If the content is larger than the specified
|
|
93
|
+
height, scrolling is enabled. This is ``500`` by default.
|
|
94
|
+
- ``"stretch"``: The height of the viewer matches the height of
|
|
95
|
+
its content or the height of the parent container, whichever is
|
|
96
|
+
larger. If the viewer is not in a parent container, the height
|
|
97
|
+
of the viewer matches the height of its content.
|
|
98
|
+
|
|
99
|
+
Example
|
|
100
|
+
-------
|
|
101
|
+
>>> st.pdf("https://example.com/sample.pdf")
|
|
102
|
+
>>> st.pdf("https://example.com/sample.pdf", height=600)
|
|
103
|
+
"""
|
|
104
|
+
# Validate data parameter early
|
|
105
|
+
if data is None:
|
|
106
|
+
raise StreamlitAPIException(
|
|
107
|
+
"The PDF data cannot be None. Please provide a valid PDF file path, URL, "
|
|
108
|
+
"bytes data, or file-like object."
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Check if custom PDF component is available first
|
|
112
|
+
pdf_component = _get_pdf_component()
|
|
113
|
+
if pdf_component is None:
|
|
114
|
+
return self._show_pdf_warning()
|
|
115
|
+
|
|
116
|
+
return self._call_pdf_component(pdf_component, data, height, key)
|
|
117
|
+
|
|
118
|
+
def _call_pdf_component(
|
|
119
|
+
self,
|
|
120
|
+
pdf_component: Any,
|
|
121
|
+
data: PdfData,
|
|
122
|
+
height: HeightWithoutContent,
|
|
123
|
+
key: str | None,
|
|
124
|
+
) -> DeltaGenerator:
|
|
125
|
+
"""Call the custom PDF component with the provided data."""
|
|
126
|
+
# Validate height parameter after confirming component is available
|
|
127
|
+
validate_height(height, allow_content=False)
|
|
128
|
+
|
|
129
|
+
# Convert data to the format expected by pdf_viewer component
|
|
130
|
+
file_param: str | bytes
|
|
131
|
+
|
|
132
|
+
if isinstance(data, (str, Path)):
|
|
133
|
+
data_str = str(data).strip() # Strip whitespace from URLs
|
|
134
|
+
if url_util.is_url(data_str, allowed_schemas=("http", "https")):
|
|
135
|
+
# It's a URL - pass directly
|
|
136
|
+
file_param = data_str
|
|
137
|
+
else:
|
|
138
|
+
# It's a local file path - read the content as bytes for security
|
|
139
|
+
try:
|
|
140
|
+
with open(data_str, "rb") as file:
|
|
141
|
+
file_param = file.read()
|
|
142
|
+
except (FileNotFoundError, PermissionError) as e:
|
|
143
|
+
raise StreamlitAPIException(
|
|
144
|
+
f"Unable to read file '{data_str}': {e}"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
elif isinstance(data, bytes):
|
|
148
|
+
# Pass bytes directly - the component will handle uploading to media storage
|
|
149
|
+
file_param = data
|
|
150
|
+
elif hasattr(data, "read") and hasattr(data, "getvalue"):
|
|
151
|
+
# Handle BytesIO and similar
|
|
152
|
+
file_param = data.getvalue()
|
|
153
|
+
elif hasattr(data, "read"):
|
|
154
|
+
# Handle other file-like objects
|
|
155
|
+
file_param = data.read()
|
|
156
|
+
else:
|
|
157
|
+
# Provide a more helpful error message
|
|
158
|
+
raise StreamlitAPIException(
|
|
159
|
+
f"Unsupported data type for PDF: {type(data).__name__}. "
|
|
160
|
+
f"Please provide a file path (str or Path), URL (str), bytes data, "
|
|
161
|
+
f"or file-like object (such as BytesIO or UploadedFile)."
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Convert to component-compatible format
|
|
165
|
+
if height == "stretch":
|
|
166
|
+
# For stretch, we need to pass a special value the component understands
|
|
167
|
+
# This maintains compatibility with the component while using standard layout
|
|
168
|
+
component_height = "stretch"
|
|
169
|
+
else:
|
|
170
|
+
component_height = str(height)
|
|
171
|
+
|
|
172
|
+
result = pdf_component(
|
|
173
|
+
file=file_param,
|
|
174
|
+
height=component_height,
|
|
175
|
+
key=key,
|
|
176
|
+
)
|
|
177
|
+
return cast("DeltaGenerator", result)
|
|
178
|
+
|
|
179
|
+
def _show_pdf_warning(self) -> DeltaGenerator:
|
|
180
|
+
"""Raise an exception that the PDF component is not available."""
|
|
181
|
+
raise StreamlitAPIException(
|
|
182
|
+
"The PDF viewer requires the `streamlit-pdf` component to be installed.\n\n"
|
|
183
|
+
"Please run `pip install streamlit[pdf]` to install it.\n\n"
|
|
184
|
+
"For more information, see the Streamlit PDF documentation at "
|
|
185
|
+
"https://docs.streamlit.io/develop/api-reference/media/st.pdf."
|
|
186
|
+
# TODO: Update this URL when docs are updated
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def dg(self) -> DeltaGenerator:
|
|
191
|
+
"""Get our DeltaGenerator."""
|
|
192
|
+
return cast("DeltaGenerator", self)
|
|
@@ -333,7 +333,9 @@ class PlotlyMixin:
|
|
|
333
333
|
can install all charting dependencies (except Bokeh) as an extra
|
|
334
334
|
with Streamlit:
|
|
335
335
|
|
|
336
|
-
|
|
336
|
+
.. code-block:: shell
|
|
337
|
+
|
|
338
|
+
pip install streamlit[charts]
|
|
337
339
|
|
|
338
340
|
Parameters
|
|
339
341
|
----------
|
|
@@ -556,7 +558,6 @@ class PlotlyMixin:
|
|
|
556
558
|
plotly_chart_proto.id = compute_and_register_element_id(
|
|
557
559
|
"plotly_chart",
|
|
558
560
|
user_key=key,
|
|
559
|
-
form_id=plotly_chart_proto.form_id,
|
|
560
561
|
dg=self.dg,
|
|
561
562
|
plotly_spec=plotly_chart_proto.spec,
|
|
562
563
|
plotly_config=plotly_chart_proto.config,
|
streamlit/elements/pyplot.py
CHANGED
|
@@ -19,8 +19,12 @@ from __future__ import annotations
|
|
|
19
19
|
import io
|
|
20
20
|
from typing import TYPE_CHECKING, Any, cast
|
|
21
21
|
|
|
22
|
-
from streamlit.deprecation_util import
|
|
23
|
-
|
|
22
|
+
from streamlit.deprecation_util import (
|
|
23
|
+
make_deprecated_name_warning,
|
|
24
|
+
show_deprecation_warning,
|
|
25
|
+
)
|
|
26
|
+
from streamlit.elements.lib.image_utils import marshall_images
|
|
27
|
+
from streamlit.elements.lib.layout_utils import LayoutConfig, Width, validate_width
|
|
24
28
|
from streamlit.proto.Image_pb2 import ImageList as ImageListProto
|
|
25
29
|
from streamlit.runtime.metrics_util import gather_metrics
|
|
26
30
|
|
|
@@ -36,7 +40,9 @@ class PyplotMixin:
|
|
|
36
40
|
self,
|
|
37
41
|
fig: Figure | None = None,
|
|
38
42
|
clear_figure: bool | None = None,
|
|
39
|
-
|
|
43
|
+
*,
|
|
44
|
+
width: Width = "stretch",
|
|
45
|
+
use_container_width: bool | None = None,
|
|
40
46
|
**kwargs: Any,
|
|
41
47
|
) -> DeltaGenerator:
|
|
42
48
|
"""Display a matplotlib.pyplot figure.
|
|
@@ -46,7 +52,9 @@ class PyplotMixin:
|
|
|
46
52
|
install all charting dependencies (except Bokeh) as an extra with
|
|
47
53
|
Streamlit:
|
|
48
54
|
|
|
49
|
-
|
|
55
|
+
.. code-block:: shell
|
|
56
|
+
|
|
57
|
+
pip install streamlit[charts]
|
|
50
58
|
|
|
51
59
|
Parameters
|
|
52
60
|
----------
|
|
@@ -69,6 +77,19 @@ class PyplotMixin:
|
|
|
69
77
|
- If ``fig`` is not set, defaults to ``True``. This simulates Jupyter's
|
|
70
78
|
approach to matplotlib rendering.
|
|
71
79
|
|
|
80
|
+
width : "stretch", "content", or int
|
|
81
|
+
The width of the chart element. This can be one of the following:
|
|
82
|
+
|
|
83
|
+
- ``"stretch"`` (default): The width of the element matches the
|
|
84
|
+
width of the parent container.
|
|
85
|
+
- ``"content"``: The width of the element matches the
|
|
86
|
+
width of its content, but doesn't exceed the width of the parent
|
|
87
|
+
container.
|
|
88
|
+
- An integer specifying the width in pixels: The element has a
|
|
89
|
+
fixed width. If the specified width is greater than the width of
|
|
90
|
+
the parent container, the width of the element matches the width
|
|
91
|
+
of the parent container.
|
|
92
|
+
|
|
72
93
|
use_container_width : bool
|
|
73
94
|
Whether to override the figure's native width with the width of
|
|
74
95
|
the parent container. If ``use_container_width`` is ``True``
|
|
@@ -81,6 +102,12 @@ class PyplotMixin:
|
|
|
81
102
|
**kwargs : any
|
|
82
103
|
Arguments to pass to Matplotlib's savefig function.
|
|
83
104
|
|
|
105
|
+
.. deprecated::
|
|
106
|
+
``use_container_width`` is deprecated and will be removed in a
|
|
107
|
+
future release. For ``use_container_width=True``, use
|
|
108
|
+
``width="stretch"``. For ``use_container_width=False``, use
|
|
109
|
+
``width="content"``.
|
|
110
|
+
|
|
84
111
|
Example
|
|
85
112
|
-------
|
|
86
113
|
>>> import matplotlib.pyplot as plt
|
|
@@ -106,6 +133,21 @@ class PyplotMixin:
|
|
|
106
133
|
|
|
107
134
|
"""
|
|
108
135
|
|
|
136
|
+
if use_container_width is not None:
|
|
137
|
+
show_deprecation_warning(
|
|
138
|
+
make_deprecated_name_warning(
|
|
139
|
+
"use_container_width",
|
|
140
|
+
"width",
|
|
141
|
+
"2025-12-31",
|
|
142
|
+
"For `use_container_width=True`, use `width='stretch'`. "
|
|
143
|
+
"For `use_container_width=False`, use `width='content'`.",
|
|
144
|
+
include_st_prefix=False,
|
|
145
|
+
),
|
|
146
|
+
show_in_browser=False,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
width = "stretch" if use_container_width else "content"
|
|
150
|
+
|
|
109
151
|
if not fig:
|
|
110
152
|
show_deprecation_warning("""
|
|
111
153
|
Calling `st.pyplot()` without providing a figure argument has been deprecated
|
|
@@ -125,16 +167,19 @@ If you have a specific use case that requires this functionality, please let us
|
|
|
125
167
|
know via [issue on Github](https://github.com/streamlit/streamlit/issues).
|
|
126
168
|
""")
|
|
127
169
|
|
|
170
|
+
validate_width(width, allow_content=True)
|
|
171
|
+
layout_config = LayoutConfig(width=width)
|
|
172
|
+
|
|
128
173
|
image_list_proto = ImageListProto()
|
|
129
174
|
marshall(
|
|
130
175
|
self.dg._get_delta_path_str(),
|
|
131
176
|
image_list_proto,
|
|
177
|
+
layout_config,
|
|
132
178
|
fig,
|
|
133
179
|
clear_figure,
|
|
134
|
-
use_container_width,
|
|
135
180
|
**kwargs,
|
|
136
181
|
)
|
|
137
|
-
return self.dg._enqueue("imgs", image_list_proto)
|
|
182
|
+
return self.dg._enqueue("imgs", image_list_proto, layout_config=layout_config)
|
|
138
183
|
|
|
139
184
|
@property
|
|
140
185
|
def dg(self) -> DeltaGenerator:
|
|
@@ -145,9 +190,9 @@ know via [issue on Github](https://github.com/streamlit/streamlit/issues).
|
|
|
145
190
|
def marshall(
|
|
146
191
|
coordinates: str,
|
|
147
192
|
image_list_proto: ImageListProto,
|
|
193
|
+
layout_config: LayoutConfig,
|
|
148
194
|
fig: Figure | None = None,
|
|
149
195
|
clear_figure: bool | None = True,
|
|
150
|
-
use_container_width: bool = True,
|
|
151
196
|
**kwargs: Any,
|
|
152
197
|
) -> None:
|
|
153
198
|
try:
|
|
@@ -178,14 +223,11 @@ def marshall(
|
|
|
178
223
|
|
|
179
224
|
image = io.BytesIO()
|
|
180
225
|
fig.savefig(image, **kwargs)
|
|
181
|
-
image_width = (
|
|
182
|
-
WidthBehavior.COLUMN if use_container_width else WidthBehavior.ORIGINAL
|
|
183
|
-
)
|
|
184
226
|
marshall_images(
|
|
185
227
|
coordinates=coordinates,
|
|
186
228
|
image=image,
|
|
187
229
|
caption=None,
|
|
188
|
-
|
|
230
|
+
layout_config=layout_config,
|
|
189
231
|
proto_imgs=image_list_proto,
|
|
190
232
|
clamp=False,
|
|
191
233
|
channels="RGB",
|
streamlit/elements/toast.py
CHANGED
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from typing import TYPE_CHECKING, cast
|
|
17
|
+
from typing import TYPE_CHECKING, Literal, cast
|
|
18
18
|
|
|
19
|
-
from streamlit.errors import StreamlitAPIException
|
|
19
|
+
from streamlit.errors import StreamlitAPIException, StreamlitValueError
|
|
20
20
|
from streamlit.proto.Toast_pb2 import Toast as ToastProto
|
|
21
21
|
from streamlit.runtime.metrics_util import gather_metrics
|
|
22
22
|
from streamlit.string_util import clean_text, validate_icon_or_emoji
|
|
@@ -41,6 +41,7 @@ class ToastMixin:
|
|
|
41
41
|
body: SupportsStr,
|
|
42
42
|
*, # keyword-only args:
|
|
43
43
|
icon: str | None = None,
|
|
44
|
+
duration: Literal["short", "long", "infinite"] | int = "short",
|
|
44
45
|
) -> DeltaGenerator:
|
|
45
46
|
"""Display a short message, known as a notification "toast".
|
|
46
47
|
The toast appears in the app's top-right corner and disappears after four seconds.
|
|
@@ -79,16 +80,91 @@ class ToastMixin:
|
|
|
79
80
|
<https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
|
|
80
81
|
font library.
|
|
81
82
|
|
|
83
|
+
duration : "short", "long", "infinite", or int
|
|
84
|
+
The time to display the toast message. This can be one of the
|
|
85
|
+
following:
|
|
82
86
|
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
- ``"short"`` (default): Displays for 4 seconds.
|
|
88
|
+
- ``"long"``: Displays for 10 seconds.
|
|
89
|
+
- ``"infinite"``: Shows the toast until the user dismisses it.
|
|
90
|
+
- An integer: Displays for the specified number of seconds.
|
|
91
|
+
|
|
92
|
+
Examples
|
|
93
|
+
--------
|
|
94
|
+
**Example 1: Show a toast message**
|
|
95
|
+
|
|
96
|
+
>>> import streamlit as st
|
|
97
|
+
>>>
|
|
98
|
+
>>> st.toast("Your edited image was saved!", icon="😍")
|
|
99
|
+
|
|
100
|
+
.. output::
|
|
101
|
+
https://doc-status-toast.streamlit.app
|
|
102
|
+
height: 200px
|
|
103
|
+
|
|
104
|
+
**Example 2: Show multiple toasts**
|
|
105
|
+
|
|
106
|
+
When multiple toasts are generated, they will stack. Hovering over a
|
|
107
|
+
toast will stop it from disappearing. When hovering ends, the toast
|
|
108
|
+
will disappear after time specified in ``duration``.
|
|
109
|
+
|
|
110
|
+
>>> import time
|
|
85
111
|
>>> import streamlit as st
|
|
86
112
|
>>>
|
|
87
|
-
>>> st.
|
|
113
|
+
>>> if st.button("Three cheers"):
|
|
114
|
+
>>> st.toast("Hip!")
|
|
115
|
+
>>> time.sleep(0.5)
|
|
116
|
+
>>> st.toast("Hip!")
|
|
117
|
+
>>> time.sleep(0.5)
|
|
118
|
+
>>> st.toast("Hooray!", icon="🎉")
|
|
119
|
+
|
|
120
|
+
.. output::
|
|
121
|
+
https://doc-status-toast1.streamlit.app
|
|
122
|
+
height: 300px
|
|
123
|
+
|
|
124
|
+
**Example 3: Update a toast message**
|
|
125
|
+
|
|
126
|
+
Toast messages can also be updated. Assign ``st.toast(my_message)`` to
|
|
127
|
+
a variable and use the ``.toast()`` method to update it. If a toast has
|
|
128
|
+
already disappeared or been dismissed, the update will not be seen.
|
|
129
|
+
|
|
130
|
+
>>> import time
|
|
131
|
+
>>> import streamlit as st
|
|
132
|
+
>>>
|
|
133
|
+
>>> def cook_breakfast():
|
|
134
|
+
>>> msg = st.toast("Gathering ingredients...")
|
|
135
|
+
>>> time.sleep(1)
|
|
136
|
+
>>> msg.toast("Cooking...")
|
|
137
|
+
>>> time.sleep(1)
|
|
138
|
+
>>> msg.toast("Ready!", icon="🥞")
|
|
139
|
+
>>>
|
|
140
|
+
>>> if st.button("Cook breakfast"):
|
|
141
|
+
>>> cook_breakfast()
|
|
142
|
+
|
|
143
|
+
.. output::
|
|
144
|
+
https://doc-status-toast2.streamlit.app
|
|
145
|
+
height: 200px
|
|
146
|
+
|
|
88
147
|
"""
|
|
89
148
|
toast_proto = ToastProto()
|
|
90
149
|
toast_proto.body = clean_text(validate_text(body))
|
|
91
150
|
toast_proto.icon = validate_icon_or_emoji(icon)
|
|
151
|
+
|
|
152
|
+
if duration in ["short", "long", "infinite"] or (
|
|
153
|
+
isinstance(duration, int) and duration > 0
|
|
154
|
+
):
|
|
155
|
+
if duration == "short":
|
|
156
|
+
toast_proto.duration = 4
|
|
157
|
+
elif duration == "long":
|
|
158
|
+
toast_proto.duration = 10
|
|
159
|
+
elif duration == "infinite":
|
|
160
|
+
toast_proto.duration = 0
|
|
161
|
+
else:
|
|
162
|
+
toast_proto.duration = duration
|
|
163
|
+
else:
|
|
164
|
+
raise StreamlitValueError(
|
|
165
|
+
"duration", ["short", "long", "infinite", "a positive integer"]
|
|
166
|
+
)
|
|
167
|
+
|
|
92
168
|
return self.dg._enqueue("toast", toast_proto)
|
|
93
169
|
|
|
94
170
|
@property
|
|
@@ -387,18 +387,14 @@ def _convert_altair_to_vega_lite_spec(
|
|
|
387
387
|
alt.data_transformers.register("id", id_transform) # type: ignore[arg-type,attr-defined,unused-ignore]
|
|
388
388
|
|
|
389
389
|
# alt.themes was deprecated in Altair 5.5.0 in favor of alt.theme
|
|
390
|
-
|
|
391
|
-
alt.themes if type_util.is_altair_version_less_than("5.5.0") else alt.theme
|
|
390
|
+
alt_theme = (
|
|
391
|
+
alt.themes if type_util.is_altair_version_less_than("5.5.0") else alt.theme # ty: ignore[unresolved-attribute]
|
|
392
392
|
)
|
|
393
393
|
|
|
394
394
|
# The default altair theme has some width/height defaults defined
|
|
395
395
|
# which are not useful for Streamlit. Therefore, we change the theme to
|
|
396
396
|
# "none" to avoid those defaults.
|
|
397
|
-
with (
|
|
398
|
-
altair_theme.enable("none")
|
|
399
|
-
if altair_theme.active == "default"
|
|
400
|
-
else nullcontext()
|
|
401
|
-
): # type: ignore[attr-defined,unused-ignore]
|
|
397
|
+
with alt_theme.enable("none") if alt_theme.active == "default" else nullcontext(): # ty: ignore
|
|
402
398
|
with alt.data_transformers.enable("id"): # type: ignore[attr-defined,unused-ignore]
|
|
403
399
|
chart_dict = altair_chart.to_dict()
|
|
404
400
|
|
|
@@ -2083,7 +2079,6 @@ class VegaChartsMixin:
|
|
|
2083
2079
|
vega_lite_proto.id = compute_and_register_element_id(
|
|
2084
2080
|
"arrow_vega_lite_chart",
|
|
2085
2081
|
user_key=key,
|
|
2086
|
-
form_id=vega_lite_proto.form_id,
|
|
2087
2082
|
dg=self.dg,
|
|
2088
2083
|
vega_lite_spec=vega_lite_proto.spec,
|
|
2089
2084
|
# The data is either in vega_lite_proto.data.data
|
|
@@ -914,8 +914,6 @@ class ButtonMixin:
|
|
|
914
914
|
element_id = compute_and_register_element_id(
|
|
915
915
|
"download_button",
|
|
916
916
|
user_key=key,
|
|
917
|
-
# download_button is not allowed to be used in a form.
|
|
918
|
-
form_id=None,
|
|
919
917
|
dg=self.dg,
|
|
920
918
|
label=label,
|
|
921
919
|
icon=icon,
|
|
@@ -1123,8 +1121,6 @@ class ButtonMixin:
|
|
|
1123
1121
|
element_id = compute_and_register_element_id(
|
|
1124
1122
|
"button",
|
|
1125
1123
|
user_key=key,
|
|
1126
|
-
# Only the
|
|
1127
|
-
form_id=form_id,
|
|
1128
1124
|
dg=self.dg,
|
|
1129
1125
|
label=label,
|
|
1130
1126
|
icon=icon,
|
|
@@ -1031,7 +1031,6 @@ class ButtonGroupMixin:
|
|
|
1031
1031
|
|
|
1032
1032
|
check_widget_policies(self.dg, key, on_change, default_value=_default)
|
|
1033
1033
|
|
|
1034
|
-
widget_name = "button_group"
|
|
1035
1034
|
ctx = get_script_run_ctx()
|
|
1036
1035
|
form_id = current_form_id(self.dg)
|
|
1037
1036
|
formatted_options = (
|
|
@@ -1042,10 +1041,12 @@ class ButtonGroupMixin:
|
|
|
1042
1041
|
for index, _ in enumerate(indexable_options)
|
|
1043
1042
|
]
|
|
1044
1043
|
)
|
|
1044
|
+
|
|
1045
1045
|
element_id = compute_and_register_element_id(
|
|
1046
|
-
|
|
1046
|
+
# The borderless style is used by st.feedback, but users expect to see
|
|
1047
|
+
# "feedback" in errors
|
|
1048
|
+
"feedback" if style == "borderless" else style,
|
|
1047
1049
|
user_key=key,
|
|
1048
|
-
form_id=form_id,
|
|
1049
1050
|
dg=self.dg,
|
|
1050
1051
|
options=formatted_options,
|
|
1051
1052
|
default=default,
|
|
@@ -1088,7 +1089,7 @@ class ButtonGroupMixin:
|
|
|
1088
1089
|
if ctx:
|
|
1089
1090
|
save_for_app_testing(ctx, element_id, format_func)
|
|
1090
1091
|
|
|
1091
|
-
self.dg._enqueue(
|
|
1092
|
+
self.dg._enqueue("button_group", proto, layout_config=layout_config)
|
|
1092
1093
|
|
|
1093
1094
|
return widget_state
|
|
1094
1095
|
|