@operato/board 0.2.44 → 0.2.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.
Files changed (145) hide show
  1. package/@types/global/index.d.ts +1 -0
  2. package/CHANGELOG.md +57 -0
  3. package/assets/images/components/no-image.png +0 -0
  4. package/custom-elements.json +4272 -174
  5. package/demo/index-modeller.html +101 -0
  6. package/demo/index.html +3 -3
  7. package/dist/src/index.d.ts +1 -0
  8. package/dist/src/index.js +1 -0
  9. package/dist/src/index.js.map +1 -1
  10. package/dist/src/modeller/component-toolbar/component-detail.d.ts +4 -0
  11. package/dist/src/modeller/component-toolbar/component-detail.js +56 -0
  12. package/dist/src/modeller/component-toolbar/component-detail.js.map +1 -0
  13. package/dist/src/modeller/component-toolbar/component-menu.d.ts +4 -0
  14. package/dist/src/modeller/component-toolbar/component-menu.js +194 -0
  15. package/dist/src/modeller/component-toolbar/component-menu.js.map +1 -0
  16. package/dist/src/modeller/component-toolbar/component-toolbar.d.ts +4 -0
  17. package/dist/src/modeller/component-toolbar/component-toolbar.js +170 -0
  18. package/dist/src/modeller/component-toolbar/component-toolbar.js.map +1 -0
  19. package/dist/src/modeller/edit-toolbar-style.d.ts +4 -0
  20. package/dist/src/modeller/edit-toolbar-style.js +227 -0
  21. package/dist/src/modeller/edit-toolbar-style.js.map +1 -0
  22. package/dist/src/modeller/edit-toolbar.d.ts +61 -0
  23. package/dist/src/modeller/edit-toolbar.js +644 -0
  24. package/dist/src/modeller/edit-toolbar.js.map +1 -0
  25. package/dist/src/modeller/property-sidebar/abstract-property.d.ts +10 -0
  26. package/dist/src/modeller/property-sidebar/abstract-property.js +58 -0
  27. package/dist/src/modeller/property-sidebar/abstract-property.js.map +1 -0
  28. package/dist/src/modeller/property-sidebar/data-binding/data-binding-mapper.d.ts +48 -0
  29. package/dist/src/modeller/property-sidebar/data-binding/data-binding-mapper.js +351 -0
  30. package/dist/src/modeller/property-sidebar/data-binding/data-binding-mapper.js.map +1 -0
  31. package/dist/src/modeller/property-sidebar/data-binding/data-binding.d.ts +8 -0
  32. package/dist/src/modeller/property-sidebar/data-binding/data-binding.js +432 -0
  33. package/dist/src/modeller/property-sidebar/data-binding/data-binding.js.map +1 -0
  34. package/dist/src/modeller/property-sidebar/effects/effects-shared-style.d.ts +4 -0
  35. package/dist/src/modeller/property-sidebar/effects/effects-shared-style.js +57 -0
  36. package/dist/src/modeller/property-sidebar/effects/effects-shared-style.js.map +1 -0
  37. package/dist/src/modeller/property-sidebar/effects/effects.d.ts +6 -0
  38. package/dist/src/modeller/property-sidebar/effects/effects.js +55 -0
  39. package/dist/src/modeller/property-sidebar/effects/effects.js.map +1 -0
  40. package/dist/src/modeller/property-sidebar/effects/property-animation.d.ts +22 -0
  41. package/dist/src/modeller/property-sidebar/effects/property-animation.js +127 -0
  42. package/dist/src/modeller/property-sidebar/effects/property-animation.js.map +1 -0
  43. package/dist/src/modeller/property-sidebar/effects/property-animations.d.ts +5 -0
  44. package/dist/src/modeller/property-sidebar/effects/property-animations.js +83 -0
  45. package/dist/src/modeller/property-sidebar/effects/property-animations.js.map +1 -0
  46. package/dist/src/modeller/property-sidebar/effects/property-event-hover.d.ts +4 -0
  47. package/dist/src/modeller/property-sidebar/effects/property-event-hover.js +124 -0
  48. package/dist/src/modeller/property-sidebar/effects/property-event-hover.js.map +1 -0
  49. package/dist/src/modeller/property-sidebar/effects/property-event-tap.d.ts +4 -0
  50. package/dist/src/modeller/property-sidebar/effects/property-event-tap.js +120 -0
  51. package/dist/src/modeller/property-sidebar/effects/property-event-tap.js.map +1 -0
  52. package/dist/src/modeller/property-sidebar/effects/property-event.d.ts +5 -0
  53. package/dist/src/modeller/property-sidebar/effects/property-event.js +59 -0
  54. package/dist/src/modeller/property-sidebar/effects/property-event.js.map +1 -0
  55. package/dist/src/modeller/property-sidebar/effects/property-shadow.d.ts +22 -0
  56. package/dist/src/modeller/property-sidebar/effects/property-shadow.js +106 -0
  57. package/dist/src/modeller/property-sidebar/effects/property-shadow.js.map +1 -0
  58. package/dist/src/modeller/property-sidebar/effects/value-converter.d.ts +1 -0
  59. package/dist/src/modeller/property-sidebar/effects/value-converter.js +23 -0
  60. package/dist/src/modeller/property-sidebar/effects/value-converter.js.map +1 -0
  61. package/dist/src/modeller/property-sidebar/inspector/inspector.d.ts +24 -0
  62. package/dist/src/modeller/property-sidebar/inspector/inspector.js +290 -0
  63. package/dist/src/modeller/property-sidebar/inspector/inspector.js.map +1 -0
  64. package/dist/src/modeller/property-sidebar/property-shared-style.d.ts +4 -0
  65. package/dist/src/modeller/property-sidebar/property-shared-style.js +131 -0
  66. package/dist/src/modeller/property-sidebar/property-shared-style.js.map +1 -0
  67. package/dist/src/modeller/property-sidebar/property-sidebar.d.ts +10 -0
  68. package/dist/src/modeller/property-sidebar/property-sidebar.js +313 -0
  69. package/dist/src/modeller/property-sidebar/property-sidebar.js.map +1 -0
  70. package/dist/src/modeller/property-sidebar/shapes/box-padding-editor-styles.d.ts +1 -0
  71. package/dist/src/modeller/property-sidebar/shapes/box-padding-editor-styles.js +94 -0
  72. package/dist/src/modeller/property-sidebar/shapes/box-padding-editor-styles.js.map +1 -0
  73. package/dist/src/modeller/property-sidebar/shapes/shapes.d.ts +6 -0
  74. package/dist/src/modeller/property-sidebar/shapes/shapes.js +406 -0
  75. package/dist/src/modeller/property-sidebar/shapes/shapes.js.map +1 -0
  76. package/dist/src/modeller/property-sidebar/specifics/specific-properties-builder.d.ts +4 -0
  77. package/dist/src/modeller/property-sidebar/specifics/specific-properties-builder.js +127 -0
  78. package/dist/src/modeller/property-sidebar/specifics/specific-properties-builder.js.map +1 -0
  79. package/dist/src/modeller/property-sidebar/specifics/specifics.d.ts +5 -0
  80. package/dist/src/modeller/property-sidebar/specifics/specifics.js +78 -0
  81. package/dist/src/modeller/property-sidebar/specifics/specifics.js.map +1 -0
  82. package/dist/src/modeller/property-sidebar/styles/styles.d.ts +8 -0
  83. package/dist/src/modeller/property-sidebar/styles/styles.js +562 -0
  84. package/dist/src/modeller/property-sidebar/styles/styles.js.map +1 -0
  85. package/dist/src/modeller/scene-viewer/confidential-overlay.d.ts +4 -0
  86. package/dist/src/modeller/scene-viewer/confidential-overlay.js +14 -0
  87. package/dist/src/modeller/scene-viewer/confidential-overlay.js.map +1 -0
  88. package/dist/src/modeller/scene-viewer/ox-scene-handler.d.ts +11 -0
  89. package/dist/src/modeller/scene-viewer/ox-scene-handler.js +36 -0
  90. package/dist/src/modeller/scene-viewer/ox-scene-handler.js.map +1 -0
  91. package/dist/src/modeller/scene-viewer/ox-scene-layer.d.ts +10 -0
  92. package/dist/src/modeller/scene-viewer/ox-scene-layer.js +42 -0
  93. package/dist/src/modeller/scene-viewer/ox-scene-layer.js.map +1 -0
  94. package/dist/src/modeller/scene-viewer/ox-scene-player.d.ts +1 -0
  95. package/dist/src/modeller/scene-viewer/ox-scene-player.js +99 -0
  96. package/dist/src/modeller/scene-viewer/ox-scene-player.js.map +1 -0
  97. package/dist/src/modeller/scene-viewer/ox-scene-property.d.ts +6 -0
  98. package/dist/src/modeller/scene-viewer/ox-scene-property.js +19 -0
  99. package/dist/src/modeller/scene-viewer/ox-scene-property.js.map +1 -0
  100. package/dist/src/modeller/scene-viewer/ox-scene-viewer.d.ts +39 -0
  101. package/dist/src/modeller/scene-viewer/ox-scene-viewer.js +245 -0
  102. package/dist/src/modeller/scene-viewer/ox-scene-viewer.js.map +1 -0
  103. package/dist/src/ox-board-modeller.d.ts +13 -4
  104. package/dist/src/ox-board-modeller.js +130 -40
  105. package/dist/src/ox-board-modeller.js.map +1 -1
  106. package/dist/src/types.d.ts +12 -0
  107. package/dist/src/types.js +2 -0
  108. package/dist/src/types.js.map +1 -0
  109. package/dist/tsconfig.tsbuildinfo +1 -1
  110. package/package.json +26 -5
  111. package/src/index.ts +1 -0
  112. package/src/modeller/component-toolbar/component-detail.ts +53 -0
  113. package/src/modeller/component-toolbar/component-menu.ts +190 -0
  114. package/src/modeller/component-toolbar/component-toolbar.ts +161 -0
  115. package/src/modeller/edit-toolbar-style.ts +228 -0
  116. package/src/modeller/edit-toolbar.ts +640 -0
  117. package/src/modeller/property-sidebar/abstract-property.ts +73 -0
  118. package/src/modeller/property-sidebar/data-binding/data-binding-mapper.ts +371 -0
  119. package/src/modeller/property-sidebar/data-binding/data-binding.ts +449 -0
  120. package/src/modeller/property-sidebar/effects/effects-shared-style.ts +58 -0
  121. package/src/modeller/property-sidebar/effects/effects.ts +57 -0
  122. package/src/modeller/property-sidebar/effects/property-animation.ts +133 -0
  123. package/src/modeller/property-sidebar/effects/property-animations.ts +84 -0
  124. package/src/modeller/property-sidebar/effects/property-event-hover.ts +133 -0
  125. package/src/modeller/property-sidebar/effects/property-event-tap.ts +129 -0
  126. package/src/modeller/property-sidebar/effects/property-event.ts +65 -0
  127. package/src/modeller/property-sidebar/effects/property-shadow.ts +114 -0
  128. package/src/modeller/property-sidebar/effects/value-converter.ts +26 -0
  129. package/src/modeller/property-sidebar/inspector/inspector.ts +327 -0
  130. package/src/modeller/property-sidebar/property-shared-style.ts +132 -0
  131. package/src/modeller/property-sidebar/property-sidebar.ts +308 -0
  132. package/src/modeller/property-sidebar/shapes/box-padding-editor-styles.ts +94 -0
  133. package/src/modeller/property-sidebar/shapes/shapes.ts +409 -0
  134. package/src/modeller/property-sidebar/specifics/specific-properties-builder.ts +135 -0
  135. package/src/modeller/property-sidebar/specifics/specifics.ts +72 -0
  136. package/src/modeller/property-sidebar/styles/styles.ts +578 -0
  137. package/src/modeller/scene-viewer/confidential-overlay.ts +18 -0
  138. package/src/modeller/scene-viewer/ox-scene-handler.ts +40 -0
  139. package/src/modeller/scene-viewer/ox-scene-layer.ts +42 -0
  140. package/src/modeller/scene-viewer/ox-scene-player.ts +104 -0
  141. package/src/modeller/scene-viewer/ox-scene-property.ts +10 -0
  142. package/src/modeller/scene-viewer/ox-scene-viewer.ts +248 -0
  143. package/src/ox-board-modeller.ts +138 -42
  144. package/src/types.ts +26 -0
  145. package/yarn-error.log +18355 -0
