streamlit 1.50.0__py3-none-any.whl → 1.52.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 (406) hide show
  1. streamlit/__init__.py +5 -1
  2. streamlit/commands/execution_control.py +89 -14
  3. streamlit/commands/navigation.py +4 -6
  4. streamlit/commands/page_config.py +4 -6
  5. streamlit/components/v1/component_arrow.py +7 -7
  6. streamlit/components/v2/__init__.py +514 -0
  7. streamlit/components/v2/bidi_component/__init__.py +20 -0
  8. streamlit/components/v2/bidi_component/constants.py +29 -0
  9. streamlit/components/v2/bidi_component/main.py +534 -0
  10. streamlit/components/v2/bidi_component/serialization.py +272 -0
  11. streamlit/components/v2/bidi_component/state.py +92 -0
  12. streamlit/components/v2/component_definition_resolver.py +143 -0
  13. streamlit/components/v2/component_file_watcher.py +403 -0
  14. streamlit/components/v2/component_manager.py +439 -0
  15. streamlit/components/v2/component_manifest_handler.py +122 -0
  16. streamlit/components/v2/component_path_utils.py +245 -0
  17. streamlit/components/v2/component_registry.py +426 -0
  18. streamlit/components/v2/get_bidi_component_manager.py +51 -0
  19. streamlit/components/v2/manifest_scanner.py +615 -0
  20. streamlit/components/v2/presentation.py +198 -0
  21. streamlit/components/v2/types.py +324 -0
  22. streamlit/config.py +456 -53
  23. streamlit/config_option.py +4 -1
  24. streamlit/config_util.py +650 -1
  25. streamlit/connections/snowflake_connection.py +1 -1
  26. streamlit/connections/snowpark_connection.py +1 -1
  27. streamlit/dataframe_util.py +33 -26
  28. streamlit/delta_generator.py +13 -4
  29. streamlit/delta_generator_singletons.py +11 -15
  30. streamlit/deprecation_util.py +17 -6
  31. streamlit/elements/alert.py +16 -0
  32. streamlit/elements/arrow.py +68 -10
  33. streamlit/elements/bokeh_chart.py +10 -78
  34. streamlit/elements/code.py +2 -2
  35. streamlit/elements/deck_gl_json_chart.py +98 -40
  36. streamlit/elements/dialog_decorator.py +2 -1
  37. streamlit/elements/exception.py +4 -2
  38. streamlit/elements/form.py +27 -0
  39. streamlit/elements/graphviz_chart.py +1 -3
  40. streamlit/elements/heading.py +63 -10
  41. streamlit/elements/html.py +13 -2
  42. streamlit/elements/image.py +3 -5
  43. streamlit/elements/layouts.py +59 -33
  44. streamlit/elements/lib/built_in_chart_utils.py +50 -19
  45. streamlit/elements/lib/color_util.py +9 -19
  46. streamlit/elements/lib/column_config_utils.py +9 -12
  47. streamlit/elements/lib/column_types.py +40 -12
  48. streamlit/elements/lib/dialog.py +2 -2
  49. streamlit/elements/lib/image_utils.py +3 -5
  50. streamlit/elements/lib/layout_utils.py +100 -13
  51. streamlit/elements/lib/mutable_status_container.py +2 -2
  52. streamlit/elements/lib/options_selector_utils.py +2 -2
  53. streamlit/elements/lib/pandas_styler_utils.py +17 -9
  54. streamlit/elements/lib/shortcut_utils.py +152 -0
  55. streamlit/elements/lib/utils.py +4 -4
  56. streamlit/elements/map.py +80 -37
  57. streamlit/elements/markdown.py +50 -3
  58. streamlit/elements/media.py +5 -7
  59. streamlit/elements/metric.py +34 -6
  60. streamlit/elements/pdf.py +2 -4
  61. streamlit/elements/plotly_chart.py +197 -20
  62. streamlit/elements/progress.py +2 -4
  63. streamlit/elements/space.py +113 -0
  64. streamlit/elements/spinner.py +1 -1
  65. streamlit/elements/text.py +20 -3
  66. streamlit/elements/toast.py +2 -0
  67. streamlit/elements/vega_charts.py +356 -149
  68. streamlit/elements/widgets/audio_input.py +12 -11
  69. streamlit/elements/widgets/button.py +280 -43
  70. streamlit/elements/widgets/button_group.py +60 -9
  71. streamlit/elements/widgets/camera_input.py +3 -5
  72. streamlit/elements/widgets/chat.py +307 -43
  73. streamlit/elements/widgets/color_picker.py +8 -1
  74. streamlit/elements/widgets/data_editor.py +88 -44
  75. streamlit/elements/widgets/file_uploader.py +9 -11
  76. streamlit/elements/widgets/multiselect.py +4 -3
  77. streamlit/elements/widgets/number_input.py +4 -4
  78. streamlit/elements/widgets/radio.py +10 -3
  79. streamlit/elements/widgets/select_slider.py +8 -5
  80. streamlit/elements/widgets/selectbox.py +6 -3
  81. streamlit/elements/widgets/slider.py +38 -42
  82. streamlit/elements/widgets/text_widgets.py +2 -0
  83. streamlit/elements/widgets/time_widgets.py +587 -21
  84. streamlit/elements/write.py +27 -6
  85. streamlit/emojis.py +1 -1
  86. streamlit/errors.py +137 -0
  87. streamlit/git_util.py +1 -1
  88. streamlit/hello/hello.py +8 -0
  89. streamlit/hello/utils.py +2 -1
  90. streamlit/material_icon_names.py +1 -1
  91. streamlit/navigation/page.py +11 -1
  92. streamlit/net_util.py +2 -2
  93. streamlit/proto/Alert_pb2.pyi +3 -3
  94. streamlit/proto/AppPage_pb2.pyi +7 -1
  95. streamlit/proto/ArrowData_pb2.py +27 -0
  96. streamlit/proto/ArrowData_pb2.pyi +52 -0
  97. streamlit/proto/ArrowNamedDataSet_pb2.pyi +7 -1
  98. streamlit/proto/ArrowVegaLiteChart_pb2.pyi +7 -1
  99. streamlit/proto/Arrow_pb2.py +10 -10
  100. streamlit/proto/Arrow_pb2.pyi +19 -12
  101. streamlit/proto/AudioInput_pb2.pyi +7 -1
  102. streamlit/proto/Audio_pb2.pyi +7 -1
  103. streamlit/proto/AuthRedirect_pb2.pyi +7 -1
  104. streamlit/proto/AutoRerun_pb2.pyi +7 -1
  105. streamlit/proto/BackMsg_pb2.py +4 -2
  106. streamlit/proto/BackMsg_pb2.pyi +34 -4
  107. streamlit/proto/Balloons_pb2.pyi +7 -1
  108. streamlit/proto/BidiComponent_pb2.py +34 -0
  109. streamlit/proto/BidiComponent_pb2.pyi +159 -0
  110. streamlit/proto/Block_pb2.py +7 -7
  111. streamlit/proto/Block_pb2.pyi +39 -36
  112. streamlit/proto/BokehChart_pb2.pyi +7 -1
  113. streamlit/proto/ButtonGroup_pb2.pyi +9 -9
  114. streamlit/proto/Button_pb2.py +2 -2
  115. streamlit/proto/Button_pb2.pyi +11 -2
  116. streamlit/proto/CameraInput_pb2.pyi +7 -1
  117. streamlit/proto/ChatInput_pb2.py +6 -6
  118. streamlit/proto/ChatInput_pb2.pyi +18 -6
  119. streamlit/proto/Checkbox_pb2.pyi +3 -3
  120. streamlit/proto/ClientState_pb2.pyi +10 -4
  121. streamlit/proto/Code_pb2.pyi +7 -1
  122. streamlit/proto/ColorPicker_pb2.pyi +7 -1
  123. streamlit/proto/Common_pb2.py +3 -3
  124. streamlit/proto/Common_pb2.pyi +35 -23
  125. streamlit/proto/Components_pb2.pyi +19 -13
  126. streamlit/proto/DataFrame_pb2.pyi +55 -49
  127. streamlit/proto/DateInput_pb2.pyi +7 -1
  128. streamlit/proto/DateTimeInput_pb2.py +28 -0
  129. streamlit/proto/DateTimeInput_pb2.pyi +92 -0
  130. streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
  131. streamlit/proto/DeckGlJsonChart_pb2.pyi +12 -6
  132. streamlit/proto/Delta_pb2.pyi +7 -1
  133. streamlit/proto/DocString_pb2.pyi +10 -4
  134. streamlit/proto/DownloadButton_pb2.py +2 -2
  135. streamlit/proto/DownloadButton_pb2.pyi +16 -2
  136. streamlit/proto/Element_pb2.py +7 -3
  137. streamlit/proto/Element_pb2.pyi +33 -5
  138. streamlit/proto/Empty_pb2.pyi +7 -1
  139. streamlit/proto/Exception_pb2.pyi +7 -1
  140. streamlit/proto/Favicon_pb2.pyi +7 -1
  141. streamlit/proto/FileUploader_pb2.pyi +7 -1
  142. streamlit/proto/ForwardMsg_pb2.py +12 -10
  143. streamlit/proto/ForwardMsg_pb2.pyi +42 -15
  144. streamlit/proto/GapSize_pb2.pyi +4 -4
  145. streamlit/proto/GitInfo_pb2.pyi +3 -3
  146. streamlit/proto/GraphVizChart_pb2.pyi +7 -1
  147. streamlit/proto/Heading_pb2.pyi +7 -1
  148. streamlit/proto/HeightConfig_pb2.py +2 -2
  149. streamlit/proto/HeightConfig_pb2.pyi +13 -4
  150. streamlit/proto/Html_pb2.py +2 -2
  151. streamlit/proto/Html_pb2.pyi +11 -2
  152. streamlit/proto/IFrame_pb2.pyi +7 -1
  153. streamlit/proto/Image_pb2.pyi +10 -4
  154. streamlit/proto/Json_pb2.pyi +7 -1
  155. streamlit/proto/LabelVisibilityMessage_pb2.pyi +3 -3
  156. streamlit/proto/LinkButton_pb2.py +2 -2
  157. streamlit/proto/LinkButton_pb2.pyi +15 -2
  158. streamlit/proto/Logo_pb2.pyi +7 -1
  159. streamlit/proto/Markdown_pb2.pyi +3 -3
  160. streamlit/proto/Metric_pb2.pyi +7 -7
  161. streamlit/proto/MetricsEvent_pb2.pyi +10 -4
  162. streamlit/proto/MultiSelect_pb2.pyi +7 -1
  163. streamlit/proto/NamedDataSet_pb2.pyi +7 -1
  164. streamlit/proto/Navigation_pb2.pyi +3 -3
  165. streamlit/proto/NewSession_pb2.py +18 -18
  166. streamlit/proto/NewSession_pb2.pyi +59 -40
  167. streamlit/proto/NumberInput_pb2.pyi +3 -3
  168. streamlit/proto/PageConfig_pb2.pyi +7 -7
  169. streamlit/proto/PageInfo_pb2.pyi +7 -1
  170. streamlit/proto/PageLink_pb2.py +2 -2
  171. streamlit/proto/PageLink_pb2.pyi +11 -2
  172. streamlit/proto/PageNotFound_pb2.pyi +7 -1
  173. streamlit/proto/PageProfile_pb2.pyi +13 -7
  174. streamlit/proto/PagesChanged_pb2.pyi +7 -1
  175. streamlit/proto/ParentMessage_pb2.pyi +7 -1
  176. streamlit/proto/PlotlyChart_pb2.py +8 -6
  177. streamlit/proto/PlotlyChart_pb2.pyi +9 -7
  178. streamlit/proto/Progress_pb2.pyi +7 -1
  179. streamlit/proto/Radio_pb2.pyi +7 -1
  180. streamlit/proto/RootContainer_pb2.pyi +1 -1
  181. streamlit/proto/Selectbox_pb2.pyi +7 -1
  182. streamlit/proto/SessionEvent_pb2.pyi +7 -1
  183. streamlit/proto/SessionStatus_pb2.pyi +7 -1
  184. streamlit/proto/Skeleton_pb2.pyi +3 -3
  185. streamlit/proto/Slider_pb2.pyi +5 -5
  186. streamlit/proto/Snow_pb2.pyi +7 -1
  187. streamlit/proto/Space_pb2.py +27 -0
  188. streamlit/proto/Space_pb2.pyi +48 -0
  189. streamlit/proto/Spinner_pb2.pyi +7 -1
  190. streamlit/proto/TextAlignmentConfig_pb2.py +29 -0
  191. streamlit/proto/TextAlignmentConfig_pb2.pyi +68 -0
  192. streamlit/proto/TextArea_pb2.pyi +7 -1
  193. streamlit/proto/TextInput_pb2.pyi +3 -3
  194. streamlit/proto/Text_pb2.pyi +7 -1
  195. streamlit/proto/TimeInput_pb2.pyi +7 -1
  196. streamlit/proto/Toast_pb2.pyi +7 -1
  197. streamlit/proto/VegaLiteChart_pb2.pyi +7 -1
  198. streamlit/proto/Video_pb2.pyi +6 -6
  199. streamlit/proto/WidgetStates_pb2.py +2 -2
  200. streamlit/proto/WidgetStates_pb2.pyi +23 -7
  201. streamlit/proto/WidthConfig_pb2.py +2 -2
  202. streamlit/proto/WidthConfig_pb2.pyi +13 -4
  203. streamlit/proto/openmetrics_data_model_pb2.pyi +52 -52
  204. streamlit/runtime/app_session.py +65 -2
  205. streamlit/runtime/caching/cache_data_api.py +5 -5
  206. streamlit/runtime/caching/cache_errors.py +4 -1
  207. streamlit/runtime/caching/cache_resource_api.py +5 -4
  208. streamlit/runtime/caching/cache_utils.py +3 -2
  209. streamlit/runtime/caching/cached_message_replay.py +3 -3
  210. streamlit/runtime/caching/hashing.py +4 -5
  211. streamlit/runtime/caching/legacy_cache_api.py +2 -1
  212. streamlit/runtime/connection_factory.py +1 -3
  213. streamlit/runtime/download_data_util.py +53 -0
  214. streamlit/runtime/forward_msg_queue.py +5 -1
  215. streamlit/runtime/fragment.py +2 -1
  216. streamlit/runtime/media_file_manager.py +178 -2
  217. streamlit/runtime/memory_media_file_storage.py +1 -1
  218. streamlit/runtime/metrics_util.py +91 -3
  219. streamlit/runtime/runtime.py +14 -0
  220. streamlit/runtime/scriptrunner/exec_code.py +2 -1
  221. streamlit/runtime/scriptrunner/script_runner.py +5 -3
  222. streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
  223. streamlit/runtime/secrets.py +2 -4
  224. streamlit/runtime/session_manager.py +3 -1
  225. streamlit/runtime/state/common.py +30 -5
  226. streamlit/runtime/state/presentation.py +85 -0
  227. streamlit/runtime/state/query_params.py +80 -29
  228. streamlit/runtime/state/safe_session_state.py +2 -2
  229. streamlit/runtime/state/session_state.py +221 -17
  230. streamlit/runtime/state/widgets.py +19 -3
  231. streamlit/runtime/websocket_session_manager.py +3 -1
  232. streamlit/source_util.py +2 -2
  233. streamlit/static/index.html +2 -2
  234. streamlit/static/manifest.json +557 -239
  235. streamlit/static/static/css/{index.CIiu7Ygf.css → index.BpABIXK9.css} +1 -1
  236. streamlit/static/static/css/index.DgR7E2CV.css +1 -0
  237. streamlit/static/static/js/{ErrorOutline.esm.DUpR0_Ka.js → ErrorOutline.esm.ZJDbmVTx.js} +1 -1
  238. streamlit/static/static/js/{FileDownload.esm.CN4j9-1w.js → FileDownload.esm.Dx0vI3vH.js} +1 -1
  239. streamlit/static/static/js/{FileHelper.CaIUKG91.js → FileHelper.B7Ero7qQ.js} +3 -3
  240. streamlit/static/static/js/{FormClearHelper.DTcdrasw.js → FormClearHelper.CG2XN1_g.js} +1 -1
  241. streamlit/static/static/js/IFrameUtil.DefezniK.js +1 -0
  242. streamlit/static/static/js/InputInstructions.Cj5-1zf6.js +1 -0
  243. streamlit/static/static/js/Particles.BfWfv0Aw.js +1 -0
  244. streamlit/static/static/js/{ProgressBar.DetlP5aY.js → ProgressBar.CGQ8OgfO.js} +2 -2
  245. streamlit/static/static/js/StreamlitSyntaxHighlighter.DTKLpwhl.js +20 -0
  246. streamlit/static/static/js/{Toolbar.C77ar7rq.js → Toolbar.B2qFUmd9.js} +1 -1
  247. streamlit/static/static/js/_arrayIncludes.B19Iyn2B.js +1 -0
  248. streamlit/static/static/js/_baseIndexOf.BTknn6Gb.js +1 -0
  249. streamlit/static/static/js/{base-input.BQft14La.js → base-input.o9tL8MDP.js} +4 -4
  250. streamlit/static/static/js/{checkbox.yZOfXCeX.js → checkbox.0BeV1IBL.js} +1 -1
  251. streamlit/static/static/js/{createSuper.Dh9w1cs8.js → createSuper.RBO59fEm.js} +1 -1
  252. streamlit/static/static/js/data-grid-overlay-editor.CiTkUy0t.js +1 -0
  253. streamlit/static/static/js/{downloader.MeHtkq8r.js → downloader.DwNZg3Mw.js} +1 -1
  254. streamlit/static/static/js/embed.XT9xNd3F.js +195 -0
  255. streamlit/static/static/js/{es6.VpBPGCnM.js → es6.x9KsYQg-.js} +2 -2
  256. streamlit/static/static/js/{iframeResizer.contentWindow.yMw_ARIL.js → iframeResizer.contentWindow.ZVXpMPi0.js} +1 -1
  257. streamlit/static/static/js/index.5VPOamri.js +1 -0
  258. streamlit/static/static/js/index.8HslT92O.js +14 -0
  259. streamlit/static/static/js/index.AnXMIBz3.js +7 -0
  260. streamlit/static/static/js/index.B0yp3bM1.js +6 -0
  261. streamlit/static/static/js/index.B1fRb5wF.js +1 -0
  262. streamlit/static/static/js/index.B527JZdO.js +3 -0
  263. streamlit/static/static/js/index.BHgV-yW4.js +1 -0
  264. streamlit/static/static/js/index.BQr-XwGV.js +1 -0
  265. streamlit/static/static/js/index.BTtmaLDB.js +1 -0
  266. streamlit/static/static/js/index.BWB_91TA.js +1 -0
  267. streamlit/static/static/js/index.BfEKaEmw.js +1 -0
  268. streamlit/static/static/js/index.BfXjTO8b.js +1 -0
  269. streamlit/static/static/js/index.Bjy4NRu9.js +3 -0
  270. streamlit/static/static/js/index.Bu5JWpT_.js +1 -0
  271. streamlit/static/static/js/index.BuCx76ZV.js +1 -0
  272. streamlit/static/static/js/index.BxjzhVUb.js +2 -0
  273. streamlit/static/static/js/index.By55VdPY.js +1 -0
  274. streamlit/static/static/js/index.CF5MxTbK.js +1 -0
  275. streamlit/static/static/js/index.CLmq_z9K.js +1 -0
  276. streamlit/static/static/js/index.CNH4rdSz.js +1 -0
  277. streamlit/static/static/js/{index.B0H9IXUJ.js → index.CTgm_-jO.js} +10 -41
  278. streamlit/static/static/js/index.C_rK-Swb.js +188 -0
  279. streamlit/static/static/js/index.CjozwSzS.js +1 -0
  280. streamlit/static/static/js/{index.CH1tqnSs.js → index.CkGVt6-G.js} +1 -1
  281. streamlit/static/static/js/index.CuvXOyER.js +2 -0
  282. streamlit/static/static/js/{index.FFOzOWzC.js → index.CyUHWoCC.js} +2 -2
  283. streamlit/static/static/js/index.CyroQtI4.js +2 -0
  284. streamlit/static/static/js/index.D6HmkoDm.js +263 -0
  285. streamlit/static/static/js/index.DAqCNvsO.js +1 -0
  286. streamlit/static/static/js/index.DB_w_CZQ.js +1 -0
  287. streamlit/static/static/js/index.DBalctjj.js +2 -0
  288. streamlit/static/static/js/index.DK0RFJUG.js +11 -0
  289. streamlit/static/static/js/index.DMxc2XFp.js +151 -0
  290. streamlit/static/static/js/index.DO5utP74.js +2 -0
  291. streamlit/static/static/js/index.DS7lf09n.js +1 -0
  292. streamlit/static/static/js/index.DWexTVLY.js +1 -0
  293. streamlit/static/static/js/index.DXxnU5ej.js +1 -0
  294. streamlit/static/static/js/index.DcU3uDvB.js +2 -0
  295. streamlit/static/static/js/index.DlltaH7J.js +1 -0
  296. streamlit/static/static/js/index.DpNTZz82.js +27 -0
  297. streamlit/static/static/js/index.Dr9HIhQw.js +1 -0
  298. streamlit/static/static/js/index.DsgAU5lc.js +1 -0
  299. streamlit/static/static/js/{index.64ejlaaT.js → index.KfXqjDYy.js} +1 -1
  300. streamlit/static/static/js/index.PaidgjCs.js +1 -0
  301. streamlit/static/static/js/index.RJZuWCGA.js +1 -0
  302. streamlit/static/static/js/{index.Ctn27_AE.js → index.hbeqcRTn.js} +53 -122
  303. streamlit/static/static/js/index.q5hIQwAY.js +1 -0
  304. streamlit/static/static/js/index.rORSX6IW.js +1 -0
  305. streamlit/static/static/js/index.uSX757_v.js +1 -0
  306. streamlit/static/static/js/index.x_QRaLMd.js +1 -0
  307. streamlit/static/static/js/{input.s6pjQ49A.js → input.D5oh9-aB.js} +2 -2
  308. streamlit/static/static/js/main.q9oGOg0H.js +13 -0
  309. streamlit/static/static/js/{memory.Cuvsdfrl.js → memory.5kCSFUJS.js} +1 -1
  310. streamlit/static/static/js/moment.C3j7ZXd7.js +4 -0
  311. streamlit/static/static/js/number-overlay-editor.Cn_LsK8N.js +9 -0
  312. streamlit/static/static/js/pandasStylerUtils.BqhXt51_.js +1 -0
  313. streamlit/static/static/js/{possibleConstructorReturn.CqidKeei.js → possibleConstructorReturn.DD9NK1Z8.js} +1 -1
  314. streamlit/static/static/js/record.B-tDciZb.js +1 -0
  315. streamlit/static/static/js/{sandbox.CCQREcJx.js → sandbox.DACSyz29.js} +1 -1
  316. streamlit/static/static/js/styled-components.C3R090At.js +1 -0
  317. streamlit/static/static/js/threshold.Q1mXg5rX.js +1 -0
  318. streamlit/static/static/js/throttle.B0GR3Iyz.js +1 -0
  319. streamlit/static/static/js/{timepicker.mkJF97Bb.js → timepicker.BdhzPxrv.js} +1 -1
  320. streamlit/static/static/js/timer.C2hYhUse.js +1 -0
  321. streamlit/static/static/js/{toConsumableArray.De7I7KVR.js → toConsumableArray.Db2pdqM2.js} +1 -1
  322. streamlit/static/static/js/uniqueId.CtqIr-Yh.js +1 -0
  323. streamlit/static/static/js/urls.BwSlolu9.js +1 -0
  324. streamlit/static/static/js/{useBasicWidgetState.CedkNjUW.js → useBasicWidgetState.Bfp6TnSw.js} +1 -1
  325. streamlit/static/static/js/useIntlLocale.hRV75Xgj.js +12 -0
  326. streamlit/static/static/js/{useTextInputAutoExpand.Ca7w8dVs.js → useTextInputAutoExpand.QepX7n8Y.js} +1 -1
  327. streamlit/static/static/js/useUpdateUiValue.DHx8TzX6.js +1 -0
  328. streamlit/static/static/js/useWaveformController.WxVzpzEX.js +1 -0
  329. streamlit/static/static/js/value.B4vHRSi7.js +1 -0
  330. streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
  331. streamlit/static/static/js/withCalculatedWidth.DcKeRSWJ.js +1 -0
  332. streamlit/static/static/js/withFullScreenWrapper.CrHddARq.js +1 -0
  333. streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
  334. streamlit/string_util.py +9 -4
  335. streamlit/testing/v1/app_test.py +17 -2
  336. streamlit/testing/v1/element_tree.py +85 -9
  337. streamlit/testing/v1/util.py +2 -2
  338. streamlit/type_util.py +3 -4
  339. streamlit/url_util.py +1 -3
  340. streamlit/user_info.py +1 -2
  341. streamlit/util.py +3 -1
  342. streamlit/watcher/event_based_path_watcher.py +23 -12
  343. streamlit/watcher/local_sources_watcher.py +11 -1
  344. streamlit/watcher/path_watcher.py +9 -6
  345. streamlit/watcher/polling_path_watcher.py +4 -1
  346. streamlit/watcher/util.py +2 -2
  347. streamlit/web/bootstrap.py +24 -0
  348. streamlit/web/cli.py +51 -22
  349. streamlit/web/server/bidi_component_request_handler.py +193 -0
  350. streamlit/web/server/component_file_utils.py +97 -0
  351. streamlit/web/server/component_request_handler.py +8 -21
  352. streamlit/web/server/oauth_authlib_routes.py +5 -2
  353. streamlit/web/server/oidc_mixin.py +3 -1
  354. streamlit/web/server/routes.py +2 -2
  355. streamlit/web/server/server.py +9 -0
  356. streamlit/web/server/server_util.py +3 -1
  357. streamlit/web/server/upload_file_request_handler.py +19 -1
  358. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/METADATA +10 -7
  359. streamlit-1.52.0.dist-info/RECORD +620 -0
  360. streamlit/static/static/css/index.CHEnSPGk.css +0 -1
  361. streamlit/static/static/js/Hooks.BRba_Own.js +0 -1
  362. streamlit/static/static/js/InputInstructions.xnSDuYeQ.js +0 -1
  363. streamlit/static/static/js/Particles.CElH0XX2.js +0 -1
  364. streamlit/static/static/js/data-grid-overlay-editor.DcuHuCyW.js +0 -1
  365. streamlit/static/static/js/index.6xX1278W.js +0 -975
  366. streamlit/static/static/js/index.B-hiXRzw.js +0 -1
  367. streamlit/static/static/js/index.B4cAbHP6.js +0 -1
  368. streamlit/static/static/js/index.B4dUQfni.js +0 -1
  369. streamlit/static/static/js/index.BPQo7BKk.js +0 -1
  370. streamlit/static/static/js/index.Baqa90pe.js +0 -2
  371. streamlit/static/static/js/index.Bj9JgOEC.js +0 -1
  372. streamlit/static/static/js/index.BjCwMzj4.js +0 -3
  373. streamlit/static/static/js/index.Bm3VbPB5.js +0 -1
  374. streamlit/static/static/js/index.Bxz2yX3P.js +0 -1
  375. streamlit/static/static/js/index.BycLveZ4.js +0 -1
  376. streamlit/static/static/js/index.C9BdUqTi.js +0 -1
  377. streamlit/static/static/js/index.CFMf5_ez.js +0 -197
  378. streamlit/static/static/js/index.CGYqqs6j.js +0 -1
  379. streamlit/static/static/js/index.CMItVsFA.js +0 -1
  380. streamlit/static/static/js/index.CTBk8Vk2.js +0 -1
  381. streamlit/static/static/js/index.CiAQIz1H.js +0 -7
  382. streamlit/static/static/js/index.Cj7DSzVR.js +0 -73
  383. streamlit/static/static/js/index.Ck8rQ9OL.js +0 -1
  384. streamlit/static/static/js/index.ClELlchS.js +0 -1617
  385. streamlit/static/static/js/index.Cnpi3o3E.js +0 -1
  386. streamlit/static/static/js/index.D2QEXQq_.js +0 -1
  387. streamlit/static/static/js/index.DH71Ezyj.js +0 -1
  388. streamlit/static/static/js/index.DHh-U0dK.js +0 -3
  389. streamlit/static/static/js/index.DK7hD7_w.js +0 -1
  390. streamlit/static/static/js/index.DKv_lNO7.js +0 -2
  391. streamlit/static/static/js/index.DNLrMXgm.js +0 -12
  392. streamlit/static/static/js/index.DW0Grddz.js +0 -1
  393. streamlit/static/static/js/index.Dbe-Q3C-.js +0 -2
  394. streamlit/static/static/js/index.DcPNYEUo.js +0 -1
  395. streamlit/static/static/js/index.DuxqVQpd.js +0 -1
  396. streamlit/static/static/js/index.GRUzrudl.js +0 -1
  397. streamlit/static/static/js/number-overlay-editor.DdgVR5m3.js +0 -9
  398. streamlit/static/static/js/uniqueId.RI1LJdtz.js +0 -1
  399. streamlit/static/static/js/useUpdateUiValue.DeXelfRH.js +0 -1
  400. streamlit/static/static/js/withFullScreenWrapper.C3561XxJ.js +0 -1
  401. streamlit/static/static/media/MaterialSymbols-Rounded.DeCZgS-4.woff2 +0 -0
  402. streamlit-1.50.0.dist-info/RECORD +0 -557
  403. {streamlit-1.50.0.data → streamlit-1.52.0.data}/scripts/streamlit.cmd +0 -0
  404. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/WHEEL +0 -0
  405. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/entry_points.txt +0 -0
  406. {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/top_level.txt +0 -0
@@ -42,6 +42,7 @@ class HtmlMixin:
42
42
  body: str | Path | SupportsStr | SupportsReprHtml,
43
43
  *, # keyword-only arguments:
44
44
  width: Width = "stretch",
45
+ unsafe_allow_javascript: bool = False,
45
46
  ) -> DeltaGenerator:
