streamlit 1.47.0__py3-none-any.whl → 1.48.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 (189) hide show
  1. streamlit/cli_util.py +1 -1
  2. streamlit/commands/echo.py +2 -2
  3. streamlit/commands/execution_control.py +1 -1
  4. streamlit/commands/page_config.py +16 -16
  5. streamlit/components/v1/component_arrow.py +4 -4
  6. streamlit/config.py +23 -5
  7. streamlit/connections/base_connection.py +2 -2
  8. streamlit/connections/snowflake_connection.py +2 -2
  9. streamlit/connections/sql_connection.py +4 -3
  10. streamlit/dataframe_util.py +1 -1
  11. streamlit/deprecation_util.py +20 -5
  12. streamlit/elements/arrow.py +105 -79
  13. streamlit/elements/deck_gl_json_chart.py +6 -6
  14. streamlit/elements/dialog_decorator.py +72 -17
  15. streamlit/elements/form.py +36 -7
  16. streamlit/elements/graphviz_chart.py +7 -0
  17. streamlit/elements/json.py +3 -3
  18. streamlit/elements/layouts.py +241 -75
  19. streamlit/elements/lib/built_in_chart_utils.py +11 -3
  20. streamlit/elements/lib/dialog.py +43 -0
  21. streamlit/elements/lib/file_uploader_utils.py +21 -2
  22. streamlit/elements/lib/layout_utils.py +88 -2
  23. streamlit/elements/lib/options_selector_utils.py +1 -1
  24. streamlit/elements/lib/utils.py +23 -3
  25. streamlit/elements/map.py +12 -11
  26. streamlit/elements/plotly_chart.py +21 -21
  27. streamlit/elements/pyplot.py +8 -4
  28. streamlit/elements/vega_charts.py +237 -143
  29. streamlit/elements/widgets/audio_input.py +2 -2
  30. streamlit/elements/widgets/button.py +147 -35
  31. streamlit/elements/widgets/button_group.py +9 -8
  32. streamlit/elements/widgets/camera_input.py +2 -2
  33. streamlit/elements/widgets/chat.py +8 -2
  34. streamlit/elements/widgets/checkbox.py +4 -4
  35. streamlit/elements/widgets/color_picker.py +2 -2
  36. streamlit/elements/widgets/data_editor.py +22 -15
  37. streamlit/elements/widgets/file_uploader.py +8 -2
  38. streamlit/elements/widgets/multiselect.py +27 -17
  39. streamlit/elements/widgets/number_input.py +2 -2
  40. streamlit/elements/widgets/radio.py +5 -4
  41. streamlit/elements/widgets/select_slider.py +8 -5
  42. streamlit/elements/widgets/selectbox.py +14 -4
  43. streamlit/elements/widgets/slider.py +59 -33
  44. streamlit/elements/widgets/text_widgets.py +4 -4
  45. streamlit/elements/widgets/time_widgets.py +4 -4
  46. streamlit/elements/write.py +9 -8
  47. streamlit/env_util.py +1 -1
  48. streamlit/errors.py +20 -4
  49. streamlit/file_util.py +1 -1
  50. streamlit/git_util.py +1 -1
  51. streamlit/logger.py +2 -2
  52. streamlit/proto/Block_pb2.py +39 -31
  53. streamlit/proto/Block_pb2.pyi +54 -3
  54. streamlit/proto/Button_pb2.py +4 -2
  55. streamlit/proto/Button_pb2.pyi +1 -0
  56. streamlit/runtime/caching/cache_data_api.py +15 -2
  57. streamlit/runtime/caching/cache_errors.py +1 -1
  58. streamlit/runtime/caching/cache_resource_api.py +24 -2
  59. streamlit/runtime/caching/cache_utils.py +6 -3
  60. streamlit/runtime/caching/hashing.py +6 -9
  61. streamlit/runtime/fragment.py +3 -2
  62. streamlit/runtime/runtime.py +19 -2
  63. streamlit/runtime/scriptrunner/script_runner.py +3 -3
  64. streamlit/runtime/state/common.py +2 -1
  65. streamlit/runtime/state/query_params.py +2 -1
  66. streamlit/runtime/state/session_state.py +1 -1
  67. streamlit/static/index.html +1 -1
  68. streamlit/static/manifest.json +231 -231
  69. streamlit/static/static/css/index.CQt5TjGB.css +1 -0
  70. streamlit/static/static/js/{ErrorOutline.esm.bg5MMAri.js → ErrorOutline.esm.D_4oFNKB.js} +1 -1
  71. streamlit/static/static/js/{FileDownload.esm.ZD5PIl3I.js → FileDownload.esm.NPgaLlUE.js} +1 -1
  72. streamlit/static/static/js/{FileHelper.B6jszxAn.js → FileHelper.B2t9ikoS.js} +1 -1
  73. streamlit/static/static/js/{FormClearHelper.DuzI-rET.js → FormClearHelper.BLEIUk6L.js} +1 -1
  74. streamlit/static/static/js/{Hooks.qKXFrFZm.js → Hooks.BGm9sd4U.js} +1 -1
  75. streamlit/static/static/js/{InputInstructions.7NdlV9ze.js → InputInstructions.DtUxCBS8.js} +1 -1
  76. streamlit/static/static/js/Particles.BDRPO7r3.js +1 -0
  77. streamlit/static/static/js/ProgressBar.B64DUUqp.js +2 -0
  78. streamlit/static/static/js/Toolbar.B3FquPk5.js +1 -0
  79. streamlit/static/static/js/{base-input.Dl5fJ2xw.js → base-input.DeBqm5mN.js} +4 -4
  80. streamlit/static/static/js/{checkbox.DCoT7yTn.js → checkbox.C0odQfKb.js} +2 -2
  81. streamlit/static/static/js/createDownloadLinkElement.ZaXNnPK4.js +1 -0
  82. streamlit/static/static/js/{createSuper.DIDXPRra.js → createSuper.DqQ5L3XG.js} +1 -1
  83. streamlit/static/static/js/data-grid-overlay-editor.DbNsQa8Y.js +1 -0
  84. streamlit/static/static/js/{downloader.DKv2kGmf.js → downloader.Bx1D0jhz.js} +1 -1
  85. streamlit/static/static/js/{es6.JcohG4tM.js → es6.CbPK4m0H.js} +2 -2
  86. streamlit/static/static/js/{iframeResizer.contentWindow.3rtAterA.js → iframeResizer.contentWindow.CfLKrptA.js} +1 -1
  87. streamlit/static/static/js/{index.BO22lkaO.js → index.0XDwe9RV.js} +12 -12
  88. streamlit/static/static/js/{index.Wj4EUfiO.js → index.4lI9TuZm.js} +3 -3
  89. streamlit/static/static/js/index.6s0nVIis.js +3855 -0
  90. streamlit/static/static/js/index.9E7bRUBU.js +1 -0
  91. streamlit/static/static/js/index.B9PgeLrZ.js +1 -0
  92. streamlit/static/static/js/index.B9vzGbOt.js +1 -0
  93. streamlit/static/static/js/index.BDrQKMCm.js +1 -0
  94. streamlit/static/static/js/index.BPsoiGgP.js +1 -0
  95. streamlit/static/static/js/index.CJzdLAun.js +1 -0
  96. streamlit/static/static/js/index.CNNlC1NL.js +1 -0
  97. streamlit/static/static/js/index.CO1sClzJ.js +2 -0
  98. streamlit/static/static/js/index.CZnagxXD.js +1 -0
  99. streamlit/static/static/js/{index.CnNERm7h.js → index.Cb0xSF7V.js} +289 -289
  100. streamlit/static/static/js/index.CgUt3tz_.js +1 -0
  101. streamlit/static/static/js/index.CjImmcsV.js +1 -0
  102. streamlit/static/static/js/index.ClRTsv8m.js +2 -0
  103. streamlit/static/static/js/{index.DBhELRFO.js → index.CnfWsQzS.js} +1 -1
  104. streamlit/static/static/js/index.CrJ1XD_V.js +1 -0
  105. streamlit/static/static/js/index.CtiKsjSC.js +1 -0
  106. streamlit/static/static/js/index.CwAuytgV.js +1 -0
  107. streamlit/static/static/js/index.D7GB-kly.js +1 -0
  108. streamlit/static/static/js/index.DA5wU0mQ.js +1 -0
  109. streamlit/static/static/js/{index.BVTVGhCW.js → index.DCpyIFTV.js} +1 -1
  110. streamlit/static/static/js/{index.Brmdn6cI.js → index.DE9wNOje.js} +1 -1
  111. streamlit/static/static/js/{index.B4UgLnfD.js → index.DHnB-C8A.js} +1 -1
  112. streamlit/static/static/js/{index.DmB_1wAI.js → index.DRTn9zvD.js} +1 -1
  113. streamlit/static/static/js/index.DjMjyJl9.js +7 -0
  114. streamlit/static/static/js/{index.BTGIlECR.js → index.DvRPFfw6.js} +162 -188
  115. streamlit/static/static/js/{index.BlIoUPom.js → index.DwaoC4Zp.js} +3 -3
  116. streamlit/static/static/js/index.F9tSej94.js +1 -0
  117. streamlit/static/static/js/index.HeVbRh9H.js +73 -0
  118. streamlit/static/static/js/index.J2D_m7LY.js +197 -0
  119. streamlit/static/static/js/index.PyIqRRSR.js +1 -0
  120. streamlit/static/static/js/index.dfivzJNz.js +1 -0
  121. streamlit/static/static/js/index.mRztGO69.js +3 -0
  122. streamlit/static/static/js/index.tB1kn_7z.js +1 -0
  123. streamlit/static/static/js/index.wDYef4mQ.js +12 -0
  124. streamlit/static/static/js/{input.vCGI-j0z.js → input.BL2buuce.js} +2 -2
  125. streamlit/static/static/js/{memory.CAr59PeX.js → memory.CUxjUWS7.js} +1 -1
  126. streamlit/static/static/js/{mergeWith.KUX-f18q.js → mergeWith.C1kp1zIi.js} +1 -1
  127. streamlit/static/static/js/{number-overlay-editor.7_qeQYbF.js → number-overlay-editor.WpheGpmR.js} +1 -1
  128. streamlit/static/static/js/{possibleConstructorReturn.ChgdWjjy.js → possibleConstructorReturn.DbvQboK3.js} +1 -1
  129. streamlit/static/static/js/{sandbox.6mITyM_H.js → sandbox.6lnFVWhX.js} +1 -1
  130. streamlit/static/static/js/{timepicker.BlKW9Kob.js → timepicker.Bg4xAK95.js} +1 -1
  131. streamlit/static/static/js/{toConsumableArray.DkNUwUhg.js → toConsumableArray.D9x7Ktv4.js} +1 -1
  132. streamlit/static/static/js/{uniqueId.BW6icrs1.js → uniqueId.Bm8FHN92.js} +1 -1
  133. streamlit/static/static/js/{useBasicWidgetState.oPxte5Mj.js → useBasicWidgetState.CUSYQZpm.js} +1 -1
  134. streamlit/static/static/js/{useTextInputAutoExpand.s7ZXp9QC.js → useTextInputAutoExpand.Bf2egQOG.js} +2 -2
  135. streamlit/static/static/js/useUpdateUiValue.lE5xnYWF.js +1 -0
  136. streamlit/static/static/js/withFullScreenWrapper.CCOXR7N6.js +1 -0
  137. streamlit/temporary_directory.py +5 -3
  138. streamlit/testing/v1/app_test.py +4 -1
  139. streamlit/testing/v1/element_tree.py +4 -5
  140. streamlit/type_util.py +10 -3
  141. streamlit/user_info.py +18 -14
  142. streamlit/util.py +11 -1
  143. streamlit/watcher/local_sources_watcher.py +4 -3
  144. streamlit/web/bootstrap.py +18 -12
  145. streamlit/web/cli.py +2 -1
  146. streamlit/web/server/oauth_authlib_routes.py +59 -3
  147. streamlit/web/server/routes.py +3 -0
  148. streamlit/web/server/server.py +72 -21
  149. {streamlit-1.47.0.dist-info → streamlit-1.48.0.dist-info}/METADATA +14 -2
  150. {streamlit-1.47.0.dist-info → streamlit-1.48.0.dist-info}/RECORD +154 -154
  151. streamlit/static/static/css/index.CsLB_Bnz.css +0 -1
  152. streamlit/static/static/js/ProgressBar.d6X6RRog.js +0 -2
  153. streamlit/static/static/js/RenderInPortalIfExists.DEmedSWH.js +0 -1
  154. streamlit/static/static/js/Toolbar.D8wuuqZd.js +0 -1
  155. streamlit/static/static/js/createDownloadLinkElement.DZMwyjvU.js +0 -1
  156. streamlit/static/static/js/data-grid-overlay-editor.Bxxjm6-o.js +0 -1
  157. streamlit/static/static/js/index.0dTVhOfX.js +0 -1
  158. streamlit/static/static/js/index.4yEdNndV.js +0 -1
  159. streamlit/static/static/js/index.5n6QoSUA.js +0 -1
  160. streamlit/static/static/js/index.6nngkCAa.js +0 -2
  161. streamlit/static/static/js/index.94f3Fw7s.js +0 -1
  162. streamlit/static/static/js/index.B61tWuMK.js +0 -73
  163. streamlit/static/static/js/index.B7u9Flh8.js +0 -1
  164. streamlit/static/static/js/index.BASsihSP.js +0 -1
  165. streamlit/static/static/js/index.BL9HK8jG.js +0 -1
  166. streamlit/static/static/js/index.BQWRZ6al.js +0 -3855
  167. streamlit/static/static/js/index.BQXddtYi.js +0 -1
  168. streamlit/static/static/js/index.BUnHfDxu.js +0 -1
  169. streamlit/static/static/js/index.BWQlvt-p.js +0 -1
  170. streamlit/static/static/js/index.BhB2h-IN.js +0 -1
  171. streamlit/static/static/js/index.BjbAdGl1.js +0 -2
  172. streamlit/static/static/js/index.BqMXJWvY.js +0 -197
  173. streamlit/static/static/js/index.BteAxTUz.js +0 -1
  174. streamlit/static/static/js/index.ByH19tU7.js +0 -1
  175. streamlit/static/static/js/index.CH_JROvL.js +0 -1
  176. streamlit/static/static/js/index.CRMaL4_D.js +0 -1
  177. streamlit/static/static/js/index.CitqAWcf.js +0 -7
  178. streamlit/static/static/js/index.DNTjV0h_.js +0 -3
  179. streamlit/static/static/js/index.Df2TZ_h-.js +0 -1
  180. streamlit/static/static/js/index.GID7Wiqx.js +0 -1
  181. streamlit/static/static/js/index.hprQgsHY.js +0 -1
  182. streamlit/static/static/js/index.mJxNfDOA.js +0 -12
  183. streamlit/static/static/js/index.qkxYEW65.js +0 -1
  184. streamlit/static/static/js/useOnInputChange.CBaDeGVQ.js +0 -1
  185. streamlit/static/static/js/withFullScreenWrapper.DkugyWpW.js +0 -1
  186. {streamlit-1.47.0.data → streamlit-1.48.0.data}/scripts/streamlit.cmd +0 -0
  187. {streamlit-1.47.0.dist-info → streamlit-1.48.0.dist-info}/WHEEL +0 -0
  188. {streamlit-1.47.0.dist-info → streamlit-1.48.0.dist-info}/entry_points.txt +0 -0
  189. {streamlit-1.47.0.dist-info → streamlit-1.48.0.dist-info}/top_level.txt +0 -0
