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
@@ -0,0 +1,272 @@
1
+ # Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2025)
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ from dataclasses import dataclass
19
+ from typing import TYPE_CHECKING, Any, cast
20
+
21
+ from streamlit.components.v2.bidi_component.constants import ARROW_REF_KEY
22
+ from streamlit.dataframe_util import convert_anything_to_arrow_bytes, is_dataframe_like
23
+ from streamlit.logger import get_logger
24
+ from streamlit.proto.BidiComponent_pb2 import BidiComponent as BidiComponentProto
25
+ from streamlit.proto.BidiComponent_pb2 import MixedData as MixedDataProto
26
+ from streamlit.util import AttributeDictionary, calc_md5
27
+
28
+ if TYPE_CHECKING:
29
+ from streamlit.components.v2.bidi_component.state import BidiComponentState
30
+
31
+ _LOGGER = get_logger(__name__)
32
+
33
+
34
+ def _extract_dataframes_from_dict(
35
+ data: dict[str, Any], arrow_blobs: dict[str, bytes] | None = None
36
+ ) -> dict[str, Any]:
37
+ """Extract dataframe-like objects from a dictionary and replace them with
38
+ placeholders.
39
+
40
+ This function traverses the first level of a dictionary, detects any
41
+ dataframe-like objects, stores their Arrow bytes representation in the
42
+ `arrow_blobs` dictionary, and replaces them with JSON-serializable
43
+ placeholder objects.
44
+
45
+ Parameters
46
+ ----------
47
+ data
48
+ The dictionary to process. Only the first level is checked for
49
+ dataframe-like objects.
50
+ arrow_blobs
51
+ The dictionary to store the extracted Arrow bytes in, keyed by a unique
52
+ reference ID.
53
+
54
+ Returns
55
+ -------
56
+ dict[str, Any]
57
+ A new dictionary with dataframe-like objects replaced by placeholders.
58
+ """
59
+ if arrow_blobs is None:
60
+ arrow_blobs = {}
61
+
62
+ processed_data = {}
63
+
64
+ for key, value in data.items():
65
+ if is_dataframe_like(value):
66
+ # This is a dataframe-like object, serialize it to Arrow
67
+ try:
68
+ arrow_bytes = convert_anything_to_arrow_bytes(value)
69
+ # Use deterministic, content-addressed ref IDs so placeholders
70
+ # are stable for identical content on each run. This also provides
71
+ # natural deduplication - identical DataFrames share a single blob.
72
+ ref_id = calc_md5(arrow_bytes)
73
+ arrow_blobs[ref_id] = arrow_bytes
74
+ processed_data[key] = {ARROW_REF_KEY: ref_id}
75
+ except Exception as e:
76
+ # If Arrow serialization fails, keep the original value for JSON
77
+ # serialization attempt downstream.
78
+ _LOGGER.debug(
79
+ "Arrow serialization failed for key %r, keeping original value: %s",
80
+ key,
81
+ e,
82
+ )
83
+ processed_data[key] = value
84
+ else:
85
+ # Not dataframe-like, keep as-is
86
+ processed_data[key] = value
87
+
88
+ return processed_data
89
+
90
+
91
+ def serialize_mixed_data(data: Any, bidi_component_proto: BidiComponentProto) -> None:
92
+ """Serialize mixed data with automatic dataframe detection into a protobuf message.
93
+
94
+ This function detects dataframe-like objects in the first level of a dictionary,
95
+ extracts them into separate Arrow blobs, and populates a `MixedDataProto`
96
+ protobuf message for efficient serialization.
97
+
98
+ Parameters
99
+ ----------
100
+ data
101
+ The data structure to serialize. If it is a dictionary, its first
102
+ level will be scanned for dataframe-like objects.
103
+ bidi_component_proto
104
+ The protobuf message to populate with the serialized data.
105
+
106
+ """
107
+ arrow_blobs: dict[str, bytes] = {}
108
+
109
+ # Only process dictionaries for automatic dataframe detection
110
+ if isinstance(data, dict):
111
+ processed_data = _extract_dataframes_from_dict(data, arrow_blobs)
112
+ else:
113
+ # For non-dict data (lists, tuples, etc.), pass through as-is
114
+ # We don't automatically detect dataframes in these structures
115
+ processed_data = data
116
+
117
+ if arrow_blobs:
118
+ # We have dataframes, use mixed data serialization
119
+ mixed_proto = MixedDataProto()
120
+ try:
121
+ mixed_proto.json = json.dumps(processed_data)
122
+ except TypeError:
123
+ # If JSON serialization fails (e.g., due to undetected dataframes),
124
+ # fall back to string representation
125
+ mixed_proto.json = json.dumps(str(processed_data))
126
+
127
+ # Add Arrow blobs to the protobuf
128
+ for ref_id, arrow_bytes in arrow_blobs.items():
129
+ mixed_proto.arrow_blobs[ref_id].data = arrow_bytes
130
+
131
+ bidi_component_proto.mixed.CopyFrom(mixed_proto)
132
+ else:
133
+ # No dataframes found, use regular JSON serialization
134
+ try:
135
+ bidi_component_proto.json = json.dumps(processed_data)
136
+ except TypeError:
137
+ # If JSON serialization fails (e.g., due to dataframes in lists/tuples),
138
+ # fall back to string representation
139
+ bidi_component_proto.json = json.dumps(str(processed_data))
140
+
141
+
142
+ def handle_deserialize(s: str | None) -> Any:
143
+ """Deserialize a JSON string, returning the string itself if it's not valid JSON.
144
+
145
+ Parameters
146
+ ----------
147
+ s
148
+ The string to deserialize.
149
+
150
+ Returns
151
+ -------
152
+ Any
153
+ The deserialized JSON object, or the original string if parsing fails.
154
+ Returns `None` if the input is `None`.
155
+
156
+ """
157
+ if s is None:
158
+ return None
159
+ try:
160
+ return json.loads(s)
161
+ except json.JSONDecodeError:
162
+ return s
163
+
164
+
165
+ def deserialize_trigger_list(s: str | None) -> list[Any] | None:
166
+ """Deserialize trigger aggregator payloads as a list.
167
+
168
+ For bidirectional components, the frontend always sends a JSON array of payload
169
+ objects. This deserializer normalizes older or singular payloads into a list
170
+ while preserving ``None`` for cleared values.
171
+
172
+ Parameters
173
+ ----------
174
+ s
175
+ The JSON string to deserialize, hopefully representing a list of payloads.
176
+
177
+ Returns
178
+ -------
179
+ list[Any] or None
180
+ A list of payloads, or `None` if the input was `None`.
181
+
182
+ """
183
+ value = handle_deserialize(s)
184
+ if value is None:
185
+ return None
186
+ if isinstance(value, list):
187
+ return value
188
+ return [value]
189
+
190
+
191
+ @dataclass
192
+ class BidiComponentSerde:
193
+ """Serialization and deserialization logic for a bidirectional component.
194
+
195
+ This class handles the conversion of component state between the frontend
196
+ (JSON strings) and the backend (Python objects).
197
+
198
+ The canonical shape is a flat mapping of state keys to values.
199
+
200
+ Parameters
201
+ ----------
202
+ default
203
+ A dictionary of default values to be applied to the state when
204
+ deserializing, if the corresponding keys are not already present.
205
+
206
+ """
207
+
208
+ default: dict[str, Any] | None = None
209
+
210
+ def deserialize(self, ui_value: str | dict[str, Any] | None) -> BidiComponentState:
211
+ """Deserialize the component's state from a frontend value.
212
+
213
+ Parameters
214
+ ----------
215
+ ui_value
216
+ The value received from the frontend, which can be a JSON string,
217
+ a dictionary, or `None`.
218
+
219
+ Returns
220
+ -------
221
+ BidiComponentState
222
+ The deserialized state as a flat mapping.
223
+
224
+ """
225
+ # Normalize the incoming JSON payload into a dict. Any failure to decode
226
+ # (or an unexpected non-mapping structure) results in an empty mapping
227
+ # so that the returned type adheres to :class:`BidiComponentState`.
228
+
229
+ deserialized_value: dict[str, Any]
230
+
231
+ if isinstance(ui_value, dict):
232
+ deserialized_value = ui_value
233
+ elif isinstance(ui_value, str):
234
+ try:
235
+ parsed = json.loads(ui_value)
236
+ deserialized_value = parsed if isinstance(parsed, dict) else {}
237
+ except (json.JSONDecodeError, TypeError) as e:
238
+ _LOGGER.warning(
239
+ "Failed to deserialize component state from frontend: %s",
240
+ e,
241
+ exc_info=e,
242
+ )
243
+ deserialized_value = {}
244
+ else:
245
+ deserialized_value = {}
246
+
247
+ # Apply default values for keys that don't exist in the current state
248
+ if self.default is not None:
249
+ for default_key, default_value in self.default.items():
250
+ if default_key not in deserialized_value:
251
+ deserialized_value[default_key] = default_value
252
+
253
+ state: BidiComponentState = cast(
254
+ "BidiComponentState", AttributeDictionary(deserialized_value)
255
+ )
256
+ return state
257
+
258
+ def serialize(self, value: Any) -> str:
259
+ """Serialize the component's state into a JSON string for the frontend.
260
+
261
+ Parameters
262
+ ----------
263
+ value
264
+ The component state to serialize.
265
+
266
+ Returns
267
+ -------
268
+ str
269
+ A JSON string representation of the value.
270
+
271
+ """
272
+ return json.dumps(value)
@@ -0,0 +1,92 @@
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 typing import Any, TypedDict
18
+
19
+ from streamlit.util import AttributeDictionary
20
+
21
+
22
+ class BidiComponentState(TypedDict, total=False):
23
+ """
24
+ The schema for the state of a bidirectional component.
25
+
26
+ The state is a flat dictionary-like object (key -> value) that supports
27
+ both key and attribute notation via :class:`AttributeDictionary`.
28
+ """
29
+
30
+ # Flat mapping of state key -> value
31
+ # (kept empty to reflect open set of keys)
32
+
33
+
34
+ class BidiComponentResult(AttributeDictionary):
35
+ """The schema for the custom component result object.
36
+
37
+ The custom component result object is a dictionary-like object that
38
+ supports both key and attribute notation. It contains all of the
39
+ component's state and trigger values.
40
+
41
+ Attributes
42
+ ----------
43
+ <state_keys> : Any
44
+ All state values from the component. State values are persistent across
45
+ app reruns until explicitly changed. You can have multiple state keys
46
+ as attributes.
47
+ <trigger_keys> : Any
48
+ All trigger values from the component. Trigger values are transient and
49
+ reset to ``None`` after one script run. You can have multiple trigger
50
+ keys as attributes.
51
+
52
+ """
53
+
54
+ def __init__(
55
+ self,
56
+ state_vals: dict[str, Any] | None = None,
57
+ trigger_vals: dict[str, Any] | None = None,
58
+ ) -> None:
59
+ """Initialize a BidiComponentResult.
60
+
61
+ Parameters
62
+ ----------
63
+ state_vals : dict[str, Any] or None
64
+ A dictionary of state values from the component.
65
+ trigger_vals : dict[str, Any] or None
66
+ A dictionary of trigger values from the component.
67
+ """
68
+ if state_vals is None:
69
+ state_vals = {}
70
+ if trigger_vals is None:
71
+ trigger_vals = {}
72
+
73
+ super().__init__(
74
+ {
75
+ # The order here matters, because all stateful values will
76
+ # always be returned, but trigger values may be transient. This
77
+ # mirrors presentation behavior in
78
+ # `make_bidi_component_presenter`.
79
+ **trigger_vals,
80
+ **state_vals,
81
+ }
82
+ )
83
+
84
+
85
+ def unwrap_component_state(raw_state: Any) -> dict[str, Any]:
86
+ """Return flat mapping when given a dict; otherwise, empty dict.
87
+
88
+ The new canonical state is flat, so this is effectively an identity for
89
+ dict inputs and a guard for other types.
90
+ """
91
+
92
+ return dict(raw_state) if isinstance(raw_state, dict) else {}
@@ -0,0 +1,143 @@
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
+ """Shared resolver for building component definitions with path validation.
16
+
17
+ This module centralizes the logic for interpreting js/css inputs as inline
18
+ content vs path/glob strings, validating them against a component's asset
19
+ directory, and producing a BidiComponentDefinition with correct asset-relative
20
+ URLs used by the server.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ from pathlib import Path
26
+ from typing import TYPE_CHECKING
27
+
28
+ from streamlit.components.v2.component_path_utils import ComponentPathUtils
29
+ from streamlit.components.v2.component_registry import BidiComponentDefinition
30
+ from streamlit.errors import StreamlitAPIException
31
+
32
+ if TYPE_CHECKING:
33
+ from streamlit.components.v2.component_manager import BidiComponentManager
34
+
35
+
36
+ def build_definition_with_validation(
37
+ *,
38
+ manager: BidiComponentManager,
39
+ component_key: str,
40
+ html: str | None,
41
+ css: str | None,
42
+ js: str | None,
43
+ ) -> BidiComponentDefinition:
44
+ """Construct a definition and validate ``js``/``css`` inputs against ``asset_dir``.
45
+
46
+ Parameters
47
+ ----------
48
+ manager : BidiComponentManager
49
+ Component manager used to resolve the component's ``asset_dir`` and
50
+ related metadata.
51
+ component_key : str
52
+ Fully-qualified name of the component to build a definition for.
53
+ html : str | None
54
+ Inline HTML content to include in the definition. If ``None``, the
55
+ component will not include HTML content.
56
+ css : str | None
57
+ Either inline CSS content or a path/glob to a CSS file inside the
58
+ component's ``asset_dir``. Inline strings are kept as-is; file-backed
59
+ inputs are validated and converted to an ``asset_dir``-relative URL.
60
+ js : str | None
61
+ Either inline JavaScript content or a path/glob to a JS file inside the
62
+ component's ``asset_dir``. Inline strings are kept as-is; file-backed
63
+ inputs are validated and converted to an ``asset_dir``-relative URL.
64
+
65
+ Returns
66
+ -------
67
+ BidiComponentDefinition
68
+ A component definition with inline content preserved and file-backed
69
+ entries resolved to absolute filesystem paths plus their
70
+ ``asset_dir``-relative URLs.
71
+
72
+ Raises
73
+ ------
74
+ StreamlitAPIException
75
+ If a path/glob is provided but the component has no declared
76
+ ``asset_dir``, if a glob resolves to zero or multiple files, or if any
77
+ resolved path escapes the declared ``asset_dir``.
78
+
79
+ Notes
80
+ -----
81
+ - Inline strings are treated as content (no manifest required).
82
+ - Path-like strings require the component to be declared in the package
83
+ manifest with an ``asset_dir``.
84
+ - Globs are supported only within ``asset_dir`` and must resolve to exactly
85
+ one file.
86
+ - Relative paths are resolved strictly against the component's ``asset_dir``
87
+ and must remain within it after resolution. Absolute paths are not
88
+ allowed.
89
+ - For file-backed entries, the URL sent to the frontend is the
90
+ ``asset_dir``-relative path, served under
91
+ ``/_stcore/bidi-components/<component>/<relative_path>``.
92
+ """
93
+
94
+ asset_root = manager.get_component_asset_root(component_key)
95
+
96
+ def _resolve_entry(
97
+ value: str | None, *, kind: str
98
+ ) -> tuple[str | None, str | None]:
99
+ # Inline content: None rel URL
100
+ if value is None:
101
+ return None, None
102
+ if ComponentPathUtils.looks_like_inline_content(value):
103
+ return value, None
104
+
105
+ # For path-like strings, asset_root must exist
106
+ if asset_root is None:
107
+ raise StreamlitAPIException(
108
+ f"Component '{component_key}' must be declared in pyproject.toml with asset_dir "
109
+ f"to use file-backed {kind}."
110
+ )
111
+
112
+ value_str = value
113
+
114
+ # If looks like a glob, resolve strictly inside asset_root
115
+ if ComponentPathUtils.has_glob_characters(value_str):
116
+ resolved = ComponentPathUtils.resolve_glob_pattern(value_str, asset_root)
117
+ ComponentPathUtils.ensure_within_root(resolved, asset_root, kind=kind)
118
+ # Use resolved absolute paths to avoid macOS /private prefix mismatch
119
+ rel_url = str(
120
+ resolved.resolve().relative_to(asset_root.resolve()).as_posix()
121
+ )
122
+ return str(resolved), rel_url
123
+
124
+ # Concrete path: must be asset-dir-relative (reject absolute & traversal)
125
+ ComponentPathUtils.validate_path_security(value_str)
126
+ candidate = asset_root / Path(value_str)
127
+ ComponentPathUtils.ensure_within_root(candidate, asset_root, kind=kind)
128
+ resolved_candidate = candidate.resolve()
129
+ rel_url = str(resolved_candidate.relative_to(asset_root.resolve()).as_posix())
130
+ return str(resolved_candidate), rel_url
131
+
132
+ css_value, css_rel = _resolve_entry(css, kind="css")
133
+ js_value, js_rel = _resolve_entry(js, kind="js")
134
+
135
+ # Build definition with possible asset_dir-relative paths
136
+ return BidiComponentDefinition(
137
+ name=component_key,
138
+ html=html,
139
+ css=css_value,
140
+ js=js_value,
141
+ css_asset_relative_path=css_rel,
142
+ js_asset_relative_path=js_rel,
143
+ )