@operato/board 10.0.0-beta.5 → 10.0.0-beta.50
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 +408 -0
- package/dist/src/component/container.js +18 -3
- package/dist/src/component/container.js.map +1 -1
- package/dist/src/component/conveyance.d.ts +2 -0
- package/dist/src/component/conveyance.js +38 -0
- package/dist/src/component/conveyance.js.map +1 -0
- package/dist/src/component/etc.js +2 -10
- package/dist/src/component/etc.js.map +1 -1
- package/dist/src/component/facility.d.ts +2 -0
- package/dist/src/component/facility.js +35 -0
- package/dist/src/component/facility.js.map +1 -0
- package/dist/src/component/index.d.ts +5 -0
- package/dist/src/component/index.js +5 -0
- package/dist/src/component/index.js.map +1 -1
- package/dist/src/component/line.js +4 -28
- package/dist/src/component/line.js.map +1 -1
- package/dist/src/component/manufacturing.d.ts +2 -0
- package/dist/src/component/manufacturing.js +41 -0
- package/dist/src/component/manufacturing.js.map +1 -0
- package/dist/src/component/register-default-groups.js +19 -2
- package/dist/src/component/register-default-groups.js.map +1 -1
- package/dist/src/component/shape.js +5 -29
- package/dist/src/component/shape.js.map +1 -1
- package/dist/src/component/storage.d.ts +2 -0
- package/dist/src/component/storage.js +27 -0
- package/dist/src/component/storage.js.map +1 -0
- package/dist/src/component/text-and-media.js +2 -25
- package/dist/src/component/text-and-media.js.map +1 -1
- package/dist/src/component/transport.d.ts +2 -0
- package/dist/src/component/transport.js +36 -0
- package/dist/src/component/transport.js.map +1 -0
- package/dist/src/component/warehouse.d.ts +1 -0
- package/dist/src/component/warehouse.js +8 -1
- package/dist/src/component/warehouse.js.map +1 -1
- package/dist/src/data-storage/board-model-cache.d.ts +30 -0
- package/dist/src/data-storage/board-model-cache.js +93 -0
- package/dist/src/data-storage/board-model-cache.js.map +1 -0
- package/dist/src/graphql/playback-buffer.d.ts +79 -0
- package/dist/src/graphql/playback-buffer.js +139 -0
- package/dist/src/graphql/playback-buffer.js.map +1 -0
- package/dist/src/graphql/playback-buffer.test.d.ts +1 -0
- package/dist/src/graphql/playback-buffer.test.js +261 -0
- package/dist/src/graphql/playback-buffer.test.js.map +1 -0
- package/dist/src/graphql/playback-subscription.d.ts +89 -0
- package/dist/src/graphql/playback-subscription.js +258 -0
- package/dist/src/graphql/playback-subscription.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/modeller/bulk-create-dialog.d.ts +51 -0
- package/dist/src/modeller/bulk-create-dialog.js +531 -0
- package/dist/src/modeller/bulk-create-dialog.js.map +1 -0
- package/dist/src/modeller/component-toolbar/component-menu.js +8 -1
- package/dist/src/modeller/component-toolbar/component-menu.js.map +1 -1
- package/dist/src/modeller/edit-toolbar-style.js +38 -1
- package/dist/src/modeller/edit-toolbar-style.js.map +1 -1
- package/dist/src/modeller/edit-toolbar.d.ts +21 -16
- package/dist/src/modeller/edit-toolbar.js +305 -201
- package/dist/src/modeller/edit-toolbar.js.map +1 -1
- package/dist/src/modeller/scene-viewer/ox-scene-viewer.d.ts +2 -1
- package/dist/src/modeller/scene-viewer/ox-scene-viewer.js +7 -11
- package/dist/src/modeller/scene-viewer/ox-scene-viewer.js.map +1 -1
- package/dist/src/ox-board-modeller.d.ts +8 -1
- package/dist/src/ox-board-modeller.js +125 -6
- package/dist/src/ox-board-modeller.js.map +1 -1
- package/dist/src/ox-board-preview.d.ts +36 -0
- package/dist/src/ox-board-preview.js +114 -0
- package/dist/src/ox-board-preview.js.map +1 -0
- package/dist/src/ox-board-template-list.d.ts +1 -0
- package/dist/src/ox-board-template-list.js +19 -1
- package/dist/src/ox-board-template-list.js.map +1 -1
- package/dist/src/ox-board-viewer.d.ts +50 -1
- package/dist/src/ox-board-viewer.js +271 -28
- package/dist/src/ox-board-viewer.js.map +1 -1
- package/dist/src/ox-playback-controls.d.ts +56 -0
- package/dist/src/ox-playback-controls.js +515 -0
- package/dist/src/ox-playback-controls.js.map +1 -0
- package/dist/src/selector/ox-board-selector.js +11 -1
- package/dist/src/selector/ox-board-selector.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -12
- package/translations/en.json +19 -1
- package/translations/ja.json +19 -1
- package/translations/ko.json +19 -1
- package/translations/ms.json +19 -1
- package/translations/zh.json +19 -1
|
@@ -3,18 +3,28 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { __decorate } from "tslib";
|
|
5
5
|
import { html, LitElement } from 'lit';
|
|
6
|
-
import { property,
|
|
6
|
+
import { property, state } from 'lit/decorators.js';
|
|
7
7
|
import { copyToClipboard, isMacOS } from '@operato/utils';
|
|
8
|
+
import { OxPopup } from '@operato/popup';
|
|
8
9
|
import { style } from './edit-toolbar-style.js';
|
|
10
|
+
import './bulk-create-dialog.js';
|
|
9
11
|
const MACOS = isMacOS();
|
|
10
12
|
export class EditToolbar extends LitElement {
|
|
11
13
|
constructor() {
|
|
12
14
|
super(...arguments);
|
|
13
15
|
this.selected = [];
|
|
14
16
|
this.hideProperty = false;
|
|
17
|
+
this._dimension = null;
|
|
18
|
+
this._gizmoAttached = false;
|
|
15
19
|
}
|
|
16
20
|
firstUpdated() {
|
|
17
21
|
this.addEventListener('mousewheel', this.onWheelEvent.bind(this), false);
|
|
22
|
+
// 툴바 버튼 클릭 후 씬으로 포커스를 돌려서 키보드 단축키가 계속 작동하도록 한다
|
|
23
|
+
this.addEventListener('click', () => {
|
|
24
|
+
var _a, _b, _c;
|
|
25
|
+
;
|
|
26
|
+
(_c = (_b = (_a = this.scene) === null || _a === void 0 ? void 0 : _a.root) === null || _b === void 0 ? void 0 : _b.element) === null || _c === void 0 ? void 0 : _c.focus();
|
|
27
|
+
});
|
|
18
28
|
window.addEventListener('paste', (e) => {
|
|
19
29
|
var _a;
|
|
20
30
|
try {
|
|
@@ -24,33 +34,7 @@ export class EditToolbar extends LitElement {
|
|
|
24
34
|
console.error('model paste failed', e);
|
|
25
35
|
}
|
|
26
36
|
});
|
|
27
|
-
|
|
28
|
-
this.zorders.forEach(zorder => zorder.addEventListener('click', this.onTapZorder.bind(this)));
|
|
29
|
-
this.distributes.forEach(distribute => distribute.addEventListener('click', this.onTapDistribute.bind(this)));
|
|
30
|
-
this.undo.addEventListener('click', this.onTapUndo.bind(this));
|
|
31
|
-
this.redo.addEventListener('click', this.onTapRedo.bind(this));
|
|
32
|
-
this.fullscreen.addEventListener('click', this.onTapFullscreen.bind(this));
|
|
33
|
-
this.styleCopy.addEventListener('click', this.onStartStylePasteMode.bind(this));
|
|
34
|
-
this.databindCopy.addEventListener('click', this.onStartDatabindPasteMode.bind(this));
|
|
35
|
-
this.cut.addEventListener('click', this.onTapCut.bind(this));
|
|
36
|
-
this.copy.addEventListener('click', this.onTapCopy.bind(this));
|
|
37
|
-
this.paste.addEventListener('click', this.onTapPaste.bind(this));
|
|
38
|
-
this.delete.addEventListener('click', this.onTapDelete.bind(this));
|
|
39
|
-
this.renderRoot
|
|
40
|
-
.querySelector('#font-increase')
|
|
41
|
-
.addEventListener('click', this.onTapFontIncrease.bind(this));
|
|
42
|
-
this.renderRoot
|
|
43
|
-
.querySelector('#font-decrease')
|
|
44
|
-
.addEventListener('click', this.onTapFontDecrease.bind(this));
|
|
45
|
-
this.renderRoot.querySelector('#group').addEventListener('click', this.onTapGroup.bind(this));
|
|
46
|
-
this.renderRoot.querySelector('#ungroup').addEventListener('click', this.onTapUngroup.bind(this));
|
|
47
|
-
this.renderRoot
|
|
48
|
-
.querySelector('#toggle-property')
|
|
49
|
-
.addEventListener('click', this.onTapToggle.bind(this));
|
|
50
|
-
this.renderRoot
|
|
51
|
-
.querySelector('#fit-scene')
|
|
52
|
-
.addEventListener('click', this.onTapFitScene.bind(this));
|
|
53
|
-
this.renderRoot.querySelector('#preview').addEventListener('click', this.onTapPreview.bind(this));
|
|
37
|
+
// 모든 버튼은 템플릿 @click 디렉티브로 바인딩 — 조건부 렌더링 시에도 정상 작동
|
|
54
38
|
}
|
|
55
39
|
updated(changes) {
|
|
56
40
|
changes.has('scene') && this.onSceneChanged(this.scene, changes.get('scene'));
|
|
@@ -61,127 +45,122 @@ export class EditToolbar extends LitElement {
|
|
|
61
45
|
<div tools>
|
|
62
46
|
<span><slot></slot></span>
|
|
63
47
|
|
|
64
|
-
<span button id="undo" title="undo (${this.getShortcutString('cmd', 'z')})"> </span>
|
|
65
|
-
<span button id="redo" title="redo (${this.getShortcutString('cmd', 'shift', 'z')})"> </span>
|
|
48
|
+
<span button id="undo" title="undo (${this.getShortcutString('cmd', 'z')})" @click=${this.onTapUndo}> </span>
|
|
49
|
+
<span button id="redo" title="redo (${this.getShortcutString('cmd', 'shift', 'z')})" @click=${this.onTapRedo}> </span>
|
|
66
50
|
|
|
67
51
|
<span class="vline"></span>
|
|
68
52
|
|
|
69
|
-
<span button id="style-copy" title="style copy (${this.getShortcutString('cmd', '1')})"> </span>
|
|
70
|
-
<span button id="databind-copy" title="databind copy (${this.getShortcutString('cmd', '2')})"> </span>
|
|
53
|
+
<span button id="style-copy" title="style copy (${this.getShortcutString('cmd', '1')})" @click=${this.onStartStylePasteMode}> </span>
|
|
54
|
+
<span button id="databind-copy" title="databind copy (${this.getShortcutString('cmd', '2')})" @click=${this.onStartDatabindPasteMode}> </span>
|
|
71
55
|
|
|
72
56
|
<span class="vline"></span>
|
|
73
57
|
|
|
74
|
-
<span button id="cut" title="cut (${this.getShortcutString('cmd', 'x')})"> </span>
|
|
75
|
-
<span button id="copy" title="copy (${this.getShortcutString('cmd', 'c')})"> </span>
|
|
76
|
-
<span button id="paste" title="paste (${this.getShortcutString('cmd', 'v')})"> </span>
|
|
77
|
-
<span
|
|
78
|
-
button
|
|
79
|
-
id="delete"
|
|
58
|
+
<span button id="cut" title="cut (${this.getShortcutString('cmd', 'x')})" @click=${this.onTapCut}> </span>
|
|
59
|
+
<span button id="copy" title="copy (${this.getShortcutString('cmd', 'c')})" @click=${this.onTapCopy}> </span>
|
|
60
|
+
<span button id="paste" title="paste (${this.getShortcutString('cmd', 'v')})" @click=${this.onTapPaste}> </span>
|
|
61
|
+
<span button id="delete"
|
|
80
62
|
title="delete (${this.getShortcutString('backspace')}, ${this.getShortcutString('delete')})"
|
|
81
|
-
|
|
82
|
-
</span>
|
|
63
|
+
@click=${this.onTapDelete}> </span>
|
|
83
64
|
|
|
84
65
|
<span class="vline"></span>
|
|
85
66
|
|
|
86
|
-
<span
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
</span>
|
|
93
|
-
<span
|
|
94
|
-
button
|
|
95
|
-
data-align="center"
|
|
96
|
-
id="align-center"
|
|
97
|
-
title="align center (${this.getShortcutString('alt', 'shift', 'c')})"
|
|
98
|
-
>
|
|
99
|
-
</span>
|
|
100
|
-
<span
|
|
101
|
-
button
|
|
102
|
-
data-align="right"
|
|
103
|
-
id="align-right"
|
|
104
|
-
title="align right (${this.getShortcutString('alt', 'shift', 'r')})"
|
|
105
|
-
>
|
|
106
|
-
</span>
|
|
67
|
+
<span button data-align="left" id="align-left"
|
|
68
|
+
title="align left (${this.getShortcutString('alt', 'shift', 'l')})" @click=${this.onTapAlign}> </span>
|
|
69
|
+
<span button data-align="center" id="align-center"
|
|
70
|
+
title="align center (${this.getShortcutString('alt', 'shift', 'c')})" @click=${this.onTapAlign}> </span>
|
|
71
|
+
<span button data-align="right" id="align-right"
|
|
72
|
+
title="align right (${this.getShortcutString('alt', 'shift', 'r')})" @click=${this.onTapAlign}> </span>
|
|
107
73
|
|
|
108
|
-
<span button data-align="top" id="align-top"
|
|
109
|
-
|
|
110
|
-
<span
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
title="align middle (${this.getShortcutString('alt', 'shift', 'm')})"
|
|
115
|
-
>
|
|
116
|
-
</span>
|
|
117
|
-
<span
|
|
118
|
-
button
|
|
119
|
-
data-align="bottom"
|
|
120
|
-
id="align-bottom"
|
|
121
|
-
title="align bottom (${this.getShortcutString('alt', 'shift', 'b')})"
|
|
122
|
-
>
|
|
123
|
-
</span>
|
|
74
|
+
<span button data-align="top" id="align-top"
|
|
75
|
+
title="align top (${this.getShortcutString('alt', 'shift', 't')})" @click=${this.onTapAlign}> </span>
|
|
76
|
+
<span button data-align="middle" id="align-middle"
|
|
77
|
+
title="align middle (${this.getShortcutString('alt', 'shift', 'm')})" @click=${this.onTapAlign}> </span>
|
|
78
|
+
<span button data-align="bottom" id="align-bottom"
|
|
79
|
+
title="align bottom (${this.getShortcutString('alt', 'shift', 'b')})" @click=${this.onTapAlign}> </span>
|
|
124
80
|
|
|
125
|
-
<span
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
title="distribute horizontally (${this.getShortcutString('alt', 'shift', 'h')})"
|
|
130
|
-
>
|
|
131
|
-
</span>
|
|
81
|
+
<span button data-distribute="HORIZONTAL" id="distribute-horizontal"
|
|
82
|
+
title="distribute horizontally (${this.getShortcutString('alt', 'shift', 'h')})" @click=${this.onTapDistribute}> </span>
|
|
83
|
+
<span button data-distribute="VERTICAL" id="distribute-vertical"
|
|
84
|
+
title="distribute vertically (${this.getShortcutString('alt', 'shift', 'v')})" @click=${this.onTapDistribute}> </span>
|
|
132
85
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
id="distribute-vertical"
|
|
137
|
-
title="distribute vertically (${this.getShortcutString('alt', 'shift', 'v')})"
|
|
138
|
-
>
|
|
139
|
-
</span>
|
|
86
|
+
${this._dimension === '3d'
|
|
87
|
+
? html `
|
|
88
|
+
<span class="vline"></span>
|
|
140
89
|
|
|
141
|
-
|
|
90
|
+
<span button data-align="z-front" id="align-z-front" title="align Z front" @click=${this.onTapAlign}> </span>
|
|
91
|
+
<span button data-align="z-middle" id="align-z-middle" title="align Z middle" @click=${this.onTapAlign}> </span>
|
|
92
|
+
<span button data-align="z-back" id="align-z-back" title="align Z back" @click=${this.onTapAlign}> </span>
|
|
93
|
+
<span button data-distribute="Z" id="distribute-z" title="distribute Z" @click=${this.onTapDistribute}> </span>
|
|
94
|
+
`
|
|
95
|
+
: this._dimension === '2d'
|
|
96
|
+
? html `
|
|
97
|
+
<span class="vline"></span>
|
|
142
98
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
</span>
|
|
154
|
-
<span button id="backward" data-zorder="backward" title="send backward (${this.getShortcutString('cmd', 'b')})">
|
|
155
|
-
</span>
|
|
99
|
+
<span button id="front" data-zorder="front"
|
|
100
|
+
title="bring to front (${this.getShortcutString('cmd', 'shift', 'f')})" @click=${this.onTapZorder}> </span>
|
|
101
|
+
<span button id="back" data-zorder="back"
|
|
102
|
+
title="send to back (${this.getShortcutString('cmd', 'shift', 'b')})" @click=${this.onTapZorder}> </span>
|
|
103
|
+
<span button id="forward" data-zorder="forward"
|
|
104
|
+
title="bring forward (${this.getShortcutString('cmd', 'f')})" @click=${this.onTapZorder}> </span>
|
|
105
|
+
<span button id="backward" data-zorder="backward"
|
|
106
|
+
title="send backward (${this.getShortcutString('cmd', 'b')})" @click=${this.onTapZorder}> </span>
|
|
107
|
+
`
|
|
108
|
+
: ''}
|
|
156
109
|
|
|
157
|
-
|
|
110
|
+
${this._dimension === '2d' ? html `
|
|
111
|
+
<span class="vline"></span>
|
|
158
112
|
|
|
159
|
-
|
|
160
|
-
|
|
113
|
+
<span button id="group" title="group (${this.getShortcutString('cmd', 'g')})" @click=${this.onTapGroup}> </span>
|
|
114
|
+
<span button id="ungroup" title="ungroup (${this.getShortcutString('cmd', 'shift', 'g')})" @click=${this.onTapUngroup}> </span>
|
|
115
|
+
` : this._dimension === '3d' ? html `
|
|
116
|
+
<span class="vline"></span>
|
|
117
|
+
|
|
118
|
+
<span button class="gizmo-btn" data-gizmo="translate" title="Move (W)"
|
|
119
|
+
@click=${() => this._setGizmoMode('translate')}>
|
|
120
|
+
<svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8">
|
|
121
|
+
<line x1="10" y1="2" x2="10" y2="18"/><line x1="2" y1="10" x2="18" y2="10"/>
|
|
122
|
+
<polyline points="10,2 7.5,5"/><polyline points="10,2 12.5,5"/>
|
|
123
|
+
<polyline points="18,10 15,7.5"/><polyline points="18,10 15,12.5"/>
|
|
124
|
+
<polyline points="10,18 7.5,15"/><polyline points="10,18 12.5,15"/>
|
|
125
|
+
<polyline points="2,10 5,7.5"/><polyline points="2,10 5,12.5"/>
|
|
126
|
+
</svg>
|
|
127
|
+
</span>
|
|
128
|
+
<span button class="gizmo-btn" data-gizmo="rotate" title="Rotate (E)"
|
|
129
|
+
@click=${() => this._setGizmoMode('rotate')}>
|
|
130
|
+
<svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8">
|
|
131
|
+
<path d="M14.5 3.5A7 7 0 1 0 17 10"/>
|
|
132
|
+
<polyline points="14,1 15,3.5 12.5,4.5"/>
|
|
133
|
+
</svg>
|
|
134
|
+
</span>
|
|
135
|
+
<span button class="gizmo-btn" data-gizmo="scale" title="Scale (R)"
|
|
136
|
+
@click=${() => this._setGizmoMode('scale')}>
|
|
137
|
+
<svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8">
|
|
138
|
+
<line x1="4" y1="16" x2="16" y2="4"/>
|
|
139
|
+
<rect x="2" y="13" width="4" height="4" rx="0.5" fill="currentColor"/>
|
|
140
|
+
<rect x="14" y="2" width="4" height="4" rx="0.5" fill="currentColor"/>
|
|
141
|
+
</svg>
|
|
142
|
+
</span>
|
|
143
|
+
` : ''}
|
|
161
144
|
|
|
162
145
|
<span class="vline"></span>
|
|
163
146
|
|
|
164
|
-
<span button id="font-increase" title="increase font size"></span>
|
|
165
|
-
<span button id="font-decrease" title="decrease font size" style="scale: 0.7;"></span>
|
|
147
|
+
<span button id="font-increase" title="increase font size" @click=${this.onTapFontIncrease}></span>
|
|
148
|
+
<span button id="font-decrease" title="decrease font size" style="scale: 0.7;" @click=${this.onTapFontDecrease}></span>
|
|
166
149
|
|
|
167
150
|
<span class="vline"></span>
|
|
168
151
|
<span padding></span>
|
|
169
152
|
|
|
170
|
-
<span button id="fit-scene" title="fit scene (${this.getShortcutString('cmd', 'd')})"> </span>
|
|
153
|
+
<span button id="fit-scene" title="fit scene (${this.getShortcutString('cmd', 'd')})" @click=${this.onTapFitScene}> </span>
|
|
171
154
|
|
|
172
155
|
<span class="vline"></span>
|
|
173
156
|
|
|
174
|
-
<span button id="preview" title="preview (${this.getShortcutString('ctrl', 'p')})"> </span>
|
|
157
|
+
<span button id="preview" title="preview (${this.getShortcutString('ctrl', 'p')})" @click=${this.onTapPreview}> </span>
|
|
175
158
|
|
|
176
|
-
<span button id="fullscreen" title="fullscreen (${this.getShortcutString('f11')})"> </span>
|
|
159
|
+
<span button id="fullscreen" title="fullscreen (${this.getShortcutString('f11')})" @click=${this.onTapFullscreen}> </span>
|
|
177
160
|
|
|
178
|
-
<span
|
|
179
|
-
button
|
|
180
|
-
id="toggle-property"
|
|
161
|
+
<span button id="toggle-property"
|
|
181
162
|
title="toggle property panel (${this.getShortcutString('cmd', 'h')})"
|
|
182
|
-
toggles="true"
|
|
183
|
-
>
|
|
184
|
-
</span>
|
|
163
|
+
toggles="true" @click=${this.onTapToggle}> </span>
|
|
185
164
|
</div>
|
|
186
165
|
`;
|
|
187
166
|
}
|
|
@@ -224,7 +203,7 @@ export class EditToolbar extends LitElement {
|
|
|
224
203
|
return symbols.join(MACOS ? '' : '+');
|
|
225
204
|
}
|
|
226
205
|
onShortcut(e) {
|
|
227
|
-
var _a, _b, _c, _d;
|
|
206
|
+
var _a, _b, _c, _d, _e, _f;
|
|
228
207
|
if (MACOS)
|
|
229
208
|
var ctrlKey = e.metaKey;
|
|
230
209
|
else
|
|
@@ -262,7 +241,12 @@ export class EditToolbar extends LitElement {
|
|
|
262
241
|
this.onTapCut();
|
|
263
242
|
break;
|
|
264
243
|
case 'KeyV':
|
|
265
|
-
if (ctrlKey && !
|
|
244
|
+
if (ctrlKey && shiftKey && !altKey) {
|
|
245
|
+
// Ctrl+Shift+V = Bulk Paste — 클립보드의 *단일* 컴포넌트를 N개로 일괄 붙여넣기.
|
|
246
|
+
this.onBulkPaste();
|
|
247
|
+
defaultPrevent = true;
|
|
248
|
+
}
|
|
249
|
+
else if (ctrlKey && !shiftKey) {
|
|
266
250
|
this.onTapPaste();
|
|
267
251
|
defaultPrevent = false;
|
|
268
252
|
}
|
|
@@ -275,23 +259,43 @@ export class EditToolbar extends LitElement {
|
|
|
275
259
|
defaultPrevent = true;
|
|
276
260
|
break;
|
|
277
261
|
case 'KeyG':
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
262
|
+
if (this._dimension === '2d') {
|
|
263
|
+
if (ctrlKey && !shiftKey)
|
|
264
|
+
this.onTapGroup();
|
|
265
|
+
else if (ctrlKey && shiftKey)
|
|
266
|
+
this.onTapUngroup();
|
|
267
|
+
}
|
|
282
268
|
break;
|
|
283
|
-
case '
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
(
|
|
269
|
+
case 'BracketRight':
|
|
270
|
+
// Ctrl+] = Bring Forward, Ctrl+Shift+] = Bring to Front
|
|
271
|
+
// (Photoshop / Illustrator 표준 컨벤션)
|
|
272
|
+
if (this._dimension === '2d') {
|
|
273
|
+
if (ctrlKey && !shiftKey) {
|
|
274
|
+
(_a = this.scene) === null || _a === void 0 ? void 0 : _a.zorder('forward');
|
|
275
|
+
defaultPrevent = true;
|
|
276
|
+
}
|
|
277
|
+
else if (ctrlKey && shiftKey) {
|
|
278
|
+
(_b = this.scene) === null || _b === void 0 ? void 0 : _b.zorder('front');
|
|
279
|
+
defaultPrevent = true;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
break;
|
|
283
|
+
case 'BracketLeft':
|
|
284
|
+
// Ctrl+[ = Send Backward, Ctrl+Shift+[ = Send to Back
|
|
285
|
+
if (this._dimension === '2d') {
|
|
286
|
+
if (ctrlKey && !shiftKey) {
|
|
287
|
+
(_c = this.scene) === null || _c === void 0 ? void 0 : _c.zorder('backward');
|
|
288
|
+
defaultPrevent = true;
|
|
289
|
+
}
|
|
290
|
+
else if (ctrlKey && shiftKey) {
|
|
291
|
+
(_d = this.scene) === null || _d === void 0 ? void 0 : _d.zorder('back');
|
|
292
|
+
defaultPrevent = true;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
288
295
|
break;
|
|
289
296
|
case 'KeyB':
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
else if (ctrlKey && shiftKey)
|
|
293
|
-
(_d = this.scene) === null || _d === void 0 ? void 0 : _d.zorder('back');
|
|
294
|
-
else if (altKey && shiftKey)
|
|
297
|
+
// zorder 는 BracketLeft 로 이동. KeyB 의 Alt+Shift+B = align bottom 만 유지.
|
|
298
|
+
if (altKey && shiftKey)
|
|
295
299
|
this.onTapAlign('bottom');
|
|
296
300
|
break;
|
|
297
301
|
case 'KeyH':
|
|
@@ -335,23 +339,38 @@ export class EditToolbar extends LitElement {
|
|
|
335
339
|
this.onTapFitScene();
|
|
336
340
|
defaultPrevent = true;
|
|
337
341
|
}
|
|
342
|
+
else if (!shiftKey && !altKey) {
|
|
343
|
+
const target = e.composedPath()[0];
|
|
344
|
+
const tagName = target.tagName;
|
|
345
|
+
if (!target.isContentEditable && tagName !== 'INPUT' && tagName !== 'SELECT' && tagName !== 'TEXTAREA') {
|
|
346
|
+
this.onTapDataBinding();
|
|
347
|
+
defaultPrevent = true;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
338
350
|
break;
|
|
339
351
|
case 'KeyE':
|
|
340
352
|
if (ctrlKey && shiftKey)
|
|
341
353
|
this.onTapDownloadModel();
|
|
342
354
|
break;
|
|
355
|
+
case 'F10':
|
|
356
|
+
this.onTapEditModel();
|
|
357
|
+
defaultPrevent = true;
|
|
358
|
+
break;
|
|
343
359
|
case 'Digit1':
|
|
344
360
|
if (ctrlKey) {
|
|
345
|
-
console.log('MODEL', this.scene && this.scene.model);
|
|
346
361
|
defaultPrevent = true;
|
|
347
362
|
}
|
|
348
363
|
break;
|
|
349
364
|
case 'Digit2':
|
|
350
365
|
if (ctrlKey) {
|
|
351
|
-
console.log('SELECTED', this.scene && this.scene.selected);
|
|
352
366
|
defaultPrevent = true;
|
|
353
367
|
}
|
|
354
368
|
break;
|
|
369
|
+
case 'Escape':
|
|
370
|
+
(_e = this.scene) === null || _e === void 0 ? void 0 : _e.stopStylePasteMode();
|
|
371
|
+
(_f = this.scene) === null || _f === void 0 ? void 0 : _f.stopDatabindPasteMode();
|
|
372
|
+
defaultPrevent = true;
|
|
373
|
+
break;
|
|
355
374
|
default:
|
|
356
375
|
return false;
|
|
357
376
|
}
|
|
@@ -359,40 +378,75 @@ export class EditToolbar extends LitElement {
|
|
|
359
378
|
e.preventDefault();
|
|
360
379
|
return true;
|
|
361
380
|
}
|
|
381
|
+
_setDisabled(id, disabled) {
|
|
382
|
+
const el = this.renderRoot.querySelector(`#${id}`);
|
|
383
|
+
disabled ? el === null || el === void 0 ? void 0 : el.setAttribute('disabled', '') : el === null || el === void 0 ? void 0 : el.removeAttribute('disabled');
|
|
384
|
+
}
|
|
362
385
|
onExecute(command, undoable, redoable) {
|
|
363
|
-
|
|
364
|
-
|
|
386
|
+
this._setDisabled('undo', !undoable);
|
|
387
|
+
this._setDisabled('redo', !redoable);
|
|
365
388
|
}
|
|
366
389
|
onUndo(undoable, redoable) {
|
|
367
|
-
|
|
368
|
-
|
|
390
|
+
this._setDisabled('undo', !undoable);
|
|
391
|
+
this._setDisabled('redo', !redoable);
|
|
369
392
|
}
|
|
370
393
|
onRedo(undoable, redoable) {
|
|
371
|
-
|
|
372
|
-
|
|
394
|
+
this._setDisabled('undo', !undoable);
|
|
395
|
+
this._setDisabled('redo', !redoable);
|
|
373
396
|
}
|
|
374
397
|
onSceneChanged(after, before) {
|
|
398
|
+
var _a, _b;
|
|
375
399
|
if (before) {
|
|
376
400
|
before.off('execute', this.onExecute, this);
|
|
377
401
|
before.off('undo', this.onUndo, this);
|
|
378
402
|
before.off('redo', this.onRedo, this);
|
|
403
|
+
before.off('dimension', this._onDimensionChanged, this);
|
|
404
|
+
before.off('gizmoattach', this._onGizmoAttachChanged, this);
|
|
379
405
|
}
|
|
380
406
|
if (after) {
|
|
381
407
|
after.on('execute', this.onExecute, this);
|
|
382
408
|
after.on('undo', this.onUndo, this);
|
|
383
409
|
after.on('redo', this.onRedo, this);
|
|
410
|
+
after.on('dimension', this._onDimensionChanged, this);
|
|
411
|
+
after.on('gizmoattach', this._onGizmoAttachChanged, this);
|
|
412
|
+
// scene 설정 시 현재 dimension을 즉시 반영 (초기 이벤트를 놓친 경우 대비)
|
|
413
|
+
const threed = (_b = (_a = after.model_layer) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.threed;
|
|
414
|
+
this._dimension = threed ? '3d' : '2d';
|
|
384
415
|
}
|
|
385
416
|
}
|
|
417
|
+
_onDimensionChanged(dimension) {
|
|
418
|
+
this._dimension = dimension;
|
|
419
|
+
}
|
|
420
|
+
_onGizmoAttachChanged(isAttached) {
|
|
421
|
+
this._gizmoAttached = isAttached;
|
|
422
|
+
}
|
|
423
|
+
_setGizmoMode(mode) {
|
|
424
|
+
var _a, _b;
|
|
425
|
+
;
|
|
426
|
+
(_b = (_a = this.scene) === null || _a === void 0 ? void 0 : _a.root) === null || _b === void 0 ? void 0 : _b.setGizmoMode(mode);
|
|
427
|
+
}
|
|
386
428
|
onSelectedChanged(after, before) {
|
|
429
|
+
var hasSelection = after.length > 0;
|
|
387
430
|
var alignable = after.length > 1;
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
431
|
+
['style-copy', 'databind-copy', 'cut', 'copy', 'delete'].forEach(id => this._setDisabled(id, !hasSelection));
|
|
432
|
+
// 정렬 버튼
|
|
433
|
+
this.renderRoot.querySelectorAll('[data-align]').forEach(el => alignable ? el.removeAttribute('disabled') : el.setAttribute('disabled', ''));
|
|
434
|
+
if (this._dimension === '2d') {
|
|
435
|
+
var movable = after.length === 1;
|
|
436
|
+
/* forward, backward 이동은 한 컴포넌트만 가능하다. */
|
|
437
|
+
this._setDisabled('forward', !movable);
|
|
438
|
+
this._setDisabled('backward', !movable);
|
|
439
|
+
/* 여러 컴포넌트는 front, back 이동이 가능하다. */
|
|
440
|
+
this._setDisabled('front', !(alignable || movable));
|
|
441
|
+
this._setDisabled('back', !(alignable || movable));
|
|
442
|
+
}
|
|
443
|
+
// 분배 버튼
|
|
444
|
+
this.renderRoot.querySelectorAll('[data-distribute]').forEach(el => alignable ? el.removeAttribute('disabled') : el.setAttribute('disabled', ''));
|
|
445
|
+
if (this._dimension === '3d') {
|
|
446
|
+
this.renderRoot.querySelectorAll('.gizmo-btn').forEach(btn => {
|
|
447
|
+
hasSelection ? btn.removeAttribute('disabled') : btn.setAttribute('disabled', '');
|
|
448
|
+
});
|
|
449
|
+
}
|
|
396
450
|
}
|
|
397
451
|
onTapUndo() {
|
|
398
452
|
var _a;
|
|
@@ -403,12 +457,20 @@ export class EditToolbar extends LitElement {
|
|
|
403
457
|
(_a = this.scene) === null || _a === void 0 ? void 0 : _a.redo();
|
|
404
458
|
}
|
|
405
459
|
onStartStylePasteMode() {
|
|
406
|
-
var _a;
|
|
407
|
-
(_a = this.
|
|
460
|
+
var _a, _b, _c;
|
|
461
|
+
if (((_a = this.selected) === null || _a === void 0 ? void 0 : _a.length) !== 1)
|
|
462
|
+
return;
|
|
463
|
+
if (this.selected[0] === ((_b = this.scene) === null || _b === void 0 ? void 0 : _b.root))
|
|
464
|
+
return;
|
|
465
|
+
(_c = this.scene) === null || _c === void 0 ? void 0 : _c.startStylePasteMode();
|
|
408
466
|
}
|
|
409
467
|
onStartDatabindPasteMode() {
|
|
410
|
-
var _a;
|
|
411
|
-
(_a = this.
|
|
468
|
+
var _a, _b, _c;
|
|
469
|
+
if (((_a = this.selected) === null || _a === void 0 ? void 0 : _a.length) !== 1)
|
|
470
|
+
return;
|
|
471
|
+
if (this.selected[0] === ((_b = this.scene) === null || _b === void 0 ? void 0 : _b.root))
|
|
472
|
+
return;
|
|
473
|
+
(_c = this.scene) === null || _c === void 0 ? void 0 : _c.startDatabindPasteMode();
|
|
412
474
|
}
|
|
413
475
|
onTapCut() {
|
|
414
476
|
var _a;
|
|
@@ -432,6 +494,84 @@ export class EditToolbar extends LitElement {
|
|
|
432
494
|
var _a;
|
|
433
495
|
(_a = this.scene) === null || _a === void 0 ? void 0 : _a.remove();
|
|
434
496
|
}
|
|
497
|
+
/**
|
|
498
|
+
* 멀티 컴포넌트 일괄 붙여넣기 — Ctrl+Shift+V 진입점.
|
|
499
|
+
*
|
|
500
|
+
* 흐름:
|
|
501
|
+
* 1. 클립보드 (this.cliped) 검증 — *단일* 컴포넌트만 허용
|
|
502
|
+
* 2. scene.startBulkCreateMode → AddLayer 가 캔버스 위에 드래그 박스 그림
|
|
503
|
+
* 3. 사용자가 영역 드래그 → Promise resolve({area, template})
|
|
504
|
+
* ESC/취소 → Promise resolve(null)
|
|
505
|
+
* 4. 영역이 결정되면 dialog 오픈
|
|
506
|
+
*/
|
|
507
|
+
async onBulkPaste() {
|
|
508
|
+
var _a;
|
|
509
|
+
if (!this.cliped) {
|
|
510
|
+
console.warn('bulk-paste: 먼저 Ctrl+C 로 컴포넌트를 복사하세요.');
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
let parsed;
|
|
514
|
+
try {
|
|
515
|
+
parsed = JSON.parse(this.cliped);
|
|
516
|
+
}
|
|
517
|
+
catch (e) {
|
|
518
|
+
console.warn('bulk-paste: 클립보드 파싱 실패', e);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
if (!Array.isArray(parsed) || parsed.length === 0)
|
|
522
|
+
return;
|
|
523
|
+
if (parsed.length > 1) {
|
|
524
|
+
console.warn('bulk-paste: 단일 컴포넌트만 일괄 붙여넣기 가능. 다중은 일반 paste 사용.');
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
const template = parsed[0];
|
|
528
|
+
// bulk 모드 임을 시각 구분하기 위해 파란 점선 (일반 add 의 검정과 색만 차별).
|
|
529
|
+
const result = await ((_a = this.scene) === null || _a === void 0 ? void 0 : _a.startBulkCreateMode(template, { boxStrokeStyle: '#2964c2' }));
|
|
530
|
+
if (result) {
|
|
531
|
+
this._openBulkCreateDialog(template, result.area);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
_openBulkCreateDialog(template, initialArea) {
|
|
535
|
+
var _a;
|
|
536
|
+
const dialogEl = document.createElement('bulk-create-dialog');
|
|
537
|
+
dialogEl.template = template;
|
|
538
|
+
dialogEl.initialArea = initialArea;
|
|
539
|
+
// scene 의 모든 id 수집 — indexMap 기반 scene.ids 대신 트리 walk 로 안정성 확보.
|
|
540
|
+
const existingIds = new Set();
|
|
541
|
+
const collectIds = (comp) => {
|
|
542
|
+
var _a, _b, _c;
|
|
543
|
+
if (!comp)
|
|
544
|
+
return;
|
|
545
|
+
const id = (_b = (_a = comp === null || comp === void 0 ? void 0 : comp.state) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : (_c = comp === null || comp === void 0 ? void 0 : comp.model) === null || _c === void 0 ? void 0 : _c.id;
|
|
546
|
+
if (typeof id === 'string' && id)
|
|
547
|
+
existingIds.add(id);
|
|
548
|
+
const children = comp.components || [];
|
|
549
|
+
for (const c of children)
|
|
550
|
+
collectIds(c);
|
|
551
|
+
};
|
|
552
|
+
const root = (_a = this.scene) === null || _a === void 0 ? void 0 : _a.root;
|
|
553
|
+
if (root)
|
|
554
|
+
collectIds(root);
|
|
555
|
+
dialogEl.existingIds = existingIds;
|
|
556
|
+
dialogEl.onConfirm = (models) => {
|
|
557
|
+
const scene = this.scene;
|
|
558
|
+
if (!scene || !models.length) {
|
|
559
|
+
popup === null || popup === void 0 ? void 0 : popup.close();
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
scene.undoableChange(() => {
|
|
563
|
+
scene.add(models, {});
|
|
564
|
+
});
|
|
565
|
+
popup === null || popup === void 0 ? void 0 : popup.close();
|
|
566
|
+
};
|
|
567
|
+
dialogEl.onCancel = () => {
|
|
568
|
+
popup === null || popup === void 0 ? void 0 : popup.close();
|
|
569
|
+
};
|
|
570
|
+
const popup = OxPopup.open({
|
|
571
|
+
template: dialogEl,
|
|
572
|
+
backdrop: true
|
|
573
|
+
});
|
|
574
|
+
}
|
|
435
575
|
onTapSelectAll() {
|
|
436
576
|
var _a;
|
|
437
577
|
(_a = this.scene) === null || _a === void 0 ? void 0 : _a.select('(child)');
|
|
@@ -523,9 +663,15 @@ export class EditToolbar extends LitElement {
|
|
|
523
663
|
onTapPreview() {
|
|
524
664
|
this.dispatchEvent(new CustomEvent('open-preview'));
|
|
525
665
|
}
|
|
666
|
+
onTapDataBinding() {
|
|
667
|
+
this.dispatchEvent(new CustomEvent('open-data-binding'));
|
|
668
|
+
}
|
|
526
669
|
onTapDownloadModel() {
|
|
527
670
|
this.dispatchEvent(new CustomEvent('download-model'));
|
|
528
671
|
}
|
|
672
|
+
onTapEditModel() {
|
|
673
|
+
this.dispatchEvent(new CustomEvent('edit-model'));
|
|
674
|
+
}
|
|
529
675
|
onTapDistribute(e) {
|
|
530
676
|
if (!this.scene)
|
|
531
677
|
return;
|
|
@@ -548,51 +694,9 @@ __decorate([
|
|
|
548
694
|
property({ type: Boolean })
|
|
549
695
|
], EditToolbar.prototype, "hideProperty", void 0);
|
|
550
696
|
__decorate([
|
|
551
|
-
|
|
552
|
-
], EditToolbar.prototype, "
|
|
553
|
-
__decorate([
|
|
554
|
-
query('#undo')
|
|
555
|
-
], EditToolbar.prototype, "undo", void 0);
|
|
556
|
-
__decorate([
|
|
557
|
-
query('#fullscreen')
|
|
558
|
-
], EditToolbar.prototype, "fullscreen", void 0);
|
|
559
|
-
__decorate([
|
|
560
|
-
query('#style-copy')
|
|
561
|
-
], EditToolbar.prototype, "styleCopy", void 0);
|
|
562
|
-
__decorate([
|
|
563
|
-
query('#databind-copy')
|
|
564
|
-
], EditToolbar.prototype, "databindCopy", void 0);
|
|
565
|
-
__decorate([
|
|
566
|
-
query('#cut')
|
|
567
|
-
], EditToolbar.prototype, "cut", void 0);
|
|
568
|
-
__decorate([
|
|
569
|
-
query('#copy')
|
|
570
|
-
], EditToolbar.prototype, "copy", void 0);
|
|
571
|
-
__decorate([
|
|
572
|
-
query('#paste')
|
|
573
|
-
], EditToolbar.prototype, "paste", void 0);
|
|
574
|
-
__decorate([
|
|
575
|
-
query('#delete')
|
|
576
|
-
], EditToolbar.prototype, "delete", void 0);
|
|
577
|
-
__decorate([
|
|
578
|
-
query('#forward')
|
|
579
|
-
], EditToolbar.prototype, "forward", void 0);
|
|
580
|
-
__decorate([
|
|
581
|
-
query('#backward')
|
|
582
|
-
], EditToolbar.prototype, "backward", void 0);
|
|
583
|
-
__decorate([
|
|
584
|
-
query('#front')
|
|
585
|
-
], EditToolbar.prototype, "front", void 0);
|
|
586
|
-
__decorate([
|
|
587
|
-
query('#back')
|
|
588
|
-
], EditToolbar.prototype, "back", void 0);
|
|
589
|
-
__decorate([
|
|
590
|
-
queryAll('[data-align]')
|
|
591
|
-
], EditToolbar.prototype, "aligners", void 0);
|
|
592
|
-
__decorate([
|
|
593
|
-
queryAll('[data-zorder]')
|
|
594
|
-
], EditToolbar.prototype, "zorders", void 0);
|
|
697
|
+
state()
|
|
698
|
+
], EditToolbar.prototype, "_dimension", void 0);
|
|
595
699
|
__decorate([
|
|
596
|
-
|
|
597
|
-
], EditToolbar.prototype, "
|
|
700
|
+
state()
|
|
701
|
+
], EditToolbar.prototype, "_gizmoAttached", void 0);
|
|
598
702
|
//# sourceMappingURL=edit-toolbar.js.map
|