streamlit-nightly 1.45.2.dev20250527__py3-none-any.whl → 1.45.2.dev20250530__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 (180) hide show
  1. streamlit/auth_util.py +3 -3
  2. streamlit/commands/echo.py +1 -1
  3. streamlit/config.py +32 -12
  4. streamlit/config_option.py +3 -5
  5. streamlit/config_util.py +4 -5
  6. streamlit/connections/snowflake_connection.py +4 -3
  7. streamlit/delta_generator.py +10 -14
  8. streamlit/elements/arrow.py +1 -0
  9. streamlit/elements/deck_gl_json_chart.py +1 -0
  10. streamlit/elements/doc_string.py +7 -15
  11. streamlit/elements/exception.py +4 -12
  12. streamlit/elements/form.py +14 -0
  13. streamlit/elements/graphviz_chart.py +1 -1
  14. streamlit/elements/heading.py +3 -4
  15. streamlit/elements/json.py +7 -6
  16. streamlit/elements/layouts.py +21 -3
  17. streamlit/elements/lib/image_utils.py +2 -3
  18. streamlit/elements/lib/layout_utils.py +24 -0
  19. streamlit/elements/lib/mutable_status_container.py +9 -0
  20. streamlit/elements/lib/streamlit_plotly_theme.py +54 -53
  21. streamlit/elements/lib/utils.py +15 -0
  22. streamlit/elements/markdown.py +34 -4
  23. streamlit/elements/media.py +1 -1
  24. streamlit/elements/plotly_chart.py +1 -0
  25. streamlit/elements/progress.py +6 -15
  26. streamlit/elements/spinner.py +5 -4
  27. streamlit/elements/vega_charts.py +1 -0
  28. streamlit/elements/widgets/audio_input.py +4 -10
  29. streamlit/elements/widgets/button.py +3 -1
  30. streamlit/elements/widgets/button_group.py +1 -0
  31. streamlit/elements/widgets/camera_input.py +6 -9
  32. streamlit/elements/widgets/chat.py +11 -13
  33. streamlit/elements/widgets/checkbox.py +1 -0
  34. streamlit/elements/widgets/color_picker.py +9 -14
  35. streamlit/elements/widgets/data_editor.py +9 -5
  36. streamlit/elements/widgets/file_uploader.py +10 -9
  37. streamlit/elements/widgets/multiselect.py +1 -0
  38. streamlit/elements/widgets/number_input.py +12 -12
  39. streamlit/elements/widgets/radio.py +2 -1
  40. streamlit/elements/widgets/select_slider.py +4 -10
  41. streamlit/elements/widgets/selectbox.py +11 -13
  42. streamlit/elements/widgets/slider.py +28 -41
  43. streamlit/elements/widgets/text_widgets.py +16 -24
  44. streamlit/elements/widgets/time_widgets.py +15 -22
  45. streamlit/hello/animation_demo.py +9 -9
  46. streamlit/hello/dataframe_demo.py +2 -2
  47. streamlit/hello/hello.py +1 -0
  48. streamlit/hello/mapping_demo.py +5 -6
  49. streamlit/hello/streamlit_app.py +27 -25
  50. streamlit/logger.py +1 -1
  51. streamlit/proto/AudioInput_pb2.py +3 -4
  52. streamlit/proto/AudioInput_pb2.pyi +2 -7
  53. streamlit/proto/Block_pb2.py +27 -27
  54. streamlit/proto/Block_pb2.pyi +3 -17
  55. streamlit/proto/CameraInput_pb2.py +3 -4
  56. streamlit/proto/CameraInput_pb2.pyi +2 -8
  57. streamlit/proto/ChatInput_pb2.py +7 -8
  58. streamlit/proto/ChatInput_pb2.pyi +1 -10
  59. streamlit/proto/Code_pb2.py +3 -4
  60. streamlit/proto/DateInput_pb2.py +3 -4
  61. streamlit/proto/DateInput_pb2.pyi +2 -8
  62. streamlit/proto/DocString_pb2.py +5 -6
  63. streamlit/proto/DocString_pb2.pyi +1 -9
  64. streamlit/proto/FileUploader_pb2.py +3 -4
  65. streamlit/proto/FileUploader_pb2.pyi +2 -8
  66. streamlit/proto/Json_pb2.py +3 -4
  67. streamlit/proto/Json_pb2.pyi +2 -9
  68. streamlit/proto/NewSession_pb2.py +16 -16
  69. streamlit/proto/NewSession_pb2.pyi +7 -2
  70. streamlit/proto/NumberInput_pb2.py +5 -6
  71. streamlit/proto/NumberInput_pb2.pyi +2 -9
  72. streamlit/proto/Progress_pb2.py +3 -4
  73. streamlit/proto/Progress_pb2.pyi +1 -7
  74. streamlit/proto/Selectbox_pb2.py +3 -4
  75. streamlit/proto/Selectbox_pb2.pyi +2 -9
  76. streamlit/proto/Slider_pb2.py +7 -8
  77. streamlit/proto/Slider_pb2.pyi +2 -8
  78. streamlit/proto/TextArea_pb2.py +3 -4
  79. streamlit/proto/TextArea_pb2.pyi +2 -9
  80. streamlit/proto/TextInput_pb2.py +5 -6
  81. streamlit/proto/TextInput_pb2.pyi +2 -9
  82. streamlit/proto/TimeInput_pb2.py +3 -4
  83. streamlit/proto/TimeInput_pb2.pyi +2 -9
  84. streamlit/runtime/app_session.py +11 -8
  85. streamlit/runtime/caching/hashing.py +8 -9
  86. streamlit/runtime/caching/storage/local_disk_cache_storage.py +3 -3
  87. streamlit/runtime/connection_factory.py +12 -12
  88. streamlit/runtime/credentials.py +13 -26
  89. streamlit/runtime/runtime_util.py +2 -2
  90. streamlit/runtime/scriptrunner/script_runner.py +8 -7
  91. streamlit/static/index.html +1 -1
  92. streamlit/static/manifest.json +1240 -0
  93. streamlit/static/static/js/{ErrorOutline.esm.qteVcUUN.js → ErrorOutline.esm.D5NgCh5m.js} +1 -1
  94. streamlit/static/static/js/{FileDownload.esm.ncu7N-Hr.js → FileDownload.esm.NuObx1Tl.js} +1 -1
  95. streamlit/static/static/js/{FileHelper.zsMZ7RXt.js → FileHelper.BH7o4_P9.js} +5 -5
  96. streamlit/static/static/js/{FormClearHelper.W8yVYXZp.js → FormClearHelper.BAxB8JFY.js} +1 -1
  97. streamlit/static/static/js/{Hooks.DBj6srQ1.js → Hooks.Bjt8oBOT.js} +1 -1
  98. streamlit/static/static/js/{InputInstructions.BobLsJJb.js → InputInstructions.BZZLp6t9.js} +1 -1
  99. streamlit/static/static/js/{ProgressBar.CtvJrIzN.js → ProgressBar.BwRgGfI0.js} +2 -2
  100. streamlit/static/static/js/{RenderInPortalIfExists.DnT_UdzV.js → RenderInPortalIfExists.C_c286r8.js} +1 -1
  101. streamlit/static/static/js/{Toolbar.BVF7NtOB.js → Toolbar.5tXjF_eX.js} +1 -1
  102. streamlit/static/static/js/{base-input.B4sdS3vw.js → base-input.wfBDFTlB.js} +1 -1
  103. streamlit/static/static/js/{checkbox.DKDitzF8.js → checkbox.D1GhNngU.js} +1 -1
  104. streamlit/static/static/js/{createSuper.mhx956J9.js → createSuper.CudEEVs2.js} +1 -1
  105. streamlit/static/static/js/{data-grid-overlay-editor.CmXS0PAX.js → data-grid-overlay-editor.DUTI_Rbg.js} +1 -1
  106. streamlit/static/static/js/{downloader.Cnd9SuxG.js → downloader.BwLpAoXN.js} +1 -1
  107. streamlit/static/static/js/{es6.DM-pf09u.js → es6.B_HLnUb9.js} +2 -2
  108. streamlit/static/static/js/{iframeResizer.contentWindow.Gc5GAjZM.js → iframeResizer.contentWindow.BNcjOcan.js} +1 -1
  109. streamlit/static/static/js/{index.D4XRYl23.js → index.3WJoJFGb.js} +1 -1
  110. streamlit/static/static/js/{index.C_2m4F7k.js → index.B0h616Th.js} +1 -1
  111. streamlit/static/static/js/{index.p2Wl4zMi.js → index.B0paBg5x.js} +1 -1
  112. streamlit/static/static/js/index.B3vWaIrN.js +1 -0
  113. streamlit/static/static/js/{index.B45ExNhw.js → index.B4PbMsBe.js} +1 -1
  114. streamlit/static/static/js/{index.BWTBe3a1.js → index.BGKVW2u9.js} +1 -1
  115. streamlit/static/static/js/index.BJQPxOFd.js +12 -0
  116. streamlit/static/static/js/{index.DdyZtGcg.js → index.BOHEcsVb.js} +1 -1
  117. streamlit/static/static/js/{index.BR-S54Iv.js → index.BPGAPI9w.js} +1 -1
  118. streamlit/static/static/js/{index.gBOr8z2K.js → index.Bj6uLiaA.js} +1 -1
  119. streamlit/static/static/js/{index.I3iNnzJx.js → index.BkvVxUIW.js} +1 -1
  120. streamlit/static/static/js/{index._BaeK1t7.js → index.Bs0m0eUy.js} +1 -1
  121. streamlit/static/static/js/{index.DwUISpCs.js → index.BtpsTdHN.js} +177 -174
  122. streamlit/static/static/js/index.C1GNiWbH.js +1 -0
  123. streamlit/static/static/js/{index.B6xTo8b8.js → index.CL0UH4WF.js} +1 -1
  124. streamlit/static/static/js/{index.BJQNG4O1.js → index.CXP5ffxh.js} +1 -1
  125. streamlit/static/static/js/{index.DAvhwYMG.js → index.Ca-9xoC2.js} +1 -1
  126. streamlit/static/static/js/{index.COBionvf.js → index.Cdd7Ri21.js} +1 -1
  127. streamlit/static/static/js/index.Cf8KcH2X.js +1 -0
  128. streamlit/static/static/js/{index.BkLkRTpZ.js → index.CfzaRR6P.js} +1 -1
  129. streamlit/static/static/js/{index.CkKptP1T.js → index.CjRwuAdg.js} +1 -1
  130. streamlit/static/static/js/{index.CjBaoWYr.js → index.CkOUlPYT.js} +1 -1
  131. streamlit/static/static/js/{index.DQGSbu2C.js → index.CxtkoiKl.js} +1 -1
  132. streamlit/static/static/js/index.D3wYqvI6.js +1 -0
  133. streamlit/static/static/js/index.D8i27llu.js +3 -0
  134. streamlit/static/static/js/{index.BfusYuD8.js → index.DA7wmIe4.js} +1 -1
  135. streamlit/static/static/js/index.DIG9Mo9J.js +1 -0
  136. streamlit/static/static/js/index.DNR4wKJg.js +1 -0
  137. streamlit/static/static/js/{index.B29JQLHa.js → index.DNS8a-dx.js} +20 -20
  138. streamlit/static/static/js/{index.BNNR5Jmd.js → index.NveskZ7j.js} +1 -1
  139. streamlit/static/static/js/{index.CWgnk1N4.js → index.PR2mcvVR.js} +1 -1
  140. streamlit/static/static/js/{index.CJ-XXd1r.js → index.df4uuSoD.js} +1 -1
  141. streamlit/static/static/js/{index.WWYmGCrM.js → index.flyQEkeT.js} +1 -1
  142. streamlit/static/static/js/{index.vOqxh1m2.js → index.iF9jUtwl.js} +1 -1
  143. streamlit/static/static/js/{index.C5KKmyWy.js → index.jyqBAhvH.js} +1 -1
  144. streamlit/static/static/js/{index.AWkO-7e-.js → index.sYLAHlH0.js} +1 -1
  145. streamlit/static/static/js/{index.CZ5fZcT5.js → index.zq3LdRhj.js} +1 -1
  146. streamlit/static/static/js/{input.BvD9DHLa.js → input.CtZjQ6Pv.js} +1 -1
  147. streamlit/static/static/js/{memory.DCVB1HOm.js → memory.Ddl3R0up.js} +1 -1
  148. streamlit/static/static/js/{mergeWith.BqTORFAq.js → mergeWith.D-TqDY0-.js} +1 -1
  149. streamlit/static/static/js/{number-overlay-editor.VB_OvuPv.js → number-overlay-editor.Dndf05Hx.js} +1 -1
  150. streamlit/static/static/js/{possibleConstructorReturn.DhYxBDlj.js → possibleConstructorReturn.DNEY6J9G.js} +1 -1
  151. streamlit/static/static/js/{sandbox.CoN7LRFk.js → sandbox.B_XDPkfx.js} +1 -1
  152. streamlit/static/static/js/{textarea.DkHpIjdT.js → textarea.BZ9lTMhV.js} +1 -1
  153. streamlit/static/static/js/{timepicker.C8UIzYhf.js → timepicker.D9UUwpRT.js} +1 -1
  154. streamlit/static/static/js/{toConsumableArray.DXfr1fvT.js → toConsumableArray.DNJjbOUS.js} +1 -1
  155. streamlit/static/static/js/{uniqueId.CgrMSBTb.js → uniqueId.psBJ_tSg.js} +1 -1
  156. streamlit/static/static/js/{useBasicWidgetState.C-e-WEFS.js → useBasicWidgetState.CTpx4w-3.js} +1 -1
  157. streamlit/static/static/js/{useOnInputChange.CtRJhZD6.js → useOnInputChange.WKTDSC4O.js} +1 -1
  158. streamlit/static/static/js/{withFullScreenWrapper.od0SAvAK.js → withFullScreenWrapper.oyWCn2-3.js} +1 -1
  159. streamlit/watcher/local_sources_watcher.py +1 -1
  160. streamlit/watcher/path_watcher.py +2 -3
  161. streamlit/web/bootstrap.py +1 -1
  162. streamlit/web/cli.py +5 -5
  163. streamlit/web/server/authlib_tornado_integration.py +3 -3
  164. streamlit/web/server/oauth_authlib_routes.py +4 -2
  165. streamlit/web/server/oidc_mixin.py +6 -5
  166. streamlit/web/server/server.py +1 -1
  167. {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250530.dist-info}/METADATA +2 -2
  168. {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250530.dist-info}/RECORD +172 -171
  169. streamlit/static/static/js/index.B0E6Rv1F.js +0 -1
  170. streamlit/static/static/js/index.BONHiJUZ.js +0 -1
  171. streamlit/static/static/js/index.BV38yp5k.js +0 -1
  172. streamlit/static/static/js/index.CgOynO1t.js +0 -1
  173. streamlit/static/static/js/index.DIyx-z1Q.js +0 -1
  174. streamlit/static/static/js/index.DOYomqqU.js +0 -1
  175. streamlit/static/static/js/index.DOl-SOKu.js +0 -3
  176. streamlit/static/static/js/index.DTU7qmDP.js +0 -12
  177. {streamlit_nightly-1.45.2.dev20250527.data → streamlit_nightly-1.45.2.dev20250530.data}/scripts/streamlit.cmd +0 -0
  178. {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250530.dist-info}/WHEEL +0 -0
  179. {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250530.dist-info}/entry_points.txt +0 -0
  180. {streamlit_nightly-1.45.2.dev20250527.dist-info → streamlit_nightly-1.45.2.dev20250530.dist-info}/top_level.txt +0 -0
