@fmsim/board 2.0.0-beta.86 → 2.0.0-beta.89

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.
@@ -189,9 +189,10 @@ export const etc = {
189
189
  width: 500,
190
190
  height: 500,
191
191
  depth: 2,
192
- fillStyle: '#e8e8e8',
192
+ fillStyle: 'rgba(232, 232, 232, 0.7)',
193
193
  strokeStyle: '#999999',
194
- alpha: 0.7
194
+ // fmsim 기본 바닥 재질 = rubber 매트 (things-scene 글로벌 기본은 그대로).
195
+ material3d: { preset: 'rubber' }
195
196
  }
196
197
  }
197
198
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"etc.js","sourceRoot":"","sources":["../../../src/component/etc.ts"],"names":[],"mappings":"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","sourcesContent":["import { ComponentGroup } from '../types'\n\nconst text = new URL('../../../icons/components/text.png', import.meta.url).href\nconst rect = new URL('../../../icons/components/rect.png', import.meta.url).href\nconst ellipse = new URL('../../../icons/components/ellipse.png', import.meta.url).href\nconst lineIcon = new URL('../../../icons/components/line.png', import.meta.url).href\nconst dash = new URL('../../../icons/components/dash.png', import.meta.url).href\nconst triangle = new URL('../../../icons/components/triangle.png', import.meta.url).href\nconst container = new URL('../../../icons/components/container.png', import.meta.url).href\nconst popup = new URL('../../../icons/components/popup.png', import.meta.url).href\n\nconst icon = `\n<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 30 30\" style=\"enable-background:new 0 0 30 30;\" xml:space=\"preserve\">\n <style type=\"text/css\">\n .st0{fill:{{strokeColor}};}\n </style>\n <g>\n <circle class=\"st0\" cx=\"7.1\" cy=\"15\" r=\"2\"/>\n <circle class=\"st0\" cx=\"15\" cy=\"15\" r=\"2\"/>\n <circle class=\"st0\" cx=\"22.9\" cy=\"15\" r=\"2\"/>\n </g>\n</svg>\n`\n\nexport const etc: ComponentGroup = {\n name: 'etc',\n description: 'a group of components that have not yet been defined.',\n icon,\n templates: [\n {\n type: 'text',\n description: 'text',\n icon: text,\n group: 'shape',\n model: {\n type: 'text',\n left: 100,\n top: 100,\n width: 200,\n height: 50,\n fillStyle: 'transparent',\n fontColor: '#000',\n fontSize: 16,\n text: 'Text'\n }\n },\n {\n type: 'rect',\n description: 'rectangle shape',\n icon: rect,\n group: 'shape',\n model: {\n type: 'rect',\n left: 100,\n top: 100,\n width: 100,\n height: 100,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 1,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'ellipse',\n description: 'ellipse shape',\n icon: ellipse,\n group: 'shape',\n model: {\n type: 'ellipse',\n rx: 50,\n ry: 50,\n cx: 150,\n cy: 150,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 1,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'triangle',\n description: 'triangle shape',\n icon: triangle,\n group: 'shape',\n model: {\n type: 'triangle',\n x1: 150,\n y1: 100,\n x2: 100,\n y2: 200,\n x3: 200,\n y3: 200,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 1,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'line',\n description: 'simple line',\n icon: lineIcon,\n group: 'line',\n model: {\n type: 'line',\n x1: 100,\n y1: 100,\n x2: 200,\n y2: 200,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 3,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'dash',\n description: 'dash line',\n icon: dash,\n group: 'line',\n model: {\n type: 'line',\n x1: 100,\n y1: 100,\n x2: 200,\n y2: 200,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 3,\n lineDash: 'round-dot',\n lineCap: 'butt'\n }\n },\n {\n type: 'container',\n description: 'container shape',\n icon: container,\n group: 'container',\n model: {\n type: 'container',\n left: 100,\n top: 100,\n width: 400,\n height: 300,\n fillStyle: '#fff',\n strokeStyle: '#999',\n alpha: 1,\n hidden: false,\n lineWidth: 1,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'popup',\n description: 'popup window',\n icon: popup,\n group: 'container',\n model: {\n type: 'popup',\n left: 100,\n top: 100,\n width: 100,\n height: 100,\n fillStyle: '#fff',\n strokeStyle: 'DarkGoldenRod'\n }\n },\n {\n type: 'floor-plate',\n description: 'floor plate for multi-story layout',\n icon: rect,\n group: '3d',\n model: {\n type: 'floor-plate',\n left: 100,\n top: 100,\n width: 500,\n height: 500,\n depth: 2,\n fillStyle: '#e8e8e8',\n strokeStyle: '#999999',\n alpha: 0.7\n }\n }\n ]\n}\n"]}
1
+ {"version":3,"file":"etc.js","sourceRoot":"","sources":["../../../src/component/etc.ts"],"names":[],"mappings":"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","sourcesContent":["import { ComponentGroup } from '../types'\n\nconst text = new URL('../../../icons/components/text.png', import.meta.url).href\nconst rect = new URL('../../../icons/components/rect.png', import.meta.url).href\nconst ellipse = new URL('../../../icons/components/ellipse.png', import.meta.url).href\nconst lineIcon = new URL('../../../icons/components/line.png', import.meta.url).href\nconst dash = new URL('../../../icons/components/dash.png', import.meta.url).href\nconst triangle = new URL('../../../icons/components/triangle.png', import.meta.url).href\nconst container = new URL('../../../icons/components/container.png', import.meta.url).href\nconst popup = new URL('../../../icons/components/popup.png', import.meta.url).href\n\nconst icon = `\n<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\" viewBox=\"0 0 30 30\" style=\"enable-background:new 0 0 30 30;\" xml:space=\"preserve\">\n <style type=\"text/css\">\n .st0{fill:{{strokeColor}};}\n </style>\n <g>\n <circle class=\"st0\" cx=\"7.1\" cy=\"15\" r=\"2\"/>\n <circle class=\"st0\" cx=\"15\" cy=\"15\" r=\"2\"/>\n <circle class=\"st0\" cx=\"22.9\" cy=\"15\" r=\"2\"/>\n </g>\n</svg>\n`\n\nexport const etc: ComponentGroup = {\n name: 'etc',\n description: 'a group of components that have not yet been defined.',\n icon,\n templates: [\n {\n type: 'text',\n description: 'text',\n icon: text,\n group: 'shape',\n model: {\n type: 'text',\n left: 100,\n top: 100,\n width: 200,\n height: 50,\n fillStyle: 'transparent',\n fontColor: '#000',\n fontSize: 16,\n text: 'Text'\n }\n },\n {\n type: 'rect',\n description: 'rectangle shape',\n icon: rect,\n group: 'shape',\n model: {\n type: 'rect',\n left: 100,\n top: 100,\n width: 100,\n height: 100,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 1,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'ellipse',\n description: 'ellipse shape',\n icon: ellipse,\n group: 'shape',\n model: {\n type: 'ellipse',\n rx: 50,\n ry: 50,\n cx: 150,\n cy: 150,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 1,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'triangle',\n description: 'triangle shape',\n icon: triangle,\n group: 'shape',\n model: {\n type: 'triangle',\n x1: 150,\n y1: 100,\n x2: 100,\n y2: 200,\n x3: 200,\n y3: 200,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 1,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'line',\n description: 'simple line',\n icon: lineIcon,\n group: 'line',\n model: {\n type: 'line',\n x1: 100,\n y1: 100,\n x2: 200,\n y2: 200,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 3,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'dash',\n description: 'dash line',\n icon: dash,\n group: 'line',\n model: {\n type: 'line',\n x1: 100,\n y1: 100,\n x2: 200,\n y2: 200,\n fillStyle: '#fff',\n strokeStyle: '#000',\n alpha: 1,\n hidden: false,\n lineWidth: 3,\n lineDash: 'round-dot',\n lineCap: 'butt'\n }\n },\n {\n type: 'container',\n description: 'container shape',\n icon: container,\n group: 'container',\n model: {\n type: 'container',\n left: 100,\n top: 100,\n width: 400,\n height: 300,\n fillStyle: '#fff',\n strokeStyle: '#999',\n alpha: 1,\n hidden: false,\n lineWidth: 1,\n lineDash: 'solid',\n lineCap: 'butt'\n }\n },\n {\n type: 'popup',\n description: 'popup window',\n icon: popup,\n group: 'container',\n model: {\n type: 'popup',\n left: 100,\n top: 100,\n width: 100,\n height: 100,\n fillStyle: '#fff',\n strokeStyle: 'DarkGoldenRod'\n }\n },\n {\n type: 'floor-plate',\n description: 'floor plate for multi-story layout',\n icon: rect,\n group: '3d',\n model: {\n type: 'floor-plate',\n left: 100,\n top: 100,\n width: 500,\n height: 500,\n depth: 2,\n fillStyle: 'rgba(232, 232, 232, 0.7)',\n strokeStyle: '#999999',\n // fmsim 기본 바닥 재질 = rubber 매트 (things-scene 글로벌 기본은 그대로).\n material3d: { preset: 'rubber' }\n }\n }\n ]\n}\n"]}
@@ -18,5 +18,14 @@ export declare class PropertyEffects extends PropertyEffects_base {
18
18
  'property-event': typeof PropertyEvent;
19
19
  };
