open-grid 1.1.0 → 1.1.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/CHANGELOG.md +20 -0
- package/THIRD_PARTY_LICENSES.txt +43 -0
- package/dist/OpenGrid-LcZ5iixx.cjs +97 -0
- package/dist/OpenGrid-yg4mw6Ge.js +9505 -0
- package/dist/open-grid-base.css +5 -5
- package/dist/open-grid-react.cjs +1 -1
- package/dist/open-grid-react.js +1 -1
- package/dist/open-grid-skins.css +111 -0
- package/dist/open-grid-vue.cjs +1 -1
- package/dist/open-grid-vue.js +1 -1
- package/dist/open-grid.cjs +3 -3
- package/dist/open-grid.js +129 -119
- package/dist/types/core/AppearanceResolver.d.ts +100 -0
- package/dist/types/core/CrossGridController.d.ts +70 -0
- package/dist/types/core/ExtensionPointRegistry.d.ts +92 -0
- package/dist/types/core/FormulaController.d.ts +79 -0
- package/dist/types/core/GridComposer.d.ts +137 -0
- package/dist/types/core/GridRenderer.d.ts +41 -4
- package/dist/types/core/IconRegistry.d.ts +55 -0
- package/dist/types/core/MutationService.d.ts +126 -0
- package/dist/types/core/OpenGrid.d.ts +88 -51
- package/dist/types/core/OrgChart.d.ts +2 -0
- package/dist/types/core/RenderController.d.ts +65 -0
- package/dist/types/core/SkinRegistry.d.ts +53 -0
- package/dist/types/core/editors/CellEditor.d.ts +17 -1
- package/dist/types/core/icons/bootstrap-icons.d.ts +9 -0
- package/dist/types/core/renderers/CellRenderer.d.ts +38 -2
- package/dist/types/core/types.d.ts +43 -3
- package/dist/types/index.d.ts +4 -0
- package/package.json +1 -1
- package/dist/OpenGrid-5flQwc3W.js +0 -8434
- package/dist/OpenGrid-DahxRY7C.cjs +0 -92
package/dist/open-grid.js
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
import { b as E } from "./OpenGrid-
|
|
2
|
-
import { O as
|
|
1
|
+
import { b as E } from "./OpenGrid-yg4mw6Ge.js";
|
|
2
|
+
import { D as $, I as S, O, S as D, i as k, r as M, s as B } from "./OpenGrid-yg4mw6Ge.js";
|
|
3
3
|
class C {
|
|
4
|
-
constructor(t, e,
|
|
4
|
+
constructor(t, e, o, i = {}) {
|
|
5
5
|
this._left = t, this._right = e;
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
return
|
|
11
|
-
|
|
12
|
-
}),
|
|
13
|
-
|
|
14
|
-
}),
|
|
6
|
+
const r = document.createElement("div");
|
|
7
|
+
r.className = "og-shuttle", r.style.cssText = `display:flex;gap:6px;align-items:center;justify-content:center;flex-direction:${i.layout === "horizontal" ? "row" : "column"};`;
|
|
8
|
+
const a = (m, f, u) => {
|
|
9
|
+
const c = document.createElement("button");
|
|
10
|
+
return c.type = "button", c.className = "og-shuttle-btn", c.textContent = m, c.title = f, c.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);", c.addEventListener("mouseover", () => {
|
|
11
|
+
c.style.background = "#f0f6ff", c.style.borderColor = "#1976d2";
|
|
12
|
+
}), c.addEventListener("mouseout", () => {
|
|
13
|
+
c.style.background = "#fff", c.style.borderColor = "#bbb";
|
|
14
|
+
}), c.addEventListener("click", u), c;
|
|
15
15
|
}, _ = i.labels ?? {};
|
|
16
|
-
|
|
16
|
+
r.appendChild(a(
|
|
17
17
|
_.toRight ?? "▶",
|
|
18
18
|
"체크한 행을 오른쪽 그리드로 이동",
|
|
19
19
|
() => {
|
|
20
20
|
this._left.moveCheckedTo(this._right);
|
|
21
21
|
}
|
|
22
|
-
)),
|
|
22
|
+
)), r.appendChild(a(
|
|
23
23
|
_.toLeft ?? "◀",
|
|
24
24
|
"체크한 행을 왼쪽 그리드로 이동",
|
|
25
25
|
() => {
|
|
26
26
|
this._right.moveCheckedTo(this._left);
|
|
27
27
|
}
|
|
28
|
-
)), i.includeAll && (
|
|
28
|
+
)), i.includeAll && (r.appendChild(a(
|
|
29
29
|
_.allRight ?? "⏩",
|
|
30
30
|
"왼쪽 전체를 오른쪽으로 이동",
|
|
31
31
|
() => {
|
|
32
32
|
this._moveAll(this._left, this._right);
|
|
33
33
|
}
|
|
34
|
-
)),
|
|
34
|
+
)), r.appendChild(a(
|
|
35
35
|
_.allLeft ?? "⏪",
|
|
36
36
|
"오른쪽 전체를 왼쪽으로 이동",
|
|
37
37
|
() => {
|
|
38
38
|
this._moveAll(this._right, this._left);
|
|
39
39
|
}
|
|
40
|
-
))),
|
|
40
|
+
))), o.appendChild(r), this._el = r;
|
|
41
41
|
}
|
|
42
42
|
_moveAll(t, e) {
|
|
43
|
-
const
|
|
44
|
-
|
|
43
|
+
const o = t.getData().length;
|
|
44
|
+
o > 0 && t.moveRowsTo(e, Array.from({ length: o }, (i, r) => r));
|
|
45
45
|
}
|
|
46
46
|
destroy() {
|
|
47
47
|
this._el.remove();
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
function v(
|
|
51
|
-
return new C(
|
|
50
|
+
function v(A, t, e, o) {
|
|
51
|
+
return new C(A, t, e, o);
|
|
52
52
|
}
|
|
53
53
|
class N {
|
|
54
54
|
constructor(t, e) {
|
|
@@ -65,16 +65,20 @@ class N {
|
|
|
65
65
|
}
|
|
66
66
|
setData(t) {
|
|
67
67
|
this._data = t;
|
|
68
|
-
const { idField: e, parentIdField:
|
|
69
|
-
i && this._expandedKeys.size === 0 && t.forEach((
|
|
68
|
+
const { idField: e, parentIdField: o, expandOnLoad: i } = this._opts;
|
|
69
|
+
i && this._expandedKeys.size === 0 && t.forEach((r) => this._expandedKeys.add(r[e])), this._roots = E(t, { idField: e, parentIdField: o }, this._expandedKeys), this._render();
|
|
70
70
|
}
|
|
71
71
|
setTheme(t) {
|
|
72
72
|
this._container.setAttribute("data-og-theme", t);
|
|
73
73
|
}
|
|
74
|
+
/** R12b: FORM(스킨) 축 — data-og-skin 을 자기 컨테이너에 설정(setTheme 과 동형, 색과 직교). */
|
|
75
|
+
setSkin(t) {
|
|
76
|
+
this._container.setAttribute("data-og-skin", t);
|
|
77
|
+
}
|
|
74
78
|
expandAll() {
|
|
75
79
|
const t = (e) => {
|
|
76
|
-
for (const
|
|
77
|
-
this._expandedKeys.add(
|
|
80
|
+
for (const o of e)
|
|
81
|
+
this._expandedKeys.add(o._treeId), o.children.length && t(o.children);
|
|
78
82
|
};
|
|
79
83
|
t(this._roots), this._rebuild();
|
|
80
84
|
}
|
|
@@ -90,65 +94,65 @@ class N {
|
|
|
90
94
|
}
|
|
91
95
|
// ── 레이아웃 계산 (post-order: 리프부터 배치, 부모는 자식 중앙) ──
|
|
92
96
|
_calcLayout() {
|
|
93
|
-
const { nodeWidth: t, nodeHeight: e, levelGap:
|
|
94
|
-
let
|
|
97
|
+
const { nodeWidth: t, nodeHeight: e, levelGap: o, siblingGap: i } = this._opts, r = /* @__PURE__ */ new Map();
|
|
98
|
+
let a = 0;
|
|
95
99
|
const _ = (u) => {
|
|
96
|
-
const
|
|
100
|
+
const c = u._depth * (e + o), p = u._expanded ? u.children : [];
|
|
97
101
|
if (!p.length) {
|
|
98
|
-
const
|
|
99
|
-
return
|
|
102
|
+
const g = a;
|
|
103
|
+
return a += t + i, r.set(u._treeId, { x: g, y: c }), { minX: g, maxX: g };
|
|
100
104
|
}
|
|
101
105
|
let n = 1 / 0, l = -1 / 0;
|
|
102
|
-
for (const
|
|
103
|
-
const { minX: s, maxX: h } = _(
|
|
106
|
+
for (const g of p) {
|
|
107
|
+
const { minX: s, maxX: h } = _(g);
|
|
104
108
|
s < n && (n = s), h > l && (l = h);
|
|
105
109
|
}
|
|
106
110
|
const d = n + (l - n + t) / 2 - t / 2;
|
|
107
|
-
return
|
|
111
|
+
return r.set(u._treeId, { x: d, y: c }), { minX: n, maxX: l };
|
|
108
112
|
};
|
|
109
113
|
for (const u of this._roots) _(u);
|
|
110
|
-
let m = 0,
|
|
111
|
-
for (const { x: u, y:
|
|
112
|
-
u + t > m && (m = u + t),
|
|
113
|
-
return { layout:
|
|
114
|
+
let m = 0, f = 0;
|
|
115
|
+
for (const { x: u, y: c } of r.values())
|
|
116
|
+
u + t > m && (m = u + t), c + e > f && (f = c + e);
|
|
117
|
+
return { layout: r, totalW: m + i, totalH: f + o + 16 };
|
|
114
118
|
}
|
|
115
119
|
// ── SVG 직선 헬퍼 ──
|
|
116
|
-
_line(t, e,
|
|
117
|
-
const
|
|
118
|
-
|
|
120
|
+
_line(t, e, o, i, r) {
|
|
121
|
+
const a = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
|
122
|
+
a.setAttribute("x1", String(e)), a.setAttribute("y1", String(o)), a.setAttribute("x2", String(i)), a.setAttribute("y2", String(r)), a.setAttribute("class", "og-orgchart-line"), t.appendChild(a);
|
|
119
123
|
}
|
|
120
124
|
// ── 렌더 ──
|
|
121
125
|
_render() {
|
|
122
|
-
const { nodeWidth: t, nodeHeight: e, levelGap:
|
|
126
|
+
const { nodeWidth: t, nodeHeight: e, levelGap: o, columns: i } = this._opts, { layout: r, totalW: a, totalH: _ } = this._calcLayout();
|
|
123
127
|
this._container.innerHTML = "";
|
|
124
128
|
const m = document.createElement("div");
|
|
125
|
-
m.className = "og-orgchart-wrap", m.style.cssText = `width:${
|
|
126
|
-
const
|
|
127
|
-
|
|
129
|
+
m.className = "og-orgchart-wrap", m.style.cssText = `width:${a}px;height:${_}px;`;
|
|
130
|
+
const f = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
131
|
+
f.setAttribute("width", String(a)), f.setAttribute("height", String(_)), f.style.cssText = "position:absolute;top:0;left:0;pointer-events:none;overflow:visible;";
|
|
128
132
|
const u = (p) => {
|
|
129
133
|
for (const n of p) {
|
|
130
134
|
if (!n._expanded || !n.children.length) continue;
|
|
131
|
-
const l =
|
|
132
|
-
if (this._line(
|
|
133
|
-
const x =
|
|
134
|
-
this._line(
|
|
135
|
+
const l = r.get(n._treeId), d = l.x + t / 2, g = l.y + e, s = g + o / 2, h = n.children;
|
|
136
|
+
if (this._line(f, d, g, d, s), h.length > 1) {
|
|
137
|
+
const x = r.get(h[0]._treeId), y = r.get(h[h.length - 1]._treeId);
|
|
138
|
+
this._line(f, x.x + t / 2, s, y.x + t / 2, s);
|
|
135
139
|
}
|
|
136
140
|
for (const x of h) {
|
|
137
|
-
const y =
|
|
138
|
-
this._line(
|
|
141
|
+
const y = r.get(x._treeId), b = y.x + t / 2;
|
|
142
|
+
this._line(f, b, s, b, y.y);
|
|
139
143
|
}
|
|
140
144
|
u(h);
|
|
141
145
|
}
|
|
142
146
|
};
|
|
143
|
-
u(this._roots), m.appendChild(
|
|
144
|
-
const
|
|
147
|
+
u(this._roots), m.appendChild(f);
|
|
148
|
+
const c = (p) => {
|
|
145
149
|
for (const n of p) {
|
|
146
|
-
const l =
|
|
150
|
+
const l = r.get(n._treeId);
|
|
147
151
|
if (!l) continue;
|
|
148
152
|
const d = document.createElement("div");
|
|
149
153
|
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;`;
|
|
150
|
-
const
|
|
151
|
-
|
|
154
|
+
const g = document.createElement("div");
|
|
155
|
+
g.className = "og-orgchart-node-content";
|
|
152
156
|
for (const s of i) {
|
|
153
157
|
const h = n.data[s.field], x = document.createElement("div");
|
|
154
158
|
if (x.className = "og-orgchart-col" + (s.className ? " " + s.className : ""), s.style) {
|
|
@@ -160,9 +164,9 @@ class N {
|
|
|
160
164
|
typeof y == "string" ? x.innerHTML = y : x.appendChild(y);
|
|
161
165
|
} else
|
|
162
166
|
x.textContent = h ?? "";
|
|
163
|
-
|
|
167
|
+
g.appendChild(x);
|
|
164
168
|
}
|
|
165
|
-
if (d.appendChild(
|
|
169
|
+
if (d.appendChild(g), n._hasChildren) {
|
|
166
170
|
const s = document.createElement("button");
|
|
167
171
|
s.type = "button", s.className = "og-orgchart-toggle", s.setAttribute("aria-expanded", n._expanded ? "true" : "false"), s.setAttribute("aria-label", n._expanded ? "접기" : "펼치기");
|
|
168
172
|
const h = document.createElement("i");
|
|
@@ -172,13 +176,13 @@ class N {
|
|
|
172
176
|
}
|
|
173
177
|
d.addEventListener("click", () => {
|
|
174
178
|
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");
|
|
175
|
-
}), m.appendChild(d), n._expanded && n.children.length &&
|
|
179
|
+
}), m.appendChild(d), n._expanded && n.children.length && c(n.children);
|
|
176
180
|
}
|
|
177
181
|
};
|
|
178
|
-
|
|
182
|
+
c(this._roots), this._container.appendChild(m);
|
|
179
183
|
}
|
|
180
184
|
}
|
|
181
|
-
class
|
|
185
|
+
class I {
|
|
182
186
|
// ── 1. XML → 데이터 배열 ────────────────────────────────────
|
|
183
187
|
/**
|
|
184
188
|
* XML 문자열을 파싱하여 그리드 데이터 배열로 변환.
|
|
@@ -188,28 +192,28 @@ class w {
|
|
|
188
192
|
*/
|
|
189
193
|
static parse(t, e = {}) {
|
|
190
194
|
var p, n;
|
|
191
|
-
const { fieldMap:
|
|
195
|
+
const { fieldMap: o = {}, trim: i = !0 } = e, a = new DOMParser().parseFromString(t.trim(), "text/xml"), _ = a.querySelector("parsererror");
|
|
192
196
|
if (_) throw new Error(`XML 파싱 오류: ${(p = _.textContent) == null ? void 0 : p.trim()}`);
|
|
193
|
-
const m =
|
|
194
|
-
let
|
|
195
|
-
if (!
|
|
196
|
-
const l = e.rootTag ?
|
|
197
|
-
|
|
197
|
+
const m = a.documentElement;
|
|
198
|
+
let f = e.rowTag;
|
|
199
|
+
if (!f) {
|
|
200
|
+
const l = e.rootTag ? a.querySelector(e.rootTag) : m;
|
|
201
|
+
f = ((n = l == null ? void 0 : l.children[0]) == null ? void 0 : n.tagName) ?? "row";
|
|
198
202
|
}
|
|
199
|
-
const u =
|
|
203
|
+
const u = a.getElementsByTagName(f), c = [];
|
|
200
204
|
for (let l = 0; l < u.length; l++) {
|
|
201
|
-
const d = u[l],
|
|
205
|
+
const d = u[l], g = {};
|
|
202
206
|
for (const s of Array.from(d.attributes)) {
|
|
203
|
-
const h =
|
|
204
|
-
|
|
207
|
+
const h = o[s.name] ?? s.name;
|
|
208
|
+
g[h] = i ? s.value.trim() : s.value;
|
|
205
209
|
}
|
|
206
210
|
for (const s of Array.from(d.children)) {
|
|
207
|
-
const h =
|
|
208
|
-
|
|
211
|
+
const h = o[s.tagName] ?? s.tagName, x = s.textContent ?? "";
|
|
212
|
+
g[h] = i ? x.trim() : x;
|
|
209
213
|
}
|
|
210
|
-
|
|
214
|
+
c.push(g);
|
|
211
215
|
}
|
|
212
|
-
return
|
|
216
|
+
return c;
|
|
213
217
|
}
|
|
214
218
|
// ── 2. 데이터 배열 → XML ─────────────────────────────────────
|
|
215
219
|
/**
|
|
@@ -217,34 +221,34 @@ class w {
|
|
|
217
221
|
*/
|
|
218
222
|
static stringify(t, e = {}) {
|
|
219
223
|
const {
|
|
220
|
-
rootTag:
|
|
224
|
+
rootTag: o = "rows",
|
|
221
225
|
rowTag: i = "row",
|
|
222
|
-
mode:
|
|
223
|
-
fieldMap:
|
|
226
|
+
mode: r = "element",
|
|
227
|
+
fieldMap: a = {},
|
|
224
228
|
declaration: _ = !0,
|
|
225
229
|
indent: m = 2,
|
|
226
|
-
nullAs:
|
|
230
|
+
nullAs: f = "",
|
|
227
231
|
excludeFields: u = []
|
|
228
|
-
} = e,
|
|
229
|
-
_ && p.push('<?xml version="1.0" encoding="UTF-8"?>'), p.push(`<${
|
|
232
|
+
} = e, c = " ".repeat(m), p = [];
|
|
233
|
+
_ && p.push('<?xml version="1.0" encoding="UTF-8"?>'), p.push(`<${o}>`);
|
|
230
234
|
for (const n of t) {
|
|
231
235
|
const l = Object.entries(n).filter(([d]) => !u.includes(d));
|
|
232
|
-
if (
|
|
233
|
-
const d = l.map(([
|
|
234
|
-
const h =
|
|
236
|
+
if (r === "attribute") {
|
|
237
|
+
const d = l.map(([g, s]) => {
|
|
238
|
+
const h = a[g] ?? g, x = s == null ? f : String(s);
|
|
235
239
|
return `${h}="${this._escAttr(x)}"`;
|
|
236
240
|
}).join(" ");
|
|
237
|
-
p.push(`${
|
|
241
|
+
p.push(`${c}<${i}${d ? " " + d : ""} />`);
|
|
238
242
|
} else {
|
|
239
|
-
p.push(`${
|
|
240
|
-
for (const [d,
|
|
241
|
-
const s =
|
|
242
|
-
p.push(`${
|
|
243
|
+
p.push(`${c}<${i}>`);
|
|
244
|
+
for (const [d, g] of l) {
|
|
245
|
+
const s = a[d] ?? d, h = g == null ? f : String(g);
|
|
246
|
+
p.push(`${c}${c}<${s}>${this._escText(h)}</${s}>`);
|
|
243
247
|
}
|
|
244
|
-
p.push(`${
|
|
248
|
+
p.push(`${c}</${i}>`);
|
|
245
249
|
}
|
|
246
250
|
}
|
|
247
|
-
return p.push(`</${
|
|
251
|
+
return p.push(`</${o}>`), p.join(`
|
|
248
252
|
`);
|
|
249
253
|
}
|
|
250
254
|
// ── 3. SAP BAPI XML 응답 파싱 ────────────────────────────────
|
|
@@ -257,38 +261,38 @@ class w {
|
|
|
257
261
|
* <RETURN><TYPE>S</TYPE><MESSAGE>...</MESSAGE></RETURN>
|
|
258
262
|
*/
|
|
259
263
|
static parseSap(t) {
|
|
260
|
-
var m,
|
|
261
|
-
const
|
|
262
|
-
if (
|
|
263
|
-
for (const p of Array.from(
|
|
264
|
+
var m, f, u, c;
|
|
265
|
+
const o = new DOMParser().parseFromString(t.trim(), "text/xml"), i = { header: {}, items: [], returns: [], raw: o }, r = o.getElementsByTagName("DOCUMENTHEADER")[0];
|
|
266
|
+
if (r)
|
|
267
|
+
for (const p of Array.from(r.children))
|
|
264
268
|
i.header[p.tagName] = ((m = p.textContent) == null ? void 0 : m.trim()) ?? "";
|
|
265
|
-
const
|
|
266
|
-
for (const p of Array.from(
|
|
269
|
+
const a = o.getElementsByTagName("RETURN");
|
|
270
|
+
for (const p of Array.from(a)) {
|
|
267
271
|
const n = {};
|
|
268
272
|
for (const l of Array.from(p.children))
|
|
269
|
-
n[l.tagName] = ((
|
|
273
|
+
n[l.tagName] = ((f = l.textContent) == null ? void 0 : f.trim()) ?? "";
|
|
270
274
|
i.returns.push(n);
|
|
271
275
|
}
|
|
272
276
|
const _ = ["ACCOUNTGL", "ACCOUNTRECEIVABLE", "ACCOUNTPAYABLE", "ITEMS"];
|
|
273
277
|
for (const p of _) {
|
|
274
|
-
const n =
|
|
278
|
+
const n = o.getElementsByTagName(p)[0];
|
|
275
279
|
if (!n) continue;
|
|
276
280
|
const l = n.getElementsByTagName("ITEM"), d = l.length > 0 ? Array.from(l) : [n];
|
|
277
|
-
for (const
|
|
281
|
+
for (const g of d) {
|
|
278
282
|
const s = {};
|
|
279
|
-
for (const h of Array.from(
|
|
283
|
+
for (const h of Array.from(g.children))
|
|
280
284
|
s[h.tagName] = ((u = h.textContent) == null ? void 0 : u.trim()) ?? "";
|
|
281
285
|
i.items.push(s);
|
|
282
286
|
}
|
|
283
287
|
break;
|
|
284
288
|
}
|
|
285
289
|
if (i.items.length === 0) {
|
|
286
|
-
const p =
|
|
290
|
+
const p = o.documentElement, n = Array.from(p.children).filter((l) => l.hasAttribute("SEGMENT"));
|
|
287
291
|
for (const l of n) {
|
|
288
292
|
if (l.tagName === "EDI_DC40") continue;
|
|
289
293
|
const d = {};
|
|
290
|
-
for (const
|
|
291
|
-
d[
|
|
294
|
+
for (const g of Array.from(l.children))
|
|
295
|
+
d[g.tagName] = ((c = g.textContent) == null ? void 0 : c.trim()) ?? "";
|
|
292
296
|
Object.keys(d).length > 0 && i.items.push(d);
|
|
293
297
|
}
|
|
294
298
|
}
|
|
@@ -306,22 +310,22 @@ class w {
|
|
|
306
310
|
];
|
|
307
311
|
if (t.BAPI_FUNCTION && e.push(` <FUNCTION>${this._escText(t.BAPI_FUNCTION)}</FUNCTION>`), t.DOCUMENTHEADER && typeof t.DOCUMENTHEADER == "object") {
|
|
308
312
|
e.push(" <DOCUMENTHEADER>");
|
|
309
|
-
for (const [i,
|
|
310
|
-
|
|
313
|
+
for (const [i, r] of Object.entries(t.DOCUMENTHEADER))
|
|
314
|
+
r != null && r !== "" && e.push(` <${i}>${this._escText(String(r))}</${i}>`);
|
|
311
315
|
e.push(" </DOCUMENTHEADER>");
|
|
312
316
|
}
|
|
313
|
-
const
|
|
317
|
+
const o = Object.keys(t).find(
|
|
314
318
|
(i) => Array.isArray(t[i]) && !i.startsWith("_")
|
|
315
319
|
);
|
|
316
|
-
if (
|
|
317
|
-
e.push(` <${
|
|
318
|
-
for (const i of t[
|
|
320
|
+
if (o) {
|
|
321
|
+
e.push(` <${o}>`);
|
|
322
|
+
for (const i of t[o]) {
|
|
319
323
|
e.push(" <ITEM>");
|
|
320
|
-
for (const [
|
|
321
|
-
|
|
324
|
+
for (const [r, a] of Object.entries(i))
|
|
325
|
+
a != null && a !== "" && !r.startsWith("_") && e.push(` <${r}>${this._escText(String(a))}</${r}>`);
|
|
322
326
|
e.push(" </ITEM>");
|
|
323
327
|
}
|
|
324
|
-
e.push(` </${
|
|
328
|
+
e.push(` </${o}>`);
|
|
325
329
|
}
|
|
326
330
|
return e.push("</BAPI_CALL>"), e.join(`
|
|
327
331
|
`);
|
|
@@ -336,12 +340,12 @@ class w {
|
|
|
336
340
|
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
337
341
|
`<BAPI_BATCH total="${t.documents.length}">`
|
|
338
342
|
];
|
|
339
|
-
return t.documents.forEach((
|
|
343
|
+
return t.documents.forEach((o, i) => {
|
|
340
344
|
e.push(` <BAPI_CALL seq="${i + 1}">`);
|
|
341
|
-
const
|
|
342
|
-
`).filter((
|
|
345
|
+
const r = this.stringifySap(o).split(`
|
|
346
|
+
`).filter((a) => !a.startsWith("<?xml")).map((a) => " " + a).join(`
|
|
343
347
|
`);
|
|
344
|
-
e.push(
|
|
348
|
+
e.push(r), e.push(" </BAPI_CALL>");
|
|
345
349
|
}), e.push("</BAPI_BATCH>"), e.join(`
|
|
346
350
|
`);
|
|
347
351
|
}
|
|
@@ -354,10 +358,16 @@ class w {
|
|
|
354
358
|
}
|
|
355
359
|
}
|
|
356
360
|
export {
|
|
361
|
+
$ as DEFAULT_ICON_ROLES,
|
|
357
362
|
C as GridShuttle,
|
|
358
|
-
|
|
363
|
+
S as IconRegistry,
|
|
364
|
+
O as OpenGrid,
|
|
359
365
|
N as OrgChart,
|
|
360
|
-
|
|
361
|
-
|
|
366
|
+
D as SkinRegistry,
|
|
367
|
+
I as XmlConverter,
|
|
368
|
+
v as createGridShuttle,
|
|
369
|
+
k as iconRegistry,
|
|
370
|
+
M as renderIcon,
|
|
371
|
+
B as skinRegistry
|
|
362
372
|
};
|
|
363
373
|
//# sourceMappingURL=open-grid.js.map
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThemeContext — DOM-free 값 객체. 활성 색 테마(및 미래의 스킨) 식별자를 운반한다.
|
|
3
|
+
* R12a 에서 resolver 메서드는 아직 이 컨텍스트로 분기하지 않는다(반환은 항상 `var()` 문자열이라
|
|
4
|
+
* 브라우저가 런타임에 테마별로 재계산 → 오늘의 zero-rerender 테마 전환을 보존, 현상맵 §1.3).
|
|
5
|
+
* R12b(스킨)에서 `skin` 을 읽어 FORM 토큰을 해결하는 자리를 여기 마련해 둔다.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ThemeContext {
|
|
8
|
+
readonly theme: string;
|
|
9
|
+
readonly skin: string;
|
|
10
|
+
constructor(theme?: string, skin?: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* propagateAppearance — 분리(portal-ed) UI 로 외관 축을 함께 복사(item3 §4.3, HANMS Q8).
|
|
14
|
+
* 두 속성(`data-og-theme` COLOR · `data-og-skin` FORM)을 **한 번에** 복사해, 컴포넌트마다
|
|
15
|
+
* 두 번째 속성을 잊어 스킨만 안 먹는 조용한 사고(§6-9)를 구조적으로 막는다.
|
|
16
|
+
* `fromEl` 에서 가장 가까운 속성 보유 조상을 찾아 `toEl` 에 복사한다.
|
|
17
|
+
*/
|
|
18
|
+
export declare function propagateAppearance(fromEl: Element | null, toEl: Element): void;
|
|
19
|
+
/** border()/focusRing() 형태 옵션(미래 스킨용). 미지정 시 오늘의 기본값 = byte-identical. */
|
|
20
|
+
export interface BorderOptions {
|
|
21
|
+
/** 보더 스타일 키워드(기본 'solid'). */
|
|
22
|
+
style?: string;
|
|
23
|
+
/** true 면 상태(added/edited/removed·selection·range) 보더 — HANMS G-ST2: 항상 solid 강제. */
|
|
24
|
+
state?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface FocusRingOptions {
|
|
27
|
+
width?: number;
|
|
28
|
+
style?: string;
|
|
29
|
+
color?: string;
|
|
30
|
+
}
|
|
31
|
+
export type ElevationLevel = 'sm' | 'md' | 'lg';
|
|
32
|
+
/**
|
|
33
|
+
* AppearanceResolver — 렌더 레이어가 "형태 값"을 물어보는 단일 지점.
|
|
34
|
+
* R12a 는 **결정을 객체화**할 뿐 값은 오늘과 동일하다(회귀 0). 상태 없음(순수) — 반환은
|
|
35
|
+
* `var()` 기반 문자열 또는 px 패스스루라, 인스턴스 공유가 안전하다(멀티그리드 격리 무해).
|
|
36
|
+
*/
|
|
37
|
+
export declare class AppearanceResolver {
|
|
38
|
+
private _ctx;
|
|
39
|
+
constructor(_ctx?: ThemeContext);
|
|
40
|
+
/** 활성 테마/스킨 컨텍스트(R12b 스킨 해결의 진입점). */
|
|
41
|
+
get context(): ThemeContext;
|
|
42
|
+
/** 스킨이 활성(비-default)인가. default 면 오늘의 리터럴을 그대로 반환(byte-identical). */
|
|
43
|
+
private _skinActive;
|
|
44
|
+
/**
|
|
45
|
+
* R12b: 스킨 컨텍스트 교체(테마는 유지). 파사드 setSkin 이 호출한 뒤 재렌더하면 인라인 form 사이트가
|
|
46
|
+
* 이 컨텍스트로 재해석된다. default → named 전환 시 border/divider 가 리터럴 → var() 로 승격.
|
|
47
|
+
*/
|
|
48
|
+
setSkin(skin: string): void;
|
|
49
|
+
/** border-color 토큰 참조(폴백 포함) — 렌더 코드가 오늘 쓰는 문자열과 동일. */
|
|
50
|
+
private _borderColorVar;
|
|
51
|
+
/**
|
|
52
|
+
* 셀/헤더 가장자리 보더. 오늘의 리터럴 `1px solid var(--og-border-color,#e0e0e0)` 과
|
|
53
|
+
* **문자 단위 동일**. HANMS G-ST2: state 보더는 스타일을 solid 로 강제(현재 호출은 state 미지정 → no-op).
|
|
54
|
+
*/
|
|
55
|
+
border(opts?: BorderOptions): string;
|
|
56
|
+
/**
|
|
57
|
+
* 행/섹션 구획선(가로 separator). 오늘은 border() 와 동일 문자열(=`1px solid var(--og-border-color,#e0e0e0)`).
|
|
58
|
+
* 별도 메서드로 둔 이유: R12b 스킨에서 divider-style 이 border-style 과 갈라질 수 있어(§1.2)
|
|
59
|
+
* 결정 지점을 미리 분리해 둔다. 현재 출력은 border() 와 byte-identical.
|
|
60
|
+
*/
|
|
61
|
+
divider(): string;
|
|
62
|
+
/**
|
|
63
|
+
* G-ST1(코어 불변식, HANMS §2): 텍스처 존 제한. 텍스처는 컨테이너 배경·헤더 여백·빈 상태·온보딩
|
|
64
|
+
* 오버레이에만 렌더되고, **데이터/상태/범위/병합/포커스 셀 배경 뒤에는 절대 렌더 금지**(스킨이 끌 수 없음).
|
|
65
|
+
* 렌더 레이어가 셀 배경 텍스처를 바를 때 이 메서드로 zone 을 물어본다.
|
|
66
|
+
* - 금지 zone → 항상 `'none'`(스킨과 무관).
|
|
67
|
+
* - 허용 zone → `var(--og-texture-bg, none)`(스킨 미설정 시 none = byte-identical).
|
|
68
|
+
*/
|
|
69
|
+
texture(zone: 'container' | 'header-pad' | 'empty' | 'onboarding' | 'data' | 'status' | 'range' | 'merge' | 'focus'): string;
|
|
70
|
+
/**
|
|
71
|
+
* 반경 값 → CSS 길이 문자열. R12a 는 패스스루(`${px}px`)로 오늘의 리터럴을 그대로 보존한다.
|
|
72
|
+
* 반경 리터럴이 흩어져 있던 결정 지점(이미지/프로그레스/스위치/뱃지/마스킹/상태뱃지)을 이 한 곳으로 모은다.
|
|
73
|
+
* R12b 에서 `--og-radius-*` 스케일 토큰으로 승격할 착지점.
|
|
74
|
+
*/
|
|
75
|
+
radius(px: number): string;
|
|
76
|
+
/**
|
|
77
|
+
* 데이터/그룹 셀의 인라인 패딩. 오늘의 그룹 셀 리터럴 `2px 8px` 과 동일.
|
|
78
|
+
* R12b `--og-cell-padding-*` 승격 자리.
|
|
79
|
+
*/
|
|
80
|
+
cellPadding(): string;
|
|
81
|
+
/**
|
|
82
|
+
* 엘리베이션(box-shadow) — R12b 스킨 축의 형태/잉크 분리 seam(§1.4)을 미리 표기한다.
|
|
83
|
+
* R12a 에서는 어떤 인라인 사이트도 이 메서드를 경유하지 않는다(현재 그림자 결정이 인라인에 없음).
|
|
84
|
+
* 값은 미래 토큰 + 오늘과 무해한 기본 geometry/alpha 로, 라우팅 0 이라 출력에 영향 없음.
|
|
85
|
+
*/
|
|
86
|
+
elevation(level?: ElevationLevel): string;
|
|
87
|
+
/**
|
|
88
|
+
* 포커스 링. HANMS 하드 계약(불변식): 가시 포커스는 비협상 —
|
|
89
|
+
* `width < 2px` 또는 `style: 'none'` 은 최소 `2px solid` 로 **클램프**한다(스킨이 끌 수 없음).
|
|
90
|
+
* R12a 에서 라우팅되는 인라인 포커스 사이트는 없다(포커스 표시는 CSS 클래스 `.og-cell-focused`).
|
|
91
|
+
* 기본 반환은 현 프라이머리 색 기반의 AA-safe 링 — 미래 스킨/오버라이드가 이 초크포인트를 경유한다.
|
|
92
|
+
*/
|
|
93
|
+
focusRing(opts?: FocusRingOptions): string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 프로세스 공유 기본 resolver. CellRenderer(팩토리로 생성돼 per-instance 컨텍스트를 받지 않음)가
|
|
97
|
+
* 반경 결정을 이 초크포인트로 보낼 때 사용한다. R12a 반환은 상태 없는 순수값이라 공유가 안전하다.
|
|
98
|
+
* per-instance(테마 컨텍스트) 주입은 R12b 스킨에서 확장한다.
|
|
99
|
+
*/
|
|
100
|
+
export declare const defaultAppearance: AppearanceResolver;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { DataLayer } from './DataLayer.js';
|
|
2
|
+
import { ColumnLayout } from './ColumnLayout.js';
|
|
3
|
+
import { GridOptions, OpenGridInstance, Position, GridDropEvent } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* R7(§3.1 C8, §6-R7): 그리드 간 이동·매핑·drop 표면(`moveRowsTo`/`moveCheckedTo`/크로스변환 해석/
|
|
6
|
+
* 3단계 드롭 이벤트 발화)을 `OpenGrid` God object 에서 **동작 불변**으로 옮긴 것. `OpenGrid` 는
|
|
7
|
+
* 얇은 위임 공개 메서드만 남긴다(공개 API 불변 — R0 `public_api_surface.txt` 동결).
|
|
8
|
+
*
|
|
9
|
+
* 스트랭글러 원칙(A2): `crossGridRegistry`(프로세스 스코프 싱글턴, `CrossGridRegistry.ts`)는 지금은
|
|
10
|
+
* **AS-IS 유지**한다 — 주입 `GridRegistry` 로의 승격(C8, R-6c)은 R8 컴포지션 루트로 이연한다.
|
|
11
|
+
*
|
|
12
|
+
* cross-grid 이동은 **두 그리드**(source=this, target)를 동시에 다룬다. 각 `OpenGrid` 는 자신의
|
|
13
|
+
* CrossGridController 를 소유하므로, target 측 연산(insert/rowCount/컬럼/3단계 발화)은
|
|
14
|
+
* `getPeerController(target)` 로 얻은 상대 컨트롤러의 동명 메서드로 수행한다 — `this`(source) 와
|
|
15
|
+
* peer(target) 로 갈라 원본의 `this._x` / `targetGrid._x` 접근을 1:1 재현한다(회귀 0).
|
|
16
|
+
* **3단계 drop emit 순서(before→후 이동→after→complete, 각 source→target)는 정확히 보존한다.**
|
|
17
|
+
*/
|
|
18
|
+
export interface CrossGridControllerDeps<T extends Record<string, any> = any> {
|
|
19
|
+
/** GridDropEvent 의 sourceGrid/targetGrid 식별자 + 자기동일성 비교에 쓰는 소유 그리드. */
|
|
20
|
+
getSelf: () => OpenGridInstance<T>;
|
|
21
|
+
getData: () => DataLayer<T>;
|
|
22
|
+
getColLayout: () => ColumnLayout<T>;
|
|
23
|
+
getOptions: () => Required<GridOptions<T>>;
|
|
24
|
+
/** EventEmitter fan(this.emit) — 'gridDropBefore/After/Complete'/'gridDropMapping'. */
|
|
25
|
+
emit: (event: string, payload?: any) => void;
|
|
26
|
+
/** 공개 insertRow 위임(MutationService 경유) — target 삽입에 쓰인다. */
|
|
27
|
+
insertRow: (item: Partial<T>, position?: Position) => void;
|
|
28
|
+
/** 공개 deleteRow 위임(MutationService 경유) — source 제거에 쓰인다. */
|
|
29
|
+
deleteRow: (rowIndex: number | number[]) => void;
|
|
30
|
+
/** rowMgr.getChecked() — moveCheckedTo. */
|
|
31
|
+
getChecked: () => Array<{
|
|
32
|
+
rowIndex: number;
|
|
33
|
+
}>;
|
|
34
|
+
/** rowMgr.uncheckAll()(+재렌더) 공개 위임 — moveCheckedTo. */
|
|
35
|
+
uncheckAll: () => void;
|
|
36
|
+
/** 드래그 선택 집합 해석(_dragRowSet). OpenGrid 가 소유(RowDragDrop 배선과 공유). */
|
|
37
|
+
dragRowSet: (fromIndex: number) => number[];
|
|
38
|
+
/** 상대 그리드의 CrossGridController 획득(피어 연산 위임). 비 OpenGrid 대상은 undefined. */
|
|
39
|
+
getPeerController: (grid: OpenGridInstance<T>) => CrossGridController<T> | undefined;
|
|
40
|
+
}
|
|
41
|
+
export declare class CrossGridController<T extends Record<string, any> = any> {
|
|
42
|
+
private _deps;
|
|
43
|
+
constructor(deps: CrossGridControllerDeps<T>);
|
|
44
|
+
/** 이 그리드의 소유 인스턴스(GridDropEvent 식별자). */
|
|
45
|
+
getSelf(): OpenGridInstance<T>;
|
|
46
|
+
private _rowCount;
|
|
47
|
+
private _insertRow;
|
|
48
|
+
private _visibleLeafInfos;
|
|
49
|
+
/** 드래그 드롭 어댑터 → 공개 moveRowsTo 로 위임 */
|
|
50
|
+
handleCrossGridDrop(fromIndex: number, targetBodyEl: HTMLElement, targetIndex: number): void;
|
|
51
|
+
/**
|
|
52
|
+
* 이 그리드의 행들을 다른 그리드로 이동(move)한다. 드래그·화살표 셔틀 공통 경로.
|
|
53
|
+
* 3단계 이벤트(before→after→complete)와 crossGridMapping(필드 매핑)을 적용한다.
|
|
54
|
+
* @param target 대상 그리드
|
|
55
|
+
* @param sourceIndexes 이동할 (표시)행 인덱스들
|
|
56
|
+
* @param targetIndex 대상에서 삽입 위치 (생략 시 맨 끝에 추가)
|
|
57
|
+
* @returns 이동 성공 true, 취소/무효 false
|
|
58
|
+
*/
|
|
59
|
+
moveRowsTo(target: OpenGridInstance<T>, sourceIndexes: number[], targetIndex?: number): Promise<boolean>;
|
|
60
|
+
/** 체크된 행을 다른 그리드로 이동 (화살표 셔틀용). 체크 없으면 무시. */
|
|
61
|
+
moveCheckedTo(target: OpenGridInstance<T>): Promise<boolean>;
|
|
62
|
+
/**
|
|
63
|
+
* 크로스그리드 이동의 행 변환 함수를 결정한다.
|
|
64
|
+
* 반환: null=변환 불필요(그대로) / 함수=변환 적용 / false=매핑 모달 취소(이동 중단)
|
|
65
|
+
*/
|
|
66
|
+
private _resolveCrossTransform;
|
|
67
|
+
fireGridDropBefore(e: GridDropEvent<T>): boolean | void;
|
|
68
|
+
fireGridDropAfter(e: GridDropEvent<T>): void;
|
|
69
|
+
fireGridDropComplete(e: GridDropEvent<T>): void;
|
|
70
|
+
}
|