gnui 1.2.20 → 1.2.21

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 +528 -149
  3. package/dist/js/gnui.js +528 -149
  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 +155 -9
  13. package/styleguide/assets/js/gnui.js +528 -149
  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 +1 -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 +1 -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 +252 -29
  79. package/styleguide/tag/v.0.1.0/index.html +312 -30
package/dist/js/gnui.js CHANGED
@@ -34555,7 +34555,7 @@
34555
34555
  const newOptions = merge(this.chartDefault, merge(chartOptions, typesDefault[this.$options.type] || {}));
34556
34556
  if (!newOptions.theme) {
34557
34557
  newOptions.theme = {
34558
- palette: 'palette4'
34558
+ palette: 'palette1'
34559
34559
  };
34560
34560
  }
34561
34561
  this.$options.chart = new ApexCharts$1(this.$el, newOptions);
@@ -37225,6 +37225,13 @@
37225
37225
  this.$event(this, 'onSort', column);
37226
37226
  },
37227
37227
  renderHeader: (columns, isReset = false) => {
37228
+ if (this._isHorizontalState()) {
37229
+ return (createElement$1("div", { className: "gn-datagrid-header-row is-horizontal" },
37230
+ 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' } },
37231
+ createElement$1("input", { type: "checkbox", className: "is-allChecker", id: this._uid + '-rows-check', "on-click": (e) => {
37232
+ this._hidden.checkAll.call(this, e);
37233
+ }, disabled: this.$options.disabled }))))));
37234
+ }
37228
37235
  this._setColumnsTemplate(isReset);
