streamlit 1.48.0__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 (208) 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/iframe.py +13 -22
  17. streamlit/elements/image.py +64 -37
  18. streamlit/elements/layouts.py +2 -2
  19. streamlit/elements/lib/built_in_chart_utils.py +2 -5
  20. streamlit/elements/lib/column_config_utils.py +18 -4
  21. streamlit/elements/lib/column_types.py +75 -30
  22. streamlit/elements/lib/dialog.py +3 -3
  23. streamlit/elements/lib/image_utils.py +19 -11
  24. streamlit/elements/lib/layout_utils.py +15 -2
  25. streamlit/elements/lib/utils.py +20 -41
  26. streamlit/elements/markdown.py +7 -6
  27. streamlit/elements/media.py +6 -13
  28. streamlit/elements/metric.py +78 -1
  29. streamlit/elements/pdf.py +192 -0
  30. streamlit/elements/plotly_chart.py +3 -2
  31. streamlit/elements/pyplot.py +53 -11
  32. streamlit/elements/toast.py +81 -5
  33. streamlit/elements/vega_charts.py +3 -8
  34. streamlit/elements/widgets/audio_input.py +0 -1
  35. streamlit/elements/widgets/button.py +0 -4
  36. streamlit/elements/widgets/button_group.py +5 -4
  37. streamlit/elements/widgets/camera_input.py +0 -1
  38. streamlit/elements/widgets/chat.py +11 -13
  39. streamlit/elements/widgets/checkbox.py +0 -1
  40. streamlit/elements/widgets/color_picker.py +0 -1
  41. streamlit/elements/widgets/data_editor.py +142 -62
  42. streamlit/elements/widgets/file_uploader.py +74 -37
  43. streamlit/elements/widgets/multiselect.py +0 -1
  44. streamlit/elements/widgets/number_input.py +0 -1
  45. streamlit/elements/widgets/radio.py +0 -1
  46. streamlit/elements/widgets/select_slider.py +0 -1
  47. streamlit/elements/widgets/selectbox.py +0 -1
  48. streamlit/elements/widgets/slider.py +0 -1
  49. streamlit/elements/widgets/text_widgets.py +0 -2
  50. streamlit/elements/widgets/time_widgets.py +0 -2
  51. streamlit/errors.py +11 -0
  52. streamlit/material_icon_names.py +1 -1
  53. streamlit/proto/Arrow_pb2.py +14 -8
  54. streamlit/proto/Arrow_pb2.pyi +11 -3
  55. streamlit/proto/Block_pb2.py +16 -16
  56. streamlit/proto/Block_pb2.pyi +2 -0
  57. streamlit/proto/ChatInput_pb2.py +3 -3
  58. streamlit/proto/ChatInput_pb2.pyi +2 -0
  59. streamlit/proto/FileUploader_pb2.py +2 -2
  60. streamlit/proto/FileUploader_pb2.pyi +5 -1
  61. streamlit/proto/GraphVizChart_pb2.py +4 -2
  62. streamlit/proto/GraphVizChart_pb2.pyi +1 -1
  63. streamlit/proto/IFrame_pb2.py +8 -2
  64. streamlit/proto/IFrame_pb2.pyi +3 -0
  65. streamlit/proto/Image_pb2.py +4 -2
  66. streamlit/proto/Image_pb2.pyi +1 -10
  67. streamlit/proto/Metric_pb2.py +8 -6
  68. streamlit/proto/Metric_pb2.pyi +34 -10
  69. streamlit/proto/Toast_pb2.py +2 -2
  70. streamlit/proto/Toast_pb2.pyi +10 -1
  71. streamlit/runtime/caching/__init__.py +14 -2
  72. streamlit/runtime/caching/cache_data_api.py +0 -17
  73. streamlit/runtime/caching/cache_resource_api.py +0 -16
  74. streamlit/runtime/caching/cached_message_replay.py +8 -20
  75. streamlit/runtime/caching/hashing.py +31 -1
  76. streamlit/runtime/credentials.py +4 -4
  77. streamlit/runtime/fragment.py +0 -42
  78. streamlit/runtime/websocket_session_manager.py +1 -1
  79. streamlit/static/index.html +2 -2
  80. streamlit/static/manifest.json +224 -252
  81. streamlit/static/static/css/{index.CJVRHjQZ.css → index.C8X8rNzw.css} +1 -1
  82. streamlit/static/static/css/index.COe1010n.css +1 -0
  83. streamlit/static/static/js/{ErrorOutline.esm.D_4oFNKB.js → ErrorOutline.esm.u9XvzxL8.js} +1 -1
  84. streamlit/static/static/js/{FileDownload.esm.NPgaLlUE.js → FileDownload.esm.CaRyZ-b2.js} +1 -1
  85. streamlit/static/static/js/FileHelper.Dk2SwIi3.js +5 -0
  86. streamlit/static/static/js/FormClearHelper.l_UPPvkg.js +1 -0
  87. streamlit/static/static/js/{Hooks.BGm9sd4U.js → Hooks.BxrVEftw.js} +1 -1
  88. streamlit/static/static/js/InputInstructions.C254RU9X.js +1 -0
  89. streamlit/static/static/js/Particles.DkY6FDnc.js +1 -0
  90. streamlit/static/static/js/ProgressBar.BPtSM82n.js +2 -0
  91. streamlit/static/static/js/Toolbar.BO_3WBaS.js +1 -0
  92. streamlit/static/static/js/{base-input.DeBqm5mN.js → base-input.egUI4LjJ.js} +4 -4
  93. streamlit/static/static/js/{checkbox.C0odQfKb.js → checkbox.ButpszcE.js} +2 -2
  94. streamlit/static/static/js/createSuper.DYJA5xa6.js +1 -0
  95. streamlit/static/static/js/data-grid-overlay-editor.C9gQLEnU.js +1 -0
  96. streamlit/static/static/js/{downloader.Bx1D0jhz.js → downloader.B3TjsSPZ.js} +1 -1
  97. streamlit/static/static/js/es6.BYSNuG4D.js +2 -0
  98. streamlit/static/static/js/iframeResizer.contentWindow.CNPHJsF2.js +1 -0
  99. streamlit/static/static/js/index.0tDq1WXk.js +1 -0
  100. streamlit/static/static/js/index.BBnWuh07.js +976 -0
  101. streamlit/static/static/js/index.BDZorv41.js +1 -0
  102. streamlit/static/static/js/{index.DwaoC4Zp.js → index.BH79B25f.js} +3 -3
  103. streamlit/static/static/js/index.BeTC4Yl-.js +197 -0
  104. streamlit/static/static/js/index.BnOd05Ko.js +2 -0
  105. streamlit/static/static/js/index.BoJaJReB.js +1 -0
  106. streamlit/static/static/js/index.Bp1Of6L8.js +1 -0
  107. streamlit/static/static/js/index.Bpe4-O2W.js +1 -0
  108. streamlit/static/static/js/index.BrD9sbpx.js +1 -0
  109. streamlit/static/static/js/index.C1qCS-sd.js +1 -0
  110. streamlit/static/static/js/index.C3EXAI-u.js +1 -0
  111. streamlit/static/static/js/index.C77g9sAQ.js +3 -0
  112. streamlit/static/static/js/{index.PyIqRRSR.js → index.CFePF7s4.js} +1 -1
  113. streamlit/static/static/js/index.CFjU0x00.js +1 -0
  114. streamlit/static/static/js/index.Ca3y4ztK.js +1 -0
  115. streamlit/static/static/js/{index.ClRTsv8m.js → index.Cb9gN2T2.js} +2 -2
  116. streamlit/static/static/js/{index.wDYef4mQ.js → index.CbwuUwu4.js} +9 -9
  117. streamlit/static/static/js/index.CeXLlclc.js +1 -0
  118. streamlit/static/static/js/index.CfiZGqj3.js +3 -0
  119. streamlit/static/static/js/index.CjQnYKID.js +1 -0
  120. streamlit/static/static/js/index.Cl_966eE.js +3858 -0
  121. streamlit/static/static/js/{index.DCpyIFTV.js → index.CqSRo6zQ.js} +1 -1
  122. streamlit/static/static/js/index.CuEFSQ-o.js +1 -0
  123. streamlit/static/static/js/index.D4jR1m1z.js +1 -0
  124. streamlit/static/static/js/index.DGcW849X.js +1 -0
  125. streamlit/static/static/js/index.DKb-BAE2.js +1 -0
  126. streamlit/static/static/js/index.DP1rDFP0.js +1 -0
  127. streamlit/static/static/js/{index.HeVbRh9H.js → index.DStzYLqM.js} +2 -2
  128. streamlit/static/static/js/index.DVKQKDLu.js +1 -0
  129. streamlit/static/static/js/index.DWedOrkQ.js +1 -0
  130. streamlit/static/static/js/index.DYbRPmVF.js +1 -0
  131. streamlit/static/static/js/index.DgpIMUsr.js +1 -0
  132. streamlit/static/static/js/index.DtwkPJs5.js +5367 -0
  133. streamlit/static/static/js/{index.CnfWsQzS.js → index.MQLQLR5Z.js} +1 -1
  134. streamlit/static/static/js/index.uInpwWAP.js +1 -0
  135. streamlit/static/static/js/index.z992t-BQ.js +7 -0
  136. streamlit/static/static/js/{input.BL2buuce.js → input.CbP5ZuQ7.js} +2 -2
  137. streamlit/static/static/js/{memory.CUxjUWS7.js → memory.BuacVo2L.js} +1 -1
  138. streamlit/static/static/js/number-overlay-editor.BZb9zRl_.js +9 -0
  139. streamlit/static/static/js/{possibleConstructorReturn.DbvQboK3.js → possibleConstructorReturn.DSM84rOS.js} +1 -1
  140. streamlit/static/static/js/{sandbox.6lnFVWhX.js → sandbox.C480llMG.js} +1 -1
  141. streamlit/static/static/js/{timepicker.Bg4xAK95.js → timepicker.BunxCVp7.js} +4 -4
  142. streamlit/static/static/js/{toConsumableArray.D9x7Ktv4.js → toConsumableArray.B4o8rEx1.js} +3 -3
  143. streamlit/static/static/js/uniqueId.tii0yosY.js +1 -0
  144. streamlit/static/static/js/{useBasicWidgetState.CUSYQZpm.js → useBasicWidgetState.Bnm4FD6K.js} +1 -1
  145. streamlit/static/static/js/useTextInputAutoExpand.Dgtwc1m0.js +2 -0
  146. streamlit/static/static/js/useUpdateUiValue.DjXdMFGw.js +1 -0
  147. streamlit/static/static/js/withFullScreenWrapper.0cy2pVf5.js +1 -0
  148. streamlit/static/static/media/MaterialSymbols-Rounded.CBxVaFdk.woff2 +0 -0
  149. streamlit/user_info.py +16 -13
  150. streamlit/web/server/browser_websocket_handler.py +15 -0
  151. streamlit/web/server/oauth_authlib_routes.py +3 -59
  152. {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/METADATA +4 -2
  153. {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/RECORD +157 -160
  154. streamlit/static/static/css/index.CQt5TjGB.css +0 -1
  155. streamlit/static/static/js/FileHelper.B2t9ikoS.js +0 -5
  156. streamlit/static/static/js/FormClearHelper.BLEIUk6L.js +0 -1
  157. streamlit/static/static/js/InputInstructions.DtUxCBS8.js +0 -1
  158. streamlit/static/static/js/Particles.BDRPO7r3.js +0 -1
  159. streamlit/static/static/js/ProgressBar.B64DUUqp.js +0 -2
  160. streamlit/static/static/js/Toolbar.B3FquPk5.js +0 -1
  161. streamlit/static/static/js/createSuper.DqQ5L3XG.js +0 -1
  162. streamlit/static/static/js/data-grid-overlay-editor.DbNsQa8Y.js +0 -1
  163. streamlit/static/static/js/es6.CbPK4m0H.js +0 -2
  164. streamlit/static/static/js/iframeResizer.contentWindow.CfLKrptA.js +0 -1
  165. streamlit/static/static/js/index.0XDwe9RV.js +0 -203
  166. streamlit/static/static/js/index.4lI9TuZm.js +0 -3
  167. streamlit/static/static/js/index.6s0nVIis.js +0 -3855
  168. streamlit/static/static/js/index.9E7bRUBU.js +0 -1
  169. streamlit/static/static/js/index.B9PgeLrZ.js +0 -1
  170. streamlit/static/static/js/index.B9vzGbOt.js +0 -1
  171. streamlit/static/static/js/index.BDrQKMCm.js +0 -1
  172. streamlit/static/static/js/index.BPsoiGgP.js +0 -1
  173. streamlit/static/static/js/index.CJzdLAun.js +0 -1
  174. streamlit/static/static/js/index.CNNlC1NL.js +0 -1
  175. streamlit/static/static/js/index.CO1sClzJ.js +0 -2
  176. streamlit/static/static/js/index.CZnagxXD.js +0 -1
  177. streamlit/static/static/js/index.Cb0xSF7V.js +0 -5366
  178. streamlit/static/static/js/index.CgUt3tz_.js +0 -1
  179. streamlit/static/static/js/index.CjImmcsV.js +0 -1
  180. streamlit/static/static/js/index.CrJ1XD_V.js +0 -1
  181. streamlit/static/static/js/index.CtiKsjSC.js +0 -1
  182. streamlit/static/static/js/index.CwAuytgV.js +0 -1
  183. streamlit/static/static/js/index.D7GB-kly.js +0 -1
  184. streamlit/static/static/js/index.DA5wU0mQ.js +0 -1
  185. streamlit/static/static/js/index.DE9wNOje.js +0 -1
  186. streamlit/static/static/js/index.DHnB-C8A.js +0 -1
  187. streamlit/static/static/js/index.DRTn9zvD.js +0 -1
  188. streamlit/static/static/js/index.DjMjyJl9.js +0 -7
  189. streamlit/static/static/js/index.DvRPFfw6.js +0 -781
  190. streamlit/static/static/js/index.F9tSej94.js +0 -1
  191. streamlit/static/static/js/index.J2D_m7LY.js +0 -197
  192. streamlit/static/static/js/index.dfivzJNz.js +0 -1
  193. streamlit/static/static/js/index.mRztGO69.js +0 -3
  194. streamlit/static/static/js/index.tB1kn_7z.js +0 -1
  195. streamlit/static/static/js/mergeWith.C1kp1zIi.js +0 -1
  196. streamlit/static/static/js/number-overlay-editor.WpheGpmR.js +0 -9
  197. streamlit/static/static/js/threshold.DjX0wlsa.js +0 -1
  198. streamlit/static/static/js/timer.CAwTRJ_g.js +0 -1
  199. streamlit/static/static/js/uniqueId.Bm8FHN92.js +0 -1
  200. streamlit/static/static/js/useTextInputAutoExpand.Bf2egQOG.js +0 -2
  201. streamlit/static/static/js/useUpdateUiValue.lE5xnYWF.js +0 -1
  202. streamlit/static/static/js/value.CgPGBV_l.js +0 -1
  203. streamlit/static/static/js/withFullScreenWrapper.CCOXR7N6.js +0 -1
  204. streamlit/static/static/media/MaterialSymbols-Rounded.DsbC8sYI.woff2 +0 -0
  205. {streamlit-1.48.0.data → streamlit-1.49.0.data}/scripts/streamlit.cmd +0 -0
  206. {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/WHEEL +0 -0
  207. {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/entry_points.txt +0 -0
  208. {streamlit-1.48.0.dist-info → streamlit-1.49.0.dist-info}/top_level.txt +0 -0
@@ -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,
@@ -20,6 +20,7 @@ from typing import TYPE_CHECKING, Any, Literal, Union, cast
20
20
 
21
21
  from typing_extensions import TypeAlias
22
22
 
23
+ from streamlit.dataframe_util import OptionSequence, convert_anything_to_list
23
24
  from streamlit.elements.lib.layout_utils import (
24
25
  Height,
25
26
  LayoutConfig,
@@ -62,11 +63,14 @@ class MetricMixin:
62
63
  value: Value,
63
64
  delta: Delta = None,
64
65
  delta_color: DeltaColor = "normal",
66
+ *,
65
67
  help: str | None = None,
66
68
  label_visibility: LabelVisibility = "visible",
67
69
  border: bool = False,
68
70
  width: Width = "stretch",
69
71
  height: Height = "content",
72
+ chart_data: OptionSequence[Any] | None = None,
73
+ chart_type: Literal["line", "bar", "area"] = "line",
70
74
  ) -> DeltaGenerator:
71
75
  r"""Display a metric in big bold font, with an optional indicator of how the metric changed.
72
76
 
@@ -156,6 +160,22 @@ class MetricMixin:
156
160
  the parent container, the width of the element matches the width
157
161
  of the parent container.
158
162
 
163
+ chart_data : Iterable or None
164
+ A sequence of numeric values to display as a sparkline chart. If
165
+ this is ``None`` (default), no chart is displayed. The sequence can
166
+ be anything supported by ``st.dataframe``, including a ``list`` or
167
+ ``set``. If the sequence is dataframe-like, the first column will
168
+ be used. Each value will be cast to ``float`` internally by
169
+ default.
170
+
171
+ chart_type : "line", "bar", or "area"
172
+ The type of sparkline chart to display. This can be one of the
173
+ following:
174
+
175
+ - ``"line"`` (default): A simple sparkline.
176
+ - ``"area"``: A sparkline with area shading.
177
+ - ``"bar"``: A bar chart.
178
+
159
179
  Examples
160
180
  --------
161
181
  **Example 1: Show a metric**
@@ -192,7 +212,10 @@ class MetricMixin:
192
212
  >>> st.metric(label="Gas price", value=4, delta=-0.5, delta_color="inverse")
193
213
  >>>
194
214
  >>> st.metric(
195
- ... label="Active developers", value=123, delta=123, delta_color="off"
215
+ ... label="Active developers",
216
+ ... value=123,
217
+ ... delta=123,
218
+ ... delta_color="off",
196
219
  ... )
197
220
 
198
221
  .. output::
@@ -218,6 +241,33 @@ class MetricMixin:
218
241
  https://doc-metric-example4.streamlit.app/
219
242
  height: 350px
220
243
 
244
+ **Example 5: Show sparklines**
245
+
246
+ To show trends over time, add sparklines.
247
+
248
+ >>> import streamlit as st
249
+ >>> from numpy.random import default_rng as rng
250
+ >>>
251
+ >>> changes = list(rng(4).standard_normal(20))
252
+ >>> data = [sum(changes[:i]) for i in range(20)]
253
+ >>> delta = round(data[-1], 2)
254
+ >>>
255
+ >>> row = st.container(horizontal=True)
256
+ >>> with row:
257
+ >>> st.metric(
258
+ ... "Line", 10, delta, chart_data=data, chart_type="line", border=True
259
+ ... )
260
+ >>> st.metric(
261
+ ... "Area", 10, delta, chart_data=data, chart_type="area", border=True
262
+ ... )
263
+ >>> st.metric(
264
+ ... "Bar", 10, delta, chart_data=data, chart_type="bar", border=True
265
+ ... )
266
+
267
+ .. output::
268
+ https://doc-metric-example5.streamlit.app/
269
+ height: 300px
270
+
221
271
  """
222
272
  maybe_raise_label_warnings(label, label_visibility)
223
273
 
@@ -238,6 +288,22 @@ class MetricMixin:
238
288
  label_visibility
239
289
  )
240
290
 
291
+ if chart_data is not None:
292
+ prepared_data: list[float] = []
293
+ for val in convert_anything_to_list(chart_data):
294
+ try:
295
+ prepared_data.append(float(val))
296
+ except Exception as ex: # noqa: PERF203
297
+ raise StreamlitAPIException(
298
+ "Only numeric values are supported for chart data sequence. The "
299
+ f"value '{val}' is of type {type(val)} and "
300
+ "cannot be converted to float."
301
+ ) from ex
302
+ if len(prepared_data) > 0:
303
+ metric_proto.chart_data.extend(prepared_data)
304
+
305
+ metric_proto.chart_type = _parse_chart_type(chart_type)
306
+
241
307
  validate_height(height, allow_content=True)
242
308
  validate_width(width, allow_content=True)
243
309
  layout_config = LayoutConfig(width=width, height=height)
@@ -249,6 +315,17 @@ class MetricMixin:
249
315
  return cast("DeltaGenerator", self)
250
316
 
251
317
 
318
+ def _parse_chart_type(
319
+ chart_type: Literal["line", "bar", "area"],
320
+ ) -> MetricProto.ChartType.ValueType:
321
+ if chart_type == "bar":
322
+ return MetricProto.ChartType.BAR
323
+ if chart_type == "area":
324
+ return MetricProto.ChartType.AREA
325
+ # Use line as default chart:
326
+ return MetricProto.ChartType.LINE
327
+
328
+
252
329
  def _parse_label(label: str) -> str:
253
330
  if not isinstance(label, str):
254
331
  raise TypeError(
@@ -0,0 +1,192 @@
1
+ # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import io
18
+ from pathlib import Path
19
+ from typing import TYPE_CHECKING, Any, Union, cast
20
+
21
+ from typing_extensions import TypeAlias
22
+
23
+ from streamlit import url_util
24
+ from streamlit.elements.lib.layout_utils import validate_height
25
+ from streamlit.errors import StreamlitAPIException
26
+ from streamlit.runtime.metrics_util import gather_metrics
27
+
28
+ if TYPE_CHECKING:
29
+ from streamlit.delta_generator import DeltaGenerator
30
+ from streamlit.elements.lib.layout_utils import HeightWithoutContent
31
+
32
+ PdfData: TypeAlias = Union[str, Path, bytes, io.BytesIO]
33
+
34
+
35
+ def _get_pdf_component() -> Any | None:
36
+ """Get the PDF custom component if available.
37
+
38
+ Returns
39
+ -------
40
+ Any | None
41
+ The pdf_viewer function if the streamlit-pdf component is available,
42
+ None otherwise.
43
+ """
44
+ try:
45
+ import streamlit_pdf # type: ignore
46
+
47
+ return streamlit_pdf.pdf_viewer
48
+ except ImportError:
49
+ return None
50
+
51
+
52
+ class PdfMixin:
53
+ @gather_metrics("pdf")
54
+ def pdf(
55
+ self,
56
+ data: PdfData,
57
+ *,
58
+ height: HeightWithoutContent = 500,
59
+ key: str | None = None,
60
+ ) -> DeltaGenerator:
61
+ """Display a PDF viewer.
62
+
63
+ .. Important::
64
+
65
+ You must install |streamlit-pdf|_ to use this command. You can
66
+ install it as an extra with Streamlit:
67
+
68
+ .. code-block:: shell
69
+
70
+ pip install streamlit[pdf]
71
+
72
+ .. |streamlit-pdf| replace:: ``streamlit-pdf``
73
+ .. _streamlit-pdf: https://github.com/streamlit/streamlit-pdf
74
+
75
+ Parameters
76
+ ----------
77
+ data : str, Path, BytesIO, or bytes
78
+ The PDF file to show. This can be one of the following:
79
+
80
+ - A URL (string) for a hosted PDF file.
81
+ - A path to a local PDF file. If you use a relative path, it must
82
+ be relative to the current working directory.
83
+ - A file-like object. For example, this can be an ``UploadedFile``
84
+ from ``st.file_uploader``, or this can be a local file opened
85
+ with ``open()``.
86
+ - Raw bytes data.
87
+
88
+ height : int or "stretch"
89
+ The height of the PDF viewer. This can be one of the following:
90
+
91
+ - An integer specifying the height in pixels: The viewer has a
92
+ fixed height. If the content is larger than the specified
93
+ height, scrolling is enabled. This is ``500`` by default.
94
+ - ``"stretch"``: The height of the viewer matches the height of
95
+ its content or the height of the parent container, whichever is
96
+ larger. If the viewer is not in a parent container, the height
97
+ of the viewer matches the height of its content.
98
+
99
+ Example
100
+ -------
101
+ >>> st.pdf("https://example.com/sample.pdf")
102
+ >>> st.pdf("https://example.com/sample.pdf", height=600)
103
+ """
104
+ # Validate data parameter early
105
+ if data is None:
106
+ raise StreamlitAPIException(
107
+ "The PDF data cannot be None. Please provide a valid PDF file path, URL, "
108
+ "bytes data, or file-like object."
109
+ )
110
+
111
+ # Check if custom PDF component is available first
112
+ pdf_component = _get_pdf_component()
113
+ if pdf_component is None:
114
+ return self._show_pdf_warning()
115
+
116
+ return self._call_pdf_component(pdf_component, data, height, key)
117
+
118
+ def _call_pdf_component(
119
+ self,
120
+ pdf_component: Any,
121
+ data: PdfData,
122
+ height: HeightWithoutContent,
123
+ key: str | None,
124
+ ) -> DeltaGenerator:
125
+ """Call the custom PDF component with the provided data."""
126
+ # Validate height parameter after confirming component is available
127
+ validate_height(height, allow_content=False)
128
+
129
+ # Convert data to the format expected by pdf_viewer component
130
+ file_param: str | bytes
131
+
132
+ if isinstance(data, (str, Path)):
133
+ data_str = str(data).strip() # Strip whitespace from URLs
134
+ if url_util.is_url(data_str, allowed_schemas=("http", "https")):
135
+ # It's a URL - pass directly
136
+ file_param = data_str
137
+ else:
138
+ # It's a local file path - read the content as bytes for security
139
+ try:
140
+ with open(data_str, "rb") as file:
141
+ file_param = file.read()
142
+ except (FileNotFoundError, PermissionError) as e:
143
+ raise StreamlitAPIException(
144
+ f"Unable to read file '{data_str}': {e}"
145
+ )
146
+
147
+ elif isinstance(data, bytes):
148
+ # Pass bytes directly - the component will handle uploading to media storage
149
+ file_param = data
150
+ elif hasattr(data, "read") and hasattr(data, "getvalue"):
151
+ # Handle BytesIO and similar
152
+ file_param = data.getvalue()
153
+ elif hasattr(data, "read"):
154
+ # Handle other file-like objects
155
+ file_param = data.read()
156
+ else:
157
+ # Provide a more helpful error message
158
+ raise StreamlitAPIException(
159
+ f"Unsupported data type for PDF: {type(data).__name__}. "
160
+ f"Please provide a file path (str or Path), URL (str), bytes data, "
161
+ f"or file-like object (such as BytesIO or UploadedFile)."
162
+ )
163
+
164
+ # Convert to component-compatible format
165
+ if height == "stretch":
166
+ # For stretch, we need to pass a special value the component understands
167
+ # This maintains compatibility with the component while using standard layout
168
+ component_height = "stretch"
169
+ else:
170
+ component_height = str(height)
171
+
172
+ result = pdf_component(
173
+ file=file_param,
174
+ height=component_height,
175
+ key=key,
176
+ )
177
+ return cast("DeltaGenerator", result)
178
+
179
+ def _show_pdf_warning(self) -> DeltaGenerator:
180
+ """Raise an exception that the PDF component is not available."""
181
+ raise StreamlitAPIException(
182
+ "The PDF viewer requires the `streamlit-pdf` component to be installed.\n\n"
183
+ "Please run `pip install streamlit[pdf]` to install it.\n\n"
184
+ "For more information, see the Streamlit PDF documentation at "
185
+ "https://docs.streamlit.io/develop/api-reference/media/st.pdf."
186
+ # TODO: Update this URL when docs are updated
187
+ )
188
+
189
+ @property
190
+ def dg(self) -> DeltaGenerator:
191
+ """Get our DeltaGenerator."""
192
+ return cast("DeltaGenerator", self)
@@ -333,7 +333,9 @@ class PlotlyMixin:
333
333
  can install all charting dependencies (except Bokeh) as an extra
334
334
  with Streamlit:
335
335
 
336
- >>> pip install streamlit[charts]
336
+ .. code-block:: shell
337
+
338
+ pip install streamlit[charts]
337
339
 
338
340
  Parameters
339
341
  ----------
@@ -556,7 +558,6 @@ class PlotlyMixin:
556
558
  plotly_chart_proto.id = compute_and_register_element_id(
557
559
  "plotly_chart",
558
560
  user_key=key,
559
- form_id=plotly_chart_proto.form_id,
560
561
  dg=self.dg,
561
562
  plotly_spec=plotly_chart_proto.spec,
562
563
  plotly_config=plotly_chart_proto.config,
@@ -19,8 +19,12 @@ from __future__ import annotations
19
19
  import io
20
20
  from typing import TYPE_CHECKING, Any, cast
21
21
 
22
- from streamlit.deprecation_util import show_deprecation_warning
23
- from streamlit.elements.lib.image_utils import WidthBehavior, marshall_images
22
+ from streamlit.deprecation_util import (
23
+ make_deprecated_name_warning,
24
+ show_deprecation_warning,
25
+ )
26
+ from streamlit.elements.lib.image_utils import marshall_images
27
+ from streamlit.elements.lib.layout_utils import LayoutConfig, Width, validate_width
24
28
  from streamlit.proto.Image_pb2 import ImageList as ImageListProto
25
29
  from streamlit.runtime.metrics_util import gather_metrics
26
30
 
@@ -36,7 +40,9 @@ class PyplotMixin:
36
40
  self,
37
41
  fig: Figure | None = None,
38
42
  clear_figure: bool | None = None,
39
- use_container_width: bool = True,
43
+ *,
44
+ width: Width = "stretch",
45
+ use_container_width: bool | None = None,
40
46
  **kwargs: Any,
41
47
  ) -> DeltaGenerator:
42
48
  """Display a matplotlib.pyplot figure.
@@ -46,7 +52,9 @@ class PyplotMixin:
46
52
  install all charting dependencies (except Bokeh) as an extra with
47
53
  Streamlit:
48
54
 
49
- >>> pip install streamlit[charts]
55
+ .. code-block:: shell
56
+
57
+ pip install streamlit[charts]
50
58
 
51
59
  Parameters
52
60
  ----------
@@ -69,6 +77,19 @@ class PyplotMixin:
69
77
  - If ``fig`` is not set, defaults to ``True``. This simulates Jupyter's
70
78
  approach to matplotlib rendering.
71
79
 
80
+ width : "stretch", "content", or int
81
+ The width of the chart element. This can be one of the following:
82
+
83
+ - ``"stretch"`` (default): The width of the element matches the
84
+ width of the parent container.
85
+ - ``"content"``: The width of the element matches the
86
+ width of its content, but doesn't exceed the width of the parent
87
+ container.
88
+ - An integer specifying the width in pixels: The element has a
89
+ fixed width. If the specified width is greater than the width of
90
+ the parent container, the width of the element matches the width
91
+ of the parent container.
92
+
72
93
  use_container_width : bool
73
94
  Whether to override the figure's native width with the width of
74
95
  the parent container. If ``use_container_width`` is ``True``
@@ -81,6 +102,12 @@ class PyplotMixin:
81
102
  **kwargs : any
82
103
  Arguments to pass to Matplotlib's savefig function.
83
104
 
105
+ .. deprecated::
106
+ ``use_container_width`` is deprecated and will be removed in a
107
+ future release. For ``use_container_width=True``, use
108
+ ``width="stretch"``. For ``use_container_width=False``, use
109
+ ``width="content"``.
110
+
84
111
  Example
85
112
  -------
86
113
  >>> import matplotlib.pyplot as plt
@@ -106,6 +133,21 @@ class PyplotMixin:
106
133
 
107
134
  """
108
135
 
136
+ if use_container_width is not None:
137
+ show_deprecation_warning(
138
+ make_deprecated_name_warning(
139
+ "use_container_width",
140
+ "width",
141
+ "2025-12-31",
142
+ "For `use_container_width=True`, use `width='stretch'`. "
143
+ "For `use_container_width=False`, use `width='content'`.",
144
+ include_st_prefix=False,
145
+ ),
146
+ show_in_browser=False,
147
+ )
148
+
149
+ width = "stretch" if use_container_width else "content"
150
+
109
151
  if not fig:
110
152
  show_deprecation_warning("""
111
153
  Calling `st.pyplot()` without providing a figure argument has been deprecated
@@ -125,16 +167,19 @@ If you have a specific use case that requires this functionality, please let us
125
167
  know via [issue on Github](https://github.com/streamlit/streamlit/issues).
126
168
  """)
127
169
 
170
+ validate_width(width, allow_content=True)
171
+ layout_config = LayoutConfig(width=width)
172
+
128
173
  image_list_proto = ImageListProto()
129
174
  marshall(
130
175
  self.dg._get_delta_path_str(),
131
176
  image_list_proto,
177
+ layout_config,
132
178
  fig,
133
179
  clear_figure,
134
- use_container_width,
135
180
  **kwargs,
136
181
  )
137
- return self.dg._enqueue("imgs", image_list_proto)
182
+ return self.dg._enqueue("imgs", image_list_proto, layout_config=layout_config)
138
183
 
139
184
  @property
140
185
  def dg(self) -> DeltaGenerator:
@@ -145,9 +190,9 @@ know via [issue on Github](https://github.com/streamlit/streamlit/issues).
145
190
  def marshall(
146
191
  coordinates: str,
147
192
  image_list_proto: ImageListProto,
193
+ layout_config: LayoutConfig,
148
194
  fig: Figure | None = None,
149
195
  clear_figure: bool | None = True,
150
- use_container_width: bool = True,
151
196
  **kwargs: Any,
152
197
  ) -> None:
153
198
  try:
@@ -178,14 +223,11 @@ def marshall(
178
223
 
179
224
  image = io.BytesIO()
180
225
  fig.savefig(image, **kwargs)
181
- image_width = (
182
- WidthBehavior.COLUMN if use_container_width else WidthBehavior.ORIGINAL
183
- )
184
226
  marshall_images(
185
227
  coordinates=coordinates,
186
228
  image=image,
187
229
  caption=None,
188
- width=image_width,
230
+ layout_config=layout_config,
189
231
  proto_imgs=image_list_proto,
190
232
  clamp=False,
191
233
  channels="RGB",