streamlit-nightly 1.43.2.dev20250307__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 (563) hide show
  1. streamlit/__init__.py +306 -0
  2. streamlit/__main__.py +20 -0
  3. streamlit/auth_util.py +218 -0
  4. streamlit/cli_util.py +105 -0
  5. streamlit/column_config.py +56 -0
  6. streamlit/commands/__init__.py +13 -0
  7. streamlit/commands/echo.py +126 -0
  8. streamlit/commands/execution_control.py +238 -0
  9. streamlit/commands/experimental_query_params.py +169 -0
  10. streamlit/commands/logo.py +189 -0
  11. streamlit/commands/navigation.py +385 -0
  12. streamlit/commands/page_config.py +311 -0
  13. streamlit/components/__init__.py +13 -0
  14. streamlit/components/lib/__init__.py +13 -0
  15. streamlit/components/lib/local_component_registry.py +84 -0
  16. streamlit/components/types/__init__.py +13 -0
  17. streamlit/components/types/base_component_registry.py +99 -0
  18. streamlit/components/types/base_custom_component.py +150 -0
  19. streamlit/components/v1/__init__.py +31 -0
  20. streamlit/components/v1/component_arrow.py +141 -0
  21. streamlit/components/v1/component_registry.py +130 -0
  22. streamlit/components/v1/components.py +38 -0
  23. streamlit/components/v1/custom_component.py +243 -0
  24. streamlit/config.py +1513 -0
  25. streamlit/config_option.py +311 -0
  26. streamlit/config_util.py +177 -0
  27. streamlit/connections/__init__.py +28 -0
  28. streamlit/connections/base_connection.py +174 -0
  29. streamlit/connections/snowflake_connection.py +562 -0
  30. streamlit/connections/snowpark_connection.py +213 -0
  31. streamlit/connections/sql_connection.py +425 -0
  32. streamlit/connections/util.py +97 -0
  33. streamlit/cursor.py +210 -0
  34. streamlit/dataframe_util.py +1416 -0
  35. streamlit/delta_generator.py +602 -0
  36. streamlit/delta_generator_singletons.py +204 -0
  37. streamlit/deprecation_util.py +209 -0
  38. streamlit/development.py +21 -0
  39. streamlit/elements/__init__.py +13 -0
  40. streamlit/elements/alert.py +234 -0
  41. streamlit/elements/arrow.py +962 -0
  42. streamlit/elements/balloons.py +47 -0
  43. streamlit/elements/bokeh_chart.py +133 -0
  44. streamlit/elements/code.py +114 -0
  45. streamlit/elements/deck_gl_json_chart.py +546 -0
  46. streamlit/elements/dialog_decorator.py +267 -0
  47. streamlit/elements/doc_string.py +558 -0
  48. streamlit/elements/empty.py +130 -0
  49. streamlit/elements/exception.py +331 -0
  50. streamlit/elements/form.py +354 -0
  51. streamlit/elements/graphviz_chart.py +150 -0
  52. streamlit/elements/heading.py +302 -0
  53. streamlit/elements/html.py +105 -0
  54. streamlit/elements/iframe.py +191 -0
  55. streamlit/elements/image.py +196 -0
  56. streamlit/elements/json.py +139 -0
  57. streamlit/elements/layouts.py +879 -0
  58. streamlit/elements/lib/__init__.py +13 -0
  59. streamlit/elements/lib/built_in_chart_utils.py +1157 -0
  60. streamlit/elements/lib/color_util.py +263 -0
  61. streamlit/elements/lib/column_config_utils.py +542 -0
  62. streamlit/elements/lib/column_types.py +2188 -0
  63. streamlit/elements/lib/dialog.py +147 -0
  64. streamlit/elements/lib/dicttools.py +154 -0
  65. streamlit/elements/lib/event_utils.py +37 -0
  66. streamlit/elements/lib/file_uploader_utils.py +66 -0
  67. streamlit/elements/lib/form_utils.py +77 -0
  68. streamlit/elements/lib/image_utils.py +441 -0
  69. streamlit/elements/lib/js_number.py +105 -0
  70. streamlit/elements/lib/mutable_status_container.py +183 -0
  71. streamlit/elements/lib/options_selector_utils.py +250 -0
  72. streamlit/elements/lib/pandas_styler_utils.py +274 -0
  73. streamlit/elements/lib/policies.py +194 -0
  74. streamlit/elements/lib/streamlit_plotly_theme.py +207 -0
  75. streamlit/elements/lib/subtitle_utils.py +176 -0
  76. streamlit/elements/lib/utils.py +250 -0
  77. streamlit/elements/map.py +508 -0
  78. streamlit/elements/markdown.py +277 -0
  79. streamlit/elements/media.py +793 -0
  80. streamlit/elements/metric.py +301 -0
  81. streamlit/elements/plotly_chart.py +546 -0
  82. streamlit/elements/progress.py +156 -0
  83. streamlit/elements/pyplot.py +194 -0
  84. streamlit/elements/snow.py +47 -0
  85. streamlit/elements/spinner.py +113 -0
  86. streamlit/elements/text.py +76 -0
  87. streamlit/elements/toast.py +98 -0
  88. streamlit/elements/vega_charts.py +1984 -0
  89. streamlit/elements/widgets/__init__.py +13 -0
  90. streamlit/elements/widgets/audio_input.py +310 -0
  91. streamlit/elements/widgets/button.py +1123 -0
  92. streamlit/elements/widgets/button_group.py +1008 -0
  93. streamlit/elements/widgets/camera_input.py +263 -0
  94. streamlit/elements/widgets/chat.py +647 -0
  95. streamlit/elements/widgets/checkbox.py +352 -0
  96. streamlit/elements/widgets/color_picker.py +265 -0
  97. streamlit/elements/widgets/data_editor.py +983 -0
  98. streamlit/elements/widgets/file_uploader.py +486 -0
  99. streamlit/elements/widgets/multiselect.py +338 -0
  100. streamlit/elements/widgets/number_input.py +545 -0
  101. streamlit/elements/widgets/radio.py +407 -0
  102. streamlit/elements/widgets/select_slider.py +437 -0
  103. streamlit/elements/widgets/selectbox.py +366 -0
  104. streamlit/elements/widgets/slider.py +880 -0
  105. streamlit/elements/widgets/text_widgets.py +628 -0
  106. streamlit/elements/widgets/time_widgets.py +970 -0
  107. streamlit/elements/write.py +574 -0
  108. streamlit/emojis.py +34 -0
  109. streamlit/env_util.py +61 -0
  110. streamlit/error_util.py +105 -0
  111. streamlit/errors.py +452 -0
  112. streamlit/external/__init__.py +13 -0
  113. streamlit/external/langchain/__init__.py +23 -0
  114. streamlit/external/langchain/streamlit_callback_handler.py +406 -0
  115. streamlit/file_util.py +247 -0
  116. streamlit/git_util.py +173 -0
  117. streamlit/hello/__init__.py +13 -0
  118. streamlit/hello/animation_demo.py +82 -0
  119. streamlit/hello/dataframe_demo.py +71 -0
  120. streamlit/hello/hello.py +37 -0
  121. streamlit/hello/mapping_demo.py +114 -0
  122. streamlit/hello/plotting_demo.py +55 -0
  123. streamlit/hello/streamlit_app.py +55 -0
  124. streamlit/hello/utils.py +28 -0
  125. streamlit/logger.py +130 -0
  126. streamlit/material_icon_names.py +25 -0
  127. streamlit/navigation/__init__.py +13 -0
  128. streamlit/navigation/page.py +302 -0
  129. streamlit/net_util.py +125 -0
  130. streamlit/platform.py +33 -0
  131. streamlit/proto/Alert_pb2.py +29 -0
  132. streamlit/proto/Alert_pb2.pyi +90 -0
  133. streamlit/proto/AppPage_pb2.py +27 -0
  134. streamlit/proto/AppPage_pb2.pyi +64 -0
  135. streamlit/proto/ArrowNamedDataSet_pb2.py +28 -0
  136. streamlit/proto/ArrowNamedDataSet_pb2.pyi +57 -0
  137. streamlit/proto/ArrowVegaLiteChart_pb2.py +29 -0
  138. streamlit/proto/ArrowVegaLiteChart_pb2.pyi +84 -0
  139. streamlit/proto/Arrow_pb2.py +33 -0
  140. streamlit/proto/Arrow_pb2.pyi +188 -0
  141. streamlit/proto/AudioInput_pb2.py +28 -0
  142. streamlit/proto/AudioInput_pb2.pyi +58 -0
  143. streamlit/proto/Audio_pb2.py +27 -0
  144. streamlit/proto/Audio_pb2.pyi +58 -0
  145. streamlit/proto/AuthRedirect_pb2.py +27 -0
  146. streamlit/proto/AuthRedirect_pb2.pyi +41 -0
  147. streamlit/proto/AutoRerun_pb2.py +27 -0
  148. streamlit/proto/AutoRerun_pb2.pyi +45 -0
  149. streamlit/proto/BackMsg_pb2.py +29 -0
  150. streamlit/proto/BackMsg_pb2.pyi +105 -0
  151. streamlit/proto/Balloons_pb2.py +27 -0
  152. streamlit/proto/Balloons_pb2.pyi +43 -0
  153. streamlit/proto/Block_pb2.py +53 -0
  154. streamlit/proto/Block_pb2.pyi +322 -0
  155. streamlit/proto/BokehChart_pb2.py +27 -0
  156. streamlit/proto/BokehChart_pb2.pyi +49 -0
  157. streamlit/proto/ButtonGroup_pb2.py +36 -0
  158. streamlit/proto/ButtonGroup_pb2.pyi +169 -0
  159. streamlit/proto/Button_pb2.py +27 -0
  160. streamlit/proto/Button_pb2.pyi +71 -0
  161. streamlit/proto/CameraInput_pb2.py +28 -0
  162. streamlit/proto/CameraInput_pb2.pyi +58 -0
  163. streamlit/proto/ChatInput_pb2.py +31 -0
  164. streamlit/proto/ChatInput_pb2.pyi +111 -0
  165. streamlit/proto/Checkbox_pb2.py +30 -0
  166. streamlit/proto/Checkbox_pb2.pyi +90 -0
  167. streamlit/proto/ClientState_pb2.py +30 -0
  168. streamlit/proto/ClientState_pb2.pyi +90 -0
  169. streamlit/proto/Code_pb2.py +27 -0
  170. streamlit/proto/Code_pb2.pyi +55 -0
  171. streamlit/proto/ColorPicker_pb2.py +28 -0
  172. streamlit/proto/ColorPicker_pb2.pyi +67 -0
  173. streamlit/proto/Common_pb2.py +51 -0
  174. streamlit/proto/Common_pb2.pyi +293 -0
  175. streamlit/proto/Components_pb2.py +35 -0
  176. streamlit/proto/Components_pb2.pyi +172 -0
  177. streamlit/proto/DataFrame_pb2.py +56 -0
  178. streamlit/proto/DataFrame_pb2.pyi +397 -0
  179. streamlit/proto/DateInput_pb2.py +28 -0
  180. streamlit/proto/DateInput_pb2.pyi +83 -0
  181. streamlit/proto/DeckGlJsonChart_pb2.py +29 -0
  182. streamlit/proto/DeckGlJsonChart_pb2.pyi +102 -0
  183. streamlit/proto/Delta_pb2.py +31 -0
  184. streamlit/proto/Delta_pb2.pyi +74 -0
  185. streamlit/proto/DocString_pb2.py +29 -0
  186. streamlit/proto/DocString_pb2.pyi +93 -0
  187. streamlit/proto/DownloadButton_pb2.py +27 -0
  188. streamlit/proto/DownloadButton_pb2.pyi +70 -0
  189. streamlit/proto/Element_pb2.py +78 -0
  190. streamlit/proto/Element_pb2.pyi +312 -0
  191. streamlit/proto/Empty_pb2.py +27 -0
  192. streamlit/proto/Empty_pb2.pyi +36 -0
  193. streamlit/proto/Exception_pb2.py +27 -0
  194. streamlit/proto/Exception_pb2.pyi +72 -0
  195. streamlit/proto/Favicon_pb2.py +27 -0
  196. streamlit/proto/Favicon_pb2.pyi +40 -0
  197. streamlit/proto/FileUploader_pb2.py +28 -0
  198. streamlit/proto/FileUploader_pb2.pyi +78 -0
  199. streamlit/proto/ForwardMsg_pb2.py +53 -0
  200. streamlit/proto/ForwardMsg_pb2.pyi +293 -0
  201. streamlit/proto/GitInfo_pb2.py +29 -0
  202. streamlit/proto/GitInfo_pb2.pyi +83 -0
  203. streamlit/proto/GraphVizChart_pb2.py +27 -0
  204. streamlit/proto/GraphVizChart_pb2.pyi +53 -0
  205. streamlit/proto/Heading_pb2.py +27 -0
  206. streamlit/proto/Heading_pb2.pyi +56 -0
  207. streamlit/proto/Html_pb2.py +27 -0
  208. streamlit/proto/Html_pb2.pyi +42 -0
  209. streamlit/proto/IFrame_pb2.py +27 -0
  210. streamlit/proto/IFrame_pb2.pyi +59 -0
  211. streamlit/proto/Image_pb2.py +29 -0
  212. streamlit/proto/Image_pb2.pyi +84 -0
  213. streamlit/proto/Json_pb2.py +27 -0
  214. streamlit/proto/Json_pb2.pyi +53 -0
  215. streamlit/proto/LabelVisibilityMessage_pb2.py +29 -0
  216. streamlit/proto/LabelVisibilityMessage_pb2.pyi +68 -0
  217. streamlit/proto/LinkButton_pb2.py +27 -0
  218. streamlit/proto/LinkButton_pb2.pyi +58 -0
  219. streamlit/proto/Logo_pb2.py +27 -0
  220. streamlit/proto/Logo_pb2.pyi +51 -0
  221. streamlit/proto/Markdown_pb2.py +29 -0
  222. streamlit/proto/Markdown_pb2.pyi +86 -0
  223. streamlit/proto/Metric_pb2.py +32 -0
  224. streamlit/proto/Metric_pb2.pyi +101 -0
  225. streamlit/proto/MetricsEvent_pb2.py +30 -0
  226. streamlit/proto/MetricsEvent_pb2.pyi +200 -0
  227. streamlit/proto/MultiSelect_pb2.py +28 -0
  228. streamlit/proto/MultiSelect_pb2.pyi +81 -0
  229. streamlit/proto/NamedDataSet_pb2.py +28 -0
  230. streamlit/proto/NamedDataSet_pb2.pyi +59 -0
  231. streamlit/proto/Navigation_pb2.py +30 -0
  232. streamlit/proto/Navigation_pb2.pyi +84 -0
  233. streamlit/proto/NewSession_pb2.py +51 -0
  234. streamlit/proto/NewSession_pb2.pyi +481 -0
  235. streamlit/proto/NumberInput_pb2.py +30 -0
  236. streamlit/proto/NumberInput_pb2.pyi +121 -0
  237. streamlit/proto/PageConfig_pb2.py +33 -0
  238. streamlit/proto/PageConfig_pb2.pyi +126 -0
  239. streamlit/proto/PageInfo_pb2.py +27 -0
  240. streamlit/proto/PageInfo_pb2.pyi +43 -0
  241. streamlit/proto/PageLink_pb2.py +27 -0
  242. streamlit/proto/PageLink_pb2.pyi +63 -0
  243. streamlit/proto/PageNotFound_pb2.py +27 -0
  244. streamlit/proto/PageNotFound_pb2.pyi +42 -0
  245. streamlit/proto/PageProfile_pb2.py +31 -0
  246. streamlit/proto/PageProfile_pb2.pyi +127 -0
  247. streamlit/proto/PagesChanged_pb2.py +28 -0
  248. streamlit/proto/PagesChanged_pb2.pyi +48 -0
  249. streamlit/proto/ParentMessage_pb2.py +27 -0
  250. streamlit/proto/ParentMessage_pb2.pyi +46 -0
  251. streamlit/proto/PlotlyChart_pb2.py +31 -0
  252. streamlit/proto/PlotlyChart_pb2.pyi +131 -0
  253. streamlit/proto/Progress_pb2.py +27 -0
  254. streamlit/proto/Progress_pb2.pyi +43 -0
  255. streamlit/proto/Radio_pb2.py +28 -0
  256. streamlit/proto/Radio_pb2.pyi +84 -0
  257. streamlit/proto/RootContainer_pb2.py +27 -0
  258. streamlit/proto/RootContainer_pb2.pyi +56 -0
  259. streamlit/proto/Selectbox_pb2.py +28 -0
  260. streamlit/proto/Selectbox_pb2.pyi +80 -0
  261. streamlit/proto/SessionEvent_pb2.py +28 -0
  262. streamlit/proto/SessionEvent_pb2.pyi +62 -0
  263. streamlit/proto/SessionStatus_pb2.py +27 -0
  264. streamlit/proto/SessionStatus_pb2.pyi +57 -0
  265. streamlit/proto/Skeleton_pb2.py +29 -0
  266. streamlit/proto/Skeleton_pb2.pyi +71 -0
  267. streamlit/proto/Slider_pb2.py +32 -0
  268. streamlit/proto/Slider_pb2.pyi +142 -0
  269. streamlit/proto/Snow_pb2.py +27 -0
  270. streamlit/proto/Snow_pb2.pyi +43 -0
  271. streamlit/proto/Spinner_pb2.py +27 -0
  272. streamlit/proto/Spinner_pb2.pyi +49 -0
  273. streamlit/proto/TextArea_pb2.py +28 -0
  274. streamlit/proto/TextArea_pb2.pyi +80 -0
  275. streamlit/proto/TextInput_pb2.py +30 -0
  276. streamlit/proto/TextInput_pb2.pyi +107 -0
  277. streamlit/proto/Text_pb2.py +27 -0
  278. streamlit/proto/Text_pb2.pyi +46 -0
  279. streamlit/proto/TimeInput_pb2.py +28 -0
  280. streamlit/proto/TimeInput_pb2.pyi +74 -0
  281. streamlit/proto/Toast_pb2.py +27 -0
  282. streamlit/proto/Toast_pb2.pyi +45 -0
  283. streamlit/proto/VegaLiteChart_pb2.py +29 -0
  284. streamlit/proto/VegaLiteChart_pb2.pyi +71 -0
  285. streamlit/proto/Video_pb2.py +31 -0
  286. streamlit/proto/Video_pb2.pyi +117 -0
  287. streamlit/proto/WidgetStates_pb2.py +31 -0
  288. streamlit/proto/WidgetStates_pb2.pyi +126 -0
  289. streamlit/proto/__init__.py +15 -0
  290. streamlit/proto/openmetrics_data_model_pb2.py +60 -0
  291. streamlit/proto/openmetrics_data_model_pb2.pyi +522 -0
  292. streamlit/py.typed +0 -0
  293. streamlit/runtime/__init__.py +50 -0
  294. streamlit/runtime/app_session.py +982 -0
  295. streamlit/runtime/caching/__init__.py +98 -0
  296. streamlit/runtime/caching/cache_data_api.py +665 -0
  297. streamlit/runtime/caching/cache_errors.py +142 -0
  298. streamlit/runtime/caching/cache_resource_api.py +527 -0
  299. streamlit/runtime/caching/cache_type.py +33 -0
  300. streamlit/runtime/caching/cache_utils.py +523 -0
  301. streamlit/runtime/caching/cached_message_replay.py +290 -0
  302. streamlit/runtime/caching/hashing.py +637 -0
  303. streamlit/runtime/caching/legacy_cache_api.py +169 -0
  304. streamlit/runtime/caching/storage/__init__.py +29 -0
  305. streamlit/runtime/caching/storage/cache_storage_protocol.py +239 -0
  306. streamlit/runtime/caching/storage/dummy_cache_storage.py +60 -0
  307. streamlit/runtime/caching/storage/in_memory_cache_storage_wrapper.py +145 -0
  308. streamlit/runtime/caching/storage/local_disk_cache_storage.py +223 -0
  309. streamlit/runtime/connection_factory.py +436 -0
  310. streamlit/runtime/context.py +280 -0
  311. streamlit/runtime/credentials.py +364 -0
  312. streamlit/runtime/forward_msg_cache.py +296 -0
  313. streamlit/runtime/forward_msg_queue.py +240 -0
  314. streamlit/runtime/fragment.py +477 -0
  315. streamlit/runtime/media_file_manager.py +234 -0
  316. streamlit/runtime/media_file_storage.py +143 -0
  317. streamlit/runtime/memory_media_file_storage.py +181 -0
  318. streamlit/runtime/memory_session_storage.py +77 -0
  319. streamlit/runtime/memory_uploaded_file_manager.py +138 -0
  320. streamlit/runtime/metrics_util.py +486 -0
  321. streamlit/runtime/pages_manager.py +165 -0
  322. streamlit/runtime/runtime.py +792 -0
  323. streamlit/runtime/runtime_util.py +106 -0
  324. streamlit/runtime/script_data.py +46 -0
  325. streamlit/runtime/scriptrunner/__init__.py +38 -0
  326. streamlit/runtime/scriptrunner/exec_code.py +159 -0
  327. streamlit/runtime/scriptrunner/magic.py +273 -0
  328. streamlit/runtime/scriptrunner/magic_funcs.py +32 -0
  329. streamlit/runtime/scriptrunner/script_cache.py +89 -0
  330. streamlit/runtime/scriptrunner/script_runner.py +756 -0
  331. streamlit/runtime/scriptrunner_utils/__init__.py +19 -0
  332. streamlit/runtime/scriptrunner_utils/exceptions.py +48 -0
  333. streamlit/runtime/scriptrunner_utils/script_requests.py +307 -0
  334. streamlit/runtime/scriptrunner_utils/script_run_context.py +287 -0
  335. streamlit/runtime/secrets.py +534 -0
  336. streamlit/runtime/session_manager.py +394 -0
  337. streamlit/runtime/state/__init__.py +41 -0
  338. streamlit/runtime/state/common.py +191 -0
  339. streamlit/runtime/state/query_params.py +205 -0
  340. streamlit/runtime/state/query_params_proxy.py +218 -0
  341. streamlit/runtime/state/safe_session_state.py +138 -0
  342. streamlit/runtime/state/session_state.py +772 -0
  343. streamlit/runtime/state/session_state_proxy.py +153 -0
  344. streamlit/runtime/state/widgets.py +135 -0
  345. streamlit/runtime/stats.py +109 -0
  346. streamlit/runtime/uploaded_file_manager.py +148 -0
  347. streamlit/runtime/websocket_session_manager.py +167 -0
  348. streamlit/source_util.py +98 -0
  349. streamlit/static/favicon.png +0 -0
  350. streamlit/static/index.html +61 -0
  351. streamlit/static/static/css/index.Bmkmz40k.css +1 -0
  352. streamlit/static/static/css/index.DpJG_94W.css +1 -0
  353. streamlit/static/static/css/index.DzuxGC_t.css +1 -0
  354. streamlit/static/static/js/FileDownload.esm.Bp9m5jrx.js +1 -0
  355. streamlit/static/static/js/FileHelper.D_3pbilj.js +5 -0
  356. streamlit/static/static/js/FormClearHelper.Ct2rwLXo.js +1 -0
  357. streamlit/static/static/js/Hooks.BKdzj5MJ.js +1 -0
  358. streamlit/static/static/js/InputInstructions.DB3QGNJP.js +1 -0
  359. streamlit/static/static/js/ProgressBar.D40A5xc2.js +2 -0
  360. streamlit/static/static/js/RenderInPortalIfExists.DLUCooTN.js +1 -0
  361. streamlit/static/static/js/Toolbar.BiGGIQun.js +1 -0
  362. streamlit/static/static/js/UploadFileInfo.C-jY39rj.js +1 -0
  363. streamlit/static/static/js/base-input.CQBQT24M.js +4 -0
  364. streamlit/static/static/js/checkbox.Buj8gd_M.js +9 -0
  365. streamlit/static/static/js/createDownloadLinkElement.DZMwyjvU.js +1 -0
  366. streamlit/static/static/js/createSuper.CesK3I23.js +1 -0
  367. streamlit/static/static/js/data-grid-overlay-editor.B69OOFM4.js +1 -0
  368. streamlit/static/static/js/downloader.BZQhlBNT.js +1 -0
  369. streamlit/static/static/js/es6.D9Zhqujy.js +2 -0
  370. streamlit/static/static/js/iframeResizer.contentWindow.CAzcBpCC.js +1 -0
  371. streamlit/static/static/js/index.08vcOOvb.js +1 -0
  372. streamlit/static/static/js/index.0uqKfJUS.js +1 -0
  373. streamlit/static/static/js/index.B02M5u69.js +203 -0
  374. streamlit/static/static/js/index.B7mcZKMx.js +1 -0
  375. streamlit/static/static/js/index.BAQDHFA_.js +1 -0
  376. streamlit/static/static/js/index.BI60cMVr.js +2 -0
  377. streamlit/static/static/js/index.BLug2inK.js +1 -0
  378. streamlit/static/static/js/index.BM6TMY8g.js +2 -0
  379. streamlit/static/static/js/index.BZ9p1t7G.js +1 -0
  380. streamlit/static/static/js/index.BZqa87a1.js +2 -0
  381. streamlit/static/static/js/index.BcsRUzZZ.js +1 -0
  382. streamlit/static/static/js/index.BgVMiY_P.js +197 -0
  383. streamlit/static/static/js/index.BtuGy7By.js +6 -0
  384. streamlit/static/static/js/index.BuDuBmrs.js +1 -0
  385. streamlit/static/static/js/index.BvXU2oKV.js +1 -0
  386. streamlit/static/static/js/index.BxcwPacT.js +73 -0
  387. streamlit/static/static/js/index.CWX8KB81.js +1 -0
  388. streamlit/static/static/js/index.CXzZTo_q.js +1 -0
  389. streamlit/static/static/js/index.CcRWp_KL.js +1 -0
  390. streamlit/static/static/js/index.Cd-_xe55.js +3 -0
  391. streamlit/static/static/js/index.CdG2PXln.js +4537 -0
  392. streamlit/static/static/js/index.CjXvXmcP.js +1 -0
  393. streamlit/static/static/js/index.D1HZENZx.js +776 -0
  394. streamlit/static/static/js/index.D21Efo64.js +1617 -0
  395. streamlit/static/static/js/index.D9WgGVBx.js +7 -0
  396. streamlit/static/static/js/index.DEcsHtvb.js +12 -0
  397. streamlit/static/static/js/index.DFeMfr_K.js +1 -0
  398. streamlit/static/static/js/index.DHFBoItz.js +1 -0
  399. streamlit/static/static/js/index.D_PrBKnJ.js +3 -0
  400. streamlit/static/static/js/index.DmuRkekN.js +3855 -0
  401. streamlit/static/static/js/index.Do6eY8sf.js +1 -0
  402. streamlit/static/static/js/index.Dz3lP2P-.js +1 -0
  403. streamlit/static/static/js/index.Dz_UqF-s.js +1 -0
  404. streamlit/static/static/js/index.GkSUsPhJ.js +1 -0
  405. streamlit/static/static/js/index.H1U1IC_d.js +3 -0
  406. streamlit/static/static/js/index.g6p_4DPr.js +1 -0
  407. streamlit/static/static/js/index.g9x_GKss.js +1 -0
  408. streamlit/static/static/js/index.zo9jm08y.js +1 -0
  409. streamlit/static/static/js/input.DnaFglHq.js +2 -0
  410. streamlit/static/static/js/inputUtils.CQWz5UKz.js +1 -0
  411. streamlit/static/static/js/memory.Crb9x4-F.js +1 -0
  412. streamlit/static/static/js/mergeWith.ouAz0sK3.js +1 -0
  413. streamlit/static/static/js/number-overlay-editor._UaN-O48.js +9 -0
  414. streamlit/static/static/js/possibleConstructorReturn.CtGjGFHz.js +1 -0
  415. streamlit/static/static/js/sandbox.CBybYOhV.js +1 -0
  416. streamlit/static/static/js/sprintf.D7DtBTRn.js +1 -0
  417. streamlit/static/static/js/textarea.Cb_uJt5U.js +2 -0
  418. streamlit/static/static/js/threshold.DjX0wlsa.js +1 -0
  419. streamlit/static/static/js/timepicker.DKT7pfoF.js +4 -0
  420. streamlit/static/static/js/timer.CAwTRJ_g.js +1 -0
  421. streamlit/static/static/js/toConsumableArray.05Ikp13-.js +3 -0
  422. streamlit/static/static/js/uniqueId.D2FMWUEI.js +1 -0
  423. streamlit/static/static/js/useBasicWidgetState.urnZLANY.js +1 -0
  424. streamlit/static/static/js/useOnInputChange.BOKIIdJ1.js +1 -0
  425. streamlit/static/static/js/value.CgPGBV_l.js +1 -0
  426. streamlit/static/static/js/withFullScreenWrapper.C_N8J0Xx.js +1 -0
  427. streamlit/static/static/media/KaTeX_AMS-Regular.BQhdFMY1.woff2 +0 -0
  428. streamlit/static/static/media/KaTeX_AMS-Regular.DMm9YOAa.woff +0 -0
  429. streamlit/static/static/media/KaTeX_AMS-Regular.DRggAlZN.ttf +0 -0
  430. streamlit/static/static/media/KaTeX_Caligraphic-Bold.ATXxdsX0.ttf +0 -0
  431. streamlit/static/static/media/KaTeX_Caligraphic-Bold.BEiXGLvX.woff +0 -0
  432. streamlit/static/static/media/KaTeX_Caligraphic-Bold.Dq_IR9rO.woff2 +0 -0
  433. streamlit/static/static/media/KaTeX_Caligraphic-Regular.CTRA-rTL.woff +0 -0
  434. streamlit/static/static/media/KaTeX_Caligraphic-Regular.Di6jR-x-.woff2 +0 -0
  435. streamlit/static/static/media/KaTeX_Caligraphic-Regular.wX97UBjC.ttf +0 -0
  436. streamlit/static/static/media/KaTeX_Fraktur-Bold.BdnERNNW.ttf +0 -0
  437. streamlit/static/static/media/KaTeX_Fraktur-Bold.BsDP51OF.woff +0 -0
  438. streamlit/static/static/media/KaTeX_Fraktur-Bold.CL6g_b3V.woff2 +0 -0
  439. streamlit/static/static/media/KaTeX_Fraktur-Regular.CB_wures.ttf +0 -0
  440. streamlit/static/static/media/KaTeX_Fraktur-Regular.CTYiF6lA.woff2 +0 -0
  441. streamlit/static/static/media/KaTeX_Fraktur-Regular.Dxdc4cR9.woff +0 -0
  442. streamlit/static/static/media/KaTeX_Main-Bold.Cx986IdX.woff2 +0 -0
  443. streamlit/static/static/media/KaTeX_Main-Bold.Jm3AIy58.woff +0 -0
  444. streamlit/static/static/media/KaTeX_Main-Bold.waoOVXN0.ttf +0 -0
  445. streamlit/static/static/media/KaTeX_Main-BoldItalic.DxDJ3AOS.woff2 +0 -0
  446. streamlit/static/static/media/KaTeX_Main-BoldItalic.DzxPMmG6.ttf +0 -0
  447. streamlit/static/static/media/KaTeX_Main-BoldItalic.SpSLRI95.woff +0 -0
  448. streamlit/static/static/media/KaTeX_Main-Italic.3WenGoN9.ttf +0 -0
  449. streamlit/static/static/media/KaTeX_Main-Italic.BMLOBm91.woff +0 -0
  450. streamlit/static/static/media/KaTeX_Main-Italic.NWA7e6Wa.woff2 +0 -0
  451. streamlit/static/static/media/KaTeX_Main-Regular.B22Nviop.woff2 +0 -0
  452. streamlit/static/static/media/KaTeX_Main-Regular.Dr94JaBh.woff +0 -0
  453. streamlit/static/static/media/KaTeX_Main-Regular.ypZvNtVU.ttf +0 -0
  454. streamlit/static/static/media/KaTeX_Math-BoldItalic.B3XSjfu4.ttf +0 -0
  455. streamlit/static/static/media/KaTeX_Math-BoldItalic.CZnvNsCZ.woff2 +0 -0
  456. streamlit/static/static/media/KaTeX_Math-BoldItalic.iY-2wyZ7.woff +0 -0
  457. streamlit/static/static/media/KaTeX_Math-Italic.DA0__PXp.woff +0 -0
  458. streamlit/static/static/media/KaTeX_Math-Italic.flOr_0UB.ttf +0 -0
  459. streamlit/static/static/media/KaTeX_Math-Italic.t53AETM-.woff2 +0 -0
  460. streamlit/static/static/media/KaTeX_SansSerif-Bold.CFMepnvq.ttf +0 -0
  461. streamlit/static/static/media/KaTeX_SansSerif-Bold.D1sUS0GD.woff2 +0 -0
  462. streamlit/static/static/media/KaTeX_SansSerif-Bold.DbIhKOiC.woff +0 -0
  463. streamlit/static/static/media/KaTeX_SansSerif-Italic.C3H0VqGB.woff2 +0 -0
  464. streamlit/static/static/media/KaTeX_SansSerif-Italic.DN2j7dab.woff +0 -0
  465. streamlit/static/static/media/KaTeX_SansSerif-Italic.YYjJ1zSn.ttf +0 -0
  466. streamlit/static/static/media/KaTeX_SansSerif-Regular.BNo7hRIc.ttf +0 -0
  467. streamlit/static/static/media/KaTeX_SansSerif-Regular.CS6fqUqJ.woff +0 -0
  468. streamlit/static/static/media/KaTeX_SansSerif-Regular.DDBCnlJ7.woff2 +0 -0
  469. streamlit/static/static/media/KaTeX_Script-Regular.C5JkGWo-.ttf +0 -0
  470. streamlit/static/static/media/KaTeX_Script-Regular.D3wIWfF6.woff2 +0 -0
  471. streamlit/static/static/media/KaTeX_Script-Regular.D5yQViql.woff +0 -0
  472. streamlit/static/static/media/KaTeX_Size1-Regular.C195tn64.woff +0 -0
  473. streamlit/static/static/media/KaTeX_Size1-Regular.Dbsnue_I.ttf +0 -0
  474. streamlit/static/static/media/KaTeX_Size1-Regular.mCD8mA8B.woff2 +0 -0
  475. streamlit/static/static/media/KaTeX_Size2-Regular.B7gKUWhC.ttf +0 -0
  476. streamlit/static/static/media/KaTeX_Size2-Regular.Dy4dx90m.woff2 +0 -0
  477. streamlit/static/static/media/KaTeX_Size2-Regular.oD1tc_U0.woff +0 -0
  478. streamlit/static/static/media/KaTeX_Size3-Regular.CTq5MqoE.woff +0 -0
  479. streamlit/static/static/media/KaTeX_Size3-Regular.DgpXs0kz.ttf +0 -0
  480. streamlit/static/static/media/KaTeX_Size4-Regular.BF-4gkZK.woff +0 -0
  481. streamlit/static/static/media/KaTeX_Size4-Regular.DWFBv043.ttf +0 -0
  482. streamlit/static/static/media/KaTeX_Size4-Regular.Dl5lxZxV.woff2 +0 -0
  483. streamlit/static/static/media/KaTeX_Typewriter-Regular.C0xS9mPB.woff +0 -0
  484. streamlit/static/static/media/KaTeX_Typewriter-Regular.CO6r4hn1.woff2 +0 -0
  485. streamlit/static/static/media/KaTeX_Typewriter-Regular.D3Ib7_Hf.ttf +0 -0
  486. streamlit/static/static/media/MaterialSymbols-Rounded.DcZbplWk.woff2 +0 -0
  487. streamlit/static/static/media/SourceCodePro-Bold.CFEfr7-q.woff2 +0 -0
  488. streamlit/static/static/media/SourceCodePro-BoldItalic.C-LkFXxa.woff2 +0 -0
  489. streamlit/static/static/media/SourceCodePro-Italic.CxFOx7N-.woff2 +0 -0
  490. streamlit/static/static/media/SourceCodePro-Regular.CBOlD63d.woff2 +0 -0
  491. streamlit/static/static/media/SourceCodePro-SemiBold.CFHwW3Wd.woff2 +0 -0
  492. streamlit/static/static/media/SourceCodePro-SemiBoldItalic.Cg2yRu82.woff2 +0 -0
  493. streamlit/static/static/media/SourceSansPro-Bold.-6c9oR8J.woff2 +0 -0
  494. streamlit/static/static/media/SourceSansPro-BoldItalic.DmM_grLY.woff2 +0 -0
  495. streamlit/static/static/media/SourceSansPro-Italic.I1ipWe7Q.woff2 +0 -0
  496. streamlit/static/static/media/SourceSansPro-Regular.DZLUzqI4.woff2 +0 -0
  497. streamlit/static/static/media/SourceSansPro-SemiBold.sKQIyTMz.woff2 +0 -0
  498. streamlit/static/static/media/SourceSansPro-SemiBoldItalic.C0wP0icr.woff2 +0 -0
  499. streamlit/static/static/media/SourceSerifPro-Bold.8TUnKj4x.woff2 +0 -0
  500. streamlit/static/static/media/SourceSerifPro-BoldItalic.CBVO7Ve7.woff2 +0 -0
  501. streamlit/static/static/media/SourceSerifPro-Italic.DkFgL2HZ.woff2 +0 -0
  502. streamlit/static/static/media/SourceSerifPro-Regular.CNJNET2S.woff2 +0 -0
  503. streamlit/static/static/media/SourceSerifPro-SemiBold.CHyh9GC5.woff2 +0 -0
  504. streamlit/static/static/media/SourceSerifPro-SemiBoldItalic.CBtz8sWN.woff2 +0 -0
  505. streamlit/static/static/media/balloon-0.Czj7AKwE.png +0 -0
  506. streamlit/static/static/media/balloon-1.CNvFFrND.png +0 -0
  507. streamlit/static/static/media/balloon-2.DTvC6B1t.png +0 -0
  508. streamlit/static/static/media/balloon-3.CgSk4tbL.png +0 -0
  509. streamlit/static/static/media/balloon-4.mbtFrzxf.png +0 -0
  510. streamlit/static/static/media/balloon-5.CSwkUfRA.png +0 -0
  511. streamlit/static/static/media/fireworks.B4d-_KUe.gif +0 -0
  512. streamlit/static/static/media/flake-0.DgWaVvm5.png +0 -0
  513. streamlit/static/static/media/flake-1.B2r5AHMK.png +0 -0
  514. streamlit/static/static/media/flake-2.BnWSExPC.png +0 -0
  515. streamlit/static/static/media/snowflake.JU2jBHL8.svg +11 -0
  516. streamlit/string_util.py +203 -0
  517. streamlit/temporary_directory.py +56 -0
  518. streamlit/testing/__init__.py +13 -0
  519. streamlit/testing/v1/__init__.py +17 -0
  520. streamlit/testing/v1/app_test.py +1050 -0
  521. streamlit/testing/v1/element_tree.py +2083 -0
  522. streamlit/testing/v1/local_script_runner.py +180 -0
  523. streamlit/testing/v1/util.py +53 -0
  524. streamlit/time_util.py +75 -0
  525. streamlit/type_util.py +460 -0
  526. streamlit/url_util.py +122 -0
  527. streamlit/user_info.py +519 -0
  528. streamlit/util.py +72 -0
  529. streamlit/vendor/__init__.py +0 -0
  530. streamlit/vendor/pympler/__init__.py +0 -0
  531. streamlit/vendor/pympler/asizeof.py +2869 -0
  532. streamlit/version.py +18 -0
  533. streamlit/watcher/__init__.py +28 -0
  534. streamlit/watcher/event_based_path_watcher.py +406 -0
  535. streamlit/watcher/folder_black_list.py +82 -0
  536. streamlit/watcher/local_sources_watcher.py +233 -0
  537. streamlit/watcher/path_watcher.py +185 -0
  538. streamlit/watcher/polling_path_watcher.py +124 -0
  539. streamlit/watcher/util.py +207 -0
  540. streamlit/web/__init__.py +13 -0
  541. streamlit/web/bootstrap.py +353 -0
  542. streamlit/web/cache_storage_manager_config.py +38 -0
  543. streamlit/web/cli.py +369 -0
  544. streamlit/web/server/__init__.py +26 -0
  545. streamlit/web/server/app_static_file_handler.py +93 -0
  546. streamlit/web/server/authlib_tornado_integration.py +60 -0
  547. streamlit/web/server/browser_websocket_handler.py +246 -0
  548. streamlit/web/server/component_request_handler.py +116 -0
  549. streamlit/web/server/media_file_handler.py +141 -0
  550. streamlit/web/server/oauth_authlib_routes.py +176 -0
  551. streamlit/web/server/oidc_mixin.py +108 -0
  552. streamlit/web/server/routes.py +295 -0
  553. streamlit/web/server/server.py +479 -0
  554. streamlit/web/server/server_util.py +161 -0
  555. streamlit/web/server/stats_request_handler.py +95 -0
  556. streamlit/web/server/upload_file_request_handler.py +137 -0
  557. streamlit/web/server/websocket_headers.py +56 -0
  558. streamlit_nightly-1.43.2.dev20250307.data/scripts/streamlit.cmd +16 -0
  559. streamlit_nightly-1.43.2.dev20250307.dist-info/METADATA +207 -0
  560. streamlit_nightly-1.43.2.dev20250307.dist-info/RECORD +563 -0
  561. streamlit_nightly-1.43.2.dev20250307.dist-info/WHEEL +5 -0
  562. streamlit_nightly-1.43.2.dev20250307.dist-info/entry_points.txt +2 -0
  563. streamlit_nightly-1.43.2.dev20250307.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1008 @@
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
+ from collections.abc import Sequence
18
+ from typing import (
19
+ TYPE_CHECKING,
20
+ Any,
21
+ Callable,
22
+ Final,
23
+ Generic,
24
+ Literal,
25
+ TypeVar,
26
+ cast,
27
+ overload,
28
+ )
29
+
30
+ from typing_extensions import TypeAlias
31
+
32
+ from streamlit.elements.lib.form_utils import current_form_id
33
+ from streamlit.elements.lib.options_selector_utils import (
34
+ convert_to_sequence_and_check_comparable,
35
+ get_default_indices,
36
+ )
37
+ from streamlit.elements.lib.policies import (
38
+ check_widget_policies,
39
+ maybe_raise_label_warnings,
40
+ )
41
+ from streamlit.elements.lib.utils import (
42
+ Key,
43
+ LabelVisibility,
44
+ compute_and_register_element_id,
45
+ get_label_visibility_proto_value,
46
+ save_for_app_testing,
47
+ to_key,
48
+ )
49
+ from streamlit.elements.widgets.multiselect import MultiSelectSerde
50
+ from streamlit.errors import StreamlitAPIException
51
+ from streamlit.proto.ButtonGroup_pb2 import ButtonGroup as ButtonGroupProto
52
+ from streamlit.runtime.metrics_util import gather_metrics
53
+ from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
54
+ from streamlit.runtime.state import register_widget
55
+ from streamlit.string_util import is_emoji, validate_material_icon
56
+ from streamlit.type_util import T
57
+
58
+ if TYPE_CHECKING:
59
+ from streamlit.dataframe_util import OptionSequence
60
+ from streamlit.delta_generator import DeltaGenerator
61
+ from streamlit.runtime.state import (
62
+ WidgetArgs,
63
+ WidgetCallback,
64
+ WidgetKwargs,
65
+ )
66
+ from streamlit.runtime.state.common import (
67
+ RegisterWidgetResult,
68
+ WidgetDeserializer,
69
+ WidgetSerializer,
70
+ )
71
+
72
+
73
+ V = TypeVar("V")
74
+
75
+ _THUMB_ICONS: Final = (":material/thumb_up:", ":material/thumb_down:")
76
+ _FACES_ICONS: Final = (
77
+ ":material/sentiment_sad:",
78
+ ":material/sentiment_dissatisfied:",
79
+ ":material/sentiment_neutral:",
80
+ ":material/sentiment_satisfied:",
81
+ ":material/sentiment_very_satisfied:",
82
+ )
83
+ _NUMBER_STARS: Final = 5
84
+ _STAR_ICON: Final = ":material/star:"
85
+ # we don't have the filled-material icon library as a dependency. Hence, we have it here
86
+ # in base64 format and send it over the wire as an image.
87
+ _SELECTED_STAR_ICON: Final = ":material/star_filled:"
88
+
89
+ SelectionMode: TypeAlias = Literal["single", "multi"]
90
+
91
+
92
+ class SingleSelectSerde(Generic[T]):
93
+ """Uses the MultiSelectSerde under-the-hood, but accepts a single index value
94
+ and deserializes to a single index value.
95
+ This is because button_group can be single and multi select, but we use the same
96
+ proto for both and, thus, map single values to a list of values and a receiving
97
+ value wrapped in a list to a single value.
98
+
99
+ When a default_value is provided is provided, the option corresponding to the
100
+ index is serialized/deserialized.
101
+ """
102
+
103
+ def __init__(
104
+ self,
105
+ option_indices: Sequence[T],
106
+ default_value: list[int] | None = None,
107
+ ) -> None:
108
+ # see docstring about why we use MultiSelectSerde here
109
+ self.multiselect_serde: MultiSelectSerde[T] = MultiSelectSerde(
110
+ option_indices, default_value if default_value is not None else []
111
+ )
112
+
113
+ def serialize(self, value: T | None) -> list[int]:
114
+ _value = [value] if value is not None else []
115
+ return self.multiselect_serde.serialize(_value)
116
+
117
+ def deserialize(self, ui_value: list[int] | None, widget_id: str = "") -> T | None:
118
+ deserialized = self.multiselect_serde.deserialize(ui_value, widget_id)
119
+
120
+ if len(deserialized) == 0:
121
+ return None
122
+
123
+ return deserialized[0]
124
+
125
+
126
+ class SingleOrMultiSelectSerde(Generic[T]):
127
+ """A serde that can handle both single and multi select options.
128
+
129
+ It uses the same proto to wire the data, so that we can send and receive
130
+ single values via a list. We have different serdes for both cases though so
131
+ that when setting / getting the value via session_state, it is mapped correctly.
132
+ So for single select, the value will be a single value and for multi select, it will
133
+ be a list of values.
134
+ """
135
+
136
+ def __init__(
137
+ self,
138
+ options: Sequence[T],
139
+ default_values: list[int],
140
+ type: Literal["single", "multi"],
141
+ ):
142
+ self.options = options
143
+ self.default_values = default_values
144
+ self.type = type
145
+ self.serde: SingleSelectSerde[T] | MultiSelectSerde[T] = (
146
+ SingleSelectSerde(options, default_value=default_values)
147
+ if type == "single"
148
+ else MultiSelectSerde(options, default_values)
149
+ )
150
+
151
+ def serialize(self, value: T | list[T] | None) -> list[int]:
152
+ return self.serde.serialize(cast(Any, value))
153
+
154
+ def deserialize(
155
+ self, ui_value: list[int] | None, widget_id: str = ""
156
+ ) -> list[T] | T | None:
157
+ return self.serde.deserialize(ui_value, widget_id)
158
+
159
+
160
+ def get_mapped_options(
161
+ feedback_option: Literal["thumbs", "faces", "stars"],
162
+ ) -> tuple[list[ButtonGroupProto.Option], list[int]]:
163
+ # options object understandable by the web app
164
+ options: list[ButtonGroupProto.Option] = []
165
+ # we use the option index in the webapp communication to
166
+ # indicate which option is selected
167
+ options_indices: list[int] = []
168
+
169
+ if feedback_option == "thumbs":
170
+ # reversing the index mapping to have thumbs up first (but still with the higher
171
+ # index (=sentiment) in the list)
172
+ options_indices = list(reversed(range(len(_THUMB_ICONS))))
173
+ options = [ButtonGroupProto.Option(content_icon=icon) for icon in _THUMB_ICONS]
174
+ elif feedback_option == "faces":
175
+ options_indices = list(range(len(_FACES_ICONS)))
176
+ options = [ButtonGroupProto.Option(content_icon=icon) for icon in _FACES_ICONS]
177
+ elif feedback_option == "stars":
178
+ options_indices = list(range(_NUMBER_STARS))
179
+ options = [
180
+ ButtonGroupProto.Option(
181
+ content_icon=_STAR_ICON,
182
+ selected_content_icon=_SELECTED_STAR_ICON,
183
+ )
184
+ ] * _NUMBER_STARS
185
+
186
+ return options, options_indices
187
+
188
+
189
+ def _build_proto(
190
+ widget_id: str,
191
+ formatted_options: Sequence[ButtonGroupProto.Option],
192
+ default_values: list[int],
193
+ disabled: bool,
194
+ current_form_id: str,
195
+ click_mode: ButtonGroupProto.ClickMode.ValueType,
196
+ selection_visualization: ButtonGroupProto.SelectionVisualization.ValueType = (
197
+ ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
198
+ ),
199
+ style: Literal["borderless", "pills", "segmented_control"] = "pills",
200
+ label: str | None = None,
201
+ label_visibility: LabelVisibility = "visible",
202
+ help: str | None = None,
203
+ ) -> ButtonGroupProto:
204
+ proto = ButtonGroupProto()
205
+
206
+ proto.id = widget_id
207
+ proto.default[:] = default_values
208
+ proto.form_id = current_form_id
209
+ proto.disabled = disabled
210
+ proto.click_mode = click_mode
211
+ proto.style = ButtonGroupProto.Style.Value(style.upper())
212
+
213
+ # not passing the label looks the same as a collapsed label
214
+ if label is not None:
215
+ proto.label = label
216
+ proto.label_visibility.value = get_label_visibility_proto_value(
217
+ label_visibility
218
+ )
219
+ if help is not None:
220
+ proto.help = help
221
+
222
+ for formatted_option in formatted_options:
223
+ proto.options.append(formatted_option)
224
+ proto.selection_visualization = selection_visualization
225
+ return proto
226
+
227
+
228
+ def _maybe_raise_selection_mode_warning(selection_mode: SelectionMode):
229
+ """Check if the selection_mode value is valid or raise exception otherwise."""
230
+ if selection_mode not in ["single", "multi"]:
231
+ raise StreamlitAPIException(
232
+ "The selection_mode argument must be one of ['single', 'multi']. "
233
+ f"The argument passed was '{selection_mode}'."
234
+ )
235
+
236
+
237
+ class ButtonGroupMixin:
238
+ # These overloads are not documented in the docstring, at least not at this time, on
239
+ # the theory that most people won't know what it means. And the Literals here are a
240
+ # subclass of int anyway. Usually, we would make a type alias for
241
+ # Literal["thumbs", "faces", "stars"]; but, in this case, we don't use it in too
242
+ # many other places, and it's a more helpful autocomplete if we just enumerate the
243
+ # values explicitly, so a decision has been made to keep it as not an alias.
244
+ @overload
245
+ def feedback(
246
+ self,
247
+ options: Literal["thumbs"] = ...,
248
+ *,
249
+ key: Key | None = None,
250
+ disabled: bool = False,
251
+ on_change: WidgetCallback | None = None,
252
+ args: WidgetArgs | None = None,
253
+ kwargs: WidgetKwargs | None = None,
254
+ ) -> Literal[0, 1] | None: ...
255
+ @overload
256
+ def feedback(
257
+ self,
258
+ options: Literal["faces", "stars"] = ...,
259
+ *,
260
+ key: Key | None = None,
261
+ disabled: bool = False,
262
+ on_change: WidgetCallback | None = None,
263
+ args: WidgetArgs | None = None,
264
+ kwargs: WidgetKwargs | None = None,
265
+ ) -> Literal[0, 1, 2, 3, 4] | None: ...
266
+ @gather_metrics("feedback")
267
+ def feedback(
268
+ self,
269
+ options: Literal["thumbs", "faces", "stars"] = "thumbs",
270
+ *,
271
+ key: Key | None = None,
272
+ disabled: bool = False,
273
+ on_change: WidgetCallback | None = None,
274
+ args: WidgetArgs | None = None,
275
+ kwargs: WidgetKwargs | None = None,
276
+ ) -> int | None:
277
+ """Display a feedback widget.
278
+
279
+ A feedback widget is an icon-based button group available in three
280
+ styles, as described in ``options``. It is commonly used in chat and AI
281
+ apps to allow users to rate responses.
282
+
283
+ Parameters
284
+ ----------
285
+ options: "thumbs", "faces", or "stars"
286
+ The feedback options displayed to the user. ``options`` can be one
287
+ of the following:
288
+
289
+ - ``"thumbs"`` (default): Streamlit displays a thumb-up and
290
+ thumb-down button group.
291
+ - ``"faces"``: Streamlit displays a row of five buttons with
292
+ facial expressions depicting increasing satisfaction from left to
293
+ right.
294
+ - ``"stars"``: Streamlit displays a row of star icons, allowing the
295
+ user to select a rating from one to five stars.
296
+
297
+ key : str or int
298
+ An optional string or integer to use as the unique key for the widget.
299
+ If this is omitted, a key will be generated for the widget
300
+ based on its content. No two widgets may have the same key.
301
+
302
+ disabled : bool
303
+ An optional boolean that disables the feedback widget if set
304
+ to ``True``. The default is ``False``.
305
+
306
+ on_change : callable
307
+ An optional callback invoked when this feedback widget's value
308
+ changes.
309
+
310
+ args : tuple
311
+ An optional tuple of args to pass to the callback.
312
+
313
+ kwargs : dict
314
+ An optional dict of kwargs to pass to the callback.
315
+
316
+ Returns
317
+ -------
318
+ int or None
319
+ An integer indicating the user's selection, where ``0`` is the
320
+ lowest feedback. Higher values indicate more positive feedback.
321
+ If no option was selected, the widget returns ``None``.
322
+
323
+ - For ``options="thumbs"``, a return value of ``0`` indicates
324
+ thumbs-down, and ``1`` indicates thumbs-up.
325
+ - For ``options="faces"`` and ``options="stars"``, return values
326
+ range from ``0`` (least satisfied) to ``4`` (most satisfied).
327
+
328
+ Examples
329
+ --------
330
+ Display a feedback widget with stars, and show the selected sentiment:
331
+
332
+ >>> import streamlit as st
333
+ >>>
334
+ >>> sentiment_mapping = ["one", "two", "three", "four", "five"]
335
+ >>> selected = st.feedback("stars")
336
+ >>> if selected is not None:
337
+ >>> st.markdown(f"You selected {sentiment_mapping[selected]} star(s).")
338
+
339
+ .. output ::
340
+ https://doc-feedback-stars.streamlit.app/
341
+ height: 200px
342
+
343
+ Display a feedback widget with thumbs, and show the selected sentiment:
344
+
345
+ >>> import streamlit as st
346
+ >>>
347
+ >>> sentiment_mapping = [":material/thumb_down:", ":material/thumb_up:"]
348
+ >>> selected = st.feedback("thumbs")
349
+ >>> if selected is not None:
350
+ >>> st.markdown(f"You selected: {sentiment_mapping[selected]}")
351
+
352
+ .. output ::
353
+ https://doc-feedback-thumbs.streamlit.app/
354
+ height: 200px
355
+
356
+ """
357
+
358
+ if options not in ["thumbs", "faces", "stars"]:
359
+ raise StreamlitAPIException(
360
+ "The options argument to st.feedback must be one of "
361
+ "['thumbs', 'faces', 'stars']. "
362
+ f"The argument passed was '{options}'."
363
+ )
364
+ transformed_options, options_indices = get_mapped_options(options)
365
+ serde = SingleSelectSerde[int](options_indices)
366
+
367
+ selection_visualization = ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
368
+ if options == "stars":
369
+ selection_visualization = (
370
+ ButtonGroupProto.SelectionVisualization.ALL_UP_TO_SELECTED
371
+ )
372
+
373
+ sentiment = self._button_group(
374
+ transformed_options,
375
+ default=None,
376
+ key=key,
377
+ selection_mode="single",
378
+ disabled=disabled,
379
+ deserializer=serde.deserialize,
380
+ serializer=serde.serialize,
381
+ on_change=on_change,
382
+ args=args,
383
+ kwargs=kwargs,
384
+ selection_visualization=selection_visualization,
385
+ style="borderless",
386
+ )
387
+ return sentiment.value
388
+
389
+ @overload
390
+ def pills(
391
+ self,
392
+ label: str,
393
+ options: OptionSequence[V],
394
+ *,
395
+ selection_mode: Literal["single"] = "single",
396
+ default: V | None = None,
397
+ format_func: Callable[[Any], str] | None = None,
398
+ key: Key | None = None,
399
+ help: str | None = None,
400
+ on_change: WidgetCallback | None = None,
401
+ args: WidgetArgs | None = None,
402
+ kwargs: WidgetKwargs | None = None,
403
+ disabled: bool = False,
404
+ label_visibility: LabelVisibility = "visible",
405
+ ) -> V | None: ...
406
+ @overload
407
+ def pills(
408
+ self,
409
+ label: str,
410
+ options: OptionSequence[V],
411
+ *,
412
+ selection_mode: Literal["multi"],
413
+ default: Sequence[V] | V | None = None,
414
+ format_func: Callable[[Any], str] | None = None,
415
+ key: Key | None = None,
416
+ help: str | None = None,
417
+ on_change: WidgetCallback | None = None,
418
+ args: WidgetArgs | None = None,
419
+ kwargs: WidgetKwargs | None = None,
420
+ disabled: bool = False,
421
+ label_visibility: LabelVisibility = "visible",
422
+ ) -> list[V]: ...
423
+ @gather_metrics("pills")
424
+ def pills(
425
+ self,
426
+ label: str,
427
+ options: OptionSequence[V],
428
+ *,
429
+ selection_mode: Literal["single", "multi"] = "single",
430
+ default: Sequence[V] | V | None = None,
431
+ format_func: Callable[[Any], str] | None = None,
432
+ key: Key | None = None,
433
+ help: str | None = None,
434
+ on_change: WidgetCallback | None = None,
435
+ args: WidgetArgs | None = None,
436
+ kwargs: WidgetKwargs | None = None,
437
+ disabled: bool = False,
438
+ label_visibility: LabelVisibility = "visible",
439
+ ) -> list[V] | V | None:
440
+ r"""Display a pills widget.
441
+
442
+ A pills widget is similar to a ``st.selectbox`` or ``st.multiselect``
443
+ where the ``options`` are displayed as pill-buttons instead of a
444
+ drop-down list.
445
+
446
+ Parameters
447
+ ----------
448
+ label: str
449
+ A short label explaining to the user what this widget is for.
450
+ The label can optionally contain GitHub-flavored Markdown of the
451
+ following types: Bold, Italics, Strikethroughs, Inline Code, Links,
452
+ and Images. Images display like icons, with a max height equal to
453
+ the font height.
454
+
455
+ Unsupported Markdown elements are unwrapped so only their children
456
+ (text contents) render. Display unsupported elements as literal
457
+ characters by backslash-escaping them. E.g.,
458
+ ``"1\. Not an ordered list"``.
459
+
460
+ See the ``body`` parameter of |st.markdown|_ for additional,
461
+ supported Markdown directives.
462
+
463
+ For accessibility reasons, you should never set an empty label, but
464
+ you can hide it with ``label_visibility`` if needed. In the future,
465
+ we may disallow empty labels by raising an exception.
466
+
467
+ .. |st.markdown| replace:: ``st.markdown``
468
+ .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
469
+
470
+ options: Iterable of V
471
+ Labels for the select options in an ``Iterable``. This can be a
472
+ ``list``, ``set``, or anything supported by ``st.dataframe``. If
473
+ ``options`` is dataframe-like, the first column will be used. Each
474
+ label will be cast to ``str`` internally by default and can
475
+ optionally contain GitHub-flavored Markdown, including the Markdown
476
+ directives described in the ``body`` parameter of ``st.markdown``.
477
+
478
+ selection_mode: "single" or "multi"
479
+ The selection mode for the widget. If this is ``"single"``
480
+ (default), only one option can be selected. If this is ``"multi"``,
481
+ multiple options can be selected.
482
+
483
+ default: Iterable of V, V, or None
484
+ The value of the widget when it first renders. If the
485
+ ``selection_mode`` is ``multi``, this can be a list of values, a
486
+ single value, or ``None``. If the ``selection_mode`` is
487
+ ``"single"``, this can be a single value or ``None``.
488
+
489
+ format_func: function
490
+ Function to modify the display of the options. It receives
491
+ the raw option as an argument and should output the label to be
492
+ shown for that option. This has no impact on the return value of
493
+ the command. The output can optionally contain GitHub-flavored
494
+ Markdown, including the Markdown directives described in the
495
+ ``body`` parameter of ``st.markdown``.
496
+
497
+ key: str or int
498
+ An optional string or integer to use as the unique key for the widget.
499
+ If this is omitted, a key will be generated for the widget
500
+ based on its content. Multiple widgets of the same type may
501
+ not share the same key.
502
+
503
+ help: str or None
504
+ A tooltip that gets displayed next to the widget label. Streamlit
505
+ only displays the tooltip when ``label_visibility="visible"``. If
506
+ this is ``None`` (default), no tooltip is displayed.
507
+
508
+ The tooltip can optionally contain GitHub-flavored Markdown,
509
+ including the Markdown directives described in the ``body``
510
+ parameter of ``st.markdown``.
511
+
512
+ on_change: callable
513
+ An optional callback invoked when this widget's value changes.
514
+
515
+ args: tuple
516
+ An optional tuple of args to pass to the callback.
517
+
518
+ kwargs: dict
519
+ An optional dict of kwargs to pass to the callback.
520
+
521
+ disabled: bool
522
+ An optional boolean that disables the widget if set to ``True``.
523
+ The default is ``False``.
524
+
525
+ label_visibility: "visible", "hidden", or "collapsed"
526
+ The visibility of the label. The default is ``"visible"``. If this
527
+ is ``"hidden"``, Streamlit displays an empty spacer instead of the
528
+ label, which can help keep the widget alligned with other widgets.
529
+ If this is ``"collapsed"``, Streamlit displays no label or spacer.
530
+
531
+ Returns
532
+ -------
533
+ list of V, V, or None
534
+ If the ``selection_mode`` is ``multi``, this is a list of selected
535
+ options or an empty list. If the ``selection_mode`` is
536
+ ``"single"``, this is a selected option or ``None``.
537
+
538
+ Examples
539
+ --------
540
+
541
+ **Example 1: Multi-select pills**
542
+
543
+ Display a multi-select pills widget, and show the selection:
544
+
545
+ >>> import streamlit as st
546
+ >>>
547
+ >>> options = ["North", "East", "South", "West"]
548
+ >>> selection = st.pills("Directions", options, selection_mode="multi")
549
+ >>> st.markdown(f"Your selected options: {selection}.")
550
+
551
+ .. output::
552
+ https://doc-pills-multi.streamlit.app/
553
+ height: 200px
554
+
555
+ **Example 2: Single-select pills with icons**
556
+
557
+ Display a single-select pills widget with icons:
558
+
559
+ >>> import streamlit as st
560
+ >>>
561
+ >>> option_map = {
562
+ ... 0: ":material/add:",
563
+ ... 1: ":material/zoom_in:",
564
+ ... 2: ":material/zoom_out:",
565
+ ... 3: ":material/zoom_out_map:",
566
+ ... }
567
+ >>> selection = st.pills(
568
+ ... "Tool",
569
+ ... options=option_map.keys(),
570
+ ... format_func=lambda option: option_map[option],
571
+ ... selection_mode="single",
572
+ ... )
573
+ >>> st.write(
574
+ ... "Your selected option: "
575
+ ... f"{None if selection is None else option_map[selection]}"
576
+ ... )
577
+
578
+ .. output::
579
+ https://doc-pills-single.streamlit.app/
580
+ height: 200px
581
+
582
+ """
583
+ return self._internal_button_group(
584
+ options,
585
+ label=label,
586
+ selection_mode=selection_mode,
587
+ default=default,
588
+ format_func=format_func,
589
+ key=key,
590
+ help=help,
591
+ style="pills",
592
+ on_change=on_change,
593
+ args=args,
594
+ kwargs=kwargs,
595
+ disabled=disabled,
596
+ label_visibility=label_visibility,
597
+ )
598
+
599
+ @overload
600
+ def segmented_control(
601
+ self,
602
+ label: str,
603
+ options: OptionSequence[V],
604
+ *,
605
+ selection_mode: Literal["single"] = "single",
606
+ default: V | None = None,
607
+ format_func: Callable[[Any], str] | None = None,
608
+ key: str | int | None = None,
609
+ help: str | None = None,
610
+ on_change: WidgetCallback | None = None,
611
+ args: WidgetArgs | None = None,
612
+ kwargs: WidgetKwargs | None = None,
613
+ disabled: bool = False,
614
+ label_visibility: LabelVisibility = "visible",
615
+ ) -> V | None: ...
616
+ @overload
617
+ def segmented_control(
618
+ self,
619
+ label: str,
620
+ options: OptionSequence[V],
621
+ *,
622
+ selection_mode: Literal["multi"],
623
+ default: Sequence[V] | V | None = None,
624
+ format_func: Callable[[Any], str] | None = None,
625
+ key: str | int | None = None,
626
+ help: str | None = None,
627
+ on_change: WidgetCallback | None = None,
628
+ args: WidgetArgs | None = None,
629
+ kwargs: WidgetKwargs | None = None,
630
+ disabled: bool = False,
631
+ label_visibility: LabelVisibility = "visible",
632
+ ) -> list[V]: ...
633
+
634
+ @gather_metrics("segmented_control")
635
+ def segmented_control(
636
+ self,
637
+ label: str,
638
+ options: OptionSequence[V],
639
+ *,
640
+ selection_mode: Literal["single", "multi"] = "single",
641
+ default: Sequence[V] | V | None = None,
642
+ format_func: Callable[[Any], str] | None = None,
643
+ key: str | int | None = None,
644
+ help: str | None = None,
645
+ on_change: WidgetCallback | None = None,
646
+ args: WidgetArgs | None = None,
647
+ kwargs: WidgetKwargs | None = None,
648
+ disabled: bool = False,
649
+ label_visibility: LabelVisibility = "visible",
650
+ ) -> list[V] | V | None:
651
+ r"""Display a segmented control widget.
652
+
653
+ A segmented control widget is a linear set of segments where each of
654
+ the passed ``options`` functions like a toggle button.
655
+
656
+ Parameters
657
+ ----------
658
+ label : str
659
+ A short label explaining to the user what this widget is for.
660
+ The label can optionally contain GitHub-flavored Markdown of the
661
+ following types: Bold, Italics, Strikethroughs, Inline Code, Links,
662
+ and Images. Images display like icons, with a max height equal to
663
+ the font height.
664
+
665
+ Unsupported Markdown elements are unwrapped so only their children
666
+ (text contents) render. Display unsupported elements as literal
667
+ characters by backslash-escaping them. E.g.,
668
+ ``"1\. Not an ordered list"``.
669
+
670
+ See the ``body`` parameter of |st.markdown|_ for additional,
671
+ supported Markdown directives.
672
+
673
+ For accessibility reasons, you should never set an empty label, but
674
+ you can hide it with ``label_visibility`` if needed. In the future,
675
+ we may disallow empty labels by raising an exception.
676
+
677
+ .. |st.markdown| replace:: ``st.markdown``
678
+ .. _st.markdown: https://docs.streamlit.io/develop/api-reference/text/st.markdown
679
+
680
+ options: Iterable of V
681
+ Labels for the select options in an ``Iterable``. This can be a
682
+ ``list``, ``set``, or anything supported by ``st.dataframe``. If
683
+ ``options`` is dataframe-like, the first column will be used. Each
684
+ label will be cast to ``str`` internally by default and can
685
+ optionally contain GitHub-flavored Markdown, including the Markdown
686
+ directives described in the ``body`` parameter of ``st.markdown``.
687
+
688
+ selection_mode: "single" or "multi"
689
+ The selection mode for the widget. If this is ``"single"``
690
+ (default), only one option can be selected. If this is ``"multi"``,
691
+ multiple options can be selected.
692
+
693
+ default: Iterable of V, V, or None
694
+ The value of the widget when it first renders. If the
695
+ ``selection_mode`` is ``multi``, this can be a list of values, a
696
+ single value, or ``None``. If the ``selection_mode`` is
697
+ ``"single"``, this can be a single value or ``None``.
698
+
699
+ format_func: function
700
+ Function to modify the display of the options. It receives
701
+ the raw option as an argument and should output the label to be
702
+ shown for that option. This has no impact on the return value of
703
+ the command. The output can optionally contain GitHub-flavored
704
+ Markdown, including the Markdown directives described in the
705
+ ``body`` parameter of ``st.markdown``.
706
+
707
+ key: str or int
708
+ An optional string or integer to use as the unique key for the widget.
709
+ If this is omitted, a key will be generated for the widget
710
+ based on its content. Multiple widgets of the same type may
711
+ not share the same key.
712
+
713
+ help: str or None
714
+ A tooltip that gets displayed next to the widget label. Streamlit
715
+ only displays the tooltip when ``label_visibility="visible"``. If
716
+ this is ``None`` (default), no tooltip is displayed.
717
+
718
+ The tooltip can optionally contain GitHub-flavored Markdown,
719
+ including the Markdown directives described in the ``body``
720
+ parameter of ``st.markdown``.
721
+
722
+ on_change: callable
723
+ An optional callback invoked when this widget's value changes.
724
+
725
+ args: tuple
726
+ An optional tuple of args to pass to the callback.
727
+
728
+ kwargs: dict
729
+ An optional dict of kwargs to pass to the callback.
730
+
731
+ disabled: bool
732
+ An optional boolean that disables the widget if set to ``True``.
733
+ The default is ``False``.
734
+
735
+ label_visibility: "visible", "hidden", or "collapsed"
736
+ The visibility of the label. The default is ``"visible"``. If this
737
+ is ``"hidden"``, Streamlit displays an empty spacer instead of the
738
+ label, which can help keep the widget alligned with other widgets.
739
+ If this is ``"collapsed"``, Streamlit displays no label or spacer.
740
+
741
+ Returns
742
+ -------
743
+ list of V, V, or None
744
+ If the ``selection_mode`` is ``multi``, this is a list of selected
745
+ options or an empty list. If the ``selection_mode`` is
746
+ ``"single"``, this is a selected option or ``None``.
747
+
748
+ Examples
749
+ --------
750
+
751
+ **Example 1: Multi-select segmented control**
752
+
753
+ Display a multi-select segmented control widget, and show the
754
+ selection:
755
+
756
+ >>> import streamlit as st
757
+ >>>
758
+ >>> options = ["North", "East", "South", "West"]
759
+ >>> selection = st.segmented_control(
760
+ ... "Directions", options, selection_mode="multi"
761
+ ... )
762
+ >>> st.markdown(f"Your selected options: {selection}.")
763
+
764
+ .. output::
765
+ https://doc-segmented-control-multi.streamlit.app/
766
+ height: 200px
767
+
768
+ **Example 2: Single-select segmented control with icons**
769
+
770
+ Display a single-select segmented control widget with icons:
771
+
772
+ >>> import streamlit as st
773
+ >>>
774
+ >>> option_map = {
775
+ ... 0: ":material/add:",
776
+ ... 1: ":material/zoom_in:",
777
+ ... 2: ":material/zoom_out:",
778
+ ... 3: ":material/zoom_out_map:",
779
+ ... }
780
+ >>> selection = st.segmented_control(
781
+ ... "Tool",
782
+ ... options=option_map.keys(),
783
+ ... format_func=lambda option: option_map[option],
784
+ ... selection_mode="single",
785
+ ... )
786
+ >>> st.write(
787
+ ... "Your selected option: "
788
+ ... f"{None if selection is None else option_map[selection]}"
789
+ ... )
790
+
791
+ .. output::
792
+ https://doc-segmented-control-single.streamlit.app/
793
+ height: 200px
794
+
795
+ """
796
+ return self._internal_button_group(
797
+ options,
798
+ label=label,
799
+ selection_mode=selection_mode,
800
+ default=default,
801
+ format_func=format_func,
802
+ key=key,
803
+ help=help,
804
+ style="segmented_control",
805
+ on_change=on_change,
806
+ args=args,
807
+ kwargs=kwargs,
808
+ disabled=disabled,
809
+ label_visibility=label_visibility,
810
+ )
811
+
812
+ @gather_metrics("_internal_button_group")
813
+ def _internal_button_group(
814
+ self,
815
+ options: OptionSequence[V],
816
+ *,
817
+ key: Key | None = None,
818
+ default: Sequence[V] | V | None = None,
819
+ selection_mode: Literal["single", "multi"] = "single",
820
+ disabled: bool = False,
821
+ format_func: Callable[[Any], str] | None = None,
822
+ style: Literal["pills", "segmented_control"] = "segmented_control",
823
+ on_change: WidgetCallback | None = None,
824
+ args: WidgetArgs | None = None,
825
+ kwargs: WidgetKwargs | None = None,
826
+ label: str | None = None,
827
+ label_visibility: LabelVisibility = "visible",
828
+ help: str | None = None,
829
+ ) -> list[V] | V | None:
830
+ maybe_raise_label_warnings(label, label_visibility)
831
+
832
+ def _transformed_format_func(option: V) -> ButtonGroupProto.Option:
833
+ """If option starts with a material icon or an emoji, we extract it to send
834
+ it parsed to the frontend."""
835
+ transformed = format_func(option) if format_func else str(option)
836
+ transformed_parts = transformed.split(" ")
837
+ icon: str | None = None
838
+ if len(transformed_parts) > 0:
839
+ maybe_icon = transformed_parts[0].strip()
840
+ try:
841
+ if maybe_icon.startswith(":material"):
842
+ icon = validate_material_icon(maybe_icon)
843
+ elif is_emoji(maybe_icon):
844
+ icon = maybe_icon
845
+
846
+ if icon:
847
+ # reassamble the option string without the icon - also
848
+ # works if len(transformed_parts) == 1
849
+ transformed = " ".join(transformed_parts[1:])
850
+ except StreamlitAPIException:
851
+ # we don't have a valid icon or emoji, so we just pass
852
+ pass
853
+ return ButtonGroupProto.Option(
854
+ content=transformed,
855
+ content_icon=icon,
856
+ )
857
+
858
+ indexable_options = convert_to_sequence_and_check_comparable(options)
859
+ default_values = get_default_indices(indexable_options, default)
860
+
861
+ serde: SingleOrMultiSelectSerde[V] = SingleOrMultiSelectSerde[V](
862
+ indexable_options, default_values, selection_mode
863
+ )
864
+
865
+ res = self._button_group(
866
+ indexable_options,
867
+ default=default_values,
868
+ selection_mode=selection_mode,
869
+ disabled=disabled,
870
+ format_func=_transformed_format_func,
871
+ key=key,
872
+ help=help,
873
+ style=style,
874
+ serializer=serde.serialize,
875
+ deserializer=serde.deserialize,
876
+ on_change=on_change,
877
+ args=args,
878
+ kwargs=kwargs,
879
+ label=label,
880
+ label_visibility=label_visibility,
881
+ )
882
+
883
+ if selection_mode == "multi":
884
+ return res.value
885
+
886
+ return res.value
887
+
888
+ def _button_group(
889
+ self,
890
+ indexable_options: Sequence[Any],
891
+ *,
892
+ key: Key | None = None,
893
+ default: list[int] | None = None,
894
+ selection_mode: SelectionMode = "single",
895
+ disabled: bool = False,
896
+ style: Literal[
897
+ "borderless", "pills", "segmented_control"
898
+ ] = "segmented_control",
899
+ format_func: Callable[[V], ButtonGroupProto.Option] | None = None,
900
+ deserializer: WidgetDeserializer[T],
901
+ serializer: WidgetSerializer[T],
902
+ on_change: WidgetCallback | None = None,
903
+ args: WidgetArgs | None = None,
904
+ kwargs: WidgetKwargs | None = None,
905
+ selection_visualization: ButtonGroupProto.SelectionVisualization.ValueType = (
906
+ ButtonGroupProto.SelectionVisualization.ONLY_SELECTED
907
+ ),
908
+ label: str | None = None,
909
+ label_visibility: LabelVisibility = "visible",
910
+ help: str | None = None,
911
+ ) -> RegisterWidgetResult[T]:
912
+ _maybe_raise_selection_mode_warning(selection_mode)
913
+
914
+ parsed_selection_mode: ButtonGroupProto.ClickMode.ValueType = (
915
+ ButtonGroupProto.SINGLE_SELECT
916
+ if selection_mode == "single"
917
+ else ButtonGroupProto.MULTI_SELECT
918
+ )
919
+
920
+ # when selection mode is a single-value selection, the default must be a single
921
+ # value too.
922
+ if (
923
+ parsed_selection_mode == ButtonGroupProto.SINGLE_SELECT
924
+ and default is not None
925
+ and isinstance(default, Sequence)
926
+ and len(default) > 1
927
+ ):
928
+ # add more commands to the error message
929
+ raise StreamlitAPIException(
930
+ "The default argument to `st.pills` must be a single value when "
931
+ "`selection_mode='single'`."
932
+ )
933
+
934
+ if style not in ["borderless", "pills", "segmented_control"]:
935
+ raise StreamlitAPIException(
936
+ "The style argument must be one of ['borderless', 'pills', 'segmented_control']. "
937
+ f"The argument passed was '{style}'."
938
+ )
939
+
940
+ key = to_key(key)
941
+
942
+ _default = default
943
+ if default is not None and len(default) == 0:
944
+ _default = None
945
+
946
+ check_widget_policies(self.dg, key, on_change, default_value=_default)
947
+
948
+ widget_name = "button_group"
949
+ ctx = get_script_run_ctx()
950
+ form_id = current_form_id(self.dg)
951
+ formatted_options = (
952
+ indexable_options
953
+ if format_func is None
954
+ else [
955
+ format_func(indexable_options[index])
956
+ for index, _ in enumerate(indexable_options)
957
+ ]
958
+ )
959
+ element_id = compute_and_register_element_id(
960
+ widget_name,
961
+ user_key=key,
962
+ form_id=form_id,
963
+ options=formatted_options,
964
+ default=default,
965
+ click_mode=parsed_selection_mode,
966
+ style=style,
967
+ )
968
+
969
+ proto = _build_proto(
970
+ element_id,
971
+ formatted_options,
972
+ default or [],
973
+ disabled,
974
+ form_id,
975
+ click_mode=parsed_selection_mode,
976
+ selection_visualization=selection_visualization,
977
+ style=style,
978
+ label=label,
979
+ label_visibility=label_visibility,
980
+ help=help,
981
+ )
982
+
983
+ widget_state = register_widget(
984
+ proto.id,
985
+ on_change_handler=on_change,
986
+ args=args,
987
+ kwargs=kwargs,
988
+ deserializer=deserializer,
989
+ serializer=serializer,
990
+ ctx=ctx,
991
+ value_type="int_array_value",
992
+ )
993
+
994
+ if widget_state.value_changed:
995
+ proto.value[:] = serializer(widget_state.value)
996
+ proto.set_value = True
997
+
998
+ if ctx:
999
+ save_for_app_testing(ctx, element_id, format_func)
1000
+
1001
+ self.dg._enqueue(widget_name, proto)
1002
+
1003
+ return widget_state
1004
+
1005
+ @property
1006
+ def dg(self) -> DeltaGenerator:
1007
+ """Get our DeltaGenerator."""
1008
+ return cast("DeltaGenerator", self)