├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── feature_request.yml └── pull_request_template.md ├── .gitignore ├── .husky └── pre-commit ├── .prettierrc ├── LICENSE ├── README.md ├── docs ├── assets │ ├── index-0cec1eac.js │ └── index-8d4966bc.css ├── audios │ ├── loop-1.mp3 │ ├── loop-2.mp3 │ ├── loop-3.mp3 │ ├── loop-4.mp3 │ ├── loop-5.mp3 │ ├── loop-6.mp3 │ ├── loop-7.mp3 │ ├── loop-8.mp3 │ └── loop-9.mp3 ├── cn-readme.md ├── favicon.svg └── index.html ├── example ├── README.md ├── index.html ├── package.json ├── pnpm-lock.yaml ├── postcss.config.cjs ├── public │ ├── audios │ │ ├── loop-1.mp3 │ │ ├── loop-2.mp3 │ │ ├── loop-3.mp3 │ │ ├── loop-4.mp3 │ │ ├── loop-5.mp3 │ │ ├── loop-6.mp3 │ │ ├── loop-7.mp3 │ │ ├── loop-8.mp3 │ │ └── loop-9.mp3 │ └── favicon.svg ├── src │ ├── App.vue │ ├── components │ │ ├── Demo.vue │ │ └── icons │ │ │ ├── Moon.vue │ │ │ ├── Pause.vue │ │ │ ├── Play.vue │ │ │ ├── Replay.vue │ │ │ └── Sun.vue │ ├── env.d.ts │ ├── main.ts │ └── style.css ├── tailwind.config.cjs ├── tsconfig.config.json ├── tsconfig.json └── vite.config.ts ├── lib ├── 1llest-waveform-vue.mjs ├── 1llest-waveform-vue.umd.js ├── style.css └── types │ ├── components │ └── IllestWaveform.vue.d.ts │ ├── index.d.ts │ ├── modules │ ├── Audio.d.ts │ ├── AudioController.d.ts │ ├── Wave.d.ts │ └── index.d.ts │ ├── types │ └── waveform.d.ts │ └── utils │ ├── format-time.d.ts │ ├── lazy-load.d.ts │ └── time-counter.d.ts ├── package.json ├── pnpm-lock.yaml ├── src ├── components │ └── IllestWaveform.vue ├── index.ts ├── modules │ ├── Audio.ts │ ├── AudioController.ts │ ├── Wave.ts │ └── index.ts ├── types │ └── waveform.ts └── utils │ ├── format-time.ts │ ├── lazy-load.ts │ └── time-counter.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line= lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | insert_final_newline = false 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib/* 3 | docs/* 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | }, 6 | extends: [ 7 | 'plugin:vue/vue3-recommended', 8 | '@vue/standard', 9 | '@vue/typescript/recommended', 10 | 'eslint-config-prettier', 11 | ], 12 | parser: 'vue-eslint-parser', 13 | parserOptions: { 14 | parser: '@typescript-eslint/parser', 15 | }, 16 | rules: { 17 | 'space-before-function-paren': 'off', 18 | '@typescript-eslint/no-explicit-any': 'off', 19 | '@typescript-eslint/no-non-null-assertion': 'off', 20 | 'vue/no-setup-props-destructure': 'off', 21 | 'vue/multi-word-component-names': 'off', 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 🐛Bug Report 2 | description: File a bug report here 3 | title: "[BUG]: " 4 | labels: ["bug"] 5 | assignees: "codeacme17" 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Thanks for taking the time to fill out this bug report 🤗 11 | Make sure there aren't any open/closed issues for this topic 😃 12 | 13 | - type: textarea 14 | id: bug-description 15 | attributes: 16 | label: Description of the bug 17 | description: Give us a brief description of what happened and what should have happened 18 | validations: 19 | required: true 20 | 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: ✨Feature Request 2 | description: Request a new feature or enhancement 3 | labels: ["enhancement"] 4 | assignees: "codeacme17" 5 | title: "[FEAT]: " 6 | body: 7 | - type: markdown 8 | attributes: 9 | value: | 10 | Please make sure this feature request hasn't been already submitted by someone by looking through other open/closed issues 😃 11 | 12 | - type: textarea 13 | id: description 14 | attributes: 15 | label: Description 16 | description: Give us a brief description of the feature or enhancement you would like 17 | validations: 18 | required: true 19 | 20 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Thanks for creating this pull request 🤗 2 | 3 | Please make sure that the pull request is limited to one type (docs, feature, etc.) and keep it as small as possible. You can open multiple prs instead of opening a huge one. 4 | 5 | 6 | ## 📑 Description 7 | 8 | 9 | > You can also choose to add a list of changes and if they have been completed or not by using the markdown to-do list syntax 10 | - [ ] Not Completed 11 | - [x] Completed 12 | 13 | 14 | ## ✅ Checks 15 | > Make sure your pr passes the CI checks and do check the following fields as needed 16 | - [ ] My pull request adheres to the code style of this project 17 | - [ ] My code requires changes to the documentation 18 | - [ ] I have updated the documentation as required 19 | - [ ] All the tests have passed 20 | 21 | ## ℹ Additional Information 22 | > Any additional information like breaking changes, dependencies added, screenshots, comparisons between new and old behavior, etc. 23 | 24 | ## 🔔 The commit standard 25 | #### TEMPLATE: 26 | 27 | ```bash 28 | type(scope): subject 29 | 30 | body 31 | 32 | footer 33 | ``` 34 | 35 | #### WHERE: 36 | `type` Indicates the type of change being made. Possible values include: 37 | 38 | - feat: A new feature. 39 | - fix: A bug fix. 40 | - docs: Documentation changes. 41 | - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc). 42 | - refactor: A code change that neither fixes a bug nor adds a feature. 43 | - perf: A code change that improves performance. 44 | - test: Adding missing tests or correcting existing tests. 45 | - chore: Changes to the build process or auxiliary tools and libraries such as documentation generation. 46 | 47 | `scope` Indicates the scope of the change. This can be anything describing the area of the code that was affected. 48 | 49 | `subject` A brief summary of the change 50 | 51 | `body` A more detailed description of the change, including any additional context or reasoning. 52 | 53 | `footer` Any relevant metadata related to the change, such as references to related issues or pull requests. 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npm run lint 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "tabWidth": 2 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 leyoonafr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 6 | to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 12 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 13 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | logo 4 |

5 | 6 |

7 | 8 | 1llest-waveform-vue 9 | 10 |

11 | 12 |

13 | 14 | A lightweight and controllable audio visualization vue3 plugin 15 | 16 |

17 |
18 | 19 | ## Description 20 |

21 | 22 | English | [简写中文](docs/cn-readme.md) 23 | 24 |

25 | 26 | This component is written using the native [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API), and does not use any dependencies other than vue3 in the production environment. Of course, this means: if your target browser does not support the features of the web audio api, then my Plugins will also not apply. You can go to [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API#audiocontext_2) to see the `AudioContext` line to check whether it is compatible with the target browser 27 | 28 | **Example** - [Live Demo](https://codeacme17.github.io/1llest-waveform-vue/) 29 | 30 | 31 | ## Start 32 | ### Install 33 | ```bash 34 | npm install 1llest-waveform-vue 35 | ``` 36 | 37 | ### Usage 38 | Global component 39 | ```javascript 40 | // main.ts 41 | import { createApp } from "vue" 42 | import App from "./App.vue" 43 | 44 | import IllestWaveform from "1llest-waveform-vue" 45 | import "1llest-waveform-vue/lib/style.css" 46 | 47 | const app = createApp(App) 48 | 49 | app.use(IllestWaveform) 50 | app.mount("#app") 51 | ``` 52 | Local component 53 | ```js 54 | // example.vue 55 | import { IllestWaveform } from "1llest-waveform-vue" 56 | import "1llest-waveform-vue/lib/style.css" 57 | ``` 58 | ### Component 59 | ```vue 60 | 74 | 75 | 145 | ``` 146 | 147 | 148 | ## Documentation 149 | ### Component Props 150 | 151 | | prop | description | type | default | 152 | |:---------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------|:----------| 153 | | url | the url of the audio file | `String` | - | 154 | | requestOptions | the object passed to the `fetch` request function | `RequestInit` | - | 155 | | lineWidth | the width of each vertical line that makes up the waveform | `Number` | `0.5` | 156 | | lineCap | the style at the end of each vertical line that makes up the waveform | `CanvasLineCap` | `round` | 157 | | lineColor | the color of each vertical line that makes up the waveform | `String` | `#5e5e5e` | 158 | | samplingRate | indicates your audio sampling rate. The larger the value, the more lines the waveform will present and the higher the accuracy. But this value is not recommended to be too large, because too large a value will slow down rendering efficiency, the recommended value is between ` 8000 - 44100 ` | `Number` | `22050` | 159 | | cursorWidth | indicates your cursor width | `Number` | `2` | 160 | | cursorColor | the color of your cursor | `String` | `#fff` | 161 | | maskColor | the color of the waveform mask layer | `String` | `#fff` | 162 | | lazy | whether to enable lazy loading mode, if you want to display multiple waveforms as a list, this property is very useful | `Boolean` | `true` | 163 | | skeleton | whether to enable the skeleton during waveform loading | `Boolean` | `true` | 164 | | skeletonColor | the color of the skeleton | `String` | `#232323` | 165 | | interact | indicates whether you want the user to interact with the waveform | `Boolean` | `true` | 166 | | fade | achieve fade-in and fade-out effects when playing and pausing audio, this can give the user a smoother listening experience | `Boolean` | `true` | 167 | 168 | ### Events 169 | 170 | > When using the following events, you need to add the `on-` prefix in front, such as `@on-init="initHandler"` 171 | 172 | | event | description | params | 173 | | :------ | :----------------------------------------------------------- | :----------------- | 174 | | init | the hook event before the waveform starts to initialize | `Boolean` | 175 | | fetched | the hook event after accepting the audio file | `Boolean` | 176 | | ready | the hook event triggered after the waveform completes all initialization and rendering to the page | `Boolean` | 177 | | play | event fired when playback starts | `Boolean` | 178 | | pause | event fired when playback is paused | `Boolean` | 179 | | finish | the event triggered when the playback is completed (the playback completion refers to the completion of the entire audio) | `Boolean` | 180 | | click | event triggered when waveform is clicked | `Ref` | 181 | 182 | ### Methods 183 | 184 | > You can call these methods directly on the waveform component instance, such like `waveform_ref.value.play()` 185 | 186 | | method | description | return | 187 | | :------------- | :----------------------------------------------------------- | -------- | 188 | | play | trigger the playback method of the waveform so that it starts playing the current audio | - | 189 | | pause | trigger the pause method of the waveform to make it pause playback | - | 190 | | replay | this method can restart playing the current audio again | - | 191 | | getCurrentTime | this method can get the current playing time. If you want to get the current playback time in real time, you can wrap it in the `watchEffect` hook | `string` | 192 | | getDuration | this method can get the duration of the current audio, but **this method must be placed after the `ready` hook event is triggered to get the correct duration** | `string` | 193 | 194 | 195 | 196 | ## Contributing 197 | 198 | Contributions to the project are welcome! If you find a bug or have an idea for a new feature, please submit an issue or pull request. 199 | 200 | 201 | 202 | ## License 203 | [MIT](https://github.com/codeacme17/1llg-terminal-GPT/blob/main/LICENSE) License © 2023-Present [leyoonafr](https://github.com/codeacme17) 204 | -------------------------------------------------------------------------------- /docs/assets/index-0cec1eac.js: -------------------------------------------------------------------------------- 1 | (function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const r of document.querySelectorAll('link[rel="modulepreload"]'))s(r);new MutationObserver(r=>{for(const i of r)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&s(o)}).observe(document,{childList:!0,subtree:!0});function n(r){const i={};return r.integrity&&(i.integrity=r.integrity),r.referrerPolicy&&(i.referrerPolicy=r.referrerPolicy),r.crossOrigin==="use-credentials"?i.credentials="include":r.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(r){if(r.ep)return;r.ep=!0;const i=n(r);fetch(r.href,i)}})();function Xn(e,t){const n=Object.create(null),s=e.split(",");for(let r=0;r!!n[r.toLowerCase()]:r=>!!n[r]}function ct(e){if(N(e)){const t={};for(let n=0;n{if(n){const s=n.split(Fi);s.length>1&&(t[s[0].trim()]=s[1].trim())}}),t}function Oe(e){let t="";if(oe(e))t=e;else if(N(e))for(let n=0;noe(e)?e:e==null?"":N(e)||G(e)&&(e.toString===Or||!L(e.toString))?JSON.stringify(e,wr,2):String(e),wr=(e,t)=>t&&t.__v_isRef?wr(e,t.value):_t(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((n,[s,r])=>(n[`${s} =>`]=r,n),{})}:xr(t)?{[`Set(${t.size})`]:[...t.values()]}:G(t)&&!N(t)&&!Er(t)?String(t):t,Z={},gt=[],Ae=()=>{},Ri=()=>!1,ki=/^on[^a-z]/,dn=e=>ki.test(e),Zn=e=>e.startsWith("onUpdate:"),ae=Object.assign,Gn=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},Bi=Object.prototype.hasOwnProperty,W=(e,t)=>Bi.call(e,t),N=Array.isArray,_t=e=>hn(e)==="[object Map]",xr=e=>hn(e)==="[object Set]",L=e=>typeof e=="function",oe=e=>typeof e=="string",es=e=>typeof e=="symbol",G=e=>e!==null&&typeof e=="object",Cr=e=>G(e)&&L(e.then)&&L(e.catch),Or=Object.prototype.toString,hn=e=>Or.call(e),ji=e=>hn(e).slice(8,-1),Er=e=>hn(e)==="[object Object]",ts=e=>oe(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,tn=Xn(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),pn=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},Hi=/-(\w)/g,bt=pn(e=>e.replace(Hi,(t,n)=>n?n.toUpperCase():"")),Wi=/\B([A-Z])/g,Ot=pn(e=>e.replace(Wi,"-$1").toLowerCase()),Ar=pn(e=>e.charAt(0).toUpperCase()+e.slice(1)),An=pn(e=>e?`on${Ar(e)}`:""),Rt=(e,t)=>!Object.is(e,t),Tn=(e,t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:n})},Ui=e=>{const t=parseFloat(e);return isNaN(t)?e:t},zi=e=>{const t=oe(e)?Number(e):NaN;return isNaN(t)?e:t};let As;const Ki=()=>As||(As=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});let me;class Vi{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=me,!t&&me&&(this.index=(me.scopes||(me.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const n=me;try{return me=this,t()}finally{me=n}}}on(){me=this}off(){me=this.parent}stop(t){if(this._active){let n,s;for(n=0,s=this.effects.length;n{const t=new Set(e);return t.w=0,t.n=0,t},Pr=e=>(e.w&Qe)>0,Ir=e=>(e.n&Qe)>0,Qi=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let n=0;for(let s=0;s{(d==="length"||d>=a)&&l.push(f)})}else switch(n!==void 0&&l.push(o.get(n)),t){case"add":N(e)?ts(n)&&l.push(o.get("length")):(l.push(o.get(ut)),_t(e)&&l.push(o.get(Ln)));break;case"delete":N(e)||(l.push(o.get(ut)),_t(e)&&l.push(o.get(Ln)));break;case"set":_t(e)&&l.push(o.get(ut));break}if(l.length===1)l[0]&&Rn(l[0]);else{const a=[];for(const f of l)f&&a.push(...f);Rn(ns(a))}}function Rn(e,t){const n=N(e)?e:[...e];for(const s of n)s.computed&&Ps(s);for(const s of n)s.computed||Ps(s)}function Ps(e,t){(e!==Ce||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}const Xi=Xn("__proto__,__v_isRef,__isVue"),Fr=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(es)),Zi=rs(),Gi=rs(!1,!0),eo=rs(!0),Is=to();function to(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...n){const s=U(this);for(let i=0,o=this.length;i{e[t]=function(...n){Et();const s=U(this)[t].apply(this,n);return At(),s}}),e}function no(e){const t=U(this);return pe(t,"has",e),t.hasOwnProperty(e)}function rs(e=!1,t=!1){return function(s,r,i){if(r==="__v_isReactive")return!e;if(r==="__v_isReadonly")return e;if(r==="__v_isShallow")return t;if(r==="__v_raw"&&i===(e?t?yo:Rr:t?Lr:Dr).get(s))return s;const o=N(s);if(!e){if(o&&W(Is,r))return Reflect.get(Is,r,i);if(r==="hasOwnProperty")return no}const l=Reflect.get(s,r,i);return(es(r)?Fr.has(r):Xi(r))||(e||pe(s,"get",r),t)?l:ce(l)?o&&ts(r)?l:l.value:G(l)?e?ls(l):zt(l):l}}const so=Nr(),ro=Nr(!0);function Nr(e=!1){return function(n,s,r,i){let o=n[s];if(wt(o)&&ce(o)&&!ce(r))return!1;if(!e&&(!cn(r)&&!wt(r)&&(o=U(o),r=U(r)),!N(n)&&ce(o)&&!ce(r)))return o.value=r,!0;const l=N(n)&&ts(s)?Number(s)e,gn=e=>Reflect.getPrototypeOf(e);function Qt(e,t,n=!1,s=!1){e=e.__v_raw;const r=U(e),i=U(t);n||(t!==i&&pe(r,"get",t),pe(r,"get",i));const{has:o}=gn(r),l=s?is:n?as:kt;if(o.call(r,t))return l(e.get(t));if(o.call(r,i))return l(e.get(i));e!==r&&e.get(t)}function Yt(e,t=!1){const n=this.__v_raw,s=U(n),r=U(e);return t||(e!==r&&pe(s,"has",e),pe(s,"has",r)),e===r?n.has(e):n.has(e)||n.has(r)}function Xt(e,t=!1){return e=e.__v_raw,!t&&pe(U(e),"iterate",ut),Reflect.get(e,"size",e)}function $s(e){e=U(e);const t=U(this);return gn(t).has.call(t,e)||(t.add(e),ke(t,"add",e,e)),this}function Ss(e,t){t=U(t);const n=U(this),{has:s,get:r}=gn(n);let i=s.call(n,e);i||(e=U(e),i=s.call(n,e));const o=r.call(n,e);return n.set(e,t),i?Rt(t,o)&&ke(n,"set",e,t):ke(n,"add",e,t),this}function Fs(e){const t=U(this),{has:n,get:s}=gn(t);let r=n.call(t,e);r||(e=U(e),r=n.call(t,e)),s&&s.call(t,e);const i=t.delete(e);return r&&ke(t,"delete",e,void 0),i}function Ns(){const e=U(this),t=e.size!==0,n=e.clear();return t&&ke(e,"clear",void 0,void 0),n}function Zt(e,t){return function(s,r){const i=this,o=i.__v_raw,l=U(o),a=t?is:e?as:kt;return!e&&pe(l,"iterate",ut),o.forEach((f,d)=>s.call(r,a(f),a(d),i))}}function Gt(e,t,n){return function(...s){const r=this.__v_raw,i=U(r),o=_t(i),l=e==="entries"||e===Symbol.iterator&&o,a=e==="keys"&&o,f=r[e](...s),d=n?is:t?as:kt;return!t&&pe(i,"iterate",a?Ln:ut),{next(){const{value:p,done:m}=f.next();return m?{value:p,done:m}:{value:l?[d(p[0]),d(p[1])]:d(p),done:m}},[Symbol.iterator](){return this}}}}function He(e){return function(...t){return e==="delete"?!1:this}}function uo(){const e={get(i){return Qt(this,i)},get size(){return Xt(this)},has:Yt,add:$s,set:Ss,delete:Fs,clear:Ns,forEach:Zt(!1,!1)},t={get(i){return Qt(this,i,!1,!0)},get size(){return Xt(this)},has:Yt,add:$s,set:Ss,delete:Fs,clear:Ns,forEach:Zt(!1,!0)},n={get(i){return Qt(this,i,!0)},get size(){return Xt(this,!0)},has(i){return Yt.call(this,i,!0)},add:He("add"),set:He("set"),delete:He("delete"),clear:He("clear"),forEach:Zt(!0,!1)},s={get(i){return Qt(this,i,!0,!0)},get size(){return Xt(this,!0)},has(i){return Yt.call(this,i,!0)},add:He("add"),set:He("set"),delete:He("delete"),clear:He("clear"),forEach:Zt(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(i=>{e[i]=Gt(i,!1,!1),n[i]=Gt(i,!0,!1),t[i]=Gt(i,!1,!0),s[i]=Gt(i,!0,!0)}),[e,n,t,s]}const[fo,ho,po,go]=uo();function os(e,t){const n=t?e?go:po:e?ho:fo;return(s,r,i)=>r==="__v_isReactive"?!e:r==="__v_isReadonly"?e:r==="__v_raw"?s:Reflect.get(W(n,r)&&r in s?n:s,r,i)}const _o={get:os(!1,!1)},mo={get:os(!1,!0)},vo={get:os(!0,!1)},Dr=new WeakMap,Lr=new WeakMap,Rr=new WeakMap,yo=new WeakMap;function bo(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function wo(e){return e.__v_skip||!Object.isExtensible(e)?0:bo(ji(e))}function zt(e){return wt(e)?e:cs(e,!1,Mr,_o,Dr)}function xo(e){return cs(e,!1,ao,mo,Lr)}function ls(e){return cs(e,!0,co,vo,Rr)}function cs(e,t,n,s,r){if(!G(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const i=r.get(e);if(i)return i;const o=wo(e);if(o===0)return e;const l=new Proxy(e,o===2?s:n);return r.set(e,l),l}function mt(e){return wt(e)?mt(e.__v_raw):!!(e&&e.__v_isReactive)}function wt(e){return!!(e&&e.__v_isReadonly)}function cn(e){return!!(e&&e.__v_isShallow)}function kr(e){return mt(e)||wt(e)}function U(e){const t=e&&e.__v_raw;return t?U(t):e}function Br(e){return ln(e,"__v_skip",!0),e}const kt=e=>G(e)?zt(e):e,as=e=>G(e)?ls(e):e;function jr(e){Ke&&Ce&&(e=U(e),Sr(e.dep||(e.dep=ns())))}function Hr(e,t){e=U(e);const n=e.dep;n&&Rn(n)}function ce(e){return!!(e&&e.__v_isRef===!0)}function ne(e){return Wr(e,!1)}function Co(e){return Wr(e,!0)}function Wr(e,t){return ce(e)?e:new Oo(e,t)}class Oo{constructor(t,n){this.__v_isShallow=n,this.dep=void 0,this.__v_isRef=!0,this._rawValue=n?t:U(t),this._value=n?t:kt(t)}get value(){return jr(this),this._value}set value(t){const n=this.__v_isShallow||cn(t)||wt(t);t=n?t:U(t),Rt(t,this._rawValue)&&(this._rawValue=t,this._value=n?t:kt(t),Hr(this))}}function de(e){return ce(e)?e.value:e}const Eo={get:(e,t,n)=>de(Reflect.get(e,t,n)),set:(e,t,n,s)=>{const r=e[t];return ce(r)&&!ce(n)?(r.value=n,!0):Reflect.set(e,t,n,s)}};function Ur(e){return mt(e)?e:new Proxy(e,Eo)}var zr;class Ao{constructor(t,n,s,r){this._setter=n,this.dep=void 0,this.__v_isRef=!0,this[zr]=!1,this._dirty=!0,this.effect=new ss(t,()=>{this._dirty||(this._dirty=!0,Hr(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!r,this.__v_isReadonly=s}get value(){const t=U(this);return jr(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}zr="__v_isReadonly";function To(e,t,n=!1){let s,r;const i=L(e);return i?(s=e,r=Ae):(s=e.get,r=e.set),new Ao(s,r,i||!r,n)}function Ve(e,t,n,s){let r;try{r=s?e(...s):e()}catch(i){_n(i,t,n)}return r}function be(e,t,n,s){if(L(e)){const i=Ve(e,t,n,s);return i&&Cr(i)&&i.catch(o=>{_n(o,t,n)}),i}const r=[];for(let i=0;i>>1;jt(ue[s])Se&&ue.splice(t,1)}function So(e){N(e)?vt.push(...e):(!De||!De.includes(e,e.allowRecurse?it+1:it))&&vt.push(e),Vr()}function Ms(e,t=Bt?Se+1:0){for(;tjt(n)-jt(s)),it=0;ite.id==null?1/0:e.id,Fo=(e,t)=>{const n=jt(e)-jt(t);if(n===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return n};function Jr(e){kn=!1,Bt=!0,ue.sort(Fo);const t=Ae;try{for(Se=0;Seoe(w)?w.trim():w)),p&&(r=n.map(Ui))}let l,a=s[l=An(t)]||s[l=An(bt(t))];!a&&i&&(a=s[l=An(Ot(t))]),a&&be(a,e,6,r);const f=s[l+"Once"];if(f){if(!e.emitted)e.emitted={};else if(e.emitted[l])return;e.emitted[l]=!0,be(f,e,6,r)}}function Qr(e,t,n=!1){const s=t.emitsCache,r=s.get(e);if(r!==void 0)return r;const i=e.emits;let o={},l=!1;if(!L(e)){const a=f=>{const d=Qr(f,t,!0);d&&(l=!0,ae(o,d))};!n&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}return!i&&!l?(G(e)&&s.set(e,null),null):(N(i)?i.forEach(a=>o[a]=null):ae(o,i),G(e)&&s.set(e,o),o)}function mn(e,t){return!e||!dn(t)?!1:(t=t.slice(2).replace(/Once$/,""),W(e,t[0].toLowerCase()+t.slice(1))||W(e,Ot(t))||W(e,t))}let ye=null,vn=null;function an(e){const t=ye;return ye=e,vn=e&&e.type.__scopeId||null,t}function Yr(e){vn=e}function Xr(){vn=null}function Zr(e,t=ye,n){if(!t||e._n)return e;const s=(...r)=>{s._d&&Us(-1);const i=an(t);let o;try{o=e(...r)}finally{an(i),s._d&&Us(1)}return o};return s._n=!0,s._c=!0,s._d=!0,s}function Pn(e){const{type:t,vnode:n,proxy:s,withProxy:r,props:i,propsOptions:[o],slots:l,attrs:a,emit:f,render:d,renderCache:p,data:m,setupState:w,ctx:A,inheritAttrs:E}=e;let H,M;const z=an(e);try{if(n.shapeFlag&4){const k=r||s;H=$e(d.call(k,k,p,i,w,m,A)),M=a}else{const k=t;H=$e(k.length>1?k(i,{attrs:a,slots:l,emit:f}):k(i,null)),M=t.props?a:Mo(a)}}catch(k){Dt.length=0,_n(k,e,1),H=ie(Re)}let P=H;if(M&&E!==!1){const k=Object.keys(M),{shapeFlag:K}=P;k.length&&K&7&&(o&&k.some(Zn)&&(M=Do(M,o)),P=Ye(P,M))}return n.dirs&&(P=Ye(P),P.dirs=P.dirs?P.dirs.concat(n.dirs):n.dirs),n.transition&&(P.transition=n.transition),H=P,an(z),H}const Mo=e=>{let t;for(const n in e)(n==="class"||n==="style"||dn(n))&&((t||(t={}))[n]=e[n]);return t},Do=(e,t)=>{const n={};for(const s in e)(!Zn(s)||!(s.slice(9)in t))&&(n[s]=e[s]);return n};function Lo(e,t,n){const{props:s,children:r,component:i}=e,{props:o,children:l,patchFlag:a}=t,f=i.emitsOptions;if(t.dirs||t.transition)return!0;if(n&&a>=0){if(a&1024)return!0;if(a&16)return s?Ds(s,o,f):!!o;if(a&8){const d=t.dynamicProps;for(let p=0;pe.__isSuspense;function Bo(e,t){t&&t.pendingBranch?N(e)?t.effects.push(...e):t.effects.push(e):So(e)}function jo(e,t){if(re){let n=re.provides;const s=re.parent&&re.parent.provides;s===n&&(n=re.provides=Object.create(s)),n[e]=t}}function nn(e,t,n=!1){const s=re||ye;if(s){const r=s.parent==null?s.vnode.appContext&&s.vnode.appContext.provides:s.parent.provides;if(r&&e in r)return r[e];if(arguments.length>1)return n&&L(t)?t.call(s.proxy):t}}function yt(e,t){return hs(e,null,t)}const en={};function ft(e,t,n){return hs(e,t,n)}function hs(e,t,{immediate:n,deep:s,flush:r,onTrack:i,onTrigger:o}=Z){const l=Tr()===(re==null?void 0:re.scope)?re:null;let a,f=!1,d=!1;if(ce(e)?(a=()=>e.value,f=cn(e)):mt(e)?(a=()=>e,s=!0):N(e)?(d=!0,f=e.some(P=>mt(P)||cn(P)),a=()=>e.map(P=>{if(ce(P))return P.value;if(mt(P))return at(P);if(L(P))return Ve(P,l,2)})):L(e)?t?a=()=>Ve(e,l,2):a=()=>{if(!(l&&l.isUnmounted))return p&&p(),be(e,l,3,[m])}:a=Ae,t&&s){const P=a;a=()=>at(P())}let p,m=P=>{p=M.onStop=()=>{Ve(P,l,4)}},w;if(Wt)if(m=Ae,t?n&&be(t,l,3,[a(),d?[]:void 0,m]):a(),r==="sync"){const P=Ml();w=P.__watcherHandles||(P.__watcherHandles=[])}else return Ae;let A=d?new Array(e.length).fill(en):en;const E=()=>{if(M.active)if(t){const P=M.run();(s||f||(d?P.some((k,K)=>Rt(k,A[K])):Rt(P,A)))&&(p&&p(),be(t,l,3,[P,A===en?void 0:d&&A[0]===en?[]:A,m]),A=P)}else M.run()};E.allowRecurse=!!t;let H;r==="sync"?H=E:r==="post"?H=()=>he(E,l&&l.suspense):(E.pre=!0,l&&(E.id=l.uid),H=()=>ds(E));const M=new ss(a,H);t?n?E():A=M.run():r==="post"?he(M.run.bind(M),l&&l.suspense):M.run();const z=()=>{M.stop(),l&&l.scope&&Gn(l.scope.effects,M)};return w&&w.push(z),z}function Ho(e,t,n){const s=this.proxy,r=oe(e)?e.includes(".")?Gr(s,e):()=>s[e]:e.bind(s,s);let i;L(t)?i=t:(i=t.handler,n=t);const o=re;xt(this);const l=hs(r,i.bind(s),n);return o?xt(o):dt(),l}function Gr(e,t){const n=t.split(".");return()=>{let s=e;for(let r=0;r{at(n,t)});else if(Er(e))for(const n in e)at(e[n],t);return e}function Wo(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return Kt(()=>{e.isMounted=!0}),ri(()=>{e.isUnmounting=!0}),e}const ve=[Function,Array],Uo={name:"BaseTransition",props:{mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:ve,onEnter:ve,onAfterEnter:ve,onEnterCancelled:ve,onBeforeLeave:ve,onLeave:ve,onAfterLeave:ve,onLeaveCancelled:ve,onBeforeAppear:ve,onAppear:ve,onAfterAppear:ve,onAppearCancelled:ve},setup(e,{slots:t}){const n=_i(),s=Wo();let r;return()=>{const i=t.default&&ni(t.default(),!0);if(!i||!i.length)return;let o=i[0];if(i.length>1){for(const E of i)if(E.type!==Re){o=E;break}}const l=U(e),{mode:a}=l;if(s.isLeaving)return In(o);const f=Ls(o);if(!f)return In(o);const d=Bn(f,l,s,n);jn(f,d);const p=n.subTree,m=p&&Ls(p);let w=!1;const{getTransitionKey:A}=f.type;if(A){const E=A();r===void 0?r=E:E!==r&&(r=E,w=!0)}if(m&&m.type!==Re&&(!ot(f,m)||w)){const E=Bn(m,l,s,n);if(jn(m,E),a==="out-in")return s.isLeaving=!0,E.afterLeave=()=>{s.isLeaving=!1,n.update.active!==!1&&n.update()},In(o);a==="in-out"&&f.type!==Re&&(E.delayLeave=(H,M,z)=>{const P=ti(s,m);P[String(m.key)]=m,H._leaveCb=()=>{M(),H._leaveCb=void 0,delete d.delayedLeave},d.delayedLeave=z})}return o}}},ei=Uo;function ti(e,t){const{leavingVNodes:n}=e;let s=n.get(t.type);return s||(s=Object.create(null),n.set(t.type,s)),s}function Bn(e,t,n,s){const{appear:r,mode:i,persisted:o=!1,onBeforeEnter:l,onEnter:a,onAfterEnter:f,onEnterCancelled:d,onBeforeLeave:p,onLeave:m,onAfterLeave:w,onLeaveCancelled:A,onBeforeAppear:E,onAppear:H,onAfterAppear:M,onAppearCancelled:z}=t,P=String(e.key),k=ti(n,e),K=(O,R)=>{O&&be(O,s,9,R)},V=(O,R)=>{const j=R[1];K(O,R),N(O)?O.every(Q=>Q.length<=1)&&j():O.length<=1&&j()},J={mode:i,persisted:o,beforeEnter(O){let R=l;if(!n.isMounted)if(r)R=E||l;else return;O._leaveCb&&O._leaveCb(!0);const j=k[P];j&&ot(e,j)&&j.el._leaveCb&&j.el._leaveCb(),K(R,[O])},enter(O){let R=a,j=f,Q=d;if(!n.isMounted)if(r)R=H||a,j=M||f,Q=z||d;else return;let I=!1;const ee=O._enterCb=ge=>{I||(I=!0,ge?K(Q,[O]):K(j,[O]),J.delayedLeave&&J.delayedLeave(),O._enterCb=void 0)};R?V(R,[O,ee]):ee()},leave(O,R){const j=String(e.key);if(O._enterCb&&O._enterCb(!0),n.isUnmounting)return R();K(p,[O]);let Q=!1;const I=O._leaveCb=ee=>{Q||(Q=!0,R(),ee?K(A,[O]):K(w,[O]),O._leaveCb=void 0,k[j]===e&&delete k[j])};k[j]=e,m?V(m,[O,I]):I()},clone(O){return Bn(O,t,n,s)}};return J}function In(e){if(yn(e))return e=Ye(e),e.children=null,e}function Ls(e){return yn(e)?e.children?e.children[0]:void 0:e}function jn(e,t){e.shapeFlag&6&&e.component?jn(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function ni(e,t=!1,n){let s=[],r=0;for(let i=0;i1)for(let i=0;i!!e.type.__asyncLoader,yn=e=>e.type.__isKeepAlive;function zo(e,t){si(e,"a",t)}function Ko(e,t){si(e,"da",t)}function si(e,t,n=re){const s=e.__wdc||(e.__wdc=()=>{let r=n;for(;r;){if(r.isDeactivated)return;r=r.parent}return e()});if(bn(t,s,n),n){let r=n.parent;for(;r&&r.parent;)yn(r.parent.vnode)&&Vo(s,t,n,r),r=r.parent}}function Vo(e,t,n,s){const r=bn(t,e,s,!0);gs(()=>{Gn(s[t],r)},n)}function bn(e,t,n=re,s=!1){if(n){const r=n[e]||(n[e]=[]),i=t.__weh||(t.__weh=(...o)=>{if(n.isUnmounted)return;Et(),xt(n);const l=be(t,n,e,o);return dt(),At(),l});return s?r.unshift(i):r.push(i),i}}const je=e=>(t,n=re)=>(!Wt||e==="sp")&&bn(e,(...s)=>t(...s),n),qo=je("bm"),Kt=je("m"),Jo=je("bu"),Qo=je("u"),ri=je("bum"),gs=je("um"),Yo=je("sp"),Xo=je("rtg"),Zo=je("rtc");function Go(e,t=re){bn("ec",e,t)}function qe(e,t){const n=ye;if(n===null)return e;const s=Cn(n)||n.proxy,r=e.dirs||(e.dirs=[]);for(let i=0;it(o,l,void 0,i&&i[l]));else{const o=Object.keys(e);r=new Array(o.length);for(let l=0,a=o.length;le?mi(e)?Cn(e)||e.proxy:Hn(e.parent):null,Mt=ae(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Hn(e.parent),$root:e=>Hn(e.root),$emit:e=>e.emit,$options:e=>_s(e),$forceUpdate:e=>e.f||(e.f=()=>ds(e.update)),$nextTick:e=>e.n||(e.n=fs.bind(e.proxy)),$watch:e=>Ho.bind(e)}),$n=(e,t)=>e!==Z&&!e.__isScriptSetup&&W(e,t),nl={get({_:e},t){const{ctx:n,setupState:s,data:r,props:i,accessCache:o,type:l,appContext:a}=e;let f;if(t[0]!=="$"){const w=o[t];if(w!==void 0)switch(w){case 1:return s[t];case 2:return r[t];case 4:return n[t];case 3:return i[t]}else{if($n(s,t))return o[t]=1,s[t];if(r!==Z&&W(r,t))return o[t]=2,r[t];if((f=e.propsOptions[0])&&W(f,t))return o[t]=3,i[t];if(n!==Z&&W(n,t))return o[t]=4,n[t];Wn&&(o[t]=0)}}const d=Mt[t];let p,m;if(d)return t==="$attrs"&&pe(e,"get",t),d(e);if((p=l.__cssModules)&&(p=p[t]))return p;if(n!==Z&&W(n,t))return o[t]=4,n[t];if(m=a.config.globalProperties,W(m,t))return m[t]},set({_:e},t,n){const{data:s,setupState:r,ctx:i}=e;return $n(r,t)?(r[t]=n,!0):s!==Z&&W(s,t)?(s[t]=n,!0):W(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(i[t]=n,!0)},has({_:{data:e,setupState:t,accessCache:n,ctx:s,appContext:r,propsOptions:i}},o){let l;return!!n[o]||e!==Z&&W(e,o)||$n(t,o)||(l=i[0])&&W(l,o)||W(s,o)||W(Mt,o)||W(r.config.globalProperties,o)},defineProperty(e,t,n){return n.get!=null?e._.accessCache[t]=0:W(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};let Wn=!0;function sl(e){const t=_s(e),n=e.proxy,s=e.ctx;Wn=!1,t.beforeCreate&&Rs(t.beforeCreate,e,"bc");const{data:r,computed:i,methods:o,watch:l,provide:a,inject:f,created:d,beforeMount:p,mounted:m,beforeUpdate:w,updated:A,activated:E,deactivated:H,beforeDestroy:M,beforeUnmount:z,destroyed:P,unmounted:k,render:K,renderTracked:V,renderTriggered:J,errorCaptured:O,serverPrefetch:R,expose:j,inheritAttrs:Q,components:I,directives:ee,filters:ge}=t;if(f&&rl(f,s,null,e.appContext.config.unwrapInjectedRef),o)for(const te in o){const Y=o[te];L(Y)&&(s[te]=Y.bind(n))}if(r){const te=r.call(n,n);G(te)&&(e.data=zt(te))}if(Wn=!0,i)for(const te in i){const Y=i[te],Ze=L(Y)?Y.bind(n,n):L(Y.get)?Y.get.bind(n,n):Ae,qt=!L(Y)&&L(Y.set)?Y.set.bind(n):Ae,Ge=Le({get:Ze,set:qt});Object.defineProperty(s,te,{enumerable:!0,configurable:!0,get:()=>Ge.value,set:Te=>Ge.value=Te})}if(l)for(const te in l)ii(l[te],s,n,te);if(a){const te=L(a)?a.call(n):a;Reflect.ownKeys(te).forEach(Y=>{jo(Y,te[Y])})}d&&Rs(d,e,"c");function le(te,Y){N(Y)?Y.forEach(Ze=>te(Ze.bind(n))):Y&&te(Y.bind(n))}if(le(qo,p),le(Kt,m),le(Jo,w),le(Qo,A),le(zo,E),le(Ko,H),le(Go,O),le(Zo,V),le(Xo,J),le(ri,z),le(gs,k),le(Yo,R),N(j))if(j.length){const te=e.exposed||(e.exposed={});j.forEach(Y=>{Object.defineProperty(te,Y,{get:()=>n[Y],set:Ze=>n[Y]=Ze})})}else e.exposed||(e.exposed={});K&&e.render===Ae&&(e.render=K),Q!=null&&(e.inheritAttrs=Q),I&&(e.components=I),ee&&(e.directives=ee)}function rl(e,t,n=Ae,s=!1){N(e)&&(e=Un(e));for(const r in e){const i=e[r];let o;G(i)?"default"in i?o=nn(i.from||r,i.default,!0):o=nn(i.from||r):o=nn(i),ce(o)&&s?Object.defineProperty(t,r,{enumerable:!0,configurable:!0,get:()=>o.value,set:l=>o.value=l}):t[r]=o}}function Rs(e,t,n){be(N(e)?e.map(s=>s.bind(t.proxy)):e.bind(t.proxy),t,n)}function ii(e,t,n,s){const r=s.includes(".")?Gr(n,s):()=>n[s];if(oe(e)){const i=t[e];L(i)&&ft(r,i)}else if(L(e))ft(r,e.bind(n));else if(G(e))if(N(e))e.forEach(i=>ii(i,t,n,s));else{const i=L(e.handler)?e.handler.bind(n):t[e.handler];L(i)&&ft(r,i,e)}}function _s(e){const t=e.type,{mixins:n,extends:s}=t,{mixins:r,optionsCache:i,config:{optionMergeStrategies:o}}=e.appContext,l=i.get(t);let a;return l?a=l:!r.length&&!n&&!s?a=t:(a={},r.length&&r.forEach(f=>un(a,f,o,!0)),un(a,t,o)),G(t)&&i.set(t,a),a}function un(e,t,n,s=!1){const{mixins:r,extends:i}=t;i&&un(e,i,n,!0),r&&r.forEach(o=>un(e,o,n,!0));for(const o in t)if(!(s&&o==="expose")){const l=il[o]||n&&n[o];e[o]=l?l(e[o],t[o]):t[o]}return e}const il={data:ks,props:rt,emits:rt,methods:rt,computed:rt,beforeCreate:fe,created:fe,beforeMount:fe,mounted:fe,beforeUpdate:fe,updated:fe,beforeDestroy:fe,beforeUnmount:fe,destroyed:fe,unmounted:fe,activated:fe,deactivated:fe,errorCaptured:fe,serverPrefetch:fe,components:rt,directives:rt,watch:ll,provide:ks,inject:ol};function ks(e,t){return t?e?function(){return ae(L(e)?e.call(this,this):e,L(t)?t.call(this,this):t)}:t:e}function ol(e,t){return rt(Un(e),Un(t))}function Un(e){if(N(e)){const t={};for(let n=0;n0)&&!(o&16)){if(o&8){const d=e.vnode.dynamicProps;for(let p=0;p{a=!0;const[m,w]=li(p,t,!0);ae(o,m),w&&l.push(...w)};!n&&t.mixins.length&&t.mixins.forEach(d),e.extends&&d(e.extends),e.mixins&&e.mixins.forEach(d)}if(!i&&!a)return G(e)&&s.set(e,gt),gt;if(N(i))for(let d=0;d-1,w[1]=E<0||A-1||W(w,"default"))&&l.push(p)}}}const f=[o,l];return G(e)&&s.set(e,f),f}function Bs(e){return e[0]!=="$"}function js(e){const t=e&&e.toString().match(/^\s*(function|class) (\w+)/);return t?t[2]:e===null?"null":""}function Hs(e,t){return js(e)===js(t)}function Ws(e,t){return N(t)?t.findIndex(n=>Hs(n,e)):L(t)&&Hs(t,e)?0:-1}const ci=e=>e[0]==="_"||e==="$stable",ms=e=>N(e)?e.map($e):[$e(e)],ul=(e,t,n)=>{if(t._n)return t;const s=Zr((...r)=>ms(t(...r)),n);return s._c=!1,s},ai=(e,t,n)=>{const s=e._ctx;for(const r in e){if(ci(r))continue;const i=e[r];if(L(i))t[r]=ul(r,i,s);else if(i!=null){const o=ms(i);t[r]=()=>o}}},ui=(e,t)=>{const n=ms(t);e.slots.default=()=>n},fl=(e,t)=>{if(e.vnode.shapeFlag&32){const n=t._;n?(e.slots=U(t),ln(t,"_",n)):ai(t,e.slots={})}else e.slots={},t&&ui(e,t);ln(e.slots,xn,1)},dl=(e,t,n)=>{const{vnode:s,slots:r}=e;let i=!0,o=Z;if(s.shapeFlag&32){const l=t._;l?n&&l===1?i=!1:(ae(r,t),!n&&l===1&&delete r._):(i=!t.$stable,ai(t,r)),o=t}else t&&(ui(e,t),o={default:1});if(i)for(const l in r)!ci(l)&&!(l in o)&&delete r[l]};function fi(){return{app:null,config:{isNativeTag:Ri,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let hl=0;function pl(e,t){return function(s,r=null){L(s)||(s=Object.assign({},s)),r!=null&&!G(r)&&(r=null);const i=fi(),o=new Set;let l=!1;const a=i.app={_uid:hl++,_component:s,_props:r,_container:null,_context:i,_instance:null,version:Dl,get config(){return i.config},set config(f){},use(f,...d){return o.has(f)||(f&&L(f.install)?(o.add(f),f.install(a,...d)):L(f)&&(o.add(f),f(a,...d))),a},mixin(f){return i.mixins.includes(f)||i.mixins.push(f),a},component(f,d){return d?(i.components[f]=d,a):i.components[f]},directive(f,d){return d?(i.directives[f]=d,a):i.directives[f]},mount(f,d,p){if(!l){const m=ie(s,r);return m.appContext=i,d&&t?t(m,f):e(m,f,p),l=!0,a._container=f,f.__vue_app__=a,Cn(m.component)||m.component.proxy}},unmount(){l&&(e(null,a._container),delete a._container.__vue_app__)},provide(f,d){return i.provides[f]=d,a}};return a}}function Kn(e,t,n,s,r=!1){if(N(e)){e.forEach((m,w)=>Kn(m,t&&(N(t)?t[w]:t),n,s,r));return}if(sn(s)&&!r)return;const i=s.shapeFlag&4?Cn(s.component)||s.component.proxy:s.el,o=r?null:i,{i:l,r:a}=e,f=t&&t.r,d=l.refs===Z?l.refs={}:l.refs,p=l.setupState;if(f!=null&&f!==a&&(oe(f)?(d[f]=null,W(p,f)&&(p[f]=null)):ce(f)&&(f.value=null)),L(a))Ve(a,l,12,[o,d]);else{const m=oe(a),w=ce(a);if(m||w){const A=()=>{if(e.f){const E=m?W(p,a)?p[a]:d[a]:a.value;r?N(E)&&Gn(E,i):N(E)?E.includes(i)||E.push(i):m?(d[a]=[i],W(p,a)&&(p[a]=d[a])):(a.value=[i],e.k&&(d[e.k]=a.value))}else m?(d[a]=o,W(p,a)&&(p[a]=o)):w&&(a.value=o,e.k&&(d[e.k]=o))};o?(A.id=-1,he(A,n)):A()}}}const he=Bo;function gl(e){return _l(e)}function _l(e,t){const n=Ki();n.__VUE__=!0;const{insert:s,remove:r,patchProp:i,createElement:o,createText:l,createComment:a,setText:f,setElementText:d,parentNode:p,nextSibling:m,setScopeId:w=Ae,insertStaticContent:A}=e,E=(c,u,h,_=null,g=null,b=null,C=!1,y=null,x=!!u.dynamicChildren)=>{if(c===u)return;c&&!ot(c,u)&&(_=Jt(c),Te(c,g,b,!0),c=null),u.patchFlag===-2&&(x=!1,u.dynamicChildren=null);const{type:v,ref:$,shapeFlag:T}=u;switch(v){case wn:H(c,u,h,_);break;case Re:M(c,u,h,_);break;case rn:c==null&&z(u,h,_,C);break;case xe:I(c,u,h,_,g,b,C,y,x);break;default:T&1?K(c,u,h,_,g,b,C,y,x):T&6?ee(c,u,h,_,g,b,C,y,x):(T&64||T&128)&&v.process(c,u,h,_,g,b,C,y,x,ht)}$!=null&&g&&Kn($,c&&c.ref,b,u||c,!u)},H=(c,u,h,_)=>{if(c==null)s(u.el=l(u.children),h,_);else{const g=u.el=c.el;u.children!==c.children&&f(g,u.children)}},M=(c,u,h,_)=>{c==null?s(u.el=a(u.children||""),h,_):u.el=c.el},z=(c,u,h,_)=>{[c.el,c.anchor]=A(c.children,u,h,_,c.el,c.anchor)},P=({el:c,anchor:u},h,_)=>{let g;for(;c&&c!==u;)g=m(c),s(c,h,_),c=g;s(u,h,_)},k=({el:c,anchor:u})=>{let h;for(;c&&c!==u;)h=m(c),r(c),c=h;r(u)},K=(c,u,h,_,g,b,C,y,x)=>{C=C||u.type==="svg",c==null?V(u,h,_,g,b,C,y,x):R(c,u,g,b,C,y,x)},V=(c,u,h,_,g,b,C,y)=>{let x,v;const{type:$,props:T,shapeFlag:S,transition:D,dirs:B}=c;if(x=c.el=o(c.type,b,T&&T.is,T),S&8?d(x,c.children):S&16&&O(c.children,x,null,_,g,b&&$!=="foreignObject",C,y),B&&et(c,null,_,"created"),J(x,c,c.scopeId,C,_),T){for(const q in T)q!=="value"&&!tn(q)&&i(x,q,null,T[q],b,c.children,_,g,Ne);"value"in T&&i(x,"value",null,T.value),(v=T.onVnodeBeforeMount)&&Ie(v,_,c)}B&&et(c,null,_,"beforeMount");const X=(!g||g&&!g.pendingBranch)&&D&&!D.persisted;X&&D.beforeEnter(x),s(x,u,h),((v=T&&T.onVnodeMounted)||X||B)&&he(()=>{v&&Ie(v,_,c),X&&D.enter(x),B&&et(c,null,_,"mounted")},g)},J=(c,u,h,_,g)=>{if(h&&w(c,h),_)for(let b=0;b<_.length;b++)w(c,_[b]);if(g){let b=g.subTree;if(u===b){const C=g.vnode;J(c,C,C.scopeId,C.slotScopeIds,g.parent)}}},O=(c,u,h,_,g,b,C,y,x=0)=>{for(let v=x;v{const y=u.el=c.el;let{patchFlag:x,dynamicChildren:v,dirs:$}=u;x|=c.patchFlag&16;const T=c.props||Z,S=u.props||Z;let D;h&&tt(h,!1),(D=S.onVnodeBeforeUpdate)&&Ie(D,h,u,c),$&&et(u,c,h,"beforeUpdate"),h&&tt(h,!0);const B=g&&u.type!=="foreignObject";if(v?j(c.dynamicChildren,v,y,h,_,B,b):C||Y(c,u,y,null,h,_,B,b,!1),x>0){if(x&16)Q(y,u,T,S,h,_,g);else if(x&2&&T.class!==S.class&&i(y,"class",null,S.class,g),x&4&&i(y,"style",T.style,S.style,g),x&8){const X=u.dynamicProps;for(let q=0;q{D&&Ie(D,h,u,c),$&&et(u,c,h,"updated")},_)},j=(c,u,h,_,g,b,C)=>{for(let y=0;y{if(h!==_){if(h!==Z)for(const y in h)!tn(y)&&!(y in _)&&i(c,y,h[y],null,C,u.children,g,b,Ne);for(const y in _){if(tn(y))continue;const x=_[y],v=h[y];x!==v&&y!=="value"&&i(c,y,v,x,C,u.children,g,b,Ne)}"value"in _&&i(c,"value",h.value,_.value)}},I=(c,u,h,_,g,b,C,y,x)=>{const v=u.el=c?c.el:l(""),$=u.anchor=c?c.anchor:l("");let{patchFlag:T,dynamicChildren:S,slotScopeIds:D}=u;D&&(y=y?y.concat(D):D),c==null?(s(v,h,_),s($,h,_),O(u.children,h,$,g,b,C,y,x)):T>0&&T&64&&S&&c.dynamicChildren?(j(c.dynamicChildren,S,h,g,b,C,y),(u.key!=null||g&&u===g.subTree)&&di(c,u,!0)):Y(c,u,h,$,g,b,C,y,x)},ee=(c,u,h,_,g,b,C,y,x)=>{u.slotScopeIds=y,c==null?u.shapeFlag&512?g.ctx.activate(u,h,_,C,x):ge(u,h,_,g,b,C,x):Tt(c,u,x)},ge=(c,u,h,_,g,b,C)=>{const y=c.component=Al(c,_,g);if(yn(c)&&(y.ctx.renderer=ht),Tl(y),y.asyncDep){if(g&&g.registerDep(y,le),!c.el){const x=y.subTree=ie(Re);M(null,x,u,h)}return}le(y,c,u,h,g,b,C)},Tt=(c,u,h)=>{const _=u.component=c.component;if(Lo(c,u,h))if(_.asyncDep&&!_.asyncResolved){te(_,u,h);return}else _.next=u,$o(_.update),_.update();else u.el=c.el,_.vnode=u},le=(c,u,h,_,g,b,C)=>{const y=()=>{if(c.isMounted){let{next:$,bu:T,u:S,parent:D,vnode:B}=c,X=$,q;tt(c,!1),$?($.el=B.el,te(c,$,C)):$=B,T&&Tn(T),(q=$.props&&$.props.onVnodeBeforeUpdate)&&Ie(q,D,$,B),tt(c,!0);const se=Pn(c),we=c.subTree;c.subTree=se,E(we,se,p(we.el),Jt(we),c,g,b),$.el=se.el,X===null&&Ro(c,se.el),S&&he(S,g),(q=$.props&&$.props.onVnodeUpdated)&&he(()=>Ie(q,D,$,B),g)}else{let $;const{el:T,props:S}=u,{bm:D,m:B,parent:X}=c,q=sn(u);if(tt(c,!1),D&&Tn(D),!q&&($=S&&S.onVnodeBeforeMount)&&Ie($,X,u),tt(c,!0),T&&En){const se=()=>{c.subTree=Pn(c),En(T,c.subTree,c,g,null)};q?u.type.__asyncLoader().then(()=>!c.isUnmounted&&se()):se()}else{const se=c.subTree=Pn(c);E(null,se,h,_,c,g,b),u.el=se.el}if(B&&he(B,g),!q&&($=S&&S.onVnodeMounted)){const se=u;he(()=>Ie($,X,se),g)}(u.shapeFlag&256||X&&sn(X.vnode)&&X.vnode.shapeFlag&256)&&c.a&&he(c.a,g),c.isMounted=!0,u=h=_=null}},x=c.effect=new ss(y,()=>ds(v),c.scope),v=c.update=()=>x.run();v.id=c.uid,tt(c,!0),v()},te=(c,u,h)=>{u.component=c;const _=c.vnode.props;c.vnode=u,c.next=null,al(c,u.props,_,h),dl(c,u.children,h),Et(),Ms(),At()},Y=(c,u,h,_,g,b,C,y,x=!1)=>{const v=c&&c.children,$=c?c.shapeFlag:0,T=u.children,{patchFlag:S,shapeFlag:D}=u;if(S>0){if(S&128){qt(v,T,h,_,g,b,C,y,x);return}else if(S&256){Ze(v,T,h,_,g,b,C,y,x);return}}D&8?($&16&&Ne(v,g,b),T!==v&&d(h,T)):$&16?D&16?qt(v,T,h,_,g,b,C,y,x):Ne(v,g,b,!0):($&8&&d(h,""),D&16&&O(T,h,_,g,b,C,y,x))},Ze=(c,u,h,_,g,b,C,y,x)=>{c=c||gt,u=u||gt;const v=c.length,$=u.length,T=Math.min(v,$);let S;for(S=0;S$?Ne(c,g,b,!0,!1,T):O(u,h,_,g,b,C,y,x,T)},qt=(c,u,h,_,g,b,C,y,x)=>{let v=0;const $=u.length;let T=c.length-1,S=$-1;for(;v<=T&&v<=S;){const D=c[v],B=u[v]=x?ze(u[v]):$e(u[v]);if(ot(D,B))E(D,B,h,null,g,b,C,y,x);else break;v++}for(;v<=T&&v<=S;){const D=c[T],B=u[S]=x?ze(u[S]):$e(u[S]);if(ot(D,B))E(D,B,h,null,g,b,C,y,x);else break;T--,S--}if(v>T){if(v<=S){const D=S+1,B=D<$?u[D].el:_;for(;v<=S;)E(null,u[v]=x?ze(u[v]):$e(u[v]),h,B,g,b,C,y,x),v++}}else if(v>S)for(;v<=T;)Te(c[v],g,b,!0),v++;else{const D=v,B=v,X=new Map;for(v=B;v<=S;v++){const _e=u[v]=x?ze(u[v]):$e(u[v]);_e.key!=null&&X.set(_e.key,v)}let q,se=0;const we=S-B+1;let pt=!1,Cs=0;const Pt=new Array(we);for(v=0;v=we){Te(_e,g,b,!0);continue}let Pe;if(_e.key!=null)Pe=X.get(_e.key);else for(q=B;q<=S;q++)if(Pt[q-B]===0&&ot(_e,u[q])){Pe=q;break}Pe===void 0?Te(_e,g,b,!0):(Pt[Pe-B]=v+1,Pe>=Cs?Cs=Pe:pt=!0,E(_e,u[Pe],h,null,g,b,C,y,x),se++)}const Os=pt?ml(Pt):gt;for(q=Os.length-1,v=we-1;v>=0;v--){const _e=B+v,Pe=u[_e],Es=_e+1<$?u[_e+1].el:_;Pt[v]===0?E(null,Pe,h,Es,g,b,C,y,x):pt&&(q<0||v!==Os[q]?Ge(Pe,h,Es,2):q--)}}},Ge=(c,u,h,_,g=null)=>{const{el:b,type:C,transition:y,children:x,shapeFlag:v}=c;if(v&6){Ge(c.component.subTree,u,h,_);return}if(v&128){c.suspense.move(u,h,_);return}if(v&64){C.move(c,u,h,ht);return}if(C===xe){s(b,u,h);for(let T=0;Ty.enter(b),g);else{const{leave:T,delayLeave:S,afterLeave:D}=y,B=()=>s(b,u,h),X=()=>{T(b,()=>{B(),D&&D()})};S?S(b,B,X):X()}else s(b,u,h)},Te=(c,u,h,_=!1,g=!1)=>{const{type:b,props:C,ref:y,children:x,dynamicChildren:v,shapeFlag:$,patchFlag:T,dirs:S}=c;if(y!=null&&Kn(y,null,h,c,!0),$&256){u.ctx.deactivate(c);return}const D=$&1&&S,B=!sn(c);let X;if(B&&(X=C&&C.onVnodeBeforeUnmount)&&Ie(X,u,c),$&6)$i(c.component,h,_);else{if($&128){c.suspense.unmount(h,_);return}D&&et(c,null,u,"beforeUnmount"),$&64?c.type.remove(c,u,h,g,ht,_):v&&(b!==xe||T>0&&T&64)?Ne(v,u,h,!1,!0):(b===xe&&T&384||!g&&$&16)&&Ne(x,u,h),_&&ws(c)}(B&&(X=C&&C.onVnodeUnmounted)||D)&&he(()=>{X&&Ie(X,u,c),D&&et(c,null,u,"unmounted")},h)},ws=c=>{const{type:u,el:h,anchor:_,transition:g}=c;if(u===xe){Ii(h,_);return}if(u===rn){k(c);return}const b=()=>{r(h),g&&!g.persisted&&g.afterLeave&&g.afterLeave()};if(c.shapeFlag&1&&g&&!g.persisted){const{leave:C,delayLeave:y}=g,x=()=>C(h,b);y?y(c.el,b,x):x()}else b()},Ii=(c,u)=>{let h;for(;c!==u;)h=m(c),r(c),c=h;r(u)},$i=(c,u,h)=>{const{bum:_,scope:g,update:b,subTree:C,um:y}=c;_&&Tn(_),g.stop(),b&&(b.active=!1,Te(C,c,u,h)),y&&he(y,u),he(()=>{c.isUnmounted=!0},u),u&&u.pendingBranch&&!u.isUnmounted&&c.asyncDep&&!c.asyncResolved&&c.suspenseId===u.pendingId&&(u.deps--,u.deps===0&&u.resolve())},Ne=(c,u,h,_=!1,g=!1,b=0)=>{for(let C=b;Cc.shapeFlag&6?Jt(c.component.subTree):c.shapeFlag&128?c.suspense.next():m(c.anchor||c.el),xs=(c,u,h)=>{c==null?u._vnode&&Te(u._vnode,null,null,!0):E(u._vnode||null,c,u,null,null,null,h),Ms(),qr(),u._vnode=c},ht={p:E,um:Te,m:Ge,r:ws,mt:ge,mc:O,pc:Y,pbc:j,n:Jt,o:e};let On,En;return t&&([On,En]=t(ht)),{render:xs,hydrate:On,createApp:pl(xs,On)}}function tt({effect:e,update:t},n){e.allowRecurse=t.allowRecurse=n}function di(e,t,n=!1){const s=e.children,r=t.children;if(N(s)&&N(r))for(let i=0;i>1,e[n[l]]0&&(t[s]=n[i-1]),n[i]=s)}}for(i=n.length,o=n[i-1];i-- >0;)n[i]=o,o=t[o];return n}const vl=e=>e.__isTeleport,xe=Symbol(void 0),wn=Symbol(void 0),Re=Symbol(void 0),rn=Symbol(void 0),Dt=[];let Ee=null;function Fe(e=!1){Dt.push(Ee=e?null:[])}function yl(){Dt.pop(),Ee=Dt[Dt.length-1]||null}let Ht=1;function Us(e){Ht+=e}function hi(e){return e.dynamicChildren=Ht>0?Ee||gt:null,yl(),Ht>0&&Ee&&Ee.push(e),e}function Be(e,t,n,s,r,i){return hi(F(e,t,n,s,r,i,!0))}function bl(e,t,n,s,r){return hi(ie(e,t,n,s,r,!0))}function Vn(e){return e?e.__v_isVNode===!0:!1}function ot(e,t){return e.type===t.type&&e.key===t.key}const xn="__vInternal",pi=({key:e})=>e??null,on=({ref:e,ref_key:t,ref_for:n})=>e!=null?oe(e)||ce(e)||L(e)?{i:ye,r:e,k:t,f:!!n}:e:null;function F(e,t=null,n=null,s=0,r=null,i=e===xe?0:1,o=!1,l=!1){const a={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&pi(t),ref:t&&on(t),scopeId:vn,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:i,patchFlag:s,dynamicProps:r,dynamicChildren:null,appContext:null,ctx:ye};return l?(vs(a,n),i&128&&e.normalize(a)):n&&(a.shapeFlag|=oe(n)?8:16),Ht>0&&!o&&Ee&&(a.patchFlag>0||i&6)&&a.patchFlag!==32&&Ee.push(a),a}const ie=wl;function wl(e,t=null,n=null,s=0,r=null,i=!1){if((!e||e===el)&&(e=Re),Vn(e)){const l=Ye(e,t,!0);return n&&vs(l,n),Ht>0&&!i&&Ee&&(l.shapeFlag&6?Ee[Ee.indexOf(e)]=l:Ee.push(l)),l.patchFlag|=-2,l}if(Sl(e)&&(e=e.__vccOpts),t){t=xl(t);let{class:l,style:a}=t;l&&!oe(l)&&(t.class=Oe(l)),G(a)&&(kr(a)&&!N(a)&&(a=ae({},a)),t.style=ct(a))}const o=oe(e)?1:ko(e)?128:vl(e)?64:G(e)?4:L(e)?2:0;return F(e,t,n,s,r,o,i,!0)}function xl(e){return e?kr(e)||xn in e?ae({},e):e:null}function Ye(e,t,n=!1){const{props:s,ref:r,patchFlag:i,children:o}=e,l=t?gi(s||{},t):s;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:l,key:l&&pi(l),ref:t&&t.ref?n&&r?N(r)?r.concat(on(t)):[r,on(t)]:on(t):r,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:o,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==xe?i===-1?16:i|16:i,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Ye(e.ssContent),ssFallback:e.ssFallback&&Ye(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function Lt(e=" ",t=0){return ie(wn,null,e,t)}function Cl(e,t){const n=ie(rn,null,e);return n.staticCount=t,n}function $e(e){return e==null||typeof e=="boolean"?ie(Re):N(e)?ie(xe,null,e.slice()):typeof e=="object"?ze(e):ie(wn,null,String(e))}function ze(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Ye(e)}function vs(e,t){let n=0;const{shapeFlag:s}=e;if(t==null)t=null;else if(N(t))n=16;else if(typeof t=="object")if(s&65){const r=t.default;r&&(r._c&&(r._d=!1),vs(e,r()),r._c&&(r._d=!0));return}else{n=32;const r=t._;!r&&!(xn in t)?t._ctx=ye:r===3&&ye&&(ye.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else L(t)?(t={default:t,_ctx:ye},n=32):(t=String(t),s&64?(n=16,t=[Lt(t)]):n=8);e.children=t,e.shapeFlag|=n}function gi(...e){const t={};for(let n=0;nre||ye,xt=e=>{re=e,e.scope.on()},dt=()=>{re&&re.scope.off(),re=null};function mi(e){return e.vnode.shapeFlag&4}let Wt=!1;function Tl(e,t=!1){Wt=t;const{props:n,children:s}=e.vnode,r=mi(e);cl(e,n,r,t),fl(e,s);const i=r?Pl(e,t):void 0;return Wt=!1,i}function Pl(e,t){const n=e.type;e.accessCache=Object.create(null),e.proxy=Br(new Proxy(e.ctx,nl));const{setup:s}=n;if(s){const r=e.setupContext=s.length>1?$l(e):null;xt(e),Et();const i=Ve(s,e,0,[e.props,r]);if(At(),dt(),Cr(i)){if(i.then(dt,dt),t)return i.then(o=>{zs(e,o,t)}).catch(o=>{_n(o,e,0)});e.asyncDep=i}else zs(e,i,t)}else vi(e,t)}function zs(e,t,n){L(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:G(t)&&(e.setupState=Ur(t)),vi(e,n)}let Ks;function vi(e,t,n){const s=e.type;if(!e.render){if(!t&&Ks&&!s.render){const r=s.template||_s(e).template;if(r){const{isCustomElement:i,compilerOptions:o}=e.appContext.config,{delimiters:l,compilerOptions:a}=s,f=ae(ae({isCustomElement:i,delimiters:l},o),a);s.render=Ks(r,f)}}e.render=s.render||Ae}xt(e),Et(),sl(e),At(),dt()}function Il(e){return new Proxy(e.attrs,{get(t,n){return pe(e,"get","$attrs"),t[n]}})}function $l(e){const t=s=>{e.exposed=s||{}};let n;return{get attrs(){return n||(n=Il(e))},slots:e.slots,emit:e.emit,expose:t}}function Cn(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Ur(Br(e.exposed)),{get(t,n){if(n in t)return t[n];if(n in Mt)return Mt[n](e)},has(t,n){return n in t||n in Mt}}))}function Sl(e){return L(e)&&"__vccOpts"in e}const Le=(e,t)=>To(e,t,Wt);function Fl(e,t,n){const s=arguments.length;return s===2?G(t)&&!N(t)?Vn(t)?ie(e,null,[t]):ie(e,t):ie(e,null,t):(s>3?n=Array.prototype.slice.call(arguments,2):s===3&&Vn(n)&&(n=[n]),ie(e,t,n))}const Nl=Symbol(""),Ml=()=>nn(Nl),Dl="3.2.47",Ll="http://www.w3.org/2000/svg",lt=typeof document<"u"?document:null,Vs=lt&<.createElement("template"),Rl={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,s)=>{const r=t?lt.createElementNS(Ll,e):lt.createElement(e,n?{is:n}:void 0);return e==="select"&&s&&s.multiple!=null&&r.setAttribute("multiple",s.multiple),r},createText:e=>lt.createTextNode(e),createComment:e=>lt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>lt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,s,r,i){const o=n?n.previousSibling:t.lastChild;if(r&&(r===i||r.nextSibling))for(;t.insertBefore(r.cloneNode(!0),n),!(r===i||!(r=r.nextSibling)););else{Vs.innerHTML=s?`${e}`:e;const l=Vs.content;if(s){const a=l.firstChild;for(;a.firstChild;)l.appendChild(a.firstChild);l.removeChild(a)}t.insertBefore(l,n)}return[o?o.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}};function kl(e,t,n){const s=e._vtc;s&&(t=(t?[t,...s]:[...s]).join(" ")),t==null?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}function Bl(e,t,n){const s=e.style,r=oe(n);if(n&&!r){if(t&&!oe(t))for(const i in t)n[i]==null&&qn(s,i,"");for(const i in n)qn(s,i,n[i])}else{const i=s.display;r?t!==n&&(s.cssText=n):t&&e.removeAttribute("style"),"_vod"in e&&(s.display=i)}}const qs=/\s*!important$/;function qn(e,t,n){if(N(n))n.forEach(s=>qn(e,t,s));else if(n==null&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const s=jl(e,t);qs.test(n)?e.setProperty(Ot(s),n.replace(qs,""),"important"):e[s]=n}}const Js=["Webkit","Moz","ms"],Sn={};function jl(e,t){const n=Sn[t];if(n)return n;let s=bt(t);if(s!=="filter"&&s in e)return Sn[t]=s;s=Ar(s);for(let r=0;rFn||(ql.then(()=>Fn=0),Fn=Date.now());function Ql(e,t){const n=s=>{if(!s._vts)s._vts=Date.now();else if(s._vts<=n.attached)return;be(Yl(s,n.value),t,5,[s])};return n.value=e,n.attached=Jl(),n}function Yl(e,t){if(N(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(s=>r=>!r._stopped&&s&&s(r))}else return t}const Xs=/^on[a-z]/,Xl=(e,t,n,s,r=!1,i,o,l,a)=>{t==="class"?kl(e,s,r):t==="style"?Bl(e,n,s):dn(t)?Zn(t)||Kl(e,t,n,s,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):Zl(e,t,s,r))?Wl(e,t,s,i,o,l,a):(t==="true-value"?e._trueValue=s:t==="false-value"&&(e._falseValue=s),Hl(e,t,s,r))};function Zl(e,t,n,s){return s?!!(t==="innerHTML"||t==="textContent"||t in e&&Xs.test(t)&&L(n)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||Xs.test(t)&&oe(n)?!1:t in e}const We="transition",It="animation",ys=(e,{slots:t})=>Fl(ei,Gl(e),t);ys.displayName="Transition";const yi={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};ys.props=ae({},ei.props,yi);const nt=(e,t=[])=>{N(e)?e.forEach(n=>n(...t)):e&&e(...t)},Zs=e=>e?N(e)?e.some(t=>t.length>1):e.length>1:!1;function Gl(e){const t={};for(const I in e)I in yi||(t[I]=e[I]);if(e.css===!1)return t;const{name:n="v",type:s,duration:r,enterFromClass:i=`${n}-enter-from`,enterActiveClass:o=`${n}-enter-active`,enterToClass:l=`${n}-enter-to`,appearFromClass:a=i,appearActiveClass:f=o,appearToClass:d=l,leaveFromClass:p=`${n}-leave-from`,leaveActiveClass:m=`${n}-leave-active`,leaveToClass:w=`${n}-leave-to`}=e,A=ec(r),E=A&&A[0],H=A&&A[1],{onBeforeEnter:M,onEnter:z,onEnterCancelled:P,onLeave:k,onLeaveCancelled:K,onBeforeAppear:V=M,onAppear:J=z,onAppearCancelled:O=P}=t,R=(I,ee,ge)=>{st(I,ee?d:l),st(I,ee?f:o),ge&&ge()},j=(I,ee)=>{I._isLeaving=!1,st(I,p),st(I,w),st(I,m),ee&&ee()},Q=I=>(ee,ge)=>{const Tt=I?J:z,le=()=>R(ee,I,ge);nt(Tt,[ee,le]),Gs(()=>{st(ee,I?a:i),Ue(ee,I?d:l),Zs(Tt)||er(ee,s,E,le)})};return ae(t,{onBeforeEnter(I){nt(M,[I]),Ue(I,i),Ue(I,o)},onBeforeAppear(I){nt(V,[I]),Ue(I,a),Ue(I,f)},onEnter:Q(!1),onAppear:Q(!0),onLeave(I,ee){I._isLeaving=!0;const ge=()=>j(I,ee);Ue(I,p),sc(),Ue(I,m),Gs(()=>{I._isLeaving&&(st(I,p),Ue(I,w),Zs(k)||er(I,s,H,ge))}),nt(k,[I,ge])},onEnterCancelled(I){R(I,!1),nt(P,[I])},onAppearCancelled(I){R(I,!0),nt(O,[I])},onLeaveCancelled(I){j(I),nt(K,[I])}})}function ec(e){if(e==null)return null;if(G(e))return[Nn(e.enter),Nn(e.leave)];{const t=Nn(e);return[t,t]}}function Nn(e){return zi(e)}function Ue(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.add(n)),(e._vtc||(e._vtc=new Set)).add(t)}function st(e,t){t.split(/\s+/).forEach(s=>s&&e.classList.remove(s));const{_vtc:n}=e;n&&(n.delete(t),n.size||(e._vtc=void 0))}function Gs(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let tc=0;function er(e,t,n,s){const r=e._endId=++tc,i=()=>{r===e._endId&&s()};if(n)return setTimeout(i,n);const{type:o,timeout:l,propCount:a}=nc(e,t);if(!o)return s();const f=o+"end";let d=0;const p=()=>{e.removeEventListener(f,m),i()},m=w=>{w.target===e&&++d>=a&&p()};setTimeout(()=>{d(n[A]||"").split(", "),r=s(`${We}Delay`),i=s(`${We}Duration`),o=tr(r,i),l=s(`${It}Delay`),a=s(`${It}Duration`),f=tr(l,a);let d=null,p=0,m=0;t===We?o>0&&(d=We,p=o,m=i.length):t===It?f>0&&(d=It,p=f,m=a.length):(p=Math.max(o,f),d=p>0?o>f?We:It:null,m=d?d===We?i.length:a.length:0);const w=d===We&&/\b(transform|all)(,|$)/.test(s(`${We}Property`).toString());return{type:d,timeout:p,propCount:m,hasTransform:w}}function tr(e,t){for(;e.lengthnr(n)+nr(e[s])))}function nr(e){return Number(e.slice(0,-1).replace(",","."))*1e3}function sc(){return document.body.offsetHeight}const Je={beforeMount(e,{value:t},{transition:n}){e._vod=e.style.display==="none"?"":e.style.display,n&&t?n.beforeEnter(e):$t(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:s}){!t!=!n&&(s?t?(s.beforeEnter(e),$t(e,!0),s.enter(e)):s.leave(e,()=>{$t(e,!1)}):$t(e,t))},beforeUnmount(e,{value:t}){$t(e,t)}};function $t(e,t){e.style.display=t?e._vod:"none"}const rc=ae({patchProp:Xl},Rl);let sr;function ic(){return sr||(sr=gl(rc))}const oc=(...e)=>{const t=ic().createApp(...e),{mount:n}=t;return t.mount=s=>{const r=lc(s);if(!r)return;const i=t._component;!L(i)&&!i.render&&!i.template&&(i.template=r.innerHTML),r.innerHTML="";const o=n(r,!1,r instanceof SVGElement);return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),o},t};function lc(e){return oe(e)?document.querySelector(e):e}const cc="/1llest-waveform-vue/favicon.svg";var rr;const bi=typeof window<"u",ac=e=>typeof e=="function",uc=e=>typeof e=="string",fc=()=>{};bi&&((rr=window==null?void 0:window.navigator)!=null&&rr.userAgent)&&/iP(ad|hone|od)/.test(window.navigator.userAgent);function Ut(e){return typeof e=="function"?e():de(e)}function dc(e,t){function n(...s){return new Promise((r,i)=>{Promise.resolve(e(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(r).catch(i)})}return n}const wi=e=>e();function hc(e=wi){const t=ne(!0);function n(){t.value=!1}function s(){t.value=!0}const r=(...i)=>{t.value&&e(...i)};return{isActive:ls(t),pause:n,resume:s,eventFilter:r}}function pc(e){return e}function xi(e){return Tr()?(Ji(e),!0):!1}function gc(e){return typeof e=="function"?Le(e):ne(e)}function Ci(e,t=!0){_i()?Kt(e):t?e():fs(e)}function _c(e=!1,t={}){const{truthyValue:n=!0,falsyValue:s=!1}=t,r=ce(e),i=ne(e);function o(l){if(arguments.length)return i.value=l,i.value;{const a=Ut(n);return i.value=i.value===a?Ut(s):a,i.value}}return r?o:[i,o]}var ir=Object.getOwnPropertySymbols,mc=Object.prototype.hasOwnProperty,vc=Object.prototype.propertyIsEnumerable,yc=(e,t)=>{var n={};for(var s in e)mc.call(e,s)&&t.indexOf(s)<0&&(n[s]=e[s]);if(e!=null&&ir)for(var s of ir(e))t.indexOf(s)<0&&vc.call(e,s)&&(n[s]=e[s]);return n};function bc(e,t,n={}){const s=n,{eventFilter:r=wi}=s,i=yc(s,["eventFilter"]);return ft(e,dc(r,t),i)}var wc=Object.defineProperty,xc=Object.defineProperties,Cc=Object.getOwnPropertyDescriptors,fn=Object.getOwnPropertySymbols,Oi=Object.prototype.hasOwnProperty,Ei=Object.prototype.propertyIsEnumerable,or=(e,t,n)=>t in e?wc(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Oc=(e,t)=>{for(var n in t||(t={}))Oi.call(t,n)&&or(e,n,t[n]);if(fn)for(var n of fn(t))Ei.call(t,n)&&or(e,n,t[n]);return e},Ec=(e,t)=>xc(e,Cc(t)),Ac=(e,t)=>{var n={};for(var s in e)Oi.call(e,s)&&t.indexOf(s)<0&&(n[s]=e[s]);if(e!=null&&fn)for(var s of fn(e))t.indexOf(s)<0&&Ei.call(e,s)&&(n[s]=e[s]);return n};function Tc(e,t,n={}){const s=n,{eventFilter:r}=s,i=Ac(s,["eventFilter"]),{eventFilter:o,pause:l,resume:a,isActive:f}=hc(r);return{stop:bc(e,t,Ec(Oc({},i),{eventFilter:o})),pause:l,resume:a,isActive:f}}function Pc(e){var t;const n=Ut(e);return(t=n==null?void 0:n.$el)!=null?t:n}const Ct=bi?window:void 0;function lr(...e){let t,n,s,r;if(uc(e[0])||Array.isArray(e[0])?([n,s,r]=e,t=Ct):[t,n,s,r]=e,!t)return fc;Array.isArray(n)||(n=[n]),Array.isArray(s)||(s=[s]);const i=[],o=()=>{i.forEach(d=>d()),i.length=0},l=(d,p,m,w)=>(d.addEventListener(p,m,w),()=>d.removeEventListener(p,m,w)),a=ft(()=>[Pc(t),Ut(r)],([d,p])=>{o(),d&&i.push(...n.flatMap(m=>s.map(w=>l(d,m,w,p))))},{immediate:!0,flush:"post"}),f=()=>{a(),o()};return xi(f),f}function Ic(e,t=!1){const n=ne(),s=()=>n.value=!!e();return s(),Ci(s,t),n}function $c(e,t={}){const{window:n=Ct}=t,s=Ic(()=>n&&"matchMedia"in n&&typeof n.matchMedia=="function");let r;const i=ne(!1),o=()=>{r&&("removeEventListener"in r?r.removeEventListener("change",l):r.removeListener(l))},l=()=>{s.value&&(o(),r=n.matchMedia(gc(e).value),i.value=r.matches,"addEventListener"in r?r.addEventListener("change",l):r.addListener(l))};return yt(l),xi(()=>o()),i}const Jn=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Qn="__vueuse_ssr_handlers__";Jn[Qn]=Jn[Qn]||{};const Sc=Jn[Qn];function Ai(e,t){return Sc[e]||t}function Fc(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}var Nc=Object.defineProperty,cr=Object.getOwnPropertySymbols,Mc=Object.prototype.hasOwnProperty,Dc=Object.prototype.propertyIsEnumerable,ar=(e,t,n)=>t in e?Nc(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,ur=(e,t)=>{for(var n in t||(t={}))Mc.call(t,n)&&ar(e,n,t[n]);if(cr)for(var n of cr(t))Dc.call(t,n)&&ar(e,n,t[n]);return e};const Lc={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},fr="vueuse-storage";function Nt(e,t,n,s={}){var r;const{flush:i="pre",deep:o=!0,listenToStorageChanges:l=!0,writeDefaults:a=!0,mergeDefaults:f=!1,shallow:d,window:p=Ct,eventFilter:m,onError:w=O=>{console.error(O)}}=s,A=(d?Co:ne)(t);if(!n)try{n=Ai("getDefaultStorage",()=>{var O;return(O=Ct)==null?void 0:O.localStorage})()}catch(O){w(O)}if(!n)return A;const E=Ut(t),H=Fc(E),M=(r=s.serializer)!=null?r:Lc[H],{pause:z,resume:P}=Tc(A,()=>k(A.value),{flush:i,deep:o,eventFilter:m});return p&&l&&(lr(p,"storage",J),lr(p,fr,V)),J(),A;function k(O){try{if(O==null)n.removeItem(e);else{const R=M.write(O),j=n.getItem(e);j!==R&&(n.setItem(e,R),p&&p.dispatchEvent(new CustomEvent(fr,{detail:{key:e,oldValue:j,newValue:R,storageArea:n}})))}}catch(R){w(R)}}function K(O){const R=O?O.newValue:n.getItem(e);if(R==null)return a&&E!==null&&n.setItem(e,M.write(E)),E;if(!O&&f){const j=M.read(R);return ac(f)?f(j,E):H==="object"&&!Array.isArray(j)?ur(ur({},E),j):j}else return typeof R!="string"?R:M.read(R)}function V(O){J(O.detail)}function J(O){if(!(O&&O.storageArea!==n)){if(O&&O.key==null){A.value=E;return}if(!(O&&O.key!==e)){z();try{A.value=K(O)}catch(R){w(R)}finally{O?fs(P):P()}}}}}function Ti(e){return $c("(prefers-color-scheme: dark)",e)}var Rc=Object.defineProperty,dr=Object.getOwnPropertySymbols,kc=Object.prototype.hasOwnProperty,Bc=Object.prototype.propertyIsEnumerable,hr=(e,t,n)=>t in e?Rc(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,jc=(e,t)=>{for(var n in t||(t={}))kc.call(t,n)&&hr(e,n,t[n]);if(dr)for(var n of dr(t))Bc.call(t,n)&&hr(e,n,t[n]);return e};function Hc(e={}){const{selector:t="html",attribute:n="class",initialValue:s="auto",window:r=Ct,storage:i,storageKey:o="vueuse-color-scheme",listenToStorageChanges:l=!0,storageRef:a,emitAuto:f}=e,d=jc({auto:"",light:"light",dark:"dark"},e.modes||{}),p=Ti({window:r}),m=Le(()=>p.value?"dark":"light"),w=a||(o==null?ne(s):Nt(o,s,i,{window:r,listenToStorageChanges:l})),A=Le({get(){return w.value==="auto"&&!f?m.value:w.value},set(z){w.value=z}}),E=Ai("updateHTMLAttrs",(z,P,k)=>{const K=r==null?void 0:r.document.querySelector(z);if(K)if(P==="class"){const V=k.split(/\s/g);Object.values(d).flatMap(J=>(J||"").split(/\s/g)).filter(Boolean).forEach(J=>{V.includes(J)?K.classList.add(J):K.classList.remove(J)})}else K.setAttribute(P,k)});function H(z){var P;const k=z==="auto"?m.value:z;E(t,n,(P=d[k])!=null?P:k)}function M(z){e.onChanged?e.onChanged(z,H):H(z)}return ft(A,M,{flush:"post",immediate:!0}),f&&ft(m,()=>M(A.value),{flush:"post"}),Ci(()=>M(A.value)),A}var Wc=Object.defineProperty,Uc=Object.defineProperties,zc=Object.getOwnPropertyDescriptors,pr=Object.getOwnPropertySymbols,Kc=Object.prototype.hasOwnProperty,Vc=Object.prototype.propertyIsEnumerable,gr=(e,t,n)=>t in e?Wc(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,qc=(e,t)=>{for(var n in t||(t={}))Kc.call(t,n)&&gr(e,n,t[n]);if(pr)for(var n of pr(t))Vc.call(t,n)&&gr(e,n,t[n]);return e},Jc=(e,t)=>Uc(e,zc(t));function Pi(e={}){const{valueDark:t="dark",valueLight:n="",window:s=Ct}=e,r=Hc(Jc(qc({},e),{onChanged:(l,a)=>{var f;e.onChanged?(f=e.onChanged)==null||f.call(e,l==="dark"):a(l)},modes:{dark:t,light:n}})),i=Ti({window:s});return Le({get(){return r.value==="dark"},set(l){l===i.value?r.value="auto":r.value=l?"dark":"light"}})}var _r;(function(e){e.UP="UP",e.RIGHT="RIGHT",e.DOWN="DOWN",e.LEFT="LEFT",e.NONE="NONE"})(_r||(_r={}));var Qc=Object.defineProperty,mr=Object.getOwnPropertySymbols,Yc=Object.prototype.hasOwnProperty,Xc=Object.prototype.propertyIsEnumerable,vr=(e,t,n)=>t in e?Qc(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,Zc=(e,t)=>{for(var n in t||(t={}))Yc.call(t,n)&&vr(e,n,t[n]);if(mr)for(var n of mr(t))Xc.call(t,n)&&vr(e,n,t[n]);return e};const Gc={easeInSine:[.12,0,.39,0],easeOutSine:[.61,1,.88,1],easeInOutSine:[.37,0,.63,1],easeInQuad:[.11,0,.5,0],easeOutQuad:[.5,1,.89,1],easeInOutQuad:[.45,0,.55,1],easeInCubic:[.32,0,.67,0],easeOutCubic:[.33,1,.68,1],easeInOutCubic:[.65,0,.35,1],easeInQuart:[.5,0,.75,0],easeOutQuart:[.25,1,.5,1],easeInOutQuart:[.76,0,.24,1],easeInQuint:[.64,0,.78,0],easeOutQuint:[.22,1,.36,1],easeInOutQuint:[.83,0,.17,1],easeInExpo:[.7,0,.84,0],easeOutExpo:[.16,1,.3,1],easeInOutExpo:[.87,0,.13,1],easeInCirc:[.55,0,1,.45],easeOutCirc:[0,.55,.45,1],easeInOutCirc:[.85,0,.15,1],easeInBack:[.36,0,.66,-.56],easeOutBack:[.34,1.56,.64,1],easeInOutBack:[.68,-.6,.32,1.6]};Zc({linear:pc},Gc);let Me=(e=21)=>crypto.getRandomValues(new Uint8Array(e)).reduce((t,n)=>(n&=63,n<36?t+=n.toString(36):n<62?t+=(n-26).toString(36).toUpperCase():n>62?t+="-":t+="_",t),"");class ea{constructor(t,n,s){var r;this.canvas=t,this.props=n,this.filteredData=s,this.canvas=t,this.canvasCtx=(r=this.canvas)==null?void 0:r.getContext("2d"),this.props=n,this.filteredData=s}get _canvas(){return this.canvas}set _props(t){this.props=t}get _props(){return this.props}setupCanvas(){this.setCanvasBase(),this.translateCanvasCtx(),this.drawCanvasLines()}setCanvasBase(){this.canvas.width=this.canvas.offsetWidth,this.canvas.height=this.canvas.offsetHeight,this.canvas.style.opacity="1",this.canvasCtx.fillStyle="transparent",this.canvasCtx.fillRect(0,0,this.canvas.width,this.canvas.height)}translateCanvasCtx(){this.canvasCtx.translate(this.canvas.width/this.filteredData.length,this.canvas.height/2-this.canvas.height/2)}drawCanvasLines(){const{canvas:t,canvasCtx:n,filteredData:s}=this;s.forEach((r,i)=>{const o=t.width/s.length,l=o*i-o/2;n.moveTo(l,t.height/2-Math.abs(r)*t.height*.4),n.lineTo(l,t.height/2+Math.abs(r)*t.height*.4)})}drawMask(t){const{canvas:n,canvasCtx:s,props:r}=this;s.globalCompositeOperation="destination-atop",s.fillStyle=r.maskColor,s.fillRect(0,0,t,n.height)}drawWave(){const{canvasCtx:t,props:n}=this;t.lineWidth=n.lineWidth,t.lineCap=n.lineCap,t.strokeStyle=n.lineColor,t.stroke()}setWaveStyle(t){const{canvas:n,canvasCtx:s}=this;s.clearRect(0,0,n.width,n.height),this.drawMask(t),this.drawWave()}}class ta{constructor(t){this.props=t,this.audioCtx=new AudioContext}get _filteredData(){return this.filteredData}get _audioDuration(){if(!this.audioBuffer)throw new Error("can not get duration before audio inited");return this.audioBuffer.duration}async setupAudio(){await this.createAudioBuffer(),this.createFilterData(),this.createGainNode()}async fetchAudioFile(){try{const t=await fetch(this.props.url);this.arrayBuffer=await t.arrayBuffer()}catch(t){console.error(t)}}async createAudioBuffer(){this.audioBuffer=await this.audioCtx.decodeAudioData(this.arrayBuffer)}createGainNode(){this.gainNode=this.audioCtx.createGain(),this.gainNode.gain.setValueAtTime(0,this.audioCtx.currentTime)}createFilterData(){const t=this.props.samplingRate,n=[],s=this.audioBuffer.getChannelData(0);for(let r=0;rsetTimeout(t,e))}class sa extends ta{constructor(t){super(t),this.startAt=0,this.pauseAt=0,this.pickAt=0,this.playing=!1,this.FADE_DURATION=this.props.fade?.08:0}get _playing(){return this.playing}get _currentTime(){return this.pauseAt?this.pauseAt:this.startAt?this.audioCtx.currentTime-this.startAt:this.audioCtx.currentTime}play(){this.disconnectDestination(),this.createAudioBufferSourceNode(),this.connectDestination();const t=this.pickAt?this.pickAt:this.pauseAt;this.audioBufferSourceNode.start(0,t),this.startAt=this.audioCtx.currentTime-t,this.pauseAt=0,this.playing=!0,this.props.fade?(this.setGainValue(0),this.setGainLinearRamp(1)):this.setGainValue(1)}async pause(){const t=this.audioCtx.currentTime-this.startAt;this.props.fade&&(this.setGainLinearRamp(0),await na(this.FADE_DURATION*1e3)),this.disconnectDestination(),this.initializeState(),this.pauseAt=t+this.FADE_DURATION}pick(t){this.pickAt=t,this.playing&&(this.disconnectDestination(),this.play())}replay(){this.audioBufferSourceNode&&(this.disconnectDestination(),this.initializeState()),this.play()}finish(){this.pauseAt=0,this.disconnectDestination(),this.initializeState()}initializeState(){this.playing=!1,this.startAt=0,this.pauseAt=0,this.pickAt=0}createAudioBufferSourceNode(){this.audioBufferSourceNode||(this.audioBufferSourceNode=this.audioCtx.createBufferSource(),this.audioBufferSourceNode.buffer=this.audioBuffer)}connectDestination(){this.audioBufferSourceNode&&(this.audioBufferSourceNode.connect(this.gainNode),this.gainNode.connect(this.audioCtx.destination))}disconnectDestination(){this.audioBufferSourceNode&&(this.audioBufferSourceNode.disconnect(),this.audioBufferSourceNode.stop(),this.audioBufferSourceNode=null)}setGainValue(t){this.gainNode.gain.setValueAtTime(t,this.audioCtx.currentTime)}setGainLinearRamp(t){this.gainNode.gain.linearRampToValueAtTime(t,this.audioCtx.currentTime+this.FADE_DURATION)}}function yr(e){const t=Math.floor(e/60),n=Math.floor(e%60);return`${t}:${n<10?"0":""}${n}`}class ra{constructor(t,n){this.el=t,this.handler=n,this.timer=null,this.rended=!1}observe(){const t=n=>{if(this.rended)return this.unobserve();const s=n[0],r=260;s.intersectionRatio>0?this.timer=setTimeout(()=>{this.handler(),this.rended=!0},r):this.timer&&(clearTimeout(this.timer),this.timer=null)};this.intersectionObserver=new IntersectionObserver(t),this.intersectionObserver.observe(this.el)}unobserve(){this.intersectionObserver.unobserve(this.el)}}let Yn;function ia(e,t){Yn=new ra(e,t),Yn.observe()}function oa(){Yn.unobserve()}const la=ps({__name:"IllestWaveform",props:{url:null,lineWidth:{default:.5},lineCap:{default:"round"},lineColor:{default:"#5e5e5e"},samplingRate:{default:22050},cursorWidth:{default:2},cursorColor:{default:"#fff"},maskColor:{default:"#fff"},lazy:{type:[Boolean,null],default:!0},skeleton:{type:[Boolean,null],default:!0},skeletonColor:{default:"#232323"},interact:{type:[Boolean,null],default:!0},fade:{type:[Boolean,null],default:!0}},emits:["onInit","onFetched","onReady","onPlay","onPause","onFinish","onClick"],setup(e,{expose:t,emit:n}){const s=e,r=ne(!1),i=ne(null);Kt(async()=>{s.lazy?(ia(i.value,o),yt(async()=>{r.value&&await p()})):await p()}),gs(()=>{s.lazy&&oa(),f&&f.pause()});function o(){r.value=!0}const l=ne(null),a=ne(!1);let f,d;async function p(){a.value||(n("onInit",!0),await m(),await w(),a.value=!0,n("onReady",a.value))}async function m(){f=new sa(s),await f.fetchAudioFile(),n("onFetched",!0),await f.setupAudio(),O()}async function w(){d=new ea(l.value,s,f._filteredData),d.setupCanvas(),yt(()=>{d._props=s,d.setWaveStyle(H.value)})}const A=ne(0),E=ne(0),H=ne(0);function M(){f._playing&&(requestAnimationFrame(M),E.value=f._currentTime,H.value=E.value/f._audioDuration*d._canvas.width)}function z(Q){!a.value||!s.interact||(Q.layerX<=0?A.value=0:Q.layerX>=d._canvas.width?A.value=d._canvas.width:A.value=Q.layerX)}function P(){if(!a.value||!s.interact)return;H.value=A.value;const Q=A.value/d._canvas.width*f._audioDuration;f.pick(Q),E.value=Q,n("onClick",i),n("onFinish",!1)}function k(){a.value&&(f.play(),n("onPlay",!0),M())}function K(){f.replay(),n("onFinish",!1),n("onPlay",!0),M()}function V(){f.pause(),n("onPause",!1)}function J(){f.finish(),n("onPlay",!1),n("onFinish",!0)}function O(){yt(()=>{E.value<=f._audioDuration||J()})}function R(){return yr(E.value)}function j(){const Q=f._audioDuration;return yr(Q)}return t({play:k,pause:V,replay:K,getCurrentTime:R,getDuration:j}),(Q,I)=>(Fe(),Be("section",{id:"illest-waveform",ref_key:"__illestWaveformRef__",ref:i,style:ct(`${a.value&&e.interact?"cursor: pointer":""}`),onMousemove:z,onClick:P},[ie(ys,{name:"fade"},{default:Zr(()=>[qe(F("div",{id:"illest-waveform__skeleton",style:ct(`background-color: ${e.skeletonColor}`)},[qe(F("div",{id:"illest-waveform__skeleton__load",style:ct(`background-color: ${e.skeletonColor}`)},null,4),[[Je,!a.value]])],4),[[Je,s.skeleton&&!a.value]])]),_:1}),F("canvas",{id:"illest-waveform__view",ref_key:"waveRef",ref:l},null,512),qe(F("div",{id:"illest-waveform__cursor",style:ct(`width:${s.cursorWidth}px; transform: translateX(${A.value}px);background-color: ${s.cursorColor}; `)},null,4),[[Je,a.value&&s.interact]])],36))}});const Xe=(e,t)=>{const n=e.__vccOpts||e;for(const[s,r]of t)n[s]=r;return n},ca=Xe(la,[["__scopeId","data-v-d844bea3"]]);const aa={},ua={xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"currentColor",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round","stroke-linejoin":"round",class:"feather feather-play"},fa=F("polygon",{points:"5 3 19 12 5 21 5 3"},null,-1),da=[fa];function ha(e,t){return Fe(),Be("svg",ua,da)}const pa=Xe(aa,[["render",ha]]),ga={},_a={xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"currentColor",stroke:"currentColor","stroke-width":"1.5","stroke-linecap":"round","stroke-linejoin":"round",class:"feather feather-pause"},ma=F("rect",{x:"6",y:"4",width:"4",height:"16"},null,-1),va=F("rect",{x:"14",y:"4",width:"4",height:"16"},null,-1),ya=[ma,va];function ba(e,t){return Fe(),Be("svg",_a,ya)}const wa=Xe(ga,[["render",ba]]),xa={},Ca={xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"3","stroke-linecap":"round","stroke-linejoin":"round",class:"feather feather-refresh-cw"},Oa=F("polyline",{points:"23 4 23 10 17 10"},null,-1),Ea=F("polyline",{points:"1 20 1 14 7 14"},null,-1),Aa=F("path",{d:"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"},null,-1),Ta=[Oa,Ea,Aa];function Pa(e,t){return Fe(),Be("svg",Ca,Ta)}const Ia=Xe(xa,[["render",Pa]]),bs=e=>(Yr("data-v-112b9430"),e=e(),Xr(),e),$a={class:"flex flex-col mb-14"},Sa={class:"h-16 w-[700px] mx-auto"},Fa={class:"flex mt-2 items-end"},Na={class:"ml-auto"},Ma={class:"text-neutral-400"},Da={class:"ml-5"},La=bs(()=>F("div",{class:"ml-2"},"PLAY",-1)),Ra=bs(()=>F("div",null,"PAUSE",-1)),ka=bs(()=>F("div",null,"REPLAY",-1)),Ba=ps({__name:"Demo",props:["url","interact","skeleton","lazy","fade"],setup(e){const t=e,n=Pi(),s=zt({url:t.url,interact:Le(()=>t.interact),skeleton:Le(()=>t.skeleton),lazy:Le(()=>t.lazy),fade:Le(()=>t.fade)});yt(()=>{n.value?(s.lineColor="#5e5e5e",s.maskColor="#fff",s.skeletonColor="#232323",s.cursorColor="#fff"):(s.lineColor="#a1a1aa",s.maskColor="#000",s.skeletonColor="#f3f4f6",s.cursorColor="#000")});const r=ne(null);Kt(()=>{k()});const i=ne(!1),o=ne(!1),l=ne(!1),a=ne(!1),f=ne(!1),d=ne("0:00"),p=ne("0:00"),m=V=>{i.value=V},w=V=>{o.value=V},A=V=>{f.value=V,K()},E=V=>{a.value=V},H=V=>{},M=()=>{r.value.play()},z=()=>{r.value.replay()},P=()=>{r.value.pause()},k=()=>{yt(()=>{const V=r.value.getCurrentTime();d.value=V})},K=()=>{const V=r.value.getDuration();p.value=V};return(V,J)=>(Fe(),Be("section",$a,[F("div",Sa,[ie(ca,gi({ref_key:"waveformRef",ref:r},s,{onOnInit:m,onOnFetched:w,onOnReady:A,onOnPlay:J[0]||(J[0]=O=>l.value=O),onOnPause:J[1]||(J[1]=O=>l.value=O),onOnFinish:E,onOnClick:H}),null,16)]),F("div",Fa,[F("div",{class:Oe(["flex items-center w-28",`${o.value?"":"animate-pulse"}`])},[F("span",{class:Oe(["tag",`${o.value?"bg-green-600 dark:bg-green-400":"bg-gray-400"}`])},null,2),Lt(" "+St(o.value?"fetched":"fetching"),1)],2),F("div",{class:Oe(["flex items-center w-28",`${f.value?"":"animate-pulse"}`])},[F("span",{class:Oe(["tag",`${f.value?"bg-green-600 dark:bg-green-400":"bg-gray-400"}`])},null,2),Lt(" "+St(f.value?"ready":"rendering"),1)],2),F("div",Na,[F("span",Ma,St(d.value),1),Lt(" / "),F("strong",null,St(p.value),1)]),F("div",Da,[qe(F("button",{class:"text-[#3e6bff]",onClick:M},[ie(pa),La],512),[[Je,!l.value&&!a.value]]),qe(F("button",{class:"text-yellow-500",onClick:P},[ie(wa),Ra],512),[[Je,l.value&&!a.value]]),qe(F("button",{class:"text-green-500",onClick:z},[ie(Ia),ka],512),[[Je,a.value]])])])]))}});const ja=Xe(Ba,[["__scopeId","data-v-112b9430"]]),Ha={},Wa={xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round",class:"feather feather-sun"},Ua=Cl('',9),za=[Ua];function Ka(e,t){return Fe(),Be("svg",Wa,za)}const Va=Xe(Ha,[["render",Ka]]),qa={},Ja={xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round",class:"feather feather-moon"},Qa=F("path",{d:"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"},null,-1),Ya=[Qa];function Xa(e,t){return Fe(),Be("svg",Ja,Ya)}const Za=Xe(qa,[["render",Xa]]),Vt=e=>(Yr("data-v-a119e57b"),e=e(),Xr(),e),Ga={class:"flex flex-col items-center"},eu=Vt(()=>F("h1",{class:"flex flex-col items-center mt-2 mb-5"},[F("img",{src:cc,class:"w-32 h-32"}),F("span",{class:"ml-1 font-black text-[20px]"},[F("span",{class:"text-[24px]"},"1"),Lt("LLEST-WAVEFORM-PLUGIN ")])],-1)),tu={class:"mb-8 flex"},nu=Vt(()=>F("div",null,"interact",-1)),su=Vt(()=>F("div",null,"skeleton",-1)),ru=Vt(()=>F("div",null,"lazy",-1)),iu=Vt(()=>F("div",null,"fade",-1)),ou=ps({__name:"App",setup(e){const t=Pi(),n=_c(t),s=zt([{id:Me(),url:"/1llest-waveform-vue/audios/loop-1.mp3"},{id:Me(),url:"/1llest-waveform-vue/audios/loop-2.mp3"},{id:Me(),url:"/1llest-waveform-vue/audios/loop-3.mp3"},{id:Me(),url:"/1llest-waveform-vue/audios/loop-4.mp3"},{id:Me(),url:"/1llest-waveform-vue/audios/loop-5.mp3"},{id:Me(),url:"/1llest-waveform-vue/audios/loop-6.mp3"},{id:Me(),url:"/1llest-waveform-vue/audios/loop-7.mp3"},{id:Me(),url:"/1llest-waveform-vue/audios/loop-8.mp3"},{id:Me(),url:"/1llest-waveform-vue/audios/loop-9.mp3"}]),r=Nt("skeleton",!0),i=Nt("interact",!0),o=Nt("lazy",!0),l=Nt("fade",!0),a=()=>{i.value=!i.value},f=()=>{r.value=!r.value},d=()=>{o.value=!o.value},p=()=>{l.value=!l.value};return(m,w)=>(Fe(),Be("section",Ga,[eu,F("button",{class:"mb-5",onClick:w[0]||(w[0]=A=>de(n)())},[qe(ie(Va,{class:"w-5"},null,512),[[Je,!de(t)]]),qe(ie(Za,{class:"w-5"},null,512),[[Je,de(t)]]),F("div",null,St(de(t)?"dark":"light"),1)]),F("div",tu,[F("button",{onClick:w[1]||(w[1]=A=>a())},[F("span",{class:Oe({"bg-green-500":de(i)})},null,2),nu]),F("button",{onClick:w[2]||(w[2]=A=>f())},[F("span",{class:Oe({"bg-green-500":de(r)})},null,2),su]),F("button",{onClick:w[3]||(w[3]=A=>d())},[F("span",{class:Oe({"bg-green-500":de(o)})},null,2),ru]),F("button",{onClick:w[4]||(w[4]=A=>p())},[F("span",{class:Oe({"bg-green-500":de(l)})},null,2),iu])]),(Fe(!0),Be(xe,null,tl(s,A=>(Fe(),bl(ja,{key:A.id,url:A.url,interact:de(i),skeleton:de(r),lazy:de(o),fade:de(l)},null,8,["url","interact","skeleton","lazy","fade"]))),128))]))}});const lu=Xe(ou,[["__scopeId","data-v-a119e57b"]]);const cu=oc(lu);cu.mount("#app"); 2 | -------------------------------------------------------------------------------- /docs/assets/index-8d4966bc.css: -------------------------------------------------------------------------------- 1 | #illest-waveform[data-v-d844bea3]{position:relative;width:100%;height:100%;overflow:hidden}#illest-waveform>#illest-waveform__skeleton[data-v-d844bea3]{position:absolute;left:0;top:0;width:100%;height:100%;border-radius:7px;overflow:hidden;z-index:0}#illest-waveform>#illest-waveform__skeleton>#illest-waveform__skeleton__load[data-v-d844bea3]{background-image:linear-gradient(to right,rgba(0,0,0,0) 0%,rgba(0,0,0,.1) 50%,rgba(0,0,0,0) 100%);height:100%;width:30%;animation:skeleton-load-d844bea3 2.5s ease 0s infinite}#illest-waveform>#illest-waveform__view[data-v-d844bea3]{width:inherit;height:inherit;opacity:0}#illest-waveform>#illest-waveform__cursor[data-v-d844bea3]{position:absolute;height:inherit;left:0px;top:0px;opacity:0;transition:opacity .2s ease-in-out}#illest-waveform:hover #illest-waveform__cursor[data-v-d844bea3]{opacity:1}@keyframes skeleton-load-d844bea3{0%{transform:translate(-80%)}to{transform:translate(330%)}}.fade-enter-active[data-v-d844bea3],.fade-leave-active[data-v-d844bea3]{transition:all ease-in-out .4s}.fade-enter[data-v-d844bea3],.fade-leave-to[data-v-d844bea3]{opacity:0}#illest-waveform[data-v-6d613eae]{position:relative;width:100%;height:100%;overflow:hidden}#illest-waveform>#illest-waveform__skeleton[data-v-6d613eae]{position:absolute;left:0;top:0;width:100%;height:100%;border-radius:7px;overflow:hidden;z-index:0}#illest-waveform>#illest-waveform__skeleton>#illest-waveform__skeleton__load[data-v-6d613eae]{background-image:linear-gradient(to right,rgba(0,0,0,0) 0%,rgba(0,0,0,.1) 50%,rgba(0,0,0,0) 100%);height:100%;width:30%;animation:skeleton-load-6d613eae 2.5s ease 0s infinite}#illest-waveform>#illest-waveform__view[data-v-6d613eae]{width:inherit;height:inherit;opacity:0}#illest-waveform>#illest-waveform__cursor[data-v-6d613eae]{position:absolute;height:inherit;left:0px;top:0px;opacity:0;transition:opacity .2s ease-in-out}#illest-waveform:hover #illest-waveform__cursor[data-v-6d613eae]{opacity:1}@keyframes skeleton-load-6d613eae{0%{transform:translate(-80%)}to{transform:translate(330%)}}.fade-enter-active[data-v-6d613eae],.fade-leave-active[data-v-6d613eae]{transition:all ease-in-out .4s}.fade-enter[data-v-6d613eae],.fade-leave-to[data-v-6d613eae]{opacity:0}.tag[data-v-112b9430]{margin-right:.5rem;display:inline-flex;height:.5rem;width:.5rem;border-radius:9999px;opacity:.75}button[data-v-112b9430]{display:flex;align-items:center;border-radius:.125rem;--tw-bg-opacity: 1;background-color:rgb(229 229 229 / var(--tw-bg-opacity));padding:.25rem 1.25rem}.dark button[data-v-112b9430]{--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity))}button div[data-v-112b9430]{margin-left:.25rem;margin-bottom:-.125rem;font-weight:700}button[data-v-a119e57b]{margin-left:.75rem;margin-right:.75rem;display:flex;align-items:center}button[data-v-a119e57b]:hover{opacity:.8}button div[data-v-a119e57b]{margin-left:.25rem;margin-top:.25rem}button span[data-v-a119e57b]{height:1rem;width:1rem;border-radius:9999px;border-width:2px;--tw-border-opacity: 1;border-color:rgb(107 114 128 / var(--tw-border-opacity));transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.dark button span[data-v-a119e57b]{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.mx-auto{margin-left:auto;margin-right:auto}.-mb-0{margin-bottom:-0px}.mb-14{margin-bottom:3.5rem}.mb-5{margin-bottom:1.25rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-5{margin-left:1.25rem}.ml-auto{margin-left:auto}.mr-2{margin-right:.5rem}.mt-2{margin-top:.5rem}.flex{display:flex}.inline-flex{display:inline-flex}.h-16{height:4rem}.h-2{height:.5rem}.h-32{height:8rem}.h-4{height:1rem}.w-2{width:.5rem}.w-28{width:7rem}.w-32{width:8rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-\[700px\]{width:700px}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.flex-col{flex-direction:column}.items-end{align-items:flex-end}.items-center{align-items:center}.rounded-full{border-radius:9999px}.border-\[2px\]{border-width:2px}.border-gray-500{--tw-border-opacity: 1;border-color:rgb(107 114 128 / var(--tw-border-opacity))}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity))}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity))}.bg-neutral-200{--tw-bg-opacity: 1;background-color:rgb(229 229 229 / var(--tw-bg-opacity))}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.text-\[20px\]{font-size:20px}.text-\[24px\]{font-size:24px}.font-black{font-weight:900}.font-bold{font-weight:700}.text-\[\#3e6bff\]{--tw-text-opacity: 1;color:rgb(62 107 255 / var(--tw-text-opacity))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity))}.text-neutral-400{--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity))}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity))}.transition-\[background-color\]{transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}:root{--dark-main: #1e1e1e}html{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity));--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity));font-family:JetBrains Mono;transition:all ease-in .2s}.dark{background-color:var(--dark-main);--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}::-webkit-scrollbar{width:9px;height:9px}::-webkit-scrollbar-track{background:#3e3e3e}::-webkit-scrollbar-thumb{border-radius:10px;background-color:#525252}.hover\:opacity-80:hover{opacity:.8}.dark .dark\:border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}.dark .dark\:bg-green-400{--tw-bg-opacity: 1;background-color:rgb(74 222 128 / var(--tw-bg-opacity))}.dark .dark\:bg-neutral-700{--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity))} 2 | -------------------------------------------------------------------------------- /docs/audios/loop-1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/docs/audios/loop-1.mp3 -------------------------------------------------------------------------------- /docs/audios/loop-2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/docs/audios/loop-2.mp3 -------------------------------------------------------------------------------- /docs/audios/loop-3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/docs/audios/loop-3.mp3 -------------------------------------------------------------------------------- /docs/audios/loop-4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/docs/audios/loop-4.mp3 -------------------------------------------------------------------------------- /docs/audios/loop-5.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/docs/audios/loop-5.mp3 -------------------------------------------------------------------------------- /docs/audios/loop-6.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/docs/audios/loop-6.mp3 -------------------------------------------------------------------------------- /docs/audios/loop-7.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/docs/audios/loop-7.mp3 -------------------------------------------------------------------------------- /docs/audios/loop-8.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/docs/audios/loop-8.mp3 -------------------------------------------------------------------------------- /docs/audios/loop-9.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/docs/audios/loop-9.mp3 -------------------------------------------------------------------------------- /docs/cn-readme.md: -------------------------------------------------------------------------------- 1 |
2 |

3 | logo 4 |

5 | 6 |

7 | 8 | 1llest-waveform-vue 9 | 10 |

11 | 12 |

13 | 14 | 一款轻量可视的 Vue3 音频播放插件 15 | 16 |

17 | 18 | ## 描述 19 | 20 | 该组件是使用原生的 [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) 编写的,在生产环境中除了依赖于 Vue 3 之外没有使用任何其他依赖。当然,这意味着:如果您的目标浏览器不支持 Web Audio API 的功能,那么我的插件也将无法应用。您可以前往 [浏览器兼容性](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API#audiocontext_2) 页面查看 AudioContext 一行,以检查它是否与目标浏览器兼容。 21 | 22 | **样本** - [Live Demo](https://codeacme17.github.io/1llest-waveform-vue/) 23 | 24 | ## 开始 25 | 26 | ### 下载 27 | 28 | ```bash 29 | npm install 1llest-waveform-vue 30 | ``` 31 | 32 | ### 使用 33 | 34 | 全局组件使用 35 | 36 | ```javascript 37 | // main.ts 38 | import { createApp } from 'vue' 39 | import App from './App.vue' 40 | 41 | import IllestWaveform from '1llest-waveform-vue' 42 | import '1llest-waveform-vue/lib/style.css' 43 | 44 | const app = createApp(App) 45 | 46 | app.use(IllestWaveform) 47 | app.mount('#app') 48 | ``` 49 | 50 | 本地组件使用 51 | 52 | ```js 53 | // example.vue 54 | import { IllestWaveform } from '1llest-waveform-vue' 55 | import '1llest-waveform-vue/lib/style.css' 56 | ``` 57 | 58 | ### 组件使用方式 59 | 60 | ```vue 61 | 75 | 76 | 146 | ``` 147 | 148 | ## 文档 149 | 150 | ### 组件属性 151 | 152 | | 属性 | 描述 | 类型 | 默认值 | 153 | | :------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------- |:----------------|:----------| 154 | | url | 音频文件的 URL 地址 | `String` | - | 155 | | requestOptions | 传递给 `fetch` 请求函数的对象 | `RequestInit` | - | 156 | | lineWidth | 组成波形的每条垂直线的宽度 | `Number` | `0.5` | 157 | | lineCap | 组成波形的每条垂直线末端的样式 | `CanvasLineCap` | `round` | 158 | | lineColor | 组成波形的每条垂直线的颜色 | `String` | `#5e5e5e` | 159 | | samplingRate | 指示您的音频采样率。值越大,波形将呈现出更多的线条,并具有更高的准确性。但不建议将此值设置得太大,因为过大的值会降低渲染效率,推荐值介于 `8000 - 44100` 之间 | `Number` | `22050` | 160 | | cursorWidth | 指示光标的宽度 | `Number` | `2` | 161 | | cursorColor | 光标的颜色 | `String` | `#fff` | 162 | | maskColor | 波形遮罩层的颜色 | `String` | `#fff` | 163 | | lazy | 是否启用延迟加载模式,如果您想将多个波形显示为列表,此属性非常有用 | `Boolean` | `true` | 164 | | skeleton | 是否在波形加载期间启用骨架屏效果 | `Boolean` | `true` | 165 | | skeletonColor | 骨架屏的颜色 | `String` | `#232323` | 166 | | interact | 是否允许用户与波形进行交互 | `Boolean` | `true` | 167 | | fade | 在播放和暂停音频时实现淡入淡出效果,这可以为用户提供更流畅的听觉体验 | `Boolean` | `true` | 168 | 169 | ### 事件 170 | 171 | > 在使用以下事件时,您需要在前面添加 `on-` 前缀,例如 `@on-init="initHandler"` 172 | 173 | | 事件 | 描述 | 参数 | 174 | | :------ | :----------------------------------------------------- | :----------------- | 175 | | init | 波形开始初始化之前的钩子事件 | `Boolean` | 176 | | fetched | 接受音频文件后的钩子事件 | `Boolean` | 177 | | ready | 在波形完成所有初始化和页面渲染后触发的钩子事件 | `Boolean` | 178 | | play | 在播放开始时触发的事件 | `Boolean` | 179 | | pause | 在播放暂停时触发的事件 | `Boolean` | 180 | | finish | 在播放完成时触发的事件(播放完成是指整个音频播放完毕) | `Boolean` | 181 | | click | 在单击波形时触发的事件 | `Ref` | 182 | 183 | ### 方法 184 | 185 | > 您可以直接在波形组件实例上调用这些方法,例如 `waveform_ref.value.play()` 186 | 187 | | 方法 | 描述 | 返回值 | 188 | | :------------- | :-------------------------------------------------------------------------------------------------- | -------- | 189 | | play | 触发波形的播放方法,使其开始播放当前音频 | - | 190 | | pause | 触发波形的暂停方法,使其暂停播放 | - | 191 | | replay | 此方法可以重新开始播放当前音频 | - | 192 | | getCurrentTime | 此方法可以获取当前播放时间。如果您想实时获取当前播放时间,可以将其包装在 `watchEffect` 钩子中 | `string` | 193 | | getDuration | 此方法可以获取当前音频的持续时间,但是**此方法必须在 `ready` 钩子事件触发后才能获得正确的持续时间** | `string` | 194 | -------------------------------------------------------------------------------- /docs/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 1LLEST-WAVEFORM-PLUGIN 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | 2 | ```bash 3 | pnpm install 4 | pnpm dev 5 | ``` 6 | 7 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 1LLEST-WAVEFORM-PLUGIN 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build --emptyOutDir", 8 | "preview": "vite preview", 9 | "build-only": "vite build", 10 | "type-check": "vue-tsc --noEmit" 11 | }, 12 | "dependencies": { 13 | "@vueuse/core": "^9.13.0", 14 | "nanoid": "^3.3.6", 15 | "sass": "^1.60.0", 16 | "vue": "^3.2.45" 17 | }, 18 | "devDependencies": { 19 | "@types/node": "^18.11.12", 20 | "@vitejs/plugin-vue": "^4.0.0", 21 | "@vue/tsconfig": "^0.1.3", 22 | "autoprefixer": "^10.4.14", 23 | "npm-run-all": "^4.1.5", 24 | "postcss": "^8.4.21", 25 | "tailwindcss": "^3.2.7", 26 | "typescript": "~4.7.4", 27 | "vite": "^4.0.0", 28 | "vue-tsc": "^1.0.12" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /example/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /example/public/audios/loop-1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/example/public/audios/loop-1.mp3 -------------------------------------------------------------------------------- /example/public/audios/loop-2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/example/public/audios/loop-2.mp3 -------------------------------------------------------------------------------- /example/public/audios/loop-3.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/example/public/audios/loop-3.mp3 -------------------------------------------------------------------------------- /example/public/audios/loop-4.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/example/public/audios/loop-4.mp3 -------------------------------------------------------------------------------- /example/public/audios/loop-5.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/example/public/audios/loop-5.mp3 -------------------------------------------------------------------------------- /example/public/audios/loop-6.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/example/public/audios/loop-6.mp3 -------------------------------------------------------------------------------- /example/public/audios/loop-7.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/example/public/audios/loop-7.mp3 -------------------------------------------------------------------------------- /example/public/audios/loop-8.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/example/public/audios/loop-8.mp3 -------------------------------------------------------------------------------- /example/public/audios/loop-9.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeacme17/1llest-waveform-vue/94aa99bb2d1665d2f89365213af8b2033337b18e/example/public/audios/loop-9.mp3 -------------------------------------------------------------------------------- /example/public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /example/src/App.vue: -------------------------------------------------------------------------------- 1 | 77 | 78 | 127 | 128 | 141 | -------------------------------------------------------------------------------- /example/src/components/Demo.vue: -------------------------------------------------------------------------------- 1 | 104 | 105 | 178 | 179 | 192 | -------------------------------------------------------------------------------- /example/src/components/icons/Moon.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /example/src/components/icons/Pause.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /example/src/components/icons/Play.vue: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /example/src/components/icons/Replay.vue: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /example/src/components/icons/Sun.vue: -------------------------------------------------------------------------------- 1 | 25 | -------------------------------------------------------------------------------- /example/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /example/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from "vue" 2 | import App from "./App.vue" 3 | import "./style.css" 4 | 5 | const app = createApp(App) 6 | 7 | app.mount("#app") 8 | -------------------------------------------------------------------------------- /example/src/style.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | :root { 6 | --dark-main: #1e1e1e; 7 | } 8 | 9 | html { 10 | @apply text-slate-900 bg-white; 11 | font-family: "JetBrains Mono"; 12 | transition: all ease-in 0.2s 13 | } 14 | 15 | .dark { 16 | @apply text-white bg-[var(--dark-main)]; 17 | } 18 | 19 | 20 | ::-webkit-scrollbar { 21 | width: 9px; 22 | height: 9px; 23 | } 24 | 25 | ::-webkit-scrollbar-track { 26 | background: #3e3e3e; 27 | } 28 | 29 | ::-webkit-scrollbar-thumb { 30 | border-radius: 10px; 31 | background-color: #525252; 32 | } 33 | -------------------------------------------------------------------------------- /example/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | 3 | module.exports = { 4 | content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], 5 | darkMode: 'class', 6 | theme: { 7 | extend: {}, 8 | }, 9 | plugins: [], 10 | } 11 | -------------------------------------------------------------------------------- /example/tsconfig.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.node.json", 3 | "include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"], 4 | "compilerOptions": { 5 | "composite": true, 6 | "types": ["node"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.web.json", 3 | "include": [ 4 | "src/env.d.ts", 5 | "src/**/*", 6 | "src/**/*.vue" 7 | ], 8 | "compilerOptions": { 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": [ 12 | "./src/*" 13 | ] 14 | } 15 | }, 16 | "references": [ 17 | { 18 | "path": "./tsconfig.config.json" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /example/vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from "path" 2 | import vue from "@vitejs/plugin-vue" 3 | import { defineConfig } from "vite" 4 | import { resolve } from 'path' 5 | 6 | export default defineConfig({ 7 | plugins: [vue()], 8 | base: process.env.NODE_ENV === "development" ? "" : "/1llest-waveform-vue/", 9 | build: { 10 | outDir: resolve(__dirname, "../docs"), 11 | }, 12 | resolve: { 13 | alias: { 14 | "@": path.resolve(__dirname, "src"), 15 | }, 16 | }, 17 | }) 18 | -------------------------------------------------------------------------------- /lib/1llest-waveform-vue.mjs: -------------------------------------------------------------------------------- 1 | var E = Object.defineProperty; 2 | var L = (a, e, t) => e in a ? E(a, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[e] = t; 3 | var s = (a, e, t) => (L(a, typeof e != "symbol" ? e + "" : e, t), t); 4 | import { defineComponent as M, ref as h, onMounted as G, watchEffect as g, onUnmounted as $, openBlock as V, createElementBlock as P, normalizeStyle as y, createVNode as U, Transition as X, withCtx as H, withDirectives as w, createElementVNode as m, vShow as A } from "vue"; 5 | class q { 6 | constructor(e, t, i) { 7 | s(this, "canvasCtx"); 8 | var n; 9 | this.canvas = e, this.props = t, this.filteredData = i, this.canvas = e, this.canvasCtx = (n = this.canvas) == null ? void 0 : n.getContext("2d"), this.props = t, this.filteredData = i; 10 | } 11 | get _canvas() { 12 | return this.canvas; 13 | } 14 | set _props(e) { 15 | this.props = e; 16 | } 17 | get _props() { 18 | return this.props; 19 | } 20 | setupCanvas() { 21 | this.setCanvasBase(), this.translateCanvasCtx(), this.drawCanvasLines(); 22 | } 23 | setCanvasBase() { 24 | this.canvas.width = this.canvas.offsetWidth, this.canvas.height = this.canvas.offsetHeight, this.canvas.style.opacity = "1", this.canvasCtx.fillStyle = "transparent", this.canvasCtx.fillRect(0, 0, this.canvas.width, this.canvas.height); 25 | } 26 | translateCanvasCtx() { 27 | this.canvasCtx.translate( 28 | this.canvas.width / this.filteredData.length, 29 | this.canvas.height / 2 - this.canvas.height / 2 30 | ); 31 | } 32 | drawCanvasLines() { 33 | const { canvas: e, canvasCtx: t, filteredData: i } = this; 34 | i.forEach((n, c) => { 35 | const d = e.width / i.length, v = d * c - d / 2; 36 | t.moveTo( 37 | v, 38 | e.height / 2 - Math.abs(n) * e.height * 0.4 39 | ), t.lineTo( 40 | v, 41 | e.height / 2 + Math.abs(n) * e.height * 0.4 42 | ); 43 | }); 44 | } 45 | drawMask(e) { 46 | const { canvas: t, canvasCtx: i, props: n } = this; 47 | i.globalCompositeOperation = "destination-atop", i.fillStyle = n.maskColor, i.fillRect(0, 0, e, t.height); 48 | } 49 | drawWave() { 50 | const { canvasCtx: e, props: t } = this; 51 | e.lineWidth = t.lineWidth, e.lineCap = t.lineCap, e.strokeStyle = t.lineColor, e.stroke(); 52 | } 53 | setWaveStyle(e) { 54 | const { canvas: t, canvasCtx: i } = this; 55 | i.clearRect(0, 0, t.width, t.height), this.drawMask(e), this.drawWave(); 56 | } 57 | } 58 | class Y { 59 | constructor(e) { 60 | s(this, "props"); 61 | s(this, "audioCtx"); 62 | s(this, "audioBuffer"); 63 | s(this, "gainNode"); 64 | s(this, "filteredData"); 65 | s(this, "arrayBuffer"); 66 | this.props = e, this.audioCtx = new AudioContext(); 67 | } 68 | get _filteredData() { 69 | return this.filteredData; 70 | } 71 | get _audioDuration() { 72 | if (!this.audioBuffer) 73 | throw new Error("can not get duration before audio inited"); 74 | return this.audioBuffer.duration; 75 | } 76 | async setupAudio() { 77 | await this.createAudioBuffer(), this.createFilterData(), this.createGainNode(); 78 | } 79 | async fetchAudioFile() { 80 | try { 81 | const e = await fetch(this.props.url, this.props.requestOptions); 82 | this.arrayBuffer = await e.arrayBuffer(); 83 | } catch (e) { 84 | console.error(e); 85 | } 86 | } 87 | async createAudioBuffer() { 88 | this.audioBuffer = await this.audioCtx.decodeAudioData(this.arrayBuffer); 89 | } 90 | createGainNode() { 91 | this.gainNode = this.audioCtx.createGain(), this.gainNode.gain.setValueAtTime(0, this.audioCtx.currentTime); 92 | } 93 | createFilterData() { 94 | const e = this.props.samplingRate, t = [], i = this.audioBuffer.getChannelData(0); 95 | for (let n = 0; n < e; n++) { 96 | const c = Math.floor(i.length / e), d = i[n * c]; 97 | t.push(d); 98 | } 99 | this.filteredData = t; 100 | } 101 | } 102 | function j(a) { 103 | return new Promise((e) => setTimeout(e, a)); 104 | } 105 | class J extends Y { 106 | constructor(t) { 107 | super(t); 108 | s(this, "startAt"); 109 | s(this, "pauseAt"); 110 | s(this, "pickAt"); 111 | s(this, "playing"); 112 | s(this, "audioBufferSourceNode"); 113 | s(this, "FADE_DURATION"); 114 | this.startAt = 0, this.pauseAt = 0, this.pickAt = 0, this.playing = !1, this.FADE_DURATION = this.props.fade ? 0.08 : 0; 115 | } 116 | get _playing() { 117 | return this.playing; 118 | } 119 | get _currentTime() { 120 | return this.pauseAt ? this.pauseAt : this.startAt ? this.audioCtx.currentTime - this.startAt : this.audioCtx.currentTime; 121 | } 122 | play() { 123 | this.disconnectDestination(), this.createAudioBufferSourceNode(), this.connectDestination(); 124 | const t = this.pickAt ? this.pickAt : this.pauseAt; 125 | this.audioBufferSourceNode.start(0, t), this.startAt = this.audioCtx.currentTime - t, this.pauseAt = 0, this.playing = !0, this.props.fade ? (this.setGainValue(0), this.setGainLinearRamp(1)) : this.setGainValue(1); 126 | } 127 | async pause() { 128 | const t = this.audioCtx.currentTime - this.startAt; 129 | this.props.fade && (this.setGainLinearRamp(0), await j(this.FADE_DURATION * 1e3)), this.disconnectDestination(), this.initializeState(), this.pauseAt = t + this.FADE_DURATION; 130 | } 131 | pick(t) { 132 | this.pickAt = t, this.playing && (this.disconnectDestination(), this.play()); 133 | } 134 | replay() { 135 | this.audioBufferSourceNode && (this.disconnectDestination(), this.initializeState()), this.play(); 136 | } 137 | finish() { 138 | this.pauseAt = 0, this.disconnectDestination(), this.initializeState(); 139 | } 140 | initializeState() { 141 | this.playing = !1, this.startAt = 0, this.pauseAt = 0, this.pickAt = 0; 142 | } 143 | createAudioBufferSourceNode() { 144 | this.audioBufferSourceNode || (this.audioBufferSourceNode = this.audioCtx.createBufferSource(), this.audioBufferSourceNode.buffer = this.audioBuffer); 145 | } 146 | connectDestination() { 147 | !this.audioBufferSourceNode || (this.audioBufferSourceNode.connect(this.gainNode), this.gainNode.connect(this.audioCtx.destination)); 148 | } 149 | disconnectDestination() { 150 | !this.audioBufferSourceNode || (this.audioBufferSourceNode.disconnect(), this.audioBufferSourceNode.stop(), this.audioBufferSourceNode = null); 151 | } 152 | setGainValue(t) { 153 | this.gainNode.gain.setValueAtTime(t, this.audioCtx.currentTime); 154 | } 155 | setGainLinearRamp(t) { 156 | this.gainNode.gain.linearRampToValueAtTime( 157 | t, 158 | this.audioCtx.currentTime + this.FADE_DURATION 159 | ); 160 | } 161 | } 162 | function x(a) { 163 | const e = Math.floor(a / 60), t = Math.floor(a % 60); 164 | return `${e}:${t < 10 ? "0" : ""}${t}`; 165 | } 166 | class K { 167 | constructor(e, t) { 168 | s(this, "el"); 169 | s(this, "handler"); 170 | s(this, "intersectionObserver"); 171 | s(this, "timer"); 172 | s(this, "rended"); 173 | this.el = e, this.handler = t, this.timer = null, this.rended = !1; 174 | } 175 | observe() { 176 | const e = (t) => { 177 | if (this.rended) 178 | return this.unobserve(); 179 | const i = t[0], n = 260; 180 | i.intersectionRatio > 0 ? this.timer = setTimeout(() => { 181 | this.handler(), this.rended = !0; 182 | }, n) : this.timer && (clearTimeout(this.timer), this.timer = null); 183 | }; 184 | this.intersectionObserver = new IntersectionObserver(e), this.intersectionObserver.observe(this.el); 185 | } 186 | unobserve() { 187 | this.intersectionObserver.unobserve(this.el); 188 | } 189 | } 190 | let D; 191 | function Q(a, e) { 192 | D = new K(a, e), D.observe(); 193 | } 194 | function Z() { 195 | D.unobserve(); 196 | } 197 | const tt = /* @__PURE__ */ M({ 198 | __name: "IllestWaveform", 199 | props: { 200 | url: null, 201 | requestOptions: { default: () => ({}) }, 202 | lineWidth: { default: 0.5 }, 203 | lineCap: { default: "round" }, 204 | lineColor: { default: "#5e5e5e" }, 205 | samplingRate: { default: 22050 }, 206 | cursorWidth: { default: 2 }, 207 | cursorColor: { default: "#fff" }, 208 | maskColor: { default: "#fff" }, 209 | lazy: { type: [Boolean, null], default: !0 }, 210 | skeleton: { type: [Boolean, null], default: !0 }, 211 | skeletonColor: { default: "#232323" }, 212 | interact: { type: [Boolean, null], default: !0 }, 213 | fade: { type: [Boolean, null], default: !0 } 214 | }, 215 | emits: [ 216 | "onInit", 217 | "onFetched", 218 | "onReady", 219 | "onPlay", 220 | "onPause", 221 | "onFinish", 222 | "onClick" 223 | ], 224 | setup(a, { expose: e, emit: t }) { 225 | const i = a, n = h(!1), c = h(null); 226 | G(async () => { 227 | i.lazy ? (Q(c.value, d), g(async () => { 228 | n.value && await k(); 229 | })) : await k(); 230 | }), $(() => { 231 | i.lazy && Z(), o && o.pause(); 232 | }); 233 | function d() { 234 | n.value = !0; 235 | } 236 | const v = h(null), r = h(!1); 237 | let o, l; 238 | async function k() { 239 | r.value || (t("onInit", !0), await B(), await T(), r.value = !0, t("onReady", r.value)); 240 | } 241 | async function B() { 242 | o = new J(i), await o.fetchAudioFile(), t("onFetched", !0), await o.setupAudio(), I(); 243 | } 244 | async function T() { 245 | l = new q( 246 | v.value, 247 | i, 248 | o._filteredData 249 | ), l.setupCanvas(), g(() => { 250 | l._props = i, l.setWaveStyle(_.value); 251 | }); 252 | } 253 | const f = h(0), p = h(0), _ = h(0); 254 | function C() { 255 | !o._playing || (requestAnimationFrame(C), p.value = o._currentTime, _.value = p.value / o._audioDuration * l._canvas.width); 256 | } 257 | function N(u) { 258 | !r.value || !i.interact || (u.layerX <= 0 ? f.value = 0 : u.layerX >= l._canvas.width ? f.value = l._canvas.width : f.value = u.layerX); 259 | } 260 | function S() { 261 | if (!r.value || !i.interact) 262 | return; 263 | _.value = f.value; 264 | const u = f.value / l._canvas.width * o._audioDuration; 265 | o.pick(u), p.value = u, t("onClick", c), t("onFinish", !1); 266 | } 267 | function b() { 268 | !r.value || (o.play(), t("onPlay", !0), C()); 269 | } 270 | function W() { 271 | o.replay(), t("onFinish", !1), t("onPlay", !0), C(); 272 | } 273 | function R() { 274 | o.pause(), t("onPause", !1); 275 | } 276 | function F() { 277 | o.finish(), t("onPlay", !1), t("onFinish", !0); 278 | } 279 | function I() { 280 | g(() => { 281 | p.value <= o._audioDuration || F(); 282 | }); 283 | } 284 | function O() { 285 | return x(p.value); 286 | } 287 | function z() { 288 | const u = o._audioDuration; 289 | return x(u); 290 | } 291 | return e({ 292 | play: b, 293 | pause: R, 294 | replay: W, 295 | getCurrentTime: O, 296 | getDuration: z 297 | }), (u, at) => (V(), P("section", { 298 | id: "illest-waveform", 299 | ref_key: "__illestWaveformRef__", 300 | ref: c, 301 | style: y(`${r.value && a.interact ? "cursor: pointer" : ""}`), 302 | onMousemove: N, 303 | onClick: S 304 | }, [ 305 | U(X, { name: "fade" }, { 306 | default: H(() => [ 307 | w(m("div", { 308 | id: "illest-waveform__skeleton", 309 | style: y(`background-color: ${a.skeletonColor}`) 310 | }, [ 311 | w(m("div", { 312 | id: "illest-waveform__skeleton__load", 313 | style: y(`background-color: ${a.skeletonColor}`) 314 | }, null, 4), [ 315 | [A, !r.value] 316 | ]) 317 | ], 4), [ 318 | [A, i.skeleton && !r.value] 319 | ]) 320 | ]), 321 | _: 1 322 | }), 323 | m("canvas", { 324 | id: "illest-waveform__view", 325 | ref_key: "waveRef", 326 | ref: v 327 | }, null, 512), 328 | w(m("div", { 329 | id: "illest-waveform__cursor", 330 | style: y(`width:${i.cursorWidth}px; transform: translateX(${f.value}px);background-color: ${i.cursorColor}; `) 331 | }, null, 4), [ 332 | [A, r.value && i.interact] 333 | ]) 334 | ], 36)); 335 | } 336 | }); 337 | const et = (a, e) => { 338 | const t = a.__vccOpts || a; 339 | for (const [i, n] of e) 340 | t[i] = n; 341 | return t; 342 | }, it = /* @__PURE__ */ et(tt, [["__scopeId", "data-v-59075811"]]), ot = { 343 | install: (a) => { 344 | a.component("IllestWaveform", it); 345 | } 346 | }; 347 | export { 348 | it as IllestWaveform, 349 | ot as default 350 | }; 351 | -------------------------------------------------------------------------------- /lib/1llest-waveform-vue.umd.js: -------------------------------------------------------------------------------- 1 | (function(l,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(l=typeof globalThis<"u"?globalThis:l||self,e(l["1llest-waveform-vue"]={},l.Vue))})(this,function(l,e){"use strict";var P=Object.defineProperty;var U=(l,e,f)=>e in l?P(l,e,{enumerable:!0,configurable:!0,writable:!0,value:f}):l[e]=f;var n=(l,e,f)=>(U(l,typeof e!="symbol"?e+"":e,f),f);class f{constructor(i,t,a){n(this,"canvasCtx");var o;this.canvas=i,this.props=t,this.filteredData=a,this.canvas=i,this.canvasCtx=(o=this.canvas)==null?void 0:o.getContext("2d"),this.props=t,this.filteredData=a}get _canvas(){return this.canvas}set _props(i){this.props=i}get _props(){return this.props}setupCanvas(){this.setCanvasBase(),this.translateCanvasCtx(),this.drawCanvasLines()}setCanvasBase(){this.canvas.width=this.canvas.offsetWidth,this.canvas.height=this.canvas.offsetHeight,this.canvas.style.opacity="1",this.canvasCtx.fillStyle="transparent",this.canvasCtx.fillRect(0,0,this.canvas.width,this.canvas.height)}translateCanvasCtx(){this.canvasCtx.translate(this.canvas.width/this.filteredData.length,this.canvas.height/2-this.canvas.height/2)}drawCanvasLines(){const{canvas:i,canvasCtx:t,filteredData:a}=this;a.forEach((o,d)=>{const p=i.width/a.length,y=p*d-p/2;t.moveTo(y,i.height/2-Math.abs(o)*i.height*.4),t.lineTo(y,i.height/2+Math.abs(o)*i.height*.4)})}drawMask(i){const{canvas:t,canvasCtx:a,props:o}=this;a.globalCompositeOperation="destination-atop",a.fillStyle=o.maskColor,a.fillRect(0,0,i,t.height)}drawWave(){const{canvasCtx:i,props:t}=this;i.lineWidth=t.lineWidth,i.lineCap=t.lineCap,i.strokeStyle=t.lineColor,i.stroke()}setWaveStyle(i){const{canvas:t,canvasCtx:a}=this;a.clearRect(0,0,t.width,t.height),this.drawMask(i),this.drawWave()}}class x{constructor(i){n(this,"props");n(this,"audioCtx");n(this,"audioBuffer");n(this,"gainNode");n(this,"filteredData");n(this,"arrayBuffer");this.props=i,this.audioCtx=new AudioContext}get _filteredData(){return this.filteredData}get _audioDuration(){if(!this.audioBuffer)throw new Error("can not get duration before audio inited");return this.audioBuffer.duration}async setupAudio(){await this.createAudioBuffer(),this.createFilterData(),this.createGainNode()}async fetchAudioFile(){try{const i=await fetch(this.props.url,this.props.requestOptions);this.arrayBuffer=await i.arrayBuffer()}catch(i){console.error(i)}}async createAudioBuffer(){this.audioBuffer=await this.audioCtx.decodeAudioData(this.arrayBuffer)}createGainNode(){this.gainNode=this.audioCtx.createGain(),this.gainNode.gain.setValueAtTime(0,this.audioCtx.currentTime)}createFilterData(){const i=this.props.samplingRate,t=[],a=this.audioBuffer.getChannelData(0);for(let o=0;osetTimeout(i,s))}class B extends x{constructor(t){super(t);n(this,"startAt");n(this,"pauseAt");n(this,"pickAt");n(this,"playing");n(this,"audioBufferSourceNode");n(this,"FADE_DURATION");this.startAt=0,this.pauseAt=0,this.pickAt=0,this.playing=!1,this.FADE_DURATION=this.props.fade?.08:0}get _playing(){return this.playing}get _currentTime(){return this.pauseAt?this.pauseAt:this.startAt?this.audioCtx.currentTime-this.startAt:this.audioCtx.currentTime}play(){this.disconnectDestination(),this.createAudioBufferSourceNode(),this.connectDestination();const t=this.pickAt?this.pickAt:this.pauseAt;this.audioBufferSourceNode.start(0,t),this.startAt=this.audioCtx.currentTime-t,this.pauseAt=0,this.playing=!0,this.props.fade?(this.setGainValue(0),this.setGainLinearRamp(1)):this.setGainValue(1)}async pause(){const t=this.audioCtx.currentTime-this.startAt;this.props.fade&&(this.setGainLinearRamp(0),await k(this.FADE_DURATION*1e3)),this.disconnectDestination(),this.initializeState(),this.pauseAt=t+this.FADE_DURATION}pick(t){this.pickAt=t,this.playing&&(this.disconnectDestination(),this.play())}replay(){this.audioBufferSourceNode&&(this.disconnectDestination(),this.initializeState()),this.play()}finish(){this.pauseAt=0,this.disconnectDestination(),this.initializeState()}initializeState(){this.playing=!1,this.startAt=0,this.pauseAt=0,this.pickAt=0}createAudioBufferSourceNode(){this.audioBufferSourceNode||(this.audioBufferSourceNode=this.audioCtx.createBufferSource(),this.audioBufferSourceNode.buffer=this.audioBuffer)}connectDestination(){!this.audioBufferSourceNode||(this.audioBufferSourceNode.connect(this.gainNode),this.gainNode.connect(this.audioCtx.destination))}disconnectDestination(){!this.audioBufferSourceNode||(this.audioBufferSourceNode.disconnect(),this.audioBufferSourceNode.stop(),this.audioBufferSourceNode=null)}setGainValue(t){this.gainNode.gain.setValueAtTime(t,this.audioCtx.currentTime)}setGainLinearRamp(t){this.gainNode.gain.linearRampToValueAtTime(t,this.audioCtx.currentTime+this.FADE_DURATION)}}function g(s){const i=Math.floor(s/60),t=Math.floor(s%60);return`${i}:${t<10?"0":""}${t}`}class S{constructor(i,t){n(this,"el");n(this,"handler");n(this,"intersectionObserver");n(this,"timer");n(this,"rended");this.el=i,this.handler=t,this.timer=null,this.rended=!1}observe(){const i=t=>{if(this.rended)return this.unobserve();const a=t[0],o=260;a.intersectionRatio>0?this.timer=setTimeout(()=>{this.handler(),this.rended=!0},o):this.timer&&(clearTimeout(this.timer),this.timer=null)};this.intersectionObserver=new IntersectionObserver(i),this.intersectionObserver.observe(this.el)}unobserve(){this.intersectionObserver.unobserve(this.el)}}let _;function T(s,i){_=new S(s,i),_.observe()}function N(){_.unobserve()}const b=e.defineComponent({__name:"IllestWaveform",props:{url:null,requestOptions:{default:()=>({})},lineWidth:{default:.5},lineCap:{default:"round"},lineColor:{default:"#5e5e5e"},samplingRate:{default:22050},cursorWidth:{default:2},cursorColor:{default:"#fff"},maskColor:{default:"#fff"},lazy:{type:[Boolean,null],default:!0},skeleton:{type:[Boolean,null],default:!0},skeletonColor:{default:"#232323"},interact:{type:[Boolean,null],default:!0},fade:{type:[Boolean,null],default:!0}},emits:["onInit","onFetched","onReady","onPlay","onPause","onFinish","onClick"],setup(s,{expose:i,emit:t}){const a=s,o=e.ref(!1),d=e.ref(null);e.onMounted(async()=>{a.lazy?(T(d.value,p),e.watchEffect(async()=>{o.value&&await D()})):await D()}),e.onUnmounted(()=>{a.lazy&&N(),r&&r.pause()});function p(){o.value=!0}const y=e.ref(null),u=e.ref(!1);let r,h;async function D(){u.value||(t("onInit",!0),await R(),await E(),u.value=!0,t("onReady",u.value))}async function R(){r=new B(a),await r.fetchAudioFile(),t("onFetched",!0),await r.setupAudio(),V()}async function E(){h=new f(y.value,a,r._filteredData),h.setupCanvas(),e.watchEffect(()=>{h._props=a,h.setWaveStyle(w.value)})}const v=e.ref(0),m=e.ref(0),w=e.ref(0);function C(){!r._playing||(requestAnimationFrame(C),m.value=r._currentTime,w.value=m.value/r._audioDuration*h._canvas.width)}function F(c){!u.value||!a.interact||(c.layerX<=0?v.value=0:c.layerX>=h._canvas.width?v.value=h._canvas.width:v.value=c.layerX)}function z(){if(!u.value||!a.interact)return;w.value=v.value;const c=v.value/h._canvas.width*r._audioDuration;r.pick(c),m.value=c,t("onClick",d),t("onFinish",!1)}function I(){!u.value||(r.play(),t("onPlay",!0),C())}function O(){r.replay(),t("onFinish",!1),t("onPlay",!0),C()}function M(){r.pause(),t("onPause",!1)}function L(){r.finish(),t("onPlay",!1),t("onFinish",!0)}function V(){e.watchEffect(()=>{m.value<=r._audioDuration||L()})}function G(){return g(m.value)}function $(){const c=r._audioDuration;return g(c)}return i({play:I,pause:M,replay:O,getCurrentTime:G,getDuration:$}),(c,H)=>(e.openBlock(),e.createElementBlock("section",{id:"illest-waveform",ref_key:"__illestWaveformRef__",ref:d,style:e.normalizeStyle(`${u.value&&s.interact?"cursor: pointer":""}`),onMousemove:F,onClick:z},[e.createVNode(e.Transition,{name:"fade"},{default:e.withCtx(()=>[e.withDirectives(e.createElementVNode("div",{id:"illest-waveform__skeleton",style:e.normalizeStyle(`background-color: ${s.skeletonColor}`)},[e.withDirectives(e.createElementVNode("div",{id:"illest-waveform__skeleton__load",style:e.normalizeStyle(`background-color: ${s.skeletonColor}`)},null,4),[[e.vShow,!u.value]])],4),[[e.vShow,a.skeleton&&!u.value]])]),_:1}),e.createElementVNode("canvas",{id:"illest-waveform__view",ref_key:"waveRef",ref:y},null,512),e.withDirectives(e.createElementVNode("div",{id:"illest-waveform__cursor",style:e.normalizeStyle(`width:${a.cursorWidth}px; transform: translateX(${v.value}px);background-color: ${a.cursorColor}; `)},null,4),[[e.vShow,u.value&&a.interact]])],36))}}),X="",A=((s,i)=>{const t=s.__vccOpts||s;for(const[a,o]of i)t[a]=o;return t})(b,[["__scopeId","data-v-59075811"]]),W={install:s=>{s.component("IllestWaveform",A)}};l.IllestWaveform=A,l.default=W,Object.defineProperties(l,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}); 2 | -------------------------------------------------------------------------------- /lib/style.css: -------------------------------------------------------------------------------- 1 | #illest-waveform[data-v-59075811]{position:relative;width:100%;height:100%;overflow:hidden}#illest-waveform>#illest-waveform__skeleton[data-v-59075811]{position:absolute;left:0;top:0;width:100%;height:100%;border-radius:7px;overflow:hidden;z-index:0}#illest-waveform>#illest-waveform__skeleton>#illest-waveform__skeleton__load[data-v-59075811]{background-image:linear-gradient(to right,rgba(0,0,0,0) 0%,rgba(0,0,0,.1) 50%,rgba(0,0,0,0) 100%);height:100%;width:30%;animation:skeleton-load-59075811 2.5s ease 0s infinite}#illest-waveform>#illest-waveform__view[data-v-59075811]{width:inherit;height:inherit;opacity:0}#illest-waveform>#illest-waveform__cursor[data-v-59075811]{position:absolute;height:inherit;left:0px;top:0px;opacity:0;transition:opacity .2s ease-in-out}#illest-waveform:hover #illest-waveform__cursor[data-v-59075811]{opacity:1}@keyframes skeleton-load-59075811{0%{transform:translate(-80%)}to{transform:translate(330%)}}.fade-enter-active[data-v-59075811],.fade-leave-active[data-v-59075811]{transition:all ease-in-out .4s}.fade-enter[data-v-59075811],.fade-leave-to[data-v-59075811]{opacity:0} 2 | -------------------------------------------------------------------------------- /lib/types/components/IllestWaveform.vue.d.ts: -------------------------------------------------------------------------------- 1 | import type { Ref } from 'vue'; 2 | declare const _default: import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{ 3 | url: string; 4 | requestOptions?: RequestInit | undefined; 5 | lineWidth?: number | undefined; 6 | lineCap?: ("butt" | "round" | "square") | undefined; 7 | lineColor?: string | undefined; 8 | samplingRate?: number | undefined; 9 | cursorWidth?: number | undefined; 10 | cursorColor?: string | undefined; 11 | maskColor?: string | undefined; 12 | lazy?: boolean | Ref | undefined; 13 | skeleton?: boolean | Ref | undefined; 14 | skeletonColor?: string | undefined; 15 | interact?: boolean | Ref | undefined; 16 | fade?: boolean | Ref | undefined; 17 | }>, { 18 | requestOptions: () => {}; 19 | lineWidth: number; 20 | lineCap: string; 21 | lineColor: string; 22 | cursorWidth: number; 23 | cursorColor: string; 24 | samplingRate: number; 25 | maskColor: string; 26 | lazy: boolean; 27 | skeleton: boolean; 28 | skeletonColor: string; 29 | interact: boolean; 30 | fade: boolean; 31 | }>, { 32 | play: () => void; 33 | pause: () => void; 34 | replay: () => void; 35 | getCurrentTime: () => string; 36 | getDuration: () => string; 37 | }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("onInit" | "onFetched" | "onReady" | "onPlay" | "onPause" | "onFinish" | "onClick")[], "onInit" | "onFetched" | "onReady" | "onPlay" | "onPause" | "onFinish" | "onClick", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly | undefined; 48 | skeleton?: boolean | Ref | undefined; 49 | skeletonColor?: string | undefined; 50 | interact?: boolean | Ref | undefined; 51 | fade?: boolean | Ref | undefined; 52 | }>, { 53 | requestOptions: () => {}; 54 | lineWidth: number; 55 | lineCap: string; 56 | lineColor: string; 57 | cursorWidth: number; 58 | cursorColor: string; 59 | samplingRate: number; 60 | maskColor: string; 61 | lazy: boolean; 62 | skeleton: boolean; 63 | skeletonColor: string; 64 | interact: boolean; 65 | fade: boolean; 66 | }>>> & { 67 | onOnInit?: ((...args: any[]) => any) | undefined; 68 | onOnFetched?: ((...args: any[]) => any) | undefined; 69 | onOnReady?: ((...args: any[]) => any) | undefined; 70 | onOnPlay?: ((...args: any[]) => any) | undefined; 71 | onOnPause?: ((...args: any[]) => any) | undefined; 72 | onOnFinish?: ((...args: any[]) => any) | undefined; 73 | onOnClick?: ((...args: any[]) => any) | undefined; 74 | }, { 75 | requestOptions: RequestInit; 76 | lineWidth: number; 77 | lineCap: "butt" | "round" | "square"; 78 | lineColor: string; 79 | samplingRate: number; 80 | cursorWidth: number; 81 | cursorColor: string; 82 | maskColor: string; 83 | lazy: boolean | Ref; 84 | skeleton: boolean | Ref; 85 | skeletonColor: string; 86 | interact: boolean | Ref; 87 | fade: boolean | Ref; 88 | }>; 89 | export default _default; 90 | type __VLS_NonUndefinedable = T extends undefined ? never : T; 91 | type __VLS_TypePropsToRuntimeProps = { 92 | [K in keyof T]-?: {} extends Pick ? { 93 | type: import('vue').PropType<__VLS_NonUndefinedable>; 94 | } : { 95 | type: import('vue').PropType; 96 | required: true; 97 | }; 98 | }; 99 | type __VLS_WithDefaults = { 100 | [K in keyof Pick]: K extends keyof D ? P[K] & { 101 | default: D[K]; 102 | } : P[K]; 103 | }; 104 | -------------------------------------------------------------------------------- /lib/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { App } from 'vue'; 2 | import IllestWaveform from './components/IllestWaveform.vue'; 3 | declare const _default: { 4 | install: (app: App) => void; 5 | }; 6 | export default _default; 7 | export type { IllestWaveformProps } from './types/waveform'; 8 | export { IllestWaveform }; 9 | -------------------------------------------------------------------------------- /lib/types/modules/Audio.d.ts: -------------------------------------------------------------------------------- 1 | import type { IllestWaveformProps } from '../types/waveform'; 2 | /** 3 | * The WebAudio class creates a playable audio instance 4 | * and converts the audio into an array for visual processing 5 | * 6 | */ 7 | export default class WebAudio { 8 | protected props: IllestWaveformProps; 9 | protected audioCtx: AudioContext; 10 | protected audioBuffer: AudioBuffer; 11 | protected gainNode: GainNode; 12 | private filteredData; 13 | private arrayBuffer; 14 | constructor(props: IllestWaveformProps); 15 | get _filteredData(): number[]; 16 | get _audioDuration(): number; 17 | setupAudio(): Promise; 18 | fetchAudioFile(): Promise; 19 | private createAudioBuffer; 20 | private createGainNode; 21 | private createFilterData; 22 | } 23 | -------------------------------------------------------------------------------- /lib/types/modules/AudioController.d.ts: -------------------------------------------------------------------------------- 1 | import WebAudio from './Audio'; 2 | import type { IllestWaveformProps } from '../types/waveform'; 3 | /** 4 | * WebAudioController Class creates construct, 5 | * which can control the web audio behaviors. 6 | * It's inheirts from WebAudio Class. 7 | * 8 | */ 9 | export default class WebAudioController extends WebAudio { 10 | private startAt; 11 | private pauseAt; 12 | private pickAt; 13 | private playing; 14 | private audioBufferSourceNode; 15 | private FADE_DURATION; 16 | constructor(props: IllestWaveformProps); 17 | get _playing(): boolean; 18 | get _currentTime(): number; 19 | play(): void; 20 | pause(): Promise; 21 | pick(pickedTime: number): void; 22 | replay(): void; 23 | finish(): void; 24 | private initializeState; 25 | private createAudioBufferSourceNode; 26 | private connectDestination; 27 | private disconnectDestination; 28 | private setGainValue; 29 | private setGainLinearRamp; 30 | } 31 | -------------------------------------------------------------------------------- /lib/types/modules/Wave.d.ts: -------------------------------------------------------------------------------- 1 | import type { IllestWaveformProps } from '../types/waveform'; 2 | export default class Wave { 3 | private canvas; 4 | private props; 5 | private filteredData; 6 | private canvasCtx; 7 | constructor(canvas: HTMLCanvasElement, props: IllestWaveformProps, filteredData: number[]); 8 | get _canvas(): HTMLCanvasElement; 9 | set _props(props: IllestWaveformProps); 10 | get _props(): IllestWaveformProps; 11 | setupCanvas(): void; 12 | private setCanvasBase; 13 | private translateCanvasCtx; 14 | private drawCanvasLines; 15 | private drawMask; 16 | private drawWave; 17 | setWaveStyle(maskWidth: number): void; 18 | } 19 | -------------------------------------------------------------------------------- /lib/types/modules/index.d.ts: -------------------------------------------------------------------------------- 1 | import Wave from './Wave'; 2 | import WebAudio from './Audio'; 3 | import AudioController from './AudioController'; 4 | export { Wave, WebAudio, AudioController }; 5 | -------------------------------------------------------------------------------- /lib/types/types/waveform.d.ts: -------------------------------------------------------------------------------- 1 | import type { Ref } from 'vue'; 2 | type CanvasLineCap = 'butt' | 'round' | 'square'; 3 | export type IllestWaveformProps = { 4 | url: string; 5 | requestOptions?: RequestInit; 6 | lineWidth?: number; 7 | lineCap?: CanvasLineCap; 8 | lineColor?: string; 9 | samplingRate?: number; 10 | cursorWidth?: number; 11 | cursorColor?: string; 12 | maskColor?: string; 13 | lazy?: boolean | Ref; 14 | skeleton?: boolean | Ref; 15 | skeletonColor?: string; 16 | interact?: boolean | Ref; 17 | fade?: boolean | Ref; 18 | }; 19 | export {}; 20 | -------------------------------------------------------------------------------- /lib/types/utils/format-time.d.ts: -------------------------------------------------------------------------------- 1 | declare function formatSecond(second: number): string; 2 | export { formatSecond }; 3 | -------------------------------------------------------------------------------- /lib/types/utils/lazy-load.d.ts: -------------------------------------------------------------------------------- 1 | declare function lazyLoader(el: HTMLElement, handler: () => void): void; 2 | declare function unobserve(): void; 3 | export { lazyLoader, unobserve }; 4 | -------------------------------------------------------------------------------- /lib/types/utils/time-counter.d.ts: -------------------------------------------------------------------------------- 1 | declare function timeCounter(targetTime: number): Promise; 2 | export default timeCounter; 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1llest-waveform-vue", 3 | "version": "1.2.0", 4 | "author": "leyoonafr", 5 | "license": "MIT", 6 | "description": "A lightweight and controllable audio visualization vue3 plugin", 7 | "keywords": [ 8 | "vue3 plugin", 9 | "waveform", 10 | "audio visualization", 11 | "web audio api", 12 | "vue plugin" 13 | ], 14 | "homepage": "https://github.com/codeacme17/1llest-waveform-vue#readme", 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/codeacme17/1llest-waveform-vue" 18 | }, 19 | "files": [ 20 | "lib" 21 | ], 22 | "main": "./lib/1llest-waveform-vue.umd.js", 23 | "module": "./lib/1llest-waveform-vue.mjs", 24 | "types": "./lib/types/index.d.ts", 25 | "exports": { 26 | ".": { 27 | "import": "./lib/1llest-waveform-vue.mjs", 28 | "require": "./lib/1llest-waveform-vue.umd.js" 29 | }, 30 | "./lib/style.css": "./lib/style.css" 31 | }, 32 | "scripts": { 33 | "build": "vite build --outDir lib", 34 | "build:types": "vue-tsc --declaration --emitDeclarationOnly --declarationDir ./lib/types", 35 | "lint": "eslint src --ext .ts,.vue", 36 | "prepare": "husky install" 37 | }, 38 | "dependencies": { 39 | "vue": "^3.2.41" 40 | }, 41 | "devDependencies": { 42 | "@babel/core": "^7.20.12", 43 | "@types/node": "^18.11.10", 44 | "@typescript-eslint/eslint-plugin": "^5.56.0", 45 | "@typescript-eslint/parser": "^5.56.0", 46 | "@vitejs/plugin-vue": "^3.2.0", 47 | "@vue/eslint-config-standard": "^8.0.1", 48 | "@vue/eslint-config-typescript": "^11.0.2", 49 | "eslint": "^8.36.0", 50 | "eslint-config-prettier": "^8.8.0", 51 | "eslint-plugin-prettier": "^4.2.1", 52 | "eslint-plugin-vue": "^9.10.0", 53 | "husky": "^8.0.3", 54 | "prettier": "^2.8.3", 55 | "typescript": "^4.6.4", 56 | "vite": "^3.2.0", 57 | "vue-tsc": "^1.2.0" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/components/IllestWaveform.vue: -------------------------------------------------------------------------------- 1 | 198 | 199 | 230 | 231 | 302 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { App } from 'vue' 2 | import IllestWaveform from './components/IllestWaveform.vue' 3 | 4 | export default { 5 | install: (app: App) => { 6 | app.component('IllestWaveform', IllestWaveform) 7 | }, 8 | } 9 | 10 | export type { IllestWaveformProps } from './types/waveform' 11 | export { IllestWaveform } 12 | -------------------------------------------------------------------------------- /src/modules/Audio.ts: -------------------------------------------------------------------------------- 1 | import type { IllestWaveformProps } from '../types/waveform' 2 | 3 | /** 4 | * The WebAudio class creates a playable audio instance 5 | * and converts the audio into an array for visual processing 6 | * 7 | */ 8 | 9 | export default class WebAudio { 10 | protected props: IllestWaveformProps 11 | protected audioCtx: AudioContext 12 | protected audioBuffer!: AudioBuffer 13 | protected gainNode!: GainNode 14 | private filteredData!: number[] 15 | private arrayBuffer!: ArrayBuffer 16 | 17 | constructor(props: IllestWaveformProps) { 18 | this.props = props 19 | this.audioCtx = new AudioContext() 20 | } 21 | 22 | get _filteredData(): number[] { 23 | return this.filteredData 24 | } 25 | 26 | get _audioDuration(): number { 27 | if (!this.audioBuffer) 28 | throw new Error('can not get duration before audio inited') 29 | return this.audioBuffer.duration 30 | } 31 | 32 | public async setupAudio(): Promise { 33 | await this.createAudioBuffer() 34 | this.createFilterData() 35 | this.createGainNode() 36 | } 37 | 38 | public async fetchAudioFile(): Promise { 39 | try { 40 | const response = await fetch(this.props.url, this.props.requestOptions) 41 | this.arrayBuffer = await response.arrayBuffer() 42 | } catch (error) { 43 | console.error(error) 44 | } 45 | } 46 | 47 | private async createAudioBuffer(): Promise { 48 | this.audioBuffer = await this.audioCtx.decodeAudioData(this.arrayBuffer) 49 | } 50 | 51 | private createGainNode(): void { 52 | this.gainNode = this.audioCtx.createGain() 53 | this.gainNode.gain.setValueAtTime(0, this.audioCtx.currentTime) 54 | } 55 | 56 | private createFilterData(): void { 57 | const samplingRate: number = this.props.samplingRate as number 58 | const filteredData: number[] = [] 59 | 60 | const rawDataList: Float32Array = this.audioBuffer.getChannelData(0) 61 | 62 | for (let index = 0; index < samplingRate; index++) { 63 | const blockSize = Math.floor(rawDataList.length / samplingRate) 64 | const temp = rawDataList[index * blockSize] 65 | filteredData.push(temp) 66 | } 67 | 68 | this.filteredData = filteredData 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/modules/AudioController.ts: -------------------------------------------------------------------------------- 1 | import WebAudio from './Audio' 2 | import type { IllestWaveformProps } from '../types/waveform' 3 | import timeCounter from '../utils/time-counter' 4 | 5 | /** 6 | * WebAudioController Class creates construct, 7 | * which can control the web audio behaviors. 8 | * It's inheirts from WebAudio Class. 9 | * 10 | */ 11 | 12 | export default class WebAudioController extends WebAudio { 13 | private startAt: number 14 | private pauseAt: number 15 | private pickAt: number 16 | private playing: boolean 17 | private audioBufferSourceNode!: AudioBufferSourceNode | null 18 | private FADE_DURATION: number 19 | 20 | constructor(props: IllestWaveformProps) { 21 | super(props) 22 | this.startAt = 0 23 | this.pauseAt = 0 24 | this.pickAt = 0 25 | this.playing = false 26 | this.FADE_DURATION = this.props.fade ? 0.08 : 0 27 | } 28 | 29 | get _playing(): boolean { 30 | return this.playing 31 | } 32 | 33 | get _currentTime(): number { 34 | if (this.pauseAt) return this.pauseAt 35 | if (this.startAt) return this.audioCtx.currentTime - this.startAt 36 | return this.audioCtx.currentTime 37 | } 38 | 39 | public play(): void { 40 | this.disconnectDestination() 41 | this.createAudioBufferSourceNode() 42 | this.connectDestination() 43 | 44 | const offset = this.pickAt ? this.pickAt : this.pauseAt 45 | this.audioBufferSourceNode!.start(0, offset) 46 | this.startAt = this.audioCtx.currentTime - offset 47 | this.pauseAt = 0 48 | this.playing = true 49 | 50 | if (!this.props.fade) { 51 | this.setGainValue(1) 52 | } else { 53 | this.setGainValue(0) 54 | this.setGainLinearRamp(1) 55 | } 56 | } 57 | 58 | public async pause(): Promise { 59 | const elapsed = this.audioCtx.currentTime - this.startAt 60 | 61 | if (this.props.fade) { 62 | this.setGainLinearRamp(0) 63 | await timeCounter(this.FADE_DURATION * 1000) 64 | } 65 | 66 | this.disconnectDestination() 67 | this.initializeState() 68 | this.pauseAt = elapsed + this.FADE_DURATION 69 | } 70 | 71 | public pick(pickedTime: number): void { 72 | this.pickAt = pickedTime 73 | if (!this.playing) return 74 | this.disconnectDestination() 75 | this.play() 76 | } 77 | 78 | public replay(): void { 79 | if (this.audioBufferSourceNode) { 80 | this.disconnectDestination() 81 | this.initializeState() 82 | } 83 | this.play() 84 | } 85 | 86 | public finish(): void { 87 | this.pauseAt = 0 88 | this.disconnectDestination() 89 | this.initializeState() 90 | } 91 | 92 | private initializeState() { 93 | this.playing = false 94 | this.startAt = 0 95 | this.pauseAt = 0 96 | this.pickAt = 0 97 | } 98 | 99 | private createAudioBufferSourceNode(): void { 100 | if (this.audioBufferSourceNode) return 101 | this.audioBufferSourceNode = this.audioCtx.createBufferSource() 102 | this.audioBufferSourceNode.buffer = this.audioBuffer 103 | } 104 | 105 | private connectDestination(): void { 106 | if (!this.audioBufferSourceNode) return 107 | this.audioBufferSourceNode.connect(this.gainNode) 108 | this.gainNode.connect(this.audioCtx.destination) 109 | } 110 | 111 | private disconnectDestination(): void { 112 | if (!this.audioBufferSourceNode) return 113 | this.audioBufferSourceNode.disconnect() 114 | this.audioBufferSourceNode.stop() 115 | this.audioBufferSourceNode = null 116 | } 117 | 118 | private setGainValue(v: number): void { 119 | this.gainNode.gain.setValueAtTime(v, this.audioCtx.currentTime) 120 | } 121 | 122 | private setGainLinearRamp(v: number): void { 123 | this.gainNode.gain.linearRampToValueAtTime( 124 | v, 125 | this.audioCtx.currentTime + this.FADE_DURATION! 126 | ) 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/modules/Wave.ts: -------------------------------------------------------------------------------- 1 | import type { IllestWaveformProps } from '../types/waveform' 2 | 3 | export default class Wave { 4 | private canvasCtx!: CanvasRenderingContext2D 5 | 6 | constructor( 7 | private canvas: HTMLCanvasElement, 8 | private props: IllestWaveformProps, 9 | private filteredData: number[] 10 | ) { 11 | this.canvas = canvas 12 | this.canvasCtx = this.canvas?.getContext('2d') as CanvasRenderingContext2D 13 | this.props = props 14 | this.filteredData = filteredData 15 | } 16 | 17 | get _canvas(): HTMLCanvasElement { 18 | return this.canvas 19 | } 20 | 21 | set _props(props: IllestWaveformProps) { 22 | this.props = props 23 | } 24 | 25 | get _props(): IllestWaveformProps { 26 | return this.props 27 | } 28 | 29 | public setupCanvas(): void { 30 | this.setCanvasBase() 31 | this.translateCanvasCtx() 32 | this.drawCanvasLines() 33 | } 34 | 35 | private setCanvasBase(): void { 36 | this.canvas.width = this.canvas.offsetWidth 37 | this.canvas.height = this.canvas.offsetHeight 38 | this.canvas.style.opacity = '1' 39 | this.canvasCtx.fillStyle = 'transparent' 40 | this.canvasCtx.fillRect(0, 0, this.canvas.width, this.canvas.height) 41 | } 42 | 43 | private translateCanvasCtx(): void { 44 | this.canvasCtx.translate( 45 | this.canvas.width / this.filteredData.length, 46 | this.canvas.height / 2 - this.canvas.height / 2 47 | ) 48 | } 49 | 50 | private drawCanvasLines(): void { 51 | const { canvas, canvasCtx, filteredData } = this 52 | filteredData.forEach((item: number, index: number) => { 53 | const singleLineWidth = canvas.width / filteredData.length 54 | const x = singleLineWidth * index - singleLineWidth / 2 55 | canvasCtx.moveTo( 56 | x, 57 | canvas.height / 2 - Math.abs(item) * canvas.height * 0.4 58 | ) 59 | canvasCtx.lineTo( 60 | x, 61 | canvas.height / 2 + Math.abs(item) * canvas.height * 0.4 62 | ) 63 | }) 64 | } 65 | 66 | private drawMask(maskWidth: number): void { 67 | const { canvas, canvasCtx, props } = this 68 | canvasCtx.globalCompositeOperation = 'destination-atop' 69 | canvasCtx.fillStyle = props.maskColor as string 70 | canvasCtx.fillRect(0, 0, maskWidth, canvas.height) 71 | } 72 | 73 | private drawWave(): void { 74 | const { canvasCtx, props } = this 75 | canvasCtx.lineWidth = props.lineWidth as number 76 | canvasCtx.lineCap = props.lineCap as CanvasLineCap 77 | canvasCtx.strokeStyle = props.lineColor as string 78 | canvasCtx.stroke() 79 | } 80 | 81 | public setWaveStyle(maskWidth: number): void { 82 | const { canvas, canvasCtx } = this 83 | canvasCtx.clearRect(0, 0, canvas.width, canvas.height) 84 | this.drawMask(maskWidth) 85 | this.drawWave() 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/modules/index.ts: -------------------------------------------------------------------------------- 1 | import Wave from './Wave' 2 | import WebAudio from './Audio' 3 | import AudioController from './AudioController' 4 | 5 | export { Wave, WebAudio, AudioController } 6 | -------------------------------------------------------------------------------- /src/types/waveform.ts: -------------------------------------------------------------------------------- 1 | import type { Ref } from 'vue' 2 | 3 | type CanvasLineCap = 'butt' | 'round' | 'square' 4 | 5 | export type IllestWaveformProps = { 6 | url: string 7 | requestOptions?: RequestInit 8 | lineWidth?: number 9 | lineCap?: CanvasLineCap 10 | lineColor?: string 11 | samplingRate?: number 12 | cursorWidth?: number 13 | cursorColor?: string 14 | maskColor?: string 15 | lazy?: boolean | Ref 16 | skeleton?: boolean | Ref 17 | skeletonColor?: string 18 | interact?: boolean | Ref 19 | fade?: boolean | Ref 20 | } 21 | -------------------------------------------------------------------------------- /src/utils/format-time.ts: -------------------------------------------------------------------------------- 1 | function formatSecond(second: number): string { 2 | const minutes = Math.floor(second / 60) 3 | const seconds = Math.floor(second % 60) 4 | const formattedTime = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}` 5 | return formattedTime 6 | } 7 | 8 | export { formatSecond } 9 | -------------------------------------------------------------------------------- /src/utils/lazy-load.ts: -------------------------------------------------------------------------------- 1 | class LazyLoader { 2 | private el: HTMLElement 3 | private handler: () => void 4 | private intersectionObserver!: IntersectionObserver 5 | private timer: NodeJS.Timeout | null 6 | private rended: boolean 7 | 8 | constructor(el: HTMLElement, handler: () => void) { 9 | this.el = el 10 | this.handler = handler 11 | this.timer = null 12 | this.rended = false 13 | } 14 | 15 | public observe() { 16 | const cb = (entries: IntersectionObserverEntry[]) => { 17 | if (this.rended) return this.unobserve() 18 | 19 | const entry = entries[0] 20 | const DELAY_TIME = 260 21 | 22 | if (entry.intersectionRatio > 0) { 23 | this.timer = setTimeout(() => { 24 | this.handler() 25 | this.rended = true 26 | }, DELAY_TIME) 27 | } else { 28 | if (this.timer) { 29 | clearTimeout(this.timer) 30 | this.timer = null 31 | } 32 | } 33 | } 34 | 35 | this.intersectionObserver = new IntersectionObserver(cb) 36 | this.intersectionObserver.observe(this.el) 37 | } 38 | 39 | public unobserve() { 40 | this.intersectionObserver.unobserve(this.el) 41 | } 42 | } 43 | 44 | let lz: LazyLoader 45 | 46 | function lazyLoader(el: HTMLElement, handler: () => void) { 47 | lz = new LazyLoader(el, handler) 48 | lz.observe() 49 | } 50 | 51 | function unobserve() { 52 | lz.unobserve() 53 | } 54 | 55 | export { lazyLoader, unobserve } 56 | -------------------------------------------------------------------------------- /src/utils/time-counter.ts: -------------------------------------------------------------------------------- 1 | function timeCounter(targetTime: number): Promise { 2 | return new Promise((resolve) => setTimeout(resolve, targetTime)) 3 | } 4 | 5 | export default timeCounter 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "outDir": "dist", 5 | "useDefineForClassFields": true, 6 | "module": "ESNext", 7 | "moduleResolution": "Node", 8 | "strict": true, 9 | "jsx": "preserve", 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "esModuleInterop": true, 13 | "lib": [ 14 | "ESNext", 15 | "DOM", 16 | ], 17 | "skipLibCheck": true, 18 | "allowJs": true, 19 | "baseUrl": ".", 20 | "paths": { 21 | "@/*": [ 22 | "src/*" 23 | ], 24 | } 25 | }, 26 | "include": [ 27 | "src/**/*.ts", 28 | "src/**/*.d.ts", 29 | "src/**/*.tsx", 30 | "src/**/*.vue", 31 | ], 32 | "references": [ 33 | { 34 | "path": "./tsconfig.node.json" 35 | } 36 | ], 37 | } -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": [ 9 | "vite.config.ts" 10 | ] 11 | } -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import vue from '@vitejs/plugin-vue' 2 | import { resolve } from 'path' 3 | import { defineConfig } from 'vite' 4 | 5 | export default defineConfig({ 6 | plugins: [vue()], 7 | build: { 8 | lib: { 9 | entry: resolve(__dirname, 'src/index.ts'), 10 | name: '1llest-waveform-vue', 11 | }, 12 | rollupOptions: { 13 | external: ['vue'], 14 | output: { 15 | globals: { 16 | vue: 'Vue', 17 | }, 18 | }, 19 | }, 20 | }, 21 | }) 22 | --------------------------------------------------------------------------------