streamlit-nightly 1.53.2.dev20260128__py3-none-any.whl → 1.53.2.dev20260202__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/commands/execution_control.py +2 -2
- streamlit/config.py +3 -2
- streamlit/config_util.py +63 -8
- streamlit/delta_generator.py +2 -0
- streamlit/elements/deck_gl_json_chart.py +5 -1
- streamlit/elements/lib/built_in_chart_utils.py +24 -4
- streamlit/elements/lib/color_util.py +20 -1
- streamlit/elements/lib/column_types.py +6 -2
- streamlit/elements/lib/utils.py +6 -6
- streamlit/elements/markdown.py +0 -1
- streamlit/elements/metric.py +2 -1
- streamlit/elements/vega_charts.py +24 -4
- streamlit/elements/widgets/button_group.py +6 -276
- streamlit/elements/widgets/feedback.py +322 -0
- streamlit/elements/widgets/number_input.py +2 -1
- streamlit/elements/widgets/slider.py +2 -1
- streamlit/material_icon_names.py +1 -1
- streamlit/proto/Alert_pb2.py +2 -3
- streamlit/proto/AppPage_pb2.py +2 -3
- streamlit/proto/ArrowData_pb2.py +2 -3
- streamlit/proto/ArrowNamedDataSet_pb2.py +2 -3
- streamlit/proto/ArrowVegaLiteChart_pb2.py +2 -3
- streamlit/proto/Arrow_pb2.py +11 -18
- streamlit/proto/Arrow_pb2.pyi +1 -42
- streamlit/proto/AudioInput_pb2.py +5 -6
- streamlit/proto/AudioInput_pb2.pyi +3 -3
- streamlit/proto/Audio_pb2.py +3 -4
- streamlit/proto/AuthRedirect_pb2.py +2 -3
- streamlit/proto/AutoRerun_pb2.py +2 -3
- streamlit/proto/BackMsg_pb2.py +2 -3
- streamlit/proto/BackMsg_pb2.pyi +2 -10
- streamlit/proto/Balloons_pb2.py +2 -3
- streamlit/proto/Balloons_pb2.pyi +0 -2
- streamlit/proto/BidiComponent_pb2.py +2 -3
- streamlit/proto/Block_pb2.py +36 -43
- streamlit/proto/Block_pb2.pyi +3 -48
- streamlit/proto/ButtonGroup_pb2.py +11 -14
- streamlit/proto/ButtonGroup_pb2.pyi +6 -41
- streamlit/proto/ButtonLikeIconPosition_pb2.py +2 -3
- streamlit/proto/Button_pb2.py +3 -6
- streamlit/proto/Button_pb2.pyi +1 -18
- streamlit/proto/CameraInput_pb2.py +5 -6
- streamlit/proto/CameraInput_pb2.pyi +3 -3
- streamlit/proto/ChatInput_pb2.py +5 -8
- streamlit/proto/ChatInput_pb2.pyi +1 -17
- streamlit/proto/Checkbox_pb2.py +7 -8
- streamlit/proto/Checkbox_pb2.pyi +3 -3
- streamlit/proto/ClientState_pb2.py +2 -3
- streamlit/proto/Code_pb2.py +3 -6
- streamlit/proto/Code_pb2.pyi +1 -18
- streamlit/proto/ColorPicker_pb2.py +5 -6
- streamlit/proto/ColorPicker_pb2.pyi +3 -3
- streamlit/proto/Common_pb2.py +7 -8
- streamlit/proto/Common_pb2.pyi +2 -10
- streamlit/proto/Components_pb2.py +2 -3
- streamlit/proto/DateInput_pb2.py +5 -6
- streamlit/proto/DateInput_pb2.pyi +3 -3
- streamlit/proto/DateTimeInput_pb2.py +5 -6
- streamlit/proto/DateTimeInput_pb2.pyi +3 -3
- streamlit/proto/DeckGlJsonChart_pb2.py +5 -12
- streamlit/proto/DeckGlJsonChart_pb2.pyi +1 -54
- streamlit/proto/Delta_pb2.py +4 -6
- streamlit/proto/Delta_pb2.pyi +5 -14
- streamlit/proto/DocString_pb2.py +2 -3
- streamlit/proto/DownloadButton_pb2.py +2 -3
- streamlit/proto/Element_pb2.py +5 -8
- streamlit/proto/Element_pb2.pyi +9 -29
- streamlit/proto/Empty_pb2.py +2 -3
- streamlit/proto/Exception_pb2.py +2 -3
- streamlit/proto/Favicon_pb2.py +2 -3
- streamlit/proto/Feedback_pb2.py +28 -0
- streamlit/proto/Feedback_pb2.pyi +93 -0
- streamlit/proto/FileUploader_pb2.py +5 -6
- streamlit/proto/FileUploader_pb2.pyi +3 -3
- streamlit/proto/ForwardMsg_pb2.py +12 -18
- streamlit/proto/ForwardMsg_pb2.pyi +4 -48
- streamlit/proto/GapSize_pb2.py +2 -3
- streamlit/proto/GitInfo_pb2.py +2 -3
- streamlit/proto/GraphVizChart_pb2.py +3 -6
- streamlit/proto/GraphVizChart_pb2.pyi +1 -18
- streamlit/proto/Heading_pb2.py +2 -3
- streamlit/proto/HeightConfig_pb2.py +2 -3
- streamlit/proto/Html_pb2.py +2 -3
- streamlit/proto/IFrame_pb2.py +4 -11
- streamlit/proto/IFrame_pb2.pyi +1 -42
- streamlit/proto/Image_pb2.py +5 -8
- streamlit/proto/Image_pb2.pyi +2 -25
- streamlit/proto/Json_pb2.py +2 -3
- streamlit/proto/LabelVisibility_pb2.py +28 -0
- streamlit/proto/{LabelVisibilityMessage_pb2.pyi → LabelVisibility_pb2.pyi} +14 -14
- streamlit/proto/LinkButton_pb2.py +2 -3
- streamlit/proto/Logo_pb2.py +2 -3
- streamlit/proto/Markdown_pb2.py +5 -6
- streamlit/proto/Markdown_pb2.pyi +1 -5
- streamlit/proto/Metric_pb2.py +11 -12
- streamlit/proto/Metric_pb2.pyi +3 -3
- streamlit/proto/MetricsEvent_pb2.py +2 -3
- streamlit/proto/MultiSelect_pb2.py +5 -8
- streamlit/proto/MultiSelect_pb2.pyi +4 -14
- streamlit/proto/Navigation_pb2.py +2 -3
- streamlit/proto/NewSession_pb2.py +39 -28
- streamlit/proto/NewSession_pb2.pyi +44 -20
- streamlit/proto/NumberInput_pb2.py +7 -8
- streamlit/proto/NumberInput_pb2.pyi +3 -3
- streamlit/proto/PageConfig_pb2.py +2 -3
- streamlit/proto/PageInfo_pb2.py +2 -3
- streamlit/proto/PageLink_pb2.py +2 -3
- streamlit/proto/PageNotFound_pb2.py +2 -3
- streamlit/proto/PageProfile_pb2.py +2 -3
- streamlit/proto/ParentMessage_pb2.py +2 -3
- streamlit/proto/PlotlyChart_pb2.py +5 -10
- streamlit/proto/PlotlyChart_pb2.pyi +1 -58
- streamlit/proto/Progress_pb2.py +2 -3
- streamlit/proto/Radio_pb2.py +5 -8
- streamlit/proto/Radio_pb2.pyi +5 -22
- streamlit/proto/RootContainer_pb2.py +2 -3
- streamlit/proto/Selectbox_pb2.py +5 -8
- streamlit/proto/Selectbox_pb2.pyi +5 -25
- streamlit/proto/SessionEvent_pb2.py +2 -3
- streamlit/proto/SessionStatus_pb2.py +2 -3
- streamlit/proto/Skeleton_pb2.py +2 -3
- streamlit/proto/Slider_pb2.py +9 -10
- streamlit/proto/Slider_pb2.pyi +3 -3
- streamlit/proto/Snow_pb2.py +2 -3
- streamlit/proto/Snow_pb2.pyi +0 -2
- streamlit/proto/Space_pb2.py +2 -3
- streamlit/proto/Spinner_pb2.py +2 -3
- streamlit/proto/TextAlignmentConfig_pb2.py +2 -3
- streamlit/proto/TextArea_pb2.py +5 -8
- streamlit/proto/TextArea_pb2.pyi +4 -21
- streamlit/proto/TextInput_pb2.py +7 -8
- streamlit/proto/TextInput_pb2.pyi +3 -3
- streamlit/proto/Text_pb2.py +2 -3
- streamlit/proto/TimeInput_pb2.py +5 -6
- streamlit/proto/TimeInput_pb2.pyi +3 -3
- streamlit/proto/Toast_pb2.py +2 -3
- streamlit/proto/Transient_pb2.py +2 -3
- streamlit/proto/Video_pb2.py +3 -4
- streamlit/proto/WidgetStates_pb2.py +2 -3
- streamlit/proto/WidthConfig_pb2.py +2 -3
- streamlit/proto/openmetrics_data_model_pb2.py +2 -3
- streamlit/runtime/runtime.py +0 -4
- streamlit/static/index.html +2 -2
- streamlit/static/manifest.json +327 -312
- streamlit/static/static/css/{index.BUP6fTcR.css → index.C8MrxwGF.css} +1 -1
- streamlit/static/static/js/{ErrorOutline.esm.D71F8ziR.js → ErrorOutline.esm.CLuz0rSD.js} +1 -1
- streamlit/static/static/js/{FileDownload.esm.yTkppsJy.js → FileDownload.esm.CO68LcnZ.js} +1 -1
- streamlit/static/static/js/{FileHelper.hUOqtbwa.js → FileHelper.DAXgY6Ug.js} +1 -1
- streamlit/static/static/js/{FormClearHelper.DN8D_YXO.js → FormClearHelper.zxJ53Nym.js} +1 -1
- streamlit/static/static/js/{InputInstructions.DbssY6d4.js → InputInstructions.CCbg8esE.js} +1 -1
- streamlit/static/static/js/{Particles.BznyVdfo.js → Particles.BJw0A-zv.js} +1 -1
- streamlit/static/static/js/{ProgressBar.C5uBOtcx.js → ProgressBar.BrrHeAEh.js} +2 -2
- streamlit/static/static/js/{StreamlitSyntaxHighlighter.Nf1895x-.js → StreamlitSyntaxHighlighter.DvPLy3zk.js} +1 -1
- streamlit/static/static/js/{TableChart.esm.DHKzVs3a.js → TableChart.esm.BawvAi5p.js} +1 -1
- streamlit/static/static/js/{Toolbar.CQsWYXer.js → Toolbar.CbpscbNb.js} +1 -1
- streamlit/static/static/js/{WidgetLabelHelpIconInline.6xCU76OE.js → WidgetLabelHelpIconInline.DA4S2HFP.js} +1 -1
- streamlit/static/static/js/{base-input.Cs-E6S71.js → base-input.BKKl2eBF.js} +4 -4
- streamlit/static/static/js/{checkbox.OTGupu18.js → checkbox.CB43AKV4.js} +1 -1
- streamlit/static/static/js/{createDownloadLinkElement.DnBEQQbK.js → createDownloadLinkElement.jVwF96ey.js} +1 -1
- streamlit/static/static/js/data-grid-overlay-editor.CxQizSv7.js +1 -0
- streamlit/static/static/js/{downloader.K0GUNeuj.js → downloader.CKlIgsy5.js} +1 -1
- streamlit/static/static/js/{embed.o8HvK3mH.js → embed.BhRb_2n8.js} +1 -1
- streamlit/static/static/js/{es6.BHy5pqTP.js → es6.DPyfPmWm.js} +2 -2
- streamlit/static/static/js/formatNumber.DtfMnnPx.js +1 -0
- streamlit/static/static/js/{iconPosition.2YynQUxu.js → iconPosition.DkZAlu_k.js} +1 -1
- streamlit/static/static/js/{iframeResizer.contentWindow.D5h3hQuU.js → iframeResizer.contentWindow.l5sQWLra.js} +1 -1
- streamlit/static/static/js/{index.BZ-GJVxB.js → index.465nmxtO.js} +2 -2
- streamlit/static/static/js/{index.BPdmXoYW.js → index.6J1N4is3.js} +1 -1
- streamlit/static/static/js/{index.Bfo1cXfC.js → index.AZ9T4EqJ.js} +1 -1
- streamlit/static/static/js/{index.cfuZ69LI.js → index.BAK0CG1Q.js} +1 -1
- streamlit/static/static/js/{index.5zqfJ-in.js → index.BLD3tJ2C.js} +1 -1
- streamlit/static/static/js/{index.CxWzt6oi.js → index.BUlT_mOL.js} +3 -3
- streamlit/static/static/js/{index.DxGXuhh6.js → index.Bc_FQ4Wb.js} +1 -1
- streamlit/static/static/js/{index.DJfMW0Gy.js → index.BpCj2-sQ.js} +1 -1
- streamlit/static/static/js/{index.DLUSo6de.js → index.BzO83wKm.js} +1 -1
- streamlit/static/static/js/index.CAoX2tlo.js +2 -0
- streamlit/static/static/js/{index.CwtpGPHA.js → index.CBbYMKZp.js} +1 -1
- streamlit/static/static/js/{index.Bgf49D1Z.js → index.CL7it7tU.js} +222 -222
- streamlit/static/static/js/{index.DxfYCrPp.js → index.CL_icBXS.js} +1 -1
- streamlit/static/static/js/index.C_19KWNs.js +2 -0
- streamlit/static/static/js/index.CaU3Uv_L.js +1 -0
- streamlit/static/static/js/{index.Dh3PJIlq.js → index.Ccye_uLl.js} +1 -1
- streamlit/static/static/js/{index.C65jHNhe.js → index.CiS4giQ2.js} +1 -1
- streamlit/static/static/js/{index.hlAfdSqC.js → index.Ck64OQhV.js} +1 -1
- streamlit/static/static/js/{index.HmRK3HyC.js → index.CmbqbRMZ.js} +1 -1
- streamlit/static/static/js/{index.8MlRyIxN.js → index.CsEZTo6L.js} +2 -2
- streamlit/static/static/js/{index.DVRCyxMp.js → index.CsIENsKH.js} +1 -1
- streamlit/static/static/js/{index.Bqmx23jK.js → index.Cwg8nWw5.js} +1 -1
- streamlit/static/static/js/{index.CZf7Go1Z.js → index.D83azq2w.js} +1 -1
- streamlit/static/static/js/{index.CUkhn-vu.js → index.DDr-BLbJ.js} +1 -1
- streamlit/static/static/js/{index.iUV9rb8C.js → index.DKoJr0Se.js} +1 -1
- streamlit/static/static/js/{index.C2EoeVjP.js → index.DL_ywOgf.js} +2 -2
- streamlit/static/static/js/{index.q0ceUXt6.js → index.DR6V0uBJ.js} +1 -1
- streamlit/static/static/js/index.DZOGT9vX.js +1 -0
- streamlit/static/static/js/{index.BtuskCwg.js → index.Dac9Jib-.js} +1 -1
- streamlit/static/static/js/{index.6c-qDsD7.js → index.DiBeetOH.js} +1 -1
- streamlit/static/static/js/{index.DlgcEr0f.js → index.DjuMEZ6m.js} +1 -1
- streamlit/static/static/js/{index.DBPWUJsj.js → index.DmWUXdjc.js} +54 -54
- streamlit/static/static/js/{index.DL_yE83J.js → index.DpSc4e1j.js} +2 -2
- streamlit/static/static/js/{index.CgVv04GM.js → index.DzdPUxsx.js} +2 -2
- streamlit/static/static/js/{index.BtRWcqZV.js → index.FioS1Y9m.js} +1 -1
- streamlit/static/static/js/{index.BfMPq234.js → index.L9pOjBEn.js} +3 -3
- streamlit/static/static/js/{index.TjMWsKSH.js → index.LjqoQCm5.js} +3 -3
- streamlit/static/static/js/index.OizPL4jg.js +1 -0
- streamlit/static/static/js/{index.Cb03y5I8.js → index.Q2t_iBn0.js} +1 -1
- streamlit/static/static/js/index.WIMtx3m0.js +2 -0
- streamlit/static/static/js/index.Y9wPTZIf.js +1 -0
- streamlit/static/static/js/{index.COh5V_89.js → index.YutgmD9x.js} +2 -2
- streamlit/static/static/js/{index.BIqcOZ_u.js → index.b_f-McZ5.js} +1 -1
- streamlit/static/static/js/{index.BzTVI_BY.js → index.e6Ry6-Ft.js} +1 -1
- streamlit/static/static/js/index.hnu9U-5g.js +1 -0
- streamlit/static/static/js/{index.C6wyTXhz.js → index.rvbQETlC.js} +1 -1
- streamlit/static/static/js/index.w7yKy9fh.js +6 -0
- streamlit/static/static/js/{index.C7wst9Tm.js → index.y0h42OXL.js} +1 -1
- streamlit/static/static/js/{index.aCorc3Yt.js → index.y5HxPwg9.js} +48 -48
- streamlit/static/static/js/{index.CX0KdFyR.js → index.yHLCvUGh.js} +1 -1
- streamlit/static/static/js/{input.CXGIJ7D6.js → input.CAtwSQ27.js} +1 -1
- streamlit/static/static/js/{main.CCVkbuxC.js → main.VeMVx6VI.js} +1 -1
- streamlit/static/static/js/{memory.CNbnYs2A.js → memory.CxS_lIUn.js} +1 -1
- streamlit/static/static/js/number-overlay-editor.CoqRgZW_.js +9 -0
- streamlit/static/static/js/{pandasStylerUtils.CFSReOTm.js → pandasStylerUtils.DGWgd5sM.js} +1 -1
- streamlit/static/static/js/{sandbox.Bld0L3us.js → sandbox.2mSqEau0.js} +1 -1
- streamlit/static/static/js/sprintfjs.CsoVVZ9k.js +1 -0
- streamlit/static/static/js/{styled-components.BoUHK6TA.js → styled-components.BShfh7J8.js} +1 -1
- streamlit/static/static/js/{throttle.ByDFm7WV.js → throttle.Fq1DQK4p.js} +1 -1
- streamlit/static/static/js/{timepicker.CN6CUZEL.js → timepicker.DmyY-qtn.js} +1 -1
- streamlit/static/static/js/{toConsumableArray.DwMycSpg.js → toConsumableArray.Dvd9AIqV.js} +1 -1
- streamlit/static/static/js/uniqueId.CCajdEK8.js +1 -0
- streamlit/static/static/js/{useBasicWidgetState.Bg0ZMUt5.js → useBasicWidgetState.COLQ5AFB.js} +1 -1
- streamlit/static/static/js/{useIntlLocale.DgBUDcPA.js → useIntlLocale.kdIj0ego.js} +1 -1
- streamlit/static/static/js/{useTextInputAutoExpand.DDBezxks.js → useTextInputAutoExpand.DkuG1C1S.js} +1 -1
- streamlit/static/static/js/{useUpdateUiValue.Df1h6fXC.js → useUpdateUiValue.-UI_JsjT.js} +1 -1
- streamlit/static/static/js/{useWaveformController.DbWw5MEk.js → useWaveformController.C5PTwL6I.js} +1 -1
- streamlit/static/static/js/{withCalculatedWidth.YaK0HIIP.js → withCalculatedWidth.BREyS0pJ.js} +1 -1
- streamlit/static/static/js/{withFullScreenWrapper.CcWCKoY8.js → withFullScreenWrapper.DYDiEOrW.js} +1 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.CnH1S47a.woff2 +0 -0
- streamlit/testing/v1/app_test.py +21 -5
- streamlit/testing/v1/element_tree.py +81 -4
- streamlit/web/server/server.py +0 -1
- streamlit/web/server/starlette/starlette_app.py +0 -1
- {streamlit_nightly-1.53.2.dev20260128.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/METADATA +10 -25
- {streamlit_nightly-1.53.2.dev20260128.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/RECORD +245 -252
- streamlit/proto/BokehChart_pb2.py +0 -27
- streamlit/proto/BokehChart_pb2.pyi +0 -56
- streamlit/proto/DataFrame_pb2.py +0 -56
- streamlit/proto/DataFrame_pb2.pyi +0 -430
- streamlit/proto/LabelVisibilityMessage_pb2.py +0 -29
- streamlit/proto/NamedDataSet_pb2.py +0 -28
- streamlit/proto/NamedDataSet_pb2.pyi +0 -67
- streamlit/proto/PagesChanged_pb2.py +0 -28
- streamlit/proto/PagesChanged_pb2.pyi +0 -55
- streamlit/proto/VegaLiteChart_pb2.py +0 -29
- streamlit/proto/VegaLiteChart_pb2.pyi +0 -79
- streamlit/static/static/js/data-grid-overlay-editor.COiiMi5r.js +0 -1
- streamlit/static/static/js/formatNumber.BK7h0k2z.js +0 -1
- streamlit/static/static/js/index.BBTKOM0z.js +0 -6
- streamlit/static/static/js/index.CSPY26T2.js +0 -1
- streamlit/static/static/js/index.CYhhEdja.js +0 -1
- streamlit/static/static/js/index.CdsyTabv.js +0 -1
- streamlit/static/static/js/index.CjRU8O1O.js +0 -2
- streamlit/static/static/js/index.Dc5-tFdw.js +0 -2
- streamlit/static/static/js/index.DcngUOyD.js +0 -2
- streamlit/static/static/js/index.VwDKazgt.js +0 -1
- streamlit/static/static/js/number-overlay-editor.CvI6wkld.js +0 -9
- streamlit/static/static/js/sprintf.DpPCfzXw.js +0 -1
- streamlit/static/static/js/uniqueId.DcCWa2cf.js +0 -1
- streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
- streamlit_nightly-1.53.2.dev20260128.data/scripts/streamlit.cmd +0 -16
- {streamlit_nightly-1.53.2.dev20260128.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/WHEEL +0 -0
- {streamlit_nightly-1.53.2.dev20260128.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/entry_points.txt +0 -0
- {streamlit_nightly-1.53.2.dev20260128.dist-info → streamlit_nightly-1.53.2.dev20260202.dist-info}/top_level.txt +0 -0
streamlit/static/static/js/{useWaveformController.DbWw5MEk.js → useWaveformController.C5PTwL6I.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{l as Z,r as i,aP as M,aa as $,aQ as O}from"./index.aCorc3Yt.js";async function q(l,e=16e3){if(!l||l.size===0)throw new Error("Invalid or empty blob provided");if(!window.AudioContext)throw new Error("AudioContext not supported in this browser");const o=new AudioContext;try{const n=await l.arrayBuffer(),r=await o.decodeAudioData(n),d=e??r.sampleRate,s=await Q(r,d);return J(s,d)}finally{o.close()}}async function Q(l,e){const{duration:o,numberOfChannels:n,sampleRate:r}=l,d=Math.ceil(o*e);if(!window.OfflineAudioContext)throw new Error("OfflineAudioContext not supported");const s=new OfflineAudioContext(1,d,e),p=s.createBufferSource();if(p.buffer=l,n>1){const h=s.createChannelSplitter(n),m=s.createChannelMerger(1);p.connect(h);for(let c=0;c<n;c++){const u=s.createGain();u.gain.value=1/n,h.connect(u,c),u.connect(m,0,0)}m.connect(s.destination)}else p.connect(s.destination);p.start(0);try{return await s.startRendering()}catch(h){throw new Error(`Failed to resample audio from ${r}Hz to ${e}Hz: ${h instanceof Error?h.message:String(h)}`)}}function J(l,e){const n=l.length,r=n*2+44,d=new ArrayBuffer(r),s=new DataView(d),p=l.getChannelData(0),h=(c,u)=>{for(let y=0;y<u.length;y++)s.setUint8(c+y,u.charCodeAt(y))};h(0,"RIFF"),s.setUint32(4,r-8,!0),h(8,"WAVE"),h(12,"fmt "),s.setUint32(16,16,!0),s.setUint16(20,1,!0),s.setUint16(22,1,!0),s.setUint32(24,e,!0),s.setUint32(28,e*2,!0),s.setUint16(32,2,!0),s.setUint16(34,16,!0),h(36,"data"),s.setUint32(40,n*2,!0);let m=44;for(let c=0;c<n;c++){const u=Math.max(-1,Math.min(1,p[c]));s.setInt16(m,u*32767,!0),m+=2}return new Blob([d],{type:"audio/wav"})}class W{constructor(){this.wavesurfer=null,this.currentBlobUrl=null,this.events={},this.isPlaying=!1}initialize(e){this.wavesurfer=e,this.setupEventListeners()}setupEventListeners(){this.wavesurfer&&(this.teardownEventListeners(),this.handleTimeUpdate=e=>{this.events.onTimeUpdate?.(e*1e3)},this.handlePause=()=>{this.isPlaying=!1,this.events.onPause?.()},this.handlePlay=()=>{this.isPlaying=!0,this.events.onPlay?.()},this.handleFinish=()=>{this.isPlaying=!1,this.events.onFinish?.()},this.handleReady=()=>{this.events.onReady?.()},this.handleError=e=>{const o=e instanceof Error?e:new Error(String(e));this.events.onError?.(o)},this.wavesurfer.on("timeupdate",this.handleTimeUpdate),this.wavesurfer.on("pause",this.handlePause),this.wavesurfer.on("play",this.handlePlay),this.wavesurfer.on("finish",this.handleFinish),this.wavesurfer.on("ready",this.handleReady),this.wavesurfer.on("error",this.handleError))}setEventHandlers(e){this.events=e}async load(e){if(!this.wavesurfer)throw new Error("WaveSurfer not initialized");this.cleanupPreviousUrl();let o,n=null;try{if(e instanceof Blob)n=URL.createObjectURL(e),o=n;else if(e instanceof ArrayBuffer){const r=new Blob([e]);n=URL.createObjectURL(r),o=n}else o=e;this.currentBlobUrl=n,await this.wavesurfer.load(o)}catch(r){throw this.cleanupPreviousUrl(),r}}async play(){if(!this.wavesurfer)throw new Error("WaveSurfer not initialized");await this.wavesurfer.play()}pause(){this.wavesurfer&&this.wavesurfer.pause()}getDuration(){return this.wavesurfer?this.wavesurfer.getDuration()*1e3:0}getCurrentTime(){return this.wavesurfer?this.wavesurfer.getCurrentTime()*1e3:0}getIsPlaying(){return this.isPlaying}seekToStart(){this.wavesurfer&&this.wavesurfer.seekTo(0)}cleanupPreviousUrl(){this.currentBlobUrl&&(URL.revokeObjectURL(this.currentBlobUrl),this.currentBlobUrl=null)}destroy(){this.pause(),this.cleanupPreviousUrl(),this.wavesurfer&&(this.teardownEventListeners(),this.wavesurfer.empty(),this.wavesurfer=null),this.events={},this.isPlaying=!1,this.handleTimeUpdate=void 0,this.handlePause=void 0,this.handlePlay=void 0,this.handleFinish=void 0,this.handleReady=void 0,this.handleError=void 0}teardownEventListeners(){this.wavesurfer&&(this.handleTimeUpdate&&(this.wavesurfer.un("timeupdate",this.handleTimeUpdate),this.handleTimeUpdate=void 0),this.handlePause&&(this.wavesurfer.un("pause",this.handlePause),this.handlePause=void 0),this.handlePlay&&(this.wavesurfer.un("play",this.handlePlay),this.handlePlay=void 0),this.handleFinish&&(this.wavesurfer.un("finish",this.handleFinish),this.handleFinish=void 0),this.handleReady&&(this.wavesurfer.un("ready",this.handleReady),this.handleReady=void 0),this.handleError&&(this.wavesurfer.un("error",this.handleError),this.handleError=void 0))}}function I(l){return l.name==="NotAllowedError"||l.name==="PermissionDeniedError"||l.message?.toLowerCase().includes("permission denied")}class K{constructor(e={}){this.wavesurfer=null,this.recordPlugin=null,this.isRecording=!1,this.recordEndResolve=null,this.recordEndReject=null,this.events={},this.options=e}initialize(e,o){this.wavesurfer=e;try{const n={renderRecordedAudio:!1,mimeType:"audio/webm"};this.recordPlugin=e.registerPlugin(o.create(n)),this.setupEventListeners()}catch(n){const r=n instanceof Error?n:new Error(String(n));throw I(r)?(this.events.onPermissionDenied?.(),new Error("Microphone permission denied")):(this.events.onError?.(r),r)}}setupEventListeners(){this.recordPlugin&&(this.recordPlugin.on("record-start",()=>{this.isRecording=!0,this.events.onRecordStart?.()}),this.recordPlugin.on("record-end",e=>{this.isRecording=!1,this.events.onRecordEnd?.(e),this.recordEndResolve&&e&&e.size>0?(this.recordEndResolve(e),this.recordEndResolve=null,this.recordEndReject=null):this.recordEndReject?(this.recordEndReject(new Error("Invalid or empty recording")),this.recordEndResolve=null,this.recordEndReject=null):(this.recordEndResolve=null,this.recordEndReject=null)}),this.recordPlugin.on("record-progress",e=>{this.events.onRecordProgress?.(e)}))}setEventHandlers(e){this.events=e}async startRecording(){if(!this.recordPlugin)throw new Error("Record plugin not initialized");if(this.isRecording)return;const e=typeof this.options.sampleRate=="number"?this.options.sampleRate:void 0,o={};e!==void 0&&(o.sampleRate={ideal:e}),await this.startRecordingWithConstraints(o,e!==void 0)}async startRecordingWithConstraints(e,o){if(!this.recordPlugin)throw new Error("Record plugin not initialized");try{const n=Object.keys(e).length?e:void 0;await this.recordPlugin.startRecording(n)}catch(n){const r=n instanceof Error?n:new Error(String(n));if(I(r))throw this.events.onPermissionDenied?.(),new Error("Microphone permission denied");if(o&&(r.name==="OverconstrainedError"||r.name==="NotReadableError")){this.options.sampleRate=void 0,await this.startRecordingWithConstraints({},!1);return}throw this.events.onError?.(r),r}}async stopRecording(){if(!this.recordPlugin||!this.isRecording)throw new Error("Not currently recording");try{return await new Promise((e,o)=>{this.recordEndResolve=e,this.recordEndReject=o,this.recordPlugin?.stopRecording()})}catch(e){const o=e instanceof Error?e:new Error(String(e));throw this.events.onError?.(o),o}}cancelRecording(){this.recordPlugin&&this.isRecording&&(this.recordPlugin.stopRecording(),this.isRecording=!1,this.recordEndResolve=null,this.recordEndReject=null)}destroy(){this.cancelRecording(),this.recordPlugin&&(this.recordPlugin.destroy(),this.recordPlugin=null),this.wavesurfer=null,this.events={}}}const X=4,Y=4,ee=8,re=0,te=16e3;function se({containerRef:l,sampleRate:e,events:o,waveformPadding:n=0}){const r=Z(),[d,s]=i.useState("idle"),[p,h]=i.useState(null),[m,c]=i.useState(!1),u=i.useRef(null),y=i.useRef(null),a=i.useRef(null),f=i.useRef(o),S=i.useRef(!1),D=i.useRef(!1),E=i.useRef(new Set),P=i.useRef(!1),b=e===void 0?te:e,A=i.useCallback(()=>{E.current.clear(),c(!1),y.current&&(y.current.destroy(),y.current=null),a.current&&(a.current.destroy(),a.current=null),u.current&&(u.current.destroy(),u.current=null),S.current=!1,P.current=!1,s("idle"),h(null)},[]),x=i.useCallback(()=>{const t=Array.from(E.current);E.current.clear(),t.forEach(w=>{w.resolve()})},[]),_=i.useCallback(t=>{c(!1);const w=Array.from(E.current);E.current.clear(),w.forEach(v=>{v.reject(t)})},[]),T=i.useCallback(t=>{const w={onPlay:()=>{c(!0),f.current.onPlaybackPlay?.()},onPause:()=>{c(!1),f.current.onPlaybackPause?.()},onFinish:()=>{c(!1),f.current.onPlaybackFinish?.()},onReady:()=>{x()},onError:v=>{c(!1),_(v),f.current.onError?.(v)}};t.setEventHandlers(w)},[x,_]);i.useEffect(()=>{f.current=o,a.current&&T(a.current)},[o,T]);const U=i.useCallback(async()=>{if(!(S.current||D.current||!l.current)){D.current=!0;try{const[t,w]=await Promise.all([M(()=>import("./wavesurfer.esm.D1Sty35j.js"),[],import.meta.url),M(()=>import("./record.DytFsBUt.js"),[],import.meta.url)]),v=t.default,B=w.default,k=v.create({container:l.current,waveColor:r.colors.primary,progressColor:r.colors.bodyText,height:n>0?$(r.sizes.largestElementHeight)-2*n:"auto",barWidth:X,barGap:Y,barRadius:ee,cursorWidth:re,interact:!0});u.current=k,P.current=!1;const C=new K({sampleRate:b});C.initialize(k,B),C.setEventHandlers({onRecordProgress:R=>{f.current.onProgressMs?.(R)},onPermissionDenied:()=>{f.current.onPermissionDenied(),s("idle")},onError:R=>{f.current.onError(R),s("idle")}}),y.current=C;const g=new W;g.initialize(k),a.current=g,T(g),S.current=!0}catch(t){const w=t instanceof Error?t:new Error(String(t));f.current.onError?.(w)}finally{D.current=!1}}},[l,r,b,T,n]);i.useEffect(()=>(U(),()=>{A()}),[A,U]),i.useEffect(()=>{const t=u.current;if(t){if(d==="recording"){t.setOptions({waveColor:r.colors.primary,progressColor:r.colors.primary});return}if(P.current){t.setOptions({interact:!0,waveColor:O(r.colors.fadedText40,r.colors.secondaryBg),progressColor:r.colors.bodyText});return}t.setOptions({waveColor:r.colors.primary,progressColor:r.colors.bodyText})}},[d,r.colors.bodyText,r.colors.fadedText40,r.colors.primary,r.colors.secondaryBg]);const F=i.useCallback(async()=>{if(d!=="recording"){if(S.current||await U(),!y.current)throw new Error("Record backend not initialized");u.current&&u.current.setOptions({waveColor:r.colors.primary,progressColor:r.colors.primary}),P.current=!1,await y.current.startRecording(),s("recording"),h(null),c(!1),f.current.onRecordStart?.()}},[d,U,r.colors.primary]),L=i.useCallback(()=>{a.current&&u.current&&(a.current.destroy(),a.current=new W,a.current.initialize(u.current),E.current.clear(),c(!1),T(a.current)),P.current=!1},[T]),z=i.useCallback(()=>{a.current?.seekToStart(),c(!1),P.current=!0,u.current&&u.current.setOptions({interact:!0,waveColor:O(r.colors.fadedText40,r.colors.secondaryBg),progressColor:r.colors.bodyText})},[r.colors.bodyText,r.colors.fadedText40,r.colors.secondaryBg]),H=i.useCallback(async()=>{if(d!=="recording")throw new Error("Not currently recording");if(!y.current||!a.current)throw new Error("Backends not initialized");try{const t=await y.current.stopRecording();h(t),await new Promise((k,C)=>{if(!a.current){C(new Error("Player not initialized"));return}const g={resolve:()=>{E.current.delete(g),k()},reject:R=>{E.current.delete(g),C(R)}};E.current.add(g),a.current.load(t).catch(R=>{E.current.delete(g),C(R instanceof Error?R:new Error(String(R)))})}),s("idle"),c(!1),z();const v={durationMs:a.current?.getDuration()??0,sampleRate:typeof b=="number"?b:null,mimeType:t.type||"audio/webm",size:t.size},B={blob:t,meta:v};return f.current.onRecordReady?.(t),B}catch(t){const w=t instanceof Error?t:new Error(String(t));return c(!1),s("idle"),f.current.onError(w),{blob:new Blob,meta:{durationMs:0,sampleRate:null,mimeType:"audio/webm",size:0}}}},[d,z,b]),j=i.useCallback(async t=>{const w=t??p;if(!w){const v=new Error("No recorded audio to approve");f.current.onError(v);return}try{const v=await q(w,b);await f.current.onApprove?.(v),h(null),s("idle")}catch(v){const B=v instanceof Error?v:new Error(String(v));f.current.onError(B)}},[p,b]),N=i.useCallback(()=>{d==="recording"&&y.current?.cancelRecording(),L(),h(null),s("idle"),c(!1),P.current=!1,f.current.onCancel?.()},[d,L]),V=i.useMemo(()=>({isPlaying:()=>a.current?.getIsPlaying()??!1,play:async()=>{if(!a.current)throw new Error("Player not initialized");await a.current.play()},pause:()=>{a.current?.pause()},load:async t=>{if(S.current||await U(),!a.current)throw new Error("Player not initialized");await a.current.load(t),z()},getCurrentTimeMs:()=>a.current?.getCurrentTime()??0,getDurationMs:()=>a.current?.getDuration()??0}),[z,U]),G=i.useCallback(t=>{f.current=t},[]);return i.useEffect(()=>()=>{A()},[A]),{state:d,isPlaybackPlaying:m,mountRef:l,start:F,stop:H,approve:j,cancel:N,destroy:A,playback:V,setEventHandlers:G}}export{se as u};
|
|
1
|
+
import{l as Z,r as i,aR as M,ac as $,aS as O}from"./index.y5HxPwg9.js";async function q(l,e=16e3){if(!l||l.size===0)throw new Error("Invalid or empty blob provided");if(!window.AudioContext)throw new Error("AudioContext not supported in this browser");const o=new AudioContext;try{const n=await l.arrayBuffer(),r=await o.decodeAudioData(n),d=e??r.sampleRate,s=await J(r,d);return K(s,d)}finally{o.close()}}async function J(l,e){const{duration:o,numberOfChannels:n,sampleRate:r}=l,d=Math.ceil(o*e);if(!window.OfflineAudioContext)throw new Error("OfflineAudioContext not supported");const s=new OfflineAudioContext(1,d,e),p=s.createBufferSource();if(p.buffer=l,n>1){const h=s.createChannelSplitter(n),m=s.createChannelMerger(1);p.connect(h);for(let c=0;c<n;c++){const u=s.createGain();u.gain.value=1/n,h.connect(u,c),u.connect(m,0,0)}m.connect(s.destination)}else p.connect(s.destination);p.start(0);try{return await s.startRendering()}catch(h){throw new Error(`Failed to resample audio from ${r}Hz to ${e}Hz: ${h instanceof Error?h.message:String(h)}`)}}function K(l,e){const n=l.length,r=n*2+44,d=new ArrayBuffer(r),s=new DataView(d),p=l.getChannelData(0),h=(c,u)=>{for(let y=0;y<u.length;y++)s.setUint8(c+y,u.charCodeAt(y))};h(0,"RIFF"),s.setUint32(4,r-8,!0),h(8,"WAVE"),h(12,"fmt "),s.setUint32(16,16,!0),s.setUint16(20,1,!0),s.setUint16(22,1,!0),s.setUint32(24,e,!0),s.setUint32(28,e*2,!0),s.setUint16(32,2,!0),s.setUint16(34,16,!0),h(36,"data"),s.setUint32(40,n*2,!0);let m=44;for(let c=0;c<n;c++){const u=Math.max(-1,Math.min(1,p[c]));s.setInt16(m,u*32767,!0),m+=2}return new Blob([d],{type:"audio/wav"})}class W{constructor(){this.wavesurfer=null,this.currentBlobUrl=null,this.events={},this.isPlaying=!1}initialize(e){this.wavesurfer=e,this.setupEventListeners()}setupEventListeners(){this.wavesurfer&&(this.teardownEventListeners(),this.handleTimeUpdate=e=>{this.events.onTimeUpdate?.(e*1e3)},this.handlePause=()=>{this.isPlaying=!1,this.events.onPause?.()},this.handlePlay=()=>{this.isPlaying=!0,this.events.onPlay?.()},this.handleFinish=()=>{this.isPlaying=!1,this.events.onFinish?.()},this.handleReady=()=>{this.events.onReady?.()},this.handleError=e=>{const o=e instanceof Error?e:new Error(String(e));this.events.onError?.(o)},this.wavesurfer.on("timeupdate",this.handleTimeUpdate),this.wavesurfer.on("pause",this.handlePause),this.wavesurfer.on("play",this.handlePlay),this.wavesurfer.on("finish",this.handleFinish),this.wavesurfer.on("ready",this.handleReady),this.wavesurfer.on("error",this.handleError))}setEventHandlers(e){this.events=e}async load(e){if(!this.wavesurfer)throw new Error("WaveSurfer not initialized");this.cleanupPreviousUrl();let o,n=null;try{if(e instanceof Blob)n=URL.createObjectURL(e),o=n;else if(e instanceof ArrayBuffer){const r=new Blob([e]);n=URL.createObjectURL(r),o=n}else o=e;this.currentBlobUrl=n,await this.wavesurfer.load(o)}catch(r){throw this.cleanupPreviousUrl(),r}}async play(){if(!this.wavesurfer)throw new Error("WaveSurfer not initialized");await this.wavesurfer.play()}pause(){this.wavesurfer&&this.wavesurfer.pause()}getDuration(){return this.wavesurfer?this.wavesurfer.getDuration()*1e3:0}getCurrentTime(){return this.wavesurfer?this.wavesurfer.getCurrentTime()*1e3:0}getIsPlaying(){return this.isPlaying}seekToStart(){this.wavesurfer&&this.wavesurfer.seekTo(0)}cleanupPreviousUrl(){this.currentBlobUrl&&(URL.revokeObjectURL(this.currentBlobUrl),this.currentBlobUrl=null)}destroy(){this.pause(),this.cleanupPreviousUrl(),this.wavesurfer&&(this.teardownEventListeners(),this.wavesurfer.empty(),this.wavesurfer=null),this.events={},this.isPlaying=!1,this.handleTimeUpdate=void 0,this.handlePause=void 0,this.handlePlay=void 0,this.handleFinish=void 0,this.handleReady=void 0,this.handleError=void 0}teardownEventListeners(){this.wavesurfer&&(this.handleTimeUpdate&&(this.wavesurfer.un("timeupdate",this.handleTimeUpdate),this.handleTimeUpdate=void 0),this.handlePause&&(this.wavesurfer.un("pause",this.handlePause),this.handlePause=void 0),this.handlePlay&&(this.wavesurfer.un("play",this.handlePlay),this.handlePlay=void 0),this.handleFinish&&(this.wavesurfer.un("finish",this.handleFinish),this.handleFinish=void 0),this.handleReady&&(this.wavesurfer.un("ready",this.handleReady),this.handleReady=void 0),this.handleError&&(this.wavesurfer.un("error",this.handleError),this.handleError=void 0))}}function I(l){return l.name==="NotAllowedError"||l.name==="PermissionDeniedError"||l.message?.toLowerCase().includes("permission denied")}class Q{constructor(e={}){this.wavesurfer=null,this.recordPlugin=null,this.isRecording=!1,this.recordEndResolve=null,this.recordEndReject=null,this.events={},this.options=e}initialize(e,o){this.wavesurfer=e;try{const n={renderRecordedAudio:!1,mimeType:"audio/webm"};this.recordPlugin=e.registerPlugin(o.create(n)),this.setupEventListeners()}catch(n){const r=n instanceof Error?n:new Error(String(n));throw I(r)?(this.events.onPermissionDenied?.(),new Error("Microphone permission denied")):(this.events.onError?.(r),r)}}setupEventListeners(){this.recordPlugin&&(this.recordPlugin.on("record-start",()=>{this.isRecording=!0,this.events.onRecordStart?.()}),this.recordPlugin.on("record-end",e=>{this.isRecording=!1,this.events.onRecordEnd?.(e),this.recordEndResolve&&e&&e.size>0?(this.recordEndResolve(e),this.recordEndResolve=null,this.recordEndReject=null):this.recordEndReject?(this.recordEndReject(new Error("Invalid or empty recording")),this.recordEndResolve=null,this.recordEndReject=null):(this.recordEndResolve=null,this.recordEndReject=null)}),this.recordPlugin.on("record-progress",e=>{this.events.onRecordProgress?.(e)}))}setEventHandlers(e){this.events=e}async startRecording(){if(!this.recordPlugin)throw new Error("Record plugin not initialized");if(this.isRecording)return;const e=typeof this.options.sampleRate=="number"?this.options.sampleRate:void 0,o={};e!==void 0&&(o.sampleRate={ideal:e}),await this.startRecordingWithConstraints(o,e!==void 0)}async startRecordingWithConstraints(e,o){if(!this.recordPlugin)throw new Error("Record plugin not initialized");try{const n=Object.keys(e).length?e:void 0;await this.recordPlugin.startRecording(n)}catch(n){const r=n instanceof Error?n:new Error(String(n));if(I(r))throw this.events.onPermissionDenied?.(),new Error("Microphone permission denied");if(o&&(r.name==="OverconstrainedError"||r.name==="NotReadableError")){this.options.sampleRate=void 0,await this.startRecordingWithConstraints({},!1);return}throw this.events.onError?.(r),r}}async stopRecording(){if(!this.recordPlugin||!this.isRecording)throw new Error("Not currently recording");try{return await new Promise((e,o)=>{this.recordEndResolve=e,this.recordEndReject=o,this.recordPlugin?.stopRecording()})}catch(e){const o=e instanceof Error?e:new Error(String(e));throw this.events.onError?.(o),o}}cancelRecording(){this.recordPlugin&&this.isRecording&&(this.recordPlugin.stopRecording(),this.isRecording=!1,this.recordEndResolve=null,this.recordEndReject=null)}destroy(){this.cancelRecording(),this.recordPlugin&&(this.recordPlugin.destroy(),this.recordPlugin=null),this.wavesurfer=null,this.events={}}}const X=4,Y=4,ee=8,re=0,te=16e3;function se({containerRef:l,sampleRate:e,events:o,waveformPadding:n=0}){const r=Z(),[d,s]=i.useState("idle"),[p,h]=i.useState(null),[m,c]=i.useState(!1),u=i.useRef(null),y=i.useRef(null),a=i.useRef(null),f=i.useRef(o),U=i.useRef(!1),D=i.useRef(!1),E=i.useRef(new Set),P=i.useRef(!1),b=e===void 0?te:e,A=i.useCallback(()=>{E.current.clear(),c(!1),y.current&&(y.current.destroy(),y.current=null),a.current&&(a.current.destroy(),a.current=null),u.current&&(u.current.destroy(),u.current=null),U.current=!1,P.current=!1,s("idle"),h(null)},[]),x=i.useCallback(()=>{const t=Array.from(E.current);E.current.clear(),t.forEach(w=>{w.resolve()})},[]),_=i.useCallback(t=>{c(!1);const w=Array.from(E.current);E.current.clear(),w.forEach(v=>{v.reject(t)})},[]),T=i.useCallback(t=>{const w={onPlay:()=>{c(!0),f.current.onPlaybackPlay?.()},onPause:()=>{c(!1),f.current.onPlaybackPause?.()},onFinish:()=>{c(!1),f.current.onPlaybackFinish?.()},onReady:()=>{x()},onError:v=>{c(!1),_(v),f.current.onError?.(v)}};t.setEventHandlers(w)},[x,_]);i.useEffect(()=>{f.current=o,a.current&&T(a.current)},[o,T]);const S=i.useCallback(async()=>{if(!(U.current||D.current||!l.current)){D.current=!0;try{const[t,w]=await Promise.all([M(()=>import("./wavesurfer.esm.D1Sty35j.js"),[],import.meta.url),M(()=>import("./record.DytFsBUt.js"),[],import.meta.url)]),v=t.default,B=w.default,k=v.create({container:l.current,waveColor:r.colors.primary,progressColor:r.colors.bodyText,height:n>0?$(r.sizes.largestElementHeight)-2*n:"auto",barWidth:X,barGap:Y,barRadius:ee,cursorWidth:re,interact:!0});u.current=k,P.current=!1;const C=new Q({sampleRate:b});C.initialize(k,B),C.setEventHandlers({onRecordProgress:R=>{f.current.onProgressMs?.(R)},onPermissionDenied:()=>{f.current.onPermissionDenied(),s("idle")},onError:R=>{f.current.onError(R),s("idle")}}),y.current=C;const g=new W;g.initialize(k),a.current=g,T(g),U.current=!0}catch(t){const w=t instanceof Error?t:new Error(String(t));f.current.onError?.(w)}finally{D.current=!1}}},[l,r,b,T,n]);i.useEffect(()=>(S(),()=>{A()}),[A,S]),i.useEffect(()=>{const t=u.current;if(t){if(d==="recording"){t.setOptions({waveColor:r.colors.primary,progressColor:r.colors.primary});return}if(P.current){t.setOptions({interact:!0,waveColor:O(r.colors.fadedText40,r.colors.secondaryBg),progressColor:r.colors.bodyText});return}t.setOptions({waveColor:r.colors.primary,progressColor:r.colors.bodyText})}},[d,r.colors.bodyText,r.colors.fadedText40,r.colors.primary,r.colors.secondaryBg]);const F=i.useCallback(async()=>{if(d!=="recording"){if(U.current||await S(),!y.current)throw new Error("Record backend not initialized");u.current&&u.current.setOptions({waveColor:r.colors.primary,progressColor:r.colors.primary}),P.current=!1,await y.current.startRecording(),s("recording"),h(null),c(!1),f.current.onRecordStart?.()}},[d,S,r.colors.primary]),L=i.useCallback(()=>{a.current&&u.current&&(a.current.destroy(),a.current=new W,a.current.initialize(u.current),E.current.clear(),c(!1),T(a.current)),P.current=!1},[T]),z=i.useCallback(()=>{a.current?.seekToStart(),c(!1),P.current=!0,u.current&&u.current.setOptions({interact:!0,waveColor:O(r.colors.fadedText40,r.colors.secondaryBg),progressColor:r.colors.bodyText})},[r.colors.bodyText,r.colors.fadedText40,r.colors.secondaryBg]),H=i.useCallback(async()=>{if(d!=="recording")throw new Error("Not currently recording");if(!y.current||!a.current)throw new Error("Backends not initialized");try{const t=await y.current.stopRecording();h(t),await new Promise((k,C)=>{if(!a.current){C(new Error("Player not initialized"));return}const g={resolve:()=>{E.current.delete(g),k()},reject:R=>{E.current.delete(g),C(R)}};E.current.add(g),a.current.load(t).catch(R=>{E.current.delete(g),C(R instanceof Error?R:new Error(String(R)))})}),s("idle"),c(!1),z();const v={durationMs:a.current?.getDuration()??0,sampleRate:typeof b=="number"?b:null,mimeType:t.type||"audio/webm",size:t.size},B={blob:t,meta:v};return f.current.onRecordReady?.(t),B}catch(t){const w=t instanceof Error?t:new Error(String(t));return c(!1),s("idle"),f.current.onError(w),{blob:new Blob,meta:{durationMs:0,sampleRate:null,mimeType:"audio/webm",size:0}}}},[d,z,b]),j=i.useCallback(async t=>{const w=t??p;if(!w){const v=new Error("No recorded audio to approve");f.current.onError(v);return}try{const v=await q(w,b);await f.current.onApprove?.(v),h(null),s("idle")}catch(v){const B=v instanceof Error?v:new Error(String(v));f.current.onError(B)}},[p,b]),N=i.useCallback(()=>{d==="recording"&&y.current?.cancelRecording(),L(),h(null),s("idle"),c(!1),P.current=!1,f.current.onCancel?.()},[d,L]),V=i.useMemo(()=>({isPlaying:()=>a.current?.getIsPlaying()??!1,play:async()=>{if(!a.current)throw new Error("Player not initialized");await a.current.play()},pause:()=>{a.current?.pause()},load:async t=>{if(U.current||await S(),!a.current)throw new Error("Player not initialized");await a.current.load(t),z()},getCurrentTimeMs:()=>a.current?.getCurrentTime()??0,getDurationMs:()=>a.current?.getDuration()??0}),[z,S]),G=i.useCallback(t=>{f.current=t},[]);return i.useEffect(()=>()=>{A()},[A]),{state:d,isPlaybackPlaying:m,mountRef:l,start:F,stop:H,approve:j,cancel:N,destroy:A,playback:V,setEventHandlers:G}}export{se as u};
|
streamlit/static/static/js/{withCalculatedWidth.YaK0HIIP.js → withCalculatedWidth.BREyS0pJ.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{h as l,k as h,j as s,d as n}from"./index.
|
|
1
|
+
import{h as l,k as h,j as s,d as n}from"./index.y5HxPwg9.js";const o=t=>{const a=e=>{const{width:i,elementRef:c}=h();return s(n,{ref:c,children:s(t,{...e,width:i})})};return a.displayName=`withCalculatedWidth(${t.displayName||t.name})`,l(a,t)};export{o as w};
|
streamlit/static/static/js/{withFullScreenWrapper.CcWCKoY8.js → withFullScreenWrapper.DYDiEOrW.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as n,z as f,
|
|
1
|
+
import{r as n,z as f,b7 as p,b8 as h,l as x,k as y,j as i,h as g}from"./index.y5HxPwg9.js";const m=n.createContext(null);m.displayName="ElementFullscreenContext";const w=f("div",{target:"e5bcvgj0"})(({theme:e,isExpanded:t})=>({width:"100%",height:"100%",...t?{position:"fixed",top:0,left:0,bottom:0,right:0,background:e.colors.bgColor,zIndex:e.zIndices.fullscreenWrapper,padding:e.spacing.md,paddingTop:e.sizes.fullScreenHeaderHeight,overflow:"auto",display:"flex",alignItems:"center",justifyContent:"center"}:{}})),C=()=>{const{setFullScreen:e}=n.useContext(p),[t,s]=n.useState(!1),{fullHeight:a,fullWidth:c}=h(),l=n.useCallback(r=>{s(r),e(r)},[e]),u=n.useCallback(()=>{document.body.style.overflow="hidden",l(!0)},[l]),o=n.useCallback(()=>{document.body.style.overflow="unset",l(!1)},[l]),d=n.useCallback(r=>{r.keyCode===27&&t&&o()},[o,t]);return n.useEffect(()=>(document.addEventListener("keydown",d,!1),()=>{document.removeEventListener("keydown",d,!1)}),[d]),n.useMemo(()=>({expanded:t,zoomIn:u,zoomOut:o,fullHeight:a,fullWidth:c}),[t,u,o,a,c])},b=({children:e})=>{const t=x(),{expanded:s,fullHeight:a,fullWidth:c,zoomIn:l,zoomOut:u}=C(),{width:o,elementRef:d}=y(),r=n.useMemo(()=>({width:s?c:o,height:s?a:void 0,expanded:s,expand:l,collapse:u}),[s,a,c,o,l,u]);return i(m.Provider,{value:r,children:i(w,{ref:d,isExpanded:s,"data-testid":"stFullScreenFrame",theme:t,children:e})})};function S(e){const t=s=>i(b,{children:i(e,{...s})});return t.displayName=`withFullScreenWrapper(${e.displayName||e.name})`,g(t,e)}export{m as E,S as w};
|
|
Binary file
|
streamlit/testing/v1/app_test.py
CHANGED
|
@@ -55,6 +55,7 @@ from streamlit.testing.v1.element_tree import (
|
|
|
55
55
|
Error,
|
|
56
56
|
Exception, # noqa: A004
|
|
57
57
|
Expander,
|
|
58
|
+
Feedback,
|
|
58
59
|
Header,
|
|
59
60
|
Info,
|
|
60
61
|
Json,
|
|
@@ -468,15 +469,16 @@ class AppTest:
|
|
|
468
469
|
|
|
469
470
|
@property
|
|
470
471
|
def button_group(self) -> WidgetList[ButtonGroup[Any]]:
|
|
471
|
-
"""Sequence of all ``st.
|
|
472
|
+
"""Sequence of all ``st.pills`` and ``st.segmented_control`` widgets.
|
|
472
473
|
|
|
473
474
|
Returns
|
|
474
475
|
-------
|
|
475
476
|
WidgetList of ButtonGroup
|
|
476
|
-
Sequence of all ``st.
|
|
477
|
-
accessed from a WidgetList by index
|
|
478
|
-
example, ``at.button_group[0]`` for
|
|
479
|
-
``at.button_group(key="my_key")`` for a widget
|
|
477
|
+
Sequence of all ``st.pills`` and ``st.segmented_control`` widgets.
|
|
478
|
+
Individual widgets can be accessed from a WidgetList by index
|
|
479
|
+
(order on the page) or key. For example, ``at.button_group[0]`` for
|
|
480
|
+
the first widget or ``at.button_group(key="my_key")`` for a widget
|
|
481
|
+
with a given key.
|
|
480
482
|
"""
|
|
481
483
|
return self._tree.button_group
|
|
482
484
|
|
|
@@ -665,6 +667,20 @@ class AppTest:
|
|
|
665
667
|
"""
|
|
666
668
|
return self._tree.exception
|
|
667
669
|
|
|
670
|
+
@property
|
|
671
|
+
def feedback(self) -> WidgetList[Feedback]:
|
|
672
|
+
"""Sequence of all ``st.feedback`` widgets.
|
|
673
|
+
|
|
674
|
+
Returns
|
|
675
|
+
-------
|
|
676
|
+
WidgetList of Feedback
|
|
677
|
+
Sequence of all ``st.feedback`` widgets. Individual widgets can be
|
|
678
|
+
accessed from a WidgetList by index (order on the page) or key. For
|
|
679
|
+
example, ``at.feedback[0]`` for the first widget or
|
|
680
|
+
``at.feedback(key="my_key")`` to access by key.
|
|
681
|
+
"""
|
|
682
|
+
return self._tree.feedback
|
|
683
|
+
|
|
668
684
|
@property
|
|
669
685
|
def expander(self) -> Sequence[Expander]:
|
|
670
686
|
"""Sequence of all ``st.expander`` elements.
|
|
@@ -25,6 +25,7 @@ from datetime import date, datetime, time, timedelta
|
|
|
25
25
|
from typing import (
|
|
26
26
|
TYPE_CHECKING,
|
|
27
27
|
Any,
|
|
28
|
+
ClassVar,
|
|
28
29
|
Generic,
|
|
29
30
|
TypeAlias,
|
|
30
31
|
TypeVar,
|
|
@@ -47,6 +48,7 @@ from streamlit.elements.widgets.time_widgets import (
|
|
|
47
48
|
)
|
|
48
49
|
from streamlit.proto.Alert_pb2 import Alert as AlertProto
|
|
49
50
|
from streamlit.proto.Checkbox_pb2 import Checkbox as CheckboxProto
|
|
51
|
+
from streamlit.proto.GapSize_pb2 import GapSize
|
|
50
52
|
from streamlit.proto.Markdown_pb2 import Markdown as MarkdownProto
|
|
51
53
|
from streamlit.proto.Slider_pb2 import Slider as SliderProto
|
|
52
54
|
from streamlit.proto.WidgetStates_pb2 import WidgetState, WidgetStates
|
|
@@ -66,6 +68,7 @@ if TYPE_CHECKING:
|
|
|
66
68
|
from streamlit.proto.DateTimeInput_pb2 import DateTimeInput as DateTimeInputProto
|
|
67
69
|
from streamlit.proto.Element_pb2 import Element as ElementProto
|
|
68
70
|
from streamlit.proto.Exception_pb2 import Exception as ExceptionProto
|
|
71
|
+
from streamlit.proto.Feedback_pb2 import Feedback as FeedbackProto
|
|
69
72
|
from streamlit.proto.ForwardMsg_pb2 import ForwardMsg
|
|
70
73
|
from streamlit.proto.Heading_pb2 import Heading as HeadingProto
|
|
71
74
|
from streamlit.proto.Json_pb2 import Json as JsonProto
|
|
@@ -634,7 +637,6 @@ class Json(Element):
|
|
|
634
637
|
class Markdown(Element):
|
|
635
638
|
proto: MarkdownProto = field(repr=False)
|
|
636
639
|
|
|
637
|
-
is_caption: bool
|
|
638
640
|
allow_html: bool
|
|
639
641
|
key: None
|
|
640
642
|
|
|
@@ -648,6 +650,11 @@ class Markdown(Element):
|
|
|
648
650
|
def value(self) -> str:
|
|
649
651
|
return self.proto.body
|
|
650
652
|
|
|
653
|
+
@property
|
|
654
|
+
def is_caption(self) -> bool:
|
|
655
|
+
"""Whether this is a caption element (derived from element_type)."""
|
|
656
|
+
return self.proto.element_type == MarkdownProto.Type.CAPTION
|
|
657
|
+
|
|
651
658
|
|
|
652
659
|
@dataclass(repr=False)
|
|
653
660
|
class Caption(Markdown):
|
|
@@ -705,7 +712,7 @@ class Metric(Element):
|
|
|
705
712
|
|
|
706
713
|
@dataclass(repr=False)
|
|
707
714
|
class ButtonGroup(Widget, Generic[T]):
|
|
708
|
-
"""A representation of
|
|
715
|
+
"""A representation of ``st.pills`` and ``st.segmented_control``."""
|
|
709
716
|
|
|
710
717
|
_value: list[T] | None
|
|
711
718
|
|
|
@@ -785,6 +792,58 @@ class ButtonGroup(Widget, Generic[T]):
|
|
|
785
792
|
return self
|
|
786
793
|
|
|
787
794
|
|
|
795
|
+
@dataclass(repr=False)
|
|
796
|
+
class Feedback(Widget):
|
|
797
|
+
"""A representation of ``st.feedback``."""
|
|
798
|
+
|
|
799
|
+
_value: int | InitialValue | None
|
|
800
|
+
|
|
801
|
+
proto: FeedbackProto = field(repr=False)
|
|
802
|
+
form_id: str
|
|
803
|
+
|
|
804
|
+
def __init__(self, proto: FeedbackProto, root: ElementTree) -> None:
|
|
805
|
+
super().__init__(proto, root)
|
|
806
|
+
self._value = InitialValue()
|
|
807
|
+
self.type = "feedback"
|
|
808
|
+
|
|
809
|
+
@property
|
|
810
|
+
def _widget_state(self) -> WidgetState:
|
|
811
|
+
"""Protobuf message representing the state of the widget, including
|
|
812
|
+
any interactions that have happened.
|
|
813
|
+
Should be the same as the frontend would produce for those interactions.
|
|
814
|
+
|
|
815
|
+
Uses string_value as wire format to distinguish three states:
|
|
816
|
+
- None: User explicitly cleared -> string_value = ""
|
|
817
|
+
- int: User selected -> string_value = str(value)
|
|
818
|
+
- No string_value set: No interaction yet (use default)
|
|
819
|
+
"""
|
|
820
|
+
ws = WidgetState()
|
|
821
|
+
ws.id = self.id
|
|
822
|
+
|
|
823
|
+
# Get the effective value: either from explicit set_value() or session state
|
|
824
|
+
effective_value = self.value
|
|
825
|
+
|
|
826
|
+
if effective_value is None:
|
|
827
|
+
ws.string_value = "" # Cleared or no default
|
|
828
|
+
else:
|
|
829
|
+
ws.string_value = str(effective_value) # User selected a value
|
|
830
|
+
return ws
|
|
831
|
+
|
|
832
|
+
@property
|
|
833
|
+
def value(self) -> int | None:
|
|
834
|
+
"""The currently selected feedback value. (int or None)""" # noqa: D400
|
|
835
|
+
if not isinstance(self._value, InitialValue):
|
|
836
|
+
return self._value
|
|
837
|
+
state = self.root.session_state
|
|
838
|
+
assert state
|
|
839
|
+
return cast("int | None", state[self.id])
|
|
840
|
+
|
|
841
|
+
def set_value(self, v: int | None) -> Feedback:
|
|
842
|
+
"""Set the value of the feedback widget. (int or None)""" # noqa: D400
|
|
843
|
+
self._value = v
|
|
844
|
+
return self
|
|
845
|
+
|
|
846
|
+
|
|
788
847
|
@dataclass(repr=False)
|
|
789
848
|
class Multiselect(Widget, Generic[T]):
|
|
790
849
|
"""A representation of ``st.multiselect``."""
|
|
@@ -1617,6 +1676,10 @@ class Block:
|
|
|
1617
1676
|
def exception(self) -> ElementList[Exception]:
|
|
1618
1677
|
return ElementList(self.get("exception")) # type: ignore
|
|
1619
1678
|
|
|
1679
|
+
@property
|
|
1680
|
+
def feedback(self) -> WidgetList[Feedback]:
|
|
1681
|
+
return WidgetList(self.get("feedback")) # type: ignore
|
|
1682
|
+
|
|
1620
1683
|
@property
|
|
1621
1684
|
def expander(self) -> Sequence[Expander]:
|
|
1622
1685
|
return self.get("expander") # type: ignore
|
|
@@ -1836,7 +1899,19 @@ class Column(Block):
|
|
|
1836
1899
|
type: str = field(repr=False)
|
|
1837
1900
|
proto: BlockProto.Column = field(repr=False)
|
|
1838
1901
|
weight: float
|
|
1839
|
-
gap: str
|
|
1902
|
+
gap: str | None
|
|
1903
|
+
|
|
1904
|
+
# Mapping from GapSize enum to string
|
|
1905
|
+
_GAP_SIZE_TO_STRING: ClassVar[dict[int, str | None]] = {
|
|
1906
|
+
GapSize.NONE: None,
|
|
1907
|
+
GapSize.XXSMALL: "xxsmall",
|
|
1908
|
+
GapSize.XSMALL: "xsmall",
|
|
1909
|
+
GapSize.SMALL: "small",
|
|
1910
|
+
GapSize.MEDIUM: "medium",
|
|
1911
|
+
GapSize.LARGE: "large",
|
|
1912
|
+
GapSize.XLARGE: "xlarge",
|
|
1913
|
+
GapSize.XXLARGE: "xxlarge",
|
|
1914
|
+
}
|
|
1840
1915
|
|
|
1841
1916
|
def __init__(
|
|
1842
1917
|
self,
|
|
@@ -1848,7 +1923,7 @@ class Column(Block):
|
|
|
1848
1923
|
self.root = root
|
|
1849
1924
|
self.type = "column"
|
|
1850
1925
|
self.weight = proto.weight
|
|
1851
|
-
self.gap = proto.
|
|
1926
|
+
self.gap = self._GAP_SIZE_TO_STRING.get(proto.gap_config.gap_size)
|
|
1852
1927
|
|
|
1853
1928
|
|
|
1854
1929
|
@dataclass(repr=False)
|
|
@@ -2063,6 +2138,8 @@ def parse_tree_from_messages(messages: list[ForwardMsg]) -> ElementTree:
|
|
|
2063
2138
|
new_node = DateTimeInput(elt.date_time_input, root=root)
|
|
2064
2139
|
elif ty == "exception":
|
|
2065
2140
|
new_node = Exception(elt.exception, root=root)
|
|
2141
|
+
elif ty == "feedback":
|
|
2142
|
+
new_node = Feedback(elt.feedback, root=root)
|
|
2066
2143
|
elif ty == "heading":
|
|
2067
2144
|
if elt.heading.tag == HeadingProtoTag.TITLE_TAG.value:
|
|
2068
2145
|
new_node = Title(elt.heading, root=root)
|
streamlit/web/server/server.py
CHANGED
|
@@ -310,7 +310,6 @@ class Server:
|
|
|
310
310
|
self._runtime = Runtime(
|
|
311
311
|
RuntimeConfig(
|
|
312
312
|
script_path=main_script_path,
|
|
313
|
-
command_line=None,
|
|
314
313
|
media_file_storage=media_file_storage,
|
|
315
314
|
uploaded_file_manager=uploaded_file_mgr,
|
|
316
315
|
cache_storage_manager=create_default_cache_storage_manager(),
|
|
@@ -417,7 +417,6 @@ class App:
|
|
|
417
417
|
return Runtime(
|
|
418
418
|
RuntimeConfig(
|
|
419
419
|
script_path=str(script_path),
|
|
420
|
-
command_line=None,
|
|
421
420
|
media_file_storage=media_file_storage,
|
|
422
421
|
uploaded_file_manager=uploaded_file_mgr,
|
|
423
422
|
cache_storage_manager=create_default_cache_storage_manager(),
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: streamlit-nightly
|
|
3
|
-
Version: 1.53.2.
|
|
3
|
+
Version: 1.53.2.dev20260202
|
|
4
4
|
Summary: A faster way to build and share data apps
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
Author-email: Snowflake Inc <hello@streamlit.io>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://streamlit.io
|
|
8
|
+
Project-URL: Documentation, https://docs.streamlit.io/
|
|
9
9
|
Project-URL: Source Code, https://github.com/streamlit/streamlit
|
|
10
10
|
Project-URL: Bug Tracker, https://github.com/streamlit/streamlit/issues
|
|
11
|
-
Project-URL: Release
|
|
12
|
-
Project-URL: Documentation, https://docs.streamlit.io/
|
|
11
|
+
Project-URL: Release Notes, https://docs.streamlit.io/develop/quick-reference/changelog
|
|
13
12
|
Project-URL: Community, https://discuss.streamlit.io/
|
|
14
|
-
Project-URL: Twitter, https://twitter.com/streamlit
|
|
15
13
|
Classifier: Development Status :: 5 - Production/Stable
|
|
16
14
|
Classifier: Environment :: Console
|
|
17
15
|
Classifier: Environment :: Web Environment
|
|
18
16
|
Classifier: Intended Audience :: Developers
|
|
19
17
|
Classifier: Intended Audience :: Science/Research
|
|
20
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
21
18
|
Classifier: Programming Language :: Python :: 3.10
|
|
22
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -35,20 +32,20 @@ Requires-Dist: altair!=5.4.0,!=5.4.1,<7,>=4.0
|
|
|
35
32
|
Requires-Dist: blinker<2,>=1.5.0
|
|
36
33
|
Requires-Dist: cachetools<7,>=5.5
|
|
37
34
|
Requires-Dist: click<9,>=7.0
|
|
35
|
+
Requires-Dist: gitpython!=3.1.19,<4,>=3.0.7
|
|
38
36
|
Requires-Dist: numpy<3,>=1.23
|
|
39
37
|
Requires-Dist: packaging>=20
|
|
40
38
|
Requires-Dist: pandas<3,>=1.4.0
|
|
41
39
|
Requires-Dist: pillow<13,>=7.1.0
|
|
40
|
+
Requires-Dist: pydeck<1,>=0.8.0b4
|
|
42
41
|
Requires-Dist: protobuf<7,>=3.20
|
|
43
42
|
Requires-Dist: pyarrow>=7.0
|
|
44
43
|
Requires-Dist: requests<3,>=2.27
|
|
45
44
|
Requires-Dist: tenacity<10,>=8.1.0
|
|
46
45
|
Requires-Dist: toml<2,>=0.10.1
|
|
46
|
+
Requires-Dist: tornado!=6.5.0,<7,>=6.0.3
|
|
47
47
|
Requires-Dist: typing-extensions<5,>=4.10.0
|
|
48
48
|
Requires-Dist: watchdog<7,>=2.1.5; platform_system != "Darwin"
|
|
49
|
-
Requires-Dist: gitpython!=3.1.19,<4,>=3.0.7
|
|
50
|
-
Requires-Dist: pydeck<1,>=0.8.0b4
|
|
51
|
-
Requires-Dist: tornado!=6.5.0,<7,>=6.0.3
|
|
52
49
|
Provides-Extra: snowflake
|
|
53
50
|
Requires-Dist: snowflake-snowpark-python[modin]>=1.17.0; python_version < "3.12" and extra == "snowflake"
|
|
54
51
|
Requires-Dist: snowflake-connector-python>=3.3.0; python_version < "3.12" and extra == "snowflake"
|
|
@@ -72,23 +69,11 @@ Provides-Extra: sql
|
|
|
72
69
|
Requires-Dist: SQLAlchemy>=2.0.0; extra == "sql"
|
|
73
70
|
Provides-Extra: performance
|
|
74
71
|
Requires-Dist: orjson>=3.5.0; extra == "performance"
|
|
75
|
-
Requires-Dist: uvloop>=0.15.2; (sys_platform != "win32" and
|
|
72
|
+
Requires-Dist: uvloop>=0.15.2; (sys_platform != "win32" and sys_platform != "cygwin" and platform_python_implementation != "PyPy") and extra == "performance"
|
|
76
73
|
Requires-Dist: httptools>=0.6.3; extra == "performance"
|
|
77
74
|
Provides-Extra: all
|
|
78
75
|
Requires-Dist: streamlit[auth,charts,pdf,performance,snowflake,sql]; extra == "all"
|
|
79
76
|
Requires-Dist: rich>=11.0.0; extra == "all"
|
|
80
|
-
Dynamic: author
|
|
81
|
-
Dynamic: author-email
|
|
82
|
-
Dynamic: classifier
|
|
83
|
-
Dynamic: description
|
|
84
|
-
Dynamic: description-content-type
|
|
85
|
-
Dynamic: home-page
|
|
86
|
-
Dynamic: license
|
|
87
|
-
Dynamic: project-url
|
|
88
|
-
Dynamic: provides-extra
|
|
89
|
-
Dynamic: requires-dist
|
|
90
|
-
Dynamic: requires-python
|
|
91
|
-
Dynamic: summary
|
|
92
77
|
|
|
93
78
|
<br>
|
|
94
79
|
|