@operato/input 10.9.0 → 10.10.0
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 +23 -0
- package/dist/src/image-selector.d.ts +14 -0
- package/dist/src/image-selector.js +61 -0
- package/dist/src/image-selector.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/ox-input-background-pattern.d.ts +15 -2
- package/dist/src/ox-input-background-pattern.js +47 -10
- package/dist/src/ox-input-background-pattern.js.map +1 -1
- package/dist/src/ox-input-color-stops.d.ts +2 -1
- package/dist/src/ox-input-color-stops.js +10 -4
- package/dist/src/ox-input-color-stops.js.map +1 -1
- package/dist/src/ox-input-container.js +18 -1
- package/dist/src/ox-input-container.js.map +1 -1
- package/dist/src/ox-input-formula.d.ts +1 -1
- package/dist/src/ox-input-formula.js +14 -2
- package/dist/src/ox-input-formula.js.map +1 -1
- package/dist/src/ox-input-search.js +15 -1
- package/dist/src/ox-input-search.js.map +1 -1
- package/dist/src/ox-input-secret.js +14 -0
- package/dist/src/ox-input-secret.js.map +1 -1
- package/dist/src/ox-input-select-buttons.js +1 -1
- package/dist/src/ox-input-select-buttons.js.map +1 -1
- package/dist/test/image-selector.test.d.ts +1 -0
- package/dist/test/image-selector.test.js +63 -0
- package/dist/test/image-selector.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -5
- package/test/image-selector.test.ts +81 -0
- package/translations/en.json +6 -5
- package/translations/ja.json +6 -5
- package/translations/ko.json +6 -5
- package/translations/ms.json +6 -5
- package/translations/zh.json +6 -5
|
@@ -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'\nimport './ox-input-formula-help-popup.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'\nimport { InputStyles } from './input-styles.js'\nimport { OxInputFormulaHelpPopup, HelpContent } from './ox-input-formula-help-popup.js'\nimport { ScrollbarStyles } from '@operato/styles'\n\ntype FormulaVariable = {\n name: string\n description?: string\n type?: string\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 * .availableFunctions=${functions}\n * .includeDefaultFunctions=${true}\n * ></ox-input-formula>\n */\n@customElement('ox-input-formula')\nexport class KpiFormulaEditor extends OxFormField {\n static styles = [\n InputStyles,\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n margin-bottom: calc(var(--ox-input-gap) * 3);\n gap: calc(var(--ox-input-gap) * 2);\n }\n\n .formula-container {\n display: flex;\n flex-direction: column;\n gap: var(--ox-input-gap);\n }\n\n .formula-input-container {\n display: flex;\n flex-direction: column;\n gap: var(--ox-input-gap);\n }\n\n .formula-textarea {\n min-height: var(--ox-formula-textarea-min-height, 120px);\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n padding: var(--ox-input-padding);\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: var(--ox-formula-textarea-font-size, 1.3rem);\n line-height: var(--ox-input-line-height);\n resize: vertical;\n background-color: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n }\n\n .formula-textarea:focus {\n outline: none;\n border-color: var(--md-sys-color-primary);\n background-color: var(--ox-input-background);\n }\n\n .variables-container {\n display: flex;\n flex-direction: column;\n gap: var(--ox-input-gap);\n }\n\n .variables-header {\n display: flex;\n align-items: center;\n gap: var(--ox-input-gap);\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(--ox-input-gap);\n max-height: var(--ox-formula-grid-max-height, 200px);\n overflow-y: auto;\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n padding: var(--ox-input-gap);\n background-color: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n }\n\n .variable-item {\n display: flex;\n flex-direction: column;\n padding: var(--ox-input-gap);\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n background-color: var(--ox-input-background);\n cursor: pointer;\n transition: var(--ox-input-transition);\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: var(--ox-input-shadow);\n }\n\n .variable-name {\n font-weight: 500;\n color: var(--md-sys-color-primary);\n font-size: var(--ox-formula-font-size-small, 0.75rem);\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n }\n\n .variable-description {\n font-size: var(--ox-formula-font-size-tiny, 0.6875rem);\n color: var(--md-sys-color-on-surface-variant);\n margin-top: 2px;\n }\n\n .variable-type {\n font-size: var(--ox-formula-font-size-tiny, 0.6875rem);\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: var(--ox-input-font-size);\n color: var(--md-sys-color-outline);\n cursor: pointer;\n padding: var(--ox-formula-icon-padding, 2px);\n border-radius: var(--ox-input-radius);\n transition: var(--ox-input-transition);\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(--ox-input-gap);\n margin-top: var(--ox-input-gap);\n }\n\n .operator-button {\n padding: var(--ox-input-padding);\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n background-color: var(--ox-input-background);\n cursor: pointer;\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: var(--ox-formula-font-size-small, 0.75rem);\n transition: var(--ox-input-transition);\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(--ox-input-gap);\n margin-top: var(--ox-input-gap);\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(--ox-input-gap);\n }\n\n .function-button {\n padding: var(--ox-input-gap);\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n background-color: var(--ox-input-background);\n cursor: pointer;\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: var(--ox-formula-font-size-tiny, 0.6875rem);\n text-align: left;\n transition: var(--ox-input-transition);\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: calc(var(--ox-input-gap) * 2);\n padding: var(--ox-input-padding);\n background-color: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border-radius: var(--ox-input-radius);\n border: var(--ox-input-border);\n }\n\n .preview-title {\n font-weight: 500;\n margin-bottom: var(--ox-input-gap);\n color: var(--md-sys-color-on-surface);\n }\n\n .preview-formula {\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n background-color: var(--ox-input-background);\n padding: var(--ox-input-gap);\n border-radius: var(--ox-input-radius);\n border: var(--ox-input-border);\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: var(--ox-formula-font-size-small, 0.75rem);\n margin-top: var(--ox-input-gap);\n }\n\n .info-message {\n color: var(--md-sys-color-on-surface-variant);\n font-size: var(--ox-formula-font-size-small, 0.75rem);\n margin-top: var(--ox-input-gap);\n }\n\n /* 도움말 팝업 스타일 */\n .help-popup {\n max-width: 500px;\n max-height: 400px;\n overflow-y: auto;\n background: var(--ox-input-background);\n border-radius: var(--ox-input-popup-radius);\n box-shadow: var(--ox-input-shadow);\n }\n\n .help-title {\n font-size: 20px;\n font-weight: 600;\n margin-bottom: 16px;\n color: var(--md-sys-color-primary);\n padding: 20px 20px 16px 20px;\n background: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border-bottom: var(--ox-input-border);\n border-radius: var(--ox-input-popup-radius) var(--ox-input-popup-radius) 0 0;\n }\n\n .help-section {\n margin-bottom: 16px;\n padding: 0 20px;\n }\n\n .help-section-title {\n font-weight: 600;\n margin-bottom: 8px;\n color: var(--ox-input-color);\n font-size: var(--ox-input-font-size);\n border-bottom: var(--ox-input-border);\n padding-bottom: 4px;\n }\n\n .help-content {\n font-size: var(--ox-input-font-size);\n line-height: 1.6;\n color: var(--ox-input-placeholder-color);\n padding: 4px 0;\n }\n\n .help-syntax {\n background: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n padding: 12px;\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: 13px;\n color: var(--ox-input-color);\n margin: 8px 0;\n }\n\n .help-example {\n background: var(--md-sys-color-secondary-container);\n border: 1px solid var(--md-sys-color-tertiary-container);\n border-radius: var(--ox-input-radius);\n padding: 12px;\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: 13px;\n color: var(--md-sys-color-on-tertiary-container);\n margin: 8px 0;\n }\n\n .help-parameters {\n margin: 8px 0;\n }\n\n .help-parameter {\n background: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border-left: 3px solid var(--md-sys-color-primary);\n border-radius: var(--ox-input-radius);\n padding: 8px 12px;\n margin-bottom: 4px;\n font-size: 13px;\n }\n\n .help-parameter-desc {\n color: var(--ox-input-placeholder-color);\n }\n\n /* Dialog specific styles */\n .help-dialog {\n border: none;\n border-radius: var(--ox-input-popup-radius);\n box-shadow: var(--ox-input-shadow);\n padding: 0;\n max-width: 500px;\n max-height: 80vh;\n overflow-y: auto;\n background-color: var(--ox-input-background);\n }\n\n .help-dialog::backdrop {\n background-color: var(--ox-input-scrim);\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n padding: 16px 20px;\n border-top: var(--ox-input-border);\n background: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border-radius: 0 0 8px 8px;\n }\n\n .close-btn {\n padding: 8px 16px;\n border: 1px solid var(--md-sys-color-primary);\n border-radius: var(--ox-input-radius);\n background-color: var(--md-sys-color-primary);\n color: var(--md-sys-color-on-primary);\n cursor: pointer;\n font-size: var(--ox-input-font-size);\n font-weight: 500;\n transition: var(--ox-input-transition);\n }\n\n .close-btn:hover {\n background-color: var(--ox-input-focus-color);\n border-color: var(--ox-input-focus-color);\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 @property({ type: Array }) availableFunctions: FormulaFunction[] = []\n @property({ type: Boolean }) includeDefaultFunctions: boolean = true\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 // 기본 함수들 (도움말 정보 포함)\n private readonly _defaultFunctions: 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 // 사용 가능한 함수 목록을 가져오는 getter\n get functions(): FormulaFunction[] {\n let resultFunctions: FormulaFunction[] = []\n\n // 기본 함수 포함 여부 확인\n if (this.includeDefaultFunctions) {\n resultFunctions = [...this._defaultFunctions]\n }\n\n // 사용자 정의 함수들 추가\n if (this.availableFunctions && this.availableFunctions.length > 0) {\n for (const customFunc of this.availableFunctions) {\n const existingIndex = resultFunctions.findIndex(f => f.name === customFunc.name)\n if (existingIndex >= 0) {\n // 기존 함수를 사용자 정의 함수로 교체\n resultFunctions[existingIndex] = customFunc\n } else {\n // 새로운 함수 추가\n resultFunctions.push(customFunc)\n }\n }\n }\n\n return resultFunctions\n }\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 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 ${this.functions.length > 0\n ? html`\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: var(--ox-formula-font-size-tiny, 0.6875rem); color: var(--md-sys-color-on-surface-variant);\">\n ${func.description}\n </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: var(--ox-formula-font-size-small, 0.75rem);\"\n >\n help\n </md-icon>\n `\n : ''}\n </div>\n `\n )}\n </div>\n </div>\n `\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 const sections: Array<{\n title: string\n content: string\n type?: 'text' | 'code' | 'parameter' | 'example'\n }> = []\n\n if (variable.description) {\n sections.push({\n title: '설명',\n content: variable.description,\n type: 'text'\n })\n }\n\n if (variable.type) {\n sections.push({\n title: '타입',\n content: variable.type,\n type: 'text'\n })\n }\n\n if (variable.unit) {\n sections.push({\n title: '단위',\n content: variable.unit,\n type: 'text'\n })\n }\n\n if (variable.help) {\n sections.push({\n title: '상세 설명',\n content: variable.help,\n type: 'text'\n })\n }\n\n if (variable.example) {\n sections.push({\n title: '사용 예시',\n content: variable.example,\n type: 'example'\n })\n }\n\n const helpContent: HelpContent = {\n title: variable.name,\n sections\n }\n\n this._showHelpPopup(helpContent)\n }\n\n _showFunctionHelp(e: Event, func: FormulaFunction) {\n e.stopPropagation()\n\n const sections: Array<{\n title: string\n content: string\n type?: 'text' | 'code' | 'parameter' | 'example'\n }> = [\n {\n title: '설명',\n content: func.description,\n type: 'text'\n },\n {\n title: '구문',\n content: func.syntax,\n type: 'code'\n },\n {\n title: '매개변수',\n content: func.parameters.join('\\n'),\n type: 'parameter'\n },\n {\n title: '반환 타입',\n content: func.returnType,\n type: 'text'\n }\n ]\n\n if (func.help) {\n sections.push({\n title: '상세 설명',\n content: func.help,\n type: 'text'\n })\n }\n\n if (func.examples && func.examples.length > 0) {\n sections.push({\n title: '사용 예시',\n content: func.examples.join('\\n'),\n type: 'example'\n })\n }\n\n const helpContent: HelpContent = {\n title: func.name,\n sections\n }\n\n this._showHelpPopup(helpContent)\n }\n\n private _showHelpPopup(content: HelpContent) {\n const dialog = document.createElement('dialog')\n dialog.style.cssText = `\n border: none;\n border-radius: var(--ox-input-popup-radius);\n box-shadow: var(--ox-input-shadow);\n padding: 0;\n max-width: 500px;\n max-height: 80vh;\n overflow-y: auto;\n background-color: var(--ox-input-background);\n `\n\n const helpPopup = document.createElement('ox-input-formula-help-popup') as OxInputFormulaHelpPopup\n helpPopup.content = content\n helpPopup.onClose = () => {\n dialog.close()\n }\n\n dialog.appendChild(helpPopup)\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"]}
|
|
1
|
+
{"version":3,"file":"ox-input-formula.js","sourceRoot":"","sources":["../../src/ox-input-formula.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,4BAA4B,CAAA;AACnC,OAAO,yCAAyC,CAAA;AAChD,OAAO,kCAAkC,CAAA;AAEzC,OAAO,0BAA0B,CAAA;AACjC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEzE;;;;;;;;;GASG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAsBjD;;;;;;;;;;;GAWG;AAEI,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,WAAW;IAA1C;;QA8VuB,UAAK,GAAW,EAAE,CAAA;QACnB,uBAAkB,GAAsB,EAAE,CAAA;QAC1C,uBAAkB,GAAsB,EAAE,CAAA;QACxC,4BAAuB,GAAY,IAAI,CAAA;QAEnD,iBAAY,GAAW,EAAE,CAAA;QACzB,YAAO,GAAY,IAAI,CAAA;QAIhC,iBAAY,GAAY,KAAK,CAAA;QAErC,qBAAqB;QACJ,sBAAiB,GAAsB;YACtD;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,mBAAmB;gBAC7B,MAAM,EAAE,iBAAiB;gBACzB,UAAU,EAAE,CAAC,8BAA8B,CAAC;gBAC5C,UAAU,EAAE,QAAQ;gBACpB,IAAI,EAAE,2CAA2C;gBACjD,QAAQ,EAAE,CAAC,gCAAgC,EAAE,sBAAsB,EAAE,oBAAoB,CAAC;aAC3F;YACD;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,mBAAmB;gBAC7B,MAAM,EAAE,iBAAiB;gBACzB,UAAU,EAAE,CAAC,8BAA8B,CAAC;gBAC5C,UAAU,EAAE,QAAQ;gBACpB,IAAI,EAAE,2CAA2C;gBACjD,QAAQ,EAAE,CAAC,qBAAqB,EAAE,gCAAgC,EAAE,iBAAiB,CAAC;aACvF;YACD;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,KAAK;gBAClB,QAAQ,EAAE,mBAAmB;gBAC7B,MAAM,EAAE,iBAAiB;gBACzB,UAAU,EAAE,CAAC,8BAA8B,CAAC;gBAC5C,UAAU,EAAE,QAAQ;gBACpB,IAAI,EAAE,sBAAsB;gBAC5B,QAAQ,EAAE,CAAC,uBAAuB,EAAE,gCAAgC,EAAE,oBAAoB,CAAC;aAC5F;YACD;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,KAAK;gBAClB,QAAQ,EAAE,mBAAmB;gBAC7B,MAAM,EAAE,iBAAiB;gBACzB,UAAU,EAAE,CAAC,8BAA8B,CAAC;gBAC5C,UAAU,EAAE,QAAQ;gBACpB,IAAI,EAAE,sBAAsB;gBAC5B,QAAQ,EAAE,CAAC,qBAAqB,EAAE,gCAAgC,EAAE,iBAAiB,CAAC;aACvF;YACD;gBACE,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,qBAAqB;gBAC/B,MAAM,EAAE,mBAAmB;gBAC3B,UAAU,EAAE,CAAC,4BAA4B,CAAC;gBAC1C,UAAU,EAAE,QAAQ;gBACpB,IAAI,EAAE,oBAAoB;gBAC1B,QAAQ,EAAE,CAAC,wBAAwB,EAAE,kCAAkC,EAAE,sBAAsB,CAAC;aACjG;YACD;gBACE,IAAI,EAAE,SAAS;gBACf,WAAW,EAAE,KAAK;gBAClB,QAAQ,EAAE,wBAAwB;gBAClC,MAAM,EAAE,6BAA6B;gBACrC,UAAU,EAAE,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;gBAClE,UAAU,EAAE,QAAQ;gBACpB,IAAI,EAAE,6BAA6B;gBACnC,QAAQ,EAAE,CAAC,0BAA0B,EAAE,mBAAmB,EAAE,uBAAuB,CAAC;aACrF;YACD;gBACE,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,KAAK;gBAClB,QAAQ,EAAE,mBAAmB;gBAC7B,MAAM,EAAE,iBAAiB;gBACzB,UAAU,EAAE,CAAC,wBAAwB,CAAC;gBACtC,UAAU,EAAE,QAAQ;gBACpB,IAAI,EAAE,oBAAoB;gBAC1B,QAAQ,EAAE,CAAC,eAAe,EAAE,uBAAuB,EAAE,gBAAgB,CAAC;aACvE;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,KAAK;gBAClB,QAAQ,EAAE,8CAA8C;gBACxD,MAAM,EAAE,wCAAwC;gBAChD,UAAU,EAAE;oBACV,8BAA8B;oBAC9B,6BAA6B;oBAC7B,+BAA+B;iBAChC;gBACD,UAAU,EAAE,KAAK;gBACjB,IAAI,EAAE,mEAAmE;gBACzE,QAAQ,EAAE;oBACR,4BAA4B;oBAC5B,8BAA8B;oBAC9B,uEAAuE;iBACxE;aACF;YACD;gBACE,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,MAAM;gBACnB,QAAQ,EAAE,mEAAmE;gBAC7E,MAAM,EAAE,yFAAyF;gBACjG,UAAU,EAAE;oBACV,oBAAoB;oBACpB,4BAA4B;oBAC5B,uCAAuC;oBACvC,eAAe;iBAChB;gBACD,UAAU,EAAE,KAAK;gBACjB,IAAI,EAAE,wCAAwC;gBAC9C,QAAQ,EAAE;oBACR,2EAA2E;oBAC3E,gFAAgF;iBACjF;aACF;SACF,CAAA;QA6DD,UAAU;QACO,cAAS,GAAG;YAC3B,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE;YACnC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE;YAClC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE;YACnC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE;YACnC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE;YACrC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE;YACrC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE;YAClC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE;YACpC,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE;YACrC,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE;YAC1C,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE;YAC1C,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE;YACnC,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE;YACpC,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE;SACpC,CAAA;IA0bH,CAAC;aA59BQ,WAAM,GAAG;QACd,WAAW;QACX,eAAe;QACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuVF;KACF,AA3VY,CA2VZ;IA4HD,4BAA4B;IAC5B,IAAI,SAAS;QACX,IAAI,eAAe,GAAsB,EAAE,CAAA;QAE3C,iBAAiB;QACjB,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACjC,eAAe,GAAG,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAA;QAC/C,CAAC;QAED,gBAAgB;QAChB,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClE,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBACjD,MAAM,aAAa,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,CAAC,CAAA;gBAChF,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;oBACvB,uBAAuB;oBACvB,eAAe,CAAC,aAAa,CAAC,GAAG,UAAU,CAAA;gBAC7C,CAAC;qBAAM,CAAC;oBACN,YAAY;oBACZ,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;gBAClC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,eAAe,CAAA;IACxB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED,QAAQ,CAAC,KAAU;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,gBAAgB,EAAE,CAAA;IACzB,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACvB,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAA;IAC1B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IACrB,CAAC;IAED,IAAI;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA;IACpB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;QACf,IAAI,CAAC,YAAY,GAAG,EAAE,CAAA;QACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,IAAI,CAAC,YAAY,EAAE,CAAA;IACrB,CAAC;IAoBD,YAAY;QACV,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5D,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAA;;;;;;;;;qBASM,IAAI,CAAC,KAAK;qBACV,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;;;;YAIxC,IAAI,CAAC,YAAY;YACjB,CAAC,CAAC,IAAI,CAAA;;;oBAGE,IAAI,CAAC,YAAY;;eAEtB;YACH,CAAC,CAAC,EAAE;YACJ,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK;YAChC,CAAC,CAAC,IAAI,CAAA;;;;;eAKH;YACH,CAAC,CAAC,EAAE;;;;;;;;;;cAUF,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAC3B,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAA;oDACsB,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;gDAC7C,QAAQ,CAAC,IAAI;oBACzC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAA,sCAAsC,QAAQ,CAAC,WAAW,SAAS,CAAC,CAAC,CAAC,EAAE;oBACnG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,+BAA+B,QAAQ,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE;oBAC9E,QAAQ,CAAC,IAAI;YACb,CAAC,CAAC,IAAI,CAAA;4DACkC,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,QAAQ,CAAC;;;uBAGtF;YACH,CAAC,CAAC,EAAE;;eAET,CACF;;;;;;;;;;YAUD,IAAI,CAAC,SAAS,CAAC,GAAG,CAClB,EAAE,CAAC,EAAE,CAAC,IAAI,CAAA;uDACiC,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,WAAW;kBACnG,EAAE,CAAC,MAAM;;aAEd,CACF;;;UAGD,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;YACzB,CAAC,CAAC,IAAI,CAAA;;;;;;;;oBAQI,IAAI,CAAC,SAAS,CAAC,GAAG,CAClB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA;4DAC4B,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC;yDAC5C,IAAI,CAAC,IAAI;;;;4BAItC,IAAI,CAAC,WAAW;;0BAElB,IAAI,CAAC,IAAI;gBACT,CAAC,CAAC,IAAI,CAAA;;;yCAGS,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC;;;;;6BAKzD;gBACH,CAAC,CAAC,EAAE;;qBAET,CACF;;;aAGN;YACH,CAAC,CAAC,EAAE;UACJ,IAAI,CAAC,KAAK;YACV,CAAC,CAAC,IAAI,CAAA;;;;;;+CAM+B,IAAI,CAAC,KAAK;;aAE5C;YACH,CAAC,CAAC,EAAE;;KAET,CAAA;IACH,CAAC;IAED,OAAO,CAAC,OAAY;QAClB,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACzB,CAAC;IACH,CAAC;IAED,SAAS,CAAC,CAAQ;QAChB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAM;QACR,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;QACxB,IAAI,CAAC,YAAY,EAAE,CAAA;QACnB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAA;IAC3B,CAAC;IAED,eAAe,CAAC,CAAQ;QACtB,MAAM,QAAQ,GAAG,CAAC,CAAC,MAA6B,CAAA;QAChD,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAA;QAC3B,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACvB,IAAI,CAAC,YAAY,EAAE,CAAA;IACrB,CAAC;IAED,eAAe,CAAC,YAAoB;QAClC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAA;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAA;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAA;QAEtC,yBAAyB;QACzB,MAAM,UAAU,GAAG,IAAI,YAAY,GAAG,CAAA;QACtC,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,UAAU,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAC5F,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAA;QAC5B,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAA;QAErB,WAAW;QACX,MAAM,YAAY,GAAG,KAAK,GAAG,UAAU,CAAC,MAAM,CAAA;QAC9C,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;QACzD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAEnB,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACvB,IAAI,CAAC,YAAY,EAAE,CAAA;IACrB,CAAC;IAED,eAAe,CAAC,QAAgB;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAA;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAA;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAA;QAEtC,gBAAgB;QAChB,MAAM,UAAU,GAAG,IAAI,QAAQ,GAAG,CAAA;QAClC,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,UAAU,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAC5F,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAA;QAC5B,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAA;QAErB,WAAW;QACX,MAAM,YAAY,GAAG,KAAK,GAAG,UAAU,CAAC,MAAM,CAAA;QAC9C,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;QACzD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAEnB,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACvB,IAAI,CAAC,YAAY,EAAE,CAAA;IACrB,CAAC;IAED,eAAe,CAAC,QAAgB;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,CAAA;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAA;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAA;QAEtC,mCAAmC;QACnC,MAAM,YAAY,GAAG,YAAY,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACvD,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,YAAY,IAAI,YAAY,CAAC,CAAA;QAEjF,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,UAAU,GAAG,YAAY,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAC5F,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAA;QAC5B,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAA;QAErB,gCAAgC;QAChC,MAAM,eAAe,GAAG,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;QAChE,MAAM,aAAa,GAAG,eAAe,GAAG,YAAY,CAAC,MAAM,CAAA;QAC3D,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,eAAe,EAAE,aAAa,CAAC,CAAA;QAC7D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAEnB,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACvB,IAAI,CAAC,YAAY,EAAE,CAAA;IACrB,CAAC;IAED,iBAAiB,CAAC,CAAQ,EAAE,QAAyB;QACnD,CAAC,CAAC,eAAe,EAAE,CAAA;QAEnB,MAAM,QAAQ,GAIT,EAAE,CAAA;QAEP,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;YACzB,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,QAAQ,CAAC,WAAW;gBAC7B,IAAI,EAAE,MAAM;aACb,CAAC,CAAA;QACJ,CAAC;QAED,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,QAAQ,CAAC,IAAI;gBACtB,IAAI,EAAE,MAAM;aACb,CAAC,CAAA;QACJ,CAAC;QAED,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,QAAQ,CAAC,IAAI;gBACtB,IAAI,EAAE,MAAM;aACb,CAAC,CAAA;QACJ,CAAC;QAED,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,OAAO;gBACd,OAAO,EAAE,QAAQ,CAAC,IAAI;gBACtB,IAAI,EAAE,MAAM;aACb,CAAC,CAAA;QACJ,CAAC;QAED,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,OAAO;gBACd,OAAO,EAAE,QAAQ,CAAC,OAAO;gBACzB,IAAI,EAAE,SAAS;aAChB,CAAC,CAAA;QACJ,CAAC;QAED,MAAM,WAAW,GAAgB;YAC/B,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,QAAQ;SACT,CAAA;QAED,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;IAClC,CAAC;IAED,iBAAiB,CAAC,CAAQ,EAAE,IAAqB;QAC/C,CAAC,CAAC,eAAe,EAAE,CAAA;QAEnB,MAAM,QAAQ,GAIT;YACH;gBACE,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,IAAI,CAAC,WAAW;gBACzB,IAAI,EAAE,MAAM;aACb;YACD;gBACE,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,IAAI,CAAC,MAAM;gBACpB,IAAI,EAAE,MAAM;aACb;YACD;gBACE,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;gBACnC,IAAI,EAAE,WAAW;aAClB;YACD;gBACE,KAAK,EAAE,OAAO;gBACd,OAAO,EAAE,IAAI,CAAC,UAAU;gBACxB,IAAI,EAAE,MAAM;aACb;SACF,CAAA;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,OAAO;gBACd,OAAO,EAAE,IAAI,CAAC,IAAI;gBAClB,IAAI,EAAE,MAAM;aACb,CAAC,CAAA;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,OAAO;gBACd,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;gBACjC,IAAI,EAAE,SAAS;aAChB,CAAC,CAAA;QACJ,CAAC;QAED,MAAM,WAAW,GAAgB;YAC/B,KAAK,EAAE,IAAI,CAAC,IAAI;YAChB,QAAQ;SACT,CAAA;QAED,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAA;IAClC,CAAC;IAEO,cAAc,CAAC,OAAoB;QACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;QAC/C,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG;;;;;;;;;KAStB,CAAA;QAED,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,6BAA6B,CAA4B,CAAA;QAClG,SAAS,CAAC,OAAO,GAAG,OAAO,CAAA;QAC3B,SAAS,CAAC,OAAO,GAAG,GAAG,EAAE;YACvB,MAAM,CAAC,KAAK,EAAE,CAAA;QAChB,CAAC,CAAA;QAED,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAA;QAC7B,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QACjC,MAAM,CAAC,SAAS,EAAE,CAAA;QAElB,aAAa;QACb,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;YACvC,MAAM,IAAI,GAAG,MAAM,CAAC,qBAAqB,EAAE,CAAA;YAC3C,MAAM,UAAU,GACd,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI;gBAC1B,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK;gBAC3B,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG;gBACzB,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,MAAM,CAAA;YAE9B,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,CAAC,KAAK,EAAE,CAAA;YAChB,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YACpC,IAAI,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;YACnC,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,YAAY;QACZ,MAAM,SAAS,GAAG,CAAC,CAAgB,EAAE,EAAE;YACrC,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACvB,MAAM,CAAC,KAAK,EAAE,CAAA;gBACd,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;YACpD,CAAC;QACH,CAAC,CAAA;QACD,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IACjD,CAAC;IAED,gBAAgB;QACd,iBAAiB;QACjB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;QAEjC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,YAAY,GAAG,EAAE,CAAA;YACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;YACnB,OAAM;QACR,CAAC;QAED,WAAW;QACX,MAAM,YAAY,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAA;QACxD,MAAM,aAAa,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAA;QAEzD,IAAI,YAAY,KAAK,aAAa,EAAE,CAAC;YACnC,IAAI,CAAC,YAAY,GAAG,mBAAmB,CAAA;YACvC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;YACpB,OAAM;QACR,CAAC;QAED,sBAAsB;QACtB,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAA;QACzD,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA,CAAC,iBAAiB;YAClD,MAAM,iBAAiB,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;YAClE,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACzC,IAAI,CAAC,YAAY,GAAG,cAAc,OAAO,EAAE,CAAA;gBAC3C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;gBACpB,OAAM;YACR,CAAC;QACH,CAAC;QAED,WAAW;QACX,MAAM,eAAe,GAAG;YACtB,aAAa,EAAE,UAAU;YACzB,aAAa,EAAE,SAAS;YACxB,aAAa,EAAE,UAAU;YACzB,SAAS,CAAC,OAAO;SAClB,CAAA;QAED,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;YACtC,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC1B,IAAI,CAAC,YAAY,GAAG,mBAAmB,CAAA;gBACvC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;gBACpB,OAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,EAAE,CAAA;QACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;IACrB,CAAC;IAED,YAAY;QACV,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,QAAQ,EAAE;YACxB,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,IAAI,CAAC,KAAK;SACnB,CAAC,CACH,CAAA;IACH,CAAC;;AA9nB2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CAAmB;AACnB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;4DAA2C;AAC1C;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;4DAA2C;AACxC;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;iEAAwC;AAEnD;IAAhB,KAAK,EAAE;sDAAkC;AACzB;IAAhB,KAAK,EAAE;iDAAgC;AAEZ;IAA3B,KAAK,CAAC,mBAAmB,CAAC;gDAA6B;AAtW7C,gBAAgB;IAD5B,aAAa,CAAC,kBAAkB,CAAC;GACrB,gBAAgB,CA69B5B","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport './ox-input-formula-help-popup.js'\n\nimport '@operato/i18n/ox-i18n.js'\nimport { css, html } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\n/*\n * 이 파일은 @operato/input 안에 있다 — 자기 패키지를 이름으로 부르지 않는다.\n *\n * 전에는 '@operato/input' 에서 가져왔다. 그러면 package.json 의 exports 를 타고 **자기 dist** 로\n * 돌아 들어가서, 이미 만들어 둔 dist/src/*.d.ts 가 컴파일 대상에 섞인다. tsc 는 자기가 읽고 있는\n * 파일 위에 다시 쓸 수 없으므로 TS5055 로 멈추고, noEmitOnError 라 **패키지가 아예 빌드되지 않는다**\n * (ox-checkbox · ox-form-field · ox-input-search 등 일곱 개).\n *\n * 같은 패키지 안에서는 상대 경로로 가져온다.\n */\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\nimport { OxInputFormulaHelpPopup, HelpContent } from './ox-input-formula-help-popup.js'\nimport { ScrollbarStyles } from '@operato/styles'\n\ntype FormulaVariable = {\n name: string\n description?: string\n type?: string\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 * .availableFunctions=${functions}\n * .includeDefaultFunctions=${true}\n * ></ox-input-formula>\n */\n@customElement('ox-input-formula')\nexport class KpiFormulaEditor extends OxFormField {\n static styles = [\n InputStyles,\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n margin-bottom: calc(var(--ox-input-gap) * 3);\n gap: calc(var(--ox-input-gap) * 2);\n }\n\n .formula-container {\n display: flex;\n flex-direction: column;\n gap: var(--ox-input-gap);\n }\n\n .formula-input-container {\n display: flex;\n flex-direction: column;\n gap: var(--ox-input-gap);\n }\n\n .formula-textarea {\n min-height: var(--ox-formula-textarea-min-height, 120px);\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n padding: var(--ox-input-padding);\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: var(--ox-formula-textarea-font-size, 1.3rem);\n line-height: var(--ox-input-line-height);\n resize: vertical;\n background-color: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n }\n\n .formula-textarea:focus {\n outline: none;\n border-color: var(--md-sys-color-primary);\n background-color: var(--ox-input-background);\n }\n\n .variables-container {\n display: flex;\n flex-direction: column;\n gap: var(--ox-input-gap);\n }\n\n .variables-header {\n display: flex;\n align-items: center;\n gap: var(--ox-input-gap);\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(--ox-input-gap);\n max-height: var(--ox-formula-grid-max-height, 200px);\n overflow-y: auto;\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n padding: var(--ox-input-gap);\n background-color: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n }\n\n .variable-item {\n display: flex;\n flex-direction: column;\n padding: var(--ox-input-gap);\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n background-color: var(--ox-input-background);\n cursor: pointer;\n transition: var(--ox-input-transition);\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: var(--ox-input-shadow);\n }\n\n .variable-name {\n font-weight: 500;\n color: var(--md-sys-color-primary);\n font-size: var(--ox-formula-font-size-small, 0.75rem);\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n }\n\n .variable-description {\n font-size: var(--ox-formula-font-size-tiny, 0.6875rem);\n color: var(--md-sys-color-on-surface-variant);\n margin-top: 2px;\n }\n\n .variable-type {\n font-size: var(--ox-formula-font-size-tiny, 0.6875rem);\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: var(--ox-input-font-size);\n color: var(--md-sys-color-outline);\n cursor: pointer;\n padding: var(--ox-formula-icon-padding, 2px);\n border-radius: var(--ox-input-radius);\n transition: var(--ox-input-transition);\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(--ox-input-gap);\n margin-top: var(--ox-input-gap);\n }\n\n .operator-button {\n padding: var(--ox-input-padding);\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n background-color: var(--ox-input-background);\n cursor: pointer;\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: var(--ox-formula-font-size-small, 0.75rem);\n transition: var(--ox-input-transition);\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(--ox-input-gap);\n margin-top: var(--ox-input-gap);\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(--ox-input-gap);\n }\n\n .function-button {\n padding: var(--ox-input-gap);\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n background-color: var(--ox-input-background);\n cursor: pointer;\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: var(--ox-formula-font-size-tiny, 0.6875rem);\n text-align: left;\n transition: var(--ox-input-transition);\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: calc(var(--ox-input-gap) * 2);\n padding: var(--ox-input-padding);\n background-color: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border-radius: var(--ox-input-radius);\n border: var(--ox-input-border);\n }\n\n .preview-title {\n font-weight: 500;\n margin-bottom: var(--ox-input-gap);\n color: var(--md-sys-color-on-surface);\n }\n\n .preview-formula {\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n background-color: var(--ox-input-background);\n padding: var(--ox-input-gap);\n border-radius: var(--ox-input-radius);\n border: var(--ox-input-border);\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: var(--ox-formula-font-size-small, 0.75rem);\n margin-top: var(--ox-input-gap);\n }\n\n .info-message {\n color: var(--md-sys-color-on-surface-variant);\n font-size: var(--ox-formula-font-size-small, 0.75rem);\n margin-top: var(--ox-input-gap);\n }\n\n /* 도움말 팝업 스타일 */\n .help-popup {\n max-width: 500px;\n max-height: 400px;\n overflow-y: auto;\n background: var(--ox-input-background);\n border-radius: var(--ox-input-popup-radius);\n box-shadow: var(--ox-input-shadow);\n }\n\n .help-title {\n font-size: 20px;\n font-weight: 600;\n margin-bottom: 16px;\n color: var(--md-sys-color-primary);\n padding: 20px 20px 16px 20px;\n background: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border-bottom: var(--ox-input-border);\n border-radius: var(--ox-input-popup-radius) var(--ox-input-popup-radius) 0 0;\n }\n\n .help-section {\n margin-bottom: 16px;\n padding: 0 20px;\n }\n\n .help-section-title {\n font-weight: 600;\n margin-bottom: 8px;\n color: var(--ox-input-color);\n font-size: var(--ox-input-font-size);\n border-bottom: var(--ox-input-border);\n padding-bottom: 4px;\n }\n\n .help-content {\n font-size: var(--ox-input-font-size);\n line-height: 1.6;\n color: var(--ox-input-placeholder-color);\n padding: 4px 0;\n }\n\n .help-syntax {\n background: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border: var(--ox-input-border);\n border-radius: var(--ox-input-radius);\n padding: 12px;\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: 13px;\n color: var(--ox-input-color);\n margin: 8px 0;\n }\n\n .help-example {\n background: var(--md-sys-color-secondary-container);\n border: 1px solid var(--md-sys-color-tertiary-container);\n border-radius: var(--ox-input-radius);\n padding: 12px;\n font-family: var(--ox-formula-font-family, 'Courier New', monospace);\n font-size: 13px;\n color: var(--md-sys-color-on-tertiary-container);\n margin: 8px 0;\n }\n\n .help-parameters {\n margin: 8px 0;\n }\n\n .help-parameter {\n background: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border-left: 3px solid var(--md-sys-color-primary);\n border-radius: var(--ox-input-radius);\n padding: 8px 12px;\n margin-bottom: 4px;\n font-size: 13px;\n }\n\n .help-parameter-desc {\n color: var(--ox-input-placeholder-color);\n }\n\n /* Dialog specific styles */\n .help-dialog {\n border: none;\n border-radius: var(--ox-input-popup-radius);\n box-shadow: var(--ox-input-shadow);\n padding: 0;\n max-width: 500px;\n max-height: 80vh;\n overflow-y: auto;\n background-color: var(--ox-input-background);\n }\n\n .help-dialog::backdrop {\n background-color: var(--ox-input-scrim);\n }\n\n .dialog-actions {\n display: flex;\n justify-content: flex-end;\n padding: 16px 20px;\n border-top: var(--ox-input-border);\n background: var(--ox-formula-sunken-background, var(--md-sys-color-surface-container-low, #f8f9fa));\n border-radius: 0 0 8px 8px;\n }\n\n .close-btn {\n padding: 8px 16px;\n border: 1px solid var(--md-sys-color-primary);\n border-radius: var(--ox-input-radius);\n background-color: var(--md-sys-color-primary);\n color: var(--md-sys-color-on-primary);\n cursor: pointer;\n font-size: var(--ox-input-font-size);\n font-weight: 500;\n transition: var(--ox-input-transition);\n }\n\n .close-btn:hover {\n background-color: var(--ox-input-focus-color);\n border-color: var(--ox-input-focus-color);\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 @property({ type: Array }) availableFunctions: FormulaFunction[] = []\n @property({ type: Boolean }) includeDefaultFunctions: boolean = true\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 // 기본 함수들 (도움말 정보 포함)\n private readonly _defaultFunctions: 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 // 사용 가능한 함수 목록을 가져오는 getter\n get functions(): FormulaFunction[] {\n let resultFunctions: FormulaFunction[] = []\n\n // 기본 함수 포함 여부 확인\n if (this.includeDefaultFunctions) {\n resultFunctions = [...this._defaultFunctions]\n }\n\n // 사용자 정의 함수들 추가\n if (this.availableFunctions && this.availableFunctions.length > 0) {\n for (const customFunc of this.availableFunctions) {\n const existingIndex = resultFunctions.findIndex(f => f.name === customFunc.name)\n if (existingIndex >= 0) {\n // 기존 함수를 사용자 정의 함수로 교체\n resultFunctions[existingIndex] = customFunc\n } else {\n // 새로운 함수 추가\n resultFunctions.push(customFunc)\n }\n }\n }\n\n return resultFunctions\n }\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 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 ${this.functions.length > 0\n ? html`\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\n style=\"font-size: var(--ox-formula-font-size-tiny, 0.6875rem); color: var(--md-sys-color-on-surface-variant);\"\n >\n ${func.description}\n </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: var(--ox-formula-font-size-small, 0.75rem);\"\n >\n help\n </md-icon>\n `\n : ''}\n </div>\n `\n )}\n </div>\n </div>\n `\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 const sections: Array<{\n title: string\n content: string\n type?: 'text' | 'code' | 'parameter' | 'example'\n }> = []\n\n if (variable.description) {\n sections.push({\n title: '설명',\n content: variable.description,\n type: 'text'\n })\n }\n\n if (variable.type) {\n sections.push({\n title: '타입',\n content: variable.type,\n type: 'text'\n })\n }\n\n if (variable.unit) {\n sections.push({\n title: '단위',\n content: variable.unit,\n type: 'text'\n })\n }\n\n if (variable.help) {\n sections.push({\n title: '상세 설명',\n content: variable.help,\n type: 'text'\n })\n }\n\n if (variable.example) {\n sections.push({\n title: '사용 예시',\n content: variable.example,\n type: 'example'\n })\n }\n\n const helpContent: HelpContent = {\n title: variable.name,\n sections\n }\n\n this._showHelpPopup(helpContent)\n }\n\n _showFunctionHelp(e: Event, func: FormulaFunction) {\n e.stopPropagation()\n\n const sections: Array<{\n title: string\n content: string\n type?: 'text' | 'code' | 'parameter' | 'example'\n }> = [\n {\n title: '설명',\n content: func.description,\n type: 'text'\n },\n {\n title: '구문',\n content: func.syntax,\n type: 'code'\n },\n {\n title: '매개변수',\n content: func.parameters.join('\\n'),\n type: 'parameter'\n },\n {\n title: '반환 타입',\n content: func.returnType,\n type: 'text'\n }\n ]\n\n if (func.help) {\n sections.push({\n title: '상세 설명',\n content: func.help,\n type: 'text'\n })\n }\n\n if (func.examples && func.examples.length > 0) {\n sections.push({\n title: '사용 예시',\n content: func.examples.join('\\n'),\n type: 'example'\n })\n }\n\n const helpContent: HelpContent = {\n title: func.name,\n sections\n }\n\n this._showHelpPopup(helpContent)\n }\n\n private _showHelpPopup(content: HelpContent) {\n const dialog = document.createElement('dialog')\n dialog.style.cssText = `\n border: none;\n border-radius: var(--ox-input-popup-radius);\n box-shadow: var(--ox-input-shadow);\n padding: 0;\n max-width: 500px;\n max-height: 80vh;\n overflow-y: auto;\n background-color: var(--ox-input-background);\n `\n\n const helpPopup = document.createElement('ox-input-formula-help-popup') as OxInputFormulaHelpPopup\n helpPopup.content = content\n helpPopup.onClose = () => {\n dialog.close()\n }\n\n dialog.appendChild(helpPopup)\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"]}
|
|
@@ -7,6 +7,7 @@ import '@material/web/icon/icon.js';
|
|
|
7
7
|
import { css, html } from 'lit';
|
|
8
8
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
9
9
|
import { customElement, property, query } from 'lit/decorators.js';
|
|
10
|
+
import { i18next } from '@operato/i18n';
|
|
10
11
|
import { OxFormField } from './ox-form-field.js';
|
|
11
12
|
import { InputStyles } from './input-styles.js';
|
|
12
13
|
let OxInputSearch = class OxInputSearch extends OxFormField {
|
|
@@ -59,9 +60,22 @@ let OxInputSearch = class OxInputSearch extends OxFormField {
|
|
|
59
60
|
// private dispatchChangeEventDebouncer = debounce((value: string) => this.dispatchChangeEvent(value), 100)
|
|
60
61
|
render() {
|
|
61
62
|
return html `
|
|
62
|
-
|
|
63
|
+
<!--
|
|
64
|
+
돋보기 — 누르면 검색을 건다. 그런데 md-icon 은 포커스를 받지 않아서 키보드로는 닿지 않는다.
|
|
65
|
+
같은 일을 입력칸에서 Enter 로 할 수 있으므로 기능이 막힌 것은 아니다. 이름 없는 클릭 대상이
|
|
66
|
+
하나 더 읽히지 않도록 보조기술에서는 지운다 — 감춰도 잃는 동작이 없다.
|
|
67
|
+
-->
|
|
68
|
+
<md-icon aria-hidden="true" @click=${(e) => !this.disabled && this._onClickSearch(e)}>search</md-icon>
|
|
69
|
+
<!--
|
|
70
|
+
입력칸에 이름을 붙인다. 전에는 placeholder 만 있었다 — placeholder 는 이름이 아니다.
|
|
71
|
+
글자를 치는 순간 사라지므로 「내가 지금 무엇을 적고 있었나」를 되물을 수 없고, 부르는 쪽이
|
|
72
|
+
placeholder 를 안 넘기면 아무것도 남지 않는다(대부분의 화면이 안 넘긴다).
|
|
73
|
+
|
|
74
|
+
부르는 쪽이 정한 문구가 있으면 그것을 쓰고, 없으면 「검색어」로 물러난다.
|
|
75
|
+
-->
|
|
63
76
|
<input
|
|
64
77
|
type="text"
|
|
78
|
+
aria-label=${this.placeholder || i18next.t('label.search', { defaultValue: 'search' })}
|
|
65
79
|
.value=${this.value || ''}
|
|
66
80
|
.placeholder=${this.placeholder || ''}
|
|
67
81
|
maxlength=${ifDefined(this.maxLength)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-input-search.js","sourceRoot":"","sources":["../../src/ox-input-search.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,4BAA4B,CAAA;AAEnC,+CAA+C;AAC/C,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AACxD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAGxC,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,WAAW;aACrC,WAAM,GAAG;QACd,WAAW;QACX,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0CF;KACF,AA7CY,CA6CZ;IAQD,2GAA2G;IAE3G,MAAM;QACJ,OAAO,IAAI,CAAA
|
|
1
|
+
{"version":3,"file":"ox-input-search.js","sourceRoot":"","sources":["../../src/ox-input-search.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/icon/icon.js'\n\n// import debounce from 'lodash-es/debounce.js'\nimport { css, html } from 'lit'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { customElement, property, query } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\n\n@customElement('ox-input-search')\nexport class OxInputSearch extends OxFormField {\n static styles = [\n InputStyles,\n css`\n :host {\n display: flex;\n position: relative;\n align-items: center;\n\n color: var(--ox-input-search-color, var(--md-sys-color-on-surface-variant));\n background-color: var(--ox-input-search-background-color, var(--md-sys-color-surface-variant));\n\n --md-icon-size: 20px;\n }\n\n [type='text'] {\n flex: 1;\n color: inherit;\n background-color: transparent;\n border: 0;\n padding: var(--input-search-padding, calc(var(--ox-input-gap) / 2));\n padding-left: 25px;\n overflow: hidden;\n }\n\n [type='text']:focus {\n outline: none;\n }\n\n /*\n * 아이콘 색을 글자와 따로 받는다.\n *\n * 돋보기는 **장치**이고 입력한 글자는 **값**이다. 둘이 같은 색이면 장치가 값만큼 눈에 걸린다.\n * 기본은 물려받는 색이라 지금 쓰는 곳의 거동이 바뀌지 않고, 담는 화면이 필요할 때만 내린다.\n */\n md-icon {\n position: absolute;\n color: var(--ox-input-search-icon-color, inherit);\n }\n\n input {\n background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));\n color: var(--input-field-color, var(--md-sys-color-on-surface));\n width: 100%;\n }\n `\n ]\n\n @property({ type: String }) placeholder?: string\n @property({ attribute: 'select-after-change', type: Boolean }) selectAfterChange?: boolean\n @property({ type: Number, attribute: 'max-length' }) maxLength?: number\n\n @query('input') input!: HTMLInputElement\n\n // private dispatchChangeEventDebouncer = debounce((value: string) => this.dispatchChangeEvent(value), 100)\n\n render() {\n return html`\n <!--\n 돋보기 — 누르면 검색을 건다. 그런데 md-icon 은 포커스를 받지 않아서 키보드로는 닿지 않는다.\n 같은 일을 입력칸에서 Enter 로 할 수 있으므로 기능이 막힌 것은 아니다. 이름 없는 클릭 대상이\n 하나 더 읽히지 않도록 보조기술에서는 지운다 — 감춰도 잃는 동작이 없다.\n -->\n <md-icon aria-hidden=\"true\" @click=${(e: Event) => !this.disabled && this._onClickSearch(e)}>search</md-icon>\n <!--\n 입력칸에 이름을 붙인다. 전에는 placeholder 만 있었다 — placeholder 는 이름이 아니다.\n 글자를 치는 순간 사라지므로 「내가 지금 무엇을 적고 있었나」를 되물을 수 없고, 부르는 쪽이\n placeholder 를 안 넘기면 아무것도 남지 않는다(대부분의 화면이 안 넘긴다).\n\n 부르는 쪽이 정한 문구가 있으면 그것을 쓰고, 없으면 「검색어」로 물러난다.\n -->\n <input\n type=\"text\"\n aria-label=${this.placeholder || i18next.t('label.search', { defaultValue: 'search' })}\n .value=${this.value || ''}\n .placeholder=${this.placeholder || ''}\n maxlength=${ifDefined(this.maxLength)}\n @change=${(e: Event) => {\n e.stopPropagation()\n this.dispatchChangeEvent((e.target as HTMLInputElement).value)\n // this.dispatchChangeEventDebouncer((e.target as HTMLInputElement).value)\n }}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n if ((e.target as HTMLInputElement).value == this.value) {\n /* Even if the value has not changed, the enter key triggers a change event. */\n e.preventDefault() /* Prevent change event from occurring twice. */\n\n this.input.dispatchEvent(\n new CustomEvent('change', {\n detail: (e.target as HTMLInputElement).value\n })\n )\n }\n }\n }}\n ?disabled=${this.disabled}\n />\n `\n }\n\n firstUpdated() {\n if (this.autofocus) {\n this.input.focus()\n }\n }\n\n dispatchChangeEvent(value: string) {\n this.value = value\n\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: value\n })\n )\n\n if (this.selectAfterChange) {\n requestAnimationFrame(() => {\n this.input.select()\n })\n }\n }\n\n _onClickSearch(e: Event) {\n if (this._form) {\n e.stopPropagation()\n this._form.requestSubmit()\n } else {\n this.input.dispatchEvent(\n new CustomEvent('change', {\n detail: this.input.value\n })\n )\n }\n }\n}\n"]}
|
|
@@ -125,8 +125,22 @@ let OxInputSecret = class OxInputSecret extends OxFormField {
|
|
|
125
125
|
spellcheck="false"
|
|
126
126
|
data-form-type="other"
|
|
127
127
|
/>
|
|
128
|
+
<!--
|
|
129
|
+
보이기·감추기는 이 표식 하나뿐이다. md-icon 은 키보드 초점을 받지 못하므로 role 과
|
|
130
|
+
tabindex 를 주고 Enter · Space 를 함께 받는다 — 그러지 않으면 키보드만 쓰는 사람은
|
|
131
|
+
자기가 무엇을 입력했는지 확인할 방법이 없다.
|
|
132
|
+
-->
|
|
128
133
|
<md-icon
|
|
129
134
|
class="secret-toggle"
|
|
135
|
+
role="button"
|
|
136
|
+
tabindex="0"
|
|
137
|
+
@keydown=${(e) => {
|
|
138
|
+
if (e.key !== 'Enter' && e.key !== ' ')
|
|
139
|
+
return;
|
|
140
|
+
e.preventDefault();
|
|
141
|
+
e.stopPropagation();
|
|
142
|
+
this.togglePasswordVisibility();
|
|
143
|
+
}}
|
|
130
144
|
@click=${(e) => {
|
|
131
145
|
e.stopPropagation();
|
|
132
146
|
this.togglePasswordVisibility();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-input-secret.js","sourceRoot":"","sources":["../../src/ox-input-secret.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,4BAA4B,CAAA;AAEnC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAGxC,IAAM,aAAa,GAAnB,MAAM,aAAc,SAAQ,WAA+B;aACzD,WAAM,GAAG;QACd,WAAW;QACX,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+DF;KACF,AAlEY,CAkEZ;IAQO,wBAAwB;QAC9B,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAM;QAEvB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAA;YACxB,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,gBAAgB,CAAgB,CAAA;YAC3E,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,WAAW,GAAG,YAAY,CAAA;gBAC/B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAA;YAClD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,UAAU,CAAA;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,gBAAgB,CAAgB,CAAA;YAC3E,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,WAAW,GAAG,gBAAgB,CAAA;gBACnC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAA;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAA;;;;mBAII,IAAI,CAAC,KAAK,IAAI,EAAE;yBACV,IAAI,CAAC,WAAW,IAAI,OAAO,CAAC,CAAC,CAAC,+BAA+B,CAAC;oBACnE,CAAC,CAAQ,EAAE,EAAE;YACrB,CAAC,CAAC,eAAe,EAAE,CAAA;YACnB,IAAI,CAAC,mBAAmB,CAAE,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC,CAAA;QAChE,CAAC;qBACU,CAAC,CAAgB,EAAE,EAAE;YAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;gBACtB,IAAK,CAAC,CAAC,MAA2B,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBACvD,+EAA+E;oBAC/E,CAAC,CAAC,cAAc,EAAE,CAAA,CAAC,gDAAgD;oBAEnE,IAAI,CAAC,KAAK,CAAC,aAAa,CACtB,IAAI,WAAW,CAAC,QAAQ,EAAE;wBACxB,MAAM,EAAG,CAAC,CAAC,MAA2B,CAAC,KAAK;qBAC7C,CAAC,CACH,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;sBACW,IAAI,CAAC,QAAQ
|
|
1
|
+
{"version":3,"file":"ox-input-secret.js","sourceRoot":"","sources":["../../src/ox-input-secret.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/icon/icon.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\nimport { i18next } from '@operato/i18n'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\n\n@customElement('ox-input-secret')\nexport class OxInputSecret extends OxFormField<string | undefined> {\n static styles = [\n InputStyles,\n css`\n :host {\n display: flex;\n position: relative;\n align-items: center;\n\n color: var(--ox-input-secret-color, var(--md-sys-color-on-surface-variant));\n background-color: var(--ox-input-secret-background-color, var(--md-sys-color-surface-variant));\n\n --md-icon-size: 20px;\n }\n\n .secret-container {\n display: flex;\n align-items: center;\n justify-content: space-between;\n position: relative;\n width: 100%;\n }\n\n input {\n flex: 1;\n color: inherit;\n background-color: transparent;\n border: 0;\n padding: var(--input-secret-padding, calc(var(--ox-input-gap) / 2));\n padding-right: 20px;\n overflow: hidden;\n text-overflow: ellipsis;\n font-family: inherit;\n font-size: inherit;\n letter-spacing: 0.5px;\n }\n\n input:focus {\n outline: none;\n }\n\n input:focus {\n outline: none;\n border: none;\n box-shadow: none;\n }\n\n .secret-toggle {\n position: absolute;\n right: 0px;\n cursor: pointer;\n font-size: 16px;\n color: var(--md-sys-color-on-surface-variant);\n user-select: none;\n opacity: 0.7;\n transition: opacity 0.2s;\n }\n\n .secret-toggle:hover {\n opacity: 1;\n color: var(--md-sys-color-primary);\n }\n\n .secret-container:hover .secret-toggle {\n opacity: 1;\n }\n `\n ]\n\n @property({ type: String }) placeholder?: string\n @property({ attribute: 'select-after-change', type: Boolean }) selectAfterChange?: boolean\n @property({ type: String }) value?: string | undefined\n\n @query('input') input!: HTMLInputElement\n\n private togglePasswordVisibility() {\n if (!this.input) return\n\n if (this.input.type === 'password') {\n this.input.type = 'text'\n const icon = this.renderRoot.querySelector('.secret-toggle') as HTMLElement\n if (icon) {\n icon.textContent = 'visibility'\n icon.title = i18next.t('text.input-secret-hide')\n }\n } else {\n this.input.type = 'password'\n const icon = this.renderRoot.querySelector('.secret-toggle') as HTMLElement\n if (icon) {\n icon.textContent = 'visibility_off'\n icon.title = i18next.t('text.input-secret-show')\n }\n }\n }\n\n render() {\n return html`\n <div class=\"secret-container\">\n <input\n type=\"password\"\n .value=${this.value || ''}\n .placeholder=${this.placeholder || i18next.t('text.input-secret-placeholder')}\n @change=${(e: Event) => {\n e.stopPropagation()\n this.dispatchChangeEvent((e.target as HTMLInputElement).value)\n }}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n if ((e.target as HTMLInputElement).value == this.value) {\n /* Even if the value has not changed, the enter key triggers a change event. */\n e.preventDefault() /* Prevent change event from occurring twice. */\n\n this.input.dispatchEvent(\n new CustomEvent('change', {\n detail: (e.target as HTMLInputElement).value\n })\n )\n }\n }\n }}\n ?disabled=${this.disabled}\n autocomplete=\"off\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n spellcheck=\"false\"\n data-form-type=\"other\"\n />\n <!--\n 보이기·감추기는 이 표식 하나뿐이다. md-icon 은 키보드 초점을 받지 못하므로 role 과\n tabindex 를 주고 Enter · Space 를 함께 받는다 — 그러지 않으면 키보드만 쓰는 사람은\n 자기가 무엇을 입력했는지 확인할 방법이 없다.\n -->\n <md-icon\n class=\"secret-toggle\"\n role=\"button\"\n tabindex=\"0\"\n @keydown=${(e: KeyboardEvent) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n e.stopPropagation()\n this.togglePasswordVisibility()\n }}\n @click=${(e: Event) => {\n e.stopPropagation()\n this.togglePasswordVisibility()\n }}\n title=${i18next.t('text.input-secret-toggle')}\n >\n visibility_off\n </md-icon>\n </div>\n `\n }\n\n firstUpdated() {\n if (this.autofocus) {\n this.input.focus()\n }\n }\n\n dispatchChangeEvent(value: string) {\n this.value = value\n\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n composed: true,\n detail: value\n })\n )\n\n if (this.selectAfterChange) {\n requestAnimationFrame(() => {\n this.input.select()\n })\n }\n }\n}\n"]}
|
|
@@ -22,7 +22,7 @@ let OxInputSelectButtons = class OxInputSelectButtons extends OxFormField {
|
|
|
22
22
|
/*
|
|
23
23
|
* 필터는 **목록보다 조용해야 한다.**
|
|
24
24
|
*
|
|
25
|
-
*
|
|
25
|
+
* 확인해 보니 칩 글자가 16px 이었고 목록 본문은 14px 이었다. 걸러진 것이 하나도 없는 상태에서도 이
|
|
26
26
|
* 줄이 화면에서 가장 크고 진했다. 테두리 색도 본문 글자와 같은 검정이라, 네 개가 나란히 서면
|
|
27
27
|
* 그 선들이 제일 먼저 눈에 걸렸다.
|
|
28
28
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-input-select-buttons.js","sourceRoot":"","sources":["../../src/ox-input-select-buttons.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,oCAAoC,CAAA;AAC3C,OAAO,iCAAiC,CAAA;AAExC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAA;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAiBxC,IAAM,oBAAoB,GAA1B,MAAM,oBAAqB,SAAQ,WAAW;IAA9C;;QAqDsB,UAAK,GAAkC,EAAE,CAAA;QACzC,YAAO,GAAa,EAAE,CAAA;QACpB,aAAQ,GAAY,KAAK,CAAA;IA6CxD,CAAC;aAnGQ,WAAM,GAAG;QACd,WAAW;QACX,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+CF;KACF,AAlDY,CAkDZ;IAMD,MAAM;QACJ,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAE3G,OAAO,IAAI,CAAA;;UAEL,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CACnB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAA;;2BAEjB,KAAK;sBACV,OAAO;sBACP,SAAS,CAAC,IAAI,CAAC;0BACX,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;uBACzB,CAAC,CAA0B,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;;WAE7E,CACF;;KAEJ,CAAA;IACH,CAAC;IAED,OAAO,CAAC,CAA0B;QAChC,CAAC,CAAC,eAAe,EAAE,CAAA;QAEnB,MAAM,MAAM,GAAG,CAAC,CAAC,MAAsB,CAAA;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,CAAW,CAAA;QAEzD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YAE3G,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YAC7C,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC;gBACd,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YACvB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACpB,CAAC;YACD,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,CAAA;QAC1B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAA;QACvD,CAAC;QAED,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IACtG,CAAC;;AA9C0B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;mDAA0C;AACzC;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;qDAAuB;AACpB;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;sDAA0B;AAvD3C,oBAAoB;IADhC,aAAa,CAAC,yBAAyB,CAAC;GAC5B,oBAAoB,CAoGhC","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/chips/filter-chip.js'\nimport '@material/web/chips/chip-set.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\nimport { MdFilterChip } from '@material/web/chips/filter-chip.js'\n\ntype Option = {\n display: string\n value: string\n /**\n * 마우스를 올렸을 때 보이는 뜻.\n *\n * 칩의 이름은 짧아야 하는데, 이름만으로는 무엇이 걸러지는지 알 수 없는 것이 있다 — 「중요」가\n * 우선순위 몇 이상인지, 「만기」가 몇 시간 안인지. 그 값을 화면이 말하지 않으면 사용자는 눌러 보고\n * 결과를 되짚어야 한다.\n */\n hint?: string\n}\n\n@customElement('ox-input-select-buttons')\nexport class OxInputSelectButtons extends OxFormField {\n static styles = [\n InputStyles,\n css`\n /*\n * 필터는 **목록보다 조용해야 한다.**\n *\n *
|
|
1
|
+
{"version":3,"file":"ox-input-select-buttons.js","sourceRoot":"","sources":["../../src/ox-input-select-buttons.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/chips/filter-chip.js'\nimport '@material/web/chips/chip-set.js'\n\nimport { css, html } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { InputStyles } from './input-styles.js'\nimport { MdFilterChip } from '@material/web/chips/filter-chip.js'\n\ntype Option = {\n display: string\n value: string\n /**\n * 마우스를 올렸을 때 보이는 뜻.\n *\n * 칩의 이름은 짧아야 하는데, 이름만으로는 무엇이 걸러지는지 알 수 없는 것이 있다 — 「중요」가\n * 우선순위 몇 이상인지, 「만기」가 몇 시간 안인지. 그 값을 화면이 말하지 않으면 사용자는 눌러 보고\n * 결과를 되짚어야 한다.\n */\n hint?: string\n}\n\n@customElement('ox-input-select-buttons')\nexport class OxInputSelectButtons extends OxFormField {\n static styles = [\n InputStyles,\n css`\n /*\n * 필터는 **목록보다 조용해야 한다.**\n *\n * 확인해 보니 칩 글자가 16px 이었고 목록 본문은 14px 이었다. 걸러진 것이 하나도 없는 상태에서도 이\n * 줄이 화면에서 가장 크고 진했다. 테두리 색도 본문 글자와 같은 검정이라, 네 개가 나란히 서면\n * 그 선들이 제일 먼저 눈에 걸렸다.\n *\n * 그래서 꺼져 있을 때는 물러나고 켜져 있을 때만 나선다. 지금 무엇으로 걸렀는지가 이 줄에서\n * 바로 읽혀야 한다 — 목록이 짧아진 이유를 화면이 말해야 한다.\n *\n * md 칩을 갈아치우지 않고 그 토큰으로만 조정한다. 이 컴포넌트를 쓰는 화면이 많고, 자기 것으로\n * 다시 만들면 그 화면들이 두 모양으로 갈린다.\n */\n :host {\n display: flex;\n flex-flow: row;\n flex-wrap: wrap;\n gap: 6px;\n\n /* 크기 — 목록 본문보다 한 단계 작게. */\n --md-filter-chip-container-height: 26px;\n --md-filter-chip-label-text-size: 12.5px;\n --md-filter-chip-label-text-weight: 560;\n --md-filter-chip-container-shape: 13px;\n --md-filter-chip-leading-space: 11px;\n --md-filter-chip-trailing-space: 11px;\n --md-filter-chip-with-leading-icon-leading-space: 8px;\n --md-filter-chip-icon-size: 15px;\n\n /* 꺼진 상태 — 선은 흐리게, 글자는 보조 글자 색으로. */\n --md-filter-chip-outline-color: var(--md-sys-color-outline-variant);\n --md-filter-chip-outline-width: 1px;\n --md-filter-chip-label-text-color: var(--md-sys-color-on-surface-variant);\n --md-filter-chip-hover-label-text-color: var(--md-sys-color-on-surface);\n --md-filter-chip-hover-state-layer-opacity: 0.06;\n\n /* 켜진 상태 — 채워서 확실히 다르게. 켜졌는지 아닌지가 헷갈리면 필터는 쓸모가 없다. */\n --md-filter-chip-selected-container-color: var(--md-sys-color-primary);\n --md-filter-chip-selected-label-text-color: var(--md-sys-color-on-primary);\n --md-filter-chip-selected-outline-width: 0px;\n --md-filter-chip-selected-focus-label-text-color: var(--md-sys-color-on-primary);\n --md-filter-chip-selected-hover-label-text-color: var(--md-sys-color-on-primary);\n --md-filter-chip-selected-pressed-label-text-color: var(--md-sys-color-on-primary);\n --md-filter-chip-selected-leading-icon-color: var(--md-sys-color-on-primary);\n --md-filter-chip-selected-hover-leading-icon-color: var(--md-sys-color-on-primary);\n }\n `\n ]\n\n @property({ type: Array }) value: string[] | string | undefined = []\n @property({ type: Array }) options: Option[] = []\n @property({ type: Boolean }) multiple: boolean = false\n\n render() {\n const options = this.options.filter(option => !!option.value)\n const values = this.value instanceof Array ? this.value : typeof this.value == 'string' ? [this.value] : []\n\n return html`\n <md-chip-set>\n ${(options || []).map(\n ({ display, value, hint }) => html`\n <md-filter-chip\n data-value=${value}\n label=${display}\n title=${ifDefined(hint)}\n ?selected=${values.includes(value)}\n @click=${(e: MouseEvent | TouchEvent) => !this.disabled && this.onClick(e)}\n ></md-filter-chip>\n `\n )}\n </md-chip-set>\n `\n }\n\n onClick(e: MouseEvent | TouchEvent) {\n e.stopPropagation()\n\n const target = e.target as MdFilterChip\n const value = target.getAttribute('data-value') as string\n\n if (this.multiple) {\n const values = this.value instanceof Array ? this.value : typeof this.value == 'string' ? [this.value] : []\n\n const idx = (this.value || []).indexOf(value)\n if (idx != -1) {\n values.splice(idx, 1)\n } else {\n values.push(value)\n }\n this.value = [...values]\n } else {\n this.value = this.value === value ? undefined : value\n }\n\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '../src/ox-input-background-pattern.js';
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { expect, fixture } from '@open-wc/testing';
|
|
2
|
+
import { html } from 'lit';
|
|
3
|
+
import '../src/ox-input-background-pattern.js';
|
|
4
|
+
import { registerImageSelector } from '../src/image-selector.js';
|
|
5
|
+
/**
|
|
6
|
+
* 그림 고르는 칸의 자리.
|
|
7
|
+
*
|
|
8
|
+
* ## 왜 시험이 필요한가
|
|
9
|
+
*
|
|
10
|
+
* `@operato/input` 이 `@operato/attachment` 를 직접 부르고 있었다. 가장 아래의 부품이 위의 기능을
|
|
11
|
+
* 아는 모양이라 고리가 생겼고(input ▶ attachment ▶ data-grist ▶ input), 그 고리 때문에 이 package
|
|
12
|
+
* 는 **빌드되지 않았다**(TS5055 일곱 건, noEmitOnError).
|
|
13
|
+
*
|
|
14
|
+
* 화살표를 뒤집으면서 두 가지가 지켜져야 한다.
|
|
15
|
+
*
|
|
16
|
+
* ```
|
|
17
|
+
* 비지 않는다 등록이 없어도 칸이 있어야 한다. 등록 안 된 custom element 는 소리 없이 빈 상자다
|
|
18
|
+
* 값이 담긴다 어느 갈래가 그려지든 value-key 와 change 로 값이 같은 길을 지나야 한다
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
describe('그림 고르는 칸은 위 layer 가 채운다', () => {
|
|
22
|
+
async function pattern(value = {}) {
|
|
23
|
+
const el = await fixture(html `<ox-input-background-pattern .value=${value}></ox-input-background-pattern>`);
|
|
24
|
+
await el.updateComplete;
|
|
25
|
+
return el;
|
|
26
|
+
}
|
|
27
|
+
it('등록이 없으면 글자 칸이다 — 빈 자리로 두지 않는다', async () => {
|
|
28
|
+
const el = await pattern({ image: 'https://example.com/a.png' });
|
|
29
|
+
const field = el.renderRoot.querySelector('[value-key="image"]');
|
|
30
|
+
expect(field, '그림 칸이 아예 없다').to.exist;
|
|
31
|
+
expect(field.tagName).to.equal('INPUT');
|
|
32
|
+
expect(field.value, '적혀 있던 주소가 칸에 실리지 않았다').to.equal('https://example.com/a.png');
|
|
33
|
+
});
|
|
34
|
+
it('글자 칸에 적은 주소가 값으로 담긴다', async () => {
|
|
35
|
+
const el = await pattern({});
|
|
36
|
+
const field = el.renderRoot.querySelector('[value-key="image"]');
|
|
37
|
+
field.value = 'https://example.com/b.png';
|
|
38
|
+
field.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
39
|
+
expect(el.value.image).to.equal('https://example.com/b.png');
|
|
40
|
+
});
|
|
41
|
+
it('그림을 가진 쪽이 자기 칸을 등록하면 그것으로 바뀐다', async () => {
|
|
42
|
+
class FakeSelector extends HTMLElement {
|
|
43
|
+
}
|
|
44
|
+
customElements.define('test-image-selector', FakeSelector);
|
|
45
|
+
const el = await pattern({ image: 'https://example.com/c.png' });
|
|
46
|
+
/* 요소가 먼저 그려지고 등록이 나중에 와도 자리가 글자 칸으로 남아 있으면 안 된다. */
|
|
47
|
+
registerImageSelector('test-image-selector');
|
|
48
|
+
await el.updateComplete;
|
|
49
|
+
const field = el.renderRoot.querySelector('[value-key="image"]');
|
|
50
|
+
expect(field.tagName).to.equal('TEST-IMAGE-SELECTOR');
|
|
51
|
+
expect(field.value).to.equal('https://example.com/c.png');
|
|
52
|
+
expect(field.properties).to.deep.equal({ category: 'image' });
|
|
53
|
+
});
|
|
54
|
+
it('등록된 칸이 올린 change 도 같은 길로 값이 담긴다', async () => {
|
|
55
|
+
registerImageSelector('test-image-selector');
|
|
56
|
+
const el = await pattern({});
|
|
57
|
+
const field = el.renderRoot.querySelector('[value-key="image"]');
|
|
58
|
+
field.value = 'https://example.com/d.png';
|
|
59
|
+
field.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
60
|
+
expect(el.value.image).to.equal('https://example.com/d.png');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=image-selector.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-selector.test.js","sourceRoot":"","sources":["../../test/image-selector.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, fixture } from '@open-wc/testing'\nimport { html } from 'lit'\n\nimport '../src/ox-input-background-pattern.js'\nimport { registerImageSelector } from '../src/image-selector.js'\n\n/**\n * 그림 고르는 칸의 자리.\n *\n * ## 왜 시험이 필요한가\n *\n * `@operato/input` 이 `@operato/attachment` 를 직접 부르고 있었다. 가장 아래의 부품이 위의 기능을\n * 아는 모양이라 고리가 생겼고(input ▶ attachment ▶ data-grist ▶ input), 그 고리 때문에 이 package\n * 는 **빌드되지 않았다**(TS5055 일곱 건, noEmitOnError).\n *\n * 화살표를 뒤집으면서 두 가지가 지켜져야 한다.\n *\n * ```\n * 비지 않는다 등록이 없어도 칸이 있어야 한다. 등록 안 된 custom element 는 소리 없이 빈 상자다\n * 값이 담긴다 어느 갈래가 그려지든 value-key 와 change 로 값이 같은 길을 지나야 한다\n * ```\n */\ndescribe('그림 고르는 칸은 위 layer 가 채운다', () => {\n async function pattern(value: any = {}) {\n const el: any = await fixture(html`<ox-input-background-pattern .value=${value}></ox-input-background-pattern>`)\n await el.updateComplete\n return el\n }\n\n it('등록이 없으면 글자 칸이다 — 빈 자리로 두지 않는다', async () => {\n const el = await pattern({ image: 'https://example.com/a.png' })\n\n const field = el.renderRoot.querySelector('[value-key=\"image\"]') as HTMLInputElement\n\n expect(field, '그림 칸이 아예 없다').to.exist\n expect(field.tagName).to.equal('INPUT')\n expect(field.value, '적혀 있던 주소가 칸에 실리지 않았다').to.equal('https://example.com/a.png')\n })\n\n it('글자 칸에 적은 주소가 값으로 담긴다', async () => {\n const el = await pattern({})\n\n const field = el.renderRoot.querySelector('[value-key=\"image\"]') as HTMLInputElement\n field.value = 'https://example.com/b.png'\n field.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n\n expect(el.value.image).to.equal('https://example.com/b.png')\n })\n\n it('그림을 가진 쪽이 자기 칸을 등록하면 그것으로 바뀐다', async () => {\n class FakeSelector extends HTMLElement {\n value: any\n properties: any\n }\n customElements.define('test-image-selector', FakeSelector)\n\n const el = await pattern({ image: 'https://example.com/c.png' })\n\n /* 요소가 먼저 그려지고 등록이 나중에 와도 자리가 글자 칸으로 남아 있으면 안 된다. */\n registerImageSelector('test-image-selector')\n await el.updateComplete\n\n const field = el.renderRoot.querySelector('[value-key=\"image\"]') as any\n\n expect(field.tagName).to.equal('TEST-IMAGE-SELECTOR')\n expect(field.value).to.equal('https://example.com/c.png')\n expect(field.properties).to.deep.equal({ category: 'image' })\n })\n\n it('등록된 칸이 올린 change 도 같은 길로 값이 담긴다', async () => {\n registerImageSelector('test-image-selector')\n\n const el = await pattern({})\n const field = el.renderRoot.querySelector('[value-key=\"image\"]') as any\n\n field.value = 'https://example.com/d.png'\n field.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n\n expect(el.value.image).to.equal('https://example.com/d.png')\n })\n})\n"]}
|