@@ -0,0 +1,104 @@
1
+ import { LitElement, PropertyValues, css, html } from 'lit'
2
+ import { customElement, property } from 'lit/decorators.js'
3
+
4
+ import { Scene } from '@hatiolab/things-scene'
5
+
6
+ @customElement('things-scene-player')
7
+ class OxScenePlayer extends LitElement {
8
+ static styles = [
9
+ css`
10
+ :host {
11
+ display: block;
12
+ width: 100%;
13
+ }
14
+
15
+ #root {
16
+ width: 100%;
17
+ height: 100%;
18
+ }
19
+ `
20
+ ]
21
+
22
+ @property({ type: String }) sceneId: string = ''
23
+ /*
24
+ * 캔바스에 모델을 어떻게 적절하게 보여줄 것인지를 설정한다.
25
+ *
26
+ * @none 가로, 세로 스케일을 1로 고정하고, {0, 0}좌표로 translate시킨다.
27
+ * @both 캔바스에 모델을 꼭 채우도록 가로, 세로 스케일을 조정하고, {0, 0}좌표로 translate시킨다.
28
+ * @width 캔바스의 폭에 모델의 폭을 일치하도록 가로, 세로 스케일을 동일하게 조정하고, {0, 0}좌표로 translate시킨다.
29
+ * @height 캔바스의 높이에 모델의 높이를 일치하도록 가로, 세로 스케일을 동일하게 조정하고, {0, 0}좌표로 translate시킨다.
30
+ * @center 가로, 세로 스케일을 1로 고정하고 모델이 화면의 중앙에 위치하도록 translate시킨다.
31
+ * @ratio 모델의 모든 부분이 캔바스에 최대 크기로 표현될 수 있도록 가로, 세로 동일한 스케일로 조정하고, {0, 0}좌표로 translate시킨다.
32
+ *
33
+ * @todo things-real 에서는 enumeration type 이며, FitMode.RATIO | FitMode.BOTH 중 하나로 정의한다.
34
+ */
35
+ @property({ type: String }) fit: 'none' | 'both' | 'width' | 'height' | 'center' | 'ratio' = 'ratio'
36
+ @property({ type: Object }) provider: any
37
+
38
+ private scene?: Scene
39
+
40
+ render() {
41
+ return html` <div id="root"></div> `
42
+ }
43
+
44
+ connectedCallback() {
45
+ super.connectedCallback()
46
+
47
+ window.addEventListener('resize', () => {
48
+ requestAnimationFrame(() => {
49
+ if (this.scene) {
50
+ this.scene.resize()
51
+
52
+ if (this.offsetWidth) {
53
+ this.scene.fit(this.fit)
54
+ }
55
+ }
56
+ })
57
+ })
58
+ }
59
+
60
+ disconnectedCallback() {
61
+ super.disconnectedCallback()
62
+
63
+ this._releaseRef()
64
+ }
65
+
66
+ updated(change: PropertyValues<this>) {
67
+ change.has('sceneId') && this._onSceneIdChanged()
68
+ }
69
+
70
+ _releaseRef() {
71
+ if (this.scene) {
72
+ this.scene.target = null
73
+ this.scene.release()
74
+ delete this.scene
75
+ }
76
+ }
77
+
78
+ _onSceneIdChanged() {
79
+ if (!this.provider) return
80
+
81
+ this._releaseRef()
82
+
83
+ if (!this.sceneId) return
84
+
85
+ this.provider.get(this.sceneId, true).then(
86
+ (scene: Scene) => {
87
+ this.scene = scene
88
+
89
+ if (!this.scene) {
90
+ return
91
+ }
92
+
93
+ this.scene.target = this.renderRoot.querySelector('#root')
94
+
95
+ /* 이 컴포넌트의 폭이 값을 가지고 있으면 - 화면상에 자리를 잡고 보여지고 있음을 의미한다.
96
+ * 이 때는 정상적으로 그려주고,
97
+ * 그렇지 않으면, 다음 Resize Handling시에 처리하도록 한다.
98
+ */
99
+ if (this.scene.target?.offsetWidth) this.scene.fit(this.fit)
100
+ },
101
+ (e: any) => {}
102
+ )
103
+ }
104
+ }
@@ -0,0 +1,10 @@
1
+ import { customElement, property } from 'lit/decorators.js'
2
+
3
+ import { LitElement } from 'lit'
4
+
5
+ @customElement('ox-scene-property')
6
+ export default class OxSceneProperty extends LitElement {
7
+ @property({ type: String }) name!: string
8
+ @property({ type: String }) value!: string
9
+ @property({ type: String }) type!: string
10
+ }
@@ -0,0 +1,248 @@
1
+ import './confidential-overlay'
2
+ import './ox-scene-layer'
3
+ import './ox-scene-handler'
4
+
5
+ import { Component, FITMODE, Model, Properties, SCENE_MODE, Scene, create as createScene } from '@hatiolab/things-scene'
6
+ import { LitElement, PropertyValues, css, html } from 'lit'
7
+ import { customElement, property } from 'lit/decorators.js'
8
+
9
+ import OxSceneLayer from './ox-scene-layer'
10
+
11
+ @customElement('ox-scene-viewer')
12
+ export default class OxSceneViewer extends LitElement {
13
+ static styles = css`
14
+ :host {
15
+ outline: none;
16
+ }
17
+ `
18
+
19
+ @property({ type: Object }) scene: Scene | null = null
20
+ @property({ type: Object }) model?: Model
21
+ /* Scene Mode - mode 0 : view mode, mode 1 : edit mode, mode 2 : shift mode */
22
+ @property({ type: Number }) mode: SCENE_MODE = SCENE_MODE.VIEW
23
+ @property({ type: Number }) screenSize: number = 13.3
24
+ @property({ type: Object }) variables: Properties = {}
25
+ @property({ type: Object }) data: any
26
+ /*
27
+ * 캔바스에 모델을 어떻게 적절하게 보여줄 것인지를 설정한다.
28
+ *
29
+ * @none 가로, 세로 스케일을 1로 고정하고, {0, 0}좌표로 translate시킨다.
30
+ * @both 캔바스에 모델을 꼭 채우도록 가로, 세로 스케일을 조정하고, {0, 0}좌표로 translate시킨다.
31
+ * @width 캔바스의 폭에 모델의 폭을 일치하도록 가로, 세로 스케일을 동일하게 조정하고, {0, 0}좌표로 translate시킨다.
32
+ * @height 캔바스의 높이에 모델의 높이를 일치하도록 가로, 세로 스케일을 동일하게 조정하고, {0, 0}좌표로 translate시킨다.
33
+ * @center 가로, 세로 스케일을 1로 고정하고 모델이 화면의 중앙에 위치하도록 translate시킨다.
34
+ * @ratio 모델의 모든 부분이 캔바스에 최대 크기로 표현될 수 있도록 가로, 세로 동일한 스케일로 조정하고, {0, 0}좌표로 translate시킨다.
35
+ */
36
+ @property({ type: String }) fit: FITMODE = 'none'
37
+ @property({ type: Array }) selected: Component[] = []
38
+ @property({ type: Boolean }) disposeWhenDetached: boolean = false
39
+ @property({ type: String }) baseUrl: string = ''
40
+ @property({ type: Object }) provider: any
41
+ @property({ type: String }) name: string = 'noname'
42
+ @property({ type: Boolean }) enableInspector: boolean = true
43
+ @property({ type: Boolean }) showInspector: boolean = false
44
+
45
+ private lastOffsetWidth?: number
46
+
47
+ disconnectedCallback() {
48
+ super.disconnectedCallback()
49
+
50
+ if (this.scene && this.disposeWhenDetached) {
51
+ this._disposeScene()
52
+ }
53
+ }
54
+
55
+ render() {
56
+ return html` <slot></slot> `
57
+ }
58
+
59
+ updated(change: PropertyValues<this>) {
60
+ change.has('model') && this._onModelChanged(this.model)
61
+ change.has('mode') && this._onModeChanged(this.mode)
62
+ change.has('screenSize') && this._onDisplayChanged(this.screenSize)
63
+ change.has('data') && this._onDataChanged(this.data)
64
+ change.has('baseUrl') && this._onBaseUrlChanged(this.baseUrl)
65
+ }
66
+
67
+ _setScene(scene: Scene | null) {
68
+ this.scene = scene
69
+ this.dispatchEvent(
70
+ new CustomEvent('scene-changed', {
71
+ bubbles: true,
72
+ composed: true,
73
+ detail: { value: scene }
74
+ })
75
+ )
76
+ }
77
+
78
+ _setMode(mode: SCENE_MODE) {
79
+ this.mode = mode
80
+ this.dispatchEvent(
81
+ new CustomEvent('mode-changed', {
82
+ bubbles: true,
83
+ composed: true,
84
+ detail: { value: mode }
85
+ })
86
+ )
87
+ }
88
+
89
+ _setVariables(variables: Properties) {
90
+ this.variables = variables
91
+ this.dispatchEvent(
92
+ new CustomEvent('variables-changed', {
93
+ bubbles: true,
94
+ composed: true,
95
+ detail: { value: variables }
96
+ })
97
+ )
98
+ }
99
+
100
+ _setSelected(selected: Component[]) {
101
+ this.selected = selected
102
+ this.dispatchEvent(
103
+ new CustomEvent('selected-changed', {
104
+ bubbles: true,
105
+ composed: true,
106
+ detail: { value: selected }
107
+ })
108
+ )
109
+ }
110
+
111
+ _disposeScene() {
112
+ if (this.scene) {
113
+ this.scene.off('selected', this._onSelectedChanged, this)
114
+ this.scene.off('mode', this._onSceneModeChanged, this)
115
+
116
+ if (this.provider) {
117
+ this.scene.release()
118
+ } else {
119
+ this.scene.dispose()
120
+ }
121
+
122
+ this._setScene(null)
123
+ this._setSelected([])
124
+ }
125
+ }
126
+
127
+ resize(force: boolean) {
128
+ if (typeof this.scene == 'object') {
129
+ if (force || this.fit === 'both' || Math.abs(this.offsetWidth - (this.lastOffsetWidth || 0)) >= 1) {
130
+ requestAnimationFrame(() => {
131
+ if (this.scene) {
132
+ this.scene.resize()
133
+ this.scene.fit(this.fit)
134
+ }
135
+ })
136
+ }
137
+
138
+ this.lastOffsetWidth = this.offsetWidth
139
+ }
140
+ }
141
+
142
+ _onModelChanged(model?: Model) {
143
+ this._disposeScene()
144
+
145
+ if (!model) {
146
+ return
147
+ }
148
+
149
+ const layers = Array.from(this.querySelectorAll('ox-scene-layer')).map(layer => (layer as OxSceneLayer).getModel())
150
+
151
+ const handlers = Array.from(this.querySelectorAll('ox-scene-handler')).map(handler => handler.getAttribute('type'))
152
+
153
+ this._setScene(
154
+ createScene({
155
+ target: this,
156
+ model: JSON.parse(JSON.stringify(model)),
157
+ layers,
158
+ handlers,
159
+ mode: this.mode,
160
+ refProvider: this.provider
161
+ })
162
+ )
163
+
164
+ if (this.provider) {
165
+ this.provider.add(this.name, this.scene)
166
+ }
167
+
168
+ this.scene!.screen = this.screenSize
169
+
170
+ /* 이 컴포넌트의 폭이 값을 가지고 있으면 - 화면상에 자리를 잡고 보여지고 있음을 의미한다.
171
+ * 이 때는 정상적으로 그려주고,
172
+ * 그렇지 않으면, 다음 Resize Handling시에 처리하도록 한다.
173
+ */
174
+ this.resize(true)
175
+
176
+ this._setVariables(model.variables || this.scene!.variables)
177
+
178
+ this.scene!.on('selected', this._onSelectedChanged, this)
179
+ this.scene!.on('mode', this._onSceneModeChanged, this)
180
+
181
+ this._onModeChanged(this.mode)
182
+ this._onDisplayChanged(this.screenSize)
183
+ this._onBaseUrlChanged(this.baseUrl)
184
+ }
185
+
186
+ _onDisplayChanged(screenSize: string | number) {
187
+ if (!this.scene) {
188
+ return
189
+ }
190
+
191
+ if (screenSize) {
192
+ this.scene.screen = parseFloat(String(screenSize))
193
+ }
194
+ }
195
+
196
+ _onModeChanged(mode: SCENE_MODE) {
197
+ if (!this.scene) {
198
+ return
199
+ }
200
+ this.scene.mode = Number(mode)
201
+ }
202
+
203
+ _onDataChanged(data: any) {
204
+ if (!this.scene || !data) {
205
+ return
206
+ }
207
+
208
+ this.scene.data = data
209
+ }
210
+
211
+ _onSelectedChanged(after: Component[]) {
212
+ /*
213
+ scene 컴포넌트의 속성을 속성 에디터(input box등)에서 변경하다가,
214
+ scene의 다른 컴포넌트를 클릭해서 포커스(선택) 컴포넌트를 변경하게되면,
215
+ 속성 에디터(input box등)의 value change 이벤트의 처리와 충돌(레이스)하게된다.
216
+
217
+ 기대하는 순서는 먼저 속성 에디터의 value change 이벤트를 처리한 후에,
218
+ selected 이벤트를 처리할 수 있도록 requestAnimationFrame으로 한 프레임을 지연하도록 하였다.
219
+ */
220
+ requestAnimationFrame(() => {
221
+ this._setSelected(after)
222
+ })
223
+ }
224
+
225
+ _onSceneModeChanged(after: SCENE_MODE) {
226
+ if (!this.scene) {
227
+ return
228
+ }
229
+
230
+ if (this.mode !== after) {
231
+ this._setMode(after)
232
+ }
233
+
234
+ if (after === 2) {
235
+ this.style.cursor = 'all-scroll'
236
+ } else {
237
+ this.style.cursor = 'default'
238
+ }
239
+ }
240
+
241
+ _onBaseUrlChanged(after: string) {
242
+ if (!this.scene) {
243
+ return
244
+ }
245
+
246
+ this.scene.baseUrl = after
247
+ }
248
+ }
@@ -1,37 +1,70 @@
1
1
  import '@material/mwc-fab'
