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
@@ -33527,11 +33527,13 @@
33527
33527
  : find('select', this.$el).value;
33528
33528
  },
33529
33529
  changeData: (data) => {
33530
+ var _a;
33530
33531
  this.$options.data = data;
33531
33532
  this._hidden.flatData();
33532
33533
  this.$options.hasSearch && this._hidden.resetSearch();
33533
33534
  this.$template.reRender(find('.dropdown-text', this.$el), this._hidden.renderLabel());
33534
33535
  this.$template.reRender(find('.dropdown-items > div:not(.dropdown-search)', this.$el), this._hidden.renderSub(data));
33536
+ (_a = this.$options._tooltipCache) === null || _a === void 0 ? void 0 : _a.clear();
33535
33537
  },
33536
33538
  search: (e) => {
33537
33539
  clearTimeout(this.$options.timer);
@@ -33647,7 +33649,7 @@
33647
33649
  (isArray$1(this.$options.value) ? this.$options.value.find((v) => v.value === option.value) : option.value === this.$options.value.value)
33648
33650
  ? ' is-active'
33649
33651
  : '') +
33650
- (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)) : '' },
33652
+ (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)) : '' },
33651
33653
  createElement$1("span", { className: "dropdown-text", innerHTML: option.html ? option.html : '' },
33652
33654
  option.html ? ('') : renderAsCols ? (createElement$1("div", { className: "gn-checks dropdown-cols" },
33653
33655
  this.$options.multiple && (createElement$1("div", { className: "is-small is-no-padding" },
@@ -33724,6 +33726,76 @@
33724
33726
  enable: () => {
33725
33727
  this.$options.disabled = false;
33726
33728
  removeClass(this.$el, 'is-disabled');
33729
+ },
33730
+ showOptionTooltip: (option, e) => {
33731
+ var _a;
33732
+ if (!this.$options.optionTooltip || !this.$options._tooltipPanel)
33733
+ return;
33734
+ const panel = this.$options._tooltipPanel;
33735
+ const direction = this.$options.optionTooltip.direction || 'right';
33736
+ const rect = e.currentTarget.getBoundingClientRect();
33737
+ panel.className = `gn-tooltip is-${direction}`;
33738
+ panel.style.position = 'fixed';
33739
+ panel.style.zIndex = '9999';
33740
+ switch (direction) {
33741
+ case 'left':
33742
+ panel.style.top = (rect.top + rect.height / 2) + 'px';
33743
+ panel.style.left = rect.left + 'px';
33744
+ break;
33745
+ case 'top':
33746
+ panel.style.top = rect.top + 'px';
33747
+ panel.style.left = (rect.left + rect.width / 2) + 'px';
33748
+ break;
33749
+ case 'bottom':
33750
+ panel.style.top = rect.bottom + 'px';
33751
+ panel.style.left = (rect.left + rect.width / 2) + 'px';
33752
+ break;
33753
+ default:
33754
+ panel.style.top = (rect.top + rect.height / 2) + 'px';
33755
+ panel.style.left = (rect.right + 10) + 'px';
33756
+ }
33757
+ addClass(panel, 'is-active');
33758
+ const cacheKey = String(option.value);
33759
+ const cache = this.$options._tooltipCache;
33760
+ if (cache.has(cacheKey)) {
33761
+ panel.innerHTML = (_a = cache.get(cacheKey)) !== null && _a !== void 0 ? _a : '';
33762
+ return;
33763
+ }
33764
+ const { content, fetch: fetchFn } = this.$options.optionTooltip;
33765
+ if (content) {
33766
+ // content()는 개발자가 제공하는 함수 — XSS 방지는 호출자 책임
33767
+ const html = content(option);
33768
+ cache.set(cacheKey, html);
33769
+ panel.innerHTML = html;
33770
+ }
33771
+ else if (fetchFn) {
33772
+ const requestId = ++this.$options._tooltipRequestId;
33773
+ panel.innerHTML = '<div class="gn-loader is-inline"></div>';
33774
+ try {
33775
+ fetchFn(option)
33776
+ .then((html) => {
33777
+ if (requestId !== this.$options._tooltipRequestId)
33778
+ return;
33779
+ cache.set(cacheKey, html);
33780
+ if (panel.classList.contains('is-active')) {
33781
+ panel.innerHTML = html;
33782
+ }
33783
+ })
33784
+ .catch(() => {
33785
+ if (requestId === this.$options._tooltipRequestId) {
33786
+ removeClass(panel, 'is-active');
33787
+ }
33788
+ });
33789
+ }
33790
+ catch (_b) {
33791
+ removeClass(panel, 'is-active');
33792
+ }
33793
+ }
33794
+ },
33795
+ hideOptionTooltip: () => {
33796
+ if (!this.$options._tooltipPanel)
33797
+ return;
33798
+ removeClass(this.$options._tooltipPanel, 'is-active');
33727
33799
  }
33728
33800
  };
33729
33801
  this.config = {
@@ -33740,7 +33812,8 @@
33740
33812
  scrollHeight: 0,
33741
33813
  timer: 0,
33742
33814
  disabled: false,
33743
- multiple: false
33815
+ multiple: false,
33816
+ optionTooltip: undefined
33744
33817
  };
33745
33818
  this.events = {
33746
33819
  onChange: true
@@ -33824,6 +33897,22 @@
33824
33897
  setValue(this.$options.value, options);
33825
33898
  }
33826
33899
  }
33900
+ if (this.$options.optionTooltip) {
33901
+ this.$options._tooltipCache = new Map();
33902
+ this.$options._tooltipRequestId = 0;
33903
+ const direction = this.$options.optionTooltip.direction || 'right';
33904
+ const panel = document.createElement('div');
33905
+ panel.className = `gn-tooltip is-${direction}`;
33906
+ panel.style.position = 'fixed';
33907
+ panel.style.zIndex = '9999';
33908
+ document.body.appendChild(panel);
33909
+ this.$options._tooltipPanel = panel;
33910
+ this.$options._destroy = () => {
33911
+ if (panel.parentElement) {
33912
+ panel.parentElement.removeChild(panel);
33913
+ }
33914
+ };
33915
+ }
33827
33916
  }
33828
33917
  isBrandIcon(iconName) {
33829
33918
  const iconLookup = { prefix: 'fab', iconName: iconName };
@@ -34555,7 +34644,7 @@
34555
34644
  const newOptions = merge(this.chartDefault, merge(chartOptions, typesDefault[this.$options.type] || {}));
34556
34645
  if (!newOptions.theme) {
34557
34646
  newOptions.theme = {
34558
- palette: 'palette4'
34647
+ palette: 'palette1'
34559
34648
  };
34560
34649
  }
34561
34650
  this.$options.chart = new ApexCharts$1(this.$el, newOptions);
@@ -37225,6 +37314,13 @@
37225
37314
  this.$event(this, 'onSort', column);
37226
37315
  },
37227
37316
  renderHeader: (columns, isReset = false) => {
37317
+ if (this._isHorizontalState()) {
37318
+ return (createElement$1("div", { className: "gn-datagrid-header-row is-horizontal" },
37319
+ 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' } },
37320
+ createElement$1("input", { type: "checkbox", className: "is-allChecker", id: this._uid + '-rows-check', "on-click": (e) => {
37321
+ this._hidden.checkAll.call(this, e);
37322
+ }, disabled: this.$options.disabled }))))));
37323
+ }
37228
37324
  this._setColumnsTemplate(isReset);
