open-grid 0.3.1 → 0.4.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/README.md +3 -2
- package/dist/OpenGrid-ClmeIJYR.cjs +88 -0
- package/dist/OpenGrid-ClmeIJYR.cjs.map +1 -0
- package/dist/{OpenGrid-Dult64jp.js → OpenGrid-doS5aFVl.js} +976 -708
- package/dist/OpenGrid-doS5aFVl.js.map +1 -0
- package/dist/open-grid-base.css +24 -0
- package/dist/open-grid-react.cjs +1 -1
- package/dist/open-grid-react.js +1 -1
- package/dist/open-grid-vue.cjs +1 -1
- package/dist/open-grid-vue.js +1 -1
- package/dist/open-grid.cjs +6 -6
- package/dist/open-grid.cjs.map +1 -1
- package/dist/open-grid.js +224 -172
- package/dist/open-grid.js.map +1 -1
- package/dist/types/core/CrossGridMapper.d.ts +21 -0
- package/dist/types/core/CrossGridRegistry.d.ts +13 -0
- package/dist/types/core/DragVisuals.d.ts +23 -0
- package/dist/types/core/GridShuttle.d.ts +25 -0
- package/dist/types/core/OpenGrid.d.ts +28 -0
- package/dist/types/core/RowDragDrop.d.ts +25 -5
- package/dist/types/core/renderers/CellRenderer.d.ts +12 -1
- package/dist/types/core/types.d.ts +57 -0
- package/dist/types/index.d.ts +2 -0
- package/package.json +2 -5
- package/dist/OpenGrid-CzP1mcZW.cjs +0 -90
- package/dist/OpenGrid-CzP1mcZW.cjs.map +0 -1
- package/dist/OpenGrid-Dult64jp.js.map +0 -1
package/dist/open-grid-base.css
CHANGED
|
@@ -235,6 +235,20 @@
|
|
|
235
235
|
transition: background var(--og-transition-fast), box-shadow var(--og-transition-fast);
|
|
236
236
|
}
|
|
237
237
|
.og-row:nth-child(even) { background: var(--og-row-alt-bg); }
|
|
238
|
+
|
|
239
|
+
/* ── 가변 행 높이(autoHeight, 비가상 모드) ──
|
|
240
|
+
가상 스크롤은 고정 rowHeight 절대배치를 쓰지만, autoHeight 모드에서는 모든 행을
|
|
241
|
+
일반 플로우로 쌓아 내용(특히 wrap 컬럼 줄바꿈)에 따라 높이가 자동으로 늘어나게 한다. */
|
|
242
|
+
.og-autoheight { height: auto !important; }
|
|
243
|
+
.og-autoheight .og-row,
|
|
244
|
+
.og-autoheight .og-group-row {
|
|
245
|
+
position: relative !important;
|
|
246
|
+
top: auto !important;
|
|
247
|
+
height: auto !important;
|
|
248
|
+
min-height: var(--og-row-height, 32px);
|
|
249
|
+
align-items: stretch;
|
|
250
|
+
}
|
|
251
|
+
.og-autoheight .og-cell { height: auto; align-items: center; }
|
|
238
252
|
.og-row:hover { background: var(--og-row-hover-bg) !important; box-shadow: inset var(--og-row-accent-width) 0 0 var(--og-row-accent-color); }
|
|
239
253
|
|
|
240
254
|
/* 선택된 행 — 배경 + 텍스트 모두 강제 적용 */
|
|
@@ -289,6 +303,16 @@
|
|
|
289
303
|
word-break: break-word;
|
|
290
304
|
line-height: 1.35;
|
|
291
305
|
}
|
|
306
|
+
/* 셀 내부 텍스트 span(.og-cell-text/.og-cell-date)은 렌더러가 인라인으로
|
|
307
|
+
white-space:nowrap 을 박는다. wrap 컬럼에서는 그 인라인을 !important 로 무력화해야
|
|
308
|
+
실제로 여러 줄로 꺾인다(클래스만으로는 인라인을 못 이김). */
|
|
309
|
+
.og-cell--wrap .og-cell-text,
|
|
310
|
+
.og-cell--wrap .og-cell-date {
|
|
311
|
+
white-space: normal !important;
|
|
312
|
+
text-overflow: clip !important;
|
|
313
|
+
overflow: visible;
|
|
314
|
+
word-break: break-word;
|
|
315
|
+
}
|
|
292
316
|
|
|
293
317
|
/* WCAG 2.2 2.4.13: 포커스 셀 outline 최소 3px, 대비 3:1 이상 */
|
|
294
318
|
.og-cell.og-cell-focused {
|
package/dist/open-grid-react.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("react/jsx-runtime"),r=require("react"),D=require("./OpenGrid-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=require("react/jsx-runtime"),r=require("react"),D=require("./OpenGrid-ClmeIJYR.cjs");function M({data:e,columns:t,height:u=400,width:s="100%",editable:l=!1,sortable:O=!0,filterable:o=!0,rowNumber:x=!1,checkColumn:y=!1,stateColumn:R=!1,draggable:G=!1,frozenColumns:j=0,theme:f="default",options:P,style:W,className:z,onReady:c,onDataChange:b,onCellClick:q,onRowClick:S,onEditEnd:d,onSortChange:v,onFilterChange:E,onRowDrop:T}){const i=r.useRef(null),n=r.useRef(null),A={height:typeof u=="number"?`${u}px`:u,width:typeof s=="number"?`${s}px`:s,display:"block",boxSizing:"border-box",...W};return r.useEffect(()=>{if(!i.current)return;const B={columns:t,height:"100%",width:"100%",editable:l,sortable:O,filterable:o,rowNumber:x,checkColumn:y,stateColumn:R,draggable:G,frozenColumns:j,theme:f,...P,onReady:p=>{n.current=p,e!=null&&e.length&&p.setData(e),c==null||c(p)},...b&&{onDataChange:b},...q&&{onCellClick:q},...S&&{onRowClick:S},...d&&{onEditEnd:d},...v&&{onSortChange:v},...E&&{onFilterChange:E},...T&&{onRowDrop:T}},$=new D.OpenGrid(i.current,B);return n.current=$,()=>{$.destroy(),n.current=null}},[t,l,O,o,x,y,R,G,j]),r.useEffect(()=>{n.current&&e&&n.current.setData(e)},[e]),r.useEffect(()=>{n.current&&n.current.setTheme(f)},[f]),g.jsx("div",{ref:i,style:A,className:z})}const H=r.forwardRef((e,t)=>{r.useRef(null);const u=r.useRef(null);return r.useEffect(()=>{u.current&&t&&(typeof t=="function"?t(u.current):t.current=u.current)}),g.jsx(M,{...e})});H.displayName="OpenGrid";exports.OpenGrid=M;
|
|
2
2
|
//# sourceMappingURL=open-grid-react.cjs.map
|
package/dist/open-grid-react.js
CHANGED
package/dist/open-grid-vue.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("vue"),p=require("./OpenGrid-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("vue"),p=require("./OpenGrid-ClmeIJYR.cjs"),h=a.defineComponent({__name:"OpenGrid",props:{data:{default:()=>[]},columns:{},height:{default:400},width:{default:"100%"},editable:{type:Boolean,default:!1},sortable:{type:Boolean,default:!0},filterable:{type:Boolean,default:!0},rowNumber:{type:Boolean,default:!1},checkColumn:{type:Boolean,default:!1},stateColumn:{type:Boolean,default:!1},draggable:{type:Boolean,default:!1},frozenColumns:{default:0},theme:{default:"default"},options:{}},emits:["update:data","ready","cell-click","row-click","edit-end","sort-change","filter-change","row-check"],setup(r,{expose:c,emit:u}){const e=r,n=u,d=a.ref(),o=a.shallowRef(null);let i=null;const f=a.computed(()=>({height:typeof e.height=="number"?`${e.height}px`:e.height,width:typeof e.width=="number"?`${e.width}px`:e.width}));return a.onMounted(()=>{if(!d.value)return;const l={columns:e.columns,height:"100%",width:"100%",editable:e.editable,sortable:e.sortable,filterable:e.filterable,rowNumber:e.rowNumber,checkColumn:e.checkColumn,stateColumn:e.stateColumn,draggable:e.draggable,frozenColumns:e.frozenColumns,theme:e.theme,...e.options,onReady:t=>{var s;(s=e.data)!=null&&s.length&&t.setData(e.data),n("ready",t)},onCellClick:t=>n("cell-click",t),onRowClick:t=>n("row-click",t),onEditEnd:t=>n("edit-end",t),onSortChange:t=>n("sort-change",t),onFilterChange:t=>n("filter-change",t),onDataChange:t=>{i=t,n("update:data",t)}};o.value=new p.OpenGrid(d.value,l)}),a.watch(()=>e.data,l=>{!o.value||!l||l!==i&&o.value.setData(l)},{deep:!1}),a.watch(()=>e.theme,l=>{o.value&&l&&o.value.setTheme(l)}),a.watch(()=>e.columns,l=>{o.value&&o.value.applyColumns(l)},{deep:!1}),a.onUnmounted(()=>{var l;(l=o.value)==null||l.destroy(),o.value=null}),c({grid:o}),(l,t)=>(a.openBlock(),a.createElementBlock("div",{ref_key:"containerRef",ref:d,class:"og-vue-wrapper",style:a.normalizeStyle(f.value)},null,4))}}),m=(r,c)=>{const u=r.__vccOpts||r;for(const[e,n]of c)u[e]=n;return u},g=m(h,[["__scopeId","data-v-0a49d4fc"]]);exports.OpenGrid=g;
|
|
2
2
|
//# sourceMappingURL=open-grid-vue.cjs.map
|
package/dist/open-grid-vue.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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-
|
|
2
|
+
import { O as w } from "./OpenGrid-doS5aFVl.js";
|
|
3
3
|
const _ = /* @__PURE__ */ p({
|
|
4
4
|
__name: "OpenGrid",
|
|
5
5
|
props: {
|
package/dist/open-grid.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("./OpenGrid-
|
|
2
|
-
`)}static parseSap(t){var
|
|
3
|
-
`)}static stringifySapBatch(t){const
|
|
4
|
-
`).filter(
|
|
5
|
-
`);
|
|
6
|
-
`)}static _escText(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}static _escAttr(t){return this._escText(t).replace(/"/g,""").replace(/'/g,"'")}}exports.OpenGrid=A.OpenGrid;exports.
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("./OpenGrid-ClmeIJYR.cjs");class C{constructor(t,e,o,i={}){this._left=t,this._right=e;const r=document.createElement("div");r.className="og-shuttle",r.style.cssText=`display:flex;gap:6px;align-items:center;justify-content:center;flex-direction:${i.layout==="horizontal"?"row":"column"};`;const c=(m,f,u)=>{const a=document.createElement("button");return a.type="button",a.className="og-shuttle-btn",a.textContent=m,a.title=f,a.style.cssText="min-width:34px;height:30px;padding:0 8px;border:1px solid #bbb;border-radius:7px;background:#fff;cursor:pointer;font-size:14px;color:#444;line-height:1;box-shadow:0 1px 2px rgba(0,0,0,0.06);",a.addEventListener("mouseover",()=>{a.style.background="#f0f6ff",a.style.borderColor="#1976d2"}),a.addEventListener("mouseout",()=>{a.style.background="#fff",a.style.borderColor="#bbb"}),a.addEventListener("click",u),a},_=i.labels??{};r.appendChild(c(_.toRight??"▶","체크한 행을 오른쪽 그리드로 이동",()=>{this._left.moveCheckedTo(this._right)})),r.appendChild(c(_.toLeft??"◀","체크한 행을 왼쪽 그리드로 이동",()=>{this._right.moveCheckedTo(this._left)})),i.includeAll&&(r.appendChild(c(_.allRight??"⏩","왼쪽 전체를 오른쪽으로 이동",()=>{this._moveAll(this._left,this._right)})),r.appendChild(c(_.allLeft??"⏪","오른쪽 전체를 왼쪽으로 이동",()=>{this._moveAll(this._right,this._left)}))),o.appendChild(r),this._el=r}_moveAll(t,e){const o=t.getData().length;o>0&&t.moveRowsTo(e,Array.from({length:o},(i,r)=>r))}destroy(){this._el.remove()}}function T(b,t,e,o){return new C(b,t,e,o)}class v{constructor(t,e){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:()=>{},...e},this._container.classList.add("og-orgchart")}setData(t){this._data=t;const{idField:e,parentIdField:o,expandOnLoad:i}=this._opts;i&&this._expandedKeys.size===0&&t.forEach(r=>this._expandedKeys.add(r[e])),this._roots=A.buildTree(t,{idField:e,parentIdField:o},this._expandedKeys),this._render()}setTheme(t){this._container.setAttribute("data-og-theme",t)}expandAll(){const t=e=>{for(const o of e)this._expandedKeys.add(o._treeId),o.children.length&&t(o.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:e}=this._opts;this._roots=A.buildTree(this._data,{idField:t,parentIdField:e},this._expandedKeys),this._render()}_calcLayout(){const{nodeWidth:t,nodeHeight:e,levelGap:o,siblingGap:i}=this._opts,r=new Map;let c=0;const _=u=>{const a=u._depth*(e+o),p=u._expanded?u.children:[];if(!p.length){const g=c;return c+=t+i,r.set(u._treeId,{x:g,y:a}),{minX:g,maxX:g}}let n=1/0,l=-1/0;for(const g of p){const{minX:s,maxX:h}=_(g);s<n&&(n=s),h>l&&(l=h)}const d=n+(l-n+t)/2-t/2;return r.set(u._treeId,{x:d,y:a}),{minX:n,maxX:l}};for(const u of this._roots)_(u);let m=0,f=0;for(const{x:u,y:a}of r.values())u+t>m&&(m=u+t),a+e>f&&(f=a+e);return{layout:r,totalW:m+i,totalH:f+o+16}}_line(t,e,o,i,r){const c=document.createElementNS("http://www.w3.org/2000/svg","line");c.setAttribute("x1",String(e)),c.setAttribute("y1",String(o)),c.setAttribute("x2",String(i)),c.setAttribute("y2",String(r)),c.setAttribute("class","og-orgchart-line"),t.appendChild(c)}_render(){const{nodeWidth:t,nodeHeight:e,levelGap:o,columns:i}=this._opts,{layout:r,totalW:c,totalH:_}=this._calcLayout();this._container.innerHTML="";const m=document.createElement("div");m.className="og-orgchart-wrap",m.style.cssText=`width:${c}px;height:${_}px;`;const f=document.createElementNS("http://www.w3.org/2000/svg","svg");f.setAttribute("width",String(c)),f.setAttribute("height",String(_)),f.style.cssText="position:absolute;top:0;left:0;pointer-events:none;overflow:visible;";const u=p=>{for(const n of p){if(!n._expanded||!n.children.length)continue;const l=r.get(n._treeId),d=l.x+t/2,g=l.y+e,s=g+o/2,h=n.children;if(this._line(f,d,g,d,s),h.length>1){const x=r.get(h[0]._treeId),y=r.get(h[h.length-1]._treeId);this._line(f,x.x+t/2,s,y.x+t/2,s)}for(const x of h){const y=r.get(x._treeId),E=y.x+t/2;this._line(f,E,s,E,y.y)}u(h)}};u(this._roots),m.appendChild(f);const a=p=>{for(const n of p){const l=r.get(n._treeId);if(!l)continue;const d=document.createElement("div");d.className="og-orgchart-node",n._hasChildren&&d.classList.add("og-orgchart-node--branch"),n._expanded&&d.classList.add("og-orgchart-node--expanded"),this._selectedId===n._treeId&&d.classList.add("og-orgchart-node--selected"),d.style.cssText=`left:${l.x}px;top:${l.y}px;width:${t}px;height:${e}px;`;const g=document.createElement("div");g.className="og-orgchart-node-content";for(const s of i){const h=n.data[s.field],x=document.createElement("div");if(x.className="og-orgchart-col"+(s.className?" "+s.className:""),s.style){const y=typeof s.style=="function"?s.style(h,n.data):s.style;x.setAttribute("style",y)}if(s.renderer){const y=s.renderer(h,n.data);typeof y=="string"?x.innerHTML=y:x.appendChild(y)}else x.textContent=h??"";g.appendChild(x)}if(d.appendChild(g),n._hasChildren){const s=document.createElement("button");s.type="button",s.className="og-orgchart-toggle",s.setAttribute("aria-expanded",n._expanded?"true":"false"),s.setAttribute("aria-label",n._expanded?"접기":"펼치기");const h=document.createElement("i");h.setAttribute("aria-hidden","true"),h.className=n._expanded?"bi bi-dash-circle":"bi bi-plus-circle",s.appendChild(h),s.addEventListener("click",x=>{x.stopPropagation(),this._toggle(n._treeId)}),d.appendChild(s)}d.addEventListener("click",()=>{this._selectedId=n._treeId,this._opts.onNodeClick(n._treeId,n.data),this._container.querySelectorAll(".og-orgchart-node--selected").forEach(s=>s.classList.remove("og-orgchart-node--selected")),d.classList.add("og-orgchart-node--selected")}),m.appendChild(d),n._expanded&&n.children.length&&a(n.children)}};a(this._roots),this._container.appendChild(m)}}class N{static parse(t,e={}){var p,n;const{fieldMap:o={},trim:i=!0}=e,c=new DOMParser().parseFromString(t.trim(),"text/xml"),_=c.querySelector("parsererror");if(_)throw new Error(`XML 파싱 오류: ${(p=_.textContent)==null?void 0:p.trim()}`);const m=c.documentElement;let f=e.rowTag;if(!f){const l=e.rootTag?c.querySelector(e.rootTag):m;f=((n=l==null?void 0:l.children[0])==null?void 0:n.tagName)??"row"}const u=c.getElementsByTagName(f),a=[];for(let l=0;l<u.length;l++){const d=u[l],g={};for(const s of Array.from(d.attributes)){const h=o[s.name]??s.name;g[h]=i?s.value.trim():s.value}for(const s of Array.from(d.children)){const h=o[s.tagName]??s.tagName,x=s.textContent??"";g[h]=i?x.trim():x}a.push(g)}return a}static stringify(t,e={}){const{rootTag:o="rows",rowTag:i="row",mode:r="element",fieldMap:c={},declaration:_=!0,indent:m=2,nullAs:f="",excludeFields:u=[]}=e,a=" ".repeat(m),p=[];_&&p.push('<?xml version="1.0" encoding="UTF-8"?>'),p.push(`<${o}>`);for(const n of t){const l=Object.entries(n).filter(([d])=>!u.includes(d));if(r==="attribute"){const d=l.map(([g,s])=>{const h=c[g]??g,x=s==null?f:String(s);return`${h}="${this._escAttr(x)}"`}).join(" ");p.push(`${a}<${i}${d?" "+d:""} />`)}else{p.push(`${a}<${i}>`);for(const[d,g]of l){const s=c[d]??d,h=g==null?f:String(g);p.push(`${a}${a}<${s}>${this._escText(h)}</${s}>`)}p.push(`${a}</${i}>`)}}return p.push(`</${o}>`),p.join(`
|
|
2
|
+
`)}static parseSap(t){var m,f,u,a;const o=new DOMParser().parseFromString(t.trim(),"text/xml"),i={header:{},items:[],returns:[],raw:o},r=o.getElementsByTagName("DOCUMENTHEADER")[0];if(r)for(const p of Array.from(r.children))i.header[p.tagName]=((m=p.textContent)==null?void 0:m.trim())??"";const c=o.getElementsByTagName("RETURN");for(const p of Array.from(c)){const n={};for(const l of Array.from(p.children))n[l.tagName]=((f=l.textContent)==null?void 0:f.trim())??"";i.returns.push(n)}const _=["ACCOUNTGL","ACCOUNTRECEIVABLE","ACCOUNTPAYABLE","ITEMS"];for(const p of _){const n=o.getElementsByTagName(p)[0];if(!n)continue;const l=n.getElementsByTagName("ITEM"),d=l.length>0?Array.from(l):[n];for(const g of d){const s={};for(const h of Array.from(g.children))s[h.tagName]=((u=h.textContent)==null?void 0:u.trim())??"";i.items.push(s)}break}if(i.items.length===0){const p=o.documentElement,n=Array.from(p.children).filter(l=>l.hasAttribute("SEGMENT"));for(const l of n){if(l.tagName==="EDI_DC40")continue;const d={};for(const g of Array.from(l.children))d[g.tagName]=((a=g.textContent)==null?void 0:a.trim())??"";Object.keys(d).length>0&&i.items.push(d)}}return i}static stringifySap(t){const e=['<?xml version="1.0" encoding="UTF-8"?>',"<BAPI_CALL>"];if(t.BAPI_FUNCTION&&e.push(` <FUNCTION>${this._escText(t.BAPI_FUNCTION)}</FUNCTION>`),t.DOCUMENTHEADER&&typeof t.DOCUMENTHEADER=="object"){e.push(" <DOCUMENTHEADER>");for(const[i,r]of Object.entries(t.DOCUMENTHEADER))r!=null&&r!==""&&e.push(` <${i}>${this._escText(String(r))}</${i}>`);e.push(" </DOCUMENTHEADER>")}const o=Object.keys(t).find(i=>Array.isArray(t[i])&&!i.startsWith("_"));if(o){e.push(` <${o}>`);for(const i of t[o]){e.push(" <ITEM>");for(const[r,c]of Object.entries(i))c!=null&&c!==""&&!r.startsWith("_")&&e.push(` <${r}>${this._escText(String(c))}</${r}>`);e.push(" </ITEM>")}e.push(` </${o}>`)}return e.push("</BAPI_CALL>"),e.join(`
|
|
3
|
+
`)}static stringifySapBatch(t){const e=['<?xml version="1.0" encoding="UTF-8"?>',`<BAPI_BATCH total="${t.documents.length}">`];return t.documents.forEach((o,i)=>{e.push(` <BAPI_CALL seq="${i+1}">`);const r=this.stringifySap(o).split(`
|
|
4
|
+
`).filter(c=>!c.startsWith("<?xml")).map(c=>" "+c).join(`
|
|
5
|
+
`);e.push(r),e.push(" </BAPI_CALL>")}),e.push("</BAPI_BATCH>"),e.join(`
|
|
6
|
+
`)}static _escText(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}static _escAttr(t){return this._escText(t).replace(/"/g,""").replace(/'/g,"'")}}exports.OpenGrid=A.OpenGrid;exports.GridShuttle=C;exports.OrgChart=v;exports.XmlConverter=N;exports.createGridShuttle=T;
|
|
7
7
|
//# sourceMappingURL=open-grid.cjs.map
|
package/dist/open-grid.cjs.map
CHANGED
|
@@ -1 +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, '&').replace(/</g, '<').replace(/>/g, '>');\n }\n\n private static _escAttr(s: string): string {\n return this._escText(s).replace(/\"/g, '"').replace(/'/g, ''');\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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"}
|
|
1
|
+
{"version":3,"file":"open-grid.cjs","sources":["../src/core/GridShuttle.ts","../src/core/OrgChart.ts","../src/core/XmlConverter.ts"],"sourcesContent":["// ============================================================\n// 그리드 셔틀 — 두 그리드 사이에 화살표 버튼을 두고\n// \"체크된 행\"을 드래그 없이 버튼으로 이동(move)시킨다.\n// 이동 자체는 grid.moveCheckedTo() 를 호출 → crossGridMapping(필드 매핑)과\n// 3단계 이벤트가 드래그 이동과 100% 동일하게 적용된다.\n// ============================================================\nimport type { OpenGridInstance } from './types.js';\n\nexport interface GridShuttleOptions {\n /** 버튼 배치 방향 (기본 'vertical') */\n layout?: 'vertical' | 'horizontal';\n /** 전체 이동(≫ ≪) 버튼도 표시 (기본 false) */\n includeAll?: boolean;\n /** 버튼 라벨 커스터마이즈 */\n labels?: { toRight?: string; toLeft?: string; allRight?: string; allLeft?: string };\n}\n\nexport class GridShuttle {\n private _el: HTMLElement;\n\n constructor(\n private _left: OpenGridInstance,\n private _right: OpenGridInstance,\n mount: HTMLElement,\n opts: GridShuttleOptions = {},\n ) {\n const wrap = document.createElement('div');\n wrap.className = 'og-shuttle';\n wrap.style.cssText =\n `display:flex;gap:6px;align-items:center;justify-content:center;` +\n `flex-direction:${opts.layout === 'horizontal' ? 'row' : 'column'};`;\n\n const mk = (label: string, title: string, fn: () => void): HTMLButtonElement => {\n const b = document.createElement('button');\n b.type = 'button';\n b.className = 'og-shuttle-btn';\n b.textContent = label;\n b.title = title;\n b.style.cssText =\n 'min-width:34px;height:30px;padding:0 8px;border:1px solid #bbb;border-radius:7px;' +\n 'background:#fff;cursor:pointer;font-size:14px;color:#444;line-height:1;' +\n 'box-shadow:0 1px 2px rgba(0,0,0,0.06);';\n b.addEventListener('mouseover', () => { b.style.background = '#f0f6ff'; b.style.borderColor = '#1976d2'; });\n b.addEventListener('mouseout', () => { b.style.background = '#fff'; b.style.borderColor = '#bbb'; });\n b.addEventListener('click', fn);\n return b;\n };\n\n const L = opts.labels ?? {};\n wrap.appendChild(mk(L.toRight ?? '▶', '체크한 행을 오른쪽 그리드로 이동',\n () => { void this._left.moveCheckedTo(this._right); }));\n wrap.appendChild(mk(L.toLeft ?? '◀', '체크한 행을 왼쪽 그리드로 이동',\n () => { void this._right.moveCheckedTo(this._left); }));\n\n if (opts.includeAll) {\n wrap.appendChild(mk(L.allRight ?? '⏩', '왼쪽 전체를 오른쪽으로 이동',\n () => { void this._moveAll(this._left, this._right); }));\n wrap.appendChild(mk(L.allLeft ?? '⏪', '오른쪽 전체를 왼쪽으로 이동',\n () => { void this._moveAll(this._right, this._left); }));\n }\n\n mount.appendChild(wrap);\n this._el = wrap;\n }\n\n private _moveAll(from: OpenGridInstance, to: OpenGridInstance): void {\n const n = from.getData().length;\n if (n > 0) void from.moveRowsTo(to, Array.from({ length: n }, (_, i) => i));\n }\n\n destroy(): void { this._el.remove(); }\n}\n\n/** 두 그리드 사이에 셔틀(화살표 이동) 버튼을 만든다 */\nexport function createGridShuttle(\n left: OpenGridInstance,\n right: OpenGridInstance,\n mount: HTMLElement,\n opts?: GridShuttleOptions,\n): GridShuttle {\n return new GridShuttle(left, right, mount, opts);\n}\n","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, '&').replace(/</g, '<').replace(/>/g, '>');\n }\n\n private static _escAttr(s: string): string {\n return this._escText(s).replace(/\"/g, '"').replace(/'/g, ''');\n }\n}\n"],"names":["GridShuttle","_left","_right","mount","opts","wrap","mk","label","title","fn","b","L","from","to","n","_","i","createGridShuttle","left","right","OrgChart","selector","data","idField","parentIdField","expandOnLoad","buildTree","theme","collect","nodes","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","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","row","attr","field","text","rootTag","mode","declaration","indent","nullAs","excludeFields","pad","lines","item","entries","k","attrs","v","tag","result","headerEl","returnEls","r","ret","itemParentTags","parentTag","parentEl","itemEls","targets","_c","segments","seg","_d","payload","itemsKey","inner","l"],"mappings":"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"}
|