@@ -270,8 +270,11 @@ def _apply_cell_edits(
270
270
  # The edited cell is part of the index
271
271
  # TODO(lukasmasuch): To support multi-index in the future:
272
272
  # use a tuple of values here instead of a single value
273
- df.index.to_numpy()[row_pos] = _parse_value(
274
- value, dataframe_schema[INDEX_IDENTIFIER]
273
+ old_idx_value = df.index[row_pos]
274
+ new_idx_value = _parse_value(value, dataframe_schema[INDEX_IDENTIFIER])
275
+ df.rename(
276
+ index={old_idx_value: new_idx_value},
277
+ inplace=True, # noqa: PD002
275
278
  )
276
279
  else:
277
280
  col_pos = df.columns.get_loc(col_name)
@@ -370,8 +373,8 @@ def _apply_row_additions(
370
373
  # Row cannot be added -> skip it and log a warning.
371
374
  _LOGGER.warning(
372
375
  "Cannot automatically add row for the index "
373
- f"of type {type(df.index).__name__} without an explicit index value. "
374
- "Row addition skipped."
376
+ "of type %s without an explicit index value. Row addition skipped.",
377
+ type(df.index).__name__,
375
378
  )
376
379
 
377
380
 
@@ -697,7 +700,7 @@ class DataEditorMixin:
697
700
  - A string to set the display label of the column.
698
701
 
699
702
  - One of the column types defined under ``st.column_config``, e.g.
700
- ``st.column_config.NumberColumn("Dollar values”, format=”$ %d")`` to show
703
+ ``st.column_config.NumberColumn("Dollar values", format="$ %d")`` to show
701
704
  a column as dollar amounts. See more info on the available column types
702
705
  and config options `here <https://docs.streamlit.io/develop/api-reference/data/st.column_config>`_.
703
706
 
@@ -933,6 +936,7 @@ class DataEditorMixin:
933
936
  "data_editor",
934
937
  user_key=key,
935
938
  form_id=current_form_id(self.dg),
939
+ dg=self.dg,
936
940
  data=arrow_bytes,
937
941
  width=width,
938
942
  height=height,
@@ -26,7 +26,11 @@ from streamlit.elements.lib.file_uploader_utils import (
26
26
  normalize_upload_file_type,
27
27
  )
28
28
  from streamlit.elements.lib.form_utils import current_form_id
29
- from streamlit.elements.lib.layout_utils import WidthWithoutContent, validate_width
29
+ from streamlit.elements.lib.layout_utils import (
30
+ LayoutConfig,
31
+ WidthWithoutContent,
32
+ validate_width,
33
+ )
30
34
  from streamlit.elements.lib.policies import (
31
35
  check_widget_policies,
32
36
  maybe_raise_label_warnings,
@@ -41,7 +45,6 @@ from streamlit.elements.lib.utils import (
41
45
  from streamlit.proto.Common_pb2 import FileUploaderState as FileUploaderStateProto
42
46
  from streamlit.proto.Common_pb2 import UploadedFileInfo as UploadedFileInfoProto
43
47
  from streamlit.proto.FileUploader_pb2 import FileUploader as FileUploaderProto
44
- from streamlit.proto.WidthConfig_pb2 import WidthConfig
45
48
  from streamlit.runtime.metrics_util import gather_metrics
46
49
  from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
47
50
  from streamlit.runtime.state import (
@@ -441,6 +444,7 @@ class FileUploaderMixin:
441
444
  "file_uploader",
442
445
  user_key=key,
443
446
  form_id=current_form_id(self.dg),
447
+ dg=self.dg,
444
448
  label=label,
445
449
  type=type,
446
450
  accept_multiple_files=accept_multiple_files,
@@ -486,14 +490,11 @@ class FileUploaderMixin:
486
490
  )
487
491
 
488
492
  validate_width(width)
489
- width_config = WidthConfig()
490
- if isinstance(width, int):
491
- width_config.pixel_width = width
492
- else:
493
- width_config.use_stretch = True
494
- file_uploader_proto.width_config.CopyFrom(width_config)
493
+ layout_config = LayoutConfig(width=width)
495
494
 
496
- self.dg._enqueue("file_uploader", file_uploader_proto)
495
+ self.dg._enqueue(
496
+ "file_uploader", file_uploader_proto, layout_config=layout_config
497
+ )
497
498
 
498
499
  if isinstance(widget_state.value, DeletedFile):
499
500
  return None
@@ -449,6 +449,7 @@ class MultiSelectMixin:
449
449
  widget_name,
450
450
  user_key=key,
451
451
  form_id=form_id,
452
+ dg=self.dg,
452
453
  label=label,
453
454
  options=formatted_options,
454
455
  default=default_values,
@@ -23,7 +23,11 @@ from typing_extensions import TypeAlias
23
23
 
24
24
  from streamlit.elements.lib.form_utils import current_form_id
25
25
  from streamlit.elements.lib.js_number import JSNumber, JSNumberBoundsException
26
- from streamlit.elements.lib.layout_utils import WidthWithoutContent, validate_width
26
+ from streamlit.elements.lib.layout_utils import (
27
+ LayoutConfig,
28
+ WidthWithoutContent,
29
+ validate_width,
30
+ )
27
31
  from streamlit.elements.lib.policies import (
28
32
  check_widget_policies,
29
33
  maybe_raise_label_warnings,
@@ -43,7 +47,6 @@ from streamlit.errors import (
43
47
  StreamlitValueBelowMinError,
44
48
  )
45
49
  from streamlit.proto.NumberInput_pb2 import NumberInput as NumberInputProto
46
- from streamlit.proto.WidthConfig_pb2 import WidthConfig
47
50
  from streamlit.runtime.metrics_util import gather_metrics
48
51
  from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
49
52
  from streamlit.runtime.state import (
@@ -437,12 +440,12 @@ class NumberInputMixin:
437
440
  default_value=value if value != "min" else None,
438
441
  )
439
442
  maybe_raise_label_warnings(label, label_visibility)
440
- validate_width(width)
441
443
 
442
444
  element_id = compute_and_register_element_id(
443
445
  "number_input",
444
446
  user_key=key,
445
447
  form_id=current_form_id(self.dg),
448
+ dg=self.dg,
446
449
  label=label,
447
450
  min_value=min_value,
448
451
  max_value=max_value,
@@ -605,14 +608,6 @@ class NumberInputMixin:
605
608
  if icon is not None:
606
609
  number_input_proto.icon = validate_icon_or_emoji(icon)
607
610
 
608
- # Set up width configuration
609
- width_config = WidthConfig()
610
- if isinstance(width, int):
611
- width_config.pixel_width = width
612
- else:
613
- width_config.use_stretch = True
614
- number_input_proto.width_config.CopyFrom(width_config)
615
-
616
611
  serde = NumberInputSerde(value, data_type)
617
612
  widget_state = register_widget(
618
613
  number_input_proto.id,
@@ -647,7 +642,12 @@ class NumberInputMixin:
647
642
  number_input_proto.value = widget_state.value
648
643
  number_input_proto.set_value = True
649
644
 
650
- self.dg._enqueue("number_input", number_input_proto)
645
+ validate_width(width)
646
+ layout_config = LayoutConfig(width=width)
647
+
648
+ self.dg._enqueue(
649
+ "number_input", number_input_proto, layout_config=layout_config
650
+ )
651
651
  return widget_state.value
652
652
 
653
653
  @property
@@ -341,6 +341,7 @@ class RadioMixin:
341
341
  "radio",
342
342
  user_key=key,
343
343
  form_id=current_form_id(self.dg),
344
+ dg=self.dg,
344
345
  label=label,
345
346
  options=[str(format_func(option)) for option in opt],
346
347
  index=index,
@@ -351,7 +352,7 @@ class RadioMixin:
351
352
 
352
353
  if not isinstance(index, int) and index is not None:
353
354
  raise StreamlitAPIException(
354
- "Radio Value has invalid type: %s" % type(index).__name__
355
+ f"Radio Value has invalid type: {type(index).__name__}"
355
356
  )
356
357
 
357
358
  if index is not None and len(opt) > 0 and not 0 <= index < len(opt):
@@ -29,7 +29,7 @@ from typing_extensions import TypeGuard
29
29
 
30
30
  from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
31
31
  from streamlit.elements.lib.form_utils import current_form_id
32
- from streamlit.elements.lib.layout_utils import validate_width
32
+ from streamlit.elements.lib.layout_utils import LayoutConfig, validate_width
33
33
  from streamlit.elements.lib.options_selector_utils import (
34
34
  index_,
35
35
  maybe_coerce_enum,
@@ -49,7 +49,6 @@ from streamlit.elements.lib.utils import (
49
49
  )
50
50
  from streamlit.errors import StreamlitAPIException
51
51
  from streamlit.proto.Slider_pb2 import Slider as SliderProto
52
- from streamlit.proto.WidthConfig_pb2 import WidthConfig
53
52
  from streamlit.runtime.metrics_util import gather_metrics
54
53
  from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
55
54
  from streamlit.runtime.state import (
@@ -370,6 +369,7 @@ class SelectSliderMixin:
370
369
  "select_slider",
371
370
  user_key=key,
372
371
  form_id=current_form_id(self.dg),
372
+ dg=self.dg,
373
373
  label=label,
374
374
  options=[str(format_func(option)) for option in opt],
375
375
  value=slider_value,
@@ -396,14 +396,8 @@ class SelectSliderMixin:
396
396
  if help is not None:
397
397
  slider_proto.help = dedent(help)
398
398
 
399
- # Set width config
400
399
  validate_width(width)
401
- width_config = WidthConfig()
402
- if isinstance(width, int):
403
- width_config.pixel_width = width
404
- else:
405
- width_config.use_stretch = True
406
- slider_proto.width_config.CopyFrom(width_config)
400
+ layout_config = LayoutConfig(width=width)
407
401
 
408
402
  serde = SelectSliderSerde(opt, slider_value, _is_range_value(value))
409
403
 
@@ -431,7 +425,7 @@ class SelectSliderMixin:
431
425
  if ctx:
432
426
  save_for_app_testing(ctx, element_id, format_func)
433
427
 
434
- self.dg._enqueue("slider", slider_proto)
428
+ self.dg._enqueue("slider", slider_proto, layout_config=layout_config)
435
429
  return widget_state.value
436
430
 
437
431
  @property
@@ -20,7 +20,11 @@ from typing_extensions import Never
20
20
 
21
21
  from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
22
22
  from streamlit.elements.lib.form_utils import current_form_id
23
- from streamlit.elements.lib.layout_utils import WidthWithoutContent, validate_width
23
+ from streamlit.elements.lib.layout_utils import (
24
+ LayoutConfig,
25
+ WidthWithoutContent,
26
+ validate_width,
27
+ )
24
28
  from streamlit.elements.lib.options_selector_utils import (
25
29
  create_mappings,
26
30
  index_,
@@ -40,7 +44,6 @@ from streamlit.elements.lib.utils import (
40
44
  )
41
45
  from streamlit.errors import StreamlitAPIException
42
46
  from streamlit.proto.Selectbox_pb2 import Selectbox as SelectboxProto
43
- from streamlit.proto.WidthConfig_pb2 import WidthConfig
44
47
  from streamlit.runtime.metrics_util import gather_metrics
45
48
  from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
46
49
  from streamlit.runtime.state import (
@@ -488,14 +491,13 @@ class SelectboxMixin:
488
491
  default_value=None if index == 0 else index,
489
492
  )
490
493
  maybe_raise_label_warnings(label, label_visibility)
491
- validate_width(width)
492
494
 
493
495
  opt = convert_anything_to_list(options)
494
496
  check_python_comparable(opt)
495
497
 
496
498
  if not isinstance(index, int) and index is not None:
497
499
  raise StreamlitAPIException(
498
- "Selectbox Value has invalid type: %s" % type(index).__name__
500
+ f"Selectbox Value has invalid type: {type(index).__name__}"
499
501
  )
500
502
 
501
503
  if index is not None and len(opt) > 0 and not 0 <= index < len(opt):
@@ -519,6 +521,7 @@ class SelectboxMixin:
519
521
  "selectbox",
520
522
  user_key=key,
521
523
  form_id=current_form_id(self.dg),
524
+ dg=self.dg,
522
525
  label=label,
523
526
  options=formatted_options,
524
527
  index=index,
@@ -549,14 +552,6 @@ class SelectboxMixin:
549
552
  if help is not None:
550
553
  selectbox_proto.help = dedent(help)
551
554
 
552
- # Set up width configuration
553
- width_config = WidthConfig()
554
- if isinstance(width, int):
555
- width_config.pixel_width = width
556
- else:
557
- width_config.use_stretch = True
558
- selectbox_proto.width_config.CopyFrom(width_config)
559
-
560
555
  serde = SelectboxSerde(
561
556
  opt,
562
557
  formatted_options=formatted_options,
@@ -581,9 +576,12 @@ class SelectboxMixin:
581
576
  selectbox_proto.raw_value = serialized_value
582
577
  selectbox_proto.set_value = True
583
578
 
579
+ validate_width(width)
580
+ layout_config = LayoutConfig(width=width)
581
+
584
582
  if ctx:
585
583
  save_for_app_testing(ctx, element_id, format_func)
586
- self.dg._enqueue("selectbox", selectbox_proto)
584
+ self.dg._enqueue("selectbox", selectbox_proto, layout_config=layout_config)
587
585
  return widget_state.value
588
586
 
589
587
  @property
@@ -34,7 +34,7 @@ from typing_extensions import TypeAlias
34
34
 
35
35
  from streamlit.elements.lib.form_utils import current_form_id
36
36
  from streamlit.elements.lib.js_number import JSNumber, JSNumberBoundsException
37
- from streamlit.elements.lib.layout_utils import validate_width
37
+ from streamlit.elements.lib.layout_utils import LayoutConfig, validate_width
38
38
  from streamlit.elements.lib.policies import (
39
39
  check_widget_policies,
40
40
  maybe_raise_label_warnings,
@@ -52,7 +52,6 @@ from streamlit.errors import (
52
52
  StreamlitValueBelowMinError,
53
53
  )
54
54
  from streamlit.proto.Slider_pb2 import Slider as SliderProto
55
- from streamlit.proto.WidthConfig_pb2 import WidthConfig
56
55
  from streamlit.runtime.metrics_util import gather_metrics
57
56
  from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
58
57
  from streamlit.runtime.state import (
@@ -118,6 +117,15 @@ DAYS_TO_MICROS: Final = 24 * 60 * 60 * SECONDS_TO_MICROS
118
117
 
119
118
  UTC_EPOCH: Final = datetime(1970, 1, 1, tzinfo=timezone.utc)
120
119
 
120
+ SUPPORTED_TYPES: Final = {
121
+ Integral: SliderProto.INT,
122
+ Real: SliderProto.FLOAT,
123
+ datetime: SliderProto.DATETIME,
124
+ date: SliderProto.DATE,
125
+ time: SliderProto.TIME,
126
+ }
127
+ TIMELIKE_TYPES: Final = (SliderProto.DATETIME, SliderProto.TIME, SliderProto.DATE)
128
+
121
129
 
122
130
  def _time_to_datetime(time_: time) -> datetime:
123
131
  # Note, here we pick an arbitrary date well after Unix epoch.
@@ -665,6 +673,7 @@ class SliderMixin:
665
673
  "slider",
666
674
  user_key=key,
667
675
  form_id=current_form_id(self.dg),
676
+ dg=self.dg,
668
677
  label=label,
669
678
  min_value=min_value,
670
679
  max_value=max_value,
@@ -675,15 +684,6 @@ class SliderMixin:
675
684
  width=width,
676
685
  )
677
686
 
678
- SUPPORTED_TYPES = {
679
- Integral: SliderProto.INT,
680
- Real: SliderProto.FLOAT,
681
- datetime: SliderProto.DATETIME,
682
- date: SliderProto.DATE,
683
- time: SliderProto.TIME,
684
- }
685
- TIMELIKE_TYPES = (SliderProto.DATETIME, SliderProto.TIME, SliderProto.DATE)
686
-
687
687
  if value is None:
688
688
  # We need to know if this is a single or range slider, but don't have
689
689
  # a default value, so we check if session_state can tell us.
@@ -747,7 +747,7 @@ class SliderMixin:
747
747
  datetime_min = value[0] - timedelta(days=14)
748
748
  datetime_max = value[0] + timedelta(days=14)
749
749
 
750
- DEFAULTS = {
750
+ defaults: Final = {
751
751
  SliderProto.INT: {
752
752
  "min_value": 0,
753
753
  "max_value": 100,
@@ -781,18 +781,18 @@ class SliderMixin:
781
781
  }
782
782
 
783
783
  if min_value is None:
784
- min_value = DEFAULTS[data_type]["min_value"]
784
+ min_value = defaults[data_type]["min_value"]
785
785
  if max_value is None:
786
- max_value = DEFAULTS[data_type]["max_value"]
786
+ max_value = defaults[data_type]["max_value"]
787
787
  if step is None:
788
- step = DEFAULTS[data_type]["step"]
788
+ step = defaults[data_type]["step"]
789
789
  if data_type in (
790
790
  SliderProto.DATETIME,
791
791
  SliderProto.DATE,
792
792
  ) and max_value - min_value < timedelta(days=1):
793
793
  step = timedelta(minutes=15)
794
794
  if format is None:
795
- format = cast("str", DEFAULTS[data_type]["format"]) # noqa: A001
795
+ format = cast("str", defaults[data_type]["format"]) # noqa: A001
796
796
 
797
797
  if step == 0:
798
798
  raise StreamlitAPIException(
@@ -813,17 +813,13 @@ class SliderMixin:
813
813
  )
814
814
 
815
815
  if not int_args and not float_args and not timelike_args:
816
- raise StreamlitAPIException(
816
+ msg = (
817
817
  "Slider value arguments must be of matching types."
818
- "\n`min_value` has %(min_type)s type."
819
- "\n`max_value` has %(max_type)s type."
820
- "\n`step` has %(step)s type."
821
- % {
822
- "min_type": type(min_value).__name__,
823
- "max_type": type(max_value).__name__,
824
- "step": type(step).__name__,
825
- }
818
+ f"\n`min_value` has {type(min_value).__name__} type."
819
+ f"\n`max_value` has {type(max_value).__name__} type."
820
+ f"\n`step` has {type(step).__name__} type."
826
821
  )
822
+ raise StreamlitAPIException(msg)
827
823
 
828
824
  # Ensure that the value matches arguments' types.
829
825
  all_ints = data_type == SliderProto.INT and int_args
@@ -831,17 +827,13 @@ class SliderMixin:
831
827
  all_timelikes = data_type in TIMELIKE_TYPES and timelike_args
832
828
 
833
829
  if not all_ints and not all_floats and not all_timelikes:
834
- raise StreamlitAPIException(
830
+ msg = (
835
831
  "Both value and arguments must be of the same type."
836
- "\n`value` has %(value_type)s type."
837
- "\n`min_value` has %(min_type)s type."
838
- "\n`max_value` has %(max_type)s type."
839
- % {
840
- "value_type": type(value).__name__,
841
- "min_type": type(min_value).__name__,
842
- "max_type": type(max_value).__name__,
843
- }
832
+ f"\n`value` has {type(value).__name__} type."
833
+ f"\n`min_value` has {type(min_value).__name__} type."
834
+ f"\n`max_value` has {type(max_value).__name__} type."
844
835
  )
836
+ raise StreamlitAPIException(msg)
845
837
 
846
838
  # Ensure that min <= value(s) <= max, adjusting the bounds as necessary.
847
839
  min_value = min(min_value, max_value)
@@ -972,14 +964,9 @@ class SliderMixin:
972
964
  slider_proto.set_value = True
973
965
 
974
966
  validate_width(width)
975
- width_config = WidthConfig()
976
- if isinstance(width, int):
977
- width_config.pixel_width = width
978
- else:
979
- width_config.use_stretch = True
980
- slider_proto.width_config.CopyFrom(width_config)
967
+ layout_config = LayoutConfig(width=width)
981
968
 
982
- self.dg._enqueue("slider", slider_proto)
969
+ self.dg._enqueue("slider", slider_proto, layout_config=layout_config)
983
970
  return cast("SliderReturn", widget_state.value)
984
971
 
985
972
  @property
@@ -19,7 +19,11 @@ from textwrap import dedent
19
19
  from typing import TYPE_CHECKING, Literal, cast, overload
20
20
 
21
21
  from streamlit.elements.lib.form_utils import current_form_id
22
- from streamlit.elements.lib.layout_utils import WidthWithoutContent, validate_width
22
+ from streamlit.elements.lib.layout_utils import (
23
+ LayoutConfig,
24
+ WidthWithoutContent,
25
+ validate_width,
26
+ )
23
27
  from streamlit.elements.lib.policies import (
24
28
  check_widget_policies,
25
29
  maybe_raise_label_warnings,
@@ -34,7 +38,6 @@ from streamlit.elements.lib.utils import (
34
38
  from streamlit.errors import StreamlitAPIException
35
39
  from streamlit.proto.TextArea_pb2 import TextArea as TextAreaProto
36
40
  from streamlit.proto.TextInput_pb2 import TextInput as TextInputProto
37
- from streamlit.proto.WidthConfig_pb2 import WidthConfig
38
41
  from streamlit.runtime.metrics_util import gather_metrics
39
42
  from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
40
43
  from streamlit.runtime.state import (
@@ -308,7 +311,6 @@ class TextWidgetsMixin:
308
311
  default_value=None if value == "" else value,
309
312
  )
310
313
  maybe_raise_label_warnings(label, label_visibility)
311
- validate_width(width)
312
314
 
313
315
  # Make sure value is always string or None:
314
316
  value = str(value) if value is not None else None
@@ -317,6 +319,7 @@ class TextWidgetsMixin:
317
319
  "text_input",
318
320
  user_key=key,
319
321
  form_id=current_form_id(self.dg),
322
+ dg=self.dg,
320
323
  label=label,
321
324
  value=value,
322
325
  max_chars=max_chars,
@@ -355,22 +358,13 @@ class TextWidgetsMixin:
355
358
  if icon is not None:
356
359
  text_input_proto.icon = validate_icon_or_emoji(icon)
357
360
 
358
- # Set up width configuration
359
- width_config = WidthConfig()
360
- if isinstance(width, int):
361
- width_config.pixel_width = width
362
- else:
363
- width_config.use_stretch = True
364
- text_input_proto.width_config.CopyFrom(width_config)
365
-
366
361
  if type == "default":
367
362
  text_input_proto.type = TextInputProto.DEFAULT
368
363
  elif type == "password":
369
364
  text_input_proto.type = TextInputProto.PASSWORD
370
365
  else:
371
366
  raise StreamlitAPIException(
372
- "'%s' is not a valid text_input type. Valid types are 'default' and 'password'."
373
- % type
367
+ f"'{type}' is not a valid text_input type. Valid types are 'default' and 'password'."
374
368
  )
375
369
 
376
370
  # Marshall the autocomplete param. If unspecified, this will be
@@ -397,7 +391,10 @@ class TextWidgetsMixin:
397
391
  text_input_proto.value = widget_state.value
398
392
  text_input_proto.set_value = True
399
393
 
400
- self.dg._enqueue("text_input", text_input_proto)
394
+ validate_width(width)
395
+ layout_config = LayoutConfig(width=width)
396
+
397
+ self.dg._enqueue("text_input", text_input_proto, layout_config=layout_config)
401
398
  return widget_state.value
402
399
 
403
400
  @overload
@@ -614,7 +611,6 @@ class TextWidgetsMixin:
614
611
  default_value=None if value == "" else value,
615
612
  )
616
613
  maybe_raise_label_warnings(label, label_visibility)
617
- validate_width(width)
618
614
 
619
615
  value = str(value) if value is not None else None
620
616
 
@@ -622,6 +618,7 @@ class TextWidgetsMixin:
622
618
  "text_area",
623
619
  user_key=key,
624
620
  form_id=current_form_id(self.dg),
621
+ dg=self.dg,
625
622
  label=label,
626
623
  value=value,
627
624
  height=height,
@@ -658,14 +655,6 @@ class TextWidgetsMixin:
658
655
  if placeholder is not None:
659
656
  text_area_proto.placeholder = str(placeholder)
660
657
 
661
- # Set up width configuration
662
- width_config = WidthConfig()
663
- if isinstance(width, int):
664
- width_config.pixel_width = width
665
- else:
666
- width_config.use_stretch = True
667
- text_area_proto.width_config.CopyFrom(width_config)
668
-
669
658
  serde = TextAreaSerde(value)
670
659
  widget_state = register_widget(
671
660
  text_area_proto.id,
@@ -683,7 +672,10 @@ class TextWidgetsMixin:
683
672
  text_area_proto.value = widget_state.value
684
673
  text_area_proto.set_value = True
685
674
 
686
- self.dg._enqueue("text_area", text_area_proto)
675
+ validate_width(width)
676
+ layout_config = LayoutConfig(width=width)
677
+
678
+ self.dg._enqueue("text_area", text_area_proto, layout_config=layout_config)
687
679
  return widget_state.value
688
680
 
689
681
  @property
@@ -31,7 +31,11 @@ from typing import (
31
31
  from typing_extensions import TypeAlias
32
32
 
33
33
  from streamlit.elements.lib.form_utils import current_form_id
34
- from streamlit.elements.lib.layout_utils import WidthWithoutContent, validate_width
34
+ from streamlit.elements.lib.layout_utils import (
35
+ LayoutConfig,
36
+ WidthWithoutContent,
37
+ validate_width,
38
+ )
35
39
  from streamlit.elements.lib.policies import (
36
40
  check_widget_policies,
37
41
  maybe_raise_label_warnings,
@@ -46,7 +50,6 @@ from streamlit.elements.lib.utils import (
46
50
  from streamlit.errors import StreamlitAPIException
47
51
  from streamlit.proto.DateInput_pb2 import DateInput as DateInputProto
48
52
  from streamlit.proto.TimeInput_pb2 import TimeInput as TimeInputProto
49
- from streamlit.proto.WidthConfig_pb2 import WidthConfig
50
53
  from streamlit.runtime.metrics_util import gather_metrics
51
54
  from streamlit.runtime.scriptrunner import ScriptRunContext, get_script_run_ctx
52
55
  from streamlit.runtime.state import (
@@ -514,7 +517,6 @@ class TimeWidgetsMixin:
514
517
  default_value=value if value != "now" else None,
515
518
  )
516
519
  maybe_raise_label_warnings(label, label_visibility)
517
- validate_width(width)
518
520
 
519
521
  parsed_time: time | None
520
522
  parsed_time = None if value is None else _convert_timelike_to_time(value)
@@ -523,6 +525,7 @@ class TimeWidgetsMixin:
523
525
  "time_input",
524
526
  user_key=key,
525
527
  form_id=current_form_id(self.dg),
528
+ dg=self.dg,
526
529
  label=label,
527
530
  value=parsed_time if isinstance(value, (datetime, time)) else value,
528
531
  help=help,
@@ -560,14 +563,6 @@ class TimeWidgetsMixin:
560
563
  if help is not None:
561
564
  time_input_proto.help = dedent(help)
562
565
 
563
- # Set up width configuration
564
- width_config = WidthConfig()
565
- if isinstance(width, int):
566
- width_config.pixel_width = width
567
- else:
568
- width_config.use_stretch = True
569
- time_input_proto.width_config.CopyFrom(width_config)
570
-
571
566
  serde = TimeInputSerde(parsed_time)
572
567
  widget_state = register_widget(
573
568
  time_input_proto.id,
@@ -585,7 +580,10 @@ class TimeWidgetsMixin:
585
580
  time_input_proto.value = serialized_value
586
581
  time_input_proto.set_value = True
587
582
 
588
- self.dg._enqueue("time_input", time_input_proto)
583
+ validate_width(width)
584
+ layout_config = LayoutConfig(width=width)
585
+
586
+ self.dg._enqueue("time_input", time_input_proto, layout_config=layout_config)
589
587
  return widget_state.value
590
588
 
591
589
  @overload
@@ -873,7 +871,6 @@ class TimeWidgetsMixin:
873
871
  default_value=value if value != "today" else None,
874
872
  )
875
873
  maybe_raise_label_warnings(label, label_visibility)
876
- validate_width(width)
877
874
 
878
875
  def parse_date_deterministic_for_id(v: NullableScalarDateValue) -> str | None:
879
876
  if v == "today":
@@ -909,6 +906,7 @@ class TimeWidgetsMixin:
909
906
  "date_input",
910
907
  user_key=key,
911
908
  form_id=current_form_id(self.dg),
909
+ dg=self.dg,
912
910
  label=label,
913
911
  value=parsed,
914
912
  min_value=parsed_min_date,
@@ -973,14 +971,6 @@ class TimeWidgetsMixin:
973
971
  if help is not None:
974
972
  date_input_proto.help = dedent(help)
975
973
 
976
- # Set up width configuration
977
- width_config = WidthConfig()
978
- if isinstance(width, int):
979
- width_config.pixel_width = width
980
- else:
981
- width_config.use_stretch = True
982
- date_input_proto.width_config.CopyFrom(width_config)
983
-
984
974
  serde = DateInputSerde(parsed_values)
985
975
 
986
976
  widget_state = register_widget(
@@ -998,7 +988,10 @@ class TimeWidgetsMixin:
998
988
  date_input_proto.value[:] = serde.serialize(widget_state.value)
999
989
  date_input_proto.set_value = True
1000
990
 
1001
- self.dg._enqueue("date_input", date_input_proto)
991
+ validate_width(width)
992
+ layout_config = LayoutConfig(width=width)
993
+
994
+ self.dg._enqueue("date_input", date_input_proto, layout_config=layout_config)
1002
995
  return widget_state.value
1003
996
 
1004
997
  @property