open-grid 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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +366 -0
  3. package/dist/OpenGrid-CAodJLLm.cjs +90 -0
  4. package/dist/OpenGrid-CAodJLLm.cjs.map +1 -0
  5. package/dist/OpenGrid-CfZy3e7Q.js +4376 -0
  6. package/dist/OpenGrid-CfZy3e7Q.js.map +1 -0
  7. package/dist/open-grid-base.css +1595 -0
  8. package/dist/open-grid-react.cjs +2 -0
  9. package/dist/open-grid-react.cjs.map +1 -0
  10. package/dist/open-grid-react.js +91 -0
  11. package/dist/open-grid-react.js.map +1 -0
  12. package/dist/open-grid-themes.css +630 -0
  13. package/dist/open-grid-vue.cjs +2 -0
  14. package/dist/open-grid-vue.cjs.map +1 -0
  15. package/dist/open-grid-vue.js +84 -0
  16. package/dist/open-grid-vue.js.map +1 -0
  17. package/dist/open-grid.cjs +7 -0
  18. package/dist/open-grid.cjs.map +1 -0
  19. package/dist/open-grid.js +311 -0
  20. package/dist/open-grid.js.map +1 -0
  21. package/dist/types/bench/perf.d.ts +16 -0
  22. package/dist/types/core/CellEditManager.d.ts +46 -0
  23. package/dist/types/core/CellEventHandler.d.ts +28 -0
  24. package/dist/types/core/CellTypeRegistry.d.ts +5 -0
  25. package/dist/types/core/ColumnLayout.d.ts +41 -0
  26. package/dist/types/core/ContextMenu.d.ts +33 -0
  27. package/dist/types/core/DataLayer.d.ts +65 -0
  28. package/dist/types/core/EventEmitter.d.ts +11 -0
  29. package/dist/types/core/ExportManager.d.ts +28 -0
  30. package/dist/types/core/FilterPanel.d.ts +20 -0
  31. package/dist/types/core/FilterSelect.d.ts +96 -0
  32. package/dist/types/core/FindBarManager.d.ts +26 -0
  33. package/dist/types/core/FooterManager.d.ts +16 -0
  34. package/dist/types/core/FormulaEngine.d.ts +10 -0
  35. package/dist/types/core/GridRenderer.d.ts +42 -0
  36. package/dist/types/core/GroupEngine.d.ts +47 -0
  37. package/dist/types/core/GroupTreeManager.d.ts +43 -0
  38. package/dist/types/core/KeyboardManager.d.ts +26 -0
  39. package/dist/types/core/MaskingEngine.d.ts +25 -0
  40. package/dist/types/core/MathUtils.d.ts +26 -0
  41. package/dist/types/core/MergeEngine.d.ts +35 -0
  42. package/dist/types/core/OGDecimal.d.ts +49 -0
  43. package/dist/types/core/OpenGrid.d.ts +213 -0
  44. package/dist/types/core/OrgChart.d.ts +35 -0
  45. package/dist/types/core/Pagination.d.ts +34 -0
  46. package/dist/types/core/PivotEngine.d.ts +20 -0
  47. package/dist/types/core/RowDragDrop.d.ts +18 -0
  48. package/dist/types/core/RowManager.d.ts +30 -0
  49. package/dist/types/core/SortFilterManager.d.ts +36 -0
  50. package/dist/types/core/TreeEngine.d.ts +34 -0
  51. package/dist/types/core/TriggerManager.d.ts +10 -0
  52. package/dist/types/core/VirtualScroll.d.ts +31 -0
  53. package/dist/types/core/WorksheetManager.d.ts +24 -0
  54. package/dist/types/core/XmlConverter.d.ts +88 -0
  55. package/dist/types/core/editors/CellEditor.d.ts +55 -0
  56. package/dist/types/core/editors/DateEditor.d.ts +15 -0
  57. package/dist/types/core/editors/SelectEditor.d.ts +21 -0
  58. package/dist/types/core/renderers/CellRenderer.d.ts +138 -0
  59. package/dist/types/core/types.d.ts +497 -0
  60. package/dist/types/index.d.ts +9 -0
  61. package/dist/types/react/OpenGrid.d.ts +34 -0
  62. package/dist/types/react/index.d.ts +2 -0
  63. package/dist/types/vue/OpenGrid.vue.d.ts +80 -0
  64. package/dist/types/vue/index.d.ts +2 -0
  65. package/dist/types/vue/types.d.ts +28 -0
  66. package/dist/xlsx.min-Bx-LxWOf.cjs +138 -0
  67. package/dist/xlsx.min-Bx-LxWOf.cjs.map +1 -0
  68. package/dist/xlsx.min-Wavxcamn.js +11907 -0
  69. package/dist/xlsx.min-Wavxcamn.js.map +1 -0
  70. package/package.json +102 -0
