@topgrid/grid-export 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +111 -0
- package/dist/index.cjs +408 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +138 -0
- package/dist/index.d.ts +138 -0
- package/dist/index.mjs +381 -0
- package/dist/index.mjs.map +1 -0
- package/dist/legacy/downloadExcel.cjs +128 -0
- package/dist/legacy/downloadExcel.cjs.map +1 -0
- package/dist/legacy/downloadExcel.d.cts +24 -0
- package/dist/legacy/downloadExcel.d.ts +24 -0
- package/dist/legacy/downloadExcel.mjs +106 -0
- package/dist/legacy/downloadExcel.mjs.map +1 -0
- package/dist/types-BCeqH-13.d.cts +231 -0
- package/dist/types-BCeqH-13.d.ts +231 -0
- package/package.json +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/loadKoreanFont.ts","../src/internal/getRowsByScope.ts","../src/exportToExcel.ts","../src/exportToCSV.ts","../src/exportToPdf.ts","../src/copyToClipboard.ts","../src/printGrid.ts","../src/exportRowsToExcel.ts"],"names":["XLSX","loadKoreanFont"],"mappings":";;;;;;;;;;;;;AAAA,IAAA,sBAAA,GAAA,EAAA;AAAA,QAAA,CAAA,sBAAA,EAAA;AAAA,EAAA,cAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AA0BA,eAAsB,eAAe,GAAA,EAA+B;AAQlE,EAAA,OAAA,CAAQ,IAAA;AAAA,IACN;AAAA,GAGF;AACF;AAvCA,IAAA,mBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,gCAAA,GAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACOO,SAAS,cAAA,CACd,OACA,KAAA,EACc;AACd,EAAA,IAAI,UAAU,KAAA,EAAO;AACnB,IAAA,OAAO,KAAA,CAAM,iBAAgB,CAAE,IAAA;AAAA,EACjC;AACA,EAAA,IAAI,UAAU,UAAA,EAAY;AACxB,IAAA,OAAO,KAAA,CAAM,qBAAoB,CAAE,IAAA;AAAA,EACrC;AAEA,EAAA,OAAO,KAAA,CAAM,qBAAoB,CAAE,IAAA;AACrC;;;ACPA,SAAS,kBAAkB,WAAA,EAA8B;AACvD,EAAA,IAAI,OAAO,gBAAgB,QAAA,EAAU;AACnC,IAAA,OAAO,WAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAA;AACT;AAUA,SAAS,gBAAuB,KAAA,EAG9B;AACA,EAAA,MAAM,YAAA,GAAe,MAAM,eAAA,EAAgB;AAC3C,EAAA,MAAM,SAAuB,EAAC;AAC9B,EAAA,MAAM,aAA0B,EAAC;AAEjC,EAAA,KAAA,IAAS,MAAA,GAAS,CAAA,EAAG,MAAA,GAAS,YAAA,CAAa,QAAQ,MAAA,EAAA,EAAU;AAC3D,IAAA,MAAM,KAAA,GAAQ,aAAa,MAAM,CAAA;AACjC,IAAA,MAAM,MAAiB,EAAC;AAExB,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,KAAA,MAAW,MAAA,IAAU,MAAM,OAAA,EAAS;AAClC,MAAA,IAAI,OAAO,aAAA,EAAe;AAExB,QAAA,GAAA,CAAI,KAAK,EAAE,CAAA;AAAA,MACb,CAAA,MAAO;AACL,QAAA,MAAM,IAAA,GAAO,iBAAA;AAAA,UACX,OAAO,MAAA,CAAO,MAAA,CAAO,SAAA,CAAU,MAAA,KAAW,QAAA,GACtC,MAAA,CAAO,MAAA,CAAO,SAAA,CAAU,MAAA,GACxB,MAAA,CAAO,MAAA,CAAO;AAAA,SACpB;AACA,QAAA,GAAA,CAAI,KAAK,IAAI,CAAA;AAGb,QAAA,IAAI,MAAA,CAAO,UAAU,CAAA,EAAG;AACtB,UAAA,MAAA,CAAO,IAAA,CAAK;AAAA,YACV,CAAA,EAAG,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAG,MAAA,EAAO;AAAA,YAC1B,CAAA,EAAG,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAG,MAAA,GAAS,MAAA,CAAO,UAAU,CAAA;AAAE,WAChD,CAAA;AAAA,QACH;AAAA,MACF;AACA,MAAA,MAAA,EAAA;AAAA,IACF;AAEA,IAAA,UAAA,CAAW,KAAK,GAAG,CAAA;AAAA,EACrB;AAIA,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,IAAA,KAAA,IAAS,SAAS,CAAA,EAAG,MAAA,GAAS,YAAA,CAAa,MAAA,GAAS,GAAG,MAAA,EAAA,EAAU;AAC/D,MAAA,MAAM,KAAA,GAAQ,aAAa,MAAM,CAAA;AACjC,MAAA,IAAI,MAAA,GAAS,CAAA;AACb,MAAA,KAAA,MAAW,MAAA,IAAU,MAAM,OAAA,EAAS;AAElC,QAAA,IAAI,CAAC,MAAA,CAAO,aAAA,IAAiB,MAAA,CAAO,YAAY,CAAA,EAAG;AACjD,UAAA,IAAI,MAAA,GAAS,CAAA,IAAK,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG;AACzC,YAAA,MAAA,CAAO,IAAA,CAAK;AAAA,cACV,CAAA,EAAG,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAG,MAAA,EAAO;AAAA,cAC1B,GAAG,EAAE,CAAA,EAAG,aAAa,MAAA,GAAS,CAAA,EAAG,GAAG,MAAA;AAAO,aAC5C,CAAA;AAAA,UACH;AAAA,QACF;AACA,QAAA,MAAA,EAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,YAAY,MAAA,EAAO;AAC9B;AA+BO,SAAS,aAAA,CACd,OACA,OAAA,EACM;AACN,EAAA,MAAM;AAAA,IACJ,QAAA,GAAW,aAAA;AAAA,IACX,SAAA,GAAY,QAAA;AAAA,IACZ,KAAA,GAAQ,UAAA;AAAA,IACR,aAAA,GAAgB;AAAA,GAClB,GAAI,WAAW,EAAC;AAGhB,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,KAAA,EAAO,KAAK,CAAA;AAGxC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,aAAA,KAAkB,MAAA,EAAQ;AACjD,IAAA,OAAA,CAAQ,KAAK,oGAA6C,CAAA;AAC1D,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAO,GAAI,gBAAgB,KAAK,CAAA;AAGpD,EAAA,MAAM,WAAwB,IAAA,CAAK,GAAA;AAAA,IAAI,CAAC,GAAA,KACtC,GAAA,CAAI,iBAAgB,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS;AAClC,MAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,MAAA,OAAO,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,GAAO,KAAA,GAAQ,EAAA;AAAA,IACzD,CAAC;AAAA,GACH;AAGA,EAAA,MAAM,GAAA,GAAmB,CAAC,GAAG,UAAA,EAAY,GAAG,QAAQ,CAAA;AACpD,EAAA,MAAM,EAAA,GAAUA,KAAA,CAAA,KAAA,CAAM,YAAA,CAAa,GAAG,CAAA;AAGtC,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,IAAA,EAAA,CAAG,SAAS,CAAA,GAAI,MAAA;AAAA,EAClB;AAGA,EAAA,MAAM,EAAA,GAAUA,YAAM,QAAA,EAAS;AAC/B,EAAKA,KAAA,CAAA,KAAA,CAAM,iBAAA,CAAkB,EAAA,EAAI,EAAA,EAAI,SAAS,CAAA;AAC9C,EAAA,MAAM,gBAAgB,QAAA,CAAS,QAAA,CAAS,OAAO,CAAA,GAC3C,QAAA,GACA,GAAG,QAAQ,CAAA,KAAA,CAAA;AACf,EAAKA,KAAA,CAAA,SAAA,CAAU,IAAI,aAAa,CAAA;AAClC;;;AC1JA,SAAS,cAAA,CAAe,OAAe,SAAA,EAA2B;AAChE,EAAA,MAAM,YAAA,GACJ,KAAA,CAAM,QAAA,CAAS,SAAS,KACxB,KAAA,CAAM,QAAA,CAAS,GAAG,CAAA,IAClB,MAAM,QAAA,CAAS,IAAI,CAAA,IACnB,KAAA,CAAM,SAAS,IAAI,CAAA;AACrB,EAAA,IAAI,CAAC,cAAc,OAAO,KAAA;AAC1B,EAAA,OAAO,MAAM,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,GAAI,GAAA;AAC7C;AAyBO,SAAS,WAAA,CACd,OACA,OAAA,EACM;AACN,EAAA,MAAM;AAAA,IACJ,QAAA,GAAW,YAAA;AAAA,IACX,KAAA,GAAQ,UAAA;AAAA,IACR,SAAA,GAAY,GAAA;AAAA,IACZ,aAAA,GAAgB;AAAA,GAClB,GAAI,WAAW,EAAC;AAGhB,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,KAAA,EAAO,KAAK,CAAA;AAGxC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,aAAA,KAAkB,MAAA,EAAQ;AACjD,IAAA,OAAA,CAAQ,KAAK,kGAA2C,CAAA;AACxD,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,WAAA,GAAc,MAAM,cAAA,EAAe;AACzC,EAAA,MAAM,SAAA,GAAY,WAAA,CACf,GAAA,CAAI,CAAC,CAAA,KAAM;AACV,IAAA,MAAM,SAAA,GAAY,CAAA,CAAE,MAAA,CAAO,SAAA,CAAU,MAAA;AACrC,IAAA,MAAM,OAAO,OAAO,SAAA,KAAc,QAAA,GAAW,SAAA,GAAY,EAAE,MAAA,CAAO,EAAA;AAClE,IAAA,OAAO,cAAA,CAAe,MAAM,SAAS,CAAA;AAAA,EACvC,CAAC,CAAA,CACA,IAAA,CAAK,SAAS,CAAA;AAGjB,EAAA,MAAM,WAAW,IAAA,CAAK,GAAA;AAAA,IAAI,CAAC,GAAA,KACzB,GAAA,CACG,iBAAgB,CAChB,GAAA,CAAI,CAAC,IAAA,KAAS;AACb,MAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,MAAA,MAAM,MACJ,KAAA,KAAU,IAAA,IAAQ,UAAU,MAAA,GAAY,MAAA,CAAO,KAAK,CAAA,GAAI,EAAA;AAC1D,MAAA,OAAO,cAAA,CAAe,KAAK,SAAS,CAAA;AAAA,IACtC,CAAC,CAAA,CACA,IAAA,CAAK,SAAS;AAAA,GACnB;AAGA,EAAA,MAAM,KAAA,GAAQ,CAAC,SAAA,EAAW,GAAG,QAAQ,CAAA;AACrC,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA;AAGnC,EAAA,MAAM,GAAA,GAAM,QAAA;AACZ,EAAA,MAAM,OAAO,IAAI,IAAA,CAAK,CAAC,GAAA,GAAM,SAAS,CAAA,EAAG;AAAA,IACvC,IAAA,EAAM;AAAA,GACP,CAAA;AACD,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACpC,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,GAAG,CAAA;AACvC,EAAA,IAAA,CAAK,IAAA,GAAO,GAAA;AAGZ,EAAA,MAAM,aAAA,GACJ,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,IAAK,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,GACjD,QAAA,GACA,CAAA,EAAG,QAAQ,CAAA,IAAA,CAAA;AACjB,EAAA,IAAA,CAAK,QAAA,GAAW,aAAA;AAChB,EAAA,IAAA,CAAK,KAAA,EAAM;AACX,EAAA,GAAA,CAAI,gBAAgB,GAAG,CAAA;AACzB;;;AC3EA,eAAsB,WAAA,CACpB,OACA,OAAA,EACe;AACf,EAAA,MAAM;AAAA,IACJ,QAAA,GAAW,YAAA;AAAA,IACX,KAAA;AAAA,IACA,KAAA,GAAQ,UAAA;AAAA,IACR,aAAA,GAAgB,MAAA;AAAA,IAChB,WAAA,GAAc,GAAA;AAAA,IACd,UAAA,GAAa;AAAA,GACf,GAAI,WAAW,EAAC;AAGhB,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,OAAO,OAAO,CAAA;AAChC,IAAA,KAAA,GAAQ,GAAA,CAAI,OAAA;AAAA,EACd,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,iBAAiB,CAAA;AAAA,EAChC,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAGA,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,KAAA,EAAO,KAAK,CAAA;AACxC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,aAAA,KAAkB,MAAA,EAAQ;AACjD,IAAA,OAAA,CAAQ,KAAK,kGAA2C,CAAA;AACxD,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,YAAA,GAAe,MAAM,eAAA,EAAgB;AAC3C,EAAA,MAAM,OAAmB,YAAA,CAAa,GAAA;AAAA,IAAI,CAAC,EAAA,KACzC,EAAA,CAAG,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM;AACpB,MAAA,IAAI,CAAA,CAAE,eAAe,OAAO,EAAA;AAC5B,MAAA,OAAO,OAAO,CAAA,CAAE,MAAA,CAAO,SAAA,CAAU,MAAA,KAAW,QAAA,GACxC,CAAA,CAAE,MAAA,CAAO,SAAA,CAAU,MAAA,GACnB,CAAA,CAAE,MAAA,CAAO,EAAA;AAAA,IACf,CAAC;AAAA,GACH;AAGA,EAAA,MAAM,WAAA,GAAc,MAAM,cAAA,EAAe;AACzC,EAAA,MAAM,IAAA,GAAmB,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AACzC,IAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,EAAgB;AAClC,IAAA,OAAO,WAAA,CAAY,GAAA,CAAI,CAAC,EAAA,KAAO;AAC7B,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,MAAA,CAAO,EAAA,KAAO,EAAA,CAAG,MAAA,CAAO,EAAE,CAAA;AAC3D,MAAA,OAAO,OAAO,MAAA,CAAO,IAAA,CAAK,QAAA,EAAS,IAAK,EAAE,CAAA,GAAI,EAAA;AAAA,IAChD,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAGD,EAAA,MAAM,GAAA,GAAM,IAAI,KAAA,CAAM,EAAE,aAAa,IAAA,EAAM,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA;AAG/D,EAAA,IAAI,eAAe,QAAA,EAAU;AAC3B,IAAA,MAAM,EAAE,cAAA,EAAAC,eAAAA,EAAe,GAAI,MAAM,OAAA,CAAA,OAAA,EAAA,CAAA,IAAA,CAAA,OAAA,mBAAA,EAAA,EAAA,sBAAA,CAAA,CAAA;AACjC,IAAA,MAAMA,gBAAe,GAAG,CAAA;AAAA,EAC1B;AAGA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,GAAA,CAAI,IAAA,CAAK,KAAA,EAAO,EAAA,EAAI,EAAE,CAAA;AAAA,EACxB;AAIA,EAAA,GAAA,CAAI,SAAA,CAAU,EAAE,IAAA,EAAM,IAAA,EAAM,QAAQ,KAAA,GAAQ,EAAA,GAAK,IAAI,CAAA;AAGrD,EAAA,MAAM,aAAa,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,GAAI,QAAA,GAAW,GAAG,QAAQ,CAAA,IAAA,CAAA;AACrE,EAAA,GAAA,CAAI,KAAK,UAAU,CAAA;AACrB;;;ACxGA,SAAS,eAAe,KAAA,EAAuB;AAC7C,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,WAAA,EAAa,GAAG,CAAA;AACvC;AAuBA,eAAsB,eAAA,CACpB,OACA,OAAA,EACe;AACf,EAAA,MAAM,EAAE,KAAA,GAAQ,UAAA,EAAY,gBAAgB,MAAA,EAAO,GAAI,WAAW,EAAC;AAGnE,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,KAAA,EAAO,KAAK,CAAA;AAGxC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,aAAA,KAAkB,MAAA,EAAQ;AACjD,IAAA,OAAA,CAAQ,KAAK,sGAA+C,CAAA;AAC5D,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,WAAA,GAAc,MAAM,cAAA,EAAe;AACzC,EAAA,MAAM,SAAA,GAAY,WAAA,CACf,GAAA,CAAI,CAAC,CAAA,KAAM;AACV,IAAA,MAAM,SAAA,GAAY,CAAA,CAAE,MAAA,CAAO,SAAA,CAAU,MAAA;AACrC,IAAA,MAAM,OAAO,OAAO,SAAA,KAAc,QAAA,GAAW,SAAA,GAAY,EAAE,MAAA,CAAO,EAAA;AAClE,IAAA,OAAO,eAAe,IAAI,CAAA;AAAA,EAC5B,CAAC,CAAA,CACA,IAAA,CAAK,GAAI,CAAA;AAGZ,EAAA,MAAM,WAAW,IAAA,CAAK,GAAA;AAAA,IAAI,CAAC,GAAA,KACzB,GAAA,CACG,iBAAgB,CAChB,GAAA,CAAI,CAAC,IAAA,KAAS;AACb,MAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,MAAA,MAAM,MAAM,KAAA,KAAU,IAAA,IAAQ,UAAU,MAAA,GAAY,MAAA,CAAO,KAAK,CAAA,GAAI,EAAA;AACpE,MAAA,OAAO,eAAe,GAAG,CAAA;AAAA,IAC3B,CAAC,CAAA,CACA,IAAA,CAAK,GAAI;AAAA,GACd;AAGA,EAAA,MAAM,YAAY,CAAC,SAAA,EAAW,GAAG,QAAQ,CAAA,CAAE,KAAK,IAAI,CAAA;AAGpD,EAAA,IACE,OAAO,cAAc,WAAA,IACrB,SAAA,CAAU,aACV,OAAO,SAAA,CAAU,SAAA,CAAU,SAAA,KAAc,UAAA,EACzC;AACA,IAAA,MAAM,SAAA,CAAU,SAAA,CAAU,SAAA,CAAU,SAAS,CAAA;AAAA,EAC/C,CAAA,MAAO;AAEL,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,aAAA,CAAc,UAAU,CAAA;AAClD,IAAA,QAAA,CAAS,KAAA,GAAQ,SAAA;AACjB,IAAA,QAAA,CAAS,MAAM,QAAA,GAAW,OAAA;AAC1B,IAAA,QAAA,CAAS,MAAM,OAAA,GAAU,GAAA;AACzB,IAAA,QAAA,CAAS,IAAA,CAAK,YAAY,QAAQ,CAAA;AAClC,IAAA,QAAA,CAAS,MAAA,EAAO;AAChB,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,WAAA,CAAY,MAAM,CAAA;AAC3C,IAAA,QAAA,CAAS,IAAA,CAAK,YAAY,QAAQ,CAAA;AAClC,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,MAAM,4DAA4D,CAAA;AAAA,IAC9E;AAAA,EACF;AACF;;;AC7EO,SAAS,SAAA,CACd,OACA,OAAA,EACM;AACN,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,KAAA,GAAQ,UAAA;AAAA,IACR,WAAA,GAAc,GAAA;AAAA,IACd,aAAA,GAAgB;AAAA,GAClB,GAAI,WAAW,EAAC;AAGhB,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,KAAA,EAAO,KAAK,CAAA;AAGxC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,aAAA,KAAkB,MAAA,EAAQ;AACjD,IAAA,OAAA,CAAQ,KAAK,gGAAyC,CAAA;AACtD,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,WAAA,GAAc,MAAM,cAAA,EAAe;AACzC,EAAA,MAAM,UAAA,GAAa,WAAA,CAChB,GAAA,CAAI,CAAC,CAAA,KAAM;AACV,IAAA,MAAM,SAAA,GAAY,CAAA,CAAE,MAAA,CAAO,SAAA,CAAU,MAAA;AACrC,IAAA,MAAM,OAAO,OAAO,SAAA,KAAc,QAAA,GAAW,SAAA,GAAY,EAAE,MAAA,CAAO,EAAA;AAClE,IAAA,OAAO,OAAO,IAAI,CAAA,KAAA,CAAA;AAAA,EACpB,CAAC,CAAA,CACA,IAAA,CAAK,EAAE,CAAA;AAGV,EAAA,MAAM,QAAA,GAAW,IAAA,CACd,GAAA,CAAI,CAAC,GAAA,KAAQ;AACZ,IAAA,MAAM,QAAQ,GAAA,CACX,eAAA,EAAgB,CAChB,GAAA,CAAI,CAAC,IAAA,KAAS;AACb,MAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,MAAA,MAAM,MAAM,KAAA,KAAU,IAAA,IAAQ,UAAU,MAAA,GAAY,MAAA,CAAO,KAAK,CAAA,GAAI,EAAA;AACpE,MAAA,OAAO,OAAO,GAAG,CAAA,KAAA,CAAA;AAAA,IACnB,CAAC,CAAA,CACA,IAAA,CAAK,EAAE,CAAA;AACV,IAAA,OAAO,OAAO,KAAK,CAAA,KAAA,CAAA;AAAA,EACrB,CAAC,CAAA,CACA,IAAA,CAAK,EAAE,CAAA;AAGV,EAAA,MAAM,cAAA,GAAiB,WAAA,KAAgB,GAAA,GAAM,WAAA,GAAc,UAAA;AAC3D,EAAA,MAAM,SAAA,GAAY,KAAA,GAAQ,CAAA,IAAA,EAAO,KAAK,CAAA,KAAA,CAAA,GAAU,EAAA;AAEhD,EAAA,MAAM,IAAA,GAAO,CAAA;AAAA;AAAA;AAAA;AAAA,OAAA,EAIN,SAAS,EAAE,CAAA;AAAA;AAAA,gBAAA,EAEF,cAAc,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY9B,SAAS;AAAA;AAAA,aAAA,EAEI,UAAU,CAAA;AAAA,SAAA,EACd,QAAQ,CAAA;AAAA;AAAA;AAAA,OAAA,CAAA;AAMjB,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,EAAA,EAAI,QAAQ,CAAA;AACtC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN;AAAA,KACF;AACA,IAAA;AAAA,EACF;AAKA,EAAA,KAAA,CAAM,SAAS,MAAM;AACnB,IAAA,KAAA,CAAM,KAAA,EAAM;AACZ,IAAA,KAAA,CAAM,KAAA,EAAM;AAAA,EACd,CAAA;AAEA,EAAA,KAAA,CAAM,QAAA,CAAS,MAAM,IAAI,CAAA;AACzB,EAAA,KAAA,CAAM,SAAS,KAAA,EAAM;AACvB;AClGA,SAAS,WAAA,CAAY,OAAgB,MAAA,EAAyC;AAC5E,EAAA,IAAI,KAAA,IAAS,MAAM,OAAO,EAAA;AAC1B,EAAA,IAAI,MAAA,KAAW,MAAA,IAAU,MAAA,KAAW,UAAA,EAAY;AAC9C,IAAA,MAAM,CAAA,GAAI,IAAI,IAAA,CAAK,KAAe,CAAA;AAClC,IAAA,IAAI,MAAM,CAAA,CAAE,OAAA,EAAS,CAAA,EAAG,OAAO,OAAO,KAAK,CAAA;AAC3C,IAAA,OAAO,MAAA,KAAW,aACd,CAAA,CAAE,cAAA,CAAe,OAAO,CAAA,GACxB,CAAA,CAAE,mBAAmB,OAAO,CAAA;AAAA,EAClC;AACA,EAAA,IAAI,MAAA,KAAW,QAAA,IAAY,MAAA,KAAW,UAAA,EAAY;AAChD,IAAA,MAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AACtB,IAAA,OAAO,KAAA,CAAM,CAAC,CAAA,GAAI,KAAA,GAAQ,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,KAAA;AACT;AAiBO,SAAS,iBAAA,CACd,IAAA,EACA,OAAA,EACA,OAAA,EACM;AACN,EAAA,MAAM;AAAA,IACJ,QAAA,GAAW,aAAA;AAAA,IACX,SAAA,GAAY,QAAA;AAAA,IACZ,aAAA,GAAgB;AAAA,GAClB,GAAI,WAAW,EAAC;AAEhB,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,aAAA,KAAkB,MAAA,EAAQ;AACjD,IAAA,OAAA,CAAQ,KAAK,yFAAoF,CAAA;AACjG,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,SAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,MAAM,CAAA;AAC1C,EAAA,MAAM,WAAW,IAAA,CAAK,GAAA;AAAA,IAAI,CAAC,GAAA,KACzB,OAAA,CAAQ,GAAA,CAAI,CAAC,GAAA,KAAQ,WAAA,CAAY,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,EAAG,GAAA,CAAI,MAAM,CAAC;AAAA,GAC5D;AACA,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,KAAW,CAAA,GAAI,CAAC,MAAM,CAAA,GAAI,CAAC,MAAA,EAAQ,GAAG,QAAQ,CAAA;AAE/D,EAAA,MAAM,EAAA,GAAU,KAAA,CAAA,KAAA,CAAM,YAAA,CAAa,GAAG,CAAA;AAGtC,EAAA,EAAA,CAAG,OAAO,CAAA,GAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,GAAA,EAAK,CAAA,CAAE,KAAA,IAAS,EAAA,EAAG,CAAE,CAAA;AAIzD,EAAA,MAAM,cAAmB,KAAA,CAAA,KAAA,CAAM,YAAA,CAAa,EAAA,CAAG,MAAM,KAAK,IAAI,CAAA;AAC9D,EAAA,KAAA,IAAS,CAAA,GAAI,YAAY,CAAA,CAAE,CAAA,EAAG,KAAK,WAAA,CAAY,CAAA,CAAE,GAAG,CAAA,EAAA,EAAK;AACvD,IAAA,MAAM,WAAgB,KAAA,CAAA,KAAA,CAAM,WAAA,CAAY,EAAE,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA;AACnD,IAAA,IAAI,CAAC,EAAA,CAAG,QAAQ,CAAA,EAAG;AACnB,IAAA,EAAA,CAAG,QAAQ,CAAA,CAAE,CAAA,GAAI,EAAE,IAAA,EAAM,EAAE,IAAA,EAAM,IAAA,EAAK,EAAG,IAAA,EAAM,EAAE,OAAA,EAAS,EAAE,GAAA,EAAK,QAAA,IAAW,EAAE;AAAA,EAChF;AAGA,EAAA,MAAM,EAAA,GAAU,YAAM,QAAA,EAAS;AAC/B,EAAK,KAAA,CAAA,KAAA,CAAM,iBAAA,CAAkB,EAAA,EAAI,EAAA,EAAI,SAAS,CAAA;AAE9C,EAAA,MAAM,MAAM,QAAA,CAAS,QAAA,CAAS,OAAO,CAAA,GAAI,QAAA,GAAW,GAAG,QAAQ,CAAA,KAAA,CAAA;AAC/D,EAAK,KAAA,CAAA,SAAA,CAAU,IAAI,GAAG,CAAA;AACxB","file":"index.mjs","sourcesContent":["import type { default as jsPDFType } from 'jspdf';\r\n\r\n/**\r\n * jsPDF 인스턴스에 한국어 폰트를 등록한다.\r\n *\r\n * @param pdf - jsPDF 인스턴스\r\n *\r\n * @remarks\r\n * **⚠️ STUB 구현 (W1 리스크)**\r\n *\r\n * 실 폰트 base64 데이터가 미확보 상태이므로 현재 no-op 로 동작합니다.\r\n * `fontFamily: 'korean'` 사용 시 Helvetica(기본 폰트)로 fallback되며 한국어 글자가 깨질 수 있습니다.\r\n *\r\n * **실 구현 방법 (V1 목표)**:\r\n * 1. 폰트 라이선스 확인: NotoSansKR (OFL 1.1 — 임베딩 허용) 또는 NanumGothic (OFL 1.1)\r\n * 2. 폰트 파일을 base64로 변환: `Buffer.from(fs.readFileSync('NotoSansKR.ttf')).toString('base64')`\r\n * 3. 아래 주석 해제 + base64 문자열 삽입:\r\n * ```\r\n * const fontBase64 = '<base64-string>';\r\n * pdf.addFileToVFS('NotoSansKR.ttf', fontBase64);\r\n * pdf.addFont('NotoSansKR.ttf', 'NotoSansKR', 'normal');\r\n * pdf.setFont('NotoSansKR');\r\n * ```\r\n *\r\n * @see https://github.com/parallax/jsPDF#use-of-unicode-characters--utf-8\r\n */\r\nexport async function loadKoreanFont(pdf: jsPDFType): Promise<void> {\r\n // TODO(V1): 폰트 base64 데이터 확보 후 아래 구현 활성화\r\n // 폰트 파일 라이선스: NotoSansKR OFL 1.1 또는 NanumGothic OFL 1.1 권장\r\n // 참고: spec Section 11 W1, Section 12 V1\r\n\r\n // 현재 stub 상태 — pdf 파라미터는 V1 구현 시 사용됨\r\n void pdf;\r\n\r\n console.warn(\r\n '[grid-export] exportToPdf: fontFamily: \"korean\" 옵션은 stub 상태입니다. ' +\r\n '한국어 글자가 깨질 수 있습니다. ' +\r\n 'loadKoreanFont.ts V1 구현 완료 후 사용하세요. (spec Section 12 V1)',\r\n );\r\n}\r\n","import type { Row, Table } from '@tanstack/react-table';\r\nimport type { ExportScope } from '../types';\r\n\r\n/**\r\n * TanStack scope 에 따라 Row 배열 반환 (C-2: 표준 API만 사용)\r\n * G-001 exportToExcel.ts 에서 추출 — Excel + CSV 공유 헬퍼 (D1)\r\n */\r\nexport function getRowsByScope<TData>(\r\n table: Table<TData>,\r\n scope: ExportScope,\r\n): Row<TData>[] {\r\n if (scope === 'all') {\r\n return table.getCoreRowModel().rows;\r\n }\r\n if (scope === 'selected') {\r\n return table.getSelectedRowModel().rows;\r\n }\r\n // 'filtered' (default)\r\n return table.getFilteredRowModel().rows;\r\n}\r\n","import * as XLSX from 'xlsx';\r\nimport type { Table } from '@tanstack/react-table';\r\nimport type { ExcelExportOptions } from './types';\r\nimport { getRowsByScope } from './internal/getRowsByScope';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * 헤더 텍스트 추출 헬퍼 — 헤더 값이 string 이면 그대로, 아니면 빈 문자열\r\n */\r\nfunction resolveHeaderText(headerValue: unknown): string {\r\n if (typeof headerValue === 'string') {\r\n return headerValue;\r\n }\r\n return '';\r\n}\r\n\r\n/**\r\n * TanStack Table 의 헤더 그룹을 순회하여\r\n * - AOA(Array of Arrays) 형태의 헤더 행 배열\r\n * - xlsx merge cells 배열 (다중행 헤더 GroupColumnDef 용)\r\n * 을 반환한다.\r\n *\r\n * AC-003: header.isPlaceholder + header.colSpan 이용 → ws['!merges'] 계산\r\n */\r\nfunction buildHeaderRows<TData>(table: Table<TData>): {\r\n headerRows: unknown[][];\r\n merges: XLSX.Range[];\r\n} {\r\n const headerGroups = table.getHeaderGroups();\r\n const merges: XLSX.Range[] = [];\r\n const headerRows: unknown[][] = [];\r\n\r\n for (let rowIdx = 0; rowIdx < headerGroups.length; rowIdx++) {\r\n const group = headerGroups[rowIdx];\r\n const row: unknown[] = [];\r\n\r\n let colIdx = 0;\r\n for (const header of group.headers) {\r\n if (header.isPlaceholder) {\r\n // 상위 그룹 헤더의 placeholder 자식 — 빈 셀\r\n row.push('');\r\n } else {\r\n const text = resolveHeaderText(\r\n typeof header.column.columnDef.header === 'string'\r\n ? header.column.columnDef.header\r\n : header.column.id,\r\n );\r\n row.push(text);\r\n\r\n // colSpan > 1 이면 수평 merge 범위 추가 (GroupColumnDef)\r\n if (header.colSpan > 1) {\r\n merges.push({\r\n s: { r: rowIdx, c: colIdx },\r\n e: { r: rowIdx, c: colIdx + header.colSpan - 1 },\r\n });\r\n }\r\n }\r\n colIdx++;\r\n }\r\n\r\n headerRows.push(row);\r\n }\r\n\r\n // 헤더 그룹이 2행 이상이면 하위 행 리프 헤더를 상위 행에서 수직 merge\r\n // (상위 행의 비-placeholder 단일 리프 헤더는 rowspan으로 처리)\r\n if (headerGroups.length > 1) {\r\n for (let rowIdx = 0; rowIdx < headerGroups.length - 1; rowIdx++) {\r\n const group = headerGroups[rowIdx];\r\n let colIdx = 0;\r\n for (const header of group.headers) {\r\n // isPlaceholder false 이고 colSpan == 1 이면 이 컬럼은 리프 → 수직 merge\r\n if (!header.isPlaceholder && header.colSpan === 1) {\r\n if (rowIdx + 1 <= headerGroups.length - 1) {\r\n merges.push({\r\n s: { r: rowIdx, c: colIdx },\r\n e: { r: headerGroups.length - 1, c: colIdx },\r\n });\r\n }\r\n }\r\n colIdx++;\r\n }\r\n }\r\n }\r\n\r\n return { headerRows, merges };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public API\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * TanStack Table 인스턴스를 기반으로 Excel(.xlsx) 파일을 생성·다운로드한다.\r\n *\r\n * @param table - TanStack v8 Table<TData> 인스턴스 (useReactTable 반환값)\r\n * @param options - Excel export 옵션 (fileName, sheetName, scope, emptyBehavior)\r\n * @returns void (동기 실행 — xlsx.writeFile 동기 API, D3)\r\n *\r\n * @remarks\r\n * **대용량 데이터 경고**: scope='all' 또는 대용량 필터 결과(>10,000행) 시\r\n * xlsx.writeFile 이 동기 실행되어 브라우저 메인 스레드를 블로킹할 수 있습니다.\r\n * 대용량 사용 시 Web Worker 래핑 권장 (EC-05).\r\n *\r\n * @example\r\n * // 기본 사용 (filtered 행)\r\n * exportToExcel(table, { fileName: '데이터.xlsx' });\r\n *\r\n * @example\r\n * // 선택 행 + 다중행 헤더\r\n * exportToExcel(table, {\r\n * fileName: '선택데이터.xlsx',\r\n * sheetName: '선택목록',\r\n * scope: 'selected',\r\n * emptyBehavior: 'empty',\r\n * });\r\n */\r\nexport function exportToExcel<TData>(\r\n table: Table<TData>,\r\n options?: ExcelExportOptions,\r\n): void {\r\n const {\r\n fileName = 'export.xlsx',\r\n sheetName = 'Sheet1',\r\n scope = 'filtered',\r\n emptyBehavior = 'skip',\r\n } = options ?? {};\r\n\r\n // 1) 행 결정 (C-2: TanStack 표준 API만)\r\n const rows = getRowsByScope(table, scope);\r\n\r\n // 2) 빈 데이터 처리 (EC-01, EC-03)\r\n if (rows.length === 0 && emptyBehavior === 'skip') {\r\n console.warn('[grid-export] exportToExcel: 내보낼 데이터가 없습니다.');\r\n return;\r\n }\r\n\r\n // 3) 헤더 추출 (GroupColumnDef 감지 → 다중행 + merge cells, AC-003)\r\n const { headerRows, merges } = buildHeaderRows(table);\r\n\r\n // 4) 데이터 행 추출 (AC-004: 한국어 UTF-8 — xlsx aoa_to_sheet 기본 UTF-8)\r\n const dataRows: unknown[][] = rows.map((row) =>\r\n row.getVisibleCells().map((cell) => {\r\n const value = cell.getValue();\r\n return value !== undefined && value !== null ? value : '';\r\n }),\r\n );\r\n\r\n // 5) AOA sheet 생성 (헤더 + 데이터)\r\n const aoa: unknown[][] = [...headerRows, ...dataRows];\r\n const ws = XLSX.utils.aoa_to_sheet(aoa);\r\n\r\n // 6) merge cells 적용 (다중행 헤더 있을 때, AC-003)\r\n if (merges.length > 0) {\r\n ws['!merges'] = merges;\r\n }\r\n\r\n // 7) workbook + 파일 다운로드 (EC-04: fileName 확장자 자동 추가)\r\n const wb = XLSX.utils.book_new();\r\n XLSX.utils.book_append_sheet(wb, ws, sheetName);\r\n const finalFileName = fileName.endsWith('.xlsx')\r\n ? fileName\r\n : `${fileName}.xlsx`;\r\n XLSX.writeFile(wb, finalFileName);\r\n}\r\n","import type { Table } from '@tanstack/react-table';\r\nimport type { CSVExportOptions } from './types';\r\nimport { getRowsByScope } from './internal/getRowsByScope';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helper — RFC 4180 이스케이프\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * RFC 4180 §2: 구분자/큰따옴표/개행 포함 시 큰따옴표 래핑 + 내부 따옴표 이중화\r\n * (외부 라이브러리 0 — 순수 string 조작, AC-001, AC-003)\r\n */\r\nfunction escapeCsvValue(value: string, delimiter: string): string {\r\n const needsQuoting =\r\n value.includes(delimiter) ||\r\n value.includes('\"') ||\r\n value.includes('\\n') ||\r\n value.includes('\\r');\r\n if (!needsQuoting) return value;\r\n return '\"' + value.split('\"').join('\"\"') + '\"';\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public API\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * TanStack Table 인스턴스를 기반으로 CSV 파일을 생성·다운로드한다.\r\n * UTF-8 BOM() 포함 — 한국어 Excel 정상 표시 (AC-004).\r\n *\r\n * @param table TanStack v8 Table<TData> 인스턴스 (useReactTable 반환값)\r\n * @param options CSV export 옵션 (fileName, scope, delimiter, emptyBehavior)\r\n * @returns void (순수 string 조작 + createObjectURL — 외부 라이브러리 0, D5)\r\n *\r\n * @remarks\r\n * **브라우저 전용**: URL.createObjectURL / document.createElement — SSR 환경 불가.\r\n *\r\n * @example\r\n * // 기본 사용 (filtered 행, 쉼표 구분자)\r\n * exportToCSV(table, { fileName: '데이터.csv' });\r\n *\r\n * @example\r\n * // TSV + 선택 행\r\n * exportToCSV(table, { fileName: '선택.tsv', delimiter: '\\t', scope: 'selected' });\r\n */\r\nexport function exportToCSV<TData>(\r\n table: Table<TData>,\r\n options?: CSVExportOptions,\r\n): void {\r\n const {\r\n fileName = 'export.csv',\r\n scope = 'filtered',\r\n delimiter = ',',\r\n emptyBehavior = 'skip',\r\n } = options ?? {};\r\n\r\n // 1) 행 결정 (C-2: TanStack 표준 API — getRowsByScope 공유 헬퍼, D1)\r\n const rows = getRowsByScope(table, scope);\r\n\r\n // 2) 빈 데이터 처리 (EC-02)\r\n if (rows.length === 0 && emptyBehavior === 'skip') {\r\n console.warn('[grid-export] exportToCSV: 내보낼 데이터가 없습니다.');\r\n return;\r\n }\r\n\r\n // 3) 헤더 추출 — 리프 헤더만 (단일행 CSV, CSV는 다중행 헤더 미지원)\r\n const leafHeaders = table.getLeafHeaders();\r\n const headerRow = leafHeaders\r\n .map((h) => {\r\n const headerDef = h.column.columnDef.header;\r\n const text = typeof headerDef === 'string' ? headerDef : h.column.id;\r\n return escapeCsvValue(text, delimiter);\r\n })\r\n .join(delimiter);\r\n\r\n // 4) 데이터 행 추출 (EC-04: null/undefined → 빈 문자열)\r\n const dataRows = rows.map((row) =>\r\n row\r\n .getVisibleCells()\r\n .map((cell) => {\r\n const value = cell.getValue();\r\n const str =\r\n value !== null && value !== undefined ? String(value) : '';\r\n return escapeCsvValue(str, delimiter);\r\n })\r\n .join(delimiter),\r\n );\r\n\r\n // 5) CSV 문자열 조립 (AC-003 RFC 4180: CRLF 행 구분)\r\n const lines = [headerRow, ...dataRows];\r\n const csvString = lines.join('\\r\\n');\r\n\r\n // 6) BOM + Blob 생성 → 다운로드 (AC-004: UTF-8 BOM → 한국어 Excel 정상)\r\n const bom = '';\r\n const blob = new Blob([bom + csvString], {\r\n type: 'text/csv;charset=utf-8;',\r\n });\r\n const url = URL.createObjectURL(blob);\r\n const link = document.createElement('a');\r\n link.href = url;\r\n\r\n // 7) fileName 확장자 자동 추가 (EC-05: .csv 또는 .tsv 없으면 .csv 추가)\r\n const finalFileName =\r\n fileName.endsWith('.csv') || fileName.endsWith('.tsv')\r\n ? fileName\r\n : `${fileName}.csv`;\r\n link.download = finalFileName;\r\n link.click();\r\n URL.revokeObjectURL(url);\r\n}\r\n","import type { Table } from '@tanstack/react-table';\r\nimport type { PDFExportOptions } from './types';\r\nimport { getRowsByScope } from './internal/getRowsByScope';\r\n\r\n/**\r\n * TanStack Table 인스턴스를 기반으로 PDF 파일을 생성·다운로드한다.\r\n * jspdf + jspdf-autotable을 optional peer로 dynamic import하여 사용.\r\n *\r\n * @param table - TanStack v8 Table<TData> 인스턴스 (useReactTable 반환값)\r\n * @param options - PDF export 옵션 (fileName, title, scope, orientation, fontFamily, emptyBehavior)\r\n * @returns Promise<void> — jspdf dynamic import 후 완료\r\n * @throws Error jspdf 또는 jspdf-autotable이 설치되지 않은 경우\r\n *\r\n * @remarks\r\n * **peer 설치 필요**: jspdf + jspdf-autotable은 optional peerDependency.\r\n * 사용 전 `npm install jspdf jspdf-autotable` 실행 필요.\r\n *\r\n * **한국어 폰트**: `fontFamily: 'korean'` 옵션은 W1 리스크 (loadKoreanFont.ts stub 상태).\r\n * 실 폰트 base64 데이터 확보 + 라이선스 확인 후 loadKoreanFont.ts 구현 완료 필요.\r\n *\r\n * @example\r\n * // 기본 사용 (portrait, filtered, Helvetica)\r\n * await exportToPdf(table, { fileName: '보고서.pdf' });\r\n *\r\n * @example\r\n * // 가로 방향 + 전체 행 + 제목\r\n * await exportToPdf(table, {\r\n * fileName: '전체데이터.pdf',\r\n * title: '2026년 데이터 목록',\r\n * scope: 'all',\r\n * orientation: 'l',\r\n * emptyBehavior: 'empty',\r\n * });\r\n */\r\nexport async function exportToPdf<TData>(\r\n table: Table<TData>,\r\n options?: PDFExportOptions,\r\n): Promise<void> {\r\n const {\r\n fileName = 'export.pdf',\r\n title,\r\n scope = 'filtered',\r\n emptyBehavior = 'skip',\r\n orientation = 'p',\r\n fontFamily = 'default',\r\n } = options ?? {};\r\n\r\n // 1. jspdf dynamic import (optional peer — 미설치 시 명확한 Error)\r\n let jsPDF: Awaited<typeof import('jspdf')>['default'];\r\n try {\r\n const mod = await import('jspdf');\r\n jsPDF = mod.default;\r\n } catch {\r\n throw new Error(\r\n '[exportToPdf] jspdf is not installed. Run: npm install jspdf jspdf-autotable',\r\n );\r\n }\r\n\r\n // 2. jspdf-autotable dynamic import (optional peer — 미설치 시 명확한 Error)\r\n try {\r\n await import('jspdf-autotable');\r\n } catch {\r\n throw new Error(\r\n '[exportToPdf] jspdf-autotable is not installed. Run: npm install jspdf jspdf-autotable',\r\n );\r\n }\r\n\r\n // 3. 행 수집 (getRowsByScope 재사용 — G-002 추출 헬퍼, D1)\r\n const rows = getRowsByScope(table, scope);\r\n if (rows.length === 0 && emptyBehavior === 'skip') {\r\n console.warn('[grid-export] exportToPdf: 내보낼 데이터가 없습니다.');\r\n return;\r\n }\r\n\r\n // 4. 다중행 헤더 구성 (AC-005: isPlaceholder + colSpan 처리)\r\n const headerGroups = table.getHeaderGroups();\r\n const head: string[][] = headerGroups.map((hg) =>\r\n hg.headers.map((h) => {\r\n if (h.isPlaceholder) return '';\r\n return typeof h.column.columnDef.header === 'string'\r\n ? h.column.columnDef.header\r\n : h.column.id;\r\n }),\r\n );\r\n\r\n // 5. 데이터 행 구성 (리프 헤더 순서 기준 — D7)\r\n const leafHeaders = table.getLeafHeaders();\r\n const body: string[][] = rows.map((row) => {\r\n const cells = row.getVisibleCells();\r\n return leafHeaders.map((lh) => {\r\n const cell = cells.find((c) => c.column.id === lh.column.id);\r\n return cell ? String(cell.getValue() ?? '') : '';\r\n });\r\n });\r\n\r\n // 6. jsPDF 인스턴스 생성\r\n const doc = new jsPDF({ orientation, unit: 'pt', format: 'a4' });\r\n\r\n // 7. 한국어 폰트 로드 (fontFamily === 'korean' 시 dynamic import)\r\n if (fontFamily === 'korean') {\r\n const { loadKoreanFont } = await import('./internal/loadKoreanFont');\r\n await loadKoreanFont(doc);\r\n }\r\n\r\n // 8. title 행 (있으면)\r\n if (title) {\r\n doc.text(title, 14, 20);\r\n }\r\n\r\n // 9. autoTable 렌더링\r\n // @ts-expect-error jspdf-autotable extends jsPDF prototype at runtime (W2 — see spec Section 11)\r\n doc.autoTable({ head, body, startY: title ? 30 : 14 });\r\n\r\n // 10. 파일명 정규화 + 다운로드\r\n const normalized = fileName.endsWith('.pdf') ? fileName : `${fileName}.pdf`;\r\n doc.save(normalized);\r\n}\r\n","import type { Table } from '@tanstack/react-table';\r\nimport type { ClipboardOptions } from './types';\r\nimport { getRowsByScope } from './internal/getRowsByScope';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helper — TSV 이스케이프\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * TSV 셀 값 이스케이프: 탭/개행/캐리지리턴 → 공백 치환 (D5)\r\n * TSV는 RFC 표준 quoting 없음 — delimiter(탭) 포함 값은 공백으로 대체가 Excel 호환 최우선 전략.\r\n */\r\nfunction escapeTsvValue(value: string): string {\r\n return value.replace(/[\\t\\r\\n]/g, ' ');\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public API\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * TanStack Table 데이터를 TSV 포맷으로 클립보드에 복사한다.\r\n * TSV(탭 구분, 줄바꿈 행 구분) — Excel 붙여넣기 호환.\r\n *\r\n * navigator.clipboard 미지원 환경: document.execCommand('copy') fallback 시도.\r\n * fallback도 실패 시 Error('[grid-export] copyToClipboard: Clipboard API not supported') throw.\r\n *\r\n * @param table TanStack v8 Table<TData> 인스턴스 (useReactTable 반환값)\r\n * @param options 클립보드 복사 옵션 (scope, emptyBehavior)\r\n * @returns Promise<void> — navigator.clipboard.writeText 는 async\r\n *\r\n * @example\r\n * await copyToClipboard(table);\r\n *\r\n * @example\r\n * await copyToClipboard(table, { scope: 'selected' });\r\n */\r\nexport async function copyToClipboard<TData>(\r\n table: Table<TData>,\r\n options?: ClipboardOptions,\r\n): Promise<void> {\r\n const { scope = 'filtered', emptyBehavior = 'skip' } = options ?? {};\r\n\r\n // 1) 행 결정 (C-2: TanStack 표준 API — getRowsByScope 공유 헬퍼, D1)\r\n const rows = getRowsByScope(table, scope);\r\n\r\n // 2) 빈 데이터 처리 (EC-03)\r\n if (rows.length === 0 && emptyBehavior === 'skip') {\r\n console.warn('[grid-export] copyToClipboard: 내보낼 데이터가 없습니다.');\r\n return;\r\n }\r\n\r\n // 3) 헤더 행 구성 — 리프 헤더만\r\n const leafHeaders = table.getLeafHeaders();\r\n const headerRow = leafHeaders\r\n .map((h) => {\r\n const headerDef = h.column.columnDef.header;\r\n const text = typeof headerDef === 'string' ? headerDef : h.column.id;\r\n return escapeTsvValue(text);\r\n })\r\n .join('\\t');\r\n\r\n // 4) 데이터 행 구성 (EC-07: null/undefined → 빈 문자열, EC-01/EC-02: 탭/개행 → 공백)\r\n const dataRows = rows.map((row) =>\r\n row\r\n .getVisibleCells()\r\n .map((cell) => {\r\n const value = cell.getValue();\r\n const str = value !== null && value !== undefined ? String(value) : '';\r\n return escapeTsvValue(str);\r\n })\r\n .join('\\t'),\r\n );\r\n\r\n // 5) TSV 문자열 조립 (헤더 + 데이터, 줄바꿈 행 구분)\r\n const tsvString = [headerRow, ...dataRows].join('\\n');\r\n\r\n // 6) 클립보드 쓰기 (navigator.clipboard 우선, execCommand fallback — D6, EC-04)\r\n if (\r\n typeof navigator !== 'undefined' &&\r\n navigator.clipboard &&\r\n typeof navigator.clipboard.writeText === 'function'\r\n ) {\r\n await navigator.clipboard.writeText(tsvString);\r\n } else {\r\n // fallback: document.execCommand('copy') — HTTP 개발 환경 또는 구형 브라우저 (EC-04)\r\n const textarea = document.createElement('textarea');\r\n textarea.value = tsvString;\r\n textarea.style.position = 'fixed';\r\n textarea.style.opacity = '0';\r\n document.body.appendChild(textarea);\r\n textarea.select();\r\n const success = document.execCommand('copy');\r\n document.body.removeChild(textarea);\r\n if (!success) {\r\n throw new Error('[grid-export] copyToClipboard: Clipboard API not supported');\r\n }\r\n }\r\n}\r\n","import type { Table } from '@tanstack/react-table';\r\nimport type { PrintOptions } from './types';\r\nimport { getRowsByScope } from './internal/getRowsByScope';\r\n\r\n/**\r\n * TanStack Table 데이터를 새 팝업 창에 HTML 테이블로 렌더링하여 인쇄 대화상자를 연다.\r\n * 순수 Web API 전용 (window.open + document.write + window.print).\r\n *\r\n * 팝업 차단 환경: console.warn 후 즉시 반환 (D7 — throw 하지 않음).\r\n * printGrid 자체는 동기 반환 (void). 실제 print 발화는 popup.onload 내에서 비동기 실행 (D4).\r\n *\r\n * @param table TanStack v8 Table<TData> 인스턴스 (useReactTable 반환값)\r\n * @param options 인쇄 옵션 (title, scope, orientation, emptyBehavior)\r\n * @returns void\r\n *\r\n * @example\r\n * printGrid(table);\r\n *\r\n * @example\r\n * printGrid(table, { title: '계약 목록', scope: 'filtered', orientation: 'l' });\r\n */\r\nexport function printGrid<TData>(\r\n table: Table<TData>,\r\n options?: PrintOptions,\r\n): void {\r\n const {\r\n title,\r\n scope = 'filtered',\r\n orientation = 'p',\r\n emptyBehavior = 'skip',\r\n } = options ?? {};\r\n\r\n // 1) 행 결정 (C-2: TanStack 표준 API — getRowsByScope 공유 헬퍼, D1)\r\n const rows = getRowsByScope(table, scope);\r\n\r\n // 2) 빈 데이터 처리 (EC-03)\r\n if (rows.length === 0 && emptyBehavior === 'skip') {\r\n console.warn('[grid-export] printGrid: 내보낼 데이터가 없습니다.');\r\n return;\r\n }\r\n\r\n // 3) 헤더 HTML 구성\r\n const leafHeaders = table.getLeafHeaders();\r\n const headerHtml = leafHeaders\r\n .map((h) => {\r\n const headerDef = h.column.columnDef.header;\r\n const text = typeof headerDef === 'string' ? headerDef : h.column.id;\r\n return `<th>${text}</th>`;\r\n })\r\n .join('');\r\n\r\n // 4) 데이터 행 HTML 구성 (EC-07: null/undefined → 빈 문자열)\r\n const bodyHtml = rows\r\n .map((row) => {\r\n const cells = row\r\n .getVisibleCells()\r\n .map((cell) => {\r\n const value = cell.getValue();\r\n const str = value !== null && value !== undefined ? String(value) : '';\r\n return `<td>${str}</td>`;\r\n })\r\n .join('');\r\n return `<tr>${cells}</tr>`;\r\n })\r\n .join('');\r\n\r\n // 5) HTML 문서 구성\r\n const orientationCss = orientation === 'l' ? 'landscape' : 'portrait';\r\n const titleHtml = title ? `<h2>${title}</h2>` : '';\r\n\r\n const html = `<!DOCTYPE html>\r\n<html>\r\n<head>\r\n<meta charset=\"utf-8\">\r\n<title>${title ?? ''}</title>\r\n<style>\r\n @page { size: ${orientationCss}; }\r\n body { font-family: sans-serif; font-size: 12px; margin: 16px; }\r\n h2 { font-size: 16px; margin-bottom: 12px; }\r\n table { border-collapse: collapse; width: 100%; }\r\n th, td { border: 1px solid #ccc; padding: 4px 8px; text-align: left; page-break-inside: avoid; }\r\n th { background: #f0f0f0; }\r\n @media print {\r\n body { margin: 0; }\r\n }\r\n</style>\r\n</head>\r\n<body>\r\n${titleHtml}\r\n<table>\r\n <thead><tr>${headerHtml}</tr></thead>\r\n <tbody>${bodyHtml}</tbody>\r\n</table>\r\n</body>\r\n</html>`;\r\n\r\n // 6) 팝업 창 열기 (EC-05: null 반환 = 팝업 차단 → D7 warn + return)\r\n const popup = window.open('', '_blank');\r\n if (!popup) {\r\n console.warn(\r\n '[grid-export] printGrid: 팝업이 차단되었습니다. 브라우저 설정에서 팝업을 허용 후 재시도하세요.',\r\n );\r\n return;\r\n }\r\n\r\n // 7) EC-06: onload 등록을 document.write **이전**에 해야 함 (Firefox/Safari 호환)\r\n // about:blank의 load 이벤트는 document.write 시점에 이미 발화될 수 있으므로\r\n // write 이후 등록 시 핸들러가 실행되지 않을 위험이 있음.\r\n popup.onload = () => {\r\n popup.print();\r\n popup.close();\r\n };\r\n\r\n popup.document.write(html);\r\n popup.document.close();\r\n}\r\n","/**\r\n * exportRowsToExcel — 행 배열 기반 Excel export (ADR-005, E-1 + F-1)\r\n *\r\n * TanStack Table 인스턴스 없이 raw row array + ExcelColumn[] 로 .xlsx 생성.\r\n * 거동 패리티 (spec §3 B1/B2/B3):\r\n * B1 — 컬럼 width: ws['!cols'] 적용 (ExcelColumn.width ?? 15)\r\n * B2 — 헤더 styling: bold + 회색 fill (F3F4F6) — note: xlsx community edition has limited style support\r\n * B3 — formatValue: date/datetime/number/currency 포맷 (ko-KR locale)\r\n *\r\n * @see ExcelColumn\r\n * @see ExportRowsOptions\r\n */\r\nimport * as XLSX from 'xlsx';\r\nimport type { ExcelColumn, ExportRowsOptions } from './types';\r\n\r\n// ── B3: 셀 값 포맷터 ──────────────────────────────────────────────────────\r\n\r\nfunction formatValue(value: unknown, format?: ExcelColumn['format']): unknown {\r\n if (value == null) return '';\r\n if (format === 'date' || format === 'datetime') {\r\n const d = new Date(value as string);\r\n if (isNaN(d.getTime())) return String(value);\r\n return format === 'datetime'\r\n ? d.toLocaleString('ko-KR')\r\n : d.toLocaleDateString('ko-KR');\r\n }\r\n if (format === 'number' || format === 'currency') {\r\n const n = Number(value);\r\n return isNaN(n) ? value : n;\r\n }\r\n return value;\r\n}\r\n\r\n// ── 공개 API ──────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * 행 배열을 Excel 파일(.xlsx)로 다운로드한다.\r\n *\r\n * TanStack `Table<TData>` 인스턴스 없이 사용 가능.\r\n * `@topgrid/grid-export` 의 `exportToExcel(table, options)` 와 평행 지원 (ADR-005 옵션 A).\r\n *\r\n * @example\r\n * exportRowsToExcel(rows, columns, { fileName: '보고서_2026.xlsx' });\r\n *\r\n * @param rows 내보낼 데이터 행 배열\r\n * @param columns 컬럼 정의 배열 (key / header / width? / format?)\r\n * @param options 파일명·시트명·emptyBehavior 옵션\r\n */\r\nexport function exportRowsToExcel<TData extends Record<string, unknown>>(\r\n rows: TData[],\r\n columns: ExcelColumn[],\r\n options?: ExportRowsOptions,\r\n): void {\r\n const {\r\n fileName = 'export.xlsx',\r\n sheetName = 'Sheet1',\r\n emptyBehavior = 'skip',\r\n } = options ?? {};\r\n\r\n if (rows.length === 0 && emptyBehavior === 'skip') {\r\n console.warn('[exportRowsToExcel] rows is empty — skipping file creation (emptyBehavior: \"skip\")');\r\n return;\r\n }\r\n\r\n // ── 헤더 + 데이터 AOA 구성 ─────────────────────────────────────────────\r\n const header = columns.map((c) => c.header);\r\n const dataRows = rows.map((row) =>\r\n columns.map((col) => formatValue(row[col.key], col.format))\r\n );\r\n const aoa = rows.length === 0 ? [header] : [header, ...dataRows];\r\n\r\n const ws = XLSX.utils.aoa_to_sheet(aoa);\r\n\r\n // ── B1: 컬럼 width ─────────────────────────────────────────────────────\r\n ws['!cols'] = columns.map((c) => ({ wch: c.width ?? 15 }));\r\n\r\n // ── B2: 헤더 행 styling (굵게 + 회색 fill) ────────────────────────────\r\n // note: xlsx community edition has limited style support\r\n const headerRange = XLSX.utils.decode_range(ws['!ref'] ?? 'A1');\r\n for (let c = headerRange.s.c; c <= headerRange.e.c; c++) {\r\n const cellAddr = XLSX.utils.encode_cell({ r: 0, c });\r\n if (!ws[cellAddr]) continue;\r\n ws[cellAddr].s = { font: { bold: true }, fill: { fgColor: { rgb: 'F3F4F6' } } };\r\n }\r\n\r\n // ── 워크북 생성 + 다운로드 ─────────────────────────────────────────────\r\n const wb = XLSX.utils.book_new();\r\n XLSX.utils.book_append_sheet(wb, ws, sheetName);\r\n\r\n const ext = fileName.endsWith('.xlsx') ? fileName : `${fileName}.xlsx`;\r\n XLSX.writeFile(wb, ext);\r\n}\r\n"]}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var XLSX = require('xlsx');
|
|
4
|
+
|
|
5
|
+
function _interopNamespace(e) {
|
|
6
|
+
if (e && e.__esModule) return e;
|
|
7
|
+
var n = Object.create(null);
|
|
8
|
+
if (e) {
|
|
9
|
+
Object.keys(e).forEach(function (k) {
|
|
10
|
+
if (k !== 'default') {
|
|
11
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return e[k]; }
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
n.default = e;
|
|
20
|
+
return Object.freeze(n);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var XLSX__namespace = /*#__PURE__*/_interopNamespace(XLSX);
|
|
24
|
+
|
|
25
|
+
// src/exportToExcel.ts
|
|
26
|
+
|
|
27
|
+
// src/internal/getRowsByScope.ts
|
|
28
|
+
function getRowsByScope(table, scope) {
|
|
29
|
+
if (scope === "all") {
|
|
30
|
+
return table.getCoreRowModel().rows;
|
|
31
|
+
}
|
|
32
|
+
if (scope === "selected") {
|
|
33
|
+
return table.getSelectedRowModel().rows;
|
|
34
|
+
}
|
|
35
|
+
return table.getFilteredRowModel().rows;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/exportToExcel.ts
|
|
39
|
+
function resolveHeaderText(headerValue) {
|
|
40
|
+
if (typeof headerValue === "string") {
|
|
41
|
+
return headerValue;
|
|
42
|
+
}
|
|
43
|
+
return "";
|
|
44
|
+
}
|
|
45
|
+
function buildHeaderRows(table) {
|
|
46
|
+
const headerGroups = table.getHeaderGroups();
|
|
47
|
+
const merges = [];
|
|
48
|
+
const headerRows = [];
|
|
49
|
+
for (let rowIdx = 0; rowIdx < headerGroups.length; rowIdx++) {
|
|
50
|
+
const group = headerGroups[rowIdx];
|
|
51
|
+
const row = [];
|
|
52
|
+
let colIdx = 0;
|
|
53
|
+
for (const header of group.headers) {
|
|
54
|
+
if (header.isPlaceholder) {
|
|
55
|
+
row.push("");
|
|
56
|
+
} else {
|
|
57
|
+
const text = resolveHeaderText(
|
|
58
|
+
typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : header.column.id
|
|
59
|
+
);
|
|
60
|
+
row.push(text);
|
|
61
|
+
if (header.colSpan > 1) {
|
|
62
|
+
merges.push({
|
|
63
|
+
s: { r: rowIdx, c: colIdx },
|
|
64
|
+
e: { r: rowIdx, c: colIdx + header.colSpan - 1 }
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
colIdx++;
|
|
69
|
+
}
|
|
70
|
+
headerRows.push(row);
|
|
71
|
+
}
|
|
72
|
+
if (headerGroups.length > 1) {
|
|
73
|
+
for (let rowIdx = 0; rowIdx < headerGroups.length - 1; rowIdx++) {
|
|
74
|
+
const group = headerGroups[rowIdx];
|
|
75
|
+
let colIdx = 0;
|
|
76
|
+
for (const header of group.headers) {
|
|
77
|
+
if (!header.isPlaceholder && header.colSpan === 1) {
|
|
78
|
+
if (rowIdx + 1 <= headerGroups.length - 1) {
|
|
79
|
+
merges.push({
|
|
80
|
+
s: { r: rowIdx, c: colIdx },
|
|
81
|
+
e: { r: headerGroups.length - 1, c: colIdx }
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
colIdx++;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { headerRows, merges };
|
|
90
|
+
}
|
|
91
|
+
function exportToExcel(table, options) {
|
|
92
|
+
const {
|
|
93
|
+
fileName = "export.xlsx",
|
|
94
|
+
sheetName = "Sheet1",
|
|
95
|
+
scope = "filtered",
|
|
96
|
+
emptyBehavior = "skip"
|
|
97
|
+
} = options ?? {};
|
|
98
|
+
const rows = getRowsByScope(table, scope);
|
|
99
|
+
if (rows.length === 0 && emptyBehavior === "skip") {
|
|
100
|
+
console.warn("[grid-export] exportToExcel: \uB0B4\uBCF4\uB0BC \uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const { headerRows, merges } = buildHeaderRows(table);
|
|
104
|
+
const dataRows = rows.map(
|
|
105
|
+
(row) => row.getVisibleCells().map((cell) => {
|
|
106
|
+
const value = cell.getValue();
|
|
107
|
+
return value !== void 0 && value !== null ? value : "";
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
const aoa = [...headerRows, ...dataRows];
|
|
111
|
+
const ws = XLSX__namespace.utils.aoa_to_sheet(aoa);
|
|
112
|
+
if (merges.length > 0) {
|
|
113
|
+
ws["!merges"] = merges;
|
|
114
|
+
}
|
|
115
|
+
const wb = XLSX__namespace.utils.book_new();
|
|
116
|
+
XLSX__namespace.utils.book_append_sheet(wb, ws, sheetName);
|
|
117
|
+
const finalFileName = fileName.endsWith(".xlsx") ? fileName : `${fileName}.xlsx`;
|
|
118
|
+
XLSX__namespace.writeFile(wb, finalFileName);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/legacy/downloadExcel.ts
|
|
122
|
+
function downloadExcel(table, options) {
|
|
123
|
+
exportToExcel(table, options);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
exports.downloadExcel = downloadExcel;
|
|
127
|
+
//# sourceMappingURL=downloadExcel.cjs.map
|
|
128
|
+
//# sourceMappingURL=downloadExcel.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/internal/getRowsByScope.ts","../../src/exportToExcel.ts","../../src/legacy/downloadExcel.ts"],"names":["XLSX"],"mappings":"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","file":"downloadExcel.cjs","sourcesContent":["import type { Row, Table } from '@tanstack/react-table';\r\nimport type { ExportScope } from '../types';\r\n\r\n/**\r\n * TanStack scope 에 따라 Row 배열 반환 (C-2: 표준 API만 사용)\r\n * G-001 exportToExcel.ts 에서 추출 — Excel + CSV 공유 헬퍼 (D1)\r\n */\r\nexport function getRowsByScope<TData>(\r\n table: Table<TData>,\r\n scope: ExportScope,\r\n): Row<TData>[] {\r\n if (scope === 'all') {\r\n return table.getCoreRowModel().rows;\r\n }\r\n if (scope === 'selected') {\r\n return table.getSelectedRowModel().rows;\r\n }\r\n // 'filtered' (default)\r\n return table.getFilteredRowModel().rows;\r\n}\r\n","import * as XLSX from 'xlsx';\r\nimport type { Table } from '@tanstack/react-table';\r\nimport type { ExcelExportOptions } from './types';\r\nimport { getRowsByScope } from './internal/getRowsByScope';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * 헤더 텍스트 추출 헬퍼 — 헤더 값이 string 이면 그대로, 아니면 빈 문자열\r\n */\r\nfunction resolveHeaderText(headerValue: unknown): string {\r\n if (typeof headerValue === 'string') {\r\n return headerValue;\r\n }\r\n return '';\r\n}\r\n\r\n/**\r\n * TanStack Table 의 헤더 그룹을 순회하여\r\n * - AOA(Array of Arrays) 형태의 헤더 행 배열\r\n * - xlsx merge cells 배열 (다중행 헤더 GroupColumnDef 용)\r\n * 을 반환한다.\r\n *\r\n * AC-003: header.isPlaceholder + header.colSpan 이용 → ws['!merges'] 계산\r\n */\r\nfunction buildHeaderRows<TData>(table: Table<TData>): {\r\n headerRows: unknown[][];\r\n merges: XLSX.Range[];\r\n} {\r\n const headerGroups = table.getHeaderGroups();\r\n const merges: XLSX.Range[] = [];\r\n const headerRows: unknown[][] = [];\r\n\r\n for (let rowIdx = 0; rowIdx < headerGroups.length; rowIdx++) {\r\n const group = headerGroups[rowIdx];\r\n const row: unknown[] = [];\r\n\r\n let colIdx = 0;\r\n for (const header of group.headers) {\r\n if (header.isPlaceholder) {\r\n // 상위 그룹 헤더의 placeholder 자식 — 빈 셀\r\n row.push('');\r\n } else {\r\n const text = resolveHeaderText(\r\n typeof header.column.columnDef.header === 'string'\r\n ? header.column.columnDef.header\r\n : header.column.id,\r\n );\r\n row.push(text);\r\n\r\n // colSpan > 1 이면 수평 merge 범위 추가 (GroupColumnDef)\r\n if (header.colSpan > 1) {\r\n merges.push({\r\n s: { r: rowIdx, c: colIdx },\r\n e: { r: rowIdx, c: colIdx + header.colSpan - 1 },\r\n });\r\n }\r\n }\r\n colIdx++;\r\n }\r\n\r\n headerRows.push(row);\r\n }\r\n\r\n // 헤더 그룹이 2행 이상이면 하위 행 리프 헤더를 상위 행에서 수직 merge\r\n // (상위 행의 비-placeholder 단일 리프 헤더는 rowspan으로 처리)\r\n if (headerGroups.length > 1) {\r\n for (let rowIdx = 0; rowIdx < headerGroups.length - 1; rowIdx++) {\r\n const group = headerGroups[rowIdx];\r\n let colIdx = 0;\r\n for (const header of group.headers) {\r\n // isPlaceholder false 이고 colSpan == 1 이면 이 컬럼은 리프 → 수직 merge\r\n if (!header.isPlaceholder && header.colSpan === 1) {\r\n if (rowIdx + 1 <= headerGroups.length - 1) {\r\n merges.push({\r\n s: { r: rowIdx, c: colIdx },\r\n e: { r: headerGroups.length - 1, c: colIdx },\r\n });\r\n }\r\n }\r\n colIdx++;\r\n }\r\n }\r\n }\r\n\r\n return { headerRows, merges };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public API\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * TanStack Table 인스턴스를 기반으로 Excel(.xlsx) 파일을 생성·다운로드한다.\r\n *\r\n * @param table - TanStack v8 Table<TData> 인스턴스 (useReactTable 반환값)\r\n * @param options - Excel export 옵션 (fileName, sheetName, scope, emptyBehavior)\r\n * @returns void (동기 실행 — xlsx.writeFile 동기 API, D3)\r\n *\r\n * @remarks\r\n * **대용량 데이터 경고**: scope='all' 또는 대용량 필터 결과(>10,000행) 시\r\n * xlsx.writeFile 이 동기 실행되어 브라우저 메인 스레드를 블로킹할 수 있습니다.\r\n * 대용량 사용 시 Web Worker 래핑 권장 (EC-05).\r\n *\r\n * @example\r\n * // 기본 사용 (filtered 행)\r\n * exportToExcel(table, { fileName: '데이터.xlsx' });\r\n *\r\n * @example\r\n * // 선택 행 + 다중행 헤더\r\n * exportToExcel(table, {\r\n * fileName: '선택데이터.xlsx',\r\n * sheetName: '선택목록',\r\n * scope: 'selected',\r\n * emptyBehavior: 'empty',\r\n * });\r\n */\r\nexport function exportToExcel<TData>(\r\n table: Table<TData>,\r\n options?: ExcelExportOptions,\r\n): void {\r\n const {\r\n fileName = 'export.xlsx',\r\n sheetName = 'Sheet1',\r\n scope = 'filtered',\r\n emptyBehavior = 'skip',\r\n } = options ?? {};\r\n\r\n // 1) 행 결정 (C-2: TanStack 표준 API만)\r\n const rows = getRowsByScope(table, scope);\r\n\r\n // 2) 빈 데이터 처리 (EC-01, EC-03)\r\n if (rows.length === 0 && emptyBehavior === 'skip') {\r\n console.warn('[grid-export] exportToExcel: 내보낼 데이터가 없습니다.');\r\n return;\r\n }\r\n\r\n // 3) 헤더 추출 (GroupColumnDef 감지 → 다중행 + merge cells, AC-003)\r\n const { headerRows, merges } = buildHeaderRows(table);\r\n\r\n // 4) 데이터 행 추출 (AC-004: 한국어 UTF-8 — xlsx aoa_to_sheet 기본 UTF-8)\r\n const dataRows: unknown[][] = rows.map((row) =>\r\n row.getVisibleCells().map((cell) => {\r\n const value = cell.getValue();\r\n return value !== undefined && value !== null ? value : '';\r\n }),\r\n );\r\n\r\n // 5) AOA sheet 생성 (헤더 + 데이터)\r\n const aoa: unknown[][] = [...headerRows, ...dataRows];\r\n const ws = XLSX.utils.aoa_to_sheet(aoa);\r\n\r\n // 6) merge cells 적용 (다중행 헤더 있을 때, AC-003)\r\n if (merges.length > 0) {\r\n ws['!merges'] = merges;\r\n }\r\n\r\n // 7) workbook + 파일 다운로드 (EC-04: fileName 확장자 자동 추가)\r\n const wb = XLSX.utils.book_new();\r\n XLSX.utils.book_append_sheet(wb, ws, sheetName);\r\n const finalFileName = fileName.endsWith('.xlsx')\r\n ? fileName\r\n : `${fileName}.xlsx`;\r\n XLSX.writeFile(wb, finalFileName);\r\n}\r\n","import type { Table } from '@tanstack/react-table';\r\nimport type { DownloadExcelOptions } from '../types';\r\nimport { exportToExcel } from '../exportToExcel';\r\n\r\n/**\r\n * DataTable `buttonInfo.downloadAction` 마이그레이션 호환 alias.\r\n *\r\n * 내부적으로 `exportToExcel(table, options)` 에 위임한다.\r\n * scope 기본값은 'filtered' (현재 필터/정렬 반영 행).\r\n *\r\n * @param table - TanStack v8 Table<TData> 인스턴스\r\n * @param options - export 옵션 (scope 기본값: 'filtered')\r\n *\r\n * @deprecated DataTable buttonInfo.downloadAction 마이그레이션 alias.\r\n * 1 minor 버전 이상 유지 (C-6, C-23).\r\n * 신규 코드는 `exportToExcel()` 직접 사용 권장.\r\n *\r\n * @example\r\n * import { downloadExcel } from '@topgrid/grid-export/legacy';\r\n * // DataTable 기존 패턴 교체\r\n * downloadExcel(table);\r\n */\r\nexport function downloadExcel<TData>(\r\n table: Table<TData>,\r\n options?: DownloadExcelOptions,\r\n): void {\r\n // C-29 exactOptionalPropertyTypes 대응:\r\n // DownloadExcelOptions 의 optional props 를 직접 forwarding 하지 않고\r\n // options 전체를 spread 하여 exportToExcel 에 위임.\r\n // scope 기본값 'filtered' 는 exportToExcel 내부에서 처리됨.\r\n exportToExcel(table, options);\r\n}\r\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Table } from '@tanstack/react-table';
|
|
2
|
+
import { D as DownloadExcelOptions } from '../types-BCeqH-13.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* DataTable `buttonInfo.downloadAction` 마이그레이션 호환 alias.
|
|
6
|
+
*
|
|
7
|
+
* 내부적으로 `exportToExcel(table, options)` 에 위임한다.
|
|
8
|
+
* scope 기본값은 'filtered' (현재 필터/정렬 반영 행).
|
|
9
|
+
*
|
|
10
|
+
* @param table - TanStack v8 Table<TData> 인스턴스
|
|
11
|
+
* @param options - export 옵션 (scope 기본값: 'filtered')
|
|
12
|
+
*
|
|
13
|
+
* @deprecated DataTable buttonInfo.downloadAction 마이그레이션 alias.
|
|
14
|
+
* 1 minor 버전 이상 유지 (C-6, C-23).
|
|
15
|
+
* 신규 코드는 `exportToExcel()` 직접 사용 권장.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* import { downloadExcel } from '@topgrid/grid-export/legacy';
|
|
19
|
+
* // DataTable 기존 패턴 교체
|
|
20
|
+
* downloadExcel(table);
|
|
21
|
+
*/
|
|
22
|
+
declare function downloadExcel<TData>(table: Table<TData>, options?: DownloadExcelOptions): void;
|
|
23
|
+
|
|
24
|
+
export { downloadExcel };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Table } from '@tanstack/react-table';
|
|
2
|
+
import { D as DownloadExcelOptions } from '../types-BCeqH-13.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* DataTable `buttonInfo.downloadAction` 마이그레이션 호환 alias.
|
|
6
|
+
*
|
|
7
|
+
* 내부적으로 `exportToExcel(table, options)` 에 위임한다.
|
|
8
|
+
* scope 기본값은 'filtered' (현재 필터/정렬 반영 행).
|
|
9
|
+
*
|
|
10
|
+
* @param table - TanStack v8 Table<TData> 인스턴스
|
|
11
|
+
* @param options - export 옵션 (scope 기본값: 'filtered')
|
|
12
|
+
*
|
|
13
|
+
* @deprecated DataTable buttonInfo.downloadAction 마이그레이션 alias.
|
|
14
|
+
* 1 minor 버전 이상 유지 (C-6, C-23).
|
|
15
|
+
* 신규 코드는 `exportToExcel()` 직접 사용 권장.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* import { downloadExcel } from '@topgrid/grid-export/legacy';
|
|
19
|
+
* // DataTable 기존 패턴 교체
|
|
20
|
+
* downloadExcel(table);
|
|
21
|
+
*/
|
|
22
|
+
declare function downloadExcel<TData>(table: Table<TData>, options?: DownloadExcelOptions): void;
|
|
23
|
+
|
|
24
|
+
export { downloadExcel };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import * as XLSX from 'xlsx';
|
|
2
|
+
|
|
3
|
+
// src/exportToExcel.ts
|
|
4
|
+
|
|
5
|
+
// src/internal/getRowsByScope.ts
|
|
6
|
+
function getRowsByScope(table, scope) {
|
|
7
|
+
if (scope === "all") {
|
|
8
|
+
return table.getCoreRowModel().rows;
|
|
9
|
+
}
|
|
10
|
+
if (scope === "selected") {
|
|
11
|
+
return table.getSelectedRowModel().rows;
|
|
12
|
+
}
|
|
13
|
+
return table.getFilteredRowModel().rows;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/exportToExcel.ts
|
|
17
|
+
function resolveHeaderText(headerValue) {
|
|
18
|
+
if (typeof headerValue === "string") {
|
|
19
|
+
return headerValue;
|
|
20
|
+
}
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
function buildHeaderRows(table) {
|
|
24
|
+
const headerGroups = table.getHeaderGroups();
|
|
25
|
+
const merges = [];
|
|
26
|
+
const headerRows = [];
|
|
27
|
+
for (let rowIdx = 0; rowIdx < headerGroups.length; rowIdx++) {
|
|
28
|
+
const group = headerGroups[rowIdx];
|
|
29
|
+
const row = [];
|
|
30
|
+
let colIdx = 0;
|
|
31
|
+
for (const header of group.headers) {
|
|
32
|
+
if (header.isPlaceholder) {
|
|
33
|
+
row.push("");
|
|
34
|
+
} else {
|
|
35
|
+
const text = resolveHeaderText(
|
|
36
|
+
typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : header.column.id
|
|
37
|
+
);
|
|
38
|
+
row.push(text);
|
|
39
|
+
if (header.colSpan > 1) {
|
|
40
|
+
merges.push({
|
|
41
|
+
s: { r: rowIdx, c: colIdx },
|
|
42
|
+
e: { r: rowIdx, c: colIdx + header.colSpan - 1 }
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
colIdx++;
|
|
47
|
+
}
|
|
48
|
+
headerRows.push(row);
|
|
49
|
+
}
|
|
50
|
+
if (headerGroups.length > 1) {
|
|
51
|
+
for (let rowIdx = 0; rowIdx < headerGroups.length - 1; rowIdx++) {
|
|
52
|
+
const group = headerGroups[rowIdx];
|
|
53
|
+
let colIdx = 0;
|
|
54
|
+
for (const header of group.headers) {
|
|
55
|
+
if (!header.isPlaceholder && header.colSpan === 1) {
|
|
56
|
+
if (rowIdx + 1 <= headerGroups.length - 1) {
|
|
57
|
+
merges.push({
|
|
58
|
+
s: { r: rowIdx, c: colIdx },
|
|
59
|
+
e: { r: headerGroups.length - 1, c: colIdx }
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
colIdx++;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { headerRows, merges };
|
|
68
|
+
}
|
|
69
|
+
function exportToExcel(table, options) {
|
|
70
|
+
const {
|
|
71
|
+
fileName = "export.xlsx",
|
|
72
|
+
sheetName = "Sheet1",
|
|
73
|
+
scope = "filtered",
|
|
74
|
+
emptyBehavior = "skip"
|
|
75
|
+
} = options ?? {};
|
|
76
|
+
const rows = getRowsByScope(table, scope);
|
|
77
|
+
if (rows.length === 0 && emptyBehavior === "skip") {
|
|
78
|
+
console.warn("[grid-export] exportToExcel: \uB0B4\uBCF4\uB0BC \uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const { headerRows, merges } = buildHeaderRows(table);
|
|
82
|
+
const dataRows = rows.map(
|
|
83
|
+
(row) => row.getVisibleCells().map((cell) => {
|
|
84
|
+
const value = cell.getValue();
|
|
85
|
+
return value !== void 0 && value !== null ? value : "";
|
|
86
|
+
})
|
|
87
|
+
);
|
|
88
|
+
const aoa = [...headerRows, ...dataRows];
|
|
89
|
+
const ws = XLSX.utils.aoa_to_sheet(aoa);
|
|
90
|
+
if (merges.length > 0) {
|
|
91
|
+
ws["!merges"] = merges;
|
|
92
|
+
}
|
|
93
|
+
const wb = XLSX.utils.book_new();
|
|
94
|
+
XLSX.utils.book_append_sheet(wb, ws, sheetName);
|
|
95
|
+
const finalFileName = fileName.endsWith(".xlsx") ? fileName : `${fileName}.xlsx`;
|
|
96
|
+
XLSX.writeFile(wb, finalFileName);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// src/legacy/downloadExcel.ts
|
|
100
|
+
function downloadExcel(table, options) {
|
|
101
|
+
exportToExcel(table, options);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { downloadExcel };
|
|
105
|
+
//# sourceMappingURL=downloadExcel.mjs.map
|
|
106
|
+
//# sourceMappingURL=downloadExcel.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/internal/getRowsByScope.ts","../../src/exportToExcel.ts","../../src/legacy/downloadExcel.ts"],"names":[],"mappings":";;;;;AAOO,SAAS,cAAA,CACd,OACA,KAAA,EACc;AACd,EAAA,IAAI,UAAU,KAAA,EAAO;AACnB,IAAA,OAAO,KAAA,CAAM,iBAAgB,CAAE,IAAA;AAAA,EACjC;AACA,EAAA,IAAI,UAAU,UAAA,EAAY;AACxB,IAAA,OAAO,KAAA,CAAM,qBAAoB,CAAE,IAAA;AAAA,EACrC;AAEA,EAAA,OAAO,KAAA,CAAM,qBAAoB,CAAE,IAAA;AACrC;;;ACPA,SAAS,kBAAkB,WAAA,EAA8B;AACvD,EAAA,IAAI,OAAO,gBAAgB,QAAA,EAAU;AACnC,IAAA,OAAO,WAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAA;AACT;AAUA,SAAS,gBAAuB,KAAA,EAG9B;AACA,EAAA,MAAM,YAAA,GAAe,MAAM,eAAA,EAAgB;AAC3C,EAAA,MAAM,SAAuB,EAAC;AAC9B,EAAA,MAAM,aAA0B,EAAC;AAEjC,EAAA,KAAA,IAAS,MAAA,GAAS,CAAA,EAAG,MAAA,GAAS,YAAA,CAAa,QAAQ,MAAA,EAAA,EAAU;AAC3D,IAAA,MAAM,KAAA,GAAQ,aAAa,MAAM,CAAA;AACjC,IAAA,MAAM,MAAiB,EAAC;AAExB,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,KAAA,MAAW,MAAA,IAAU,MAAM,OAAA,EAAS;AAClC,MAAA,IAAI,OAAO,aAAA,EAAe;AAExB,QAAA,GAAA,CAAI,KAAK,EAAE,CAAA;AAAA,MACb,CAAA,MAAO;AACL,QAAA,MAAM,IAAA,GAAO,iBAAA;AAAA,UACX,OAAO,MAAA,CAAO,MAAA,CAAO,SAAA,CAAU,MAAA,KAAW,QAAA,GACtC,MAAA,CAAO,MAAA,CAAO,SAAA,CAAU,MAAA,GACxB,MAAA,CAAO,MAAA,CAAO;AAAA,SACpB;AACA,QAAA,GAAA,CAAI,KAAK,IAAI,CAAA;AAGb,QAAA,IAAI,MAAA,CAAO,UAAU,CAAA,EAAG;AACtB,UAAA,MAAA,CAAO,IAAA,CAAK;AAAA,YACV,CAAA,EAAG,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAG,MAAA,EAAO;AAAA,YAC1B,CAAA,EAAG,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAG,MAAA,GAAS,MAAA,CAAO,UAAU,CAAA;AAAE,WAChD,CAAA;AAAA,QACH;AAAA,MACF;AACA,MAAA,MAAA,EAAA;AAAA,IACF;AAEA,IAAA,UAAA,CAAW,KAAK,GAAG,CAAA;AAAA,EACrB;AAIA,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,IAAA,KAAA,IAAS,SAAS,CAAA,EAAG,MAAA,GAAS,YAAA,CAAa,MAAA,GAAS,GAAG,MAAA,EAAA,EAAU;AAC/D,MAAA,MAAM,KAAA,GAAQ,aAAa,MAAM,CAAA;AACjC,MAAA,IAAI,MAAA,GAAS,CAAA;AACb,MAAA,KAAA,MAAW,MAAA,IAAU,MAAM,OAAA,EAAS;AAElC,QAAA,IAAI,CAAC,MAAA,CAAO,aAAA,IAAiB,MAAA,CAAO,YAAY,CAAA,EAAG;AACjD,UAAA,IAAI,MAAA,GAAS,CAAA,IAAK,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG;AACzC,YAAA,MAAA,CAAO,IAAA,CAAK;AAAA,cACV,CAAA,EAAG,EAAE,CAAA,EAAG,MAAA,EAAQ,GAAG,MAAA,EAAO;AAAA,cAC1B,GAAG,EAAE,CAAA,EAAG,aAAa,MAAA,GAAS,CAAA,EAAG,GAAG,MAAA;AAAO,aAC5C,CAAA;AAAA,UACH;AAAA,QACF;AACA,QAAA,MAAA,EAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,YAAY,MAAA,EAAO;AAC9B;AA+BO,SAAS,aAAA,CACd,OACA,OAAA,EACM;AACN,EAAA,MAAM;AAAA,IACJ,QAAA,GAAW,aAAA;AAAA,IACX,SAAA,GAAY,QAAA;AAAA,IACZ,KAAA,GAAQ,UAAA;AAAA,IACR,aAAA,GAAgB;AAAA,GAClB,GAAI,WAAW,EAAC;AAGhB,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,KAAA,EAAO,KAAK,CAAA;AAGxC,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,aAAA,KAAkB,MAAA,EAAQ;AACjD,IAAA,OAAA,CAAQ,KAAK,oGAA6C,CAAA;AAC1D,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,EAAE,UAAA,EAAY,MAAA,EAAO,GAAI,gBAAgB,KAAK,CAAA;AAGpD,EAAA,MAAM,WAAwB,IAAA,CAAK,GAAA;AAAA,IAAI,CAAC,GAAA,KACtC,GAAA,CAAI,iBAAgB,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS;AAClC,MAAA,MAAM,KAAA,GAAQ,KAAK,QAAA,EAAS;AAC5B,MAAA,OAAO,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,GAAO,KAAA,GAAQ,EAAA;AAAA,IACzD,CAAC;AAAA,GACH;AAGA,EAAA,MAAM,GAAA,GAAmB,CAAC,GAAG,UAAA,EAAY,GAAG,QAAQ,CAAA;AACpD,EAAA,MAAM,EAAA,GAAU,IAAA,CAAA,KAAA,CAAM,YAAA,CAAa,GAAG,CAAA;AAGtC,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,IAAA,EAAA,CAAG,SAAS,CAAA,GAAI,MAAA;AAAA,EAClB;AAGA,EAAA,MAAM,EAAA,GAAU,WAAM,QAAA,EAAS;AAC/B,EAAK,IAAA,CAAA,KAAA,CAAM,iBAAA,CAAkB,EAAA,EAAI,EAAA,EAAI,SAAS,CAAA;AAC9C,EAAA,MAAM,gBAAgB,QAAA,CAAS,QAAA,CAAS,OAAO,CAAA,GAC3C,QAAA,GACA,GAAG,QAAQ,CAAA,KAAA,CAAA;AACf,EAAK,IAAA,CAAA,SAAA,CAAU,IAAI,aAAa,CAAA;AAClC;;;AChJO,SAAS,aAAA,CACd,OACA,OAAA,EACM;AAKN,EAAA,aAAA,CAAc,OAAO,OAAO,CAAA;AAC9B","file":"downloadExcel.mjs","sourcesContent":["import type { Row, Table } from '@tanstack/react-table';\r\nimport type { ExportScope } from '../types';\r\n\r\n/**\r\n * TanStack scope 에 따라 Row 배열 반환 (C-2: 표준 API만 사용)\r\n * G-001 exportToExcel.ts 에서 추출 — Excel + CSV 공유 헬퍼 (D1)\r\n */\r\nexport function getRowsByScope<TData>(\r\n table: Table<TData>,\r\n scope: ExportScope,\r\n): Row<TData>[] {\r\n if (scope === 'all') {\r\n return table.getCoreRowModel().rows;\r\n }\r\n if (scope === 'selected') {\r\n return table.getSelectedRowModel().rows;\r\n }\r\n // 'filtered' (default)\r\n return table.getFilteredRowModel().rows;\r\n}\r\n","import * as XLSX from 'xlsx';\r\nimport type { Table } from '@tanstack/react-table';\r\nimport type { ExcelExportOptions } from './types';\r\nimport { getRowsByScope } from './internal/getRowsByScope';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * 헤더 텍스트 추출 헬퍼 — 헤더 값이 string 이면 그대로, 아니면 빈 문자열\r\n */\r\nfunction resolveHeaderText(headerValue: unknown): string {\r\n if (typeof headerValue === 'string') {\r\n return headerValue;\r\n }\r\n return '';\r\n}\r\n\r\n/**\r\n * TanStack Table 의 헤더 그룹을 순회하여\r\n * - AOA(Array of Arrays) 형태의 헤더 행 배열\r\n * - xlsx merge cells 배열 (다중행 헤더 GroupColumnDef 용)\r\n * 을 반환한다.\r\n *\r\n * AC-003: header.isPlaceholder + header.colSpan 이용 → ws['!merges'] 계산\r\n */\r\nfunction buildHeaderRows<TData>(table: Table<TData>): {\r\n headerRows: unknown[][];\r\n merges: XLSX.Range[];\r\n} {\r\n const headerGroups = table.getHeaderGroups();\r\n const merges: XLSX.Range[] = [];\r\n const headerRows: unknown[][] = [];\r\n\r\n for (let rowIdx = 0; rowIdx < headerGroups.length; rowIdx++) {\r\n const group = headerGroups[rowIdx];\r\n const row: unknown[] = [];\r\n\r\n let colIdx = 0;\r\n for (const header of group.headers) {\r\n if (header.isPlaceholder) {\r\n // 상위 그룹 헤더의 placeholder 자식 — 빈 셀\r\n row.push('');\r\n } else {\r\n const text = resolveHeaderText(\r\n typeof header.column.columnDef.header === 'string'\r\n ? header.column.columnDef.header\r\n : header.column.id,\r\n );\r\n row.push(text);\r\n\r\n // colSpan > 1 이면 수평 merge 범위 추가 (GroupColumnDef)\r\n if (header.colSpan > 1) {\r\n merges.push({\r\n s: { r: rowIdx, c: colIdx },\r\n e: { r: rowIdx, c: colIdx + header.colSpan - 1 },\r\n });\r\n }\r\n }\r\n colIdx++;\r\n }\r\n\r\n headerRows.push(row);\r\n }\r\n\r\n // 헤더 그룹이 2행 이상이면 하위 행 리프 헤더를 상위 행에서 수직 merge\r\n // (상위 행의 비-placeholder 단일 리프 헤더는 rowspan으로 처리)\r\n if (headerGroups.length > 1) {\r\n for (let rowIdx = 0; rowIdx < headerGroups.length - 1; rowIdx++) {\r\n const group = headerGroups[rowIdx];\r\n let colIdx = 0;\r\n for (const header of group.headers) {\r\n // isPlaceholder false 이고 colSpan == 1 이면 이 컬럼은 리프 → 수직 merge\r\n if (!header.isPlaceholder && header.colSpan === 1) {\r\n if (rowIdx + 1 <= headerGroups.length - 1) {\r\n merges.push({\r\n s: { r: rowIdx, c: colIdx },\r\n e: { r: headerGroups.length - 1, c: colIdx },\r\n });\r\n }\r\n }\r\n colIdx++;\r\n }\r\n }\r\n }\r\n\r\n return { headerRows, merges };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Public API\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * TanStack Table 인스턴스를 기반으로 Excel(.xlsx) 파일을 생성·다운로드한다.\r\n *\r\n * @param table - TanStack v8 Table<TData> 인스턴스 (useReactTable 반환값)\r\n * @param options - Excel export 옵션 (fileName, sheetName, scope, emptyBehavior)\r\n * @returns void (동기 실행 — xlsx.writeFile 동기 API, D3)\r\n *\r\n * @remarks\r\n * **대용량 데이터 경고**: scope='all' 또는 대용량 필터 결과(>10,000행) 시\r\n * xlsx.writeFile 이 동기 실행되어 브라우저 메인 스레드를 블로킹할 수 있습니다.\r\n * 대용량 사용 시 Web Worker 래핑 권장 (EC-05).\r\n *\r\n * @example\r\n * // 기본 사용 (filtered 행)\r\n * exportToExcel(table, { fileName: '데이터.xlsx' });\r\n *\r\n * @example\r\n * // 선택 행 + 다중행 헤더\r\n * exportToExcel(table, {\r\n * fileName: '선택데이터.xlsx',\r\n * sheetName: '선택목록',\r\n * scope: 'selected',\r\n * emptyBehavior: 'empty',\r\n * });\r\n */\r\nexport function exportToExcel<TData>(\r\n table: Table<TData>,\r\n options?: ExcelExportOptions,\r\n): void {\r\n const {\r\n fileName = 'export.xlsx',\r\n sheetName = 'Sheet1',\r\n scope = 'filtered',\r\n emptyBehavior = 'skip',\r\n } = options ?? {};\r\n\r\n // 1) 행 결정 (C-2: TanStack 표준 API만)\r\n const rows = getRowsByScope(table, scope);\r\n\r\n // 2) 빈 데이터 처리 (EC-01, EC-03)\r\n if (rows.length === 0 && emptyBehavior === 'skip') {\r\n console.warn('[grid-export] exportToExcel: 내보낼 데이터가 없습니다.');\r\n return;\r\n }\r\n\r\n // 3) 헤더 추출 (GroupColumnDef 감지 → 다중행 + merge cells, AC-003)\r\n const { headerRows, merges } = buildHeaderRows(table);\r\n\r\n // 4) 데이터 행 추출 (AC-004: 한국어 UTF-8 — xlsx aoa_to_sheet 기본 UTF-8)\r\n const dataRows: unknown[][] = rows.map((row) =>\r\n row.getVisibleCells().map((cell) => {\r\n const value = cell.getValue();\r\n return value !== undefined && value !== null ? value : '';\r\n }),\r\n );\r\n\r\n // 5) AOA sheet 생성 (헤더 + 데이터)\r\n const aoa: unknown[][] = [...headerRows, ...dataRows];\r\n const ws = XLSX.utils.aoa_to_sheet(aoa);\r\n\r\n // 6) merge cells 적용 (다중행 헤더 있을 때, AC-003)\r\n if (merges.length > 0) {\r\n ws['!merges'] = merges;\r\n }\r\n\r\n // 7) workbook + 파일 다운로드 (EC-04: fileName 확장자 자동 추가)\r\n const wb = XLSX.utils.book_new();\r\n XLSX.utils.book_append_sheet(wb, ws, sheetName);\r\n const finalFileName = fileName.endsWith('.xlsx')\r\n ? fileName\r\n : `${fileName}.xlsx`;\r\n XLSX.writeFile(wb, finalFileName);\r\n}\r\n","import type { Table } from '@tanstack/react-table';\r\nimport type { DownloadExcelOptions } from '../types';\r\nimport { exportToExcel } from '../exportToExcel';\r\n\r\n/**\r\n * DataTable `buttonInfo.downloadAction` 마이그레이션 호환 alias.\r\n *\r\n * 내부적으로 `exportToExcel(table, options)` 에 위임한다.\r\n * scope 기본값은 'filtered' (현재 필터/정렬 반영 행).\r\n *\r\n * @param table - TanStack v8 Table<TData> 인스턴스\r\n * @param options - export 옵션 (scope 기본값: 'filtered')\r\n *\r\n * @deprecated DataTable buttonInfo.downloadAction 마이그레이션 alias.\r\n * 1 minor 버전 이상 유지 (C-6, C-23).\r\n * 신규 코드는 `exportToExcel()` 직접 사용 권장.\r\n *\r\n * @example\r\n * import { downloadExcel } from '@topgrid/grid-export/legacy';\r\n * // DataTable 기존 패턴 교체\r\n * downloadExcel(table);\r\n */\r\nexport function downloadExcel<TData>(\r\n table: Table<TData>,\r\n options?: DownloadExcelOptions,\r\n): void {\r\n // C-29 exactOptionalPropertyTypes 대응:\r\n // DownloadExcelOptions 의 optional props 를 직접 forwarding 하지 않고\r\n // options 전체를 spread 하여 exportToExcel 에 위임.\r\n // scope 기본값 'filtered' 는 exportToExcel 내부에서 처리됨.\r\n exportToExcel(table, options);\r\n}\r\n"]}
|