2
- import './scene-viewer/things-scene-viewer'
3
- import './component-toolbar/component-toolbar'
4
- import './property-sidebar/property-sidebar'
2
+ import './modeller/scene-viewer/ox-scene-viewer'
3
+ import './modeller/component-toolbar/component-toolbar'
4
+ import './modeller/property-sidebar/property-sidebar'
5
+ import './modeller/edit-toolbar'
5
6
  import '@hatiolab/things-scene'
6
7
  import './ox-board-viewer'
7
8
 
8
- import { LitElement, css, html } from 'lit'
9
- import { SCENE_MODE, Scene } from '@hatiolab/things-scene'
10
- import { customElement, property, query, state } from 'lit/decorators.js'
9
+ import { saveAs } from 'file-saver'
10
+ import { css, html, LitElement } from 'lit'
11
+ import { customElement, property, query } from 'lit/decorators.js'
11
12
 
13
+ import { Scene, SCENE_MODE } from '@hatiolab/things-scene'
12
14
  import { OxPopup } from '@operato/popup'
13
15
 
16
+ import { EditToolbar } from './modeller/edit-toolbar'
17
+ import { togglefullscreen } from './utils/fullscreen'
18
+
14
19
  const isMacOS = navigator.userAgent.indexOf('Mac') != -1
