gnui 1.2.16 → 1.2.18
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/dist/js/gnui.esm.js +772 -111
- package/dist/js/gnui.js +772 -111
- package/dist/js/gnui.min.js +6 -6
- package/dist/styles/default.css +1018 -108
- package/dist/styles/gpi.css +1018 -108
- package/dist/styles/green24.css +1229 -289
- package/dist/styles/insights.css +1018 -108
- package/dist/styles/nac.css +1019 -109
- package/dist/styles/ztnac.css +1205 -265
- package/package.json +2 -2
- package/styleguide/assets/components.js +216 -9
- package/styleguide/assets/js/gnui.js +772 -111
- package/styleguide/assets/js/gnui.min.js +6 -6
- package/styleguide/assets/styles/default.css +1018 -108
- package/styleguide/assets/styles/gpi.css +1018 -108
- package/styleguide/assets/styles/green24.css +1229 -289
- package/styleguide/assets/styles/insights.css +1018 -108
- package/styleguide/assets/styles/nac.css +1019 -109
- package/styleguide/assets/styles/ztnac.css +1205 -265
- package/styleguide/category/COLOR/index.html +2 -2
- package/styleguide/category/COMPONENT/Alert(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Bignumber/index.html +2 -2
- package/styleguide/category/COMPONENT/Breadcrumb/index.html +2 -2
- package/styleguide/category/COMPONENT/Calendar(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Card/index.html +2 -2
- package/styleguide/category/COMPONENT/Chart(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Datagrid(js)/index.html +136 -9
- package/styleguide/category/COMPONENT/Datalist(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Growl(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/JsonView(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Loader(js)/index.html +21 -4
- package/styleguide/category/COMPONENT/MenuButton(js)/index.html +74 -6
- package/styleguide/category/COMPONENT/Message(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Modal(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Pagination(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Panel/index.html +2 -2
- package/styleguide/category/COMPONENT/Progressbar(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Tab(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Tagcloud(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Tooltip(js)/index.html +2 -2
- package/styleguide/category/COMPONENT/Tree(js)/index.html +2 -2
- package/styleguide/category/CONTROLS/Button(js)/index.html +2 -2
- package/styleguide/category/CONTROLS/Checkbox/index.html +2 -2
- package/styleguide/category/CONTROLS/Colorpicker(js)/index.html +2 -2
- package/styleguide/category/CONTROLS/Datepicker(js)/index.html +2 -2
- package/styleguide/category/CONTROLS/Dropdown(js)/index.html +2 -2
- package/styleguide/category/CONTROLS/File/index.html +2 -2
- package/styleguide/category/CONTROLS/Form/Control/index.html +2 -2
- package/styleguide/category/CONTROLS/Form/Field/index.html +2 -2
- package/styleguide/category/CONTROLS/Form/Plain/index.html +2 -2
- package/styleguide/category/CONTROLS/Input/index.html +2 -2
- package/styleguide/category/CONTROLS/MultiText(js)/index.html +2 -2
- package/styleguide/category/CONTROLS/Picklist(js)/index.html +28 -18
- package/styleguide/category/CONTROLS/Radio/index.html +2 -2
- package/styleguide/category/CONTROLS/Select/index.html +2 -2
- package/styleguide/category/CONTROLS/SelectButton(js)/index.html +2 -2
- package/styleguide/category/CONTROLS/Slider/index.html +2 -2
- package/styleguide/category/CONTROLS/SortableList(js)/index.html +487 -0
- package/styleguide/category/CONTROLS/Switch(js)/index.html +2 -2
- package/styleguide/category/CONTROLS/SyntaxInput(js)/index.html +2 -2
- package/styleguide/category/CONTROLS/Textarea/index.html +2 -2
- package/styleguide/category/CONTROLS/Time(js)/index.html +2 -2
- package/styleguide/category/ELEMENTS/Box/index.html +2 -2
- package/styleguide/category/ELEMENTS/Icon/index.html +2 -2
- package/styleguide/category/ELEMENTS/Image/index.html +2 -2
- package/styleguide/category/ELEMENTS/List/index.html +2 -2
- package/styleguide/category/ELEMENTS/Table/index.html +2 -2
- package/styleguide/category/ELEMENTS/Tag/index.html +2 -2
- package/styleguide/category/ELEMENTS/Title/index.html +2 -2
- package/styleguide/category/LAYOUT/Container/index.html +2 -2
- package/styleguide/category/LAYOUT/Grid/index.html +2 -2
- package/styleguide/category/LAYOUT/Splitter(js)/index.html +2 -2
- package/styleguide/category/UTILITY/index.html +2 -2
- package/styleguide/category/Utils/index.html +2 -2
- package/styleguide/color.html +2 -2
- package/styleguide/index.html +2 -2
- package/styleguide/tag/javascript/index.html +608 -31
- package/styleguide/tag/v.0.1.0/index.html +608 -31
package/dist/js/gnui.esm.js
CHANGED
|
@@ -14112,15 +14112,15 @@ function findValue(obj, pathString) {
|
|
|
14112
14112
|
if (!obj || !pathString) {
|
|
14113
14113
|
return "";
|
|
14114
14114
|
}
|
|
14115
|
-
|
|
14116
|
-
|
|
14117
|
-
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14122
|
-
return "";
|
|
14115
|
+
const keys = isString(pathString) ? pathString.split(".") : pathString;
|
|
14116
|
+
let current = obj;
|
|
14117
|
+
for (const key of keys) {
|
|
14118
|
+
if (current === void 0 || current === null) {
|
|
14119
|
+
return "";
|
|
14120
|
+
}
|
|
14121
|
+
current = current[key];
|
|
14123
14122
|
}
|
|
14123
|
+
return current !== void 0 ? current : "";
|
|
14124
14124
|
}
|
|
14125
14125
|
function findProperty(obj, predicate) {
|
|
14126
14126
|
let result = [];
|
|
@@ -14259,17 +14259,18 @@ function interpolateURL(url, source) {
|
|
|
14259
14259
|
return dmustach.test(result) ? interpolateURL(result, source) : result;
|
|
14260
14260
|
}
|
|
14261
14261
|
function interpolateCop(textCondition, data2, parent2, $2) {
|
|
14262
|
-
const onlymustach = /^\{{2}[
|
|
14262
|
+
const onlymustach = /^\{{2}[\w.$\[\]]+\}{2}$/;
|
|
14263
14263
|
if (onlymustach.test(textCondition)) {
|
|
14264
14264
|
const path = textCondition.replace("{{", "").replace("}}", "");
|
|
14265
14265
|
return findValue({ data: data2, parent: parent2, $: $2 }, path);
|
|
14266
14266
|
}
|
|
14267
14267
|
const dmustach = new RegExp(/\{{([^{}]*)}}/gm);
|
|
14268
|
+
const context = { data: data2, parent: parent2, $: $2 };
|
|
14268
14269
|
const result = textCondition.replace(dmustach, (match) => {
|
|
14269
14270
|
const conditionalOp = match.replace(/\{{|\}}/gm, "");
|
|
14270
|
-
return new Function("
|
|
14271
|
+
return new Function("ctx", "const {data, parent, $} = ctx; return " + conditionalOp)(context);
|
|
14271
14272
|
});
|
|
14272
|
-
return dmustach.test(result) ?
|
|
14273
|
+
return dmustach.test(result) ? interpolateCop(result, context.data, context.parent, context.$) : result;
|
|
14273
14274
|
}
|
|
14274
14275
|
function parseBundle(text2, locale) {
|
|
14275
14276
|
let _value = text2;
|
|
@@ -14703,7 +14704,10 @@ function apply(element, args, fn) {
|
|
|
14703
14704
|
});
|
|
14704
14705
|
}
|
|
14705
14706
|
function getArgs(args) {
|
|
14706
|
-
return args.reduce(
|
|
14707
|
+
return args.reduce(
|
|
14708
|
+
(args2, arg) => args2.concat.call(args2, isString(arg) && includes(arg, " ") ? arg.trim().split(" ") : arg),
|
|
14709
|
+
[]
|
|
14710
|
+
);
|
|
14707
14711
|
}
|
|
14708
14712
|
var supports = {
|
|
14709
14713
|
get Multiple() {
|
|
@@ -14729,7 +14733,7 @@ function hslToRgb([h, s, l]) {
|
|
|
14729
14733
|
s = s / 100;
|
|
14730
14734
|
l = l / 100;
|
|
14731
14735
|
const c = (1 - Math.abs(2 * l - 1)) * s, x = c * (1 - Math.abs(h / 60 % 2 - 1)), m = l - c / 2;
|
|
14732
|
-
let r, g, b;
|
|
14736
|
+
let r = 0, g = 0, b = 0;
|
|
14733
14737
|
switch (true) {
|
|
14734
14738
|
case (h > -1 && h < 60):
|
|
14735
14739
|
r = c;
|
|
@@ -15008,7 +15012,14 @@ function monthData(locale) {
|
|
|
15008
15012
|
function dateData(locale) {
|
|
15009
15013
|
return ["S", "M", "T", "W", "T", "F", "S"];
|
|
15010
15014
|
}
|
|
15011
|
-
function objToDate({
|
|
15015
|
+
function objToDate({
|
|
15016
|
+
year,
|
|
15017
|
+
month,
|
|
15018
|
+
day,
|
|
15019
|
+
hour,
|
|
15020
|
+
minute,
|
|
15021
|
+
second
|
|
15022
|
+
}) {
|
|
15012
15023
|
if (hour === void 0) {
|
|
15013
15024
|
hour = "00";
|
|
15014
15025
|
}
|
|
@@ -15237,7 +15248,11 @@ function offset(element, coordinates) {
|
|
|
15237
15248
|
["left", "top"].forEach((prop) => {
|
|
15238
15249
|
if (prop in coordinates) {
|
|
15239
15250
|
const value = css$1(element, prop);
|
|
15240
|
-
css$1(
|
|
15251
|
+
css$1(
|
|
15252
|
+
element,
|
|
15253
|
+
prop,
|
|
15254
|
+
coordinates[prop] - (currentOffset == null ? void 0 : currentOffset[prop]) + toFloat(pos === "absolute" && value === "auto" ? position(element)[prop] : value)
|
|
15255
|
+
);
|
|
15241
15256
|
}
|
|
15242
15257
|
});
|
|
15243
15258
|
}
|
|
@@ -15360,7 +15375,10 @@ function before(ref, element) {
|
|
|
15360
15375
|
}
|
|
15361
15376
|
function after(ref, element) {
|
|
15362
15377
|
ref = $(ref);
|
|
15363
|
-
return insertNodes(
|
|
15378
|
+
return insertNodes(
|
|
15379
|
+
element,
|
|
15380
|
+
(element2) => ref.nextSibling ? before(ref.nextSibling, element2) : append(ref.parentNode, element2)
|
|
15381
|
+
);
|
|
15364
15382
|
}
|
|
15365
15383
|
function insertNodes(element, fn) {
|
|
15366
15384
|
element = isString(element) ? fragment(element) : element;
|
|
@@ -15384,13 +15402,21 @@ function on(...args) {
|
|
|
15384
15402
|
listener = delegate(targets, selector, listener);
|
|
15385
15403
|
}
|
|
15386
15404
|
useCapture = useCaptureFilter(useCapture);
|
|
15387
|
-
type.split(" ").forEach(
|
|
15405
|
+
type.split(" ").forEach(
|
|
15406
|
+
(type2) => targets.forEach(
|
|
15407
|
+
(target) => target.addEventListener(type2, listener, useCapture)
|
|
15408
|
+
)
|
|
15409
|
+
);
|
|
15388
15410
|
return () => off(targets, type, listener, useCapture);
|
|
15389
15411
|
}
|
|
15390
15412
|
function off(targets, type, listener, useCapture = false) {
|
|
15391
15413
|
useCapture = useCaptureFilter(useCapture);
|
|
15392
15414
|
targets = toEventTargets(targets);
|
|
15393
|
-
type.split(" ").forEach(
|
|
15415
|
+
type.split(" ").forEach(
|
|
15416
|
+
(type2) => targets.forEach(
|
|
15417
|
+
(target) => target.removeEventListener(type2, listener, useCapture)
|
|
15418
|
+
)
|
|
15419
|
+
);
|
|
15394
15420
|
}
|
|
15395
15421
|
function once(...args) {
|
|
15396
15422
|
const [element, type, selector, listener, useCapture, condition] = getArgs2(args);
|
|
@@ -15410,7 +15436,10 @@ function once(...args) {
|
|
|
15410
15436
|
return off2;
|
|
15411
15437
|
}
|
|
15412
15438
|
function trigger(targets, event, detail2) {
|
|
15413
|
-
return toEventTargets(targets).reduce(
|
|
15439
|
+
return toEventTargets(targets).reduce(
|
|
15440
|
+
(notCanceled, target) => notCanceled && target.dispatchEvent(createEvent(event, true, true, detail2)),
|
|
15441
|
+
true
|
|
15442
|
+
);
|
|
15414
15443
|
}
|
|
15415
15444
|
function createEvent(e, bubbles = true, cancelable = false, detail2) {
|
|
15416
15445
|
if (isString(e)) {
|
|
@@ -16895,7 +16924,10 @@ class GNCoreEventManager {
|
|
|
16895
16924
|
// 이벤트 삭제
|
|
16896
16925
|
delete this._eventMap[uid];
|
|
16897
16926
|
}
|
|
16898
|
-
|
|
16927
|
+
/**
|
|
16928
|
+
* lifeCycle 핸들러 실행
|
|
16929
|
+
*/
|
|
16930
|
+
cyclepatch(uid, name, params) {
|
|
16899
16931
|
const _events = this._getEvent(uid, name);
|
|
16900
16932
|
if (_events.length) {
|
|
16901
16933
|
_events.forEach((_event) => {
|
|
@@ -16904,6 +16936,28 @@ class GNCoreEventManager {
|
|
|
16904
16936
|
});
|
|
16905
16937
|
}
|
|
16906
16938
|
}
|
|
16939
|
+
/**
|
|
16940
|
+
* 등록된 이벤트 핸들러 실행
|
|
16941
|
+
*
|
|
16942
|
+
* - sync/async 핸들러를 모두 지원한다.
|
|
16943
|
+
* - 모든 핸들러를 순차 실행한 뒤, 하나라도 `false` 를 반환한 경우 `true`(cancelled)를 반환한다.
|
|
16944
|
+
* (첫 false 에서 중단하지 않고, 나머지 핸들러도 계속 실행한다)
|
|
16945
|
+
*/
|
|
16946
|
+
async dispatch(uid, name, params) {
|
|
16947
|
+
const _events = this._getEvent(uid, name);
|
|
16948
|
+
let cancelled = false;
|
|
16949
|
+
if (_events.length) {
|
|
16950
|
+
for (const _event of _events) {
|
|
16951
|
+
const _target = _event.target || this;
|
|
16952
|
+
// sync/async 둘 다 지원: Promise.resolve 로 감싸서 await
|
|
16953
|
+
const result = await Promise.resolve(params ? _event.handler.call(_target, ...params) : _event.handler.call(_target));
|
|
16954
|
+
if (result === false) {
|
|
16955
|
+
cancelled = true;
|
|
16956
|
+
}
|
|
16957
|
+
}
|
|
16958
|
+
}
|
|
16959
|
+
return cancelled;
|
|
16960
|
+
}
|
|
16907
16961
|
_getEvent(uid, name) {
|
|
16908
16962
|
// parameters에 해당하는 이벤트 반환
|
|
16909
16963
|
return this._eventMap[uid]
|
|
@@ -16988,7 +17042,7 @@ class GNUIState {
|
|
|
16988
17042
|
});
|
|
16989
17043
|
return _findComponent;
|
|
16990
17044
|
}
|
|
16991
|
-
// 등록된 컴포넌트 제거
|
|
17045
|
+
// 등록된 컴포넌트 제거 (selector 기반)
|
|
16992
17046
|
_removeComponent(selector) {
|
|
16993
17047
|
if (!selector) {
|
|
16994
17048
|
return;
|
|
@@ -16997,10 +17051,30 @@ class GNUIState {
|
|
|
16997
17051
|
Object.values(this._componentMap).forEach(n => {
|
|
16998
17052
|
// 동일한 selector 인지 비교해서 동일한 component의 selector이면 제거 처리
|
|
16999
17053
|
if (isEquals(n.selector, _selector)) {
|
|
17000
|
-
|
|
17054
|
+
// componentMap에서 완전히 제거
|
|
17055
|
+
delete this._componentMap[n.uid];
|
|
17056
|
+
// 컴포넌트 내부 참조도 제거 (메모리 누수 방지)
|
|
17057
|
+
if (n.component) {
|
|
17058
|
+
n.component = null;
|
|
17059
|
+
}
|
|
17060
|
+
n.selector = null;
|
|
17001
17061
|
}
|
|
17002
17062
|
});
|
|
17003
17063
|
}
|
|
17064
|
+
// 등록된 컴포넌트 제거 (uid 기반 - 더 효율적)
|
|
17065
|
+
_removeComponentByUid(uid) {
|
|
17066
|
+
if (!uid || !this._componentMap[uid]) {
|
|
17067
|
+
return;
|
|
17068
|
+
}
|
|
17069
|
+
// 컴포넌트 내부 참조 제거 (메모리 누수 방지)
|
|
17070
|
+
const componentInfo = this._componentMap[uid];
|
|
17071
|
+
if (componentInfo.component) {
|
|
17072
|
+
componentInfo.component = null;
|
|
17073
|
+
}
|
|
17074
|
+
componentInfo.selector = null;
|
|
17075
|
+
// componentMap에서 완전히 제거
|
|
17076
|
+
delete this._componentMap[uid];
|
|
17077
|
+
}
|
|
17004
17078
|
// 컴포넌트 life cycle에 따른 eventManager dispatch
|
|
17005
17079
|
_detectedCycle(uid, name) {
|
|
17006
17080
|
// component 마지막 status 업데이트
|
|
@@ -17010,7 +17084,7 @@ class GNUIState {
|
|
|
17010
17084
|
// event manager를 이용해 해당 uid 이벤트 dispatch
|
|
17011
17085
|
const eventManager = GNCoreEventManager.getInstance();
|
|
17012
17086
|
// 호출 후
|
|
17013
|
-
eventManager.
|
|
17087
|
+
eventManager.cyclepatch(uid, name, '');
|
|
17014
17088
|
// 이벤트 해제 - life cycle 은 컴포넌트 별로 한번씩만 존재하므로..
|
|
17015
17089
|
eventManager.remove(uid, name);
|
|
17016
17090
|
}
|
|
@@ -17024,6 +17098,7 @@ class GNUIState {
|
|
|
17024
17098
|
function _removedNode(removed) {
|
|
17025
17099
|
Array.prototype.forEach.call(removed, (rm) => {
|
|
17026
17100
|
// 삭제노드 연관 컴포넌트 (ex. tooltip) 삭제
|
|
17101
|
+
var _a;
|
|
17027
17102
|
const dependents = findAll('[data-gnui]', rm);
|
|
17028
17103
|
each(dependents, (dependent) => {
|
|
17029
17104
|
if (isElement$2(dependent)) {
|
|
@@ -17037,7 +17112,7 @@ class GNUIState {
|
|
|
17037
17112
|
remove($('#' + attr(rm, 'data-gnui')));
|
|
17038
17113
|
}
|
|
17039
17114
|
const findComponent = closerThis._getComponent($(rm));
|
|
17040
|
-
if (findComponent && findComponent._uid && !findComponent.$el.parentNode && findComponent.$name !== 'modal') {
|
|
17115
|
+
if (findComponent && findComponent._uid && !((_a = findComponent.$el) === null || _a === void 0 ? void 0 : _a.parentNode) && findComponent.$name !== 'modal') {
|
|
17041
17116
|
// state manager 에서 component 삭제
|
|
17042
17117
|
closerThis._removeComponent(rm);
|
|
17043
17118
|
// event manager 에서 unbind
|
|
@@ -17236,25 +17311,48 @@ class GNCoreInstance {
|
|
|
17236
17311
|
}
|
|
17237
17312
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
17238
17313
|
$update(element = this.$el, e) { }
|
|
17239
|
-
|
|
17314
|
+
/**
|
|
17315
|
+
* 컴포넌트 이벤트 디스패치 헬퍼
|
|
17316
|
+
*
|
|
17317
|
+
* - sync/async 핸들러 모두 지원한다.
|
|
17318
|
+
* - 하나 이상의 핸들러에서 `false`를 반환하면 `true`(cancelled) 를 반환한다.
|
|
17319
|
+
* - 단순 알림용(fire-and-forget) 이벤트는 반환값/await 없이 호출해도 된다.
|
|
17320
|
+
*/
|
|
17321
|
+
async $event(component, name, ...params) {
|
|
17240
17322
|
const eventManager = GNCoreEventManager.getInstance();
|
|
17241
|
-
eventManager.dispatch(component._uid, name, params);
|
|
17323
|
+
return eventManager.dispatch(component._uid, name, params);
|
|
17242
17324
|
}
|
|
17243
17325
|
$destroy(component = this, removeEl = true) {
|
|
17326
|
+
var _a;
|
|
17244
17327
|
const stateManager = GNUIState.getInstance();
|
|
17245
17328
|
// state manager 를 통해 destroy 상태 dispatch
|
|
17246
17329
|
stateManager._detectedCycle(component._uid, 'destroy');
|
|
17247
|
-
// remove Component in state manager
|
|
17248
|
-
stateManager._removeComponent(component.$selector);
|
|
17249
17330
|
// remove DOM (by removeEl)
|
|
17250
17331
|
if (removeEl) {
|
|
17251
17332
|
style(component.$el, 'display', 'none');
|
|
17252
17333
|
remove(component.$el);
|
|
17253
17334
|
}
|
|
17335
|
+
if (((_a = component.$options) === null || _a === void 0 ? void 0 : _a._destroy) && isFunction(component.$options._destroy)) {
|
|
17336
|
+
component.$options._destroy();
|
|
17337
|
+
}
|
|
17254
17338
|
// state manager 를 통해 destroy 상태 dispatch
|
|
17255
17339
|
stateManager._detectedCycle(component._uid, 'destroyed');
|
|
17256
|
-
// event manager 에서 등록
|
|
17340
|
+
// event manager 에서 등록 해제
|
|
17257
17341
|
GNCoreEventManager.getInstance().removeAll(component._uid);
|
|
17342
|
+
// state manager에서 component 제거 (uid 기반으로 효율적 제거)
|
|
17343
|
+
stateManager._removeComponentByUid(component._uid);
|
|
17344
|
+
// 메모리 누수 방지: component의 모든 hasOwnProperty 제거
|
|
17345
|
+
// config, events, methods, _hidden 등 동적으로 추가된 속성 포함
|
|
17346
|
+
Object.keys(component).forEach((key) => {
|
|
17347
|
+
try {
|
|
17348
|
+
component[key] = null;
|
|
17349
|
+
delete component[key];
|
|
17350
|
+
}
|
|
17351
|
+
catch (e) {
|
|
17352
|
+
// readonly 속성 등 삭제 불가능한 경우 무시
|
|
17353
|
+
}
|
|
17354
|
+
});
|
|
17355
|
+
component = null;
|
|
17258
17356
|
}
|
|
17259
17357
|
}
|
|
17260
17358
|
|
|
@@ -33455,8 +33553,19 @@ class Dropdown extends GNCoreInstance {
|
|
|
33455
33553
|
});
|
|
33456
33554
|
if (this.$options.value) {
|
|
33457
33555
|
if (this.$options.multiple) {
|
|
33458
|
-
|
|
33459
|
-
|
|
33556
|
+
// multiple 모드에서 다양한 타입의 value를 문자열 배열로 변환
|
|
33557
|
+
// 지원 타입: 문자열(쉼표 구분), 객체 배열, 단일 객체, 문자열 배열
|
|
33558
|
+
const values = typeof this.$options.value === 'string'
|
|
33559
|
+
? this.$options.value.split(',') // 케이스 1: 'item1,item2,item3'
|
|
33560
|
+
: Array.isArray(this.$options.value)
|
|
33561
|
+
? this.$options.value.map((v) => (typeof v === 'object' && v !== null && 'value' in v ? String(v.value) : String(v))) // 케이스 3: [{value:'item1', text:'항목1'}, ...] 또는 ['item1', 'item2']
|
|
33562
|
+
: typeof this.$options.value === 'object' && this.$options.value !== null && 'value' in this.$options.value
|
|
33563
|
+
? [String(this.$options.value.value)] // 케이스 2: {value:'item1', text:'항목1'}
|
|
33564
|
+
: [String(this.$options.value)]; // 기타: 숫자 등
|
|
33565
|
+
this.$options.value = this.$options.flatData.filter((opt) => {
|
|
33566
|
+
const optValue = typeof opt.value === 'string' ? opt.value : String(opt.value);
|
|
33567
|
+
return values.includes(optValue) && opt.text;
|
|
33568
|
+
});
|
|
33460
33569
|
}
|
|
33461
33570
|
else {
|
|
33462
33571
|
this.$options.value = this.$options.flatData.find((opt) => opt.value + '' === this.$options.value + '' && opt.text);
|
|
@@ -36971,26 +37080,8 @@ class DataGrid extends GNCoreInstance {
|
|
|
36971
37080
|
}
|
|
36972
37081
|
this.$event(this, 'onSort', column);
|
|
36973
37082
|
},
|
|
36974
|
-
renderHeader: (columns) => {
|
|
36975
|
-
this
|
|
36976
|
-
!this.$options.readonly &&
|
|
36977
|
-
columns.push({
|
|
36978
|
-
label: this.$options.textSets.orderLabel,
|
|
36979
|
-
key: 'btnOrder',
|
|
36980
|
-
style: {
|
|
36981
|
-
width: '50px'
|
|
36982
|
-
}
|
|
36983
|
-
});
|
|
36984
|
-
this.$options.hasDelete &&
|
|
36985
|
-
!this.$options.readonly &&
|
|
36986
|
-
columns.push({
|
|
36987
|
-
label: this.$options.textSets.deleteLabel,
|
|
36988
|
-
key: 'btnDelete',
|
|
36989
|
-
style: {
|
|
36990
|
-
width: '30px'
|
|
36991
|
-
}
|
|
36992
|
-
});
|
|
36993
|
-
this._setColumnsTemplate();
|
|
37083
|
+
renderHeader: (columns, isReset = false) => {
|
|
37084
|
+
this._setColumnsTemplate(isReset);
|
|
36994
37085
|
return (createElement$1("div", { className: "gn-datagrid-header-row", style: {
|
|
36995
37086
|
'grid-template-columns': this._columnsTemplate.join(' ')
|
|
36996
37087
|
} },
|
|
@@ -37029,6 +37120,10 @@ class DataGrid extends GNCoreInstance {
|
|
|
37029
37120
|
column.draggable && (this.$options.headers ? idx < this.$options.headers.length - 1 : true) && createElement$1("span", { className: "is-handle", "data-index": idx })));
|
|
37030
37121
|
},
|
|
37031
37122
|
renderBody: (data, columns) => {
|
|
37123
|
+
// 헤더가 숨겨진 경우에도 body 렌더 전에 템플릿 폭을 준비한다
|
|
37124
|
+
if (!this._columnsTemplate || !this._columnsTemplate.length) {
|
|
37125
|
+
this._setColumnsTemplate();
|
|
37126
|
+
}
|
|
37032
37127
|
rowIdx$1 = 0;
|
|
37033
37128
|
return (createElement$1("div", { className: "gn-datagrid-body", style: {
|
|
37034
37129
|
maxHeight: this.$options.bodyHeight ? this.$options.bodyHeight : 'auto'
|
|
@@ -37042,7 +37137,6 @@ class DataGrid extends GNCoreInstance {
|
|
|
37042
37137
|
});
|
|
37043
37138
|
},
|
|
37044
37139
|
renderRow: (row, columns, depth = 0, hasChild, isOpened, isCheck = false) => {
|
|
37045
|
-
row._depth = depth;
|
|
37046
37140
|
const _index = rowIdx$1++;
|
|
37047
37141
|
if (row.isChecked) {
|
|
37048
37142
|
isCheck = true;
|
|
@@ -37176,8 +37270,9 @@ class DataGrid extends GNCoreInstance {
|
|
|
37176
37270
|
e.stopPropagation();
|
|
37177
37271
|
toggler = parents(e.currentTarget, '.gn-datagrid-body-row');
|
|
37178
37272
|
}
|
|
37179
|
-
const
|
|
37180
|
-
|
|
37273
|
+
const rowDepth = Number(attr(toggler, 'data-depth')) || 0;
|
|
37274
|
+
const children = nextUntil(toggler, '.gn-datagrid-body-row[data-depth="' + rowDepth + '"]').filter((x) => {
|
|
37275
|
+
return Number(attr(x, 'data-depth')) > rowDepth;
|
|
37181
37276
|
});
|
|
37182
37277
|
type = type ? type : hasClass(toggler, 'is-collapsed') ? 'expand' : 'collapse';
|
|
37183
37278
|
if (type === 'collapse') {
|
|
@@ -37193,7 +37288,7 @@ class DataGrid extends GNCoreInstance {
|
|
|
37193
37288
|
//show childs
|
|
37194
37289
|
removeClass(toggler, 'is-collapsed');
|
|
37195
37290
|
removeClass(children.filter((x) => {
|
|
37196
|
-
return x
|
|
37291
|
+
return Number(attr(x, 'data-depth')) == rowDepth + 1;
|
|
37197
37292
|
}), 'is-hidden');
|
|
37198
37293
|
this.$event(this, 'onToggle', 'expanded', row, index$1(toggler));
|
|
37199
37294
|
}
|
|
@@ -37251,13 +37346,15 @@ class DataGrid extends GNCoreInstance {
|
|
|
37251
37346
|
e.stopPropagation();
|
|
37252
37347
|
const checker = parents(e.currentTarget, '.gn-datagrid-body-row');
|
|
37253
37348
|
const checkerState = e.target.checked;
|
|
37254
|
-
find('.is-allChecker', this.$el)
|
|
37349
|
+
const allChecker = find('.is-allChecker', this.$el);
|
|
37350
|
+
allChecker && (allChecker.checked = false);
|
|
37351
|
+
const rowDepth = Number(attr(checker, 'data-depth')) || 0;
|
|
37255
37352
|
// 1. row에 자식노드가 있는지 확인한다.
|
|
37256
37353
|
if (this.$options.checkCapturing && row[this.$options.childField] && row[this.$options.childField].length) {
|
|
37257
37354
|
// 2. 자식노드가 있는경우 자식 체크박스도 함께 토글한다.
|
|
37258
|
-
nextUntil(checker, '.gn-datagrid-body-row[data-depth="' +
|
|
37355
|
+
nextUntil(checker, '.gn-datagrid-body-row[data-depth="' + rowDepth + '"]')
|
|
37259
37356
|
.filter((x) => {
|
|
37260
|
-
return x
|
|
37357
|
+
return Number(attr(x, 'data-depth')) > rowDepth;
|
|
37261
37358
|
})
|
|
37262
37359
|
.forEach((x) => {
|
|
37263
37360
|
const _checker = find('.is-rowChecker', x);
|
|
@@ -37267,17 +37364,17 @@ class DataGrid extends GNCoreInstance {
|
|
|
37267
37364
|
});
|
|
37268
37365
|
}
|
|
37269
37366
|
// 3. 체크 해제인 경우만 부모노드가 있는지 확인한다.
|
|
37270
|
-
if (this.$options.checkCapturing &&
|
|
37367
|
+
if (this.$options.checkCapturing && rowDepth > 0 && !checkerState) {
|
|
37271
37368
|
// 4. 부모노드가 체크되어 있는지 확인한다
|
|
37272
37369
|
const exeDepth = [];
|
|
37273
37370
|
prevUntil(checker, '.gn-datagrid-body-row[data-depth="0"]')
|
|
37274
37371
|
.filter((x) => {
|
|
37275
|
-
const _thisDepth = x
|
|
37372
|
+
const _thisDepth = attr(x, 'data-depth');
|
|
37276
37373
|
if (exeDepth.includes(_thisDepth)) {
|
|
37277
37374
|
return false;
|
|
37278
37375
|
}
|
|
37279
37376
|
exeDepth.push(_thisDepth);
|
|
37280
|
-
return _thisDepth <
|
|
37377
|
+
return Number(_thisDepth) < rowDepth;
|
|
37281
37378
|
})
|
|
37282
37379
|
.forEach((x) => {
|
|
37283
37380
|
const _checker = find('.is-rowChecker', x);
|
|
@@ -37293,9 +37390,21 @@ class DataGrid extends GNCoreInstance {
|
|
|
37293
37390
|
if (hasCheck === undefined) {
|
|
37294
37391
|
hasCheck = this.$options.hasCheck;
|
|
37295
37392
|
}
|
|
37296
|
-
this.$options.headers
|
|
37393
|
+
const prevHeaders = [...(this.$options.headers || [])];
|
|
37394
|
+
// _prepareHeaders가 배열을 변경하므로 비교용(prevHeaders)과 가공용(baseHeaders)을 분리한다
|
|
37395
|
+
const baseHeaders = headers ? [...headers] : [...prevHeaders];
|
|
37396
|
+
const preparedHeaders = this._prepareHeaders(baseHeaders);
|
|
37397
|
+
// 헤더 배열의 내용(길이, key)이 바뀐 경우에만 DOM 기반 폭 계산을 리셋한다
|
|
37398
|
+
const isReset = prevHeaders.length !== preparedHeaders.length || prevHeaders.some((header, idx) => { var _a; return header.key !== ((_a = preparedHeaders[idx]) === null || _a === void 0 ? void 0 : _a.key); });
|
|
37297
37399
|
this.$options.hasCheck = hasCheck;
|
|
37298
|
-
|
|
37400
|
+
const headerRow = find('.gn-datagrid-header-row', this.$el);
|
|
37401
|
+
// 헤더가 없을 때도 컬럼 수/폭 변경을 반영하기 위해 템플릿을 갱신한다
|
|
37402
|
+
if (this.$options.hasHeader && headerRow) {
|
|
37403
|
+
this.$template.reRender(headerRow, this._hidden.renderHeader(preparedHeaders, isReset));
|
|
37404
|
+
}
|
|
37405
|
+
else {
|
|
37406
|
+
this._setColumnsTemplate(isReset);
|
|
37407
|
+
}
|
|
37299
37408
|
this._hidden.resetData(data ? arrClone(data) : this.$options.data);
|
|
37300
37409
|
this.$render(this.$options);
|
|
37301
37410
|
isFunction(resolve) && resolve();
|
|
@@ -37310,6 +37419,10 @@ class DataGrid extends GNCoreInstance {
|
|
|
37310
37419
|
});
|
|
37311
37420
|
},
|
|
37312
37421
|
awaitData: (data) => {
|
|
37422
|
+
// asyncData 콜백 실행 중 컴포넌트가 destroy된 경우 안전하게 종료
|
|
37423
|
+
if (!this.$options || !this._hidden) {
|
|
37424
|
+
return;
|
|
37425
|
+
}
|
|
37313
37426
|
if (this.$options.asyncData && this.$options.paginator && !this._paginator) {
|
|
37314
37427
|
this._paginator = new Pagination('pagination', find('.gn-datagrid-footer', this.$el), {
|
|
37315
37428
|
total: this.$options.paginator.total || 0,
|
|
@@ -37334,7 +37447,8 @@ class DataGrid extends GNCoreInstance {
|
|
|
37334
37447
|
this._fixCellStyleOnDraggable();
|
|
37335
37448
|
// 체크박스가 있는경우 전체 체크항목을 해제해준다
|
|
37336
37449
|
if (this.$options.hasCheck) {
|
|
37337
|
-
find('.is-allChecker', this.$el)
|
|
37450
|
+
const allChecker = find('.is-allChecker', this.$el);
|
|
37451
|
+
allChecker && (allChecker.checked = false);
|
|
37338
37452
|
}
|
|
37339
37453
|
isFunction(resolve) && resolve();
|
|
37340
37454
|
});
|
|
@@ -37369,8 +37483,18 @@ class DataGrid extends GNCoreInstance {
|
|
|
37369
37483
|
stopRowSelectEvent: (e) => {
|
|
37370
37484
|
e.stopPropagation();
|
|
37371
37485
|
},
|
|
37372
|
-
deleteRow: (index) => {
|
|
37373
|
-
|
|
37486
|
+
deleteRow: async (index) => {
|
|
37487
|
+
var _a;
|
|
37488
|
+
const confirmMessage = (_a = this.$options.textSets) === null || _a === void 0 ? void 0 : _a.deleteConfirmMessage;
|
|
37489
|
+
if (confirmMessage && !window.confirm(confirmMessage)) {
|
|
37490
|
+
return;
|
|
37491
|
+
}
|
|
37492
|
+
const removedData = this._hidden.findData(index);
|
|
37493
|
+
const cancelled = await this.$event(this, 'onDelete', removedData, index);
|
|
37494
|
+
if (cancelled) {
|
|
37495
|
+
return;
|
|
37496
|
+
}
|
|
37497
|
+
this._hidden.deleteData(index);
|
|
37374
37498
|
this._hidden.resetData(this.$options.data);
|
|
37375
37499
|
this.$event(this, 'onChange', this.$options.data);
|
|
37376
37500
|
},
|
|
@@ -37405,22 +37529,38 @@ class DataGrid extends GNCoreInstance {
|
|
|
37405
37529
|
col.offHover && col.offHover.call(this, row, col, index, e);
|
|
37406
37530
|
},
|
|
37407
37531
|
findData: (index) => {
|
|
37408
|
-
|
|
37409
|
-
|
|
37410
|
-
|
|
37411
|
-
|
|
37412
|
-
|
|
37532
|
+
return this._hidden.walkByIndex(index, 'find');
|
|
37533
|
+
},
|
|
37534
|
+
deleteData: (index) => {
|
|
37535
|
+
return this._hidden.walkByIndex(index, 'delete');
|
|
37536
|
+
},
|
|
37537
|
+
walkByIndex: (index, action) => {
|
|
37538
|
+
let deter = 0;
|
|
37539
|
+
let result = null;
|
|
37540
|
+
const findIndex = (datas) => {
|
|
37541
|
+
for (let i = 0; i < datas.length; i++) {
|
|
37542
|
+
if (deter === index) {
|
|
37543
|
+
switch (action) {
|
|
37544
|
+
case 'find':
|
|
37545
|
+
result = datas[i];
|
|
37546
|
+
break;
|
|
37547
|
+
case 'delete':
|
|
37548
|
+
result = datas.splice(i, 1)[0];
|
|
37549
|
+
break;
|
|
37550
|
+
}
|
|
37413
37551
|
return true;
|
|
37414
37552
|
}
|
|
37415
|
-
|
|
37416
|
-
|
|
37417
|
-
|
|
37553
|
+
deter++;
|
|
37554
|
+
const children = datas[i][this.$options.childField];
|
|
37555
|
+
if (Array.isArray(children) && children.length) {
|
|
37556
|
+
if (findIndex(children))
|
|
37557
|
+
return true;
|
|
37418
37558
|
}
|
|
37419
|
-
|
|
37420
|
-
|
|
37559
|
+
}
|
|
37560
|
+
return false;
|
|
37421
37561
|
};
|
|
37422
|
-
findIndex(this.$options.data
|
|
37423
|
-
return
|
|
37562
|
+
findIndex(this.$options.data);
|
|
37563
|
+
return result;
|
|
37424
37564
|
},
|
|
37425
37565
|
getChecked: () => {
|
|
37426
37566
|
return findAll('.is-rowChecker', this.$el)
|
|
@@ -37507,11 +37647,13 @@ class DataGrid extends GNCoreInstance {
|
|
|
37507
37647
|
hasOrder: false,
|
|
37508
37648
|
hasDelete: false,
|
|
37509
37649
|
isEllipsis: false,
|
|
37650
|
+
hasHeader: true,
|
|
37510
37651
|
data: [],
|
|
37511
37652
|
textSets: {
|
|
37512
37653
|
noData: 'No records available.',
|
|
37513
37654
|
orderLabel: '',
|
|
37514
|
-
deleteLabel: ''
|
|
37655
|
+
deleteLabel: '',
|
|
37656
|
+
deleteConfirmMessage: ''
|
|
37515
37657
|
},
|
|
37516
37658
|
childField: 'child',
|
|
37517
37659
|
checkCapturing: true,
|
|
@@ -37529,7 +37671,8 @@ class DataGrid extends GNCoreInstance {
|
|
|
37529
37671
|
onCheck: true,
|
|
37530
37672
|
onDoubleClick: true,
|
|
37531
37673
|
onChange: true,
|
|
37532
|
-
onDragEnd: true
|
|
37674
|
+
onDragEnd: true,
|
|
37675
|
+
onDelete: true
|
|
37533
37676
|
};
|
|
37534
37677
|
this.methods = {
|
|
37535
37678
|
reRender(options) {
|
|
@@ -37589,18 +37732,21 @@ class DataGrid extends GNCoreInstance {
|
|
|
37589
37732
|
this.$selector = this.$selector;
|
|
37590
37733
|
this.$init(this, options);
|
|
37591
37734
|
}
|
|
37592
|
-
_setColumnsTemplate() {
|
|
37735
|
+
_setColumnsTemplate(isReset = false) {
|
|
37593
37736
|
// header cell의 각 넓이를 배열로 가져온다
|
|
37594
37737
|
// ! 모든 컬럼의 넓이가 지정된 경우 이동(btnOrder), 삭제(btnDelete) 컬럼을 제외한 마지막 컬럼은 1fr로 고정
|
|
37595
37738
|
const _isfixedAllWidth = this.$options.headers.every((header) => { var _a; return ((_a = header.style) === null || _a === void 0 ? void 0 : _a.width) !== undefined; });
|
|
37596
37739
|
const _fixedTemplateColumn = this.$options.headers.findLast((header) => !this._isSystemAddedColumn(header.key) && !header.isHidden);
|
|
37740
|
+
// 헤더 DOM이 없거나 모든 일반 컬럼이 숨겨진 경우에도 안전하게 비교할 수 있도록 key만 옵셔널하게 캐싱한다
|
|
37741
|
+
const _fixedTemplateKey = _fixedTemplateColumn === null || _fixedTemplateColumn === void 0 ? void 0 : _fixedTemplateColumn.key;
|
|
37597
37742
|
const columns = findAll('.gn-datagrid-header-cell', this.$el);
|
|
37598
|
-
|
|
37743
|
+
// isReset이면 기존 DOM 폭을 재사용하지 않고 헤더 정의로 재계산
|
|
37744
|
+
if (this.$el && columns.length && !isReset) {
|
|
37599
37745
|
this._columnsTemplate = findAll('.gn-datagrid-header-cell', this.$el).map((header, idx) => {
|
|
37600
37746
|
if (this.$options.headers[idx].isHidden) {
|
|
37601
37747
|
return '';
|
|
37602
37748
|
}
|
|
37603
|
-
else if (_isfixedAllWidth && this.$options.headers[idx].key ===
|
|
37749
|
+
else if (_isfixedAllWidth && _fixedTemplateKey && this.$options.headers[idx].key === _fixedTemplateKey) {
|
|
37604
37750
|
return '1fr';
|
|
37605
37751
|
}
|
|
37606
37752
|
else {
|
|
@@ -37614,7 +37760,7 @@ class DataGrid extends GNCoreInstance {
|
|
|
37614
37760
|
if (header.isHidden) {
|
|
37615
37761
|
return '';
|
|
37616
37762
|
}
|
|
37617
|
-
else if (_isfixedAllWidth && header.key ===
|
|
37763
|
+
else if (_isfixedAllWidth && _fixedTemplateKey && header.key === _fixedTemplateKey) {
|
|
37618
37764
|
return '1fr';
|
|
37619
37765
|
}
|
|
37620
37766
|
else {
|
|
@@ -37635,18 +37781,45 @@ class DataGrid extends GNCoreInstance {
|
|
|
37635
37781
|
_isSystemAddedColumn(key) {
|
|
37636
37782
|
return ['btnOrder', 'btnDelete'].includes(key);
|
|
37637
37783
|
}
|
|
37784
|
+
// 옵션에 따른 추가 해더 구성
|
|
37785
|
+
_prepareHeaders(headers = []) {
|
|
37786
|
+
const hasOrderColumn = headers.some((header) => header.key === 'btnOrder');
|
|
37787
|
+
const hasDeleteColumn = headers.some((header) => header.key === 'btnDelete');
|
|
37788
|
+
if (this.$options.hasOrder && !this.$options.readonly && !hasOrderColumn) {
|
|
37789
|
+
headers.push({
|
|
37790
|
+
label: this.$options.textSets.orderLabel,
|
|
37791
|
+
key: 'btnOrder',
|
|
37792
|
+
style: {
|
|
37793
|
+
width: '50px'
|
|
37794
|
+
}
|
|
37795
|
+
});
|
|
37796
|
+
}
|
|
37797
|
+
if (this.$options.hasDelete && !this.$options.readonly && !hasDeleteColumn) {
|
|
37798
|
+
headers.push({
|
|
37799
|
+
label: this.$options.textSets.deleteLabel,
|
|
37800
|
+
key: 'btnDelete',
|
|
37801
|
+
style: {
|
|
37802
|
+
width: '30px'
|
|
37803
|
+
}
|
|
37804
|
+
});
|
|
37805
|
+
}
|
|
37806
|
+
this.$options.headers = headers;
|
|
37807
|
+
return headers;
|
|
37808
|
+
}
|
|
37638
37809
|
template(config) {
|
|
37639
37810
|
const styles = {};
|
|
37811
|
+
const headers = this._prepareHeaders(config.headers);
|
|
37640
37812
|
return (createElement$1("div", { id: this._uid, className: 'gn-datagrid' +
|
|
37641
37813
|
(config.style ? ' is-' + config.style : '') +
|
|
37642
37814
|
(config.isEllipsis ? ' is-ellipsis' : '') +
|
|
37643
37815
|
(config.bodyHeight ? ' has-fixed-body' : '') +
|
|
37644
37816
|
(config.fixHeader ? ' has-fixed-header' : '') +
|
|
37645
37817
|
(config.fixFooter ? ' has-fixed-footer' : '') +
|
|
37818
|
+
(!config.hasHeader ? ' is-headless' : '') +
|
|
37646
37819
|
(config.data.some((d) => isArray$1(d[this.$options.childField])) ? ' has-left-padding' : '') +
|
|
37647
37820
|
(config.disabled ? ' is-disabled' : ''), style: styles },
|
|
37648
|
-
createElement$1("div", { className: "gn-datagrid-header" }, this._hidden.renderHeader(
|
|
37649
|
-
createElement$1("div", { className: "gn-datagrid-contents", style: { marginTop: this.$options.bodyTopMargin ? this.$options.bodyTopMargin : '0', marginBottom: this.$options.bodyBottomMargin ? this.$options.bodyBottomMargin : '0' } }, this._hidden.renderBody(arrClone(config.data),
|
|
37821
|
+
config.hasHeader && createElement$1("div", { className: "gn-datagrid-header" }, this._hidden.renderHeader(headers)),
|
|
37822
|
+
createElement$1("div", { className: "gn-datagrid-contents", style: { marginTop: this.$options.bodyTopMargin ? this.$options.bodyTopMargin : '0', marginBottom: this.$options.bodyBottomMargin ? this.$options.bodyBottomMargin : '0' } }, this._hidden.renderBody(arrClone(config.data), headers)),
|
|
37650
37823
|
config.paginator /* 페이지네이터 옵션 확인 */ && createElement$1("div", { className: "gn-datagrid-footer" })));
|
|
37651
37824
|
}
|
|
37652
37825
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -37663,18 +37836,20 @@ class DataGrid extends GNCoreInstance {
|
|
|
37663
37836
|
}
|
|
37664
37837
|
}
|
|
37665
37838
|
completed() {
|
|
37666
|
-
if (this.$options.fixHeader) {
|
|
37839
|
+
if (this.$options.fixHeader && this.$options.hasHeader) {
|
|
37667
37840
|
const body = find('.gn-datagrid-contents', this.$el);
|
|
37668
37841
|
const header = find('.gn-datagrid-header', this.$el);
|
|
37669
|
-
|
|
37670
|
-
|
|
37671
|
-
|
|
37842
|
+
if (header) {
|
|
37843
|
+
const _offset = offset(header);
|
|
37844
|
+
this.$options.bodyTopMargin = _offset.height ? _offset.height - 1 + 'px' : '2.4rem';
|
|
37845
|
+
css$1(body, 'margin-top', this.$options.bodyTopMargin);
|
|
37846
|
+
}
|
|
37672
37847
|
if (this.$options.paginator) {
|
|
37673
37848
|
this.$options.bodyBottomMargin = '2.4rem';
|
|
37674
37849
|
css$1(body, 'margin-bottom', this.$options.bodyBottomMargin);
|
|
37675
37850
|
}
|
|
37676
37851
|
}
|
|
37677
|
-
if (this.$options.fixHeader || this.$options.bodyHeight) {
|
|
37852
|
+
if ((this.$options.fixHeader && this.$options.hasHeader) || this.$options.bodyHeight) {
|
|
37678
37853
|
this._hidden.setBlankHeader();
|
|
37679
37854
|
on(window, 'resize', this._hidden.setBlankHeader);
|
|
37680
37855
|
}
|
|
@@ -39019,7 +39194,9 @@ class MenuButton extends GNCoreInstance {
|
|
|
39019
39194
|
super(name, selector, options);
|
|
39020
39195
|
this._hidden = {
|
|
39021
39196
|
open: () => {
|
|
39022
|
-
|
|
39197
|
+
if (!this.$options.disabled) {
|
|
39198
|
+
addClass(this.$el, 'is-open');
|
|
39199
|
+
}
|
|
39023
39200
|
},
|
|
39024
39201
|
close: () => {
|
|
39025
39202
|
removeClass(this.$el, 'is-open');
|
|
@@ -39031,6 +39208,62 @@ class MenuButton extends GNCoreInstance {
|
|
|
39031
39208
|
changeText: (buttonText) => {
|
|
39032
39209
|
this.$options.textSets.buttonText = buttonText;
|
|
39033
39210
|
html(find('.menuButton-text', this.$el), buttonText);
|
|
39211
|
+
},
|
|
39212
|
+
disable: () => {
|
|
39213
|
+
this.$options.disabled = true;
|
|
39214
|
+
const buttonEl = find('button', this.$el);
|
|
39215
|
+
if (buttonEl) {
|
|
39216
|
+
attr(buttonEl, 'disabled', true);
|
|
39217
|
+
}
|
|
39218
|
+
addClass(this.$el, 'is-disabled');
|
|
39219
|
+
this._hidden.close();
|
|
39220
|
+
},
|
|
39221
|
+
enable: () => {
|
|
39222
|
+
this.$options.disabled = false;
|
|
39223
|
+
const buttonEl = find('button', this.$el);
|
|
39224
|
+
if (buttonEl) {
|
|
39225
|
+
removeAttr(buttonEl, 'disabled');
|
|
39226
|
+
}
|
|
39227
|
+
removeClass(this.$el, 'is-disabled');
|
|
39228
|
+
},
|
|
39229
|
+
renderMenus: (menus, depth = 0, parentPath = '') => {
|
|
39230
|
+
return (createElement$1("ul", { className: depth > 0 ? 'menuButton-submenu' : '' }, menus.map((menu, index) => {
|
|
39231
|
+
const hasChild = menu.child && isArray$1(menu.child) && menu.child.length > 0;
|
|
39232
|
+
const hasHtml = !!menu.html;
|
|
39233
|
+
// html이 있으면 innerHTML이 모든 자식 요소를 덮어쓰므로 서브메뉴를 렌더링하지 않음
|
|
39234
|
+
const canRenderChild = hasChild && depth < 2 && !hasHtml; // 최대 2단계까지만 허용
|
|
39235
|
+
const isDisabled = menu.disabled === true;
|
|
39236
|
+
const isActived = menu.actived === true;
|
|
39237
|
+
// 부모 경로를 포함한 고유한 ID 생성
|
|
39238
|
+
const currentPath = parentPath ? `${parentPath}-${index}` : `${index}`;
|
|
39239
|
+
const uniqueId = `${this._uid}-${currentPath}`;
|
|
39240
|
+
return (createElement$1("li", { id: uniqueId, className: 'menuButton-menu' +
|
|
39241
|
+
(this.$options.align ? ' has-text-' + this.$options.align : '') +
|
|
39242
|
+
(canRenderChild ? ' has-submenu' : '') +
|
|
39243
|
+
(depth > 0 ? ' is-submenu-item' : '') +
|
|
39244
|
+
(isDisabled ? ' is-disabled' : '') +
|
|
39245
|
+
(isActived ? ' is-actived' : ''), "on-click": (e) => {
|
|
39246
|
+
// disabled 상태이거나 자식 메뉴가 있는 경우 클릭 이벤트 처리하지 않음
|
|
39247
|
+
if (isDisabled) {
|
|
39248
|
+
e.stopPropagation();
|
|
39249
|
+
e.preventDefault();
|
|
39250
|
+
return;
|
|
39251
|
+
}
|
|
39252
|
+
// 자식 메뉴가 없는 경우에만 select 이벤트 발생
|
|
39253
|
+
if (!canRenderChild) {
|
|
39254
|
+
e.stopPropagation();
|
|
39255
|
+
this._hidden.select.call(this, menu, e);
|
|
39256
|
+
}
|
|
39257
|
+
}, innerHTML: hasHtml ? menu.html : '' },
|
|
39258
|
+
hasHtml ? ('') : (createElement$1("span", { className: "menuButton-menu-content" },
|
|
39259
|
+
createElement$1("span", { className: "menuButton-menu-text" }, menu.text),
|
|
39260
|
+
canRenderChild && (createElement$1("span", { className: "menuButton-menu-arrow" },
|
|
39261
|
+
createElement$1("i", { className: "fas fa-caret-right" }))))),
|
|
39262
|
+
canRenderChild && this._hidden.renderMenus.call(this, menu.child, depth + 1, currentPath)));
|
|
39263
|
+
})));
|
|
39264
|
+
},
|
|
39265
|
+
renderSub: (data) => {
|
|
39266
|
+
return createElement$1("div", null, isArray$1(data) && data.length && isArray$1(data[0]) ? data.map((menus) => this._hidden.renderMenus.call(this, menus)) : this._hidden.renderMenus.call(this, data));
|
|
39034
39267
|
}
|
|
39035
39268
|
};
|
|
39036
39269
|
this.config = {
|
|
@@ -39050,6 +39283,19 @@ class MenuButton extends GNCoreInstance {
|
|
|
39050
39283
|
},
|
|
39051
39284
|
buttonText(text) {
|
|
39052
39285
|
this._hidden.changeText(text);
|
|
39286
|
+
},
|
|
39287
|
+
reRender(data) {
|
|
39288
|
+
this.$options.data = data;
|
|
39289
|
+
const menuMenusEl = find('.menuButton-menus > div', this.$el);
|
|
39290
|
+
if (menuMenusEl && this.$template) {
|
|
39291
|
+
this.$template.reRender(menuMenusEl, this._hidden.renderSub.call(this, data));
|
|
39292
|
+
}
|
|
39293
|
+
},
|
|
39294
|
+
disabled() {
|
|
39295
|
+
this._hidden.disable();
|
|
39296
|
+
},
|
|
39297
|
+
enabled() {
|
|
39298
|
+
this._hidden.enable();
|
|
39053
39299
|
}
|
|
39054
39300
|
};
|
|
39055
39301
|
this.$selector = this.$selector;
|
|
@@ -39060,23 +39306,19 @@ class MenuButton extends GNCoreInstance {
|
|
|
39060
39306
|
if (config.width) {
|
|
39061
39307
|
styles.width = getUnit('width', config.width);
|
|
39062
39308
|
}
|
|
39063
|
-
|
|
39064
|
-
|
|
39065
|
-
|
|
39066
|
-
|
|
39067
|
-
|
|
39068
|
-
|
|
39069
|
-
return createElement$1("div", null, isArray$1(data) && data.length && isArray$1(data[0]) ? data.map((menus) => renderMenus(menus)) : renderMenus(data));
|
|
39070
|
-
};
|
|
39071
|
-
return (createElement$1("div", { id: this._uid, className: 'gn-menuButton' + (config.color ? ' is-' + config.color : '') + (config.style ? ' is-' + config.style : '') + (config.size ? ' is-' + config.size : ''), style: styles },
|
|
39072
|
-
createElement$1("button", { type: "button", className: config.align ? 'has-text-' + config.align : '', "on-click": this._hidden.open },
|
|
39309
|
+
return (createElement$1("div", { id: this._uid, className: 'gn-menuButton' +
|
|
39310
|
+
(config.color ? ' is-' + config.color : '') +
|
|
39311
|
+
(config.style ? ' is-' + config.style : '') +
|
|
39312
|
+
(config.size ? ' is-' + config.size : '') +
|
|
39313
|
+
(config.disabled ? ' is-disabled' : ''), style: styles },
|
|
39314
|
+
createElement$1("button", { type: "button", className: config.align ? 'has-text-' + config.align : '', disabled: config.disabled, "on-click": this._hidden.open },
|
|
39073
39315
|
config.icon && (createElement$1("span", { className: 'gn-icon is-' + (config.size === 'large' ? 'medium' : config.size === 'medium' ? 'normal' : 'small') },
|
|
39074
39316
|
createElement$1("i", { className: 'fas fa-' + config.icon }),
|
|
39075
39317
|
' ')),
|
|
39076
39318
|
createElement$1("span", { className: "gn-icon is-small menuButton-icon" },
|
|
39077
39319
|
createElement$1("i", { className: "fas fa-caret-down" })),
|
|
39078
39320
|
createElement$1("span", { className: "menuButton-text" }, config.textSets.buttonText)),
|
|
39079
|
-
createElement$1("div", { className: "menuButton-menus" }, renderSub(config.data))));
|
|
39321
|
+
createElement$1("div", { className: "menuButton-menus" }, this._hidden.renderSub.call(this, config.data))));
|
|
39080
39322
|
}
|
|
39081
39323
|
completed() {
|
|
39082
39324
|
// 해당 컴포넌트 외 클릭 시 menu panel 숨김
|
|
@@ -39287,6 +39529,7 @@ class MultiTextArea extends GNCoreInstance {
|
|
|
39287
39529
|
}
|
|
39288
39530
|
}
|
|
39289
39531
|
|
|
39532
|
+
library$1.add(icons$1, icons);
|
|
39290
39533
|
class Picklist extends GNCoreInstance {
|
|
39291
39534
|
constructor(name, selector, options = {}) {
|
|
39292
39535
|
super(name, selector, options);
|
|
@@ -39428,17 +39671,26 @@ class Picklist extends GNCoreInstance {
|
|
|
39428
39671
|
},
|
|
39429
39672
|
renderSub: (item) => {
|
|
39430
39673
|
const items = this.$options.data[item] || [];
|
|
39431
|
-
return (createElement$1("ul", null, items.map((option, index) =>
|
|
39432
|
-
|
|
39433
|
-
|
|
39434
|
-
|
|
39435
|
-
|
|
39436
|
-
|
|
39437
|
-
|
|
39674
|
+
return (createElement$1("ul", null, items.map((option, index) => {
|
|
39675
|
+
var _a;
|
|
39676
|
+
return (createElement$1("li", { id: this._uid + '_opt_' + index, className: 'dropdown-item' + (option.selected ? ' is-active' : ''), "data-value": option.value, "on-click": !option.text ? null : this._hidden.toggle.bind(this), "on-dblclick": !option.text
|
|
39677
|
+
? null
|
|
39678
|
+
: this._hidden.move.bind(this, item === 'source' ? 'add' : 'remove', [
|
|
39679
|
+
{
|
|
39680
|
+
value: option.value,
|
|
39681
|
+
text: option.text,
|
|
39682
|
+
html: (_a = option.html) !== null && _a !== void 0 ? _a : null
|
|
39683
|
+
}
|
|
39684
|
+
]) },
|
|
39685
|
+
createElement$1("span", { className: "dropdown-text", innerHTML: option.html ? option.html : '' }, option.html ? ('') : option.icon ? (createElement$1("span", null,
|
|
39686
|
+
createElement$1("span", { className: 'gn-icon' + (this.$options.size ? ' is-' + this.$options.size : '') },
|
|
39687
|
+
createElement$1("i", { className: (this.isBrandIcon(option.icon) ? 'fab' : 'fa') + ` fa-${option.icon}` })),
|
|
39688
|
+
escapeEntity(option.text))) : (escapeEntity(option.text)))));
|
|
39689
|
+
})));
|
|
39438
39690
|
},
|
|
39439
39691
|
getSelection: (target) => {
|
|
39440
39692
|
return findAll('.is-active', this.$options.delegates[target]).map((select) => {
|
|
39441
|
-
return
|
|
39693
|
+
return this.$options.data[target].find((option) => option.value === attr(select, 'data-value'));
|
|
39442
39694
|
});
|
|
39443
39695
|
},
|
|
39444
39696
|
disable: () => {
|
|
@@ -39598,6 +39850,11 @@ class Picklist extends GNCoreInstance {
|
|
|
39598
39850
|
style(find('.picklist-target .dropdown-items', this.$el), 'height', getUnit('height', getNumber(this.$options.height) - getNumber(style(find('.picklist-target .picklist-caption', this.$el), 'height'))));
|
|
39599
39851
|
}
|
|
39600
39852
|
}
|
|
39853
|
+
isBrandIcon(iconName) {
|
|
39854
|
+
const iconLookup = { prefix: 'fab', iconName: iconName };
|
|
39855
|
+
const iconDefinition = findIconDefinition$1(iconLookup);
|
|
39856
|
+
return iconDefinition !== undefined;
|
|
39857
|
+
}
|
|
39601
39858
|
}
|
|
39602
39859
|
|
|
39603
39860
|
class Progressbar extends GNCoreInstance {
|
|
@@ -39756,6 +40013,409 @@ class SelectButton extends GNCoreInstance {
|
|
|
39756
40013
|
}
|
|
39757
40014
|
}
|
|
39758
40015
|
|
|
40016
|
+
const CLASS_DRAGGING = 'is-dragging';
|
|
40017
|
+
const CLASS_GROUP_DRAGGING = 'is-group-dragging';
|
|
40018
|
+
const CLASS_DRAG_OVER_TOP = 'is-drag-over-top';
|
|
40019
|
+
const CLASS_DRAG_OVER_BOTTOM = 'is-drag-over-bottom';
|
|
40020
|
+
const DEFAULT_NO_DATA = 'No records available.';
|
|
40021
|
+
const DRAG_STATE_CLASSES = [CLASS_DRAGGING, CLASS_GROUP_DRAGGING, CLASS_DRAG_OVER_TOP, CLASS_DRAG_OVER_BOTTOM];
|
|
40022
|
+
class SortableList extends GNCoreInstance {
|
|
40023
|
+
constructor(name, selector, options = {}) {
|
|
40024
|
+
super(name, selector, options);
|
|
40025
|
+
this._dragging = null;
|
|
40026
|
+
this._selection = new Set();
|
|
40027
|
+
this.DRAG_IMAGE_OFFSET_X = 0;
|
|
40028
|
+
this.DRAG_IMAGE_OFFSET_Y = 0;
|
|
40029
|
+
this.DRAG_OVER_THRESHOLD_RATIO = 0.5;
|
|
40030
|
+
this._hidden = {
|
|
40031
|
+
toggle: (e) => {
|
|
40032
|
+
if (this.$options.disabled) {
|
|
40033
|
+
return;
|
|
40034
|
+
}
|
|
40035
|
+
const value = attr(e.currentTarget, 'data-value');
|
|
40036
|
+
const hasItem = this.$options.data.some((option) => option.value === value);
|
|
40037
|
+
if (!value || !hasItem) {
|
|
40038
|
+
return;
|
|
40039
|
+
}
|
|
40040
|
+
if (this._selection.has(value)) {
|
|
40041
|
+
this._selection.delete(value);
|
|
40042
|
+
removeClass(e.currentTarget, 'is-active');
|
|
40043
|
+
}
|
|
40044
|
+
else {
|
|
40045
|
+
this._selection.add(value);
|
|
40046
|
+
addClass(e.currentTarget, 'is-active');
|
|
40047
|
+
}
|
|
40048
|
+
},
|
|
40049
|
+
sort: (dir) => {
|
|
40050
|
+
const items = this.$options.data || [];
|
|
40051
|
+
const selected = this._hidden.getSelection();
|
|
40052
|
+
if (!selected.length || selected.length === items.length) {
|
|
40053
|
+
return;
|
|
40054
|
+
}
|
|
40055
|
+
const selectedValues = new Set(selected.map((item) => item.value));
|
|
40056
|
+
// dir: up/down → 이동, up-all/down-all → 맨 위/맨 아래로 보내기
|
|
40057
|
+
if (dir.indexOf('all') > -1) {
|
|
40058
|
+
this.$options.data = items.slice().sort((a, b) => {
|
|
40059
|
+
const _sort = dir === 'up-all' ? -1 : 1;
|
|
40060
|
+
const aSel = selectedValues.has(a.value);
|
|
40061
|
+
const bSel = selectedValues.has(b.value);
|
|
40062
|
+
if (aSel && bSel) {
|
|
40063
|
+
return 0;
|
|
40064
|
+
}
|
|
40065
|
+
else if (aSel) {
|
|
40066
|
+
return _sort;
|
|
40067
|
+
}
|
|
40068
|
+
else if (bSel) {
|
|
40069
|
+
return _sort * -1;
|
|
40070
|
+
}
|
|
40071
|
+
return 0;
|
|
40072
|
+
});
|
|
40073
|
+
}
|
|
40074
|
+
else {
|
|
40075
|
+
if (dir === 'up') {
|
|
40076
|
+
const reordered = items.slice();
|
|
40077
|
+
// 한 번에 한 칸씩만 올려 상대 순서를 유지한다
|
|
40078
|
+
for (let i = 1; i < reordered.length; i++) {
|
|
40079
|
+
if (!selectedValues.has(reordered[i].value) || selectedValues.has(reordered[i - 1].value)) {
|
|
40080
|
+
continue;
|
|
40081
|
+
}
|
|
40082
|
+
const temp = reordered[i - 1];
|
|
40083
|
+
reordered[i - 1] = reordered[i];
|
|
40084
|
+
reordered[i] = temp;
|
|
40085
|
+
}
|
|
40086
|
+
this.$options.data = reordered;
|
|
40087
|
+
}
|
|
40088
|
+
else {
|
|
40089
|
+
let reordered = [];
|
|
40090
|
+
let itemsToMoveDown = [];
|
|
40091
|
+
items.forEach((option) => {
|
|
40092
|
+
// reordered: 최종 순서를 쌓는 버퍼, itemsToMoveDown: 아래로 밀어야 할 선택 항목 임시 저장
|
|
40093
|
+
// 비선택 항목은 흐름대로 push, 선택 항목은 dir에 따라 위/아래로 밀어 넣음
|
|
40094
|
+
if (!selectedValues.has(option.value)) {
|
|
40095
|
+
reordered.push(option);
|
|
40096
|
+
if (itemsToMoveDown.length) {
|
|
40097
|
+
reordered = reordered.concat(itemsToMoveDown);
|
|
40098
|
+
itemsToMoveDown = [];
|
|
40099
|
+
}
|
|
40100
|
+
}
|
|
40101
|
+
else if (dir === 'down') {
|
|
40102
|
+
itemsToMoveDown.push(option);
|
|
40103
|
+
}
|
|
40104
|
+
});
|
|
40105
|
+
if (itemsToMoveDown.length) {
|
|
40106
|
+
reordered = reordered.concat(itemsToMoveDown);
|
|
40107
|
+
itemsToMoveDown = [];
|
|
40108
|
+
}
|
|
40109
|
+
this.$options.data = reordered.slice();
|
|
40110
|
+
}
|
|
40111
|
+
}
|
|
40112
|
+
this._hidden.reRender();
|
|
40113
|
+
this._hidden.updateControls();
|
|
40114
|
+
this.$event(this, 'onChange', this.$options.data);
|
|
40115
|
+
},
|
|
40116
|
+
renderSub: () => {
|
|
40117
|
+
var _a, _b;
|
|
40118
|
+
const items = this.$options.data || [];
|
|
40119
|
+
const hasCols = items.some((item) => isArray$1(item.cols) && item.cols.length);
|
|
40120
|
+
if (!items.length) {
|
|
40121
|
+
return (createElement$1("ul", { className: "sortablelist-rows" },
|
|
40122
|
+
createElement$1("li", { className: "dropdown-item is-empty" }, (_b = (_a = this.$options.textSets) === null || _a === void 0 ? void 0 : _a.noData) !== null && _b !== void 0 ? _b : DEFAULT_NO_DATA)));
|
|
40123
|
+
}
|
|
40124
|
+
return (createElement$1("ul", { className: 'sortablelist-rows' + (hasCols ? ' is-cols' : '') }, items.map((option, index) => {
|
|
40125
|
+
var _a;
|
|
40126
|
+
return (createElement$1("li", { id: this._uid + '_opt_' + index, className: 'dropdown-item' + (this._selection.has(option.value) ? ' is-active' : ''), "data-value": option.value, draggable: this.$options.draggable && !this.$options.disabled ? true : null, "on-click": this._hidden.toggle.bind(this), "on-dragstart": this.$options.draggable ? this._hidden.dragStart.bind(this) : null, "on-dragover": this.$options.draggable ? this._hidden.dragOver.bind(this) : null, "on-dragleave": this.$options.draggable ? this._hidden.dragLeave.bind(this) : null, "on-drop": this.$options.draggable ? this._hidden.drop.bind(this) : null, "on-dragend": this.$options.draggable ? this._hidden.dragEnd.bind(this) : null }, hasCols && isArray$1(option.cols) && option.cols.length ? (createElement$1("div", { className: "sortablelist-cols" }, option.cols.map((col, colIndex) => (createElement$1("span", { className: "sortablelist-col", "data-col": colIndex }, escapeEntity(col)))))) : (createElement$1("span", { className: "dropdown-text" }, escapeEntity((_a = option.text) !== null && _a !== void 0 ? _a : option.value)))));
|
|
40127
|
+
})));
|
|
40128
|
+
},
|
|
40129
|
+
getSelection: () => {
|
|
40130
|
+
return this.$options.data.filter((option) => this._selection.has(option.value));
|
|
40131
|
+
},
|
|
40132
|
+
reRender: () => {
|
|
40133
|
+
const listContainer = find('ul', this.$options.delegates.list);
|
|
40134
|
+
listContainer && this.$template.reRender(listContainer, this._hidden.renderSub());
|
|
40135
|
+
},
|
|
40136
|
+
syncSelection: () => {
|
|
40137
|
+
const values = new Set(this.$options.data.map((item) => item.value));
|
|
40138
|
+
this._selection.forEach(val => {
|
|
40139
|
+
if (!values.has(val)) {
|
|
40140
|
+
this._selection.delete(val);
|
|
40141
|
+
}
|
|
40142
|
+
});
|
|
40143
|
+
},
|
|
40144
|
+
hydrateSelection: (items) => {
|
|
40145
|
+
this._selection.clear();
|
|
40146
|
+
items.forEach((item) => {
|
|
40147
|
+
if (item.selected) {
|
|
40148
|
+
this._selection.add(item.value);
|
|
40149
|
+
}
|
|
40150
|
+
});
|
|
40151
|
+
},
|
|
40152
|
+
validateData: (items) => {
|
|
40153
|
+
if (!isArray$1(items)) {
|
|
40154
|
+
throw new TypeError('Invalid SortableList data: data must be an array');
|
|
40155
|
+
}
|
|
40156
|
+
const seen = new Set();
|
|
40157
|
+
items.forEach((item) => {
|
|
40158
|
+
if (!item || typeof item.value !== 'string') {
|
|
40159
|
+
throw new TypeError('Invalid SortableList data: value must be string');
|
|
40160
|
+
}
|
|
40161
|
+
if (item.value === '') {
|
|
40162
|
+
throw new TypeError('Invalid SortableList data: value cannot be empty');
|
|
40163
|
+
}
|
|
40164
|
+
if (seen.has(item.value)) {
|
|
40165
|
+
throw new TypeError(`Invalid SortableList data: duplicate value '${item.value}'`);
|
|
40166
|
+
}
|
|
40167
|
+
seen.add(item.value);
|
|
40168
|
+
});
|
|
40169
|
+
},
|
|
40170
|
+
updateControls: () => {
|
|
40171
|
+
const hasData = (this.$options.data || []).length > 0;
|
|
40172
|
+
const disableButtons = this.$options.disabled || !hasData;
|
|
40173
|
+
if (disableButtons) {
|
|
40174
|
+
attr(findAll('button', this.$el), 'disabled', true);
|
|
40175
|
+
}
|
|
40176
|
+
else {
|
|
40177
|
+
removeAttr(findAll('button', this.$el), 'disabled');
|
|
40178
|
+
}
|
|
40179
|
+
if (!hasData) {
|
|
40180
|
+
addClass(this.$el, 'is-empty');
|
|
40181
|
+
}
|
|
40182
|
+
else {
|
|
40183
|
+
removeClass(this.$el, 'is-empty');
|
|
40184
|
+
}
|
|
40185
|
+
},
|
|
40186
|
+
clearDragState: () => {
|
|
40187
|
+
var _a;
|
|
40188
|
+
DRAG_STATE_CLASSES.forEach(className => {
|
|
40189
|
+
removeClass(findAll(`.${className}`, this.$el), className);
|
|
40190
|
+
});
|
|
40191
|
+
if ((_a = this._dragging) === null || _a === void 0 ? void 0 : _a.preview) {
|
|
40192
|
+
this._dragging.preview.remove();
|
|
40193
|
+
}
|
|
40194
|
+
this._dragging = null;
|
|
40195
|
+
},
|
|
40196
|
+
dragStart: (e) => {
|
|
40197
|
+
if (this.$options.disabled || !this.$options.draggable) {
|
|
40198
|
+
return;
|
|
40199
|
+
}
|
|
40200
|
+
// 기존 드래그 상태 정리 (이전 드래그가 중단된 경우 대비)
|
|
40201
|
+
this._hidden.clearDragState();
|
|
40202
|
+
const value = attr(e.currentTarget, 'data-value');
|
|
40203
|
+
if (!value) {
|
|
40204
|
+
return;
|
|
40205
|
+
}
|
|
40206
|
+
const selected = this._hidden.getSelection().map((item) => item.value);
|
|
40207
|
+
const isGroup = selected.length > 1 && selected.includes(value);
|
|
40208
|
+
const dragValues = isGroup ? selected : [value];
|
|
40209
|
+
this._dragging = { values: dragValues, isGroup: isGroup, preview: null };
|
|
40210
|
+
if (e.dataTransfer) {
|
|
40211
|
+
e.dataTransfer.setData('text/plain', value);
|
|
40212
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
40213
|
+
if (isGroup) {
|
|
40214
|
+
const preview = document.createElement('div');
|
|
40215
|
+
preview.className = 'sortablelist-drag-preview';
|
|
40216
|
+
preview.setAttribute('data-count', String(dragValues.length));
|
|
40217
|
+
const list = document.createElement('div');
|
|
40218
|
+
list.className = 'sortablelist-drag-preview-list';
|
|
40219
|
+
dragValues.forEach((dragValue) => {
|
|
40220
|
+
const itemEl = find(`[data-value="${CSS.escape(dragValue)}"]`, this.$options.delegates.list);
|
|
40221
|
+
if (!(itemEl instanceof HTMLElement)) {
|
|
40222
|
+
return;
|
|
40223
|
+
}
|
|
40224
|
+
const clone = itemEl.cloneNode(true);
|
|
40225
|
+
removeClass(clone, CLASS_DRAGGING);
|
|
40226
|
+
removeClass(clone, CLASS_GROUP_DRAGGING);
|
|
40227
|
+
removeClass(clone, CLASS_DRAG_OVER_TOP);
|
|
40228
|
+
removeClass(clone, CLASS_DRAG_OVER_BOTTOM);
|
|
40229
|
+
addClass(clone, 'is-ghost');
|
|
40230
|
+
list.appendChild(clone);
|
|
40231
|
+
});
|
|
40232
|
+
preview.appendChild(list);
|
|
40233
|
+
document.body.appendChild(preview);
|
|
40234
|
+
e.dataTransfer.setDragImage(preview, this.DRAG_IMAGE_OFFSET_X, this.DRAG_IMAGE_OFFSET_Y);
|
|
40235
|
+
this._dragging.preview = preview;
|
|
40236
|
+
}
|
|
40237
|
+
}
|
|
40238
|
+
findAll('.dropdown-item', this.$options.delegates.list).forEach((node) => {
|
|
40239
|
+
const itemValue = attr(node, 'data-value');
|
|
40240
|
+
if (dragValues.includes(itemValue)) {
|
|
40241
|
+
addClass(node, CLASS_DRAGGING);
|
|
40242
|
+
if (isGroup) {
|
|
40243
|
+
addClass(node, CLASS_GROUP_DRAGGING);
|
|
40244
|
+
}
|
|
40245
|
+
}
|
|
40246
|
+
});
|
|
40247
|
+
},
|
|
40248
|
+
dragOver: (e) => {
|
|
40249
|
+
if (!this._dragging || this.$options.disabled || !this.$options.draggable) {
|
|
40250
|
+
return;
|
|
40251
|
+
}
|
|
40252
|
+
e.preventDefault();
|
|
40253
|
+
if (!(e.currentTarget instanceof HTMLElement)) {
|
|
40254
|
+
return;
|
|
40255
|
+
}
|
|
40256
|
+
const target = e.currentTarget;
|
|
40257
|
+
const value = attr(target, 'data-value');
|
|
40258
|
+
if (this._dragging.values.includes(value)) {
|
|
40259
|
+
return;
|
|
40260
|
+
}
|
|
40261
|
+
removeClass(target, CLASS_DRAG_OVER_TOP);
|
|
40262
|
+
removeClass(target, CLASS_DRAG_OVER_BOTTOM);
|
|
40263
|
+
const rect = target.getBoundingClientRect();
|
|
40264
|
+
const midpoint = rect.top + rect.height * this.DRAG_OVER_THRESHOLD_RATIO;
|
|
40265
|
+
if (e.clientY > midpoint) {
|
|
40266
|
+
addClass(target, CLASS_DRAG_OVER_BOTTOM);
|
|
40267
|
+
}
|
|
40268
|
+
else {
|
|
40269
|
+
addClass(target, CLASS_DRAG_OVER_TOP);
|
|
40270
|
+
}
|
|
40271
|
+
},
|
|
40272
|
+
dragLeave: (e) => {
|
|
40273
|
+
if (e.currentTarget instanceof HTMLElement) {
|
|
40274
|
+
removeClass(e.currentTarget, 'is-drag-over-top');
|
|
40275
|
+
removeClass(e.currentTarget, 'is-drag-over-bottom');
|
|
40276
|
+
}
|
|
40277
|
+
},
|
|
40278
|
+
drop: (e) => {
|
|
40279
|
+
if (!this._dragging || this.$options.disabled || !this.$options.draggable) {
|
|
40280
|
+
return;
|
|
40281
|
+
}
|
|
40282
|
+
e.preventDefault();
|
|
40283
|
+
if (!(e.currentTarget instanceof HTMLElement)) {
|
|
40284
|
+
return;
|
|
40285
|
+
}
|
|
40286
|
+
const targetEl = e.currentTarget;
|
|
40287
|
+
const targetValue = attr(targetEl, 'data-value');
|
|
40288
|
+
const dragValues = this._dragging.values;
|
|
40289
|
+
if (!targetValue || dragValues.includes(targetValue)) {
|
|
40290
|
+
this._hidden.clearDragState();
|
|
40291
|
+
return;
|
|
40292
|
+
}
|
|
40293
|
+
const items = this.$options.data;
|
|
40294
|
+
const dragItems = items.filter((item) => dragValues.includes(item.value));
|
|
40295
|
+
const remain = items.filter((item) => !dragValues.includes(item.value));
|
|
40296
|
+
const targetIndex = remain.findIndex((item) => item.value === targetValue);
|
|
40297
|
+
const rect = targetEl.getBoundingClientRect();
|
|
40298
|
+
const midpoint = rect.top + rect.height * this.DRAG_OVER_THRESHOLD_RATIO;
|
|
40299
|
+
const insertAfter = e.clientY > midpoint;
|
|
40300
|
+
const insertIndex = targetIndex === -1 ? remain.length : insertAfter ? targetIndex + 1 : targetIndex;
|
|
40301
|
+
remain.splice(insertIndex, 0, ...dragItems);
|
|
40302
|
+
this.$options.data = remain;
|
|
40303
|
+
this._hidden.reRender();
|
|
40304
|
+
this._hidden.updateControls();
|
|
40305
|
+
this.$event(this, 'onChange', this.$options.data);
|
|
40306
|
+
this._hidden.clearDragState();
|
|
40307
|
+
},
|
|
40308
|
+
dragEnd: () => {
|
|
40309
|
+
this._hidden.clearDragState();
|
|
40310
|
+
},
|
|
40311
|
+
setData: (data) => {
|
|
40312
|
+
// 드래그 중일 경우 상태 정리 (DOM 요소가 제거되면 dragend 이벤트가 발생하지 않을 수 있음)
|
|
40313
|
+
this._hidden.clearDragState();
|
|
40314
|
+
this._hidden.validateData(data);
|
|
40315
|
+
this.$options.data = data;
|
|
40316
|
+
this._hidden.hydrateSelection(data);
|
|
40317
|
+
this._hidden.syncSelection();
|
|
40318
|
+
this._hidden.reRender();
|
|
40319
|
+
this._hidden.updateControls();
|
|
40320
|
+
this.$event(this, 'onChange', this.$options.data);
|
|
40321
|
+
},
|
|
40322
|
+
disable: () => {
|
|
40323
|
+
// 드래그 중일 경우 상태 정리
|
|
40324
|
+
this._hidden.clearDragState();
|
|
40325
|
+
this.$options.disabled = true;
|
|
40326
|
+
addClass(this.$el, 'is-disabled');
|
|
40327
|
+
this._hidden.reRender();
|
|
40328
|
+
this._hidden.updateControls();
|
|
40329
|
+
},
|
|
40330
|
+
enable: () => {
|
|
40331
|
+
// 드래그 중일 경우 상태 정리
|
|
40332
|
+
this._hidden.clearDragState();
|
|
40333
|
+
this.$options.disabled = false;
|
|
40334
|
+
removeClass(this.$el, 'is-disabled');
|
|
40335
|
+
this._hidden.reRender();
|
|
40336
|
+
this._hidden.updateControls();
|
|
40337
|
+
}
|
|
40338
|
+
};
|
|
40339
|
+
this.config = {
|
|
40340
|
+
name: this.$selector.name || this._uid,
|
|
40341
|
+
data: [],
|
|
40342
|
+
delegates: {
|
|
40343
|
+
list: '.sortablelist-items'
|
|
40344
|
+
},
|
|
40345
|
+
buttonPosition: 'left',
|
|
40346
|
+
draggable: false,
|
|
40347
|
+
textSets: {
|
|
40348
|
+
noData: DEFAULT_NO_DATA
|
|
40349
|
+
},
|
|
40350
|
+
height: 150
|
|
40351
|
+
};
|
|
40352
|
+
this.events = {
|
|
40353
|
+
onChange: true
|
|
40354
|
+
};
|
|
40355
|
+
this.methods = {
|
|
40356
|
+
getData() {
|
|
40357
|
+
return this.$options.data;
|
|
40358
|
+
},
|
|
40359
|
+
setData(data) {
|
|
40360
|
+
const next = isArray$1(data) ? data : data && 'data' in data ? data.data : null;
|
|
40361
|
+
if (!isArray$1(next)) {
|
|
40362
|
+
throw new TypeError('Invalid SortableList data: data must be an array');
|
|
40363
|
+
}
|
|
40364
|
+
this._hidden.setData(next);
|
|
40365
|
+
},
|
|
40366
|
+
disable() {
|
|
40367
|
+
this._hidden.disable();
|
|
40368
|
+
},
|
|
40369
|
+
enable() {
|
|
40370
|
+
this._hidden.enable();
|
|
40371
|
+
}
|
|
40372
|
+
};
|
|
40373
|
+
this.$selector = this.$selector;
|
|
40374
|
+
this.$init(this, options);
|
|
40375
|
+
}
|
|
40376
|
+
template(config) {
|
|
40377
|
+
const styles = {};
|
|
40378
|
+
if (config.width) {
|
|
40379
|
+
styles.width = getUnit('width', config.width);
|
|
40380
|
+
}
|
|
40381
|
+
const listStyles = {};
|
|
40382
|
+
if (config.height) {
|
|
40383
|
+
const heightValue = getUnit('height', config.height);
|
|
40384
|
+
styles.height = heightValue;
|
|
40385
|
+
listStyles.height = heightValue;
|
|
40386
|
+
listStyles.maxHeight = heightValue;
|
|
40387
|
+
}
|
|
40388
|
+
const controlClass = 'sortablelist-controls gn-control is-small has-arrange is-vertical is-center' + (config.buttonPosition === 'right' ? ' is-right' : '');
|
|
40389
|
+
const buttonDisabled = config.disabled || (config.data || []).length === 0;
|
|
40390
|
+
return (createElement$1("div", { id: this._uid, className: 'gn-sortablelist' + (config.disabled ? ' is-disabled' : ''), style: styles },
|
|
40391
|
+
createElement$1("div", { className: controlClass },
|
|
40392
|
+
createElement$1("button", { type: "button", className: "gn-button is-outline", "on-click": this._hidden.sort.bind(this, 'up-all'), disabled: buttonDisabled },
|
|
40393
|
+
createElement$1("span", { className: "gn-icon" },
|
|
40394
|
+
createElement$1("i", { className: "fa fa-light fa-angle-double-up" }))),
|
|
40395
|
+
createElement$1("button", { type: "button", className: "gn-button is-outline", "on-click": this._hidden.sort.bind(this, 'up'), disabled: buttonDisabled },
|
|
40396
|
+
createElement$1("span", { className: "gn-icon" },
|
|
40397
|
+
createElement$1("i", { className: "fa fa-light fa-angle-up" }))),
|
|
40398
|
+
createElement$1("button", { type: "button", className: "gn-button is-outline", "on-click": this._hidden.sort.bind(this, 'down'), disabled: buttonDisabled },
|
|
40399
|
+
createElement$1("span", { className: "gn-icon" },
|
|
40400
|
+
createElement$1("i", { className: "fa fa-light fa-angle-down" }))),
|
|
40401
|
+
createElement$1("button", { type: "button", className: "gn-button is-outline", "on-click": this._hidden.sort.bind(this, 'down-all'), disabled: buttonDisabled },
|
|
40402
|
+
createElement$1("span", { className: "gn-icon" },
|
|
40403
|
+
createElement$1("i", { className: "fa fa-light fa-angle-double-down" })))),
|
|
40404
|
+
createElement$1("div", { className: "gn-dropdown is-opened sortablelist-items" },
|
|
40405
|
+
createElement$1("div", { className: "dropdown-items", style: listStyles }, this._hidden.renderSub()))));
|
|
40406
|
+
}
|
|
40407
|
+
beforeMount() {
|
|
40408
|
+
this._hidden.validateData(this.$options.data);
|
|
40409
|
+
this._hidden.hydrateSelection(this.$options.data);
|
|
40410
|
+
}
|
|
40411
|
+
completed() {
|
|
40412
|
+
this._hidden.updateControls();
|
|
40413
|
+
}
|
|
40414
|
+
destroyed() {
|
|
40415
|
+
this._hidden.clearDragState();
|
|
40416
|
+
}
|
|
40417
|
+
}
|
|
40418
|
+
|
|
39759
40419
|
class Splitter extends GNCoreInstance {
|
|
39760
40420
|
constructor(name, selector, options = {}) {
|
|
39761
40421
|
super(name, selector, options);
|
|
@@ -40403,6 +41063,7 @@ var gnUIComp = {
|
|
|
40403
41063
|
picklist: Picklist,
|
|
40404
41064
|
progressbar: Progressbar,
|
|
40405
41065
|
selectbutton: SelectButton,
|
|
41066
|
+
sortablelist: SortableList,
|
|
40406
41067
|
splitter: Splitter,
|
|
40407
41068
|
switch: Switch,
|
|
40408
41069
|
syntaxinput: SyntaxInput,
|