@fmsim/board 1.0.88 → 2.0.0-beta.101

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.
Files changed (144) hide show
  1. package/custom-elements.json +7366 -3448
  2. package/demo/index-modeller.html +1 -1
  3. package/demo/index-player.html +2 -2
  4. package/demo/index-viewer.html +2 -2
  5. package/demo/index.html +2 -2
  6. package/dist/src/component/etc.js +36 -0
  7. package/dist/src/component/etc.js.map +1 -1
  8. package/dist/src/component/index.d.ts +1 -0
  9. package/dist/src/component/index.js +1 -0
  10. package/dist/src/component/index.js.map +1 -1
  11. package/dist/src/component/restful-attachment-creation-card.js +1 -1
  12. package/dist/src/component/restful-attachment-creation-card.js.map +1 -1
  13. package/dist/src/component/restful-attachment-selector.js +8 -9
  14. package/dist/src/component/restful-attachment-selector.js.map +1 -1
  15. package/dist/src/component/restful-input-attachment-selector.d.ts +1 -1
  16. package/dist/src/component/restful-input-attachment-selector.js +3 -3
  17. package/dist/src/component/restful-input-attachment-selector.js.map +1 -1
  18. package/dist/src/component/restful-input-fill-style.d.ts +13 -2
  19. package/dist/src/component/restful-input-fill-style.js.map +1 -1
  20. package/dist/src/component/restful-property-editor-backdrop-faces.d.ts +50 -0
  21. package/dist/src/component/restful-property-editor-backdrop-faces.js +524 -0
  22. package/dist/src/component/restful-property-editor-backdrop-faces.js.map +1 -0
  23. package/dist/src/index.d.ts +1 -0
  24. package/dist/src/index.js +1 -0
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/layers/mcs-mouse-event-handler.js +8 -0
  27. package/dist/src/layers/mcs-mouse-event-handler.js.map +1 -1
  28. package/dist/src/layers/movement-layer.d.ts +7 -6
  29. package/dist/src/layers/movement-layer.js +56 -11
  30. package/dist/src/layers/movement-layer.js.map +1 -1
  31. package/dist/src/modeller/bulk-create-dialog.d.ts +51 -0
  32. package/dist/src/modeller/bulk-create-dialog.js +531 -0
  33. package/dist/src/modeller/bulk-create-dialog.js.map +1 -0
  34. package/dist/src/modeller/bulk-create.d.ts +101 -0
  35. package/dist/src/modeller/bulk-create.js +199 -0
  36. package/dist/src/modeller/bulk-create.js.map +1 -0
  37. package/dist/src/modeller/component-toolbar/component-menu.d.ts +1 -1
  38. package/dist/src/modeller/component-toolbar/component-toolbar.d.ts +4 -4
  39. package/dist/src/modeller/component-toolbar/component-toolbar.js.map +1 -1
  40. package/dist/src/modeller/edit-toolbar-style.js +43 -3
  41. package/dist/src/modeller/edit-toolbar-style.js.map +1 -1
  42. package/dist/src/modeller/edit-toolbar.d.ts +21 -14
  43. package/dist/src/modeller/edit-toolbar.js +371 -213
  44. package/dist/src/modeller/edit-toolbar.js.map +1 -1
  45. package/dist/src/modeller/property-sidebar/abstract-property.js +10 -2
  46. package/dist/src/modeller/property-sidebar/abstract-property.js.map +1 -1
  47. package/dist/src/modeller/property-sidebar/data-binding/data-binding-mapper.js +1 -1
  48. package/dist/src/modeller/property-sidebar/data-binding/data-binding-mapper.js.map +1 -1
  49. package/dist/src/modeller/property-sidebar/data-binding/data-binding.d.ts +2 -2
  50. package/dist/src/modeller/property-sidebar/data-binding/data-binding.js +18 -18
  51. package/dist/src/modeller/property-sidebar/data-binding/data-binding.js.map +1 -1
  52. package/dist/src/modeller/property-sidebar/effects/effects.d.ts +10 -1
  53. package/dist/src/modeller/property-sidebar/effects/effects.js +66 -1
  54. package/dist/src/modeller/property-sidebar/effects/effects.js.map +1 -1
  55. package/dist/src/modeller/property-sidebar/effects/event-handler-adapter.d.ts +44 -0
  56. package/dist/src/modeller/property-sidebar/effects/event-handler-adapter.js +70 -0
  57. package/dist/src/modeller/property-sidebar/effects/event-handler-adapter.js.map +1 -0
  58. package/dist/src/modeller/property-sidebar/effects/property-event-hover.js +3 -3
  59. package/dist/src/modeller/property-sidebar/effects/property-event-hover.js.map +1 -1
  60. package/dist/src/modeller/property-sidebar/effects/property-event.d.ts +13 -3
  61. package/dist/src/modeller/property-sidebar/effects/property-event.js +20 -11
  62. package/dist/src/modeller/property-sidebar/effects/property-event.js.map +1 -1
  63. package/dist/src/modeller/property-sidebar/inspector/inspector-controller.d.ts +62 -0
  64. package/dist/src/modeller/property-sidebar/inspector/inspector-controller.js +276 -0
  65. package/dist/src/modeller/property-sidebar/inspector/inspector-controller.js.map +1 -0
  66. package/dist/src/modeller/property-sidebar/inspector/inspector-group-view.d.ts +15 -0
  67. package/dist/src/modeller/property-sidebar/inspector/inspector-group-view.js +56 -0
  68. package/dist/src/modeller/property-sidebar/inspector/inspector-group-view.js.map +1 -0
  69. package/dist/src/modeller/property-sidebar/inspector/inspector-highlight.d.ts +7 -0
  70. package/dist/src/modeller/property-sidebar/inspector/inspector-highlight.js +25 -0
  71. package/dist/src/modeller/property-sidebar/inspector/inspector-highlight.js.map +1 -0
  72. package/dist/src/modeller/property-sidebar/inspector/inspector-model.d.ts +44 -0
  73. package/dist/src/modeller/property-sidebar/inspector/inspector-model.js +72 -0
  74. package/dist/src/modeller/property-sidebar/inspector/inspector-model.js.map +1 -0
  75. package/dist/src/modeller/property-sidebar/inspector/inspector-tree-view.d.ts +18 -0
  76. package/dist/src/modeller/property-sidebar/inspector/inspector-tree-view.js +61 -0
  77. package/dist/src/modeller/property-sidebar/inspector/inspector-tree-view.js.map +1 -0
  78. package/dist/src/modeller/property-sidebar/inspector/inspector.d.ts +17 -12
  79. package/dist/src/modeller/property-sidebar/inspector/inspector.js +281 -154
  80. package/dist/src/modeller/property-sidebar/inspector/inspector.js.map +1 -1
  81. package/dist/src/modeller/property-sidebar/property-sidebar.d.ts +2 -2
  82. package/dist/src/modeller/property-sidebar/property-sidebar.js +11 -24
  83. package/dist/src/modeller/property-sidebar/property-sidebar.js.map +1 -1
  84. package/dist/src/modeller/property-sidebar/shapes/ox-input-entity-id.d.ts +75 -0
  85. package/dist/src/modeller/property-sidebar/shapes/ox-input-entity-id.js +346 -0
  86. package/dist/src/modeller/property-sidebar/shapes/ox-input-entity-id.js.map +1 -0
  87. package/dist/src/modeller/property-sidebar/shapes/shapes.d.ts +23 -2
  88. package/dist/src/modeller/property-sidebar/shapes/shapes.js +96 -4
  89. package/dist/src/modeller/property-sidebar/shapes/shapes.js.map +1 -1
  90. package/dist/src/modeller/property-sidebar/specifics/specifics.d.ts +25 -1
  91. package/dist/src/modeller/property-sidebar/specifics/specifics.js +112 -2
  92. package/dist/src/modeller/property-sidebar/specifics/specifics.js.map +1 -1
  93. package/dist/src/modeller/property-sidebar/styles/styles.d.ts +6 -4
  94. package/dist/src/modeller/property-sidebar/styles/styles.js +140 -437
  95. package/dist/src/modeller/property-sidebar/styles/styles.js.map +1 -1
  96. package/dist/src/modeller/scene-viewer/ox-scene-layer.d.ts +4 -3
  97. package/dist/src/modeller/scene-viewer/ox-scene-layer.js +2 -1
  98. package/dist/src/modeller/scene-viewer/ox-scene-layer.js.map +1 -1
  99. package/dist/src/modeller/scene-viewer/ox-scene-viewer.d.ts +6 -5
  100. package/dist/src/modeller/scene-viewer/ox-scene-viewer.js +7 -3
  101. package/dist/src/modeller/scene-viewer/ox-scene-viewer.js.map +1 -1
  102. package/dist/src/ox-board-component-info.d.ts +3 -3
  103. package/dist/src/ox-board-component-info.js +58 -19
  104. package/dist/src/ox-board-component-info.js.map +1 -1
  105. package/dist/src/ox-board-list.js +12 -12
  106. package/dist/src/ox-board-list.js.map +1 -1
  107. package/dist/src/ox-board-modeller.d.ts +9 -6
  108. package/dist/src/ox-board-modeller.js +32 -33
  109. package/dist/src/ox-board-modeller.js.map +1 -1
  110. package/dist/src/ox-board-viewer.d.ts +129 -17
  111. package/dist/src/ox-board-viewer.js +804 -115
  112. package/dist/src/ox-board-viewer.js.map +1 -1
  113. package/dist/src/ox-editor-board-selector.d.ts +4 -1
  114. package/dist/src/ox-editor-board-selector.js +41 -12
  115. package/dist/src/ox-editor-board-selector.js.map +1 -1
  116. package/dist/src/ox-playback-controls.d.ts +157 -0
  117. package/dist/src/ox-playback-controls.js +1089 -0
  118. package/dist/src/ox-playback-controls.js.map +1 -0
  119. package/dist/src/ox-property-editor-theme.js +2 -2
  120. package/dist/src/ox-property-editor-theme.js.map +1 -1
  121. package/dist/src/playback/carrier-tracking-store.d.ts +51 -0
  122. package/dist/src/playback/carrier-tracking-store.js +115 -0
  123. package/dist/src/playback/carrier-tracking-store.js.map +1 -0
  124. package/dist/src/playback/playback-engine.d.ts +106 -0
  125. package/dist/src/playback/playback-engine.js +395 -0
  126. package/dist/src/playback/playback-engine.js.map +1 -0
  127. package/dist/src/selector/board-creation-popup.d.ts +4 -5
  128. package/dist/src/selector/board-creation-popup.js +16 -19
  129. package/dist/src/selector/board-creation-popup.js.map +1 -1
  130. package/dist/src/selector/board-thumbnail-card.js +8 -8
  131. package/dist/src/selector/board-thumbnail-card.js.map +1 -1
  132. package/dist/src/selector/ox-board-creation-card.d.ts +1 -1
  133. package/dist/src/selector/ox-board-creation-card.js +7 -7
  134. package/dist/src/selector/ox-board-creation-card.js.map +1 -1
  135. package/dist/src/selector/ox-board-selector.js +21 -10
  136. package/dist/src/selector/ox-board-selector.js.map +1 -1
  137. package/dist/tsconfig.tsbuildinfo +1 -1
  138. package/icons/components/text.png +0 -0
  139. package/icons/fab/mode-2d.svg +25 -0
  140. package/icons/fab/mode-3d.svg +25 -0
  141. package/icons/fab/playback-play.svg +49 -0
  142. package/icons/fab/playback-stop.svg +50 -0
  143. package/icons/icon-htoolbar.png +0 -0
  144. package/package.json +22 -21
