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.
- streamlit/__init__.py +5 -1
- streamlit/commands/execution_control.py +89 -14
- streamlit/commands/navigation.py +4 -6
- streamlit/commands/page_config.py +4 -6
- streamlit/components/v1/component_arrow.py +7 -7
- streamlit/components/v2/__init__.py +514 -0
- streamlit/components/v2/bidi_component/__init__.py +20 -0
- streamlit/components/v2/bidi_component/constants.py +29 -0
- streamlit/components/v2/bidi_component/main.py +534 -0
- streamlit/components/v2/bidi_component/serialization.py +272 -0
- streamlit/components/v2/bidi_component/state.py +92 -0
- streamlit/components/v2/component_definition_resolver.py +143 -0
- streamlit/components/v2/component_file_watcher.py +403 -0
- streamlit/components/v2/component_manager.py +439 -0
- streamlit/components/v2/component_manifest_handler.py +122 -0
- streamlit/components/v2/component_path_utils.py +245 -0
- streamlit/components/v2/component_registry.py +426 -0
- streamlit/components/v2/get_bidi_component_manager.py +51 -0
- streamlit/components/v2/manifest_scanner.py +615 -0
- streamlit/components/v2/presentation.py +198 -0
- streamlit/components/v2/types.py +324 -0
- streamlit/config.py +456 -53
- streamlit/config_option.py +4 -1
- streamlit/config_util.py +650 -1
- streamlit/connections/snowflake_connection.py +1 -1
- streamlit/connections/snowpark_connection.py +1 -1
- streamlit/dataframe_util.py +33 -26
- streamlit/delta_generator.py +13 -4
- streamlit/delta_generator_singletons.py +11 -15
- streamlit/deprecation_util.py +17 -6
- streamlit/elements/alert.py +16 -0
- streamlit/elements/arrow.py +68 -10
- streamlit/elements/bokeh_chart.py +10 -78
- streamlit/elements/code.py +2 -2
- streamlit/elements/deck_gl_json_chart.py +98 -40
- streamlit/elements/dialog_decorator.py +2 -1
- streamlit/elements/exception.py +4 -2
- streamlit/elements/form.py +27 -0
- streamlit/elements/graphviz_chart.py +1 -3
- streamlit/elements/heading.py +63 -10
- streamlit/elements/html.py +13 -2
- streamlit/elements/image.py +3 -5
- streamlit/elements/layouts.py +59 -33
- streamlit/elements/lib/built_in_chart_utils.py +50 -19
- streamlit/elements/lib/color_util.py +9 -19
- streamlit/elements/lib/column_config_utils.py +9 -12
- streamlit/elements/lib/column_types.py +40 -12
- streamlit/elements/lib/dialog.py +2 -2
- streamlit/elements/lib/image_utils.py +3 -5
- streamlit/elements/lib/layout_utils.py +100 -13
- streamlit/elements/lib/mutable_status_container.py +2 -2
- streamlit/elements/lib/options_selector_utils.py +2 -2
- streamlit/elements/lib/pandas_styler_utils.py +17 -9
- streamlit/elements/lib/shortcut_utils.py +152 -0
- streamlit/elements/lib/utils.py +4 -4
- streamlit/elements/map.py +80 -37
- streamlit/elements/markdown.py +50 -3
- streamlit/elements/media.py +5 -7
- streamlit/elements/metric.py +34 -6
- streamlit/elements/pdf.py +2 -4
- streamlit/elements/plotly_chart.py +197 -20
- streamlit/elements/progress.py +2 -4
- streamlit/elements/space.py +113 -0
- streamlit/elements/spinner.py +1 -1
- streamlit/elements/text.py +20 -3
- streamlit/elements/toast.py +2 -0
- streamlit/elements/vega_charts.py +356 -149
- streamlit/elements/widgets/audio_input.py +12 -11
- streamlit/elements/widgets/button.py +280 -43
- streamlit/elements/widgets/button_group.py +60 -9
- streamlit/elements/widgets/camera_input.py +3 -5
- streamlit/elements/widgets/chat.py +307 -43
- streamlit/elements/widgets/color_picker.py +8 -1
- streamlit/elements/widgets/data_editor.py +88 -44
- streamlit/elements/widgets/file_uploader.py +9 -11
- streamlit/elements/widgets/multiselect.py +4 -3
- streamlit/elements/widgets/number_input.py +4 -4
- streamlit/elements/widgets/radio.py +10 -3
- streamlit/elements/widgets/select_slider.py +8 -5
- streamlit/elements/widgets/selectbox.py +6 -3
- streamlit/elements/widgets/slider.py +38 -42
- streamlit/elements/widgets/text_widgets.py +2 -0
- streamlit/elements/widgets/time_widgets.py +587 -21
- streamlit/elements/write.py +27 -6
- streamlit/emojis.py +1 -1
- streamlit/errors.py +137 -0
- streamlit/git_util.py +1 -1
- streamlit/hello/hello.py +8 -0
- streamlit/hello/utils.py +2 -1
- streamlit/material_icon_names.py +1 -1
- streamlit/navigation/page.py +11 -1
- streamlit/net_util.py +2 -2
- streamlit/proto/Alert_pb2.pyi +3 -3
- streamlit/proto/AppPage_pb2.pyi +7 -1
- streamlit/proto/ArrowData_pb2.py +27 -0
- streamlit/proto/ArrowData_pb2.pyi +52 -0
- streamlit/proto/ArrowNamedDataSet_pb2.pyi +7 -1
- streamlit/proto/ArrowVegaLiteChart_pb2.pyi +7 -1
- streamlit/proto/Arrow_pb2.py +10 -10
- streamlit/proto/Arrow_pb2.pyi +19 -12
- streamlit/proto/AudioInput_pb2.pyi +7 -1
- streamlit/proto/Audio_pb2.pyi +7 -1
- streamlit/proto/AuthRedirect_pb2.pyi +7 -1
- streamlit/proto/AutoRerun_pb2.pyi +7 -1
- streamlit/proto/BackMsg_pb2.py +4 -2
- streamlit/proto/BackMsg_pb2.pyi +34 -4
- streamlit/proto/Balloons_pb2.pyi +7 -1
- streamlit/proto/BidiComponent_pb2.py +34 -0
- streamlit/proto/BidiComponent_pb2.pyi +159 -0
- streamlit/proto/Block_pb2.py +7 -7
- streamlit/proto/Block_pb2.pyi +39 -36
- streamlit/proto/BokehChart_pb2.pyi +7 -1
- streamlit/proto/ButtonGroup_pb2.pyi +9 -9
- streamlit/proto/Button_pb2.py +2 -2
- streamlit/proto/Button_pb2.pyi +11 -2
- streamlit/proto/CameraInput_pb2.pyi +7 -1
- streamlit/proto/ChatInput_pb2.py +6 -6
- streamlit/proto/ChatInput_pb2.pyi +18 -6
- streamlit/proto/Checkbox_pb2.pyi +3 -3
- streamlit/proto/ClientState_pb2.pyi +10 -4
- streamlit/proto/Code_pb2.pyi +7 -1
- streamlit/proto/ColorPicker_pb2.pyi +7 -1
- streamlit/proto/Common_pb2.py +3 -3
- streamlit/proto/Common_pb2.pyi +35 -23
- streamlit/proto/Components_pb2.pyi +19 -13
- streamlit/proto/DataFrame_pb2.pyi +55 -49
- streamlit/proto/DateInput_pb2.pyi +7 -1
- streamlit/proto/DateTimeInput_pb2.py +28 -0
- streamlit/proto/DateTimeInput_pb2.pyi +92 -0
- streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
- streamlit/proto/DeckGlJsonChart_pb2.pyi +12 -6
- streamlit/proto/Delta_pb2.pyi +7 -1
- streamlit/proto/DocString_pb2.pyi +10 -4
- streamlit/proto/DownloadButton_pb2.py +2 -2
- streamlit/proto/DownloadButton_pb2.pyi +16 -2
- streamlit/proto/Element_pb2.py +7 -3
- streamlit/proto/Element_pb2.pyi +33 -5
- streamlit/proto/Empty_pb2.pyi +7 -1
- streamlit/proto/Exception_pb2.pyi +7 -1
- streamlit/proto/Favicon_pb2.pyi +7 -1
- streamlit/proto/FileUploader_pb2.pyi +7 -1
- streamlit/proto/ForwardMsg_pb2.py +12 -10
- streamlit/proto/ForwardMsg_pb2.pyi +42 -15
- streamlit/proto/GapSize_pb2.pyi +4 -4
- streamlit/proto/GitInfo_pb2.pyi +3 -3
- streamlit/proto/GraphVizChart_pb2.pyi +7 -1
- streamlit/proto/Heading_pb2.pyi +7 -1
- streamlit/proto/HeightConfig_pb2.py +2 -2
- streamlit/proto/HeightConfig_pb2.pyi +13 -4
- streamlit/proto/Html_pb2.py +2 -2
- streamlit/proto/Html_pb2.pyi +11 -2
- streamlit/proto/IFrame_pb2.pyi +7 -1
- streamlit/proto/Image_pb2.pyi +10 -4
- streamlit/proto/Json_pb2.pyi +7 -1
- streamlit/proto/LabelVisibilityMessage_pb2.pyi +3 -3
- streamlit/proto/LinkButton_pb2.py +2 -2
- streamlit/proto/LinkButton_pb2.pyi +15 -2
- streamlit/proto/Logo_pb2.pyi +7 -1
- streamlit/proto/Markdown_pb2.pyi +3 -3
- streamlit/proto/Metric_pb2.pyi +7 -7
- streamlit/proto/MetricsEvent_pb2.pyi +10 -4
- streamlit/proto/MultiSelect_pb2.pyi +7 -1
- streamlit/proto/NamedDataSet_pb2.pyi +7 -1
- streamlit/proto/Navigation_pb2.pyi +3 -3
- streamlit/proto/NewSession_pb2.py +18 -18
- streamlit/proto/NewSession_pb2.pyi +59 -40
- streamlit/proto/NumberInput_pb2.pyi +3 -3
- streamlit/proto/PageConfig_pb2.pyi +7 -7
- streamlit/proto/PageInfo_pb2.pyi +7 -1
- streamlit/proto/PageLink_pb2.py +2 -2
- streamlit/proto/PageLink_pb2.pyi +11 -2
- streamlit/proto/PageNotFound_pb2.pyi +7 -1
- streamlit/proto/PageProfile_pb2.pyi +13 -7
- streamlit/proto/PagesChanged_pb2.pyi +7 -1
- streamlit/proto/ParentMessage_pb2.pyi +7 -1
- streamlit/proto/PlotlyChart_pb2.py +8 -6
- streamlit/proto/PlotlyChart_pb2.pyi +9 -7
- streamlit/proto/Progress_pb2.pyi +7 -1
- streamlit/proto/Radio_pb2.pyi +7 -1
- streamlit/proto/RootContainer_pb2.pyi +1 -1
- streamlit/proto/Selectbox_pb2.pyi +7 -1
- streamlit/proto/SessionEvent_pb2.pyi +7 -1
- streamlit/proto/SessionStatus_pb2.pyi +7 -1
- streamlit/proto/Skeleton_pb2.pyi +3 -3
- streamlit/proto/Slider_pb2.pyi +5 -5
- streamlit/proto/Snow_pb2.pyi +7 -1
- streamlit/proto/Space_pb2.py +27 -0
- streamlit/proto/Space_pb2.pyi +48 -0
- streamlit/proto/Spinner_pb2.pyi +7 -1
- streamlit/proto/TextAlignmentConfig_pb2.py +29 -0
- streamlit/proto/TextAlignmentConfig_pb2.pyi +68 -0
- streamlit/proto/TextArea_pb2.pyi +7 -1
- streamlit/proto/TextInput_pb2.pyi +3 -3
- streamlit/proto/Text_pb2.pyi +7 -1
- streamlit/proto/TimeInput_pb2.pyi +7 -1
- streamlit/proto/Toast_pb2.pyi +7 -1
- streamlit/proto/VegaLiteChart_pb2.pyi +7 -1
- streamlit/proto/Video_pb2.pyi +6 -6
- streamlit/proto/WidgetStates_pb2.py +2 -2
- streamlit/proto/WidgetStates_pb2.pyi +23 -7
- streamlit/proto/WidthConfig_pb2.py +2 -2
- streamlit/proto/WidthConfig_pb2.pyi +13 -4
- streamlit/proto/openmetrics_data_model_pb2.pyi +52 -52
- streamlit/runtime/app_session.py +65 -2
- streamlit/runtime/caching/cache_data_api.py +5 -5
- streamlit/runtime/caching/cache_errors.py +4 -1
- streamlit/runtime/caching/cache_resource_api.py +5 -4
- streamlit/runtime/caching/cache_utils.py +3 -2
- streamlit/runtime/caching/cached_message_replay.py +3 -3
- streamlit/runtime/caching/hashing.py +4 -5
- streamlit/runtime/caching/legacy_cache_api.py +2 -1
- streamlit/runtime/connection_factory.py +1 -3
- streamlit/runtime/download_data_util.py +53 -0
- streamlit/runtime/forward_msg_queue.py +5 -1
- streamlit/runtime/fragment.py +2 -1
- streamlit/runtime/media_file_manager.py +178 -2
- streamlit/runtime/memory_media_file_storage.py +1 -1
- streamlit/runtime/metrics_util.py +91 -3
- streamlit/runtime/runtime.py +14 -0
- streamlit/runtime/scriptrunner/exec_code.py +2 -1
- streamlit/runtime/scriptrunner/script_runner.py +5 -3
- streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
- streamlit/runtime/secrets.py +2 -4
- streamlit/runtime/session_manager.py +3 -1
- streamlit/runtime/state/common.py +30 -5
- streamlit/runtime/state/presentation.py +85 -0
- streamlit/runtime/state/query_params.py +80 -29
- streamlit/runtime/state/safe_session_state.py +2 -2
- streamlit/runtime/state/session_state.py +221 -17
- streamlit/runtime/state/widgets.py +19 -3
- streamlit/runtime/websocket_session_manager.py +3 -1
- streamlit/source_util.py +2 -2
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +557 -239
- streamlit/static/static/css/{index.CIiu7Ygf.css → index.BpABIXK9.css} +1 -1
- streamlit/static/static/css/index.DgR7E2CV.css +1 -0
- streamlit/static/static/js/{ErrorOutline.esm.DUpR0_Ka.js → ErrorOutline.esm.ZJDbmVTx.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.CN4j9-1w.js → FileDownload.esm.Dx0vI3vH.js} +1 -1
- streamlit/static/static/js/{FileHelper.CaIUKG91.js → FileHelper.B7Ero7qQ.js} +3 -3
- streamlit/static/static/js/{FormClearHelper.DTcdrasw.js → FormClearHelper.CG2XN1_g.js} +1 -1
- streamlit/static/static/js/IFrameUtil.DefezniK.js +1 -0
- streamlit/static/static/js/InputInstructions.Cj5-1zf6.js +1 -0
- streamlit/static/static/js/Particles.BfWfv0Aw.js +1 -0
- streamlit/static/static/js/{ProgressBar.DetlP5aY.js → ProgressBar.CGQ8OgfO.js} +2 -2
- streamlit/static/static/js/StreamlitSyntaxHighlighter.DTKLpwhl.js +20 -0
- streamlit/static/static/js/{Toolbar.C77ar7rq.js → Toolbar.B2qFUmd9.js} +1 -1
- streamlit/static/static/js/_arrayIncludes.B19Iyn2B.js +1 -0
- streamlit/static/static/js/_baseIndexOf.BTknn6Gb.js +1 -0
- streamlit/static/static/js/{base-input.BQft14La.js → base-input.o9tL8MDP.js} +4 -4
- streamlit/static/static/js/{checkbox.yZOfXCeX.js → checkbox.0BeV1IBL.js} +1 -1
- streamlit/static/static/js/{createSuper.Dh9w1cs8.js → createSuper.RBO59fEm.js} +1 -1
- streamlit/static/static/js/data-grid-overlay-editor.CiTkUy0t.js +1 -0
- streamlit/static/static/js/{downloader.MeHtkq8r.js → downloader.DwNZg3Mw.js} +1 -1
- streamlit/static/static/js/embed.XT9xNd3F.js +195 -0
- streamlit/static/static/js/{es6.VpBPGCnM.js → es6.x9KsYQg-.js} +2 -2
- streamlit/static/static/js/{iframeResizer.contentWindow.yMw_ARIL.js → iframeResizer.contentWindow.ZVXpMPi0.js} +1 -1
- streamlit/static/static/js/index.5VPOamri.js +1 -0
- streamlit/static/static/js/index.8HslT92O.js +14 -0
- streamlit/static/static/js/index.AnXMIBz3.js +7 -0
- streamlit/static/static/js/index.B0yp3bM1.js +6 -0
- streamlit/static/static/js/index.B1fRb5wF.js +1 -0
- streamlit/static/static/js/index.B527JZdO.js +3 -0
- streamlit/static/static/js/index.BHgV-yW4.js +1 -0
- streamlit/static/static/js/index.BQr-XwGV.js +1 -0
- streamlit/static/static/js/index.BTtmaLDB.js +1 -0
- streamlit/static/static/js/index.BWB_91TA.js +1 -0
- streamlit/static/static/js/index.BfEKaEmw.js +1 -0
- streamlit/static/static/js/index.BfXjTO8b.js +1 -0
- streamlit/static/static/js/index.Bjy4NRu9.js +3 -0
- streamlit/static/static/js/index.Bu5JWpT_.js +1 -0
- streamlit/static/static/js/index.BuCx76ZV.js +1 -0
- streamlit/static/static/js/index.BxjzhVUb.js +2 -0
- streamlit/static/static/js/index.By55VdPY.js +1 -0
- streamlit/static/static/js/index.CF5MxTbK.js +1 -0
- streamlit/static/static/js/index.CLmq_z9K.js +1 -0
- streamlit/static/static/js/index.CNH4rdSz.js +1 -0
- streamlit/static/static/js/{index.B0H9IXUJ.js → index.CTgm_-jO.js} +10 -41
- streamlit/static/static/js/index.C_rK-Swb.js +188 -0
- streamlit/static/static/js/index.CjozwSzS.js +1 -0
- streamlit/static/static/js/{index.CH1tqnSs.js → index.CkGVt6-G.js} +1 -1
- streamlit/static/static/js/index.CuvXOyER.js +2 -0
- streamlit/static/static/js/{index.FFOzOWzC.js → index.CyUHWoCC.js} +2 -2
- streamlit/static/static/js/index.CyroQtI4.js +2 -0
- streamlit/static/static/js/index.D6HmkoDm.js +263 -0
- streamlit/static/static/js/index.DAqCNvsO.js +1 -0
- streamlit/static/static/js/index.DB_w_CZQ.js +1 -0
- streamlit/static/static/js/index.DBalctjj.js +2 -0
- streamlit/static/static/js/index.DK0RFJUG.js +11 -0
- streamlit/static/static/js/index.DMxc2XFp.js +151 -0
- streamlit/static/static/js/index.DO5utP74.js +2 -0
- streamlit/static/static/js/index.DS7lf09n.js +1 -0
- streamlit/static/static/js/index.DWexTVLY.js +1 -0
- streamlit/static/static/js/index.DXxnU5ej.js +1 -0
- streamlit/static/static/js/index.DcU3uDvB.js +2 -0
- streamlit/static/static/js/index.DlltaH7J.js +1 -0
- streamlit/static/static/js/index.DpNTZz82.js +27 -0
- streamlit/static/static/js/index.Dr9HIhQw.js +1 -0
- streamlit/static/static/js/index.DsgAU5lc.js +1 -0
- streamlit/static/static/js/{index.64ejlaaT.js → index.KfXqjDYy.js} +1 -1
- streamlit/static/static/js/index.PaidgjCs.js +1 -0
- streamlit/static/static/js/index.RJZuWCGA.js +1 -0
- streamlit/static/static/js/{index.Ctn27_AE.js → index.hbeqcRTn.js} +53 -122
- streamlit/static/static/js/index.q5hIQwAY.js +1 -0
- streamlit/static/static/js/index.rORSX6IW.js +1 -0
- streamlit/static/static/js/index.uSX757_v.js +1 -0
- streamlit/static/static/js/index.x_QRaLMd.js +1 -0
- streamlit/static/static/js/{input.s6pjQ49A.js → input.D5oh9-aB.js} +2 -2
- streamlit/static/static/js/main.q9oGOg0H.js +13 -0
- streamlit/static/static/js/{memory.Cuvsdfrl.js → memory.5kCSFUJS.js} +1 -1
- streamlit/static/static/js/moment.C3j7ZXd7.js +4 -0
- streamlit/static/static/js/number-overlay-editor.Cn_LsK8N.js +9 -0
- streamlit/static/static/js/pandasStylerUtils.BqhXt51_.js +1 -0
- streamlit/static/static/js/{possibleConstructorReturn.CqidKeei.js → possibleConstructorReturn.DD9NK1Z8.js} +1 -1
- streamlit/static/static/js/record.B-tDciZb.js +1 -0
- streamlit/static/static/js/{sandbox.CCQREcJx.js → sandbox.DACSyz29.js} +1 -1
- streamlit/static/static/js/styled-components.C3R090At.js +1 -0
- streamlit/static/static/js/threshold.Q1mXg5rX.js +1 -0
- streamlit/static/static/js/throttle.B0GR3Iyz.js +1 -0
- streamlit/static/static/js/{timepicker.mkJF97Bb.js → timepicker.BdhzPxrv.js} +1 -1
- streamlit/static/static/js/timer.C2hYhUse.js +1 -0
- streamlit/static/static/js/{toConsumableArray.De7I7KVR.js → toConsumableArray.Db2pdqM2.js} +1 -1
- streamlit/static/static/js/uniqueId.CtqIr-Yh.js +1 -0
- streamlit/static/static/js/urls.BwSlolu9.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.CedkNjUW.js → useBasicWidgetState.Bfp6TnSw.js} +1 -1
- streamlit/static/static/js/useIntlLocale.hRV75Xgj.js +12 -0
- streamlit/static/static/js/{useTextInputAutoExpand.Ca7w8dVs.js → useTextInputAutoExpand.QepX7n8Y.js} +1 -1
- streamlit/static/static/js/useUpdateUiValue.DHx8TzX6.js +1 -0
- streamlit/static/static/js/useWaveformController.WxVzpzEX.js +1 -0
- streamlit/static/static/js/value.B4vHRSi7.js +1 -0
- streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
- streamlit/static/static/js/withCalculatedWidth.DcKeRSWJ.js +1 -0
- streamlit/static/static/js/withFullScreenWrapper.CrHddARq.js +1 -0
- streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
- streamlit/string_util.py +9 -4
- streamlit/testing/v1/app_test.py +17 -2
- streamlit/testing/v1/element_tree.py +85 -9
- streamlit/testing/v1/util.py +2 -2
- streamlit/type_util.py +3 -4
- streamlit/url_util.py +1 -3
- streamlit/user_info.py +1 -2
- streamlit/util.py +3 -1
- streamlit/watcher/event_based_path_watcher.py +23 -12
- streamlit/watcher/local_sources_watcher.py +11 -1
- streamlit/watcher/path_watcher.py +9 -6
- streamlit/watcher/polling_path_watcher.py +4 -1
- streamlit/watcher/util.py +2 -2
- streamlit/web/bootstrap.py +24 -0
- streamlit/web/cli.py +51 -22
- streamlit/web/server/bidi_component_request_handler.py +193 -0
- streamlit/web/server/component_file_utils.py +97 -0
- streamlit/web/server/component_request_handler.py +8 -21
- streamlit/web/server/oauth_authlib_routes.py +5 -2
- streamlit/web/server/oidc_mixin.py +3 -1
- streamlit/web/server/routes.py +2 -2
- streamlit/web/server/server.py +9 -0
- streamlit/web/server/server_util.py +3 -1
- streamlit/web/server/upload_file_request_handler.py +19 -1
- {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/METADATA +10 -7
- streamlit-1.52.0.dist-info/RECORD +620 -0
- streamlit/static/static/css/index.CHEnSPGk.css +0 -1
- streamlit/static/static/js/Hooks.BRba_Own.js +0 -1
- streamlit/static/static/js/InputInstructions.xnSDuYeQ.js +0 -1
- streamlit/static/static/js/Particles.CElH0XX2.js +0 -1
- streamlit/static/static/js/data-grid-overlay-editor.DcuHuCyW.js +0 -1
- streamlit/static/static/js/index.6xX1278W.js +0 -975
- streamlit/static/static/js/index.B-hiXRzw.js +0 -1
- streamlit/static/static/js/index.B4cAbHP6.js +0 -1
- streamlit/static/static/js/index.B4dUQfni.js +0 -1
- streamlit/static/static/js/index.BPQo7BKk.js +0 -1
- streamlit/static/static/js/index.Baqa90pe.js +0 -2
- streamlit/static/static/js/index.Bj9JgOEC.js +0 -1
- streamlit/static/static/js/index.BjCwMzj4.js +0 -3
- streamlit/static/static/js/index.Bm3VbPB5.js +0 -1
- streamlit/static/static/js/index.Bxz2yX3P.js +0 -1
- streamlit/static/static/js/index.BycLveZ4.js +0 -1
- streamlit/static/static/js/index.C9BdUqTi.js +0 -1
- streamlit/static/static/js/index.CFMf5_ez.js +0 -197
- streamlit/static/static/js/index.CGYqqs6j.js +0 -1
- streamlit/static/static/js/index.CMItVsFA.js +0 -1
- streamlit/static/static/js/index.CTBk8Vk2.js +0 -1
- streamlit/static/static/js/index.CiAQIz1H.js +0 -7
- streamlit/static/static/js/index.Cj7DSzVR.js +0 -73
- streamlit/static/static/js/index.Ck8rQ9OL.js +0 -1
- streamlit/static/static/js/index.ClELlchS.js +0 -1617
- streamlit/static/static/js/index.Cnpi3o3E.js +0 -1
- streamlit/static/static/js/index.D2QEXQq_.js +0 -1
- streamlit/static/static/js/index.DH71Ezyj.js +0 -1
- streamlit/static/static/js/index.DHh-U0dK.js +0 -3
- streamlit/static/static/js/index.DK7hD7_w.js +0 -1
- streamlit/static/static/js/index.DKv_lNO7.js +0 -2
- streamlit/static/static/js/index.DNLrMXgm.js +0 -12
- streamlit/static/static/js/index.DW0Grddz.js +0 -1
- streamlit/static/static/js/index.Dbe-Q3C-.js +0 -2
- streamlit/static/static/js/index.DcPNYEUo.js +0 -1
- streamlit/static/static/js/index.DuxqVQpd.js +0 -1
- streamlit/static/static/js/index.GRUzrudl.js +0 -1
- streamlit/static/static/js/number-overlay-editor.DdgVR5m3.js +0 -9
- streamlit/static/static/js/uniqueId.RI1LJdtz.js +0 -1
- streamlit/static/static/js/useUpdateUiValue.DeXelfRH.js +0 -1
- streamlit/static/static/js/withFullScreenWrapper.C3561XxJ.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.DeCZgS-4.woff2 +0 -0
- streamlit-1.50.0.dist-info/RECORD +0 -557
- {streamlit-1.50.0.data → streamlit-1.52.0.data}/scripts/streamlit.cmd +0 -0
- {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/WHEEL +0 -0
- {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/entry_points.txt +0 -0
- {streamlit-1.50.0.dist-info → streamlit-1.52.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,534 @@
|
|
|
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 collections.abc import Mapping
|
|
19
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
20
|
+
|
|
21
|
+
from streamlit.components.v2.bidi_component.constants import (
|
|
22
|
+
EVENT_DELIM,
|
|
23
|
+
INTERNAL_COMPONENT_NAME,
|
|
24
|
+
)
|
|
25
|
+
from streamlit.components.v2.bidi_component.serialization import (
|
|
26
|
+
BidiComponentSerde,
|
|
27
|
+
deserialize_trigger_list,
|
|
28
|
+
serialize_mixed_data,
|
|
29
|
+
)
|
|
30
|
+
from streamlit.components.v2.bidi_component.state import (
|
|
31
|
+
BidiComponentResult,
|
|
32
|
+
unwrap_component_state,
|
|
33
|
+
)
|
|
34
|
+
from streamlit.components.v2.presentation import make_bidi_component_presenter
|
|
35
|
+
from streamlit.dataframe_util import (
|
|
36
|
+
DataFormat,
|
|
37
|
+
convert_anything_to_arrow_bytes,
|
|
38
|
+
determine_data_format,
|
|
39
|
+
)
|
|
40
|
+
from streamlit.elements.lib.form_utils import current_form_id
|
|
41
|
+
from streamlit.elements.lib.layout_utils import (
|
|
42
|
+
Height,
|
|
43
|
+
LayoutConfig,
|
|
44
|
+
Width,
|
|
45
|
+
validate_width,
|
|
46
|
+
)
|
|
47
|
+
from streamlit.elements.lib.policies import check_cache_replay_rules
|
|
48
|
+
from streamlit.elements.lib.utils import compute_and_register_element_id, to_key
|
|
49
|
+
from streamlit.errors import (
|
|
50
|
+
BidiComponentInvalidCallbackNameError,
|
|
51
|
+
BidiComponentInvalidDefaultKeyError,
|
|
52
|
+
BidiComponentInvalidIdError,
|
|
53
|
+
BidiComponentMissingContentError,
|
|
54
|
+
BidiComponentUnserializableDataError,
|
|
55
|
+
)
|
|
56
|
+
from streamlit.proto.ArrowData_pb2 import ArrowData as ArrowDataProto
|
|
57
|
+
from streamlit.proto.BidiComponent_pb2 import BidiComponent as BidiComponentProto
|
|
58
|
+
from streamlit.proto.BidiComponent_pb2 import MixedData as MixedDataProto
|
|
59
|
+
from streamlit.runtime.metrics_util import gather_metrics
|
|
60
|
+
from streamlit.runtime.scriptrunner_utils.script_run_context import get_script_run_ctx
|
|
61
|
+
from streamlit.runtime.state import register_widget
|
|
62
|
+
from streamlit.util import calc_md5
|
|
63
|
+
|
|
64
|
+
if TYPE_CHECKING:
|
|
65
|
+
from streamlit.components.v2.types import (
|
|
66
|
+
BidiComponentData,
|
|
67
|
+
BidiComponentDefaults,
|
|
68
|
+
BidiComponentKey,
|
|
69
|
+
ComponentIsolateStyles,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
if TYPE_CHECKING:
|
|
73
|
+
# Define DeltaGenerator for type checking the dg property
|
|
74
|
+
from streamlit.delta_generator import DeltaGenerator
|
|
75
|
+
from streamlit.runtime.state.common import WidgetCallback
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _make_trigger_id(base: str, event: str) -> str:
|
|
79
|
+
"""Construct the per-event *trigger widget* identifier.
|
|
80
|
+
|
|
81
|
+
The widget ID for a trigger is derived from the *base* component ID plus
|
|
82
|
+
an *event* name. We join those two parts with :py:const:`EVENT_DELIM` and
|
|
83
|
+
perform a couple of validations so that downstream logic can always split
|
|
84
|
+
the identifier unambiguously.
|
|
85
|
+
|
|
86
|
+
Trigger widgets are marked as internal by prefixing with an internal key prefix,
|
|
87
|
+
so they won't be exposed in `st.session_state` to end users.
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
base
|
|
92
|
+
The unique, framework-assigned ID of the component instance.
|
|
93
|
+
event
|
|
94
|
+
The event name as provided by either the frontend or the developer
|
|
95
|
+
(e.g., "click", "change").
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
str
|
|
100
|
+
The composite widget ID in the form ``"$$STREAMLIT_INTERNAL_KEY_{base}__{event}"``
|
|
101
|
+
where ``__`` is the delimiter.
|
|
102
|
+
|
|
103
|
+
Raises
|
|
104
|
+
------
|
|
105
|
+
StreamlitAPIException
|
|
106
|
+
If either `base` or `event` already contains the delimiter sequence.
|
|
107
|
+
|
|
108
|
+
"""
|
|
109
|
+
from streamlit.runtime.state.session_state import STREAMLIT_INTERNAL_KEY_PREFIX
|
|
110
|
+
|
|
111
|
+
if EVENT_DELIM in base:
|
|
112
|
+
raise BidiComponentInvalidIdError("base", EVENT_DELIM)
|
|
113
|
+
if EVENT_DELIM in event:
|
|
114
|
+
raise BidiComponentInvalidIdError("event", EVENT_DELIM)
|
|
115
|
+
|
|
116
|
+
return f"{STREAMLIT_INTERNAL_KEY_PREFIX}_{base}{EVENT_DELIM}{event}"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class BidiComponentMixin:
|
|
120
|
+
"""Mixin class for the bidi_component DeltaGenerator method."""
|
|
121
|
+
|
|
122
|
+
def _canonicalize_json_for_identity(self, payload: str) -> str:
|
|
123
|
+
"""Return a deterministic JSON string for identity comparisons.
|
|
124
|
+
|
|
125
|
+
Payloads that cannot be parsed (or re-serialized) are returned as-is to
|
|
126
|
+
avoid mutating developer data.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
if not payload:
|
|
130
|
+
return payload
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
parsed = json.loads(payload)
|
|
134
|
+
except (TypeError, ValueError):
|
|
135
|
+
return payload
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
return json.dumps(parsed, sort_keys=True)
|
|
139
|
+
except (TypeError, ValueError):
|
|
140
|
+
return payload
|
|
141
|
+
|
|
142
|
+
def _canonical_json_digest_for_identity(self, payload: str) -> str:
|
|
143
|
+
"""Return the hash of the canonicalized JSON payload for identity use.
|
|
144
|
+
|
|
145
|
+
Hashing keeps the kwargs passed to ``compute_and_register_element_id``
|
|
146
|
+
small even when the JSON payload is very large, while still changing the
|
|
147
|
+
identity whenever the canonical JSON content changes.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
canonical = self._canonicalize_json_for_identity(payload)
|
|
151
|
+
return calc_md5(canonical)
|
|
152
|
+
|
|
153
|
+
def _build_bidi_identity_kwargs(
|
|
154
|
+
self,
|
|
155
|
+
*,
|
|
156
|
+
component_name: str,
|
|
157
|
+
isolate_styles: bool,
|
|
158
|
+
width: Width,
|
|
159
|
+
height: Height,
|
|
160
|
+
proto: BidiComponentProto,
|
|
161
|
+
data: BidiComponentData = None,
|
|
162
|
+
) -> dict[str, Any]:
|
|
163
|
+
"""Build deterministic identity kwargs for ID computation.
|
|
164
|
+
|
|
165
|
+
Construct a stable mapping of identity-relevant properties for
|
|
166
|
+
``compute_and_register_element_id``. This includes structural
|
|
167
|
+
properties (name, style isolation, layout) and an explicit, typed
|
|
168
|
+
handling of the ``BidiComponent`` ``oneof data`` field to ensure
|
|
169
|
+
unkeyed components change identity when their serialized payload
|
|
170
|
+
changes.
|
|
171
|
+
|
|
172
|
+
Parameters
|
|
173
|
+
----------
|
|
174
|
+
component_name : str
|
|
175
|
+
The registered component name.
|
|
176
|
+
isolate_styles : bool
|
|
177
|
+
Whether the component styles are rendered in a Shadow DOM.
|
|
178
|
+
width : Width
|
|
179
|
+
Desired width configuration passed to the component.
|
|
180
|
+
height : Height
|
|
181
|
+
Desired height configuration passed to the component.
|
|
182
|
+
proto : BidiComponentProto
|
|
183
|
+
The populated component protobuf. Its ``data`` oneof determines
|
|
184
|
+
which serialized payload (JSON, Arrow, bytes, or Mixed) contributes
|
|
185
|
+
to identity.
|
|
186
|
+
data : BidiComponentData
|
|
187
|
+
The raw data passed to the component. Used to optimize identity
|
|
188
|
+
calculation for JSON payloads by avoiding a parse/serialize cycle.
|
|
189
|
+
|
|
190
|
+
Returns
|
|
191
|
+
-------
|
|
192
|
+
dict[str, Any]
|
|
193
|
+
A mapping of deterministic values to be forwarded into
|
|
194
|
+
``compute_and_register_element_id``.
|
|
195
|
+
|
|
196
|
+
Raises
|
|
197
|
+
------
|
|
198
|
+
RuntimeError
|
|
199
|
+
If an unhandled ``oneof data`` variant is encountered (guards
|
|
200
|
+
against adding new fields without updating identity computation).
|
|
201
|
+
"""
|
|
202
|
+
identity: dict[str, Any] = {
|
|
203
|
+
"component_name": component_name,
|
|
204
|
+
"isolate_styles": isolate_styles,
|
|
205
|
+
"width": width,
|
|
206
|
+
"height": height,
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
data_field = proto.WhichOneof("data")
|
|
210
|
+
if data_field is None:
|
|
211
|
+
return identity
|
|
212
|
+
|
|
213
|
+
if data_field == "json":
|
|
214
|
+
# Canonicalize only for identity so unkeyed widgets don't churn when
|
|
215
|
+
# dict insertion order changes.
|
|
216
|
+
#
|
|
217
|
+
# Optimization: Use raw `data` if available to avoid the overhead of
|
|
218
|
+
# parsing `proto.json` back into a dict.
|
|
219
|
+
canonical_digest = None
|
|
220
|
+
|
|
221
|
+
if data is not None:
|
|
222
|
+
try:
|
|
223
|
+
canonical = json.dumps(data, sort_keys=True)
|
|
224
|
+
canonical_digest = calc_md5(canonical)
|
|
225
|
+
except (TypeError, ValueError):
|
|
226
|
+
# Fallback to existing logic if direct dump fails
|
|
227
|
+
pass
|
|
228
|
+
|
|
229
|
+
if canonical_digest is None:
|
|
230
|
+
canonical_digest = self._canonical_json_digest_for_identity(proto.json)
|
|
231
|
+
|
|
232
|
+
identity["json"] = canonical_digest
|
|
233
|
+
elif data_field == "arrow_data":
|
|
234
|
+
# Hash large payloads instead of shoving raw bytes through the ID
|
|
235
|
+
# hasher for performance.
|
|
236
|
+
identity["arrow_data"] = calc_md5(proto.arrow_data.data)
|
|
237
|
+
elif data_field == "bytes":
|
|
238
|
+
# Same story for arbitrary bytes payloads: content-address the data
|
|
239
|
+
# so identity changes track real mutations without re-hashing the
|
|
240
|
+
# whole blob every run.
|
|
241
|
+
identity["bytes"] = calc_md5(proto.bytes)
|
|
242
|
+
elif data_field == "mixed":
|
|
243
|
+
mixed: MixedDataProto = proto.mixed
|
|
244
|
+
# Add the JSON content of the MixedData to the identity.
|
|
245
|
+
identity["mixed_json"] = self._canonical_json_digest_for_identity(
|
|
246
|
+
mixed.json
|
|
247
|
+
)
|
|
248
|
+
# Add the sorted content-addressed ref IDs of the Arrow blobs to the identity.
|
|
249
|
+
# Unlike other data types where we include actual bytes, here we only include
|
|
250
|
+
# the blob keys. This is sufficient because keys are MD5 hashes of the blob
|
|
251
|
+
# content (content-addressed), so identical content produces identical keys.
|
|
252
|
+
identity["mixed_arrow_blobs"] = ",".join(sorted(mixed.arrow_blobs.keys()))
|
|
253
|
+
else:
|
|
254
|
+
raise RuntimeError(
|
|
255
|
+
f"Unhandled BidiComponent.data oneof field: {data_field}"
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
return identity
|
|
259
|
+
|
|
260
|
+
@gather_metrics("_bidi_component")
|
|
261
|
+
def _bidi_component(
|
|
262
|
+
self,
|
|
263
|
+
component_name: str,
|
|
264
|
+
key: BidiComponentKey = None,
|
|
265
|
+
isolate_styles: ComponentIsolateStyles = True,
|
|
266
|
+
data: BidiComponentData = None,
|
|
267
|
+
default: BidiComponentDefaults = None,
|
|
268
|
+
width: Width = "stretch",
|
|
269
|
+
height: Height = "content",
|
|
270
|
+
**kwargs: WidgetCallback | None,
|
|
271
|
+
) -> BidiComponentResult:
|
|
272
|
+
"""Add a bidirectional component instance to the app.
|
|
273
|
+
|
|
274
|
+
This method uses a component that has already been registered with the
|
|
275
|
+
application.
|
|
276
|
+
|
|
277
|
+
Parameters
|
|
278
|
+
----------
|
|
279
|
+
component_name
|
|
280
|
+
The name of the registered component to use. The component's HTML,
|
|
281
|
+
CSS, and JavaScript will be loaded from the registry.
|
|
282
|
+
key
|
|
283
|
+
An optional string to use as the unique key for the component.
|
|
284
|
+
If this is omitted, a key will be generated based on the
|
|
285
|
+
component's execution sequence.
|
|
286
|
+
isolate_styles
|
|
287
|
+
Whether to sandbox the component's styles in a shadow root.
|
|
288
|
+
Defaults to True.
|
|
289
|
+
data
|
|
290
|
+
Data to pass to the component. This can be any JSON-serializable
|
|
291
|
+
data, or a pandas DataFrame, NumPy array, or other dataframe-like
|
|
292
|
+
object that can be serialized to Arrow.
|
|
293
|
+
default
|
|
294
|
+
A dictionary of default values for the component's state properties.
|
|
295
|
+
These defaults are applied only when the state key doesn't exist
|
|
296
|
+
in session state. Keys must correspond to valid state names (those
|
|
297
|
+
with `on_*_change` callbacks). Trigger values do not support
|
|
298
|
+
defaults.
|
|
299
|
+
width
|
|
300
|
+
The desired width of the component. This can be one of "stretch",
|
|
301
|
+
"content", or a number of pixels.
|
|
302
|
+
height
|
|
303
|
+
The desired height of the component. This can be one of "stretch",
|
|
304
|
+
"content", or a number of pixels.
|
|
305
|
+
**kwargs
|
|
306
|
+
Keyword arguments to pass to the component. Callbacks can be passed
|
|
307
|
+
here, with the naming convention `on_{event_name}_change`.
|
|
308
|
+
|
|
309
|
+
Returns
|
|
310
|
+
-------
|
|
311
|
+
BidiComponentResult
|
|
312
|
+
A dictionary-like object that holds the component's state and
|
|
313
|
+
trigger values.
|
|
314
|
+
|
|
315
|
+
Raises
|
|
316
|
+
------
|
|
317
|
+
ValueError
|
|
318
|
+
If the component name is not found in the registry.
|
|
319
|
+
StreamlitAPIException
|
|
320
|
+
If the component does not have the required JavaScript or HTML
|
|
321
|
+
content, or if the provided data cannot be serialized.
|
|
322
|
+
|
|
323
|
+
"""
|
|
324
|
+
check_cache_replay_rules()
|
|
325
|
+
|
|
326
|
+
key = to_key(key)
|
|
327
|
+
ctx = get_script_run_ctx()
|
|
328
|
+
|
|
329
|
+
if ctx is None:
|
|
330
|
+
# Create an empty state with the default value and return it
|
|
331
|
+
return BidiComponentResult({}, {})
|
|
332
|
+
|
|
333
|
+
# Get the component definition from the registry
|
|
334
|
+
from streamlit.runtime import Runtime
|
|
335
|
+
|
|
336
|
+
registry = Runtime.instance().bidi_component_registry
|
|
337
|
+
component_def = registry.get(component_name)
|
|
338
|
+
|
|
339
|
+
if component_def is None:
|
|
340
|
+
raise ValueError(f"Component '{component_name}' is not registered")
|
|
341
|
+
|
|
342
|
+
# Validate that the component has the required content
|
|
343
|
+
has_js = bool(component_def.js_content or component_def.js_url)
|
|
344
|
+
has_html = bool(component_def.html_content)
|
|
345
|
+
|
|
346
|
+
if not has_js and not has_html:
|
|
347
|
+
raise BidiComponentMissingContentError(component_name)
|
|
348
|
+
|
|
349
|
+
# ------------------------------------------------------------------
|
|
350
|
+
# 1. Parse user-supplied callbacks
|
|
351
|
+
# ------------------------------------------------------------------
|
|
352
|
+
# Event-specific callbacks follow the pattern ``on_<event>_change``.
|
|
353
|
+
# We deliberately *do not* support the legacy generic ``on_change``
|
|
354
|
+
# or ``on_<event>`` forms.
|
|
355
|
+
callbacks_by_event: dict[str, WidgetCallback] = {}
|
|
356
|
+
for kwarg_key, kwarg_value in list(kwargs.items()):
|
|
357
|
+
if not callable(kwarg_value):
|
|
358
|
+
continue
|
|
359
|
+
|
|
360
|
+
if kwarg_key.startswith("on_") and kwarg_key.endswith("_change"):
|
|
361
|
+
# Preferred pattern: on_<event>_change
|
|
362
|
+
event_name = kwarg_key[3:-7] # strip prefix + suffix
|
|
363
|
+
else:
|
|
364
|
+
# Not an event callback we recognize - skip.
|
|
365
|
+
continue
|
|
366
|
+
|
|
367
|
+
if not event_name or event_name == "_":
|
|
368
|
+
raise BidiComponentInvalidCallbackNameError(kwarg_key)
|
|
369
|
+
|
|
370
|
+
callbacks_by_event[event_name] = kwarg_value
|
|
371
|
+
|
|
372
|
+
# ------------------------------------------------------------------
|
|
373
|
+
# 2. Validate default keys against registered callbacks
|
|
374
|
+
# ------------------------------------------------------------------
|
|
375
|
+
if default is not None:
|
|
376
|
+
for state_key in default:
|
|
377
|
+
if state_key not in callbacks_by_event:
|
|
378
|
+
raise BidiComponentInvalidDefaultKeyError(
|
|
379
|
+
state_key, list(callbacks_by_event.keys())
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
# Set up the component proto
|
|
383
|
+
bidi_component_proto = BidiComponentProto()
|
|
384
|
+
bidi_component_proto.component_name = component_name
|
|
385
|
+
bidi_component_proto.isolate_styles = isolate_styles
|
|
386
|
+
bidi_component_proto.js_content = component_def.js_content or ""
|
|
387
|
+
bidi_component_proto.js_source_path = component_def.js_url or ""
|
|
388
|
+
bidi_component_proto.html_content = component_def.html_content or ""
|
|
389
|
+
bidi_component_proto.css_content = component_def.css_content or ""
|
|
390
|
+
bidi_component_proto.css_source_path = component_def.css_url or ""
|
|
391
|
+
|
|
392
|
+
validate_width(width, allow_content=True)
|
|
393
|
+
layout_config = LayoutConfig(width=width, height=height)
|
|
394
|
+
|
|
395
|
+
if data is not None:
|
|
396
|
+
try:
|
|
397
|
+
# 1. Raw byte payloads - forward as-is.
|
|
398
|
+
if isinstance(data, (bytes, bytearray)):
|
|
399
|
+
bidi_component_proto.bytes = bytes(data)
|
|
400
|
+
|
|
401
|
+
# 2. Mapping-like structures (e.g. plain dict) - check for mixed data.
|
|
402
|
+
elif isinstance(data, (Mapping, list, tuple)):
|
|
403
|
+
serialize_mixed_data(data, bidi_component_proto)
|
|
404
|
+
|
|
405
|
+
# 3. Dataframe-like structures - attempt Arrow serialization.
|
|
406
|
+
else:
|
|
407
|
+
data_format = determine_data_format(data)
|
|
408
|
+
|
|
409
|
+
if data_format != DataFormat.UNKNOWN:
|
|
410
|
+
arrow_bytes = convert_anything_to_arrow_bytes(data)
|
|
411
|
+
|
|
412
|
+
arrow_data_proto = ArrowDataProto()
|
|
413
|
+
arrow_data_proto.data = arrow_bytes
|
|
414
|
+
|
|
415
|
+
bidi_component_proto.arrow_data.CopyFrom(arrow_data_proto)
|
|
416
|
+
else:
|
|
417
|
+
# Fallback to JSON.
|
|
418
|
+
bidi_component_proto.json = json.dumps(data)
|
|
419
|
+
except Exception:
|
|
420
|
+
# As a last resort attempt JSON serialization so that we don't
|
|
421
|
+
# silently drop developer data.
|
|
422
|
+
try:
|
|
423
|
+
bidi_component_proto.json = json.dumps(data)
|
|
424
|
+
except Exception:
|
|
425
|
+
raise BidiComponentUnserializableDataError()
|
|
426
|
+
bidi_component_proto.form_id = current_form_id(self.dg)
|
|
427
|
+
|
|
428
|
+
# Build identity kwargs for the component instance now that the proto is
|
|
429
|
+
# populated.
|
|
430
|
+
identity_kwargs = self._build_bidi_identity_kwargs(
|
|
431
|
+
component_name=component_name,
|
|
432
|
+
isolate_styles=isolate_styles,
|
|
433
|
+
width=width,
|
|
434
|
+
height=height,
|
|
435
|
+
proto=bidi_component_proto,
|
|
436
|
+
data=data,
|
|
437
|
+
)
|
|
438
|
+
# Compute a unique ID for this component instance now that the proto is
|
|
439
|
+
# populated.
|
|
440
|
+
computed_id = compute_and_register_element_id(
|
|
441
|
+
"bidi_component",
|
|
442
|
+
user_key=key,
|
|
443
|
+
key_as_main_identity=True,
|
|
444
|
+
dg=self.dg,
|
|
445
|
+
**identity_kwargs,
|
|
446
|
+
)
|
|
447
|
+
bidi_component_proto.id = computed_id
|
|
448
|
+
|
|
449
|
+
# Instantiate the Serde for this component instance
|
|
450
|
+
serde = BidiComponentSerde(default=default)
|
|
451
|
+
|
|
452
|
+
# ------------------------------------------------------------------
|
|
453
|
+
# 3. Prepare IDs and register widgets
|
|
454
|
+
# ------------------------------------------------------------------
|
|
455
|
+
|
|
456
|
+
# Compute trigger aggregator id from the base id
|
|
457
|
+
def _make_trigger_aggregator_id(base: str) -> str:
|
|
458
|
+
return _make_trigger_id(base, "events")
|
|
459
|
+
|
|
460
|
+
aggregator_id = _make_trigger_aggregator_id(computed_id)
|
|
461
|
+
|
|
462
|
+
# With generalized runtime dispatch, we can attach per-key callbacks
|
|
463
|
+
# directly to the state widget by passing the callbacks mapping.
|
|
464
|
+
# We also register a presenter to shape the user-visible session_state.
|
|
465
|
+
# Allowed state keys are the ones that have callbacks registered.
|
|
466
|
+
allowed_state_keys = (
|
|
467
|
+
set(callbacks_by_event.keys()) if callbacks_by_event else None
|
|
468
|
+
)
|
|
469
|
+
presenter = make_bidi_component_presenter(
|
|
470
|
+
aggregator_id,
|
|
471
|
+
computed_id,
|
|
472
|
+
allowed_state_keys,
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
component_state = register_widget(
|
|
476
|
+
bidi_component_proto.id,
|
|
477
|
+
deserializer=serde.deserialize,
|
|
478
|
+
serializer=serde.serialize,
|
|
479
|
+
ctx=ctx,
|
|
480
|
+
callbacks=callbacks_by_event if callbacks_by_event else None,
|
|
481
|
+
value_type="json_value",
|
|
482
|
+
presenter=presenter,
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
# ------------------------------------------------------------------
|
|
486
|
+
# 4. Register a single *trigger aggregator* widget
|
|
487
|
+
# ------------------------------------------------------------------
|
|
488
|
+
trigger_vals: dict[str, Any] = {}
|
|
489
|
+
|
|
490
|
+
trig_state = register_widget(
|
|
491
|
+
aggregator_id,
|
|
492
|
+
deserializer=deserialize_trigger_list, # always returns list or None
|
|
493
|
+
serializer=lambda v: json.dumps(v), # send dict as JSON
|
|
494
|
+
ctx=ctx,
|
|
495
|
+
callbacks=callbacks_by_event if callbacks_by_event else None,
|
|
496
|
+
value_type="json_trigger_value",
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
# Surface per-event trigger values derived from the aggregator payload list.
|
|
500
|
+
payloads: list[object] = trig_state.value or []
|
|
501
|
+
|
|
502
|
+
event_to_value: dict[str, Any] = {}
|
|
503
|
+
for payload in payloads:
|
|
504
|
+
if isinstance(payload, dict):
|
|
505
|
+
ev = payload.get("event")
|
|
506
|
+
if isinstance(ev, str):
|
|
507
|
+
event_to_value[ev] = payload.get("value")
|
|
508
|
+
|
|
509
|
+
for evt_name in callbacks_by_event:
|
|
510
|
+
trigger_vals[evt_name] = event_to_value.get(evt_name)
|
|
511
|
+
|
|
512
|
+
# Note: We intentionally do not inspect SessionState for additional
|
|
513
|
+
# trigger widget IDs here because doing so can raise KeyErrors when
|
|
514
|
+
# widgets are freshly registered but their values haven't been
|
|
515
|
+
# populated yet. Only the triggers explicitly registered above are
|
|
516
|
+
# included in the result object.
|
|
517
|
+
|
|
518
|
+
# ------------------------------------------------------------------
|
|
519
|
+
# 5. Enqueue proto and assemble the result object
|
|
520
|
+
# ------------------------------------------------------------------
|
|
521
|
+
self.dg._enqueue(
|
|
522
|
+
INTERNAL_COMPONENT_NAME,
|
|
523
|
+
bidi_component_proto,
|
|
524
|
+
layout_config=layout_config,
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
state_vals = unwrap_component_state(component_state.value)
|
|
528
|
+
|
|
529
|
+
return BidiComponentResult(state_vals, trigger_vals)
|
|
530
|
+
|
|
531
|
+
@property
|
|
532
|
+
def dg(self) -> DeltaGenerator:
|
|
533
|
+
"""Get our DeltaGenerator."""
|
|
534
|
+
return cast("DeltaGenerator", self)
|