@@ -0,0 +1,84 @@
1
+ import { defineComponent as p, ref as m, shallowRef as h, computed as g, onMounted as y, watch as d, onUnmounted as b, openBlock as v, createElementBlock as C, normalizeStyle as k } from "vue";
2
+ import { O as w } from "./OpenGrid-CfZy3e7Q.js";
3
+ const _ = /* @__PURE__ */ p({
4
+ __name: "OpenGrid",
5
+ props: {
6
+ data: { default: () => [] },
7
+ columns: {},
8
+ height: { default: 400 },
9
+ width: { default: "100%" },
10
+ editable: { type: Boolean, default: !1 },
11
+ sortable: { type: Boolean, default: !0 },
12
+ filterable: { type: Boolean, default: !0 },
13
+ rowNumber: { type: Boolean, default: !1 },
14
+ checkColumn: { type: Boolean, default: !1 },
15
+ stateColumn: { type: Boolean, default: !1 },
16
+ draggable: { type: Boolean, default: !1 },
17
+ frozenColumns: { default: 0 },
18
+ theme: { default: "default" },
19
+ options: {}
20
+ },
21
+ emits: ["update:data", "ready", "cell-click", "row-click", "edit-end", "sort-change", "filter-change", "row-check"],
22
+ setup(n, { expose: u, emit: r }) {
23
+ const e = n, o = r, c = m(), a = h(null);
24
+ let i = null;
25
+ const f = g(() => ({
26
+ height: typeof e.height == "number" ? `${e.height}px` : e.height,
27
+ width: typeof e.width == "number" ? `${e.width}px` : e.width
28
+ }));
29
+ return y(() => {
30
+ if (!c.value) return;
31
+ const l = {
32
+ columns: e.columns,
33
+ height: "100%",
34
+ width: "100%",
35
+ editable: e.editable,
36
+ sortable: e.sortable,
37
+ filterable: e.filterable,
38
+ rowNumber: e.rowNumber,
39
+ checkColumn: e.checkColumn,
40
+ stateColumn: e.stateColumn,
41
+ draggable: e.draggable,
42
+ frozenColumns: e.frozenColumns,
43
+ theme: e.theme,
44
+ ...e.options,
45
+ onReady: (t) => {
46
+ var s;
47
+ (s = e.data) != null && s.length && t.setData(e.data), o("ready", t);
48
+ },
49
+ onCellClick: (t) => o("cell-click", t),
50
+ onRowClick: (t) => o("row-click", t),
51
+ onEditEnd: (t) => o("edit-end", t),
52
+ onSortChange: (t) => o("sort-change", t),
53
+ onFilterChange: (t) => o("filter-change", t),
54
+ onDataChange: (t) => {
55
+ i = t, o("update:data", t);
56
+ }
57
+ };
58
+ a.value = new w(c.value, l);
59
+ }), d(() => e.data, (l) => {
60
+ !a.value || !l || l !== i && a.value.setData(l);
61
+ }, { deep: !1 }), d(() => e.theme, (l) => {
62
+ a.value && l && a.value.setTheme(l);
63
+ }), d(() => e.columns, (l) => {
64
+ a.value && a.value.applyColumns(l);
65
+ }, { deep: !1 }), b(() => {
66
+ var l;
67
+ (l = a.value) == null || l.destroy(), a.value = null;
68
+ }), u({ grid: a }), (l, t) => (v(), C("div", {
69
+ ref_key: "containerRef",
70
+ ref: c,
71
+ class: "og-vue-wrapper",
72
+ style: k(f.value)
73
+ }, null, 4));
74
+ }
75
+ }), B = (n, u) => {
76
+ const r = n.__vccOpts || n;
77
+ for (const [e, o] of u)
78
+ r[e] = o;
79
+ return r;
80
+ }, R = /* @__PURE__ */ B(_, [["__scopeId", "data-v-0a49d4fc"]]);
81
+ export {
82
+ R as OpenGrid
83
+ };
84
+ //# sourceMappingURL=open-grid-vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-grid-vue.js","sources":["../src/vue/OpenGrid.vue"],"sourcesContent":["<template>\n <div ref=\"containerRef\" class=\"og-vue-wrapper\" :style=\"containerStyle\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch, shallowRef, computed } from 'vue';\nimport { OpenGrid } from '../core/OpenGrid.js';\nimport type { GridOptions, OpenGridInstance } from '../core/types.js';\nimport type { OpenGridProps, OpenGridEmits } from './types.js';\nimport '../styles/base.css';\n\nconst props = withDefaults(defineProps<OpenGridProps>(), {\n data: () => [],\n height: 400,\n width: '100%',\n editable: false,\n sortable: true,\n filterable: true,\n rowNumber: false,\n checkColumn: false,\n stateColumn: false,\n draggable: false,\n frozenColumns: 0,\n theme: 'default',\n});\n\nconst emit = defineEmits<OpenGridEmits>();\n\nconst containerRef = ref<HTMLElement>();\nconst gridInstance = shallowRef<OpenGridInstance | null>(null);\n\n// dataChange 루프 방지: 그리드에서 발행한 데이터를 watch가 다시 setData하지 않도록 추적\nlet _lastEmittedData: any[] | null = null;\n\nconst containerStyle = computed(() => ({\n height: typeof props.height === 'number' ? `${props.height}px` : props.height,\n width: typeof props.width === 'number' ? `${props.width}px` : props.width,\n}));\n\nonMounted(() => {\n if (!containerRef.value) return;\n\n const options: GridOptions = {\n columns: props.columns,\n height: '100%',\n width: '100%',\n editable: props.editable,\n sortable: props.sortable,\n filterable: props.filterable,\n rowNumber: props.rowNumber,\n checkColumn: props.checkColumn,\n stateColumn: props.stateColumn,\n draggable: props.draggable,\n frozenColumns: props.frozenColumns,\n theme: props.theme,\n ...props.options,\n\n onReady: (grid) => {\n if (props.data?.length) grid.setData(props.data);\n emit('ready', grid);\n },\n onCellClick: (e) => emit('cell-click', e),\n onRowClick: (e) => emit('row-click', e),\n onEditEnd: (e) => emit('edit-end', e),\n onSortChange: (e) => emit('sort-change', e),\n onFilterChange: (e) => emit('filter-change', e),\n onDataChange: (data) => {\n _lastEmittedData = data;\n emit('update:data', data);\n },\n };\n\n gridInstance.value = new OpenGrid(containerRef.value, options);\n});\n\n// data prop 변경 감지 → 그리드 갱신 (그리드 자신이 발행한 데이터는 무시하여 루프 방지)\nwatch(() => props.data, (newData) => {\n if (!gridInstance.value || !newData) return;\n if (newData === _lastEmittedData) return;\n gridInstance.value.setData(newData);\n}, { deep: false });\n\n// theme prop 변경 감지 → setTheme 호출\nwatch(() => props.theme, (newTheme) => {\n if (gridInstance.value && newTheme) {\n gridInstance.value.setTheme(newTheme);\n }\n});\n\n// columns 변경 감지\nwatch(() => props.columns, (newCols) => {\n if (gridInstance.value) {\n gridInstance.value.applyColumns(newCols);\n }\n}, { deep: false });\n\nonUnmounted(() => {\n gridInstance.value?.destroy();\n gridInstance.value = null;\n});\n\n// 그리드 인스턴스 외부 노출\ndefineExpose({ grid: gridInstance });\n</script>\n\n<style scoped>\n.og-vue-wrapper {\n display: block;\n box-sizing: border-box;\n}\n</style>\n"],"names":["props","__props","emit","__emit","containerRef","ref","gridInstance","shallowRef","_lastEmittedData","containerStyle","computed","onMounted","options","grid","_a","e","data","OpenGrid","watch","newData","newTheme","newCols","onUnmounted","__expose","_createElementBlock"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAWA,UAAMA,IAAQC,GAeRC,IAAOC,GAEPC,IAAeC,EAAA,GACfC,IAAeC,EAAoC,IAAI;AAG7D,QAAIC,IAAiC;AAErC,UAAMC,IAAiBC,EAAS,OAAO;AAAA,MACrC,QAAQ,OAAOV,EAAM,UAAW,WAAW,GAAGA,EAAM,MAAM,OAAOA,EAAM;AAAA,MACvE,OAAO,OAAOA,EAAM,SAAU,WAAW,GAAGA,EAAM,KAAK,OAAOA,EAAM;AAAA,IAAA,EACpE;AAEF,WAAAW,EAAU,MAAM;AACd,UAAI,CAACP,EAAa,MAAO;AAEzB,YAAMQ,IAAuB;AAAA,QAC3B,SAASZ,EAAM;AAAA,QACf,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,UAAUA,EAAM;AAAA,QAChB,UAAUA,EAAM;AAAA,QAChB,YAAYA,EAAM;AAAA,QAClB,WAAWA,EAAM;AAAA,QACjB,aAAaA,EAAM;AAAA,QACnB,aAAaA,EAAM;AAAA,QACnB,WAAWA,EAAM;AAAA,QACjB,eAAeA,EAAM;AAAA,QACrB,OAAOA,EAAM;AAAA,QACb,GAAGA,EAAM;AAAA,QAET,SAAS,CAACa,MAAS;;AACjB,WAAIC,IAAAd,EAAM,SAAN,QAAAc,EAAY,UAAQD,EAAK,QAAQb,EAAM,IAAI,GAC/CE,EAAK,SAASW,CAAI;AAAA,QACpB;AAAA,QACA,aAAa,CAACE,MAAMb,EAAK,cAAca,CAAC;AAAA,QACxC,YAAY,CAACA,MAAMb,EAAK,aAAaa,CAAC;AAAA,QACtC,WAAW,CAACA,MAAMb,EAAK,YAAYa,CAAC;AAAA,QACpC,cAAc,CAACA,MAAMb,EAAK,eAAea,CAAC;AAAA,QAC1C,gBAAgB,CAACA,MAAMb,EAAK,iBAAiBa,CAAC;AAAA,QAC9C,cAAc,CAACC,MAAS;AACtB,UAAAR,IAAmBQ,GACnBd,EAAK,eAAec,CAAI;AAAA,QAC1B;AAAA,MAAA;AAGF,MAAAV,EAAa,QAAQ,IAAIW,EAASb,EAAa,OAAOQ,CAAO;AAAA,IAC/D,CAAC,GAGDM,EAAM,MAAMlB,EAAM,MAAM,CAACmB,MAAY;AACnC,MAAI,CAACb,EAAa,SAAS,CAACa,KACxBA,MAAYX,KAChBF,EAAa,MAAM,QAAQa,CAAO;AAAA,IACpC,GAAG,EAAE,MAAM,IAAO,GAGlBD,EAAM,MAAMlB,EAAM,OAAO,CAACoB,MAAa;AACrC,MAAId,EAAa,SAASc,KACxBd,EAAa,MAAM,SAASc,CAAQ;AAAA,IAExC,CAAC,GAGDF,EAAM,MAAMlB,EAAM,SAAS,CAACqB,MAAY;AACtC,MAAIf,EAAa,SACfA,EAAa,MAAM,aAAae,CAAO;AAAA,IAE3C,GAAG,EAAE,MAAM,IAAO,GAElBC,EAAY,MAAM;;AAChB,OAAAR,IAAAR,EAAa,UAAb,QAAAQ,EAAoB,WACpBR,EAAa,QAAQ;AAAA,IACvB,CAAC,GAGDiB,EAAa,EAAE,MAAMjB,GAAc,mBArGjCkB,EAAyE,OAAA;AAAA,eAAhE;AAAA,MAAJ,KAAIpB;AAAA,MAAe,OAAM;AAAA,MAAkB,SAAOK,EAAA,KAAc;AAAA,IAAA;;;;;;;;"}
@@ -0,0 +1,7 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("./OpenGrid-CAodJLLm.cjs");class C{constructor(t,s){this._data=[],this._roots=[],this._expandedKeys=new Set,this._selectedId=null,this._container=typeof t=="string"?document.querySelector(t):t,this._opts={nodeWidth:160,nodeHeight:72,levelGap:52,siblingGap:20,expandOnLoad:!0,onNodeClick:()=>{},...s},this._container.classList.add("og-orgchart")}setData(t){this._data=t;const{idField:s,parentIdField:c,expandOnLoad:o}=this._opts;o&&this._expandedKeys.size===0&&t.forEach(a=>this._expandedKeys.add(a[s])),this._roots=A.buildTree(t,{idField:s,parentIdField:c},this._expandedKeys),this._render()}setTheme(t){this._container.setAttribute("data-og-theme",t)}expandAll(){const t=s=>{for(const c of s)this._expandedKeys.add(c._treeId),c.children.length&&t(c.children)};t(this._roots),this._rebuild()}collapseAll(){this._expandedKeys.clear(),this._rebuild()}_toggle(t){this._expandedKeys.has(t)?this._expandedKeys.delete(t):this._expandedKeys.add(t),this._rebuild()}_rebuild(){const{idField:t,parentIdField:s}=this._opts;this._roots=A.buildTree(this._data,{idField:t,parentIdField:s},this._expandedKeys),this._render()}_calcLayout(){const{nodeWidth:t,nodeHeight:s,levelGap:c,siblingGap:o}=this._opts,a=new Map;let l=0;const x=f=>{const u=f._depth*(s+c),h=f._expanded?f.children:[];if(!h.length){const p=l;return l+=t+o,a.set(f._treeId,{x:p,y:u}),{minX:p,maxX:p}}let n=1/0,r=-1/0;for(const p of h){const{minX:e,maxX:d}=x(p);e<n&&(n=e),d>r&&(r=d)}const i=n+(r-n+t)/2-t/2;return a.set(f._treeId,{x:i,y:u}),{minX:n,maxX:r}};for(const f of this._roots)x(f);let _=0,g=0;for(const{x:f,y:u}of a.values())f+t>_&&(_=f+t),u+s>g&&(g=u+s);return{layout:a,totalW:_+o,totalH:g+c+16}}_line(t,s,c,o,a){const l=document.createElementNS("http://www.w3.org/2000/svg","line");l.setAttribute("x1",String(s)),l.setAttribute("y1",String(c)),l.setAttribute("x2",String(o)),l.setAttribute("y2",String(a)),l.setAttribute("class","og-orgchart-line"),t.appendChild(l)}_render(){const{nodeWidth:t,nodeHeight:s,levelGap:c,columns:o}=this._opts,{layout:a,totalW:l,totalH:x}=this._calcLayout();this._container.innerHTML="";const _=document.createElement("div");_.className="og-orgchart-wrap",_.style.cssText=`width:${l}px;height:${x}px;`;const g=document.createElementNS("http://www.w3.org/2000/svg","svg");g.setAttribute("width",String(l)),g.setAttribute("height",String(x)),g.style.cssText="position:absolute;top:0;left:0;pointer-events:none;overflow:visible;";const f=h=>{for(const n of h){if(!n._expanded||!n.children.length)continue;const r=a.get(n._treeId),i=r.x+t/2,p=r.y+s,e=p+c/2,d=n.children;if(this._line(g,i,p,i,e),d.length>1){const m=a.get(d[0]._treeId),y=a.get(d[d.length-1]._treeId);this._line(g,m.x+t/2,e,y.x+t/2,e)}for(const m of d){const y=a.get(m._treeId),E=y.x+t/2;this._line(g,E,e,E,y.y)}f(d)}};f(this._roots),_.appendChild(g);const u=h=>{for(const n of h){const r=a.get(n._treeId);if(!r)continue;const i=document.createElement("div");i.className="og-orgchart-node",n._hasChildren&&i.classList.add("og-orgchart-node--branch"),n._expanded&&i.classList.add("og-orgchart-node--expanded"),this._selectedId===n._treeId&&i.classList.add("og-orgchart-node--selected"),i.style.cssText=`left:${r.x}px;top:${r.y}px;width:${t}px;height:${s}px;`;const p=document.createElement("div");p.className="og-orgchart-node-content";for(const e of o){const d=n.data[e.field],m=document.createElement("div");if(m.className="og-orgchart-col"+(e.className?" "+e.className:""),e.style){const y=typeof e.style=="function"?e.style(d,n.data):e.style;m.setAttribute("style",y)}if(e.renderer){const y=e.renderer(d,n.data);typeof y=="string"?m.innerHTML=y:m.appendChild(y)}else m.textContent=d??"";p.appendChild(m)}if(i.appendChild(p),n._hasChildren){const e=document.createElement("button");e.type="button",e.className="og-orgchart-toggle",e.setAttribute("aria-expanded",n._expanded?"true":"false"),e.setAttribute("aria-label",n._expanded?"접기":"펼치기");const d=document.createElement("i");d.setAttribute("aria-hidden","true"),d.className=n._expanded?"bi bi-dash-circle":"bi bi-plus-circle",e.appendChild(d),e.addEventListener("click",m=>{m.stopPropagation(),this._toggle(n._treeId)}),i.appendChild(e)}i.addEventListener("click",()=>{this._selectedId=n._treeId,this._opts.onNodeClick(n._treeId,n.data),this._container.querySelectorAll(".og-orgchart-node--selected").forEach(e=>e.classList.remove("og-orgchart-node--selected")),i.classList.add("og-orgchart-node--selected")}),_.appendChild(i),n._expanded&&n.children.length&&u(n.children)}};u(this._roots),this._container.appendChild(_)}}class N{static parse(t,s={}){var h,n;const{fieldMap:c={},trim:o=!0}=s,l=new DOMParser().parseFromString(t.trim(),"text/xml"),x=l.querySelector("parsererror");if(x)throw new Error(`XML 파싱 오류: ${(h=x.textContent)==null?void 0:h.trim()}`);const _=l.documentElement;let g=s.rowTag;if(!g){const r=s.rootTag?l.querySelector(s.rootTag):_;g=((n=r==null?void 0:r.children[0])==null?void 0:n.tagName)??"row"}const f=l.getElementsByTagName(g),u=[];for(let r=0;r<f.length;r++){const i=f[r],p={};for(const e of Array.from(i.attributes)){const d=c[e.name]??e.name;p[d]=o?e.value.trim():e.value}for(const e of Array.from(i.children)){const d=c[e.tagName]??e.tagName,m=e.textContent??"";p[d]=o?m.trim():m}u.push(p)}return u}static stringify(t,s={}){const{rootTag:c="rows",rowTag:o="row",mode:a="element",fieldMap:l={},declaration:x=!0,indent:_=2,nullAs:g="",excludeFields:f=[]}=s,u=" ".repeat(_),h=[];x&&h.push('<?xml version="1.0" encoding="UTF-8"?>'),h.push(`<${c}>`);for(const n of t){const r=Object.entries(n).filter(([i])=>!f.includes(i));if(a==="attribute"){const i=r.map(([p,e])=>{const d=l[p]??p,m=e==null?g:String(e);return`${d}="${this._escAttr(m)}"`}).join(" ");h.push(`${u}<${o}${i?" "+i:""} />`)}else{h.push(`${u}<${o}>`);for(const[i,p]of r){const e=l[i]??i,d=p==null?g:String(p);h.push(`${u}${u}<${e}>${this._escText(d)}</${e}>`)}h.push(`${u}</${o}>`)}}return h.push(`</${c}>`),h.join(`
2
+ `)}static parseSap(t){var _,g,f,u;const c=new DOMParser().parseFromString(t.trim(),"text/xml"),o={header:{},items:[],returns:[],raw:c},a=c.getElementsByTagName("DOCUMENTHEADER")[0];if(a)for(const h of Array.from(a.children))o.header[h.tagName]=((_=h.textContent)==null?void 0:_.trim())??"";const l=c.getElementsByTagName("RETURN");for(const h of Array.from(l)){const n={};for(const r of Array.from(h.children))n[r.tagName]=((g=r.textContent)==null?void 0:g.trim())??"";o.returns.push(n)}const x=["ACCOUNTGL","ACCOUNTRECEIVABLE","ACCOUNTPAYABLE","ITEMS"];for(const h of x){const n=c.getElementsByTagName(h)[0];if(!n)continue;const r=n.getElementsByTagName("ITEM"),i=r.length>0?Array.from(r):[n];for(const p of i){const e={};for(const d of Array.from(p.children))e[d.tagName]=((f=d.textContent)==null?void 0:f.trim())??"";o.items.push(e)}break}if(o.items.length===0){const h=c.documentElement,n=Array.from(h.children).filter(r=>r.hasAttribute("SEGMENT"));for(const r of n){if(r.tagName==="EDI_DC40")continue;const i={};for(const p of Array.from(r.children))i[p.tagName]=((u=p.textContent)==null?void 0:u.trim())??"";Object.keys(i).length>0&&o.items.push(i)}}return o}static stringifySap(t){const s=['<?xml version="1.0" encoding="UTF-8"?>',"<BAPI_CALL>"];if(t.BAPI_FUNCTION&&s.push(` <FUNCTION>${this._escText(t.BAPI_FUNCTION)}</FUNCTION>`),t.DOCUMENTHEADER&&typeof t.DOCUMENTHEADER=="object"){s.push(" <DOCUMENTHEADER>");for(const[o,a]of Object.entries(t.DOCUMENTHEADER))a!=null&&a!==""&&s.push(` <${o}>${this._escText(String(a))}</${o}>`);s.push(" </DOCUMENTHEADER>")}const c=Object.keys(t).find(o=>Array.isArray(t[o])&&!o.startsWith("_"));if(c){s.push(` <${c}>`);for(const o of t[c]){s.push(" <ITEM>");for(const[a,l]of Object.entries(o))l!=null&&l!==""&&!a.startsWith("_")&&s.push(` <${a}>${this._escText(String(l))}</${a}>`);s.push(" </ITEM>")}s.push(` </${c}>`)}return s.push("</BAPI_CALL>"),s.join(`
3
+ `)}static stringifySapBatch(t){const s=['<?xml version="1.0" encoding="UTF-8"?>',`<BAPI_BATCH total="${t.documents.length}">`];return t.documents.forEach((c,o)=>{s.push(` <BAPI_CALL seq="${o+1}">`);const a=this.stringifySap(c).split(`
4
+ `).filter(l=>!l.startsWith("<?xml")).map(l=>" "+l).join(`
5
+ `);s.push(a),s.push(" </BAPI_CALL>")}),s.push("</BAPI_BATCH>"),s.join(`
6
+ `)}static _escText(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}static _escAttr(t){return this._escText(t).replace(/"/g,"&quot;").replace(/'/g,"&apos;")}}exports.OpenGrid=A.OpenGrid;exports.OrgChart=C;exports.XmlConverter=N;
7
+ //# sourceMappingURL=open-grid.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-grid.cjs","sources":["../src/core/OrgChart.ts","../src/core/XmlConverter.ts"],"sourcesContent":["import { buildTree, TreeNode } from './TreeEngine.js';\n\nexport interface OrgChartColumnDef {\n field: string;\n className?: string;\n style?: string | ((value: any, row: Record<string, any>) => string);\n renderer?: (value: any, row: Record<string, any>) => HTMLElement | string;\n}\n\nexport interface OrgChartOptions {\n idField: string;\n parentIdField: string;\n columns: OrgChartColumnDef[];\n nodeWidth?: number;\n nodeHeight?: number;\n levelGap?: number;\n siblingGap?: number;\n expandOnLoad?: boolean;\n onNodeClick?: (id: any, data: Record<string, any>) => void;\n}\n\ninterface LayoutInfo { x: number; y: number; }\n\nexport class OrgChart {\n private _container: HTMLElement;\n private _opts: Required<OrgChartOptions>;\n private _data: Record<string, any>[] = [];\n private _roots: TreeNode<any>[] = [];\n private _expandedKeys = new Set<any>();\n private _selectedId: any = null;\n\n constructor(selector: string | HTMLElement, opts: OrgChartOptions) {\n this._container = typeof selector === 'string'\n ? (document.querySelector(selector) as HTMLElement)\n : selector;\n this._opts = {\n nodeWidth: 160, nodeHeight: 72, levelGap: 52, siblingGap: 20,\n expandOnLoad: true, onNodeClick: () => {},\n ...opts,\n };\n this._container.classList.add('og-orgchart');\n }\n\n setData(data: Record<string, any>[]): void {\n this._data = data;\n const { idField, parentIdField, expandOnLoad } = this._opts;\n if (expandOnLoad && this._expandedKeys.size === 0) {\n data.forEach(r => this._expandedKeys.add(r[idField]));\n }\n this._roots = buildTree(data, { idField, parentIdField }, this._expandedKeys);\n this._render();\n }\n\n setTheme(theme: string): void {\n this._container.setAttribute('data-og-theme', theme);\n }\n\n expandAll(): void {\n const collect = (nodes: TreeNode<any>[]) => {\n for (const n of nodes) {\n this._expandedKeys.add(n._treeId);\n if (n.children.length) collect(n.children);\n }\n };\n collect(this._roots);\n this._rebuild();\n }\n\n collapseAll(): void {\n this._expandedKeys.clear();\n this._rebuild();\n }\n\n private _toggle(id: any): void {\n if (this._expandedKeys.has(id)) this._expandedKeys.delete(id);\n else this._expandedKeys.add(id);\n this._rebuild();\n }\n\n private _rebuild(): void {\n const { idField, parentIdField } = this._opts;\n this._roots = buildTree(this._data, { idField, parentIdField }, this._expandedKeys);\n this._render();\n }\n\n // ── 레이아웃 계산 (post-order: 리프부터 배치, 부모는 자식 중앙) ──\n private _calcLayout(): { layout: Map<any, LayoutInfo>; totalW: number; totalH: number } {\n const { nodeWidth, nodeHeight, levelGap, siblingGap } = this._opts;\n const layout = new Map<any, LayoutInfo>();\n let nextX = 0;\n\n const place = (node: TreeNode<any>): { minX: number; maxX: number } => {\n const y = node._depth * (nodeHeight + levelGap);\n const vis = node._expanded ? node.children : [];\n\n if (!vis.length) {\n const x = nextX;\n nextX += nodeWidth + siblingGap;\n layout.set(node._treeId, { x, y });\n return { minX: x, maxX: x };\n }\n\n let firstX = Infinity, lastX = -Infinity;\n for (const child of vis) {\n const { minX, maxX } = place(child);\n if (minX < firstX) firstX = minX;\n if (maxX > lastX) lastX = maxX;\n }\n // 자식들의 span 중앙에 부모 배치\n const x = firstX + (lastX - firstX + nodeWidth) / 2 - nodeWidth / 2;\n layout.set(node._treeId, { x, y });\n return { minX: firstX, maxX: lastX };\n };\n\n for (const root of this._roots) place(root);\n\n let maxX = 0, maxY = 0;\n for (const { x, y } of layout.values()) {\n if (x + nodeWidth > maxX) maxX = x + nodeWidth;\n if (y + nodeHeight > maxY) maxY = y + nodeHeight;\n }\n return { layout, totalW: maxX + siblingGap, totalH: maxY + levelGap + 16 };\n }\n\n // ── SVG 직선 헬퍼 ──\n private _line(svg: SVGSVGElement, x1: number, y1: number, x2: number, y2: number): void {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n el.setAttribute('x1', String(x1));\n el.setAttribute('y1', String(y1));\n el.setAttribute('x2', String(x2));\n el.setAttribute('y2', String(y2));\n el.setAttribute('class', 'og-orgchart-line');\n svg.appendChild(el);\n }\n\n // ── 렌더 ──\n private _render(): void {\n const { nodeWidth, nodeHeight, levelGap, columns } = this._opts;\n const { layout, totalW, totalH } = this._calcLayout();\n\n this._container.innerHTML = '';\n\n const wrap = document.createElement('div');\n wrap.className = 'og-orgchart-wrap';\n wrap.style.cssText = `width:${totalW}px;height:${totalH}px;`;\n\n // ① SVG 연결선\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', String(totalW));\n svg.setAttribute('height', String(totalH));\n svg.style.cssText = 'position:absolute;top:0;left:0;pointer-events:none;overflow:visible;';\n\n const drawLines = (nodes: TreeNode<any>[]): void => {\n for (const node of nodes) {\n if (!node._expanded || !node.children.length) continue;\n const p = layout.get(node._treeId)!;\n const px = p.x + nodeWidth / 2;\n const py = p.y + nodeHeight;\n const midY = py + levelGap / 2;\n const vis = node.children;\n\n // 부모 → midY\n this._line(svg, px, py, px, midY);\n\n if (vis.length > 1) {\n const c0 = layout.get(vis[0]._treeId)!;\n const cn = layout.get(vis[vis.length - 1]._treeId)!;\n // 수평 브래킷\n this._line(svg, c0.x + nodeWidth / 2, midY, cn.x + nodeWidth / 2, midY);\n }\n for (const child of vis) {\n const ci = layout.get(child._treeId)!;\n const cx = ci.x + nodeWidth / 2;\n // midY → 자식 상단\n this._line(svg, cx, midY, cx, ci.y);\n }\n drawLines(vis);\n }\n };\n drawLines(this._roots);\n wrap.appendChild(svg);\n\n // ② 카드 렌더\n const renderNodes = (nodes: TreeNode<any>[]): void => {\n for (const node of nodes) {\n const info = layout.get(node._treeId);\n if (!info) continue;\n\n const card = document.createElement('div');\n card.className = 'og-orgchart-node';\n if (node._hasChildren) card.classList.add('og-orgchart-node--branch');\n if (node._expanded) card.classList.add('og-orgchart-node--expanded');\n if (this._selectedId === node._treeId) card.classList.add('og-orgchart-node--selected');\n card.style.cssText = `left:${info.x}px;top:${info.y}px;width:${nodeWidth}px;height:${nodeHeight}px;`;\n\n // 컬럼 렌더\n const content = document.createElement('div');\n content.className = 'og-orgchart-node-content';\n for (const col of columns) {\n const val = node.data[col.field];\n const div = document.createElement('div');\n div.className = 'og-orgchart-col' + (col.className ? ' ' + col.className : '');\n if (col.style) {\n const s = typeof col.style === 'function' ? col.style(val, node.data) : col.style;\n div.setAttribute('style', s);\n }\n if (col.renderer) {\n const out = col.renderer(val, node.data);\n if (typeof out === 'string') div.innerHTML = out;\n else div.appendChild(out);\n } else {\n div.textContent = val ?? '';\n }\n content.appendChild(div);\n }\n card.appendChild(content);\n\n // 확장/축소 토글 버튼 (카드 하단 중앙)\n if (node._hasChildren) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'og-orgchart-toggle';\n btn.setAttribute('aria-expanded', node._expanded ? 'true' : 'false');\n btn.setAttribute('aria-label', node._expanded ? '접기' : '펼치기');\n const icon = document.createElement('i');\n icon.setAttribute('aria-hidden', 'true');\n icon.className = node._expanded ? 'bi bi-dash-circle' : 'bi bi-plus-circle';\n btn.appendChild(icon);\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n this._toggle(node._treeId);\n });\n card.appendChild(btn);\n }\n\n card.addEventListener('click', () => {\n this._selectedId = node._treeId;\n this._opts.onNodeClick(node._treeId, node.data);\n // 선택 하이라이트만 갱신 (전체 재렌더 최소화)\n this._container.querySelectorAll('.og-orgchart-node--selected')\n .forEach(el => el.classList.remove('og-orgchart-node--selected'));\n card.classList.add('og-orgchart-node--selected');\n });\n\n wrap.appendChild(card);\n\n if (node._expanded && node.children.length) renderNodes(node.children);\n }\n };\n renderNodes(this._roots);\n\n this._container.appendChild(wrap);\n }\n}\n","/**\n * XmlConverter — XML ↔ 그리드 데이터 양방향 변환 유틸리티.\n *\n * 지원 포맷:\n * A. Element 방식 <row><name>홍길동</name></row>\n * B. Attribute 방식 <row name=\"홍길동\" />\n * C. SAP BAPI XML 응답 <RETURN><TYPE>S</TYPE><BELNR>...</BELNR></RETURN>\n * D. SAP IDoc XML <IDOC><E1HEADER SEGMENT=\"1\"><BUKRS>1000</BUKRS></IDOC>\n *\n * 외부 의존성 없음 — 브라우저 내장 DOMParser 사용.\n */\n\n// ─── 파싱 옵션 ────────────────────────────────────────────────\nexport interface XmlParseOptions {\n /** 루트 엘리먼트 태그명 (생략 시 문서 루트 자동 사용) */\n rootTag?: string;\n /** 행 엘리먼트 태그명 (생략 시 루트의 첫 번째 자식 자동 감지) */\n rowTag?: string;\n /** 값 추출 방식: 'element' | 'attribute' | 'auto'(기본) */\n mode?: 'element' | 'attribute' | 'auto';\n /** XML 태그명 → 그리드 field명 매핑 (생략 시 태그명 그대로 사용) */\n fieldMap?: Record<string, string>;\n /** 텍스트 값 앞뒤 공백 제거 (기본 true) */\n trim?: boolean;\n}\n\n// ─── 직렬화 옵션 ─────────────────────────────────────────────\nexport interface XmlStringifyOptions {\n /** 루트 태그명 (기본 'rows') */\n rootTag?: string;\n /** 행 태그명 (기본 'row') */\n rowTag?: string;\n /** 출력 방식: 'element'(기본) | 'attribute' */\n mode?: 'element' | 'attribute';\n /** 그리드 field명 → XML 태그명 매핑 */\n fieldMap?: Record<string, string>;\n /** XML 선언부 포함 여부 (기본 true) */\n declaration?: boolean;\n /** 들여쓰기 공백 수 (기본 2) */\n indent?: number;\n /** null/undefined 처리 문자열 (기본 '') */\n nullAs?: string;\n /** 출력에서 제외할 필드 목록 */\n excludeFields?: string[];\n}\n\n// ─── SAP 파싱 결과 ────────────────────────────────────────────\nexport interface SapParseResult {\n header: Record<string, string>;\n items: Record<string, string>[];\n returns: Record<string, string>[];\n raw?: Document;\n}\n\n// ─── 메인 클래스 ─────────────────────────────────────────────\nexport class XmlConverter {\n\n // ── 1. XML → 데이터 배열 ────────────────────────────────────\n /**\n * XML 문자열을 파싱하여 그리드 데이터 배열로 변환.\n * Element / Attribute 방식 자동 감지.\n *\n * @throws XML 파싱 오류 시 Error 발생\n */\n static parse(xml: string, options: XmlParseOptions = {}): Record<string, any>[] {\n const { fieldMap = {}, trim = true } = options;\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml.trim(), 'text/xml');\n\n const errNode = doc.querySelector('parsererror');\n if (errNode) throw new Error(`XML 파싱 오류: ${errNode.textContent?.trim()}`);\n\n const root = doc.documentElement;\n\n // rowTag 자동 감지: 명시 → rootTag의 첫 자식 → 루트의 첫 자식\n let rowTag = options.rowTag;\n if (!rowTag) {\n const rootEl = options.rootTag ? doc.querySelector(options.rootTag) : root;\n rowTag = rootEl?.children[0]?.tagName ?? 'row';\n }\n\n const rowEls = doc.getElementsByTagName(rowTag);\n const rows: Record<string, any>[] = [];\n\n for (let i = 0; i < rowEls.length; i++) {\n const el = rowEls[i]!;\n const row: Record<string, any> = {};\n\n // Attribute 방식\n for (const attr of Array.from(el.attributes)) {\n const field = fieldMap[attr.name] ?? attr.name;\n row[field] = trim ? attr.value.trim() : attr.value;\n }\n\n // Element 방식 (자식 태그가 있으면 우선)\n for (const child of Array.from(el.children)) {\n const field = fieldMap[child.tagName] ?? child.tagName;\n const text = child.textContent ?? '';\n row[field] = trim ? text.trim() : text;\n }\n\n rows.push(row);\n }\n\n return rows;\n }\n\n // ── 2. 데이터 배열 → XML ─────────────────────────────────────\n /**\n * 그리드 데이터 배열을 XML 문자열로 직렬화.\n */\n static stringify(data: Record<string, any>[], options: XmlStringifyOptions = {}): string {\n const {\n rootTag = 'rows',\n rowTag = 'row',\n mode = 'element',\n fieldMap = {},\n declaration = true,\n indent = 2,\n nullAs = '',\n excludeFields = [],\n } = options;\n\n const pad = ' '.repeat(indent);\n const lines: string[] = [];\n\n if (declaration) lines.push('<?xml version=\"1.0\" encoding=\"UTF-8\"?>');\n lines.push(`<${rootTag}>`);\n\n for (const item of data) {\n const entries = Object.entries(item).filter(([k]) => !excludeFields.includes(k));\n\n if (mode === 'attribute') {\n const attrs = entries\n .map(([k, v]) => {\n const tag = fieldMap[k] ?? k;\n const val = v == null ? nullAs : String(v);\n return `${tag}=\"${this._escAttr(val)}\"`;\n })\n .join(' ');\n lines.push(`${pad}<${rowTag}${attrs ? ' ' + attrs : ''} />`);\n } else {\n lines.push(`${pad}<${rowTag}>`);\n for (const [k, v] of entries) {\n const tag = fieldMap[k] ?? k;\n const val = v == null ? nullAs : String(v);\n lines.push(`${pad}${pad}<${tag}>${this._escText(val)}</${tag}>`);\n }\n lines.push(`${pad}</${rowTag}>`);\n }\n }\n\n lines.push(`</${rootTag}>`);\n return lines.join('\\n');\n }\n\n // ── 3. SAP BAPI XML 응답 파싱 ────────────────────────────────\n /**\n * SAP BAPI XML 응답을 파싱하여 { header, items, returns } 구조로 반환.\n *\n * 지원 패턴:\n * <DOCUMENTHEADER>...</DOCUMENTHEADER>\n * <ACCOUNTGL><ITEM>...</ITEM></ACCOUNTGL>\n * <RETURN><TYPE>S</TYPE><MESSAGE>...</MESSAGE></RETURN>\n */\n static parseSap(xml: string): SapParseResult {\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml.trim(), 'text/xml');\n\n const result: SapParseResult = { header: {}, items: [], returns: [], raw: doc };\n\n // DOCUMENTHEADER\n const headerEl = doc.getElementsByTagName('DOCUMENTHEADER')[0];\n if (headerEl) {\n for (const child of Array.from(headerEl.children)) {\n result.header[child.tagName] = child.textContent?.trim() ?? '';\n }\n }\n\n // RETURN (복수 지원)\n const returnEls = doc.getElementsByTagName('RETURN');\n for (const r of Array.from(returnEls)) {\n const ret: Record<string, string> = {};\n for (const child of Array.from(r.children)) {\n ret[child.tagName] = child.textContent?.trim() ?? '';\n }\n result.returns.push(ret);\n }\n\n // 라인 아이템 — 순서대로 시도\n const itemParentTags = ['ACCOUNTGL', 'ACCOUNTRECEIVABLE', 'ACCOUNTPAYABLE', 'ITEMS'];\n for (const parentTag of itemParentTags) {\n const parentEl = doc.getElementsByTagName(parentTag)[0];\n if (!parentEl) continue;\n\n // <ITEM> 자식이 있으면 ITEM 단위로, 없으면 parentEl 자체를 1개 아이템으로\n const itemEls = parentEl.getElementsByTagName('ITEM');\n const targets = itemEls.length > 0 ? Array.from(itemEls) : [parentEl];\n\n for (const el of targets) {\n const row: Record<string, string> = {};\n for (const child of Array.from(el.children)) {\n row[child.tagName] = child.textContent?.trim() ?? '';\n }\n result.items.push(row);\n }\n break;\n }\n\n // IDoc 패턴: <SEGMENT> 속성이 있는 최상위 자식들\n if (result.items.length === 0) {\n const root = doc.documentElement;\n const segments = Array.from(root.children).filter(el => el.hasAttribute('SEGMENT'));\n for (const seg of segments) {\n if (seg.tagName === 'EDI_DC40') continue; // 제어 레코드 제외\n const row: Record<string, string> = {};\n for (const child of Array.from(seg.children)) {\n row[child.tagName] = child.textContent?.trim() ?? '';\n }\n if (Object.keys(row).length > 0) result.items.push(row);\n }\n }\n\n return result;\n }\n\n // ── 4. SAP BAPI 페이로드 → XML 직렬화 ───────────────────────\n /**\n * BAPI 페이로드 객체를 SAP XML 형식으로 직렬화.\n * sapGenPayload()의 결과 또는 단일 document 객체를 받음.\n */\n static stringifySap(payload: {\n BAPI_FUNCTION?: string;\n DOCUMENTHEADER?: Record<string, any>;\n ACCOUNTGL?: Record<string, any>[];\n [key: string]: any;\n }): string {\n const lines: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<BAPI_CALL>',\n ];\n\n if (payload.BAPI_FUNCTION) {\n lines.push(` <FUNCTION>${this._escText(payload.BAPI_FUNCTION)}</FUNCTION>`);\n }\n\n if (payload.DOCUMENTHEADER && typeof payload.DOCUMENTHEADER === 'object') {\n lines.push(' <DOCUMENTHEADER>');\n for (const [k, v] of Object.entries(payload.DOCUMENTHEADER)) {\n if (v != null && v !== '') {\n lines.push(` <${k}>${this._escText(String(v))}</${k}>`);\n }\n }\n lines.push(' </DOCUMENTHEADER>');\n }\n\n // 배열 타입 필드를 ACCOUNTGL로 처리\n const itemsKey = Object.keys(payload).find(\n k => Array.isArray(payload[k]) && !k.startsWith('_')\n );\n if (itemsKey) {\n lines.push(` <${itemsKey}>`);\n for (const item of (payload[itemsKey] as Record<string, any>[])) {\n lines.push(' <ITEM>');\n for (const [k, v] of Object.entries(item)) {\n if (v != null && v !== '' && !k.startsWith('_')) {\n lines.push(` <${k}>${this._escText(String(v))}</${k}>`);\n }\n }\n lines.push(' </ITEM>');\n }\n lines.push(` </${itemsKey}>`);\n }\n\n lines.push('</BAPI_CALL>');\n return lines.join('\\n');\n }\n\n // ── 5. 다건 documents 배열 → XML (sapGenPayload 결과 전체) ───\n /**\n * sapGenPayload()의 { totalDocuments, documents[] } 결과를\n * 다건 BAPI XML로 직렬화.\n */\n static stringifySapBatch(payload: { documents: any[] }): string {\n const lines: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n `<BAPI_BATCH total=\"${payload.documents.length}\">`,\n ];\n payload.documents.forEach((doc, i) => {\n lines.push(` <BAPI_CALL seq=\"${i + 1}\">`);\n const inner = this.stringifySap(doc)\n .split('\\n')\n .filter(l => !l.startsWith('<?xml'))\n .map(l => ' ' + l)\n .join('\\n');\n lines.push(inner);\n lines.push(' </BAPI_CALL>');\n });\n lines.push('</BAPI_BATCH>');\n return lines.join('\\n');\n }\n\n // ── 내부 이스케이프 헬퍼 ─────────────────────────────────────\n private static _escText(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n\n private static _escAttr(s: string): string {\n return this._escText(s).replace(/\"/g, '&quot;').replace(/'/g, '&apos;');\n }\n}\n"],"names":["OrgChart","selector","opts","data","idField","parentIdField","expandOnLoad","r","buildTree","theme","collect","nodes","n","id","nodeWidth","nodeHeight","levelGap","siblingGap","layout","nextX","place","node","y","vis","x","firstX","lastX","child","minX","maxX","root","maxY","svg","x1","y1","x2","y2","el","columns","totalW","totalH","wrap","drawLines","p","px","py","midY","c0","cn","ci","cx","renderNodes","info","card","content","col","val","div","s","out","btn","icon","e","XmlConverter","xml","options","fieldMap","trim","doc","errNode","_a","rowTag","rootEl","_b","rowEls","rows","i","row","attr","field","text","rootTag","mode","declaration","indent","nullAs","excludeFields","pad","lines","item","entries","k","attrs","v","tag","result","headerEl","returnEls","ret","itemParentTags","parentTag","parentEl","itemEls","targets","_c","segments","seg","_d","payload","itemsKey","inner"],"mappings":"2HAuBO,MAAMA,CAAS,CAQpB,YAAYC,EAAgCC,EAAuB,CALnE,KAAQ,MAA+B,CAAA,EACvC,KAAQ,OAA0B,CAAA,EAClC,KAAQ,kBAAoB,IAC5B,KAAQ,YAAmB,KAGzB,KAAK,WAAa,OAAOD,GAAa,SACjC,SAAS,cAAcA,CAAQ,EAChCA,EACJ,KAAK,MAAQ,CACX,UAAW,IAAK,WAAY,GAAI,SAAU,GAAI,WAAY,GAC1D,aAAc,GAAM,YAAa,IAAM,CAAC,EACxC,GAAGC,CAAA,EAEL,KAAK,WAAW,UAAU,IAAI,aAAa,CAC7C,CAEA,QAAQC,EAAmC,CACzC,KAAK,MAAQA,EACb,KAAM,CAAE,QAAAC,EAAS,cAAAC,EAAe,aAAAC,CAAA,EAAiB,KAAK,MAClDA,GAAgB,KAAK,cAAc,OAAS,GAC9CH,EAAK,WAAa,KAAK,cAAc,IAAII,EAAEH,CAAO,CAAC,CAAC,EAEtD,KAAK,OAASI,EAAAA,UAAUL,EAAM,CAAE,QAAAC,EAAS,cAAAC,CAAA,EAAiB,KAAK,aAAa,EAC5E,KAAK,QAAA,CACP,CAEA,SAASI,EAAqB,CAC5B,KAAK,WAAW,aAAa,gBAAiBA,CAAK,CACrD,CAEA,WAAkB,CAChB,MAAMC,EAAWC,GAA2B,CAC1C,UAAWC,KAAKD,EACd,KAAK,cAAc,IAAIC,EAAE,OAAO,EAC5BA,EAAE,SAAS,QAAQF,EAAQE,EAAE,QAAQ,CAE7C,EACAF,EAAQ,KAAK,MAAM,EACnB,KAAK,SAAA,CACP,CAEA,aAAoB,CAClB,KAAK,cAAc,MAAA,EACnB,KAAK,SAAA,CACP,CAEQ,QAAQG,EAAe,CACzB,KAAK,cAAc,IAAIA,CAAE,EAAG,KAAK,cAAc,OAAOA,CAAE,EACvD,KAAK,cAAc,IAAIA,CAAE,EAC9B,KAAK,SAAA,CACP,CAEQ,UAAiB,CACvB,KAAM,CAAE,QAAAT,EAAS,cAAAC,CAAA,EAAkB,KAAK,MACxC,KAAK,OAASG,EAAAA,UAAU,KAAK,MAAO,CAAE,QAAAJ,EAAS,cAAAC,CAAA,EAAiB,KAAK,aAAa,EAClF,KAAK,QAAA,CACP,CAGQ,aAAgF,CACtF,KAAM,CAAE,UAAAS,EAAW,WAAAC,EAAY,SAAAC,EAAU,WAAAC,CAAA,EAAe,KAAK,MACvDC,MAAa,IACnB,IAAIC,EAAQ,EAEZ,MAAMC,EAASC,GAAwD,CACrE,MAAMC,EAAID,EAAK,QAAUN,EAAaC,GAChCO,EAAMF,EAAK,UAAYA,EAAK,SAAW,CAAA,EAE7C,GAAI,CAACE,EAAI,OAAQ,CACf,MAAMC,EAAIL,EACV,OAAAA,GAASL,EAAYG,EACrBC,EAAO,IAAIG,EAAK,QAAS,CAAE,EAAAG,EAAG,EAAAF,EAAG,EAC1B,CAAE,KAAME,EAAG,KAAMA,CAAAA,CAC1B,CAEA,IAAIC,EAAS,IAAUC,EAAQ,KAC/B,UAAWC,KAASJ,EAAK,CACvB,KAAM,CAAE,KAAAK,EAAM,KAAAC,CAAAA,EAAST,EAAMO,CAAK,EAC9BC,EAAOH,IAAQA,EAASG,GACxBC,EAAOH,IAAOA,EAAQG,EAC5B,CAEA,MAAML,EAAIC,GAAUC,EAAQD,EAASX,GAAa,EAAIA,EAAY,EAClE,OAAAI,EAAO,IAAIG,EAAK,QAAS,CAAE,EAAAG,EAAG,EAAAF,EAAG,EAC1B,CAAE,KAAMG,EAAQ,KAAMC,CAAA,CAC/B,EAEA,UAAWI,KAAQ,KAAK,OAAQV,EAAMU,CAAI,EAE1C,IAAID,EAAO,EAAGE,EAAO,EACrB,SAAW,CAAE,EAAAP,EAAG,EAAAF,CAAA,IAAOJ,EAAO,SACxBM,EAAIV,EAAYe,IAAMA,EAAOL,EAAIV,GACjCQ,EAAIP,EAAagB,IAAMA,EAAOT,EAAIP,GAExC,MAAO,CAAE,OAAAG,EAAQ,OAAQW,EAAOZ,EAAY,OAAQc,EAAOf,EAAW,EAAA,CACxE,CAGQ,MAAMgB,EAAoBC,EAAYC,EAAYC,EAAYC,EAAkB,CACtF,MAAMC,EAAK,SAAS,gBAAgB,6BAA8B,MAAM,EACxEA,EAAG,aAAa,KAAM,OAAOJ,CAAE,CAAC,EAChCI,EAAG,aAAa,KAAM,OAAOH,CAAE,CAAC,EAChCG,EAAG,aAAa,KAAM,OAAOF,CAAE,CAAC,EAChCE,EAAG,aAAa,KAAM,OAAOD,CAAE,CAAC,EAChCC,EAAG,aAAa,QAAS,kBAAkB,EAC3CL,EAAI,YAAYK,CAAE,CACpB,CAGQ,SAAgB,CACtB,KAAM,CAAE,UAAAvB,EAAW,WAAAC,EAAY,SAAAC,EAAU,QAAAsB,CAAA,EAAY,KAAK,MACpD,CAAE,OAAApB,EAAQ,OAAAqB,EAAQ,OAAAC,CAAA,EAAW,KAAK,YAAA,EAExC,KAAK,WAAW,UAAY,GAE5B,MAAMC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,mBACjBA,EAAK,MAAM,QAAU,SAASF,CAAM,aAAaC,CAAM,MAGvD,MAAMR,EAAM,SAAS,gBAAgB,6BAA8B,KAAK,EACxEA,EAAI,aAAa,QAAS,OAAOO,CAAM,CAAC,EACxCP,EAAI,aAAa,SAAU,OAAOQ,CAAM,CAAC,EACzCR,EAAI,MAAM,QAAU,uEAEpB,MAAMU,EAAa/B,GAAiC,CAClD,UAAWU,KAAQV,EAAO,CACxB,GAAI,CAACU,EAAK,WAAa,CAACA,EAAK,SAAS,OAAQ,SAC9C,MAAMsB,EAAIzB,EAAO,IAAIG,EAAK,OAAO,EAC3BuB,EAAKD,EAAE,EAAI7B,EAAY,EACvB+B,EAAKF,EAAE,EAAI5B,EACX+B,EAAOD,EAAK7B,EAAW,EACvBO,EAAMF,EAAK,SAKjB,GAFA,KAAK,MAAMW,EAAKY,EAAIC,EAAID,EAAIE,CAAI,EAE5BvB,EAAI,OAAS,EAAG,CAClB,MAAMwB,EAAK7B,EAAO,IAAIK,EAAI,CAAC,EAAE,OAAO,EAC9ByB,EAAK9B,EAAO,IAAIK,EAAIA,EAAI,OAAS,CAAC,EAAE,OAAO,EAEjD,KAAK,MAAMS,EAAKe,EAAG,EAAIjC,EAAY,EAAGgC,EAAME,EAAG,EAAIlC,EAAY,EAAGgC,CAAI,CACxE,CACA,UAAWnB,KAASJ,EAAK,CACvB,MAAM0B,EAAK/B,EAAO,IAAIS,EAAM,OAAO,EAC7BuB,EAAKD,EAAG,EAAInC,EAAY,EAE9B,KAAK,MAAMkB,EAAKkB,EAAIJ,EAAMI,EAAID,EAAG,CAAC,CACpC,CACAP,EAAUnB,CAAG,CACf,CACF,EACAmB,EAAU,KAAK,MAAM,EACrBD,EAAK,YAAYT,CAAG,EAGpB,MAAMmB,EAAexC,GAAiC,CACpD,UAAWU,KAAQV,EAAO,CACxB,MAAMyC,EAAOlC,EAAO,IAAIG,EAAK,OAAO,EACpC,GAAI,CAAC+B,EAAM,SAEX,MAAMC,EAAO,SAAS,cAAc,KAAK,EACzCA,EAAK,UAAY,mBACbhC,EAAK,cAAcgC,EAAK,UAAU,IAAI,0BAA0B,EAChEhC,EAAK,WAAcgC,EAAK,UAAU,IAAI,4BAA4B,EAClE,KAAK,cAAgBhC,EAAK,SAASgC,EAAK,UAAU,IAAI,4BAA4B,EACtFA,EAAK,MAAM,QAAU,QAAQD,EAAK,CAAC,UAAUA,EAAK,CAAC,YAAYtC,CAAS,aAAaC,CAAU,MAG/F,MAAMuC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,2BACpB,UAAWC,KAAOjB,EAAS,CACzB,MAAMkB,EAAMnC,EAAK,KAAKkC,EAAI,KAAK,EACzBE,EAAM,SAAS,cAAc,KAAK,EAExC,GADAA,EAAI,UAAY,mBAAqBF,EAAI,UAAY,IAAMA,EAAI,UAAY,IACvEA,EAAI,MAAO,CACb,MAAMG,EAAI,OAAOH,EAAI,OAAU,WAAaA,EAAI,MAAMC,EAAKnC,EAAK,IAAI,EAAIkC,EAAI,MAC5EE,EAAI,aAAa,QAASC,CAAC,CAC7B,CACA,GAAIH,EAAI,SAAU,CAChB,MAAMI,EAAMJ,EAAI,SAASC,EAAKnC,EAAK,IAAI,EACnC,OAAOsC,GAAQ,SAAUF,EAAI,UAAYE,EACxCF,EAAI,YAAYE,CAAG,CAC1B,MACEF,EAAI,YAAcD,GAAO,GAE3BF,EAAQ,YAAYG,CAAG,CACzB,CAIA,GAHAJ,EAAK,YAAYC,CAAO,EAGpBjC,EAAK,aAAc,CACrB,MAAMuC,EAAM,SAAS,cAAc,QAAQ,EAC3CA,EAAI,KAAO,SACXA,EAAI,UAAY,qBAChBA,EAAI,aAAa,gBAAiBvC,EAAK,UAAY,OAAS,OAAO,EACnEuC,EAAI,aAAa,aAAcvC,EAAK,UAAY,KAAO,KAAK,EAC5D,MAAMwC,EAAO,SAAS,cAAc,GAAG,EACvCA,EAAK,aAAa,cAAe,MAAM,EACvCA,EAAK,UAAYxC,EAAK,UAAY,oBAAsB,oBACxDuC,EAAI,YAAYC,CAAI,EACpBD,EAAI,iBAAiB,QAAUE,GAAM,CACnCA,EAAE,gBAAA,EACF,KAAK,QAAQzC,EAAK,OAAO,CAC3B,CAAC,EACDgC,EAAK,YAAYO,CAAG,CACtB,CAEAP,EAAK,iBAAiB,QAAS,IAAM,CACnC,KAAK,YAAchC,EAAK,QACxB,KAAK,MAAM,YAAYA,EAAK,QAASA,EAAK,IAAI,EAE9C,KAAK,WAAW,iBAAiB,6BAA6B,EAC3D,WAAcgB,EAAG,UAAU,OAAO,4BAA4B,CAAC,EAClEgB,EAAK,UAAU,IAAI,4BAA4B,CACjD,CAAC,EAEDZ,EAAK,YAAYY,CAAI,EAEjBhC,EAAK,WAAaA,EAAK,SAAS,QAAQ8B,EAAY9B,EAAK,QAAQ,CACvE,CACF,EACA8B,EAAY,KAAK,MAAM,EAEvB,KAAK,WAAW,YAAYV,CAAI,CAClC,CACF,CCtMO,MAAMsB,CAAa,CASxB,OAAO,MAAMC,EAAaC,EAA2B,GAA2B,SAC9E,KAAM,CAAE,SAAAC,EAAW,CAAA,EAAI,KAAAC,EAAO,IAASF,EAGjCG,EADS,IAAI,UAAA,EACG,gBAAgBJ,EAAI,KAAA,EAAQ,UAAU,EAEtDK,EAAUD,EAAI,cAAc,aAAa,EAC/C,GAAIC,QAAe,IAAI,MAAM,eAAcC,EAAAD,EAAQ,cAAR,YAAAC,EAAqB,MAAM,EAAE,EAExE,MAAMxC,EAAOsC,EAAI,gBAGjB,IAAIG,EAASN,EAAQ,OACrB,GAAI,CAACM,EAAQ,CACX,MAAMC,EAASP,EAAQ,QAAUG,EAAI,cAAcH,EAAQ,OAAO,EAAInC,EACtEyC,IAASE,EAAAD,GAAA,YAAAA,EAAQ,SAAS,KAAjB,YAAAC,EAAqB,UAAW,KAC3C,CAEA,MAAMC,EAASN,EAAI,qBAAqBG,CAAM,EACxCI,EAA8B,CAAA,EAEpC,QAASC,EAAI,EAAGA,EAAIF,EAAO,OAAQE,IAAK,CACtC,MAAMvC,EAAMqC,EAAOE,CAAC,EACdC,EAA2B,CAAA,EAGjC,UAAWC,KAAQ,MAAM,KAAKzC,EAAG,UAAU,EAAG,CAC5C,MAAM0C,EAAQb,EAASY,EAAK,IAAI,GAAKA,EAAK,KAC1CD,EAAIE,CAAK,EAAKZ,EAAOW,EAAK,MAAM,KAAA,EAASA,EAAK,KAChD,CAGA,UAAWnD,KAAS,MAAM,KAAKU,EAAG,QAAQ,EAAG,CAC3C,MAAM0C,EAASb,EAASvC,EAAM,OAAO,GAAKA,EAAM,QAC1CqD,EAASrD,EAAM,aAAe,GACpCkD,EAAIE,CAAK,EAAMZ,EAAOa,EAAK,OAASA,CACtC,CAEAL,EAAK,KAAKE,CAAG,CACf,CAEA,OAAOF,CACT,CAMA,OAAO,UAAUxE,EAA6B8D,EAA+B,GAAY,CACvF,KAAM,CACJ,QAAAgB,EAAe,OACf,OAAAV,EAAe,MACf,KAAAW,EAAe,UACf,SAAAhB,EAAe,CAAA,EACf,YAAAiB,EAAe,GACf,OAAAC,EAAe,EACf,OAAAC,EAAe,GACf,cAAAC,EAAgB,CAAA,CAAC,EACfrB,EAEEsB,EAAQ,IAAI,OAAOH,CAAM,EACzBI,EAAkB,CAAA,EAEpBL,GAAaK,EAAM,KAAK,wCAAwC,EACpEA,EAAM,KAAK,IAAIP,CAAO,GAAG,EAEzB,UAAWQ,KAAQtF,EAAM,CACvB,MAAMuF,EAAU,OAAO,QAAQD,CAAI,EAAE,OAAO,CAAC,CAACE,CAAC,IAAM,CAACL,EAAc,SAASK,CAAC,CAAC,EAE/E,GAAIT,IAAS,YAAa,CACxB,MAAMU,EAAQF,EACX,IAAI,CAAC,CAACC,EAAGE,CAAC,IAAM,CACf,MAAMC,EAAM5B,EAASyB,CAAC,GAAKA,EACrBnC,EAAMqC,GAAK,KAAOR,EAAS,OAAOQ,CAAC,EACzC,MAAO,GAAGC,CAAG,KAAK,KAAK,SAAStC,CAAG,CAAC,GACtC,CAAC,EACA,KAAK,GAAG,EACXgC,EAAM,KAAK,GAAGD,CAAG,IAAIhB,CAAM,GAAGqB,EAAQ,IAAMA,EAAQ,EAAE,KAAK,CAC7D,KAAO,CACLJ,EAAM,KAAK,GAAGD,CAAG,IAAIhB,CAAM,GAAG,EAC9B,SAAW,CAACoB,EAAGE,CAAC,IAAKH,EAAS,CAC5B,MAAMI,EAAM5B,EAASyB,CAAC,GAAKA,EACrBnC,EAAMqC,GAAK,KAAOR,EAAS,OAAOQ,CAAC,EACzCL,EAAM,KAAK,GAAGD,CAAG,GAAGA,CAAG,IAAIO,CAAG,IAAI,KAAK,SAAStC,CAAG,CAAC,KAAKsC,CAAG,GAAG,CACjE,CACAN,EAAM,KAAK,GAAGD,CAAG,KAAKhB,CAAM,GAAG,CACjC,CACF,CAEA,OAAAiB,EAAM,KAAK,KAAKP,CAAO,GAAG,EACnBO,EAAM,KAAK;AAAA,CAAI,CACxB,CAWA,OAAO,SAASxB,EAA6B,aAE3C,MAAMI,EADS,IAAI,UAAA,EACG,gBAAgBJ,EAAI,KAAA,EAAQ,UAAU,EAEtD+B,EAAyB,CAAE,OAAQ,GAAI,MAAO,CAAA,EAAI,QAAS,CAAA,EAAI,IAAK3B,CAAA,EAGpE4B,EAAW5B,EAAI,qBAAqB,gBAAgB,EAAE,CAAC,EAC7D,GAAI4B,EACF,UAAWrE,KAAS,MAAM,KAAKqE,EAAS,QAAQ,EAC9CD,EAAO,OAAOpE,EAAM,OAAO,IAAI2C,EAAA3C,EAAM,cAAN,YAAA2C,EAAmB,SAAU,GAKhE,MAAM2B,EAAY7B,EAAI,qBAAqB,QAAQ,EACnD,UAAW7D,KAAK,MAAM,KAAK0F,CAAS,EAAG,CACrC,MAAMC,EAA8B,CAAA,EACpC,UAAWvE,KAAS,MAAM,KAAKpB,EAAE,QAAQ,EACvC2F,EAAIvE,EAAM,OAAO,IAAI8C,EAAA9C,EAAM,cAAN,YAAA8C,EAAmB,SAAU,GAEpDsB,EAAO,QAAQ,KAAKG,CAAG,CACzB,CAGA,MAAMC,EAAiB,CAAC,YAAa,oBAAqB,iBAAkB,OAAO,EACnF,UAAWC,KAAaD,EAAgB,CACtC,MAAME,EAAWjC,EAAI,qBAAqBgC,CAAS,EAAE,CAAC,EACtD,GAAI,CAACC,EAAU,SAGf,MAAMC,EAAUD,EAAS,qBAAqB,MAAM,EAC9CE,EAAUD,EAAQ,OAAS,EAAI,MAAM,KAAKA,CAAO,EAAI,CAACD,CAAQ,EAEpE,UAAWhE,KAAMkE,EAAS,CACxB,MAAM1B,EAA8B,CAAA,EACpC,UAAWlD,KAAS,MAAM,KAAKU,EAAG,QAAQ,EACxCwC,EAAIlD,EAAM,OAAO,IAAI6E,EAAA7E,EAAM,cAAN,YAAA6E,EAAmB,SAAU,GAEpDT,EAAO,MAAM,KAAKlB,CAAG,CACvB,CACA,KACF,CAGA,GAAIkB,EAAO,MAAM,SAAW,EAAG,CAC7B,MAAMjE,EAAWsC,EAAI,gBACfqC,EAAW,MAAM,KAAK3E,EAAK,QAAQ,EAAE,OAAOO,GAAMA,EAAG,aAAa,SAAS,CAAC,EAClF,UAAWqE,KAAOD,EAAU,CAC1B,GAAIC,EAAI,UAAY,WAAY,SAChC,MAAM7B,EAA8B,CAAA,EACpC,UAAWlD,KAAS,MAAM,KAAK+E,EAAI,QAAQ,EACzC7B,EAAIlD,EAAM,OAAO,IAAIgF,EAAAhF,EAAM,cAAN,YAAAgF,EAAmB,SAAU,GAEhD,OAAO,KAAK9B,CAAG,EAAE,OAAS,GAAGkB,EAAO,MAAM,KAAKlB,CAAG,CACxD,CACF,CAEA,OAAOkB,CACT,CAOA,OAAO,aAAaa,EAKT,CACT,MAAMpB,EAAkB,CACtB,yCACA,aAAA,EAOF,GAJIoB,EAAQ,eACVpB,EAAM,KAAK,eAAe,KAAK,SAASoB,EAAQ,aAAa,CAAC,aAAa,EAGzEA,EAAQ,gBAAkB,OAAOA,EAAQ,gBAAmB,SAAU,CACxEpB,EAAM,KAAK,oBAAoB,EAC/B,SAAW,CAACG,EAAGE,CAAC,IAAK,OAAO,QAAQe,EAAQ,cAAc,EACpDf,GAAK,MAAQA,IAAM,IACrBL,EAAM,KAAK,QAAQG,CAAC,IAAI,KAAK,SAAS,OAAOE,CAAC,CAAC,CAAC,KAAKF,CAAC,GAAG,EAG7DH,EAAM,KAAK,qBAAqB,CAClC,CAGA,MAAMqB,EAAW,OAAO,KAAKD,CAAO,EAAE,KACpCjB,GAAK,MAAM,QAAQiB,EAAQjB,CAAC,CAAC,GAAK,CAACA,EAAE,WAAW,GAAG,CAAA,EAErD,GAAIkB,EAAU,CACZrB,EAAM,KAAK,MAAMqB,CAAQ,GAAG,EAC5B,UAAWpB,KAASmB,EAAQC,CAAQ,EAA6B,CAC/DrB,EAAM,KAAK,YAAY,EACvB,SAAW,CAACG,EAAGE,CAAC,IAAK,OAAO,QAAQJ,CAAI,EAClCI,GAAK,MAAQA,IAAM,IAAM,CAACF,EAAE,WAAW,GAAG,GAC5CH,EAAM,KAAK,UAAUG,CAAC,IAAI,KAAK,SAAS,OAAOE,CAAC,CAAC,CAAC,KAAKF,CAAC,GAAG,EAG/DH,EAAM,KAAK,aAAa,CAC1B,CACAA,EAAM,KAAK,OAAOqB,CAAQ,GAAG,CAC/B,CAEA,OAAArB,EAAM,KAAK,cAAc,EAClBA,EAAM,KAAK;AAAA,CAAI,CACxB,CAOA,OAAO,kBAAkBoB,EAAuC,CAC9D,MAAMpB,EAAkB,CACtB,yCACA,sBAAsBoB,EAAQ,UAAU,MAAM,IAAA,EAEhD,OAAAA,EAAQ,UAAU,QAAQ,CAACxC,EAAKQ,IAAM,CACpCY,EAAM,KAAK,qBAAqBZ,EAAI,CAAC,IAAI,EACzC,MAAMkC,EAAQ,KAAK,aAAa1C,CAAG,EAChC,MAAM;AAAA,CAAI,EACV,OAAO,GAAK,CAAC,EAAE,WAAW,OAAO,CAAC,EAClC,OAAS,OAAS,CAAC,EACnB,KAAK;AAAA,CAAI,EACZoB,EAAM,KAAKsB,CAAK,EAChBtB,EAAM,KAAK,gBAAgB,CAC7B,CAAC,EACDA,EAAM,KAAK,eAAe,EACnBA,EAAM,KAAK;AAAA,CAAI,CACxB,CAGA,OAAe,SAAS9B,EAAmB,CACzC,OAAOA,EAAE,QAAQ,KAAM,OAAO,EAAE,QAAQ,KAAM,MAAM,EAAE,QAAQ,KAAM,MAAM,CAC5E,CAEA,OAAe,SAASA,EAAmB,CACzC,OAAO,KAAK,SAASA,CAAC,EAAE,QAAQ,KAAM,QAAQ,EAAE,QAAQ,KAAM,QAAQ,CACxE,CACF"}
@@ -0,0 +1,311 @@
1
+ import { b as E } from "./OpenGrid-CfZy3e7Q.js";
2
+ import { O as w } from "./OpenGrid-CfZy3e7Q.js";
3
+ class N {
4
+ constructor(t, s) {
5
+ this._data = [], this._roots = [], this._expandedKeys = /* @__PURE__ */ new Set(), this._selectedId = null, this._container = typeof t == "string" ? document.querySelector(t) : t, this._opts = {
6
+ nodeWidth: 160,
7
+ nodeHeight: 72,
8
+ levelGap: 52,
9
+ siblingGap: 20,
10
+ expandOnLoad: !0,
11
+ onNodeClick: () => {
12
+ },
13
+ ...s
14
+ }, this._container.classList.add("og-orgchart");
15
+ }
16
+ setData(t) {
17
+ this._data = t;
18
+ const { idField: s, parentIdField: c, expandOnLoad: o } = this._opts;
19
+ o && this._expandedKeys.size === 0 && t.forEach((a) => this._expandedKeys.add(a[s])), this._roots = E(t, { idField: s, parentIdField: c }, this._expandedKeys), this._render();
20
+ }
21
+ setTheme(t) {
22
+ this._container.setAttribute("data-og-theme", t);
23
+ }
24
+ expandAll() {
25
+ const t = (s) => {
26
+ for (const c of s)
27
+ this._expandedKeys.add(c._treeId), c.children.length && t(c.children);
28
+ };
29
+ t(this._roots), this._rebuild();
30
+ }
31
+ collapseAll() {
32
+ this._expandedKeys.clear(), this._rebuild();
33
+ }
34
+ _toggle(t) {
35
+ this._expandedKeys.has(t) ? this._expandedKeys.delete(t) : this._expandedKeys.add(t), this._rebuild();
36
+ }
37
+ _rebuild() {
38
+ const { idField: t, parentIdField: s } = this._opts;
39
+ this._roots = E(this._data, { idField: t, parentIdField: s }, this._expandedKeys), this._render();
40
+ }
41
+ // ── 레이아웃 계산 (post-order: 리프부터 배치, 부모는 자식 중앙) ──
42
+ _calcLayout() {
43
+ const { nodeWidth: t, nodeHeight: s, levelGap: c, siblingGap: o } = this._opts, a = /* @__PURE__ */ new Map();
44
+ let l = 0;
45
+ const x = (f) => {
46
+ const m = f._depth * (s + c), h = f._expanded ? f.children : [];
47
+ if (!h.length) {
48
+ const p = l;
49
+ return l += t + o, a.set(f._treeId, { x: p, y: m }), { minX: p, maxX: p };
50
+ }
51
+ let n = 1 / 0, r = -1 / 0;
52
+ for (const p of h) {
53
+ const { minX: e, maxX: d } = x(p);
54
+ e < n && (n = e), d > r && (r = d);
55
+ }
56
+ const i = n + (r - n + t) / 2 - t / 2;
57
+ return a.set(f._treeId, { x: i, y: m }), { minX: n, maxX: r };
58
+ };
59
+ for (const f of this._roots) x(f);
60
+ let _ = 0, g = 0;
61
+ for (const { x: f, y: m } of a.values())
62
+ f + t > _ && (_ = f + t), m + s > g && (g = m + s);
63
+ return { layout: a, totalW: _ + o, totalH: g + c + 16 };
64
+ }
65
+ // ── SVG 직선 헬퍼 ──
66
+ _line(t, s, c, o, a) {
67
+ const l = document.createElementNS("http://www.w3.org/2000/svg", "line");
68
+ l.setAttribute("x1", String(s)), l.setAttribute("y1", String(c)), l.setAttribute("x2", String(o)), l.setAttribute("y2", String(a)), l.setAttribute("class", "og-orgchart-line"), t.appendChild(l);
69
+ }
70
+ // ── 렌더 ──
71
+ _render() {
72
+ const { nodeWidth: t, nodeHeight: s, levelGap: c, columns: o } = this._opts, { layout: a, totalW: l, totalH: x } = this._calcLayout();
73
+ this._container.innerHTML = "";
74
+ const _ = document.createElement("div");
75
+ _.className = "og-orgchart-wrap", _.style.cssText = `width:${l}px;height:${x}px;`;
76
+ const g = document.createElementNS("http://www.w3.org/2000/svg", "svg");
77
+ g.setAttribute("width", String(l)), g.setAttribute("height", String(x)), g.style.cssText = "position:absolute;top:0;left:0;pointer-events:none;overflow:visible;";
78
+ const f = (h) => {
79
+ for (const n of h) {
80
+ if (!n._expanded || !n.children.length) continue;
81
+ const r = a.get(n._treeId), i = r.x + t / 2, p = r.y + s, e = p + c / 2, d = n.children;
82
+ if (this._line(g, i, p, i, e), d.length > 1) {
83
+ const u = a.get(d[0]._treeId), y = a.get(d[d.length - 1]._treeId);
84
+ this._line(g, u.x + t / 2, e, y.x + t / 2, e);
85
+ }
86
+ for (const u of d) {
87
+ const y = a.get(u._treeId), A = y.x + t / 2;
88
+ this._line(g, A, e, A, y.y);
89
+ }
90
+ f(d);
91
+ }
92
+ };
93
+ f(this._roots), _.appendChild(g);
94
+ const m = (h) => {
95
+ for (const n of h) {
96
+ const r = a.get(n._treeId);
97
+ if (!r) continue;
98
+ const i = document.createElement("div");
99
+ i.className = "og-orgchart-node", n._hasChildren && i.classList.add("og-orgchart-node--branch"), n._expanded && i.classList.add("og-orgchart-node--expanded"), this._selectedId === n._treeId && i.classList.add("og-orgchart-node--selected"), i.style.cssText = `left:${r.x}px;top:${r.y}px;width:${t}px;height:${s}px;`;
100
+ const p = document.createElement("div");
101
+ p.className = "og-orgchart-node-content";
102
+ for (const e of o) {
103
+ const d = n.data[e.field], u = document.createElement("div");
104
+ if (u.className = "og-orgchart-col" + (e.className ? " " + e.className : ""), e.style) {
105
+ const y = typeof e.style == "function" ? e.style(d, n.data) : e.style;
106
+ u.setAttribute("style", y);
107
+ }
108
+ if (e.renderer) {
109
+ const y = e.renderer(d, n.data);
110
+ typeof y == "string" ? u.innerHTML = y : u.appendChild(y);
111
+ } else
112
+ u.textContent = d ?? "";
113
+ p.appendChild(u);
114
+ }
115
+ if (i.appendChild(p), n._hasChildren) {
116
+ const e = document.createElement("button");
117
+ e.type = "button", e.className = "og-orgchart-toggle", e.setAttribute("aria-expanded", n._expanded ? "true" : "false"), e.setAttribute("aria-label", n._expanded ? "접기" : "펼치기");
118
+ const d = document.createElement("i");
119
+ d.setAttribute("aria-hidden", "true"), d.className = n._expanded ? "bi bi-dash-circle" : "bi bi-plus-circle", e.appendChild(d), e.addEventListener("click", (u) => {
120
+ u.stopPropagation(), this._toggle(n._treeId);
121
+ }), i.appendChild(e);
122
+ }
123
+ i.addEventListener("click", () => {
124
+ this._selectedId = n._treeId, this._opts.onNodeClick(n._treeId, n.data), this._container.querySelectorAll(".og-orgchart-node--selected").forEach((e) => e.classList.remove("og-orgchart-node--selected")), i.classList.add("og-orgchart-node--selected");
125
+ }), _.appendChild(i), n._expanded && n.children.length && m(n.children);
126
+ }
127
+ };
128
+ m(this._roots), this._container.appendChild(_);
129
+ }
130
+ }
131
+ class b {
132
+ // ── 1. XML → 데이터 배열 ────────────────────────────────────
133
+ /**
134
+ * XML 문자열을 파싱하여 그리드 데이터 배열로 변환.
135
+ * Element / Attribute 방식 자동 감지.
136
+ *
137
+ * @throws XML 파싱 오류 시 Error 발생
138
+ */
139
+ static parse(t, s = {}) {
140
+ var h, n;
141
+ const { fieldMap: c = {}, trim: o = !0 } = s, l = new DOMParser().parseFromString(t.trim(), "text/xml"), x = l.querySelector("parsererror");
142
+ if (x) throw new Error(`XML 파싱 오류: ${(h = x.textContent) == null ? void 0 : h.trim()}`);
143
+ const _ = l.documentElement;
144
+ let g = s.rowTag;
145
+ if (!g) {
146
+ const r = s.rootTag ? l.querySelector(s.rootTag) : _;
147
+ g = ((n = r == null ? void 0 : r.children[0]) == null ? void 0 : n.tagName) ?? "row";
148
+ }
149
+ const f = l.getElementsByTagName(g), m = [];
150
+ for (let r = 0; r < f.length; r++) {
151
+ const i = f[r], p = {};
152
+ for (const e of Array.from(i.attributes)) {
153
+ const d = c[e.name] ?? e.name;
154
+ p[d] = o ? e.value.trim() : e.value;
155
+ }
156
+ for (const e of Array.from(i.children)) {
157
+ const d = c[e.tagName] ?? e.tagName, u = e.textContent ?? "";
158
+ p[d] = o ? u.trim() : u;
159
+ }
160
+ m.push(p);
161
+ }
162
+ return m;
163
+ }
164
+ // ── 2. 데이터 배열 → XML ─────────────────────────────────────
165
+ /**
166
+ * 그리드 데이터 배열을 XML 문자열로 직렬화.
167
+ */
168
+ static stringify(t, s = {}) {
169
+ const {
170
+ rootTag: c = "rows",
171
+ rowTag: o = "row",
172
+ mode: a = "element",
173
+ fieldMap: l = {},
174
+ declaration: x = !0,
175
+ indent: _ = 2,
176
+ nullAs: g = "",
177
+ excludeFields: f = []
178
+ } = s, m = " ".repeat(_), h = [];
179
+ x && h.push('<?xml version="1.0" encoding="UTF-8"?>'), h.push(`<${c}>`);
180
+ for (const n of t) {
181
+ const r = Object.entries(n).filter(([i]) => !f.includes(i));
182
+ if (a === "attribute") {
183
+ const i = r.map(([p, e]) => {
184
+ const d = l[p] ?? p, u = e == null ? g : String(e);
185
+ return `${d}="${this._escAttr(u)}"`;
186
+ }).join(" ");
187
+ h.push(`${m}<${o}${i ? " " + i : ""} />`);
188
+ } else {
189
+ h.push(`${m}<${o}>`);
190
+ for (const [i, p] of r) {
191
+ const e = l[i] ?? i, d = p == null ? g : String(p);
192
+ h.push(`${m}${m}<${e}>${this._escText(d)}</${e}>`);
193
+ }
194
+ h.push(`${m}</${o}>`);
195
+ }
196
+ }
197
+ return h.push(`</${c}>`), h.join(`
198
+ `);
199
+ }
200
+ // ── 3. SAP BAPI XML 응답 파싱 ────────────────────────────────
201
+ /**
202
+ * SAP BAPI XML 응답을 파싱하여 { header, items, returns } 구조로 반환.
203
+ *
204
+ * 지원 패턴:
205
+ * <DOCUMENTHEADER>...</DOCUMENTHEADER>
206
+ * <ACCOUNTGL><ITEM>...</ITEM></ACCOUNTGL>
207
+ * <RETURN><TYPE>S</TYPE><MESSAGE>...</MESSAGE></RETURN>
208
+ */
209
+ static parseSap(t) {
210
+ var _, g, f, m;
211
+ const c = new DOMParser().parseFromString(t.trim(), "text/xml"), o = { header: {}, items: [], returns: [], raw: c }, a = c.getElementsByTagName("DOCUMENTHEADER")[0];
212
+ if (a)
213
+ for (const h of Array.from(a.children))
214
+ o.header[h.tagName] = ((_ = h.textContent) == null ? void 0 : _.trim()) ?? "";
215
+ const l = c.getElementsByTagName("RETURN");
216
+ for (const h of Array.from(l)) {
217
+ const n = {};
218
+ for (const r of Array.from(h.children))
219
+ n[r.tagName] = ((g = r.textContent) == null ? void 0 : g.trim()) ?? "";
220
+ o.returns.push(n);
221
+ }
222
+ const x = ["ACCOUNTGL", "ACCOUNTRECEIVABLE", "ACCOUNTPAYABLE", "ITEMS"];
223
+ for (const h of x) {
224
+ const n = c.getElementsByTagName(h)[0];
225
+ if (!n) continue;
226
+ const r = n.getElementsByTagName("ITEM"), i = r.length > 0 ? Array.from(r) : [n];
227
+ for (const p of i) {
228
+ const e = {};
229
+ for (const d of Array.from(p.children))
230
+ e[d.tagName] = ((f = d.textContent) == null ? void 0 : f.trim()) ?? "";
231
+ o.items.push(e);
232
+ }
233
+ break;
234
+ }
235
+ if (o.items.length === 0) {
236
+ const h = c.documentElement, n = Array.from(h.children).filter((r) => r.hasAttribute("SEGMENT"));
237
+ for (const r of n) {
238
+ if (r.tagName === "EDI_DC40") continue;
239
+ const i = {};
240
+ for (const p of Array.from(r.children))
241
+ i[p.tagName] = ((m = p.textContent) == null ? void 0 : m.trim()) ?? "";
242
+ Object.keys(i).length > 0 && o.items.push(i);
243
+ }
244
+ }
245
+ return o;
246
+ }
247
+ // ── 4. SAP BAPI 페이로드 → XML 직렬화 ───────────────────────
248
+ /**
249
+ * BAPI 페이로드 객체를 SAP XML 형식으로 직렬화.
250
+ * sapGenPayload()의 결과 또는 단일 document 객체를 받음.
251
+ */
252
+ static stringifySap(t) {
253
+ const s = [
254
+ '<?xml version="1.0" encoding="UTF-8"?>',
255
+ "<BAPI_CALL>"
256
+ ];
257
+ if (t.BAPI_FUNCTION && s.push(` <FUNCTION>${this._escText(t.BAPI_FUNCTION)}</FUNCTION>`), t.DOCUMENTHEADER && typeof t.DOCUMENTHEADER == "object") {
258
+ s.push(" <DOCUMENTHEADER>");
259
+ for (const [o, a] of Object.entries(t.DOCUMENTHEADER))
260
+ a != null && a !== "" && s.push(` <${o}>${this._escText(String(a))}</${o}>`);
261
+ s.push(" </DOCUMENTHEADER>");
262
+ }
263
+ const c = Object.keys(t).find(
264
+ (o) => Array.isArray(t[o]) && !o.startsWith("_")
265
+ );
266
+ if (c) {
267
+ s.push(` <${c}>`);
268
+ for (const o of t[c]) {
269
+ s.push(" <ITEM>");
270
+ for (const [a, l] of Object.entries(o))
271
+ l != null && l !== "" && !a.startsWith("_") && s.push(` <${a}>${this._escText(String(l))}</${a}>`);
272
+ s.push(" </ITEM>");
273
+ }
274
+ s.push(` </${c}>`);
275
+ }
276
+ return s.push("</BAPI_CALL>"), s.join(`
277
+ `);
278
+ }
279
+ // ── 5. 다건 documents 배열 → XML (sapGenPayload 결과 전체) ───
280
+ /**
281
+ * sapGenPayload()의 { totalDocuments, documents[] } 결과를
282
+ * 다건 BAPI XML로 직렬화.
283
+ */
284
+ static stringifySapBatch(t) {
285
+ const s = [
286
+ '<?xml version="1.0" encoding="UTF-8"?>',
287
+ `<BAPI_BATCH total="${t.documents.length}">`
288
+ ];
289
+ return t.documents.forEach((c, o) => {
290
+ s.push(` <BAPI_CALL seq="${o + 1}">`);
291
+ const a = this.stringifySap(c).split(`
292
+ `).filter((l) => !l.startsWith("<?xml")).map((l) => " " + l).join(`
293
+ `);
294
+ s.push(a), s.push(" </BAPI_CALL>");
295
+ }), s.push("</BAPI_BATCH>"), s.join(`
296
+ `);
297
+ }
298
+ // ── 내부 이스케이프 헬퍼 ─────────────────────────────────────
299
+ static _escText(t) {
300
+ return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
301
+ }
302
+ static _escAttr(t) {
303
+ return this._escText(t).replace(/"/g, "&quot;").replace(/'/g, "&apos;");
304
+ }
305
+ }
306
+ export {
307
+ w as OpenGrid,
308
+ N as OrgChart,
309
+ b as XmlConverter
310
+ };
311
+ //# sourceMappingURL=open-grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-grid.js","sources":["../src/core/OrgChart.ts","../src/core/XmlConverter.ts"],"sourcesContent":["import { buildTree, TreeNode } from './TreeEngine.js';\n\nexport interface OrgChartColumnDef {\n field: string;\n className?: string;\n style?: string | ((value: any, row: Record<string, any>) => string);\n renderer?: (value: any, row: Record<string, any>) => HTMLElement | string;\n}\n\nexport interface OrgChartOptions {\n idField: string;\n parentIdField: string;\n columns: OrgChartColumnDef[];\n nodeWidth?: number;\n nodeHeight?: number;\n levelGap?: number;\n siblingGap?: number;\n expandOnLoad?: boolean;\n onNodeClick?: (id: any, data: Record<string, any>) => void;\n}\n\ninterface LayoutInfo { x: number; y: number; }\n\nexport class OrgChart {\n private _container: HTMLElement;\n private _opts: Required<OrgChartOptions>;\n private _data: Record<string, any>[] = [];\n private _roots: TreeNode<any>[] = [];\n private _expandedKeys = new Set<any>();\n private _selectedId: any = null;\n\n constructor(selector: string | HTMLElement, opts: OrgChartOptions) {\n this._container = typeof selector === 'string'\n ? (document.querySelector(selector) as HTMLElement)\n : selector;\n this._opts = {\n nodeWidth: 160, nodeHeight: 72, levelGap: 52, siblingGap: 20,\n expandOnLoad: true, onNodeClick: () => {},\n ...opts,\n };\n this._container.classList.add('og-orgchart');\n }\n\n setData(data: Record<string, any>[]): void {\n this._data = data;\n const { idField, parentIdField, expandOnLoad } = this._opts;\n if (expandOnLoad && this._expandedKeys.size === 0) {\n data.forEach(r => this._expandedKeys.add(r[idField]));\n }\n this._roots = buildTree(data, { idField, parentIdField }, this._expandedKeys);\n this._render();\n }\n\n setTheme(theme: string): void {\n this._container.setAttribute('data-og-theme', theme);\n }\n\n expandAll(): void {\n const collect = (nodes: TreeNode<any>[]) => {\n for (const n of nodes) {\n this._expandedKeys.add(n._treeId);\n if (n.children.length) collect(n.children);\n }\n };\n collect(this._roots);\n this._rebuild();\n }\n\n collapseAll(): void {\n this._expandedKeys.clear();\n this._rebuild();\n }\n\n private _toggle(id: any): void {\n if (this._expandedKeys.has(id)) this._expandedKeys.delete(id);\n else this._expandedKeys.add(id);\n this._rebuild();\n }\n\n private _rebuild(): void {\n const { idField, parentIdField } = this._opts;\n this._roots = buildTree(this._data, { idField, parentIdField }, this._expandedKeys);\n this._render();\n }\n\n // ── 레이아웃 계산 (post-order: 리프부터 배치, 부모는 자식 중앙) ──\n private _calcLayout(): { layout: Map<any, LayoutInfo>; totalW: number; totalH: number } {\n const { nodeWidth, nodeHeight, levelGap, siblingGap } = this._opts;\n const layout = new Map<any, LayoutInfo>();\n let nextX = 0;\n\n const place = (node: TreeNode<any>): { minX: number; maxX: number } => {\n const y = node._depth * (nodeHeight + levelGap);\n const vis = node._expanded ? node.children : [];\n\n if (!vis.length) {\n const x = nextX;\n nextX += nodeWidth + siblingGap;\n layout.set(node._treeId, { x, y });\n return { minX: x, maxX: x };\n }\n\n let firstX = Infinity, lastX = -Infinity;\n for (const child of vis) {\n const { minX, maxX } = place(child);\n if (minX < firstX) firstX = minX;\n if (maxX > lastX) lastX = maxX;\n }\n // 자식들의 span 중앙에 부모 배치\n const x = firstX + (lastX - firstX + nodeWidth) / 2 - nodeWidth / 2;\n layout.set(node._treeId, { x, y });\n return { minX: firstX, maxX: lastX };\n };\n\n for (const root of this._roots) place(root);\n\n let maxX = 0, maxY = 0;\n for (const { x, y } of layout.values()) {\n if (x + nodeWidth > maxX) maxX = x + nodeWidth;\n if (y + nodeHeight > maxY) maxY = y + nodeHeight;\n }\n return { layout, totalW: maxX + siblingGap, totalH: maxY + levelGap + 16 };\n }\n\n // ── SVG 직선 헬퍼 ──\n private _line(svg: SVGSVGElement, x1: number, y1: number, x2: number, y2: number): void {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n el.setAttribute('x1', String(x1));\n el.setAttribute('y1', String(y1));\n el.setAttribute('x2', String(x2));\n el.setAttribute('y2', String(y2));\n el.setAttribute('class', 'og-orgchart-line');\n svg.appendChild(el);\n }\n\n // ── 렌더 ──\n private _render(): void {\n const { nodeWidth, nodeHeight, levelGap, columns } = this._opts;\n const { layout, totalW, totalH } = this._calcLayout();\n\n this._container.innerHTML = '';\n\n const wrap = document.createElement('div');\n wrap.className = 'og-orgchart-wrap';\n wrap.style.cssText = `width:${totalW}px;height:${totalH}px;`;\n\n // ① SVG 연결선\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('width', String(totalW));\n svg.setAttribute('height', String(totalH));\n svg.style.cssText = 'position:absolute;top:0;left:0;pointer-events:none;overflow:visible;';\n\n const drawLines = (nodes: TreeNode<any>[]): void => {\n for (const node of nodes) {\n if (!node._expanded || !node.children.length) continue;\n const p = layout.get(node._treeId)!;\n const px = p.x + nodeWidth / 2;\n const py = p.y + nodeHeight;\n const midY = py + levelGap / 2;\n const vis = node.children;\n\n // 부모 → midY\n this._line(svg, px, py, px, midY);\n\n if (vis.length > 1) {\n const c0 = layout.get(vis[0]._treeId)!;\n const cn = layout.get(vis[vis.length - 1]._treeId)!;\n // 수평 브래킷\n this._line(svg, c0.x + nodeWidth / 2, midY, cn.x + nodeWidth / 2, midY);\n }\n for (const child of vis) {\n const ci = layout.get(child._treeId)!;\n const cx = ci.x + nodeWidth / 2;\n // midY → 자식 상단\n this._line(svg, cx, midY, cx, ci.y);\n }\n drawLines(vis);\n }\n };\n drawLines(this._roots);\n wrap.appendChild(svg);\n\n // ② 카드 렌더\n const renderNodes = (nodes: TreeNode<any>[]): void => {\n for (const node of nodes) {\n const info = layout.get(node._treeId);\n if (!info) continue;\n\n const card = document.createElement('div');\n card.className = 'og-orgchart-node';\n if (node._hasChildren) card.classList.add('og-orgchart-node--branch');\n if (node._expanded) card.classList.add('og-orgchart-node--expanded');\n if (this._selectedId === node._treeId) card.classList.add('og-orgchart-node--selected');\n card.style.cssText = `left:${info.x}px;top:${info.y}px;width:${nodeWidth}px;height:${nodeHeight}px;`;\n\n // 컬럼 렌더\n const content = document.createElement('div');\n content.className = 'og-orgchart-node-content';\n for (const col of columns) {\n const val = node.data[col.field];\n const div = document.createElement('div');\n div.className = 'og-orgchart-col' + (col.className ? ' ' + col.className : '');\n if (col.style) {\n const s = typeof col.style === 'function' ? col.style(val, node.data) : col.style;\n div.setAttribute('style', s);\n }\n if (col.renderer) {\n const out = col.renderer(val, node.data);\n if (typeof out === 'string') div.innerHTML = out;\n else div.appendChild(out);\n } else {\n div.textContent = val ?? '';\n }\n content.appendChild(div);\n }\n card.appendChild(content);\n\n // 확장/축소 토글 버튼 (카드 하단 중앙)\n if (node._hasChildren) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'og-orgchart-toggle';\n btn.setAttribute('aria-expanded', node._expanded ? 'true' : 'false');\n btn.setAttribute('aria-label', node._expanded ? '접기' : '펼치기');\n const icon = document.createElement('i');\n icon.setAttribute('aria-hidden', 'true');\n icon.className = node._expanded ? 'bi bi-dash-circle' : 'bi bi-plus-circle';\n btn.appendChild(icon);\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n this._toggle(node._treeId);\n });\n card.appendChild(btn);\n }\n\n card.addEventListener('click', () => {\n this._selectedId = node._treeId;\n this._opts.onNodeClick(node._treeId, node.data);\n // 선택 하이라이트만 갱신 (전체 재렌더 최소화)\n this._container.querySelectorAll('.og-orgchart-node--selected')\n .forEach(el => el.classList.remove('og-orgchart-node--selected'));\n card.classList.add('og-orgchart-node--selected');\n });\n\n wrap.appendChild(card);\n\n if (node._expanded && node.children.length) renderNodes(node.children);\n }\n };\n renderNodes(this._roots);\n\n this._container.appendChild(wrap);\n }\n}\n","/**\n * XmlConverter — XML ↔ 그리드 데이터 양방향 변환 유틸리티.\n *\n * 지원 포맷:\n * A. Element 방식 <row><name>홍길동</name></row>\n * B. Attribute 방식 <row name=\"홍길동\" />\n * C. SAP BAPI XML 응답 <RETURN><TYPE>S</TYPE><BELNR>...</BELNR></RETURN>\n * D. SAP IDoc XML <IDOC><E1HEADER SEGMENT=\"1\"><BUKRS>1000</BUKRS></IDOC>\n *\n * 외부 의존성 없음 — 브라우저 내장 DOMParser 사용.\n */\n\n// ─── 파싱 옵션 ────────────────────────────────────────────────\nexport interface XmlParseOptions {\n /** 루트 엘리먼트 태그명 (생략 시 문서 루트 자동 사용) */\n rootTag?: string;\n /** 행 엘리먼트 태그명 (생략 시 루트의 첫 번째 자식 자동 감지) */\n rowTag?: string;\n /** 값 추출 방식: 'element' | 'attribute' | 'auto'(기본) */\n mode?: 'element' | 'attribute' | 'auto';\n /** XML 태그명 → 그리드 field명 매핑 (생략 시 태그명 그대로 사용) */\n fieldMap?: Record<string, string>;\n /** 텍스트 값 앞뒤 공백 제거 (기본 true) */\n trim?: boolean;\n}\n\n// ─── 직렬화 옵션 ─────────────────────────────────────────────\nexport interface XmlStringifyOptions {\n /** 루트 태그명 (기본 'rows') */\n rootTag?: string;\n /** 행 태그명 (기본 'row') */\n rowTag?: string;\n /** 출력 방식: 'element'(기본) | 'attribute' */\n mode?: 'element' | 'attribute';\n /** 그리드 field명 → XML 태그명 매핑 */\n fieldMap?: Record<string, string>;\n /** XML 선언부 포함 여부 (기본 true) */\n declaration?: boolean;\n /** 들여쓰기 공백 수 (기본 2) */\n indent?: number;\n /** null/undefined 처리 문자열 (기본 '') */\n nullAs?: string;\n /** 출력에서 제외할 필드 목록 */\n excludeFields?: string[];\n}\n\n// ─── SAP 파싱 결과 ────────────────────────────────────────────\nexport interface SapParseResult {\n header: Record<string, string>;\n items: Record<string, string>[];\n returns: Record<string, string>[];\n raw?: Document;\n}\n\n// ─── 메인 클래스 ─────────────────────────────────────────────\nexport class XmlConverter {\n\n // ── 1. XML → 데이터 배열 ────────────────────────────────────\n /**\n * XML 문자열을 파싱하여 그리드 데이터 배열로 변환.\n * Element / Attribute 방식 자동 감지.\n *\n * @throws XML 파싱 오류 시 Error 발생\n */\n static parse(xml: string, options: XmlParseOptions = {}): Record<string, any>[] {\n const { fieldMap = {}, trim = true } = options;\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml.trim(), 'text/xml');\n\n const errNode = doc.querySelector('parsererror');\n if (errNode) throw new Error(`XML 파싱 오류: ${errNode.textContent?.trim()}`);\n\n const root = doc.documentElement;\n\n // rowTag 자동 감지: 명시 → rootTag의 첫 자식 → 루트의 첫 자식\n let rowTag = options.rowTag;\n if (!rowTag) {\n const rootEl = options.rootTag ? doc.querySelector(options.rootTag) : root;\n rowTag = rootEl?.children[0]?.tagName ?? 'row';\n }\n\n const rowEls = doc.getElementsByTagName(rowTag);\n const rows: Record<string, any>[] = [];\n\n for (let i = 0; i < rowEls.length; i++) {\n const el = rowEls[i]!;\n const row: Record<string, any> = {};\n\n // Attribute 방식\n for (const attr of Array.from(el.attributes)) {\n const field = fieldMap[attr.name] ?? attr.name;\n row[field] = trim ? attr.value.trim() : attr.value;\n }\n\n // Element 방식 (자식 태그가 있으면 우선)\n for (const child of Array.from(el.children)) {\n const field = fieldMap[child.tagName] ?? child.tagName;\n const text = child.textContent ?? '';\n row[field] = trim ? text.trim() : text;\n }\n\n rows.push(row);\n }\n\n return rows;\n }\n\n // ── 2. 데이터 배열 → XML ─────────────────────────────────────\n /**\n * 그리드 데이터 배열을 XML 문자열로 직렬화.\n */\n static stringify(data: Record<string, any>[], options: XmlStringifyOptions = {}): string {\n const {\n rootTag = 'rows',\n rowTag = 'row',\n mode = 'element',\n fieldMap = {},\n declaration = true,\n indent = 2,\n nullAs = '',\n excludeFields = [],\n } = options;\n\n const pad = ' '.repeat(indent);\n const lines: string[] = [];\n\n if (declaration) lines.push('<?xml version=\"1.0\" encoding=\"UTF-8\"?>');\n lines.push(`<${rootTag}>`);\n\n for (const item of data) {\n const entries = Object.entries(item).filter(([k]) => !excludeFields.includes(k));\n\n if (mode === 'attribute') {\n const attrs = entries\n .map(([k, v]) => {\n const tag = fieldMap[k] ?? k;\n const val = v == null ? nullAs : String(v);\n return `${tag}=\"${this._escAttr(val)}\"`;\n })\n .join(' ');\n lines.push(`${pad}<${rowTag}${attrs ? ' ' + attrs : ''} />`);\n } else {\n lines.push(`${pad}<${rowTag}>`);\n for (const [k, v] of entries) {\n const tag = fieldMap[k] ?? k;\n const val = v == null ? nullAs : String(v);\n lines.push(`${pad}${pad}<${tag}>${this._escText(val)}</${tag}>`);\n }\n lines.push(`${pad}</${rowTag}>`);\n }\n }\n\n lines.push(`</${rootTag}>`);\n return lines.join('\\n');\n }\n\n // ── 3. SAP BAPI XML 응답 파싱 ────────────────────────────────\n /**\n * SAP BAPI XML 응답을 파싱하여 { header, items, returns } 구조로 반환.\n *\n * 지원 패턴:\n * <DOCUMENTHEADER>...</DOCUMENTHEADER>\n * <ACCOUNTGL><ITEM>...</ITEM></ACCOUNTGL>\n * <RETURN><TYPE>S</TYPE><MESSAGE>...</MESSAGE></RETURN>\n */\n static parseSap(xml: string): SapParseResult {\n const parser = new DOMParser();\n const doc = parser.parseFromString(xml.trim(), 'text/xml');\n\n const result: SapParseResult = { header: {}, items: [], returns: [], raw: doc };\n\n // DOCUMENTHEADER\n const headerEl = doc.getElementsByTagName('DOCUMENTHEADER')[0];\n if (headerEl) {\n for (const child of Array.from(headerEl.children)) {\n result.header[child.tagName] = child.textContent?.trim() ?? '';\n }\n }\n\n // RETURN (복수 지원)\n const returnEls = doc.getElementsByTagName('RETURN');\n for (const r of Array.from(returnEls)) {\n const ret: Record<string, string> = {};\n for (const child of Array.from(r.children)) {\n ret[child.tagName] = child.textContent?.trim() ?? '';\n }\n result.returns.push(ret);\n }\n\n // 라인 아이템 — 순서대로 시도\n const itemParentTags = ['ACCOUNTGL', 'ACCOUNTRECEIVABLE', 'ACCOUNTPAYABLE', 'ITEMS'];\n for (const parentTag of itemParentTags) {\n const parentEl = doc.getElementsByTagName(parentTag)[0];\n if (!parentEl) continue;\n\n // <ITEM> 자식이 있으면 ITEM 단위로, 없으면 parentEl 자체를 1개 아이템으로\n const itemEls = parentEl.getElementsByTagName('ITEM');\n const targets = itemEls.length > 0 ? Array.from(itemEls) : [parentEl];\n\n for (const el of targets) {\n const row: Record<string, string> = {};\n for (const child of Array.from(el.children)) {\n row[child.tagName] = child.textContent?.trim() ?? '';\n }\n result.items.push(row);\n }\n break;\n }\n\n // IDoc 패턴: <SEGMENT> 속성이 있는 최상위 자식들\n if (result.items.length === 0) {\n const root = doc.documentElement;\n const segments = Array.from(root.children).filter(el => el.hasAttribute('SEGMENT'));\n for (const seg of segments) {\n if (seg.tagName === 'EDI_DC40') continue; // 제어 레코드 제외\n const row: Record<string, string> = {};\n for (const child of Array.from(seg.children)) {\n row[child.tagName] = child.textContent?.trim() ?? '';\n }\n if (Object.keys(row).length > 0) result.items.push(row);\n }\n }\n\n return result;\n }\n\n // ── 4. SAP BAPI 페이로드 → XML 직렬화 ───────────────────────\n /**\n * BAPI 페이로드 객체를 SAP XML 형식으로 직렬화.\n * sapGenPayload()의 결과 또는 단일 document 객체를 받음.\n */\n static stringifySap(payload: {\n BAPI_FUNCTION?: string;\n DOCUMENTHEADER?: Record<string, any>;\n ACCOUNTGL?: Record<string, any>[];\n [key: string]: any;\n }): string {\n const lines: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<BAPI_CALL>',\n ];\n\n if (payload.BAPI_FUNCTION) {\n lines.push(` <FUNCTION>${this._escText(payload.BAPI_FUNCTION)}</FUNCTION>`);\n }\n\n if (payload.DOCUMENTHEADER && typeof payload.DOCUMENTHEADER === 'object') {\n lines.push(' <DOCUMENTHEADER>');\n for (const [k, v] of Object.entries(payload.DOCUMENTHEADER)) {\n if (v != null && v !== '') {\n lines.push(` <${k}>${this._escText(String(v))}</${k}>`);\n }\n }\n lines.push(' </DOCUMENTHEADER>');\n }\n\n // 배열 타입 필드를 ACCOUNTGL로 처리\n const itemsKey = Object.keys(payload).find(\n k => Array.isArray(payload[k]) && !k.startsWith('_')\n );\n if (itemsKey) {\n lines.push(` <${itemsKey}>`);\n for (const item of (payload[itemsKey] as Record<string, any>[])) {\n lines.push(' <ITEM>');\n for (const [k, v] of Object.entries(item)) {\n if (v != null && v !== '' && !k.startsWith('_')) {\n lines.push(` <${k}>${this._escText(String(v))}</${k}>`);\n }\n }\n lines.push(' </ITEM>');\n }\n lines.push(` </${itemsKey}>`);\n }\n\n lines.push('</BAPI_CALL>');\n return lines.join('\\n');\n }\n\n // ── 5. 다건 documents 배열 → XML (sapGenPayload 결과 전체) ───\n /**\n * sapGenPayload()의 { totalDocuments, documents[] } 결과를\n * 다건 BAPI XML로 직렬화.\n */\n static stringifySapBatch(payload: { documents: any[] }): string {\n const lines: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n `<BAPI_BATCH total=\"${payload.documents.length}\">`,\n ];\n payload.documents.forEach((doc, i) => {\n lines.push(` <BAPI_CALL seq=\"${i + 1}\">`);\n const inner = this.stringifySap(doc)\n .split('\\n')\n .filter(l => !l.startsWith('<?xml'))\n .map(l => ' ' + l)\n .join('\\n');\n lines.push(inner);\n lines.push(' </BAPI_CALL>');\n });\n lines.push('</BAPI_BATCH>');\n return lines.join('\\n');\n }\n\n // ── 내부 이스케이프 헬퍼 ─────────────────────────────────────\n private static _escText(s: string): string {\n return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n\n private static _escAttr(s: string): string {\n return this._escText(s).replace(/\"/g, '&quot;').replace(/'/g, '&apos;');\n }\n}\n"],"names":["OrgChart","selector","opts","data","idField","parentIdField","expandOnLoad","r","buildTree","theme","collect","nodes","n","id","nodeWidth","nodeHeight","levelGap","siblingGap","layout","nextX","place","node","y","vis","x","firstX","lastX","child","minX","maxX","root","maxY","svg","x1","y1","x2","y2","el","columns","totalW","totalH","wrap","drawLines","p","px","py","midY","c0","cn","ci","cx","renderNodes","info","card","content","col","val","div","s","out","btn","icon","e","XmlConverter","xml","options","fieldMap","trim","doc","errNode","_a","rowTag","rootEl","_b","rowEls","rows","i","row","attr","field","text","rootTag","mode","declaration","indent","nullAs","excludeFields","pad","lines","item","entries","k","attrs","v","tag","result","headerEl","returnEls","ret","itemParentTags","parentTag","parentEl","itemEls","targets","_c","segments","seg","_d","payload","itemsKey","inner"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * OPEN_GRID 성능 벤치마크
3
+ *
4
+ * 브라우저 콘솔 또는 Node 환경에서 실행:
5
+ * npx vite-node src/bench/perf.ts
6
+ *
7
+ * 측정 항목:
8
+ * - 10만 행 데이터 생성 시간
9
+ * - DataLayer.setData() 시간
10
+ * - DataLayer.applySort() 시간
11
+ * - DataLayer.applyFilter() 시간
12
+ * - buildGroups() 시간
13
+ * - buildTree() 시간
14
+ * - MergeEngine.applyAutoMerge() 시간
15
+ */
16
+ export {};