20
20
  render(): import("lit-html").TemplateResult<1>;
21
+ /**
22
+ * 3D 그림자 토글 — material3d.castShadow / receiveShadow 만 갱신.
23
+ *
24
+ * material3d 는 단일 객체 속성이므로 기존 material3d 전체를 보존한 채 해당
25
+ * 키만 덮어써 dispatch 한다 ({ castShadow } 만 보내면 set() 의 top-level shallow
26
+ * merge 로 material3d 전체가 사라짐). value-key 를 두지 않아 AbstractProperty
27
+ * 의 제너릭 change 핸들러는 이 입력을 무시한다.
28
+ */
29
+ private _onShadow3dChange;
21
30
  }
22
31
  export {};
@@ -25,7 +25,15 @@ export class PropertyEffects extends ScopedElementsMixin(AbstractProperty) {
25
25
  };
26
26
  }
27
27
  render() {
28
+ var _a, _b, _c;
28
29
  const value = this.value || {};
30
+ // 3D 그림자 편집은 단일 선택 + 3D 표현 가능한 컴포넌트에서만 노출.
31
+ // (material3d 는 컴포넌트별 객체라 다중 선택 일괄 병합은 위험 — 단일로 제한.)
32
+ const target = this.selected.length == 1 ? this.selected[0] : null;
33
+ const is3d = !!((_a = target === null || target === void 0 ? void 0 : target.is3dish) === null || _a === void 0 ? void 0 : _a.call(target));
34
+ const material3d = value.material3d || {};
35
+ const castShadow = (_b = material3d.castShadow) !== null && _b !== void 0 ? _b : true;
36
+ const receiveShadow = (_c = material3d.receiveShadow) !== null && _c !== void 0 ? _c : false;
29
37
  return html `
30
38
  <fieldset>
31
39
  <legend>
@@ -35,6 +43,38 @@ export class PropertyEffects extends ScopedElementsMixin(AbstractProperty) {
35
43
  <property-shadow value-key="shadow" .value=${value.shadow || {}}> </property-shadow>
36
44
  </fieldset>
37
45
 
46
+ ${is3d
47
+ ? html `
48
+ <fieldset>
49
+ <legend>
50
+ <ox-i18n topic="board-modeller/effects/shadow-3d" msgid="label.shadow-3d">3D shadow</ox-i18n>
51
+ </legend>
52
+
53
+ <div>
54
+ <input
55
+ id="cb-cast-shadow"
56
+ type="checkbox"
57
+ .checked=${castShadow}
58
+ @change=${(e) => this._onShadow3dChange('castShadow', e)}
59
+ />
60
+ <label for="cb-cast-shadow">
61
+ <ox-i18n msgid="label.cast-shadow">cast shadow</ox-i18n>
62
+ </label>
63
+
64
+ <input
65
+ id="cb-receive-shadow"
66
+ type="checkbox"
67
+ .checked=${receiveShadow}
68
+ @change=${(e) => this._onShadow3dChange('receiveShadow', e)}
69
+ />
70
+ <label for="cb-receive-shadow">
71
+ <ox-i18n msgid="label.receive-shadow">receive shadow</ox-i18n>
72
+ </label>
73
+ </div>
74
+ </fieldset>
75
+ `
76
+ : nothing}
77
+
38
78
  ${this.selected.length == 1
39
79
  ? html `
40
80
  <property-event
@@ -47,6 +87,24 @@ export class PropertyEffects extends ScopedElementsMixin(AbstractProperty) {
47
87
  : nothing}
48
88
  `;
49
89
  }
90
+ /**
91
+ * 3D 그림자 토글 — material3d.castShadow / receiveShadow 만 갱신.
92
+ *
93
+ * material3d 는 단일 객체 속성이므로 기존 material3d 전체를 보존한 채 해당
94
+ * 키만 덮어써 dispatch 한다 ({ castShadow } 만 보내면 set() 의 top-level shallow
95
+ * merge 로 material3d 전체가 사라짐). value-key 를 두지 않아 AbstractProperty
96
+ * 의 제너릭 change 핸들러는 이 입력을 무시한다.
97
+ */
98
+ _onShadow3dChange(key, e) {
99
+ var _a;
100
+ const checked = e.target.checked;
101
+ const current = ((_a = this.value) === null || _a === void 0 ? void 0 : _a.material3d) || {};
102
+ this.dispatchEvent(new CustomEvent('property-change', {
103
+ bubbles: true,
104
+ composed: true,
105
+ detail: { material3d: { ...current, [key]: checked } }
106
+ }));
107
+ }
50
108
  }
51
109
  PropertyEffects.styles = [PropertySharedStyle];
52
110
  __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"effects.js","sourceRoot":"","sources":["../../../../../src/modeller/property-sidebar/effects/effects.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,0BAA0B,CAAA;AAEjC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAG5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,MAAM,OAAO,eAAgB,SAAQ,mBAAmB,CAAC,gBAAgB,CAAC;IAA1E;;QAK6B,aAAQ,GAAgB,EAAE,CAAA;IAqCvD,CAAC;IAnCC,YAAY;QACV,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5E,CAAC;IAED,MAAM,KAAK,cAAc;QACvB,OAAO;YACL,iBAAiB,EAAE,cAAc;YACjC,gBAAgB,EAAE,aAAa;SAChC,CAAA;IACH,CAAC;IAED,MAAM;QACJ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;QAE9B,OAAO,IAAI,CAAA;;;;;;qDAMsC,KAAK,CAAC,MAAM,IAAI,EAAE;;;QAG/D,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC;YACzB,CAAC,CAAC,IAAI,CAAA;;;uBAGS,IAAI,CAAC,KAAK;uBACV,KAAK,CAAC,aAAa,IAAI,EAAE;;;WAGrC;YACH,CAAC,CAAC,OAAO;KACZ,CAAA;IACH,CAAC;;AAxCM,sBAAM,GAAG,CAAC,mBAAmB,CAAC,AAAxB,CAAwB;AAET;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAAmB;AAClB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAAc;AACd;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;iDAA2B","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@operato/i18n/ox-i18n.js'\n\nimport { html, nothing } from 'lit'\nimport { property } from 'lit/decorators.js'\n\nimport { Component, Properties, Scene } from '@hatiolab/things-scene'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\n\nimport { AbstractProperty } from '../abstract-property.js'\nimport { PropertySharedStyle } from '../property-shared-style.js'\nimport { PropertyEvent } from './property-event.js'\nimport { PropertyShadow } from './property-shadow.js'\n\nexport class PropertyEffects extends ScopedElementsMixin(AbstractProperty) {\n static styles = [PropertySharedStyle]\n\n @property({ type: Object }) value?: Properties\n @property({ type: Object }) scene?: Scene\n @property({ type: Array }) selected: Component[] = []\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', this._onValueChange.bind(this))\n }\n\n static get scopedElements() {\n return {\n 'property-shadow': PropertyShadow,\n 'property-event': PropertyEvent\n }\n }\n\n render() {\n const value = this.value || {}\n\n return html`\n <fieldset>\n <legend>\n <ox-i18n topic=\"board-modeller/effects/shadow\" msgid=\"label.shadow\">shadow</ox-i18n>\n </legend>\n\n <property-shadow value-key=\"shadow\" .value=${value.shadow || {}}> </property-shadow>\n </fieldset>\n\n ${this.selected.length == 1\n ? html`\n <property-event\n value-key=\"eventHandlers\"\n .scene=${this.scene}\n .value=${value.eventHandlers || []}\n >\n </property-event>\n `\n : nothing}\n `\n }\n}\n"]}
