gnui 1.2.20 → 1.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/@types/gnui.d.ts +8 -0
  2. package/dist/js/gnui.esm.js +712 -153
  3. package/dist/js/gnui.js +712 -153
  4. package/dist/js/gnui.min.js +6 -6
  5. package/dist/styles/default.css +144 -0
  6. package/dist/styles/gpi.css +144 -0
  7. package/dist/styles/green24.css +145 -1
  8. package/dist/styles/insights.css +144 -0
  9. package/dist/styles/nac.css +144 -0
  10. package/dist/styles/ztnac.css +145 -1
  11. package/package.json +7 -2
  12. package/styleguide/assets/components.js +237 -9
  13. package/styleguide/assets/js/gnui.js +712 -153
  14. package/styleguide/assets/js/gnui.min.js +6 -6
  15. package/styleguide/assets/styles/default.css +144 -0
  16. package/styleguide/assets/styles/gpi.css +144 -0
  17. package/styleguide/assets/styles/green24.css +145 -1
  18. package/styleguide/assets/styles/insights.css +144 -0
  19. package/styleguide/assets/styles/nac.css +144 -0
  20. package/styleguide/assets/styles/ztnac.css +145 -1
  21. package/styleguide/category/COLOR/index.html +1 -1
  22. package/styleguide/category/COMPONENT/Alert(js)/index.html +1 -1
  23. package/styleguide/category/COMPONENT/Bignumber/index.html +1 -1
  24. package/styleguide/category/COMPONENT/Breadcrumb/index.html +1 -1
  25. package/styleguide/category/COMPONENT/Calendar(js)/index.html +1 -1
  26. package/styleguide/category/COMPONENT/Card/index.html +1 -1
  27. package/styleguide/category/COMPONENT/Chart(js)/index.html +1 -1
  28. package/styleguide/category/COMPONENT/Datagrid(js)/index.html +109 -11
  29. package/styleguide/category/COMPONENT/Datalist(js)/index.html +1 -1
  30. package/styleguide/category/COMPONENT/Growl(js)/index.html +1 -1
  31. package/styleguide/category/COMPONENT/JsonView(js)/index.html +1 -1
  32. package/styleguide/category/COMPONENT/Loader(js)/index.html +1 -1
  33. package/styleguide/category/COMPONENT/MenuButton(js)/index.html +1 -1
  34. package/styleguide/category/COMPONENT/Message(js)/index.html +1 -1
  35. package/styleguide/category/COMPONENT/Modal(js)/index.html +31 -1
  36. package/styleguide/category/COMPONENT/Pagination(js)/index.html +1 -1
  37. package/styleguide/category/COMPONENT/Panel/index.html +1 -1
  38. package/styleguide/category/COMPONENT/Progressbar(js)/index.html +1 -1
  39. package/styleguide/category/COMPONENT/Tab(js)/index.html +1 -1
  40. package/styleguide/category/COMPONENT/Tagcloud(js)/index.html +1 -1
  41. package/styleguide/category/COMPONENT/Tooltip(js)/index.html +1 -1
  42. package/styleguide/category/COMPONENT/Tree(js)/index.html +83 -19
  43. package/styleguide/category/CONTROLS/Button(js)/index.html +1 -1
  44. package/styleguide/category/CONTROLS/Checkbox/index.html +1 -1
  45. package/styleguide/category/CONTROLS/Colorpicker(js)/index.html +1 -1
  46. package/styleguide/category/CONTROLS/Datepicker(js)/index.html +1 -1
  47. package/styleguide/category/CONTROLS/Dropdown(js)/index.html +83 -1
  48. package/styleguide/category/CONTROLS/File/index.html +1 -1
  49. package/styleguide/category/CONTROLS/Form/Control/index.html +1 -1
  50. package/styleguide/category/CONTROLS/Form/Field/index.html +53 -1
  51. package/styleguide/category/CONTROLS/Form/Plain/index.html +1 -1
  52. package/styleguide/category/CONTROLS/Input/index.html +1 -1
  53. package/styleguide/category/CONTROLS/MultiText(js)/index.html +32 -1
  54. package/styleguide/category/CONTROLS/Picklist(js)/index.html +35 -1
  55. package/styleguide/category/CONTROLS/Radio/index.html +1 -1
  56. package/styleguide/category/CONTROLS/Select/index.html +1 -1
  57. package/styleguide/category/CONTROLS/SelectButton(js)/index.html +1 -1
  58. package/styleguide/category/CONTROLS/Slider/index.html +1 -1
  59. package/styleguide/category/CONTROLS/SortableList(js)/index.html +1 -1
  60. package/styleguide/category/CONTROLS/Switch(js)/index.html +1 -1
  61. package/styleguide/category/CONTROLS/SyntaxInput(js)/index.html +1 -1
  62. package/styleguide/category/CONTROLS/Textarea/index.html +1 -1
  63. package/styleguide/category/CONTROLS/Time(js)/index.html +1 -1
  64. package/styleguide/category/ELEMENTS/Box/index.html +1 -1
  65. package/styleguide/category/ELEMENTS/Icon/index.html +1 -1
  66. package/styleguide/category/ELEMENTS/Image/index.html +1 -1
  67. package/styleguide/category/ELEMENTS/List/index.html +1 -1
  68. package/styleguide/category/ELEMENTS/Table/index.html +1 -1
  69. package/styleguide/category/ELEMENTS/Tag/index.html +1 -1
  70. package/styleguide/category/ELEMENTS/Title/index.html +1 -1
  71. package/styleguide/category/LAYOUT/Container/index.html +1 -1
  72. package/styleguide/category/LAYOUT/Grid/index.html +1 -1
  73. package/styleguide/category/LAYOUT/Splitter(js)/index.html +1 -1
  74. package/styleguide/category/UTILITY/index.html +9 -2
  75. package/styleguide/category/Utils/index.html +1 -1
  76. package/styleguide/color.html +1 -1
  77. package/styleguide/index.html +1 -1
  78. package/styleguide/tag/javascript/index.html +368 -29
  79. package/styleguide/tag/v.0.1.0/index.html +428 -30
@@ -33521,11 +33521,13 @@ class Dropdown extends GNCoreInstance {
33521
33521
  : find('select', this.$el).value;
33522
33522
  },
33523
33523
  changeData: (data) => {
33524
+ var _a;
33524
33525
  this.$options.data = data;
33525
33526
  this._hidden.flatData();
33526
33527
  this.$options.hasSearch && this._hidden.resetSearch();
33527
33528
  this.$template.reRender(find('.dropdown-text', this.$el), this._hidden.renderLabel());
33528
33529
  this.$template.reRender(find('.dropdown-items > div:not(.dropdown-search)', this.$el), this._hidden.renderSub(data));
33530
+ (_a = this.$options._tooltipCache) === null || _a === void 0 ? void 0 : _a.clear();
33529
33531
  },