37229
37236
  return (createElement$1("div", { className: "gn-datagrid-header-row", style: {
37230
37237
  'grid-template-columns': this._columnsTemplate.join(' ')
@@ -37265,15 +37272,24 @@
37265
37272
  },
37266
37273
  renderBody: (data, columns) => {
37267
37274
  // 헤더가 숨겨진 경우에도 body 렌더 전에 템플릿 폭을 준비한다
37268
- if (!this._columnsTemplate || !this._columnsTemplate.length) {
37275
+ if (!this._isHorizontalState() && (!this._columnsTemplate || !this._columnsTemplate.length)) {
37269
37276
  this._setColumnsTemplate();
37270
37277
  }
37271
37278
  rowIdx$1 = 0;
37272
- return (createElement$1("div", { className: "gn-datagrid-body", style: {
37279
+ return (createElement$1("div", { className: 'gn-datagrid-body' + (this._isHorizontalState() ? ' is-horizontal' : ''), style: {
37280
+ 'grid-template-columns': this._isHorizontalState()
37281
+ ? this._orientationState.columns === 'auto-fit'
37282
+ ? `repeat(auto-fit, minmax(${this._orientationState.minWidth}, 1fr))`
37283
+ : `repeat(${this._orientationState.columns}, minmax(0, 1fr))`
37284
+ : '',
37285
+ gap: this._isHorizontalState() ? this._orientationState.gap : '',
37273
37286
  maxHeight: this.$options.bodyHeight ? this.$options.bodyHeight : 'auto'
37274
37287
  } }, (data === null || data === void 0 ? void 0 : data.length) ? this._hidden.renderRows(data, columns) : this._hidden.renderNodata()));
37275
37288
  },
37276
37289
  renderRows: (rows, columns, depth = 0, isOpen = false) => {
37290
+ if (this._isHorizontalState()) {
37291
+ return rows.map((row) => this._hidden.renderRow(row, columns, 0, false, false));
37292
+ }
37277
37293
  return rows.map((row) => {
37278
37294
  return row[this.$options.childField] && isArray$1(row[this.$options.childField])
37279
37295
  ? [this._hidden.renderRow(row, columns, depth, true, isOpen), this._hidden.renderRows(row[this.$options.childField], columns, depth + 1, row.isOpened)]
@@ -37282,6 +37298,23 @@
37282
37298
  },
37283
37299
  renderRow: (row, columns, depth = 0, hasChild, isOpened, isCheck = false) => {
37284
37300
  const _index = rowIdx$1++;
37301
+ const getHorizontalRowClass = () => {
37302
+ if (!this._isHorizontalState() || this._orientationState.columns === 'auto-fit') {
37303
+ return '';
37304
+ }
37305
+ const classes = ['is-horizontal'];
37306
+ if (_index % this._orientationState.columns === 0) {
37307
+ classes.push('is-horizontal-first-col');
37308
+ }
37309
+ if ((_index + 1) % this._orientationState.columns === 0 || _index === this.$options.data.length - 1) {
37310
+ classes.push('is-horizontal-last-col');
37311
+ }
37312
+ if (_index < this._orientationState.columns) {
37313
+ classes.push('is-horizontal-first-row');
37314
+ }
37315
+ return ' ' + classes.join(' ');
37316
+ };
37317
+ const horizontalClass = getHorizontalRowClass();
37285
37318
  if (row.isChecked) {
37286
37319
  isCheck = true;
37287
37320
  }
@@ -37291,76 +37324,114 @@
37291
37324
  }, "on-dblclick": (e) => {
37292
37325
  var _a;
37293
37326
  ((_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);
37327
+ }, className: 'gn-datagrid-body-row' +
37328
+ (hasChild ? ' has-child' : '') +
37329
+ (row.isOpened ? '' : ' is-collapsed') +
37330
+ (depth > 0 && !isOpened ? ' is-hidden' : '') +
37331
+ (row.color ? ` ${row.color}` : '') +
37332
+ horizontalClass, style: {
37333
+ 'grid-template-columns': this._isHorizontalState() ? '' : this._columnsTemplate.join(' ')
37334
+ }, id: this._uid + '-row-' + _index, "data-depth": depth },
37335
+ this._isHorizontalState() && this._hidden.renderHorizontalCardHeader(row, _index, hasChild, isCheck),
37336
+ columns.map((col, idx) => {
37337
+ const cellStyle = {};
37338
+ if (col.bodyStyle || col.style) {
37339
+ each(col.bodyStyle || col.style, (value, key) => {
37340
+ if (key !== 'width') {
37341
+ cellStyle[key] = value;
37342
+ }
37343
+ });
37344
+ }
37345
+ if (idx === 0 && depth !== 0) {
37346
+ cellStyle.paddingLeft = depth * 15 + 10 + 'px';
37347
+ }
37348
+ if (isIE) {
37349
+ cellStyle.display = 'inline-block';
37350
+ }
37351
+ if (col.key === 'btnOrder') {
37352
+ cellStyle.display = 'flex';
37353
+ cellStyle.padding = '0';
37354
+ cellStyle['justify-content'] = 'space-evenly';
37355
+ cellStyle['align-items'] = 'center';
37356
+ 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) => {
37357
+ this._hidden.stopRowSelectEvent(e);
37325
37358
  } },
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);
37359
+ createElement$1("span", { className: 'gn-icon btn-order ' + (_index == 0 ? 'is-cancel' : 'is-info'), "on-click": () => {
37360
+ !this.$options.disabled && this._hidden.moveRowUp.call(this, _index);
37361
+ } },
37362
+ createElement$1("i", { className: "fas fa-arrow-circle-up" })),
37363
+ createElement$1("span", { className: 'gn-icon btn-order ' + (_index == this.$options.data.length - 1 ? 'is-cancel' : 'is-info'), "on-click": () => {
37364
+ !this.$options.disabled && this._hidden.moveRowDown.call(this, _index);
37365
+ } },
37366
+ createElement$1("i", { className: "fas fa-arrow-circle-down" }))));
37367
+ }
37368
+ if (col.key === 'btnDelete') {
37369
+ cellStyle.display = 'flex';
37370
+ cellStyle['justify-content'] = 'center';
37371
+ cellStyle['align-items'] = 'center';
37372
+ 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) => {
37373
+ this._hidden.stopRowSelectEvent(e);
37337
37374
  } },
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) => {
37375
+ createElement$1("span", { className: "gn-icon is-small is-mono", "on-click": () => {
37376
+ !this.$options.disabled && this._hidden.deleteRow.call(this, _index);
37377
+ } },
37378
+ createElement$1("i", { className: "fas fa-trash" }))));
37379
+ }
37380
+ return (createElement$1("div", { className: 'gn-datagrid-body-cell ' +
37381
+ (col.bodyClass ? col.bodyClass : col.className ? col.className : '') +
37382
+ (isFunction(col.onSelect) ? ' is-selectable' : '') +
37383
+ (col.isHidden ? ' is-unvisible' : '') +
37384
+ (this._isHorizontalState() ? ' is-horizontal' : ''), "data-key": col.key, style: cellStyle, "on-click": (e) => {
37385
+ col.onSelect && !this.$options.disabled && this._hidden.selectCell.call(this, col, row, _index, e);
37386
+ }, "on-mouseenter": (e) => {
37387
+ col.onHover && !this.$options.disabled && this._hidden.hoverCell.call(this, col, row, _index, e);
37388
+ }, "on-mouseleave": (e) => {
37389
+ col.offHover && this._hidden.blurCell.call(this, col, row, _index, e);
37390
+ }, 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)));
37391
+ })));
37392
+ },
37393
+ renderHorizontalCellLabel: (col) => {
37394
+ if (this._isSystemAddedColumn(col.key)) {
37395
+ return null;
37396
+ }
37397
+ return createElement$1("span", { className: "gn-datagrid-cell-label" }, col.label);
37398
+ },
37399
+ renderHorizontalCardHeader: (row, index, hasChild, isCheck) => {
37400
+ const hasHeader = this.$options.hasCheck || (this.$options.hasDelete && !this.$options.readonly);
37401
+ const showCheck = this.$options.hasCheck && row.noCheck !== true && row.noCheck !== 'true';
37402
+ const showDelete = this.$options.hasDelete && !this.$options.readonly;
37403
+ if (!hasHeader) {
37404
+ return null;
37405
+ }
37406
+ return (createElement$1("div", { className: "gn-datagrid-card-header" },
37407
+ createElement$1("div", { className: "gn-datagrid-card-header-left" }, showCheck && (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
37408
+ createElement$1("input", { type: "checkbox", id: this._uid + '-row-check-' + index, className: "is-rowChecker", "on-click": (e) => {
37409
+ this._hidden.check.call(this, row, e);
37410
+ }, defaultChecked: isCheck, disabled: this.$options.disabled || row.disabled })))),
37411
+ createElement$1("div", { className: "gn-datagrid-card-header-right" }, showDelete && (createElement$1("span", { className: "gn-icon is-small is-mono", "on-click": (e) => {
37412
+ this._hidden.stopRowSelectEvent(e);
37413
+ !this.$options.disabled && this._hidden.deleteRow.call(this, index);
37414
+ } },
37415
+ createElement$1("i", { className: "fas fa-trash" }))))));
37416
+ },
37417
+ renderCellValue: (row, col, idx, hasChild, isCheck, _index) => {
37353
37418
  return [
37354
- idx === 0 && hasChild ? (createElement$1("span", { className: "is-toggler", "on-click": (e) => {
37419
+ idx === 0 && hasChild && !this._isHorizontalState() ? (createElement$1("span", { className: "is-toggler", "on-click": (e) => {
37355
37420
  !this.$options.disabled && this._hidden.toggle.call(this, row, e);
37356
37421
  } })) : (''),
37357
- idx === 0 && this.$options.hasCheck && row.noCheck !== true && row.noCheck !== 'true' ? (createElement$1("label", { className: "gn-checkbox is-no-padding", style: { width: '20px' } },
37422
+ 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
37423
  createElement$1("input", { type: "checkbox", id: this._uid + '-row-check-' + _index, className: "is-rowChecker", "on-click": (e) => {
37359
37424
  this._hidden.check.call(this, row, e);
37360
37425
  }, defaultChecked: isCheck, disabled: this.$options.disabled || row.disabled }))) : (''),
37361
37426
  col.template ? createElement$1("span", { className: "gn-datagrid-cell", innerHTML: col.template(col.key, row, col) }) : row[col.key] !== undefined ? row[col.key] : ''
37362
37427
  ];
37363
37428
  },
37429
+ renderCell: (row, col, idx, hasChild, isCheck, _index) => {
37430
+ if (this._isHorizontalState()) {
37431
+ return [this._hidden.renderHorizontalCellLabel(col), createElement$1("div", { className: "gn-datagrid-cell-value" }, this._hidden.renderCellValue(row, col, idx, hasChild, isCheck, _index))];
37432
+ }
37433
+ return this._hidden.renderCellValue(row, col, idx, hasChild, isCheck, _index);
37434
+ },
37364
37435
  renderNodata: () => {
37365
37436
  return (createElement$1("div", { className: "gn-datagrid-body-row is-nodata" },
37366
37437
  createElement$1("div", { className: "gn-datagrid-body-cell has-text-center" }, this.$options.textSets.noData)));
@@ -37446,7 +37517,10 @@
37446
37517
  });
37447
37518
  this.$event(this, 'onCheckAll', e.target.checked);
37448
37519
  },
37449
- showDetail(index, headerKeys, rawDataKeys) {
37520
+ showDetail: (index, headerKeys, rawDataKeys) => {
37521
+ if (this._isHorizontalState()) {
37522
+ return;
37523
+ }
37450
37524
  const rows = findAll(`.gn-datagrid-body > .gn-datagrid-body-row`, this.$el);
37451
37525
  const row = rows[+index];
37452
37526
  if (next(row) && hasClass(next(row), 'gn-datagrid-body-row-detail')) {
@@ -37533,6 +37607,7 @@
37533
37607
  },
37534
37608
  reRender: ({ headers, data, hasCheck }) => {
37535
37609
  return new Promise(resolve => {
37610
+ this._refreshOrientationState(this.$options);
37536
37611
  if (hasCheck === undefined) {
37537
37612
  hasCheck = this.$options.hasCheck;
37538
37613
  }
@@ -37741,8 +37816,8 @@
37741
37816
  visibles.forEach((visible, index) => {
37742
37817
  const colNumber = index + 1;
37743
37818
  !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');
37819
+ ? addClass(findAll(`.gn-datagrid-body-cell[data-key="${this.$options.headers[index].key}"]`, this.$el), 'is-unvisible')
37820
+ : removeClass(findAll(`.gn-datagrid-body-cell[data-key="${this.$options.headers[index].key}"]`, this.$el), 'is-unvisible');
37746
37821
  !visible
37747
37822
  ? addClass(findAll('.gn-datagrid-header-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible')
37748
37823
  : removeClass(findAll('.gn-datagrid-header-cell:nth-child(' + colNumber + ')', this.$el), 'is-unvisible');
@@ -37787,6 +37862,13 @@
37787
37862
  removeClass(this.$el, 'is-disabled');
37788
37863
  }
37789
37864
  };
37865
+ this._orientationState = {
37866
+ orientation: 'vertical',
37867
+ columns: 1,
37868
+ gap: 0,
37869
+ minWidth: 240,
37870
+ hasGap: false
37871
+ };
37790
37872
  this.config = {
37791
37873
  width: '100%',
37792
37874
  hasCheck: false,
@@ -37801,6 +37883,7 @@
37801
37883
  deleteLabel: '',
37802
37884
  deleteConfirmMessage: ''
37803
37885
  },
37886
+ orientation: 'vertical',
37804
37887
  childField: 'child',
37805
37888
  checkCapturing: true,
37806
37889
  sort: {
@@ -37821,10 +37904,10 @@
37821
37904
  onDelete: true
37822
37905
  };
37823
37906
  this.methods = {
37824
- reRender(options) {
37907
+ reRender: (options) => {
37825
37908
  return this._hidden.reRender(options);
37826
37909
  },
37827
- resetData(data) {
37910
+ resetData: (data) => {
37828
37911
  if (isFunction(data)) {
37829
37912
  this.$options.asyncData = data;
37830
37913
  data = [];
@@ -37833,45 +37916,60 @@
37833
37916
  }
37834
37917
  return this._hidden.resetData(arrClone(data));
37835
37918
  },
37836
- addChild(index, data) {
37919
+ addChild: (index, data) => {
37920
+ if (this._isHorizontalState()) {
37921
+ return;
37922
+ }
37837
37923
  this._hidden.addChild(index, arrClone(data));
37838
37924
  },
37839
- addRow(data) {
37925
+ addRow: (data) => {
37926
+ if (this._isHorizontalState()) {
37927
+ return;
37928
+ }
37840
37929
  this._hidden.addChild(null, arrClone(data));
37841
37930
  this.$options.data = this.$options.data.concat(data);
37842
37931
  },
37843
- expand(index) {
37932
+ expand: (index) => {
37933
+ if (this._isHorizontalState()) {
37934
+ return;
37935
+ }
37844
37936
  this._hidden.expand(index);
37845
37937
  },
37846
- collapse(index) {
37938
+ collapse: (index) => {
37939
+ if (this._isHorizontalState()) {
37940
+ return;
37941
+ }
37847
37942
  this._hidden.collapse(index);
37848
37943
  },
37849
- getChecked() {
37944
+ getChecked: () => {
37850
37945
  return this._hidden.getChecked();
37851
37946
  },
37852
- hideCols(keys) {
37947
+ hideCols: (keys) => {
37853
37948
  this._hidden.hideCols(keys);
37854
37949
  },
37855
- showCols(keys) {
37950
+ showCols: (keys) => {
37856
37951
  this._hidden.showCols(keys);
37857
37952
  },
37858
- showAll() {
37953
+ showAll: () => {
37859
37954
  this._hidden.showAll();
37860
37955
  },
37861
- showDetail(index, headerKeys, rawDataKeys) {
37956
+ showDetail: (index, headerKeys, rawDataKeys) => {
37957
+ if (this._isHorizontalState()) {
37958
+ return;
37959
+ }
37862
37960
  this._hidden.showDetail.call(this, index, headerKeys, rawDataKeys);
37863
37961
  },
37864
- selectRow(index, rowData) {
37962
+ selectRow: (index, rowData) => {
37865
37963
  let row = rowData;
37866
37964
  if (!row) {
37867
37965
  row = this.$options.data[index];
37868
37966
  }
37869
37967
  !this.$options.disable && this._hidden.selectRow(row, index);
37870
37968
  },
37871
- disable() {
37969
+ disable: () => {
37872
37970
  this._hidden.disable();
37873
37971
  },
37874
- enable() {
37972
+ enable: () => {
37875
37973
  this._hidden.enable();
37876
37974
  }
37877
37975
  };
@@ -37924,6 +38022,34 @@
37924
38022
  });
37925
38023
  }
37926
38024
  }
38025
+ // 렌더에서 바로 쓸 수 있는 orientation 상태를 만든다.
38026
+ _resolveOrientationState(config = this.$options) {
38027
+ var _a, _b, _c, _d, _e;
38028
+ const orientation = (config === null || config === void 0 ? void 0 : config.orientation) === 'horizontal' ? 'horizontal' : 'vertical';
38029
+ const optionColumns = (_a = config === null || config === void 0 ? void 0 : config.orientationOptions) === null || _a === void 0 ? void 0 : _a.columns;
38030
+ const columns = optionColumns === 'auto-fit' ? optionColumns : Number.isInteger(Number(optionColumns)) && Number(optionColumns) > 0 ? Number(optionColumns) : 1;
38031
+ 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;
38032
+ const isZeroLikeGap = optionGap === 0 || optionGap === '0' || optionGap === '0px' || optionGap === '';
38033
+ const gap = columns === 'auto-fit' && isZeroLikeGap ? '5px' : isZeroLikeGap ? 0 : typeof optionGap === 'number' ? optionGap + 'px' : optionGap;
38034
+ const rawMinWidth = (_e = (_d = config.orientationOptions) === null || _d === void 0 ? void 0 : _d.minWidth) !== null && _e !== void 0 ? _e : 240;
38035
+ const minWidth = typeof rawMinWidth === 'number' ? rawMinWidth + 'px' : rawMinWidth;
38036
+ return {
38037
+ orientation,
38038
+ columns,
38039
+ gap,
38040
+ minWidth,
38041
+ hasGap: gap !== 0
38042
+ };
38043
+ }
38044
+ // 실제 옵션이 갱신될 때 내부 orientation 상태를 새로 계산한다.
38045
+ _refreshOrientationState(config = this.$options) {
38046
+ this._orientationState = this._resolveOrientationState(config);
38047
+ return this._orientationState;
38048
+ }
38049
+ // 내부 렌더 분기에서는 orientationState만 기준으로 사용한다.
38050
+ _isHorizontalState() {
38051
+ return this._orientationState.orientation === 'horizontal';
38052
+ }
37927
38053
  _isSystemAddedColumn(key) {
37928
38054
  return ['btnOrder', 'btnDelete'].includes(key);
37929
38055
  }
@@ -37931,6 +38057,10 @@
37931
38057
  _prepareHeaders(headers = []) {
37932
38058
  const hasOrderColumn = headers.some((header) => header.key === 'btnOrder');
37933
38059
  const hasDeleteColumn = headers.some((header) => header.key === 'btnDelete');
38060
+ const horizontal = this._isHorizontalState();
38061
+ if (horizontal) {
38062
+ headers = headers.map((header) => (Object.assign(Object.assign({}, header), { sortable: false, draggable: false })));
38063
+ }
37934
38064
  if (this.$options.hasOrder && !this.$options.readonly && !hasOrderColumn) {
37935
38065
  headers.push({
37936
38066
  label: this.$options.textSets.orderLabel,
@@ -37940,7 +38070,7 @@
37940
38070
  }
37941
38071
  });
37942
38072
  }
37943
- if (this.$options.hasDelete && !this.$options.readonly && !hasDeleteColumn) {
38073
+ if (this.$options.hasDelete && !this.$options.readonly && !hasDeleteColumn && !horizontal) {
37944
38074
  headers.push({
37945
38075
  label: this.$options.textSets.deleteLabel,
37946
38076
  key: 'btnDelete',
@@ -37953,9 +38083,14 @@
37953
38083
  return headers;
37954
38084
  }
37955
38085
  template(config) {
38086
+ const resolvedConfig = Object.assign(Object.assign({}, this.$options), config);
38087
+ this._refreshOrientationState(resolvedConfig);
38088
+ const contentsMarginTop = this.$options.bodyTopMargin ? this.$options.bodyTopMargin : this._isHorizontalState() && this._orientationState.hasGap ? String(this._orientationState.gap) : '0';
37956
38089
  const styles = {};
37957
38090
  const headers = this._prepareHeaders(config.headers);
37958
38091
  return (createElement$1("div", { id: this._uid, className: 'gn-datagrid' +
38092
+ (this._isHorizontalState() ? ' is-horizontal' : '') +
38093
+ (this._isHorizontalState() && this._orientationState.hasGap ? ' has-horizontal-gap' : '') +
37959
38094
  (config.style ? ' is-' + config.style : '') +
37960
38095
  (config.isEllipsis ? ' is-ellipsis' : '') +
37961
38096
  (config.bodyHeight ? ' has-fixed-body' : '') +
@@ -37965,7 +38100,7 @@
37965
38100
  (config.data.some((d) => isArray$1(d[this.$options.childField])) ? ' has-left-padding' : '') +
37966
38101
  (config.disabled ? ' is-disabled' : ''), style: styles },
37967
38102
  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)),
38103
+ 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
38104
  config.paginator /* 페이지네이터 옵션 확인 */ && createElement$1("div", { className: "gn-datagrid-footer" })));
37970
38105
  }
37971
38106
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -37982,7 +38117,12 @@
37982
38117
  }
37983
38118
  }
37984
38119
  completed() {
37985
- if (this.$options.fixHeader && this.$options.hasHeader) {
38120
+ const isHorizontal = this._isHorizontalState();
38121
+ const isVertical = !isHorizontal;
38122
+ const usesFixedHeader = this.$options.fixHeader && this.$options.hasHeader;
38123
+ const needsBlankHeader = usesFixedHeader || this.$options.bodyHeight;
38124
+ isHorizontal ? addClass(this.$el, 'is-horizontal') : removeClass(this.$el, 'is-horizontal');
38125
+ if (usesFixedHeader && isVertical) {
37986
38126
  const body = find('.gn-datagrid-contents', this.$el);
37987
38127
  const header = find('.gn-datagrid-header', this.$el);
37988
38128
  if (header) {
@@ -37995,7 +38135,7 @@
37995
38135
  css$1(body, 'margin-bottom', this.$options.bodyBottomMargin);
37996
38136
  }
37997
38137
  }
37998
- if ((this.$options.fixHeader && this.$options.hasHeader) || this.$options.bodyHeight) {
38138
+ if (isVertical && needsBlankHeader) {
37999
38139
  this._hidden.setBlankHeader();
38000
38140
  on(window, 'resize', this._hidden.setBlankHeader);
38001
38141
  }
@@ -38473,6 +38613,10 @@
38473
38613
  focus: () => {
38474
38614
  const modal = find('.modal-content', this.$el);
38475
38615
  modal.focus();
38616
+ },
38617
+ extra: (actionKey) => {
38618
+ // notify page about which extra button clicked
38619
+ this.$event(this, 'onExtra', actionKey);
38476
38620
  }
38477
38621
  };
38478
38622
  this.config = {
@@ -38490,6 +38634,7 @@
38490
38634
  hasClose: true,
38491
38635
  hasConfirm: false,
38492
38636
  hasCancel: false,
38637
+ extraButtons: [],
38493
38638
  isModal: true,
38494
38639
  minimized: false,
38495
38640
  resizable: false,
@@ -38500,7 +38645,8 @@
38500
38645
  this.events = {
38501
38646
  onClose: true,
38502
38647
  onConfirm: true,
38503
- onOpen: true
38648
+ onOpen: true,
38649
+ onExtra: true
38504
38650
  };
38505
38651
  this.methods = {
38506
38652
  close() {
@@ -38542,7 +38688,10 @@
38542
38688
  createElement$1("i", { className: "fas fa-times" })))))),
38543
38689
  createElement$1("div", { className: "modal-body", style: styles },
38544
38690
  createElement$1("div", { className: "modal-body-content", style: contStyles })),
38545
- (config.hasConfirm || config.hasCancel) /* 확인/취소 옵션 확인 */ && (createElement$1("div", { className: "modal-footer has-text-center" },
38691
+ (config.hasConfirm || config.hasCancel || (Array.isArray(config.extraButtons) && config.extraButtons.length > 0)) /* 확인/취소/추가버튼 옵션 확인 */ && (createElement$1("div", { className: "modal-footer has-text-center" },
38692
+ Array.isArray(config.extraButtons) &&
38693
+ config.extraButtons.length > 0 &&
38694
+ 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
38695
  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
38696
  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
38697
  }
@@ -39581,15 +39730,124 @@
39581
39730
  }
39582
39731
 
39583
39732
  class MultiTextArea extends GNCoreInstance {
39733
+ _isMaxLengthMessageEnabled() {
39734
+ return !!(this.$options.maxlength && this.$options.useMaxLengthMessage);
39735
+ }
39736
+ _getTotalLength(valueSet) {
39737
+ return this.$options.lang.reduce((sum, currentLang) => {
39738
+ const currentValue = valueSet[currentLang] || '';
39739
+ return sum + currentValue.length;
39740
+ }, 0);
39741
+ }
39742
+ _getTotalLengthWithoutLang(valueSet, excludeLang) {
39743
+ return this.$options.lang.reduce((sum, currentLang) => {
39744
+ if (currentLang === excludeLang) {
39745
+ return sum;
39746
+ }
39747
+ const currentValue = valueSet[currentLang] || '';
39748
+ return sum + currentValue.length;
39749
+ }, 0);
39750
+ }
39751
+ _getRemainMessage(remain) {
39752
+ var _a, _b;
39753
+ const template = ((_b = (_a = this.$options) === null || _a === void 0 ? void 0 : _a.textSets) === null || _b === void 0 ? void 0 : _b.maxLengthMessage) || '{{maxlength}}자 입력 가능합니다.';
39754
+ return template.replace(/\{\{\s*maxlength\s*\}\}/g, String(remain));
39755
+ }
39584
39756
  constructor(name, selector, options = {}) {
39585
39757
  super(name, selector, options);
39586
39758
  this._hidden = {
39759
+ beforeInput: (e) => {
39760
+ var _a, _b;
39761
+ if (!this.$options.maxlength || !this._isMaxLengthMessageEnabled()) {
39762
+ return;
39763
+ }
39764
+ const target = e.target;
39765
+ const lang = data(target, 'data-lang');
39766
+ if (!lang) {
39767
+ return;
39768
+ }
39769
+ if (e.inputType && e.inputType.startsWith('delete')) {
39770
+ return;
39771
+ }
39772
+ const currentValue = val(target) || '';
39773
+ const selectionStart = typeof target.selectionStart === 'number' ? target.selectionStart : currentValue.length;
39774
+ const selectionEnd = typeof target.selectionEnd === 'number' ? target.selectionEnd : currentValue.length;
39775
+ const selectedLength = Math.max(0, selectionEnd - selectionStart);
39776
+ let insertValue = e.data || '';
39777
+ if (e.inputType === 'insertLineBreak' || e.inputType === 'insertParagraph') {
39778
+ insertValue = '\n';
39779
+ }
39780
+ if (e.inputType === 'insertFromPaste' && !insertValue) {
39781
+ 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');
39782
+ insertValue = typeof pastedText === 'string' ? pastedText : '';
39783
+ }
39784
+ // 현재 언어를 제외한 나머지 언어들의 총 입력 길이를 기준으로 남은 입력 가능 길이를 계산한다.
39785
+ const totalLengthWithoutCurrent = this._getTotalLengthWithoutLang(this.$options.value, lang);
39786
+ const allowedLengthForCurrent = Math.max(0, this.$options.maxlength - totalLengthWithoutCurrent);
39787
+ const remainingForInsert = this.$options.maxlength - totalLengthWithoutCurrent - (currentValue.length - selectedLength);
39788
+ // paste는 "붙여넣기 내용 우선 반영 + 전체 결과의 뒤를 자르기" 정책을 적용한다.
39789
+ if (e.inputType === 'insertFromPaste') {
39790
+ if (remainingForInsert <= 0) {
39791
+ e.preventDefault();
39792
+ return;
39793
+ }
39794
+ const before = currentValue.slice(0, selectionStart);
39795
+ const after = currentValue.slice(selectionEnd);
39796
+ const nextValue = `${before}${insertValue}${after}`;
39797
+ if (nextValue.length <= allowedLengthForCurrent) {
39798
+ return;
39799
+ }
39800
+ e.preventDefault();
39801
+ const clamped = nextValue.slice(0, allowedLengthForCurrent);
39802
+ val(target, clamped);
39803
+ const nextCaret = Math.min((before + insertValue).length, clamped.length);
39804
+ target.setSelectionRange(nextCaret, nextCaret);
39805
+ trigger(target, 'input');
39806
+ return;
39807
+ }
39808
+ if (remainingForInsert >= insertValue.length) {
39809
+ return;
39810
+ }
39811
+ if (remainingForInsert <= 0) {
39812
+ e.preventDefault();
39813
+ return;
39814
+ }
39815
+ // 붙여넣기/다중 입력이 한도를 넘는 경우 허용 가능한 길이만 잘라서 반영한다.
39816
+ e.preventDefault();
39817
+ const partial = insertValue.slice(0, remainingForInsert);
39818
+ target.setRangeText(partial, selectionStart, selectionEnd, 'end');
39819
+ trigger(target, 'input');
39820
+ },
39587
39821
  change: (e) => {
39588
39822
  const target = e.target;
39589
39823
  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);
39824
+ if (!lang) {
39825
+ return;
39826
+ }
39827
+ this.$options.value[lang] = val(target) || '';
39828
+ if (this.$options.maxlength && this._isMaxLengthMessageEnabled()) {
39829
+ // 총합 maxlength를 넘지 않도록 현재 언어 값만 상한선까지 보정한다.
39830
+ const totalLengthWithoutCurrent = this._getTotalLengthWithoutLang(this.$options.value, lang);
39831
+ const allowedLength = Math.max(0, this.$options.maxlength - totalLengthWithoutCurrent);
39832
+ const clampedValue = this.$options.value[lang].slice(0, allowedLength);
39833
+ if (clampedValue !== this.$options.value[lang]) {
39834
+ this.$options.value[lang] = clampedValue;
39835
+ val(target, clampedValue);
39836
+ }
39837
+ }
39838
+ if (this.$options.maxlength && this.$options.delegates[lang]) {
39839
+ const hasMaxLengthMessage = this._isMaxLengthMessageEnabled();
39840
+ if (hasMaxLengthMessage) {
39841
+ // 메시지 모드에서는 모든 탭에 동일한 "남은 글자 수" 안내를 동기화한다.
39842
+ const totalLength = this._getTotalLength(this.$options.value);
39843
+ const textValue = this._getRemainMessage(this.$options.maxlength - totalLength);
39844
+ this.$options.lang.forEach((targetLang) => {
39845
+ text$1(this.$options.delegates[targetLang], textValue);
39846
+ });
39847
+ }
39848
+ else {
39849
+ text$1(this.$options.delegates[lang], this.$options.value[lang].length);
39850
+ }
39593
39851
  }
39594
39852
  this.$event(this, 'onChange', this.$options.value);
39595
39853
  },
@@ -39606,7 +39864,7 @@
39606
39864
  }
39607
39865
  const textInput = find(`[data-lang=${lang}]`, this.$el);
39608
39866
  val(textInput, value[lang]);
39609
- trigger(textInput, 'keyup');
39867
+ trigger(textInput, 'input');
39610
39868
  });
39611
39869
  },
39612
39870
  disable: () => {
@@ -39625,6 +39883,10 @@
39625
39883
  this.config = {
39626
39884
  lang: ['en', 'ko'],
39627
39885
  value: {},
39886
+ useMaxLengthMessage: false,
39887
+ textSets: {
39888
+ maxLengthMessage: '{{maxlength}}자 입력 가능합니다.'
39889
+ },
39628
39890
  delegates: {}
39629
39891
  };
39630
39892
  this.events = {
@@ -39649,6 +39911,12 @@
39649
39911
  }
39650
39912
  template(config) {
39651
39913
  const styles = {};
39914
+ const totalLength = config.lang.reduce((sum, currentLang) => {
39915
+ const currentValue = config.value && config.value[currentLang] ? config.value[currentLang] : '';
39916
+ return sum + currentValue.length;
39917
+ }, 0);
39918
+ const hasMaxLengthMessage = this._isMaxLengthMessageEnabled();
39919
+ const remainMessage = config.maxlength ? this._getRemainMessage(config.maxlength - totalLength) : '';
39652
39920
  if (config.width) {
39653
39921
  styles.width = getUnit('width', config.width);
39654
39922
  }
@@ -39657,11 +39925,14 @@
39657
39925
  createElement$1("ul", null, config.lang.map((l, index) => (createElement$1("li", { className: index === 0 ? 'is-active' : '' },
39658
39926
  createElement$1("a", { href: '#' + this._uid + '-' + l }, l)))))),
39659
39927
  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))))))));
39928
+ 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] : ''),
39929
+ config.maxlength && (createElement$1("div", { className: "has-text-size6" },
39930
+ !hasMaxLengthMessage && (createElement$1("p", null,
39931
+ createElement$1("span", { className: "charLen", "data-lang": l }, config.value && config.value[l] ? config.value[l].length : 0),
39932
+ "/",
39933
+ config.maxlength)),
39934
+ hasMaxLengthMessage && (createElement$1("p", null,
39935
+ createElement$1("span", { className: "charLen", "data-lang": l }, remainMessage)))))))))));
39665
39936
  }
39666
39937
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
39667
39938
  $render(config) {
@@ -40952,41 +41223,56 @@
40952
41223
  class Tree extends GNCoreInstance {
40953
41224
  constructor(name, selector, options = {}) {
40954
41225
  super(name, selector, options);
41226
+ this._checkerIdSeq = 0;
40955
41227
  this._hidden = {
40956
41228
  select: (item, e) => {
40957
41229
  if (item.disabled) {
40958
41230
  return;
40959
41231
  }
41232
+ if (hasClass(this.$el, 'is-disabled')) {
41233
+ return;
41234
+ }
40960
41235
  let target = e.target;
40961
- // 트리 아이콘을 클릭한 경우, 텍스트로 타겟 변경
40962
41236
  if (this.$options.showIcon && target.tagName === 'I') {
40963
41237
  target = parent(target);
40964
41238
  }
40965
- if (!this.$options.multiple) {
41239
+ if (this.$options.hasCheck) {
41240
+ // hasCheck 시: 노드 클릭으로 체크박스 토글, is-active 미적용
41241
+ const itemEl = hasClass(target, 'tree-item') ? target : parents(target, '.tree-item')[0];
41242
+ if (!itemEl)
41243
+ return;
41244
+ const checker = find('.is-checker', itemEl);
41245
+ if (!checker)
41246
+ return;
41247
+ // 라벨 또는 input 직접 클릭 시 여기서 토글하지 않음 → input 클릭 핸들러만 한 번 실행되게 함 (이중 토글·이중 onCheck 방지)
41248
+ const labelTarget = parents(e.target, 'label')[0];
41249
+ if (e.target === checker || (labelTarget && checker.id && labelTarget.getAttribute('for') === checker.id)) {
41250
+ return;
41251
+ }
41252
+ checker.checked = !checker.checked;
41253
+ this._hidden.check.call(this, item, { target: checker, stopPropagation: () => { } });
41254
+ }
41255
+ else {
41256
+ // hasCheck 미사용 시: 노드 클릭 시 is-active 적용, onSelect 발생
40966
41257
  removeClass(findAll('.tree-item', this.$el), 'is-active');
40967
41258
  addClass(target, 'is-active');
40968
41259
  this.$event(this, 'onSelect', item, e);
40969
41260
  }
40970
- else {
40971
- toggleClass(target, 'is-active');
40972
- if (hasClass(target, 'is-active')) {
40973
- this.$event(this, 'onSelect', item, e);
40974
- }
40975
- }
40976
41261
  },
40977
41262
  addChild: (index, addData) => {
40978
41263
  const itemEl = findAll('.tree-item', this.$el)[index];
40979
41264
  const itemData = this._hidden.findData(index);
41265
+ const nextChildren = this._hidden.setPaths(addData.slice(), itemData.path);
40980
41266
  if (!itemData[this.$options.childField]) {
40981
41267
  itemData[this.$options.childField] = [];
40982
41268
  }
40983
- itemData[this.$options.childField] = itemData[this.$options.childField].concat(addData);
41269
+ itemData[this.$options.childField] = itemData[this.$options.childField].concat(nextChildren);
40984
41270
  const appendTarget = siblings(itemEl, 'ul').pop();
40985
41271
  if (!appendTarget) {
40986
41272
  this.$template.reRender(parent(itemEl), this._hidden.renderItem(itemData));
40987
41273
  }
40988
41274
  else {
40989
- addData.forEach((item) => {
41275
+ nextChildren.forEach((item) => {
40990
41276
  const newItem = document.createElement('li');
40991
41277
  append(appendTarget, newItem);
40992
41278
  this.$template.reRender(newItem, this._hidden.renderItem(item));
@@ -41017,38 +41303,59 @@
41017
41303
  },
41018
41304
  check: (item, e) => {
41019
41305
  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
- });
41306
+ if (hasClass(this.$el, 'is-disabled') || item.disabled) {
41307
+ if (typeof e.preventDefault === 'function')
41308
+ e.preventDefault();
41309
+ target.checked = !target.checked; // 브라우저가 이미 토글했으므로 원래대로 되돌림
41310
+ return;
41044
41311
  }
41312
+ if (typeof e.stopPropagation === 'function')
41313
+ e.stopPropagation();
41314
+ this._hidden.applyCheckedState(target, target.checked);
41045
41315
  this.$event(this, 'onCheck', item, target.checked, this._hidden.getItemIndex(target), e);
41046
41316
  },
41047
41317
  checkAll: (isChecked) => {
41318
+ if (this.$options.disabled) {
41319
+ return;
41320
+ }
41048
41321
  findAll('.is-checker', this.$el).forEach((c) => {
41322
+ if (c.disabled) {
41323
+ return;
41324
+ }
41049
41325
  c.checked = isChecked;
41050
41326
  });
41051
41327
  },
41328
+ setChecked: (targets, checked) => {
41329
+ if (!this.$options.hasCheck || this.$options.disabled) {
41330
+ return;
41331
+ }
41332
+ const normalizedTargets = Array.isArray(targets) ? targets : [targets];
41333
+ const targetSet = new Set(normalizedTargets);
41334
+ findAll('.tree-item', this.$el).forEach((itemEl, index) => {
41335
+ const itemData = this._hidden.findData(index);
41336
+ const itemValue = itemData === null || itemData === void 0 ? void 0 : itemData.value;
41337
+ if (itemValue === undefined || itemValue === null || itemValue === '') {
41338
+ return;
41339
+ }
41340
+ if (!targetSet.has(String(itemValue))) {
41341
+ return;
41342
+ }
41343
+ const checker = find('.is-checker', itemEl);
41344
+ if (!checker) {
41345
+ return;
41346
+ }
41347
+ if (checker.disabled || (itemData === null || itemData === void 0 ? void 0 : itemData.disabled)) {
41348
+ return;
41349
+ }
41350
+ checker.checked = checked;
41351
+ this._hidden.applyCheckedState(checker, checked);
41352
+ });
41353
+ },
41354
+ setCheckersDisabled: (disabled) => {
41355
+ findAll('.is-checker', this.$el).forEach((el) => {
41356
+ el.disabled = disabled;
41357
+ });
41358
+ },
41052
41359
  getChecked: (withStatus = false) => {
41053
41360
  if (!this.$options.hasCheck) {
41054
41361
  return [];
@@ -41072,14 +41379,53 @@
41072
41379
  findData.__status.isOpened = hasClass(target, 'is-open');
41073
41380
  findData.__status.isChecked = find('.is-checker', target).checked;
41074
41381
  findData.__status.isSelected = hasClass(target, 'is-active');
41075
- findData.__status.hasChildren = isArray$1(findData.child);
41382
+ findData.__status.hasChildren = isArray$1(findData[this.$options.childField]);
41076
41383
  }
41077
41384
  return findData;
41078
41385
  });
41079
41386
  },
41080
41387
  getItemIndex: (item) => {
41388
+ const itemEl = hasClass(item, 'tree-item') ? item : parents(item, '.tree-item')[0];
41389
+ if (!itemEl) {
41390
+ return -1;
41391
+ }
41081
41392
  const itemList = findAll('.tree-item', this.$el);
41082
- return itemList.findIndex((el) => el == item);
41393
+ return itemList.findIndex((el) => el == itemEl);
41394
+ },
41395
+ applyCheckedState: (checker, checked) => {
41396
+ const listItem = parents(checker, 'li')[0];
41397
+ if (!listItem) {
41398
+ return;
41399
+ }
41400
+ if (this.$options.checkChild !== false) {
41401
+ findAll('.is-checker', listItem).forEach((childChecker) => {
41402
+ if (childChecker.disabled) {
41403
+ return;
41404
+ }
41405
+ childChecker.checked = checked;
41406
+ });
41407
+ }
41408
+ if (!this.$options.checkPath) {
41409
+ return;
41410
+ }
41411
+ parents(checker, 'ul')
41412
+ .map((list) => siblings(list, '.tree-item').pop())
41413
+ .filter((item) => item)
41414
+ .forEach((item) => {
41415
+ const parentChecker = find('.is-checker', item);
41416
+ if (!parentChecker) {
41417
+ return;
41418
+ }
41419
+ const parentLi = parents(item, 'li')[0];
41420
+ if (!parentLi) {
41421
+ return;
41422
+ }
41423
+ const descendantCheckers = findAll('.is-checker', parentLi).filter((candidate) => candidate !== parentChecker);
41424
+ if (!descendantCheckers.length) {
41425
+ return;
41426
+ }
41427
+ parentChecker.checked = descendantCheckers.some((candidate) => candidate.checked);
41428
+ });
41083
41429
  },
41084
41430
  getPathArray(path) {
41085
41431
  const pathParts = path.split('/');
@@ -41158,34 +41504,46 @@
41158
41504
  }
41159
41505
  this.$event(this, 'onToggle', item, hasClass(target, 'is-open') ? 'expanded' : 'collapsed', this._hidden.getItemIndex(target), e);
41160
41506
  },
41161
- renderTree: (data) => {
41162
- return (createElement$1("ul", null, data.map((item) => {
41163
- return this._hidden.renderItem(item);
41507
+ renderTree: (data, keyPath = '') => {
41508
+ return (createElement$1("ul", null, data.map((item, idx) => {
41509
+ const itemKeyPath = keyPath ? `${keyPath}-${idx}` : `${idx}`;
41510
+ return this._hidden.renderItem(item, itemKeyPath);
41164
41511
  })));
41165
41512
  },
41166
- renderItem: (item) => {
41513
+ renderItem: (item, keyPath) => {
41167
41514
  var _a;
41515
+ const resolvedKeyPath = keyPath !== null && keyPath !== void 0 ? keyPath : `seq-${this._checkerIdSeq++}`;
41516
+ const checkerId = `${this._uid}-chk-${resolvedKeyPath}`;
41168
41517
  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 },
41518
+ createElement$1("div", { className: [
41519
+ 'tree-item',
41520
+ item[this.$options.childField] ? 'has-child' : '',
41521
+ item.opened ? 'is-open' : '',
41522
+ !this.$options.hasCheck && item.actived ? ' is-active' : '',
41523
+ item.disabled ? 'is-disabled' : ''
41524
+ ].join(' '), "on-click": this._hidden.select.bind(this, item), "data-path": (_a = item.path) !== null && _a !== void 0 ? _a : '', title: item.text },
41170
41525
  // has child field - arrow toggle
41171
41526
  item[this.$options.childField] ? (createElement$1("div", { className: "is-toggler", "on-click": (e) => {
41172
41527
  this._hidden.toggle.call(this, item, e);
41173
41528
  } })) : (''),
41174
41529
  // 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) => {
41530
+ this.$options.hasCheck && item.noCheck !== true && item.noCheck !== 'true' ? (createElement$1("div", { className: "gn-checks is-small is-no-padding" },
41531
+ createElement$1("input", { type: "checkbox", className: "is-checker", id: checkerId, disabled: !!this.$options.disabled || !!item.disabled, "on-click": (e) => {
41177
41532
  this._hidden.check.call(this, item, e);
41178
- }, defaultChecked: !!item.selected }))) : (''),
41533
+ }, defaultChecked: !!item.selected }),
41534
+ createElement$1("label", { for: checkerId }, item.text))) : (''),
41179
41535
  // show icon
41180
41536
  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])));
41537
+ !(this.$options.hasCheck && item.noCheck !== true && item.noCheck !== 'true') && item.text),
41538
+ item[this.$options.childField] && this._hidden.renderTree(item[this.$options.childField], resolvedKeyPath)));
41183
41539
  },
