open-grid 0.3.2 → 1.0.0-rc.1
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-C6SK6VeK.cjs +90 -0
- package/dist/OpenGrid-C6SK6VeK.cjs.map +1 -0
- package/dist/OpenGrid-D7EJOVi1.js +4864 -0
- package/dist/OpenGrid-D7EJOVi1.js.map +1 -0
- package/dist/open-grid-base.css +14 -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/CellEditManager.d.ts +2 -3
- package/dist/types/core/CellEventHandler.d.ts +4 -5
- package/dist/types/core/CellTypeRegistry.d.ts +1 -2
- package/dist/types/core/ColumnLayout.d.ts +1 -2
- package/dist/types/core/ContextMenu.d.ts +1 -2
- package/dist/types/core/CrossGridMapper.d.ts +21 -0
- package/dist/types/core/CrossGridRegistry.d.ts +12 -0
- package/dist/types/core/DataLayer.d.ts +4 -2
- package/dist/types/core/DragVisuals.d.ts +23 -0
- package/dist/types/core/ExportManager.d.ts +4 -3
- package/dist/types/core/FilterPanel.d.ts +1 -2
- package/dist/types/core/FilterSelect.d.ts +1 -2
- package/dist/types/core/FindBarManager.d.ts +4 -5
- package/dist/types/core/FooterManager.d.ts +2 -1
- package/dist/types/core/FormulaEngine.d.ts +1 -2
- package/dist/types/core/GridRenderer.d.ts +3 -2
- package/dist/types/core/GridShuttle.d.ts +24 -0
- package/dist/types/core/GroupEngine.d.ts +7 -4
- package/dist/types/core/GroupTreeManager.d.ts +6 -3
- package/dist/types/core/KeyboardManager.d.ts +4 -5
- package/dist/types/core/OpenGrid.d.ts +55 -4
- package/dist/types/core/OverrideKernel.d.ts +70 -0
- package/dist/types/core/PivotEngine.d.ts +1 -2
- package/dist/types/core/RowDragDrop.d.ts +25 -5
- package/dist/types/core/RowManager.d.ts +0 -1
- package/dist/types/core/SortFilterManager.d.ts +5 -6
- package/dist/types/core/TriggerManager.d.ts +1 -2
- package/dist/types/core/WorksheetManager.d.ts +1 -2
- package/dist/types/core/editors/CellEditor.d.ts +2 -3
- package/dist/types/core/editors/DateEditor.d.ts +2 -3
- package/dist/types/core/editors/SelectEditor.d.ts +2 -3
- package/dist/types/core/renderers/CellRenderer.d.ts +15 -4
- package/dist/types/core/types.d.ts +115 -0
- package/dist/types/index.d.ts +3 -1
- package/dist/types/react/OpenGrid.d.ts +3 -3
- package/dist/types/vue/types.d.ts +1 -2
- package/package.json +99 -102
- package/dist/OpenGrid-CzP1mcZW.cjs +0 -90
- package/dist/OpenGrid-CzP1mcZW.cjs.map +0 -1
- package/dist/OpenGrid-Dult64jp.js +0 -4401
- package/dist/OpenGrid-Dult64jp.js.map +0 -1
package/dist/open-grid.js.map
CHANGED
|
@@ -1 +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, '&').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.js","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","r","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","ret","itemParentTags","parentTag","parentEl","itemEls","targets","_c","segments","seg","_d","payload","itemsKey","inner","l"],"mappings":"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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { DataLayer } from './DataLayer.js';
|
|
2
2
|
import { ColumnLayout } from './ColumnLayout.js';
|
|
3
3
|
import { GridRenderer } from './GridRenderer.js';
|
|
4
|
-
import { CellEditor } from './editors/CellEditor.js';
|
|
5
|
-
import { ColumnDef } from './types.js';
|
|
6
|
-
|
|
4
|
+
import type { CellEditor } from './editors/CellEditor.js';
|
|
5
|
+
import type { ColumnDef } from './types.js';
|
|
7
6
|
export interface CellEditDeps<T extends Record<string, any>> {
|
|
8
7
|
data: DataLayer<T>;
|
|
9
8
|
colLayout: ColumnLayout<T>;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { DataLayer } from './DataLayer.js';
|
|
2
|
-
import { ColumnLayout } from './ColumnLayout.js';
|
|
3
|
-
import { CellEditManager } from './CellEditManager.js';
|
|
4
|
-
import { RowManager } from './RowManager.js';
|
|
5
|
-
|
|
1
|
+
import type { DataLayer } from './DataLayer.js';
|
|
2
|
+
import type { ColumnLayout } from './ColumnLayout.js';
|
|
3
|
+
import type { CellEditManager } from './CellEditManager.js';
|
|
4
|
+
import type { RowManager } from './RowManager.js';
|
|
6
5
|
export interface CellEventDeps<T extends Record<string, any>> {
|
|
7
6
|
getData: () => DataLayer<T>;
|
|
8
7
|
getColLayout: () => ColumnLayout<T>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { ColumnDef } from './types.js';
|
|
2
|
-
|
|
1
|
+
import type { ColumnDef } from './types.js';
|
|
3
2
|
export declare function isToggleCol<T>(col: ColumnDef<T>): boolean;
|
|
4
3
|
export declare function isSelectCol<T>(col: ColumnDef<T>): boolean;
|
|
5
4
|
export declare function isRadioCol<T>(col: ColumnDef<T>): boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface FieldInfo {
|
|
2
|
+
field: string;
|
|
3
|
+
header: string;
|
|
4
|
+
}
|
|
5
|
+
export interface MappingResult {
|
|
6
|
+
/** 타깃필드 → 소스필드 (빈 문자열이면 미매핑) */
|
|
7
|
+
mapping: Record<string, string>;
|
|
8
|
+
/** crossGridMapping 에 그대로 쓸 수 있는 변환 함수 소스 */
|
|
9
|
+
script: string;
|
|
10
|
+
}
|
|
11
|
+
/** mapping → 변환 함수 스크립트 문자열 생성 */
|
|
12
|
+
export declare function buildMappingScript(mapping: Record<string, string>): string;
|
|
13
|
+
/** mapping → 실제 행 변환 함수 */
|
|
14
|
+
export declare function buildTransform(mapping: Record<string, string>): (src: any) => any;
|
|
15
|
+
/** 같은 필드 집합인지 (순서 무관) */
|
|
16
|
+
export declare function sameSchema(a: string[], b: string[]): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* 매핑 모달을 띄우고 사용자가 확정한 매핑을 Promise 로 반환한다. (취소 시 null)
|
|
19
|
+
* 모달은 document.body 에 오버레이로 붙는다(디자인타임 헬퍼).
|
|
20
|
+
*/
|
|
21
|
+
export declare function openCrossGridMapper(sourceFields: FieldInfo[], targetFields: FieldInfo[]): Promise<MappingResult | null>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OpenGrid } from './OpenGrid.js';
|
|
2
|
+
export declare class CrossGridRegistry {
|
|
3
|
+
private _map;
|
|
4
|
+
register(bodyEl: HTMLElement, grid: OpenGrid<any>): void;
|
|
5
|
+
unregister(bodyEl: HTMLElement): void;
|
|
6
|
+
get(bodyEl: HTMLElement): OpenGrid<any> | undefined;
|
|
7
|
+
get size(): number;
|
|
8
|
+
/** 커서 좌표 아래의 다른(crossGrid 허용) 그리드 반환. 없으면 null */
|
|
9
|
+
resolveAt(clientX: number, clientY: number, exclude: OpenGrid<any>): OpenGrid<any> | null;
|
|
10
|
+
}
|
|
11
|
+
/** 전역 단일 레지스트리 */
|
|
12
|
+
export declare const crossGridRegistry: CrossGridRegistry;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { SortItem, FilterItem } from './types.js';
|
|
2
|
-
|
|
1
|
+
import type { SortItem, FilterItem } from './types.js';
|
|
3
2
|
type RowState = 'added' | 'edited' | 'removed' | 'none';
|
|
4
3
|
export declare class DataLayer<T extends Record<string, any> = any> {
|
|
5
4
|
private _data;
|
|
@@ -10,7 +9,10 @@ export declare class DataLayer<T extends Record<string, any> = any> {
|
|
|
10
9
|
private _idMap;
|
|
11
10
|
private _findQuery;
|
|
12
11
|
private _findFields;
|
|
12
|
+
private _getStrategy;
|
|
13
13
|
constructor(idField?: string);
|
|
14
|
+
/** Phase 2: OpenGrid 가 OverrideKernel.getStrategy 를 주입(슬롯 sortComparator/filterPredicate 도달용). */
|
|
15
|
+
setStrategyResolver(resolver: <F extends Function>(slot: string, fallback: F) => F): void;
|
|
14
16
|
setData(data: T[]): void;
|
|
15
17
|
getData(): T[];
|
|
16
18
|
getOriginalData(): T[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** 커서를 따라다니는 점선 고스트. transform 으로 X·Y 모두 이동(부드럽게). */
|
|
2
|
+
export declare class DragGhost {
|
|
3
|
+
private _el;
|
|
4
|
+
private _dx;
|
|
5
|
+
private _dy;
|
|
6
|
+
constructor(rect: DOMRect, grabX: number, grabY: number, count: number);
|
|
7
|
+
/** 커서 위치로 이동 (grab 오프셋 유지) */
|
|
8
|
+
move(clientX: number, clientY: number): void;
|
|
9
|
+
destroy(): void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 드롭(삽입) 위치 마커. 행과 행 사이 경계에 "▶━━━◀" 형태로 또렷하게 표시해
|
|
13
|
+
* "여기에 삽입됩니다 / 지금 버튼을 떼면 됩니다" 를 직관적으로 알린다(워드 표 삽입 표시 느낌).
|
|
14
|
+
* 자기 그리드/타깃 그리드 모두에 재사용.
|
|
15
|
+
*/
|
|
16
|
+
export declare class DropIndicator {
|
|
17
|
+
private _el;
|
|
18
|
+
constructor(color?: string);
|
|
19
|
+
/** parent(그리드 바디) 안의 top(행 경계) 위치에 표시 */
|
|
20
|
+
showIn(parent: HTMLElement, top: number): void;
|
|
21
|
+
hide(): void;
|
|
22
|
+
destroy(): void;
|
|
23
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ColumnLayout } from './ColumnLayout.js';
|
|
2
|
-
import { WorksheetManager } from './WorksheetManager.js';
|
|
3
|
-
import { ExportOptions } from './types.js';
|
|
4
|
-
|
|
2
|
+
import type { WorksheetManager } from './WorksheetManager.js';
|
|
3
|
+
import type { ExportOptions } from './types.js';
|
|
5
4
|
export interface ExportDeps<T extends Record<string, any>> {
|
|
6
5
|
getData: () => T[];
|
|
7
6
|
getColLayout: () => ColumnLayout<T>;
|
|
@@ -10,6 +9,8 @@ export interface ExportDeps<T extends Record<string, any>> {
|
|
|
10
9
|
getContainer: () => HTMLElement;
|
|
11
10
|
getMaskEnabled: (field: string) => boolean;
|
|
12
11
|
getWsManager: () => WorksheetManager<T> | null;
|
|
12
|
+
/** Phase 2: OverrideKernel.getStrategy 주입(슬롯 cellSerializer 도달용). */
|
|
13
|
+
getStrategy?: <F extends Function>(slot: string, fallback: F) => F;
|
|
13
14
|
}
|
|
14
15
|
export declare class ExportManager<T extends Record<string, any> = any> {
|
|
15
16
|
private _d;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { ColumnLayout } from './ColumnLayout.js';
|
|
2
|
-
import { DataLayer } from './DataLayer.js';
|
|
3
|
-
import { Pagination } from './Pagination.js';
|
|
4
|
-
import { VirtualScroll } from './VirtualScroll.js';
|
|
5
|
-
|
|
1
|
+
import type { ColumnLayout } from './ColumnLayout.js';
|
|
2
|
+
import type { DataLayer } from './DataLayer.js';
|
|
3
|
+
import type { Pagination } from './Pagination.js';
|
|
4
|
+
import type { VirtualScroll } from './VirtualScroll.js';
|
|
6
5
|
export interface FindBarDeps<T extends Record<string, any>> {
|
|
7
6
|
getColLayout: () => ColumnLayout<T>;
|
|
8
7
|
getData: () => DataLayer<T>;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ColumnLayout } from './ColumnLayout.js';
|
|
2
|
-
|
|
3
2
|
export interface FooterDeps<T extends Record<string, any>> {
|
|
4
3
|
getData: () => T[];
|
|
5
4
|
getColLayout: () => ColumnLayout<T>;
|
|
6
5
|
getColWidths: () => number[];
|
|
7
6
|
getOptions: () => any;
|
|
8
7
|
getContainer: () => HTMLElement;
|
|
8
|
+
/** Phase 2: OverrideKernel.getStrategy 주입(슬롯 summaryOp 도달용). */
|
|
9
|
+
getStrategy?: <F extends Function>(slot: string, fallback: F) => F;
|
|
9
10
|
}
|
|
10
11
|
export declare class FooterManager<T extends Record<string, any> = any> {
|
|
11
12
|
private _d;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { DataLayer } from './DataLayer.js';
|
|
2
2
|
import { RowDragDrop } from './RowDragDrop.js';
|
|
3
3
|
import { MergeEngine } from './MergeEngine.js';
|
|
4
|
-
import { ColumnDef, SortItem } from './types.js';
|
|
5
|
-
|
|
4
|
+
import type { ColumnDef, SortItem } from './types.js';
|
|
6
5
|
export interface RendererCallbacks {
|
|
7
6
|
onHeaderClick: (field: string, shiftKey: boolean) => void;
|
|
8
7
|
onCellClick: (ri: number, ci: number, e: MouseEvent) => void;
|
|
@@ -32,6 +31,8 @@ export declare class GridRenderer {
|
|
|
32
31
|
get bodyWrapper(): HTMLElement;
|
|
33
32
|
constructor(root: HTMLElement, opts: any, cbs: RendererCallbacks);
|
|
34
33
|
updateSize(totalHeight: number, headerHeight: number): void;
|
|
34
|
+
/** 현재 렌더된 헤더 영역의 실제 높이(px). 헤더 줄바꿈으로 늘어난 높이를 레이아웃에 반영할 때 사용. */
|
|
35
|
+
getHeaderHeight(): number;
|
|
35
36
|
renderHeader(headerRows: any[][], leaves: ColumnDef[], widths: number[], sortList: SortItem[], opts: any): void;
|
|
36
37
|
renderBody(startIndex: number, endIndex: number, data: DataLayer<any>, leaves: ColumnDef[], widths: number[], opts: any, offsetY: number, totalHeight: number, selectedRows: Set<number>, checkedRows: Set<number>, groupFlatRows?: Array<any> | null, onGroupToggle?: (key: string) => void, onTreeToggle?: (nodeId: any) => void, extraOpts?: Record<string, any>, mergeEngine?: MergeEngine): void;
|
|
37
38
|
getCellEl(rowIndex: number, colIndex: number): HTMLElement | undefined;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { OpenGridInstance } from './types.js';
|
|
2
|
+
export interface GridShuttleOptions {
|
|
3
|
+
/** 버튼 배치 방향 (기본 'vertical') */
|
|
4
|
+
layout?: 'vertical' | 'horizontal';
|
|
5
|
+
/** 전체 이동(≫ ≪) 버튼도 표시 (기본 false) */
|
|
6
|
+
includeAll?: boolean;
|
|
7
|
+
/** 버튼 라벨 커스터마이즈 */
|
|
8
|
+
labels?: {
|
|
9
|
+
toRight?: string;
|
|
10
|
+
toLeft?: string;
|
|
11
|
+
allRight?: string;
|
|
12
|
+
allLeft?: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare class GridShuttle {
|
|
16
|
+
private _left;
|
|
17
|
+
private _right;
|
|
18
|
+
private _el;
|
|
19
|
+
constructor(_left: OpenGridInstance, _right: OpenGridInstance, mount: HTMLElement, opts?: GridShuttleOptions);
|
|
20
|
+
private _moveAll;
|
|
21
|
+
destroy(): void;
|
|
22
|
+
}
|
|
23
|
+
/** 두 그리드 사이에 셔틀(화살표 이동) 버튼을 만든다 */
|
|
24
|
+
export declare function createGridShuttle(left: OpenGridInstance, right: OpenGridInstance, mount: HTMLElement, opts?: GridShuttleOptions): GridShuttle;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { SummaryOp } from './types.js';
|
|
2
|
-
|
|
1
|
+
import type { SummaryOp } from './types.js';
|
|
3
2
|
export interface GroupRow<T = any> {
|
|
4
3
|
_isGroup: true;
|
|
5
4
|
_groupField: string;
|
|
@@ -25,8 +24,12 @@ export interface SummaryDef {
|
|
|
25
24
|
format?: string;
|
|
26
25
|
}
|
|
27
26
|
declare function _isGroup<T>(item: any): item is GroupRow<T>;
|
|
28
|
-
/**
|
|
29
|
-
|
|
27
|
+
/**
|
|
28
|
+
* flat 데이터를 fields 기준으로 계층 그룹핑.
|
|
29
|
+
* Phase 2 슬롯 #5: groupKeyFn(getKey) — 미지정 시 default = `row[field]`(현행 단일 필드 키).
|
|
30
|
+
* GroupTreeManager 가 host.getStrategy 로 주입. ⚠️ 핫패스(행당) — 슬롯 예외 비격리.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildGroups<T extends Record<string, any>>(data: T[], fields: string[], summaryDefs?: SummaryDef[], expandedKeys?: Set<string>, getRowState?: (row: T) => string, getKey?: (row: T, remainingFields: string[]) => any): GroupRow<T>[];
|
|
30
33
|
/**
|
|
31
34
|
* 숫자 포맷팅 (GroupEngine 내부 + 외부 공용)
|
|
32
35
|
* '#,##0' → 천단위 콤마, 정수
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { DataLayer } from './DataLayer.js';
|
|
2
2
|
import { VirtualScroll } from './VirtualScroll.js';
|
|
3
|
-
import { GroupRow } from './GroupEngine.js';
|
|
4
|
-
import { TreeNode } from './TreeEngine.js';
|
|
5
|
-
|
|
3
|
+
import { type GroupRow } from './GroupEngine.js';
|
|
4
|
+
import { type TreeNode } from './TreeEngine.js';
|
|
6
5
|
export interface GroupTreeDeps<T extends Record<string, any>> {
|
|
7
6
|
getData: () => T[];
|
|
8
7
|
getDataLayer: () => DataLayer<T>;
|
|
@@ -10,6 +9,8 @@ export interface GroupTreeDeps<T extends Record<string, any>> {
|
|
|
10
9
|
getVs: () => VirtualScroll | null;
|
|
11
10
|
doRenderFull: (totalRows: number) => void;
|
|
12
11
|
doRender: () => void;
|
|
12
|
+
/** Phase 2: OverrideKernel.getStrategy 주입(슬롯 groupKeyFn 도달용). */
|
|
13
|
+
getStrategy?: <F extends Function>(slot: string, fallback: F) => F;
|
|
13
14
|
}
|
|
14
15
|
export declare class GroupTreeManager<T extends Record<string, any> = any> {
|
|
15
16
|
private _groupFields;
|
|
@@ -29,6 +30,8 @@ export declare class GroupTreeManager<T extends Record<string, any> = any> {
|
|
|
29
30
|
groupBy(fields: string[]): void;
|
|
30
31
|
clearGroup(): void;
|
|
31
32
|
expandAll(): void;
|
|
33
|
+
/** Phase 2 슬롯 #5: groupKeyFn resolver. default = undefined(→ GroupEngine 가 row[field] 사용). */
|
|
34
|
+
private _groupKeyFn;
|
|
32
35
|
collapseAll(): void;
|
|
33
36
|
handleGroupToggle(groupKey: string): void;
|
|
34
37
|
rebuildGroups(): void;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { DataLayer } from './DataLayer.js';
|
|
2
|
-
import { ColumnLayout } from './ColumnLayout.js';
|
|
3
|
-
import { CellEditManager } from './CellEditManager.js';
|
|
4
|
-
import { RowManager } from './RowManager.js';
|
|
5
|
-
|
|
1
|
+
import type { DataLayer } from './DataLayer.js';
|
|
2
|
+
import type { ColumnLayout } from './ColumnLayout.js';
|
|
3
|
+
import type { CellEditManager } from './CellEditManager.js';
|
|
4
|
+
import type { RowManager } from './RowManager.js';
|
|
6
5
|
export interface KeyboardDeps<T extends Record<string, any>> {
|
|
7
6
|
getEditMgr: () => CellEditManager<T>;
|
|
8
7
|
getRowMgr: () => RowManager<T>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { EventEmitter } from './EventEmitter.js';
|
|
2
|
-
import { FilterSelectConfig } from './FilterSelect.js';
|
|
3
|
-
import { MergeCell } from './MergeEngine.js';
|
|
4
|
-
import {
|
|
5
|
-
|
|
2
|
+
import type { FilterSelectConfig } from './FilterSelect.js';
|
|
3
|
+
import { type MergeCell } from './MergeEngine.js';
|
|
4
|
+
import type { OverrideLayer } from './OverrideKernel.js';
|
|
5
|
+
import type { GridOptions, OpenGridInstance, ColumnDef, SortItem, FilterItem, ExportOptions, Position, TriggerHandler, TriggerEvent, OverrideApi, OverrideCallOptions } from './types.js';
|
|
6
6
|
export declare class OpenGrid<T extends Record<string, any> = any> extends EventEmitter implements OpenGridInstance<T> {
|
|
7
7
|
private _container;
|
|
8
8
|
private _options;
|
|
@@ -16,7 +16,10 @@ export declare class OpenGrid<T extends Record<string, any> = any> extends Event
|
|
|
16
16
|
private _editMgr;
|
|
17
17
|
private _trigMgr;
|
|
18
18
|
private _destroyed;
|
|
19
|
+
private _autoHeightWarned;
|
|
19
20
|
private _colWidths;
|
|
21
|
+
/** 사용자가 헤더 드래그로 직접 조절한 컬럼 폭 (field 기준). _recalcWidths 가 덮어쓰지 않도록 보존 */
|
|
22
|
+
private _userWidths;
|
|
20
23
|
private _filterPanel;
|
|
21
24
|
private _filterSelect;
|
|
22
25
|
private _pagination;
|
|
@@ -33,7 +36,25 @@ export declare class OpenGrid<T extends Record<string, any> = any> extends Event
|
|
|
33
36
|
private _findMgr;
|
|
34
37
|
private _grpMgr;
|
|
35
38
|
private _cellEvt;
|
|
39
|
+
private _ovk;
|
|
40
|
+
/** 공개 override API (호출가능 + .strategy). 생성자 말미에 부착. */
|
|
41
|
+
override: OverrideApi<T>;
|
|
42
|
+
/** 정적 전역 override 레이어 (모든 신규 인스턴스에 생성자 말미 적용). */
|
|
43
|
+
private static _defaultOverrides;
|
|
44
|
+
/** 정적 전역 strategy 슬롯. */
|
|
45
|
+
private static _defaultStrategies;
|
|
46
|
+
/** 정적: 모든 신규 그리드에 적용될 override 레이어 등록. */
|
|
47
|
+
static defaultOverride(name: string, fn: OverrideLayer, opts?: OverrideCallOptions): typeof OpenGrid;
|
|
48
|
+
/** 정적 전역 defaults 네임스페이스 (strategy 슬롯). */
|
|
49
|
+
static defaults: {
|
|
50
|
+
strategy(slot: string, fn: Function): typeof OpenGrid;
|
|
51
|
+
};
|
|
36
52
|
constructor(container: string | HTMLElement, options: GridOptions<T>);
|
|
53
|
+
restore(name: string): this;
|
|
54
|
+
restoreAll(): this;
|
|
55
|
+
hasOverride(name: string): boolean;
|
|
56
|
+
getOverrideNames(): string[];
|
|
57
|
+
getStrategy<F extends Function>(slot: string, fallback: F): F;
|
|
37
58
|
private _mount;
|
|
38
59
|
private _initContextMenu;
|
|
39
60
|
openContextMenu(e: MouseEvent, items?: import('./types').ContextMenuItem[]): void;
|
|
@@ -60,6 +81,11 @@ export declare class OpenGrid<T extends Record<string, any> = any> extends Event
|
|
|
60
81
|
private _onResize;
|
|
61
82
|
private _recalcWidths;
|
|
62
83
|
private _renderHeader;
|
|
84
|
+
/**
|
|
85
|
+
* 렌더된 헤더의 실제 높이를 측정해 본문(bodyWrap) 높이와 뷰포트 높이에 반영한다.
|
|
86
|
+
* 줄바꿈이 없는 헤더는 측정 높이가 headerHeight 이하라 기존 고정 동작과 동일하다.
|
|
87
|
+
*/
|
|
88
|
+
private _syncHeaderLayout;
|
|
63
89
|
private _doRender;
|
|
64
90
|
private _handleGroupToggle;
|
|
65
91
|
private _visRange;
|
|
@@ -78,6 +104,31 @@ export declare class OpenGrid<T extends Record<string, any> = any> extends Event
|
|
|
78
104
|
private _handleFilterIconClick;
|
|
79
105
|
private _handleAllCheck;
|
|
80
106
|
private _handleRowDrop;
|
|
107
|
+
/** 드래그/셔틀이 참조하는 바디 엘리먼트 (레지스트리 해석용) */
|
|
108
|
+
_crossBodyEl(): HTMLElement;
|
|
109
|
+
/** fromIndex 를 잡고 드래그할 때 함께 이동할 행 집합 (다중선택에 포함되면 선택 전체) */
|
|
110
|
+
private _dragRowSet;
|
|
111
|
+
/** 드래그 드롭 어댑터 → 공개 moveRowsTo 로 위임 */
|
|
112
|
+
private _handleCrossGridDrop;
|
|
113
|
+
/**
|
|
114
|
+
* 이 그리드의 행들을 다른 그리드로 이동(move)한다. 드래그·화살표 셔틀 공통 경로.
|
|
115
|
+
* 3단계 이벤트(before→after→complete)와 crossGridMapping(필드 매핑)을 적용한다.
|
|
116
|
+
* @param targetGrid 대상 그리드
|
|
117
|
+
* @param sourceIndexes 이동할 (표시)행 인덱스들
|
|
118
|
+
* @param targetIndex 대상에서 삽입 위치 (생략 시 맨 끝에 추가)
|
|
119
|
+
* @returns 이동 성공 true, 취소/무효 false
|
|
120
|
+
*/
|
|
121
|
+
moveRowsTo(target: OpenGridInstance<T>, sourceIndexes: number[], targetIndex?: number): Promise<boolean>;
|
|
122
|
+
/** 체크된 행을 다른 그리드로 이동 (화살표 셔틀용). 체크 없으면 무시. */
|
|
123
|
+
moveCheckedTo(target: OpenGridInstance<T>): Promise<boolean>;
|
|
124
|
+
/**
|
|
125
|
+
* 크로스그리드 이동의 행 변환 함수를 결정한다.
|
|
126
|
+
* 반환: null=변환 불필요(그대로) / 함수=변환 적용 / false=매핑 모달 취소(이동 중단)
|
|
127
|
+
*/
|
|
128
|
+
private _resolveCrossTransform;
|
|
129
|
+
private _fireGridDropBefore;
|
|
130
|
+
private _fireGridDropAfter;
|
|
131
|
+
private _fireGridDropComplete;
|
|
81
132
|
/** 행을 드롭으로 이동할 때 실행된다 */
|
|
82
133
|
/** ???꾩튂 ?대룞 */
|
|
83
134
|
reorderRow(fromIndex: number, toIndex: number): void;
|