33530
33532
  search: (e) => {
33531
33533
  clearTimeout(this.$options.timer);
@@ -33641,7 +33643,7 @@ class Dropdown extends GNCoreInstance {
33641
33643
  (isArray$1(this.$options.value) ? this.$options.value.find((v) => v.value === option.value) : option.value === this.$options.value.value)
33642
33644
  ? ' is-active'
33643
33645
  : '') +
33644
- (this.$options.multiple ? ' has-checkbox' : ''), "on-click": isArray$1(option.value) || !displayText ? null : this._hidden.select.bind(this, option), "data-value": isArray$1(option.value) ? '' : option.value, title: displayText ? escapeEntity(String(displayText)) : '' },
33646
+ (this.$options.multiple ? ' has-checkbox' : ''), "on-click": isArray$1(option.value) || !displayText ? null : this._hidden.select.bind(this, option), "on-mouseenter": this.$options.optionTooltip && displayText && !isArray$1(option.value) ? this._hidden.showOptionTooltip.bind(this, option) : null, "on-mouseleave": this.$options.optionTooltip ? this._hidden.hideOptionTooltip : null, "data-value": isArray$1(option.value) ? '' : option.value, title: displayText ? escapeEntity(String(displayText)) : '' },
33645
33647
  createElement$1("span", { className: "dropdown-text", innerHTML: option.html ? option.html : '' },
33646
33648
  option.html ? ('') : renderAsCols ? (createElement$1("div", { className: "gn-checks dropdown-cols" },
33647
33649
  this.$options.multiple && (createElement$1("div", { className: "is-small is-no-padding" },
@@ -33718,6 +33720,76 @@ class Dropdown extends GNCoreInstance {
33718
33720
  enable: () => {
33719
33721
  this.$options.disabled = false;
33720
33722
  removeClass(this.$el, 'is-disabled');
33723
+ },
33724
+ showOptionTooltip: (option, e) => {
33725
+ var _a;
33726
+ if (!this.$options.optionTooltip || !this.$options._tooltipPanel)
33727
+ return;
33728
+ const panel = this.$options._tooltipPanel;
33729
+ const direction = this.$options.optionTooltip.direction || 'right';
33730
+ const rect = e.currentTarget.getBoundingClientRect();
33731
+ panel.className = `gn-tooltip is-${direction}`;
33732
+ panel.style.position = 'fixed';
33733
+ panel.style.zIndex = '9999';
33734
+ switch (direction) {
33735
+ case 'left':
33736
+ panel.style.top = (rect.top + rect.height / 2) + 'px';
33737
+ panel.style.left = rect.left + 'px';
33738
+ break;
33739
+ case 'top':
33740
+ panel.style.top = rect.top + 'px';
33741
+ panel.style.left = (rect.left + rect.width / 2) + 'px';
33742
+ break;
33743
+ case 'bottom':
33744
+ panel.style.top = rect.bottom + 'px';
33745
+ panel.style.left = (rect.left + rect.width / 2) + 'px';
33746
+ break;
33747
+ default:
33748
+ panel.style.top = (rect.top + rect.height / 2) + 'px';
33749
+ panel.style.left = (rect.right + 10) + 'px';
33750
+ }
33751
+ addClass(panel, 'is-active');
33752
+ const cacheKey = String(option.value);
33753
+ const cache = this.$options._tooltipCache;
33754
+ if (cache.has(cacheKey)) {
33755
+ panel.innerHTML = (_a = cache.get(cacheKey)) !== null && _a !== void 0 ? _a : '';
33756
+ return;
33757
+ }
33758
+ const { content, fetch: fetchFn } = this.$options.optionTooltip;
33759
+ if (content) {
33760
+ // content()는 개발자가 제공하는 함수 — XSS 방지는 호출자 책임
33761
+ const html = content(option);
33762
+ cache.set(cacheKey, html);
33763
+ panel.innerHTML = html;
33764
+ }
33765
+ else if (fetchFn) {
33766
+ const requestId = ++this.$options._tooltipRequestId;
33767
+ panel.innerHTML = '<div class="gn-loader is-inline"></div>';
33768
+ try {
33769
+ fetchFn(option)
33770
+ .then((html) => {
33771
+ if (requestId !== this.$options._tooltipRequestId)
33772
+ return;
33773
+ cache.set(cacheKey, html);
33774
+ if (panel.classList.contains('is-active')) {
33775
+ panel.innerHTML = html;
33776
+ }
33777
+ })
33778
+ .catch(() => {
33779
+ if (requestId === this.$options._tooltipRequestId) {
33780
+ removeClass(panel, 'is-active');
33781
+ }
33782
+ });
33783
+ }
33784
+ catch (_b) {
33785
+ removeClass(panel, 'is-active');
33786
+ }
33787
+ }
33788
+ },
33789
+ hideOptionTooltip: () => {
33790
+ if (!this.$options._tooltipPanel)
33791
+ return;
33792
+ removeClass(this.$options._tooltipPanel, 'is-active');
33721
33793
  }
33722
33794
  };
33723
33795
  this.config = {
@@ -33734,7 +33806,8 @@ class Dropdown extends GNCoreInstance {
33734
33806
  scrollHeight: 0,
33735
33807
  timer: 0,
33736
33808
  disabled: false,
33737
- multiple: false
33809
+ multiple: false,
33810
+ optionTooltip: undefined
33738
33811
  };
33739
33812
  this.events = {
33740
33813
  onChange: true
@@ -33818,6 +33891,22 @@ class Dropdown extends GNCoreInstance {
33818
33891
  setValue(this.$options.value, options);
33819
33892
  }
33820
33893
  }
33894
+ if (this.$options.optionTooltip) {
33895
+ this.$options._tooltipCache = new Map();
33896
+ this.$options._tooltipRequestId = 0;
33897
+ const direction = this.$options.optionTooltip.direction || 'right';
33898
+ const panel = document.createElement('div');
33899
+ panel.className = `gn-tooltip is-${direction}`;
33900
+ panel.style.position = 'fixed';
33901
+ panel.style.zIndex = '9999';
33902
+ document.body.appendChild(panel);
33903
+ this.$options._tooltipPanel = panel;
33904
+ this.$options._destroy = () => {
33905
+ if (panel.parentElement) {
33906
+ panel.parentElement.removeChild(panel);
33907
+ }
33908
+ };
33909
+ }
33821
33910
  }
33822
33911
  isBrandIcon(iconName) {
33823
33912
  const iconLookup = { prefix: 'fab', iconName: iconName };
@@ -34549,7 +34638,7 @@ class Chart extends GNCoreInstance {
34549
34638
  const newOptions = merge(this.chartDefault, merge(chartOptions, typesDefault[this.$options.type] || {}));
34550
34639
  if (!newOptions.theme) {
34551
34640
  newOptions.theme = {
34552
- palette: 'palette4'
34641
+ palette: 'palette1'
34553
34642
  };
34554
34643
  }
34555
34644
  this.$options.chart = new ApexCharts$1(this.$el, newOptions);
@@ -37219,6 +37308,13 @@ class DataGrid extends GNCoreInstance {
37219
37308
  this.$event(this, 'onSort', column);
37220
37309
  },
37221
37310
  renderHeader: (columns, isReset = false) => {
37311
+ if (this._isHorizontalState()) {
37312
+ return (createElement$1("div", { className: "gn-datagrid-header-row is-horizontal" },
37313
+ createElement$1("div", { className: "gn-datagrid-header-cell is-horizontal" }, this.$options.hasCheck && (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
37314
+ createElement$1("input", { type: "checkbox", className: "is-allChecker", id: this._uid + '-rows-check', "on-click": (e) => {
37315
+ this._hidden.checkAll.call(this, e);
37316
+ }, disabled: this.$options.disabled }))))));
37317
+ }
37222
37318
  this._setColumnsTemplate(isReset);
37223
37319
  return (createElement$1("div", { className: "gn-datagrid-header-row", style: {
37224
37320
  'grid-template-columns': this._columnsTemplate.join(' ')
@@ -37259,15 +37355,24 @@ class DataGrid extends GNCoreInstance {
37259
37355
  },
37260
37356
  renderBody: (data, columns) => {
37261
37357
  // 헤더가 숨겨진 경우에도 body 렌더 전에 템플릿 폭을 준비한다
37262
- if (!this._columnsTemplate || !this._columnsTemplate.length) {
37358
+ if (!this._isHorizontalState() && (!this._columnsTemplate || !this._columnsTemplate.length)) {
37263
37359
  this._setColumnsTemplate();
37264
37360
  }
37265
37361
  rowIdx$1 = 0;
37266
- return (createElement$1("div", { className: "gn-datagrid-body", style: {
37362
+ return (createElement$1("div", { className: 'gn-datagrid-body' + (this._isHorizontalState() ? ' is-horizontal' : ''), style: {
37363
+ 'grid-template-columns': this._isHorizontalState()
37364
+ ? this._orientationState.columns === 'auto-fit'
37365
+ ? `repeat(auto-fit, minmax(${this._orientationState.minWidth}, 1fr))`
37366
+ : `repeat(${this._orientationState.columns}, minmax(0, 1fr))`
37367
+ : '',
37368
+ gap: this._isHorizontalState() ? this._orientationState.gap : '',
37267
37369
  maxHeight: this.$options.bodyHeight ? this.$options.bodyHeight : 'auto'
37268
37370
  } }, (data === null || data === void 0 ? void 0 : data.length) ? this._hidden.renderRows(data, columns) : this._hidden.renderNodata()));
37269
37371
  },
37270
37372
  renderRows: (rows, columns, depth = 0, isOpen = false) => {
37373
+ if (this._isHorizontalState()) {
37374
+ return rows.map((row) => this._hidden.renderRow(row, columns, 0, false, false));
37375
+ }
37271
37376
  return rows.map((row) => {
37272
37377
  return row[this.$options.childField] && isArray$1(row[this.$options.childField])
37273
37378
  ? [this._hidden.renderRow(row, columns, depth, true, isOpen), this._hidden.renderRows(row[this.$options.childField], columns, depth + 1, row.isOpened)]
@@ -37276,6 +37381,23 @@ class DataGrid extends GNCoreInstance {
37276
37381
  },
37277
37382
  renderRow: (row, columns, depth = 0, hasChild, isOpened, isCheck = false) => {
37278
37383
  const _index = rowIdx$1++;
37384
+ const getHorizontalRowClass = () => {
37385
+ if (!this._isHorizontalState() || this._orientationState.columns === 'auto-fit') {
37386
+ return '';
37387
+ }
37388
+ const classes = ['is-horizontal'];
37389
+ if (_index % this._orientationState.columns === 0) {
37390
+ classes.push('is-horizontal-first-col');
37391
+ }
37392
+ if ((_index + 1) % this._orientationState.columns === 0 || _index === this.$options.data.length - 1) {
37393
+ classes.push('is-horizontal-last-col');
37394
+ }
37395
+ if (_index < this._orientationState.columns) {
37396
+ classes.push('is-horizontal-first-row');
37397
+ }
37398
+ return ' ' + classes.join(' ');
37399
+ };
37400
+ const horizontalClass = getHorizontalRowClass();
37279
37401
  if (row.isChecked) {
37280
37402
  isCheck = true;
37281
37403
  }
@@ -37285,76 +37407,114 @@ class DataGrid extends GNCoreInstance {
37285
37407
  }, "on-dblclick": (e) => {
37286
37408
  var _a;
37287
37409
  ((_a = this === null || this === void 0 ? void 0 : this.$options) === null || _a === void 0 ? void 0 : _a.onDoubleClick) && !this.$options.disabled && this._hidden.doubleSelect.call(this, row, _index, e);
37288
- }, className: 'gn-datagrid-body-row' + (hasChild ? ' has-child' : '') + (row.isOpened ? '' : ' is-collapsed') + (depth > 0 && !isOpened ? ' is-hidden' : '') + (row.color ? ` ${row.color}` : ''), style: {
37289
- 'grid-template-columns': this._columnsTemplate.join(' ')
37290
- }, id: this._uid + '-row-' + _index, "data-depth": depth }, columns.map((col, idx) => {
37291
- const cellStyle = {};
37292
- if (col.bodyStyle || col.style) {
37293
- each(col.bodyStyle || col.style, (value, key) => {
37294
- if (key !== 'width') {
37295
- cellStyle[key] = value;
37296
- }
37297
- });
37298
- }
37299
- if (idx === 0 && depth !== 0) {
37300
- cellStyle.paddingLeft = depth * 15 + 10 + 'px';
37301
- }
37302
- if (isIE) {
37303
- cellStyle.display = 'inline-block';
37304
- }
37305
- if (col.key === 'btnOrder') {
37306
- cellStyle.display = 'flex';
37307
- cellStyle.padding = '0';
37308
- cellStyle['justify-content'] = 'space-evenly';
37309
- cellStyle['align-items'] = 'center';
37310
- return (createElement$1("div", { className: 'gn-datagrid-body-cell btn-container ' + (col.key ? col.key : ''), style: cellStyle, "on-click": (e) => {
37311
- this._hidden.stopRowSelectEvent(e);
37312
- } },
37313
- createElement$1("span", { className: 'gn-icon btn-order ' + (_index == 0 ? 'is-cancel' : 'is-info'), "on-click": () => {
37314
- !this.$options.disabled && this._hidden.moveRowUp.call(this, _index);
37315
- } },
37316
- createElement$1("i", { className: "fas fa-arrow-circle-up" })),
37317
- createElement$1("span", { className: 'gn-icon btn-order ' + (_index == this.$options.data.length - 1 ? 'is-cancel' : 'is-info'), "on-click": () => {
37318
- !this.$options.disabled && this._hidden.moveRowDown.call(this, _index);
37410
+ }, className: 'gn-datagrid-body-row' +
37411
+ (hasChild ? ' has-child' : '') +
37412
+ (row.isOpened ? '' : ' is-collapsed') +
37413
+ (depth > 0 && !isOpened ? ' is-hidden' : '') +
37414
+ (row.color ? ` ${row.color}` : '') +
37415
+ horizontalClass, style: {
37416
+ 'grid-template-columns': this._isHorizontalState() ? '' : this._columnsTemplate.join(' ')
37417
+ }, id: this._uid + '-row-' + _index, "data-depth": depth },
37418
+ this._isHorizontalState() && this._hidden.renderHorizontalCardHeader(row, _index, hasChild, isCheck),
37419
+ columns.map((col, idx) => {
37420
+ const cellStyle = {};
37421
+ if (col.bodyStyle || col.style) {
37422
+ each(col.bodyStyle || col.style, (value, key) => {
37423
+ if (key !== 'width') {
37424
+ cellStyle[key] = value;
37425
+ }
37426
+ });
37427
+ }
37428
+ if (idx === 0 && depth !== 0) {
37429
+ cellStyle.paddingLeft = depth * 15 + 10 + 'px';
37430
+ }
37431
+ if (isIE) {
37432
+ cellStyle.display = 'inline-block';
37433
+ }
37434
+ if (col.key === 'btnOrder') {
37435
+ cellStyle.display = 'flex';
37436
+ cellStyle.padding = '0';
37437
+ cellStyle['justify-content'] = 'space-evenly';
37438
+ cellStyle['align-items'] = 'center';
37439
+ return (createElement$1("div", { className: 'gn-datagrid-body-cell btn-container ' + (col.key ? col.key : '') + (this._isHorizontalState() ? ' is-horizontal' : ''), style: cellStyle, "data-key": col.key, "on-click": (e) => {
37440
+ this._hidden.stopRowSelectEvent(e);
37319
37441
  } },
37320
- createElement$1("i", { className: "fas fa-arrow-circle-down" }))));
37321
- }
37322
- if (col.key === 'btnDelete') {
37323
- cellStyle.display = 'flex';
37324
- cellStyle['justify-content'] = 'center';
37325
- cellStyle['align-items'] = 'center';
37326
- return (createElement$1("div", { className: 'gn-datagrid-body-cell btn-container ' + (col.key ? col.key : ''), style: cellStyle, "on-click": (e) => {
37327
- this._hidden.stopRowSelectEvent(e);
37328
- } },
37329
- createElement$1("span", { className: "gn-icon is-small is-mono", "on-click": () => {
37330
- !this.$options.disabled && this._hidden.deleteRow.call(this, _index);
37442
+ createElement$1("span", { className: 'gn-icon btn-order ' + (_index == 0 ? 'is-cancel' : 'is-info'), "on-click": () => {
37443
+ !this.$options.disabled && this._hidden.moveRowUp.call(this, _index);
37444
+ } },
37445
+ createElement$1("i", { className: "fas fa-arrow-circle-up" })),
37446
+ createElement$1("span", { className: 'gn-icon btn-order ' + (_index == this.$options.data.length - 1 ? 'is-cancel' : 'is-info'), "on-click": () => {
37447
+ !this.$options.disabled && this._hidden.moveRowDown.call(this, _index);
37448
+ } },
37449
+ createElement$1("i", { className: "fas fa-arrow-circle-down" }))));
37450
+ }
37451
+ if (col.key === 'btnDelete') {
37452
+ cellStyle.display = 'flex';
37453
+ cellStyle['justify-content'] = 'center';
37454
+ cellStyle['align-items'] = 'center';
37455
+ return (createElement$1("div", { className: 'gn-datagrid-body-cell btn-container ' + (col.key ? col.key : '') + (this._isHorizontalState() ? ' is-horizontal' : ''), style: cellStyle, "data-key": col.key, "on-click": (e) => {
37456
+ this._hidden.stopRowSelectEvent(e);
37331
37457
  } },
37332
- createElement$1("i", { className: "fas fa-trash" }))));
37333
- }
37334
- return (createElement$1("div", { className: 'gn-datagrid-body-cell ' +
37335
- (col.bodyClass ? col.bodyClass : col.className ? col.className : '') +
37336
- (isFunction(col.onSelect) ? ' is-selectable' : '') +
37337
- (col.isHidden ? ' is-unvisible' : ''), "data-key": col.key, style: cellStyle, "on-click": (e) => {
37338
- col.onSelect && !this.$options.disabled && this._hidden.selectCell.call(this, col, row, _index, e);
37339
- }, "on-mouseenter": (e) => {
37340
- col.onHover && !this.$options.disabled && this._hidden.hoverCell.call(this, col, row, _index, e);
37341
- }, "on-mouseleave": (e) => {
37342
- col.offHover && this._hidden.blurCell.call(this, col, row, _index, e);
37343
- }, title: col.tipField && row[col.tipField] ? row[col.tipField] : !col.template && row[col.key] ? row[col.key] : '' }, this._hidden.renderCell(row, col, idx, hasChild, isCheck, _index)));
37344
- })));
37345
- },
37346
- renderCell: (row, col, idx, hasChild, isCheck, _index) => {
37458
+ createElement$1("span", { className: "gn-icon is-small is-mono", "on-click": () => {
37459
+ !this.$options.disabled && this._hidden.deleteRow.call(this, _index);
37460
+ } },
37461
+ createElement$1("i", { className: "fas fa-trash" }))));
37462
+ }
37463
+ return (createElement$1("div", { className: 'gn-datagrid-body-cell ' +
37464
+ (col.bodyClass ? col.bodyClass : col.className ? col.className : '') +
37465
+ (isFunction(col.onSelect) ? ' is-selectable' : '') +
37466
+ (col.isHidden ? ' is-unvisible' : '') +
37467
+ (this._isHorizontalState() ? ' is-horizontal' : ''), "data-key": col.key, style: cellStyle, "on-click": (e) => {
37468
+ col.onSelect && !this.$options.disabled && this._hidden.selectCell.call(this, col, row, _index, e);
37469
+ }, "on-mouseenter": (e) => {
37470
+ col.onHover && !this.$options.disabled && this._hidden.hoverCell.call(this, col, row, _index, e);
37471
+ }, "on-mouseleave": (e) => {
37472
+ col.offHover && this._hidden.blurCell.call(this, col, row, _index, e);
37473
+ }, title: col.tipField && row[col.tipField] ? row[col.tipField] : !col.template && row[col.key] ? row[col.key] : '' }, this._hidden.renderCell(row, col, idx, hasChild, isCheck, _index)));
37474
+ })));
37475
+ },
37476
+ renderHorizontalCellLabel: (col) => {
37477
+ if (this._isSystemAddedColumn(col.key)) {
37478
+ return null;
37479
+ }
37480
+ return createElement$1("span", { className: "gn-datagrid-cell-label" }, col.label);
37481
+ },
37482
+ renderHorizontalCardHeader: (row, index, hasChild, isCheck) => {
37483
+ const hasHeader = this.$options.hasCheck || (this.$options.hasDelete && !this.$options.readonly);
37484
+ const showCheck = this.$options.hasCheck && row.noCheck !== true && row.noCheck !== 'true';
37485
+ const showDelete = this.$options.hasDelete && !this.$options.readonly;
37486
+ if (!hasHeader) {
37487
+ return null;
37488
+ }
37489
+ return (createElement$1("div", { className: "gn-datagrid-card-header" },
37490
+ createElement$1("div", { className: "gn-datagrid-card-header-left" }, showCheck && (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
37491
+ createElement$1("input", { type: "checkbox", id: this._uid + '-row-check-' + index, className: "is-rowChecker", "on-click": (e) => {
37492
+ this._hidden.check.call(this, row, e);
37493
+ }, defaultChecked: isCheck, disabled: this.$options.disabled || row.disabled })))),
37494
+ createElement$1("div", { className: "gn-datagrid-card-header-right" }, showDelete && (createElement$1("span", { className: "gn-icon is-small is-mono", "on-click": (e) => {
37495
+ this._hidden.stopRowSelectEvent(e);
37496
+ !this.$options.disabled && this._hidden.deleteRow.call(this, index);
37497
+ } },
37498
+ createElement$1("i", { className: "fas fa-trash" }))))));
37499
+ },
37500
+ renderCellValue: (row, col, idx, hasChild, isCheck, _index) => {
37347
37501
  return [
37348
- idx === 0 && hasChild ? (createElement$1("span", { className: "is-toggler", "on-click": (e) => {
37502
+ idx === 0 && hasChild && !this._isHorizontalState() ? (createElement$1("span", { className: "is-toggler", "on-click": (e) => {
37349
37503
  !this.$options.disabled && this._hidden.toggle.call(this, row, e);
37350
37504
  } })) : (''),
37351
- idx === 0 && this.$options.hasCheck && row.noCheck !== true && row.noCheck !== 'true' ? (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
37505
+ idx === 0 && this.$options.hasCheck && row.noCheck !== true && row.noCheck !== 'true' && !this._isHorizontalState() ? (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
37352
37506
  createElement$1("input", { type: "checkbox", id: this._uid + '-row-check-' + _index, className: "is-rowChecker", "on-click": (e) => {
37353
37507
  this._hidden.check.call(this, row, e);
37354
37508
  }, defaultChecked: isCheck, disabled: this.$options.disabled || row.disabled }))) : (''),
37355
37509
  col.template ? createElement$1("span", { className: "gn-datagrid-cell", innerHTML: col.template(col.key, row, col) }) : row[col.key] !== undefined ? row[col.key] : ''
37356
37510
  ];
37357
37511
  },
37512
+ renderCell: (row, col, idx, hasChild, isCheck, _index) => {
37513
+ if (this._isHorizontalState()) {
37514
+ return [this._hidden.renderHorizontalCellLabel(col), createElement$1("div", { className: "gn-datagrid-cell-value" }, this._hidden.renderCellValue(row, col, idx, hasChild, isCheck, _index))];
37515
+ }
37516
+ return this._hidden.renderCellValue(row, col, idx, hasChild, isCheck, _index);
37517
+ },
37358
37518
  renderNodata: () => {
37359
37519
  return (createElement$1("div", { className: "gn-datagrid-body-row is-nodata" },
37360
37520
  createElement$1("div", { className: "gn-datagrid-body-cell has-text-center" }, this.$options.textSets.noData)));
@@ -37440,7 +37600,10 @@ class DataGrid extends GNCoreInstance {
37440
37600
  });
37441
37601
  this.$event(this, 'onCheckAll', e.target.checked);
37442
37602
  },
37443
- showDetail(index, headerKeys, rawDataKeys) {
37603
+ showDetail: (index, headerKeys, rawDataKeys) => {
37604
+ if (this._isHorizontalState()) {
37605
+ return;
37606
+ }
37444
37607
  const rows = findAll(`.gn-datagrid-body > .gn-datagrid-body-row`, this.$el);
37445
37608
  const row = rows[+index];
37446
37609
  if (next(row) && hasClass(next(row), 'gn-datagrid-body-row-detail')) {
@@ -37527,6 +37690,7 @@ class DataGrid extends GNCoreInstance {
37527
37690
  },
37528
37691
  reRender: ({ headers, data, hasCheck }) => {
37529
37692
  return new Promise(resolve => {
37693
+ this._refreshOrientationState(this.$options);
37530
37694
  if (hasCheck === undefined) {
37531
37695
  hasCheck = this.$options.hasCheck;
37532
37696
  }
@@ -37735,8 +37899,8 @@ class DataGrid extends GNCoreInstance {
37735
37899
  visibles.forEach((visible, index) => {
37736
37900
  const colNumber = index + 1;
37737
37901
  !visible
37738
- ? addClass(findAll('.gn-datagrid-body-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible')
37739
- : removeClass(findAll('.gn-datagrid-body-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible');
37902
+ ? addClass(findAll(`.gn-datagrid-body-cell[data-key="${this.$options.headers[index].key}"]`, this.$el), 'is-unvisible')
37903
+ : removeClass(findAll(`.gn-datagrid-body-cell[data-key="${this.$options.headers[index].key}"]`, this.$el), 'is-unvisible');
37740
37904
  !visible
37741
37905
  ? addClass(findAll('.gn-datagrid-header-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible')
37742
37906
  : removeClass(findAll('.gn-datagrid-header-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible');
@@ -37781,6 +37945,13 @@ class DataGrid extends GNCoreInstance {
37781
37945
  removeClass(this.$el, 'is-disabled');
37782
37946
  }
37783
37947
  };
37948
+ this._orientationState = {
37949
+ orientation: 'vertical',
37950
+ columns: 1,
37951
+ gap: 0,
37952
+ minWidth: 240,
37953
+ hasGap: false
37954
+ };
37784
37955
  this.config = {
37785
37956
  width: '100%',
37786
37957
  hasCheck: false,
@@ -37795,6 +37966,7 @@ class DataGrid extends GNCoreInstance {
37795
37966
  deleteLabel: '',
37796
37967
  deleteConfirmMessage: ''
37797
37968
  },
37969
+ orientation: 'vertical',
37798
37970
  childField: 'child',
37799
37971
  checkCapturing: true,
37800
37972
  sort: {
@@ -37815,10 +37987,10 @@ class DataGrid extends GNCoreInstance {
37815
37987
  onDelete: true
37816
37988
  };
37817
37989
  this.methods = {
37818
- reRender(options) {
37990
+ reRender: (options) => {
37819
37991
  return this._hidden.reRender(options);
37820
37992
  },
37821
- resetData(data) {
37993
+ resetData: (data) => {
37822
37994
  if (isFunction(data)) {
37823
37995
  this.$options.asyncData = data;
37824
37996
  data = [];
@@ -37827,45 +37999,60 @@ class DataGrid extends GNCoreInstance {
37827
37999
  }
37828
38000
  return this._hidden.resetData(arrClone(data));
37829
38001
  },
37830
- addChild(index, data) {
38002
+ addChild: (index, data) => {
38003
+ if (this._isHorizontalState()) {
38004
+ return;
38005
+ }
37831
38006
  this._hidden.addChild(index, arrClone(data));
37832
38007
  },
37833
- addRow(data) {
38008
+ addRow: (data) => {
38009
+ if (this._isHorizontalState()) {
38010
+ return;
38011
+ }
37834
38012
  this._hidden.addChild(null, arrClone(data));
37835
38013
  this.$options.data = this.$options.data.concat(data);
37836
38014
  },
37837
- expand(index) {
38015
+ expand: (index) => {
38016
+ if (this._isHorizontalState()) {
38017
+ return;
38018
+ }
37838
38019
  this._hidden.expand(index);
37839
38020
  },
37840
- collapse(index) {
38021
+ collapse: (index) => {
38022
+ if (this._isHorizontalState()) {
38023
+ return;
38024
+ }
37841
38025
  this._hidden.collapse(index);
37842
38026
  },
37843
- getChecked() {
38027
+ getChecked: () => {
37844
38028
  return this._hidden.getChecked();
37845
38029
  },
37846
- hideCols(keys) {
38030
+ hideCols: (keys) => {
37847
38031
  this._hidden.hideCols(keys);
37848
38032
  },
37849
- showCols(keys) {
38033
+ showCols: (keys) => {
37850
38034
  this._hidden.showCols(keys);
37851
38035
  },
37852
- showAll() {
38036
+ showAll: () => {
37853
38037
  this._hidden.showAll();
37854
38038
  },
37855
- showDetail(index, headerKeys, rawDataKeys) {
38039
+ showDetail: (index, headerKeys, rawDataKeys) => {
38040
+ if (this._isHorizontalState()) {
38041
+ return;
38042
+ }
37856
38043
  this._hidden.showDetail.call(this, index, headerKeys, rawDataKeys);
37857
38044
  },
37858
- selectRow(index, rowData) {
38045
+ selectRow: (index, rowData) => {
37859
38046
  let row = rowData;
37860
38047
  if (!row) {
37861
38048
  row = this.$options.data[index];
37862
38049
  }
37863
38050
  !this.$options.disable && this._hidden.selectRow(row, index);
37864
38051
  },
37865
- disable() {
38052
+ disable: () => {
37866
38053
  this._hidden.disable();
37867
38054
  },
37868
- enable() {
38055
+ enable: () => {
37869
38056
  this._hidden.enable();
37870
38057
  }
37871
38058
  };
@@ -37918,6 +38105,34 @@ class DataGrid extends GNCoreInstance {
37918
38105
  });
37919
38106
  }
37920
38107
  }
38108
+ // 렌더에서 바로 쓸 수 있는 orientation 상태를 만든다.
38109
+ _resolveOrientationState(config = this.$options) {
38110
+ var _a, _b, _c, _d, _e;
38111
+ const orientation = (config === null || config === void 0 ? void 0 : config.orientation) === 'horizontal' ? 'horizontal' : 'vertical';
38112
+ const optionColumns = (_a = config === null || config === void 0 ? void 0 : config.orientationOptions) === null || _a === void 0 ? void 0 : _a.columns;
38113
+ const columns = optionColumns === 'auto-fit' ? optionColumns : Number.isInteger(Number(optionColumns)) && Number(optionColumns) > 0 ? Number(optionColumns) : 1;
38114
+ const optionGap = (_c = (_b = config === null || config === void 0 ? void 0 : config.orientationOptions) === null || _b === void 0 ? void 0 : _b.gap) !== null && _c !== void 0 ? _c : 0;
38115
+ const isZeroLikeGap = optionGap === 0 || optionGap === '0' || optionGap === '0px' || optionGap === '';
38116
+ const gap = columns === 'auto-fit' && isZeroLikeGap ? '5px' : isZeroLikeGap ? 0 : typeof optionGap === 'number' ? optionGap + 'px' : optionGap;
38117
+ const rawMinWidth = (_e = (_d = config.orientationOptions) === null || _d === void 0 ? void 0 : _d.minWidth) !== null && _e !== void 0 ? _e : 240;
38118
+ const minWidth = typeof rawMinWidth === 'number' ? rawMinWidth + 'px' : rawMinWidth;
38119
+ return {
38120
+ orientation,
38121
+ columns,
38122
+ gap,
38123
+ minWidth,
38124
+ hasGap: gap !== 0
38125
+ };
38126
+ }
38127
+ // 실제 옵션이 갱신될 때 내부 orientation 상태를 새로 계산한다.
38128
+ _refreshOrientationState(config = this.$options) {
38129
+ this._orientationState = this._resolveOrientationState(config);
38130
+ return this._orientationState;
38131
+ }
38132
+ // 내부 렌더 분기에서는 orientationState만 기준으로 사용한다.
38133
+ _isHorizontalState() {
38134
+ return this._orientationState.orientation === 'horizontal';
38135
+ }
37921
38136
  _isSystemAddedColumn(key) {
37922
38137
  return ['btnOrder', 'btnDelete'].includes(key);
37923
38138
  }
@@ -37925,6 +38140,10 @@ class DataGrid extends GNCoreInstance {
37925
38140
  _prepareHeaders(headers = []) {
37926
38141
  const hasOrderColumn = headers.some((header) => header.key === 'btnOrder');
37927
38142
  const hasDeleteColumn = headers.some((header) => header.key === 'btnDelete');
38143
+ const horizontal = this._isHorizontalState();
38144
+ if (horizontal) {
38145
+ headers = headers.map((header) => (Object.assign(Object.assign({}, header), { sortable: false, draggable: false })));
38146
+ }
37928
38147
  if (this.$options.hasOrder && !this.$options.readonly && !hasOrderColumn) {
37929
38148
  headers.push({
37930
38149
  label: this.$options.textSets.orderLabel,
@@ -37934,7 +38153,7 @@ class DataGrid extends GNCoreInstance {
37934
38153
  }
37935
38154
  });
37936
38155
  }
37937
- if (this.$options.hasDelete && !this.$options.readonly && !hasDeleteColumn) {
38156
+ if (this.$options.hasDelete && !this.$options.readonly && !hasDeleteColumn && !horizontal) {
37938
38157
  headers.push({
37939
38158
  label: this.$options.textSets.deleteLabel,
37940
38159
  key: 'btnDelete',
@@ -37947,9 +38166,14 @@ class DataGrid extends GNCoreInstance {
37947
38166
  return headers;
37948
38167
  }
37949
38168
  template(config) {
38169
+ const resolvedConfig = Object.assign(Object.assign({}, this.$options), config);
38170
+ this._refreshOrientationState(resolvedConfig);
38171
+ const contentsMarginTop = this.$options.bodyTopMargin ? this.$options.bodyTopMargin : this._isHorizontalState() && this._orientationState.hasGap ? String(this._orientationState.gap) : '0';
37950
38172
  const styles = {};
37951
38173
  const headers = this._prepareHeaders(config.headers);
37952
38174
  return (createElement$1("div", { id: this._uid, className: 'gn-datagrid' +
38175
+ (this._isHorizontalState() ? ' is-horizontal' : '') +
38176
+ (this._isHorizontalState() && this._orientationState.hasGap ? ' has-horizontal-gap' : '') +
37953
38177
  (config.style ? ' is-' + config.style : '') +
37954
38178
  (config.isEllipsis ? ' is-ellipsis' : '') +
37955
38179
  (config.bodyHeight ? ' has-fixed-body' : '') +
@@ -37959,7 +38183,7 @@ class DataGrid extends GNCoreInstance {
37959
38183
  (config.data.some((d) => isArray$1(d[this.$options.childField])) ? ' has-left-padding' : '') +
37960
38184
  (config.disabled ? ' is-disabled' : ''), style: styles },
37961
38185
  config.hasHeader && createElement$1("div", { className: "gn-datagrid-header" }, this._hidden.renderHeader(headers)),
37962
- 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)),
38186
+ createElement$1("div", { className: "gn-datagrid-contents", style: { marginTop: contentsMarginTop, marginBottom: this.$options.bodyBottomMargin ? this.$options.bodyBottomMargin : '0' } }, this._hidden.renderBody(arrClone(config.data), headers)),
37963
38187
  config.paginator /* 페이지네이터 옵션 확인 */ && createElement$1("div", { className: "gn-datagrid-footer" })));
37964
38188
  }
37965
38189
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -37976,7 +38200,12 @@ class DataGrid extends GNCoreInstance {
37976
38200
  }
37977
38201
  }
37978
38202
  completed() {
37979
- if (this.$options.fixHeader && this.$options.hasHeader) {
38203
+ const isHorizontal = this._isHorizontalState();
38204
+ const isVertical = !isHorizontal;
38205
+ const usesFixedHeader = this.$options.fixHeader && this.$options.hasHeader;
38206
+ const needsBlankHeader = usesFixedHeader || this.$options.bodyHeight;
38207
+ isHorizontal ? addClass(this.$el, 'is-horizontal') : removeClass(this.$el, 'is-horizontal');
38208
+ if (usesFixedHeader && isVertical) {
37980
38209
  const body = find('.gn-datagrid-contents', this.$el);
37981
38210
  const header = find('.gn-datagrid-header', this.$el);
37982
38211
  if (header) {
@@ -37989,7 +38218,7 @@ class DataGrid extends GNCoreInstance {
37989
38218
  css$1(body, 'margin-bottom', this.$options.bodyBottomMargin);
37990
38219
  }
37991
38220
  }
37992
- if ((this.$options.fixHeader && this.$options.hasHeader) || this.$options.bodyHeight) {
38221
+ if (isVertical && needsBlankHeader) {
37993
38222
  this._hidden.setBlankHeader();
37994
38223
  on(window, 'resize', this._hidden.setBlankHeader);
37995
38224
  }
@@ -38467,6 +38696,10 @@ class Modal extends GNCoreInstance {
38467
38696
  focus: () => {
38468
38697
  const modal = find('.modal-content', this.$el);
38469
38698
  modal.focus();
38699
+ },
38700
+ extra: (actionKey) => {
38701
+ // notify page about which extra button clicked
38702
+ this.$event(this, 'onExtra', actionKey);
38470
38703
  }
38471
38704
  };
38472
38705
  this.config = {
@@ -38484,6 +38717,7 @@ class Modal extends GNCoreInstance {
38484
38717
  hasClose: true,
38485
38718
  hasConfirm: false,
38486
38719
  hasCancel: false,
38720
+ extraButtons: [],
38487
38721
  isModal: true,
38488
38722
  minimized: false,
38489
38723
  resizable: false,
@@ -38494,7 +38728,8 @@ class Modal extends GNCoreInstance {
38494
38728
  this.events = {
38495
38729
  onClose: true,
38496
38730
  onConfirm: true,
38497
- onOpen: true
38731
+ onOpen: true,
38732
+ onExtra: true
38498
38733
  };
38499
38734
  this.methods = {
38500
38735
  close() {
@@ -38536,7 +38771,10 @@ class Modal extends GNCoreInstance {
38536
38771
  createElement$1("i", { className: "fas fa-times" })))))),
38537
38772
  createElement$1("div", { className: "modal-body", style: styles },
38538
38773
  createElement$1("div", { className: "modal-body-content", style: contStyles })),
38539
- (config.hasConfirm || config.hasCancel) /* 확인/취소 옵션 확인 */ && (createElement$1("div", { className: "modal-footer has-text-center" },
38774
+ (config.hasConfirm || config.hasCancel || (Array.isArray(config.extraButtons) && config.extraButtons.length > 0)) /* 확인/취소/추가버튼 옵션 확인 */ && (createElement$1("div", { className: "modal-footer has-text-center" },
38775
+ Array.isArray(config.extraButtons) &&
38776
+ config.extraButtons.length > 0 &&
38777
+ config.extraButtons.map((btn) => (createElement$1("button", { type: "button", className: 'gn-button ' + (btn.className ? btn.className : 'is-mono'), "on-click": this._hidden.extra.bind(this, btn.key || btn.label) }, btn.label || btn.key))),
38540
38778
  config.hasConfirm && (createElement$1("button", { type: "button", className: 'gn-button' + ` is-${config.sizeSets.confirm}`, id: this._uid + '_confirm', "on-click": this._hidden.confirm }, config.textSets.confirm)),
38541
38779
  config.hasCancel && (createElement$1("button", { type: "button", className: 'gn-button btnCloseModal is-cancel' + ` is-${config.sizeSets.cancel}`, id: this._uid + '_cancel', "on-click": this._hidden.close }, config.textSets.cancel)))))));
38542
38780
  }
@@ -39575,15 +39813,124 @@ class Tab extends GNCoreInstance {
39575
39813
  }
39576
39814
 
39577
39815
  class MultiTextArea extends GNCoreInstance {
39816
+ _isMaxLengthMessageEnabled() {
39817
+ return !!(this.$options.maxlength && this.$options.useMaxLengthMessage);
39818
+ }
39819
+ _getTotalLength(valueSet) {
39820
+ return this.$options.lang.reduce((sum, currentLang) => {
39821
+ const currentValue = valueSet[currentLang] || '';
39822
+ return sum + currentValue.length;
39823
+ }, 0);
39824
+ }
39825
+ _getTotalLengthWithoutLang(valueSet, excludeLang) {
39826
+ return this.$options.lang.reduce((sum, currentLang) => {
39827
+ if (currentLang === excludeLang) {
39828
+ return sum;
39829
+ }
39830
+ const currentValue = valueSet[currentLang] || '';
39831
+ return sum + currentValue.length;
39832
+ }, 0);
39833
+ }
39834
+ _getRemainMessage(remain) {
39835
+ var _a, _b;
39836
+ const template = ((_b = (_a = this.$options) === null || _a === void 0 ? void 0 : _a.textSets) === null || _b === void 0 ? void 0 : _b.maxLengthMessage) || '{{maxlength}}자 입력 가능합니다.';
39837
+ return template.replace(/\{\{\s*maxlength\s*\}\}/g, String(remain));
39838
+ }
39578
39839
  constructor(name, selector, options = {}) {
39579
39840
  super(name, selector, options);
39580
39841
  this._hidden = {
39842
+ beforeInput: (e) => {
39843
+ var _a, _b;
39844
+ if (!this.$options.maxlength || !this._isMaxLengthMessageEnabled()) {
39845
+ return;
39846
+ }
39847
+ const target = e.target;
39848
+ const lang = data(target, 'data-lang');
39849
+ if (!lang) {
39850
+ return;
39851
+ }
39852
+ if (e.inputType && e.inputType.startsWith('delete')) {
39853
+ return;
39854
+ }
39855
+ const currentValue = val(target) || '';
39856
+ const selectionStart = typeof target.selectionStart === 'number' ? target.selectionStart : currentValue.length;
39857
+ const selectionEnd = typeof target.selectionEnd === 'number' ? target.selectionEnd : currentValue.length;
39858
+ const selectedLength = Math.max(0, selectionEnd - selectionStart);
39859
+ let insertValue = e.data || '';
39860
+ if (e.inputType === 'insertLineBreak' || e.inputType === 'insertParagraph') {
39861
+ insertValue = '\n';
39862
+ }
39863
+ if (e.inputType === 'insertFromPaste' && !insertValue) {
39864
+ const pastedText = (_b = (_a = e.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData) === null || _b === void 0 ? void 0 : _b.call(_a, 'text/plain');
39865
+ insertValue = typeof pastedText === 'string' ? pastedText : '';
39866
+ }
39867
+ // 현재 언어를 제외한 나머지 언어들의 총 입력 길이를 기준으로 남은 입력 가능 길이를 계산한다.
39868
+ const totalLengthWithoutCurrent = this._getTotalLengthWithoutLang(this.$options.value, lang);
39869
+ const allowedLengthForCurrent = Math.max(0, this.$options.maxlength - totalLengthWithoutCurrent);
39870
+ const remainingForInsert = this.$options.maxlength - totalLengthWithoutCurrent - (currentValue.length - selectedLength);
39871
+ // paste는 "붙여넣기 내용 우선 반영 + 전체 결과의 뒤를 자르기" 정책을 적용한다.
39872
+ if (e.inputType === 'insertFromPaste') {
39873
+ if (remainingForInsert <= 0) {
39874
+ e.preventDefault();
39875
+ return;
39876
+ }
39877
+ const before = currentValue.slice(0, selectionStart);
39878
+ const after = currentValue.slice(selectionEnd);
39879
+ const nextValue = `${before}${insertValue}${after}`;
39880
+ if (nextValue.length <= allowedLengthForCurrent) {
39881
+ return;
39882
+ }
39883
+ e.preventDefault();
39884
+ const clamped = nextValue.slice(0, allowedLengthForCurrent);
39885
+ val(target, clamped);
39886
+ const nextCaret = Math.min((before + insertValue).length, clamped.length);
39887
+ target.setSelectionRange(nextCaret, nextCaret);
39888
+ trigger(target, 'input');
39889
+ return;
39890
+ }
39891
+ if (remainingForInsert >= insertValue.length) {
39892
+ return;
39893
+ }
39894
+ if (remainingForInsert <= 0) {
39895
+ e.preventDefault();
39896
+ return;
39897
+ }
39898
+ // 붙여넣기/다중 입력이 한도를 넘는 경우 허용 가능한 길이만 잘라서 반영한다.
39899
+ e.preventDefault();
39900
+ const partial = insertValue.slice(0, remainingForInsert);
39901
+ target.setRangeText(partial, selectionStart, selectionEnd, 'end');
39902
+ trigger(target, 'input');
39903
+ },
39581
39904
  change: (e) => {
39582
39905
  const target = e.target;
39583
39906
  const lang = data(target, 'data-lang');
39584
- this.$options.value[lang] = val(target);
39585
- if (this.$options.maxlength) {
39586
- text$1(this.$options.delegates[lang], this.$options.value[lang].length);
39907
+ if (!lang) {
39908
+ return;
39909
+ }
39910
+ this.$options.value[lang] = val(target) || '';
39911
+ if (this.$options.maxlength && this._isMaxLengthMessageEnabled()) {
39912
+ // 총합 maxlength를 넘지 않도록 현재 언어 값만 상한선까지 보정한다.
39913
+ const totalLengthWithoutCurrent = this._getTotalLengthWithoutLang(this.$options.value, lang);
39914
+ const allowedLength = Math.max(0, this.$options.maxlength - totalLengthWithoutCurrent);
39915
+ const clampedValue = this.$options.value[lang].slice(0, allowedLength);
39916
+ if (clampedValue !== this.$options.value[lang]) {
39917
+ this.$options.value[lang] = clampedValue;
39918
+ val(target, clampedValue);
39919
+ }
39920
+ }
39921
+ if (this.$options.maxlength && this.$options.delegates[lang]) {
39922
+ const hasMaxLengthMessage = this._isMaxLengthMessageEnabled();
39923
+ if (hasMaxLengthMessage) {
39924
+ // 메시지 모드에서는 모든 탭에 동일한 "남은 글자 수" 안내를 동기화한다.
39925
+ const totalLength = this._getTotalLength(this.$options.value);
39926
+ const textValue = this._getRemainMessage(this.$options.maxlength - totalLength);
39927
+ this.$options.lang.forEach((targetLang) => {
39928
+ text$1(this.$options.delegates[targetLang], textValue);
39929
+ });
39930
+ }
39931
+ else {
39932
+ text$1(this.$options.delegates[lang], this.$options.value[lang].length);
39933
+ }
39587
39934
  }
39588
39935
  this.$event(this, 'onChange', this.$options.value);
39589
39936
  },
@@ -39600,7 +39947,7 @@ class MultiTextArea extends GNCoreInstance {
39600
39947
  }
39601
39948
  const textInput = find(`[data-lang=${lang}]`, this.$el);
39602
39949
  val(textInput, value[lang]);
39603
- trigger(textInput, 'keyup');
39950
+ trigger(textInput, 'input');
39604
39951
  });
39605
39952
  },
39606
39953
  disable: () => {
@@ -39619,6 +39966,10 @@ class MultiTextArea extends GNCoreInstance {
39619
39966
  this.config = {
39620
39967
  lang: ['en', 'ko'],
39621
39968
  value: {},
39969
+ useMaxLengthMessage: false,
39970
+ textSets: {
39971
+ maxLengthMessage: '{{maxlength}}자 입력 가능합니다.'
39972
+ },
39622
39973
  delegates: {}
39623
39974
  };
39624
39975
  this.events = {
@@ -39643,6 +39994,12 @@ class MultiTextArea extends GNCoreInstance {
39643
39994
  }
39644
39995
  template(config) {
39645
39996
  const styles = {};
39997
+ const totalLength = config.lang.reduce((sum, currentLang) => {
39998
+ const currentValue = config.value && config.value[currentLang] ? config.value[currentLang] : '';
39999
+ return sum + currentValue.length;
40000
+ }, 0);
40001
+ const hasMaxLengthMessage = this._isMaxLengthMessageEnabled();
40002
+ const remainMessage = config.maxlength ? this._getRemainMessage(config.maxlength - totalLength) : '';
39646
40003
  if (config.width) {
39647
40004
  styles.width = getUnit('width', config.width);
39648
40005
  }
@@ -39651,11 +40008,14 @@ class MultiTextArea extends GNCoreInstance {
39651
40008
  createElement$1("ul", null, config.lang.map((l, index) => (createElement$1("li", { className: index === 0 ? 'is-active' : '' },
39652
40009
  createElement$1("a", { href: '#' + this._uid + '-' + l }, l)))))),
39653
40010
  createElement$1("div", { id: this._uid + '_content' }, config.lang.map((l) => (createElement$1("div", { id: this._uid + '-' + l },
39654
- createElement$1("textarea", { className: "gn-textarea", "data-lang": l, rows: config.rows ? config.rows : '', maxLength: config.maxlength ? config.maxlength : 524288, "on-keyup": this._hidden.change, disabled: config.disabled, readOnly: config.readonly }, config.value ? config.value[l] : ''),
39655
- config.maxlength && (createElement$1("p", { className: "has-text-right has-text-size6" },
39656
- createElement$1("span", { className: "charLen", "data-lang": l }, config.value && config.value[l] ? config.value[l].length : 0),
39657
- "/",
39658
- config.maxlength))))))));
40011
+ createElement$1("textarea", { className: "gn-textarea", "data-lang": l, rows: config.rows ? config.rows : '', maxLength: config.maxlength ? config.maxlength : 524288, "on-beforeinput": this._hidden.beforeInput, "on-input": this._hidden.change, disabled: config.disabled, readOnly: config.readonly }, config.value ? config.value[l] : ''),
40012
+ config.maxlength && (createElement$1("div", { className: "has-text-size6" },
40013
+ !hasMaxLengthMessage && (createElement$1("p", null,
40014
+ createElement$1("span", { className: "charLen", "data-lang": l }, config.value && config.value[l] ? config.value[l].length : 0),
40015
+ "/",
40016
+ config.maxlength)),
40017
+ hasMaxLengthMessage && (createElement$1("p", null,
40018
+ createElement$1("span", { className: "charLen", "data-lang": l }, remainMessage)))))))))));
39659
40019
  }
39660
40020
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
39661
40021
  $render(config) {
@@ -39866,7 +40226,7 @@ class Picklist extends GNCoreInstance {
39866
40226
  : renderAsCols
39867
40227
  ? (option.cols && option.cols.length ? String(option.cols[0]) : '')
39868
40228
  : (option.text || option.value);
39869
- return (createElement$1("li", { key: index, id: this._uid + '_opt_' + index, className: 'dropdown-item' + (renderAsCols ? ' picklist-row' : '') + (option.selected ? ' is-active' : ''), "data-value": option.value, "on-click": !displayText ? null : this._hidden.toggle.bind(this), "on-dblclick": !displayText
40229
+ return (createElement$1("li", { key: index, id: this._uid + '_opt_' + index, className: 'dropdown-item' + (renderAsCols ? ' picklist-row' : '') + (option.selected ? ' is-active' : ''), "data-value": option.value, "on-click": !displayText ? null : this._hidden.toggle.bind(this), "on-mouseenter": this.$options.optionTooltip && displayText ? this._hidden.showOptionTooltip.bind(this, option) : null, "on-mouseleave": this.$options.optionTooltip ? this._hidden.hideOptionTooltip : null, "on-dblclick": !displayText
39870
40230
  ? null
39871
40231
  : this._hidden.move.bind(this, item === 'source' ? 'add' : 'remove', [
39872
40232
  {
@@ -39899,12 +40259,86 @@ class Picklist extends GNCoreInstance {
39899
40259
  removeClass(this.$el, 'is-disabled');
39900
40260
  },
39901
40261
  setSource: (data) => {
40262
+ var _a;
39902
40263
  this.$options.data.source = data;
39903
40264
  this._hidden.reRender('source');
40265
+ (_a = this.$options._tooltipCache) === null || _a === void 0 ? void 0 : _a.clear();
39904
40266
  },
39905
40267
  setTarget: (data) => {
40268
+ var _a;
39906
40269
  this.$options.data.target = data;
39907
40270
  this._hidden.reRender('target');
40271
+ (_a = this.$options._tooltipCache) === null || _a === void 0 ? void 0 : _a.clear();
40272
+ },
40273
+ showOptionTooltip: (option, e) => {
40274
+ var _a;
40275
+ if (!this.$options.optionTooltip || !this.$options._tooltipPanel)
40276
+ return;
40277
+ const panel = this.$options._tooltipPanel;
40278
+ const direction = this.$options.optionTooltip.direction || 'right';
40279
+ const rect = e.currentTarget.getBoundingClientRect();
40280
+ panel.className = `gn-tooltip is-${direction}`;
40281
+ panel.style.position = 'fixed';
40282
+ panel.style.zIndex = '9999';
40283
+ switch (direction) {
40284
+ case 'left':
40285
+ panel.style.top = (rect.top + rect.height / 2) + 'px';
40286
+ panel.style.left = rect.left + 'px';
40287
+ break;
40288
+ case 'top':
40289
+ panel.style.top = rect.top + 'px';
40290
+ panel.style.left = (rect.left + rect.width / 2) + 'px';
40291
+ break;
40292
+ case 'bottom':
40293
+ panel.style.top = rect.bottom + 'px';
40294
+ panel.style.left = (rect.left + rect.width / 2) + 'px';
40295
+ break;
40296
+ default:
40297
+ panel.style.top = (rect.top + rect.height / 2) + 'px';
40298
+ panel.style.left = (rect.right + 10) + 'px';
40299
+ }
40300
+ addClass(panel, 'is-active');
40301
+ const cacheKey = option.value;
40302
+ const cache = this.$options._tooltipCache;
40303
+ if (cache.has(cacheKey)) {
40304
+ panel.innerHTML = (_a = cache.get(cacheKey)) !== null && _a !== void 0 ? _a : '';
40305
+ return;
40306
+ }
40307
+ const { content, fetch: fetchFn } = this.$options.optionTooltip;
40308
+ if (content) {
40309
+ // content()는 개발자가 제공하는 함수 — XSS 방지는 호출자 책임
40310
+ const html = content(option);
40311
+ cache.set(cacheKey, html);
40312
+ panel.innerHTML = html;
40313
+ }
40314
+ else if (fetchFn) {
40315
+ const requestId = ++this.$options._tooltipRequestId;
40316
+ panel.innerHTML = '<div class="gn-loader is-inline"></div>';
40317
+ try {
40318
+ fetchFn(option)
40319
+ .then((html) => {
40320
+ if (requestId !== this.$options._tooltipRequestId)
40321
+ return;
40322
+ cache.set(cacheKey, html);
40323
+ if (panel.classList.contains('is-active')) {
40324
+ panel.innerHTML = html;
40325
+ }
40326
+ })
40327
+ .catch(() => {
40328
+ if (requestId === this.$options._tooltipRequestId) {
40329
+ removeClass(panel, 'is-active');
40330
+ }
40331
+ });
40332
+ }
40333
+ catch (_b) {
40334
+ removeClass(panel, 'is-active');
40335
+ }
40336
+ }
40337
+ },
40338
+ hideOptionTooltip: () => {
40339
+ if (!this.$options._tooltipPanel)
40340
+ return;
40341
+ removeClass(this.$options._tooltipPanel, 'is-active');
39908
40342
  }
39909
40343
  };
39910
40344
  this.config = {
@@ -39933,7 +40367,8 @@ class Picklist extends GNCoreInstance {
39933
40367
  hasSourceSearch: false,
39934
40368
  hasTargetSearch: false,
39935
40369
  orderable: true,
39936
- height: 150
40370
+ height: 150,
40371
+ optionTooltip: undefined
39937
40372
  };
39938
40373
  this.events = {
39939
40374
  onChange: true,
@@ -40042,6 +40477,22 @@ class Picklist extends GNCoreInstance {
40042
40477
  if (this.$options.textSets.targetCaption.length > 0) {
40043
40478
  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'))));
40044
40479
  }
40480
+ if (this.$options.optionTooltip) {
40481
+ this.$options._tooltipCache = new Map();
40482
+ this.$options._tooltipRequestId = 0;
40483
+ const direction = this.$options.optionTooltip.direction || 'right';
40484
+ const panel = document.createElement('div');
40485
+ panel.className = `gn-tooltip is-${direction}`;
40486
+ panel.style.position = 'fixed';
40487
+ panel.style.zIndex = '9999';
40488
+ document.body.appendChild(panel);
40489
+ this.$options._tooltipPanel = panel;
40490
+ this.$options._destroy = () => {
40491
+ if (panel.parentElement) {
40492
+ panel.parentElement.removeChild(panel);
40493
+ }
40494
+ };
40495
+ }
40045
40496
  }
40046
40497
  isBrandIcon(iconName) {
40047
40498
  const iconLookup = { prefix: 'fab', iconName: iconName };
@@ -40946,41 +41397,56 @@ class Tagcloud extends GNCoreInstance {
40946
41397
  class Tree extends GNCoreInstance {
40947
41398
  constructor(name, selector, options = {}) {
40948
41399
  super(name, selector, options);
41400
+ this._checkerIdSeq = 0;
40949
41401
  this._hidden = {
40950
41402
  select: (item, e) => {
40951
41403
  if (item.disabled) {
40952
41404
  return;
40953
41405
  }
41406
+ if (hasClass(this.$el, 'is-disabled')) {
41407
+ return;
41408
+ }
40954
41409
  let target = e.target;
40955
- // 트리 아이콘을 클릭한 경우, 텍스트로 타겟 변경
40956
41410
  if (this.$options.showIcon && target.tagName === 'I') {
40957
41411
  target = parent(target);
40958
41412
  }
40959
- if (!this.$options.multiple) {
41413
+ if (this.$options.hasCheck) {
41414
+ // hasCheck 시: 노드 클릭으로 체크박스 토글, is-active 미적용
41415
+ const itemEl = hasClass(target, 'tree-item') ? target : parents(target, '.tree-item')[0];
41416
+ if (!itemEl)
41417
+ return;
41418
+ const checker = find('.is-checker', itemEl);
41419
+ if (!checker)
41420
+ return;
41421
+ // 라벨 또는 input 직접 클릭 시 여기서 토글하지 않음 → input 클릭 핸들러만 한 번 실행되게 함 (이중 토글·이중 onCheck 방지)
41422
+ const labelTarget = parents(e.target, 'label')[0];
41423
+ if (e.target === checker || (labelTarget && checker.id && labelTarget.getAttribute('for') === checker.id)) {
41424
+ return;
41425
+ }
41426
+ checker.checked = !checker.checked;
41427
+ this._hidden.check.call(this, item, { target: checker, stopPropagation: () => { } });
41428
+ }
41429
+ else {
41430
+ // hasCheck 미사용 시: 노드 클릭 시 is-active 적용, onSelect 발생
40960
41431
  removeClass(findAll('.tree-item', this.$el), 'is-active');
40961
41432
  addClass(target, 'is-active');
40962
41433
  this.$event(this, 'onSelect', item, e);
40963
41434
  }
40964
- else {
40965
- toggleClass(target, 'is-active');
40966
- if (hasClass(target, 'is-active')) {
40967
- this.$event(this, 'onSelect', item, e);
40968
- }
40969
- }
40970
41435
  },
40971
41436
  addChild: (index, addData) => {
40972
41437
  const itemEl = findAll('.tree-item', this.$el)[index];
40973
41438
  const itemData = this._hidden.findData(index);
41439
+ const nextChildren = this._hidden.setPaths(addData.slice(), itemData.path);
40974
41440
  if (!itemData[this.$options.childField]) {
40975
41441
  itemData[this.$options.childField] = [];
40976
41442
  }
40977
- itemData[this.$options.childField] = itemData[this.$options.childField].concat(addData);
41443
+ itemData[this.$options.childField] = itemData[this.$options.childField].concat(nextChildren);
40978
41444
  const appendTarget = siblings(itemEl, 'ul').pop();
40979
41445
  if (!appendTarget) {
40980
41446
  this.$template.reRender(parent(itemEl), this._hidden.renderItem(itemData));
40981
41447
  }
40982
41448
  else {
40983
- addData.forEach((item) => {
41449
+ nextChildren.forEach((item) => {
40984
41450
  const newItem = document.createElement('li');
40985
41451
  append(appendTarget, newItem);
40986
41452
  this.$template.reRender(newItem, this._hidden.renderItem(item));
@@ -41011,38 +41477,59 @@ class Tree extends GNCoreInstance {
41011
41477
  },
41012
41478
  check: (item, e) => {
41013
41479
  const target = e.target;
41014
- e.stopPropagation();
41015
- findAll('.is-checker', parents(target, 'li')[0]).forEach((c) => {
41016
- c.checked = target.checked;
41017
- });
41018
- if (this.$options.checkPath) {
41019
- parents(target, 'ul')
41020
- .map((list) => siblings(list, '.tree-item').pop())
41021
- .filter((item) => item)
41022
- .forEach((item) => {
41023
- const parentChecker = find('.is-checker', item);
41024
- if (!parentChecker) {
41025
- return;
41026
- }
41027
- const parentLi = parents(item, 'li')[0];
41028
- if (!parentLi) {
41029
- return;
41030
- }
41031
- // 자식 중 하나라도 체크면 부모 체크, 전부 해제되면 부모도 해제
41032
- const descendantCheckers = findAll('.is-checker', parentLi).filter((checker) => checker !== parentChecker);
41033
- if (!descendantCheckers.length) {
41034
- return;
41035
- }
41036
- parentChecker.checked = descendantCheckers.some((checker) => checker.checked);
41037
- });
41480
+ if (hasClass(this.$el, 'is-disabled') || item.disabled) {
41481
+ if (typeof e.preventDefault === 'function')
41482
+ e.preventDefault();
41483
+ target.checked = !target.checked; // 브라우저가 이미 토글했으므로 원래대로 되돌림
41484
+ return;
41038
41485
  }
41486
+ if (typeof e.stopPropagation === 'function')
41487
+ e.stopPropagation();
41488
+ this._hidden.applyCheckedState(target, target.checked);
41039
41489
  this.$event(this, 'onCheck', item, target.checked, this._hidden.getItemIndex(target), e);
41040
41490
  },
41041
41491
  checkAll: (isChecked) => {
41492
+ if (this.$options.disabled) {
41493
+ return;
41494
+ }
41042
41495
  findAll('.is-checker', this.$el).forEach((c) => {
41496
+ if (c.disabled) {
41497
+ return;
41498
+ }
41043
41499
  c.checked = isChecked;
41044
41500
  });
41045
41501
  },
41502
+ setChecked: (targets, checked) => {
41503
+ if (!this.$options.hasCheck || this.$options.disabled) {
41504
+ return;
41505
+ }
41506
+ const normalizedTargets = Array.isArray(targets) ? targets : [targets];
41507
+ const targetSet = new Set(normalizedTargets);
41508
+ findAll('.tree-item', this.$el).forEach((itemEl, index) => {
41509
+ const itemData = this._hidden.findData(index);
41510
+ const itemValue = itemData === null || itemData === void 0 ? void 0 : itemData.value;
41511
+ if (itemValue === undefined || itemValue === null || itemValue === '') {
41512
+ return;
41513
+ }
41514
+ if (!targetSet.has(String(itemValue))) {
41515
+ return;
41516
+ }
41517
+ const checker = find('.is-checker', itemEl);
41518
+ if (!checker) {
41519
+ return;
41520
+ }
41521
+ if (checker.disabled || (itemData === null || itemData === void 0 ? void 0 : itemData.disabled)) {
41522
+ return;
41523
+ }
41524
+ checker.checked = checked;
41525
+ this._hidden.applyCheckedState(checker, checked);
41526
+ });
41527
+ },
41528
+ setCheckersDisabled: (disabled) => {
41529
+ findAll('.is-checker', this.$el).forEach((el) => {
41530
+ el.disabled = disabled;
41531
+ });
41532
+ },
41046
41533
  getChecked: (withStatus = false) => {
41047
41534
  if (!this.$options.hasCheck) {
41048
41535
  return [];
@@ -41066,14 +41553,53 @@ class Tree extends GNCoreInstance {
41066
41553
  findData.__status.isOpened = hasClass(target, 'is-open');
41067
41554
  findData.__status.isChecked = find('.is-checker', target).checked;
41068
41555
  findData.__status.isSelected = hasClass(target, 'is-active');
41069
- findData.__status.hasChildren = isArray$1(findData.child);
41556
+ findData.__status.hasChildren = isArray$1(findData[this.$options.childField]);
41070
41557
  }
41071
41558
  return findData;
41072
41559
  });
41073
41560
  },
41074
41561
  getItemIndex: (item) => {
41562
+ const itemEl = hasClass(item, 'tree-item') ? item : parents(item, '.tree-item')[0];
41563
+ if (!itemEl) {
41564
+ return -1;
41565
+ }
41075
41566
  const itemList = findAll('.tree-item', this.$el);
41076
- return itemList.findIndex((el) => el == item);
41567
+ return itemList.findIndex((el) => el == itemEl);
41568
+ },
41569
+ applyCheckedState: (checker, checked) => {
41570
+ const listItem = parents(checker, 'li')[0];
41571
+ if (!listItem) {
41572
+ return;
41573
+ }
41574
+ if (this.$options.checkChild !== false) {
41575
+ findAll('.is-checker', listItem).forEach((childChecker) => {
41576
+ if (childChecker.disabled) {
41577
+ return;
41578
+ }
41579
+ childChecker.checked = checked;
41580
+ });
41581
+ }
41582
+ if (!this.$options.checkPath) {
41583
+ return;
41584
+ }
41585
+ parents(checker, 'ul')
41586
+ .map((list) => siblings(list, '.tree-item').pop())
41587
+ .filter((item) => item)
41588
+ .forEach((item) => {
41589
+ const parentChecker = find('.is-checker', item);
41590
+ if (!parentChecker) {
41591
+ return;
41592
+ }
41593
+ const parentLi = parents(item, 'li')[0];
41594
+ if (!parentLi) {
41595
+ return;
41596
+ }
41597
+ const descendantCheckers = findAll('.is-checker', parentLi).filter((candidate) => candidate !== parentChecker);
41598
+ if (!descendantCheckers.length) {
41599
+ return;
41600
+ }
41601
+ parentChecker.checked = descendantCheckers.some((candidate) => candidate.checked);
41602
+ });
41077
41603
  },
41078
41604
  getPathArray(path) {
41079
41605
  const pathParts = path.split('/');
@@ -41152,34 +41678,46 @@ class Tree extends GNCoreInstance {
41152
41678
  }
41153
41679
  this.$event(this, 'onToggle', item, hasClass(target, 'is-open') ? 'expanded' : 'collapsed', this._hidden.getItemIndex(target), e);
41154
41680
  },
41155
- renderTree: (data) => {
41156
- return (createElement$1("ul", null, data.map((item) => {
41157
- return this._hidden.renderItem(item);
41681
+ renderTree: (data, keyPath = '') => {
41682
+ return (createElement$1("ul", null, data.map((item, idx) => {
41683
+ const itemKeyPath = keyPath ? `${keyPath}-${idx}` : `${idx}`;
41684
+ return this._hidden.renderItem(item, itemKeyPath);
41158
41685
  })));
41159
41686
  },
41160
- renderItem: (item) => {
41687
+ renderItem: (item, keyPath) => {
41161
41688
  var _a;
41689
+ const resolvedKeyPath = keyPath !== null && keyPath !== void 0 ? keyPath : `seq-${this._checkerIdSeq++}`;
41690
+ const checkerId = `${this._uid}-chk-${resolvedKeyPath}`;
41162
41691
  return (createElement$1("li", null,
41163
- createElement$1("div", { className: ['tree-item', item[this.$options.childField] ? 'has-child' : '', item.opened ? 'is-open' : '', item.actived ? ' is-active' : '', item.disabled ? 'is-disabled' : ''].join(' '), "on-click": this._hidden.select.bind(this, item), "data-path": (_a = item.path) !== null && _a !== void 0 ? _a : '', title: item.text },
41692
+ createElement$1("div", { className: [
41693
+ 'tree-item',
41694
+ item[this.$options.childField] ? 'has-child' : '',
41695
+ item.opened ? 'is-open' : '',
41696
+ !this.$options.hasCheck && item.actived ? ' is-active' : '',
41697
+ item.disabled ? 'is-disabled' : ''
41698
+ ].join(' '), "on-click": this._hidden.select.bind(this, item), "data-path": (_a = item.path) !== null && _a !== void 0 ? _a : '', title: item.text },
41164
41699
  // has child field - arrow toggle
41165
41700
  item[this.$options.childField] ? (createElement$1("div", { className: "is-toggler", "on-click": (e) => {
41166
41701
  this._hidden.toggle.call(this, item, e);
41167
41702
  } })) : (''),
41168
41703
  // has checkbox
41169
- this.$options.hasCheck && item.noCheck !== true && item.noCheck !== 'true' ? (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
41170
- createElement$1("input", { type: "checkbox", className: "is-checker", "on-click": (e) => {
41704
+ this.$options.hasCheck && item.noCheck !== true && item.noCheck !== 'true' ? (createElement$1("div", { className: "gn-checks is-small is-no-padding" },
41705
+ createElement$1("input", { type: "checkbox", className: "is-checker", id: checkerId, disabled: !!this.$options.disabled || !!item.disabled, "on-click": (e) => {
41171
41706
  this._hidden.check.call(this, item, e);
41172
- }, defaultChecked: !!item.selected }))) : (''),
41707
+ }, defaultChecked: !!item.selected }),
41708
+ createElement$1("label", { for: checkerId }, item.text))) : (''),
41173
41709
  // show icon
41174
41710
  this.$options.showIcon && !item.hideIcon ? (item.icon ? (createElement$1("span", { innerHTML: item.icon })) : (createElement$1("i", { style: { marginRight: '5px' }, className: 'far fa-' + (item.opened ? 'folder-open' : 'folder') }))) : (''),
41175
- item.text),
41176
- item[this.$options.childField] && this._hidden.renderTree(item[this.$options.childField])));
41711
+ !(this.$options.hasCheck && item.noCheck !== true && item.noCheck !== 'true') && item.text),
41712
+ item[this.$options.childField] && this._hidden.renderTree(item[this.$options.childField], resolvedKeyPath)));
41177
41713
  },
41178
- setPaths(data, basePath = '') {
41714
+ setPaths: (data, basePath = '') => {
41179
41715
  return data.map(item => {
41180
- const itemPath = basePath ? `${basePath}/${item.text}` : item.text;
41181
- const childPath = item.child ? this.setPaths(item.child, itemPath) : null;
41182
- return Object.assign(Object.assign({}, item), { path: itemPath, child: childPath });
41716
+ const itemKey = (item === null || item === void 0 ? void 0 : item.value) !== undefined && (item === null || item === void 0 ? void 0 : item.value) !== null && (item === null || item === void 0 ? void 0 : item.value) !== '' ? String(item.value) : item.text;
41717
+ const itemPath = basePath ? `${basePath}/${itemKey}` : itemKey;
41718
+ const children = item[this.$options.childField];
41719
+ const childPath = children ? this._hidden.setPaths(children, itemPath) : null;
41720
+ return Object.assign(Object.assign({}, item), { path: itemPath, [this.$options.childField]: childPath });
41183
41721
  });
41184
41722
  }
41185
41723
  };
@@ -41190,10 +41728,11 @@ class Tree extends GNCoreInstance {
41190
41728
  data: [],
41191
41729
  childField: 'child',
41192
41730
  hasCheck: false,
41193
- multiple: false,
41731
+ checkChild: true,
41194
41732
  checkPath: false,
41195
41733
  showIcon: false,
41196
- hideIcon: false
41734
+ hideIcon: false,
41735
+ disabled: false
41197
41736
  };
41198
41737
  this.events = {
41199
41738
  onSelect: true,
@@ -41218,15 +41757,20 @@ class Tree extends GNCoreInstance {
41218
41757
  this._hidden.collapseAll();
41219
41758
  },
41220
41759
  checkAll() {
41221
- if (!this.$options.hasCheck)
41760
+ if (!this.$options.hasCheck || this.$options.disabled)
41222
41761
  return;
41223
41762
  this._hidden.checkAll(true);
41224
41763
  },
41225
41764
  uncheckAll() {
41226
- if (!this.$options.hasCheck)
41765
+ if (!this.$options.hasCheck || this.$options.disabled)
41227
41766
  return;
41228
41767
  this._hidden.checkAll(false);
41229
41768
  },
41769
+ setChecked(targets, checked) {
41770
+ if (this.$options.disabled)
41771
+ return;
41772
+ this._hidden.setChecked(targets, checked);
41773
+ },
41230
41774
  getChecked(withStatus = false) {
41231
41775
  return this._hidden.getChecked(withStatus);
41232
41776
  },
@@ -41238,14 +41782,29 @@ class Tree extends GNCoreInstance {
41238
41782
  },
41239
41783
  filter(keyword) {
41240
41784
  return this._hidden.filter(keyword);
41785
+ },
41786
+ disable() {
41787
+ this.$options.disabled = true;
41788
+ addClass(this.$el, 'is-disabled');
41789
+ this._hidden.setCheckersDisabled(true);
41790
+ },
41791
+ enable() {
41792
+ this.$options.disabled = false;
41793
+ removeClass(this.$el, 'is-disabled');
41794
+ this._hidden.setCheckersDisabled(false);
41241
41795
  }
41242
41796
  };
41797
+ // multiple → hasCheck 치환(동일 기능으로 지원 X)
41798
+ if (options && options.multiple) {
41799
+ options.hasCheck = true;
41800
+ delete options.multiple;
41801
+ }
41243
41802
  this.$init(this, options);
41244
41803
  }
41245
41804
  template(config) {
41246
41805
  config.data = this._hidden.setPaths(config.data);
41247
41806
  const styles = {};
41248
- return (createElement$1("div", { id: this._uid, className: 'gn-tree' + (config.color ? ' is-' + config.color : '') + (config.type ? ' is-' + config.type : '') + (config.size ? ' is-' + config.size : ''), style: styles },
41807
+ return (createElement$1("div", { id: this._uid, className: 'gn-tree' + (config.color ? ' is-' + config.color : '') + (config.type ? ' is-' + config.type : '') + (config.size ? ' is-' + config.size : '') + (config.disabled ? ' is-disabled' : ''), style: styles },
41249
41808
  config.textSets.title && createElement$1("p", { className: "tree-label", innerHTML: config.textSets.title }),
41250
41809
  this._hidden.renderTree(config.data)));
41251
41810
  }