41184
- setPaths(data, basePath = '') {
41540
+ setPaths: (data, basePath = '') => {
41185
41541
  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 });
41542
+ 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;
41543
+ const itemPath = basePath ? `${basePath}/${itemKey}` : itemKey;
41544
+ const children = item[this.$options.childField];
41545
+ const childPath = children ? this._hidden.setPaths(children, itemPath) : null;
41546
+ return Object.assign(Object.assign({}, item), { path: itemPath, [this.$options.childField]: childPath });
41189
41547
  });
41190
41548
  }
41191
41549
  };
@@ -41196,10 +41554,11 @@
41196
41554
  data: [],
41197
41555
  childField: 'child',
41198
41556
  hasCheck: false,
41199
- multiple: false,
41557
+ checkChild: true,
41200
41558
  checkPath: false,
41201
41559
  showIcon: false,
41202
- hideIcon: false
41560
+ hideIcon: false,
41561
+ disabled: false
41203
41562
  };
41204
41563
  this.events = {
41205
41564
  onSelect: true,
@@ -41224,15 +41583,20 @@
41224
41583
  this._hidden.collapseAll();
41225
41584
  },
41226
41585
  checkAll() {
41227
- if (!this.$options.hasCheck)
41586
+ if (!this.$options.hasCheck || this.$options.disabled)
41228
41587
  return;
41229
41588
  this._hidden.checkAll(true);
41230
41589
  },
