@operato/input 10.10.0 → 10.10.1
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 +9 -0
- package/dist/src/image-selector.d.ts +5 -5
- package/dist/src/image-selector.js +22 -29
- package/dist/src/image-selector.js.map +1 -1
- package/dist/src/ox-input-background-pattern.d.ts +6 -6
- package/dist/src/ox-input-background-pattern.js +7 -7
- package/dist/src/ox-input-background-pattern.js.map +1 -1
- package/dist/src/ox-input-formula.js +6 -6
- package/dist/src/ox-input-formula.js.map +1 -1
- package/dist/src/ox-input-search.js +7 -7
- package/dist/src/ox-input-search.js.map +1 -1
- package/dist/test/image-selector.test.js +17 -16
- package/dist/test/image-selector.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/test/image-selector.test.ts +17 -16
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
### [10.10.1](https://github.com/hatiolab/operato/compare/v10.10.0...v10.10.1) (2026-09-06)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :memo: Documentation
|
|
10
|
+
|
|
11
|
+
* **data-grist, input, attachment:** rewrite today's comments and test names in English ([09983c0](https://github.com/hatiolab/operato/commit/09983c01bd7d47962180e7d5557a20bc5901b174))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
6
15
|
## [10.10.0](https://github.com/hatiolab/operato/compare/v10.9.0...v10.10.0) (2026-09-06)
|
|
7
16
|
|
|
8
17
|
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
* @license Copyright © HatioLab Inc. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Claim the image-picking field with a tag name.
|
|
6
6
|
*
|
|
7
|
-
* `@operato/attachment/ox-attachment-selector.js`
|
|
8
|
-
*
|
|
7
|
+
* `@operato/attachment/ox-attachment-selector.js` calls this when it loads. An app can override it
|
|
8
|
+
* the same way.
|
|
9
9
|
*/
|
|
10
10
|
export declare function registerImageSelector(tag: string): void;
|
|
11
|
-
/**
|
|
11
|
+
/** The registered tag name, or '' when nothing has claimed the slot. */
|
|
12
12
|
export declare function imageSelectorTag(): string;
|
|
13
|
-
/**
|
|
13
|
+
/** Notifies on registration change. Call the returned function to stop listening. */
|
|
14
14
|
export declare function onImageSelectorChange(listener: () => void): () => void;
|
|
@@ -2,58 +2,51 @@
|
|
|
2
2
|
* @license Copyright © HatioLab Inc. All rights reserved.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* The image-picking field: a slot this package declares, filled in from above.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
* `
|
|
9
|
-
* `@operato/attachment` 의 selector 를 직접 import 해서 썼다. 그런데 `@operato/attachment` 는
|
|
10
|
-
* 이 package 보다 **위**에 있다.
|
|
7
|
+
* `ox-input-background-pattern` needs to pick an image. It used to import the selector from
|
|
8
|
+
* `@operato/attachment` directly, but that package sits above this one:
|
|
11
9
|
*
|
|
12
10
|
* input ──▶ attachment ──▶ data-grist ──▶ input
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* That cycle did not merely offend layering — it stopped `@operato/input` from building at all.
|
|
13
|
+
* tsc pulled this package's own `dist/src/*.d.ts` back into the program and failed with TS5055 on
|
|
14
|
+
* seven files, and `noEmitOnError` meant nothing was written. `@operato/attachment` was not even
|
|
15
|
+
* listed in this package's dependencies.
|
|
17
16
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* 가장 아래의 부품이 위의 기능을 안다.
|
|
17
|
+
* Two of the three arrows are right: attachment shows a list as a grid so it uses data-grist, and
|
|
18
|
+
* data-grist puts inputs in filters and editors so it uses input. Only `input ──▶ attachment` runs
|
|
19
|
+
* the wrong way — the bottom layer reaching for a feature above it.
|
|
22
20
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* (@operato/attachment)이 스스로 등록한다. 그러면 화살표가 attachment ─▶ input 하나로 정리되고,
|
|
26
|
-
* 그것은 이미 선언되어 있는 방향이다.
|
|
21
|
+
* So the arrow is reversed. `input` declares the slot; whoever actually owns images registers into
|
|
22
|
+
* it. The only remaining edge is `attachment ──▶ input`, which is already declared.
|
|
27
23
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* 등록하지 않은 앱에서 아무것도 없는 칸이 나오는 것(등록 안 된 custom element 는 소리 없이 빈
|
|
34
|
-
* 상자로 그려진다)이 가장 나쁜 결말이라, 그것만은 피한다.
|
|
24
|
+
* With nothing registered the field is a text box, not an empty gap. The attachment selector is
|
|
25
|
+
* itself a text box plus a browse icon, and its value is a plain string (URL or attachment ref), so
|
|
26
|
+
* typing or pasting an address keeps working; only the browse button is missing. An unregistered
|
|
27
|
+
* custom element renders as a silent empty box, which is the worst outcome available here.
|
|
35
28
|
*/
|
|
36
29
|
let tagName = '';
|
|
37
30
|
const listeners = new Set();
|
|
38
31
|
/**
|
|
39
|
-
*
|
|
32
|
+
* Claim the image-picking field with a tag name.
|
|
40
33
|
*
|
|
41
|
-
* `@operato/attachment/ox-attachment-selector.js`
|
|
42
|
-
*
|
|
34
|
+
* `@operato/attachment/ox-attachment-selector.js` calls this when it loads. An app can override it
|
|
35
|
+
* the same way.
|
|
43
36
|
*/
|
|
44
37
|
export function registerImageSelector(tag) {
|
|
45
38
|
if (tagName === tag) {
|
|
46
39
|
return;
|
|
47
40
|
}
|
|
48
41
|
tagName = tag;
|
|
49
|
-
/*
|
|
42
|
+
/* Fields already on screen have to swap — registration can arrive after they rendered. */
|
|
50
43
|
listeners.forEach(listener => listener());
|
|
51
44
|
}
|
|
52
|
-
/**
|
|
45
|
+
/** The registered tag name, or '' when nothing has claimed the slot. */
|
|
53
46
|
export function imageSelectorTag() {
|
|
54
47
|
return tagName;
|
|
55
48
|
}
|
|
56
|
-
/**
|
|
49
|
+
/** Notifies on registration change. Call the returned function to stop listening. */
|
|
57
50
|
export function onImageSelectorChange(listener) {
|
|
58
51
|
listeners.add(listener);
|
|
59
52
|
return () => listeners.delete(listener);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-selector.js","sourceRoot":"","sources":["../../src/image-selector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH
|
|
1
|
+
{"version":3,"file":"image-selector.js","sourceRoot":"","sources":["../../src/image-selector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,IAAI,OAAO,GAAG,EAAE,CAAA;AAEhB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAA;AAEvC;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACpB,OAAM;IACR,CAAC;IAED,OAAO,GAAG,GAAG,CAAA;IAEb,0FAA0F;IAC1F,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAA;AAC3C,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,qBAAqB,CAAC,QAAoB;IACxD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAEvB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;AACzC,CAAC","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\n/**\n * The image-picking field: a slot this package declares, filled in from above.\n *\n * `ox-input-background-pattern` needs to pick an image. It used to import the selector from\n * `@operato/attachment` directly, but that package sits above this one:\n *\n * input ──▶ attachment ──▶ data-grist ──▶ input\n *\n * That cycle did not merely offend layering — it stopped `@operato/input` from building at all.\n * tsc pulled this package's own `dist/src/*.d.ts` back into the program and failed with TS5055 on\n * seven files, and `noEmitOnError` meant nothing was written. `@operato/attachment` was not even\n * listed in this package's dependencies.\n *\n * Two of the three arrows are right: attachment shows a list as a grid so it uses data-grist, and\n * data-grist puts inputs in filters and editors so it uses input. Only `input ──▶ attachment` runs\n * the wrong way — the bottom layer reaching for a feature above it.\n *\n * So the arrow is reversed. `input` declares the slot; whoever actually owns images registers into\n * it. The only remaining edge is `attachment ──▶ input`, which is already declared.\n *\n * With nothing registered the field is a text box, not an empty gap. The attachment selector is\n * itself a text box plus a browse icon, and its value is a plain string (URL or attachment ref), so\n * typing or pasting an address keeps working; only the browse button is missing. An unregistered\n * custom element renders as a silent empty box, which is the worst outcome available here.\n */\n\nlet tagName = ''\n\nconst listeners = new Set<() => void>()\n\n/**\n * Claim the image-picking field with a tag name.\n *\n * `@operato/attachment/ox-attachment-selector.js` calls this when it loads. An app can override it\n * the same way.\n */\nexport function registerImageSelector(tag: string) {\n if (tagName === tag) {\n return\n }\n\n tagName = tag\n\n /* Fields already on screen have to swap — registration can arrive after they rendered. */\n listeners.forEach(listener => listener())\n}\n\n/** The registered tag name, or '' when nothing has claimed the slot. */\nexport function imageSelectorTag(): string {\n return tagName\n}\n\n/** Notifies on registration change. Call the returned function to stop listening. */\nexport function onImageSelectorChange(listener: () => void): () => void {\n listeners.add(listener)\n\n return () => listeners.delete(listener)\n}\n"]}
|
|
@@ -31,14 +31,14 @@ export declare class OxInputBackgroundPattern extends OxFormField {
|
|
|
31
31
|
value?: BackgroundPatternOption;
|
|
32
32
|
render(): import("lit-html").TemplateResult;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
34
|
+
* The image-picking field.
|
|
35
35
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* If a package that owns images has registered its own field, that is used — see the header of
|
|
37
|
+
* image-selector.ts. Otherwise a text box: typing or pasting an address still works, and the only
|
|
38
|
+
* thing missing is the browse button.
|
|
39
39
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* Both branches carry `value-key="image"` and raise `change`. _onChange below handles every field
|
|
41
|
+
* by that one rule, so the value takes the same path out either way.
|
|
42
42
|
*/
|
|
43
43
|
private renderImageField;
|
|
44
44
|
private unsubscribeImageSelector?;
|
|
@@ -82,14 +82,14 @@ let OxInputBackgroundPattern = class OxInputBackgroundPattern extends OxFormFiel
|
|
|
82
82
|
`;
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
|
-
*
|
|
85
|
+
* The image-picking field.
|
|
86
86
|
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
87
|
+
* If a package that owns images has registered its own field, that is used — see the header of
|
|
88
|
+
* image-selector.ts. Otherwise a text box: typing or pasting an address still works, and the only
|
|
89
|
+
* thing missing is the browse button.
|
|
90
90
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
91
|
+
* Both branches carry `value-key="image"` and raise `change`. _onChange below handles every field
|
|
92
|
+
* by that one rule, so the value takes the same path out either way.
|
|
93
93
|
*/
|
|
94
94
|
renderImageField(value) {
|
|
95
95
|
const tag = imageSelectorTag();
|
|
@@ -116,7 +116,7 @@ let OxInputBackgroundPattern = class OxInputBackgroundPattern extends OxFormFiel
|
|
|
116
116
|
}
|
|
117
117
|
connectedCallback() {
|
|
118
118
|
super.connectedCallback();
|
|
119
|
-
/*
|
|
119
|
+
/* Registration can arrive after this element renders; re-render so the field swaps. */
|
|
120
120
|
this.unsubscribeImageSelector = onImageSelectorChange(() => this.requestUpdate());
|
|
121
121
|
}
|
|
122
122
|
disconnectedCallback() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-input-background-pattern.js","sourceRoot":"","sources":["../../src/ox-input-background-pattern.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,4BAA4B,CAAA;AACnC,OAAO,0BAA0B,CAAA;AACjC,OAAO,qBAAqB,CAAA;AAE5B,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AACzB,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAE5E,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAe7E;;;;;;;;GAQG;AAGI,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,WAAW;IAAlD;;QAUuB,UAAK,GAA6B,SAAS,CAAA;IA6HzE,CAAC;aAtIQ,WAAM,GAAG;QACd,kBAAkB;QAClB,GAAG,CAAA;;;;KAIF;KACF,AAPY,CAOZ;IAID,MAAM;QACJ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAK,EAA8B,CAAA;QAE3D,OAAO,IAAI,CAAA;;;;UAIL,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;;;;2CAIK,KAAK,CAAC,KAAK,IAAI,UAAU;;;;;;;;;;;;;0DAaV,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;;;0DAG1B,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;;;wDAG5B,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;;;yDAGvB,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;;;yEAGT,KAAK,CAAC,KAAK;;iFAEH,KAAK,CAAC,UAAU;;;6EAGpB,KAAK,CAAC,QAAQ;;;+EAGZ,KAAK,CAAC,SAAS;;;KAGzF,CAAA;IACH,CAAC;IAED;;;;;;;;;OASG;IACK,gBAAgB,CAAC,KAA8B;QACrD,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAA;QAE9B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,IAAI,CAAA;;;;;mBAKE,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;;;OAGrC,CAAA;QACH,CAAC;QAED,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;QAElC,OAAO,IAAI,CAAA;SACN,QAAQ;;iBAEA,KAAK,CAAC,KAAK,IAAI,EAAE;sBACZ,EAAE,QAAQ,EAAE,OAAO,EAAE;;WAEhC,QAAQ;KACd,CAAA;IACH,CAAC;IAID,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEzB,
|
|
1
|
+
{"version":3,"file":"ox-input-background-pattern.js","sourceRoot":"","sources":["../../src/ox-input-background-pattern.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 '@operato/i18n/ox-i18n.js'\nimport './ox-input-color.js'\n\nimport { css } from 'lit'\nimport { html, unsafeStatic } from 'lit/static-html.js'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\n\nimport { OxFormField } from './ox-form-field.js'\nimport { imageSelectorTag, onImageSelectorChange } from './image-selector.js'\n\nexport type BackgroundPatternOption = {\n image?: HTMLImageElement | string\n color?: string\n align?: 'left-top' | 'top' | 'right-top' | 'left' | 'center' | 'right' | 'left-bottom' | 'bottom' | 'right-bottom'\n offsetX?: number\n offsetY?: number\n width?: number\n height?: number\n fitPattern?: boolean\n noRepeat?: boolean\n guideOnly?: boolean\n}\n\n/**\n * 컴포넌트의 fill pattern을 편집하는 element\n *\n * Example:\n * <ox-input-background-pattern\n * @change=\"${e => { this.pattern = e.target.value }}\"\n * .value=${this.pattern}\"\n * ></ox-input-background-pattern>\n */\n\n@customElement('ox-input-background-pattern')\nexport class OxInputBackgroundPattern extends OxFormField {\n static styles = [\n PropertyGridStyles,\n css`\n :host {\n display: flex;\n }\n `\n ]\n\n @property({ type: Object }) value?: BackgroundPatternOption = undefined\n\n render() {\n const value = this.value || ({} as BackgroundPatternOption)\n\n return html`\n <div class=\"property-grid\">\n <label> <ox-i18n msgid=\"label.image\">image</ox-i18n> </label>\n\n ${this.renderImageField(value)}\n\n <label> <ox-i18n msgid=\"label.align\">align</ox-i18n> </label>\n\n <select value-key=\"align\" .value=${value.align || 'left-top'}>\n <option value=\"left-top\">Left Top</option>\n <option value=\"top\">Center Top</option>\n <option value=\"right-top\">Right Top</option>\n <option value=\"left\">Left Center</option>\n <option value=\"center\">Center Center</option>\n <option value=\"right\">Right Center</option>\n <option value=\"left-bottom\">Left Bottom</option>\n <option value=\"bottom\">Center Bottom</option>\n <option value=\"right-bottom\">Right Bottom</option>\n </select>\n\n <label> <ox-i18n msgid=\"label.offset-x\">offsetX</ox-i18n> </label>\n <input type=\"number\" value-key=\"offsetX\" .value=${String(value.offsetX || 0)} />\n\n <label> <ox-i18n msgid=\"label.offset-y\">offsetY</ox-i18n> </label>\n <input type=\"number\" value-key=\"offsetY\" .value=${String(value.offsetY || 0)} />\n\n <label> <ox-i18n msgid=\"label.width\">width</ox-i18n> </label>\n <input type=\"number\" value-key=\"width\" .value=${String(value.width || 0)} />\n\n <label> <ox-i18n msgid=\"label.height\">height</ox-i18n> </label>\n <input type=\"number\" value-key=\"height\" .value=${String(value.height || 0)} />\n\n <label><md-icon>format_color_fill</md-icon></label>\n <ox-input-color class=\"custom-editor\" value-key=\"color\" .value=${value.color}> </ox-input-color>\n\n <input id=\"fitPattern\" value-key=\"fitPattern\" type=\"checkbox\" ?checked=${value.fitPattern} required />\n <label for=\"fitPattern\"> <ox-i18n msgid=\"label.fit\">fit</ox-i18n> </label>\n\n <input id=\"noRepeat\" value-key=\"noRepeat\" type=\"checkbox\" ?checked=${value.noRepeat} required />\n <label for=\"noRepeat\"> <ox-i18n msgid=\"label.no-repeat\">no repeat</ox-i18n> </label>\n\n <input id=\"guideOnly\" value-key=\"guideOnly\" type=\"checkbox\" ?checked=${value.guideOnly} required />\n <label for=\"guideOnly\"> <ox-i18n msgid=\"label.guide-only\">guide only</ox-i18n> </label>\n </div>\n `\n }\n\n /**\n * The image-picking field.\n *\n * If a package that owns images has registered its own field, that is used — see the header of\n * image-selector.ts. Otherwise a text box: typing or pasting an address still works, and the only\n * thing missing is the browse button.\n *\n * Both branches carry `value-key=\"image\"` and raise `change`. _onChange below handles every field\n * by that one rule, so the value takes the same path out either way.\n */\n private renderImageField(value: BackgroundPatternOption) {\n const tag = imageSelectorTag()\n\n if (!tag) {\n return html`\n <input\n type=\"text\"\n value-key=\"image\"\n class=\"custom-editor\"\n .value=${String(value.image || '')}\n placeholder=\"https://\"\n />\n `\n }\n\n const selector = unsafeStatic(tag)\n\n return html`\n <${selector}\n value-key=\"image\"\n .value=${value.image || ''}\n .properties=${{ category: 'image' }}\n class=\"custom-editor\"\n ></${selector}>\n `\n }\n\n private unsubscribeImageSelector?: () => void\n\n connectedCallback() {\n super.connectedCallback()\n\n /* Registration can arrive after this element renders; re-render so the field swaps. */\n this.unsubscribeImageSelector = onImageSelectorChange(() => this.requestUpdate())\n }\n\n disconnectedCallback() {\n this.unsubscribeImageSelector?.()\n this.unsubscribeImageSelector = undefined\n\n super.disconnectedCallback()\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', this._onChange.bind(this))\n }\n\n _onChange(e: Event) {\n var element = e.target as HTMLInputElement\n var key = element.getAttribute('value-key')\n var value: any = element.value\n\n if (key === 'fitPattern' || key === 'noRepeat' || key === 'guideOnly') {\n value = element.checked\n }\n\n this.value = {\n ...this.value,\n [key!]: value\n }\n\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))\n }\n}\n"]}
|
|
@@ -9,14 +9,14 @@ import '@operato/i18n/ox-i18n.js';
|
|
|
9
9
|
import { css, html } from 'lit';
|
|
10
10
|
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
11
11
|
/*
|
|
12
|
-
*
|
|
12
|
+
* This file lives inside @operato/input, so it must not import the package by name.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* (ox-checkbox
|
|
14
|
+
* It used to import from '@operato/input'. That follows package.json exports back into this
|
|
15
|
+
* package's own dist, pulling the already-built dist/src/*.d.ts into the compilation. tsc cannot
|
|
16
|
+
* write over a file it is reading, so it stops with TS5055 — and with noEmitOnError the package
|
|
17
|
+
* does not build at all (seven files: ox-checkbox, ox-form-field, ox-input-search and others).
|
|
18
18
|
*
|
|
19
|
-
*
|
|
19
|
+
* Within the same package, import by relative path.
|
|
20
20
|
*/
|
|
21
21
|
import { OxFormField } from './ox-form-field.js';
|
|
22
22
|
import { InputStyles } from './input-styles.js';
|
|
@@ -1 +1 @@
|
|
|
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"]}
|
|
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\n/*\n * This file lives inside @operato/input, so it must not import the package by name.\n *\n * It used to import from '@operato/input'. That follows package.json exports back into this\n * package's own dist, pulling the already-built dist/src/*.d.ts into the compilation. tsc cannot\n * write over a file it is reading, so it stops with TS5055 — and with noEmitOnError the package\n * does not build at all (seven files: ox-checkbox, ox-form-field, ox-input-search and others).\n *\n * Within the same package, import by relative path.\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"]}
|
|
@@ -61,17 +61,17 @@ let OxInputSearch = class OxInputSearch extends OxFormField {
|
|
|
61
61
|
render() {
|
|
62
62
|
return html `
|
|
63
63
|
<!--
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
The magnifier runs the search on click, but md-icon takes no focus, so the keyboard never
|
|
65
|
+
reaches it. Enter in the input does the same thing, so no function is blocked. Hiding it
|
|
66
|
+
from assistive tech removes one more unnamed click target and costs nothing.
|
|
67
67
|
-->
|
|
68
68
|
<md-icon aria-hidden="true" @click=${(e) => !this.disabled && this._onClickSearch(e)}>search</md-icon>
|
|
69
69
|
<!--
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
Name the input. It had only a placeholder, and a placeholder is not a name: it disappears
|
|
71
|
+
the moment you type, so there is no way to ask again what you were entering, and when the
|
|
72
|
+
caller passes none — which most screens do — nothing is left.
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
Use whatever the caller set, and fall back to "search".
|
|
75
75
|
-->
|
|
76
76
|
<input
|
|
77
77
|
type="text"
|