@operato/input 9.0.9 → 9.0.10
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.10](https://github.com/hatiolab/operato/compare/v9.0.9...v9.0.10) (2025-07-23)
|
7
|
+
|
8
|
+
|
9
|
+
### :bug: Bug Fix
|
10
|
+
|
11
|
+
* ox-grist-editor-formula ([f0e165e](https://github.com/hatiolab/operato/commit/f0e165e06a29dc6a4cf3adf85d20cc1e7b36ce4e))
|
12
|
+
|
13
|
+
|
14
|
+
|
6
15
|
### [9.0.9](https://github.com/hatiolab/operato/compare/v9.0.8...v9.0.9) (2025-07-23)
|
7
16
|
|
8
17
|
|
@@ -50,7 +50,6 @@ export declare class KpiFormulaEditor extends OxFormField {
|
|
50
50
|
reset(): void;
|
51
51
|
private readonly operators;
|
52
52
|
private readonly functions;
|
53
|
-
private _normalizeVariableName;
|
54
53
|
firstUpdated(): void;
|
55
54
|
render(): import("lit-html").TemplateResult<1>;
|
56
55
|
updated(changes: any): void;
|
@@ -514,10 +514,7 @@ let KpiFormulaEditor = class KpiFormulaEditor extends OxFormField {
|
|
514
514
|
this._updateValue();
|
515
515
|
}
|
516
516
|
// 변수명 정규화 헬퍼 메서드
|
517
|
-
_normalizeVariableName
|
518
|
-
// 공백을 언더스코어로 변경
|
519
|
-
return name.replace(/\s+/g, '_');
|
520
|
-
}
|
517
|
+
// _normalizeVariableName 메서드 완전히 삭제
|
521
518
|
firstUpdated() {
|
522
519
|
this.addEventListener('change', this._onChange.bind(this));
|
523
520
|
}
|
@@ -563,7 +560,7 @@ let KpiFormulaEditor = class KpiFormulaEditor extends OxFormField {
|
|
563
560
|
<div class="variables-grid">
|
564
561
|
${this.availableVariables.map(variable => html `
|
565
562
|
<div class="variable-item" @click=${() => this._insertVariable(variable.name)}>
|
566
|
-
<div class="variable-name">[${
|
563
|
+
<div class="variable-name">[${variable.name}]</div>
|
567
564
|
${variable.description ? html ` <div class="variable-description">${variable.description}</div> ` : ''}
|
568
565
|
${variable.type ? html ` <div class="variable-type">${variable.type}</div> ` : ''}
|
569
566
|
${variable.help
|
@@ -655,9 +652,8 @@ let KpiFormulaEditor = class KpiFormulaEditor extends OxFormField {
|
|
655
652
|
const start = this.editor.selectionStart;
|
656
653
|
const end = this.editor.selectionEnd;
|
657
654
|
const currentValue = this.editor.value;
|
658
|
-
// 변수명
|
659
|
-
const
|
660
|
-
const insertText = `[${normalizedName}]`;
|
655
|
+
// 변수명을 [변수명] 형태로만 감싸서 삽입
|
656
|
+
const insertText = `[${variableName}]`;
|
661
657
|
const newValue = currentValue.substring(0, start) + insertText + currentValue.substring(end);
|
662
658
|
this.editor.value = newValue;
|
663
659
|
this.value = newValue;
|
@@ -915,9 +911,8 @@ let KpiFormulaEditor = class KpiFormulaEditor extends OxFormField {
|
|
915
911
|
const variableRefs = formula.match(/\[([^\]]+)\]/g) || [];
|
916
912
|
for (const ref of variableRefs) {
|
917
913
|
const varName = ref.slice(1, -1); // [변수명]에서 변수명 추출
|
918
|
-
const
|
919
|
-
|
920
|
-
if (!availableVarNames.includes(normalizedVarName)) {
|
914
|
+
const availableVarNames = this.availableVariables.map(v => v.name);
|
915
|
+
if (!availableVarNames.includes(varName)) {
|
921
916
|
this.errorMessage = `알 수 없는 변수: ${varName}`;
|
922
917
|
this.isValid = false;
|
923
918
|
return;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ox-input-formula.js","sourceRoot":"","sources":["../../src/ox-input-formula.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\n\nimport '@operato/i18n/ox-i18n.js'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { OxFormField } from '@operato/input'\n\ntype FormulaVariable = {\n name: string\n description?: string\n type?: 'number' | 'string' | 'date' | 'metric' | 'kpi'\n unit?: string\n help?: string\n example?: string\n}\n\ntype FormulaFunction = {\n name: string\n description: string\n template: string\n syntax: string\n parameters: string[]\n returnType: string\n help?: string\n examples?: string[]\n}\n\n/**\n * Formula editor component for KPI calculations\n *\n * Example:\n *\n * <ox-input-formula\n * .value=${formulaValue}\n * .availableVariables=${variables}\n * ></ox-input-formula>\n */\n@customElement('ox-input-formula')\nexport class KpiFormulaEditor extends OxFormField {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n margin-bottom: var(--spacing-large);\n gap: var(--spacing-medium);\n }\n\n .formula-container {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small);\n }\n\n .formula-input-container {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small);\n }\n\n .formula-textarea {\n min-height: 120px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 4px;\n padding: var(--spacing-medium);\n font-family: 'Courier New', monospace;\n font-size: 14px;\n line-height: 1.4;\n resize: vertical;\n background-color: #f8f9fa;\n font-size: 1.3rem;\n }\n\n .formula-textarea:focus {\n outline: none;\n border-color: var(--md-sys-color-primary);\n background-color: white;\n }\n\n .variables-container {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small);\n }\n\n .variables-header {\n display: flex;\n align-items: center;\n gap: var(--spacing-small);\n font-weight: 500;\n color: var(--md-sys-color-on-surface);\n }\n\n .variables-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: var(--spacing-small);\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: 4px;\n padding: var(--spacing-small);\n background-color: #f8f9fa;\n }\n\n .variable-item {\n display: flex;\n flex-direction: column;\n padding: var(--spacing-small);\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: 4px;\n background-color: white;\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .variable-item:hover {\n border-color: var(--md-sys-color-primary);\n background-color: var(--md-sys-color-primary-container);\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n }\n\n .variable-name {\n font-weight: 500;\n color: var(--md-sys-color-primary);\n font-size: 12px;\n font-family: 'Courier New', monospace;\n }\n\n .variable-description {\n font-size: 11px;\n color: var(--md-sys-color-on-surface-variant);\n margin-top: 2px;\n }\n\n .variable-type {\n font-size: 10px;\n color: var(--md-sys-color-outline);\n margin-top: 2px;\n text-transform: uppercase;\n }\n\n .help-icon {\n position: absolute;\n top: 4px;\n right: 4px;\n font-size: 14px;\n color: var(--md-sys-color-outline);\n cursor: pointer;\n padding: 2px;\n border-radius: 2px;\n transition: all 0.2s ease;\n }\n\n .help-icon:hover {\n color: var(--md-sys-color-primary);\n background-color: var(--md-sys-color-primary-container);\n }\n\n .operators-container {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-small);\n margin-top: var(--spacing-small);\n }\n\n .operator-button {\n padding: var(--spacing-small) var(--spacing-medium);\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 4px;\n background-color: white;\n cursor: pointer;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n transition: all 0.2s ease;\n }\n\n .operator-button:hover {\n background-color: var(--md-sys-color-primary-container);\n border-color: var(--md-sys-color-primary);\n }\n\n .functions-container {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small);\n margin-top: var(--spacing-small);\n }\n\n .functions-header {\n font-weight: 500;\n color: var(--md-sys-color-on-surface);\n }\n\n .functions-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: var(--spacing-small);\n }\n\n .function-button {\n padding: var(--spacing-small);\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 4px;\n background-color: white;\n cursor: pointer;\n font-family: 'Courier New', monospace;\n font-size: 11px;\n text-align: left;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .function-button:hover {\n background-color: var(--md-sys-color-secondary-container);\n border-color: var(--md-sys-color-secondary);\n }\n\n .preview-container {\n margin-top: var(--spacing-medium);\n padding: var(--spacing-medium);\n background-color: #f8f9fa;\n border-radius: 4px;\n border: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n .preview-title {\n font-weight: 500;\n margin-bottom: var(--spacing-small);\n color: var(--md-sys-color-on-surface);\n }\n\n .preview-formula {\n font-family: 'Courier New', monospace;\n background-color: white;\n padding: var(--spacing-small);\n border-radius: 4px;\n border: 1px solid rgba(0, 0, 0, 0.1);\n white-space: pre-wrap;\n word-break: break-all;\n }\n\n .error-message {\n color: var(--md-sys-color-error);\n font-size: 12px;\n margin-top: var(--spacing-small);\n }\n\n .info-message {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n margin-top: var(--spacing-small);\n }\n\n /* 도움말 팝업 스타일 */\n .help-popup {\n max-width: 500px;\n max-height: 400px;\n overflow-y: auto;\n }\n\n .help-title {\n font-size: 16px;\n font-weight: 600;\n margin-bottom: var(--spacing-medium);\n color: var(--md-sys-color-primary);\n }\n\n .help-section {\n margin-bottom: var(--spacing-medium);\n }\n\n .help-section-title {\n font-weight: 500;\n margin-bottom: var(--spacing-small);\n color: var(--md-sys-color-on-surface);\n }\n\n .help-content {\n font-size: 14px;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface);\n }\n\n .help-syntax {\n background-color: #f8f9fa;\n padding: var(--spacing-small);\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n margin: var(--spacing-small) 0;\n border-left: 3px solid var(--md-sys-color-primary);\n }\n\n .help-example {\n background-color: #f0f8ff;\n padding: var(--spacing-small);\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n margin: var(--spacing-small) 0;\n border-left: 3px solid var(--md-sys-color-secondary);\n }\n\n .help-parameters {\n margin: var(--spacing-small) 0;\n }\n\n .help-parameter {\n display: flex;\n justify-content: space-between;\n padding: 2px 0;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n .help-parameter-name {\n font-weight: 500;\n font-family: 'Courier New', monospace;\n }\n\n .help-parameter-desc {\n color: var(--md-sys-color-on-surface-variant);\n }\n\n /* Dialog specific styles */\n .help-dialog {\n border: none;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);\n padding: 0;\n max-width: 500px;\n max-height: 80vh;\n overflow-y: auto;\n background-color: white;\n }\n\n .help-dialog::backdrop {\n background-color: rgba(0, 0, 0, 0.5);\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--spacing-small);\n margin-top: var(--spacing-medium);\n padding: var(--spacing-medium);\n border-top: 1px solid var(--md-sys-color-outline);\n }\n\n .close-btn {\n padding: var(--spacing-small) var(--spacing-medium);\n border: 1px solid var(--md-sys-color-outline);\n border-radius: 4px;\n background-color: white;\n cursor: pointer;\n font-size: 14px;\n transition: all 0.2s ease;\n }\n\n .close-btn:hover {\n background-color: var(--md-sys-color-secondary-container);\n border-color: var(--md-sys-color-secondary);\n }\n\n .middle-align {\n display: flex;\n align-items: center;\n }\n `\n ]\n\n @property({ type: String }) value: string = ''\n @property({ type: Array }) availableVariables: FormulaVariable[] = []\n\n @state() private errorMessage: string = ''\n @state() private isValid: boolean = true\n\n @query('.formula-textarea') editor!: HTMLTextAreaElement\n\n private _changingNow: boolean = false\n\n getValue(): any {\n return this.value\n }\n\n setValue(value: any): void {\n this.value = value\n this._validateFormula()\n }\n\n validate(): boolean {\n this._validateFormula()\n return this.isValid\n }\n\n getErrorMessage(): string {\n return this.errorMessage\n }\n\n focus(): void {\n this.editor.focus()\n }\n\n blur(): void {\n this.editor.blur()\n }\n\n reset(): void {\n this.value = ''\n this.errorMessage = ''\n this.isValid = true\n this._updateValue()\n }\n\n // 기본 연산자들\n private readonly operators = [\n { symbol: '+', description: '더하기' },\n { symbol: '-', description: '빼기' },\n { symbol: '*', description: '곱하기' },\n { symbol: '/', description: '나누기' },\n { symbol: '(', description: '여는 괄호' },\n { symbol: ')', description: '닫는 괄호' },\n { symbol: '=', description: '같음' },\n { symbol: '>', description: '보다 큼' },\n { symbol: '<', description: '보다 작음' },\n { symbol: '>=', description: '보다 크거나 같음' },\n { symbol: '<=', description: '보다 작거나 같음' },\n { symbol: '!=', description: '다름' },\n { symbol: '&&', description: 'AND' },\n { symbol: '||', description: 'OR' }\n ]\n\n // 기본 함수들 (도움말 정보 포함)\n private readonly functions: FormulaFunction[] = [\n {\n name: 'SUM()',\n description: '합계',\n template: 'SUM({expression})',\n syntax: 'SUM(expression)',\n parameters: ['expression - 합계를 계산할 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들의 합계를 계산합니다. 숫자 배열이나 변수들을 인자로 받습니다.',\n examples: ['SUM(metric1, metric2, metric3)', 'SUM(production_data)', 'SUM(100, 200, 300)']\n },\n {\n name: 'AVG()',\n description: '평균',\n template: 'AVG({expression})',\n syntax: 'AVG(expression)',\n parameters: ['expression - 평균을 계산할 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들의 평균을 계산합니다. 숫자 배열이나 변수들을 인자로 받습니다.',\n examples: ['AVG(quality_scores)', 'AVG(metric1, metric2, metric3)', 'AVG(10, 20, 30)']\n },\n {\n name: 'MAX()',\n description: '최대값',\n template: 'MAX({expression})',\n syntax: 'MAX(expression)',\n parameters: ['expression - 최대값을 찾을 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들 중 최대값을 반환합니다.',\n examples: ['MAX(performance_data)', 'MAX(metric1, metric2, metric3)', 'MAX(100, 200, 300)']\n },\n {\n name: 'MIN()',\n description: '최소값',\n template: 'MIN({expression})',\n syntax: 'MIN(expression)',\n parameters: ['expression - 최소값을 찾을 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들 중 최소값을 반환합니다.',\n examples: ['MIN(quality_scores)', 'MIN(metric1, metric2, metric3)', 'MIN(10, 20, 30)']\n },\n {\n name: 'COUNT()',\n description: '개수',\n template: 'COUNT({expression})',\n syntax: 'COUNT(expression)',\n parameters: ['expression - 개수를 셀 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들의 개수를 반환합니다.',\n examples: ['COUNT(active_projects)', 'COUNT(metric1, metric2, metric3)', 'COUNT(1, 2, 3, 4, 5)']\n },\n {\n name: 'ROUND()',\n description: '반올림',\n template: 'ROUND({expression}, 2)',\n syntax: 'ROUND(expression, decimals)',\n parameters: ['expression - 반올림할 값', 'decimals - 소수점 자릿수 (기본값: 0)'],\n returnType: 'number',\n help: '주어진 값을 지정된 소수점 자릿수로 반올림합니다.',\n examples: ['ROUND(3.14159, 2) → 3.14', 'ROUND(metric1, 0)', 'ROUND(AVG(scores), 1)']\n },\n {\n name: 'ABS()',\n description: '절대값',\n template: 'ABS({expression})',\n syntax: 'ABS(expression)',\n parameters: ['expression - 절대값을 구할 값'],\n returnType: 'number',\n help: '주어진 값의 절대값을 반환합니다.',\n examples: ['ABS(-10) → 10', 'ABS(metric1 - target)', 'ABS(deviation)']\n },\n {\n name: 'IF()',\n description: '조건문',\n template: 'IF({condition}, {true_value}, {false_value})',\n syntax: 'IF(condition, true_value, false_value)',\n parameters: [\n 'condition - 조건식 (true/false)',\n 'true_value - 조건이 참일 때 반환할 값',\n 'false_value - 조건이 거짓일 때 반환할 값'\n ],\n returnType: 'any',\n help: '조건에 따라 다른 값을 반환합니다. 조건이 참이면 true_value를, 거짓이면 false_value를 반환합니다.',\n examples: [\n 'IF(score > 80, \"우수\", \"보통\")',\n 'IF(metric1 > target, 100, 0)',\n 'IF(quality_score >= 90, \"A등급\", IF(quality_score >= 80, \"B등급\", \"C등급\"))'\n ]\n },\n {\n name: 'CASE()',\n description: '케이스문',\n template: 'CASE {expression} WHEN {value1} THEN {result1} ELSE {default} END',\n syntax: 'CASE expression WHEN value1 THEN result1 [WHEN value2 THEN result2]... ELSE default END',\n parameters: [\n 'expression - 비교할 값',\n 'value1, value2... - 비교할 값들',\n 'result1, result2... - 해당 값일 때 반환할 결과들',\n 'default - 기본값'\n ],\n returnType: 'any',\n help: '여러 조건에 따라 다른 값을 반환합니다. IF문의 확장된 형태입니다.',\n examples: [\n 'CASE grade WHEN \"A\" THEN 100 WHEN \"B\" THEN 80 WHEN \"C\" THEN 60 ELSE 0 END',\n 'CASE score WHEN 90 THEN \"우수\" WHEN 80 THEN \"양호\" WHEN 70 THEN \"보통\" ELSE \"미흡\" END'\n ]\n }\n ]\n\n // 변수명 정규화 헬퍼 메서드\n private _normalizeVariableName(name: string): string {\n // 공백을 언더스코어로 변경\n return name.replace(/\\s+/g, '_')\n }\n\n firstUpdated() {\n this.addEventListener('change', this._onChange.bind(this))\n }\n\n render() {\n return html`\n <div class=\"formula-container\">\n <div class=\"formula-input-container\">\n <label class=\"variables-header\">\n <ox-i18n msgid=\"label.formula\"></ox-i18n>\n </label>\n\n <textarea\n class=\"formula-textarea\"\n .value=${this.value}\n @input=${this._onFormulaInput.bind(this)}\n placeholder=\"수식을 입력하세요. 예: SUM(metric1) + AVG(metric2) * 0.5\"\n ></textarea>\n\n ${this.errorMessage\n ? html`\n <div class=\"error-message middle-align\">\n <md-icon>error</md-icon>\n ${this.errorMessage}\n </div>\n `\n : ''}\n ${!this.errorMessage && this.value\n ? html`\n <div class=\"info-message middle-align\">\n <md-icon>info</md-icon>\n 수식이 유효합니다.\n </div>\n `\n : ''}\n </div>\n\n <div class=\"variables-container\">\n <div class=\"variables-header middle-align\">\n <md-icon>variables</md-icon>\n <ox-i18n msgid=\"label.available-variables\"></ox-i18n>\n </div>\n\n <div class=\"variables-grid\">\n ${this.availableVariables.map(\n variable => html`\n <div class=\"variable-item\" @click=${() => this._insertVariable(variable.name)}>\n <div class=\"variable-name\">[${this._normalizeVariableName(variable.name)}]</div>\n ${variable.description ? html` <div class=\"variable-description\">${variable.description}</div> ` : ''}\n ${variable.type ? html` <div class=\"variable-type\">${variable.type}</div> ` : ''}\n ${variable.help\n ? html`\n <md-icon class=\"help-icon\" @click=${(e: Event) => this._showVariableHelp(e, variable)}>\n help\n </md-icon>\n `\n : ''}\n </div>\n `\n )}\n </div>\n </div>\n\n <div class=\"operators-container\">\n <div class=\"variables-header middle-align\">\n <md-icon>calculate</md-icon>\n <ox-i18n msgid=\"label.operators\"></ox-i18n>\n </div>\n\n ${this.operators.map(\n op => html`\n <button class=\"operator-button\" @click=${() => this._insertOperator(op.symbol)} title=\"${op.description}\">\n ${op.symbol}\n </button>\n `\n )}\n </div>\n\n <div class=\"functions-container\">\n <div class=\"functions-header middle-align\">\n <md-icon>functions</md-icon>\n <ox-i18n msgid=\"label.functions\"></ox-i18n>\n </div>\n\n <div class=\"functions-grid\">\n ${this.functions.map(\n func => html`\n <div class=\"function-button\" @click=${() => this._insertFunction(func.template)}>\n <div style=\"font-weight: 500;\">${func.name}</div>\n <div style=\"font-size: 10px; color: var(--md-sys-color-on-surface-variant);\">${func.description}</div>\n ${func.help\n ? html`\n <md-icon\n class=\"help-icon\"\n @click=${(e: Event) => this._showFunctionHelp(e, func)}\n style=\"position: absolute; top: 4px; right: 4px; font-size: 12px;\"\n >\n help\n </md-icon>\n `\n : ''}\n </div>\n `\n )}\n </div>\n </div>\n\n ${this.value\n ? html`\n <div class=\"preview-container\">\n <div class=\"preview-title middle-align\">\n <md-icon>preview</md-icon>\n <ox-i18n msgid=\"label.formula-preview\"></ox-i18n>\n </div>\n <div class=\"preview-formula\">${this.value}</div>\n </div>\n `\n : ''}\n </div>\n `\n }\n\n updated(changes: any) {\n if (changes.has('value')) {\n this._validateFormula()\n }\n }\n\n _onChange(e: Event) {\n if (this._changingNow) {\n return\n }\n\n this._changingNow = true\n this._updateValue()\n this._changingNow = false\n }\n\n _onFormulaInput(e: Event) {\n const textarea = e.target as HTMLTextAreaElement\n this.value = textarea.value\n this._validateFormula()\n this._updateValue()\n }\n\n _insertVariable(variableName: string) {\n const start = this.editor.selectionStart\n const end = this.editor.selectionEnd\n const currentValue = this.editor.value\n\n // 변수명 정규화 (공백을 언더스코어로 변경)\n const normalizedName = this._normalizeVariableName(variableName)\n const insertText = `[${normalizedName}]`\n const newValue = currentValue.substring(0, start) + insertText + currentValue.substring(end)\n this.editor.value = newValue\n this.value = newValue\n\n // 커서 위치 조정\n const newCursorPos = start + insertText.length\n this.editor.setSelectionRange(newCursorPos, newCursorPos)\n this.editor.focus()\n\n this._validateFormula()\n this._updateValue()\n }\n\n _insertOperator(operator: string) {\n const start = this.editor.selectionStart\n const end = this.editor.selectionEnd\n const currentValue = this.editor.value\n\n // 연산자 앞뒤에 공백 추가\n const insertText = ` ${operator} `\n const newValue = currentValue.substring(0, start) + insertText + currentValue.substring(end)\n this.editor.value = newValue\n this.value = newValue\n\n // 커서 위치 조정\n const newCursorPos = start + insertText.length\n this.editor.setSelectionRange(newCursorPos, newCursorPos)\n this.editor.focus()\n\n this._validateFormula()\n this._updateValue()\n }\n\n _insertFunction(template: string) {\n const start = this.editor.selectionStart\n const end = this.editor.selectionEnd\n const currentValue = this.editor.value\n\n // 선택된 텍스트가 있으면 그것을 expression으로 사용\n const selectedText = currentValue.substring(start, end)\n const insertText = template.replace('{expression}', selectedText || 'expression')\n\n const newValue = currentValue.substring(0, start) + insertText + currentValue.substring(end)\n this.editor.value = newValue\n this.value = newValue\n\n // 커서 위치 조정 (expression 부분에 포커스)\n const expressionStart = start + insertText.indexOf('expression')\n const expressionEnd = expressionStart + 'expression'.length\n this.editor.setSelectionRange(expressionStart, expressionEnd)\n this.editor.focus()\n\n this._validateFormula()\n this._updateValue()\n }\n\n _showVariableHelp(e: Event, variable: FormulaVariable) {\n e.stopPropagation()\n\n // 간단한 테스트 버전\n const message = `\n변수: ${variable.name}\n설명: ${variable.description || '없음'}\n타입: ${variable.type || '없음'}\n단위: ${variable.unit || '없음'}\n예시: ${variable.example || '없음'}\n `.trim()\n\n console.log('Variable help:', message)\n\n // dialog 지원 여부 확인\n if (typeof HTMLDialogElement !== 'undefined') {\n const dialog = document.createElement('dialog')\n dialog.className = 'help-dialog'\n\n // HTML 문자열로 직접 작성\n dialog.innerHTML = `\n <div class=\"help-popup\">\n <div class=\"help-title\">${variable.name}</div>\n \n ${\n variable.description\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">설명</div>\n <div class=\"help-content\">${variable.description}</div>\n </div>\n `\n : ''\n }\n \n ${\n variable.type\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">타입</div>\n <div class=\"help-content\">${variable.type}</div>\n </div>\n `\n : ''\n }\n \n ${\n variable.unit\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">단위</div>\n <div class=\"help-content\">${variable.unit}</div>\n </div>\n `\n : ''\n }\n \n ${\n variable.help\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">상세 설명</div>\n <div class=\"help-content\">${variable.help}</div>\n </div>\n `\n : ''\n }\n \n ${\n variable.example\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">사용 예시</div>\n <div class=\"help-example\">${variable.example}</div>\n </div>\n `\n : ''\n }\n </div>\n \n <div class=\"dialog-actions\">\n <button class=\"close-btn\" onclick=\"this.closest('dialog').close()\">닫기</button>\n </div>\n `\n\n document.body.appendChild(dialog)\n dialog.showModal()\n\n // 외부 클릭으로 닫기\n dialog.addEventListener('click', event => {\n const rect = dialog.getBoundingClientRect()\n const isInDialog =\n event.clientX >= rect.left &&\n event.clientX <= rect.right &&\n event.clientY >= rect.top &&\n event.clientY <= rect.bottom\n\n if (!isInDialog) {\n dialog.close()\n }\n })\n\n dialog.addEventListener('close', () => {\n if (document.body.contains(dialog)) {\n document.body.removeChild(dialog)\n }\n })\n\n // ESC 키로 닫기\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n dialog.close()\n document.removeEventListener('keydown', handleEsc)\n }\n }\n document.addEventListener('keydown', handleEsc)\n } else {\n // dialog를 지원하지 않는 브라우저에서는 alert 사용\n alert(message)\n }\n }\n\n _showFunctionHelp(e: Event, func: FormulaFunction) {\n e.stopPropagation()\n\n const dialog = document.createElement('dialog')\n dialog.className = 'help-dialog'\n\n // HTML 문자열로 직접 작성\n dialog.innerHTML = `\n <div class=\"help-popup\">\n <div class=\"help-title\">${func.name}</div>\n\n <div class=\"help-section\">\n <div class=\"help-section-title\">설명</div>\n <div class=\"help-content\">${func.description}</div>\n </div>\n\n <div class=\"help-section\">\n <div class=\"help-section-title\">구문</div>\n <div class=\"help-syntax\">${func.syntax}</div>\n </div>\n\n <div class=\"help-section\">\n <div class=\"help-section-title\">매개변수</div>\n <div class=\"help-parameters\">\n ${func.parameters\n .map(\n param => `\n <div class=\"help-parameter\">\n <span class=\"help-parameter-desc\">${param}</span>\n </div>\n `\n )\n .join('')}\n </div>\n </div>\n\n <div class=\"help-section\">\n <div class=\"help-section-title\">반환 타입</div>\n <div class=\"help-content\">${func.returnType}</div>\n </div>\n\n ${\n func.help\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">상세 설명</div>\n <div class=\"help-content\">${func.help}</div>\n </div>\n `\n : ''\n }\n \n ${\n func.examples && func.examples.length > 0\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">사용 예시</div>\n ${func.examples\n .map(\n example => `\n <div class=\"help-example\">${example}</div>\n `\n )\n .join('')}\n </div>\n `\n : ''\n }\n </div>\n \n <div class=\"dialog-actions\">\n <button class=\"close-btn\" onclick=\"this.closest('dialog').close()\">닫기</button>\n </div>\n `\n\n document.body.appendChild(dialog)\n dialog.showModal()\n\n // 외부 클릭으로 닫기\n dialog.addEventListener('click', event => {\n const rect = dialog.getBoundingClientRect()\n const isInDialog =\n event.clientX >= rect.left &&\n event.clientX <= rect.right &&\n event.clientY >= rect.top &&\n event.clientY <= rect.bottom\n\n if (!isInDialog) {\n dialog.close()\n }\n })\n\n dialog.addEventListener('close', () => {\n if (document.body.contains(dialog)) {\n document.body.removeChild(dialog)\n }\n })\n\n // ESC 키로 닫기\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n dialog.close()\n document.removeEventListener('keydown', handleEsc)\n }\n }\n document.addEventListener('keydown', handleEsc)\n }\n\n _validateFormula() {\n // 기본적인 수식 유효성 검사\n const formula = this.value.trim()\n\n if (!formula) {\n this.errorMessage = ''\n this.isValid = true\n return\n }\n\n // 괄호 균형 검사\n const openBrackets = (formula.match(/\\(/g) || []).length\n const closeBrackets = (formula.match(/\\)/g) || []).length\n\n if (openBrackets !== closeBrackets) {\n this.errorMessage = '괄호가 균형을 이루지 않습니다.'\n this.isValid = false\n return\n }\n\n // 변수 참조 검증 ([변수명] 형태)\n const variableRefs = formula.match(/\\[([^\\]]+)\\]/g) || []\n for (const ref of variableRefs) {\n const varName = ref.slice(1, -1) // [변수명]에서 변수명 추출\n const normalizedVarName = this._normalizeVariableName(varName)\n const availableVarNames = this.availableVariables.map(v => this._normalizeVariableName(v.name))\n\n if (!availableVarNames.includes(normalizedVarName)) {\n this.errorMessage = `알 수 없는 변수: ${varName}`\n this.isValid = false\n return\n }\n }\n\n // 기본 문법 검사\n const invalidPatterns = [\n /[+\\-*/]{2,}/, // 연속된 연산자\n /[+\\-*/]\\s*$/, // 끝에 연산자\n /^\\s*[+\\-*/]/, // 시작에 연산자\n /\\(\\s*\\)/ // 빈 괄호\n ]\n\n for (const pattern of invalidPatterns) {\n if (pattern.test(formula)) {\n this.errorMessage = '수식 문법이 올바르지 않습니다.'\n this.isValid = false\n return\n }\n }\n\n this.errorMessage = ''\n this.isValid = true\n }\n\n _updateValue() {\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: this.value\n })\n )\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"ox-input-formula.js","sourceRoot":"","sources":["../../src/ox-input-formula.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\n\nimport '@operato/i18n/ox-i18n.js'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { OxFormField } from '@operato/input'\n\ntype FormulaVariable = {\n name: string\n description?: string\n type?: 'number' | 'string' | 'date' | 'metric' | 'kpi'\n unit?: string\n help?: string\n example?: string\n}\n\ntype FormulaFunction = {\n name: string\n description: string\n template: string\n syntax: string\n parameters: string[]\n returnType: string\n help?: string\n examples?: string[]\n}\n\n/**\n * Formula editor component for KPI calculations\n *\n * Example:\n *\n * <ox-input-formula\n * .value=${formulaValue}\n * .availableVariables=${variables}\n * ></ox-input-formula>\n */\n@customElement('ox-input-formula')\nexport class KpiFormulaEditor extends OxFormField {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n margin-bottom: var(--spacing-large);\n gap: var(--spacing-medium);\n }\n\n .formula-container {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small);\n }\n\n .formula-input-container {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small);\n }\n\n .formula-textarea {\n min-height: 120px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 4px;\n padding: var(--spacing-medium);\n font-family: 'Courier New', monospace;\n font-size: 14px;\n line-height: 1.4;\n resize: vertical;\n background-color: #f8f9fa;\n font-size: 1.3rem;\n }\n\n .formula-textarea:focus {\n outline: none;\n border-color: var(--md-sys-color-primary);\n background-color: white;\n }\n\n .variables-container {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small);\n }\n\n .variables-header {\n display: flex;\n align-items: center;\n gap: var(--spacing-small);\n font-weight: 500;\n color: var(--md-sys-color-on-surface);\n }\n\n .variables-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: var(--spacing-small);\n max-height: 200px;\n overflow-y: auto;\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: 4px;\n padding: var(--spacing-small);\n background-color: #f8f9fa;\n }\n\n .variable-item {\n display: flex;\n flex-direction: column;\n padding: var(--spacing-small);\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: 4px;\n background-color: white;\n cursor: pointer;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .variable-item:hover {\n border-color: var(--md-sys-color-primary);\n background-color: var(--md-sys-color-primary-container);\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);\n }\n\n .variable-name {\n font-weight: 500;\n color: var(--md-sys-color-primary);\n font-size: 12px;\n font-family: 'Courier New', monospace;\n }\n\n .variable-description {\n font-size: 11px;\n color: var(--md-sys-color-on-surface-variant);\n margin-top: 2px;\n }\n\n .variable-type {\n font-size: 10px;\n color: var(--md-sys-color-outline);\n margin-top: 2px;\n text-transform: uppercase;\n }\n\n .help-icon {\n position: absolute;\n top: 4px;\n right: 4px;\n font-size: 14px;\n color: var(--md-sys-color-outline);\n cursor: pointer;\n padding: 2px;\n border-radius: 2px;\n transition: all 0.2s ease;\n }\n\n .help-icon:hover {\n color: var(--md-sys-color-primary);\n background-color: var(--md-sys-color-primary-container);\n }\n\n .operators-container {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-small);\n margin-top: var(--spacing-small);\n }\n\n .operator-button {\n padding: var(--spacing-small) var(--spacing-medium);\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 4px;\n background-color: white;\n cursor: pointer;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n transition: all 0.2s ease;\n }\n\n .operator-button:hover {\n background-color: var(--md-sys-color-primary-container);\n border-color: var(--md-sys-color-primary);\n }\n\n .functions-container {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-small);\n margin-top: var(--spacing-small);\n }\n\n .functions-header {\n font-weight: 500;\n color: var(--md-sys-color-on-surface);\n }\n\n .functions-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: var(--spacing-small);\n }\n\n .function-button {\n padding: var(--spacing-small);\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 4px;\n background-color: white;\n cursor: pointer;\n font-family: 'Courier New', monospace;\n font-size: 11px;\n text-align: left;\n transition: all 0.2s ease;\n position: relative;\n }\n\n .function-button:hover {\n background-color: var(--md-sys-color-secondary-container);\n border-color: var(--md-sys-color-secondary);\n }\n\n .preview-container {\n margin-top: var(--spacing-medium);\n padding: var(--spacing-medium);\n background-color: #f8f9fa;\n border-radius: 4px;\n border: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n .preview-title {\n font-weight: 500;\n margin-bottom: var(--spacing-small);\n color: var(--md-sys-color-on-surface);\n }\n\n .preview-formula {\n font-family: 'Courier New', monospace;\n background-color: white;\n padding: var(--spacing-small);\n border-radius: 4px;\n border: 1px solid rgba(0, 0, 0, 0.1);\n white-space: pre-wrap;\n word-break: break-all;\n }\n\n .error-message {\n color: var(--md-sys-color-error);\n font-size: 12px;\n margin-top: var(--spacing-small);\n }\n\n .info-message {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 12px;\n margin-top: var(--spacing-small);\n }\n\n /* 도움말 팝업 스타일 */\n .help-popup {\n max-width: 500px;\n max-height: 400px;\n overflow-y: auto;\n }\n\n .help-title {\n font-size: 16px;\n font-weight: 600;\n margin-bottom: var(--spacing-medium);\n color: var(--md-sys-color-primary);\n }\n\n .help-section {\n margin-bottom: var(--spacing-medium);\n }\n\n .help-section-title {\n font-weight: 500;\n margin-bottom: var(--spacing-small);\n color: var(--md-sys-color-on-surface);\n }\n\n .help-content {\n font-size: 14px;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface);\n }\n\n .help-syntax {\n background-color: #f8f9fa;\n padding: var(--spacing-small);\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n margin: var(--spacing-small) 0;\n border-left: 3px solid var(--md-sys-color-primary);\n }\n\n .help-example {\n background-color: #f0f8ff;\n padding: var(--spacing-small);\n border-radius: 4px;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n margin: var(--spacing-small) 0;\n border-left: 3px solid var(--md-sys-color-secondary);\n }\n\n .help-parameters {\n margin: var(--spacing-small) 0;\n }\n\n .help-parameter {\n display: flex;\n justify-content: space-between;\n padding: 2px 0;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n .help-parameter-name {\n font-weight: 500;\n font-family: 'Courier New', monospace;\n }\n\n .help-parameter-desc {\n color: var(--md-sys-color-on-surface-variant);\n }\n\n /* Dialog specific styles */\n .help-dialog {\n border: none;\n border-radius: 8px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);\n padding: 0;\n max-width: 500px;\n max-height: 80vh;\n overflow-y: auto;\n background-color: white;\n }\n\n .help-dialog::backdrop {\n background-color: rgba(0, 0, 0, 0.5);\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n gap: var(--spacing-small);\n margin-top: var(--spacing-medium);\n padding: var(--spacing-medium);\n border-top: 1px solid var(--md-sys-color-outline);\n }\n\n .close-btn {\n padding: var(--spacing-small) var(--spacing-medium);\n border: 1px solid var(--md-sys-color-outline);\n border-radius: 4px;\n background-color: white;\n cursor: pointer;\n font-size: 14px;\n transition: all 0.2s ease;\n }\n\n .close-btn:hover {\n background-color: var(--md-sys-color-secondary-container);\n border-color: var(--md-sys-color-secondary);\n }\n\n .middle-align {\n display: flex;\n align-items: center;\n }\n `\n ]\n\n @property({ type: String }) value: string = ''\n @property({ type: Array }) availableVariables: FormulaVariable[] = []\n\n @state() private errorMessage: string = ''\n @state() private isValid: boolean = true\n\n @query('.formula-textarea') editor!: HTMLTextAreaElement\n\n private _changingNow: boolean = false\n\n getValue(): any {\n return this.value\n }\n\n setValue(value: any): void {\n this.value = value\n this._validateFormula()\n }\n\n validate(): boolean {\n this._validateFormula()\n return this.isValid\n }\n\n getErrorMessage(): string {\n return this.errorMessage\n }\n\n focus(): void {\n this.editor.focus()\n }\n\n blur(): void {\n this.editor.blur()\n }\n\n reset(): void {\n this.value = ''\n this.errorMessage = ''\n this.isValid = true\n this._updateValue()\n }\n\n // 기본 연산자들\n private readonly operators = [\n { symbol: '+', description: '더하기' },\n { symbol: '-', description: '빼기' },\n { symbol: '*', description: '곱하기' },\n { symbol: '/', description: '나누기' },\n { symbol: '(', description: '여는 괄호' },\n { symbol: ')', description: '닫는 괄호' },\n { symbol: '=', description: '같음' },\n { symbol: '>', description: '보다 큼' },\n { symbol: '<', description: '보다 작음' },\n { symbol: '>=', description: '보다 크거나 같음' },\n { symbol: '<=', description: '보다 작거나 같음' },\n { symbol: '!=', description: '다름' },\n { symbol: '&&', description: 'AND' },\n { symbol: '||', description: 'OR' }\n ]\n\n // 기본 함수들 (도움말 정보 포함)\n private readonly functions: FormulaFunction[] = [\n {\n name: 'SUM()',\n description: '합계',\n template: 'SUM({expression})',\n syntax: 'SUM(expression)',\n parameters: ['expression - 합계를 계산할 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들의 합계를 계산합니다. 숫자 배열이나 변수들을 인자로 받습니다.',\n examples: ['SUM(metric1, metric2, metric3)', 'SUM(production_data)', 'SUM(100, 200, 300)']\n },\n {\n name: 'AVG()',\n description: '평균',\n template: 'AVG({expression})',\n syntax: 'AVG(expression)',\n parameters: ['expression - 평균을 계산할 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들의 평균을 계산합니다. 숫자 배열이나 변수들을 인자로 받습니다.',\n examples: ['AVG(quality_scores)', 'AVG(metric1, metric2, metric3)', 'AVG(10, 20, 30)']\n },\n {\n name: 'MAX()',\n description: '최대값',\n template: 'MAX({expression})',\n syntax: 'MAX(expression)',\n parameters: ['expression - 최대값을 찾을 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들 중 최대값을 반환합니다.',\n examples: ['MAX(performance_data)', 'MAX(metric1, metric2, metric3)', 'MAX(100, 200, 300)']\n },\n {\n name: 'MIN()',\n description: '최소값',\n template: 'MIN({expression})',\n syntax: 'MIN(expression)',\n parameters: ['expression - 최소값을 찾을 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들 중 최소값을 반환합니다.',\n examples: ['MIN(quality_scores)', 'MIN(metric1, metric2, metric3)', 'MIN(10, 20, 30)']\n },\n {\n name: 'COUNT()',\n description: '개수',\n template: 'COUNT({expression})',\n syntax: 'COUNT(expression)',\n parameters: ['expression - 개수를 셀 값 또는 변수'],\n returnType: 'number',\n help: '주어진 값들의 개수를 반환합니다.',\n examples: ['COUNT(active_projects)', 'COUNT(metric1, metric2, metric3)', 'COUNT(1, 2, 3, 4, 5)']\n },\n {\n name: 'ROUND()',\n description: '반올림',\n template: 'ROUND({expression}, 2)',\n syntax: 'ROUND(expression, decimals)',\n parameters: ['expression - 반올림할 값', 'decimals - 소수점 자릿수 (기본값: 0)'],\n returnType: 'number',\n help: '주어진 값을 지정된 소수점 자릿수로 반올림합니다.',\n examples: ['ROUND(3.14159, 2) → 3.14', 'ROUND(metric1, 0)', 'ROUND(AVG(scores), 1)']\n },\n {\n name: 'ABS()',\n description: '절대값',\n template: 'ABS({expression})',\n syntax: 'ABS(expression)',\n parameters: ['expression - 절대값을 구할 값'],\n returnType: 'number',\n help: '주어진 값의 절대값을 반환합니다.',\n examples: ['ABS(-10) → 10', 'ABS(metric1 - target)', 'ABS(deviation)']\n },\n {\n name: 'IF()',\n description: '조건문',\n template: 'IF({condition}, {true_value}, {false_value})',\n syntax: 'IF(condition, true_value, false_value)',\n parameters: [\n 'condition - 조건식 (true/false)',\n 'true_value - 조건이 참일 때 반환할 값',\n 'false_value - 조건이 거짓일 때 반환할 값'\n ],\n returnType: 'any',\n help: '조건에 따라 다른 값을 반환합니다. 조건이 참이면 true_value를, 거짓이면 false_value를 반환합니다.',\n examples: [\n 'IF(score > 80, \"우수\", \"보통\")',\n 'IF(metric1 > target, 100, 0)',\n 'IF(quality_score >= 90, \"A등급\", IF(quality_score >= 80, \"B등급\", \"C등급\"))'\n ]\n },\n {\n name: 'CASE()',\n description: '케이스문',\n template: 'CASE {expression} WHEN {value1} THEN {result1} ELSE {default} END',\n syntax: 'CASE expression WHEN value1 THEN result1 [WHEN value2 THEN result2]... ELSE default END',\n parameters: [\n 'expression - 비교할 값',\n 'value1, value2... - 비교할 값들',\n 'result1, result2... - 해당 값일 때 반환할 결과들',\n 'default - 기본값'\n ],\n returnType: 'any',\n help: '여러 조건에 따라 다른 값을 반환합니다. IF문의 확장된 형태입니다.',\n examples: [\n 'CASE grade WHEN \"A\" THEN 100 WHEN \"B\" THEN 80 WHEN \"C\" THEN 60 ELSE 0 END',\n 'CASE score WHEN 90 THEN \"우수\" WHEN 80 THEN \"양호\" WHEN 70 THEN \"보통\" ELSE \"미흡\" END'\n ]\n }\n ]\n\n // 변수명 정규화 헬퍼 메서드\n // _normalizeVariableName 메서드 완전히 삭제\n\n firstUpdated() {\n this.addEventListener('change', this._onChange.bind(this))\n }\n\n render() {\n return html`\n <div class=\"formula-container\">\n <div class=\"formula-input-container\">\n <label class=\"variables-header\">\n <ox-i18n msgid=\"label.formula\"></ox-i18n>\n </label>\n\n <textarea\n class=\"formula-textarea\"\n .value=${this.value}\n @input=${this._onFormulaInput.bind(this)}\n placeholder=\"수식을 입력하세요. 예: SUM(metric1) + AVG(metric2) * 0.5\"\n ></textarea>\n\n ${this.errorMessage\n ? html`\n <div class=\"error-message middle-align\">\n <md-icon>error</md-icon>\n ${this.errorMessage}\n </div>\n `\n : ''}\n ${!this.errorMessage && this.value\n ? html`\n <div class=\"info-message middle-align\">\n <md-icon>info</md-icon>\n 수식이 유효합니다.\n </div>\n `\n : ''}\n </div>\n\n <div class=\"variables-container\">\n <div class=\"variables-header middle-align\">\n <md-icon>variables</md-icon>\n <ox-i18n msgid=\"label.available-variables\"></ox-i18n>\n </div>\n\n <div class=\"variables-grid\">\n ${this.availableVariables.map(\n variable => html`\n <div class=\"variable-item\" @click=${() => this._insertVariable(variable.name)}>\n <div class=\"variable-name\">[${variable.name}]</div>\n ${variable.description ? html` <div class=\"variable-description\">${variable.description}</div> ` : ''}\n ${variable.type ? html` <div class=\"variable-type\">${variable.type}</div> ` : ''}\n ${variable.help\n ? html`\n <md-icon class=\"help-icon\" @click=${(e: Event) => this._showVariableHelp(e, variable)}>\n help\n </md-icon>\n `\n : ''}\n </div>\n `\n )}\n </div>\n </div>\n\n <div class=\"operators-container\">\n <div class=\"variables-header middle-align\">\n <md-icon>calculate</md-icon>\n <ox-i18n msgid=\"label.operators\"></ox-i18n>\n </div>\n\n ${this.operators.map(\n op => html`\n <button class=\"operator-button\" @click=${() => this._insertOperator(op.symbol)} title=\"${op.description}\">\n ${op.symbol}\n </button>\n `\n )}\n </div>\n\n <div class=\"functions-container\">\n <div class=\"functions-header middle-align\">\n <md-icon>functions</md-icon>\n <ox-i18n msgid=\"label.functions\"></ox-i18n>\n </div>\n\n <div class=\"functions-grid\">\n ${this.functions.map(\n func => html`\n <div class=\"function-button\" @click=${() => this._insertFunction(func.template)}>\n <div style=\"font-weight: 500;\">${func.name}</div>\n <div style=\"font-size: 10px; color: var(--md-sys-color-on-surface-variant);\">${func.description}</div>\n ${func.help\n ? html`\n <md-icon\n class=\"help-icon\"\n @click=${(e: Event) => this._showFunctionHelp(e, func)}\n style=\"position: absolute; top: 4px; right: 4px; font-size: 12px;\"\n >\n help\n </md-icon>\n `\n : ''}\n </div>\n `\n )}\n </div>\n </div>\n\n ${this.value\n ? html`\n <div class=\"preview-container\">\n <div class=\"preview-title middle-align\">\n <md-icon>preview</md-icon>\n <ox-i18n msgid=\"label.formula-preview\"></ox-i18n>\n </div>\n <div class=\"preview-formula\">${this.value}</div>\n </div>\n `\n : ''}\n </div>\n `\n }\n\n updated(changes: any) {\n if (changes.has('value')) {\n this._validateFormula()\n }\n }\n\n _onChange(e: Event) {\n if (this._changingNow) {\n return\n }\n\n this._changingNow = true\n this._updateValue()\n this._changingNow = false\n }\n\n _onFormulaInput(e: Event) {\n const textarea = e.target as HTMLTextAreaElement\n this.value = textarea.value\n this._validateFormula()\n this._updateValue()\n }\n\n _insertVariable(variableName: string) {\n const start = this.editor.selectionStart\n const end = this.editor.selectionEnd\n const currentValue = this.editor.value\n\n // 변수명을 [변수명] 형태로만 감싸서 삽입\n const insertText = `[${variableName}]`\n const newValue = currentValue.substring(0, start) + insertText + currentValue.substring(end)\n this.editor.value = newValue\n this.value = newValue\n\n // 커서 위치 조정\n const newCursorPos = start + insertText.length\n this.editor.setSelectionRange(newCursorPos, newCursorPos)\n this.editor.focus()\n\n this._validateFormula()\n this._updateValue()\n }\n\n _insertOperator(operator: string) {\n const start = this.editor.selectionStart\n const end = this.editor.selectionEnd\n const currentValue = this.editor.value\n\n // 연산자 앞뒤에 공백 추가\n const insertText = ` ${operator} `\n const newValue = currentValue.substring(0, start) + insertText + currentValue.substring(end)\n this.editor.value = newValue\n this.value = newValue\n\n // 커서 위치 조정\n const newCursorPos = start + insertText.length\n this.editor.setSelectionRange(newCursorPos, newCursorPos)\n this.editor.focus()\n\n this._validateFormula()\n this._updateValue()\n }\n\n _insertFunction(template: string) {\n const start = this.editor.selectionStart\n const end = this.editor.selectionEnd\n const currentValue = this.editor.value\n\n // 선택된 텍스트가 있으면 그것을 expression으로 사용\n const selectedText = currentValue.substring(start, end)\n const insertText = template.replace('{expression}', selectedText || 'expression')\n\n const newValue = currentValue.substring(0, start) + insertText + currentValue.substring(end)\n this.editor.value = newValue\n this.value = newValue\n\n // 커서 위치 조정 (expression 부분에 포커스)\n const expressionStart = start + insertText.indexOf('expression')\n const expressionEnd = expressionStart + 'expression'.length\n this.editor.setSelectionRange(expressionStart, expressionEnd)\n this.editor.focus()\n\n this._validateFormula()\n this._updateValue()\n }\n\n _showVariableHelp(e: Event, variable: FormulaVariable) {\n e.stopPropagation()\n\n // 간단한 테스트 버전\n const message = `\n변수: ${variable.name}\n설명: ${variable.description || '없음'}\n타입: ${variable.type || '없음'}\n단위: ${variable.unit || '없음'}\n예시: ${variable.example || '없음'}\n `.trim()\n\n console.log('Variable help:', message)\n\n // dialog 지원 여부 확인\n if (typeof HTMLDialogElement !== 'undefined') {\n const dialog = document.createElement('dialog')\n dialog.className = 'help-dialog'\n\n // HTML 문자열로 직접 작성\n dialog.innerHTML = `\n <div class=\"help-popup\">\n <div class=\"help-title\">${variable.name}</div>\n \n ${\n variable.description\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">설명</div>\n <div class=\"help-content\">${variable.description}</div>\n </div>\n `\n : ''\n }\n \n ${\n variable.type\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">타입</div>\n <div class=\"help-content\">${variable.type}</div>\n </div>\n `\n : ''\n }\n \n ${\n variable.unit\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">단위</div>\n <div class=\"help-content\">${variable.unit}</div>\n </div>\n `\n : ''\n }\n \n ${\n variable.help\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">상세 설명</div>\n <div class=\"help-content\">${variable.help}</div>\n </div>\n `\n : ''\n }\n \n ${\n variable.example\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">사용 예시</div>\n <div class=\"help-example\">${variable.example}</div>\n </div>\n `\n : ''\n }\n </div>\n \n <div class=\"dialog-actions\">\n <button class=\"close-btn\" onclick=\"this.closest('dialog').close()\">닫기</button>\n </div>\n `\n\n document.body.appendChild(dialog)\n dialog.showModal()\n\n // 외부 클릭으로 닫기\n dialog.addEventListener('click', event => {\n const rect = dialog.getBoundingClientRect()\n const isInDialog =\n event.clientX >= rect.left &&\n event.clientX <= rect.right &&\n event.clientY >= rect.top &&\n event.clientY <= rect.bottom\n\n if (!isInDialog) {\n dialog.close()\n }\n })\n\n dialog.addEventListener('close', () => {\n if (document.body.contains(dialog)) {\n document.body.removeChild(dialog)\n }\n })\n\n // ESC 키로 닫기\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n dialog.close()\n document.removeEventListener('keydown', handleEsc)\n }\n }\n document.addEventListener('keydown', handleEsc)\n } else {\n // dialog를 지원하지 않는 브라우저에서는 alert 사용\n alert(message)\n }\n }\n\n _showFunctionHelp(e: Event, func: FormulaFunction) {\n e.stopPropagation()\n\n const dialog = document.createElement('dialog')\n dialog.className = 'help-dialog'\n\n // HTML 문자열로 직접 작성\n dialog.innerHTML = `\n <div class=\"help-popup\">\n <div class=\"help-title\">${func.name}</div>\n\n <div class=\"help-section\">\n <div class=\"help-section-title\">설명</div>\n <div class=\"help-content\">${func.description}</div>\n </div>\n\n <div class=\"help-section\">\n <div class=\"help-section-title\">구문</div>\n <div class=\"help-syntax\">${func.syntax}</div>\n </div>\n\n <div class=\"help-section\">\n <div class=\"help-section-title\">매개변수</div>\n <div class=\"help-parameters\">\n ${func.parameters\n .map(\n param => `\n <div class=\"help-parameter\">\n <span class=\"help-parameter-desc\">${param}</span>\n </div>\n `\n )\n .join('')}\n </div>\n </div>\n\n <div class=\"help-section\">\n <div class=\"help-section-title\">반환 타입</div>\n <div class=\"help-content\">${func.returnType}</div>\n </div>\n\n ${\n func.help\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">상세 설명</div>\n <div class=\"help-content\">${func.help}</div>\n </div>\n `\n : ''\n }\n \n ${\n func.examples && func.examples.length > 0\n ? `\n <div class=\"help-section\">\n <div class=\"help-section-title\">사용 예시</div>\n ${func.examples\n .map(\n example => `\n <div class=\"help-example\">${example}</div>\n `\n )\n .join('')}\n </div>\n `\n : ''\n }\n </div>\n \n <div class=\"dialog-actions\">\n <button class=\"close-btn\" onclick=\"this.closest('dialog').close()\">닫기</button>\n </div>\n `\n\n document.body.appendChild(dialog)\n dialog.showModal()\n\n // 외부 클릭으로 닫기\n dialog.addEventListener('click', event => {\n const rect = dialog.getBoundingClientRect()\n const isInDialog =\n event.clientX >= rect.left &&\n event.clientX <= rect.right &&\n event.clientY >= rect.top &&\n event.clientY <= rect.bottom\n\n if (!isInDialog) {\n dialog.close()\n }\n })\n\n dialog.addEventListener('close', () => {\n if (document.body.contains(dialog)) {\n document.body.removeChild(dialog)\n }\n })\n\n // ESC 키로 닫기\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n dialog.close()\n document.removeEventListener('keydown', handleEsc)\n }\n }\n document.addEventListener('keydown', handleEsc)\n }\n\n _validateFormula() {\n // 기본적인 수식 유효성 검사\n const formula = this.value.trim()\n\n if (!formula) {\n this.errorMessage = ''\n this.isValid = true\n return\n }\n\n // 괄호 균형 검사\n const openBrackets = (formula.match(/\\(/g) || []).length\n const closeBrackets = (formula.match(/\\)/g) || []).length\n\n if (openBrackets !== closeBrackets) {\n this.errorMessage = '괄호가 균형을 이루지 않습니다.'\n this.isValid = false\n return\n }\n\n // 변수 참조 검증 ([변수명] 형태)\n const variableRefs = formula.match(/\\[([^\\]]+)\\]/g) || []\n for (const ref of variableRefs) {\n const varName = ref.slice(1, -1) // [변수명]에서 변수명 추출\n const availableVarNames = this.availableVariables.map(v => v.name)\n if (!availableVarNames.includes(varName)) {\n this.errorMessage = `알 수 없는 변수: ${varName}`\n this.isValid = false\n return\n }\n }\n\n // 기본 문법 검사\n const invalidPatterns = [\n /[+\\-*/]{2,}/, // 연속된 연산자\n /[+\\-*/]\\s*$/, // 끝에 연산자\n /^\\s*[+\\-*/]/, // 시작에 연산자\n /\\(\\s*\\)/ // 빈 괄호\n ]\n\n for (const pattern of invalidPatterns) {\n if (pattern.test(formula)) {\n this.errorMessage = '수식 문법이 올바르지 않습니다.'\n this.isValid = false\n return\n }\n }\n\n this.errorMessage = ''\n this.isValid = true\n }\n\n _updateValue() {\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: this.value\n })\n )\n }\n}\n"]}
|