41231
41590
  uncheckAll() {
41232
- if (!this.$options.hasCheck)
41591
+ if (!this.$options.hasCheck || this.$options.disabled)
41233
41592
  return;
41234
41593
  this._hidden.checkAll(false);
41235
41594
  },
41595
+ setChecked(targets, checked) {
41596
+ if (this.$options.disabled)
41597
+ return;
41598
+ this._hidden.setChecked(targets, checked);
41599
+ },
41236
41600
  getChecked(withStatus = false) {
41237
41601
  return this._hidden.getChecked(withStatus);
41238
41602
  },
@@ -41244,14 +41608,29 @@
41244
41608
  },
41245
41609
  filter(keyword) {
41246
41610
  return this._hidden.filter(keyword);
41611
+ },
41612
+ disable() {
41613
+ this.$options.disabled = true;
41614
+ addClass(this.$el, 'is-disabled');
41615
+ this._hidden.setCheckersDisabled(true);
41616
+ },
41617
+ enable() {
41618
+ this.$options.disabled = false;
41619
+ removeClass(this.$el, 'is-disabled');
41620
+ this._hidden.setCheckersDisabled(false);
41247
41621
  }
41248
41622
  };
41623
+ // multiple → hasCheck 치환(동일 기능으로 지원 X)
41624
+ if (options && options.multiple) {
41625
+ options.hasCheck = true;
41626
+ delete options.multiple;
41627
+ }
41249
41628
  this.$init(this, options);
41250
41629
  }
41251
41630
  template(config) {
41252
41631
  config.data = this._hidden.setPaths(config.data);
41253
41632
  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 },
41633
+ 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
41634
  config.textSets.title && createElement$1("p", { className: "tree-label", innerHTML: config.textSets.title }),
41256
41635
  this._hidden.renderTree(config.data)));
41257
41636
  }