@@ -15,7 +15,7 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  from functools import wraps
18
- from typing import TYPE_CHECKING, Any, Callable, TypeVar, cast, overload
18
+ from typing import TYPE_CHECKING, Any, Callable, Literal, TypeVar, cast, overload
19
19
 
20
20
  from streamlit.delta_generator_singletons import (
21
21
  get_dg_singleton_instance,
@@ -28,9 +28,11 @@ from streamlit.deprecation_util import (
28
28
  from streamlit.errors import StreamlitAPIException
29
29
  from streamlit.runtime.fragment import _fragment
30
30
  from streamlit.runtime.metrics_util import gather_metrics
31
+ from streamlit.type_util import get_object_name
31
32
 
32
33
  if TYPE_CHECKING:
33
34
  from streamlit.elements.lib.dialog import DialogWidth
35
+ from streamlit.runtime.state import WidgetCallback
34
36
 
35
37
 
36
38
  def _assert_no_nested_dialogs() -> None:
@@ -57,7 +59,7 @@ def _assert_no_nested_dialogs() -> None:
57
59
  raise StreamlitAPIException("Dialogs may not be nested inside other dialogs.")
58
60
 
59
61
 
60
- F = TypeVar("F", bound=Callable[..., None])
62
+ F = TypeVar("F", bound=Callable[..., Any])
61
63
 
62
64
 
63
65
  def _dialog_decorator(
@@ -66,6 +68,8 @@ def _dialog_decorator(
66
68
  *,
67
69
  width: DialogWidth = "small",
68
70
  should_show_deprecation_warning: bool = False,
71
+ dismissible: bool = True,
72
+ on_dismiss: Literal["ignore", "rerun"] | WidgetCallback = "ignore",
69
73
  ) -> F:
70
74
  if title is None or title == "":
71
75
  raise StreamlitAPIException(
@@ -80,7 +84,7 @@ def _dialog_decorator(
80
84
  # Streamlit UI flow. For example, if it is called from the sidebar, it should
81
85
  # not inherit the sidebar theming.
82
86
  dialog = get_dg_singleton_instance().event_dg._dialog(
83
- title=title, dismissible=True, width=width
87
+ title=title, dismissible=dismissible, width=width, on_dismiss=on_dismiss
84
88
  )
85
89
  dialog.open()
86
90
 
@@ -103,7 +107,7 @@ def _dialog_decorator(
103
107
  fragmented_dialog_content = cast(
104
108
  "Callable[[], None]",
105
109
  _fragment(
106
- dialog_content, additional_hash_info=non_optional_func.__qualname__
110
+ dialog_content, additional_hash_info=get_object_name(non_optional_func)
107
111
  ),
108
112
  )
109
113
 
@@ -116,7 +120,11 @@ def _dialog_decorator(
116
120
 
117
121
  @overload
118
122
  def dialog_decorator(
119
- title: str, *, width: DialogWidth = "small"
123
+ title: str,
124
+ *,
125
+ width: DialogWidth = "small",
126
+ dismissible: bool = True,
127
+ on_dismiss: Literal["ignore", "rerun"] | WidgetCallback = "ignore",
120
128
  ) -> Callable[[F], F]: ...
121
129
 
122
130
 
@@ -127,12 +135,22 @@ def dialog_decorator(
127
135
  # this 'trick'. The overload is required to have a good type hint for the decorated
128
136
  # function args.
129
137
  @overload
130
- def dialog_decorator(title: F, *, width: DialogWidth = "small") -> F: ...
138
+ def dialog_decorator(
139
+ title: F,
140
+ *,
141
+ width: DialogWidth = "small",
142
+ dismissible: bool = True,
143
+ on_dismiss: Literal["ignore", "rerun"] | WidgetCallback = "ignore",
144
+ ) -> F: ...
131
145
 
132
146
 
133
147
  @gather_metrics("dialog")
134
148
  def dialog_decorator(
135
- title: F | str, *, width: DialogWidth = "small"
149
+ title: F | str,
150
+ *,
151
+ width: DialogWidth = "small",
152
+ dismissible: bool = True,
153
+ on_dismiss: Literal["ignore", "rerun"] | WidgetCallback = "ignore",
136
154
  ) -> F | Callable[[F], F]:
137
155
  r"""Function decorator to create a modal dialog.
138
156
 
@@ -145,11 +163,15 @@ def dialog_decorator(
145
163
  called. Any values from the dialog that need to be accessed from the wider
146
164
  app should generally be stored in Session State.
147
165
 
148
- A user can dismiss a modal dialog by clicking outside of it, clicking the
149
- "**X**" in its upper-right corner, or pressing ``ESC`` on their keyboard.
150
- Dismissing a modal dialog does not trigger an app rerun. To close the modal
151
- dialog programmatically, call ``st.rerun()`` explicitly inside of the
152
- dialog function.
166
+ If a dialog is dismissible, a user can dismiss it by clicking outside of
167
+ it, clicking the "**X**" in its upper-right corner, or pressing ``ESC`` on
168
+ their keyboard. You can configure whether this triggers a rerun of the app
169
+ by setting the ``on_dismiss`` parameter.
170
+
171
+ If a dialog is not dismissible, it must be closed programmatically by
172
+ calling ``st.rerun()`` inside the dialog function. This is useful when you
173
+ want to ensure that the dialog is always closed programmatically, such as
174
+ when the dialog contains a form that must be submitted before closing.
153
175
 
154
176
  ``st.dialog`` inherits behavior from |st.fragment|_.
155
177
  When a user interacts with an input widget created inside a dialog function,
@@ -195,6 +217,33 @@ def dialog_decorator(
195
217
  modal dialog will be 500 pixels wide. If ``width`` is ``"large"``, the
196
218
  modal dialog will be about 750 pixels wide.
197
219
 
220
+ dismissible : bool
221
+ Whether the modal dialog can be dismissed by the user. If this is
222
+ ``True`` (default), the user can dismiss the dialog by clicking
223
+ outside of it, clicking the "**X**" in its upper-right corner, or
224
+ pressing ``ESC`` on their keyboard. If this is ``False``, the "**X**"
225
+ in the upper-right corner is hidden and the dialog must be closed
226
+ programmatically by calling ``st.rerun()`` inside the dialog function.
227
+
228
+ .. note::
229
+ Setting ``dismissible`` to ``False`` does not guarantee that all
230
+ interactions in the main app are blocked. Don't rely on
231
+ ``dismissible`` for security-critical checks.
232
+
233
+ on_dismiss : "ignore", "rerun", or callable
234
+ How the dialog should respond to dismissal events.
235
+ This can be one of the following:
236
+
237
+ - ``"ignore"`` (default): Streamlit will not rerun the app when the
238
+ user dismisses the dialog.
239
+
240
+ - ``"rerun"``: Streamlit will rerun the app when the user dismisses
241
+ the dialog.
242
+
243
+ - A ``callable``: Streamlit will rerun the app when the user dismisses
244
+ the dialog and execute the ``callable`` as a callback function
245
+ before the rest of the app.
246
+
198
247
  Examples
199
248
  --------
200
249
  The following example demonstrates the basic usage of ``@st.dialog``.
@@ -232,13 +281,20 @@ def dialog_decorator(
232
281
  if isinstance(func_or_title, str):
233
282
  # Support passing the params via function decorator
234
283
  def wrapper(f: F) -> F:
235
- title: str = func_or_title
236
- return _dialog_decorator(non_optional_func=f, title=title, width=width)
284
+ return _dialog_decorator(
285
+ non_optional_func=f,
286
+ title=func_or_title,
287
+ width=width,
288
+ dismissible=dismissible,
289
+ on_dismiss=on_dismiss,
290
+ )
237
291
 
238
292
  return wrapper
239
293
 
240
294
  func: F = func_or_title
241
- return _dialog_decorator(func, "", width=width)
295
+ return _dialog_decorator(
296
+ func, "", width=width, dismissible=dismissible, on_dismiss=on_dismiss
297
+ )
242
298
 
243
299
 
244
300
  @overload
@@ -267,10 +323,9 @@ def experimental_dialog_decorator(
267
323
  if isinstance(func_or_title, str):
268
324
  # Support passing the params via function decorator
269
325
  def wrapper(f: F) -> F:
270
- title: str = func_or_title
271
326
  return _dialog_decorator(
272
327
  non_optional_func=f,
273
- title=title,
328
+ title=func_or_title,
274
329
  width=width,
275
330
  should_show_deprecation_warning=True,
276
331
  )
@@ -246,7 +246,8 @@ class FormMixin:
246
246
  type: Literal["primary", "secondary", "tertiary"] = "secondary",
247
247
  icon: str | None = None,
248
248
  disabled: bool = False,
249
- use_container_width: bool = False,
249
+ use_container_width: bool | None = None,
250
+ width: Width = "content",
250
251
  ) -> bool:
251
252
  r"""Display a form submit button.
252
253
 
@@ -278,6 +279,7 @@ class FormMixin:
278
279
 
279
280
  .. |st.markdown| replace:: ``st.markdown``
280
281
  .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
282
+
281
283
  help : str or None
282
284
  A tooltip that gets displayed when the button is hovered over. If
283
285
  this is ``None`` (default), no tooltip is displayed.
@@ -285,12 +287,16 @@ class FormMixin:
285
287
  The tooltip can optionally contain GitHub-flavored Markdown,
286
288
  including the Markdown directives described in the ``body``
287
289
  parameter of ``st.markdown``.
290
+
288
291
  on_click : callable
289
292
  An optional callback invoked when this button is clicked.
290
- args : tuple
291
- An optional tuple of args to pass to the callback.
293
+
294
+ args : list or tuple
295
+ An optional list or tuple of args to pass to the callback.
296
+
292
297
  kwargs : dict
293
298
  An optional dict of kwargs to pass to the callback.
299
+
294
300
  type : "primary", "secondary", or "tertiary"
295
301
  An optional string that specifies the button type. This can be one
296
302
  of the following:
@@ -300,7 +306,7 @@ class FormMixin:
300
306
  - ``"secondary"`` (default): The button's background coordinates
301
307
  with the app's background color for normal emphasis.
302
308
  - ``"tertiary"``: The button is plain text without a border or
303
- background for subtly.
309
+ background for subtlety.
304
310
 
305
311
  icon : str or None
306
312
  An optional emoji or icon to display next to the button label. If ``icon``
@@ -318,6 +324,7 @@ class FormMixin:
318
324
  Thumb Up icon. Find additional icons in the `Material Symbols
319
325
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
320
326
  font library.
327
+
321
328
  disabled : bool
322
329
  Whether to disable the button. If this is ``False`` (default), the
323
330
  user can interact with the button. If this is ``True``, the button
@@ -336,6 +343,25 @@ class FormMixin:
336
343
  In both cases, if the contents of the button are wider than the
337
344
  parent container, the contents will line wrap.
338
345
 
346
+ width : "content", "stretch", or int
347
+ The width of the button. This can be one of the following:
348
+
349
+ - ``"content"`` (default): The width of the button matches the
350
+ width of its content, but doesn't exceed the width of the parent
351
+ container.
352
+ - ``"stretch"``: The width of the button matches the width of the
353
+ parent container.
354
+ - An integer specifying the width in pixels: The button has a
355
+ fixed width. If the specified width is greater than the width of
356
+ the parent container, the width of the button matches the width
357
+ of the parent container.
358
+
359
+ .. deprecated::
360
+ ``use_container_width`` is deprecated and will be removed in a
361
+ future release. For ``use_container_width=True``, use
362
+ ``width="stretch"``. For ``use_container_width=False``, use
363
+ ``width="content"``.
364
+
339
365
  Returns
340
366
  -------
341
367
  bool
@@ -343,6 +369,9 @@ class FormMixin:
343
369
  """
344
370
  ctx = get_script_run_ctx()
345
371
 
372
+ if use_container_width is not None:
373
+ width = "stretch" if use_container_width else "content"
374
+
346
375
  # Checks whether the entered button type is one of the allowed options
347
376
  if type not in ["primary", "secondary", "tertiary"]:
348
377
  raise StreamlitAPIException(
@@ -359,8 +388,8 @@ class FormMixin:
359
388
  type=type,
360
389
  icon=icon,
361
390
  disabled=disabled,
362
- use_container_width=use_container_width,
363
391
  ctx=ctx,
392
+ width=width,
364
393
  )
365
394
 
366
395
  def _form_submit_button(
@@ -374,8 +403,8 @@ class FormMixin:
374
403
  type: Literal["primary", "secondary", "tertiary"] = "secondary",
375
404
  icon: str | None = None,
376
405
  disabled: bool = False,
377
- use_container_width: bool = False,
378
406
  ctx: ScriptRunContext | None = None,
407
+ width: Width = "content",
379
408
  ) -> bool:
380
409
  form_id = current_form_id(self.dg)
381
410
  submit_button_key = f"FormSubmitter:{form_id}-{label}"
@@ -390,8 +419,8 @@ class FormMixin:
390
419
  type=type,
391
420
  icon=icon,
392
421
  disabled=disabled,
393
- use_container_width=use_container_width,
394
422
  ctx=ctx,
423
+ width=width,
395
424
  )
396
425
 
397
426
  @property
@@ -45,6 +45,13 @@ class GraphvizMixin:
45
45
  ) -> DeltaGenerator:
46
46
  """Display a graph using the dagre-d3 library.
47
47
 
48
+ .. Important::
49
+ You must install ``graphviz>=0.19.0`` to use this command. You can
50
+ install all charting dependencies (except Bokeh) as an extra with
51
+ Streamlit:
52
+
53
+ >>> pip install streamlit[charts]
54
+
48
55
  Parameters
49
56
  ----------
50
57
  figure_or_dot : graphviz.dot.Graph, graphviz.dot.Digraph, graphviz.sources.Source, str
@@ -109,10 +109,10 @@ class JsonMixin:
109
109
  """
110
110
 
111
111
  if is_custom_dict(body):
112
- body = body.to_dict()
112
+ body = body.to_dict() # ty: ignore[unresolved-attribute]
113
113
 
114
114
  if is_namedtuple(body):
115
- body = body._asdict()
115
+ body = body._asdict() # ty: ignore[unresolved-attribute]
116
116
 
117
117
  if isinstance(
118
118
  body, (ChainMap, types.MappingProxyType, UserDict)
@@ -120,7 +120,7 @@ class JsonMixin:
120
120
  body = dict(body) # type: ignore
121
121
 
122
122
  if is_list_like(body):
123
- body = list(body)
123
+ body = list(body) # ty: ignore[invalid-argument-type]
124
124
 
125
125
  if not isinstance(body, str):
126
126
  try: