@operato/property-panel 10.0.0-beta.47 → 10.0.0-beta.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,20 @@
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.0.0-beta.48](https://github.com/hatiolab/operato/compare/v10.0.0-beta.47...v10.0.0-beta.48) (2026-05-05)
7
+
8
+
9
+ ### :rocket: New Features
10
+
11
+ * **property-panel:** generic-object 타입 변환 UI를 specifics 탭 전용 에디터로 이동 ([4b90f57](https://github.com/hatiolab/operato/commit/4b90f574c29f1677eb0dacc73b05e9fd10c9d2b2))
12
+
13
+
14
+ ### :house: Code Refactoring
15
+
16
+ * **property-panel:** placeholder-convert 아키텍처 정리 ([ec7c805](https://github.com/hatiolab/operato/commit/ec7c80550148fe2a13704999aafb940b26558729))
17
+
18
+
19
+
6
20
  ## [10.0.0-beta.47](https://github.com/hatiolab/operato/compare/v10.0.0-beta.46...v10.0.0-beta.47) (2026-05-03)
7
21
 
8
22
 
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * placeholder → 도메인 type 변환 property editor.
5
+ *
6
+ * GenericObject.nature.properties 에 `{ type: 'placeholder-convert', name: '_convert' }` 로
7
+ * 선언되어 specific 탭에서 자동 렌더링. 별도 사용처 없음 — nature 선언으로 충분.
8
+ *
9
+ * 변환 흐름:
10
+ * 타입 버튼 클릭 → i-need-selected → specifics.ts undoableChange → convertComponentType
11
+ */
12
+ import { TemplateResult } from 'lit';
13
+ import { OxPropertyEditor } from '@operato/property-editor';
14
+ import type { PropertySpec } from '@operato/property-editor';
15
+ export declare class OxPlaceholderConvertEditor extends OxPropertyEditor {
16
+ static styles: import("lit").CSSResult[];
17
+ private _search;
18
+ editorTemplate(_value: any, _spec: PropertySpec): TemplateResult;
19
+ private _onConvert;
20
+ }
@@ -0,0 +1,125 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * placeholder → 도메인 type 변환 property editor.
5
+ *
6
+ * GenericObject.nature.properties 에 `{ type: 'placeholder-convert', name: '_convert' }` 로
7
+ * 선언되어 specific 탭에서 자동 렌더링. 별도 사용처 없음 — nature 선언으로 충분.
8
+ *
9
+ * 변환 흐름:
10
+ * 타입 버튼 클릭 → i-need-selected → specifics.ts undoableChange → convertComponentType
11
+ */
12
+ import { __decorate } from "tslib";
13
+ import { css, html } from 'lit';
14
+ import { customElement, state } from 'lit/decorators.js';
15
+ import { OxPropertyEditor } from '@operato/property-editor';
16
+ import { convertComponentType, getConvertibleTypes } from './placeholder-convert.js';
17
+ OxPropertyEditor.register({ 'placeholder-convert': 'ox-placeholder-convert-editor' });
18
+ let OxPlaceholderConvertEditor = class OxPlaceholderConvertEditor extends OxPropertyEditor {
19
+ constructor() {
20
+ super(...arguments);
21
+ this._search = '';
22
+ }
23
+ editorTemplate(_value, _spec) {
24
+ const all = getConvertibleTypes();
25
+ const q = this._search.trim().toLowerCase();
26
+ const candidates = q ? all.filter(t => t.toLowerCase().includes(q)) : all;
27
+ return html `
28
+ <div class="convert-wrap fullwidth">
29
+ <input
30
+ type="search"
31
+ class="convert-search"
32
+ placeholder="search type to convert to..."
33
+ .value=${this._search}
34
+ @input=${(e) => {
35
+ this._search = e.target.value;
36
+ }}
37
+ />
38
+ <div class="convert-list">
39
+ ${candidates.length === 0
40
+ ? html `<div class="empty">no matching type</div>`
41
+ : candidates.map(type => html `
42
+ <button class="convert-item" @click=${() => this._onConvert(type)} title=${`convert to ${type}`}>
43
+ ${type}
44
+ </button>
45
+ `)}
46
+ </div>
47
+ </div>
48
+ `;
49
+ }
50
+ _onConvert(newType) {
51
+ this.dispatchEvent(new CustomEvent('i-need-selected', {
52
+ bubbles: true,
53
+ composed: true,
54
+ detail: {
55
+ callback: (selected) => {
56
+ if (selected[0])
57
+ convertComponentType(selected[0], newType);
58
+ }
59
+ }
60
+ }));
61
+ this._search = '';
62
+ }
63
+ };
64
+ OxPlaceholderConvertEditor.styles = [
65
+ ...OxPropertyEditor.styles,
66
+ css `
67
+ .convert-wrap {
68
+ display: flex;
69
+ flex-direction: column;
70
+ gap: 4px;
71
+ padding: 4px 0;
72
+ }
73
+ .convert-search {
74
+ font-size: 12px;
75
+ padding: 4px 8px;
76
+ border: 1px solid var(--md-sys-color-outline-variant, #d0d7de);
77
+ border-radius: 4px;
78
+ background: var(--md-sys-color-surface, #fff);
79
+ color: var(--md-sys-color-on-surface, #000);
80
+ outline: none;
81
+ }
82
+ .convert-search:focus {
83
+ border-color: var(--md-sys-color-primary, #2a64d8);
84
+ }
85
+ .convert-list {
86
+ display: flex;
87
+ flex-direction: column;
88
+ gap: 2px;
89
+ max-height: 200px;
90
+ overflow-y: auto;
91
+ background: var(--md-sys-color-surface, #fff);
92
+ border-radius: 4px;
93
+ padding: 2px;
94
+ }
95
+ .convert-list .empty {
96
+ text-align: center;
97
+ font-size: 11px;
98
+ padding: 8px;
99
+ color: var(--md-sys-color-on-secondary-container, #777);
100
+ }
101
+ .convert-item {
102
+ text-align: left;
103
+ font-size: 12px;
104
+ font-family: monospace;
105
+ padding: 4px 8px;
106
+ background: transparent;
107
+ border: 1px solid transparent;
108
+ border-radius: 3px;
109
+ cursor: pointer;
110
+ color: var(--md-sys-color-on-surface, #000);
111
+ }
112
+ .convert-item:hover {
113
+ background: var(--md-sys-color-primary-container, #eaf2ff);
114
+ border-color: var(--md-sys-color-primary, #2a64d8);
115
+ }
116
+ `
117
+ ];
118
+ __decorate([
119
+ state()
120
+ ], OxPlaceholderConvertEditor.prototype, "_search", void 0);
121
+ OxPlaceholderConvertEditor = __decorate([
122
+ customElement('ox-placeholder-convert-editor')
123
+ ], OxPlaceholderConvertEditor);
124
+ export { OxPlaceholderConvertEditor };
125
+ //# sourceMappingURL=ox-placeholder-convert-editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ox-placeholder-convert-editor.js","sourceRoot":"","sources":["../../../../src/property-panel/shapes/ox-placeholder-convert-editor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;;AAEH,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAGxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAG3D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAEpF,gBAAgB,CAAC,QAAQ,CAAC,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,CAAC,CAAA;AAG9E,IAAM,0BAA0B,GAAhC,MAAM,0BAA2B,SAAQ,gBAAgB;IAAzD;;QAwDY,YAAO,GAAG,EAAE,CAAA;IA+C/B,CAAC;IA7CC,cAAc,CAAC,MAAW,EAAE,KAAmB;QAC7C,MAAM,GAAG,GAAG,mBAAmB,EAAE,CAAA;QACjC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QAC3C,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QAEzE,OAAO,IAAI,CAAA;;;;;;mBAMI,IAAI,CAAC,OAAO;mBACZ,CAAC,CAAQ,EAAE,EAAE;YACpB,IAAI,CAAC,OAAO,GAAI,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAA;QACrD,CAAC;;;YAGC,UAAU,CAAC,MAAM,KAAK,CAAC;YACvB,CAAC,CAAC,IAAI,CAAA,2CAA2C;YACjD,CAAC,CAAC,UAAU,CAAC,GAAG,CACZ,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA;wDAC4B,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,cAAc,IAAI,EAAE;sBAC3F,IAAI;;iBAET,CACF;;;KAGV,CAAA;IACH,CAAC;IAEO,UAAU,CAAC,OAAe;QAChC,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,iBAAiB,EAAE;YACjC,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE;gBACN,QAAQ,EAAE,CAAC,QAAqB,EAAE,EAAE;oBAClC,IAAI,QAAQ,CAAC,CAAC,CAAC;wBAAE,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;gBAC7D,CAAC;aACF;SACF,CAAC,CACH,CAAA;QACD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;IACnB,CAAC;;AArGM,iCAAM,GAAG;IACd,GAAG,gBAAgB,CAAC,MAAM;IAC1B,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkDF;CACF,AArDY,CAqDZ;AAEgB;IAAhB,KAAK,EAAE;2DAAqB;AAxDlB,0BAA0B;IADtC,aAAa,CAAC,+BAA+B,CAAC;GAClC,0BAA0B,CAuGtC","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n *\n * placeholder → 도메인 type 변환 property editor.\n *\n * GenericObject.nature.properties 에 `{ type: 'placeholder-convert', name: '_convert' }` 로\n * 선언되어 specific 탭에서 자동 렌더링. 별도 사용처 없음 — nature 선언으로 충분.\n *\n * 변환 흐름:\n * 타입 버튼 클릭 → i-need-selected → specifics.ts undoableChange → convertComponentType\n */\n\nimport { css, html, TemplateResult } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport type { Component } from '@hatiolab/things-scene'\nimport { OxPropertyEditor } from '@operato/property-editor'\nimport type { PropertySpec } from '@operato/property-editor'\n\nimport { convertComponentType, getConvertibleTypes } from './placeholder-convert.js'\n\nOxPropertyEditor.register({ 'placeholder-convert': 'ox-placeholder-convert-editor' })\n\n@customElement('ox-placeholder-convert-editor')\nexport class OxPlaceholderConvertEditor extends OxPropertyEditor {\n static styles = [\n ...OxPropertyEditor.styles,\n css`\n .convert-wrap {\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 4px 0;\n }\n .convert-search {\n font-size: 12px;\n padding: 4px 8px;\n border: 1px solid var(--md-sys-color-outline-variant, #d0d7de);\n border-radius: 4px;\n background: var(--md-sys-color-surface, #fff);\n color: var(--md-sys-color-on-surface, #000);\n outline: none;\n }\n .convert-search:focus {\n border-color: var(--md-sys-color-primary, #2a64d8);\n }\n .convert-list {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 200px;\n overflow-y: auto;\n background: var(--md-sys-color-surface, #fff);\n border-radius: 4px;\n padding: 2px;\n }\n .convert-list .empty {\n text-align: center;\n font-size: 11px;\n padding: 8px;\n color: var(--md-sys-color-on-secondary-container, #777);\n }\n .convert-item {\n text-align: left;\n font-size: 12px;\n font-family: monospace;\n padding: 4px 8px;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 3px;\n cursor: pointer;\n color: var(--md-sys-color-on-surface, #000);\n }\n .convert-item:hover {\n background: var(--md-sys-color-primary-container, #eaf2ff);\n border-color: var(--md-sys-color-primary, #2a64d8);\n }\n `\n ]\n\n @state() private _search = ''\n\n editorTemplate(_value: any, _spec: PropertySpec): TemplateResult {\n const all = getConvertibleTypes()\n const q = this._search.trim().toLowerCase()\n const candidates = q ? all.filter(t => t.toLowerCase().includes(q)) : all\n\n return html`\n <div class=\"convert-wrap fullwidth\">\n <input\n type=\"search\"\n class=\"convert-search\"\n placeholder=\"search type to convert to...\"\n .value=${this._search}\n @input=${(e: Event) => {\n this._search = (e.target as HTMLInputElement).value\n }}\n />\n <div class=\"convert-list\">\n ${candidates.length === 0\n ? html`<div class=\"empty\">no matching type</div>`\n : candidates.map(\n type => html`\n <button class=\"convert-item\" @click=${() => this._onConvert(type)} title=${`convert to ${type}`}>\n ${type}\n </button>\n `\n )}\n </div>\n </div>\n `\n }\n\n private _onConvert(newType: string) {\n this.dispatchEvent(\n new CustomEvent('i-need-selected', {\n bubbles: true,\n composed: true,\n detail: {\n callback: (selected: Component[]) => {\n if (selected[0]) convertComponentType(selected[0], newType)\n }\n }\n })\n )\n this._search = ''\n }\n}\n"]}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * Placeholder → 도메인 type 변환 helper.
5
+ *
6
+ * 대상: board-import 가 떨어뜨린 generic-* placeholder 컴포넌트 — 사용자가 모델러에서
7
+ * 구체 type 으로 변환하는 액션. property-panel 의 shapes 섹션이 호출.
8
+ *
9
+ * 정책:
10
+ * - **placeholder type 한정** — 일반 컴포넌트 (Stocker, Forklift 등) 는 대상 X. 안전.
11
+ * - things-scene 의 `Scene.undoableChange` 로 감싸 undo/redo 자연스럽게 통합.
12
+ * - 좌표/크기/회전/id 보존. 새 type 의 default state 는 클래스 생성자가 처리.
13
+ *
14
+ * things-scene 의 컴포넌트 type 변경은 클래스 자체 교체가 필요 (메서드 binding 이라).
15
+ * 단순 `state.type` 갱신으론 부족 → 기존 컴포넌트 제거 + 새 type 으로 compile + 같은 위치에 추가.
16
+ */
17
+ import { Component } from '@hatiolab/things-scene';
18
+ /**
19
+ * 변환 대상 placeholder 인지 판정. property-panel 의 conditional 렌더 가드.
20
+ */
21
+ export declare function isPlaceholderComponent(component: Component | undefined | null): boolean;
22
+ export declare function getConvertibleTypes(): string[];
23
+ /**
24
+ * placeholder 를 새 type 으로 변환. 좌표/크기/회전/id 보존.
25
+ *
26
+ * 동작:
27
+ * 1) component.hierarchy 로 모델 snapshot
28
+ * 2) 새 모델 = snapshot + { type: newType }
29
+ * 3) Scene.undoableChange 안에서: removeSelf → compile(newModel) → parent.insertComponentAt 같은 index
30
+ * 4) snapshot-commander 가 자동으로 undoable snapshot 캡처
31
+ *
32
+ * 실패 (newType 미등록 / 컴포넌트 placeholder 아님 등) 시 throw.
33
+ */
34
+ export declare function convertComponentType(component: Component, newType: string): void;
@@ -0,0 +1,117 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * Placeholder → 도메인 type 변환 helper.
5
+ *
6
+ * 대상: board-import 가 떨어뜨린 generic-* placeholder 컴포넌트 — 사용자가 모델러에서
7
+ * 구체 type 으로 변환하는 액션. property-panel 의 shapes 섹션이 호출.
8
+ *
9
+ * 정책:
10
+ * - **placeholder type 한정** — 일반 컴포넌트 (Stocker, Forklift 등) 는 대상 X. 안전.
11
+ * - things-scene 의 `Scene.undoableChange` 로 감싸 undo/redo 자연스럽게 통합.
12
+ * - 좌표/크기/회전/id 보존. 새 type 의 default state 는 클래스 생성자가 처리.
13
+ *
14
+ * things-scene 의 컴포넌트 type 변경은 클래스 자체 교체가 필요 (메서드 binding 이라).
15
+ * 단순 `state.type` 갱신으론 부족 → 기존 컴포넌트 제거 + 새 type 으로 compile + 같은 위치에 추가.
16
+ */
17
+ import { Component, Model } from '@hatiolab/things-scene';
18
+ /** 변환 가능한 placeholder type 모음. board-import 의 CORE_PLACEHOLDER_TYPES 와 동기화.
19
+ * 도메인 generic 추상 (GenericTransport, GenericFacility 등) 은 GLB 바디 교체 전용 —
20
+ * 여기에 포함하지 않는다 (변환 아닌 GLB attach 가 별도 UI).
21
+ */
22
+ const PLACEHOLDER_TYPES = new Set([
23
+ 'placeholder',
24
+ 'GenericObject' // 구버전 PascalCase 호환
25
+ ]);
26
+ /**
27
+ * 변환 대상 placeholder 인지 판정. property-panel 의 conditional 렌더 가드.
28
+ */
29
+ export function isPlaceholderComponent(component) {
30
+ var _a;
31
+ if (!component)
32
+ return false;
33
+ return PLACEHOLDER_TYPES.has((_a = component.state) === null || _a === void 0 ? void 0 : _a.type);
34
+ }
35
+ /**
36
+ * 변환 후보 type 목록 — 등록된 모든 component type 중 placeholder 자기 자신 + 시스템 type
37
+ * (root container, layer 등) 제외. property-panel dropdown 후보에 사용.
38
+ */
39
+ const SYSTEM_TYPES = new Set([
40
+ 'root',
41
+ 'root-container',
42
+ 'group',
43
+ 'layer',
44
+ 'model-layer',
45
+ 'tool-layer',
46
+ 'modeler-layer'
47
+ ]);
48
+ export function getConvertibleTypes() {
49
+ var _a, _b;
50
+ const all = (_b = (_a = Component).types) === null || _b === void 0 ? void 0 : _b.call(_a);
51
+ if (!all)
52
+ return [];
53
+ return all
54
+ .filter(t => !PLACEHOLDER_TYPES.has(t))
55
+ .filter(t => !SYSTEM_TYPES.has(t))
56
+ .sort();
57
+ }
58
+ /**
59
+ * placeholder 를 새 type 으로 변환. 좌표/크기/회전/id 보존.
60
+ *
61
+ * 동작:
62
+ * 1) component.hierarchy 로 모델 snapshot
63
+ * 2) 새 모델 = snapshot + { type: newType }
64
+ * 3) Scene.undoableChange 안에서: removeSelf → compile(newModel) → parent.insertComponentAt 같은 index
65
+ * 4) snapshot-commander 가 자동으로 undoable snapshot 캡처
66
+ *
67
+ * 실패 (newType 미등록 / 컴포넌트 placeholder 아님 등) 시 throw.
68
+ */
69
+ export function convertComponentType(component, newType) {
70
+ if (!isPlaceholderComponent(component)) {
71
+ throw new Error(`Component (type=${component.state.type}) is not a placeholder — convert restricted to placeholders only.`);
72
+ }
73
+ const clazz = Component.register(newType);
74
+ if (!clazz) {
75
+ throw new Error(`Unknown component type: ${newType}`);
76
+ }
77
+ if (PLACEHOLDER_TYPES.has(newType)) {
78
+ throw new Error(`Cannot convert to another placeholder type: ${newType}`);
79
+ }
80
+ const app = component.app;
81
+ if (!(app === null || app === void 0 ? void 0 : app.commander))
82
+ throw new Error('Component is not attached to an app/scene.');
83
+ const oldHierarchy = JSON.parse(JSON.stringify(component.hierarchy));
84
+ const newModel = {
85
+ ...oldHierarchy,
86
+ type: newType
87
+ };
88
+ performTypeSwap(component, newModel);
89
+ }
90
+ /**
91
+ * 공통 swap 로직 — Scene.undoableChange 안에서 component 를 새 모델로 교체.
92
+ * snapshot-commander 가 자동으로 undoable 처리.
93
+ */
94
+ function performTypeSwap(component, newModel) {
95
+ var _a, _b, _c, _d;
96
+ const app = component.app;
97
+ const parent = component.parent;
98
+ if (!parent)
99
+ throw new Error('Component has no parent — cannot swap.');
100
+ // children 인덱스 (insertComponentAt 으로 같은 위치 보존)
101
+ const siblings = parent.components;
102
+ const index = siblings ? siblings.indexOf(component) : -1;
103
+ (_b = (_a = component).removeSelf) === null || _b === void 0 ? void 0 : _b.call(_a, false);
104
+ const newComp = Model.compile(newModel, app);
105
+ if (!newComp) {
106
+ throw new Error(`Failed to compile new component type: ${newModel.type}`);
107
+ }
108
+ if (index >= 0 && parent.insertComponentAt) {
109
+ ;
110
+ parent.insertComponentAt(newComp, index);
111
+ }
112
+ else {
113
+ ;
114
+ (_d = (_c = parent).addComponent) === null || _d === void 0 ? void 0 : _d.call(_c, newComp);
115
+ }
116
+ }
117
+ //# sourceMappingURL=placeholder-convert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placeholder-convert.js","sourceRoot":"","sources":["../../../../src/property-panel/shapes/placeholder-convert.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n *\n * Placeholder → 도메인 type 변환 helper.\n *\n * 대상: board-import 가 떨어뜨린 generic-* placeholder 컴포넌트 — 사용자가 모델러에서\n * 구체 type 으로 변환하는 액션. property-panel 의 shapes 섹션이 호출.\n *\n * 정책:\n * - **placeholder type 한정** — 일반 컴포넌트 (Stocker, Forklift 등) 는 대상 X. 안전.\n * - things-scene 의 `Scene.undoableChange` 로 감싸 undo/redo 자연스럽게 통합.\n * - 좌표/크기/회전/id 보존. 새 type 의 default state 는 클래스 생성자가 처리.\n *\n * things-scene 의 컴포넌트 type 변경은 클래스 자체 교체가 필요 (메서드 binding 이라).\n * 단순 `state.type` 갱신으론 부족 → 기존 컴포넌트 제거 + 새 type 으로 compile + 같은 위치에 추가.\n */\n\nimport { Component, Model } from '@hatiolab/things-scene'\n\n/** 변환 가능한 placeholder type 모음. board-import 의 CORE_PLACEHOLDER_TYPES 와 동기화.\n * 도메인 generic 추상 (GenericTransport, GenericFacility 등) 은 GLB 바디 교체 전용 —\n * 여기에 포함하지 않는다 (변환 아닌 GLB attach 가 별도 UI).\n */\nconst PLACEHOLDER_TYPES = new Set([\n 'placeholder',\n 'GenericObject' // 구버전 PascalCase 호환\n])\n\n/**\n * 변환 대상 placeholder 인지 판정. property-panel 의 conditional 렌더 가드.\n */\nexport function isPlaceholderComponent(component: Component | undefined | null): boolean {\n if (!component) return false\n return PLACEHOLDER_TYPES.has(component.state?.type as string)\n}\n\n/**\n * 변환 후보 type 목록 — 등록된 모든 component type 중 placeholder 자기 자신 + 시스템 type\n * (root container, layer 등) 제외. property-panel dropdown 후보에 사용.\n */\nconst SYSTEM_TYPES = new Set([\n 'root',\n 'root-container',\n 'group',\n 'layer',\n 'model-layer',\n 'tool-layer',\n 'modeler-layer'\n])\n\nexport function getConvertibleTypes(): string[] {\n const all = (Component as any).types?.() as string[] | undefined\n if (!all) return []\n return all\n .filter(t => !PLACEHOLDER_TYPES.has(t))\n .filter(t => !SYSTEM_TYPES.has(t))\n .sort()\n}\n\n/**\n * placeholder 를 새 type 으로 변환. 좌표/크기/회전/id 보존.\n *\n * 동작:\n * 1) component.hierarchy 로 모델 snapshot\n * 2) 새 모델 = snapshot + { type: newType }\n * 3) Scene.undoableChange 안에서: removeSelf → compile(newModel) → parent.insertComponentAt 같은 index\n * 4) snapshot-commander 가 자동으로 undoable snapshot 캡처\n *\n * 실패 (newType 미등록 / 컴포넌트 placeholder 아님 등) 시 throw.\n */\nexport function convertComponentType(component: Component, newType: string): void {\n if (!isPlaceholderComponent(component)) {\n throw new Error(\n `Component (type=${component.state.type}) is not a placeholder — convert restricted to placeholders only.`\n )\n }\n const clazz = (Component as any).register(newType)\n if (!clazz) {\n throw new Error(`Unknown component type: ${newType}`)\n }\n if (PLACEHOLDER_TYPES.has(newType)) {\n throw new Error(`Cannot convert to another placeholder type: ${newType}`)\n }\n\n const app = (component as any).app\n if (!app?.commander) throw new Error('Component is not attached to an app/scene.')\n\n const oldHierarchy = JSON.parse(JSON.stringify((component as any).hierarchy))\n const newModel: Record<string, any> = {\n ...oldHierarchy,\n type: newType\n }\n\n performTypeSwap(component, newModel)\n}\n\n/**\n * 공통 swap 로직 — Scene.undoableChange 안에서 component 를 새 모델로 교체.\n * snapshot-commander 가 자동으로 undoable 처리.\n */\nfunction performTypeSwap(component: Component, newModel: Record<string, any>): void {\n const app = (component as any).app\n const parent = (component as any).parent\n if (!parent) throw new Error('Component has no parent — cannot swap.')\n\n // children 인덱스 (insertComponentAt 으로 같은 위치 보존)\n const siblings = (parent as any).components as Component[] | undefined\n const index = siblings ? siblings.indexOf(component) : -1\n\n // 호출자(specifics.ts의 i-need-selected → undoableChange)가 이미 감싸므로 직접 실행.\n ;(component as any).removeSelf?.(false)\n const newComp = (Model as any).compile(newModel as any, app)\n if (!newComp) {\n throw new Error(`Failed to compile new component type: ${newModel.type}`)\n }\n if (index >= 0 && (parent as any).insertComponentAt) {\n ;(parent as any).insertComponentAt(newComp, index)\n } else {\n ;(parent as any).addComponent?.(newComp)\n }\n}\n"]}
@@ -7,7 +7,7 @@ import '@operato/input/ox-buttons-radio.js';
7
7
  import '@material/web/icon/icon.js';
8
8
  import '@operato/i18n/ox-i18n.js';
9
9
  import '@operato/help/ox-title-with-help.js';
10
- import { html } from 'lit';
10
+ import { css, html } from 'lit';
11
11
  import { property, state } from 'lit/decorators.js';
12
12
  import { keyed } from 'lit/directives/keyed.js';
13
13
  import { PropertyGridStyles } from '@operato/styles/property-grid-styles.js';
@@ -316,7 +316,12 @@ export class PropertyShapes extends AbstractProperty {
316
316
  return true;
317
317
  }
318
318
  }
319
- PropertyShapes.styles = [PropertyGridStyles, BoxPaddingEditorStyles];
319
+ PropertyShapes.styles = [
320
+ PropertyGridStyles,
321
+ BoxPaddingEditorStyles,
322
+ css `
323
+ `
324
+ ];
320
325
  __decorate([
321
326
  property({ type: Object })
322
327
  ], PropertyShapes.prototype, "value", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"shapes.js","sourceRoot":"","sources":["../../../../src/property-panel/shapes/shapes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@operato/input/ox-input-angle.js'\nimport '@operato/input/ox-buttons-radio.js'\nimport '@material/web/icon/icon.js'\nimport '@operato/i18n/ox-i18n.js'\nimport '@operato/help/ox-title-with-help.js'\n\nimport { css, html } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport { keyed } from 'lit/directives/keyed.js'\n\nimport { BOUNDS, Component, Properties } from '@hatiolab/things-scene'\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\nimport { BoxPaddingEditorStyles } from '@operato/styles/box-padding-editor-styles.js'\n\nimport { AbstractProperty } from '../abstract-property.js'\n\nexport class PropertyShapes extends AbstractProperty {\n static styles = [PropertyGridStyles, BoxPaddingEditorStyles]\n\n @property({ type: Object }) value?: Properties\n @property({ type: Object }) bounds: BOUNDS | null = null\n @property({ type: Array }) selected: Component[] = []\n\n @state() private _positionExpanded: boolean = false\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', this.onValueChange.bind(this))\n }\n\n render() {\n const value = this.value || {}\n const { width = '', height = '' } = this.bounds || {}\n\n return html`\n <fieldset>\n <div class=\"property-grid\">\n ${this._isIdentifiable(this.selected)\n ? html`\n <label> <ox-i18n msgid=\"label.id\">ID</ox-i18n> </label>\n <input value-key=\"id\" .value=${value.id || ''} />\n `\n : html``}\n ${this._isClassIdentifiable(this.selected)\n ? html`\n <label> <ox-i18n msgid=\"label.class\">Class</ox-i18n> </label>\n <input value-key=\"class\" .value=${value.class || ''} />\n `\n : html``}\n ${this._hasTextProperty(this.selected)\n ? html`\n <label> <ox-i18n msgid=\"label.text\">Text</ox-i18n> </label>\n <input value-key=\"text\" .value=${value.text || ''} />\n <label> <ox-i18n msgid=\"label.text-format\">Text Format</ox-i18n> </label>\n <input value-key=\"textFormat\" .value=${value.textFormat || ''} list=\"format-list\" />\n <datalist id=\"format-list\">\n <option value=\"#,###.\"></option>\n <option value=\"#,###.#\"></option>\n <option value=\"#,###.0\"></option>\n <option value=\"#,##0.#\"></option>\n <option value=\"#,##0.0\"></option>\n <option value=\"#,##0.0%\"></option>\n </datalist>\n `\n : html``}\n ${this._hasProperties(this.selected)\n ? html`\n <input id=\"checkbox-hidden\" value-key=\"hidden\" type=\"checkbox\" .checked=${value.hidden} />\n <label for=\"checkbox-hidden\"> <ox-i18n msgid=\"label.item-hidden\">Item Hidden</ox-i18n> </label>\n\n <input id=\"checkbox-locked\" value-key=\"locked\" type=\"checkbox\" .checked=${value.locked} />\n <label for=\"checkbox-locked\"> <ox-i18n msgid=\"label.locked\">Locked</ox-i18n> </label>\n `\n : html``}\n </div>\n </fieldset>\n\n ${!this._isLine(this.selected)\n ? keyed(\n this.selected,\n html`\n <fieldset class=\"icon-label\">\n <legend>\n <ox-title-with-help topic=\"board-modeller/shapes/size\" msgid=\"label.size\">size</ox-title-with-help>\n </legend>\n\n <div class=\"property-grid\">\n <label> <md-icon>arrow_range</md-icon><ox-i18n msgid=\"label.width\">width</ox-i18n> </label>\n <input type=\"number\" value-key=\"bounds.width\" .value=${String(width)} />\n <label> <md-icon>height</md-icon><ox-i18n msgid=\"label.height\">height</ox-i18n> </label>\n <input type=\"number\" value-key=\"bounds.height\" .value=${String(height)} />\n\n ${this.selected.length && this.selected[0].isRootModel()\n ? html``\n : html`\n <label class=\"rotate\">\n <md-icon>rotate_90_degrees_cw</md-icon><ox-i18n msgid=\"label.rotate\">rotate</ox-i18n>\n </label>\n <ox-input-angle value-key=\"rotation\" .value=${value.rotation ?? 0}> </ox-input-angle>\n `}\n </div>\n </fieldset>\n `\n )\n : html``}\n ${this._isPositionable(this.selected)\n ? keyed(\n this.selected,\n html`\n <fieldset class=\"icon-label\" collapsable ?collapsed=${!this._positionExpanded}>\n <legend\n @click=${(e: Event) => {\n this._positionExpanded = !this._positionExpanded\n }}\n >\n <ox-title-with-help topic=\"board-modeller/shapes/position\" msgid=\"label.position\"\n >position</ox-title-with-help\n >\n <md-icon>${this._positionExpanded ? 'expand_less' : 'expand_more'}</md-icon>\n </legend>\n\n <div class=\"property-grid\">\n <label>Position</label>\n <select value-key=\"position\" .value=${value.position}>\n <option value=\"\">&nbsp;</option>\n <option value=\"static\">static</option>\n <option value=\"relative\">relative</option>\n <option value=\"absolute\">absolute</option>\n <option value=\"fixed\">fixed</option>\n <option value=\"sticky\">sticky</option>\n <option value=\"popup\">popup (template)</option>\n </select>\n\n <label>Origin</label>\n <select value-key=\"origin\" .value=${value.origin}>\n <option value=\"\">&nbsp;</option>\n <option value=\"left-top\">left-top</option>\n <option value=\"center-top\">center-top</option>\n <option value=\"right-top\">right-top</option>\n <option value=\"left-middle\">left-middle</option>\n <option value=\"center-middle\">center-middle</option>\n <option value=\"right-middle\">right-middle</option>\n <option value=\"left-bottom\">left-bottom</option>\n <option value=\"center-bottom\">center-bottom</option>\n <option value=\"right-bottom\">right-bottom</option>\n </select>\n\n <label> <ox-i18n msgid=\"label.offset-x\">offset-X</ox-i18n> </label>\n <input type=\"number\" value-key=\"offsetX\" .value=${String(value.offsetX ?? '')} />\n <label> <ox-i18n msgid=\"label.offset-y\">offset-Y</ox-i18n> </label>\n <input type=\"number\" value-key=\"offsetY\" .value=${String(value.offsetY ?? '')} />\n </div>\n </fieldset>\n `\n )\n : html``}\n ${this._hasTextProperty(this.selected)\n ? html`\n <fieldset>\n <legend>\n <ox-title-with-help topic=\"board-modeller/shapes/text-box\" msgid=\"label.text-box\"\n >text box</ox-title-with-help\n >\n </legend>\n\n <div class=\"property-grid\">\n <label> <ox-i18n msgid=\"label.horizontal\">horizontal</ox-i18n> </label>\n <ox-buttons-radio value-key=\"textAlign\" .value=${value.textAlign}>\n <md-icon data-value=\"left\">format_align_left</md-icon>\n <md-icon data-value=\"center\">format_align_center</md-icon>\n <md-icon data-value=\"right\">format_align_right</md-icon>\n <md-icon data-value=\"justify\">format_align_justify</md-icon>\n </ox-buttons-radio>\n\n <label> <ox-i18n msgid=\"label.vertical\">vertical</ox-i18n> </label>\n <ox-buttons-radio value-key=\"textBaseline\" .value=${value.textBaseline}>\n <md-icon data-value=\"top\">align_vertical_top</md-icon>\n <md-icon data-value=\"middle\">align_vertical_center</md-icon>\n <md-icon data-value=\"bottom\">align_vertical_bottom</md-icon>\n </ox-buttons-radio>\n\n <input\n id=\"checkbox-support-markdown\"\n type=\"checkbox\"\n value-key=\"supportMarkdown\"\n .checked=${value.supportMarkdown}\n />\n <label for=\"checkbox-support-markdown\">\n <ox-i18n msgid=\"label.support-markdown\">Support Markdown</ox-i18n>\n </label>\n\n <input id=\"checkbox-textwrap\" type=\"checkbox\" value-key=\"textWrap\" .checked=${value.textWrap} />\n <label for=\"checkbox-textwrap\"> <ox-i18n msgid=\"label.text-wrap\">Text Wrap</ox-i18n> </label>\n\n ${!value.textWrap\n ? html` <label for=\"checkbox-textOverflow\">\n <ox-i18n msgid=\"label.text-overflow\">Text Overflow</ox-i18n>\n </label>\n <select value-key=\"textOverflow\" .value=${value.textOverflow || ''}>\n <option value=\"\" selected>none</option>\n <option value=\"ellipsis\">ellipsis</option>\n <option value=\"clip\">clip</option>\n </select>`\n : ''}\n\n <label> <ox-i18n msgid=\"label.padding\">padding</ox-i18n> </label>\n <table class=\"box-padding custom-editor\">\n <tr>\n <td class=\"slide1\"></td>\n <td class=\"slide2\"></td>\n <td class=\"slide3\"></td>\n </tr>\n <tr>\n <td class=\"slide4\"></td>\n <td class=\"slide5\">\n <input type=\"number\" value-key=\"paddingTop\" .value=${value.paddingTop || 0} />\n <input type=\"number\" value-key=\"paddingLeft\" .value=${value.paddingLeft || 0} />\n <input type=\"number\" value-key=\"paddingRight\" .value=${value.paddingRight || 0} />\n <input type=\"number\" value-key=\"paddingBottom\" .value=${value.paddingBottom || 0} />\n </td>\n <td class=\"slide6\"></td>\n </tr>\n <tr>\n <td class=\"slide7\"></td>\n <td class=\"slide8\"></td>\n <td class=\"slide9\"></td>\n </tr>\n </table>\n </div>\n </fieldset>\n `\n : html``}\n ${this.selected.length && this.selected[0].isRootModel()\n ? html`\n <fieldset class=\"icon-label\">\n <legend>\n <ox-title-with-help topic=\"board-modeller/shapes/viewer-option\" msgid=\"label.viewer-option\"\n >Viewer Option</ox-title-with-help\n >\n </legend>\n\n <div class=\"property-grid\">\n <label><ox-i18n msgid=\"label.fit\">Fit</ox-i18n></label>\n <select value-key=\"fitMode\" .value=${value.fitMode || 'ratio'}>\n <option value=\"none\">none</option>\n <option value=\"center\">center</option>\n <option value=\"ratio\" selected>ratio</option>\n <option value=\"both\">both</option>\n <option value=\"width\">width</option>\n <option value=\"height\">height</option>\n </select>\n </div>\n </fieldset>\n <fieldset class=\"icon-label\">\n <legend>\n <ox-title-with-help topic=\"board-modeller/shapes/print-option\" msgid=\"label.label-print\"\n >Print Option</ox-title-with-help\n >\n </legend>\n\n <div class=\"property-grid\">\n <label class=\"rotate\"><ox-i18n msgid=\"label.label-rotation\">Label Rotation</ox-i18n></label>\n <select value-key=\"labelRotation\" .value=${value.labelRotation || 'N'}>\n <option value=\"N\" selected>0°</option>\n <option value=\"B\">90°</option>\n <option value=\"I\">180°</option>\n <option value=\"R\">270°</option>\n </select>\n </div>\n </fieldset>\n `\n : html``}\n `\n }\n\n onValueChange(e: Event) {\n var element = e.target as HTMLElement\n var key = element.getAttribute('value-key')\n\n if (!key) {\n return\n }\n\n var value = this.getValueFromEventTarget(element)\n\n if (key.indexOf('bounds.') == 0) {\n if (isNaN(value)) return\n this.dispatchEvent(\n new CustomEvent('bounds-change', {\n bubbles: true,\n composed: true,\n detail: {\n [key.substr(7)]: value\n }\n })\n )\n } else {\n this.onAfterValueChange(key, value)\n }\n }\n\n _hasTextProperty(selected: Component[]) {\n for (let i = 0; i < selected.length; i++) {\n if (!selected[i].hasTextProperty) return false\n }\n\n return true\n }\n\n _hasProperties(selected: Component[]) {\n if (!selected || selected.length == 0 || (selected[0] && selected[0].isLayer && selected[0].isLayer())) return false\n\n return true\n }\n\n _isIdentifiable(selected: Component[]) {\n if (!selected || selected.length == 0 || selected.length > 1 || (selected[0].isLayer && selected[0].isLayer()))\n return false\n\n return true\n }\n\n _isClassIdentifiable(selected: Component[]) {\n if (!selected || (selected[0] && selected[0].isLayer())) return false\n\n return true\n }\n\n _isLine(selected: Component[]) {\n if (!selected || !(selected[0] && selected[0].isLine())) return false\n\n return true\n }\n\n _isPositionable(selected: Component[]) {\n if (!selected || !(selected[0] && selected[0].isPositionable())) return false\n\n return true\n }\n}\n"]}
1
+ {"version":3,"file":"shapes.js","sourceRoot":"","sources":["../../../../src/property-panel/shapes/shapes.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,kCAAkC,CAAA;AACzC,OAAO,oCAAoC,CAAA;AAC3C,OAAO,4BAA4B,CAAA;AACnC,OAAO,0BAA0B,CAAA;AACjC,OAAO,qCAAqC,CAAA;AAE5C,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAG/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,8CAA8C,CAAA;AAErF,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IAApD;;QAS8B,WAAM,GAAkB,IAAI,CAAA;QAC7B,aAAQ,GAAgB,EAAE,CAAA;QAEpC,sBAAiB,GAAY,KAAK,CAAA;IA2TrD,CAAC;IAzTC,YAAY;QACV,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC3E,CAAC;IAED,MAAM;;QACJ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;QAC9B,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,CAAA;QAErD,OAAO,IAAI,CAAA;;;YAGH,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC;YACnC,CAAC,CAAC,IAAI,CAAA;;+CAE6B,KAAK,CAAC,EAAE,IAAI,EAAE;eAC9C;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;YACR,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC;YACxC,CAAC,CAAC,IAAI,CAAA;;kDAEgC,KAAK,CAAC,KAAK,IAAI,EAAE;eACpD;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;YACR,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC;YACpC,CAAC,CAAC,IAAI,CAAA;;iDAE+B,KAAK,CAAC,IAAI,IAAI,EAAE;;uDAEV,KAAK,CAAC,UAAU,IAAI,EAAE;;;;;;;;;eAS9D;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;YACR,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;YAClC,CAAC,CAAC,IAAI,CAAA;0FACwE,KAAK,CAAC,MAAM;;;0FAGZ,KAAK,CAAC,MAAM;;eAEvF;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;;;;QAIZ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC5B,CAAC,CAAC,KAAK,CACH,IAAI,CAAC,QAAQ,EACb,IAAI,CAAA;;;;;;;;yEAQyD,MAAM,CAAC,KAAK,CAAC;;0EAEZ,MAAM,CAAC,MAAM,CAAC;;oBAEpE,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;gBACtD,CAAC,CAAC,IAAI,CAAA,EAAE;gBACR,CAAC,CAAC,IAAI,CAAA;;;;sEAI4C,MAAA,KAAK,CAAC,QAAQ,mCAAI,CAAC;uBAClE;;;aAGV,CACF;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;QACR,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC;YACnC,CAAC,CAAC,KAAK,CACH,IAAI,CAAC,QAAQ,EACb,IAAI,CAAA;oEACoD,CAAC,IAAI,CAAC,iBAAiB;;2BAEhE,CAAC,CAAQ,EAAE,EAAE;gBACpB,IAAI,CAAC,iBAAiB,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAA;YAClD,CAAC;;;;;6BAKU,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa;;;;;wDAK3B,KAAK,CAAC,QAAQ;;;;;;;;;;;sDAWhB,KAAK,CAAC,MAAM;;;;;;;;;;;;;;oEAcE,MAAM,CAAC,MAAA,KAAK,CAAC,OAAO,mCAAI,EAAE,CAAC;;oEAE3B,MAAM,CAAC,MAAA,KAAK,CAAC,OAAO,mCAAI,EAAE,CAAC;;;aAGlF,CACF;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;QACR,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC;YACpC,CAAC,CAAC,IAAI,CAAA;;;;;;;;;;iEAUmD,KAAK,CAAC,SAAS;;;;;;;;oEAQZ,KAAK,CAAC,YAAY;;;;;;;;;;6BAUzD,KAAK,CAAC,eAAe;;;;;;8FAM4C,KAAK,CAAC,QAAQ;;;kBAG1F,CAAC,KAAK,CAAC,QAAQ;gBACf,CAAC,CAAC,IAAI,CAAA;;;gEAGwC,KAAK,CAAC,YAAY,IAAI,EAAE;;;;gCAIxD;gBACd,CAAC,CAAC,EAAE;;;;;;;;;;;;2EAYqD,KAAK,CAAC,UAAU,IAAI,CAAC;4EACpB,KAAK,CAAC,WAAW,IAAI,CAAC;6EACrB,KAAK,CAAC,YAAY,IAAI,CAAC;8EACtB,KAAK,CAAC,aAAa,IAAI,CAAC;;;;;;;;;;;;WAY3F;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;QACR,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YACtD,CAAC,CAAC,IAAI,CAAA;;;;;;;;;;qDAUuC,KAAK,CAAC,OAAO,IAAI,OAAO;;;;;;;;;;;;;;;;;;;2DAmBlB,KAAK,CAAC,aAAa,IAAI,GAAG;;;;;;;;WAQ1E;YACH,CAAC,CAAC,IAAI,CAAA,EAAE;KACX,CAAA;IACH,CAAC;IAED,aAAa,CAAC,CAAQ;QACpB,IAAI,OAAO,GAAG,CAAC,CAAC,MAAqB,CAAA;QACrC,IAAI,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;QAE3C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAM;QACR,CAAC;QAED,IAAI,KAAK,GAAG,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAA;QAEjD,IAAI,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,KAAK,CAAC;gBAAE,OAAM;YACxB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,eAAe,EAAE;gBAC/B,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE;oBACN,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK;iBACvB;aACF,CAAC,CACH,CAAA;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;QACrC,CAAC;IACH,CAAC;IAED,gBAAgB,CAAC,QAAqB;QACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,eAAe;gBAAE,OAAO,KAAK,CAAA;QAChD,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAED,cAAc,CAAC,QAAqB;QAClC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,KAAK,CAAA;QAEpH,OAAO,IAAI,CAAA;IACb,CAAC;IAED,eAAe,CAAC,QAAqB;QACnC,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAC5G,OAAO,KAAK,CAAA;QAEd,OAAO,IAAI,CAAA;IACb,CAAC;IAED,oBAAoB,CAAC,QAAqB;QACxC,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,KAAK,CAAA;QAErE,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,CAAC,QAAqB;QAC3B,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;YAAE,OAAO,KAAK,CAAA;QAErE,OAAO,IAAI,CAAA;IACb,CAAC;IAED,eAAe,CAAC,QAAqB;QACnC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC;YAAE,OAAO,KAAK,CAAA;QAE7E,OAAO,IAAI,CAAA;IACb,CAAC;;AArUM,qBAAM,GAAG;IACd,kBAAkB;IAClB,sBAAsB;IACtB,GAAG,CAAA;KACF;CACF,AALY,CAKZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;6CAAmB;AAClB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAA6B;AAC7B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;gDAA2B;AAEpC;IAAhB,KAAK,EAAE;yDAA2C","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@operato/input/ox-input-angle.js'\nimport '@operato/input/ox-buttons-radio.js'\nimport '@material/web/icon/icon.js'\nimport '@operato/i18n/ox-i18n.js'\nimport '@operato/help/ox-title-with-help.js'\n\nimport { css, html } from 'lit'\nimport { property, state } from 'lit/decorators.js'\nimport { keyed } from 'lit/directives/keyed.js'\n\nimport { BOUNDS, Component, Properties } from '@hatiolab/things-scene'\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\nimport { BoxPaddingEditorStyles } from '@operato/styles/box-padding-editor-styles.js'\n\nimport { AbstractProperty } from '../abstract-property.js'\n\nexport class PropertyShapes extends AbstractProperty {\n static styles = [\n PropertyGridStyles,\n BoxPaddingEditorStyles,\n css`\n `\n ]\n\n @property({ type: Object }) value?: Properties\n @property({ type: Object }) bounds: BOUNDS | null = null\n @property({ type: Array }) selected: Component[] = []\n\n @state() private _positionExpanded: boolean = false\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', this.onValueChange.bind(this))\n }\n\n render() {\n const value = this.value || {}\n const { width = '', height = '' } = this.bounds || {}\n\n return html`\n <fieldset>\n <div class=\"property-grid\">\n ${this._isIdentifiable(this.selected)\n ? html`\n <label> <ox-i18n msgid=\"label.id\">ID</ox-i18n> </label>\n <input value-key=\"id\" .value=${value.id || ''} />\n `\n : html``}\n ${this._isClassIdentifiable(this.selected)\n ? html`\n <label> <ox-i18n msgid=\"label.class\">Class</ox-i18n> </label>\n <input value-key=\"class\" .value=${value.class || ''} />\n `\n : html``}\n ${this._hasTextProperty(this.selected)\n ? html`\n <label> <ox-i18n msgid=\"label.text\">Text</ox-i18n> </label>\n <input value-key=\"text\" .value=${value.text || ''} />\n <label> <ox-i18n msgid=\"label.text-format\">Text Format</ox-i18n> </label>\n <input value-key=\"textFormat\" .value=${value.textFormat || ''} list=\"format-list\" />\n <datalist id=\"format-list\">\n <option value=\"#,###.\"></option>\n <option value=\"#,###.#\"></option>\n <option value=\"#,###.0\"></option>\n <option value=\"#,##0.#\"></option>\n <option value=\"#,##0.0\"></option>\n <option value=\"#,##0.0%\"></option>\n </datalist>\n `\n : html``}\n ${this._hasProperties(this.selected)\n ? html`\n <input id=\"checkbox-hidden\" value-key=\"hidden\" type=\"checkbox\" .checked=${value.hidden} />\n <label for=\"checkbox-hidden\"> <ox-i18n msgid=\"label.item-hidden\">Item Hidden</ox-i18n> </label>\n\n <input id=\"checkbox-locked\" value-key=\"locked\" type=\"checkbox\" .checked=${value.locked} />\n <label for=\"checkbox-locked\"> <ox-i18n msgid=\"label.locked\">Locked</ox-i18n> </label>\n `\n : html``}\n </div>\n </fieldset>\n\n ${!this._isLine(this.selected)\n ? keyed(\n this.selected,\n html`\n <fieldset class=\"icon-label\">\n <legend>\n <ox-title-with-help topic=\"board-modeller/shapes/size\" msgid=\"label.size\">size</ox-title-with-help>\n </legend>\n\n <div class=\"property-grid\">\n <label> <md-icon>arrow_range</md-icon><ox-i18n msgid=\"label.width\">width</ox-i18n> </label>\n <input type=\"number\" value-key=\"bounds.width\" .value=${String(width)} />\n <label> <md-icon>height</md-icon><ox-i18n msgid=\"label.height\">height</ox-i18n> </label>\n <input type=\"number\" value-key=\"bounds.height\" .value=${String(height)} />\n\n ${this.selected.length && this.selected[0].isRootModel()\n ? html``\n : html`\n <label class=\"rotate\">\n <md-icon>rotate_90_degrees_cw</md-icon><ox-i18n msgid=\"label.rotate\">rotate</ox-i18n>\n </label>\n <ox-input-angle value-key=\"rotation\" .value=${value.rotation ?? 0}> </ox-input-angle>\n `}\n </div>\n </fieldset>\n `\n )\n : html``}\n ${this._isPositionable(this.selected)\n ? keyed(\n this.selected,\n html`\n <fieldset class=\"icon-label\" collapsable ?collapsed=${!this._positionExpanded}>\n <legend\n @click=${(e: Event) => {\n this._positionExpanded = !this._positionExpanded\n }}\n >\n <ox-title-with-help topic=\"board-modeller/shapes/position\" msgid=\"label.position\"\n >position</ox-title-with-help\n >\n <md-icon>${this._positionExpanded ? 'expand_less' : 'expand_more'}</md-icon>\n </legend>\n\n <div class=\"property-grid\">\n <label>Position</label>\n <select value-key=\"position\" .value=${value.position}>\n <option value=\"\">&nbsp;</option>\n <option value=\"static\">static</option>\n <option value=\"relative\">relative</option>\n <option value=\"absolute\">absolute</option>\n <option value=\"fixed\">fixed</option>\n <option value=\"sticky\">sticky</option>\n <option value=\"popup\">popup (template)</option>\n </select>\n\n <label>Origin</label>\n <select value-key=\"origin\" .value=${value.origin}>\n <option value=\"\">&nbsp;</option>\n <option value=\"left-top\">left-top</option>\n <option value=\"center-top\">center-top</option>\n <option value=\"right-top\">right-top</option>\n <option value=\"left-middle\">left-middle</option>\n <option value=\"center-middle\">center-middle</option>\n <option value=\"right-middle\">right-middle</option>\n <option value=\"left-bottom\">left-bottom</option>\n <option value=\"center-bottom\">center-bottom</option>\n <option value=\"right-bottom\">right-bottom</option>\n </select>\n\n <label> <ox-i18n msgid=\"label.offset-x\">offset-X</ox-i18n> </label>\n <input type=\"number\" value-key=\"offsetX\" .value=${String(value.offsetX ?? '')} />\n <label> <ox-i18n msgid=\"label.offset-y\">offset-Y</ox-i18n> </label>\n <input type=\"number\" value-key=\"offsetY\" .value=${String(value.offsetY ?? '')} />\n </div>\n </fieldset>\n `\n )\n : html``}\n ${this._hasTextProperty(this.selected)\n ? html`\n <fieldset>\n <legend>\n <ox-title-with-help topic=\"board-modeller/shapes/text-box\" msgid=\"label.text-box\"\n >text box</ox-title-with-help\n >\n </legend>\n\n <div class=\"property-grid\">\n <label> <ox-i18n msgid=\"label.horizontal\">horizontal</ox-i18n> </label>\n <ox-buttons-radio value-key=\"textAlign\" .value=${value.textAlign}>\n <md-icon data-value=\"left\">format_align_left</md-icon>\n <md-icon data-value=\"center\">format_align_center</md-icon>\n <md-icon data-value=\"right\">format_align_right</md-icon>\n <md-icon data-value=\"justify\">format_align_justify</md-icon>\n </ox-buttons-radio>\n\n <label> <ox-i18n msgid=\"label.vertical\">vertical</ox-i18n> </label>\n <ox-buttons-radio value-key=\"textBaseline\" .value=${value.textBaseline}>\n <md-icon data-value=\"top\">align_vertical_top</md-icon>\n <md-icon data-value=\"middle\">align_vertical_center</md-icon>\n <md-icon data-value=\"bottom\">align_vertical_bottom</md-icon>\n </ox-buttons-radio>\n\n <input\n id=\"checkbox-support-markdown\"\n type=\"checkbox\"\n value-key=\"supportMarkdown\"\n .checked=${value.supportMarkdown}\n />\n <label for=\"checkbox-support-markdown\">\n <ox-i18n msgid=\"label.support-markdown\">Support Markdown</ox-i18n>\n </label>\n\n <input id=\"checkbox-textwrap\" type=\"checkbox\" value-key=\"textWrap\" .checked=${value.textWrap} />\n <label for=\"checkbox-textwrap\"> <ox-i18n msgid=\"label.text-wrap\">Text Wrap</ox-i18n> </label>\n\n ${!value.textWrap\n ? html` <label for=\"checkbox-textOverflow\">\n <ox-i18n msgid=\"label.text-overflow\">Text Overflow</ox-i18n>\n </label>\n <select value-key=\"textOverflow\" .value=${value.textOverflow || ''}>\n <option value=\"\" selected>none</option>\n <option value=\"ellipsis\">ellipsis</option>\n <option value=\"clip\">clip</option>\n </select>`\n : ''}\n\n <label> <ox-i18n msgid=\"label.padding\">padding</ox-i18n> </label>\n <table class=\"box-padding custom-editor\">\n <tr>\n <td class=\"slide1\"></td>\n <td class=\"slide2\"></td>\n <td class=\"slide3\"></td>\n </tr>\n <tr>\n <td class=\"slide4\"></td>\n <td class=\"slide5\">\n <input type=\"number\" value-key=\"paddingTop\" .value=${value.paddingTop || 0} />\n <input type=\"number\" value-key=\"paddingLeft\" .value=${value.paddingLeft || 0} />\n <input type=\"number\" value-key=\"paddingRight\" .value=${value.paddingRight || 0} />\n <input type=\"number\" value-key=\"paddingBottom\" .value=${value.paddingBottom || 0} />\n </td>\n <td class=\"slide6\"></td>\n </tr>\n <tr>\n <td class=\"slide7\"></td>\n <td class=\"slide8\"></td>\n <td class=\"slide9\"></td>\n </tr>\n </table>\n </div>\n </fieldset>\n `\n : html``}\n ${this.selected.length && this.selected[0].isRootModel()\n ? html`\n <fieldset class=\"icon-label\">\n <legend>\n <ox-title-with-help topic=\"board-modeller/shapes/viewer-option\" msgid=\"label.viewer-option\"\n >Viewer Option</ox-title-with-help\n >\n </legend>\n\n <div class=\"property-grid\">\n <label><ox-i18n msgid=\"label.fit\">Fit</ox-i18n></label>\n <select value-key=\"fitMode\" .value=${value.fitMode || 'ratio'}>\n <option value=\"none\">none</option>\n <option value=\"center\">center</option>\n <option value=\"ratio\" selected>ratio</option>\n <option value=\"both\">both</option>\n <option value=\"width\">width</option>\n <option value=\"height\">height</option>\n </select>\n </div>\n </fieldset>\n <fieldset class=\"icon-label\">\n <legend>\n <ox-title-with-help topic=\"board-modeller/shapes/print-option\" msgid=\"label.label-print\"\n >Print Option</ox-title-with-help\n >\n </legend>\n\n <div class=\"property-grid\">\n <label class=\"rotate\"><ox-i18n msgid=\"label.label-rotation\">Label Rotation</ox-i18n></label>\n <select value-key=\"labelRotation\" .value=${value.labelRotation || 'N'}>\n <option value=\"N\" selected>0°</option>\n <option value=\"B\">90°</option>\n <option value=\"I\">180°</option>\n <option value=\"R\">270°</option>\n </select>\n </div>\n </fieldset>\n `\n : html``}\n `\n }\n\n onValueChange(e: Event) {\n var element = e.target as HTMLElement\n var key = element.getAttribute('value-key')\n\n if (!key) {\n return\n }\n\n var value = this.getValueFromEventTarget(element)\n\n if (key.indexOf('bounds.') == 0) {\n if (isNaN(value)) return\n this.dispatchEvent(\n new CustomEvent('bounds-change', {\n bubbles: true,\n composed: true,\n detail: {\n [key.substr(7)]: value\n }\n })\n )\n } else {\n this.onAfterValueChange(key, value)\n }\n }\n\n _hasTextProperty(selected: Component[]) {\n for (let i = 0; i < selected.length; i++) {\n if (!selected[i].hasTextProperty) return false\n }\n\n return true\n }\n\n _hasProperties(selected: Component[]) {\n if (!selected || selected.length == 0 || (selected[0] && selected[0].isLayer && selected[0].isLayer())) return false\n\n return true\n }\n\n _isIdentifiable(selected: Component[]) {\n if (!selected || selected.length == 0 || selected.length > 1 || (selected[0].isLayer && selected[0].isLayer()))\n return false\n\n return true\n }\n\n _isClassIdentifiable(selected: Component[]) {\n if (!selected || (selected[0] && selected[0].isLayer())) return false\n\n return true\n }\n\n _isLine(selected: Component[]) {\n if (!selected || !(selected[0] && selected[0].isLine())) return false\n\n return true\n }\n\n _isPositionable(selected: Component[]) {\n if (!selected || !(selected[0] && selected[0].isPositionable())) return false\n\n return true\n }\n}\n"]}
@@ -2,6 +2,7 @@
2
2
  * @license Copyright © HatioLab Inc. All rights reserved.
3
3
  */
4
4
  import '@operato/help/ox-help-icon.js';
5
+ import '../shapes/ox-placeholder-convert-editor.js';
5
6
  import { LitElement } from 'lit';
6
7
  import { Component, Scene } from '@hatiolab/things-scene';
7
8
  import { SpecificPropertiesBuilder } from './specific-properties-builder.js';
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { __decorate } from "tslib";
5
5
  import '@operato/help/ox-help-icon.js';
6
+ import '../shapes/ox-placeholder-convert-editor.js';
6
7
  import { css, html, LitElement } from 'lit';
7
8
  import { property } from 'lit/decorators.js';
8
9
  import { ScopedElementsMixin } from '@open-wc/scoped-elements';
@@ -1 +1 @@
1
- {"version":3,"file":"specifics.js","sourceRoot":"","sources":["../../../../src/property-panel/specifics/specifics.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,+BAA+B,CAAA;AAEtC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAG5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAE5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAA;AAE5E,MAAM,OAAO,gBAAiB,SAAQ,mBAAmB,CAAC,UAAU,CAAC;IAArE;;QAiB8B,UAAK,GAAiB,IAAI,CAAA;QAC3B,aAAQ,GAAgB,EAAE,CAAA;QAC1B,UAAK,GAAU,EAAE,CAAA;QACjB,mBAAc,GAAU,EAAE,CAAA;QAE7C,uBAAkB,GAAQ,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAyCnE,CAAC;IAvCC,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEzB,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAA;IACnE,CAAC;IAED,oBAAoB;QAClB,KAAK,CAAC,oBAAoB,EAAE,CAAA;QAE5B,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAA;IACtE,CAAC;IACD,MAAM,KAAK,cAAc;QACvB,OAAO;YACL,6BAA6B,EAAE,yBAAyB;SACzD,CAAA;IACH,CAAC;IACD,MAAM;;QACJ,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;QAE9B,OAAO,IAAI,CAAA;;WAEJ,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,wBAAwB,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,MAAM,0CAAE,IAAI;;;4CAGnG,KAAK,WAAW,IAAI,CAAC,KAAK,oBAAoB,IAAI,CAAC,cAAc;;KAExG,CAAA;IACH,CAAC;IAEO,eAAe,CAAC,CAAc;QACpC,CAAC,CAAC,eAAe,EAAE,CAAA;QAEnB,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAA;QAE3B,IAAI,CAAC,KAAM,CAAC,cAAc,CAAC,GAAG,EAAE;YAC9B,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;IACJ,CAAC;;AA7DM,uBAAM,GAAG;IACd,kBAAkB;IAClB,GAAG,CAAA;;;;;;;;;;KAUF;CACF,AAbY,CAaZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CAAW;AACV;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CAA2B;AAC3B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;kDAA2B;AAC1B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;+CAAkB;AACjB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;wDAA2B","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@operato/help/ox-help-icon.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { property } from 'lit/decorators.js'\n\nimport { Component, Scene } from '@hatiolab/things-scene'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\n\nimport { i18next } from '@operato/i18n'\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\n\nimport { SpecificPropertiesBuilder } from './specific-properties-builder.js'\n\nexport class PropertySpecific extends ScopedElementsMixin(LitElement) {\n static styles = [\n PropertyGridStyles,\n css`\n label {\n display: flex;\n margin: 10px;\n text-align: right;\n font: bold 14px var(--theme-font);\n color: var(--md-sys-color-on-primary-container);\n text-transform: capitalize;\n align-items: center;\n }\n `\n ]\n\n @property({ type: Object }) value: any\n @property({ type: Object }) scene: Scene | null = null\n @property({ type: Array }) selected: Component[] = []\n @property({ type: Array }) props: any[] = []\n @property({ type: Array }) propertyEditor: any[] = []\n\n private boundINeedSelected: any = this.onINeedSelected.bind(this)\n\n connectedCallback() {\n super.connectedCallback()\n\n this.addEventListener('i-need-selected', this.boundINeedSelected)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n\n this.removeEventListener('i-need-selected', this.boundINeedSelected)\n }\n static get scopedElements() {\n return {\n 'specific-properties-builder': SpecificPropertiesBuilder\n }\n }\n render() {\n const selected = this.selected && this.selected[0]\n const value = this.value || {}\n\n return html`\n <label\n >${value.type ? i18next.t(`component.${value.type}`) : i18next.t('label.mixed-selection')}<ox-help-icon .topic=${selected?.nature?.help}></ox-help-icon\n ></label>\n\n <specific-properties-builder .value=${value} .props=${this.props} .propertyEditor=${this.propertyEditor}>\n </specific-properties-builder>\n `\n }\n\n private onINeedSelected(e: CustomEvent) {\n e.stopPropagation()\n\n var { callback } = e.detail\n\n this.scene!.undoableChange(() => {\n callback.call(null, this.selected)\n })\n }\n}\n"]}
1
+ {"version":3,"file":"specifics.js","sourceRoot":"","sources":["../../../../src/property-panel/specifics/specifics.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,+BAA+B,CAAA;AACtC,OAAO,4CAA4C,CAAA;AAEnD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAG5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAE9D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAE5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAA;AAE5E,MAAM,OAAO,gBAAiB,SAAQ,mBAAmB,CAAC,UAAU,CAAC;IAArE;;QAiB8B,UAAK,GAAiB,IAAI,CAAA;QAC3B,aAAQ,GAAgB,EAAE,CAAA;QAC1B,UAAK,GAAU,EAAE,CAAA;QACjB,mBAAc,GAAU,EAAE,CAAA;QAE7C,uBAAkB,GAAQ,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAyCnE,CAAC;IAvCC,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QAEzB,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAA;IACnE,CAAC;IAED,oBAAoB;QAClB,KAAK,CAAC,oBAAoB,EAAE,CAAA;QAE5B,IAAI,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAA;IACtE,CAAC;IACD,MAAM,KAAK,cAAc;QACvB,OAAO;YACL,6BAA6B,EAAE,yBAAyB;SACzD,CAAA;IACH,CAAC;IACD,MAAM;;QACJ,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;QAE9B,OAAO,IAAI,CAAA;;WAEJ,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,wBAAwB,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,MAAM,0CAAE,IAAI;;;4CAGnG,KAAK,WAAW,IAAI,CAAC,KAAK,oBAAoB,IAAI,CAAC,cAAc;;KAExG,CAAA;IACH,CAAC;IAEO,eAAe,CAAC,CAAc;QACpC,CAAC,CAAC,eAAe,EAAE,CAAA;QAEnB,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,MAAM,CAAA;QAE3B,IAAI,CAAC,KAAM,CAAC,cAAc,CAAC,GAAG,EAAE;YAC9B,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;IACJ,CAAC;;AA7DM,uBAAM,GAAG;IACd,kBAAkB;IAClB,GAAG,CAAA;;;;;;;;;;KAUF;CACF,AAbY,CAaZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CAAW;AACV;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+CAA2B;AAC3B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;kDAA2B;AAC1B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;+CAAkB;AACjB;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;wDAA2B","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@operato/help/ox-help-icon.js'\nimport '../shapes/ox-placeholder-convert-editor.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { property } from 'lit/decorators.js'\n\nimport { Component, Scene } from '@hatiolab/things-scene'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\n\nimport { i18next } from '@operato/i18n'\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\n\nimport { SpecificPropertiesBuilder } from './specific-properties-builder.js'\n\nexport class PropertySpecific extends ScopedElementsMixin(LitElement) {\n static styles = [\n PropertyGridStyles,\n css`\n label {\n display: flex;\n margin: 10px;\n text-align: right;\n font: bold 14px var(--theme-font);\n color: var(--md-sys-color-on-primary-container);\n text-transform: capitalize;\n align-items: center;\n }\n `\n ]\n\n @property({ type: Object }) value: any\n @property({ type: Object }) scene: Scene | null = null\n @property({ type: Array }) selected: Component[] = []\n @property({ type: Array }) props: any[] = []\n @property({ type: Array }) propertyEditor: any[] = []\n\n private boundINeedSelected: any = this.onINeedSelected.bind(this)\n\n connectedCallback() {\n super.connectedCallback()\n\n this.addEventListener('i-need-selected', this.boundINeedSelected)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n\n this.removeEventListener('i-need-selected', this.boundINeedSelected)\n }\n static get scopedElements() {\n return {\n 'specific-properties-builder': SpecificPropertiesBuilder\n }\n }\n render() {\n const selected = this.selected && this.selected[0]\n const value = this.value || {}\n\n return html`\n <label\n >${value.type ? i18next.t(`component.${value.type}`) : i18next.t('label.mixed-selection')}<ox-help-icon .topic=${selected?.nature?.help}></ox-help-icon\n ></label>\n\n <specific-properties-builder .value=${value} .props=${this.props} .propertyEditor=${this.propertyEditor}>\n </specific-properties-builder>\n `\n }\n\n private onINeedSelected(e: CustomEvent) {\n e.stopPropagation()\n\n var { callback } = e.detail\n\n this.scene!.undoableChange(() => {\n callback.call(null, this.selected)\n })\n }\n}\n"]}