streamlit 1.50.0__py3-none-any.whl → 1.51.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. streamlit/__init__.py +4 -1
  2. streamlit/commands/navigation.py +4 -6
  3. streamlit/commands/page_config.py +4 -6
  4. streamlit/components/v2/__init__.py +458 -0
  5. streamlit/components/v2/bidi_component/__init__.py +20 -0
  6. streamlit/components/v2/bidi_component/constants.py +29 -0
  7. streamlit/components/v2/bidi_component/main.py +386 -0
  8. streamlit/components/v2/bidi_component/serialization.py +265 -0
  9. streamlit/components/v2/bidi_component/state.py +92 -0
  10. streamlit/components/v2/component_definition_resolver.py +143 -0
  11. streamlit/components/v2/component_file_watcher.py +403 -0
  12. streamlit/components/v2/component_manager.py +431 -0
  13. streamlit/components/v2/component_manifest_handler.py +122 -0
  14. streamlit/components/v2/component_path_utils.py +245 -0
  15. streamlit/components/v2/component_registry.py +409 -0
  16. streamlit/components/v2/get_bidi_component_manager.py +51 -0
  17. streamlit/components/v2/manifest_scanner.py +615 -0
  18. streamlit/components/v2/presentation.py +198 -0
  19. streamlit/components/v2/types.py +324 -0
  20. streamlit/config.py +456 -53
  21. streamlit/config_option.py +4 -1
  22. streamlit/config_util.py +650 -1
  23. streamlit/dataframe_util.py +15 -8
  24. streamlit/delta_generator.py +6 -4
  25. streamlit/delta_generator_singletons.py +3 -1
  26. streamlit/deprecation_util.py +17 -6
  27. streamlit/elements/arrow.py +37 -9
  28. streamlit/elements/deck_gl_json_chart.py +97 -39
  29. streamlit/elements/dialog_decorator.py +2 -1
  30. streamlit/elements/exception.py +3 -1
  31. streamlit/elements/graphviz_chart.py +1 -3
  32. streamlit/elements/heading.py +3 -5
  33. streamlit/elements/image.py +2 -4
  34. streamlit/elements/layouts.py +31 -11
  35. streamlit/elements/lib/built_in_chart_utils.py +1 -3
  36. streamlit/elements/lib/color_util.py +8 -18
  37. streamlit/elements/lib/column_config_utils.py +4 -8
  38. streamlit/elements/lib/column_types.py +40 -12
  39. streamlit/elements/lib/dialog.py +2 -2
  40. streamlit/elements/lib/image_utils.py +3 -5
  41. streamlit/elements/lib/layout_utils.py +50 -13
  42. streamlit/elements/lib/mutable_status_container.py +2 -2
  43. streamlit/elements/lib/options_selector_utils.py +2 -2
  44. streamlit/elements/lib/utils.py +4 -4
  45. streamlit/elements/map.py +80 -37
  46. streamlit/elements/media.py +5 -7
  47. streamlit/elements/metric.py +3 -5
  48. streamlit/elements/pdf.py +2 -4
  49. streamlit/elements/plotly_chart.py +125 -17
  50. streamlit/elements/progress.py +2 -4
  51. streamlit/elements/space.py +113 -0
  52. streamlit/elements/vega_charts.py +339 -148
  53. streamlit/elements/widgets/audio_input.py +5 -5
  54. streamlit/elements/widgets/button.py +2 -4
  55. streamlit/elements/widgets/button_group.py +33 -7
  56. streamlit/elements/widgets/camera_input.py +2 -4
  57. streamlit/elements/widgets/chat.py +7 -1
  58. streamlit/elements/widgets/color_picker.py +1 -1
  59. streamlit/elements/widgets/data_editor.py +28 -24
  60. streamlit/elements/widgets/file_uploader.py +5 -10
  61. streamlit/elements/widgets/multiselect.py +4 -3
  62. streamlit/elements/widgets/number_input.py +2 -4
  63. streamlit/elements/widgets/radio.py +10 -3
  64. streamlit/elements/widgets/select_slider.py +8 -5
  65. streamlit/elements/widgets/selectbox.py +6 -3
  66. streamlit/elements/widgets/slider.py +38 -42
  67. streamlit/elements/widgets/time_widgets.py +6 -12
  68. streamlit/elements/write.py +27 -6
  69. streamlit/emojis.py +1 -1
  70. streamlit/errors.py +115 -0
  71. streamlit/hello/hello.py +8 -0
  72. streamlit/hello/utils.py +2 -1
  73. streamlit/material_icon_names.py +1 -1
  74. streamlit/navigation/page.py +4 -1
  75. streamlit/proto/ArrowData_pb2.py +27 -0
  76. streamlit/proto/ArrowData_pb2.pyi +46 -0
  77. streamlit/proto/BidiComponent_pb2.py +34 -0
  78. streamlit/proto/BidiComponent_pb2.pyi +153 -0
  79. streamlit/proto/Block_pb2.py +7 -7
  80. streamlit/proto/Block_pb2.pyi +4 -1
  81. streamlit/proto/DeckGlJsonChart_pb2.py +10 -4
  82. streamlit/proto/DeckGlJsonChart_pb2.pyi +9 -3
  83. streamlit/proto/Element_pb2.py +5 -3
  84. streamlit/proto/Element_pb2.pyi +14 -4
  85. streamlit/proto/HeightConfig_pb2.py +2 -2
  86. streamlit/proto/HeightConfig_pb2.pyi +6 -3
  87. streamlit/proto/NewSession_pb2.py +18 -18
  88. streamlit/proto/NewSession_pb2.pyi +25 -6
  89. streamlit/proto/PlotlyChart_pb2.py +8 -6
  90. streamlit/proto/PlotlyChart_pb2.pyi +3 -1
  91. streamlit/proto/Space_pb2.py +27 -0
  92. streamlit/proto/Space_pb2.pyi +42 -0
  93. streamlit/proto/WidgetStates_pb2.py +2 -2
  94. streamlit/proto/WidgetStates_pb2.pyi +13 -3
  95. streamlit/proto/WidthConfig_pb2.py +2 -2
  96. streamlit/proto/WidthConfig_pb2.pyi +6 -3
  97. streamlit/runtime/app_session.py +27 -1
  98. streamlit/runtime/caching/cache_data_api.py +4 -4
  99. streamlit/runtime/caching/cache_errors.py +4 -1
  100. streamlit/runtime/caching/cache_resource_api.py +3 -2
  101. streamlit/runtime/caching/cache_utils.py +2 -1
  102. streamlit/runtime/caching/cached_message_replay.py +3 -3
  103. streamlit/runtime/caching/hashing.py +3 -4
  104. streamlit/runtime/caching/legacy_cache_api.py +2 -1
  105. streamlit/runtime/connection_factory.py +1 -3
  106. streamlit/runtime/forward_msg_queue.py +4 -1
  107. streamlit/runtime/fragment.py +2 -1
  108. streamlit/runtime/memory_media_file_storage.py +1 -1
  109. streamlit/runtime/metrics_util.py +6 -2
  110. streamlit/runtime/runtime.py +14 -0
  111. streamlit/runtime/scriptrunner/exec_code.py +2 -1
  112. streamlit/runtime/scriptrunner/script_runner.py +2 -2
  113. streamlit/runtime/scriptrunner_utils/script_run_context.py +3 -6
  114. streamlit/runtime/secrets.py +2 -4
  115. streamlit/runtime/session_manager.py +3 -1
  116. streamlit/runtime/state/common.py +30 -5
  117. streamlit/runtime/state/presentation.py +85 -0
  118. streamlit/runtime/state/safe_session_state.py +2 -2
  119. streamlit/runtime/state/session_state.py +220 -16
  120. streamlit/runtime/state/widgets.py +19 -3
  121. streamlit/runtime/websocket_session_manager.py +3 -1
  122. streamlit/source_util.py +2 -2
  123. streamlit/static/index.html +2 -2
  124. streamlit/static/manifest.json +243 -226
  125. streamlit/static/static/css/{index.CIiu7Ygf.css → index.BpABIXK9.css} +1 -1
  126. streamlit/static/static/css/index.DgR7E2CV.css +1 -0
  127. streamlit/static/static/js/{ErrorOutline.esm.DUpR0_Ka.js → ErrorOutline.esm.YoJdlW1p.js} +1 -1
  128. streamlit/static/static/js/{FileDownload.esm.CN4j9-1w.js → FileDownload.esm.Ddx8VEYy.js} +1 -1
  129. streamlit/static/static/js/{FileHelper.CaIUKG91.js → FileHelper.90EtOmj9.js} +1 -1
  130. streamlit/static/static/js/{FormClearHelper.DTcdrasw.js → FormClearHelper.BB1Km6eP.js} +1 -1
  131. streamlit/static/static/js/InputInstructions.jhH15PqV.js +1 -0
  132. streamlit/static/static/js/{Particles.CElH0XX2.js → Particles.DUsputn1.js} +1 -1
  133. streamlit/static/static/js/{ProgressBar.DetlP5aY.js → ProgressBar.DLY8H6nE.js} +1 -1
  134. streamlit/static/static/js/{Toolbar.C77ar7rq.js → Toolbar.D8nHCkuz.js} +1 -1
  135. streamlit/static/static/js/{base-input.BQft14La.js → base-input.CJGiNqed.js} +3 -3
  136. streamlit/static/static/js/{checkbox.yZOfXCeX.js → checkbox.Cpdd482O.js} +1 -1
  137. streamlit/static/static/js/{createSuper.Dh9w1cs8.js → createSuper.CuQIogbW.js} +1 -1
  138. streamlit/static/static/js/{data-grid-overlay-editor.DcuHuCyW.js → data-grid-overlay-editor.2Ufgxc6y.js} +1 -1
  139. streamlit/static/static/js/{downloader.MeHtkq8r.js → downloader.CN0K7xlu.js} +1 -1
  140. streamlit/static/static/js/{es6.VpBPGCnM.js → es6.BJcsVXQ0.js} +2 -2
  141. streamlit/static/static/js/{iframeResizer.contentWindow.yMw_ARIL.js → iframeResizer.contentWindow.XzUvQqcZ.js} +1 -1
  142. streamlit/static/static/js/index.B1ZQh4P1.js +1 -0
  143. streamlit/static/static/js/index.BKstZk0M.js +27 -0
  144. streamlit/static/static/js/{index.Cnpi3o3E.js → index.BMcFsUee.js} +1 -1
  145. streamlit/static/static/js/{index.DKv_lNO7.js → index.BR-IdcTb.js} +1 -1
  146. streamlit/static/static/js/{index.FFOzOWzC.js → index.B_dWA3vd.js} +1 -1
  147. streamlit/static/static/js/{index.Bj9JgOEC.js → index.BgnZEMVh.js} +1 -1
  148. streamlit/static/static/js/{index.Bxz2yX3P.js → index.BohqXifI.js} +1 -1
  149. streamlit/static/static/js/{index.Dbe-Q3C-.js → index.Br5nxKNj.js} +1 -1
  150. streamlit/static/static/js/{index.BjCwMzj4.js → index.BrIKVbNc.js} +2 -2
  151. streamlit/static/static/js/index.BtWUPzle.js +1 -0
  152. streamlit/static/static/js/{index.CGYqqs6j.js → index.C0RLraek.js} +1 -1
  153. streamlit/static/static/js/{index.D2QEXQq_.js → index.CAIjskgG.js} +1 -1
  154. streamlit/static/static/js/{index.6xX1278W.js → index.CAj-7vWz.js} +131 -157
  155. streamlit/static/static/js/{index.DK7hD7_w.js → index.CMtEit2O.js} +1 -1
  156. streamlit/static/static/js/{index.DNLrMXgm.js → index.CkRlykEE.js} +1 -1
  157. streamlit/static/static/js/{index.ClELlchS.js → index.CmN3FXfI.js} +1 -1
  158. streamlit/static/static/js/{index.GRUzrudl.js → index.CwbFI1_-.js} +1 -1
  159. streamlit/static/static/js/{index.Ctn27_AE.js → index.CxIUUfab.js} +27 -27
  160. streamlit/static/static/js/index.D2KPNy7e.js +1 -0
  161. streamlit/static/static/js/{index.B0H9IXUJ.js → index.D3GPA5k4.js} +3 -3
  162. streamlit/static/static/js/{index.BycLveZ4.js → index.DGAh7DMq.js} +1 -1
  163. streamlit/static/static/js/index.DKb_NvmG.js +197 -0
  164. streamlit/static/static/js/{index.BPQo7BKk.js → index.DMqgUYKq.js} +1 -1
  165. streamlit/static/static/js/{index.CH1tqnSs.js → index.DOFlg3dS.js} +1 -1
  166. streamlit/static/static/js/{index.64ejlaaT.js → index.DPUXkcQL.js} +1 -1
  167. streamlit/static/static/js/{index.B-hiXRzw.js → index.DX1xY89g.js} +1 -1
  168. streamlit/static/static/js/index.DYATBCsq.js +2 -0
  169. streamlit/static/static/js/{index.DHh-U0dK.js → index.DaSmGJ76.js} +3 -3
  170. streamlit/static/static/js/{index.DuxqVQpd.js → index.Dd7bMeLP.js} +1 -1
  171. streamlit/static/static/js/{index.B4cAbHP6.js → index.DjmmgI5U.js} +1 -1
  172. streamlit/static/static/js/{index.DcPNYEUo.js → index.Dq56CyM2.js} +1 -1
  173. streamlit/static/static/js/{index.CiAQIz1H.js → index.DuiXaS5_.js} +1 -1
  174. streamlit/static/static/js/index.DvFidMLe.js +2 -0
  175. streamlit/static/static/js/{index.C9BdUqTi.js → index.DwkhC5Pc.js} +1 -1
  176. streamlit/static/static/js/{index.B4dUQfni.js → index.Q-3sFn1v.js} +1 -1
  177. streamlit/static/static/js/{index.CMItVsFA.js → index.QJ5QO9sJ.js} +1 -1
  178. streamlit/static/static/js/{index.CTBk8Vk2.js → index.VwTaeety.js} +1 -1
  179. streamlit/static/static/js/{index.Ck8rQ9OL.js → index.YOqQbeX8.js} +1 -1
  180. streamlit/static/static/js/{input.s6pjQ49A.js → input.D4MN_FzN.js} +1 -1
  181. streamlit/static/static/js/{memory.Cuvsdfrl.js → memory.DrZjtdGT.js} +1 -1
  182. streamlit/static/static/js/{number-overlay-editor.DdgVR5m3.js → number-overlay-editor.DRwAw1In.js} +1 -1
  183. streamlit/static/static/js/{possibleConstructorReturn.CqidKeei.js → possibleConstructorReturn.exeeJQEP.js} +1 -1
  184. streamlit/static/static/js/record.B-tDciZb.js +1 -0
  185. streamlit/static/static/js/{sandbox.CCQREcJx.js → sandbox.ClO3IuUr.js} +1 -1
  186. streamlit/static/static/js/{timepicker.mkJF97Bb.js → timepicker.DAhu-vcF.js} +1 -1
  187. streamlit/static/static/js/{toConsumableArray.De7I7KVR.js → toConsumableArray.DNbljYEC.js} +1 -1
  188. streamlit/static/static/js/{uniqueId.RI1LJdtz.js → uniqueId.oG4Gvj1v.js} +1 -1
  189. streamlit/static/static/js/{useBasicWidgetState.CedkNjUW.js → useBasicWidgetState.D6sOH6oI.js} +1 -1
  190. streamlit/static/static/js/{useTextInputAutoExpand.Ca7w8dVs.js → useTextInputAutoExpand.4u3_GcuN.js} +1 -1
  191. streamlit/static/static/js/{useUpdateUiValue.DeXelfRH.js → useUpdateUiValue.F2R3eTeR.js} +1 -1
  192. streamlit/static/static/js/wavesurfer.esm.vI8Eid4k.js +73 -0
  193. streamlit/static/static/js/{withFullScreenWrapper.C3561XxJ.js → withFullScreenWrapper.zothJIsI.js} +1 -1
  194. streamlit/static/static/media/MaterialSymbols-Rounded.C7IFxh57.woff2 +0 -0
  195. streamlit/string_util.py +1 -3
  196. streamlit/testing/v1/app_test.py +2 -2
  197. streamlit/testing/v1/element_tree.py +23 -9
  198. streamlit/testing/v1/util.py +2 -2
  199. streamlit/type_util.py +3 -4
  200. streamlit/url_util.py +1 -3
  201. streamlit/user_info.py +1 -2
  202. streamlit/util.py +3 -1
  203. streamlit/watcher/event_based_path_watcher.py +23 -12
  204. streamlit/watcher/local_sources_watcher.py +11 -1
  205. streamlit/watcher/path_watcher.py +9 -6
  206. streamlit/watcher/polling_path_watcher.py +4 -1
  207. streamlit/watcher/util.py +2 -2
  208. streamlit/web/cli.py +51 -22
  209. streamlit/web/server/bidi_component_request_handler.py +193 -0
  210. streamlit/web/server/component_file_utils.py +97 -0
  211. streamlit/web/server/component_request_handler.py +8 -21
  212. streamlit/web/server/oidc_mixin.py +3 -1
  213. streamlit/web/server/routes.py +2 -2
  214. streamlit/web/server/server.py +9 -0
  215. streamlit/web/server/server_util.py +3 -1
  216. streamlit/web/server/upload_file_request_handler.py +3 -1
  217. {streamlit-1.50.0.dist-info → streamlit-1.51.0.dist-info}/METADATA +4 -5
  218. {streamlit-1.50.0.dist-info → streamlit-1.51.0.dist-info}/RECORD +222 -194
  219. streamlit/static/static/css/index.CHEnSPGk.css +0 -1
  220. streamlit/static/static/js/Hooks.BRba_Own.js +0 -1
  221. streamlit/static/static/js/InputInstructions.xnSDuYeQ.js +0 -1
  222. streamlit/static/static/js/index.Baqa90pe.js +0 -2
  223. streamlit/static/static/js/index.Bm3VbPB5.js +0 -1
  224. streamlit/static/static/js/index.CFMf5_ez.js +0 -197
  225. streamlit/static/static/js/index.Cj7DSzVR.js +0 -73
  226. streamlit/static/static/js/index.DH71Ezyj.js +0 -1
  227. streamlit/static/static/js/index.DW0Grddz.js +0 -1
  228. streamlit/static/static/media/MaterialSymbols-Rounded.DeCZgS-4.woff2 +0 -0
  229. {streamlit-1.50.0.data → streamlit-1.51.0.data}/scripts/streamlit.cmd +0 -0
  230. {streamlit-1.50.0.dist-info → streamlit-1.51.0.dist-info}/WHEEL +0 -0
  231. {streamlit-1.50.0.dist-info → streamlit-1.51.0.dist-info}/entry_points.txt +0 -0
  232. {streamlit-1.50.0.dist-info → streamlit-1.51.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,73 @@
1
+ function y(p,t,e,i){return new(e||(e=Promise))(function(s,n){function r(a){try{l(i.next(a))}catch(o){n(o)}}function h(a){try{l(i.throw(a))}catch(o){n(o)}}function l(a){var o;a.done?s(a.value):(o=a.value,o instanceof e?o:new e(function(c){c(o)})).then(r,h)}l((i=i.apply(p,t||[])).next())})}class T{constructor(){this.listeners={}}on(t,e,i){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),i?.once){const s=()=>{this.un(t,s),this.un(t,e)};return this.on(t,s),s}return()=>this.un(t,e)}un(t,e){var i;(i=this.listeners[t])===null||i===void 0||i.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach(i=>i(...e))}}const R={decode:function(p,t){return y(this,void 0,void 0,function*(){const e=new AudioContext({sampleRate:t});return e.decodeAudioData(p).finally(()=>e.close())})},createBuffer:function(p,t){return typeof p[0]=="number"&&(p=[p]),function(e){const i=e[0];if(i.some(s=>s>1||s<-1)){const s=i.length;let n=0;for(let r=0;r<s;r++){const h=Math.abs(i[r]);h>n&&(n=h)}for(const r of e)for(let h=0;h<s;h++)r[h]/=n}}(p),{duration:t,length:p[0].length,sampleRate:p[0].length/t,numberOfChannels:p.length,getChannelData:e=>p?.[e],copyFromChannel:AudioBuffer.prototype.copyFromChannel,copyToChannel:AudioBuffer.prototype.copyToChannel}}};function _(p,t){const e=t.xmlns?document.createElementNS(t.xmlns,p):document.createElement(p);for(const[i,s]of Object.entries(t))if(i==="children"&&s)for(const[n,r]of Object.entries(s))r instanceof Node?e.appendChild(r):typeof r=="string"?e.appendChild(document.createTextNode(r)):e.appendChild(_(n,r));else i==="style"?Object.assign(e.style,s):i==="textContent"?e.textContent=s:e.setAttribute(i,s.toString());return e}function N(p,t,e){const i=_(p,t||{});return e?.appendChild(i),i}var B=Object.freeze({__proto__:null,createElement:N,default:N});const $={fetchBlob:function(p,t,e){return y(this,void 0,void 0,function*(){const i=yield fetch(p,e);if(i.status>=400)throw new Error(`Failed to fetch ${p}: ${i.status} (${i.statusText})`);return function(s,n){y(this,void 0,void 0,function*(){if(!s.body||!s.headers)return;const r=s.body.getReader(),h=Number(s.headers.get("Content-Length"))||0;let l=0;const a=c=>y(this,void 0,void 0,function*(){l+=c?.length||0;const d=Math.round(l/h*100);n(d)}),o=()=>y(this,void 0,void 0,function*(){let c;try{c=yield r.read()}catch{return}c.done||(a(c.value),yield o())});o()})}(i.clone(),t),i.blob()})}};class j extends T{constructor(t){super(),this.isExternalMedia=!1,t.media?(this.media=t.media,this.isExternalMedia=!0):this.media=document.createElement("audio"),t.mediaControls&&(this.media.controls=!0),t.autoplay&&(this.media.autoplay=!0),t.playbackRate!=null&&this.onMediaEvent("canplay",()=>{t.playbackRate!=null&&(this.media.playbackRate=t.playbackRate)},{once:!0})}onMediaEvent(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e,i)}getSrc(){return this.media.currentSrc||this.media.src||""}revokeSrc(){const t=this.getSrc();t.startsWith("blob:")&&URL.revokeObjectURL(t)}canPlayType(t){return this.media.canPlayType(t)!==""}setSrc(t,e){const i=this.getSrc();if(t&&i===t)return;this.revokeSrc();const s=e instanceof Blob&&(this.canPlayType(e.type)||!t)?URL.createObjectURL(e):t;if(i&&this.media.removeAttribute("src"),s||t)try{this.media.src=s}catch{this.media.src=t}}destroy(){this.isExternalMedia||(this.media.pause(),this.media.remove(),this.revokeSrc(),this.media.removeAttribute("src"),this.media.load())}setMediaElement(t){this.media=t}play(){return y(this,void 0,void 0,function*(){try{return yield this.media.play()}catch(t){if(t instanceof DOMException&&t.name==="AbortError")return;throw t}})}pause(){this.media.pause()}isPlaying(){return!this.media.paused&&!this.media.ended}setTime(t){this.media.currentTime=Math.max(0,Math.min(t,this.getDuration()))}getDuration(){return this.media.duration}getCurrentTime(){return this.media.currentTime}getVolume(){return this.media.volume}setVolume(t){this.media.volume=t}getMuted(){return this.media.muted}setMuted(t){this.media.muted=t}getPlaybackRate(){return this.media.playbackRate}isSeeking(){return this.media.seeking}setPlaybackRate(t,e){e!=null&&(this.media.preservesPitch=e),this.media.playbackRate=t}getMediaElement(){return this.media}setSinkId(t){return this.media.setSinkId(t)}}class D extends T{constructor(t,e){super(),this.timeouts=[],this.isScrollable=!1,this.audioData=null,this.resizeObserver=null,this.lastContainerWidth=0,this.isDragging=!1,this.subscriptions=[],this.unsubscribeOnScroll=[],this.subscriptions=[],this.options=t;const i=this.parentFromOptionsContainer(t.container);this.parent=i;const[s,n]=this.initHtml();i.appendChild(s),this.container=s,this.scrollContainer=n.querySelector(".scroll"),this.wrapper=n.querySelector(".wrapper"),this.canvasWrapper=n.querySelector(".canvases"),this.progressWrapper=n.querySelector(".progress"),this.cursor=n.querySelector(".cursor"),e&&n.appendChild(e),this.initEvents()}parentFromOptionsContainer(t){let e;if(typeof t=="string"?e=document.querySelector(t):t instanceof HTMLElement&&(e=t),!e)throw new Error("Container not found");return e}initEvents(){const t=e=>{const i=this.wrapper.getBoundingClientRect(),s=e.clientX-i.left,n=e.clientY-i.top;return[s/i.width,n/i.height]};if(this.wrapper.addEventListener("click",e=>{const[i,s]=t(e);this.emit("click",i,s)}),this.wrapper.addEventListener("dblclick",e=>{const[i,s]=t(e);this.emit("dblclick",i,s)}),this.options.dragToSeek!==!0&&typeof this.options.dragToSeek!="object"||this.initDrag(),this.scrollContainer.addEventListener("scroll",()=>{const{scrollLeft:e,scrollWidth:i,clientWidth:s}=this.scrollContainer,n=e/i,r=(e+s)/i;this.emit("scroll",n,r,e,e+s)}),typeof ResizeObserver=="function"){const e=this.createDelay(100);this.resizeObserver=new ResizeObserver(()=>{e().then(()=>this.onContainerResize()).catch(()=>{})}),this.resizeObserver.observe(this.scrollContainer)}}onContainerResize(){const t=this.parent.clientWidth;t===this.lastContainerWidth&&this.options.height!=="auto"||(this.lastContainerWidth=t,this.reRender())}initDrag(){this.subscriptions.push(function(t,e,i,s,n=3,r=0,h=100){if(!t)return()=>{};const l=matchMedia("(pointer: coarse)").matches;let a=()=>{};const o=c=>{if(c.button!==r)return;c.preventDefault(),c.stopPropagation();let d=c.clientX,u=c.clientY,m=!1;const w=Date.now(),g=f=>{if(f.preventDefault(),f.stopPropagation(),l&&Date.now()-w<h)return;const S=f.clientX,P=f.clientY,M=S-d,k=P-u;if(m||Math.abs(M)>n||Math.abs(k)>n){const x=t.getBoundingClientRect(),{left:O,top:A}=x;m||(i?.(d-O,u-A),m=!0),e(M,k,S-O,P-A),d=S,u=P}},v=f=>{if(m){const S=f.clientX,P=f.clientY,M=t.getBoundingClientRect(),{left:k,top:x}=M;s?.(S-k,P-x)}a()},b=f=>{f.relatedTarget&&f.relatedTarget!==document.documentElement||v(f)},E=f=>{m&&(f.stopPropagation(),f.preventDefault())},C=f=>{m&&f.preventDefault()};document.addEventListener("pointermove",g),document.addEventListener("pointerup",v),document.addEventListener("pointerout",b),document.addEventListener("pointercancel",b),document.addEventListener("touchmove",C,{passive:!1}),document.addEventListener("click",E,{capture:!0}),a=()=>{document.removeEventListener("pointermove",g),document.removeEventListener("pointerup",v),document.removeEventListener("pointerout",b),document.removeEventListener("pointercancel",b),document.removeEventListener("touchmove",C),setTimeout(()=>{document.removeEventListener("click",E,{capture:!0})},10)}};return t.addEventListener("pointerdown",o),()=>{a(),t.removeEventListener("pointerdown",o)}}(this.wrapper,(t,e,i)=>{this.emit("drag",Math.max(0,Math.min(1,i/this.wrapper.getBoundingClientRect().width)))},t=>{this.isDragging=!0,this.emit("dragstart",Math.max(0,Math.min(1,t/this.wrapper.getBoundingClientRect().width)))},t=>{this.isDragging=!1,this.emit("dragend",Math.max(0,Math.min(1,t/this.wrapper.getBoundingClientRect().width)))}))}getHeight(t,e){var i;const s=((i=this.audioData)===null||i===void 0?void 0:i.numberOfChannels)||1;if(t==null)return 128;if(!isNaN(Number(t)))return Number(t);if(t==="auto"){const n=this.parent.clientHeight||128;return e?.every(r=>!r.overlay)?n/s:n}return 128}initHtml(){const t=document.createElement("div"),e=t.attachShadow({mode:"open"}),i=this.options.cspNonce&&typeof this.options.cspNonce=="string"?this.options.cspNonce.replace(/"/g,""):"";return e.innerHTML=`
2
+ <style${i?` nonce="${i}"`:""}>
3
+ :host {
4
+ user-select: none;
5
+ min-width: 1px;
6
+ }
7
+ :host audio {
8
+ display: block;
9
+ width: 100%;
10
+ }
11
+ :host .scroll {
12
+ overflow-x: auto;
13
+ overflow-y: hidden;
14
+ width: 100%;
15
+ position: relative;
16
+ }
17
+ :host .noScrollbar {
18
+ scrollbar-color: transparent;
19
+ scrollbar-width: none;
20
+ }
21
+ :host .noScrollbar::-webkit-scrollbar {
22
+ display: none;
23
+ -webkit-appearance: none;
24
+ }
25
+ :host .wrapper {
26
+ position: relative;
27
+ overflow: visible;
28
+ z-index: 2;
29
+ }
30
+ :host .canvases {
31
+ min-height: ${this.getHeight(this.options.height,this.options.splitChannels)}px;
32
+ }
33
+ :host .canvases > div {
34
+ position: relative;
35
+ }
36
+ :host canvas {
37
+ display: block;
38
+ position: absolute;
39
+ top: 0;
40
+ image-rendering: pixelated;
41
+ }
42
+ :host .progress {
43
+ pointer-events: none;
44
+ position: absolute;
45
+ z-index: 2;
46
+ top: 0;
47
+ left: 0;
48
+ width: 0;
49
+ height: 100%;
50
+ overflow: hidden;
51
+ }
52
+ :host .progress > div {
53
+ position: relative;
54
+ }
55
+ :host .cursor {
56
+ pointer-events: none;
57
+ position: absolute;
58
+ z-index: 5;
59
+ top: 0;
60
+ left: 0;
61
+ height: 100%;
62
+ border-radius: 2px;
63
+ }
64
+ </style>
65
+
66
+ <div class="scroll" part="scroll">
67
+ <div class="wrapper" part="wrapper">
68
+ <div class="canvases" part="canvases"></div>
69
+ <div class="progress" part="progress"></div>
70
+ <div class="cursor" part="cursor"></div>
71
+ </div>
72
+ </div>
73
+ `,[t,e]}setOptions(t){if(this.options.container!==t.container){const e=this.parentFromOptionsContainer(t.container);e.appendChild(this.container),this.parent=e}t.dragToSeek!==!0&&typeof this.options.dragToSeek!="object"||this.initDrag(),this.options=t,this.reRender()}getWrapper(){return this.wrapper}getWidth(){return this.scrollContainer.clientWidth}getScroll(){return this.scrollContainer.scrollLeft}setScroll(t){this.scrollContainer.scrollLeft=t}setScrollPercentage(t){const{scrollWidth:e}=this.scrollContainer,i=e*t;this.setScroll(i)}destroy(){var t,e;this.subscriptions.forEach(i=>i()),this.container.remove(),(t=this.resizeObserver)===null||t===void 0||t.disconnect(),(e=this.unsubscribeOnScroll)===null||e===void 0||e.forEach(i=>i()),this.unsubscribeOnScroll=[]}createDelay(t=10){let e,i;const s=()=>{e&&clearTimeout(e),i&&i()};return this.timeouts.push(s),()=>new Promise((n,r)=>{s(),i=r,e=setTimeout(()=>{e=void 0,i=void 0,n()},t)})}convertColorValues(t){if(!Array.isArray(t))return t||"";if(t.length<2)return t[0]||"";const e=document.createElement("canvas"),i=e.getContext("2d"),s=e.height*(window.devicePixelRatio||1),n=i.createLinearGradient(0,0,0,s),r=1/(t.length-1);return t.forEach((h,l)=>{const a=l*r;n.addColorStop(a,h)}),n}getPixelRatio(){return Math.max(1,window.devicePixelRatio||1)}renderBarWaveform(t,e,i,s){const n=t[0],r=t[1]||t[0],h=n.length,{width:l,height:a}=i.canvas,o=a/2,c=this.getPixelRatio(),d=e.barWidth?e.barWidth*c:1,u=e.barGap?e.barGap*c:e.barWidth?d/2:0,m=e.barRadius||0,w=l/(d+u)/h,g=m&&"roundRect"in i?"roundRect":"rect";i.beginPath();let v=0,b=0,E=0;for(let C=0;C<=h;C++){const f=Math.round(C*w);if(f>v){const M=Math.round(b*o*s),k=M+Math.round(E*o*s)||1;let x=o-M;e.barAlign==="top"?x=0:e.barAlign==="bottom"&&(x=a-k),i[g](v*(d+u),x,d,k,m),v=f,b=0,E=0}const S=Math.abs(n[C]||0),P=Math.abs(r[C]||0);S>b&&(b=S),P>E&&(E=P)}i.fill(),i.closePath()}renderLineWaveform(t,e,i,s){const n=r=>{const h=t[r]||t[0],l=h.length,{height:a}=i.canvas,o=a/2,c=i.canvas.width/l;i.moveTo(0,o);let d=0,u=0;for(let m=0;m<=l;m++){const w=Math.round(m*c);if(w>d){const v=o+(Math.round(u*o*s)||1)*(r===0?-1:1);i.lineTo(d,v),d=w,u=0}const g=Math.abs(h[m]||0);g>u&&(u=g)}i.lineTo(d,o)};i.beginPath(),n(0),n(1),i.fill(),i.closePath()}renderWaveform(t,e,i){if(i.fillStyle=this.convertColorValues(e.waveColor),e.renderFunction)return void e.renderFunction(t,i);let s=e.barHeight||1;if(e.normalize){const n=Array.from(t[0]).reduce((r,h)=>Math.max(r,Math.abs(h)),0);s=n?1/n:1}e.barWidth||e.barGap||e.barAlign?this.renderBarWaveform(t,e,i,s):this.renderLineWaveform(t,e,i,s)}renderSingleCanvas(t,e,i,s,n,r,h){const l=this.getPixelRatio(),a=document.createElement("canvas");a.width=Math.round(i*l),a.height=Math.round(s*l),a.style.width=`${i}px`,a.style.height=`${s}px`,a.style.left=`${Math.round(n)}px`,r.appendChild(a);const o=a.getContext("2d");if(this.renderWaveform(t,e,o),a.width>0&&a.height>0){const c=a.cloneNode(),d=c.getContext("2d");d.drawImage(a,0,0),d.globalCompositeOperation="source-in",d.fillStyle=this.convertColorValues(e.progressColor),d.fillRect(0,0,a.width,a.height),h.appendChild(c)}}renderMultiCanvas(t,e,i,s,n,r){const h=this.getPixelRatio(),{clientWidth:l}=this.scrollContainer,a=i/h;let o=Math.min(D.MAX_CANVAS_WIDTH,l,a),c={};if(e.barWidth||e.barGap){const g=e.barWidth||.5,v=g+(e.barGap||g/2);o%v!=0&&(o=Math.floor(o/v)*v)}if(o===0)return;const d=g=>{if(g<0||g>=u||c[g])return;c[g]=!0;const v=g*o;let b=Math.min(a-v,o);if(e.barWidth||e.barGap){const C=e.barWidth||.5,f=C+(e.barGap||C/2);b=Math.floor(b/f)*f}if(b<=0)return;const E=t.map(C=>{const f=Math.floor(v/a*C.length),S=Math.floor((v+b)/a*C.length);return C.slice(f,S)});this.renderSingleCanvas(E,e,b,s,v,n,r)},u=Math.ceil(a/o);if(!this.isScrollable){for(let g=0;g<u;g++)d(g);return}const m=this.scrollContainer.scrollLeft/a,w=Math.floor(m*u);if(d(w-1),d(w),d(w+1),u>1){const g=this.on("scroll",()=>{const{scrollLeft:v}=this.scrollContainer,b=Math.floor(v/a*u);Object.keys(c).length>D.MAX_NODES&&(n.innerHTML="",r.innerHTML="",c={}),d(b-1),d(b),d(b+1)});this.unsubscribeOnScroll.push(g)}}renderChannel(t,e,i,s){var{overlay:n}=e,r=function(o,c){var d={};for(var u in o)Object.prototype.hasOwnProperty.call(o,u)&&c.indexOf(u)<0&&(d[u]=o[u]);if(o!=null&&typeof Object.getOwnPropertySymbols=="function"){var m=0;for(u=Object.getOwnPropertySymbols(o);m<u.length;m++)c.indexOf(u[m])<0&&Object.prototype.propertyIsEnumerable.call(o,u[m])&&(d[u[m]]=o[u[m]])}return d}(e,["overlay"]);const h=document.createElement("div"),l=this.getHeight(r.height,r.splitChannels);h.style.height=`${l}px`,n&&s>0&&(h.style.marginTop=`-${l}px`),this.canvasWrapper.style.minHeight=`${l}px`,this.canvasWrapper.appendChild(h);const a=h.cloneNode();this.progressWrapper.appendChild(a),this.renderMultiCanvas(t,r,i,l,h,a)}render(t){return y(this,void 0,void 0,function*(){var e;this.timeouts.forEach(l=>l()),this.timeouts=[],this.canvasWrapper.innerHTML="",this.progressWrapper.innerHTML="",this.options.width!=null&&(this.scrollContainer.style.width=typeof this.options.width=="number"?`${this.options.width}px`:this.options.width);const i=this.getPixelRatio(),s=this.scrollContainer.clientWidth,n=Math.ceil(t.duration*(this.options.minPxPerSec||0));this.isScrollable=n>s;const r=this.options.fillParent&&!this.isScrollable,h=(r?s:n)*i;if(this.wrapper.style.width=r?"100%":`${n}px`,this.scrollContainer.style.overflowX=this.isScrollable?"auto":"hidden",this.scrollContainer.classList.toggle("noScrollbar",!!this.options.hideScrollbar),this.cursor.style.backgroundColor=`${this.options.cursorColor||this.options.progressColor}`,this.cursor.style.width=`${this.options.cursorWidth}px`,this.audioData=t,this.emit("render"),this.options.splitChannels)for(let l=0;l<t.numberOfChannels;l++){const a=Object.assign(Object.assign({},this.options),(e=this.options.splitChannels)===null||e===void 0?void 0:e[l]);this.renderChannel([t.getChannelData(l)],a,h,l)}else{const l=[t.getChannelData(0)];t.numberOfChannels>1&&l.push(t.getChannelData(1)),this.renderChannel(l,this.options,h,0)}Promise.resolve().then(()=>this.emit("rendered"))})}reRender(){if(this.unsubscribeOnScroll.forEach(i=>i()),this.unsubscribeOnScroll=[],!this.audioData)return;const{scrollWidth:t}=this.scrollContainer,{right:e}=this.progressWrapper.getBoundingClientRect();if(this.render(this.audioData),this.isScrollable&&t!==this.scrollContainer.scrollWidth){const{right:i}=this.progressWrapper.getBoundingClientRect();let s=i-e;s*=2,s=s<0?Math.floor(s):Math.ceil(s),s/=2,this.scrollContainer.scrollLeft+=s}}zoom(t){this.options.minPxPerSec=t,this.reRender()}scrollIntoView(t,e=!1){const{scrollLeft:i,scrollWidth:s,clientWidth:n}=this.scrollContainer,r=t*s,h=i,l=i+n,a=n/2;if(this.isDragging)r+30>l?this.scrollContainer.scrollLeft+=30:r-30<h&&(this.scrollContainer.scrollLeft-=30);else{(r<h||r>l)&&(this.scrollContainer.scrollLeft=r-(this.options.autoCenter?a:0));const o=r-i-a;e&&this.options.autoCenter&&o>0&&(this.scrollContainer.scrollLeft+=Math.min(o,10))}{const o=this.scrollContainer.scrollLeft,c=o/s,d=(o+n)/s;this.emit("scroll",c,d,o,o+n)}}renderProgress(t,e){if(isNaN(t))return;const i=100*t;this.canvasWrapper.style.clipPath=`polygon(${i}% 0%, 100% 0%, 100% 100%, ${i}% 100%)`,this.progressWrapper.style.width=`${i}%`,this.cursor.style.left=`${i}%`,this.cursor.style.transform=this.options.cursorWidth?`translateX(-${t*this.options.cursorWidth}px)`:"",this.isScrollable&&this.options.autoScroll&&this.scrollIntoView(t,e)}exportImage(t,e,i){return y(this,void 0,void 0,function*(){const s=this.canvasWrapper.querySelectorAll("canvas");if(!s.length)throw new Error("No waveform data");if(i==="dataURL"){const n=Array.from(s).map(r=>r.toDataURL(t,e));return Promise.resolve(n)}return Promise.all(Array.from(s).map(n=>new Promise((r,h)=>{n.toBlob(l=>{l?r(l):h(new Error("Could not export image"))},t,e)})))})}}D.MAX_CANVAS_WIDTH=8e3,D.MAX_NODES=10;class z extends T{constructor(){super(...arguments),this.unsubscribe=()=>{}}start(){this.unsubscribe=this.on("tick",()=>{requestAnimationFrame(()=>{this.emit("tick")})}),this.emit("tick")}stop(){this.unsubscribe()}destroy(){this.unsubscribe()}}class L extends T{constructor(t=new AudioContext){super(),this.bufferNode=null,this.playStartTime=0,this.playedDuration=0,this._muted=!1,this._playbackRate=1,this._duration=void 0,this.buffer=null,this.currentSrc="",this.paused=!0,this.crossOrigin=null,this.seeking=!1,this.autoplay=!1,this.addEventListener=this.on,this.removeEventListener=this.un,this.audioContext=t,this.gainNode=this.audioContext.createGain(),this.gainNode.connect(this.audioContext.destination)}load(){return y(this,void 0,void 0,function*(){})}get src(){return this.currentSrc}set src(t){if(this.currentSrc=t,this._duration=void 0,!t)return this.buffer=null,void this.emit("emptied");fetch(t).then(e=>{if(e.status>=400)throw new Error(`Failed to fetch ${t}: ${e.status} (${e.statusText})`);return e.arrayBuffer()}).then(e=>this.currentSrc!==t?null:this.audioContext.decodeAudioData(e)).then(e=>{this.currentSrc===t&&(this.buffer=e,this.emit("loadedmetadata"),this.emit("canplay"),this.autoplay&&this.play())})}_play(){var t;if(!this.paused)return;this.paused=!1,(t=this.bufferNode)===null||t===void 0||t.disconnect(),this.bufferNode=this.audioContext.createBufferSource(),this.buffer&&(this.bufferNode.buffer=this.buffer),this.bufferNode.playbackRate.value=this._playbackRate,this.bufferNode.connect(this.gainNode);let e=this.playedDuration*this._playbackRate;(e>=this.duration||e<0)&&(e=0,this.playedDuration=0),this.bufferNode.start(this.audioContext.currentTime,e),this.playStartTime=this.audioContext.currentTime,this.bufferNode.onended=()=>{this.currentTime>=this.duration&&(this.pause(),this.emit("ended"))}}_pause(){var t;this.paused=!0,(t=this.bufferNode)===null||t===void 0||t.stop(),this.playedDuration+=this.audioContext.currentTime-this.playStartTime}play(){return y(this,void 0,void 0,function*(){this.paused&&(this._play(),this.emit("play"))})}pause(){this.paused||(this._pause(),this.emit("pause"))}stopAt(t){const e=t-this.currentTime,i=this.bufferNode;i?.stop(this.audioContext.currentTime+e),i?.addEventListener("ended",()=>{i===this.bufferNode&&(this.bufferNode=null,this.pause())},{once:!0})}setSinkId(t){return y(this,void 0,void 0,function*(){return this.audioContext.setSinkId(t)})}get playbackRate(){return this._playbackRate}set playbackRate(t){this._playbackRate=t,this.bufferNode&&(this.bufferNode.playbackRate.value=t)}get currentTime(){return(this.paused?this.playedDuration:this.playedDuration+(this.audioContext.currentTime-this.playStartTime))*this._playbackRate}set currentTime(t){const e=!this.paused;e&&this._pause(),this.playedDuration=t/this._playbackRate,e&&this._play(),this.emit("seeking"),this.emit("timeupdate")}get duration(){var t,e;return(t=this._duration)!==null&&t!==void 0?t:((e=this.buffer)===null||e===void 0?void 0:e.duration)||0}set duration(t){this._duration=t}get volume(){return this.gainNode.gain.value}set volume(t){this.gainNode.gain.value=t,this.emit("volumechange")}get muted(){return this._muted}set muted(t){this._muted!==t&&(this._muted=t,this._muted?this.gainNode.disconnect():this.gainNode.connect(this.audioContext.destination))}canPlayType(t){return/^(audio|video)\//.test(t)}getGainNode(){return this.gainNode}getChannelData(){const t=[];if(!this.buffer)return t;const e=this.buffer.numberOfChannels;for(let i=0;i<e;i++)t.push(this.buffer.getChannelData(i));return t}removeAttribute(t){switch(t){case"src":this.src="";break;case"playbackRate":this.playbackRate=0;break;case"currentTime":this.currentTime=0;break;case"duration":this.duration=0;break;case"volume":this.volume=0;break;case"muted":this.muted=!1}}}const H={waveColor:"#999",progressColor:"#555",cursorWidth:1,minPxPerSec:0,fillParent:!0,interact:!0,dragToSeek:!1,autoScroll:!0,autoCenter:!0,sampleRate:8e3};class W extends j{static create(t){return new W(t)}constructor(t){const e=t.media||(t.backend==="WebAudio"?new L:void 0);super({media:e,mediaControls:t.mediaControls,autoplay:t.autoplay,playbackRate:t.audioRate}),this.plugins=[],this.decodedData=null,this.stopAtPosition=null,this.subscriptions=[],this.mediaSubscriptions=[],this.abortController=null,this.options=Object.assign({},H,t),this.timer=new z;const i=e?void 0:this.getMediaElement();this.renderer=new D(this.options,i),this.initPlayerEvents(),this.initRendererEvents(),this.initTimerEvents(),this.initPlugins();const s=this.options.url||this.getSrc()||"";Promise.resolve().then(()=>{this.emit("init");const{peaks:n,duration:r}=this.options;(s||n&&r)&&this.load(s,n,r).catch(()=>null)})}updateProgress(t=this.getCurrentTime()){return this.renderer.renderProgress(t/this.getDuration(),this.isPlaying()),t}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",()=>{if(!this.isSeeking()){const t=this.updateProgress();this.emit("timeupdate",t),this.emit("audioprocess",t),this.stopAtPosition!=null&&this.isPlaying()&&t>=this.stopAtPosition&&this.pause()}}))}initPlayerEvents(){this.isPlaying()&&(this.emit("play"),this.timer.start()),this.mediaSubscriptions.push(this.onMediaEvent("timeupdate",()=>{const t=this.updateProgress();this.emit("timeupdate",t)}),this.onMediaEvent("play",()=>{this.emit("play"),this.timer.start()}),this.onMediaEvent("pause",()=>{this.emit("pause"),this.timer.stop(),this.stopAtPosition=null}),this.onMediaEvent("emptied",()=>{this.timer.stop(),this.stopAtPosition=null}),this.onMediaEvent("ended",()=>{this.emit("timeupdate",this.getDuration()),this.emit("finish"),this.stopAtPosition=null}),this.onMediaEvent("seeking",()=>{this.emit("seeking",this.getCurrentTime())}),this.onMediaEvent("error",()=>{var t;this.emit("error",(t=this.getMediaElement().error)!==null&&t!==void 0?t:new Error("Media error")),this.stopAtPosition=null}))}initRendererEvents(){this.subscriptions.push(this.renderer.on("click",(t,e)=>{this.options.interact&&(this.seekTo(t),this.emit("interaction",t*this.getDuration()),this.emit("click",t,e))}),this.renderer.on("dblclick",(t,e)=>{this.emit("dblclick",t,e)}),this.renderer.on("scroll",(t,e,i,s)=>{const n=this.getDuration();this.emit("scroll",t*n,e*n,i,s)}),this.renderer.on("render",()=>{this.emit("redraw")}),this.renderer.on("rendered",()=>{this.emit("redrawcomplete")}),this.renderer.on("dragstart",t=>{this.emit("dragstart",t)}),this.renderer.on("dragend",t=>{this.emit("dragend",t)}));{let t;this.subscriptions.push(this.renderer.on("drag",e=>{if(!this.options.interact)return;let i;this.renderer.renderProgress(e),clearTimeout(t),this.isPlaying()?i=0:this.options.dragToSeek===!0?i=200:typeof this.options.dragToSeek=="object"&&this.options.dragToSeek!==void 0&&(i=this.options.dragToSeek.debounceTime),t=setTimeout(()=>{this.seekTo(e)},i),this.emit("interaction",e*this.getDuration()),this.emit("drag",e)}))}}initPlugins(){var t;!((t=this.options.plugins)===null||t===void 0)&&t.length&&this.options.plugins.forEach(e=>{this.registerPlugin(e)})}unsubscribePlayerEvents(){this.mediaSubscriptions.forEach(t=>t()),this.mediaSubscriptions=[]}setOptions(t){this.options=Object.assign({},this.options,t),t.duration&&!t.peaks&&(this.decodedData=R.createBuffer(this.exportPeaks(),t.duration)),t.peaks&&t.duration&&(this.decodedData=R.createBuffer(t.peaks,t.duration)),this.renderer.setOptions(this.options),t.audioRate&&this.setPlaybackRate(t.audioRate),t.mediaControls!=null&&(this.getMediaElement().controls=t.mediaControls)}registerPlugin(t){if(this.plugins.includes(t))return t;t._init(this),this.plugins.push(t);const e=t.once("destroy",()=>{this.plugins=this.plugins.filter(i=>i!==t),this.subscriptions=this.subscriptions.filter(i=>i!==e)});return this.subscriptions.push(e),t}unregisterPlugin(t){this.plugins=this.plugins.filter(e=>e!==t),t.destroy()}getWrapper(){return this.renderer.getWrapper()}getWidth(){return this.renderer.getWidth()}getScroll(){return this.renderer.getScroll()}setScroll(t){return this.renderer.setScroll(t)}setScrollTime(t){const e=t/this.getDuration();this.renderer.setScrollPercentage(e)}getActivePlugins(){return this.plugins}loadAudio(t,e,i,s){return y(this,void 0,void 0,function*(){var n;if(this.emit("load",t),!this.options.media&&this.isPlaying()&&this.pause(),this.decodedData=null,this.stopAtPosition=null,!e&&!i){const h=this.options.fetchParams||{};window.AbortController&&!h.signal&&(this.abortController=new AbortController,h.signal=(n=this.abortController)===null||n===void 0?void 0:n.signal);const l=o=>this.emit("loading",o);e=yield $.fetchBlob(t,l,h);const a=this.options.blobMimeType;a&&(e=new Blob([e],{type:a}))}this.setSrc(t,e);const r=yield new Promise(h=>{const l=s||this.getDuration();l?h(l):this.mediaSubscriptions.push(this.onMediaEvent("loadedmetadata",()=>h(this.getDuration()),{once:!0}))});if(!t&&!e){const h=this.getMediaElement();h instanceof L&&(h.duration=r)}if(i)this.decodedData=R.createBuffer(i,r||0);else if(e){const h=yield e.arrayBuffer();this.decodedData=yield R.decode(h,this.options.sampleRate)}this.decodedData&&(this.emit("decode",this.getDuration()),this.renderer.render(this.decodedData)),this.emit("ready",this.getDuration())})}load(t,e,i){return y(this,void 0,void 0,function*(){try{return yield this.loadAudio(t,void 0,e,i)}catch(s){throw this.emit("error",s),s}})}loadBlob(t,e,i){return y(this,void 0,void 0,function*(){try{return yield this.loadAudio("",t,e,i)}catch(s){throw this.emit("error",s),s}})}zoom(t){if(!this.decodedData)throw new Error("No audio loaded");this.renderer.zoom(t),this.emit("zoom",t)}getDecodedData(){return this.decodedData}exportPeaks({channels:t=2,maxLength:e=8e3,precision:i=1e4}={}){if(!this.decodedData)throw new Error("The audio has not been decoded yet");const s=Math.min(t,this.decodedData.numberOfChannels),n=[];for(let r=0;r<s;r++){const h=this.decodedData.getChannelData(r),l=[],a=h.length/e;for(let o=0;o<e;o++){const c=h.slice(Math.floor(o*a),Math.ceil((o+1)*a));let d=0;for(let u=0;u<c.length;u++){const m=c[u];Math.abs(m)>Math.abs(d)&&(d=m)}l.push(Math.round(d*i)/i)}n.push(l)}return n}getDuration(){let t=super.getDuration()||0;return t!==0&&t!==1/0||!this.decodedData||(t=this.decodedData.duration),t}toggleInteraction(t){this.options.interact=t}setTime(t){this.stopAtPosition=null,super.setTime(t),this.updateProgress(t),this.emit("timeupdate",t)}seekTo(t){const e=this.getDuration()*t;this.setTime(e)}play(t,e){const i=Object.create(null,{play:{get:()=>super.play}});return y(this,void 0,void 0,function*(){t!=null&&this.setTime(t);const s=yield i.play.call(this);return e!=null&&(this.media instanceof L?this.media.stopAt(e):this.stopAtPosition=e),s})}playPause(){return y(this,void 0,void 0,function*(){return this.isPlaying()?this.pause():this.play()})}stop(){this.pause(),this.setTime(0)}skip(t){this.setTime(this.getCurrentTime()+t)}empty(){this.load("",[[0]],.001)}setMediaElement(t){this.unsubscribePlayerEvents(),super.setMediaElement(t),this.initPlayerEvents()}exportImage(){return y(this,arguments,void 0,function*(t="image/png",e=1,i="dataURL"){return this.renderer.exportImage(t,e,i)})}destroy(){var t;this.emit("destroy"),(t=this.abortController)===null||t===void 0||t.abort(),this.plugins.forEach(e=>e.destroy()),this.subscriptions.forEach(e=>e()),this.unsubscribePlayerEvents(),this.timer.destroy(),this.renderer.destroy(),super.destroy()}}W.BasePlugin=class extends T{constructor(p){super(),this.subscriptions=[],this.isDestroyed=!1,this.options=p}onInit(){}_init(p){this.isDestroyed&&(this.subscriptions=[],this.isDestroyed=!1),this.wavesurfer=p,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach(p=>p()),this.subscriptions=[],this.isDestroyed=!0,this.wavesurfer=void 0}},W.dom=B;export{W as default};
@@ -1 +1 @@
1
- import{r as n,v as f,L as p,aq as h,u as x,a4 as y,j as i,ar as g}from"./index.6xX1278W.js";const m=n.createContext(null);m.displayName="ElementFullscreenContext";const C=f("div",{target:"e13s7uld0"})(({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"}:{}})),w=()=>{const{setFullScreen:e}=n.useContext(p),[t,s]=n.useState(!1),{fullHeight:a,fullWidth:u}=h(),l=n.useCallback(r=>{s(r),e(r)},[e]),c=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:c,zoomOut:o,fullHeight:a,fullWidth:u}),[t,c,o,a,u])},F=({children:e})=>{const t=x(),{expanded:s,fullHeight:a,fullWidth:u,zoomIn:l,zoomOut:c}=w(),{width:o,elementRef:d}=y(),r=n.useMemo(()=>({width:s?u:o,height:s?a:void 0,expanded:s,expand:l,collapse:c}),[s,a,u,o,l,c]);return i(m.Provider,{value:r,children:i(C,{ref:d,isExpanded:s,"data-testid":"stFullScreenFrame",theme:t,children:e})})};function E(e){const t=s=>i(F,{children:i(e,{...s})});return t.displayName=`withFullScreenWrapper(${e.displayName||e.name})`,g(t,e)}export{m as E,E as w};
1
+ import{r as n,s as f,L as p,ap as h,u as x,a3 as y,j as i,aq as g}from"./index.CAj-7vWz.js";const m=n.createContext(null);m.displayName="ElementFullscreenContext";const C=f("div",{target:"e13s7uld0"})(({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"}:{}})),w=()=>{const{setFullScreen:e}=n.useContext(p),[t,s]=n.useState(!1),{fullHeight:r,fullWidth:u}=h(),l=n.useCallback(a=>{s(a),e(a)},[e]),c=n.useCallback(()=>{document.body.style.overflow="hidden",l(!0)},[l]),o=n.useCallback(()=>{document.body.style.overflow="unset",l(!1)},[l]),d=n.useCallback(a=>{a.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:c,zoomOut:o,fullHeight:r,fullWidth:u}),[t,c,o,r,u])},F=({children:e})=>{const t=x(),{expanded:s,fullHeight:r,fullWidth:u,zoomIn:l,zoomOut:c}=w(),{width:o,elementRef:d}=y(),a=n.useMemo(()=>({width:s?u:o,height:s?r:void 0,expanded:s,expand:l,collapse:c}),[s,r,u,o,l,c]);return i(m.Provider,{value:a,children:i(C,{ref:d,isExpanded:s,"data-testid":"stFullScreenFrame",theme:t,children:e})})};function S(e){const t=s=>i(F,{children:i(e,{...s})});return t.displayName=`withFullScreenWrapper(${e.displayName||e.name})`,g(t,e)}export{m as E,S as w};
streamlit/string_util.py CHANGED
@@ -19,9 +19,7 @@ import fractions
19
19
  import numbers
20
20
  import re
21
21
  import textwrap
22
- from typing import TYPE_CHECKING, Any, Final, Union
23
-
24
- from typing_extensions import TypeAlias
22
+ from typing import TYPE_CHECKING, Any, Final, TypeAlias, Union
25
23
 
26
24
  from streamlit.errors import StreamlitAPIException
27
25
 
@@ -18,7 +18,7 @@ import tempfile
18
18
  import textwrap
19
19
  import traceback
20
20
  from pathlib import Path
21
- from typing import TYPE_CHECKING, Any, Callable
21
+ from typing import TYPE_CHECKING, Any
22
22
  from unittest.mock import MagicMock
23
23
  from urllib import parse
24
24
 
@@ -88,7 +88,7 @@ from streamlit.testing.v1.util import patch_config_options
88
88
  from streamlit.util import calc_md5
89
89
 
90
90
  if TYPE_CHECKING:
91
- from collections.abc import Iterator, Sequence
91
+ from collections.abc import Callable, Iterator, Sequence
92
92
 
93
93
  from streamlit.proto.WidgetStates_pb2 import WidgetStates
94
94
 
@@ -19,21 +19,20 @@ from __future__ import annotations
19
19
 
20
20
  import textwrap
21
21
  from abc import ABC, abstractmethod
22
- from collections.abc import Iterator, Sequence
22
+ from collections.abc import Callable, Iterator, Sequence
23
23
  from dataclasses import dataclass, field, fields, is_dataclass
24
24
  from datetime import date, datetime, time, timedelta
25
25
  from typing import (
26
26
  TYPE_CHECKING,
27
27
  Any,
28
- Callable,
29
28
  Generic,
29
+ TypeAlias,
30
30
  TypeVar,
31
- Union,
32
31
  cast,
33
32
  overload,
34
33
  )
35
34
 
36
- from typing_extensions import Self, TypeAlias
35
+ from typing_extensions import Self
37
36
 
38
37
  from streamlit import dataframe_util, util
39
38
  from streamlit.elements.heading import HeadingProtoTag
@@ -73,6 +72,7 @@ if TYPE_CHECKING:
73
72
  from streamlit.proto.NumberInput_pb2 import NumberInput as NumberInputProto
74
73
  from streamlit.proto.Radio_pb2 import Radio as RadioProto
75
74
  from streamlit.proto.Selectbox_pb2 import Selectbox as SelectboxProto
75
+ from streamlit.proto.Space_pb2 import Space as SpaceProto
76
76
  from streamlit.proto.Text_pb2 import Text as TextProto
77
77
  from streamlit.proto.TextArea_pb2 import TextArea as TextAreaProto
78
78
  from streamlit.proto.TextInput_pb2 import TextInput as TextInputProto
@@ -505,8 +505,8 @@ class Dataframe(Element):
505
505
  return dataframe_util.convert_arrow_bytes_to_pandas_df(self.proto.data)
506
506
 
507
507
 
508
- SingleDateValue: TypeAlias = Union[date, datetime]
509
- DateValue: TypeAlias = Union[SingleDateValue, Sequence[SingleDateValue], None]
508
+ SingleDateValue: TypeAlias = date | datetime
509
+ DateValue: TypeAlias = SingleDateValue | Sequence[SingleDateValue] | None
510
510
 
511
511
 
512
512
  @dataclass(repr=False)
@@ -670,6 +670,20 @@ class Latex(Markdown):
670
670
  self.type = "latex"
671
671
 
672
672
 
673
+ @dataclass(repr=False)
674
+ class Space(Element):
675
+ """A representation of st.space for testing."""
676
+
677
+ proto: SpaceProto = field(repr=False)
678
+
679
+ key: None = None
680
+
681
+ def __init__(self, proto: SpaceProto, root: ElementTree) -> None:
682
+ self.proto = proto
683
+ self.root = root
684
+ self.type = "space"
685
+
686
+
673
687
  @dataclass(repr=False)
674
688
  class Metric(Element):
675
689
  proto: MetricProto
@@ -861,7 +875,7 @@ class Multiselect(Widget, Generic[T]):
861
875
  return self
862
876
 
863
877
 
864
- Number = Union[int, float]
878
+ Number: TypeAlias = int | float
865
879
 
866
880
 
867
881
  @dataclass(repr=False)
@@ -1308,7 +1322,7 @@ class TextInput(Widget):
1308
1322
  return self.set_value(v)
1309
1323
 
1310
1324
 
1311
- TimeValue: TypeAlias = Union[time, datetime]
1325
+ TimeValue: TypeAlias = time | datetime
1312
1326
 
1313
1327
 
1314
1328
  @dataclass(repr=False)
@@ -1828,7 +1842,7 @@ class Tab(Block):
1828
1842
  self.label = proto.label
1829
1843
 
1830
1844
 
1831
- Node: TypeAlias = Union[Element, Block]
1845
+ Node: TypeAlias = Element | Block
1832
1846
 
1833
1847
 
1834
1848
  def get_widget_state(node: Node) -> WidgetState | None:
@@ -15,12 +15,12 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  from contextlib import contextmanager
18
- from typing import TYPE_CHECKING, Any, Callable
18
+ from typing import TYPE_CHECKING, Any
19
19
 
20
20
  from streamlit import config
21
21
 
22
22
  if TYPE_CHECKING:
23
- from collections.abc import Generator
23
+ from collections.abc import Callable, Generator
24
24
 
25
25
 
26
26
  @contextmanager
streamlit/type_util.py CHANGED
@@ -38,12 +38,11 @@ from typing import (
38
38
  Literal,
39
39
  NamedTuple,
40
40
  Protocol,
41
- Union,
41
+ TypeAlias,
42
+ TypeGuard,
42
43
  overload,
43
44
  )
44
45
 
45
- from typing_extensions import TypeAlias, TypeGuard
46
-
47
46
  from streamlit.errors import StreamlitAPIException
48
47
 
49
48
  if TYPE_CHECKING:
@@ -149,7 +148,7 @@ _BYTES_LIKE_TYPES: Final[tuple[type, ...]] = (
149
148
  bytearray,
150
149
  )
151
150
 
152
- BytesLike: TypeAlias = Union[bytes, bytearray]
151
+ BytesLike: TypeAlias = bytes | bytearray
153
152
 
154
153
 
155
154
  def is_bytes_like(obj: object) -> TypeGuard[BytesLike]:
streamlit/url_util.py CHANGED
@@ -15,11 +15,9 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import re
18
- from typing import Final, Literal
18
+ from typing import Final, Literal, TypeAlias
19
19
  from urllib.parse import urlparse
20
20
 
21
- from typing_extensions import TypeAlias
22
-
23
21
  UrlSchema: TypeAlias = Literal["http", "https", "mailto", "data"]
24
22
 
25
23
 
streamlit/user_info.py CHANGED
@@ -20,7 +20,6 @@ from typing import (
20
20
  Any,
21
21
  Final,
22
22
  NoReturn,
23
- Union,
24
23
  )
25
24
 
26
25
  from streamlit import config, logger, runtime
@@ -379,7 +378,7 @@ def _get_user_info() -> UserInfo:
379
378
  return context_user_info
380
379
 
381
380
 
382
- class UserInfoProxy(Mapping[str, Union[str, bool, None]]):
381
+ class UserInfoProxy(Mapping[str, str | bool | None]):
383
382
  """
384
383
  A read-only, dict-like object for accessing information about the current\
385
384
  user.
streamlit/util.py CHANGED
@@ -19,11 +19,13 @@ from __future__ import annotations
19
19
  import dataclasses
20
20
  import functools
21
21
  import hashlib
22
- from typing import TYPE_CHECKING, Any, Callable
22
+ from typing import TYPE_CHECKING, Any
23
23
 
24
24
  from streamlit.proto.RootContainer_pb2 import RootContainer
25
25
 
26
26
  if TYPE_CHECKING:
27
+ from collections.abc import Callable
28
+
27
29
  from streamlit.delta_generator import DeltaGenerator
28
30
 
29
31
 
@@ -39,7 +39,7 @@ from __future__ import annotations
39
39
 
40
40
  import os
41
41
  import threading
42
- from typing import TYPE_CHECKING, Callable, Final, cast
42
+ from typing import TYPE_CHECKING, Final, cast
43
43
 
44
44
  from blinker import ANY, Signal
45
45
  from typing_extensions import Self
@@ -52,6 +52,8 @@ from streamlit.util import repr_
52
52
  from streamlit.watcher import util
53
53
 
54
54
  if TYPE_CHECKING:
55
+ from collections.abc import Callable
56
+
55
57
  from watchdog.observers.api import ObservedWatch
56
58
 
57
59
  _LOGGER: Final = get_logger(__name__)
@@ -372,11 +374,9 @@ class _FolderEventHandler(events.FileSystemEventHandler):
372
374
  _LOGGER.debug("Don't care about event type %s", event.event_type)
373
375
  return
374
376
 
375
- # Watchdog 5.X is supported Python >=3.9, so watchdog 4.X is used for Python 3.8.
376
- # In Watchdog 5.X, the path can be bytes or str, but in Watchdog 4.X, the path is always str,
377
- # that's why we convert the path to str, but we need to ignore the unreachable code warning for Python 3.8.
378
- if isinstance(changed_path, bytes): # type: ignore[unreachable, unused-ignore]
379
- changed_path = changed_path.decode("utf-8") # type: ignore[unreachable, unused-ignore]
377
+ # Watchdog 5.X emits bytes paths on some platforms, so we normalize to str.
378
+ if isinstance(changed_path, bytes):
379
+ changed_path = changed_path.decode("utf-8")
380
380
 
381
381
  if changed_path.endswith("~"):
382
382
  # Files ending with ~ are typically backup files created by editors.
@@ -397,12 +397,23 @@ class _FolderEventHandler(events.FileSystemEventHandler):
397
397
  # directories themselves.
398
398
  if changed_path_info is None:
399
399
  for path, info in self._watched_paths.items():
400
- if (
401
- os.path.isdir(path)
402
- and os.path.commonpath([path, abs_changed_path]) == path
403
- ):
404
- changed_path_info = info
405
- break
400
+ if not os.path.isdir(path):
401
+ continue
402
+ try:
403
+ if os.path.commonpath([path, abs_changed_path]) == path:
404
+ changed_path_info = info
405
+ break
406
+ except ValueError as ex:
407
+ # On Windows, os.path.commonpath raises ValueError when paths
408
+ # are on different drives. In that case, the changed path
409
+ # cannot be inside the watched directory.
410
+ _LOGGER.debug(
411
+ "Ignoring changed path %s.\nWatched_paths: %s",
412
+ abs_changed_path,
413
+ self._watched_paths,
414
+ exc_info=ex,
415
+ )
416
+ continue
406
417
 
407
418
  # If we still haven't found a matching path, ignore this event
408
419
  if changed_path_info is None:
@@ -16,7 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  import os
18
18
  import sys
19
- from typing import TYPE_CHECKING, Any, Callable, Final, NamedTuple
19
+ from typing import TYPE_CHECKING, Any, Final, NamedTuple
20
20
 
21
21
  from streamlit import config, file_util
22
22
  from streamlit.logger import get_logger
@@ -28,6 +28,7 @@ from streamlit.watcher.path_watcher import (
28
28
  )
29
29
 
30
30
  if TYPE_CHECKING:
31
+ from collections.abc import Callable
31
32
  from types import ModuleType
32
33
 
33
34
  from streamlit.runtime.pages_manager import PagesManager
@@ -46,6 +47,15 @@ PathWatcher: PathWatcherType | None = None
46
47
 
47
48
 
48
49
  class LocalSourcesWatcher:
50
+ """Watch local Python sources and pages to trigger app reruns.
51
+
52
+ Purpose
53
+ -------
54
+ This watcher powers Streamlit's core developer workflow: save a Python file
55
+ and the app reruns. It tracks Python modules, the main script directory, and
56
+ configured watch folders to notify the runtime when a relevant file changes.
57
+ """
58
+
49
59
  def __init__(self, pages_manager: PagesManager) -> None:
50
60
  self._pages_manager = pages_manager
51
61
  self._main_script_path = os.path.realpath(self._pages_manager.main_script_path)
@@ -15,12 +15,15 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import os
18
- from typing import Callable, Union
18
+ from typing import TYPE_CHECKING, TypeAlias
19
19
 
20
20
  import streamlit.watcher
21
21
  from streamlit import cli_util, config, env_util
22
22
  from streamlit.watcher.polling_path_watcher import PollingPathWatcher
23
23
 
24
+ if TYPE_CHECKING:
25
+ from collections.abc import Callable
26
+
24
27
 
25
28
  # local_sources_watcher.py caches the return value of
26
29
  # get_default_path_watcher_class(), so it needs to differentiate between the
@@ -45,11 +48,11 @@ class NoOpPathWatcher:
45
48
  # EventBasedPathWatcher will be a stub and have no functional
46
49
  # implementation if its import failed (due to missing watchdog module),
47
50
  # so we can't reference it directly in this type.
48
- PathWatcherType = Union[
49
- type["streamlit.watcher.event_based_path_watcher.EventBasedPathWatcher"],
50
- type[PollingPathWatcher],
51
- type[NoOpPathWatcher],
52
- ]
51
+ PathWatcherType: TypeAlias = (
52
+ type["streamlit.watcher.event_based_path_watcher.EventBasedPathWatcher"]
53
+ | type[PollingPathWatcher]
54
+ | type[NoOpPathWatcher]
55
+ )
53
56
 
54
57
 
55
58
  def _is_watchdog_available() -> bool:
@@ -19,13 +19,16 @@ from __future__ import annotations
19
19
  import time
20
20
  from concurrent.futures import ThreadPoolExecutor
21
21
  from pathlib import Path
22
- from typing import Callable, Final
22
+ from typing import TYPE_CHECKING, Final
23
23
 
24
24
  from streamlit.errors import StreamlitMaxRetriesError
25
25
  from streamlit.logger import get_logger
26
26
  from streamlit.util import repr_
27
27
  from streamlit.watcher import util
28
28
 
29
+ if TYPE_CHECKING:
30
+ from collections.abc import Callable
31
+
29
32
  _LOGGER: Final = get_logger(__name__)
30
33
 
31
34
  _MAX_WORKERS: Final = 4
streamlit/watcher/util.py CHANGED
@@ -23,13 +23,13 @@ from __future__ import annotations
23
23
  import os
24
24
  import time
25
25
  from pathlib import Path
26
- from typing import TYPE_CHECKING, Callable, TypeVar
26
+ from typing import TYPE_CHECKING, TypeVar
27
27
 
28
28
  from streamlit.errors import StreamlitMaxRetriesError
29
29
  from streamlit.util import calc_md5
30
30
 
31
31
  if TYPE_CHECKING:
32
- from collections.abc import Generator
32
+ from collections.abc import Callable, Generator
33
33
 
34
34
  # How many times to try to grab the MD5 hash.
35
35
  _MAX_RETRIES = 5
streamlit/web/cli.py CHANGED
@@ -18,7 +18,9 @@ from __future__ import annotations
18
18
 
19
19
  import os
20
20
  import sys
21
- from typing import TYPE_CHECKING, Any, Callable, Final, TypeVar
21
+ from collections.abc import Callable
22
+ from pathlib import Path
23
+ from typing import TYPE_CHECKING, Any, Final, TypeVar
22
24
 
23
25
  # We cannot lazy-load click here because its used via decorators.
24
26
  import click
@@ -195,46 +197,73 @@ def main_hello(**kwargs: Any) -> None:
195
197
 
196
198
  @main.command("run")
197
199
  @configurator_options
198
- @click.argument("target", required=True, envvar="STREAMLIT_RUN_TARGET")
200
+ @click.argument("target", default="streamlit_app.py", envvar="STREAMLIT_RUN_TARGET")
199
201
  @click.argument("args", nargs=-1)
200
202
  def main_run(target: str, args: list[str] | None = None, **kwargs: Any) -> None:
201
203
  """Run a Python script, piping stderr to Streamlit.
202
204
 
203
- The script can be local or it can be an url. In the latter case, Streamlit
204
- will download the script to a temporary file and runs this file.
205
+ If omitted, the target script will be assumed to be "streamlit_app.py".
205
206
 
207
+ Otherwise, the target script should be one of the following:
208
+ - The path to a local Python file.
209
+ - The path to a local folder where "streamlit_app.py" can be found.
210
+ - A URL pointing to a Python file. In this case Streamlit will download the
211
+ file to a temporary file and run it.
212
+
213
+ To pass command-line arguments to the script, add " -- " before them. For example:
214
+
215
+ $ streamlit run my_app.py -- --my_arg1=123 my_arg2
216
+
217
+ Your CLI args start after this.
206
218
  """
207
219
  from streamlit import url_util
208
220
 
209
- _, extension = os.path.splitext(target)
210
- if extension[1:] not in ACCEPTED_FILE_EXTENSIONS:
211
- if extension[1:] == "":
212
- raise click.BadArgumentUsage(
213
- "Streamlit requires raw Python (.py) files, but the provided file has no extension.\n"
214
- "For more information, please see https://docs.streamlit.io"
215
- )
216
- raise click.BadArgumentUsage(
217
- f"Streamlit requires raw Python (.py) files, not {extension}.\nFor more information, please see https://docs.streamlit.io"
218
- )
219
-
220
221
  if url_util.is_url(target):
221
222
  from streamlit.temporary_directory import TemporaryDirectory
222
223
 
223
224
  with TemporaryDirectory() as temp_dir:
224
225
  from urllib.parse import urlparse
225
226
 
226
- path = urlparse(target).path
227
+ url_subpath = urlparse(target).path
228
+
229
+ _check_extension_or_raise(url_subpath)
230
+
227
231
  main_script_path = os.path.join(
228
- temp_dir, path.strip("/").rsplit("/", 1)[-1]
232
+ temp_dir, url_subpath.strip("/").rsplit("/", 1)[-1]
229
233
  )
230
234
  # if this is a GitHub/Gist blob url, convert to a raw URL first.
231
- target = url_util.process_gitblob_url(target)
232
- _download_remote(main_script_path, target)
235
+ url = url_util.process_gitblob_url(target)
236
+ _download_remote(main_script_path, url)
233
237
  _main_run(main_script_path, args, flag_options=kwargs)
238
+
234
239
  else:
235
- if not os.path.exists(target):
236
- raise click.BadParameter(f"File does not exist: {target}")
237
- _main_run(target, args, flag_options=kwargs)
240
+ path = Path(target)
241
+
242
+ if path.is_dir():
243
+ path /= "streamlit_app.py"
244
+
245
+ path_str = str(path)
246
+ _check_extension_or_raise(path_str)
247
+
248
+ if not path.exists():
249
+ raise click.BadParameter(f"File does not exist: {path}")
250
+
251
+ _main_run(path_str, args, flag_options=kwargs)
252
+
253
+
254
+ def _check_extension_or_raise(path_str: str) -> None:
255
+ _, extension = os.path.splitext(path_str)
256
+
257
+ if extension[1:] not in ACCEPTED_FILE_EXTENSIONS:
258
+ if extension[1:] == "":
259
+ raise click.BadArgumentUsage(
260
+ "Streamlit requires raw Python (.py) files, but the provided file has no extension.\n"
261
+ "For more information, please see https://docs.streamlit.io"
262
+ )
263
+ raise click.BadArgumentUsage(
264
+ f"Streamlit requires raw Python (.py) files, not {extension}.\n"
265
+ "For more information, please see https://docs.streamlit.io"
266
+ )
238
267
 
239
268
 
240
269
  def _get_command_line_as_string() -> str | None: