@operato/input 9.0.13 → 9.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ### [9.0.14](https://github.com/hatiolab/operato/compare/v9.0.13...v9.0.14) (2025-07-27)
7
+
8
+
9
+ ### :bug: Bug Fix
10
+
11
+ * help popup style for ox-input-formula ([a2fec19](https://github.com/hatiolab/operato/commit/a2fec1918584b85329566f5df80dac3864d104f3))
12
+
13
+
14
+
6
15
  ### [9.0.13](https://github.com/hatiolab/operato/compare/v9.0.12...v9.0.13) (2025-07-27)
7
16
 
8
17
 
@@ -0,0 +1,18 @@
1
+ import '@material/web/icon/icon.js';
2
+ import { LitElement } from 'lit';
3
+ export type HelpContent = {
4
+ title: string;
5
+ sections: Array<{
6
+ title: string;
7
+ content: string;
8
+ type?: 'text' | 'code' | 'parameter' | 'example';
9
+ }>;
10
+ };
11
+ export declare class OxInputFormulaHelpPopup extends LitElement {
12
+ static styles: import("lit").CSSResult[];
13
+ content?: HelpContent;
14
+ onClose?: () => void;
15
+ render(): import("lit-html").TemplateResult<1>;
16
+ private _renderSectionContent;
17
+ private _onClose;
18
+ }
@@ -0,0 +1,166 @@
1
+ import { __decorate } from "tslib";
2
+ import '@material/web/icon/icon.js';
3
+ import { css, html, LitElement } from 'lit';
4
+ import { customElement, property } from 'lit/decorators.js';
5
+ import { ScrollbarStyles } from '@operato/styles';
6
+ let OxInputFormulaHelpPopup = class OxInputFormulaHelpPopup extends LitElement {
7
+ static { this.styles = [
8
+ ScrollbarStyles,
9
+ css `
10
+ :host {
11
+ display: block;
12
+ }
13
+
14
+ .help-popup {
15
+ max-width: 500px;
16
+ max-height: 400px;
17
+ overflow-y: auto;
18
+ background: white;
19
+ border-radius: 8px;
20
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
21
+ }
22
+
23
+ .help-title {
24
+ font-size: 20px;
25
+ font-weight: 600;
26
+ margin-bottom: 16px;
27
+ color: #1976d2;
28
+ padding: 20px 20px 16px 20px;
29
+ background: #f8f9fa;
30
+ border-bottom: 1px solid #e0e0e0;
31
+ border-radius: 8px 8px 0 0;
32
+ }
33
+
34
+ .help-content {
35
+ padding: 0 20px;
36
+ }
37
+
38
+ .help-section {
39
+ margin-bottom: 16px;
40
+ }
41
+
42
+ .help-section-title {
43
+ font-weight: 600;
44
+ margin-bottom: 8px;
45
+ color: #333;
46
+ font-size: 14px;
47
+ border-bottom: 1px solid #e0e0e0;
48
+ padding-bottom: 4px;
49
+ }
50
+
51
+ .help-section-content {
52
+ font-size: 14px;
53
+ line-height: 1.6;
54
+ color: #555;
55
+ padding: 4px 0;
56
+ }
57
+
58
+ .help-code {
59
+ background: #f5f5f5;
60
+ border: 1px solid #e0e0e0;
61
+ border-radius: 4px;
62
+ padding: 12px;
63
+ font-family: 'Courier New', monospace;
64
+ font-size: 13px;
65
+ color: #333;
66
+ margin: 8px 0;
67
+ }
68
+
69
+ .help-example {
70
+ background: #f0f8ff;
71
+ border: 1px solid #c8e6c9;
72
+ border-radius: 4px;
73
+ padding: 12px;
74
+ font-family: 'Courier New', monospace;
75
+ font-size: 13px;
76
+ color: #2e7d32;
77
+ margin: 8px 0;
78
+ }
79
+
80
+ .help-parameter {
81
+ background: #f8f9fa;
82
+ border-left: 3px solid #1976d2;
83
+ border-radius: 4px;
84
+ padding: 8px 12px;
85
+ margin-bottom: 4px;
86
+ font-size: 13px;
87
+ color: #555;
88
+ }
89
+
90
+ .help-footer {
91
+ display: flex;
92
+ justify-content: flex-end;
93
+ padding: 16px 20px;
94
+ border-top: 1px solid #e0e0e0;
95
+ background: #f8f9fa;
96
+ border-radius: 0 0 8px 8px;
97
+ }
98
+
99
+ .close-btn {
100
+ padding: 8px 16px;
101
+ border: 1px solid #1976d2;
102
+ border-radius: 4px;
103
+ background-color: #1976d2;
104
+ color: white;
105
+ cursor: pointer;
106
+ font-size: 14px;
107
+ font-weight: 500;
108
+ transition: all 0.2s ease;
109
+ }
110
+
111
+ .close-btn:hover {
112
+ background-color: #1565c0;
113
+ border-color: #1565c0;
114
+ }
115
+ `
116
+ ]; }
117
+ render() {
118
+ if (!this.content) {
119
+ return html ``;
120
+ }
121
+ return html `
122
+ <div class="help-popup">
123
+ <div class="help-title">${this.content.title}</div>
124
+
125
+ <div class="help-content">
126
+ ${this.content.sections.map(section => html `
127
+ <div class="help-section">
128
+ <div class="help-section-title">${section.title}</div>
129
+ ${this._renderSectionContent(section)}
130
+ </div>
131
+ `)}
132
+ </div>
133
+
134
+ <div class="help-footer">
135
+ <button class="close-btn" @click=${this._onClose}>닫기</button>
136
+ </div>
137
+ </div>
138
+ `;
139
+ }
140
+ _renderSectionContent(section) {
141
+ switch (section.type) {
142
+ case 'code':
143
+ return html `<div class="help-code">${section.content}</div>`;
144
+ case 'parameter':
145
+ return html `<div class="help-parameter">${section.content}</div>`;
146
+ case 'example':
147
+ return html `<div class="help-example">${section.content}</div>`;
148
+ default:
149
+ return html `<div class="help-section-content">${section.content}</div>`;
150
+ }
151
+ }
152
+ _onClose() {
153
+ this.onClose?.();
154
+ }
155
+ };
156
+ __decorate([
157
+ property({ type: Object })
158
+ ], OxInputFormulaHelpPopup.prototype, "content", void 0);
159
+ __decorate([
160
+ property({ type: Object })
161
+ ], OxInputFormulaHelpPopup.prototype, "onClose", void 0);
162
+ OxInputFormulaHelpPopup = __decorate([
163
+ customElement('ox-input-formula-help-popup')
164
+ ], OxInputFormulaHelpPopup);
165
+ export { OxInputFormulaHelpPopup };
166
+ //# sourceMappingURL=ox-input-formula-help-popup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ox-input-formula-help-popup.js","sourceRoot":"","sources":["../../src/ox-input-formula-help-popup.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AAEnC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAY1C,IAAM,uBAAuB,GAA7B,MAAM,uBAAwB,SAAQ,UAAU;aAC9C,WAAM,GAAG;QACd,eAAe;QACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0GF;KACF,AA7GY,CA6GZ;IAKD,MAAM;QACJ,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO,IAAI,CAAA,EAAE,CAAA;QACf,CAAC;QAED,OAAO,IAAI,CAAA;;kCAEmB,IAAI,CAAC,OAAO,CAAC,KAAK;;;YAGxC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CACzB,OAAO,CAAC,EAAE,CAAC,IAAI,CAAA;;kDAEuB,OAAO,CAAC,KAAK;kBAC7C,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;;aAExC,CACF;;;;6CAIkC,IAAI,CAAC,QAAQ;;;KAGrD,CAAA;IACH,CAAC;IAEO,qBAAqB,CAAC,OAAY;QACxC,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,MAAM;gBACT,OAAO,IAAI,CAAA,0BAA0B,OAAO,CAAC,OAAO,QAAQ,CAAA;YAC9D,KAAK,WAAW;gBACd,OAAO,IAAI,CAAA,+BAA+B,OAAO,CAAC,OAAO,QAAQ,CAAA;YACnE,KAAK,SAAS;gBACZ,OAAO,IAAI,CAAA,6BAA6B,OAAO,CAAC,OAAO,QAAQ,CAAA;YACjE;gBACE,OAAO,IAAI,CAAA,qCAAqC,OAAO,CAAC,OAAO,QAAQ,CAAA;QAC3E,CAAC;IACH,CAAC;IAEO,QAAQ;QACd,IAAI,CAAC,OAAO,EAAE,EAAE,CAAA;IAClB,CAAC;;AA7C2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wDAAsB;AACrB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wDAAqB;AAjHrC,uBAAuB;IADnC,aAAa,CAAC,6BAA6B,CAAC;GAChC,uBAAuB,CA8JnC","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ScrollbarStyles } from '@operato/styles'\n\nexport type HelpContent = {\n title: string\n sections: Array<{\n title: string\n content: string\n type?: 'text' | 'code' | 'parameter' | 'example'\n }>\n}\n\n@customElement('ox-input-formula-help-popup')\nexport class OxInputFormulaHelpPopup extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: block;\n }\n\n .help-popup {\n max-width: 500px;\n max-height: 400px;\n overflow-y: auto;\n background: white;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);\n }\n\n .help-title {\n font-size: 20px;\n font-weight: 600;\n margin-bottom: 16px;\n color: #1976d2;\n padding: 20px 20px 16px 20px;\n background: #f8f9fa;\n border-bottom: 1px solid #e0e0e0;\n border-radius: 8px 8px 0 0;\n }\n\n .help-content {\n padding: 0 20px;\n }\n\n .help-section {\n margin-bottom: 16px;\n }\n\n .help-section-title {\n font-weight: 600;\n margin-bottom: 8px;\n color: #333;\n font-size: 14px;\n border-bottom: 1px solid #e0e0e0;\n padding-bottom: 4px;\n }\n\n .help-section-content {\n font-size: 14px;\n line-height: 1.6;\n color: #555;\n padding: 4px 0;\n }\n\n .help-code {\n background: #f5f5f5;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 12px;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n color: #333;\n margin: 8px 0;\n }\n\n .help-example {\n background: #f0f8ff;\n border: 1px solid #c8e6c9;\n border-radius: 4px;\n padding: 12px;\n font-family: 'Courier New', monospace;\n font-size: 13px;\n color: #2e7d32;\n margin: 8px 0;\n }\n\n .help-parameter {\n background: #f8f9fa;\n border-left: 3px solid #1976d2;\n border-radius: 4px;\n padding: 8px 12px;\n margin-bottom: 4px;\n font-size: 13px;\n color: #555;\n }\n\n .help-footer {\n display: flex;\n justify-content: flex-end;\n padding: 16px 20px;\n border-top: 1px solid #e0e0e0;\n background: #f8f9fa;\n border-radius: 0 0 8px 8px;\n }\n\n .close-btn {\n padding: 8px 16px;\n border: 1px solid #1976d2;\n border-radius: 4px;\n background-color: #1976d2;\n color: white;\n cursor: pointer;\n font-size: 14px;\n font-weight: 500;\n transition: all 0.2s ease;\n }\n\n .close-btn:hover {\n background-color: #1565c0;\n border-color: #1565c0;\n }\n `\n ]\n\n @property({ type: Object }) content?: HelpContent\n @property({ type: Object }) onClose?: () => void\n\n render() {\n if (!this.content) {\n return html``\n }\n\n return html`\n <div class=\"help-popup\">\n <div class=\"help-title\">${this.content.title}</div>\n\n <div class=\"help-content\">\n ${this.content.sections.map(\n section => html`\n <div class=\"help-section\">\n <div class=\"help-section-title\">${section.title}</div>\n ${this._renderSectionContent(section)}\n </div>\n `\n )}\n </div>\n\n <div class=\"help-footer\">\n <button class=\"close-btn\" @click=${this._onClose}>닫기</button>\n </div>\n </div>\n `\n }\n\n private _renderSectionContent(section: any) {\n switch (section.type) {\n case 'code':\n return html`<div class=\"help-code\">${section.content}</div>`\n case 'parameter':\n return html`<div class=\"help-parameter\">${section.content}</div>`\n case 'example':\n return html`<div class=\"help-example\">${section.content}</div>`\n default:\n return html`<div class=\"help-section-content\">${section.content}</div>`\n }\n }\n\n private _onClose() {\n this.onClose?.()\n }\n}\n"]}
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import '@material/web/icon/icon.js';
5
5
  import '@material/web/button/elevated-button.js';
6
+ import './ox-input-formula-help-popup.js';
6
7
  import '@operato/i18n/ox-i18n.js';
7
8
  import { OxFormField } from '@operato/input';
8
9
  type FormulaVariable = {
@@ -65,6 +66,7 @@ export declare class KpiFormulaEditor extends OxFormField {
65
66
  _insertFunction(template: string): void;
66
67
  _showVariableHelp(e: Event, variable: FormulaVariable): void;
67
68
  _showFunctionHelp(e: Event, func: FormulaFunction): void;
69
+ private _showHelpPopup;
68
70
  _validateFormula(): void;
69
71
  _updateValue(): void;
70
72
  }
@@ -4,10 +4,12 @@
4
4
  import { __decorate } from "tslib";
5
5
  import '@material/web/icon/icon.js';
6
6
  import '@material/web/button/elevated-button.js';
7
+ import './ox-input-formula-help-popup.js';
7
8
  import '@operato/i18n/ox-i18n.js';
8
9
  import { css, html } from 'lit';
9
10
  import { customElement, property, query, state } from 'lit/decorators.js';
10
11
  import { OxFormField } from '@operato/input';
12
+ import { ScrollbarStyles } from '@operato/styles';
11
13
  /**
12
14
  * Formula editor component for KPI calculations
13
15
  *
@@ -158,6 +160,7 @@ let KpiFormulaEditor = class KpiFormulaEditor extends OxFormField {
158
160
  ];
159
161
  }
160
162
  static { this.styles = [
163
+ ScrollbarStyles,
161
164
  css `
162
165
  :host {
163
166
  display: flex;
@@ -380,69 +383,80 @@ let KpiFormulaEditor = class KpiFormulaEditor extends OxFormField {
380
383
  max-width: 500px;
381
384
  max-height: 400px;
382
385
  overflow-y: auto;
386
+ background: white;
387
+ border-radius: 8px;
388
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
383
389
  }
384
390
 
385
391
  .help-title {
386
- font-size: 16px;
392
+ font-size: 20px;
387
393
  font-weight: 600;
388
- margin-bottom: var(--spacing-medium);
394
+ margin-bottom: 16px;
389
395
  color: var(--md-sys-color-primary);
396
+ padding: 20px 20px 16px 20px;
397
+ background: #f8f9fa;
398
+ border-bottom: 1px solid #e0e0e0;
399
+ border-radius: 8px 8px 0 0;
390
400
  }
391
401
 
392
402
  .help-section {
393
- margin-bottom: var(--spacing-medium);
403
+ margin-bottom: 16px;
404
+ padding: 0 20px;
394
405
  }
395
406
 
396
407
  .help-section-title {
397
- font-weight: 500;
398
- margin-bottom: var(--spacing-small);
399
- color: var(--md-sys-color-on-surface);
408
+ font-weight: 600;
409
+ margin-bottom: 8px;
410
+ color: #333;
411
+ font-size: 14px;
412
+ border-bottom: 1px solid #e0e0e0;
413
+ padding-bottom: 4px;
400
414
  }
401
415
 
402
416
  .help-content {
403
417
  font-size: 14px;
404
- line-height: 1.5;
405
- color: var(--md-sys-color-on-surface);
418
+ line-height: 1.6;
419
+ color: #555;
420
+ padding: 4px 0;
406
421
  }
407
422
 
408
423
  .help-syntax {
409
- background-color: #f8f9fa;
410
- padding: var(--spacing-small);
424
+ background: #f5f5f5;
425
+ border: 1px solid #e0e0e0;
411
426
  border-radius: 4px;
427
+ padding: 12px;
412
428
  font-family: 'Courier New', monospace;
413
- font-size: 12px;
414
- margin: var(--spacing-small) 0;
415
- border-left: 3px solid var(--md-sys-color-primary);
429
+ font-size: 13px;
430
+ color: #333;
431
+ margin: 8px 0;
416
432
  }
417
433
 
418
434
  .help-example {
419
- background-color: #f0f8ff;
420
- padding: var(--spacing-small);
435
+ background: #f0f8ff;
436
+ border: 1px solid #c8e6c9;
421
437
  border-radius: 4px;
438
+ padding: 12px;
422
439
  font-family: 'Courier New', monospace;
423
- font-size: 12px;
424
- margin: var(--spacing-small) 0;
425
- border-left: 3px solid var(--md-sys-color-secondary);
440
+ font-size: 13px;
441
+ color: #2e7d32;
442
+ margin: 8px 0;
426
443
  }
427
444
 
428
445
  .help-parameters {
429
- margin: var(--spacing-small) 0;
446
+ margin: 8px 0;
430
447
  }
431
448
 
432
449
  .help-parameter {
433
- display: flex;
434
- justify-content: space-between;
435
- padding: 2px 0;
436
- border-bottom: 1px solid rgba(0, 0, 0, 0.1);
437
- }
438
-
439
- .help-parameter-name {
440
- font-weight: 500;
441
- font-family: 'Courier New', monospace;
450
+ background: #f8f9fa;
451
+ border-left: 3px solid var(--md-sys-color-primary);
452
+ border-radius: 4px;
453
+ padding: 8px 12px;
454
+ margin-bottom: 4px;
455
+ font-size: 13px;
442
456
  }
443
457
 
444
458
  .help-parameter-desc {
445
- color: var(--md-sys-color-on-surface-variant);
459
+ color: #555;
446
460
  }
447
461
 
448
462
  /* Dialog specific styles */
@@ -464,25 +478,27 @@ let KpiFormulaEditor = class KpiFormulaEditor extends OxFormField {
464
478
  .dialog-actions {
465
479
  display: flex;
466
480
  justify-content: flex-end;
467
- gap: var(--spacing-small);
468
- margin-top: var(--spacing-medium);
469
- padding: var(--spacing-medium);
470
- border-top: 1px solid var(--md-sys-color-outline);
481
+ padding: 16px 20px;
482
+ border-top: 1px solid #e0e0e0;
483
+ background: #f8f9fa;
484
+ border-radius: 0 0 8px 8px;
471
485
  }
472
486
 
473
487
  .close-btn {
474
- padding: var(--spacing-small) var(--spacing-medium);
475
- border: 1px solid var(--md-sys-color-outline);
488
+ padding: 8px 16px;
489
+ border: 1px solid var(--md-sys-color-primary);
476
490
  border-radius: 4px;
477
- background-color: white;
491
+ background-color: var(--md-sys-color-primary);
492
+ color: white;
478
493
  cursor: pointer;
479
494
  font-size: 14px;
495
+ font-weight: 500;
480
496
  transition: all 0.2s ease;
481
497
  }
482
498
 
483
499
  .close-btn:hover {
484
- background-color: var(--md-sys-color-secondary-container);
485
- border-color: var(--md-sys-color-secondary);
500
+ background-color: #1565c0;
501
+ border-color: #1565c0;
486
502
  }
487
503
 
488
504
  .middle-align {
@@ -730,170 +746,110 @@ let KpiFormulaEditor = class KpiFormulaEditor extends OxFormField {
730
746
  }
731
747
  _showVariableHelp(e, variable) {
732
748
  e.stopPropagation();
733
- // 간단한 테스트 버전
734
- const message = `
735
- 변수: ${variable.name}
736
- 설명: ${variable.description || '없음'}
737
- 타입: ${variable.type || '없음'}
738
- 단위: ${variable.unit || '없음'}
739
- 예시: ${variable.example || '없음'}
740
- `.trim();
741
- console.log('Variable help:', message);
742
- // dialog 지원 여부 확인
743
- if (typeof HTMLDialogElement !== 'undefined') {
744
- const dialog = document.createElement('dialog');
745
- dialog.className = 'help-dialog';
746
- // HTML 문자열로 직접 작성
747
- dialog.innerHTML = `
748
- <div class="help-popup">
749
- <div class="help-title">${variable.name}</div>
750
-
751
- ${variable.description
752
- ? `
753
- <div class="help-section">
754
- <div class="help-section-title">설명</div>
755
- <div class="help-content">${variable.description}</div>
756
- </div>
757
- `
758
- : ''}
759
-
760
- ${variable.type
761
- ? `
762
- <div class="help-section">
763
- <div class="help-section-title">타입</div>
764
- <div class="help-content">${variable.type}</div>
765
- </div>
766
- `
767
- : ''}
768
-
769
- ${variable.unit
770
- ? `
771
- <div class="help-section">
772
- <div class="help-section-title">단위</div>
773
- <div class="help-content">${variable.unit}</div>
774
- </div>
775
- `
776
- : ''}
777
-
778
- ${variable.help
779
- ? `
780
- <div class="help-section">
781
- <div class="help-section-title">상세 설명</div>
782
- <div class="help-content">${variable.help}</div>
783
- </div>
784
- `
785
- : ''}
786
-
787
- ${variable.example
788
- ? `
789
- <div class="help-section">
790
- <div class="help-section-title">사용 예시</div>
791
- <div class="help-example">${variable.example}</div>
792
- </div>
793
- `
794
- : ''}
795
- </div>
796
-
797
- <div class="dialog-actions">
798
- <button class="close-btn" onclick="this.closest('dialog').close()">닫기</button>
799
- </div>
800
- `;
801
- document.body.appendChild(dialog);
802
- dialog.showModal();
803
- // 외부 클릭으로 닫기
804
- dialog.addEventListener('click', event => {
805
- const rect = dialog.getBoundingClientRect();
806
- const isInDialog = event.clientX >= rect.left &&
807
- event.clientX <= rect.right &&
808
- event.clientY >= rect.top &&
809
- event.clientY <= rect.bottom;
810
- if (!isInDialog) {
811
- dialog.close();
812
- }
749
+ const sections = [];
750
+ if (variable.description) {
751
+ sections.push({
752
+ title: '설명',
753
+ content: variable.description,
754
+ type: 'text'
813
755
  });
814
- dialog.addEventListener('close', () => {
815
- if (document.body.contains(dialog)) {
816
- document.body.removeChild(dialog);
817
- }
756
+ }
757
+ if (variable.type) {
758
+ sections.push({
759
+ title: '타입',
760
+ content: variable.type,
761
+ type: 'text'
762
+ });
763
+ }
764
+ if (variable.unit) {
765
+ sections.push({
766
+ title: '단위',
767
+ content: variable.unit,
768
+ type: 'text'
769
+ });
770
+ }
771
+ if (variable.help) {
772
+ sections.push({
773
+ title: '상세 설명',
774
+ content: variable.help,
775
+ type: 'text'
818
776
  });
819
- // ESC 키로 닫기
820
- const handleEsc = (e) => {
821
- if (e.key === 'Escape') {
822
- dialog.close();
823
- document.removeEventListener('keydown', handleEsc);
824
- }
825
- };
826
- document.addEventListener('keydown', handleEsc);
827
777
  }
828
- else {
829
- // dialog를 지원하지 않는 브라우저에서는 alert 사용
830
- alert(message);
778
+ if (variable.example) {
779
+ sections.push({
780
+ title: '사용 예시',
781
+ content: variable.example,
782
+ type: 'example'
783
+ });
831
784
  }
785
+ const helpContent = {
786
+ title: variable.name,
787
+ sections
788
+ };
789
+ this._showHelpPopup(helpContent);
832
790
  }
833
791
  _showFunctionHelp(e, func) {
834
792
  e.stopPropagation();
793
+ const sections = [
794
+ {
795
+ title: '설명',
796
+ content: func.description,
797
+ type: 'text'
798
+ },
799
+ {
800
+ title: '구문',
801
+ content: func.syntax,
802
+ type: 'code'
803
+ },
804
+ {
805
+ title: '매개변수',
806
+ content: func.parameters.join('\n'),
807
+ type: 'parameter'
808
+ },
809
+ {
810
+ title: '반환 타입',
811
+ content: func.returnType,
812
+ type: 'text'
813
+ }
814
+ ];
815
+ if (func.help) {
816
+ sections.push({
817
+ title: '상세 설명',
818
+ content: func.help,
819
+ type: 'text'
820
+ });
821
+ }
822
+ if (func.examples && func.examples.length > 0) {
823
+ sections.push({
824
+ title: '사용 예시',
825
+ content: func.examples.join('\n'),
826
+ type: 'example'
827
+ });
828
+ }
829
+ const helpContent = {
830
+ title: func.name,
831
+ sections
832
+ };
833
+ this._showHelpPopup(helpContent);
834
+ }
835
+ _showHelpPopup(content) {
835
836
  const dialog = document.createElement('dialog');
836
- dialog.className = 'help-dialog';
837
- // HTML 문자열로 직접 작성
838
- dialog.innerHTML = `
839
- <div class="help-popup">
840
- <div class="help-title">${func.name}</div>
841
-
842
- <div class="help-section">
843
- <div class="help-section-title">설명</div>
844
- <div class="help-content">${func.description}</div>
845
- </div>
846
-
847
- <div class="help-section">
848
- <div class="help-section-title">구문</div>
849
- <div class="help-syntax">${func.syntax}</div>
850
- </div>
851
-
852
- <div class="help-section">
853
- <div class="help-section-title">매개변수</div>
854
- <div class="help-parameters">
855
- ${func.parameters
856
- .map(param => `
857
- <div class="help-parameter">
858
- <span class="help-parameter-desc">${param}</span>
859
- </div>
860
- `)
861
- .join('')}
862
- </div>
863
- </div>
864
-
865
- <div class="help-section">
866
- <div class="help-section-title">반환 타입</div>
867
- <div class="help-content">${func.returnType}</div>
868
- </div>
869
-
870
- ${func.help
871
- ? `
872
- <div class="help-section">
873
- <div class="help-section-title">상세 설명</div>
874
- <div class="help-content">${func.help}</div>
875
- </div>
876
- `
877
- : ''}
878
-
879
- ${func.examples && func.examples.length > 0
880
- ? `
881
- <div class="help-section">
882
- <div class="help-section-title">사용 예시</div>
883
- ${func.examples
884
- .map(example => `
885
- <div class="help-example">${example}</div>
886
- `)
887
- .join('')}
888
- </div>
889
- `
890
- : ''}
891
- </div>
892
-
893
- <div class="dialog-actions">
894
- <button class="close-btn" onclick="this.closest('dialog').close()">닫기</button>
895
- </div>
837
+ dialog.style.cssText = `
838
+ border: none;
839
+ border-radius: 8px;
840
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
841
+ padding: 0;
842
+ max-width: 500px;
843
+ max-height: 80vh;
844
+ overflow-y: auto;
845
+ background-color: white;
896
846
  `;
847
+ const helpPopup = document.createElement('ox-input-formula-help-popup');
848
+ helpPopup.content = content;
849
+ helpPopup.onClose = () => {
850
+ dialog.close();
851
+ };
852
+ dialog.appendChild(helpPopup);
897
853
  document.body.appendChild(dialog);
898
854
  dialog.showModal();
899
855
  // 외부 클릭으로 닫기