46
47
  """Insert HTML into your app.
47
48
 
@@ -52,8 +53,10 @@ class HtmlMixin:
52
53
  loading external code can increase the risk of vulnerabilities in your
53
54
  app.
54
55
 
55
- ``st.html`` content is **not** iframed. Executing JavaScript is not
56
- supported at this time.
56
+ ``st.html`` content is **not** iframed. By default, JavaScript is
57
+ ignored. To execute JavaScript contained in your HTML, set
58
+ ``unsafe_allow_javascript=True``. Use this with caution and never pass
59
+ untrusted input.
57
60
 
58
61
  Parameters
59
62
  ----------
@@ -89,6 +92,12 @@ class HtmlMixin:
89
92
  the parent container, the width of the element matches the width
90
93
  of the parent container.
91
94
 
95
+ unsafe_allow_javascript : bool
96
+ Whether to execute JavaScript contained in your HTML. If this is
97
+ ``False`` (default), JavaScript is ignored. If this is ``True``,
98
+ JavaScript is executed. Use this with caution and never pass
99
+ untrusted input.
100
+
92
101
  Example
93
102
  -------
94
103
  >>> import streamlit as st
@@ -136,6 +145,8 @@ class HtmlMixin:
136
145
  html_proto.body = html_content
137
146
  return self._event_dg._enqueue("html", html_proto)
138
147
  # Otherwise, send the html to the main container as normal
148
+ # Only set the unsafe JS flag for non-style-only HTML content
149
+ html_proto.unsafe_allow_javascript = unsafe_allow_javascript
139
150
  html_proto.body = html_content
140
151
  return self.dg._enqueue("html", html_proto, layout_config=layout_config)
141
152
 
@@ -21,9 +21,7 @@
21
21
 
22
22
  from __future__ import annotations
23
23
 
24
- from typing import TYPE_CHECKING, Literal, Union, cast
25
-
26
- from typing_extensions import TypeAlias
24
+ from typing import TYPE_CHECKING, Literal, TypeAlias, cast
27
25
 
28
26
  from streamlit.deprecation_util import (
29
27
  make_deprecated_name_warning,
@@ -43,7 +41,7 @@ from streamlit.runtime.metrics_util import gather_metrics
43
41
  if TYPE_CHECKING:
44
42
  from streamlit.delta_generator import DeltaGenerator
45
43
 
46
- UseColumnWith: TypeAlias = Union[Literal["auto", "always", "never"], bool, None]
44
+ UseColumnWith: TypeAlias = Literal["auto", "always", "never"] | bool | None
47
45
 
48
46
 
49
47
  class ImageMixin:
@@ -173,7 +171,7 @@ class ImageMixin:
173
171
 
174
172
  show_deprecation_warning(
175
173
  "The `use_column_width` parameter has been deprecated and will be removed "
176
- "in a future release. Please utilize the `use_container_width` parameter instead."
174
+ "in a future release. Please utilize the `width` parameter instead."
177
175
  )
178
176
  if use_column_width in {"auto", "never"} or use_column_width is False:
179
177
  width = "content"
@@ -15,9 +15,7 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  from collections.abc import Sequence
18
- from typing import TYPE_CHECKING, Literal, Union, cast
19
-
20
- from typing_extensions import TypeAlias
18
+ from typing import TYPE_CHECKING, Literal, TypeAlias, cast
21
19
 
22
20
  from streamlit.delta_generator_singletons import get_dg_singleton_instance
23
21
  from streamlit.elements.lib.layout_utils import (
@@ -54,7 +52,7 @@ if TYPE_CHECKING:
54
52
  from streamlit.elements.lib.mutable_status_container import StatusContainer
55
53
  from streamlit.runtime.state import WidgetCallback
56
54
 
57
- SpecType: TypeAlias = Union[int, Sequence[Union[int, float]]]
55
+ SpecType: TypeAlias = int | Sequence[int | float]
58
56
 
59
57
 
60
58
  class LayoutsMixin:
@@ -64,7 +62,7 @@ class LayoutsMixin:
64
62
  *,
65
63
  border: bool | None = None,
66
64
  key: Key | None = None,
67
- width: WidthWithoutContent = "stretch",
65
+ width: Width = "stretch",
68
66
  height: Height = "content",
69
67
  horizontal: bool = False,
70
68
  horizontal_alignment: HorizontalAlignment = "left",
@@ -94,11 +92,13 @@ class LayoutsMixin:
94
92
  Additionally, if ``key`` is provided, it will be used as CSS
95
93
  class name prefixed with ``st-key-``.
96
94
 
97
- width : "stretch" or int
95
+ width : "stretch", "content", or int
98
96
  The width of the container. This can be one of the following:
99
97
 
100
98
  - ``"stretch"`` (default): The width of the container matches the
101
99
  width of the parent container.
100
+ - ``"content"``: The width of the container matches the width of
101
+ its content.
102
102
  - An integer specifying the width in pixels: The container has a
103
103
  fixed width. If the specified width is greater than the width of
104
104
  the parent container, the width of the container matches the width
@@ -201,7 +201,7 @@ class LayoutsMixin:
201
201
  >>>
202
202
  >>> st.write("This is outside the container")
203
203
 
204
- .. output ::
204
+ .. output::
205
205
  https://doc-container1.streamlit.app/
206
206
  height: 520px
207
207
 
@@ -220,7 +220,7 @@ class LayoutsMixin:
220
220
  >>>
221
221
  >>> container.write("This is inside too")
222
222
 
223
- .. output ::
223
+ .. output::
224
224
  https://doc-container2.streamlit.app/
225
225
  height: 300px
226
226
 
@@ -238,7 +238,7 @@ class LayoutsMixin:
238
238
  >>> tile = col.container(height=120)
239
239
  >>> tile.title(":balloon:")
240
240
 
241
- .. output ::
241
+ .. output::
242
242
  https://doc-container3.streamlit.app/
243
243
  height: 350px
244
244
 
@@ -254,7 +254,7 @@ class LayoutsMixin:
254
254
  >>> with st.container(height=300):
255
255
  >>> st.markdown(long_text)
256
256
 
257
- .. output ::
257
+ .. output::
258
258
  https://doc-container4.streamlit.app/
259
259
  height: 400px
260
260
 
@@ -270,7 +270,7 @@ class LayoutsMixin:
270
270
  >>> for card in range(3):
271
271
  >>> flex.button(f"Button {card + 1}")
272
272
 
273
- .. output ::
273
+ .. output::
274
274
  https://doc-container5.streamlit.app/
275
275
  height: 250px
276
276
 
@@ -300,7 +300,7 @@ class LayoutsMixin:
300
300
  block_proto.flex_container.justify = get_justify(vertical_alignment)
301
301
  block_proto.flex_container.align = get_align(horizontal_alignment)
302
302
 
303
- validate_width(width)
303
+ validate_width(width, allow_content=True)
304
304
  block_proto.width_config.CopyFrom(get_width_config(width))
305
305
 
306
306
  if isinstance(height, int) or border:
@@ -385,13 +385,15 @@ class LayoutsMixin:
385
385
  ``False`` (default), no border is shown. If this is ``True``, a
386
386
  border is shown around each column.
387
387
 
388
- width : int or "stretch"
389
- The desired width of the columns expressed in pixels. If this is
390
- ``"stretch"`` (default), Streamlit sets the width of the columns to
391
- match the width of the parent container. Otherwise, this must be an
392
- integer. If the specified width is greater than the width of the
393
- parent container, Streamlit sets the width of the columns to match
394
- the width of the parent container.
388
+ width : "stretch" or int
389
+ The width of the column group. This can be one of the following:
390
+
391
+ - ``"stretch"`` (default): The width of the column group matches the
392
+ width of the parent container.
393
+ - An integer specifying the width in pixels: The column group has a
394
+ fixed width. If the specified width is greater than the width of
395
+ the parent container, the width of the column group matches the
396
+ width of the parent container.
395
397
 
396
398
  Returns
397
399
  -------
@@ -420,7 +422,7 @@ class LayoutsMixin:
420
422
  ... st.header("An owl")
421
423
  ... st.image("https://static.streamlit.io/examples/owl.jpg")
422
424
 
423
- .. output ::
425
+ .. output::
424
426
  https://doc-columns1.streamlit.app/
425
427
  height: 620px
426
428
 
@@ -441,7 +443,7 @@ class LayoutsMixin:
441
443
  >>> col2.subheader("A narrow column with the data")
442
444
  >>> col2.write(df)
443
445
 
444
- .. output ::
446
+ .. output::
445
447
  https://doc-columns2.streamlit.app/
446
448
  height: 550px
447
449
 
@@ -457,7 +459,7 @@ class LayoutsMixin:
457
459
  >>> middle.button("Click me", use_container_width=True)
458
460
  >>> right.checkbox("Check me")
459
461
 
460
- .. output ::
462
+ .. output::
461
463
  https://doc-columns-bottom-widgets.streamlit.app/
462
464
  height: 200px
463
465
 
@@ -476,7 +478,7 @@ class LayoutsMixin:
476
478
  >>> middle.image("https://static.streamlit.io/examples/dog.jpg")
477
479
  >>> right.image("https://static.streamlit.io/examples/owl.jpg")
478
480
 
479
- .. output ::
481
+ .. output::
480
482
  https://doc-columns-vertical-alignment.streamlit.app/
481
483
  height: 600px
482
484
 
@@ -493,7 +495,7 @@ class LayoutsMixin:
493
495
  >>> middle.markdown("Lorem ipsum " * 5)
494
496
  >>> right.markdown("Lorem ipsum ")
495
497
 
496
- .. output ::
498
+ .. output::
497
499
  https://doc-columns-borders.streamlit.app/
498
500
  height: 250px
499
501
 
@@ -640,7 +642,7 @@ class LayoutsMixin:
640
642
  ... st.header("An owl")
641
643
  ... st.image("https://static.streamlit.io/examples/owl.jpg", width=200)
642
644
 
643
- .. output ::
645
+ .. output::
644
646
  https://doc-tabs1.streamlit.app/
645
647
  height: 620px
646
648
 
@@ -661,7 +663,7 @@ class LayoutsMixin:
661
663
  >>> tab2.subheader("A tab with the data")
662
664
  >>> tab2.write(df)
663
665
 
664
- .. output ::
666
+ .. output::
665
667
  https://doc-tabs2.streamlit.app/
666
668
  height: 700px
667
669
 
@@ -686,7 +688,7 @@ class LayoutsMixin:
686
688
  >>> st.header("An owl")
687
689
  >>> st.image("https://static.streamlit.io/examples/owl.jpg", width=200)
688
690
 
689
- .. output ::
691
+ .. output::
690
692
  https://doc-tabs3.streamlit.app/
691
693
  height: 620px
692
694
 
@@ -791,6 +793,8 @@ class LayoutsMixin:
791
793
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
792
794
  font library.
793
795
 
796
+ - ``"spinner"``: Displays a spinner as an icon.
797
+
794
798
  width : "stretch" or int
795
799
  The width of the expander container. This can be one of the following:
796
800
 
@@ -817,7 +821,7 @@ class LayoutsMixin:
817
821
  ... ''')
818
822
  ... st.image("https://static.streamlit.io/examples/dice.jpg")
819
823
 
820
- .. output ::
824
+ .. output::
821
825
  https://doc-expander.streamlit.app/
822
826
  height: 750px
823
827
 
@@ -835,7 +839,7 @@ class LayoutsMixin:
835
839
  ... ''')
836
840
  >>> expander.image("https://static.streamlit.io/examples/dice.jpg")
837
841
 
838
- .. output ::
842
+ .. output::
839
843
  https://doc-expander.streamlit.app/
840
844
  height: 750px
841
845
 
@@ -862,6 +866,7 @@ class LayoutsMixin:
862
866
  self,
863
867
  label: str,
864
868
  *,
869
+ type: Literal["primary", "secondary", "tertiary"] = "secondary",
865
870
  help: str | None = None,
866
871
  icon: str | None = None,
867
872
  disabled: bool = False,
@@ -912,6 +917,17 @@ class LayoutsMixin:
912
917
  including the Markdown directives described in the ``body``
913
918
  parameter of ``st.markdown``.
914
919
 
920
+ type : "primary", "secondary", or "tertiary"
921
+ An optional string that specifies the button type. This can be one
922
+ of the following:
923
+
924
+ - ``"primary"``: The button's background is the app's primary color
925
+ for additional emphasis.
926
+ - ``"secondary"`` (default): The button's background coordinates
927
+ with the app's background color for normal emphasis.
928
+ - ``"tertiary"``: The button is plain text without a border or
929
+ background for subtlety.
930
+
915
931
  icon : str
916
932
  An optional emoji or icon to display next to the button label. If ``icon``
917
933
  is ``None`` (default), no icon is displayed. If ``icon`` is a
@@ -929,6 +945,8 @@ class LayoutsMixin:
929
945
  <https://fonts.google.com/icons?icon.set=Material+Symbols&icon.style=Rounded>`_
930
946
  font library.
931
947
 
948
+ - ``"spinner"``: Displays a spinner as an icon.
949
+
932
950
  disabled : bool
933
951
  An optional boolean that disables the popover button if set to
934
952
  ``True``. The default is ``False``.
@@ -981,7 +999,7 @@ class LayoutsMixin:
981
999
  >>>
982
1000
  >>> st.write("Your name:", name)
983
1001
 
984
- .. output ::
1002
+ .. output::
985
1003
  https://doc-popover.streamlit.app/
986
1004
  height: 400px
987
1005
 
@@ -998,7 +1016,7 @@ class LayoutsMixin:
998
1016
  >>> if blue:
999
1017
  ... st.write(":blue[This is a blue item.]")
1000
1018
 
1001
- .. output ::
1019
+ .. output::
1002
1020
  https://doc-popover2.streamlit.app/
1003
1021
  height: 400px
1004
1022
 
@@ -1009,9 +1027,17 @@ class LayoutsMixin:
1009
1027
  if use_container_width is not None:
1010
1028
  width = "stretch" if use_container_width else "content"
1011
1029
 
1030
+ # Checks whether the entered button type is one of the allowed options
1031
+ if type not in ["primary", "secondary", "tertiary"]:
1032
+ raise StreamlitAPIException(
1033
+ 'The type argument to st.popover must be "primary", "secondary", or "tertiary". '
1034
+ f'\nThe argument passed was "{type}".'
1035
+ )
1036
+
1012
1037
  popover_proto = BlockProto.Popover()
1013
1038
  popover_proto.label = label
1014
1039
  popover_proto.disabled = disabled
1040
+ popover_proto.type = type
1015
1041
  if help:
1016
1042
  popover_proto.help = str(help)
1017
1043
  if icon is not None:
@@ -1122,7 +1148,7 @@ class LayoutsMixin:
1122
1148
  >>>
1123
1149
  >>> st.button("Rerun")
1124
1150
 
1125
- .. output ::
1151
+ .. output::
1126
1152
  https://doc-status.streamlit.app/
1127
1153
  height: 300px
1128
1154
 
@@ -1145,7 +1171,7 @@ class LayoutsMixin:
1145
1171
  >>>
1146
1172
  >>> st.button("Rerun")
1147
1173
 
1148
- .. output ::
1174
+ .. output::
1149
1175
  https://doc-status-update.streamlit.app/
1150
1176
  height: 300px
1151
1177
 
@@ -19,9 +19,7 @@ from __future__ import annotations
19
19
  from dataclasses import dataclass
20
20
  from datetime import date
21
21
  from enum import Enum
22
- from typing import TYPE_CHECKING, Any, Final, Literal, TypedDict, cast
23
-
24
- from typing_extensions import TypeAlias
22
+ from typing import TYPE_CHECKING, Any, Final, Literal, TypeAlias, TypedDict, cast
25
23
 
26
24
  from streamlit import dataframe_util, type_util
27
25
  from streamlit.elements.lib.color_util import (
@@ -48,6 +46,11 @@ if TYPE_CHECKING:
48
46
  VegaLiteType: TypeAlias = Literal["quantitative", "ordinal", "temporal", "nominal"]
49
47
  ChartStackType: TypeAlias = Literal["normalize", "center", "layered"]
50
48
 
49
+ # Threshold for applying hover event throttling on large datasets.
50
+ # For datasets with more points than this threshold, hover events are throttled
51
+ # to 16ms (~60fps) to improve performance.
52
+ _LARGE_DATASET_POINT_THRESHOLD: Final = 1000
53
+
51
54
 
52
55
  class PrepDataColumns(TypedDict):
53
56
  """Columns used for the prep_data step in Altair Arrow charts."""
@@ -288,37 +291,65 @@ def generate_chart(
288
291
  and is_altair_version_5_or_greater
289
292
  ):
290
293
  return _add_improved_hover_tooltips(
291
- chart, x_column, chart_width, chart_height
294
+ chart, x_column, chart_width, chart_height, len(df)
292
295
  ).interactive(), add_rows_metadata
293
296
 
294
297
  return chart.interactive(), add_rows_metadata
295
298
 
296
299
 
297
300
  def _add_improved_hover_tooltips(
298
- chart: alt.Chart, x_column: str, width: int | None, height: int | None
301
+ chart: alt.Chart,
302
+ x_column: str,
303
+ width: int | None,
304
+ height: int | None,
305
+ data_point_count: int,
299
306
  ) -> alt.LayerChart:
300
- """Adds improved hover tooltips to an existing line chart."""
307
+ """Adds improved hover tooltips to an existing line chart.
308
+
309
+ This implementation uses a three-layer approach for better performance:
310
+ 1. Base chart layer: The original line chart
311
+ 2. Detection layer: Invisible points for detecting the nearest point on hover
312
+ 3. Highlight layer: Only renders the selected point(s) using transform_filter
313
+
314
+ The filter-based approach is more efficient than using conditional opacity
315
+ because it only renders the selected point(s) rather than evaluating opacity
316
+ for every single data point on each hover event.
317
+ """
301
318
 
302
319
  import altair as alt
303
320
 
304
- # Create a selection that chooses the nearest point & selects based on x-value
321
+ # Throttle hover events for large datasets to 16ms (~60fps) to improve performance.
322
+ # For smaller datasets, use standard mousemove without throttling.
323
+ hover_event = (
324
+ "mousemove{16}"
325
+ if data_point_count > _LARGE_DATASET_POINT_THRESHOLD
326
+ else "mousemove"
327
+ )
328
+
329
+ # Create a selection that chooses the nearest point & selects based on x-value.
330
+ # Uses mouseleave instead of mouseout/pointerout for more reliable hover clearing
331
+ # (mouseout fires when moving over child elements like tooltips).
305
332
  nearest = alt.selection_point(
306
333
  nearest=True,
307
- on="pointerover",
334
+ on=hover_event,
308
335
  fields=[x_column],
309
336
  empty=False,
310
- clear="pointerout",
337
+ clear="mouseleave",
311
338
  )
312
339
 
313
- # Draw points on the line, and highlight based on selection
314
- points = (
315
- chart.mark_point(filled=True, size=65)
316
- .encode(opacity=alt.condition(nearest, alt.value(1), alt.value(0)))
317
- .add_params(nearest)
340
+ # Detection layer: Invisible points for detecting the nearest point.
341
+ # This layer is needed because selections must be attached to a mark.
342
+ detection_points = chart.mark_point(opacity=0).add_params(nearest)
343
+
344
+ # Highlight layer: Only renders the selected point(s) using transform_filter.
345
+ # This is more efficient than conditional opacity because it only renders
346
+ # the filtered data (typically 1-2 points) rather than all points.
347
+ highlighted_points = chart.mark_point(filled=True, size=65).transform_filter(
348
+ nearest
318
349
  )
319
350
 
320
351
  layer_chart = (
321
- alt.layer(chart, points)
352
+ alt.layer(chart, detection_points, highlighted_points)
322
353
  .configure_legend(symbolType="stroke")
323
354
  .properties(
324
355
  width=width or 0,
@@ -340,7 +371,7 @@ def prep_chart_data_for_add_rows(
340
371
  """
