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.
Files changed (203) hide show
  1. streamlit/__init__.py +3 -10
  2. streamlit/commands/logo.py +4 -3
  3. streamlit/commands/navigation.py +1 -1
  4. streamlit/commands/page_config.py +4 -1
  5. streamlit/components/v1/custom_component.py +2 -2
  6. streamlit/config.py +82 -1
  7. streamlit/connections/snowflake_connection.py +3 -1
  8. streamlit/delta_generator.py +3 -0
  9. streamlit/elements/arrow.py +155 -70
  10. streamlit/elements/bokeh_chart.py +13 -3
  11. streamlit/elements/deck_gl_json_chart.py +0 -1
  12. streamlit/elements/dialog_decorator.py +7 -59
  13. streamlit/elements/form.py +10 -1
  14. streamlit/elements/graphviz_chart.py +57 -6
  15. streamlit/elements/heading.py +17 -16
  16. streamlit/elements/image.py +64 -37
  17. streamlit/elements/layouts.py +2 -2
  18. streamlit/elements/lib/built_in_chart_utils.py +2 -5
  19. streamlit/elements/lib/column_config_utils.py +18 -4
  20. streamlit/elements/lib/column_types.py +75 -30
  21. streamlit/elements/lib/dialog.py +3 -3
  22. streamlit/elements/lib/image_utils.py +19 -11
  23. streamlit/elements/lib/layout_utils.py +15 -2
  24. streamlit/elements/lib/utils.py +20 -41
  25. streamlit/elements/markdown.py +7 -6
  26. streamlit/elements/media.py +6 -13
  27. streamlit/elements/metric.py +78 -1
  28. streamlit/elements/pdf.py +192 -0
  29. streamlit/elements/plotly_chart.py +3 -2
  30. streamlit/elements/pyplot.py +53 -11
  31. streamlit/elements/toast.py +81 -5
  32. streamlit/elements/vega_charts.py +3 -8
  33. streamlit/elements/widgets/audio_input.py +0 -1
  34. streamlit/elements/widgets/button.py +0 -4
  35. streamlit/elements/widgets/button_group.py +5 -4
  36. streamlit/elements/widgets/camera_input.py +0 -1
  37. streamlit/elements/widgets/chat.py +11 -13
  38. streamlit/elements/widgets/checkbox.py +0 -1
  39. streamlit/elements/widgets/color_picker.py +0 -1
  40. streamlit/elements/widgets/data_editor.py +142 -62
  41. streamlit/elements/widgets/file_uploader.py +74 -37
  42. streamlit/elements/widgets/multiselect.py +0 -1
  43. streamlit/elements/widgets/number_input.py +0 -1
  44. streamlit/elements/widgets/radio.py +0 -1
  45. streamlit/elements/widgets/select_slider.py +0 -1
  46. streamlit/elements/widgets/selectbox.py +0 -1
  47. streamlit/elements/widgets/slider.py +0 -1
  48. streamlit/elements/widgets/text_widgets.py +0 -2
  49. streamlit/elements/widgets/time_widgets.py +0 -2
  50. streamlit/errors.py +11 -0
  51. streamlit/material_icon_names.py +1 -1
  52. streamlit/proto/Arrow_pb2.py +14 -8
  53. streamlit/proto/Arrow_pb2.pyi +11 -3
  54. streamlit/proto/Block_pb2.py +16 -16
  55. streamlit/proto/Block_pb2.pyi +2 -0
  56. streamlit/proto/ChatInput_pb2.py +3 -3
  57. streamlit/proto/ChatInput_pb2.pyi +2 -0
  58. streamlit/proto/FileUploader_pb2.py +2 -2
  59. streamlit/proto/FileUploader_pb2.pyi +5 -1
  60. streamlit/proto/GraphVizChart_pb2.py +4 -2
  61. streamlit/proto/GraphVizChart_pb2.pyi +1 -1
  62. streamlit/proto/Image_pb2.py +4 -2
  63. streamlit/proto/Image_pb2.pyi +1 -10
  64. streamlit/proto/Metric_pb2.py +8 -6
  65. streamlit/proto/Metric_pb2.pyi +34 -10
  66. streamlit/proto/Toast_pb2.py +2 -2
  67. streamlit/proto/Toast_pb2.pyi +10 -1
  68. streamlit/runtime/caching/__init__.py +14 -2
  69. streamlit/runtime/caching/cache_data_api.py +0 -17
  70. streamlit/runtime/caching/cache_resource_api.py +0 -16
  71. streamlit/runtime/caching/cached_message_replay.py +8 -20
  72. streamlit/runtime/caching/hashing.py +31 -1
  73. streamlit/runtime/credentials.py +4 -4
  74. streamlit/runtime/fragment.py +0 -42
  75. streamlit/runtime/websocket_session_manager.py +1 -1
  76. streamlit/static/index.html +2 -2
  77. streamlit/static/manifest.json +224 -252
  78. streamlit/static/static/css/{index.CJVRHjQZ.css → index.C8X8rNzw.css} +1 -1
  79. streamlit/static/static/css/index.COe1010n.css +1 -0
  80. streamlit/static/static/js/{ErrorOutline.esm.DjObtx4K.js → ErrorOutline.esm.u9XvzxL8.js} +1 -1
  81. streamlit/static/static/js/{FileDownload.esm.Bz9nxNC5.js → FileDownload.esm.CaRyZ-b2.js} +1 -1
  82. streamlit/static/static/js/FileHelper.Dk2SwIi3.js +5 -0
  83. streamlit/static/static/js/FormClearHelper.l_UPPvkg.js +1 -0
  84. streamlit/static/static/js/{Hooks.DEoLCfOE.js → Hooks.BxrVEftw.js} +1 -1
  85. streamlit/static/static/js/InputInstructions.C254RU9X.js +1 -0
  86. streamlit/static/static/js/Particles.DkY6FDnc.js +1 -0
  87. streamlit/static/static/js/ProgressBar.BPtSM82n.js +2 -0
  88. streamlit/static/static/js/Toolbar.BO_3WBaS.js +1 -0
  89. streamlit/static/static/js/{base-input.BmvSaPd2.js → base-input.egUI4LjJ.js} +4 -4
  90. streamlit/static/static/js/{checkbox.Cgxgc0et.js → checkbox.ButpszcE.js} +2 -2
  91. streamlit/static/static/js/createSuper.DYJA5xa6.js +1 -0
  92. streamlit/static/static/js/data-grid-overlay-editor.C9gQLEnU.js +1 -0
  93. streamlit/static/static/js/{downloader.M6jQeNDf.js → downloader.B3TjsSPZ.js} +1 -1
  94. streamlit/static/static/js/es6.BYSNuG4D.js +2 -0
  95. streamlit/static/static/js/iframeResizer.contentWindow.CNPHJsF2.js +1 -0
  96. streamlit/static/static/js/index.0tDq1WXk.js +1 -0
  97. streamlit/static/static/js/index.BBnWuh07.js +976 -0
  98. streamlit/static/static/js/index.BDZorv41.js +1 -0
  99. streamlit/static/static/js/{index.CbdWnLqS.js → index.BH79B25f.js} +3 -3
  100. streamlit/static/static/js/index.BeTC4Yl-.js +197 -0
  101. streamlit/static/static/js/index.BnOd05Ko.js +2 -0
  102. streamlit/static/static/js/index.BoJaJReB.js +1 -0
  103. streamlit/static/static/js/index.Bp1Of6L8.js +1 -0
  104. streamlit/static/static/js/index.Bpe4-O2W.js +1 -0
  105. streamlit/static/static/js/index.BrD9sbpx.js +1 -0
  106. streamlit/static/static/js/index.C1qCS-sd.js +1 -0
  107. streamlit/static/static/js/index.C3EXAI-u.js +1 -0
  108. streamlit/static/static/js/index.C77g9sAQ.js +3 -0
  109. streamlit/static/static/js/{index.BXDq9dj4.js → index.CFePF7s4.js} +1 -1
  110. streamlit/static/static/js/index.CFjU0x00.js +1 -0
  111. streamlit/static/static/js/index.Ca3y4ztK.js +1 -0
  112. streamlit/static/static/js/{index.CgZDfhN4.js → index.Cb9gN2T2.js} +2 -2
  113. streamlit/static/static/js/{index.tsvTLdio.js → index.CbwuUwu4.js} +9 -9
  114. streamlit/static/static/js/index.CeXLlclc.js +1 -0
  115. streamlit/static/static/js/index.CfiZGqj3.js +3 -0
  116. streamlit/static/static/js/index.CjQnYKID.js +1 -0
  117. streamlit/static/static/js/index.Cl_966eE.js +3858 -0
  118. streamlit/static/static/js/{index.Cqa4gqqN.js → index.CqSRo6zQ.js} +1 -1
  119. streamlit/static/static/js/index.CuEFSQ-o.js +1 -0
  120. streamlit/static/static/js/index.D4jR1m1z.js +1 -0
  121. streamlit/static/static/js/index.DGcW849X.js +1 -0
  122. streamlit/static/static/js/index.DKb-BAE2.js +1 -0
  123. streamlit/static/static/js/index.DP1rDFP0.js +1 -0
  124. streamlit/static/static/js/{index.D1EayrNh.js → index.DStzYLqM.js} +2 -2
  125. streamlit/static/static/js/index.DVKQKDLu.js +1 -0
  126. streamlit/static/static/js/index.DWedOrkQ.js +1 -0
  127. streamlit/static/static/js/index.DYbRPmVF.js +1 -0
  128. streamlit/static/static/js/index.DgpIMUsr.js +1 -0
  129. streamlit/static/static/js/index.DtwkPJs5.js +5367 -0
  130. streamlit/static/static/js/{index.D1jHqUJq.js → index.MQLQLR5Z.js} +1 -1
  131. streamlit/static/static/js/index.uInpwWAP.js +1 -0
  132. streamlit/static/static/js/index.z992t-BQ.js +7 -0
  133. streamlit/static/static/js/{input.DZd6EQlV.js → input.CbP5ZuQ7.js} +2 -2
  134. streamlit/static/static/js/{memory.ptkfuI71.js → memory.BuacVo2L.js} +1 -1
  135. streamlit/static/static/js/number-overlay-editor.BZb9zRl_.js +9 -0
  136. streamlit/static/static/js/{possibleConstructorReturn.Bd4ImlQ9.js → possibleConstructorReturn.DSM84rOS.js} +1 -1
  137. streamlit/static/static/js/{sandbox.DsH8LuID.js → sandbox.C480llMG.js} +1 -1
  138. streamlit/static/static/js/{timepicker.QVekV78C.js → timepicker.BunxCVp7.js} +4 -4
  139. streamlit/static/static/js/{toConsumableArray.BJvaP8gb.js → toConsumableArray.B4o8rEx1.js} +3 -3
  140. streamlit/static/static/js/uniqueId.tii0yosY.js +1 -0
  141. streamlit/static/static/js/{useBasicWidgetState.DB3vMS9V.js → useBasicWidgetState.Bnm4FD6K.js} +1 -1
  142. streamlit/static/static/js/{useTextInputAutoExpand.CBkGkaRt.js → useTextInputAutoExpand.Dgtwc1m0.js} +2 -2
  143. streamlit/static/static/js/useUpdateUiValue.DjXdMFGw.js +1 -0
  144. streamlit/static/static/js/withFullScreenWrapper.0cy2pVf5.js +1 -0
  145. streamlit/static/static/media/MaterialSymbols-Rounded.CBxVaFdk.woff2 +0 -0
  146. streamlit/user_info.py +3 -1
  147. streamlit/web/server/browser_websocket_handler.py +15 -0
  148. {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/METADATA +4 -2
  149. {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/RECORD +153 -156
  150. streamlit/static/static/css/index.CQt5TjGB.css +0 -1
  151. streamlit/static/static/js/FileHelper.BrQvUXVD.js +0 -5
  152. streamlit/static/static/js/FormClearHelper.DF4gFAOO.js +0 -1
  153. streamlit/static/static/js/InputInstructions.D8zoMog9.js +0 -1
  154. streamlit/static/static/js/Particles.CCFySwdL.js +0 -1
  155. streamlit/static/static/js/ProgressBar.COK9j1l0.js +0 -2
  156. streamlit/static/static/js/Toolbar.Dt4jIKlY.js +0 -1
  157. streamlit/static/static/js/createSuper.siQeagI2.js +0 -1
  158. streamlit/static/static/js/data-grid-overlay-editor.Ct51iCb_.js +0 -1
  159. streamlit/static/static/js/es6.CMaUdEZ5.js +0 -2
  160. streamlit/static/static/js/iframeResizer.contentWindow.C33BryyP.js +0 -1
  161. streamlit/static/static/js/index.8GJD0eeD.js +0 -1
  162. streamlit/static/static/js/index.8QEYHMQD.js +0 -1
  163. streamlit/static/static/js/index.Ay41Wnu9.js +0 -1
  164. streamlit/static/static/js/index.BLiKiJ7_.js +0 -1
  165. streamlit/static/static/js/index.BT78cJmU.js +0 -1
  166. streamlit/static/static/js/index.BdGvnhlM.js +0 -1
  167. streamlit/static/static/js/index.BfasrT0d.js +0 -1
  168. streamlit/static/static/js/index.CCdtFMFG.js +0 -1
  169. streamlit/static/static/js/index.CFRGZDz1.js +0 -1
  170. streamlit/static/static/js/index.CFSFYiPA.js +0 -5366
  171. streamlit/static/static/js/index.CeiIiXap.js +0 -1
  172. streamlit/static/static/js/index.CzX2xpyc.js +0 -1
  173. streamlit/static/static/js/index.D1ErX5go.js +0 -2
  174. streamlit/static/static/js/index.D5gweoL5.js +0 -7
  175. streamlit/static/static/js/index.DByVKZgq.js +0 -1
  176. streamlit/static/static/js/index.DEND45D1.js +0 -3
  177. streamlit/static/static/js/index.DKN5MVff.js +0 -781
  178. streamlit/static/static/js/index.DfoxW1gP.js +0 -3855
  179. streamlit/static/static/js/index.Dtf1Ac0x.js +0 -1
  180. streamlit/static/static/js/index.DxrLhpeO.js +0 -1
  181. streamlit/static/static/js/index.J7o-_HIh.js +0 -1
  182. streamlit/static/static/js/index.LU8juINp.js +0 -197
  183. streamlit/static/static/js/index.L_N2iylt.js +0 -1
  184. streamlit/static/static/js/index.PZUX2kRz.js +0 -3
  185. streamlit/static/static/js/index.ROjU6K0k.js +0 -1
  186. streamlit/static/static/js/index.WSNLkF94.js +0 -1
  187. streamlit/static/static/js/index.X5W3gJLn.js +0 -1
  188. streamlit/static/static/js/index.k9LYqfSL.js +0 -1
  189. streamlit/static/static/js/index.pnHtHv_c.js +0 -203
  190. streamlit/static/static/js/index.tPUXqsfW.js +0 -1
  191. streamlit/static/static/js/mergeWith.GRNk8iwv.js +0 -1
  192. streamlit/static/static/js/number-overlay-editor.DXS2qb1U.js +0 -9
  193. streamlit/static/static/js/threshold.DjX0wlsa.js +0 -1
  194. streamlit/static/static/js/timer.CAwTRJ_g.js +0 -1
  195. streamlit/static/static/js/uniqueId.D_5M8Dgf.js +0 -1
  196. streamlit/static/static/js/useUpdateUiValue.C7ZKpLQK.js +0 -1
  197. streamlit/static/static/js/value.CgPGBV_l.js +0 -1
  198. streamlit/static/static/js/withFullScreenWrapper.C-gXt0Rl.js +0 -1
  199. streamlit/static/static/media/MaterialSymbols-Rounded.DsbC8sYI.woff2 +0 -0
  200. {streamlit-1.48.1.data → streamlit-1.49.0.data}/scripts/streamlit.cmd +0 -0
  201. {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/WHEEL +0 -0
  202. {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/entry_points.txt +0 -0
  203. {streamlit-1.48.1.dist-info → streamlit-1.49.0.dist-info}/top_level.txt +0 -0
@@ -18,7 +18,7 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  import datetime
21
- from typing import TYPE_CHECKING, Literal, TypedDict, Union
21
+ from typing import TYPE_CHECKING, Callable, Literal, TypedDict, Union
22
22
 
23
23
  from typing_extensions import NotRequired, TypeAlias
24
24
 
@@ -84,9 +84,17 @@ class CheckboxColumnConfig(TypedDict):
84
84
  type: Literal["checkbox"]
85
85
 
86
86
 
87
+ SelectboxOptionValue: TypeAlias = Union[str, int, float, bool]
88
+
89
+
90
+ class SelectboxOption(TypedDict):
91
+ value: SelectboxOptionValue
92
+ label: NotRequired[str | None]
93
+
94
+
87
95
  class SelectboxColumnConfig(TypedDict):
88
96
  type: Literal["selectbox"]
89
- options: NotRequired[list[str | int | float] | None]
97
+ options: NotRequired[list[SelectboxOptionValue | SelectboxOption] | None]
90
98
 
91
99
 
92
100
  class LinkColumnConfig(TypedDict):
@@ -190,8 +198,7 @@ class ColumnConfig(TypedDict, total=False):
190
198
 
191
199
  disabled: bool or None
192
200
  Whether editing should be disabled for this column. If this is ``None``
193
- (default), Streamlit will decide: indices are disabled and data columns
194
- are not.
201
+ (default), Streamlit will enable editing wherever possible.
195
202
 
196
203
  If a column has mixed types, it may become uneditable regardless of
197
204
  ``disabled``.
@@ -227,7 +234,7 @@ class ColumnConfig(TypedDict, total=False):
227
234
  disabled: bool | None
228
235
  required: bool | None
229
236
  pinned: bool | None
230
- default: str | bool | int | float | None
237
+ default: str | bool | int | float | list[str] | None
231
238
  alignment: Literal["left", "center", "right"] | None
232
239
  type_config: (
233
240
  NumberColumnConfig
@@ -295,8 +302,7 @@ def Column(
295
302
 
296
303
  disabled: bool or None
297
304
  Whether editing should be disabled for this column. If this is ``None``
298
- (default), Streamlit will decide: indices are disabled and data columns
299
- are not.
305
+ (default), Streamlit will enable editing wherever possible.
300
306
 
301
307
  If a column has mixed types, it may become uneditable regardless of
302
308
  ``disabled``.
@@ -400,8 +406,7 @@ def NumberColumn(
400
406
 
401
407
  disabled: bool or None
402
408
  Whether editing should be disabled for this column. If this is ``None``
403
- (default), Streamlit will decide: indices are disabled and data columns
404
- are not.
409
+ (default), Streamlit will enable editing wherever possible.
405
410
 
406
411
  If a column has mixed types, it may become uneditable regardless of
407
412
  ``disabled``.
@@ -563,8 +568,7 @@ def TextColumn(
563
568
 
564
569
  disabled: bool or None
565
570
  Whether editing should be disabled for this column. If this is ``None``
566
- (default), Streamlit will decide: indices are disabled and data columns
567
- are not.
571
+ (default), Streamlit will enable editing wherever possible.
568
572
 
569
573
  If a column has mixed types, it may become uneditable regardless of
570
574
  ``disabled``.
@@ -686,8 +690,7 @@ def LinkColumn(
686
690
 
687
691
  disabled: bool or None
688
692
  Whether editing should be disabled for this column. If this is ``None``
689
- (default), Streamlit will decide: indices are disabled and data columns
690
- are not.
693
+ (default), Streamlit will enable editing wherever possible.
691
694
 
692
695
  If a column has mixed types, it may become uneditable regardless of
693
696
  ``disabled``.
@@ -845,8 +848,7 @@ def CheckboxColumn(
845
848
 
846
849
  disabled: bool or None
847
850
  Whether editing should be disabled for this column. If this is ``None``
848
- (default), Streamlit will decide: indices are disabled and data columns
849
- are not.
851
+ (default), Streamlit will enable editing wherever possible.
850
852
 
851
853
  If a column has mixed types, it may become uneditable regardless of
852
854
  ``disabled``.
@@ -919,8 +921,9 @@ def SelectboxColumn(
919
921
  disabled: bool | None = None,
920
922
  required: bool | None = None,
921
923
  pinned: bool | None = None,
922
- default: str | int | float | None = None,
923
- options: Iterable[str | int | float] | None = None,
924
+ default: SelectboxOptionValue | None = None,
925
+ options: Iterable[SelectboxOptionValue] | None = None,
926
+ format_func: Callable[[SelectboxOptionValue], str] | None = None,
924
927
  ) -> ColumnConfig:
925
928
  """Configure a selectbox column in ``st.dataframe`` or ``st.data_editor``.
926
929
 
@@ -954,8 +957,7 @@ def SelectboxColumn(
954
957
 
955
958
  disabled: bool or None
956
959
  Whether editing should be disabled for this column. If this is ``None``
957
- (default), Streamlit will decide: indices are disabled and data columns
958
- are not.
960
+ (default), Streamlit will enable editing wherever possible.
959
961
 
960
962
  If a column has mixed types, it may become uneditable regardless of
961
963
  ``disabled``.
@@ -977,12 +979,19 @@ def SelectboxColumn(
977
979
  Specifies the default value in this column when a new row is added by
978
980
  the user. This defaults to ``None``.
979
981
 
980
- options: Iterable of str or None
982
+ options: Iterable[str, int, float, bool] or None
981
983
  The options that can be selected during editing. If this is ``None``
982
984
  (default), the options will be inferred from the underlying dataframe
983
985
  column if its dtype is "category". For more information, see `Pandas docs
984
986
  <https://pandas.pydata.org/docs/user_guide/categorical.html>`_).
985
987
 
988
+ format_func: function or None
989
+ Function to modify the display of the options. It receives
990
+ the raw option defined in ``options`` as an argument and should output
991
+ the label to be shown for that option. If this is ``None`` (default),
992
+ the raw option is used as the label.
993
+
994
+
986
995
  Examples
987
996
  --------
988
997
  >>> import pandas as pd
@@ -1022,6 +1031,15 @@ def SelectboxColumn(
1022
1031
  height: 300px
1023
1032
  """
1024
1033
 
1034
+ # Process options with format_func
1035
+ processed_options: Iterable[str | int | float | SelectboxOption] | None = options
1036
+ if options and format_func is not None:
1037
+ processed_options = []
1038
+ for option in options:
1039
+ processed_options.append(
1040
+ SelectboxOption(value=option, label=format_func(option))
1041
+ )
1042
+
1025
1043
  return ColumnConfig(
1026
1044
  label=label,
1027
1045
  width=width,
@@ -1031,7 +1049,8 @@ def SelectboxColumn(
1031
1049
  pinned=pinned,
1032
1050
  default=default,
1033
1051
  type_config=SelectboxColumnConfig(
1034
- type="selectbox", options=list(options) if options is not None else None
1052
+ type="selectbox",
1053
+ options=list(processed_options) if processed_options is not None else None,
1035
1054
  ),
1036
1055
  )
1037
1056
 
@@ -1427,12 +1446,20 @@ def ListColumn(
1427
1446
  width: ColumnWidth | None = None,
1428
1447
  help: str | None = None,
1429
1448
  pinned: bool | None = None,
1449
+ disabled: bool | None = None,
1450
+ required: bool | None = None,
1451
+ default: Iterable[str] | None = None,
1430
1452
  ) -> ColumnConfig:
1431
1453
  """Configure a list column in ``st.dataframe`` or ``st.data_editor``.
1432
1454
 
1433
- This is the default column type for list-like values. List columns are not editable
1434
- at the moment. This command needs to be used in the ``column_config`` parameter of
1435
- ``st.dataframe`` or ``st.data_editor``.
1455
+ This is the default column type for list-like values. This command needs to
1456
+ be used in the ``column_config`` parameter of ``st.dataframe`` or
1457
+ ``st.data_editor``.
1458
+
1459
+ .. Note::
1460
+ Editing for non-string or mixed type lists can cause issues with Arrow
1461
+ serialization. We recommend you disable editing for these columns or
1462
+ convert of all list values to strings.
1436
1463
 
1437
1464
  Parameters
1438
1465
  ----------
@@ -1464,6 +1491,24 @@ def ListColumn(
1464
1491
  (default), Streamlit will decide: index columns are pinned, and data
1465
1492
  columns are not pinned.
1466
1493
 
1494
+ disabled: bool or None
1495
+ Whether editing should be disabled for this column. If this is ``None``
1496
+ (default), Streamlit will enable editing wherever possible.
1497
+
1498
+ If a column has mixed types, it may become uneditable regardless of
1499
+ ``disabled``.
1500
+
1501
+ required: bool or None
1502
+ Whether edited cells in the column need to have a value. If this is
1503
+ ``False`` (default), the user can submit empty values for this column.
1504
+ If this is ``True``, an edited cell in this column can only be
1505
+ submitted if its value is not ``None``, and a new row will only be
1506
+ submitted after the user fills in this column.
1507
+
1508
+ default: Iterable of str or None
1509
+ Specifies the default value in this column when a new row is added by
1510
+ the user. This defaults to ``None``.
1511
+
1467
1512
  Examples
1468
1513
  --------
1469
1514
  >>> import pandas as pd
@@ -1501,6 +1546,9 @@ def ListColumn(
1501
1546
  width=width,
1502
1547
  help=help,
1503
1548
  pinned=pinned,
1549
+ disabled=disabled,
1550
+ required=required,
1551
+ default=None if default is None else list(default),
1504
1552
  type_config=ListColumnConfig(type="list"),
1505
1553
  )
1506
1554
 
@@ -1554,8 +1602,7 @@ def DatetimeColumn(
1554
1602
 
1555
1603
  disabled: bool or None
1556
1604
  Whether editing should be disabled for this column. If this is ``None``
1557
- (default), Streamlit will decide: indices are disabled and data columns
1558
- are not.
1605
+ (default), Streamlit will enable editing wherever possible.
1559
1606
 
1560
1607
  If a column has mixed types, it may become uneditable regardless of
1561
1608
  ``disabled``.
@@ -1717,8 +1764,7 @@ def TimeColumn(
1717
1764
 
1718
1765
  disabled: bool or None
1719
1766
  Whether editing should be disabled for this column. If this is ``None``
1720
- (default), Streamlit will decide: indices are disabled and data columns
1721
- are not.
1767
+ (default), Streamlit will enable editing wherever possible.
1722
1768
 
1723
1769
  If a column has mixed types, it may become uneditable regardless of
1724
1770
  ``disabled``.
@@ -1871,8 +1917,7 @@ def DateColumn(
1871
1917
 
1872
1918
  disabled: bool or None
1873
1919
  Whether editing should be disabled for this column. If this is ``None``
1874
- (default), Streamlit will decide: indices are disabled and data columns
1875
- are not.
1920
+ (default), Streamlit will enable editing wherever possible.
1876
1921
 
1877
1922
  If a column has mixed types, it may become uneditable regardless of
1878
1923
  ``disabled``.
@@ -35,7 +35,7 @@ if TYPE_CHECKING:
35
35
  from streamlit.cursor import Cursor
36
36
  from streamlit.runtime.state import WidgetCallback
37
37
 
38
- DialogWidth: TypeAlias = Literal["small", "large"]
38
+ DialogWidth: TypeAlias = Literal["small", "large", "medium"]
39
39
 
40
40
 
41
41
  def _process_dialog_width_input(
@@ -47,6 +47,8 @@ def _process_dialog_width_input(
47
47
  """
48
48
  if width == "large":
49
49
  return BlockProto.Dialog.DialogWidth.LARGE
50
+ if width == "medium":
51
+ return BlockProto.Dialog.DialogWidth.MEDIUM
50
52
 
51
53
  return BlockProto.Dialog.DialogWidth.SMALL
52
54
 
@@ -110,8 +112,6 @@ class Dialog(DeltaGenerator):
110
112
  element_id = compute_and_register_element_id(
111
113
  "dialog",
112
114
  user_key=None,
113
- # Dialogs within forms still trigger a normal rerun:
114
- form_id="",
115
115
  dg=parent,
116
116
  title=title,
117
117
  dismissible=dismissible,
@@ -34,6 +34,7 @@ if TYPE_CHECKING:
34
34
  import numpy.typing as npt
35
35
  from PIL import GifImagePlugin, Image, ImageFile
36
36
 
37
+ from streamlit.elements.lib.layout_utils import LayoutConfig
37
38
  from streamlit.proto.Image_pb2 import ImageList as ImageListProto
38
39
  from streamlit.type_util import NumpyShape
39
40
 
@@ -176,7 +177,7 @@ def _get_image_format_mimetype(image_format: ImageFormat) -> str:
176
177
 
177
178
 
178
179
  def _ensure_image_size_and_format(
179
- image_data: bytes, width: int, image_format: ImageFormat
180
+ image_data: bytes, layout_config: LayoutConfig, image_format: ImageFormat
180
181
  ) -> bytes:
181
182
  """Resize an image if it exceeds the given width, or if exceeds
182
183
  MAXIMUM_CONTENT_WIDTH. Ensure the image's format corresponds to the given
@@ -187,17 +188,25 @@ def _ensure_image_size_and_format(
187
188
  pil_image: PILImage = Image.open(io.BytesIO(image_data))
188
189
  actual_width, actual_height = pil_image.size
189
190
 
190
- if width < 0 and actual_width > MAXIMUM_CONTENT_WIDTH:
191
- width = MAXIMUM_CONTENT_WIDTH
191
+ target_width = (
192
+ layout_config.width
193
+ if isinstance(layout_config.width, int)
194
+ else MAXIMUM_CONTENT_WIDTH
195
+ )
192
196
 
193
- if width > 0 and actual_width > width:
197
+ # Resizing the image down if the embedded width is greater than
198
+ # the target width.
199
+ if target_width > 0 and actual_width > target_width:
194
200
  # We need to resize the image.
195
- new_height = int(1.0 * actual_height * width / actual_width)
201
+ new_height = int(1.0 * actual_height * target_width / actual_width)
196
202
  # pillow reexports Image.Resampling.BILINEAR as Image.BILINEAR for backwards
197
203
  # compatibility reasons, so we use the reexport to support older pillow
198
204
  # versions. The types don't seem to reflect this, though, hence the type: ignore
199
205
  # below.
200
- pil_image = pil_image.resize((width, new_height), resample=Image.BILINEAR) # type: ignore[attr-defined]
206
+ pil_image = pil_image.resize(
207
+ (target_width, new_height),
208
+ resample=Image.BILINEAR, # type: ignore[attr-defined]
209
+ )
201
210
  return _pil_to_bytes(pil_image, format=image_format, quality=90)
202
211
 
203
212
  if pil_image.format != image_format:
@@ -227,7 +236,7 @@ def _clip_image(image: npt.NDArray[Any], clamp: bool) -> npt.NDArray[Any]:
227
236
 
228
237
  def image_to_url(
229
238
  image: AtomicImage,
230
- width: int,
239
+ layout_config: LayoutConfig,
231
240
  clamp: bool,
232
241
  channels: Channels,
233
242
  output_format: ImageFormatOrAuto,
@@ -327,7 +336,7 @@ def image_to_url(
327
336
 
328
337
  # Determine the image's format, resize it, and get its mimetype
329
338
  image_format = _validate_image_format_string(image_data, output_format)
330
- image_data = _ensure_image_size_and_format(image_data, width, image_format)
339
+ image_data = _ensure_image_size_and_format(image_data, layout_config, image_format)
331
340
  mimetype = _get_image_format_mimetype(image_format)
332
341
 
333
342
  if runtime.exists():
@@ -346,7 +355,7 @@ def marshall_images(
346
355
  coordinates: str,
347
356
  image: ImageOrImageList,
348
357
  caption: str | npt.NDArray[Any] | list[str] | None,
349
- width: int | WidthBehavior,
358
+ layout_config: LayoutConfig,
350
359
  proto_imgs: ImageListProto,
351
360
  clamp: bool,
352
361
  channels: Channels = "RGB",
@@ -423,7 +432,6 @@ def marshall_images(
423
432
  f"Cannot pair {len(captions)} captions with {len(images)} images."
424
433
  )
425
434
 
426
- proto_imgs.width = int(width)
427
435
  # Each image in an image list needs to be kept track of at its own coordinates.
428
436
  for coord_suffix, (single_image, single_caption) in enumerate(
429
437
  zip(images, captions)
@@ -437,5 +445,5 @@ def marshall_images(
437
445
  image_id = f"{coordinates}-{coord_suffix}"
438
446
 
439
447
  proto_img.url = image_to_url(
440
- single_image, width, clamp, channels, output_format, image_id
448
+ single_image, layout_config, clamp, channels, output_format, image_id
441
449
  )
@@ -74,7 +74,12 @@ def validate_width(width: Width, allow_content: bool = False) -> None:
74
74
  raise StreamlitInvalidWidthError(width, allow_content)
75
75
 
76
76
 
77
- def validate_height(height: Height, allow_content: bool = False) -> None:
77
+ def validate_height(
78
+ height: Height | Literal["auto"],
79
+ allow_content: bool = False,
80
+ allow_stretch: bool = True,
81
+ additional_allowed: list[str] | None = None,
82
+ ) -> None:
78
83
  """Validate the height parameter.
79
84
 
80
85
  Parameters
@@ -83,6 +88,10 @@ def validate_height(height: Height, allow_content: bool = False) -> None:
83
88
  The height value to validate.
84
89
  allow_content : bool
85
90
  Whether to allow "content" as a valid height value.
91
+ allow_stretch : bool
92
+ Whether to allow "stretch" as a valid height value.
93
+ additional_allowed : list[str] or None
94
+ Additional string values to allow beyond the base allowed values.
86
95
 
87
96
  Raises
88
97
  ------
@@ -93,9 +102,13 @@ def validate_height(height: Height, allow_content: bool = False) -> None:
93
102
  raise StreamlitInvalidHeightError(height, allow_content)
94
103
 
95
104
  if isinstance(height, str):
96
- valid_strings = ["stretch"]
105
+ valid_strings = []
106
+ if allow_stretch:
107
+ valid_strings.append("stretch")
97
108
  if allow_content:
98
109
  valid_strings.append("content")
110
+ if additional_allowed:
111
+ valid_strings.extend(additional_allowed)
99
112
 
100
113
  if height not in valid_strings:
101
114
  raise StreamlitInvalidHeightError(height, allow_content)
@@ -28,10 +28,10 @@ from google.protobuf.message import Message
28
28
  from typing_extensions import TypeAlias
29
29
 
30
30
  from streamlit import config
31
+ from streamlit.elements.lib.form_utils import current_form_id
31
32
  from streamlit.errors import StreamlitDuplicateElementId, StreamlitDuplicateElementKey
32
33
  from streamlit.proto.ChatInput_pb2 import ChatInput
33
34
  from streamlit.proto.LabelVisibilityMessage_pb2 import LabelVisibilityMessage
34
- from streamlit.proto.RootContainer_pb2 import RootContainer
35
35
  from streamlit.runtime.scriptrunner_utils.script_run_context import (
36
36
  ScriptRunContext,
37
37
  get_script_run_ctx,
@@ -82,7 +82,7 @@ def get_label_visibility_proto_value(
82
82
 
83
83
 
84
84
  def get_chat_input_accept_file_proto_value(
85
- accept_file_value: bool | Literal["multiple"],
85
+ accept_file_value: Literal["multiple", "directory"] | bool,
86
86
  ) -> ChatInput.AcceptFile.ValueType:
87
87
  """Returns one of ChatInput.AcceptFile enum value based on string value."""
88
88
 
@@ -92,6 +92,8 @@ def get_chat_input_accept_file_proto_value(
92
92
  return ChatInput.AcceptFile.SINGLE
93
93
  if accept_file_value == "multiple":
94
94
  return ChatInput.AcceptFile.MULTIPLE
95
+ if accept_file_value == "directory":
96
+ return ChatInput.AcceptFile.DIRECTORY
95
97
 
96
98
  raise ValueError(f"Unknown accept file value: {accept_file_value}")
97
99
 
@@ -184,9 +186,8 @@ def compute_and_register_element_id(
184
186
  element_type: str,
185
187
  *,
186
188
  user_key: str | None,
187
- form_id: str | None,
188
- dg: DeltaGenerator | None = None,
189
- style: str | None = None,
189
+ dg: DeltaGenerator | None,
190
+ key_as_main_identity: bool = False,
190
191
  **kwargs: SAFE_VALUES | Iterable[SAFE_VALUES],
191
192
  ) -> str:
192
193
  """Compute and register the ID for the given element.
@@ -213,65 +214,43 @@ def compute_and_register_element_id(
213
214
  The user-specified key for the element. `None` if no key is provided
214
215
  or if the element doesn't support a specifying a key.
215
216
 
216
- form_id : str | None
217
- The ID of the form that the element belongs to. `None` or empty string
218
- if the element doesn't belong to a form or doesn't support forms.
219
-
220
217
  dg : DeltaGenerator | None
221
218
  The DeltaGenerator of each element. `None` if the element is not a widget.
222
219
 
223
- style: str | None
224
- The style of the element, to provide more context to the user in the
225
- error message. This should be `None` if the element does not support
226
- the style parameter.
227
-
228
220
  kwargs : SAFE_VALUES | Iterable[SAFE_VALUES]
229
221
  The arguments to use to compute the element ID.
230
222
  The arguments must be stable, deterministic values.
231
223
  Some common parameters like key, disabled,
232
224
  format_func, label_visibility, args, kwargs, on_change, and
233
225
  the active_script_hash are not supposed to be added here
226
+
227
+ key_as_main_identity : bool
228
+ If True, if a key is provided by the user, we don't include
229
+ command kwargs in the element ID computation.
234
230
  """
235
231
  ctx = get_script_run_ctx()
236
232
 
237
- kwargs_to_use = {**kwargs}
238
- if form_id:
239
- kwargs_to_use["form_id"] = form_id
240
- if style:
241
- kwargs_to_use["style"] = style
242
-
243
- # If style is provided, use it for the error message, to provide more
244
- # context to the user.
245
- if style == "borderless":
246
- # The borderless style is used by st.feedback, but users expect to see
247
- # "feedback" in errors
248
- element_type_for_error = "feedback"
249
- elif style:
250
- element_type_for_error = style
251
- else:
252
- element_type_for_error = element_type
233
+ ignore_command_kwargs = key_as_main_identity and user_key
234
+
235
+ kwargs_to_use = {} if ignore_command_kwargs else {**kwargs}
253
236
 
254
237
  if ctx:
255
238
  # Add the active script hash to give elements on different
256
- # pages unique IDs.
239
+ # pages unique IDs. This is added even if
240
+ # key_as_main_identity is specified.
257
241
  kwargs_to_use["active_script_hash"] = ctx.active_script_hash
258
242
 
259
- if dg:
243
+ if dg and not ignore_command_kwargs:
244
+ kwargs_to_use["form_id"] = current_form_id(dg)
260
245
  # If no key is provided and the widget element is inside the sidebar area
261
246
  # add it to the kwargs
262
247
  # allowing the same widget to be both in main area and sidebar.
263
- active_dg_root_container = dg._active_dg._root_container
264
- if active_dg_root_container == RootContainer.SIDEBAR and user_key is None:
265
- kwargs_to_use["active_dg_root_container"] = str(active_dg_root_container)
248
+ kwargs_to_use["active_dg_root_container"] = dg._active_dg._root_container
266
249
 
267
- element_id = _compute_element_id(
268
- element_type,
269
- user_key,
270
- **kwargs_to_use,
271
- )
250
+ element_id = _compute_element_id(element_type, user_key, **kwargs_to_use)
272
251
 
273
252
  if ctx:
274
- _register_element_id(ctx, element_type_for_error, element_id)
253
+ _register_element_id(ctx, element_type, element_id)
275
254
  return element_id
276
255
 
277
256
 
@@ -80,7 +80,7 @@ class MarkdownMixin:
80
80
  - Colored text and background colors for text, using the syntax
81
81
  ``:color[text to be colored]`` and ``:color-background[text to be colored]``,
82
82
  respectively. ``color`` must be replaced with any of the following
83
- supported colors: blue, green, orange, red, violet, gray/grey,
83
+ supported colors: red, orange, yellow, green, blue, violet, gray/grey,
84
84
  rainbow, or primary. For example, you can use
85
85
  ``:orange[your text here]`` or ``:blue-background[your text here]``.
86
86
  If you use "primary" for color, Streamlit will use the default
@@ -89,7 +89,7 @@ class MarkdownMixin:
89
89
 
90
90
  - Colored badges, using the syntax ``:color-badge[text in the badge]``.
91
91
  ``color`` must be replaced with any of the following supported
92
- colors: blue, green, orange, red, violet, gray/grey, or primary.
92
+ colors: red, orange, yellow, green, blue, violet, gray/grey, or primary.
93
93
  For example, you can use ``:orange-badge[your text here]`` or
94
94
  ``:blue-badge[your text here]``.
95
95
 
@@ -359,10 +359,11 @@ class MarkdownMixin:
359
359
  *, # keyword-only arguments:
360
360
  icon: str | None = None,
361
361
  color: Literal[
362
+ "red",
363
+ "orange",
364
+ "yellow",
362
365
  "blue",
363
366
  "green",
364
- "orange",
365
- "red",
366
367
  "violet",
367
368
  "gray",
368
369
  "grey",
@@ -418,8 +419,8 @@ class MarkdownMixin:
418
419
  color : str
419
420
  The color to use for the badge. This defaults to ``"blue"``.
420
421
 
421
- This can be one of the following supported colors: blue, green,
422
- orange, red, violet, gray/grey, or primary. If you use
422
+ This can be one of the following supported colors: red, orange,
423
+ yellow, blue, green, violet, gray/grey, or primary. If you use
423
424
  ``"primary"``, Streamlit will use the default primary accent color
424
425
  unless you set the ``theme.primaryColor`` configuration option.
425
426
 
@@ -23,7 +23,6 @@ from typing import TYPE_CHECKING, Final, Union, cast
23
23
  from typing_extensions import TypeAlias
24
24
 
25
25
  from streamlit import runtime, type_util, url_util
26
- from streamlit.elements.lib.form_utils import current_form_id
27
26
  from streamlit.elements.lib.layout_utils import WidthWithoutContent, validate_width
28
27
  from streamlit.elements.lib.subtitle_utils import process_subtitle_data
29
28
  from streamlit.elements.lib.utils import compute_and_register_element_id
@@ -210,6 +209,7 @@ class MediaMixin:
210
209
  )
211
210
  coordinates = self.dg._get_delta_path_str()
212
211
  marshall_audio(
212
+ self.dg,
213
213
  coordinates,
214
214
  audio_proto,
215
215
  data,
@@ -219,7 +219,6 @@ class MediaMixin:
219
219
  end_time,
220
220
  loop,
221
221
  autoplay,
222
- form_id=current_form_id(self.dg),
223
222
  width=width,
224
223
  )
225
224
  return self.dg._enqueue("audio", audio_proto)
@@ -389,6 +388,7 @@ class MediaMixin:
389
388
  video_proto = VideoProto()
390
389
  coordinates = self.dg._get_delta_path_str()
391
390
  marshall_video(
391
+ self.dg,
392
392
  coordinates,
393
393
  video_proto,
394
394
  data,
@@ -399,7 +399,6 @@ class MediaMixin:
399
399
  loop,
400
400
  autoplay,
401
401
  muted,
402
- form_id=current_form_id(self.dg),
403
402
  width=width,
404
403
  )
405
404
  return self.dg._enqueue("video", video_proto)
@@ -500,6 +499,7 @@ def _marshall_av_media(
500
499
 
501
500
 
502
501
  def marshall_video(
502
+ dg: DeltaGenerator,
503
503
  coordinates: str,
504
504
  proto: VideoProto,
505
505
  data: MediaData,
@@ -510,7 +510,6 @@ def marshall_video(
510
510
  loop: bool = False,
511
511
  autoplay: bool = False,
512
512
  muted: bool = False,
513
- form_id: str | None = None,
514
513
  width: WidthWithoutContent = "stretch",
515
514
  ) -> None:
516
515
  """Marshalls a video proto, using url processors as needed.
@@ -555,9 +554,6 @@ def marshall_video(
555
554
  muted: bool
556
555
  Whether the video should play with the audio silenced. This can be used to
557
556
  enable autoplay without user interaction. Defaults to False.
558
- form_id: str | None
559
- The ID of the form that this element is placed in. Provide None if
560
- the element is not placed in a form.
561
557
  width: int or "stretch"
562
558
  The width of the video player. This can be one of the following:
563
559
  - An int: The width in pixels, e.g. 200 for a width of 200 pixels.
@@ -643,7 +639,7 @@ def marshall_video(
643
639
  "video",
644
640
  # video does not yet allow setting a user-defined key
645
641
  user_key=None,
646
- form_id=form_id,
642
+ dg=dg,
647
643
  url=proto.url,
648
644
  mimetype=mimetype,
649
645
  start_time=start_time,
@@ -763,6 +759,7 @@ def _maybe_convert_to_wav_bytes(data: MediaData, sample_rate: int | None) -> Med
763
759
 
764
760
 
765
761
  def marshall_audio(
762
+ dg: DeltaGenerator,
766
763
  coordinates: str,
767
764
  proto: AudioProto,
768
765
  data: MediaData,
@@ -772,7 +769,6 @@ def marshall_audio(
772
769
  end_time: int | None = None,
773
770
  loop: bool = False,
774
771
  autoplay: bool = False,
775
- form_id: str | None = None,
776
772
  width: WidthWithoutContent = "stretch",
777
773
  ) -> None:
778
774
  """Marshalls an audio proto, using data and url processors as needed.
@@ -800,9 +796,6 @@ def marshall_audio(
800
796
  autoplay : bool
801
797
  Whether the audio should start playing automatically.
802
798
  Browsers will not autoplay audio files if the user has not interacted with the page yet.
803
- form_id: str | None
804
- The ID of the form that this element is placed in. Provide None if
805
- the element is not placed in a form.
806
799
  width: int or "stretch"
807
800
  The width of the audio player. This can be one of the following:
808
801
  - An int: The width in pixels, e.g. 200 for a width of 200 pixels.
@@ -838,7 +831,7 @@ def marshall_audio(
838
831
  proto.id = compute_and_register_element_id(
839
832
  "audio",
840
833
  user_key=None,
841
- form_id=form_id,
834
+ dg=dg,
842
835
  url=proto.url,
843
836
  mimetype=mimetype,
844
837
  start_time=start_time,