@@ -3,18 +3,72 @@
3
3
  */
4
4
  import { __decorate } from "tslib";
5
5
  import { html, LitElement } from 'lit';
6
- import { property, query, queryAll } from 'lit/decorators.js';
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';
10
+ import './bulk-create-dialog.js';
9
11
  const MACOS = isMacOS();
12
+ /**
13
+ * 컴포넌트 model JSON 만으로 type-aware bounding box (width, height) 추출.
14
+ *
15
+ * things-scene 의 component.bounds 는 *path 의 bounding box* 인데, model JSON 만
16
+ * 으로는 path 를 그릴 수 없으므로 type-specific 필드를 직접 본다.
17
+ * - width/height 명시 (Rect, Container 등) → 그대로
18
+ * - rx/ry (Ellipse 등) → 2*rx, 2*ry
19
+ * - points 배열 (Line, Polygon 등) → 점들의 bounding box
20
+ * - 그 외 → 50x50 fallback
21
+ *
22
+ * bulk-paste 가 영역 안에 N 개 복제할 때 *원본 크기를 보존* 하기 위해 사용.
23
+ */
24
+ function deriveBoundsFromModel(model) {
25
+ if (typeof model.width === 'number' && typeof model.height === 'number') {
26
+ return { width: model.width, height: model.height };
27
+ }
28
+ if (typeof model.rx === 'number' && typeof model.ry === 'number') {
29
+ return { width: 2 * Math.abs(model.rx), height: 2 * Math.abs(model.ry) };
30
+ }
31
+ if (Array.isArray(model.points) && model.points.length > 0) {
32
+ let minX = Infinity;
33
+ let maxX = -Infinity;
34
+ let minY = Infinity;
35
+ let maxY = -Infinity;
36
+ for (const p of model.points) {
37
+ if (typeof (p === null || p === void 0 ? void 0 : p.x) === 'number') {
38
+ if (p.x < minX)
39
+ minX = p.x;
40
+ if (p.x > maxX)
41
+ maxX = p.x;
42
+ }
43
+ if (typeof (p === null || p === void 0 ? void 0 : p.y) === 'number') {
44
+ if (p.y < minY)
45
+ minY = p.y;
46
+ if (p.y > maxY)
47
+ maxY = p.y;
48
+ }
49
+ }
50
+ if (isFinite(minX) && isFinite(maxX) && isFinite(minY) && isFinite(maxY)) {
51
+ return { width: maxX - minX, height: maxY - minY };
52
+ }
53
+ }
54
+ return { width: 50, height: 50 };
55
+ }
10
56
  export class EditToolbar extends LitElement {
11
57
  constructor() {
12
58
  super(...arguments);
13
59
  this.selected = [];
14
60
  this.hideProperty = false;
61
+ this._dimension = null;
62
+ this._gizmoAttached = false;
15
63
  }
16
64
  firstUpdated() {
17
65
  this.addEventListener('mousewheel', this.onWheelEvent.bind(this), false);
66
+ // 툴바 버튼 클릭 후 씬으로 포커스를 돌려서 키보드 단축키가 계속 작동하도록 한다
67
+ this.addEventListener('click', () => {
68
+ var _a, _b, _c;
69
+ ;
70
+ (_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();
71
+ });
18
72
  window.addEventListener('paste', (e) => {
19
73
  var _a;
20
74
  try {
@@ -24,29 +78,7 @@ export class EditToolbar extends LitElement {
24
78
  console.error('model paste failed', e);
25
79
  }
26
80
  });
27
- this.aligners.forEach(aligner => aligner.addEventListener('tap', this.onTapAlign.bind(this)));
28
- this.zorders.forEach(zorder => zorder.addEventListener('tap', this.onTapZorder.bind(this)));
29
- this.distributes.forEach(distribute => distribute.addEventListener('tap', this.onTapDistribute.bind(this)));
30
- this.undo.addEventListener('tap', this.onTapUndo.bind(this));
31
- this.redo.addEventListener('tap', this.onTapRedo.bind(this));
32
- this.fullscreen.addEventListener('tap', this.onTapFullscreen.bind(this));
33
- this.cut.addEventListener('tap', this.onTapCut.bind(this));
34
- this.copy.addEventListener('tap', this.onTapCopy.bind(this));
35
- this.paste.addEventListener('tap', this.onTapPaste.bind(this));
36
- this.delete.addEventListener('tap', this.onTapDelete.bind(this));
37
- this.renderRoot
38
- .querySelector('#font-increase')
39
- .addEventListener('tap', this.onTapFontIncrease.bind(this));
40
- this.renderRoot
41
- .querySelector('#font-decrease')
42
- .addEventListener('tap', this.onTapFontDecrease.bind(this));
43
- this.renderRoot.querySelector('#group').addEventListener('tap', this.onTapGroup.bind(this));
44
- this.renderRoot.querySelector('#ungroup').addEventListener('tap', this.onTapUngroup.bind(this));
45
- this.renderRoot
46
- .querySelector('#toggle-property')
47
- .addEventListener('tap', this.onTapToggle.bind(this));
48
- this.renderRoot.querySelector('#fit-scene').addEventListener('tap', this.onTapFitScene.bind(this));
49
- this.renderRoot.querySelector('#preview').addEventListener('tap', this.onTapPreview.bind(this));
81
+ // 모든 버튼은 템플릿 @click 디렉티브로 바인딩 — 조건부 렌더링 시에도 정상 작동
50
82
  }
51
83
  updated(changes) {
52
84
  changes.has('scene') && this.onSceneChanged(this.scene, changes.get('scene'));
@@ -59,128 +91,123 @@ export class EditToolbar extends LitElement {
59
91
 
60
92
  ${this.hasEmptySlot() ? html `` : html `<span class="vline"></span>`}
61
93
 
62
- <span button id="undo" title="undo (${this.getShortcutString('cmd', 'z')})"> </span>
63
- <span button id="redo" title="redo (${this.getShortcutString('cmd', 'shift', 'z')})"> </span>
94
+ <span button id="undo" title="undo (${this.getShortcutString('cmd', 'z')})" @click=${this.onTapUndo}> </span>
95
+ <span button id="redo" title="redo (${this.getShortcutString('cmd', 'shift', 'z')})" @click=${this.onTapRedo}> </span>
64
96
 
65
97
  <span class="vline"></span>
66
98
 
67
- <span button id="cut" title="cut (${this.getShortcutString('cmd', 'x')})"> </span>
68
- <span button id="copy" title="copy (${this.getShortcutString('cmd', 'c')})"> </span>
69
- <span button id="paste" title="paste (${this.getShortcutString('cmd', 'v')})"> </span>
70
- <span
71
- button
72
- id="delete"
73
- title="delete (${this.getShortcutString('backspace')}, ${this.getShortcutString('delete')})"
74
- >
75
- </span>
99
+ <span button id="style-copy" title="style copy (${this.getShortcutString('cmd', '1')})" @click=${this.onStartStylePasteMode}> </span>
100
+ <span button id="databind-copy" title="databind copy (${this.getShortcutString('cmd', '2')})" @click=${this.onStartDatabindPasteMode}> </span>
76
101
 
77
102
  <span class="vline"></span>
78
103
 
79
- <!-- TODO Implement style-copy
80
- <span button id="style-copy" title="format painter"></span>
104
+ <span button id="cut" title="cut (${this.getShortcutString('cmd', 'x')})" @click=${this.onTapCut}> </span>
105
+ <span button id="copy" title="copy (${this.getShortcutString('cmd', 'c')})" @click=${this.onTapCopy}> </span>
106
+ <span button id="paste" title="paste (${this.getShortcutString('cmd', 'v')})" @click=${this.onTapPaste}> </span>
107
+ <span button id="delete"
108
+ title="delete (${this.getShortcutString('backspace')}, ${this.getShortcutString('delete')})"
109
+ @click=${this.onTapDelete}> </span>
110
+
81
111
  <span class="vline"></span>
82
- -->
83
112
 
84
- <span
85
- button
86
- data-align="left"
87
- id="align-left"
88
- title="align left (${this.getShortcutString('alt', 'shift', 'l')})"
89
- >
90
- </span>
91
- <span
92
- button
93
- data-align="center"
94
- id="align-center"
95
- title="align center (${this.getShortcutString('alt', 'shift', 'c')})"
96
- >
97
- </span>
98
- <span
99
- button
100
- data-align="right"
101
- id="align-right"
102
- title="align right (${this.getShortcutString('alt', 'shift', 'r')})"
103
- >
104
- </span>
113
+ <span button data-align="left" id="align-left"
114
+ title="align left (${this.getShortcutString('alt', 'shift', 'l')})" @click=${this.onTapAlign}> </span>
115
+ <span button data-align="center" id="align-center"
116
+ title="align center (${this.getShortcutString('alt', 'shift', 'c')})" @click=${this.onTapAlign}> </span>
117
+ <span button data-align="right" id="align-right"
118
+ title="align right (${this.getShortcutString('alt', 'shift', 'r')})" @click=${this.onTapAlign}> </span>
105
119
 
106
- <span button data-align="top" id="align-top" title="align top (${this.getShortcutString('alt', 'shift', 't')})">
107
- </span>
108
- <span
109
- button
110
- data-align="middle"
111
- id="align-middle"
112
- title="align middle (${this.getShortcutString('alt', 'shift', 'm')})"
113
- >
114
- </span>
115
- <span
116
- button
117
- data-align="bottom"
118
- id="align-bottom"
119
- title="align bottom (${this.getShortcutString('alt', 'shift', 'b')})"
120
- >
121
- </span>
120
+ <span button data-align="top" id="align-top"
121
+ title="align top (${this.getShortcutString('alt', 'shift', 't')})" @click=${this.onTapAlign}> </span>
122
+ <span button data-align="middle" id="align-middle"
123
+ title="align middle (${this.getShortcutString('alt', 'shift', 'm')})" @click=${this.onTapAlign}> </span>
124
+ <span button data-align="bottom" id="align-bottom"
125
+ title="align bottom (${this.getShortcutString('alt', 'shift', 'b')})" @click=${this.onTapAlign}> </span>
122
126
 
123
- <span
124
- button
125
- data-distribute="HORIZONTAL"
126
- id="distribute-horizontal"
127
- title="distribute horizontally (${this.getShortcutString('alt', 'shift', 'h')})"
128
- >
129
- </span>
127
+ <span button data-distribute="HORIZONTAL" id="distribute-horizontal"
128
+ title="distribute horizontally (${this.getShortcutString('alt', 'shift', 'h')})" @click=${this.onTapDistribute}> </span>
129
+ <span button data-distribute="VERTICAL" id="distribute-vertical"
130
+ title="distribute vertically (${this.getShortcutString('alt', 'shift', 'v')})" @click=${this.onTapDistribute}> </span>
130
131
 
131
- <span
132
- button
133
- data-distribute="VERTICAL"
134
- id="distribute-vertical"
135
- title="distribute vertically (${this.getShortcutString('alt', 'shift', 'v')})"
136
- >
137
- </span>
132
+ ${this._dimension === '3d'
133
+ ? html `
134
+ <span class="vline"></span>
138
135
 
139
- <span class="vline"></span>
136
+ <span button data-align="z-front" id="align-z-front" title="align Z front" @click=${this.onTapAlign}> </span>
137
+ <span button data-align="z-middle" id="align-z-middle" title="align Z middle" @click=${this.onTapAlign}> </span>
138
+ <span button data-align="z-back" id="align-z-back" title="align Z back" @click=${this.onTapAlign}> </span>
139
+ <span button data-distribute="Z" id="distribute-z" title="distribute Z" @click=${this.onTapDistribute}> </span>
140
+ `
141
+ : this._dimension === '2d'
142
+ ? html `
143
+ <span class="vline"></span>
140
144
 
141
- <span
142
- button
143
- id="front"
144
- data-zorder="front"
145
- title="bring to front (${this.getShortcutString('cmd', 'shift', 'f')})"
146
- >
147
- </span>
148
- <span button id="back" data-zorder="back" title="send to back (${this.getShortcutString('cmd', 'shift', 'b')})">
149
- </span>
150
- <span button id="forward" data-zorder="forward" title="bring forward (${this.getShortcutString('cmd', 'f')})">
151
- </span>
152
- <span button id="backward" data-zorder="backward" title="send backward (${this.getShortcutString('cmd', 'b')})">
153
- </span>
145
+ <span button id="front" data-zorder="front"
146
+ title="bring to front (${this.getShortcutString('cmd', 'shift', 'f')})" @click=${this.onTapZorder}> </span>
147
+ <span button id="back" data-zorder="back"
148
+ title="send to back (${this.getShortcutString('cmd', 'shift', 'b')})" @click=${this.onTapZorder}> </span>
149
+ <span button id="forward" data-zorder="forward"
150
+ title="bring forward (${this.getShortcutString('cmd', 'f')})" @click=${this.onTapZorder}> </span>
151
+ <span button id="backward" data-zorder="backward"
152
+ title="send backward (${this.getShortcutString('cmd', 'b')})" @click=${this.onTapZorder}> </span>
153
+ `
154
+ : ''}
154
155
 
155
- <span class="vline"></span>
156
+ ${this._dimension === '2d' ? html `
157
+ <span class="vline"></span>
158
+
159
+ <span button id="group" title="group (${this.getShortcutString('cmd', 'g')})" @click=${this.onTapGroup}> </span>
160
+ <span button id="ungroup" title="ungroup (${this.getShortcutString('cmd', 'shift', 'g')})" @click=${this.onTapUngroup}> </span>
161
+ ` : this._dimension === '3d' ? html `
162
+ <span class="vline"></span>
156
163
 
157
- <span button id="group" title="group (${this.getShortcutString('cmd', 'g')})"> </span>
158
- <span button id="ungroup" title="ungroup (${this.getShortcutString('cmd', 'shift', 'g')})"> </span>
164
+ <span button class="gizmo-btn" data-gizmo="translate" title="Move (W)"
165
+ @click=${() => this._setGizmoMode('translate')}>
166
+ <svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8">
167
+ <line x1="10" y1="2" x2="10" y2="18"/><line x1="2" y1="10" x2="18" y2="10"/>
168
+ <polyline points="10,2 7.5,5"/><polyline points="10,2 12.5,5"/>
169
+ <polyline points="18,10 15,7.5"/><polyline points="18,10 15,12.5"/>
170
+ <polyline points="10,18 7.5,15"/><polyline points="10,18 12.5,15"/>
171
+ <polyline points="2,10 5,7.5"/><polyline points="2,10 5,12.5"/>
172
+ </svg>
173
+ </span>
174
+ <span button class="gizmo-btn" data-gizmo="rotate" title="Rotate (E)"
175
+ @click=${() => this._setGizmoMode('rotate')}>
176
+ <svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8">
177
+ <path d="M14.5 3.5A7 7 0 1 0 17 10"/>
178
+ <polyline points="14,1 15,3.5 12.5,4.5"/>
179
+ </svg>
180
+ </span>
181
+ <span button class="gizmo-btn" data-gizmo="scale" title="Scale (R)"
182
+ @click=${() => this._setGizmoMode('scale')}>
183
+ <svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8">
184
+ <line x1="4" y1="16" x2="16" y2="4"/>
185
+ <rect x="2" y="13" width="4" height="4" rx="0.5" fill="currentColor"/>
186
+ <rect x="14" y="2" width="4" height="4" rx="0.5" fill="currentColor"/>
187
+ </svg>
188
+ </span>
189
+ ` : ''}
159
190
 
160
191
  <span class="vline"></span>
161
192
 
162
- <span button id="font-increase" title="increase font size"></span>
163
- <span button id="font-decrease" title="decrease font size"></span>
193
+ <span button id="font-increase" title="increase font size" @click=${this.onTapFontIncrease}></span>
194
+ <span button id="font-decrease" title="decrease font size" style="scale: 0.7;" @click=${this.onTapFontDecrease}></span>
164
195
 
165
196
  <span class="vline"></span>
166
197
  <span>(v${process.env['APP-VERSION']})</span>
167
198
  <span padding></span>
168
199
 
169
- <span button id="fit-scene" title="fit scene (${this.getShortcutString('cmd', 'd')})"> </span>
200
+ <span button id="fit-scene" title="fit scene (${this.getShortcutString('cmd', 'd')})" @click=${this.onTapFitScene}> </span>
170
201
 
171
202
  <span class="vline"></span>
172
203
 
173
- <span button id="preview" title="preview (${this.getShortcutString('ctrl', 'p')})"> </span>
204
+ <span button id="preview" title="preview (${this.getShortcutString('ctrl', 'p')})" @click=${this.onTapPreview}> </span>
174
205
 
175
- <span button id="fullscreen" title="fullscreen (${this.getShortcutString('f11')})"> </span>
206
+ <span button id="fullscreen" title="fullscreen (${this.getShortcutString('f11')})" @click=${this.onTapFullscreen}> </span>
176
207
 
177
- <span
178
- button
179
- id="toggle-property"
208
+ <span button id="toggle-property"
180
209
  title="toggle property panel (${this.getShortcutString('cmd', 'h')})"
181
- toggles="true"
182
- >
183
- </span>
210
+ toggles="true" @click=${this.onTapToggle}> </span>
184
211
  </div>
185
212
  `;
186
213
  }
@@ -227,7 +254,7 @@ export class EditToolbar extends LitElement {
227
254
  return symbols.join(MACOS ? '' : '+');
228
255
  }
229
256
  onShortcut(e) {
230
- var _a, _b, _c, _d;
257
+ var _a, _b, _c, _d, _e, _f;
231
258
  if (MACOS)
232
259
  var ctrlKey = e.metaKey;
233
260
  else
@@ -246,6 +273,14 @@ export class EditToolbar extends LitElement {
246
273
  if (ctrlKey && !shiftKey)
247
274
  this.onTapRedo();
248
275
  break;
276
+ case 'Digit1':
277
+ if (ctrlKey)
278
+ this.onStartStylePasteMode();
279
+ break;
280
+ case 'Digit2':
281
+ if (ctrlKey)
282
+ this.onStartDatabindPasteMode();
283
+ break;
249
284
  case 'KeyC':
250
285
  if (ctrlKey && !shiftKey)
251
286
  this.onTapCopy();
@@ -257,7 +292,13 @@ export class EditToolbar extends LitElement {
257
292
  this.onTapCut();
258
293
  break;
259
294
  case 'KeyV':
260
- if (ctrlKey && !shiftKey) {
295
+ if (ctrlKey && shiftKey && !altKey) {
296
+ // Ctrl+Shift+V = Bulk Paste (Paste Special 컨벤션) — 클립보드의
297
+ // 단일 컴포넌트를 N개로 일괄 붙여넣기.
298
+ this.onBulkPaste();
299
+ defaultPrevent = true;
300
+ }
301
+ else if (ctrlKey && !shiftKey) {
261
302
  this.onTapPaste();
262
303
  defaultPrevent = false;
263
304
  }
@@ -270,31 +311,45 @@ export class EditToolbar extends LitElement {
270
311
  defaultPrevent = true;
271
312
  break;
272
313
  case 'KeyG':
273
- if (ctrlKey && !shiftKey)
274
- this.onTapGroup();
275
- else if (ctrlKey && shiftKey)
276
- this.onTapUngroup();
314
+ if (this._dimension === '2d') {
315
+ if (ctrlKey && !shiftKey)
316
+ this.onTapGroup();
317
+ else if (ctrlKey && shiftKey)
318
+ this.onTapUngroup();
319
+ }
277
320
  break;
278
- case 'KeyF':
279
- if (ctrlKey && !shiftKey)
280
- (_a = this.scene) === null || _a === void 0 ? void 0 : _a.zorder('forward');
281
- else if (ctrlKey && shiftKey)
282
- (_b = this.scene) === null || _b === void 0 ? void 0 : _b.zorder('front');
321
+ case 'BracketRight':
322
+ // Ctrl+] = Bring Forward, Ctrl+Shift+] = Bring to Front
323
+ // (Photoshop / Illustrator 표준 컨벤션)
324
+ if (this._dimension === '2d') {
325
+ if (ctrlKey && !shiftKey) {
326
+ (_a = this.scene) === null || _a === void 0 ? void 0 : _a.zorder('forward');
327
+ defaultPrevent = true;
328
+ }
329
+ else if (ctrlKey && shiftKey) {
330
+ (_b = this.scene) === null || _b === void 0 ? void 0 : _b.zorder('front');
331
+ defaultPrevent = true;
332
+ }
333
+ }
334
+ break;
335
+ case 'BracketLeft':
336
+ // Ctrl+[ = Send Backward, Ctrl+Shift+[ = Send to Back
337
+ if (this._dimension === '2d') {
338
+ if (ctrlKey && !shiftKey) {
339
+ (_c = this.scene) === null || _c === void 0 ? void 0 : _c.zorder('backward');
340
+ defaultPrevent = true;
341
+ }
342
+ else if (ctrlKey && shiftKey) {
343
+ (_d = this.scene) === null || _d === void 0 ? void 0 : _d.zorder('back');
344
+ defaultPrevent = true;
345
+ }
346
+ }
283
347
  break;
284
348
  case 'KeyB':
285
- if (ctrlKey && !shiftKey)
286
- (_c = this.scene) === null || _c === void 0 ? void 0 : _c.zorder('backward');
287
- else if (ctrlKey && shiftKey)
288
- (_d = this.scene) === null || _d === void 0 ? void 0 : _d.zorder('back');
289
- else if (altKey && shiftKey)
349
+ // zorder 는 BracketLeft 로 이동. KeyB 의 Alt+Shift+B = align bottom 만 유지.
350
+ if (altKey && shiftKey)
290
351
  this.onTapAlign('bottom');
291
352
  break;
292
- // case 'Equal':
293
- // if (ctrlKey) this.onTapZoom(zoomin)
294
- // break
295
- // case 'Minus':
296
- // if (ctrlKey) this.onTapZoom(zoomout)
297
- // break
298
353
  case 'KeyH':
299
354
  if (ctrlKey && !shiftKey)
300
355
  this.onTapToggle();
@@ -341,17 +396,10 @@ export class EditToolbar extends LitElement {
341
396
  if (ctrlKey && shiftKey)
342
397
  this.onTapDownloadModel();
343
398
  break;
344
- case 'Digit1':
345
- if (ctrlKey) {
346
- console.log('MODEL', this.scene && this.scene.model);
347
- defaultPrevent = true;
348
- }
349
- break;
350
- case 'Digit2':
351
- if (ctrlKey) {
352
- console.log('SELECTED', this.scene && this.scene.selected);
353
- defaultPrevent = true;
354
- }
399
+ case 'Escape':
400
+ (_e = this.scene) === null || _e === void 0 ? void 0 : _e.stopStylePasteMode();
401
+ (_f = this.scene) === null || _f === void 0 ? void 0 : _f.stopDatabindPasteMode();
402
+ defaultPrevent = true;
355
403
  break;
356
404
  default:
357
405
  return false;
@@ -360,46 +408,75 @@ export class EditToolbar extends LitElement {
360
408
  e.preventDefault();
361
409
  return true;
362
410
  }
411
+ _setDisabled(id, disabled) {
412
+ const el = this.renderRoot.querySelector(`#${id}`);
413
+ disabled ? el === null || el === void 0 ? void 0 : el.setAttribute('disabled', '') : el === null || el === void 0 ? void 0 : el.removeAttribute('disabled');
414
+ }
363
415
  onExecute(command, undoable, redoable) {
364
- !undoable ? this.undo.setAttribute('disabled', '') : this.undo.removeAttribute('disabled');
365
- !redoable ? this.redo.setAttribute('disabled', '') : this.redo.removeAttribute('disabled');
416
+ this._setDisabled('undo', !undoable);
417
+ this._setDisabled('redo', !redoable);
366
418
  }
367
419
  onUndo(undoable, redoable) {
368
- !undoable ? this.undo.setAttribute('disabled', '') : this.undo.removeAttribute('disabled');
369
- !redoable ? this.redo.setAttribute('disabled', '') : this.redo.removeAttribute('disabled');
420
+ this._setDisabled('undo', !undoable);
421
+ this._setDisabled('redo', !redoable);
370
422
  }
371
423
  onRedo(undoable, redoable) {
372
- !undoable ? this.undo.setAttribute('disabled', '') : this.undo.removeAttribute('disabled');
373
- !redoable ? this.redo.setAttribute('disabled', '') : this.redo.removeAttribute('disabled');
424
+ this._setDisabled('undo', !undoable);
425
+ this._setDisabled('redo', !redoable);
374
426
  }
375
427
  onSceneChanged(after, before) {
428
+ var _a, _b;
376
429
  if (before) {
377
430
  before.off('execute', this.onExecute, this);
378
431
  before.off('undo', this.onUndo, this);
379
432
  before.off('redo', this.onRedo, this);
433
+ before.off('dimension', this._onDimensionChanged, this);
434
+ before.off('gizmoattach', this._onGizmoAttachChanged, this);
380
435
  }
381
436
  if (after) {
382
437
  after.on('execute', this.onExecute, this);
383
438
  after.on('undo', this.onUndo, this);
384
439
  after.on('redo', this.onRedo, this);
440
+ after.on('dimension', this._onDimensionChanged, this);
441
+ after.on('gizmoattach', this._onGizmoAttachChanged, this);
442
+ // scene 설정 시 현재 dimension을 즉시 반영 (초기 이벤트를 놓친 경우 대비)
443
+ const threed = (_b = (_a = after.model_layer) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.threed;
444
+ this._dimension = threed ? '3d' : '2d';
385
445
  }
386
446
  }
387
- // @query('#align-left') private alignLeft!: HTMLElement
388
- // @query('#align-center') private alignCenter!: HTMLElement
389
- // @query('#align-right') private alignRight!: HTMLElement
390
- // @query('#align-top') private alignTop!: HTMLElement
391
- // @query('#align-middle') private alignMiddle!: HTMLElement
392
- // @query('#align-bottom') private alignBottom!: HTMLElement
447
+ _onDimensionChanged(dimension) {
448
+ this._dimension = dimension;
449
+ }
450
+ _onGizmoAttachChanged(isAttached) {
451
+ this._gizmoAttached = isAttached;
452
+ }
453
+ _setGizmoMode(mode) {
454
+ var _a, _b;
455
+ ;
456
+ (_b = (_a = this.scene) === null || _a === void 0 ? void 0 : _a.root) === null || _b === void 0 ? void 0 : _b.setGizmoMode(mode);
457
+ }
393
458
  onSelectedChanged(after, before) {
459
+ var hasSelection = after.length > 0;
394
460
  var alignable = after.length > 1;
395
- this.aligners.forEach(aligner => alignable ? aligner.removeAttribute('disabled') : aligner.setAttribute('disabled', ''));
396
- var movable = after.length === 1;
397
- /* forward, backward 이동은 한 컴포넌트만 가능하다. */
398
- !movable ? this.forward.setAttribute('disabled', '') : this.forward.removeAttribute('disabled');
399
- !movable ? this.backward.setAttribute('disabled', '') : this.backward.removeAttribute('disabled');
400
- /* 여러 컴포넌트는 front, back 이동이 가능하다. */
401
- !(alignable || movable) ? this.front.setAttribute('disabled', '') : this.front.removeAttribute('disabled');
402
- !(alignable || movable) ? this.back.setAttribute('disabled', '') : this.back.removeAttribute('disabled');
461
+ ['style-copy', 'databind-copy', 'cut', 'copy', 'delete'].forEach(id => this._setDisabled(id, !hasSelection));
462
+ // 정렬 버튼
463
+ this.renderRoot.querySelectorAll('[data-align]').forEach(el => alignable ? el.removeAttribute('disabled') : el.setAttribute('disabled', ''));
464
+ if (this._dimension === '2d') {
465
+ var movable = after.length === 1;
466
+ /* forward, backward 이동은 한 컴포넌트만 가능하다. */
467
+ this._setDisabled('forward', !movable);
468
+ this._setDisabled('backward', !movable);
469
+ /* 여러 컴포넌트는 front, back 이동이 가능하다. */
470
+ this._setDisabled('front', !(alignable || movable));
471
+ this._setDisabled('back', !(alignable || movable));
472
+ }
473
+ // 분배 버튼
474
+ this.renderRoot.querySelectorAll('[data-distribute]').forEach(el => alignable ? el.removeAttribute('disabled') : el.setAttribute('disabled', ''));
475
+ if (this._dimension === '3d') {
476
+ this.renderRoot.querySelectorAll('.gizmo-btn').forEach(btn => {
477
+ hasSelection ? btn.removeAttribute('disabled') : btn.setAttribute('disabled', '');
478
+ });
479
+ }
403
480
  }
404
481
  onTapUndo() {
405
482
  var _a;
@@ -409,6 +486,22 @@ export class EditToolbar extends LitElement {
409
486
  var _a;
410
487
  (_a = this.scene) === null || _a === void 0 ? void 0 : _a.redo();
411
488
  }
489
+ onStartStylePasteMode() {
490
+ var _a, _b, _c;
491
+ if (((_a = this.selected) === null || _a === void 0 ? void 0 : _a.length) !== 1)
492
+ return;
493
+ if (this.selected[0] === ((_b = this.scene) === null || _b === void 0 ? void 0 : _b.root))
494
+ return;
495
+ (_c = this.scene) === null || _c === void 0 ? void 0 : _c.startStylePasteMode();
496
+ }
497
+ onStartDatabindPasteMode() {
498
+ var _a, _b, _c;
499
+ if (((_a = this.selected) === null || _a === void 0 ? void 0 : _a.length) !== 1)
500
+ return;
501
+ if (this.selected[0] === ((_b = this.scene) === null || _b === void 0 ? void 0 : _b.root))
502
+ return;
503
+ (_c = this.scene) === null || _c === void 0 ? void 0 : _c.startDatabindPasteMode();
504
+ }
412
505
  onTapCut() {
413
506
  var _a;
414
507
  (_a = this.scene) === null || _a === void 0 ? void 0 : _a.cut();
@@ -431,6 +524,101 @@ export class EditToolbar extends LitElement {
431
524
  var _a;
432
525
  (_a = this.scene) === null || _a === void 0 ? void 0 : _a.remove();
433
526
  }
527
+ /**
528
+ * 멀티 컴포넌트 일괄 붙여넣기 — Ctrl+Shift+V 진입점.
529
+ *
530
+ * 흐름:
531
+ * 1. 클립보드 (this.cliped) 검증 — *단일* 컴포넌트만 허용
532
+ * 2. scene.startBulkCreateMode → AddLayer 가 캔버스 위에 드래그 박스 그림
533
+ * 3. 사용자가 영역 드래그 → Promise resolve({area, template})
534
+ * ESC/취소 → Promise resolve(null)
535
+ * 4. 영역이 결정되면 dialog 오픈
536
+ */
537
+ async onBulkPaste() {
538
+ var _a;
539
+ if (!this.cliped) {
540
+ console.warn('bulk-paste: 먼저 Ctrl+C 로 컴포넌트를 복사하세요.');
541
+ return;
542
+ }
543
+ let parsed;
544
+ try {
545
+ parsed = JSON.parse(this.cliped);
546
+ }
547
+ catch (e) {
548
+ console.warn('bulk-paste: 클립보드 파싱 실패', e);
549
+ return;
550
+ }
551
+ if (!Array.isArray(parsed) || parsed.length === 0) {
552
+ console.warn('bulk-paste: 클립보드 비어있음');
553
+ return;
554
+ }
555
+ if (parsed.length > 1) {
556
+ console.warn('bulk-paste: 단일 컴포넌트만 일괄 붙여넣기 가능. 다중은 일반 paste 사용.');
557
+ return;
558
+ }
559
+ const template = parsed[0];
560
+ // bulk 모드 임을 시각 구분하기 위해 파란 점선 (일반 add 의 검정과 색만 차별).
561
+ const result = await ((_a = this.scene) === null || _a === void 0 ? void 0 : _a.startBulkCreateMode(template, { boxStrokeStyle: '#2964c2' }));
562
+ if (result) {
563
+ this._openBulkCreateDialog(template, result.area);
564
+ }
565
+ }
566
+ _openBulkCreateDialog(template, initialArea) {
567
+ var _a;
568
+ const dialogEl = document.createElement('bulk-create-dialog');
569
+ dialogEl.template = template;
570
+ dialogEl.initialArea = initialArea;
571
+ // 충돌 검사용 — scene 의 모든 컴포넌트 id 수집.
572
+ // (scene.ids 는 indexMap 기반인데 fmsim 의 일부 컴포넌트는 indexMap 미등록
573
+ // 되는 케이스가 있어 직접 컴포넌트 트리 walk.)
574
+ const existingIds = new Set();
575
+ const collectIds = (comp) => {
576
+ var _a, _b, _c;
577
+ if (!comp)
578
+ return;
579
+ 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;
580
+ if (typeof id === 'string' && id)
581
+ existingIds.add(id);
582
+ const children = comp.components || [];
583
+ for (const c of children)
584
+ collectIds(c);
585
+ };
586
+ const root = (_a = this.scene) === null || _a === void 0 ? void 0 : _a.root;
587
+ if (root)
588
+ collectIds(root);
589
+ dialogEl.existingIds = existingIds;
590
+ dialogEl.onConfirm = (models) => {
591
+ const scene = this.scene;
592
+ if (!scene || !models.length) {
593
+ popup === null || popup === void 0 ? void 0 : popup.close();
594
+ return;
595
+ }
596
+ // cliped 의 template model 자체에서 type-aware bounds 추출. things-scene 의
597
+ // component.bounds (= path bounding box) 와 동일 결과를 model JSON 의
598
+ // type-specific 필드 (width/height, rx/ry, points) 만으로 계산.
599
+ const bounds = deriveBoundsFromModel(template);
600
+ scene.undoableChange(() => {
601
+ for (const m of models) {
602
+ const cx = m.left + m.width / 2;
603
+ const cy = m.top + m.height / 2;
604
+ scene.add(m, {
605
+ left: cx - bounds.width / 2,
606
+ top: cy - bounds.height / 2,
607
+ width: bounds.width,
608
+ height: bounds.height
609
+ });
610
+ }
611
+ });
612
+ popup === null || popup === void 0 ? void 0 : popup.close();
613
+ };
614
+ dialogEl.onCancel = () => {
615
+ popup === null || popup === void 0 ? void 0 : popup.close();
616
+ };
617
+ const popup = OxPopup.open({
618
+ template: dialogEl,
619
+ backdrop: true
620
+ });
621
+ }
434
622
  onTapSelectAll() {
435
623
  var _a;
436
624
  (_a = this.scene) === null || _a === void 0 ? void 0 : _a.select('(child)');
@@ -476,10 +664,16 @@ export class EditToolbar extends LitElement {
476
664
  if (!this.scene)
477
665
  return;
478
666
  var selected = this.scene.selected;
479
- if (selected.length <= 1)
480
- return;
481
667
  var align = typeof e === 'string' ? e : e.target.getAttribute('data-align');
482
- align && this.scene.align(align);
668
+ if (!align) {
669
+ return;
670
+ }
671
+ if (selected.length <= 1) {
672
+ this.scene.place(align);
673
+ }
674
+ else {
675
+ this.scene.align(align);
676
+ }
483
677
  }
484
678
  onTapZorder(e) {
485
679
  if (!this.scene)
@@ -541,45 +735,9 @@ __decorate([
541
735
  property({ type: Boolean })
542
736
  ], EditToolbar.prototype, "hideProperty", void 0);
543
737
  __decorate([
544
- query('#redo')
545
- ], EditToolbar.prototype, "redo", void 0);
546
- __decorate([
547
- query('#undo')
548
- ], EditToolbar.prototype, "undo", void 0);
549
- __decorate([
550
- query('#fullscreen')
551
- ], EditToolbar.prototype, "fullscreen", void 0);
552
- __decorate([
553
- query('#cut')
554
- ], EditToolbar.prototype, "cut", void 0);
555
- __decorate([
556
- query('#copy')
557
- ], EditToolbar.prototype, "copy", void 0);
558
- __decorate([
559
- query('#paste')
560
- ], EditToolbar.prototype, "paste", void 0);
561
- __decorate([
562
- query('#delete')
563
- ], EditToolbar.prototype, "delete", void 0);
564
- __decorate([
565
- query('#forward')
566
- ], EditToolbar.prototype, "forward", void 0);
567
- __decorate([
568
- query('#backward')
569
- ], EditToolbar.prototype, "backward", void 0);
570
- __decorate([
571
- query('#front')
572
- ], EditToolbar.prototype, "front", void 0);
573
- __decorate([
574
- query('#back')
575
- ], EditToolbar.prototype, "back", void 0);
576
- __decorate([
577
- queryAll('[data-align]')
578
- ], EditToolbar.prototype, "aligners", void 0);
579
- __decorate([
580
- queryAll('[data-zorder]')
581
- ], EditToolbar.prototype, "zorders", void 0);
738
+ state()
739
+ ], EditToolbar.prototype, "_dimension", void 0);
582
740
  __decorate([
583
- queryAll('[data-distribute]')
584
- ], EditToolbar.prototype, "distributes", void 0);
741
+ state()
742
+ ], EditToolbar.prototype, "_gizmoAttached", void 0);
585
743
  //# sourceMappingURL=edit-toolbar.js.map