341
372
  import pandas as pd
342
373
 
343
- df = cast("pd.DataFrame", dataframe_util.convert_anything_to_pandas_df(data))
374
+ df = dataframe_util.convert_anything_to_pandas_df(data)
344
375
 
345
376
  # Make range indices start at last_index.
346
377
  if isinstance(df.index, pd.RangeIndex):
@@ -433,7 +464,7 @@ def _infer_vegalite_type(
433
464
 
434
465
 
435
466
  def _get_pandas_index_attr(
436
- data: pd.DataFrame | pd.Series,
467
+ data: pd.DataFrame | pd.Series[Any],
437
468
  attr: str,
438
469
  ) -> Any | None:
439
470
  return getattr(data.index, attr, None)
@@ -636,7 +667,7 @@ def _drop_unused_columns(df: pd.DataFrame, *column_names: str | None) -> pd.Data
636
667
  seen.add(x)
637
668
  keep.append(x)
638
669
 
639
- return df[keep]
670
+ return df[keep] # ty: ignore[invalid-return-type]
640
671
 
641
672
 
642
673
  def _maybe_convert_color_column_in_place(
@@ -653,7 +684,7 @@ def _maybe_convert_color_column_in_place(
653
684
  pass
654
685
  elif is_color_tuple_like(first_color_datum):
655
686
  # Tuples need to be converted to CSS-valid.
656
- df.loc[:, color_column] = df[color_column].map(to_css_color)
687
+ df.loc[:, color_column] = df[color_column].apply(to_css_color)
657
688
  else:
658
689
  # Other kinds of colors columns (i.e. pure numbers or nominal strings) shouldn't
659
690
  # be converted since they are treated by Vega-Lite as sequential or categorical
@@ -14,10 +14,8 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- from collections.abc import Collection
18
- from typing import Any, Callable, Union, cast
19
-
20
- from typing_extensions import TypeAlias
17
+ from collections.abc import Callable, Collection
18
+ from typing import Any, TypeAlias, cast
21
19
 
22
20
  from streamlit.errors import StreamlitInvalidColorError
23
21
 
@@ -35,26 +33,18 @@ IntRGBAColorTuple: TypeAlias = tuple[int, int, int, int]
35
33
  # CSS uses these.
36
34
  MixedRGBAColorTuple: TypeAlias = tuple[int, int, int, float]
37
35
 
38
- Color4Tuple: TypeAlias = Union[
39
- FloatRGBAColorTuple,
40
- IntRGBAColorTuple,
41
- MixedRGBAColorTuple,
42
- ]
36
+ Color4Tuple: TypeAlias = FloatRGBAColorTuple | IntRGBAColorTuple | MixedRGBAColorTuple
43
37
 
44
- Color3Tuple: TypeAlias = Union[
45
- FloatRGBColorTuple,
46
- IntRGBColorTuple,
47
- ]
38
+ Color3Tuple: TypeAlias = FloatRGBColorTuple | IntRGBColorTuple
48
39
 
49
- ColorTuple: TypeAlias = Union[Color4Tuple, Color3Tuple]
40
+ ColorTuple: TypeAlias = Color4Tuple | Color3Tuple
50
41
 
51
- IntColorTuple = Union[IntRGBColorTuple, IntRGBAColorTuple]
52
- CSSColorStr = Union[IntRGBAColorTuple, MixedRGBAColorTuple]
42
+ IntColorTuple: TypeAlias = IntRGBColorTuple | IntRGBAColorTuple
53
43
 
54
44
  ColorStr: TypeAlias = str
55
45
 
56
- Color: TypeAlias = Union[ColorTuple, ColorStr]
57
- MaybeColor: TypeAlias = Union[str, Collection[Any]]
46
+ Color: TypeAlias = ColorTuple | ColorStr
47
+ MaybeColor: TypeAlias = str | Collection[Any]
58
48
 
59
49
 
60
50
  def to_int_color_tuple(color: MaybeColor) -> IntColorTuple:
@@ -229,7 +219,7 @@ def _normalize_tuple(
229
219
  r = rgb_formatter(color_4tuple[0], color_4tuple)
230
220
  g = rgb_formatter(color_4tuple[1], color_4tuple)
231
221
  b = rgb_formatter(color_4tuple[2], color_4tuple)
232
- alpha = alpha_formatter(color_4tuple[3], color_4tuple)
222
+ alpha = alpha_formatter(color_4tuple[3], color_4tuple) # ty: ignore[index-out-of-bounds]
233
223
  return r, g, b, alpha
234
224
 
235
225
  raise StreamlitInvalidColorError(color)
@@ -18,9 +18,7 @@ import copy
18
18
  import json
19
19
  from collections.abc import Mapping
20
20
  from enum import Enum
21
- from typing import TYPE_CHECKING, Final, Literal, Union
22
-
23
- from typing_extensions import TypeAlias
21
+ from typing import TYPE_CHECKING, Any, Final, Literal, TypeAlias
24
22
 
25
23
  from streamlit.dataframe_util import DataFormat
26
24
  from streamlit.elements.lib.column_types import ColumnConfig, ColumnType
@@ -210,7 +208,7 @@ def _determine_data_kind_via_arrow(field: pa.Field) -> ColumnDataKind:
210
208
 
211
209
 
212
210
  def _determine_data_kind_via_pandas_dtype(
213
- column: Series | Index,
211
+ column: Series[Any] | Index[Any],
214
212
  ) -> ColumnDataKind:
215
213
  """Determine the data kind by using the pandas dtype.
216
214
 
@@ -264,7 +262,7 @@ def _determine_data_kind_via_pandas_dtype(
264
262
 
265
263
 
266
264
  def _determine_data_kind_via_inferred_type(
267
- column: Series | Index,
265
+ column: Series[Any] | Index[Any],
268
266
  ) -> ColumnDataKind:
269
267
  """Determine the data kind by inferring it from the underlying data.
270
268
 
@@ -333,7 +331,7 @@ def _determine_data_kind_via_inferred_type(
333
331
 
334
332
 
335
333
  def _determine_data_kind(
336
- column: Series | Index, field: pa.Field | None = None
334
+ column: Series[Any] | Index[Any], field: pa.Field | None = None
337
335
  ) -> ColumnDataKind:
338
336
  """Determine the data kind of a column.
339
337
 
@@ -397,7 +395,8 @@ def determine_dataframe_schema(
397
395
 
398
396
  # Add types for all columns:
399
397
  for i, column in enumerate(data_df.items()):
400
- column_name, column_data = column
398
+ column_name = str(column[0])
399
+ column_data = column[1]
401
400
  dataframe_schema[column_name] = _determine_data_kind(
402
401
  column_data, arrow_schema.field(i)
403
402
  )
@@ -405,16 +404,14 @@ def determine_dataframe_schema(
405
404
 
406
405
 
407
406
  # A mapping of column names/IDs to column configs.
408
- ColumnConfigMapping: TypeAlias = dict[
409
- Union[IndexIdentifierType, str, int], ColumnConfig
410
- ]
407
+ ColumnConfigMapping: TypeAlias = dict[IndexIdentifierType | str | int, ColumnConfig]
411
408
  ColumnConfigMappingInput: TypeAlias = Mapping[
412
409
  # TODO(lukasmasuch): This should also use int here to
413
410
  # correctly type the support for positional index. However,
414
411
  # allowing int here leads mypy to complain about simple dict[str, ...]
415
412
  # as input -> which seems like a mypy bug.
416
- Union[IndexIdentifierType, str],
417
- Union[ColumnConfig, None, str],
413
+ IndexIdentifierType | str,
414
+ ColumnConfig | None | str,
418
415
  ]
419
416
 
420
417