import{g as C,x as S}from"./iframe-CMPv_g6-.js";import{o as E}from"./if-defined-DzbkssR9.js";import{o as x}from"./style-map-968Ye5qo.js";import"./preload-helper-PPVm8Dsz.js";const{events:B,args:U,argTypes:c}=C("btu-upload"),F=e=>{const o={};return e.dropzoneBg&&(o["--upload-dropzone-bg"]=e.dropzoneBg),e.dropzoneBorderColor&&(o["--upload-dropzone-border-color"]=e.dropzoneBorderColor),e.dropzoneBorderRadius&&(o["--upload-dropzone-border-radius"]=e.dropzoneBorderRadius),e.dropzoneHoverBg&&(o["--upload-dropzone-hover-bg"]=e.dropzoneHoverBg),e.dropzoneHoverBorderColor&&(o["--upload-dropzone-hover-border-color"]=e.dropzoneHoverBorderColor),e.dropzoneFocusRingColor&&(o["--upload-dropzone-focus-ring-color"]=e.dropzoneFocusRingColor),e.itemBg&&(o["--upload-item-bg"]=e.itemBg),e.itemBorderColor&&(o["--upload-item-border-color"]=e.itemBorderColor),e.itemActiveBorderColor&&(o["--upload-item-active-border-color"]=e.itemActiveBorderColor),e.itemCompleteBorderColor&&(o["--upload-item-complete-border-color"]=e.itemCompleteBorderColor),e.itemErrorBg&&(o["--upload-item-error-bg"]=e.itemErrorBg),e.itemErrorBorderColor&&(o["--upload-item-error-border-color"]=e.itemErrorBorderColor),o},T={title:"Components/Upload",component:"btu-upload",tags:["autodocs"],parameters:{docs:{subtitle:"btu-upload",description:{component:`
A file upload component with drop zone and file list.

The component is **presentation + file-selection only**. It handles file browsing
(hidden \`<input type="file">\`), drag-and-drop reception, client-side validation
(type, size, count), and rendering the file list with progress bars.

It does **not** perform network requests. The consumer listens for events, performs
their own upload (XHR, fetch, etc.), and drives state back into the component
via imperative methods.

<h3>Consumer API:</h3>
<ul>
  <li><code>setFileProgress(id, percent)</code> — Update progress bar (0-100)</li>
  <li><code>setFileStatus(id, status, message?)</code> — Set 'uploading', 'complete', or 'error'</li>
  <li><code>setFileSymbol(id, symbol)</code> — Override file icon</li>
  <li><code>removeFile(id)</code> — Remove a file programmatically</li>
  <li><code>getFiles()</code> — Get snapshot of all files and their states</li>
</ul>

<h3>Events:</h3>
<ul>
  <li><code>btu-upload-file-added</code> — File passed validation, ready for upload</li>
  <li><code>btu-upload-file-removed</code> — File removed by user or programmatically</li>
  <li><code>btu-upload-file-retry</code> — User clicked "Try again" on failed upload</li>
  <li><code>btu-upload-file-rejected</code> — File failed client-side validation</li>
</ul>
        `}},actions:{handles:B},controls:{expanded:!0}},args:{...U,accept:"","max-file-size":void 0,"max-files":void 0,disabled:!1,"no-drag":!1},argTypes:{...c,accept:{...c.accept,control:{type:"text"},description:"Accepted file types (MIME types, extensions, or comma-separated list)"},"max-file-size":{...c["max-file-size"],control:{type:"number"},description:"Maximum file size in bytes. 0 means unlimited."},"max-files":{...c["max-files"],control:{type:"number"},description:"Maximum number of files allowed. Omit for unlimited. Set to 1 for single-file mode (new selection replaces the existing file)."},disabled:{...c.disabled,control:{type:"boolean"},description:"Disables all interaction"},"no-drag":{...c["no-drag"],control:{type:"boolean"},description:"Disables drag-and-drop. File selection via click still works."},"--upload-dropzone-bg":{table:{disable:!0}},"--upload-dropzone-border-color":{table:{disable:!0}},"--upload-dropzone-border-radius":{table:{disable:!0}},"--upload-dropzone-hover-bg":{table:{disable:!0}},"--upload-dropzone-hover-border-color":{table:{disable:!0}},"--upload-dropzone-focus-ring-color":{table:{disable:!0}},"--upload-item-bg":{table:{disable:!0}},"--upload-item-border-color":{table:{disable:!0}},"--upload-item-active-border-color":{table:{disable:!0}},"--upload-item-complete-border-color":{table:{disable:!0}},"--upload-item-error-bg":{table:{disable:!0}},"--upload-item-error-border-color":{table:{disable:!0}},dropzoneBg:{name:"--upload-dropzone-bg",control:{type:"color"},description:"Drop zone background color (default: gray-25)",table:{category:"CSS Properties"}},dropzoneBorderColor:{name:"--upload-dropzone-border-color",control:{type:"color"},description:"Drop zone border color (default: gray-200)",table:{category:"CSS Properties"}},dropzoneBorderRadius:{name:"--upload-dropzone-border-radius",control:{type:"text"},description:"Drop zone border radius (default: borderRadius.lg)",table:{category:"CSS Properties"}},dropzoneHoverBg:{name:"--upload-dropzone-hover-bg",control:{type:"color"},description:"Drop zone hover background (default: gray-50)",table:{category:"CSS Properties"}},itemBg:{name:"--upload-item-bg",control:{type:"color"},description:"Item background color (default: white)",table:{category:"CSS Properties"}},itemBorderColor:{name:"--upload-item-border-color",control:{type:"color"},description:"Item border color (default: gray-200)",table:{category:"CSS Properties"}},itemErrorBg:{name:"--upload-item-error-bg",control:{type:"color"},description:"Item error background (default: error-25)",table:{category:"CSS Properties"}},itemErrorBorderColor:{name:"--upload-item-error-border-color",control:{type:"color"},description:"Item error border color (default: error-300)",table:{category:"CSS Properties"}},dropzoneHoverBorderColor:{name:"--upload-dropzone-hover-border-color",control:{type:"color"},description:"Drop zone hover border color (default: primary-300)",table:{category:"CSS Properties"}},dropzoneFocusRingColor:{name:"--upload-dropzone-focus-ring-color",control:{type:"color"},description:"Drop zone focus ring color (default: primary-100)",table:{category:"CSS Properties"}},itemActiveBorderColor:{name:"--upload-item-active-border-color",control:{type:"color"},description:"Item active/in-progress border color (default: gray-300)",table:{category:"CSS Properties"}},itemCompleteBorderColor:{name:"--upload-item-complete-border-color",control:{type:"color"},description:"Item completed border color (default: primary-500)",table:{category:"CSS Properties"}}},render:e=>{const o=F(e);return S`
      <btu-upload
        style=${x(o)}
        accept="${e.accept||""}"
        max-file-size="${e["max-file-size"]||0}"
        max-files="${E(e["max-files"])}"
        ?disabled="${e.disabled}"
        ?no-drag="${e["no-drag"]}"
      ></btu-upload>
    `}},u={},m={args:{},render:e=>{const o=`upload-sim-${crypto.randomUUID().slice(0,8)}`,p=a=>{a.addEventListener("btu-upload-file-added",(s=>{const{id:r}=s.detail;let i=0;const t=Math.random()<.3;a.setFileStatus(r,"uploading");const d=setInterval(()=>{i+=Math.random()*15+5,i>=100?(i=100,clearInterval(d),t?a.setFileStatus(r,"error","Network error: connection timed out"):(a.setFileProgress(r,100),a.setFileStatus(r,"complete"))):a.setFileProgress(r,i)},300)})),a.addEventListener("btu-upload-file-retry",(s=>{const{id:r}=s.detail;let i=0;a.setFileStatus(r,"uploading"),a.setFileProgress(r,0);const t=setInterval(()=>{i+=Math.random()*20+10,i>=100?(i=100,clearInterval(t),a.setFileProgress(r,100),a.setFileStatus(r,"complete")):a.setFileProgress(r,i)},300)}))};return setTimeout(()=>{const s=document.getElementById(o)?.querySelector("btu-upload");s&&p(s)},100),S`
      <div id="${o}">
        <btu-upload
          style=${x(F(e))}
          accept="${e.accept||""}"
          max-file-size="${e["max-file-size"]||0}"
          max-files="${E(e["max-files"])}"
          ?disabled="${e.disabled}"
          ?no-drag="${e["no-drag"]}"
        ></btu-upload>
      </div>
    `}},f={args:{accept:"image/*,application/pdf","max-file-size":5242880},render:e=>{const o=`upload-log-${crypto.randomUUID().slice(0,8)}`,p=`log-${crypto.randomUUID().slice(0,8)}`,a={"btu-upload-file-added":"text-primary-600","btu-upload-file-removed":"text-gray-600","btu-upload-file-retry":"text-warning-600","btu-upload-file-rejected":"text-error-600","btu-upload-file-completed":"text-success-600"},s=i=>i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"),r=(i,t,d=1)=>{let l=0;const n=Math.random()<d;i.setFileStatus(t,"uploading");const $=setInterval(()=>{l+=Math.random()*15+5,l>=100?(clearInterval($),n?i.setFileStatus(t,"error","Simulated network error"):(i.setFileProgress(t,100),i.setFileStatus(t,"complete"))):i.setFileProgress(t,l)},300)};return setTimeout(()=>{const t=document.getElementById(o)?.querySelector("btu-upload"),d=document.getElementById(p);if(!t||!d)return;const l=(n,$)=>{d.querySelector(".log-placeholder")?.remove();const I=document.createElement("div");I.className="flex gap-3 py-1 border-b border-gray-200 last:border-b-0";const k=new Date().toLocaleTimeString("en-US",{hour12:!1}),w=a[n]??"";I.innerHTML=`
          <span class="shrink-0 text-gray-400">${k}</span>
          <code class="shrink-0 font-semibold ${w}">${n}</code>
          <span class="truncate text-gray-700">${s(JSON.stringify($))}</span>
        `,d.prepend(I)};t.addEventListener("btu-upload-file-added",(n=>{l("btu-upload-file-added",{id:n.detail.id,name:n.detail.file.name,size:n.detail.file.size}),r(t,n.detail.id)})),t.addEventListener("btu-upload-file-removed",(n=>{l("btu-upload-file-removed",{id:n.detail.id,name:n.detail.file.name})})),t.addEventListener("btu-upload-file-retry",(n=>{l("btu-upload-file-retry",{id:n.detail.id,name:n.detail.file.name}),r(t,n.detail.id,0)})),t.addEventListener("btu-upload-file-rejected",(n=>{l("btu-upload-file-rejected",{name:n.detail.file.name,reason:n.detail.reason,size:n.detail.file.size})})),t.addEventListener("btu-upload-file-completed",(n=>{l("btu-upload-file-completed",{id:n.detail.id,name:n.detail.file.name})}))},100),S`
      <div id="${o}" class="flex flex-col gap-4">
        <btu-upload
          style=${x(F(e))}
          accept="${e.accept||""}"
          max-file-size="${e["max-file-size"]||0}"
          max-files="${E(e["max-files"])}"
          ?disabled="${e.disabled}"
          ?no-drag="${e["no-drag"]}"
        ></btu-upload>
        <div class="rounded-md border border-gray-200 bg-gray-25 p-4">
          <div class="mb-2 text-xs font-semibold uppercase tracking-wider text-gray-500">Event Log</div>
          <div id="${p}" class="max-h-64 overflow-y-auto font-mono text-xs">
            <div class="log-placeholder italic text-gray-400">No events yet. Drop files or click to upload.</div>
          </div>
        </div>
      </div>
    `},parameters:{docs:{description:{story:'Live log of all five public events: `btu-upload-file-added`, `btu-upload-file-removed`, `btu-upload-file-retry`, `btu-upload-file-rejected`, `btu-upload-file-completed`. Accepts images and PDFs up to 5 MB — drop a `.txt` file or an oversized PDF to trigger `rejected`. Added files always fail on first attempt (surfacing the "Try again" retry UX), and the retry always succeeds — so every upload exercises the full lifecycle: added → error → retry → completed.'}}}},g={render:e=>{const o=`upload-files-${crypto.randomUUID().slice(0,8)}`;return setTimeout(()=>{const a=document.getElementById(o)?.querySelector("btu-upload");a&&requestAnimationFrame(()=>{const s=[{name:"photo-vacation.jpg",type:"image/jpeg",size:42e5,status:"complete"},{name:"quarterly-report.pdf",type:"application/pdf",size:16e6,status:"uploading",progress:40},{name:"intro-video.mp4",type:"video/mp4",size:208e6,status:"error",error:"Upload failed — server returned 503"}];for(const r of s){const i=new File([""],r.name,{type:r.type});Object.defineProperty(i,"size",{value:r.size});const t=crypto.randomUUID().slice(0,8),d={id:t,file:i,status:"pending",progress:0},l=a;l._files.set(t,d),l._milestones.set(t,new Set),l._renderItem(d),l.requestUpdate(),r.status==="complete"?a.setFileStatus(t,"complete"):r.status==="error"?a.setFileStatus(t,"error",r.error):r.status==="uploading"&&a.setFileProgress(t,r.progress??0)}})},200),S`
      <div id="${o}">
        <btu-upload style=${x(F(e))}></btu-upload>
      </div>
    `}},b={args:{"max-files":1},parameters:{docs:{description:{story:'With `max-files="1"`, selecting a new file silently replaces the existing one. Only one file can be present at a time.'}}}},y={args:{accept:"image/*","max-file-size":5242880,"max-files":3},parameters:{docs:{description:{story:"Demonstrates client-side validation. Only images are accepted, with a 5 MB size limit and a maximum of 3 files. The drop zone hides when the limit is reached. Rejected files fire `btu-upload-file-rejected` events."}}}},v={args:{disabled:!0},parameters:{docs:{description:{story:"A grayed-out drop zone with muted text. File selection, drag-and-drop, and all action buttons are blocked."}}}},h={args:{"no-drag":!0},parameters:{docs:{description:{story:'With `no-drag`, drag-and-drop is disabled. Users can still select files by clicking the drop zone or the "select" link.'}}}},z={args:{},render:e=>S`
      <btu-upload
        style=${x({"--upload-dropzone-bg":"oklch(96% 0.02 260)","--upload-dropzone-border-color":"oklch(80% 0.08 260)","--upload-dropzone-hover-bg":"oklch(93% 0.04 260)","--upload-dropzone-border-radius":"1rem","--upload-item-border-color":"oklch(80% 0.08 260)"})}
        accept="${e.accept||""}"
        max-file-size="${e["max-file-size"]||0}"
        max-files="${E(e["max-files"])}"
        ?disabled="${e.disabled}"
        ?no-drag="${e["no-drag"]}"
      ></btu-upload>
    `,parameters:{docs:{description:{story:"Demonstrates theming via CSS custom properties. The drop zone uses a purple-tinted background and rounded corners, and item borders match the custom palette."}}}};u.parameters={...u.parameters,docs:{...u.parameters?.docs,source:{originalSource:"{}",...u.parameters?.docs?.source},description:{story:"Empty drop zone with all controls exposed.",...u.parameters?.docs?.description}}};m.parameters={...m.parameters,docs:{...m.parameters?.docs,source:{originalSource:`{
  args: {},
  render: (args: Record<string, unknown>) => {
    const containerId = \`upload-sim-\${crypto.randomUUID().slice(0, 8)}\`;
    const startSimulation = (uploadEl: Upload) => {
      uploadEl.addEventListener('btu-upload-file-added', ((e: CustomEvent<{
        id: string;
        file: File;
      }>) => {
        const {
          id
        } = e.detail;
        let progress = 0;
        const shouldFail = Math.random() < 0.3;
        uploadEl.setFileStatus(id, 'uploading');
        const interval = setInterval(() => {
          progress += Math.random() * 15 + 5;
          if (progress >= 100) {
            progress = 100;
            clearInterval(interval);
            if (shouldFail) {
              uploadEl.setFileStatus(id, 'error', 'Network error: connection timed out');
            } else {
              uploadEl.setFileProgress(id, 100);
              uploadEl.setFileStatus(id, 'complete');
            }
          } else {
            uploadEl.setFileProgress(id, progress);
          }
        }, 300);
      }) as EventListener);
      uploadEl.addEventListener('btu-upload-file-retry', ((e: CustomEvent<{
        id: string;
        file: File;
      }>) => {
        const {
          id
        } = e.detail;
        let progress = 0;
        uploadEl.setFileStatus(id, 'uploading');
        uploadEl.setFileProgress(id, 0);
        const interval = setInterval(() => {
          progress += Math.random() * 20 + 10;
          if (progress >= 100) {
            progress = 100;
            clearInterval(interval);
            uploadEl.setFileProgress(id, 100);
            uploadEl.setFileStatus(id, 'complete');
          } else {
            uploadEl.setFileProgress(id, progress);
          }
        }, 300);
      }) as EventListener);
    };
    setTimeout(() => {
      const container = document.getElementById(containerId);
      const uploadEl = container?.querySelector('btu-upload') as Upload | null;
      if (uploadEl) startSimulation(uploadEl);
    }, 100);
    return html\`
      <div id="\${containerId}">
        <btu-upload
          style=\${styleMap(cssPropStyles(args))}
          accept="\${args.accept || ''}"
          max-file-size="\${args['max-file-size'] || 0}"
          max-files="\${ifDefined(args['max-files'] as number | undefined)}"
          ?disabled="\${args.disabled}"
          ?no-drag="\${args['no-drag']}"
        ></btu-upload>
      </div>
    \`;
  }
}`,...m.parameters?.docs?.source},description:{story:`Interactive demo that simulates file upload progress.

Select files to see them upload with simulated progress. Some files will randomly
fail to demonstrate the error state and retry flow.`,...m.parameters?.docs?.description}}};f.parameters={...f.parameters,docs:{...f.parameters?.docs,source:{originalSource:`{
  args: {
    accept: 'image/*,application/pdf',
    'max-file-size': 5_242_880 // 5 MB
  },
  render: (args: Record<string, unknown>) => {
    const containerId = \`upload-log-\${crypto.randomUUID().slice(0, 8)}\`;
    const logId = \`log-\${crypto.randomUUID().slice(0, 8)}\`;
    const eventColors: Record<string, string> = {
      'btu-upload-file-added': 'text-primary-600',
      'btu-upload-file-removed': 'text-gray-600',
      'btu-upload-file-retry': 'text-warning-600',
      'btu-upload-file-rejected': 'text-error-600',
      'btu-upload-file-completed': 'text-success-600'
    };
    const escapeHtml = (s: string) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
    const simulateUpload = (uploadEl: Upload, id: string, failChance = 1) => {
      let progress = 0;
      const shouldFail = Math.random() < failChance;
      uploadEl.setFileStatus(id, 'uploading');
      const interval = setInterval(() => {
        progress += Math.random() * 15 + 5;
        if (progress >= 100) {
          clearInterval(interval);
          if (shouldFail) {
            uploadEl.setFileStatus(id, 'error', 'Simulated network error');
          } else {
            uploadEl.setFileProgress(id, 100);
            uploadEl.setFileStatus(id, 'complete');
          }
        } else {
          uploadEl.setFileProgress(id, progress);
        }
      }, 300);
    };
    setTimeout(() => {
      const container = document.getElementById(containerId);
      const uploadEl = container?.querySelector('btu-upload') as Upload | null;
      const logEl = document.getElementById(logId);
      if (!uploadEl || !logEl) return;
      const appendLog = (name: string, detail: Record<string, unknown>) => {
        logEl.querySelector('.log-placeholder')?.remove();
        const entry = document.createElement('div');
        entry.className = 'flex gap-3 py-1 border-b border-gray-200 last:border-b-0';
        const ts = new Date().toLocaleTimeString('en-US', {
          hour12: false
        });
        const color = eventColors[name] ?? '';
        entry.innerHTML = \`
          <span class="shrink-0 text-gray-400">\${ts}</span>
          <code class="shrink-0 font-semibold \${color}">\${name}</code>
          <span class="truncate text-gray-700">\${escapeHtml(JSON.stringify(detail))}</span>
        \`;
        logEl.prepend(entry);
      };
      uploadEl.addEventListener('btu-upload-file-added', ((e: CustomEvent<{
        id: string;
        file: File;
      }>) => {
        appendLog('btu-upload-file-added', {
          id: e.detail.id,
          name: e.detail.file.name,
          size: e.detail.file.size
        });
        simulateUpload(uploadEl, e.detail.id);
      }) as EventListener);
      uploadEl.addEventListener('btu-upload-file-removed', ((e: CustomEvent<{
        id: string;
        file: File;
      }>) => {
        appendLog('btu-upload-file-removed', {
          id: e.detail.id,
          name: e.detail.file.name
        });
      }) as EventListener);
      uploadEl.addEventListener('btu-upload-file-retry', ((e: CustomEvent<{
        id: string;
        file: File;
      }>) => {
        appendLog('btu-upload-file-retry', {
          id: e.detail.id,
          name: e.detail.file.name
        });
        simulateUpload(uploadEl, e.detail.id, 0); // retry always succeeds
      }) as EventListener);
      uploadEl.addEventListener('btu-upload-file-rejected', ((e: CustomEvent<{
        file: File;
        reason: 'type' | 'size';
      }>) => {
        appendLog('btu-upload-file-rejected', {
          name: e.detail.file.name,
          reason: e.detail.reason,
          size: e.detail.file.size
        });
      }) as EventListener);
      uploadEl.addEventListener('btu-upload-file-completed', ((e: CustomEvent<{
        id: string;
        file: File;
      }>) => {
        appendLog('btu-upload-file-completed', {
          id: e.detail.id,
          name: e.detail.file.name
        });
      }) as EventListener);
    }, 100);
    return html\`
      <div id="\${containerId}" class="flex flex-col gap-4">
        <btu-upload
          style=\${styleMap(cssPropStyles(args))}
          accept="\${args.accept || ''}"
          max-file-size="\${args['max-file-size'] || 0}"
          max-files="\${ifDefined(args['max-files'] as number | undefined)}"
          ?disabled="\${args.disabled}"
          ?no-drag="\${args['no-drag']}"
        ></btu-upload>
        <div class="rounded-md border border-gray-200 bg-gray-25 p-4">
          <div class="mb-2 text-xs font-semibold uppercase tracking-wider text-gray-500">Event Log</div>
          <div id="\${logId}" class="max-h-64 overflow-y-auto font-mono text-xs">
            <div class="log-placeholder italic text-gray-400">No events yet. Drop files or click to upload.</div>
          </div>
        </div>
      </div>
    \`;
  },
  parameters: {
    docs: {
      description: {
        story: 'Live log of all five public events: \`btu-upload-file-added\`, \`btu-upload-file-removed\`, \`btu-upload-file-retry\`, \`btu-upload-file-rejected\`, \`btu-upload-file-completed\`. Accepts images and PDFs up to 5 MB — drop a \`.txt\` file or an oversized PDF to trigger \`rejected\`. Added files always fail on first attempt (surfacing the "Try again" retry UX), and the retry always succeeds — so every upload exercises the full lifecycle: added → error → retry → completed.'
      }
    }
  }
}`,...f.parameters?.docs?.source},description:{story:`Interactive demo with a live log of every public event fired by the component.

Drop unsupported types or oversized files to see \`btu-upload-file-rejected\` entries.
Add valid files to watch the full lifecycle: added → simulated upload → complete or
error → (optional) retry → (optional) remove.`,...f.parameters?.docs?.description}}};g.parameters={...g.parameters,docs:{...g.parameters?.docs,source:{originalSource:`{
  render: (args: Record<string, unknown>) => {
    const containerId = \`upload-files-\${crypto.randomUUID().slice(0, 8)}\`;
    setTimeout(() => {
      const container = document.getElementById(containerId);
      const uploadEl = container?.querySelector('btu-upload') as Upload | null;
      if (!uploadEl) return;

      // Wait for the component to render
      requestAnimationFrame(() => {
        // Simulate adding files by programmatically triggering the internal flow
        const mockFiles = [{
          name: 'photo-vacation.jpg',
          type: 'image/jpeg',
          size: 4200000,
          status: 'complete' as const
        }, {
          name: 'quarterly-report.pdf',
          type: 'application/pdf',
          size: 16000000,
          status: 'uploading' as const,
          progress: 40
        }, {
          name: 'intro-video.mp4',
          type: 'video/mp4',
          size: 208000000,
          status: 'error' as const,
          error: 'Upload failed — server returned 503'
        }];
        for (const mock of mockFiles) {
          const file = new File([''], mock.name, {
            type: mock.type
          });
          Object.defineProperty(file, 'size', {
            value: mock.size
          });

          // Drive the component through its public imperative API. The parent-side
          // _processFiles path wants a DataTransfer-shaped payload, which can't be
          // faked here, so we reach in to add the File and then drive status via
          // the public setters. This is story-only plumbing for visual QA.
          const id = crypto.randomUUID().slice(0, 8);
          const initial: FileState = {
            id,
            file,
            status: 'pending',
            progress: 0
          };
          const internals = uploadEl as unknown as {
            _files: Map<string, FileState>;
            _milestones: Map<string, Set<number>>;
            _renderItem: (s: FileState) => void;
            requestUpdate: () => void;
          };
          internals._files.set(id, initial);
          internals._milestones.set(id, new Set());
          internals._renderItem(initial);
          internals.requestUpdate();
          if (mock.status === 'complete') {
            uploadEl.setFileStatus(id, 'complete');
          } else if (mock.status === 'error') {
            uploadEl.setFileStatus(id, 'error', mock.error);
          } else if (mock.status === 'uploading') {
            uploadEl.setFileProgress(id, mock.progress ?? 0);
          }
        }
      });
    }, 200);
    return html\`
      <div id="\${containerId}">
        <btu-upload style=\${styleMap(cssPropStyles(args))}></btu-upload>
      </div>
    \`;
  }
}`,...g.parameters?.docs?.source},description:{story:`Pre-seeded with files in mixed states: complete, uploading, and error.
Shows all icon variants across diverse MIME types.`,...g.parameters?.docs?.description}}};b.parameters={...b.parameters,docs:{...b.parameters?.docs,source:{originalSource:`{
  args: {
    'max-files': 1
  },
  parameters: {
    docs: {
      description: {
        story: 'With \`max-files="1"\`, selecting a new file silently replaces the existing one. Only one file can be present at a time.'
      }
    }
  }
}`,...b.parameters?.docs?.source},description:{story:"Single-file mode where selecting a new file replaces the existing one.",...b.parameters?.docs?.description}}};y.parameters={...y.parameters,docs:{...y.parameters?.docs,source:{originalSource:`{
  args: {
    accept: 'image/*',
    'max-file-size': 5242880,
    'max-files': 3
  },
  parameters: {
    docs: {
      description: {
        story: 'Demonstrates client-side validation. Only images are accepted, with a 5 MB size limit and a maximum of 3 files. The drop zone hides when the limit is reached. Rejected files fire \`btu-upload-file-rejected\` events.'
      }
    }
  }
}`,...y.parameters?.docs?.source},description:{story:`Validation demo with restricted file types, size limit, and file count limit.

- Accepts only images (\`image/*\`)
- Max file size: 5 MB
- Max files: 3

Rejected files fire \`btu-upload-file-rejected\` events (visible in the Actions panel).`,...y.parameters?.docs?.description}}};v.parameters={...v.parameters,docs:{...v.parameters?.docs,source:{originalSource:`{
  args: {
    disabled: true
  },
  parameters: {
    docs: {
      description: {
        story: 'A grayed-out drop zone with muted text. File selection, drag-and-drop, and all action buttons are blocked.'
      }
    }
  }
}`,...v.parameters?.docs?.source},description:{story:"Disabled state — all interaction is blocked.",...v.parameters?.docs?.description}}};h.parameters={...h.parameters,docs:{...h.parameters?.docs,source:{originalSource:`{
  args: {
    'no-drag': true
  },
  parameters: {
    docs: {
      description: {
        story: 'With \`no-drag\`, drag-and-drop is disabled. Users can still select files by clicking the drop zone or the "select" link.'
      }
    }
  }
}`,...h.parameters?.docs?.source},description:{story:"Drag-and-drop disabled — file selection via click still works.",...h.parameters?.docs?.description}}};z.parameters={...z.parameters,docs:{...z.parameters?.docs,source:{originalSource:`{
  args: {},
  render: (args: Record<string, unknown>) => {
    const styles: Record<string, string> = {
      '--upload-dropzone-bg': 'oklch(96% 0.02 260)',
      '--upload-dropzone-border-color': 'oklch(80% 0.08 260)',
      '--upload-dropzone-hover-bg': 'oklch(93% 0.04 260)',
      '--upload-dropzone-border-radius': '1rem',
      '--upload-item-border-color': 'oklch(80% 0.08 260)'
    };
    return html\`
      <btu-upload
        style=\${styleMap(styles)}
        accept="\${args.accept || ''}"
        max-file-size="\${args['max-file-size'] || 0}"
        max-files="\${ifDefined(args['max-files'] as number | undefined)}"
        ?disabled="\${args.disabled}"
        ?no-drag="\${args['no-drag']}"
      ></btu-upload>
    \`;
  },
  parameters: {
    docs: {
      description: {
        story: 'Demonstrates theming via CSS custom properties. The drop zone uses a purple-tinted background and rounded corners, and item borders match the custom palette.'
      }
    }
  }
}`,...z.parameters?.docs?.source},description:{story:"Themed upload component using CSS custom property overrides.",...z.parameters?.docs?.description}}};const j=["Default","SimulatedUpload","EventLog","WithFiles","SingleFile","Validation","Disabled","NoDrag","CSSCustomProperties"];export{z as CSSCustomProperties,u as Default,v as Disabled,f as EventLog,h as NoDrag,m as SimulatedUpload,b as SingleFile,y as Validation,g as WithFiles,j as __namedExportsOrder,T as default};
