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.
Files changed (189) hide show
  1. streamlit/commands/execution_control.py +2 -2
  2. streamlit/delta_generator.py +2 -0
  3. streamlit/elements/lib/column_types.py +6 -2
  4. streamlit/elements/lib/utils.py +6 -6
  5. streamlit/elements/markdown.py +0 -1
  6. streamlit/elements/metric.py +2 -1
  7. streamlit/elements/widgets/button_group.py +6 -276
  8. streamlit/elements/widgets/feedback.py +322 -0
  9. streamlit/elements/widgets/number_input.py +2 -1
  10. streamlit/elements/widgets/slider.py +2 -1
  11. streamlit/material_icon_names.py +1 -1
  12. streamlit/proto/AudioInput_pb2.py +4 -4
  13. streamlit/proto/AudioInput_pb2.pyi +3 -3
  14. streamlit/proto/Audio_pb2.py +2 -2
  15. streamlit/proto/BackMsg_pb2.pyi +2 -10
  16. streamlit/proto/Balloons_pb2.pyi +0 -2
  17. streamlit/proto/Block_pb2.py +35 -35
  18. streamlit/proto/ButtonGroup_pb2.py +10 -12
  19. streamlit/proto/ButtonGroup_pb2.pyi +6 -41
  20. streamlit/proto/Button_pb2.py +2 -2
  21. streamlit/proto/CameraInput_pb2.py +4 -4
  22. streamlit/proto/CameraInput_pb2.pyi +3 -3
  23. streamlit/proto/ChatInput_pb2.py +2 -2
  24. streamlit/proto/Checkbox_pb2.py +6 -6
  25. streamlit/proto/Checkbox_pb2.pyi +3 -3
  26. streamlit/proto/Code_pb2.py +2 -2
  27. streamlit/proto/ColorPicker_pb2.py +4 -4
  28. streamlit/proto/ColorPicker_pb2.pyi +3 -3
  29. streamlit/proto/Common_pb2.py +6 -6
  30. streamlit/proto/DateInput_pb2.py +4 -4
  31. streamlit/proto/DateInput_pb2.pyi +3 -3
  32. streamlit/proto/DateTimeInput_pb2.py +4 -4
  33. streamlit/proto/DateTimeInput_pb2.pyi +3 -3
  34. streamlit/proto/DeckGlJsonChart_pb2.py +2 -2
  35. streamlit/proto/Delta_pb2.py +2 -2
  36. streamlit/proto/DocString_pb2.py +1 -1
  37. streamlit/proto/Element_pb2.py +4 -4
  38. streamlit/proto/Element_pb2.pyi +9 -9
  39. streamlit/proto/Feedback_pb2.py +28 -0
  40. streamlit/proto/Feedback_pb2.pyi +93 -0
  41. streamlit/proto/FileUploader_pb2.py +4 -4
  42. streamlit/proto/FileUploader_pb2.pyi +3 -3
  43. streamlit/proto/ForwardMsg_pb2.py +8 -8
  44. streamlit/proto/GraphVizChart_pb2.py +2 -2
  45. streamlit/proto/IFrame_pb2.py +3 -3
  46. streamlit/proto/Image_pb2.py +4 -4
  47. streamlit/proto/Image_pb2.pyi +1 -7
  48. streamlit/proto/{BokehChart_pb2.py → LabelVisibility_pb2.py} +7 -5
  49. streamlit/proto/{LabelVisibilityMessage_pb2.pyi → LabelVisibility_pb2.pyi} +14 -14
  50. streamlit/proto/Markdown_pb2.py +4 -4
  51. streamlit/proto/Markdown_pb2.pyi +1 -5
  52. streamlit/proto/Metric_pb2.py +10 -10
  53. streamlit/proto/Metric_pb2.pyi +3 -3
  54. streamlit/proto/MultiSelect_pb2.py +4 -4
  55. streamlit/proto/MultiSelect_pb2.pyi +3 -3
  56. streamlit/proto/NewSession_pb2.py +38 -26
  57. streamlit/proto/NewSession_pb2.pyi +42 -8
  58. streamlit/proto/NumberInput_pb2.py +6 -6
  59. streamlit/proto/NumberInput_pb2.pyi +3 -3
  60. streamlit/proto/PlotlyChart_pb2.py +2 -2
  61. streamlit/proto/Radio_pb2.py +4 -4
  62. streamlit/proto/Radio_pb2.pyi +3 -3
  63. streamlit/proto/Selectbox_pb2.py +4 -4
  64. streamlit/proto/Selectbox_pb2.pyi +3 -6
  65. streamlit/proto/Slider_pb2.py +8 -8
  66. streamlit/proto/Slider_pb2.pyi +3 -3
  67. streamlit/proto/Snow_pb2.pyi +0 -2
  68. streamlit/proto/TextArea_pb2.py +4 -4
  69. streamlit/proto/TextArea_pb2.pyi +3 -3
  70. streamlit/proto/TextInput_pb2.py +6 -6
  71. streamlit/proto/TextInput_pb2.pyi +3 -3
  72. streamlit/proto/TimeInput_pb2.py +4 -4
  73. streamlit/proto/TimeInput_pb2.pyi +3 -3
  74. streamlit/proto/Video_pb2.py +2 -2
  75. streamlit/static/index.html +2 -2
  76. streamlit/static/manifest.json +324 -309
  77. streamlit/static/static/css/{index.BUP6fTcR.css → index.C8MrxwGF.css} +1 -1
  78. streamlit/static/static/js/{ErrorOutline.esm.DC6KVDKK.js → ErrorOutline.esm.CLuz0rSD.js} +1 -1
  79. streamlit/static/static/js/{FileDownload.esm.Z9hRQIHi.js → FileDownload.esm.CO68LcnZ.js} +1 -1
  80. streamlit/static/static/js/{FileHelper.DqvW90pm.js → FileHelper.DAXgY6Ug.js} +1 -1
  81. streamlit/static/static/js/{FormClearHelper.DTFnX0js.js → FormClearHelper.zxJ53Nym.js} +1 -1
  82. streamlit/static/static/js/{InputInstructions.CdzsN_Va.js → InputInstructions.CCbg8esE.js} +1 -1
  83. streamlit/static/static/js/{Particles.12xFSjcn.js → Particles.BJw0A-zv.js} +1 -1
  84. streamlit/static/static/js/{ProgressBar.Dg-oMbWg.js → ProgressBar.BrrHeAEh.js} +2 -2
  85. streamlit/static/static/js/{StreamlitSyntaxHighlighter.rbzmcipw.js → StreamlitSyntaxHighlighter.DvPLy3zk.js} +1 -1
  86. streamlit/static/static/js/{TableChart.esm.CzJtGIR-.js → TableChart.esm.BawvAi5p.js} +1 -1
  87. streamlit/static/static/js/{Toolbar.COH7NaOE.js → Toolbar.CbpscbNb.js} +1 -1
  88. streamlit/static/static/js/{WidgetLabelHelpIconInline.Dlc8f0Ji.js → WidgetLabelHelpIconInline.DA4S2HFP.js} +1 -1
  89. streamlit/static/static/js/{base-input.Q-zJLgRK.js → base-input.BKKl2eBF.js} +1 -1
  90. streamlit/static/static/js/{checkbox.BKgWNdeI.js → checkbox.CB43AKV4.js} +1 -1
  91. streamlit/static/static/js/{createDownloadLinkElement.6oO-YlYv.js → createDownloadLinkElement.jVwF96ey.js} +1 -1
  92. streamlit/static/static/js/data-grid-overlay-editor.CxQizSv7.js +1 -0
  93. streamlit/static/static/js/{downloader.BBXcXdX1.js → downloader.CKlIgsy5.js} +1 -1
  94. streamlit/static/static/js/{embed.CJzOXYBF.js → embed.BhRb_2n8.js} +1 -1
  95. streamlit/static/static/js/{es6.CdxPQzwJ.js → es6.DPyfPmWm.js} +2 -2
  96. streamlit/static/static/js/formatNumber.DtfMnnPx.js +1 -0
  97. streamlit/static/static/js/{iconPosition.BVScIr6G.js → iconPosition.DkZAlu_k.js} +1 -1
  98. streamlit/static/static/js/{iframeResizer.contentWindow.D_QHVqPM.js → iframeResizer.contentWindow.l5sQWLra.js} +1 -1
  99. streamlit/static/static/js/{index.CxoREvnF.js → index.465nmxtO.js} +2 -2
  100. streamlit/static/static/js/{index.BqbKiDp2.js → index.6J1N4is3.js} +1 -1
  101. streamlit/static/static/js/{index.CrY1BsL3.js → index.AZ9T4EqJ.js} +1 -1
  102. streamlit/static/static/js/{index.6DFY6LUF.js → index.BAK0CG1Q.js} +1 -1
  103. streamlit/static/static/js/{index.BxQxTpWl.js → index.BLD3tJ2C.js} +1 -1
  104. streamlit/static/static/js/{index.BQnLeHnr.js → index.BUlT_mOL.js} +3 -3
  105. streamlit/static/static/js/{index.Dud7RRHc.js → index.Bc_FQ4Wb.js} +1 -1
  106. streamlit/static/static/js/{index.DRoJNzFX.js → index.BpCj2-sQ.js} +1 -1
  107. streamlit/static/static/js/{index.BED2_zc7.js → index.BzO83wKm.js} +1 -1
  108. streamlit/static/static/js/index.CAoX2tlo.js +2 -0
  109. streamlit/static/static/js/{index.bQJYmJ2T.js → index.CBbYMKZp.js} +1 -1
  110. streamlit/static/static/js/{index.DyfvmNCy.js → index.CL7it7tU.js} +1 -1
  111. streamlit/static/static/js/{index.BDtN2n7T.js → index.CL_icBXS.js} +1 -1
  112. streamlit/static/static/js/{index.DAnczAW2.js → index.C_19KWNs.js} +1 -1
  113. streamlit/static/static/js/index.CaU3Uv_L.js +1 -0
  114. streamlit/static/static/js/{index.B80gSxrS.js → index.Ccye_uLl.js} +1 -1
  115. streamlit/static/static/js/{index.YULCxEtm.js → index.CiS4giQ2.js} +1 -1
  116. streamlit/static/static/js/{index.iXh5nbLZ.js → index.Ck64OQhV.js} +1 -1
  117. streamlit/static/static/js/{index.D9v2Y8Gk.js → index.CmbqbRMZ.js} +1 -1
  118. streamlit/static/static/js/{index.DAfIQKfP.js → index.CsEZTo6L.js} +2 -2
  119. streamlit/static/static/js/{index.BtOoVQt7.js → index.CsIENsKH.js} +1 -1
  120. streamlit/static/static/js/{index.CUYi3FrD.js → index.Cwg8nWw5.js} +1 -1
  121. streamlit/static/static/js/{index.GieKl4BG.js → index.D83azq2w.js} +1 -1
  122. streamlit/static/static/js/{index.CvtybR-u.js → index.DDr-BLbJ.js} +1 -1
  123. streamlit/static/static/js/{index.CBE2cIbj.js → index.DKoJr0Se.js} +1 -1
  124. streamlit/static/static/js/{index.DyXcT2tD.js → index.DL_ywOgf.js} +2 -2
  125. streamlit/static/static/js/{index.BiCbrx53.js → index.DR6V0uBJ.js} +1 -1
  126. streamlit/static/static/js/index.DZOGT9vX.js +1 -0
  127. streamlit/static/static/js/{index.BSpYHDvk.js → index.Dac9Jib-.js} +1 -1
  128. streamlit/static/static/js/{index.DCe7fo-m.js → index.DiBeetOH.js} +1 -1
  129. streamlit/static/static/js/{index.DrcbvB2t.js → index.DjuMEZ6m.js} +1 -1
  130. streamlit/static/static/js/{index.DU68jVpM.js → index.DmWUXdjc.js} +5 -5
  131. streamlit/static/static/js/{index._1zqETQ9.js → index.DpSc4e1j.js} +1 -1
  132. streamlit/static/static/js/{index.Biyf9aUg.js → index.DzdPUxsx.js} +2 -2
  133. streamlit/static/static/js/{index.C5oqIM3a.js → index.FioS1Y9m.js} +1 -1
  134. streamlit/static/static/js/{index.DZmBuE3z.js → index.L9pOjBEn.js} +3 -3
  135. streamlit/static/static/js/{index.DAyGxxdm.js → index.LjqoQCm5.js} +3 -3
  136. streamlit/static/static/js/{index.mSdC1FV6.js → index.OizPL4jg.js} +1 -1
  137. streamlit/static/static/js/{index.BSYebegS.js → index.Q2t_iBn0.js} +1 -1
  138. streamlit/static/static/js/index.WIMtx3m0.js +2 -0
  139. streamlit/static/static/js/index.Y9wPTZIf.js +1 -0
  140. streamlit/static/static/js/{index.BqxwnMem.js → index.YutgmD9x.js} +2 -2
  141. streamlit/static/static/js/{index.nL1fkE1D.js → index.b_f-McZ5.js} +1 -1
  142. streamlit/static/static/js/{index.y-pa6LIX.js → index.e6Ry6-Ft.js} +1 -1
  143. streamlit/static/static/js/index.hnu9U-5g.js +1 -0
  144. streamlit/static/static/js/{index.D6OexhdL.js → index.rvbQETlC.js} +1 -1
  145. streamlit/static/static/js/index.w7yKy9fh.js +6 -0
  146. streamlit/static/static/js/{index.BxMkW82k.js → index.y0h42OXL.js} +1 -1
  147. streamlit/static/static/js/{index.CPc_uZux.js → index.y5HxPwg9.js} +42 -42
  148. streamlit/static/static/js/{index.DNfyKqhQ.js → index.yHLCvUGh.js} +1 -1
  149. streamlit/static/static/js/{input.BcC6sPE_.js → input.CAtwSQ27.js} +1 -1
  150. streamlit/static/static/js/{main.TU5_aabd.js → main.VeMVx6VI.js} +1 -1
  151. streamlit/static/static/js/{memory.By_OTlI4.js → memory.CxS_lIUn.js} +1 -1
  152. streamlit/static/static/js/number-overlay-editor.CoqRgZW_.js +9 -0
  153. streamlit/static/static/js/{pandasStylerUtils.3IiIKU9-.js → pandasStylerUtils.DGWgd5sM.js} +1 -1
  154. streamlit/static/static/js/{sandbox.DnxTbWzV.js → sandbox.2mSqEau0.js} +1 -1
  155. streamlit/static/static/js/sprintfjs.CsoVVZ9k.js +1 -0
  156. streamlit/static/static/js/{styled-components.BeEcZ0vW.js → styled-components.BShfh7J8.js} +1 -1
  157. streamlit/static/static/js/{throttle.emUyC44c.js → throttle.Fq1DQK4p.js} +1 -1
  158. streamlit/static/static/js/{timepicker.DZ_ZufYF.js → timepicker.DmyY-qtn.js} +1 -1
  159. streamlit/static/static/js/{toConsumableArray.DDV1bN1-.js → toConsumableArray.Dvd9AIqV.js} +1 -1
  160. streamlit/static/static/js/uniqueId.CCajdEK8.js +1 -0
  161. streamlit/static/static/js/{useBasicWidgetState.DvpdEDYZ.js → useBasicWidgetState.COLQ5AFB.js} +1 -1
  162. streamlit/static/static/js/{useIntlLocale.BBDLbTq9.js → useIntlLocale.kdIj0ego.js} +1 -1
  163. streamlit/static/static/js/{useTextInputAutoExpand.BIApLJKn.js → useTextInputAutoExpand.DkuG1C1S.js} +1 -1
  164. streamlit/static/static/js/{useUpdateUiValue.DQ4RuJNC.js → useUpdateUiValue.-UI_JsjT.js} +1 -1
  165. streamlit/static/static/js/{useWaveformController.B0olyXLQ.js → useWaveformController.C5PTwL6I.js} +1 -1
  166. streamlit/static/static/js/{withCalculatedWidth.DYeqePuh.js → withCalculatedWidth.BREyS0pJ.js} +1 -1
  167. streamlit/static/static/js/{withFullScreenWrapper.DtkUCO_d.js → withFullScreenWrapper.DYDiEOrW.js} +1 -1
  168. streamlit/static/static/media/MaterialSymbols-Rounded.CnH1S47a.woff2 +0 -0
  169. streamlit/testing/v1/app_test.py +21 -5
  170. streamlit/testing/v1/element_tree.py +65 -2
  171. {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/METADATA +1 -1
  172. {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/RECORD +175 -173
  173. streamlit/proto/BokehChart_pb2.pyi +0 -56
  174. streamlit/proto/LabelVisibilityMessage_pb2.py +0 -28
  175. streamlit/static/static/js/data-grid-overlay-editor.CO0xdNiG.js +0 -1
  176. streamlit/static/static/js/formatNumber.DB5irY8c.js +0 -1
  177. streamlit/static/static/js/index.BBTKOM0z.js +0 -6
  178. streamlit/static/static/js/index.CE2WIFD1.js +0 -2
  179. streamlit/static/static/js/index.Cpu2p5bH.js +0 -1
  180. streamlit/static/static/js/index.CtbETWQK.js +0 -2
  181. streamlit/static/static/js/index.DhRAGiPR.js +0 -1
  182. streamlit/static/static/js/index.tuFFlbxa.js +0 -1
  183. streamlit/static/static/js/number-overlay-editor.FSRaRpbU.js +0 -9
  184. streamlit/static/static/js/sprintf.DpPCfzXw.js +0 -1
  185. streamlit/static/static/js/uniqueId.DTwvAE-J.js +0 -1
  186. streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
  187. {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/WHEEL +0 -0
  188. {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/entry_points.txt +0 -0
  189. {streamlit_nightly-1.53.2.dev20260131.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/top_level.txt +0 -0
@@ -133,7 +133,7 @@ def _set_query_params_for_switch(
133
133
  def rerun( # type: ignore[misc]
134
134
  *, # The scope argument can only be passed via keyword.
135
135
  scope: Literal["app", "fragment"] = "app",
136
- ) -> NoReturn: # ty: ignore[invalid-return-type]
136
+ ) -> NoReturn: # ty: ignore[empty-body]
137
137
  """Rerun the script immediately.
138
138
 
139
139
  When ``st.rerun()`` is called, Streamlit halts the current script run and
@@ -189,7 +189,7 @@ def switch_page( # type: ignore[misc]
189
189
  page: str | Path | StreamlitPage,
190
190
  *,
191
191
  query_params: QueryParamsInput | None = None,
192
- ) -> NoReturn: # ty: ignore[invalid-return-type]
192
+ ) -> NoReturn: # ty: ignore[empty-body]
193
193
  """Programmatically switch the current page in a multipage app.
194
194
 
195
195
  When ``st.switch_page`` is called, the current page execution stops and
@@ -91,6 +91,7 @@ from streamlit.elements.widgets.chat import ChatMixin
91
91
  from streamlit.elements.widgets.checkbox import CheckboxMixin
92
92
  from streamlit.elements.widgets.color_picker import ColorPickerMixin
93
93
  from streamlit.elements.widgets.data_editor import DataEditorMixin
94
+ from streamlit.elements.widgets.feedback import FeedbackMixin
94
95
  from streamlit.elements.widgets.file_uploader import FileUploaderMixin
95
96
  from streamlit.elements.widgets.multiselect import MultiSelectMixin
96
97
  from streamlit.elements.widgets.number_input import NumberInputMixin
@@ -189,6 +190,7 @@ class DeltaGenerator(
189
190
  ColorPickerMixin,
190
191
  EmptyMixin,
191
192
  ExceptionMixin,
193
+ FeedbackMixin,
192
194
  FileUploaderMixin,
193
195
  FormMixin,
194
196
  GraphvizMixin,
@@ -529,7 +529,9 @@ def NumberColumn(
529
529
  specifier, like ``"%d"`` to show a signed integer (e.g. "1234") or
530
530
  ``"%X"`` to show an unsigned hexadecimal integer (e.g. "4D2"). You
531
531
  can also add prefixes and suffixes. To show British pounds, use
532
- ``"£ %.2f"`` (e.g. "£ 1234.57"). For more information, see `sprint-js
532
+ ``"£ %.2f"`` (e.g. "£ 1234.57"). Use ``,`` for thousand separators
533
+ (e.g. ``"%,d"`` yields ``"1,234"``). For more information, see
534
+ `sprintf-js
533
535
  <https://github.com/alexei/sprintf.js?tab=readme-ov-file#format-specification>`_.
534
536
 
535
537
  Formatting from ``column_config`` always takes precedence over
@@ -2517,7 +2519,9 @@ def ProgressColumn(
2517
2519
  specifier, like ``"%d"`` to show a signed integer (e.g. "1234") or
2518
2520
  ``"%X"`` to show an unsigned hexadecimal integer (e.g. "4D2"). You
2519
2521
  can also add prefixes and suffixes. To show British pounds, use
2520
- ``"£ %.2f"`` (e.g. "£ 1234.57"). For more information, see `sprint-js
2522
+ ``"£ %.2f"`` (e.g. "£ 1234.57"). Use ``,`` for thousand separators
2523
+ (e.g. ``"%,d"`` yields ``"1,234"``). For more information, see
2524
+ `sprintf-js
2521
2525
  <https://github.com/alexei/sprintf.js?tab=readme-ov-file#format-specification>`_.
2522
2526
 
2523
2527
  Number formatting from ``column_config`` always takes precedence over
@@ -31,7 +31,7 @@ from streamlit import config
31
31
  from streamlit.elements.lib.form_utils import current_form_id
32
32
  from streamlit.errors import StreamlitDuplicateElementId, StreamlitDuplicateElementKey
33
33
  from streamlit.proto.ChatInput_pb2 import ChatInput
34
- from streamlit.proto.LabelVisibilityMessage_pb2 import LabelVisibilityMessage
34
+ from streamlit.proto.LabelVisibility_pb2 import LabelVisibility as LabelVisibilityProto
35
35
  from streamlit.runtime.scriptrunner_utils.script_run_context import (
36
36
  ScriptRunContext,
37
37
  get_script_run_ctx,
@@ -68,15 +68,15 @@ SAFE_VALUES: TypeAlias = Union[
68
68
 
69
69
  def get_label_visibility_proto_value(
70
70
  label_visibility_string: LabelVisibility,
71
- ) -> LabelVisibilityMessage.LabelVisibilityOptions.ValueType:
72
- """Returns one of LabelVisibilityMessage enum constants.py based on string value."""
71
+ ) -> LabelVisibilityProto.LabelVisibilityOptions.ValueType:
72
+ """Returns one of LabelVisibilityProto enum constants based on string value."""
73
73
 
74
74
  if label_visibility_string == "visible":
75
- return LabelVisibilityMessage.LabelVisibilityOptions.VISIBLE
75
+ return LabelVisibilityProto.LabelVisibilityOptions.VISIBLE
76
76
  if label_visibility_string == "hidden":
77
- return LabelVisibilityMessage.LabelVisibilityOptions.HIDDEN
77
+ return LabelVisibilityProto.LabelVisibilityOptions.HIDDEN
78
78
  if label_visibility_string == "collapsed":
79
- return LabelVisibilityMessage.LabelVisibilityOptions.COLLAPSED
79
+ return LabelVisibilityProto.LabelVisibilityOptions.COLLAPSED
80
80
 
81
81
  raise ValueError(f"Unknown label visibility value: {label_visibility_string}")
82
82
 
@@ -270,7 +270,6 @@ class MarkdownMixin:
270
270
  caption_proto = MarkdownProto()
271
271
  caption_proto.body = clean_text(body)
272
272
  caption_proto.allow_html = unsafe_allow_html
273
- caption_proto.is_caption = True
274
273
  caption_proto.element_type = MarkdownProto.Type.CAPTION
275
274
  if help:
276
275
  caption_proto.help = help
@@ -259,7 +259,8 @@ class MetricMixin:
259
259
  - ``"engineering"``: Show the number in engineering notation (e.g. "1.235E3").
260
260
  - printf-style format string: Format the number with a printf
261
261
  specifier, like ``"%d"`` to show a signed integer (e.g. "1234") or
262
- ``"%.2f"`` to show a float with 2 decimal places.
262
+ ``"%.2f"`` to show a float with 2 decimal places. Use ``,`` for
263
+ thousand separators (e.g. ``"%,d"`` yields ``"1,234"``).
263
264
 
264
265
  Examples
265
266
  --------
@@ -19,7 +19,6 @@ from dataclasses import dataclass, field
19
19
  from typing import (
20
20
  TYPE_CHECKING,
21
21
  Any,
22
- Final,
23
22
  Generic,
24
23
  Literal,
25
24
  TypeAlias,
@@ -28,7 +27,6 @@ from typing import (
28
27
  overload,
29
28
  )
30
29
 
31
- from streamlit import config
32
30
  from streamlit.elements.lib.form_utils import current_form_id
33
31
  from streamlit.elements.lib.layout_utils import (
34
32
  LayoutConfig,
@@ -76,20 +74,6 @@ if TYPE_CHECKING:
76
74
  T = TypeVar("T")
77
75
  V = TypeVar("V")
78
76
 
79
- _THUMB_ICONS: Final = (":material/thumb_up:", ":material/thumb_down:")
80
- _FACES_ICONS: Final = (
81
- ":material/sentiment_sad:",
82
- ":material/sentiment_dissatisfied:",
83
- ":material/sentiment_neutral:",
84
- ":material/sentiment_satisfied:",
85
- ":material/sentiment_very_satisfied:",
86
- )
87
- _NUMBER_STARS: Final = 5
88
- _STAR_ICON: Final = ":material/star:"
89
- # we don't have the filled-material icon library as a dependency. Hence, we have it here
90
- # in base64 format and send it over the wire as an image.
91
- _SELECTED_STAR_ICON: Final = ":material/star_filled:"
92
-
93
77
  SelectionMode: TypeAlias = Literal["single", "multi"]
94
78
 
95
79
 
@@ -185,35 +169,6 @@ class ButtonGroupSerde(Generic[T]):
185
169
  return self.serde.deserialize(ui_value)
186
170
 
187
171
 
188
- def get_mapped_options(
189
- feedback_option: Literal["thumbs", "faces", "stars"],
190
- ) -> tuple[list[ButtonGroupProto.Option], list[int]]:
191
- # options object understandable by the web app
192
- options: list[ButtonGroupProto.Option] = []
193
- # we use the option index in the webapp communication to
194
- # indicate which option is selected
195
- options_indices: list[int] = []
196
-
197
- if feedback_option == "thumbs":
198
- # reversing the index mapping to have thumbs up first (but still with the higher
199
- # index (=sentiment) in the list)
200
- options_indices = list(reversed(range(len(_THUMB_ICONS))))
201
- options = [ButtonGroupProto.Option(content_icon=icon) for icon in _THUMB_ICONS]
202
- elif feedback_option == "faces":
203
- options_indices = list(range(len(_FACES_ICONS)))
204
- options = [ButtonGroupProto.Option(content_icon=icon) for icon in _FACES_ICONS]
205
- elif feedback_option == "stars":
206
- options_indices = list(range(_NUMBER_STARS))
207
- options = [
208
- ButtonGroupProto.Option(
209
- content_icon=_STAR_ICON,
210
- selected_content_icon=_SELECTED_STAR_ICON,
211
- )
212
- ] * _NUMBER_STARS
213
-
214
- return options, options_indices
215
-
216
-
217
172
  def _build_proto(
218
173
  widget_id: str,
219
174
  formatted_options: Sequence[ButtonGroupProto.Option],
@@ -221,10 +176,7 @@ def _build_proto(
221
176
  disabled: bool,
222
177
  current_form_id: str,
223
178
  click_mode: ButtonGroupProto.ClickMode.ValueType,
224
- selection_visualization: ButtonGroupProto.SelectionVisualization.ValueType = (
225
- ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
226
- ),
227
- style: Literal["borderless", "pills", "segmented_control"] = "pills",
179
+ style: Literal["pills", "segmented_control"] = "pills",
228
180
  label: str | None = None,
229
181
  label_visibility: LabelVisibility = "visible",
230
182
  help: str | None = None,
@@ -249,7 +201,6 @@ def _build_proto(
249
201
 
250
202
  for formatted_option in formatted_options:
251
203
  proto.options.append(formatted_option)
252
- proto.selection_visualization = selection_visualization
253
204
  return proto
254
205
 
255
206
 
@@ -263,219 +214,6 @@ def _maybe_raise_selection_mode_warning(selection_mode: SelectionMode) -> None:
263
214
 
264
215
 
265
216
  class ButtonGroupMixin:
266
- # These overloads are not documented in the docstring, at least not at this time, on
267
- # the theory that most people won't know what it means. And the Literals here are a
268
- # subclass of int anyway. Usually, we would make a type alias for
269
- # Literal["thumbs", "faces", "stars"]; but, in this case, we don't use it in too
270
- # many other places, and it's a more helpful autocomplete if we just enumerate the
271
- # values explicitly, so a decision has been made to keep it as not an alias.
272
- @overload
273
- def feedback(
274
- self,
275
- options: Literal["thumbs"] = ...,
276
- *,
277
- key: Key | None = None,
278
- default: int | None = None,
279
- disabled: bool = False,
280
- on_change: WidgetCallback | None = None,
281
- args: WidgetArgs | None = None,
282
- kwargs: WidgetKwargs | None = None,
283
- width: Width = "content",
284
- ) -> Literal[0, 1] | None: ...
285
- @overload
286
- def feedback(
287
- self,
288
- options: Literal["faces", "stars"] = ...,
289
- *,
290
- key: Key | None = None,
291
- default: int | None = None,
292
- disabled: bool = False,
293
- on_change: WidgetCallback | None = None,
294
- args: WidgetArgs | None = None,
295
- kwargs: WidgetKwargs | None = None,
296
- width: Width = "content",
297
- ) -> Literal[0, 1, 2, 3, 4] | None: ...
298
- @gather_metrics("feedback")
299
- def feedback(
300
- self,
301
- options: Literal["thumbs", "faces", "stars"] = "thumbs",
302
- *,
303
- key: Key | None = None,
304
- default: int | None = None,
305
- disabled: bool = False,
306
- on_change: WidgetCallback | None = None,
307
- args: WidgetArgs | None = None,
308
- kwargs: WidgetKwargs | None = None,
309
- width: Width = "content",
310
- ) -> int | None:
311
- """Display a feedback widget.
312
-
313
- A feedback widget is an icon-based button group available in three
314
- styles, as described in ``options``. It is commonly used in chat and AI
315
- apps to allow users to rate responses.
316
-
317
- Parameters
318
- ----------
319
- options : "thumbs", "faces", or "stars"
320
- The feedback options displayed to the user. ``options`` can be one
321
- of the following:
322
-
323
- - ``"thumbs"`` (default): Streamlit displays a thumb-up and
324
- thumb-down button group.
325
- - ``"faces"``: Streamlit displays a row of five buttons with
326
- facial expressions depicting increasing satisfaction from left to
327
- right.
328
- - ``"stars"``: Streamlit displays a row of star icons, allowing the
329
- user to select a rating from one to five stars.
330
-
331
- key : str or int
332
- An optional string or integer to use as the unique key for the widget.
333
- If this is omitted, a key will be generated for the widget
334
- based on its content. No two widgets may have the same key.
335
-
336
- default : int or None
337
- Default feedback value. This must be consistent with the feedback
338
- type in ``options``:
339
-
340
- - 0 or 1 if ``options="thumbs"``.
341
- - Between 0 and 4, inclusive, if ``options="faces"`` or
342
- ``options="stars"``.
343
-
344
- disabled : bool
345
- An optional boolean that disables the feedback widget if set
346
- to ``True``. The default is ``False``.
347
-
348
- on_change : callable
349
- An optional callback invoked when this feedback widget's value
350
- changes.
351
-
352
- args : list or tuple
353
- An optional list or tuple of args to pass to the callback.
354
-
355
- kwargs : dict
356
- An optional dict of kwargs to pass to the callback.
357
-
358
- width : "content", "stretch", or int
359
- The width of the feedback widget. This can be one of the following:
360
-
361
- - ``"content"`` (default): The width of the widget matches the
362
- width of its content, but doesn't exceed the width of the parent
363
- container.
364
- - ``"stretch"``: The width of the widget matches the width of the
365
- parent container.
366
- - An integer specifying the width in pixels: The widget has a
367
- fixed width. If the specified width is greater than the width of
368
- the parent container, the width of the widget matches the width
369
- of the parent container.
370
-
371
- Returns
372
- -------
373
- int or None
374
- An integer indicating the user's selection, where ``0`` is the
375
- lowest feedback. Higher values indicate more positive feedback.
376
- If no option was selected, the widget returns ``None``.
377
-
378
- - For ``options="thumbs"``, a return value of ``0`` indicates
379
- thumbs-down, and ``1`` indicates thumbs-up.
380
- - For ``options="faces"`` and ``options="stars"``, return values
381
- range from ``0`` (least satisfied) to ``4`` (most satisfied).
382
-
383
- Examples
384
- --------
385
- Display a feedback widget with stars, and show the selected sentiment:
386
-
387
- >>> import streamlit as st
388
- >>>
389
- >>> sentiment_mapping = ["one", "two", "three", "four", "five"]
390
- >>> selected = st.feedback("stars")
391
- >>> if selected is not None:
392
- >>> st.markdown(f"You selected {sentiment_mapping[selected]} star(s).")
393
-
394
- .. output::
395
- https://doc-feedback-stars.streamlit.app/
396
- height: 200px
397
-
398
- Display a feedback widget with thumbs, and show the selected sentiment:
399
-
400
- >>> import streamlit as st
401
- >>>
402
- >>> sentiment_mapping = [":material/thumb_down:", ":material/thumb_up:"]
403
- >>> selected = st.feedback("thumbs")
404
- >>> if selected is not None:
405
- >>> st.markdown(f"You selected: {sentiment_mapping[selected]}")
406
-
407
- .. output::
408
- https://doc-feedback-thumbs.streamlit.app/
409
- height: 200px
410
-
411
- """
412
-
413
- if options not in {"thumbs", "faces", "stars"}:
414
- raise StreamlitAPIException(
415
- "The options argument to st.feedback must be one of "
416
- "['thumbs', 'faces', 'stars']. "
417
- f"The argument passed was '{options}'."
418
- )
419
- transformed_options, options_indices = get_mapped_options(options)
420
-
421
- if default is not None and (default < 0 or default >= len(transformed_options)):
422
- raise StreamlitAPIException(
423
- f"The default value in '{options}' must be a number between 0 and {len(transformed_options) - 1}."
424
- f" The passed default value is {default}"
425
- )
426
-
427
- # Convert small pixel widths to "content" to prevent icon wrapping.
428
- # Calculate threshold based on theme.baseFontSize to be responsive to
429
- # custom themes. The calculation is based on icon buttons sized in rem:
430
- # - Button size: ~1.5rem (icon 1.25rem + padding 0.125rem x 2)
431
- # - Gap: 0.125rem between buttons
432
- # - thumbs: 2 buttons + 1 gap = 3.125rem
433
- # - faces/stars: 5 buttons + 4 gaps = 8rem
434
- base_font_size = config.get_option("theme.baseFontSize") or 16
435
- button_size_rem = 1.5
436
- gap_size_rem = 0.125
437
-
438
- if options == "thumbs":
439
- # 2 buttons + 1 gap
440
- min_width_rem = 2 * button_size_rem + gap_size_rem
441
- else:
442
- # 5 buttons + 4 gaps (faces or stars)
443
- min_width_rem = 5 * button_size_rem + 4 * gap_size_rem
444
-
445
- # Convert rem to pixels based on base font size, add 10% buffer
446
- min_width_threshold = int(min_width_rem * base_font_size * 1.1)
447
-
448
- if isinstance(width, int) and width < min_width_threshold:
449
- width = "content"
450
-
451
- _default: list[int] | None = (
452
- [options_indices[default]] if default is not None else None
453
- )
454
- serde = _SingleSelectSerde[int](options_indices, default_value=_default)
455
-
456
- selection_visualization = ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
457
- if options == "stars":
458
- selection_visualization = (
459
- ButtonGroupProto.SelectionVisualization.ALL_UP_TO_SELECTED
460
- )
461
-
462
- sentiment = self._button_group(
463
- transformed_options,
464
- default=_default,
465
- key=key,
466
- selection_mode="single",
467
- disabled=disabled,
468
- deserializer=serde.deserialize,
469
- serializer=serde.serialize,
470
- on_change=on_change,
471
- args=args,
472
- kwargs=kwargs,
473
- selection_visualization=selection_visualization,
474
- style="borderless",
475
- width=width,
476
- )
477
- return sentiment.value
478
-
479
217
  @overload
480
218
  def pills(
481
219
  self,
@@ -1023,18 +761,13 @@ class ButtonGroupMixin:
1023
761
  default: list[int] | None = None,
1024
762
  selection_mode: SelectionMode = "single",
1025
763
  disabled: bool = False,
1026
- style: Literal[
1027
- "borderless", "pills", "segmented_control"
1028
- ] = "segmented_control",
764
+ style: Literal["pills", "segmented_control"] = "segmented_control",
1029
765
  format_func: Callable[[V], ButtonGroupProto.Option] | None = None,
1030
766
  deserializer: WidgetDeserializer[T],
1031
767
  serializer: WidgetSerializer[T],
1032
768
  on_change: WidgetCallback | None = None,
1033
769
  args: WidgetArgs | None = None,
1034
770
  kwargs: WidgetKwargs | None = None,
1035
- selection_visualization: ButtonGroupProto.SelectionVisualization.ValueType = (
1036
- ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
1037
- ),
1038
771
  label: str | None = None,
1039
772
  label_visibility: LabelVisibility = "visible",
1040
773
  help: str | None = None,
@@ -1062,9 +795,9 @@ class ButtonGroupMixin:
1062
795
  "`selection_mode='single'`."
1063
796
  )
1064
797
 
1065
- if style not in {"borderless", "pills", "segmented_control"}:
798
+ if style not in {"pills", "segmented_control"}:
1066
799
  raise StreamlitAPIException(
1067
- "The style argument must be one of ['borderless', 'pills', 'segmented_control']. "
800
+ "The style argument must be one of ['pills', 'segmented_control']. "
1068
801
  f"The argument passed was '{style}'."
1069
802
  )
1070
803
 
@@ -1091,11 +824,9 @@ class ButtonGroupMixin:
1091
824
  )
1092
825
 
1093
826
  element_id = compute_and_register_element_id(
1094
- # The borderless style is used by st.feedback, but users expect to see
1095
- # "feedback" in errors
1096
- "feedback" if style == "borderless" else style,
827
+ style,
1097
828
  user_key=key,
1098
- # Treat the provided key as the main identity for segmented_control, pills and feedback,
829
+ # Treat the provided key as the main identity for segmented_control and pills,
1099
830
  # and only include kwargs that can invalidate the current selection.
1100
831
  # We whitelist the formatted options and the click mode (single vs multi).
1101
832
  key_as_main_identity={"options", "click_mode"},
@@ -1116,7 +847,6 @@ class ButtonGroupMixin:
1116
847
  disabled,
1117
848
  form_id,
1118
849
  click_mode=parsed_selection_mode,
1119
- selection_visualization=selection_visualization,
1120
850
  style=style,
1121
851
  label=label,
1122
852
  label_visibility=label_visibility,