37229
37325
  return (createElement$1("div", { className: "gn-datagrid-header-row", style: {
37230
37326
  'grid-template-columns': this._columnsTemplate.join(' ')
@@ -37265,15 +37361,24 @@
37265
37361
  },
37266
37362
  renderBody: (data, columns) => {
37267
37363
  // 헤더가 숨겨진 경우에도 body 렌더 전에 템플릿 폭을 준비한다
37268
- if (!this._columnsTemplate || !this._columnsTemplate.length) {
37364
+ if (!this._isHorizontalState() && (!this._columnsTemplate || !this._columnsTemplate.length)) {
37269
37365
  this._setColumnsTemplate();
37270
37366
  }
37271
37367
  rowIdx$1 = 0;
37272
- return (createElement$1("div", { className: "gn-datagrid-body", style: {
37368
+ return (createElement$1("div", { className: 'gn-datagrid-body' + (this._isHorizontalState() ? ' is-horizontal' : ''), style: {
37369
+ 'grid-template-columns': this._isHorizontalState()
37370
+ ? this._orientationState.columns === 'auto-fit'
37371
+ ? `repeat(auto-fit, minmax(${this._orientationState.minWidth}, 1fr))`
37372
+ : `repeat(${this._orientationState.columns}, minmax(0, 1fr))`
37373
+ : '',
37374
+ gap: this._isHorizontalState() ? this._orientationState.gap : '',
37273
37375
  maxHeight: this.$options.bodyHeight ? this.$options.bodyHeight : 'auto'
37274
37376
  } }, (data === null || data === void 0 ? void 0 : data.length) ? this._hidden.renderRows(data, columns) : this._hidden.renderNodata()));
37275
37377
  },
37276
37378
  renderRows: (rows, columns, depth = 0, isOpen = false) => {
37379
+ if (this._isHorizontalState()) {
37380
+ return rows.map((row) => this._hidden.renderRow(row, columns, 0, false, false));
37381
+ }
37277
37382
  return rows.map((row) => {
37278
37383
  return row[this.$options.childField] && isArray$1(row[this.$options.childField])
37279
37384
  ? [this._hidden.renderRow(row, columns, depth, true, isOpen), this._hidden.renderRows(row[this.$options.childField], columns, depth + 1, row.isOpened)]
@@ -37282,6 +37387,23 @@
37282
37387
  },
37283
37388
  renderRow: (row, columns, depth = 0, hasChild, isOpened, isCheck = false) => {
37284
37389
  const _index = rowIdx$1++;
37390
+ const getHorizontalRowClass = () => {
37391
+ if (!this._isHorizontalState() || this._orientationState.columns === 'auto-fit') {
37392
+ return '';
37393
+ }
37394
+ const classes = ['is-horizontal'];
37395
+ if (_index % this._orientationState.columns === 0) {
37396
+ classes.push('is-horizontal-first-col');
37397
+ }
37398
+ if ((_index + 1) % this._orientationState.columns === 0 || _index === this.$options.data.length - 1) {
37399
+ classes.push('is-horizontal-last-col');
37400
+ }
37401
+ if (_index < this._orientationState.columns) {
37402
+ classes.push('is-horizontal-first-row');
37403
+ }
37404
+ return ' ' + classes.join(' ');
37405
+ };
37406
+ const horizontalClass = getHorizontalRowClass();
37285
37407
  if (row.isChecked) {
37286
37408
  isCheck = true;
37287
37409
  }
@@ -37291,76 +37413,114 @@
37291
37413
  }, "on-dblclick": (e) => {
37292
37414
  var _a;
37293
37415
  ((_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);
37294
- }, className: 'gn-datagrid-body-row' + (hasChild ? ' has-child' : '') + (row.isOpened ? '' : ' is-collapsed') + (depth > 0 && !isOpened ? ' is-hidden' : '') + (row.color ? ` ${row.color}` : ''), style: {
37295
- 'grid-template-columns': this._columnsTemplate.join(' ')
37296
- }, id: this._uid + '-row-' + _index, "data-depth": depth }, columns.map((col, idx) => {
37297
- const cellStyle = {};
37298
- if (col.bodyStyle || col.style) {
37299
- each(col.bodyStyle || col.style, (value, key) => {
37300
- if (key !== 'width') {
37301
- cellStyle[key] = value;
37302
- }
37303
- });
37304
- }
37305
- if (idx === 0 && depth !== 0) {
37306
- cellStyle.paddingLeft = depth * 15 + 10 + 'px';
37307
- }
37308
- if (isIE) {
37309
- cellStyle.display = 'inline-block';
37310
- }
37311
- if (col.key === 'btnOrder') {
37312
- cellStyle.display = 'flex';
37313
- cellStyle.padding = '0';
37314
- cellStyle['justify-content'] = 'space-evenly';
37315
- cellStyle['align-items'] = 'center';
37316
- return (createElement$1("div", { className: 'gn-datagrid-body-cell btn-container ' + (col.key ? col.key : ''), style: cellStyle, "on-click": (e) => {
37317
- this._hidden.stopRowSelectEvent(e);
37318
- } },
37319
- createElement$1("span", { className: 'gn-icon btn-order ' + (_index == 0 ? 'is-cancel' : 'is-info'), "on-click": () => {
37320
- !this.$options.disabled && this._hidden.moveRowUp.call(this, _index);
37321
- } },
37322
- createElement$1("i", { className: "fas fa-arrow-circle-up" })),
37323
- createElement$1("span", { className: 'gn-icon btn-order ' + (_index == this.$options.data.length - 1 ? 'is-cancel' : 'is-info'), "on-click": () => {
37324
- !this.$options.disabled && this._hidden.moveRowDown.call(this, _index);
37416
+ }, className: 'gn-datagrid-body-row' +
37417
+ (hasChild ? ' has-child' : '') +
37418
+ (row.isOpened ? '' : ' is-collapsed') +
37419
+ (depth > 0 && !isOpened ? ' is-hidden' : '') +
37420
+ (row.color ? ` ${row.color}` : '') +
37421
+ horizontalClass, style: {
37422
+ 'grid-template-columns': this._isHorizontalState() ? '' : this._columnsTemplate.join(' ')
37423
+ }, id: this._uid + '-row-' + _index, "data-depth": depth },
37424
+ this._isHorizontalState() && this._hidden.renderHorizontalCardHeader(row, _index, hasChild, isCheck),
37425
+ columns.map((col, idx) => {
37426
+ const cellStyle = {};
37427
+ if (col.bodyStyle || col.style) {
37428
+ each(col.bodyStyle || col.style, (value, key) => {
37429
+ if (key !== 'width') {
37430
+ cellStyle[key] = value;
37431
+ }
37432
+ });
37433
+ }
37434
+ if (idx === 0 && depth !== 0) {
37435
+ cellStyle.paddingLeft = depth * 15 + 10 + 'px';
37436
+ }
37437
+ if (isIE) {
37438
+ cellStyle.display = 'inline-block';
37439
+ }
37440
+ if (col.key === 'btnOrder') {
37441
+ cellStyle.display = 'flex';
37442
+ cellStyle.padding = '0';
37443
+ cellStyle['justify-content'] = 'space-evenly';
37444
+ cellStyle['align-items'] = 'center';
37445
+ 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) => {
37446
+ this._hidden.stopRowSelectEvent(e);
37325
37447
  } },
37326
- createElement$1("i", { className: "fas fa-arrow-circle-down" }))));
37327
- }
37328
- if (col.key === 'btnDelete') {
37329
- cellStyle.display = 'flex';
37330
- cellStyle['justify-content'] = 'center';
37331
- cellStyle['align-items'] = 'center';
37332
- return (createElement$1("div", { className: 'gn-datagrid-body-cell btn-container ' + (col.key ? col.key : ''), style: cellStyle, "on-click": (e) => {
37333
- this._hidden.stopRowSelectEvent(e);
37334
- } },
37335
- createElement$1("span", { className: "gn-icon is-small is-mono", "on-click": () => {
37336
- !this.$options.disabled && this._hidden.deleteRow.call(this, _index);
37448
+ createElement$1("span", { className: 'gn-icon btn-order ' + (_index == 0 ? 'is-cancel' : 'is-info'), "on-click": () => {
37449
+ !this.$options.disabled && this._hidden.moveRowUp.call(this, _index);
37450
+ } },
37451
+ createElement$1("i", { className: "fas fa-arrow-circle-up" })),
37452
+ createElement$1("span", { className: 'gn-icon btn-order ' + (_index == this.$options.data.length - 1 ? 'is-cancel' : 'is-info'), "on-click": () => {
37453
+ !this.$options.disabled && this._hidden.moveRowDown.call(this, _index);
37454
+ } },
37455
+ createElement$1("i", { className: "fas fa-arrow-circle-down" }))));
37456
+ }
37457
+ if (col.key === 'btnDelete') {
37458
+ cellStyle.display = 'flex';
37459
+ cellStyle['justify-content'] = 'center';
37460
+ cellStyle['align-items'] = 'center';
37461
+ 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) => {
37462
+ this._hidden.stopRowSelectEvent(e);
37337
37463
  } },
37338
- createElement$1("i", { className: "fas fa-trash" }))));
37339
- }
37340
- return (createElement$1("div", { className: 'gn-datagrid-body-cell ' +
37341
- (col.bodyClass ? col.bodyClass : col.className ? col.className : '') +
37342
- (isFunction(col.onSelect) ? ' is-selectable' : '') +
37343
- (col.isHidden ? ' is-unvisible' : ''), "data-key": col.key, style: cellStyle, "on-click": (e) => {
37344
- col.onSelect && !this.$options.disabled && this._hidden.selectCell.call(this, col, row, _index, e);
37345
- }, "on-mouseenter": (e) => {
37346
- col.onHover && !this.$options.disabled && this._hidden.hoverCell.call(this, col, row, _index, e);
37347
- }, "on-mouseleave": (e) => {
37348
- col.offHover && this._hidden.blurCell.call(this, col, row, _index, e);
37349
- }, 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)));
37350
- })));
37351
- },
37352
- renderCell: (row, col, idx, hasChild, isCheck, _index) => {
37464
+ createElement$1("span", { className: "gn-icon is-small is-mono", "on-click": () => {
37465
+ !this.$options.disabled && this._hidden.deleteRow.call(this, _index);
37466
+ } },
37467
+ createElement$1("i", { className: "fas fa-trash" }))));
37468
+ }
37469
+ return (createElement$1("div", { className: 'gn-datagrid-body-cell ' +
37470
+ (col.bodyClass ? col.bodyClass : col.className ? col.className : '') +
37471
+ (isFunction(col.onSelect) ? ' is-selectable' : '') +
37472
+ (col.isHidden ? ' is-unvisible' : '') +
37473
+ (this._isHorizontalState() ? ' is-horizontal' : ''), "data-key": col.key, style: cellStyle, "on-click": (e) => {
37474
+ col.onSelect && !this.$options.disabled && this._hidden.selectCell.call(this, col, row, _index, e);
37475
+ }, "on-mouseenter": (e) => {
37476
+ col.onHover && !this.$options.disabled && this._hidden.hoverCell.call(this, col, row, _index, e);
37477
+ }, "on-mouseleave": (e) => {
37478
+ col.offHover && this._hidden.blurCell.call(this, col, row, _index, e);
37479
+ }, 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)));
37480
+ })));
37481
+ },
37482
+ renderHorizontalCellLabel: (col) => {
37483
+ if (this._isSystemAddedColumn(col.key)) {
37484
+ return null;
37485
+ }
37486
+ return createElement$1("span", { className: "gn-datagrid-cell-label" }, col.label);
37487
+ },
37488
+ renderHorizontalCardHeader: (row, index, hasChild, isCheck) => {
37489
+ const hasHeader = this.$options.hasCheck || (this.$options.hasDelete && !this.$options.readonly);
37490
+ const showCheck = this.$options.hasCheck && row.noCheck !== true && row.noCheck !== 'true';
37491
+ const showDelete = this.$options.hasDelete && !this.$options.readonly;
37492
+ if (!hasHeader) {
37493
+ return null;
37494
+ }
37495
+ return (createElement$1("div", { className: "gn-datagrid-card-header" },
37496
+ createElement$1("div", { className: "gn-datagrid-card-header-left" }, showCheck && (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
37497
+ createElement$1("input", { type: "checkbox", id: this._uid + '-row-check-' + index, className: "is-rowChecker", "on-click": (e) => {
37498
+ this._hidden.check.call(this, row, e);
37499
+ }, defaultChecked: isCheck, disabled: this.$options.disabled || row.disabled })))),
37500
+ createElement$1("div", { className: "gn-datagrid-card-header-right" }, showDelete && (createElement$1("span", { className: "gn-icon is-small is-mono", "on-click": (e) => {
37501
+ this._hidden.stopRowSelectEvent(e);
37502
+ !this.$options.disabled && this._hidden.deleteRow.call(this, index);
37503
+ } },
37504
+ createElement$1("i", { className: "fas fa-trash" }))))));
37505
+ },
37506
+ renderCellValue: (row, col, idx, hasChild, isCheck, _index) => {
37353
37507
  return [
37354
- idx === 0 && hasChild ? (createElement$1("span", { className: "is-toggler", "on-click": (e) => {
37508
+ idx === 0 && hasChild && !this._isHorizontalState() ? (createElement$1("span", { className: "is-toggler", "on-click": (e) => {
37355
37509
  !this.$options.disabled && this._hidden.toggle.call(this, row, e);
37356
37510
  } })) : (''),
37357
- idx === 0 && this.$options.hasCheck && row.noCheck !== true && row.noCheck !== 'true' ? (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
37511
+ 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' } },
37358
37512
  createElement$1("input", { type: "checkbox", id: this._uid + '-row-check-' + _index, className: "is-rowChecker", "on-click": (e) => {
37359
37513
  this._hidden.check.call(this, row, e);
37360
37514
  }, defaultChecked: isCheck, disabled: this.$options.disabled || row.disabled }))) : (''),
37361
37515
  col.template ? createElement$1("span", { className: "gn-datagrid-cell", innerHTML: col.template(col.key, row, col) }) : row[col.key] !== undefined ? row[col.key] : ''
37362
37516
  ];
37363
37517
  },
37518
+ renderCell: (row, col, idx, hasChild, isCheck, _index) => {
37519
+ if (this._isHorizontalState()) {
37520
+ return [this._hidden.renderHorizontalCellLabel(col), createElement$1("div", { className: "gn-datagrid-cell-value" }, this._hidden.renderCellValue(row, col, idx, hasChild, isCheck, _index))];
37521
+ }
37522
+ return this._hidden.renderCellValue(row, col, idx, hasChild, isCheck, _index);
37523
+ },
37364
37524
  renderNodata: () => {
37365
37525
  return (createElement$1("div", { className: "gn-datagrid-body-row is-nodata" },
37366
37526
  createElement$1("div", { className: "gn-datagrid-body-cell has-text-center" }, this.$options.textSets.noData)));
@@ -37446,7 +37606,10 @@
37446
37606
  });
37447
37607
  this.$event(this, 'onCheckAll', e.target.checked);
37448
37608
  },
37449
- showDetail(index, headerKeys, rawDataKeys) {
37609
+ showDetail: (index, headerKeys, rawDataKeys) => {
37610
+ if (this._isHorizontalState()) {
37611
+ return;
37612
+ }
37450
37613
  const rows = findAll(`.gn-datagrid-body > .gn-datagrid-body-row`, this.$el);
37451
37614
  const row = rows[+index];
37452
37615
  if (next(row) && hasClass(next(row), 'gn-datagrid-body-row-detail')) {
@@ -37533,6 +37696,7 @@
37533
37696
  },
37534
37697
  reRender: ({ headers, data, hasCheck }) => {
37535
37698
  return new Promise(resolve => {
37699
+ this._refreshOrientationState(this.$options);
37536
37700
  if (hasCheck === undefined) {
37537
37701
  hasCheck = this.$options.hasCheck;
37538
37702
  }
@@ -37741,8 +37905,8 @@
37741
37905
  visibles.forEach((visible, index) => {
37742
37906
  const colNumber = index + 1;
37743
37907
  !visible
37744
- ? addClass(findAll('.gn-datagrid-body-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible')
37745
- : removeClass(findAll('.gn-datagrid-body-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible');
37908
+ ? addClass(findAll(`.gn-datagrid-body-cell[data-key="${this.$options.headers[index].key}"]`, this.$el), 'is-unvisible')
37909
+ : removeClass(findAll(`.gn-datagrid-body-cell[data-key="${this.$options.headers[index].key}"]`, this.$el), 'is-unvisible');
37746
37910
  !visible
37747
37911
  ? addClass(findAll('.gn-datagrid-header-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible')
37748
37912
  : removeClass(findAll('.gn-datagrid-header-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible');
@@ -37787,6 +37951,13 @@
37787
37951
  removeClass(this.$el, 'is-disabled');
37788
37952
  }
37789
37953
  };
37954
+ this._orientationState = {
37955
+ orientation: 'vertical',
37956
+ columns: 1,
37957
+ gap: 0,
37958
+ minWidth: 240,
37959
+ hasGap: false
37960
+ };
37790
37961
  this.config = {
37791
37962
  width: '100%',
37792
37963
  hasCheck: false,
@@ -37801,6 +37972,7 @@
37801
37972
  deleteLabel: '',
37802
37973
  deleteConfirmMessage: ''
37803
37974
  },
37975
+ orientation: 'vertical',
37804
37976
  childField: 'child',
37805
37977
  checkCapturing: true,
37806
37978
  sort: {
@@ -37821,10 +37993,10 @@
37821
37993
  onDelete: true
37822
37994
  };
37823
37995
  this.methods = {
37824
- reRender(options) {
37996
+ reRender: (options) => {
37825
37997
  return this._hidden.reRender(options);
37826
37998
  },
37827
- resetData(data) {
37999
+ resetData: (data) => {
37828
38000
  if (isFunction(data)) {
37829
38001
  this.$options.asyncData = data;
37830
38002
  data = [];
@@ -37833,45 +38005,60 @@
37833
38005
  }
37834
38006
  return this._hidden.resetData(arrClone(data));
37835
38007
  },
37836
- addChild(index, data) {
38008
+ addChild: (index, data) => {
38009
+ if (this._isHorizontalState()) {
38010
+ return;
38011
+ }
37837
38012
  this._hidden.addChild(index, arrClone(data));
37838
38013
  },
37839
- addRow(data) {
38014
+ addRow: (data) => {
38015
+ if (this._isHorizontalState()) {
38016
+ return;
38017
+ }
37840
38018
  this._hidden.addChild(null, arrClone(data));
37841
38019
  this.$options.data = this.$options.data.concat(data);
37842
38020
  },
37843
- expand(index) {
38021
+ expand: (index) => {
38022
+ if (this._isHorizontalState()) {
38023
+ return;
38024
+ }
37844
38025
  this._hidden.expand(index);
37845
38026
  },
37846
- collapse(index) {
38027
+ collapse: (index) => {
38028
+ if (this._isHorizontalState()) {
38029
+ return;
38030
+ }
37847
38031
  this._hidden.collapse(index);
37848
38032
  },
37849
- getChecked() {
38033
+ getChecked: () => {
37850
38034
  return this._hidden.getChecked();
37851
38035
  },
37852
- hideCols(keys) {
38036
+ hideCols: (keys) => {
37853
38037
  this._hidden.hideCols(keys);
37854
38038
  },
37855
- showCols(keys) {
38039
+ showCols: (keys) => {
37856
38040
  this._hidden.showCols(keys);
37857
38041
  },
37858
- showAll() {
38042
+ showAll: () => {
37859
38043
  this._hidden.showAll();
37860
38044
  },
37861
- showDetail(index, headerKeys, rawDataKeys) {
38045
+ showDetail: (index, headerKeys, rawDataKeys) => {
38046
+ if (this._isHorizontalState()) {
38047
+ return;
38048
+ }
37862
38049
  this._hidden.showDetail.call(this, index, headerKeys, rawDataKeys);
37863
38050
  },
37864
- selectRow(index, rowData) {
38051
+ selectRow: (index, rowData) => {
37865
38052
  let row = rowData;
37866
38053
  if (!row) {
37867
38054
  row = this.$options.data[index];
37868
38055
  }
37869
38056
  !this.$options.disable && this._hidden.selectRow(row, index);
37870
38057
  },
37871
- disable() {
38058
+ disable: () => {
37872
38059
  this._hidden.disable();
37873
38060
  },
37874
- enable() {
38061
+ enable: () => {
37875
38062
  this._hidden.enable();
37876
38063
  }
37877
38064
  };
@@ -37924,6 +38111,34 @@
37924
38111
  });
37925
38112
  }
37926
38113
  }
38114
+ // 렌더에서 바로 쓸 수 있는 orientation 상태를 만든다.
38115
+ _resolveOrientationState(config = this.$options) {
38116
+ var _a, _b, _c, _d, _e;
38117
+ const orientation = (config === null || config === void 0 ? void 0 : config.orientation) === 'horizontal' ? 'horizontal' : 'vertical';
38118
+ const optionColumns = (_a = config === null || config === void 0 ? void 0 : config.orientationOptions) === null || _a === void 0 ? void 0 : _a.columns;
38119
+ const columns = optionColumns === 'auto-fit' ? optionColumns : Number.isInteger(Number(optionColumns)) && Number(optionColumns) > 0 ? Number(optionColumns) : 1;
38120
+ 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;
38121
+ const isZeroLikeGap = optionGap === 0 || optionGap === '0' || optionGap === '0px' || optionGap === '';
38122
+ const gap = columns === 'auto-fit' && isZeroLikeGap ? '5px' : isZeroLikeGap ? 0 : typeof optionGap === 'number' ? optionGap + 'px' : optionGap;
38123
+ const rawMinWidth = (_e = (_d = config.orientationOptions) === null || _d === void 0 ? void 0 : _d.minWidth) !== null && _e !== void 0 ? _e : 240;
38124
+ const minWidth = typeof rawMinWidth === 'number' ? rawMinWidth + 'px' : rawMinWidth;
38125
+ return {
38126
+ orientation,
38127
+ columns,
38128
+ gap,
38129
+ minWidth,
38130
+ hasGap: gap !== 0
38131
+ };
38132
+ }
38133
+ // 실제 옵션이 갱신될 때 내부 orientation 상태를 새로 계산한다.
38134
+ _refreshOrientationState(config = this.$options) {
38135
+ this._orientationState = this._resolveOrientationState(config);
38136
+ return this._orientationState;
38137
+ }
38138
+ // 내부 렌더 분기에서는 orientationState만 기준으로 사용한다.
38139
+ _isHorizontalState() {
38140
+ return this._orientationState.orientation === 'horizontal';
38141
+ }
37927
38142
  _isSystemAddedColumn(key) {
37928
38143
  return ['btnOrder', 'btnDelete'].includes(key);
37929
38144
  }
@@ -37931,6 +38146,10 @@
37931
38146
  _prepareHeaders(headers = []) {
37932
38147
  const hasOrderColumn = headers.some((header) => header.key === 'btnOrder');
37933
38148
  const hasDeleteColumn = headers.some((header) => header.key === 'btnDelete');
38149
+ const horizontal = this._isHorizontalState();
38150
+ if (horizontal) {
38151
+ headers = headers.map((header) => (Object.assign(Object.assign({}, header), { sortable: false, draggable: false })));
38152
+ }
37934
38153
  if (this.$options.hasOrder && !this.$options.readonly && !hasOrderColumn) {
37935
38154
  headers.push({
37936
38155
  label: this.$options.textSets.orderLabel,
@@ -37940,7 +38159,7 @@
37940
38159
  }
37941
38160
  });
37942
38161
  }
37943
- if (this.$options.hasDelete && !this.$options.readonly && !hasDeleteColumn) {
38162
+ if (this.$options.hasDelete && !this.$options.readonly && !hasDeleteColumn && !horizontal) {
37944
38163
  headers.push({
37945
38164
  label: this.$options.textSets.deleteLabel,
37946
38165
  key: 'btnDelete',
@@ -37953,9 +38172,14 @@
37953
38172
  return headers;
37954
38173
  }
37955
38174
  template(config) {
38175
+ const resolvedConfig = Object.assign(Object.assign({}, this.$options), config);
38176
+ this._refreshOrientationState(resolvedConfig);
38177
+ const contentsMarginTop = this.$options.bodyTopMargin ? this.$options.bodyTopMargin : this._isHorizontalState() && this._orientationState.hasGap ? String(this._orientationState.gap) : '0';
37956
38178
  const styles = {};
37957
38179
  const headers = this._prepareHeaders(config.headers);
37958
38180
  return (createElement$1("div", { id: this._uid, className: 'gn-datagrid' +
38181
+ (this._isHorizontalState() ? ' is-horizontal' : '') +
38182
+ (this._isHorizontalState() && this._orientationState.hasGap ? ' has-horizontal-gap' : '') +
37959
38183
  (config.style ? ' is-' + config.style : '') +
37960
38184
  (config.isEllipsis ? ' is-ellipsis' : '') +
37961
38185
  (config.bodyHeight ? ' has-fixed-body' : '') +
@@ -37965,7 +38189,7 @@
37965
38189
  (config.data.some((d) => isArray$1(d[this.$options.childField])) ? ' has-left-padding' : '') +
37966
38190
  (config.disabled ? ' is-disabled' : ''), style: styles },
37967
38191
  config.hasHeader && createElement$1("div", { className: "gn-datagrid-header" }, this._hidden.renderHeader(headers)),
37968
- 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)),
38192
+ 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)),
37969
38193
  config.paginator /* 페이지네이터 옵션 확인 */ && createElement$1("div", { className: "gn-datagrid-footer" })));
37970
38194
  }
37971
38195
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -37982,7 +38206,12 @@
37982
38206
  }
37983
38207
  }
37984
38208
  completed() {
37985
- if (this.$options.fixHeader && this.$options.hasHeader) {
38209
+ const isHorizontal = this._isHorizontalState();
38210
+ const isVertical = !isHorizontal;
38211
+ const usesFixedHeader = this.$options.fixHeader && this.$options.hasHeader;
38212
+ const needsBlankHeader = usesFixedHeader || this.$options.bodyHeight;
38213
+ isHorizontal ? addClass(this.$el, 'is-horizontal') : removeClass(this.$el, 'is-horizontal');
38214
+ if (usesFixedHeader && isVertical) {
37986
38215
  const body = find('.gn-datagrid-contents', this.$el);
37987
38216
  const header = find('.gn-datagrid-header', this.$el);
37988
38217
  if (header) {
@@ -37995,7 +38224,7 @@
37995
38224
  css$1(body, 'margin-bottom', this.$options.bodyBottomMargin);
37996
38225
  }
37997
38226
  }
37998
- if ((this.$options.fixHeader && this.$options.hasHeader) || this.$options.bodyHeight) {
38227
+ if (isVertical && needsBlankHeader) {
37999
38228
  this._hidden.setBlankHeader();
38000
38229
  on(window, 'resize', this._hidden.setBlankHeader);
38001
38230
  }
@@ -38473,6 +38702,10 @@
38473
38702
  focus: () => {
38474
38703
  const modal = find('.modal-content', this.$el);
38475
38704
  modal.focus();
38705
+ },
38706
+ extra: (actionKey) => {
38707
+ // notify page about which extra button clicked
38708
+ this.$event(this, 'onExtra', actionKey);
38476
38709
  }
38477
38710
  };
38478
38711
  this.config = {
@@ -38490,6 +38723,7 @@
38490
38723
  hasClose: true,
38491
38724
  hasConfirm: false,
38492
38725
  hasCancel: false,
38726
+ extraButtons: [],
38493
38727
  isModal: true,
38494
38728
  minimized: false,
38495
38729
  resizable: false,
@@ -38500,7 +38734,8 @@
38500
38734
  this.events = {
38501
38735
  onClose: true,
38502
38736
  onConfirm: true,
38503
- onOpen: true
38737
+ onOpen: true,
38738
+ onExtra: true
38504
38739
  };
38505
38740
  this.methods = {
38506
38741
  close() {
@@ -38542,7 +38777,10 @@
38542
38777
  createElement$1("i", { className: "fas fa-times" })))))),
38543
38778
  createElement$1("div", { className: "modal-body", style: styles },
38544
38779
  createElement$1("div", { className: "modal-body-content", style: contStyles })),
38545
- (config.hasConfirm || config.hasCancel) /* 확인/취소 옵션 확인 */ && (createElement$1("div", { className: "modal-footer has-text-center" },
38780
+ (config.hasConfirm || config.hasCancel || (Array.isArray(config.extraButtons) && config.extraButtons.length > 0)) /* 확인/취소/추가버튼 옵션 확인 */ && (createElement$1("div", { className: "modal-footer has-text-center" },
38781
+ Array.isArray(config.extraButtons) &&
38782
+ config.extraButtons.length > 0 &&
38783
+ 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))),
38546
38784
  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)),
38547
38785
  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)))))));
38548
38786
  }
@@ -39581,15 +39819,124 @@
39581
39819
  }
39582
39820
 
39583
39821
  class MultiTextArea extends GNCoreInstance {
39822
+ _isMaxLengthMessageEnabled() {
39823
+ return !!(this.$options.maxlength && this.$options.useMaxLengthMessage);
39824
+ }
39825
+ _getTotalLength(valueSet) {
39826
+ return this.$options.lang.reduce((sum, currentLang) => {
39827
+ const currentValue = valueSet[currentLang] || '';
39828
+ return sum + currentValue.length;
39829
+ }, 0);
39830
+ }
39831
+ _getTotalLengthWithoutLang(valueSet, excludeLang) {
39832
+ return this.$options.lang.reduce((sum, currentLang) => {
39833
+ if (currentLang === excludeLang) {
39834
+ return sum;
39835
+ }
39836
+ const currentValue = valueSet[currentLang] || '';
39837
+ return sum + currentValue.length;
39838
+ }, 0);
39839
+ }
39840
+ _getRemainMessage(remain) {
39841
+ var _a, _b;
39842
+ const template = ((_b = (_a = this.$options) === null || _a === void 0 ? void 0 : _a.textSets) === null || _b === void 0 ? void 0 : _b.maxLengthMessage) || '{{maxlength}}자 입력 가능합니다.';
39843
+ return template.replace(/\{\{\s*maxlength\s*\}\}/g, String(remain));
39844
+ }
39584
39845
  constructor(name, selector, options = {}) {
39585
39846
  super(name, selector, options);
39586
39847
  this._hidden = {
39848
+ beforeInput: (e) => {
39849
+ var _a, _b;
39850
+ if (!this.$options.maxlength || !this._isMaxLengthMessageEnabled()) {
39851
+ return;
39852
+ }
39853
+ const target = e.target;
39854
+ const lang = data(target, 'data-lang');
39855
+ if (!lang) {
39856
+ return;
39857
+ }
39858
+ if (e.inputType && e.inputType.startsWith('delete')) {
39859
+ return;
39860
+ }
39861
+ const currentValue = val(target) || '';
39862
+ const selectionStart = typeof target.selectionStart === 'number' ? target.selectionStart : currentValue.length;
39863
+ const selectionEnd = typeof target.selectionEnd === 'number' ? target.selectionEnd : currentValue.length;
39864
+ const selectedLength = Math.max(0, selectionEnd - selectionStart);
39865
+ let insertValue = e.data || '';
39866
+ if (e.inputType === 'insertLineBreak' || e.inputType === 'insertParagraph') {
39867
+ insertValue = '\n';
39868
+ }
39869
+ if (e.inputType === 'insertFromPaste' && !insertValue) {
39870
+ 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');
39871
+ insertValue = typeof pastedText === 'string' ? pastedText : '';
39872
+ }
39873
+ // 현재 언어를 제외한 나머지 언어들의 총 입력 길이를 기준으로 남은 입력 가능 길이를 계산한다.
39874
+ const totalLengthWithoutCurrent = this._getTotalLengthWithoutLang(this.$options.value, lang);
39875
+ const allowedLengthForCurrent = Math.max(0, this.$options.maxlength - totalLengthWithoutCurrent);
39876
+ const remainingForInsert = this.$options.maxlength - totalLengthWithoutCurrent - (currentValue.length - selectedLength);
39877
+ // paste는 "붙여넣기 내용 우선 반영 + 전체 결과의 뒤를 자르기" 정책을 적용한다.
39878
+ if (e.inputType === 'insertFromPaste') {
39879
+ if (remainingForInsert <= 0) {
39880
+ e.preventDefault();
39881
+ return;
39882
+ }
39883
+ const before = currentValue.slice(0, selectionStart);
39884
+ const after = currentValue.slice(selectionEnd);
39885
+ const nextValue = `${before}${insertValue}${after}`;
39886
+ if (nextValue.length <= allowedLengthForCurrent) {
39887
+ return;
39888
+ }
39889
+ e.preventDefault();
39890
+ const clamped = nextValue.slice(0, allowedLengthForCurrent);
39891
+ val(target, clamped);
39892
+ const nextCaret = Math.min((before + insertValue).length, clamped.length);
39893
+ target.setSelectionRange(nextCaret, nextCaret);
39894
+ trigger(target, 'input');
39895
+ return;
39896
+ }
39897
+ if (remainingForInsert >= insertValue.length) {
39898
+ return;
39899
+ }
39900
+ if (remainingForInsert <= 0) {
39901
+ e.preventDefault();
39902
+ return;
39903
+ }
39904
+ // 붙여넣기/다중 입력이 한도를 넘는 경우 허용 가능한 길이만 잘라서 반영한다.
39905
+ e.preventDefault();
39906
+ const partial = insertValue.slice(0, remainingForInsert);
39907
+ target.setRangeText(partial, selectionStart, selectionEnd, 'end');
39908
+ trigger(target, 'input');
39909
+ },
39587
39910
  change: (e) => {
39588
39911
  const target = e.target;
39589
39912
  const lang = data(target, 'data-lang');
39590
- this.$options.value[lang] = val(target);
39591
- if (this.$options.maxlength) {
39592
- text$1(this.$options.delegates[lang], this.$options.value[lang].length);
39913
+ if (!lang) {
39914
+ return;
39915
+ }
39916
+ this.$options.value[lang] = val(target) || '';
39917
+ if (this.$options.maxlength && this._isMaxLengthMessageEnabled()) {
39918
+ // 총합 maxlength를 넘지 않도록 현재 언어 값만 상한선까지 보정한다.
39919
+ const totalLengthWithoutCurrent = this._getTotalLengthWithoutLang(this.$options.value, lang);
39920
+ const allowedLength = Math.max(0, this.$options.maxlength - totalLengthWithoutCurrent);
39921
+ const clampedValue = this.$options.value[lang].slice(0, allowedLength);
39922
+ if (clampedValue !== this.$options.value[lang]) {
39923
+ this.$options.value[lang] = clampedValue;
39924
+ val(target, clampedValue);
39925
+ }
39926
+ }
39927
+ if (this.$options.maxlength && this.$options.delegates[lang]) {
39928
+ const hasMaxLengthMessage = this._isMaxLengthMessageEnabled();
39929
+ if (hasMaxLengthMessage) {
39930
+ // 메시지 모드에서는 모든 탭에 동일한 "남은 글자 수" 안내를 동기화한다.
39931
+ const totalLength = this._getTotalLength(this.$options.value);
39932
+ const textValue = this._getRemainMessage(this.$options.maxlength - totalLength);
39933
+ this.$options.lang.forEach((targetLang) => {
39934
+ text$1(this.$options.delegates[targetLang], textValue);
39935
+ });
39936
+ }
39937
+ else {
39938
+ text$1(this.$options.delegates[lang], this.$options.value[lang].length);
39939
+ }
39593
39940
  }
39594
39941
  this.$event(this, 'onChange', this.$options.value);
39595
39942
  },
@@ -39606,7 +39953,7 @@
39606
39953
  }
39607
39954
  const textInput = find(`[data-lang=${lang}]`, this.$el);
39608
39955
  val(textInput, value[lang]);
39609
- trigger(textInput, 'keyup');
39956
+ trigger(textInput, 'input');
39610
39957
  });
39611
39958
  },
39612
39959
  disable: () => {
@@ -39625,6 +39972,10 @@
39625
39972
  this.config = {
39626
39973
  lang: ['en', 'ko'],
39627
39974
  value: {},
39975
+ useMaxLengthMessage: false,
39976
+ textSets: {
39977
+ maxLengthMessage: '{{maxlength}}자 입력 가능합니다.'
39978
+ },
39628
39979
  delegates: {}
39629
39980
  };
39630
39981
  this.events = {
@@ -39649,6 +40000,12 @@
39649
40000
  }
39650
40001
  template(config) {
39651
40002
  const styles = {};
40003
+ const totalLength = config.lang.reduce((sum, currentLang) => {
40004
+ const currentValue = config.value && config.value[currentLang] ? config.value[currentLang] : '';
40005
+ return sum + currentValue.length;
40006
+ }, 0);
40007
+ const hasMaxLengthMessage = this._isMaxLengthMessageEnabled();
40008
+ const remainMessage = config.maxlength ? this._getRemainMessage(config.maxlength - totalLength) : '';
39652
40009
  if (config.width) {
39653
40010
  styles.width = getUnit('width', config.width);
39654
40011
  }
@@ -39657,11 +40014,14 @@
39657
40014
  createElement$1("ul", null, config.lang.map((l, index) => (createElement$1("li", { className: index === 0 ? 'is-active' : '' },
39658
40015
  createElement$1("a", { href: '#' + this._uid + '-' + l }, l)))))),
39659
40016
  createElement$1("div", { id: this._uid + '_content' }, config.lang.map((l) => (createElement$1("div", { id: this._uid + '-' + l },
39660
- 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] : ''),
39661
- config.maxlength && (createElement$1("p", { className: "has-text-right has-text-size6" },
39662
- createElement$1("span", { className: "charLen", "data-lang": l }, config.value && config.value[l] ? config.value[l].length : 0),
39663
- "/",
39664
- config.maxlength))))))));
40017
+ 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] : ''),
40018
+ config.maxlength && (createElement$1("div", { className: "has-text-size6" },
40019
+ !hasMaxLengthMessage && (createElement$1("p", null,
40020
+ createElement$1("span", { className: "charLen", "data-lang": l }, config.value && config.value[l] ? config.value[l].length : 0),
40021
+ "/",
40022
+ config.maxlength)),
40023
+ hasMaxLengthMessage && (createElement$1("p", null,
40024
+ createElement$1("span", { className: "charLen", "data-lang": l }, remainMessage)))))))))));
39665
40025
  }