15
20
 
16
- @customElement('board-modeller')
21
+ @customElement('ox-board-modeller')
17
22
  export class BoardModeller extends LitElement {
18
23
  static styles = [
19
24
  css`
20
25
  :host {
21
- display: flex;
22
- flex-direction: row;
26
+ display: grid;
27
+
28
+ grid-template-rows: auto 1fr;
29
+ grid-template-columns: auto 1fr auto;
30
+ grid-template-areas: 'toolbar toolbar toolbar' 'palletbar scene propertybar';
31
+ grid-gap: 0;
32
+
23
33
  height: 100%;
24
34
  overflow: hidden;
25
35
  }
26
36
 
37
+ #toolbar {
38
+ grid-area: toolbar;
39
+ }
40
+
41
+ edit-toolbar {
42
+ grid-area: toolbar;
43
+ }
44
+
45
+ component-toolbar {
46
+ grid-area: palletbar;
47
+ }
48
+
49
+ property-sidebar {
50
+ grid-area: propertybar;
51
+ overflow: hidden;
52
+ }
53
+
27
54
  #scene-wrap {
28
- flex: 1;
55
+ grid-area: scene;
29
56
  position: relative;
30
57
 
31
58
  display: flex;
32
59
  flex-direction: row;
33
60
  }
34
61
 
62
+ ox-scene-viewer {
63
+ flex: 1;
64
+ width: 100%;
65
+ height: 100%;
66
+ }
67
+
35
68
  mwc-fab {
36
69
  position: absolute;
37
70
  right: 15px;
@@ -73,29 +106,46 @@ export class BoardModeller extends LitElement {
73
106
  @property({ type: Array }) fonts: any[] = []
74
107
  @property({ type: Array }) propertyEditor: any[] = []
75
108
 
76
- private group: string = ''
109
+ @query('edit-toolbar') private editToolbar!: EditToolbar
77
110
 
78
- // @query('#scene-wrap') private modellingContainer!: HTMLElement
111
+ private group: string = ''
112
+ private shortcutHandler?: (e: KeyboardEvent) => void
79
113
 
80
114
  constructor() {
81
115
  super()
82
116
 
83
- // document.addEventListener('get-all-scene-component-ids', e => {
84
- // var { component, callback } = e.detail
117
+ document.addEventListener('get-all-scene-component-ids', (e: Event) => {
118
+ var { component, callback } = (e as CustomEvent).detail
85
119
 
86
- // if (!this.scene) return
120
+ if (!this.scene) return
87
121
 
88
- // var ids
89
- // if (component) ids = this.scene.findAll(component).map(c => c.model.id)
90
- // else ids = this.scene.ids.map(({ key, value }) => key)
122
+ var ids
123
+ if (component) {
124
+ ids = this.scene.findAll(component).map(c => c.model.id)
125
+ } else {
126
+ // @ts-ignore
127
+ ids = this.scene.ids.map(({ key }) => key)
128
+ }
91
129
 
92
- // ids = ids.filter(id => !!id).sort()
93
- // callback(ids)
94
- // })
130
+ ids = ids.filter(id => !!id).sort()
131
+ callback(ids)
132
+ })
95
133
  }
96
134
 
97
135
  render() {
98
136
  return html`
137
+ <edit-toolbar
138
+ id="edittoolbar"
139
+ .scene=${this.scene}
140
+ .selected=${this.selected}
141
+ @hide-property-changed=${(e: CustomEvent) => (this.hideProperty = e.detail.value)}
142
+ @open-preview=${() => this.preview()}
143
+ @download-model=${() => this.downloadModel()}
144
+ @modeller-fullscreen=${() => togglefullscreen(this)}
145
+ >
146
+ ${this.renderBrandingZone()}
147
+ </edit-toolbar>
148
+
99
149
  <component-toolbar
100
150
  .scene=${this.scene}
101
151
  .mode=${this.mode}
@@ -108,7 +158,7 @@ export class BoardModeller extends LitElement {
108
158
  </component-toolbar>
109
159
 
110
160
  <div id="scene-wrap">
111
- <things-scene-viewer
161
+ <ox-scene-viewer
112
162
  id="scene"
113
163
  .scene=${this.scene}
114
164
  @scene-changed=${(e: CustomEvent) => {
@@ -129,26 +179,26 @@ export class BoardModeller extends LitElement {
129
179
  .provider=${this.provider}
130
180
  name="modeller"
131
181
  >
132
- <things-scene-layer type="selection-layer"></things-scene-layer>
133
- <things-scene-layer type="modeling-layer"></things-scene-layer>
134
- <things-scene-layer type="guide-layer">
135
- <things-scene-property name="ruler" value="disabled"></things-scene-property>
136
- </things-scene-layer>
137
- <things-scene-layer type="shift-layer">
138
- <things-scene-property name="text" value="${this.overlay}"></things-scene-property>
139
- <things-scene-property name="alpha" value="0.3"></things-scene-property>
140
- <things-scene-property name="fontFamily" value="arial"></things-scene-property>
141
- <things-scene-property name="fontSize" value="30" type="number"></things-scene-property>
142
- <things-scene-property name="fontColor" value="navy"></things-scene-property>
143
- <things-scene-property name="textBaseline" value="top"></things-scene-property>
144
- <things-scene-property name="textAlign" value="left"></things-scene-property>
145
- <things-scene-property name="paddingTop" value="50" type="number"></things-scene-property>
146
- <things-scene-property name="paddingLeft" value="50" type="number"></things-scene-property>
147
- </things-scene-layer>
148
- <things-scene-layer type="tag-layer"></things-scene-layer>
149
- <things-scene-handler type="text-editor"></things-scene-handler>
150
- <things-scene-handler type="move-handler"></things-scene-handler>
151
- </things-scene-viewer>
182
+ <ox-scene-layer type="selection-layer"></ox-scene-layer>
183
+ <ox-scene-layer type="modeling-layer"></ox-scene-layer>
184
+ <ox-scene-layer type="guide-layer">
185
+ <ox-scene-property name="ruler" value="disabled"></ox-scene-property>
186
+ </ox-scene-layer>
187
+ <ox-scene-layer type="shift-layer">
188
+ <ox-scene-property name="text" value="${this.overlay}"></ox-scene-property>
189
+ <ox-scene-property name="alpha" value="0.3"></ox-scene-property>
190
+ <ox-scene-property name="fontFamily" value="arial"></ox-scene-property>
191
+ <ox-scene-property name="fontSize" value="30" type="number"></ox-scene-property>
192
+ <ox-scene-property name="fontColor" value="navy"></ox-scene-property>
193
+ <ox-scene-property name="textBaseline" value="top"></ox-scene-property>
194
+ <ox-scene-property name="textAlign" value="left"></ox-scene-property>
195
+ <ox-scene-property name="paddingTop" value="50" type="number"></ox-scene-property>
196
+ <ox-scene-property name="paddingLeft" value="50" type="number"></ox-scene-property>
197
+ </ox-scene-layer>
198
+ <ox-scene-layer type="tag-layer"></ox-scene-layer>
199
+ <ox-scene-handler type="text-editor"></ox-scene-handler>
200
+ <ox-scene-handler type="move-handler"></ox-scene-handler>
201
+ </ox-scene-viewer>
152
202
 
153
203
  <mwc-fab icon="save" @click=${() => this.onTapSave()} title="save"> </mwc-fab>
154
204
  </div>
@@ -164,6 +214,16 @@ export class BoardModeller extends LitElement {
164
214
  `
165
215
  }
166
216
 
217
+ connectedCallback(): void {
218
+ super.connectedCallback()
219
+ this.bindShortcutEvent()
220
+ }
221
+
222
+ disconnectedCallback(): void {
223
+ super.disconnectedCallback()
224
+ this.unbindShortcutEvent()
225
+ }
226
+
167
227
  close() {
168
228
  this.model = null
169
229
  this.requestUpdate()
@@ -199,9 +259,45 @@ export class BoardModeller extends LitElement {
199
259
  })
200
260
  }
201
261
 
262
+ downloadModel() {
263
+ if (!this.scene) return
264
+
265
+ var model = JSON.stringify(this.model, null, 2)
266
+ var filename = (this.boardName || 'NONAME') + '-' + Date.now() + '.json'
267
+ saveAs(new Blob([model], { type: 'application/octet-stream' }), filename)
268
+ }
269
+
270
+ renderBrandingZone() {
271
+ return html``
272
+ }
273
+
202
274
  onTapSave() {
203
275
  this.dispatchEvent(new CustomEvent('save-model', { bubbles: true, composed: true, detail: { model: this.model } }))
204
276
  }
205
277
 
278
+ bindShortcutEvent() {
279
+ // TODO: Global Hotkey에 대한 정의를 edit-toolbar에서 가져올 수 있도록 수정해야 함.
280
+ const GLOBAL_HOTKEYS = ['Digit1', 'Digit2', 'F11', 'KeyD', 'KeyP', 'KeyS']
281
+
282
+ this.shortcutHandler = (e: KeyboardEvent) => {
283
+ const target = e.composedPath()[0] as HTMLElement
284
+ var tagName = target.tagName
285
+ var isInput = target.isContentEditable || tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA'
286
+ var isGlobalHotkey = GLOBAL_HOTKEYS.includes(e.code)
287
+
288
+ if (!isGlobalHotkey && isInput) return
289
+ if (!this.editToolbar.onShortcut(e)) this.onShortcut(e)
290
+ }
291
+
292
+ document.addEventListener('keydown', this.shortcutHandler)
293
+ }
294
+
295
+ unbindShortcutEvent() {
296
+ if (this.shortcutHandler) {
297
+ document.removeEventListener('keydown', this.shortcutHandler)
298
+ delete this.shortcutHandler
299
+ }
300
+ }
301
+
206
302
  onContextMenu() {}
207
303
  }
package/src/types.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { Model } from '@hatiolab/things-scene'
2
+
3
+ export interface PalletItem {
4
+ type: string
5
+ description: string
6
+ icon: HTMLImageElement
7
+ group:
8
+ | 'line'
9
+ | 'shape'
10
+ | 'textAndMedio'
11
+ | 'chartAndGauge'
12
+ | 'table'
13
+ | 'container'
14
+ | 'IoT'
15
+ | '3D'
16
+ | 'warehouse'
17
+ | 'form'
18
+ | 'etc'
19
+ | string
20
+ model: Model
21
+ }
22
+
23
+ export interface Pallet {
24
+ name: string
25
+ templates: PalletItem[]
26
+ }