{"version":3,"file":"xlsx.cjs","names":[],"sources":["../../src/utils/xlsx.ts"],"sourcesContent":["import { zipSync, type Zippable } from \"fflate\";\n\n/** A single spreadsheet cell — a number, a string, or an empty cell. */\ntype Cell = { v: string; t: \"s\" } | { v: number; t: \"n\" } | { v: \"\"; t: \"s\" };\n\nfunction escapeXml(value: string): string {\n    return value\n        .replace(/&/g, \"&amp;\")\n        .replace(/</g, \"&lt;\")\n        .replace(/>/g, \"&gt;\")\n        .replace(/\"/g, \"&quot;\")\n        .replace(/'/g, \"&apos;\");\n}\n\nfunction colLetter(index0: number): string {\n    let n = index0 + 1;\n    let result = \"\";\n    while (n > 0) {\n        const rem = (n - 1) % 26;\n        result = String.fromCharCode(65 + rem) + result;\n        n = Math.floor((n - 1) / 26);\n    }\n    return result;\n}\n\nfunction toCell(value: string | number | null): Cell {\n    if (typeof value === \"number\") return { v: value, t: \"n\" };\n    if (value === null || value === \"\") return { v: \"\", t: \"s\" };\n    return { v: value, t: \"s\" };\n}\n\nfunction cellXml(cell: Cell, ref: string): string {\n    if (cell.t === \"n\") return `<c r=\"${ref}\" t=\"n\"><v>${cell.v}</v></c>`;\n    if (cell.v === \"\") return `<c r=\"${ref}\" t=\"inlineStr\"><is><t></t></is></c>`;\n    return `<c r=\"${ref}\" t=\"inlineStr\"><is><t xml:space=\"preserve\">${escapeXml(cell.v)}</t></is></c>`;\n}\n\nfunction rowXml(cells: readonly Cell[], rowIndex1: number): string {\n    const inner = cells.map((c, i) => cellXml(c, `${colLetter(i)}${rowIndex1}`)).join(\"\");\n    return `<row r=\"${rowIndex1}\">${inner}</row>`;\n}\n\nfunction buildSheetXml(rows: readonly (readonly Cell[])[], columnCount: number): string {\n    const dimension = `A1:${colLetter(Math.max(columnCount - 1, 0))}${rows.length}`;\n    const body = rows.map((row, i) => rowXml(row, i + 1)).join(\"\");\n    return (\n        `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n        `<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">` +\n        `<dimension ref=\"${dimension}\"/>` +\n        `<sheetData>${body}</sheetData>` +\n        `</worksheet>`\n    );\n}\n\nconst CONTENT_TYPES_XML =\n    `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n    `<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">` +\n    `<Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/>` +\n    `<Default Extension=\"xml\" ContentType=\"application/xml\"/>` +\n    `<Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/>` +\n    `<Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/>` +\n    `</Types>`;\n\nconst ROOT_RELS_XML =\n    `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n    `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n    `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/>` +\n    `</Relationships>`;\n\nconst WORKBOOK_XML =\n    `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n    `<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"` +\n    ` xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\">` +\n    `<sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets>` +\n    `</workbook>`;\n\nconst WORKBOOK_RELS_XML =\n    `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>` +\n    `<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">` +\n    `<Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/>` +\n    `</Relationships>`;\n\n/**\n * Write a minimal single-sheet Office Open XML (`.xlsx`) workbook and return\n * its bytes. No extra dependency beyond `fflate` — the archive is assembled and\n * deflated in-process.\n *\n * The output is UTF-8 throughout, so accents round-trip in\n * Excel/LibreOffice/Google Sheets without the BOM-detection fragility that\n * plagues CSV exports. The XML stays compact: inline strings (no shared-string\n * table), no styles, no merged cells. Numeric cells use the native `\"n\"` type\n * so spreadsheets recognise them as numbers; `null` renders as an empty cell.\n *\n * @param headers - Column headers written as the first row.\n * @param rows - Data rows; each value is a string, a number, or `null` (empty).\n * @returns The `.xlsx` file contents, backed by a plain `ArrayBuffer` so the\n *   bytes go straight into `new Blob([...])` — the default `Uint8Array` is\n *   `Uint8Array<ArrayBufferLike>`, which `BlobPart` rejects because it also\n *   admits `SharedArrayBuffer`.\n *\n * @example\n * const bytes = writeXlsx(\n *   [\"Name\", \"Score\"],\n *   [[\"Ada\", 99], [\"Alan\", null]],\n * );\n * const blob = new Blob([bytes], {\n *   type: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n * });\n */\nexport function writeXlsx(\n    headers: readonly string[],\n    rows: readonly (readonly (string | number | null)[])[],\n): Uint8Array<ArrayBuffer> {\n    const headerRow: Cell[] = headers.map((h) => ({ v: h, t: \"s\" }));\n    const dataRows: Cell[][] = rows.map((row) => row.map(toCell));\n    const allRows: Cell[][] = [headerRow, ...dataRows];\n    const columnCount = Math.max(headers.length, ...dataRows.map((row) => row.length), 0);\n    const sheetXml = buildSheetXml(allRows, columnCount);\n\n    const encoder = new TextEncoder();\n    const archive: Zippable = {\n        \"[Content_Types].xml\": encoder.encode(CONTENT_TYPES_XML),\n        \"_rels/.rels\": encoder.encode(ROOT_RELS_XML),\n        \"xl/workbook.xml\": encoder.encode(WORKBOOK_XML),\n        \"xl/_rels/workbook.xml.rels\": encoder.encode(WORKBOOK_RELS_XML),\n        \"xl/worksheets/sheet1.xml\": encoder.encode(sheetXml),\n    };\n    return zipSync(archive);\n}\n"],"mappings":"wBAKA,SAAS,EAAU,EAAuB,CACtC,OAAO,EACF,QAAQ,KAAM,OAAO,CAAC,CACtB,QAAQ,KAAM,MAAM,CAAC,CACrB,QAAQ,KAAM,MAAM,CAAC,CACrB,QAAQ,KAAM,QAAQ,CAAC,CACvB,QAAQ,KAAM,QAAQ,CAC/B,CAEA,SAAS,EAAU,EAAwB,CACvC,IAAI,EAAI,EAAS,EACb,EAAS,GACb,KAAO,EAAI,GAAG,CACV,IAAM,GAAO,EAAI,GAAK,GACtB,EAAS,OAAO,aAAa,GAAK,CAAG,EAAI,EACzC,EAAI,KAAK,OAAO,EAAI,GAAK,EAAE,CAC/B,CACA,OAAO,CACX,CAEA,SAAS,EAAO,EAAqC,CAGjD,OAFI,OAAO,GAAU,SAAiB,CAAE,EAAG,EAAO,EAAG,GAAI,EACrD,IAAU,MAAQ,IAAU,GAAW,CAAE,EAAG,GAAI,EAAG,GAAI,EACpD,CAAE,EAAG,EAAO,EAAG,GAAI,CAC9B,CAEA,SAAS,EAAQ,EAAY,EAAqB,CAG9C,OAFI,EAAK,IAAM,IAAY,SAAS,EAAI,aAAa,EAAK,EAAE,UACxD,EAAK,IAAM,GAAW,SAAS,EAAI,sCAChC,SAAS,EAAI,8CAA8C,EAAU,EAAK,CAAC,EAAE,cACxF,CAEA,SAAS,EAAO,EAAwB,EAA2B,CAE/D,MAAO,WAAW,EAAU,IADd,EAAM,KAAK,EAAG,IAAM,EAAQ,EAAG,GAAG,EAAU,CAAC,IAAI,GAAW,CAAC,CAAC,CAAC,KAAK,EAClD,EAAM,OAC1C,CAEA,SAAS,EAAc,EAAoC,EAA6B,CAGpF,MACI,uJAEmB,MALC,EAAU,KAAK,IAAI,EAAc,EAAG,CAAC,CAAC,IAAI,EAAK,SAKtC,gBAJpB,EAAK,KAAK,EAAK,IAAM,EAAO,EAAK,EAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAKzC,EAAK,yBAG3B,CAEA,IAAM,EACF,gjBAQE,EACF,0SAKE,EACF,8RAME,EACF,2SAgCJ,SAAgB,EACZ,EACA,EACuB,CACvB,IAAM,EAAoB,EAAQ,IAAK,IAAO,CAAE,EAAG,EAAG,EAAG,GAAI,EAAE,EACzD,EAAqB,EAAK,IAAK,GAAQ,EAAI,IAAI,CAAM,CAAC,EAGtD,EAAW,EAAc,CAFJ,EAAW,GAAG,CAEV,EADX,KAAK,IAAI,EAAQ,OAAQ,GAAG,EAAS,IAAK,GAAQ,EAAI,MAAM,EAAG,CAC3C,CAAW,EAE7C,EAAU,IAAI,YACd,EAAoB,CACtB,sBAAuB,EAAQ,OAAO,CAAiB,EACvD,cAAe,EAAQ,OAAO,CAAa,EAC3C,kBAAmB,EAAQ,OAAO,CAAY,EAC9C,6BAA8B,EAAQ,OAAO,CAAiB,EAC9D,2BAA4B,EAAQ,OAAO,CAAQ,CACvD,EACA,OAAA,EAAO,EAAA,QAAA,CAAQ,CAAO,CAC1B"}