{"version":3,"file":"image-upload.cjs","sources":["../../../packages/components/src/image-upload.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\nimport { repeat } from 'lit/directives/repeat.js'\nimport { styleMap } from 'lit/directives/style-map.js'\nimport { safeCustomElement } from './base/define'\n\nexport type ImageUploadFile = {\n  uid?: string | number\n  name: string\n  url?: string\n  size?: number\n  status?: 'ready' | 'uploading' | 'success' | 'fail'\n  progress?: number\n  file?: File\n}\n\ntype UploadSuccessDetail = {\n  response: any\n  file: ImageUploadFile\n  files: ImageUploadFile[]\n}\n\nfunction parseJsonResponse(responseText: string) {\n  try {\n    return JSON.parse(responseText)\n  }\n  catch {\n    return responseText\n  }\n}\n\nconst previewIcon = html`\n  <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n    <path\n      d=\"M1.5 12s3.5-6 10.5-6 10.5 6 10.5 6-3.5 6-10.5 6S1.5 12 1.5 12Z\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      stroke-linecap=\"round\"\n      stroke-linejoin=\"round\"\n      stroke-width=\"1.8\"\n    />\n    <circle\n      cx=\"12\"\n      cy=\"12\"\n      r=\"3.2\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      stroke-width=\"1.8\"\n    />\n  </svg>\n`\n\nconst removeIcon = html`\n  <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n    <path\n      d=\"M7 7l10 10M17 7L7 17\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      stroke-linecap=\"round\"\n      stroke-width=\"1.9\"\n    />\n  </svg>\n`\n\n@safeCustomElement('qxs-image-upload')\nexport class QxsImageUpload extends LitElement {\n  private static _scrollLockCount = 0\n  private static _previousHtmlOverflow = ''\n  private static _previousBodyOverflow = ''\n\n  static styles = css`\n    :host {\n      display: block;\n      --upload-width: 160px;\n      --upload-height: 90px;\n      color: #0f172a;\n      font-size: 14px;\n    }\n\n    .upload {\n      display: grid;\n      gap: 10px;\n    }\n\n    .list {\n      display: flex;\n      flex-wrap: wrap;\n      gap: 10px;\n    }\n\n    .item,\n    .add {\n      position: relative;\n      width: var(--upload-width);\n      height: var(--upload-height);\n      overflow: hidden;\n      border: 1px dashed #cbd5e1;\n      border-radius: 14px;\n      background: #f8fafc;\n      transition: border-color 0.2s ease;\n    }\n\n    .item:hover {\n      border-color: #3d61e3;\n    }\n\n    .add:hover {\n      border-color: #94a3b8;\n    }\n\n    .add {\n      display: grid;\n      place-items: center;\n      cursor: pointer;\n      background: #f8fafc;\n    }\n\n    .add.is-disabled {\n      cursor: not-allowed;\n      opacity: 0.6;\n    }\n\n    .add input {\n      display: none;\n    }\n\n    .add-content {\n      display: grid;\n      gap: 8px;\n      place-items: center;\n      color: #64748b;\n      text-align: center;\n    }\n\n    .add-icon {\n      font-size: 28px;\n      line-height: 1;\n      color: #3d61e3;\n    }\n\n    .item img,\n    .viewer img {\n      width: 100%;\n      height: 100%;\n      object-fit: cover;\n    }\n\n    .item img {\n      transition: none;\n    }\n\n    .placeholder {\n      display: grid;\n      place-items: center;\n      width: 100%;\n      height: 100%;\n      color: #94a3b8;\n      background: #f8fafc;\n    }\n\n    .progress {\n      position: absolute;\n      right: 0;\n      bottom: 0;\n      left: 0;\n      height: 4px;\n      background: rgb(15 23 42 / 12%);\n    }\n\n    .progress-bar {\n      height: 100%;\n      background: #3d61e3;\n      transition: width 0.2s ease;\n    }\n\n    .actions {\n      position: absolute;\n      inset: 0;\n      display: flex;\n      gap: 14px;\n      align-items: center;\n      justify-content: center;\n      background: rgb(15 23 42 / 48%);\n      opacity: 0;\n      transition: opacity 0.2s ease;\n    }\n\n    .item:hover .actions {\n      opacity: 1;\n    }\n\n    .action {\n      display: grid;\n      place-items: center;\n      width: 38px;\n      height: 38px;\n      color: #fff;\n      cursor: pointer;\n      background: rgb(255 255 255 / 14%);\n      border: 0;\n      border-radius: 999px;\n      transition: background 0.18s ease;\n    }\n\n    .action.is-disabled {\n      cursor: not-allowed;\n      opacity: 0.45;\n    }\n\n    .action:hover {\n      background: rgb(255 255 255 / 24%);\n    }\n\n    .action:focus-visible {\n      outline: 2px solid rgb(255 255 255 / 88%);\n      outline-offset: 2px;\n    }\n\n    .action svg {\n      width: 18px;\n      height: 18px;\n    }\n\n    .tip,\n    .message {\n      font-size: 12px;\n      line-height: 1.6;\n      color: #64748b;\n    }\n\n    .message {\n      padding: 10px 12px;\n      border-radius: 12px;\n    }\n\n    .message.error {\n      color: #b91c1c;\n      background: #fef2f2;\n    }\n\n    .message.warning {\n      color: #9a3412;\n      background: #fff7ed;\n    }\n\n    .viewer {\n      position: fixed;\n      inset: 0;\n      z-index: 9999;\n      display: grid;\n      place-items: center;\n    }\n\n    .viewer-mask {\n      position: absolute;\n      inset: 0;\n      background: rgb(0 0 0 / 82%);\n    }\n\n    .viewer-inner {\n      position: relative;\n      z-index: 1;\n      width: min(88vw, 960px);\n      height: min(80vh, 640px);\n    }\n\n    .viewer-close,\n    .viewer-nav {\n      position: absolute;\n      z-index: 1;\n      color: #fff;\n      cursor: pointer;\n      background: transparent;\n      border: 0;\n    }\n\n    .viewer-close {\n      top: 16px;\n      right: 16px;\n      font-size: 32px;\n    }\n\n    .viewer-nav {\n      top: 50%;\n      font-size: 52px;\n      transform: translateY(-50%);\n    }\n\n    .viewer-nav.prev {\n      left: 20px;\n    }\n\n    .viewer-nav.next {\n      right: 20px;\n    }\n  `\n\n  @property({ type: String }) action = ''\n  @property({ attribute: false }) headers?: Record<string, string>\n  @property({ attribute: false }) data?: Record<string, string | Blob>\n  @property({ type: String }) name = 'file'\n  @property({ type: Number }) size = 20\n  @property({ type: Number }) width = 160\n  @property({ type: Number }) height = 90\n  @property({ type: String }) accept = 'image/jpeg,image/jpg,image/png,image/gif'\n  @property({ type: String }) placeholder = '上传图片'\n  @property({ type: Boolean }) notip = false\n  @property({ type: String, attribute: 'tip-text' }) tipText = ''\n  @property({ type: Boolean }) disabled = false\n  @property({ type: Number }) limit = 1\n  @property({ attribute: false }) fileList: ImageUploadFile[] = []\n\n  @state() private _internalFiles: ImageUploadFile[] = []\n  @state() private _viewerVisible = false\n  @state() private _viewerIndex = 0\n  @state() private _message = ''\n  @state() private _messageType: 'error' | 'warning' | '' = ''\n\n  @query('input[type=\"file\"]') private _input?: HTMLInputElement\n  private _hasScrollLock = false\n  private _pendingRequests = new Map<string, XMLHttpRequest>()\n\n  connectedCallback() {\n    super.connectedCallback()\n    this._syncFileList()\n  }\n\n  disconnectedCallback() {\n    this._syncScrollLock(false)\n    super.disconnectedCallback()\n    this._pendingRequests.forEach(xhr => xhr.abort())\n    this._pendingRequests.clear()\n    this._internalFiles.forEach(file => this._revokeFileUrl(file))\n  }\n\n  updated(changed: Map<string, unknown>) {\n    if (changed.has('fileList')) {\n      this._syncFileList()\n    }\n\n    if (changed.has('_viewerVisible')) {\n      this._syncScrollLock(this._viewerVisible)\n    }\n  }\n\n  private get _exts() {\n    return this.accept\n      .split(',')\n      .map(item => item.split('/').pop()?.toLowerCase() ?? '')\n      .filter(Boolean)\n  }\n\n  private get _tipMessage() {\n    if (this.tipText) {\n      return this.tipText\n    }\n    const formatText = `支持 ${this._exts.join(' / ')} 格式，大小不超过 ${this.size}MB`\n    const sizeText = this.width && this.height ? `，建议尺寸 ${this.width}×${this.height}` : ''\n    return formatText + sizeText\n  }\n\n  private _syncFileList() {\n    this._internalFiles = [...this.fileList]\n  }\n\n  private _setMessage(type: 'error' | 'warning', message: string) {\n    this._messageType = type\n    this._message = message\n  }\n\n  private _clearMessage() {\n    this._messageType = ''\n    this._message = ''\n  }\n\n  private _revokeFileUrl(file: ImageUploadFile) {\n    if (file.url?.startsWith('blob:')) {\n      URL.revokeObjectURL(file.url)\n    }\n  }\n\n  private _emitFileListChange() {\n    const detail = { fileList: this._internalFiles.slice() }\n    this.dispatchEvent(new CustomEvent('file-list-change', { detail, bubbles: true, composed: true }))\n    this.dispatchEvent(new CustomEvent('update:fileList', { detail, bubbles: true, composed: true }))\n  }\n\n  private _emitSuccess(detail: UploadSuccessDetail) {\n    this.dispatchEvent(new CustomEvent('upload-success', { detail, bubbles: true, composed: true }))\n    this.dispatchEvent(new CustomEvent('success', { detail, bubbles: true, composed: true }))\n  }\n\n  private _getFileKey(file: Pick<ImageUploadFile, 'uid' | 'name'>) {\n    return String(file.uid ?? file.name)\n  }\n\n  private _updateFileByKey(fileKey: string, updater: (file: ImageUploadFile) => ImageUploadFile) {\n    let changed = false\n    this._internalFiles = this._internalFiles.map((item) => {\n      if (this._getFileKey(item) !== fileKey) {\n        return item\n      }\n      changed = true\n      return updater(item)\n    })\n    return changed\n  }\n\n  private _emitRemove(file: ImageUploadFile) {\n    this.dispatchEvent(new CustomEvent('remove', {\n      detail: { file },\n      bubbles: true,\n      composed: true,\n    }))\n  }\n\n  private _validateFile(file: File) {\n    const fileExt = file.name.split('.').pop()?.toLowerCase() ?? ''\n    const isTypeOk = this._exts.some(ext => ext === fileExt)\n\n    if (!isTypeOk) {\n      this._setMessage('error', `仅支持上传 ${this._exts.join(' / ')} 格式的图片`)\n      return false\n    }\n\n    const fileSizeMB = file.size / 1024 / 1024\n    if (fileSizeMB > this.size) {\n      this._setMessage('error', `图片大小不能超过 ${this.size}MB`)\n      return false\n    }\n\n    return true\n  }\n\n  private _handleSelectedFiles(files: File[]) {\n    if (this.disabled || !files.length) {\n      return\n    }\n\n    this._clearMessage()\n    const validFiles = files.filter(file => this._validateFile(file))\n\n    if (!validFiles.length) {\n      return\n    }\n\n    if (!this.action) {\n      this._setMessage('warning', '请先配置上传地址 action')\n      return\n    }\n\n    if (this._internalFiles.length + validFiles.length > this.limit) {\n      this._setMessage('warning', `最多上传 ${this.limit} 张图片`)\n      return\n    }\n\n    validFiles.forEach((file) => {\n      const imageFile: ImageUploadFile = {\n        uid: Date.now() + Math.random(),\n        name: file.name,\n        size: file.size,\n        status: 'uploading',\n        progress: 0,\n        url: URL.createObjectURL(file),\n        file,\n      }\n\n      this._internalFiles = [...this._internalFiles, imageFile]\n      this._emitFileListChange()\n      this._uploadFile(file, imageFile)\n    })\n  }\n\n  private _handleInputChange(event: Event) {\n    const input = event.target as HTMLInputElement\n    const files = input.files\n    if (!files) {\n      return\n    }\n\n    this._handleSelectedFiles(Array.from(files))\n    input.value = ''\n  }\n\n  private _uploadFile(file: File, imageFile: ImageUploadFile) {\n    const formData = new FormData()\n    formData.append(this.name, file)\n\n    if (this.data) {\n      Object.entries(this.data).forEach(([key, value]) => {\n        formData.append(key, value)\n      })\n    }\n\n    const xhr = new XMLHttpRequest()\n    const fileKey = this._getFileKey(imageFile)\n    xhr.open('POST', this.action)\n    this._pendingRequests.set(fileKey, xhr)\n\n    if (this.headers) {\n      Object.entries(this.headers).forEach(([key, value]) => {\n        xhr.setRequestHeader(key, value)\n      })\n    }\n\n    xhr.upload.onprogress = (event) => {\n      if (event.lengthComputable) {\n        const progress = Math.floor((event.loaded / event.total) * 100)\n        this._updateFileByKey(fileKey, item => ({ ...item, progress }))\n      }\n    }\n\n    xhr.onload = () => {\n      if (this._pendingRequests.get(fileKey) !== xhr) {\n        return\n      }\n      this._pendingRequests.delete(fileKey)\n\n      if (xhr.status >= 200 && xhr.status < 300) {\n        const response = parseJsonResponse(xhr.responseText)\n        const changed = this._updateFileByKey(fileKey, item => ({\n          ...item,\n          status: 'success',\n          progress: 100,\n        }))\n        if (!changed) {\n          return\n        }\n        this._emitFileListChange()\n        const updatedFile = this._internalFiles.find(item => this._getFileKey(item) === fileKey)\n        if (!updatedFile) {\n          return\n        }\n        this._emitSuccess({\n          response,\n          file: { ...updatedFile },\n          files: this._internalFiles.slice(),\n        })\n      }\n      else {\n        this._updateFileByKey(fileKey, item => ({ ...item, status: 'fail', progress: 0 }))\n        this._setMessage('error', '上传失败')\n      }\n    }\n\n    xhr.onerror = () => {\n      if (this._pendingRequests.get(fileKey) !== xhr) {\n        return\n      }\n      this._pendingRequests.delete(fileKey)\n      this._updateFileByKey(fileKey, item => ({ ...item, status: 'fail', progress: 0 }))\n      this._setMessage('error', '上传失败')\n    }\n\n    xhr.onabort = () => {\n      if (this._pendingRequests.get(fileKey) !== xhr) {\n        return\n      }\n      this._pendingRequests.delete(fileKey)\n    }\n\n    xhr.send(formData)\n  }\n\n  private _handlePreview(index: number) {\n    this._viewerIndex = index\n    this._viewerVisible = true\n  }\n\n  private _closeViewer() {\n    this._viewerVisible = false\n  }\n\n  private _prevImage() {\n    this._viewerIndex = (this._viewerIndex - 1 + this._internalFiles.length) % this._internalFiles.length\n  }\n\n  private _nextImage() {\n    this._viewerIndex = (this._viewerIndex + 1) % this._internalFiles.length\n  }\n\n  private _handleRemove(index: number) {\n    if (this.disabled) {\n      return\n    }\n\n    const file = this._internalFiles[index]\n    if (!file) {\n      return\n    }\n\n    const fileKey = this._getFileKey(file)\n    const pendingRequest = this._pendingRequests.get(fileKey)\n    if (pendingRequest) {\n      this._pendingRequests.delete(fileKey)\n      pendingRequest.abort()\n    }\n\n    this._revokeFileUrl(file)\n    this._internalFiles = this._internalFiles.filter((_, fileIndex) => fileIndex !== index)\n    this._emitFileListChange()\n    this._emitRemove(file)\n\n    if (this._viewerIndex >= this._internalFiles.length) {\n      this._viewerIndex = Math.max(0, this._internalFiles.length - 1)\n    }\n    if (!this._internalFiles.length) {\n      this._viewerVisible = false\n    }\n  }\n\n  private _syncScrollLock(locked: boolean) {\n    if (typeof document === 'undefined') {\n      return\n    }\n\n    const htmlElement = document.documentElement\n    const bodyElement = document.body\n\n    if (locked) {\n      if (this._hasScrollLock) {\n        return\n      }\n\n      if (QxsImageUpload._scrollLockCount === 0) {\n        QxsImageUpload._previousHtmlOverflow = htmlElement.style.overflow\n        QxsImageUpload._previousBodyOverflow = bodyElement.style.overflow\n        htmlElement.style.overflow = 'hidden'\n        bodyElement.style.overflow = 'hidden'\n      }\n\n      QxsImageUpload._scrollLockCount += 1\n      this._hasScrollLock = true\n      return\n    }\n\n    if (!this._hasScrollLock) {\n      return\n    }\n\n    QxsImageUpload._scrollLockCount = Math.max(0, QxsImageUpload._scrollLockCount - 1)\n    this._hasScrollLock = false\n\n    if (QxsImageUpload._scrollLockCount === 0) {\n      htmlElement.style.overflow = QxsImageUpload._previousHtmlOverflow\n      bodyElement.style.overflow = QxsImageUpload._previousBodyOverflow\n      QxsImageUpload._previousHtmlOverflow = ''\n      QxsImageUpload._previousBodyOverflow = ''\n    }\n  }\n\n  render() {\n    const cssVars = {\n      '--upload-width': `${this.width}px`,\n      '--upload-height': `${this.height}px`,\n    }\n    const currentPreview = this._internalFiles[this._viewerIndex]\n\n    return html`\n      <div class=\"upload\" style=${styleMap(cssVars)} part=\"container\">\n        <div class=\"list\" part=\"list\">\n          ${repeat(this._internalFiles, file => String(file.uid ?? file.name), (file, index) => html`\n            <div class=\"item\" part=\"item\">\n              ${file.url\n                ? html`<img src=${file.url} alt=${file.name} part=\"image\">`\n                : html`<div class=\"placeholder\" part=\"placeholder\">无图片</div>`}\n\n              ${file.status === 'uploading'\n                ? html`\n                    <div class=\"progress\" part=\"progress\">\n                      <div class=\"progress-bar\" style=${styleMap({ width: `${file.progress ?? 0}%` })}></div>\n                    </div>\n                  `\n                : nothing}\n\n              <div class=\"actions\" part=\"actions\">\n                ${file.url\n                  ? html`\n                      <button\n                        class=\"action\"\n                        data-action=\"preview\"\n                        type=\"button\"\n                        aria-label=\"预览图片\"\n                        @click=${() => this._handlePreview(index)}\n                      >\n                        ${previewIcon}\n                      </button>\n                    `\n                  : nothing}\n                <button\n                  class=\"action ${this.disabled ? 'is-disabled' : ''}\"\n                  data-action=\"remove\"\n                  type=\"button\"\n                  aria-label=\"删除图片\"\n                  @click=${() => this._handleRemove(index)}\n                >\n                  ${removeIcon}\n                </button>\n              </div>\n            </div>\n          `)}\n\n          ${this._internalFiles.length < this.limit\n            ? html`\n                <label class=\"add ${this.disabled ? 'is-disabled' : ''}\" part=\"add\">\n                  <input\n                    type=\"file\"\n                    accept=${this.accept}\n                    ?multiple=${this.limit > 1}\n                    ?disabled=${this.disabled}\n                    @change=${this._handleInputChange}\n                  >\n                  <div class=\"add-content\" part=\"add-content\">\n                    <div class=\"add-icon\">＋</div>\n                    <div>${this.placeholder}</div>\n                  </div>\n                </label>\n              `\n            : nothing}\n        </div>\n\n        ${this._message\n          ? html`<div class=\"message ${this._messageType}\" part=\"message\">${this._message}</div>`\n          : nothing}\n\n        ${this.notip\n          ? nothing\n          : html`\n              <div class=\"tip\" part=\"tip\">\n                <slot name=\"tip\">${this._tipMessage}</slot>\n              </div>\n            `}\n\n        ${this._viewerVisible && currentPreview?.url\n          ? html`\n              <div class=\"viewer\" part=\"viewer\">\n                <div class=\"viewer-mask\" @click=${this._closeViewer}></div>\n                <button class=\"viewer-close\" type=\"button\" @click=${this._closeViewer}>×</button>\n                ${this._internalFiles.length > 1\n                  ? html`\n                      <button class=\"viewer-nav prev\" type=\"button\" @click=${this._prevImage}>‹</button>\n                      <button class=\"viewer-nav next\" type=\"button\" @click=${this._nextImage}>›</button>\n                    `\n                  : nothing}\n                <div class=\"viewer-inner\">\n                  <img src=${currentPreview.url} alt=${currentPreview.name}>\n                </div>\n              </div>\n            `\n          : nothing}\n      </div>\n    `\n  }\n}\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'qxs-image-upload': QxsImageUpload\n  }\n}\n"],"names":["parseJsonResponse","responseText","previewIcon","html","removeIcon","QxsImageUpload","LitElement","xhr","file","changed","item","formatText","sizeText","type","message","detail","fileKey","updater","fileExt","ext","files","validFiles","imageFile","event","input","formData","key","value","progress","response","updatedFile","index","pendingRequest","_","fileIndex","locked","htmlElement","bodyElement","cssVars","currentPreview","styleMap","repeat","nothing","css","__decorateClass","property","state","query","safeCustomElement"],"mappings":"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"}