39666
40026
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
39667
40027
  $render(config) {
@@ -39872,7 +40232,7 @@
39872
40232
  : renderAsCols
39873
40233
  ? (option.cols && option.cols.length ? String(option.cols[0]) : '')
39874
40234
  : (option.text || option.value);
39875
- 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
40235
+ 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
39876
40236
  ? null
39877
40237
  : this._hidden.move.bind(this, item === 'source' ? 'add' : 'remove', [
39878
40238
  {
@@ -39905,12 +40265,86 @@
39905
40265
  removeClass(this.$el, 'is-disabled');
39906
40266
  },
39907
40267
  setSource: (data) => {
40268
+ var _a;
39908
40269
  this.$options.data.source = data;
39909
40270
  this._hidden.reRender('source');
40271
+ (_a = this.$options._tooltipCache) === null || _a === void 0 ? void 0 : _a.clear();
39910
40272
  },
39911
40273
  setTarget: (data) => {
40274
+ var _a;
39912
40275
  this.$options.data.target = data;
39913
40276
  this._hidden.reRender('target');
40277
+ (_a = this.$options._tooltipCache) === null || _a === void 0 ? void 0 : _a.clear();
40278
+ },
40279
+ showOptionTooltip: (option, e) => {
40280
+ var _a;
40281
+ if (!this.$options.optionTooltip || !this.$options._tooltipPanel)
40282
+ return;
40283
+ const panel = this.$options._tooltipPanel;
40284
+ const direction = this.$options.optionTooltip.direction || 'right';
40285
+ const rect = e.currentTarget.getBoundingClientRect();
40286
+ panel.className = `gn-tooltip is-${direction}`;
40287
+ panel.style.position = 'fixed';
40288
+ panel.style.zIndex = '9999';
40289
+ switch (direction) {
40290
+ case 'left':
40291
+ panel.style.top = (rect.top + rect.height / 2) + 'px';
40292
+ panel.style.left = rect.left + 'px';
40293
+ break;
40294
+ case 'top':
40295
+ panel.style.top = rect.top + 'px';
40296
+ panel.style.left = (rect.left + rect.width / 2) + 'px';
40297
+ break;
40298
+ case 'bottom':
40299
+ panel.style.top = rect.bottom + 'px';
40300
+ panel.style.left = (rect.left + rect.width / 2) + 'px';
40301
+ break;
40302
+ default:
40303
+ panel.style.top = (rect.top + rect.height / 2) + 'px';
40304
+ panel.style.left = (rect.right + 10) + 'px';
40305
+ }
40306
+ addClass(panel, 'is-active');
40307
+ const cacheKey = option.value;
40308
+ const cache = this.$options._tooltipCache;
40309
+ if (cache.has(cacheKey)) {
40310
+ panel.innerHTML = (_a = cache.get(cacheKey)) !== null && _a !== void 0 ? _a : '';
40311
+ return;
40312
+ }
40313
+ const { content, fetch: fetchFn } = this.$options.optionTooltip;
40314
+ if (content) {
40315
+ // content()는 개발자가 제공하는 함수 — XSS 방지는 호출자 책임
40316
+ const html = content(option);
40317
+ cache.set(cacheKey, html);
40318
+ panel.innerHTML = html;
40319
+ }
40320
+ else if (fetchFn) {
40321
+ const requestId = ++this.$options._tooltipRequestId;
40322
+ panel.innerHTML = '<div class="gn-loader is-inline"></div>';
40323
+ try {
40324
+ fetchFn(option)
40325
+ .then((html) => {
40326
+ if (requestId !== this.$options._tooltipRequestId)
40327
+ return;
40328
+ cache.set(cacheKey, html);
40329
+ if (panel.classList.contains('is-active')) {
40330
+ panel.innerHTML = html;
40331
+ }
40332
+ })
40333
+ .catch(() => {
40334
+ if (requestId === this.$options._tooltipRequestId) {
40335
+ removeClass(panel, 'is-active');
40336
+ }
40337
+ });
40338
+ }
40339
+ catch (_b) {
40340
+ removeClass(panel, 'is-active');
40341
+ }
40342
+ }
40343
+ },
40344
+ hideOptionTooltip: () => {
40345
+ if (!this.$options._tooltipPanel)
40346
+ return;
40347
+ removeClass(this.$options._tooltipPanel, 'is-active');
39914
40348
  }
39915
40349
  };
39916
40350
  this.config = {
@@ -39939,7 +40373,8 @@
39939
40373
  hasSourceSearch: false,
39940
40374
  hasTargetSearch: false,
39941
40375
  orderable: true,
39942
- height: 150
40376
+ height: 150,
40377
+ optionTooltip: undefined
39943
40378
  };
39944
40379
  this.events = {
39945
40380
  onChange: true,
@@ -40048,6 +40483,22 @@
40048
40483
  if (this.$options.textSets.targetCaption.length > 0) {
40049
40484
  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'))));
40050
40485
  }
40486
+ if (this.$options.optionTooltip) {
40487
+ this.$options._tooltipCache = new Map();
40488
+ this.$options._tooltipRequestId = 0;
40489
+ const direction = this.$options.optionTooltip.direction || 'right';
40490
+ const panel = document.createElement('div');
40491
+ panel.className = `gn-tooltip is-${direction}`;
40492
+ panel.style.position = 'fixed';
40493
+ panel.style.zIndex = '9999';
40494
+ document.body.appendChild(panel);
40495
+ this.$options._tooltipPanel = panel;
40496
+ this.$options._destroy = () => {
40497
+ if (panel.parentElement) {
40498
+ panel.parentElement.removeChild(panel);
40499
+ }
40500
+ };
40501
+ }
40051
40502
  }
40052
40503
  isBrandIcon(iconName) {
40053
40504
  const iconLookup = { prefix: 'fab', iconName: iconName };
@@ -40952,41 +41403,56 @@
40952
41403
  class Tree extends GNCoreInstance {
40953
41404
  constructor(name, selector, options = {}) {
40954
41405
  super(name, selector, options);
41406
+ this._checkerIdSeq = 0;
40955
41407
  this._hidden = {
40956
41408
  select: (item, e) => {
40957
41409
  if (item.disabled) {
40958
41410
  return;
40959
41411
  }
41412
+ if (hasClass(this.$el, 'is-disabled')) {
41413
+ return;
41414
+ }
40960
41415
  let target = e.target;
40961
- // 트리 아이콘을 클릭한 경우, 텍스트로 타겟 변경
40962
41416
  if (this.$options.showIcon && target.tagName === 'I') {
40963
41417
  target = parent(target);
40964
41418
  }
40965
- if (!this.$options.multiple) {
41419
+ if (this.$options.hasCheck) {
41420
+ // hasCheck 시: 노드 클릭으로 체크박스 토글, is-active 미적용
41421
+ const itemEl = hasClass(target, 'tree-item') ? target : parents(target, '.tree-item')[0];
41422
+ if (!itemEl)
41423
+ return;
41424
+ const checker = find('.is-checker', itemEl);
41425
+ if (!checker)
41426
+ return;
41427
+ // 라벨 또는 input 직접 클릭 시 여기서 토글하지 않음 → input 클릭 핸들러만 한 번 실행되게 함 (이중 토글·이중 onCheck 방지)
41428
+ const labelTarget = parents(e.target, 'label')[0];
41429
+ if (e.target === checker || (labelTarget && checker.id && labelTarget.getAttribute('for') === checker.id)) {
41430
+ return;
41431
+ }
41432
+ checker.checked = !checker.checked;
41433
+ this._hidden.check.call(this, item, { target: checker, stopPropagation: () => { } });
41434
+ }
41435
+ else {
41436
+ // hasCheck 미사용 시: 노드 클릭 시 is-active 적용, onSelect 발생
40966
41437
  removeClass(findAll('.tree-item', this.$el), 'is-active');
40967
41438
  addClass(target, 'is-active');
40968
41439
  this.$event(this, 'onSelect', item, e);
40969
41440
  }
40970
- else {
40971
- toggleClass(target, 'is-active');
40972
- if (hasClass(target, 'is-active')) {
40973
- this.$event(this, 'onSelect', item, e);
40974
- }
40975
- }
40976
41441
  },
40977
41442
  addChild: (index, addData) => {
40978
41443
  const itemEl = findAll('.tree-item', this.$el)[index];
40979
41444
  const itemData = this._hidden.findData(index);
41445
+ const nextChildren = this._hidden.setPaths(addData.slice(), itemData.path);
40980
41446
  if (!itemData[this.$options.childField]) {
40981
41447
  itemData[this.$options.childField] = [];
40982
41448
  }
40983
- itemData[this.$options.childField] = itemData[this.$options.childField].concat(addData);
41449
+ itemData[this.$options.childField] = itemData[this.$options.childField].concat(nextChildren);
40984
41450
  const appendTarget = siblings(itemEl, 'ul').pop();
40985
41451
  if (!appendTarget) {
40986
41452
  this.$template.reRender(parent(itemEl), this._hidden.renderItem(itemData));
40987
41453
  }
40988
41454
  else {
40989
- addData.forEach((item) => {
41455
+ nextChildren.forEach((item) => {
40990
41456
  const newItem = document.createElement('li');
40991
41457
  append(appendTarget, newItem);
40992
41458
  this.$template.reRender(newItem, this._hidden.renderItem(item));
@@ -41017,38 +41483,59 @@
41017
41483
  },
41018
41484
  check: (item, e) => {
41019
41485
  const target = e.target;
41020
- e.stopPropagation();
41021
- findAll('.is-checker', parents(target, 'li')[0]).forEach((c) => {
41022
- c.checked = target.checked;
41023
- });
41024
- if (this.$options.checkPath) {
41025
- parents(target, 'ul')
41026
- .map((list) => siblings(list, '.tree-item').pop())
41027
- .filter((item) => item)
41028
- .forEach((item) => {
41029
- const parentChecker = find('.is-checker', item);
41030
- if (!parentChecker) {
41031
- return;
41032
- }
41033
- const parentLi = parents(item, 'li')[0];
41034
- if (!parentLi) {
41035
- return;
41036
- }
41037
- // 자식 중 하나라도 체크면 부모 체크, 전부 해제되면 부모도 해제
41038
- const descendantCheckers = findAll('.is-checker', parentLi).filter((checker) => checker !== parentChecker);
41039
- if (!descendantCheckers.length) {
41040
- return;
41041
- }
41042
- parentChecker.checked = descendantCheckers.some((checker) => checker.checked);
41043
- });
41486
+ if (hasClass(this.$el, 'is-disabled') || item.disabled) {
41487
+ if (typeof e.preventDefault === 'function')
41488
+ e.preventDefault();
41489
+ target.checked = !target.checked; // 브라우저가 이미 토글했으므로 원래대로 되돌림
41490
+ return;
41044
41491
  }
41492
+ if (typeof e.stopPropagation === 'function')
41493
+ e.stopPropagation();
41494
+ this._hidden.applyCheckedState(target, target.checked);
41045
41495
  this.$event(this, 'onCheck', item, target.checked, this._hidden.getItemIndex(target), e);
41046
41496
  },
41047
41497
  checkAll: (isChecked) => {
41498
+ if (this.$options.disabled) {
41499
+ return;
41500
+ }
41048
41501
  findAll('.is-checker', this.$el).forEach((c) => {
41502
+ if (c.disabled) {
41503
+ return;
41504
+ }
41049
41505
  c.checked = isChecked;
41050
41506
  });
41051
41507
  },
41508
+ setChecked: (targets, checked) => {
41509
+ if (!this.$options.hasCheck || this.$options.disabled) {
41510
+ return;
41511
+ }
41512
+ const normalizedTargets = Array.isArray(targets) ? targets : [targets];
41513
+ const targetSet = new Set(normalizedTargets);
41514
+ findAll('.tree-item', this.$el).forEach((itemEl, index) => {
41515
+ const itemData = this._hidden.findData(index);
41516
+ const itemValue = itemData === null || itemData === void 0 ? void 0 : itemData.value;
41517
+ if (itemValue === undefined || itemValue === null || itemValue === '') {
41518
+ return;
41519
+ }
41520
+ if (!targetSet.has(String(itemValue))) {
41521
+ return;
41522
+ }
41523
+ const checker = find('.is-checker', itemEl);
41524
+ if (!checker) {
41525
+ return;
41526
+ }
41527
+ if (checker.disabled || (itemData === null || itemData === void 0 ? void 0 : itemData.disabled)) {
41528
+ return;
41529
+ }
41530
+ checker.checked = checked;
41531
+ this._hidden.applyCheckedState(checker, checked);
41532
+ });
41533
+ },
41534
+ setCheckersDisabled: (disabled) => {
41535
+ findAll('.is-checker', this.$el).forEach((el) => {
41536
+ el.disabled = disabled;
41537
+ });
41538
+ },
41052
41539
  getChecked: (withStatus = false) => {
41053
41540
  if (!this.$options.hasCheck) {
41054
41541
  return [];
@@ -41072,14 +41559,53 @@
41072
41559
  findData.__status.isOpened = hasClass(target, 'is-open');
41073
41560
  findData.__status.isChecked = find('.is-checker', target).checked;
41074
41561
  findData.__status.isSelected = hasClass(target, 'is-active');
41075
- findData.__status.hasChildren = isArray$1(findData.child);
41562
+ findData.__status.hasChildren = isArray$1(findData[this.$options.childField]);
41076
41563
  }
41077
41564
  return findData;
41078
41565
  });
41079
41566
  },
41080
41567
  getItemIndex: (item) => {
41568
+ const itemEl = hasClass(item, 'tree-item') ? item : parents(item, '.tree-item')[0];
41569
+ if (!itemEl) {
41570
+ return -1;
41571
+ }
41081
41572
  const itemList = findAll('.tree-item', this.$el);
41082
- return itemList.findIndex((el) => el == item);
41573
+ return itemList.findIndex((el) => el == itemEl);
41574
+ },
41575
+ applyCheckedState: (checker, checked) => {
41576
+ const listItem = parents(checker, 'li')[0];
41577
+ if (!listItem) {
41578
+ return;
41579
+ }
41580
+ if (this.$options.checkChild !== false) {
41581
+ findAll('.is-checker', listItem).forEach((childChecker) => {
41582
+ if (childChecker.disabled) {
41583
+ return;
41584
+ }
41585
+ childChecker.checked = checked;
41586
+ });
41587
+ }
41588
+ if (!this.$options.checkPath) {
41589
+ return;
41590
+ }
41591
+ parents(checker, 'ul')
41592
+ .map((list) => siblings(list, '.tree-item').pop())
41593
+ .filter((item) => item)
41594
+ .forEach((item) => {
41595
+ const parentChecker = find('.is-checker', item);
41596
+ if (!parentChecker) {
41597
+ return;
41598
+ }
41599
+ const parentLi = parents(item, 'li')[0];
41600
+ if (!parentLi) {
41601
+ return;
41602
+ }
41603
+ const descendantCheckers = findAll('.is-checker', parentLi).filter((candidate) => candidate !== parentChecker);
41604
+ if (!descendantCheckers.length) {
41605
+ return;
41606
+ }
41607
+ parentChecker.checked = descendantCheckers.some((candidate) => candidate.checked);
41608
+ });
41083
41609
  },
41084
41610
  getPathArray(path) {
41085
41611
  const pathParts = path.split('/');
@@ -41158,34 +41684,46 @@
41158
41684
  }
41159
41685
  this.$event(this, 'onToggle', item, hasClass(target, 'is-open') ? 'expanded' : 'collapsed', this._hidden.getItemIndex(target), e);
41160
41686
  },
41161
- renderTree: (data) => {
41162
- return (createElement$1("ul", null, data.map((item) => {
41163
- return this._hidden.renderItem(item);
41687
+ renderTree: (data, keyPath = '') => {
41688
+ return (createElement$1("ul", null, data.map((item, idx) => {
41689
+ const itemKeyPath = keyPath ? `${keyPath}-${idx}` : `${idx}`;
41690
+ return this._hidden.renderItem(item, itemKeyPath);
41164
41691
  })));
41165
41692
  },
41166
- renderItem: (item) => {
41693
+ renderItem: (item, keyPath) => {
41167
41694
  var _a;
41695
+ const resolvedKeyPath = keyPath !== null && keyPath !== void 0 ? keyPath : `seq-${this._checkerIdSeq++}`;
41696
+ const checkerId = `${this._uid}-chk-${resolvedKeyPath}`;
41168
41697
  return (createElement$1("li", null,
41169
- 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 },
41698
+ createElement$1("div", { className: [
41699
+ 'tree-item',
41700
+ item[this.$options.childField] ? 'has-child' : '',
41701
+ item.opened ? 'is-open' : '',
41702
+ !this.$options.hasCheck && item.actived ? ' is-active' : '',
41703
+ item.disabled ? 'is-disabled' : ''
41704
+ ].join(' '), "on-click": this._hidden.select.bind(this, item), "data-path": (_a = item.path) !== null && _a !== void 0 ? _a : '', title: item.text },
41170
41705
  // has child field - arrow toggle
41171
41706
  item[this.$options.childField] ? (createElement$1("div", { className: "is-toggler", "on-click": (e) => {
41172
41707
  this._hidden.toggle.call(this, item, e);
41173
41708
  } })) : (''),
41174
41709
  // has checkbox
41175
- this.$options.hasCheck && item.noCheck !== true && item.noCheck !== 'true' ? (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
41176
- createElement$1("input", { type: "checkbox", className: "is-checker", "on-click": (e) => {
41710
+ this.$options.hasCheck && item.noCheck !== true && item.noCheck !== 'true' ? (createElement$1("div", { className: "gn-checks is-small is-no-padding" },
41711
+ createElement$1("input", { type: "checkbox", className: "is-checker", id: checkerId, disabled: !!this.$options.disabled || !!item.disabled, "on-click": (e) => {
41177
41712
  this._hidden.check.call(this, item, e);
41178
- }, defaultChecked: !!item.selected }))) : (''),
41713
+ }, defaultChecked: !!item.selected }),
41714
+ createElement$1("label", { for: checkerId }, item.text))) : (''),
41179
41715
  // show icon
41180
41716
  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') }))) : (''),
41181
- item.text),
41182
- item[this.$options.childField] && this._hidden.renderTree(item[this.$options.childField])));
41717
+ !(this.$options.hasCheck && item.noCheck !== true && item.noCheck !== 'true') && item.text),
41718
+ item[this.$options.childField] && this._hidden.renderTree(item[this.$options.childField], resolvedKeyPath)));
41183
41719
  },
41184
- setPaths(data, basePath = '') {
41720
+ setPaths: (data, basePath = '') => {
41185
41721
  return data.map(item => {
41186
- const itemPath = basePath ? `${basePath}/${item.text}` : item.text;
41187
- const childPath = item.child ? this.setPaths(item.child, itemPath) : null;
41188
- return Object.assign(Object.assign({}, item), { path: itemPath, child: childPath });
41722
+ 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;
41723
+ const itemPath = basePath ? `${basePath}/${itemKey}` : itemKey;
41724
+ const children = item[this.$options.childField];
41725
+ const childPath = children ? this._hidden.setPaths(children, itemPath) : null;
41726
+ return Object.assign(Object.assign({}, item), { path: itemPath, [this.$options.childField]: childPath });
41189
41727
  });
41190
41728
  }
41191
41729
  };
@@ -41196,10 +41734,11 @@
41196
41734
  data: [],
41197
41735
  childField: 'child',
41198
41736
  hasCheck: false,
41199
- multiple: false,
41737
+ checkChild: true,
41200
41738
  checkPath: false,
41201
41739
  showIcon: false,
41202
- hideIcon: false
41740
+ hideIcon: false,
41741
+ disabled: false
41203
41742
  };
41204
41743
  this.events = {
41205
41744
  onSelect: true,
@@ -41224,15 +41763,20 @@
41224
41763
  this._hidden.collapseAll();
41225
41764
  },
41226
41765
  checkAll() {
41227
- if (!this.$options.hasCheck)
41766
+ if (!this.$options.hasCheck || this.$options.disabled)
41228
41767
  return;
41229
41768
  this._hidden.checkAll(true);
41230
41769
  },
41231
41770
  uncheckAll() {
41232
- if (!this.$options.hasCheck)
41771
+ if (!this.$options.hasCheck || this.$options.disabled)
41233
41772
  return;
41234
41773
  this._hidden.checkAll(false);
41235
41774
  },
41775
+ setChecked(targets, checked) {
41776
+ if (this.$options.disabled)
41777
+ return;
41778
+ this._hidden.setChecked(targets, checked);
41779
+ },
41236
41780
  getChecked(withStatus = false) {
41237
41781
  return this._hidden.getChecked(withStatus);
41238
41782
  },
@@ -41244,14 +41788,29 @@
41244
41788
  },
41245
41789
  filter(keyword) {
41246
41790
  return this._hidden.filter(keyword);
41791
+ },
41792
+ disable() {
41793
+ this.$options.disabled = true;
41794
+ addClass(this.$el, 'is-disabled');
41795
+ this._hidden.setCheckersDisabled(true);
41796
+ },
41797
+ enable() {
41798
+ this.$options.disabled = false;
41799
+ removeClass(this.$el, 'is-disabled');
41800
+ this._hidden.setCheckersDisabled(false);
41247
41801
  }
41248
41802
  };
41803
+ // multiple → hasCheck 치환(동일 기능으로 지원 X)
41804
+ if (options && options.multiple) {
41805
+ options.hasCheck = true;
41806
+ delete options.multiple;
41807
+ }
41249
41808
  this.$init(this, options);
41250
41809
  }
41251
41810
  template(config) {
41252
41811
  config.data = this._hidden.setPaths(config.data);
41253
41812
  const styles = {};
41254
- 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 },
41813
+ 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 },
41255
41814
  config.textSets.title && createElement$1("p", { className: "tree-label", innerHTML: config.textSets.title }),
41256
41815
  this._hidden.renderTree(config.data)));
41257
41816
  }