streamlit-nightly 1.53.2.dev20260131__py3-none-any.whl → 1.53.2.dev20260202__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/commands/execution_control.py +2 -2
- streamlit/delta_generator.py +2 -0
- streamlit/elements/lib/column_types.py +6 -2
- streamlit/elements/lib/utils.py +6 -6
- streamlit/elements/markdown.py +0 -1
- streamlit/elements/metric.py +2 -1
- streamlit/elements/widgets/button_group.py +6 -276
- streamlit/elements/widgets/feedback.py +322 -0
- streamlit/elements/widgets/number_input.py +2 -1
- streamlit/elements/widgets/slider.py +2 -1
- streamlit/material_icon_names.py +1 -1
- streamlit/proto/AudioInput_pb2.py +4 -4
- streamlit/proto/AudioInput_pb2.pyi +3 -3
- streamlit/proto/Audio_pb2.py +2 -2
- streamlit/proto/BackMsg_pb2.pyi +2 -10
- streamlit/proto/Balloons_pb2.pyi +0 -2
- streamlit/proto/Block_pb2.py +35 -35
- streamlit/proto/ButtonGroup_pb2.py +10 -12
- streamlit/proto/ButtonGroup_pb2.pyi +6 -41
- streamlit/proto/Button_pb2.py +2 -2
- streamlit/proto/CameraInput_pb2.py +4 -4
- streamlit/proto/CameraInput_pb2.pyi +3 -3
- streamlit/proto/ChatInput_pb2.py +2 -2
- streamlit/proto/Checkbox_pb2.py +6 -6
- streamlit/proto/Checkbox_pb2.pyi +3 -3
- streamlit/proto/Code_pb2.py +2 -2
- streamlit/proto/ColorPicker_pb2.py +4 -4
- streamlit/proto/ColorPicker_pb2.pyi +3 -3
- streamlit/proto/Common_pb2.py +6 -6
- streamlit/proto/DateInput_pb2.py +4 -4
- streamlit/proto/DateInput_pb2.pyi +3 -3
- streamlit/proto/DateTimeInput_pb2.py +4 -4
- streamlit/proto/DateTimeInput_pb2.pyi +3 -3
- streamlit/proto/DeckGlJsonChart_pb2.py +2 -2
- streamlit/proto/Delta_pb2.py +2 -2
- streamlit/proto/DocString_pb2.py +1 -1
- streamlit/proto/Element_pb2.py +4 -4
- streamlit/proto/Element_pb2.pyi +9 -9
- streamlit/proto/Feedback_pb2.py +28 -0
- streamlit/proto/Feedback_pb2.pyi +93 -0
- streamlit/proto/FileUploader_pb2.py +4 -4
- streamlit/proto/FileUploader_pb2.pyi +3 -3
- streamlit/proto/ForwardMsg_pb2.py +8 -8
- streamlit/proto/GraphVizChart_pb2.py +2 -2
- streamlit/proto/IFrame_pb2.py +3 -3
- streamlit/proto/Image_pb2.py +4 -4
- streamlit/proto/Image_pb2.pyi +1 -7
- streamlit/proto/{BokehChart_pb2.py → LabelVisibility_pb2.py} +7 -5
- streamlit/proto/{LabelVisibilityMessage_pb2.pyi → LabelVisibility_pb2.pyi} +14 -14
- streamlit/proto/Markdown_pb2.py +4 -4
- streamlit/proto/Markdown_pb2.pyi +1 -5
- streamlit/proto/Metric_pb2.py +10 -10
- streamlit/proto/Metric_pb2.pyi +3 -3
- streamlit/proto/MultiSelect_pb2.py +4 -4
- streamlit/proto/MultiSelect_pb2.pyi +3 -3
- streamlit/proto/NewSession_pb2.py +38 -26
- streamlit/proto/NewSession_pb2.pyi +42 -8
- streamlit/proto/NumberInput_pb2.py +6 -6
- streamlit/proto/NumberInput_pb2.pyi +3 -3
- streamlit/proto/PlotlyChart_pb2.py +2 -2
- streamlit/proto/Radio_pb2.py +4 -4
- streamlit/proto/Radio_pb2.pyi +3 -3
- streamlit/proto/Selectbox_pb2.py +4 -4
- streamlit/proto/Selectbox_pb2.pyi +3 -6
- streamlit/proto/Slider_pb2.py +8 -8
- streamlit/proto/Slider_pb2.pyi +3 -3
- streamlit/proto/Snow_pb2.pyi +0 -2
- streamlit/proto/TextArea_pb2.py +4 -4
- streamlit/proto/TextArea_pb2.pyi +3 -3
- streamlit/proto/TextInput_pb2.py +6 -6
- streamlit/proto/TextInput_pb2.pyi +3 -3
- streamlit/proto/TimeInput_pb2.py +4 -4
- streamlit/proto/TimeInput_pb2.pyi +3 -3
- streamlit/proto/Video_pb2.py +2 -2
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +324 -309
- streamlit/static/static/css/{index.BUP6fTcR.css → index.C8MrxwGF.css} +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.DC6KVDKK.js → ErrorOutline.esm.CLuz0rSD.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.Z9hRQIHi.js → FileDownload.esm.CO68LcnZ.js} +1 -1
- streamlit/static/static/js/{FileHelper.DqvW90pm.js → FileHelper.DAXgY6Ug.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.DTFnX0js.js → FormClearHelper.zxJ53Nym.js} +1 -1
- streamlit/static/static/js/{InputInstructions.CdzsN_Va.js → InputInstructions.CCbg8esE.js} +1 -1
- streamlit/static/static/js/{Particles.12xFSjcn.js → Particles.BJw0A-zv.js} +1 -1
- streamlit/static/static/js/{ProgressBar.Dg-oMbWg.js → ProgressBar.BrrHeAEh.js} +2 -2
- streamlit/static/static/js/{StreamlitSyntaxHighlighter.rbzmcipw.js → StreamlitSyntaxHighlighter.DvPLy3zk.js} +1 -1
- streamlit/static/static/js/{TableChart.esm.CzJtGIR-.js → TableChart.esm.BawvAi5p.js} +1 -1
- streamlit/static/static/js/{Toolbar.COH7NaOE.js → Toolbar.CbpscbNb.js} +1 -1
- streamlit/static/static/js/{WidgetLabelHelpIconInline.Dlc8f0Ji.js → WidgetLabelHelpIconInline.DA4S2HFP.js} +1 -1
- streamlit/static/static/js/{base-input.Q-zJLgRK.js → base-input.BKKl2eBF.js} +1 -1
- streamlit/static/static/js/{checkbox.BKgWNdeI.js → checkbox.CB43AKV4.js} +1 -1
- streamlit/static/static/js/{createDownloadLinkElement.6oO-YlYv.js → createDownloadLinkElement.jVwF96ey.js} +1 -1
- streamlit/static/static/js/data-grid-overlay-editor.CxQizSv7.js +1 -0
- streamlit/static/static/js/{downloader.BBXcXdX1.js → downloader.CKlIgsy5.js} +1 -1
- streamlit/static/static/js/{embed.CJzOXYBF.js → embed.BhRb_2n8.js} +1 -1
- streamlit/static/static/js/{es6.CdxPQzwJ.js → es6.DPyfPmWm.js} +2 -2
- streamlit/static/static/js/formatNumber.DtfMnnPx.js +1 -0
- streamlit/static/static/js/{iconPosition.BVScIr6G.js → iconPosition.DkZAlu_k.js} +1 -1
- streamlit/static/static/js/{iframeResizer.contentWindow.D_QHVqPM.js → iframeResizer.contentWindow.l5sQWLra.js} +1 -1
- streamlit/static/static/js/{index.CxoREvnF.js → index.465nmxtO.js} +2 -2
- streamlit/static/static/js/{index.BqbKiDp2.js → index.6J1N4is3.js} +1 -1
- streamlit/static/static/js/{index.CrY1BsL3.js → index.AZ9T4EqJ.js} +1 -1
- streamlit/static/static/js/{index.6DFY6LUF.js → index.BAK0CG1Q.js} +1 -1
- streamlit/static/static/js/{index.BxQxTpWl.js → index.BLD3tJ2C.js} +1 -1
- streamlit/static/static/js/{index.BQnLeHnr.js → index.BUlT_mOL.js} +3 -3
- streamlit/static/static/js/{index.Dud7RRHc.js → index.Bc_FQ4Wb.js} +1 -1
- streamlit/static/static/js/{index.DRoJNzFX.js → index.BpCj2-sQ.js} +1 -1
- streamlit/static/static/js/{index.BED2_zc7.js → index.BzO83wKm.js} +1 -1
- streamlit/static/static/js/index.CAoX2tlo.js +2 -0
- streamlit/static/static/js/{index.bQJYmJ2T.js → index.CBbYMKZp.js} +1 -1
- streamlit/static/static/js/{index.DyfvmNCy.js → index.CL7it7tU.js} +1 -1
- streamlit/static/static/js/{index.BDtN2n7T.js → index.CL_icBXS.js} +1 -1
- streamlit/static/static/js/{index.DAnczAW2.js → index.C_19KWNs.js} +1 -1
- streamlit/static/static/js/index.CaU3Uv_L.js +1 -0
- streamlit/static/static/js/{index.B80gSxrS.js → index.Ccye_uLl.js} +1 -1
- streamlit/static/static/js/{index.YULCxEtm.js → index.CiS4giQ2.js} +1 -1
- streamlit/static/static/js/{index.iXh5nbLZ.js → index.Ck64OQhV.js} +1 -1
- streamlit/static/static/js/{index.D9v2Y8Gk.js → index.CmbqbRMZ.js} +1 -1
- streamlit/static/static/js/{index.DAfIQKfP.js → index.CsEZTo6L.js} +2 -2
- streamlit/static/static/js/{index.BtOoVQt7.js → index.CsIENsKH.js} +1 -1
- streamlit/static/static/js/{index.CUYi3FrD.js → index.Cwg8nWw5.js} +1 -1
- streamlit/static/static/js/{index.GieKl4BG.js → index.D83azq2w.js} +1 -1
- streamlit/static/static/js/{index.CvtybR-u.js → index.DDr-BLbJ.js} +1 -1
- streamlit/static/static/js/{index.CBE2cIbj.js → index.DKoJr0Se.js} +1 -1
- streamlit/static/static/js/{index.DyXcT2tD.js → index.DL_ywOgf.js} +2 -2
- streamlit/static/static/js/{index.BiCbrx53.js → index.DR6V0uBJ.js} +1 -1
- streamlit/static/static/js/index.DZOGT9vX.js +1 -0
- streamlit/static/static/js/{index.BSpYHDvk.js → index.Dac9Jib-.js} +1 -1
- streamlit/static/static/js/{index.DCe7fo-m.js → index.DiBeetOH.js} +1 -1
- streamlit/static/static/js/{index.DrcbvB2t.js → index.DjuMEZ6m.js} +1 -1
- streamlit/static/static/js/{index.DU68jVpM.js → index.DmWUXdjc.js} +5 -5
- streamlit/static/static/js/{index._1zqETQ9.js → index.DpSc4e1j.js} +1 -1
- streamlit/static/static/js/{index.Biyf9aUg.js → index.DzdPUxsx.js} +2 -2
- streamlit/static/static/js/{index.C5oqIM3a.js → index.FioS1Y9m.js} +1 -1
- streamlit/static/static/js/{index.DZmBuE3z.js → index.L9pOjBEn.js} +3 -3
- streamlit/static/static/js/{index.DAyGxxdm.js → index.LjqoQCm5.js} +3 -3
- streamlit/static/static/js/{index.mSdC1FV6.js → index.OizPL4jg.js} +1 -1
- streamlit/static/static/js/{index.BSYebegS.js → index.Q2t_iBn0.js} +1 -1
- streamlit/static/static/js/index.WIMtx3m0.js +2 -0
- streamlit/static/static/js/index.Y9wPTZIf.js +1 -0
- streamlit/static/static/js/{index.BqxwnMem.js → index.YutgmD9x.js} +2 -2
- streamlit/static/static/js/{index.nL1fkE1D.js → index.b_f-McZ5.js} +1 -1
- streamlit/static/static/js/{index.y-pa6LIX.js → index.e6Ry6-Ft.js} +1 -1
- streamlit/static/static/js/index.hnu9U-5g.js +1 -0
- streamlit/static/static/js/{index.D6OexhdL.js → index.rvbQETlC.js} +1 -1
- streamlit/static/static/js/index.w7yKy9fh.js +6 -0
- streamlit/static/static/js/{index.BxMkW82k.js → index.y0h42OXL.js} +1 -1
- streamlit/static/static/js/{index.CPc_uZux.js → index.y5HxPwg9.js} +42 -42
- streamlit/static/static/js/{index.DNfyKqhQ.js → index.yHLCvUGh.js} +1 -1
- streamlit/static/static/js/{input.BcC6sPE_.js → input.CAtwSQ27.js} +1 -1
- streamlit/static/static/js/{main.TU5_aabd.js → main.VeMVx6VI.js} +1 -1
- streamlit/static/static/js/{memory.By_OTlI4.js → memory.CxS_lIUn.js} +1 -1
- streamlit/static/static/js/number-overlay-editor.CoqRgZW_.js +9 -0
- streamlit/static/static/js/{pandasStylerUtils.3IiIKU9-.js → pandasStylerUtils.DGWgd5sM.js} +1 -1
- streamlit/static/static/js/{sandbox.DnxTbWzV.js → sandbox.2mSqEau0.js} +1 -1
- streamlit/static/static/js/sprintfjs.CsoVVZ9k.js +1 -0
- streamlit/static/static/js/{styled-components.BeEcZ0vW.js → styled-components.BShfh7J8.js} +1 -1
- streamlit/static/static/js/{throttle.emUyC44c.js → throttle.Fq1DQK4p.js} +1 -1
- streamlit/static/static/js/{timepicker.DZ_ZufYF.js → timepicker.DmyY-qtn.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.DDV1bN1-.js → toConsumableArray.Dvd9AIqV.js} +1 -1
- streamlit/static/static/js/uniqueId.CCajdEK8.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.DvpdEDYZ.js → useBasicWidgetState.COLQ5AFB.js} +1 -1
- streamlit/static/static/js/{useIntlLocale.BBDLbTq9.js → useIntlLocale.kdIj0ego.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.BIApLJKn.js → useTextInputAutoExpand.DkuG1C1S.js} +1 -1
- streamlit/static/static/js/{useUpdateUiValue.DQ4RuJNC.js → useUpdateUiValue.-UI_JsjT.js} +1 -1
- streamlit/static/static/js/{useWaveformController.B0olyXLQ.js → useWaveformController.C5PTwL6I.js} +1 -1
- streamlit/static/static/js/{withCalculatedWidth.DYeqePuh.js → withCalculatedWidth.BREyS0pJ.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.DtkUCO_d.js → withFullScreenWrapper.DYDiEOrW.js} +1 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.CnH1S47a.woff2 +0 -0
- streamlit/testing/v1/app_test.py +21 -5
- streamlit/testing/v1/element_tree.py +65 -2
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/METADATA +1 -1
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/RECORD +175 -173
- streamlit/proto/BokehChart_pb2.pyi +0 -56
- streamlit/proto/LabelVisibilityMessage_pb2.py +0 -28
- streamlit/static/static/js/data-grid-overlay-editor.CO0xdNiG.js +0 -1
- streamlit/static/static/js/formatNumber.DB5irY8c.js +0 -1
- streamlit/static/static/js/index.BBTKOM0z.js +0 -6
- streamlit/static/static/js/index.CE2WIFD1.js +0 -2
- streamlit/static/static/js/index.Cpu2p5bH.js +0 -1
- streamlit/static/static/js/index.CtbETWQK.js +0 -2
- streamlit/static/static/js/index.DhRAGiPR.js +0 -1
- streamlit/static/static/js/index.tuFFlbxa.js +0 -1
- streamlit/static/static/js/number-overlay-editor.FSRaRpbU.js +0 -9
- streamlit/static/static/js/sprintf.DpPCfzXw.js +0 -1
- streamlit/static/static/js/uniqueId.DTwvAE-J.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026)
|
|
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 typing import (
|
|
18
|
+
TYPE_CHECKING,
|
|
19
|
+
Final,
|
|
20
|
+
Literal,
|
|
21
|
+
cast,
|
|
22
|
+
overload,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
from streamlit.elements.lib.form_utils import current_form_id
|
|
26
|
+
from streamlit.elements.lib.layout_utils import (
|
|
27
|
+
LayoutConfig,
|
|
28
|
+
Width,
|
|
29
|
+
validate_width,
|
|
30
|
+
)
|
|
31
|
+
from streamlit.elements.lib.policies import check_widget_policies
|
|
32
|
+
from streamlit.elements.lib.utils import (
|
|
33
|
+
Key,
|
|
34
|
+
compute_and_register_element_id,
|
|
35
|
+
save_for_app_testing,
|
|
36
|
+
to_key,
|
|
37
|
+
)
|
|
38
|
+
from streamlit.errors import StreamlitAPIException
|
|
39
|
+
from streamlit.proto.Feedback_pb2 import Feedback as FeedbackProto
|
|
40
|
+
from streamlit.runtime.metrics_util import gather_metrics
|
|
41
|
+
from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
|
|
42
|
+
from streamlit.runtime.state import register_widget
|
|
43
|
+
|
|
44
|
+
if TYPE_CHECKING:
|
|
45
|
+
from streamlit.delta_generator import DeltaGenerator
|
|
46
|
+
from streamlit.runtime.state import (
|
|
47
|
+
WidgetArgs,
|
|
48
|
+
WidgetCallback,
|
|
49
|
+
WidgetKwargs,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# Number of options for each feedback type
|
|
54
|
+
_NUM_THUMBS_OPTIONS: Final = 2
|
|
55
|
+
_NUM_FACES_OPTIONS: Final = 5
|
|
56
|
+
_NUM_STARS_OPTIONS: Final = 5
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _get_num_options(feedback_type: Literal["thumbs", "faces", "stars"]) -> int:
|
|
60
|
+
"""Get the number of options for the given feedback type."""
|
|
61
|
+
if feedback_type == "thumbs":
|
|
62
|
+
return _NUM_THUMBS_OPTIONS
|
|
63
|
+
if feedback_type == "faces":
|
|
64
|
+
return _NUM_FACES_OPTIONS
|
|
65
|
+
return _NUM_STARS_OPTIONS
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _feedback_type_to_proto(
|
|
69
|
+
feedback_type: Literal["thumbs", "faces", "stars"],
|
|
70
|
+
) -> FeedbackProto.FeedbackType.ValueType:
|
|
71
|
+
"""Convert a feedback type string to the proto enum value."""
|
|
72
|
+
if feedback_type == "thumbs":
|
|
73
|
+
return FeedbackProto.FeedbackType.THUMBS
|
|
74
|
+
if feedback_type == "faces":
|
|
75
|
+
return FeedbackProto.FeedbackType.FACES
|
|
76
|
+
return FeedbackProto.FeedbackType.STARS
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class FeedbackSerde:
|
|
80
|
+
"""Serializer/deserializer for feedback widget values.
|
|
81
|
+
|
|
82
|
+
Uses string as the wire format to distinguish three states:
|
|
83
|
+
- None (field not set): No UI interaction yet -> use default_value
|
|
84
|
+
- "" (empty string): User explicitly cleared -> return None
|
|
85
|
+
- "2" (string with value): User selected -> return int value
|
|
86
|
+
|
|
87
|
+
This allows clearing to work correctly even when a default is set.
|
|
88
|
+
The session state and return values are always int | None.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def __init__(self, default_value: int | None = None):
|
|
92
|
+
self.default_value = default_value
|
|
93
|
+
|
|
94
|
+
def serialize(self, value: int | None) -> str:
|
|
95
|
+
"""Serialize int value to string for wire format."""
|
|
96
|
+
return "" if value is None else str(value)
|
|
97
|
+
|
|
98
|
+
def deserialize(self, ui_value: str | None) -> int | None:
|
|
99
|
+
"""Deserialize string wire format back to int value."""
|
|
100
|
+
if ui_value is None:
|
|
101
|
+
return self.default_value # No UI interaction yet
|
|
102
|
+
if ui_value == "":
|
|
103
|
+
return None # User explicitly cleared
|
|
104
|
+
return int(ui_value) # User selected a value
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class FeedbackMixin:
|
|
108
|
+
@overload
|
|
109
|
+
def feedback(
|
|
110
|
+
self,
|
|
111
|
+
options: Literal["thumbs"] = ...,
|
|
112
|
+
*,
|
|
113
|
+
key: Key | None = None,
|
|
114
|
+
default: int | None = None,
|
|
115
|
+
disabled: bool = False,
|
|
116
|
+
on_change: WidgetCallback | None = None,
|
|
117
|
+
args: WidgetArgs | None = None,
|
|
118
|
+
kwargs: WidgetKwargs | None = None,
|
|
119
|
+
width: Width = "content",
|
|
120
|
+
) -> Literal[0, 1] | None: ...
|
|
121
|
+
|
|
122
|
+
@overload
|
|
123
|
+
def feedback(
|
|
124
|
+
self,
|
|
125
|
+
options: Literal["faces", "stars"] = ...,
|
|
126
|
+
*,
|
|
127
|
+
key: Key | None = None,
|
|
128
|
+
default: int | None = None,
|
|
129
|
+
disabled: bool = False,
|
|
130
|
+
on_change: WidgetCallback | None = None,
|
|
131
|
+
args: WidgetArgs | None = None,
|
|
132
|
+
kwargs: WidgetKwargs | None = None,
|
|
133
|
+
width: Width = "content",
|
|
134
|
+
) -> Literal[0, 1, 2, 3, 4] | None: ...
|
|
135
|
+
|
|
136
|
+
@gather_metrics("feedback")
|
|
137
|
+
def feedback(
|
|
138
|
+
self,
|
|
139
|
+
options: Literal["thumbs", "faces", "stars"] = "thumbs",
|
|
140
|
+
*,
|
|
141
|
+
key: Key | None = None,
|
|
142
|
+
default: int | None = None,
|
|
143
|
+
disabled: bool = False,
|
|
144
|
+
on_change: WidgetCallback | None = None,
|
|
145
|
+
args: WidgetArgs | None = None,
|
|
146
|
+
kwargs: WidgetKwargs | None = None,
|
|
147
|
+
width: Width = "content",
|
|
148
|
+
) -> int | None:
|
|
149
|
+
"""Display a feedback widget.
|
|
150
|
+
|
|
151
|
+
A feedback widget is an icon-based button group available in three
|
|
152
|
+
styles, as described in ``options``. It is commonly used in chat and AI
|
|
153
|
+
apps to allow users to rate responses.
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
options : "thumbs", "faces", or "stars"
|
|
158
|
+
The feedback options displayed to the user. ``options`` can be one
|
|
159
|
+
of the following:
|
|
160
|
+
|
|
161
|
+
- ``"thumbs"`` (default): Streamlit displays a thumb-up and
|
|
162
|
+
thumb-down button group.
|
|
163
|
+
- ``"faces"``: Streamlit displays a row of five buttons with
|
|
164
|
+
facial expressions depicting increasing satisfaction from left to
|
|
165
|
+
right.
|
|
166
|
+
- ``"stars"``: Streamlit displays a row of star icons, allowing the
|
|
167
|
+
user to select a rating from one to five stars.
|
|
168
|
+
|
|
169
|
+
key : str or int
|
|
170
|
+
An optional string or integer to use as the unique key for the widget.
|
|
171
|
+
If this is omitted, a key will be generated for the widget
|
|
172
|
+
based on its content. No two widgets may have the same key.
|
|
173
|
+
|
|
174
|
+
default : int or None
|
|
175
|
+
Default feedback value. This must be consistent with the feedback
|
|
176
|
+
type in ``options``:
|
|
177
|
+
|
|
178
|
+
- 0 or 1 if ``options="thumbs"``.
|
|
179
|
+
- Between 0 and 4, inclusive, if ``options="faces"`` or
|
|
180
|
+
``options="stars"``.
|
|
181
|
+
|
|
182
|
+
disabled : bool
|
|
183
|
+
An optional boolean that disables the feedback widget if set
|
|
184
|
+
to ``True``. The default is ``False``.
|
|
185
|
+
|
|
186
|
+
on_change : callable
|
|
187
|
+
An optional callback invoked when this feedback widget's value
|
|
188
|
+
changes.
|
|
189
|
+
|
|
190
|
+
args : list or tuple
|
|
191
|
+
An optional list or tuple of args to pass to the callback.
|
|
192
|
+
|
|
193
|
+
kwargs : dict
|
|
194
|
+
An optional dict of kwargs to pass to the callback.
|
|
195
|
+
|
|
196
|
+
width : "content", "stretch", or int
|
|
197
|
+
The width of the feedback widget. This can be one of the following:
|
|
198
|
+
|
|
199
|
+
- ``"content"`` (default): The width of the widget matches the
|
|
200
|
+
width of its content, but doesn't exceed the width of the parent
|
|
201
|
+
container.
|
|
202
|
+
- ``"stretch"``: The width of the widget matches the width of the
|
|
203
|
+
parent container.
|
|
204
|
+
- An integer specifying the width in pixels: The widget has a
|
|
205
|
+
fixed width. If the specified width is greater than the width of
|
|
206
|
+
the parent container, the width of the widget matches the width
|
|
207
|
+
of the parent container.
|
|
208
|
+
|
|
209
|
+
Returns
|
|
210
|
+
-------
|
|
211
|
+
int or None
|
|
212
|
+
An integer indicating the user's selection, where ``0`` is the
|
|
213
|
+
lowest feedback. Higher values indicate more positive feedback.
|
|
214
|
+
If no option was selected, the widget returns ``None``.
|
|
215
|
+
|
|
216
|
+
- For ``options="thumbs"``, a return value of ``0`` indicates
|
|
217
|
+
thumbs-down, and ``1`` indicates thumbs-up.
|
|
218
|
+
- For ``options="faces"`` and ``options="stars"``, return values
|
|
219
|
+
range from ``0`` (least satisfied) to ``4`` (most satisfied).
|
|
220
|
+
|
|
221
|
+
Examples
|
|
222
|
+
--------
|
|
223
|
+
Display a feedback widget with stars, and show the selected sentiment:
|
|
224
|
+
|
|
225
|
+
>>> import streamlit as st
|
|
226
|
+
>>>
|
|
227
|
+
>>> sentiment_mapping = ["one", "two", "three", "four", "five"]
|
|
228
|
+
>>> selected = st.feedback("stars")
|
|
229
|
+
>>> if selected is not None:
|
|
230
|
+
>>> st.markdown(f"You selected {sentiment_mapping[selected]} star(s).")
|
|
231
|
+
|
|
232
|
+
.. output::
|
|
233
|
+
https://doc-feedback-stars.streamlit.app/
|
|
234
|
+
height: 200px
|
|
235
|
+
|
|
236
|
+
Display a feedback widget with thumbs, and show the selected sentiment:
|
|
237
|
+
|
|
238
|
+
>>> import streamlit as st
|
|
239
|
+
>>>
|
|
240
|
+
>>> sentiment_mapping = [":material/thumb_down:", ":material/thumb_up:"]
|
|
241
|
+
>>> selected = st.feedback("thumbs")
|
|
242
|
+
>>> if selected is not None:
|
|
243
|
+
>>> st.markdown(f"You selected: {sentiment_mapping[selected]}")
|
|
244
|
+
|
|
245
|
+
.. output::
|
|
246
|
+
https://doc-feedback-thumbs.streamlit.app/
|
|
247
|
+
height: 200px
|
|
248
|
+
|
|
249
|
+
"""
|
|
250
|
+
if options not in {"thumbs", "faces", "stars"}:
|
|
251
|
+
raise StreamlitAPIException(
|
|
252
|
+
"The options argument to st.feedback must be one of "
|
|
253
|
+
"['thumbs', 'faces', 'stars']. "
|
|
254
|
+
f"The argument passed was '{options}'."
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
num_options = _get_num_options(options)
|
|
258
|
+
|
|
259
|
+
if default is not None and (default < 0 or default >= num_options):
|
|
260
|
+
raise StreamlitAPIException(
|
|
261
|
+
f"The default value in '{options}' must be a number between 0 and {num_options - 1}."
|
|
262
|
+
f" The passed default value is {default}"
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
key = to_key(key)
|
|
266
|
+
validate_width(width, allow_content=True)
|
|
267
|
+
layout_config = LayoutConfig(width=width)
|
|
268
|
+
|
|
269
|
+
check_widget_policies(self.dg, key, on_change, default_value=default)
|
|
270
|
+
|
|
271
|
+
ctx = get_script_run_ctx()
|
|
272
|
+
form_id = current_form_id(self.dg)
|
|
273
|
+
|
|
274
|
+
element_id = compute_and_register_element_id(
|
|
275
|
+
"feedback",
|
|
276
|
+
user_key=key,
|
|
277
|
+
key_as_main_identity={"options"},
|
|
278
|
+
dg=self.dg,
|
|
279
|
+
options=options,
|
|
280
|
+
default=default,
|
|
281
|
+
width=width,
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
# Build the proto
|
|
285
|
+
proto = FeedbackProto()
|
|
286
|
+
proto.id = element_id
|
|
287
|
+
proto.type = _feedback_type_to_proto(options)
|
|
288
|
+
proto.disabled = disabled
|
|
289
|
+
proto.form_id = form_id
|
|
290
|
+
|
|
291
|
+
if default is not None:
|
|
292
|
+
proto.default = default
|
|
293
|
+
|
|
294
|
+
serde = FeedbackSerde(default_value=default)
|
|
295
|
+
|
|
296
|
+
widget_state = register_widget(
|
|
297
|
+
proto.id,
|
|
298
|
+
on_change_handler=on_change,
|
|
299
|
+
args=args,
|
|
300
|
+
kwargs=kwargs,
|
|
301
|
+
deserializer=serde.deserialize,
|
|
302
|
+
serializer=serde.serialize,
|
|
303
|
+
ctx=ctx,
|
|
304
|
+
value_type="string_value",
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
if widget_state.value_changed:
|
|
308
|
+
if widget_state.value is not None:
|
|
309
|
+
proto.value = widget_state.value
|
|
310
|
+
proto.set_value = True
|
|
311
|
+
|
|
312
|
+
if ctx:
|
|
313
|
+
save_for_app_testing(ctx, element_id, None)
|
|
314
|
+
|
|
315
|
+
self.dg._enqueue("feedback", proto, layout_config=layout_config)
|
|
316
|
+
|
|
317
|
+
return widget_state.value
|
|
318
|
+
|
|
319
|
+
@property
|
|
320
|
+
def dg(self) -> DeltaGenerator:
|
|
321
|
+
"""Get our DeltaGenerator."""
|
|
322
|
+
return cast("DeltaGenerator", self)
|
|
@@ -296,7 +296,8 @@ class NumberInputMixin:
|
|
|
296
296
|
<https://github.com/alexei/sprintf.js?tab=readme-ov-file#format-specification>`_.
|
|
297
297
|
|
|
298
298
|
For example, ``format="%0.1f"`` adjusts the displayed decimal
|
|
299
|
-
precision to only show one digit after the decimal.
|
|
299
|
+
precision to only show one digit after the decimal. Use ``,`` for
|
|
300
|
+
thousand separators (e.g. ``"%,d"`` yields ``"1,234"``).
|
|
300
301
|
|
|
301
302
|
key : str or int
|
|
302
303
|
An optional string or integer to use as the unique key for the widget.
|
|
@@ -541,7 +541,8 @@ class SliderMixin:
|
|
|
541
541
|
`sprintf.js
|
|
542
542
|
<https://github.com/alexei/sprintf.js?tab=readme-ov-file#format-specification>`_.
|
|
543
543
|
For example, ``format="%0.1f"`` adjusts the displayed decimal
|
|
544
|
-
precision to only show one digit after the decimal.
|
|
544
|
+
precision to only show one digit after the decimal. Use ``,`` for
|
|
545
|
+
thousand separators (e.g. ``"%,d"`` yields ``"1,234"``).
|
|
545
546
|
|
|
546
547
|
For datetimes, dates, and times, you can use a momentJS format string
|
|
547
548
|
or one of the following predefined formats:
|