appstore/dist/lib/ui/form/uploader.js

60 lines
6.6 KiB
JavaScript

import{css as a,html as l,Component as d,styleMap as n}from"wkit";import{resolveFiles as c,parseSize as p}from"../base/fs.js";import"../base/icon.js";function h(){return Math.random().toString(16).slice(2)}class u extends d{static props={value:[],tips:"str!",accept:"*/*",maxSize:0,limit:0,grid:!1,drag:!1,multiple:!1,disabled:!1};static styles=[a`:host{display:flex;width:100%;font-size:14px}img,a{-webkit-user-drag:none}.container{position:relative;width:100%;padding:6px 0;-webkit-user-select:none;user-select:none;--wc-icon-size: 14px}.tips,.error{display:block;line-height:1.5;font-size:12px;font-style:normal}.error{color:var(--color-red-1);background:none}.upload-button{position:relative;display:inline-flex;justify-content:center;align-items:center;width:108px;height:32px;gap:4px;border:1px solid var(--color-grey-2);border-radius:3px;cursor:pointer;transition:background .1s linear,border-color .1s linear,color .1s linear}.upload-button:hover{border-color:var(--color-grey-1)}.upload-button:active{background:var(--color-plain-1)}.upload-button.limited{background:var(--color-disabled-background);opacity:.6;cursor:not-allowed}.hidden-input{position:absolute;left:0;top:0;display:block;width:100%;height:100%;opacity:0;cursor:inherit}.hidden-input::-webkit-file-upload-button{display:none}`,a`.file-list .item{display:flex;align-items:center;padding:0 8px;line-height:24px;gap:4px;background:none no-repeat center;background-size:contain;transition:background .15s linear}.file-list .item:hover{background-color:var(--color-plain-1)}.file-list .item:hover wc-icon.del{opacity:1}.file-list .item .name{flex:1}.file-list .item wc-icon{flex-shrink:0;transition:opacity .15s linear}.file-list .item wc-icon.del{opacity:0;cursor:pointer;color:var(--color-red-1)}`,a`:host([grid]) .container{display:flex;flex-flow:row-reverse;justify-content:start;gap:12px;--size: var(--wc-uploader-size, 96px);--border-color: var(--wc-uploader-border-color, var(--color-grey-2))}:host([grid]) .tips{display:none}:host([grid]) .upload-button{width:var(--size);height:var(--size);border-radius:6px;--wc-icon-size: 18px}:host([grid]) .file-list{display:flex;gap:12px}:host([grid]) .file-list .item{justify-content:center;width:var(--size);height:var(--size);gap:6px;border:1px solid var(--border-color);border-radius:6px;--wc-icon-size: 20px}:host([grid]) .file-list .item .name{display:none}:host([grid]) .file-list .item wc-icon{padding:3px;border:1px solid rgba(255,255,255,.25);border-radius:50%;background:rgba(64,64,64,.75);color:#fff;opacity:0;cursor:pointer}:host([grid]) .file-list .item wc-icon:hover{border-color:rgba(255,255,255,.5)}:host([grid]) .file-list .item:hover wc-icon{opacity:1}`,a`:host([drag]) .container{flex-flow:column}:host([drag]) .action-area{width:100%}:host([drag]) .tips{display:block}:host([drag]) .upload-button{flex-direction:column;width:100%;height:180px;border-style:dashed;--wc-icon-size: 64px}:host([drag]) .upload-button.in{border-color:var(--color-orange-1);background:var(--color-drag-background)}:host([drag]) .upload-button:hover{color:var(--color-grey-3)}`,a`:host([disabled]){opacity:.6}:host([disabled]) .upload-button{background:var(--color-disabled-background);cursor:not-allowed}`,a`.preview{position:fixed;left:0;top:0;z-index:99;display:none;align-items:center;justify-content:center;width:100vw;height:100vh;background:rgba(0,0,0,.3)}.preview img{display:block;max-width:90%;max-height:90%;object-fit:contain;box-shadow:0 0 20px #000}`];#e=[];#i;#t(e){this.$refs.err.textContent=e,clearTimeout(this.#i),this.#i=setTimeout(()=>{this.$refs.err.textContent=""},5e3)}#s(e){let i=[...e.target.files];e.target.value="",this.#r(i)}#r(e){let{limit:i,maxSize:r}=this,o=e.length;r>0&&(e=e.filter(t=>t.size<=r),e.length<o&&(o=e.length,this.#t(`\u90E8\u5206\u6587\u4EF6\u88AB\u5FFD\u7565, \u5355\u6587\u4EF6\u6700\u5927\u5141\u8BB8 ${p(r)}`))),i>0&&(e=e.slice(0,i-this.#e.length),e.length<o&&this.#t(`\u90E8\u5206\u6587\u4EF6\u88AB\u5FFD\u7565, \u6700\u591A\u9009\u62E9 ${i} \u4E2A\u6587\u4EF6`)),e.length&&(e=e.map(t=>({file:t,id:h(),url:"",stat:0})),this.#e=this.#e.concat(e),this.$emit("upload",{files:e,send:t=>{for(let s of t)s.stat=1;this.value=this.#e.map(s=>s.url)}}),this.$requestUpdate())}#a(e,i,r){for(let o in this.#e)if(i===this.#e[o]){this.#e.splice(o,1);break}this.$requestUpdate()}#l(){this.disabled||this.$refs.button.classList.toggle("in",!0)}#n(){this.$refs.button.classList.toggle("in",!1)}async#d(e){let i;this.$refs.button.classList.toggle("in",!1),!this.disabled&&(i=await c(e.dataTransfer.items),this.#r(i.map(r=>r.file)))}#o(e,i){e.target.name!=="doc"&&(this.$refs.view.firstElementChild.src=i.url||URL.createObjectURL(i.file),this.$refs.view.style.display="flex")}#c(e){this.$refs.view.style.display=""}mounted(){}render(){let{disabled:e,grid:i,drag:r}=this,o=this.limit>0&&this.#e.length>=this.limit;return l`
<main class="container">
<header class="action-area">
<div
ref="button"
class="upload-button ${o?"limited":""}"
@dragover.prevent=${this.#l}
@dragleave.prevent=${this.#n}
@drop.prevent=${this.#d}
>
<wc-icon name=${i&&!r?"plus":"upload"}></wc-icon>
<span
>${r?"\u62D6\u62FD\u6587\u4EF6\u5230\u6B64\u5904 \u6216 \u70B9\u51FB\u9009\u62E9\u6587\u4EF6":i?"":"\u9009\u62E9\u6587\u4EF6"}</span
>
<input
class="hidden-input"
title
type="file"
accept=${this.accept}
multiple=${this.multiple}
disabled=${e||o}
@change=${this.#s}
/>
</div>
<cite class="tips">${this.tips}</cite>
<mark ref="err" class="error"></mark>
</header>
<footer
class="file-list"
style=${n({display:this.#e.length?"":"none"})}
>
${this.#e.map(t=>l`
<section
class="item"
style=${n({backgroundImage:i?`url(${t.url})`:""})}
>
<wc-icon
name=${t.stat===0?"loading":i?"search":"doc"}
@click=${s=>this.#o(s,t)}
></wc-icon>
<span class="name" @click=${s=>this.#o(s,t)}
>${t.file.name}</span
>
<wc-icon
class="del"
name="trash"
data-id=${t.id}
@click=${s=>this.#a(s,t,t.id)}
></wc-icon>
</section>
`)}
</footer>
</main>
<div class="preview" ref="view" @click.self=${this.#c}>
<img />
</div>
`}}u.reg("uploader");
appstore online