1
+ {"version":3,"file":"effects.js","sourceRoot":"","sources":["../../../../../src/modeller/property-sidebar/effects/effects.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@operato/i18n/ox-i18n.js'\n\nimport { html, nothing } from 'lit'\nimport { property } from 'lit/decorators.js'\n\nimport { Component, Properties, Scene } from '@hatiolab/things-scene'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\n\nimport { AbstractProperty } from '../abstract-property.js'\nimport { PropertySharedStyle } from '../property-shared-style.js'\nimport { PropertyEvent } from './property-event.js'\nimport { PropertyShadow } from './property-shadow.js'\n\nexport class PropertyEffects extends ScopedElementsMixin(AbstractProperty) {\n static styles = [PropertySharedStyle]\n\n @property({ type: Object }) value?: Properties\n @property({ type: Object }) scene?: Scene\n @property({ type: Array }) selected: Component[] = []\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', this._onValueChange.bind(this))\n }\n\n static get scopedElements() {\n return {\n 'property-shadow': PropertyShadow,\n 'property-event': PropertyEvent\n }\n }\n\n render() {\n const value = this.value || {}\n\n // 3D 그림자 편집은 단일 선택 + 3D 표현 가능한 컴포넌트에서만 노출.\n // (material3d 는 컴포넌트별 객체라 다중 선택 일괄 병합은 위험 — 단일로 제한.)\n const target = this.selected.length == 1 ? (this.selected[0] as any) : null\n const is3d = !!target?.is3dish?.()\n const material3d = (value.material3d as any) || {}\n const castShadow = material3d.castShadow ?? true\n const receiveShadow = material3d.receiveShadow ?? false\n\n return html`\n <fieldset>\n <legend>\n <ox-i18n topic=\"board-modeller/effects/shadow\" msgid=\"label.shadow\">shadow</ox-i18n>\n </legend>\n\n <property-shadow value-key=\"shadow\" .value=${value.shadow || {}}> </property-shadow>\n </fieldset>\n\n ${is3d\n ? html`\n <fieldset>\n <legend>\n <ox-i18n topic=\"board-modeller/effects/shadow-3d\" msgid=\"label.shadow-3d\">3D shadow</ox-i18n>\n </legend>\n\n <div>\n <input\n id=\"cb-cast-shadow\"\n type=\"checkbox\"\n .checked=${castShadow}\n @change=${(e: Event) => this._onShadow3dChange('castShadow', e)}\n />\n <label for=\"cb-cast-shadow\">\n <ox-i18n msgid=\"label.cast-shadow\">cast shadow</ox-i18n>\n </label>\n\n <input\n id=\"cb-receive-shadow\"\n type=\"checkbox\"\n .checked=${receiveShadow}\n @change=${(e: Event) => this._onShadow3dChange('receiveShadow', e)}\n />\n <label for=\"cb-receive-shadow\">\n <ox-i18n msgid=\"label.receive-shadow\">receive shadow</ox-i18n>\n </label>\n </div>\n </fieldset>\n `\n : nothing}\n\n ${this.selected.length == 1\n ? html`\n <property-event\n value-key=\"eventHandlers\"\n .scene=${this.scene}\n .value=${value.eventHandlers || []}\n >\n </property-event>\n `\n : nothing}\n `\n }\n\n /**\n * 3D 그림자 토글 — material3d.castShadow / receiveShadow 만 갱신.\n *\n * material3d 는 단일 객체 속성이므로 기존 material3d 전체를 보존한 채 해당\n * 키만 덮어써 dispatch 한다 ({ castShadow } 만 보내면 set() 의 top-level shallow\n * merge 로 material3d 전체가 사라짐). value-key 를 두지 않아 AbstractProperty\n * 의 제너릭 change 핸들러는 이 입력을 무시한다.\n */\n private _onShadow3dChange(key: 'castShadow' | 'receiveShadow', e: Event) {\n const checked = (e.target as HTMLInputElement).checked\n const current = (this.value?.material3d as any) || {}\n\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: { material3d: { ...current, [key]: checked } }\n })\n )\n }\n}\n"]}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import '@operato/i18n/ox-i18n.js';
5
+ import { LitElement, PropertyValues } from 'lit';
6
+ /**
7
+ * 컴포넌트 ID 입력기 — 자유 입력 + 타입별 백엔드(MCS) 검색 선택을 함께 제공.
8
+ *
9
+ * - 기존처럼 자유롭게 텍스트로 ID 를 입력할 수 있다 (commit = blur/Enter).
10
+ * - input 에 *포커스가 가면* 아래로 검색 드롭다운이 펼쳐진다. `entityType`
11
+ * (컴포넌트 타입) 으로 MCS 에 정의된 ID 후보를 조회한다.
12
+ * - machine 타입 → 머신 id 가 1레벨 평면으로 (선택 가능)
13
+ * - unit 타입 → machine 이 그룹 헤더, 그 아래 unit id 가 자식 (선택 가능).
14
+ * 컴포넌트가 부모 machine 을 알면(`machine` prop) 그 머신으로 좁혀 조회.
15
+ *
16
+ * value-key="id" 와 함께 property-grid 안에 두면, 이 host 가 `change`(bubbles+
17
+ * composed) 를 발행하므로 AbstractProperty 제너릭 핸들러가 `element.value` 를
18
+ * 읽어 property-change 로 전파한다.
19
+ *
20
+ * 등록: 패널 자식 커스텀 엘리먼트 컨벤션에 따라 전역 `@customElement` 가 아니라
21
+ * 부모 패널(PropertyShapes)의 `scopedElements` 로 등록한다 (@open-wc/scoped-elements).
22
+ */
23
+ export declare class OxInputEntityId extends LitElement {
24
+ static styles: import("lit").CSSResult[];
25
+ /** 현재 ID 값. */
26
+ value: string;
27
+ /** 검색 조건 — 선택된 컴포넌트 타입 (예: 'STOCKER', 'AGV', 'Port'). */
28
+ entityType: string;
29
+ /** 검색 조건 — 부모 machine id (unit 컴포넌트가 소속 machine 을 알 때). */
30
+ machine: string;
31
+ /** machine 필수 타입(예: Port) — machine 없으면 조회하지 않는다 (후보 과다 방지). */
32
+ requireMachine: boolean;
33
+ /** 백엔드 조회 대신 사용할 로컬 후보 리스트 (예: parentObject — 씬의 머신들). null 이면 백엔드 조회. */
34
+ localItems: string[] | null;
35
+ placeholder: string;
36
+ private _open;
37
+ /** 서버에서 받은 전체 후보 리스트 (포커스 시 1회 조회, 키워드 미적용). */
38
+ private _all;
39
+ private _loading;
40
+ /** machine 필수인데 machine 미지정이라 조회를 보류한 상태. */
41
+ private _needMachine;
42
+ /** 선택 가능 항목 기준 active index. */
43
+ private _activeIndex;
44
+ private _input;
45
+ private _blurTimer?;
46
+ private _loadSeq;
47
+ /** 마지막으로 발행한 값 — 같은 값 재발행(undo 중복) 방지. */
48
+ private _lastEmitted?;
49
+ disconnectedCallback(): void;
50
+ updated(changed: PropertyValues): void;
51
+ /**
52
+ * 드롭다운 표시 항목 — 입력값(초기값 포함)으로 풀텍스트 로컬 필터.
53
+ * 단, 매치가 0이면 전체 후보로 fallback (막다른 "결과 없음" 방지 — 예: committed
54
+ * id 가 후보 형식과 달라 안 맞는 경우). 서버 재조회 없음.
55
+ */
56
+ private get _items();
57
+ /** 드롭다운에서 선택 가능한 id 들 (표시 순서). */
58
+ private get _selectableIds();
59
+ render(): import("lit-html").TemplateResult<1>;
60
+ private _renderDropdown;
61
+ private _onFocus;
62
+ private _onBlur;
63
+ private _onInput;
64
+ /** 자유 입력 commit (blur/Enter 의 native change) — 기존 free-text 동작 보존. */
65
+ private _onInputCommit;
66
+ private _onKeydown;
67
+ private _select;
68
+ private _commitValue;
69
+ private _emitChange;
70
+ /**
71
+ * 후보 전체를 1회 조회 (포커스 시). keyword 는 보내지 않으며, 표시 필터는 _items
72
+ * 게터가 로컬에서 처리한다. entityType(+unit 이면 machine) 만 서버로 보낸다.
73
+ */
74
+ private _load;
75
+ }
@@ -0,0 +1,346 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import { __decorate } from "tslib";
5
+ import '@operato/i18n/ox-i18n.js';
6
+ import { css, html, LitElement } from 'lit';
7
+ import { property, query, state } from 'lit/decorators.js';
8
+ import { ScrollbarStyles } from '@operato/styles';
9
+ import { searchMachineUnits, filterMachineUnitIds } from '@fmsim/api';
10
+ /**
11
+ * 컴포넌트 ID 입력기 — 자유 입력 + 타입별 백엔드(MCS) 검색 선택을 함께 제공.
12
+ *
13
+ * - 기존처럼 자유롭게 텍스트로 ID 를 입력할 수 있다 (commit = blur/Enter).
14
+ * - input 에 *포커스가 가면* 아래로 검색 드롭다운이 펼쳐진다. `entityType`
15
+ * (컴포넌트 타입) 으로 MCS 에 정의된 ID 후보를 조회한다.
16
+ * - machine 타입 → 머신 id 가 1레벨 평면으로 (선택 가능)
17
+ * - unit 타입 → machine 이 그룹 헤더, 그 아래 unit id 가 자식 (선택 가능).
18
+ * 컴포넌트가 부모 machine 을 알면(`machine` prop) 그 머신으로 좁혀 조회.
19
+ *
20
+ * value-key="id" 와 함께 property-grid 안에 두면, 이 host 가 `change`(bubbles+
21
+ * composed) 를 발행하므로 AbstractProperty 제너릭 핸들러가 `element.value` 를
22
+ * 읽어 property-change 로 전파한다.
23
+ *
24
+ * 등록: 패널 자식 커스텀 엘리먼트 컨벤션에 따라 전역 `@customElement` 가 아니라
25
+ * 부모 패널(PropertyShapes)의 `scopedElements` 로 등록한다 (@open-wc/scoped-elements).
26
+ */
27
+ export class OxInputEntityId extends LitElement {
28
+ constructor() {
29
+ super(...arguments);
30
+ /** 현재 ID 값. */
31
+ this.value = '';
32
+ /** 검색 조건 — 선택된 컴포넌트 타입 (예: 'STOCKER', 'AGV', 'Port'). */
33
+ this.entityType = '';
34
+ /** 검색 조건 — 부모 machine id (unit 컴포넌트가 소속 machine 을 알 때). */
35
+ this.machine = '';
36
+ /** machine 필수 타입(예: Port) — machine 없으면 조회하지 않는다 (후보 과다 방지). */
37
+ this.requireMachine = false;
38
+ /** 백엔드 조회 대신 사용할 로컬 후보 리스트 (예: parentObject — 씬의 머신들). null 이면 백엔드 조회. */
39
+ this.localItems = null;
40
+ this.placeholder = '';
41
+ this._open = false;
42
+ /** 서버에서 받은 전체 후보 리스트 (포커스 시 1회 조회, 키워드 미적용). */
43
+ this._all = [];
44
+ this._loading = false;
45
+ /** machine 필수인데 machine 미지정이라 조회를 보류한 상태. */
46
+ this._needMachine = false;
47
+ /** 선택 가능 항목 기준 active index. */
48
+ this._activeIndex = -1;
49
+ this._loadSeq = 0;
50
+ }
51
+ disconnectedCallback() {
52
+ super.disconnectedCallback();
53
+ clearTimeout(this._blurTimer);
54
+ }
55
+ updated(changed) {
56
+ // 열린 상태에서 조회 조건(타입/부모 머신)이 바뀌면 재조회 (예: 부모 머신을 방금 지정).
57
+ if (this._open && (changed.has('entityType') || changed.has('machine') || changed.has('localItems'))) {
58
+ this._load();
59
+ }
60
+ // 화살표 키로 active 항목 이동 시 항상 보이도록 드롭다운을 스크롤.
61
+ if (changed.has('_activeIndex') && this._open && this._activeIndex >= 0) {
62
+ const el = this.renderRoot.querySelector('.item.active');
63
+ el === null || el === void 0 ? void 0 : el.scrollIntoView({ block: 'nearest' });
64
+ }
65
+ }
66
+ /**
67
+ * 드롭다운 표시 항목 — 입력값(초기값 포함)으로 풀텍스트 로컬 필터.
68
+ * 단, 매치가 0이면 전체 후보로 fallback (막다른 "결과 없음" 방지 — 예: committed
69
+ * id 가 후보 형식과 달라 안 맞는 경우). 서버 재조회 없음.
70
+ */
71
+ get _items() {
72
+ if (!this._all.length)
73
+ return [];
74
+ const filtered = filterMachineUnitIds(this._all, this.value || '');
75
+ return filtered.length ? filtered : this._all;
76
+ }
77
+ /** 드롭다운에서 선택 가능한 id 들 (표시 순서). */
78
+ get _selectableIds() {
79
+ return this._items;
80
+ }
81
+ render() {
82
+ return html `
83
+ <input
84
+ .value=${this.value || ''}
85
+ placeholder=${this.placeholder}
86
+ autocomplete="off"
87
+ @focus=${this._onFocus}
88
+ @blur=${this._onBlur}
89
+ @input=${this._onInput}
90
+ @change=${this._onInputCommit}
91
+ @keydown=${this._onKeydown}
92
+ />
93
+ ${this._open ? this._renderDropdown() : ''}
94
+ `;
95
+ }
96
+ _renderDropdown() {
97
+ if (this._needMachine) {
98
+ return html `<div class="dropdown">
99
+ <div class="hint"><ox-i18n msgid="text.need-parent-machine">상위 머신을 먼저 지정하세요</ox-i18n></div>
100
+ </div>`;
101
+ }
102
+ if (this._loading) {
103
+ return html `<div class="dropdown"><div class="hint"><ox-i18n msgid="text.searching">searching…</ox-i18n></div></div>`;
104
+ }
105
+ if (!this._items.length) {
106
+ return html `<div class="dropdown"><div class="hint"><ox-i18n msgid="text.no-results">no results</ox-i18n></div></div>`;
107
+ }
108
+ return html `
109
+ <div class="dropdown">
110
+ ${this._items.map((id, idx) => html `
111
+ <div
112
+ class="item ${idx === this._activeIndex ? 'active' : ''}"
113
+ @mousedown=${(e) => this._select(id, e)}
114
+ >
115
+ ${id}
116
+ </div>
117
+ `)}
118
+ </div>
119
+ `;
120
+ }
121
+ _onFocus() {
122
+ clearTimeout(this._blurTimer);
123
+ this._open = true;
124
+ this._activeIndex = -1;
125
+ this._load();
126
+ }
127
+ _onBlur() {
128
+ // 드롭다운 항목 mousedown 이 먼저 처리되도록 약간 지연 후 닫기
129
+ this._blurTimer = setTimeout(() => {
130
+ this._open = false;
131
+ this._activeIndex = -1;
132
+ }, 150);
133
+ }
134
+ _onInput(e) {
135
+ this.value = e.target.value;
136
+ this._open = true;
137
+ this._activeIndex = -1;
138
+ }
139
+ /** 자유 입력 commit (blur/Enter 의 native change) — 기존 free-text 동작 보존. */
140
+ _onInputCommit(e) {
141
+ this.value = e.target.value;
142
+ this._emitChange();
143
+ }
144
+ _onKeydown(e) {
145
+ const ids = this._selectableIds;
146
+ if (!this._open || !ids.length) {
147
+ if (e.key === 'Escape')
148
+ this._open = false;
149
+ return;
150
+ }
151
+ if (e.key === 'ArrowDown') {
152
+ e.preventDefault();
153
+ this._activeIndex = (this._activeIndex + 1) % ids.length;
154
+ }
155
+ else if (e.key === 'ArrowUp') {
156
+ e.preventDefault();
157
+ this._activeIndex = (this._activeIndex - 1 + ids.length) % ids.length;
158
+ }
159
+ else if (e.key === 'Enter') {
160
+ if (this._activeIndex >= 0) {
161
+ e.preventDefault();
162
+ this._commitValue(ids[this._activeIndex]);
163
+ }
164
+ }
165
+ else if (e.key === 'Escape') {
166
+ this._open = false;
167
+ this._activeIndex = -1;
168
+ }
169
+ }
170
+ _select(id, e) {
171
+ // mousedown 기본동작(blur) 막아 흐름 제어
172
+ e.preventDefault();
173
+ this._commitValue(id);
174
+ }
175
+ _commitValue(id) {
176
+ var _a;
177
+ this.value = id;
178
+ this._open = false;
179
+ this._activeIndex = -1;
180
+ if (this._input)
181
+ this._input.value = id;
182
+ this._emitChange();
183
+ (_a = this._input) === null || _a === void 0 ? void 0 : _a.blur();
184
+ }
185
+ _emitChange() {
186
+ // 같은 값 재발행 skip (예: 드롭다운 선택 직후 blur 의 native change 중복)
187
+ if (this.value === this._lastEmitted)
188
+ return;
189
+ this._lastEmitted = this.value;
190
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }));
191
+ }
192
+ /**
193
+ * 후보 전체를 1회 조회 (포커스 시). keyword 는 보내지 않으며, 표시 필터는 _items
194
+ * 게터가 로컬에서 처리한다. entityType(+unit 이면 machine) 만 서버로 보낸다.
195
+ */
196
+ async _load() {
197
+ // 로컬 리스트 모드(예: parentObject) — 백엔드 조회 없이 주어진 리스트 사용.
198
+ if (this.localItems != null) {
199
+ this._needMachine = false;
200
+ this._loading = false;
201
+ this._all = this.localItems;
202
+ return;
203
+ }
204
+ if (!this.entityType) {
205
+ this._all = [];
206
+ return;
207
+ }
208
+ // machine 필수 타입(Port 등)인데 부모 머신 미지정 → 조회 보류 (후보 과다 방지).
209
+ if (this.requireMachine && !this.machine) {
210
+ this._all = [];
211
+ this._needMachine = true;
212
+ return;
213
+ }
214
+ this._needMachine = false;
215
+ const seq = ++this._loadSeq;
216
+ this._loading = true;
217
+ try {
218
+ const ids = await searchMachineUnits(this.entityType, '', this.machine ? { machine: this.machine } : {});
219
+ if (seq !== this._loadSeq)
220
+ return; // 더 최신 조회가 있으면 폐기
221
+ this._all = ids;
222
+ }
223
+ catch (_a) {
224
+ if (seq === this._loadSeq)
225
+ this._all = [];
226
+ }
227
+ finally {
228
+ if (seq === this._loadSeq)
229
+ this._loading = false;
230
+ }
231
+ }
232
+ }
233
+ OxInputEntityId.styles = [
234
+ ScrollbarStyles,
235
+ css `
236
+ :host {
237
+ position: relative;
238
+ display: flex;
239
+ align-items: stretch;
240
+ width: 100%;
241
+ height: 100%;
242
+ }
243
+
244
+ input {
245
+ flex: 1 1 auto;
246
+ width: 100%;
247
+ height: 100%;
248
+ box-sizing: border-box;
249
+ margin: 0;
250
+ padding: var(--input-padding, 2px 4px);
251
+ font: inherit;
252
+ border: var(--property-sidebar-fieldset-border, 1px solid #ccc);
253
+ }
254
+
255
+ .dropdown {
256
+ position: absolute;
257
+ top: 100%;
258
+ left: 0;
259
+ right: 0;
260
+ z-index: 100;
261
+
262
+ max-height: 220px;
263
+ overflow-y: auto;
264
+
265
+ margin-top: 2px;
266
+ background: var(--md-sys-color-surface, #fff);
267
+ border: 1px solid var(--md-sys-color-outline-variant, #c4c7c5);
268
+ border-radius: 4px;
269
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.18);
270
+ }
271
+
272
+ .group-header {
273
+ padding: 3px 8px;
274
+ font-size: 10px;
275
+ font-weight: 600;
276
+ text-transform: uppercase;
277
+ letter-spacing: 0.04em;
278
+ color: var(--md-sys-color-on-surface-variant, #777);
279
+ background: var(--md-sys-color-surface-variant, #eef0f3);
280
+ position: sticky;
281
+ top: 0;
282
+ }
283
+
284
+ .item {
285
+ padding: 4px 8px;
286
+ cursor: pointer;
287
+ white-space: nowrap;
288
+ overflow: hidden;
289
+ text-overflow: ellipsis;
290
+ font: var(--property-sidebar-fieldset-label, 12px sans-serif);
291
+ }
292
+
293
+ /* unit 항목 (그룹 자식) 은 살짝 들여쓰기 */
294
+ .item.child {
295
+ padding-left: 18px;
296
+ }
297
+
298
+ .item:hover,
299
+ .item.active {
300
+ background: var(--md-sys-color-secondary-container, #d7e3ff);
301
+ }
302
+
303
+ .hint {
304
+ padding: 6px 8px;
305
+ color: var(--md-sys-color-on-surface-variant, #888);
306
+ font-size: 11px;
307
+ }
308
+ `
309
+ ];
310
+ __decorate([
311
+ property({ type: String })
312
+ ], OxInputEntityId.prototype, "value", void 0);
313
+ __decorate([
314
+ property({ type: String })
315
+ ], OxInputEntityId.prototype, "entityType", void 0);
316
+ __decorate([
317
+ property({ type: String })
318
+ ], OxInputEntityId.prototype, "machine", void 0);
319
+ __decorate([
320
+ property({ type: Boolean })
321
+ ], OxInputEntityId.prototype, "requireMachine", void 0);
322
+ __decorate([
323
+ property({ type: Array })
324
+ ], OxInputEntityId.prototype, "localItems", void 0);
325
+ __decorate([
326
+ property({ type: String })
327
+ ], OxInputEntityId.prototype, "placeholder", void 0);
328
+ __decorate([
329
+ state()
330
+ ], OxInputEntityId.prototype, "_open", void 0);
331
+ __decorate([
332
+ state()
333
+ ], OxInputEntityId.prototype, "_all", void 0);
334
+ __decorate([
335
+ state()
336
+ ], OxInputEntityId.prototype, "_loading", void 0);
337
+ __decorate([
338
+ state()
339
+ ], OxInputEntityId.prototype, "_needMachine", void 0);
340
+ __decorate([
341
+ state()
342
+ ], OxInputEntityId.prototype, "_activeIndex", void 0);
343
+ __decorate([
344
+ query('input')
345
+ ], OxInputEntityId.prototype, "_input", void 0);
346
+ //# sourceMappingURL=ox-input-entity-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ox-input-entity-id.js","sourceRoot":"","sources":["../../../../../src/modeller/property-sidebar/shapes/ox-input-entity-id.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@operato/i18n/ox-i18n.js'\n\nimport { css, html, LitElement, PropertyValues } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { searchMachineUnits, filterMachineUnitIds } from '@fmsim/api'\n\n/**\n * 컴포넌트 ID 입력기 — 자유 입력 + 타입별 백엔드(MCS) 검색 선택을 함께 제공.\n *\n * - 기존처럼 자유롭게 텍스트로 ID 를 입력할 수 있다 (commit = blur/Enter).\n * - input 에 *포커스가 가면* 아래로 검색 드롭다운이 펼쳐진다. `entityType`\n * (컴포넌트 타입) 으로 MCS 에 정의된 ID 후보를 조회한다.\n * - machine 타입 → 머신 id 가 1레벨 평면으로 (선택 가능)\n * - unit 타입 → machine 이 그룹 헤더, 그 아래 unit id 가 자식 (선택 가능).\n * 컴포넌트가 부모 machine 을 알면(`machine` prop) 그 머신으로 좁혀 조회.\n *\n * value-key=\"id\" 와 함께 property-grid 안에 두면, 이 host 가 `change`(bubbles+\n * composed) 를 발행하므로 AbstractProperty 제너릭 핸들러가 `element.value` 를\n * 읽어 property-change 로 전파한다.\n *\n * 등록: 패널 자식 커스텀 엘리먼트 컨벤션에 따라 전역 `@customElement` 가 아니라\n * 부모 패널(PropertyShapes)의 `scopedElements` 로 등록한다 (@open-wc/scoped-elements).\n */\nexport class OxInputEntityId extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n position: relative;\n display: flex;\n align-items: stretch;\n width: 100%;\n height: 100%;\n }\n\n input {\n flex: 1 1 auto;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n margin: 0;\n padding: var(--input-padding, 2px 4px);\n font: inherit;\n border: var(--property-sidebar-fieldset-border, 1px solid #ccc);\n }\n\n .dropdown {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: 100;\n\n max-height: 220px;\n overflow-y: auto;\n\n margin-top: 2px;\n background: var(--md-sys-color-surface, #fff);\n border: 1px solid var(--md-sys-color-outline-variant, #c4c7c5);\n border-radius: 4px;\n box-shadow: 0 4px 10px rgba(0, 0, 0, 0.18);\n }\n\n .group-header {\n padding: 3px 8px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n color: var(--md-sys-color-on-surface-variant, #777);\n background: var(--md-sys-color-surface-variant, #eef0f3);\n position: sticky;\n top: 0;\n }\n\n .item {\n padding: 4px 8px;\n cursor: pointer;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font: var(--property-sidebar-fieldset-label, 12px sans-serif);\n }\n\n /* unit 항목 (그룹 자식) 은 살짝 들여쓰기 */\n .item.child {\n padding-left: 18px;\n }\n\n .item:hover,\n .item.active {\n background: var(--md-sys-color-secondary-container, #d7e3ff);\n }\n\n .hint {\n padding: 6px 8px;\n color: var(--md-sys-color-on-surface-variant, #888);\n font-size: 11px;\n }\n `\n ]\n\n /** 현재 ID 값. */\n @property({ type: String }) value = ''\n /** 검색 조건 — 선택된 컴포넌트 타입 (예: 'STOCKER', 'AGV', 'Port'). */\n @property({ type: String }) entityType = ''\n /** 검색 조건 — 부모 machine id (unit 컴포넌트가 소속 machine 을 알 때). */\n @property({ type: String }) machine = ''\n /** machine 필수 타입(예: Port) — machine 없으면 조회하지 않는다 (후보 과다 방지). */\n @property({ type: Boolean }) requireMachine = false\n /** 백엔드 조회 대신 사용할 로컬 후보 리스트 (예: parentObject — 씬의 머신들). null 이면 백엔드 조회. */\n @property({ type: Array }) localItems: string[] | null = null\n @property({ type: String }) placeholder = ''\n\n @state() private _open = false\n /** 서버에서 받은 전체 후보 리스트 (포커스 시 1회 조회, 키워드 미적용). */\n @state() private _all: string[] = []\n @state() private _loading = false\n /** machine 필수인데 machine 미지정이라 조회를 보류한 상태. */\n @state() private _needMachine = false\n /** 선택 가능 항목 기준 active index. */\n @state() private _activeIndex = -1\n\n @query('input') private _input!: HTMLInputElement\n\n private _blurTimer?: ReturnType<typeof setTimeout>\n private _loadSeq = 0\n /** 마지막으로 발행한 값 — 같은 값 재발행(undo 중복) 방지. */\n private _lastEmitted?: string\n\n disconnectedCallback() {\n super.disconnectedCallback()\n clearTimeout(this._blurTimer)\n }\n\n updated(changed: PropertyValues) {\n // 열린 상태에서 조회 조건(타입/부모 머신)이 바뀌면 재조회 (예: 부모 머신을 방금 지정).\n if (this._open && (changed.has('entityType') || changed.has('machine') || changed.has('localItems'))) {\n this._load()\n }\n // 화살표 키로 active 항목 이동 시 항상 보이도록 드롭다운을 스크롤.\n if (changed.has('_activeIndex') && this._open && this._activeIndex >= 0) {\n const el = this.renderRoot.querySelector('.item.active') as HTMLElement | null\n el?.scrollIntoView({ block: 'nearest' })\n }\n }\n\n /**\n * 드롭다운 표시 항목 — 입력값(초기값 포함)으로 풀텍스트 로컬 필터.\n * 단, 매치가 0이면 전체 후보로 fallback (막다른 \"결과 없음\" 방지 — 예: committed\n * id 가 후보 형식과 달라 안 맞는 경우). 서버 재조회 없음.\n */\n private get _items(): string[] {\n if (!this._all.length) return []\n const filtered = filterMachineUnitIds(this._all, this.value || '')\n return filtered.length ? filtered : this._all\n }\n\n /** 드롭다운에서 선택 가능한 id 들 (표시 순서). */\n private get _selectableIds(): string[] {\n return this._items\n }\n\n render() {\n return html`\n <input\n .value=${this.value || ''}\n placeholder=${this.placeholder}\n autocomplete=\"off\"\n @focus=${this._onFocus}\n @blur=${this._onBlur}\n @input=${this._onInput}\n @change=${this._onInputCommit}\n @keydown=${this._onKeydown}\n />\n ${this._open ? this._renderDropdown() : ''}\n `\n }\n\n private _renderDropdown() {\n if (this._needMachine) {\n return html`<div class=\"dropdown\">\n <div class=\"hint\"><ox-i18n msgid=\"text.need-parent-machine\">상위 머신을 먼저 지정하세요</ox-i18n></div>\n </div>`\n }\n if (this._loading) {\n return html`<div class=\"dropdown\"><div class=\"hint\"><ox-i18n msgid=\"text.searching\">searching…</ox-i18n></div></div>`\n }\n if (!this._items.length) {\n return html`<div class=\"dropdown\"><div class=\"hint\"><ox-i18n msgid=\"text.no-results\">no results</ox-i18n></div></div>`\n }\n\n return html`\n <div class=\"dropdown\">\n ${this._items.map(\n (id, idx) => html`\n <div\n class=\"item ${idx === this._activeIndex ? 'active' : ''}\"\n @mousedown=${(e: MouseEvent) => this._select(id, e)}\n >\n ${id}\n </div>\n `\n )}\n </div>\n `\n }\n\n private _onFocus() {\n clearTimeout(this._blurTimer)\n this._open = true\n this._activeIndex = -1\n this._load()\n }\n\n private _onBlur() {\n // 드롭다운 항목 mousedown 이 먼저 처리되도록 약간 지연 후 닫기\n this._blurTimer = setTimeout(() => {\n this._open = false\n this._activeIndex = -1\n }, 150)\n }\n\n private _onInput(e: Event) {\n this.value = (e.target as HTMLInputElement).value\n this._open = true\n this._activeIndex = -1\n }\n\n /** 자유 입력 commit (blur/Enter 의 native change) — 기존 free-text 동작 보존. */\n private _onInputCommit(e: Event) {\n this.value = (e.target as HTMLInputElement).value\n this._emitChange()\n }\n\n private _onKeydown(e: KeyboardEvent) {\n const ids = this._selectableIds\n if (!this._open || !ids.length) {\n if (e.key === 'Escape') this._open = false\n return\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n this._activeIndex = (this._activeIndex + 1) % ids.length\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n this._activeIndex = (this._activeIndex - 1 + ids.length) % ids.length\n } else if (e.key === 'Enter') {\n if (this._activeIndex >= 0) {\n e.preventDefault()\n this._commitValue(ids[this._activeIndex])\n }\n } else if (e.key === 'Escape') {\n this._open = false\n this._activeIndex = -1\n }\n }\n\n private _select(id: string, e: MouseEvent) {\n // mousedown 기본동작(blur) 막아 흐름 제어\n e.preventDefault()\n this._commitValue(id)\n }\n\n private _commitValue(id: string) {\n this.value = id\n this._open = false\n this._activeIndex = -1\n if (this._input) this._input.value = id\n this._emitChange()\n this._input?.blur()\n }\n\n private _emitChange() {\n // 같은 값 재발행 skip (예: 드롭다운 선택 직후 blur 의 native change 중복)\n if (this.value === this._lastEmitted) return\n this._lastEmitted = this.value\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))\n }\n\n /**\n * 후보 전체를 1회 조회 (포커스 시). keyword 는 보내지 않으며, 표시 필터는 _items\n * 게터가 로컬에서 처리한다. entityType(+unit 이면 machine) 만 서버로 보낸다.\n */\n private async _load() {\n // 로컬 리스트 모드(예: parentObject) — 백엔드 조회 없이 주어진 리스트 사용.\n if (this.localItems != null) {\n this._needMachine = false\n this._loading = false\n this._all = this.localItems\n return\n }\n if (!this.entityType) {\n this._all = []\n return\n }\n // machine 필수 타입(Port 등)인데 부모 머신 미지정 → 조회 보류 (후보 과다 방지).\n if (this.requireMachine && !this.machine) {\n this._all = []\n this._needMachine = true\n return\n }\n this._needMachine = false\n const seq = ++this._loadSeq\n this._loading = true\n try {\n const ids = await searchMachineUnits(this.entityType, '', this.machine ? { machine: this.machine } : {})\n if (seq !== this._loadSeq) return // 더 최신 조회가 있으면 폐기\n this._all = ids\n } catch {\n if (seq === this._loadSeq) this._all = []\n } finally {\n if (seq === this._loadSeq) this._loading = false\n }\n }\n}\n"]}