@operato/property-panel 9.0.0-beta.14

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 (156) hide show
  1. package/.editorconfig +29 -0
  2. package/.storybook/main.js +5 -0
  3. package/.storybook/preview.js +52 -0
  4. package/.storybook/server.mjs +8 -0
  5. package/CHANGELOG.md +11 -0
  6. package/LICENSE +21 -0
  7. package/README.md +76 -0
  8. package/demo/index.html +30 -0
  9. package/dist/src/graphql/board.d.ts +6 -0
  10. package/dist/src/graphql/board.js +130 -0
  11. package/dist/src/graphql/board.js.map +1 -0
  12. package/dist/src/graphql/data-subscription.d.ts +5 -0
  13. package/dist/src/graphql/data-subscription.js +24 -0
  14. package/dist/src/graphql/data-subscription.js.map +1 -0
  15. package/dist/src/graphql/favorite-board.d.ts +1 -0
  16. package/dist/src/graphql/favorite-board.js +23 -0
  17. package/dist/src/graphql/favorite-board.js.map +1 -0
  18. package/dist/src/graphql/group.d.ts +7 -0
  19. package/dist/src/graphql/group.js +125 -0
  20. package/dist/src/graphql/group.js.map +1 -0
  21. package/dist/src/graphql/index.d.ts +4 -0
  22. package/dist/src/graphql/index.js +5 -0
  23. package/dist/src/graphql/index.js.map +1 -0
  24. package/dist/src/graphql/play-group.d.ts +13 -0
  25. package/dist/src/graphql/play-group.js +205 -0
  26. package/dist/src/graphql/play-group.js.map +1 -0
  27. package/dist/src/graphql/scenario.d.ts +6 -0
  28. package/dist/src/graphql/scenario.js +69 -0
  29. package/dist/src/graphql/scenario.js.map +1 -0
  30. package/dist/src/index.d.ts +7 -0
  31. package/dist/src/index.js +8 -0
  32. package/dist/src/index.js.map +1 -0
  33. package/dist/src/ox-property-panel.d.ts +46 -0
  34. package/dist/src/ox-property-panel.js +346 -0
  35. package/dist/src/ox-property-panel.js.map +1 -0
  36. package/dist/src/property-panel/abstract-property.d.ts +10 -0
  37. package/dist/src/property-panel/abstract-property.js +53 -0
  38. package/dist/src/property-panel/abstract-property.js.map +1 -0
  39. package/dist/src/property-panel/data-binding/data-binding-mapper.d.ts +58 -0
  40. package/dist/src/property-panel/data-binding/data-binding-mapper.js +380 -0
  41. package/dist/src/property-panel/data-binding/data-binding-mapper.js.map +1 -0
  42. package/dist/src/property-panel/data-binding/data-binding-value-map.d.ts +6 -0
  43. package/dist/src/property-panel/data-binding/data-binding-value-map.js +20 -0
  44. package/dist/src/property-panel/data-binding/data-binding-value-map.js.map +1 -0
  45. package/dist/src/property-panel/data-binding/data-binding-value-range.d.ts +6 -0
  46. package/dist/src/property-panel/data-binding/data-binding-value-range.js +20 -0
  47. package/dist/src/property-panel/data-binding/data-binding-value-range.js.map +1 -0
  48. package/dist/src/property-panel/data-binding/data-binding.d.ts +44 -0
  49. package/dist/src/property-panel/data-binding/data-binding.js +442 -0
  50. package/dist/src/property-panel/data-binding/data-binding.js.map +1 -0
  51. package/dist/src/property-panel/effects/effects.d.ts +24 -0
  52. package/dist/src/property-panel/effects/effects.js +72 -0
  53. package/dist/src/property-panel/effects/effects.js.map +1 -0
  54. package/dist/src/property-panel/effects/property-animation.d.ts +23 -0
  55. package/dist/src/property-panel/effects/property-animation.js +147 -0
  56. package/dist/src/property-panel/effects/property-animation.js.map +1 -0
  57. package/dist/src/property-panel/effects/property-animations.d.ts +22 -0
  58. package/dist/src/property-panel/effects/property-animations.js +70 -0
  59. package/dist/src/property-panel/effects/property-animations.js.map +1 -0
  60. package/dist/src/property-panel/effects/property-event-hover.d.ts +21 -0
  61. package/dist/src/property-panel/effects/property-event-hover.js +193 -0
  62. package/dist/src/property-panel/effects/property-event-hover.js.map +1 -0
  63. package/dist/src/property-panel/effects/property-event-tap.d.ts +36 -0
  64. package/dist/src/property-panel/effects/property-event-tap.js +262 -0
  65. package/dist/src/property-panel/effects/property-event-tap.js.map +1 -0
  66. package/dist/src/property-panel/effects/property-event.d.ts +22 -0
  67. package/dist/src/property-panel/effects/property-event.js +64 -0
  68. package/dist/src/property-panel/effects/property-event.js.map +1 -0
  69. package/dist/src/property-panel/effects/property-shadow.d.ts +23 -0
  70. package/dist/src/property-panel/effects/property-shadow.js +66 -0
  71. package/dist/src/property-panel/effects/property-shadow.js.map +1 -0
  72. package/dist/src/property-panel/effects/value-converter.d.ts +1 -0
  73. package/dist/src/property-panel/effects/value-converter.js +17 -0
  74. package/dist/src/property-panel/effects/value-converter.js.map +1 -0
  75. package/dist/src/property-panel/inspector/inspector.d.ts +27 -0
  76. package/dist/src/property-panel/inspector/inspector.js +357 -0
  77. package/dist/src/property-panel/inspector/inspector.js.map +1 -0
  78. package/dist/src/property-panel/shapes/shapes.d.ts +26 -0
  79. package/dist/src/property-panel/shapes/shapes.js +312 -0
  80. package/dist/src/property-panel/shapes/shapes.js.map +1 -0
  81. package/dist/src/property-panel/specifics/specific-properties-builder.d.ts +16 -0
  82. package/dist/src/property-panel/specifics/specific-properties-builder.js +138 -0
  83. package/dist/src/property-panel/specifics/specific-properties-builder.js.map +1 -0
  84. package/dist/src/property-panel/specifics/specifics.d.ts +25 -0
  85. package/dist/src/property-panel/specifics/specifics.js +84 -0
  86. package/dist/src/property-panel/specifics/specifics.js.map +1 -0
  87. package/dist/src/property-panel/styles/styles.d.ts +23 -0
  88. package/dist/src/property-panel/styles/styles.js +269 -0
  89. package/dist/src/property-panel/styles/styles.js.map +1 -0
  90. package/dist/src/types.d.ts +43 -0
  91. package/dist/src/types.js +2 -0
  92. package/dist/src/types.js.map +1 -0
  93. package/dist/stories/index.stories.d.ts +22 -0
  94. package/dist/stories/index.stories.js +121 -0
  95. package/dist/stories/index.stories.js.map +1 -0
  96. package/dist/stories/input-table-property.stories.d.ts +21 -0
  97. package/dist/stories/input-table-property.stories.js +84 -0
  98. package/dist/stories/input-table-property.stories.js.map +1 -0
  99. package/dist/test/ox-property-panel.test.d.ts +1 -0
  100. package/dist/test/ox-property-panel.test.js +24 -0
  101. package/dist/test/ox-property-panel.test.js.map +1 -0
  102. package/dist/tsconfig.tsbuildinfo +1 -0
  103. package/package.json +108 -0
  104. package/src/graphql/board.ts +144 -0
  105. package/src/graphql/data-subscription.ts +30 -0
  106. package/src/graphql/favorite-board.ts +25 -0
  107. package/src/graphql/group.ts +138 -0
  108. package/src/graphql/index.ts +4 -0
  109. package/src/graphql/play-group.ts +225 -0
  110. package/src/graphql/scenario.ts +79 -0
  111. package/src/index.ts +8 -0
  112. package/src/ox-property-panel.ts +347 -0
  113. package/src/property-panel/abstract-property.ts +67 -0
  114. package/src/property-panel/data-binding/data-binding-mapper.ts +412 -0
  115. package/src/property-panel/data-binding/data-binding-value-map.ts +19 -0
  116. package/src/property-panel/data-binding/data-binding-value-range.ts +19 -0
  117. package/src/property-panel/data-binding/data-binding.ts +464 -0
  118. package/src/property-panel/effects/effects.ts +77 -0
  119. package/src/property-panel/effects/property-animation.ts +155 -0
  120. package/src/property-panel/effects/property-animations.ts +74 -0
  121. package/src/property-panel/effects/property-event-hover.ts +212 -0
  122. package/src/property-panel/effects/property-event-tap.ts +269 -0
  123. package/src/property-panel/effects/property-event.ts +73 -0
  124. package/src/property-panel/effects/property-shadow.ts +77 -0
  125. package/src/property-panel/effects/value-converter.ts +17 -0
  126. package/src/property-panel/inspector/inspector.ts +407 -0
  127. package/src/property-panel/shapes/shapes.ts +321 -0
  128. package/src/property-panel/specifics/specific-properties-builder.ts +152 -0
  129. package/src/property-panel/specifics/specifics.ts +81 -0
  130. package/src/property-panel/styles/styles.ts +287 -0
  131. package/src/types.ts +63 -0
  132. package/stories/index.stories.ts +134 -0
  133. package/stories/input-table-property.stories.ts +96 -0
  134. package/test/ox-property-panel.test.ts +32 -0
  135. package/themes/app-theme.css +138 -0
  136. package/themes/calendar-theme.css +61 -0
  137. package/themes/dark.css +51 -0
  138. package/themes/grist-theme.css +175 -0
  139. package/themes/help-theme.css +57 -0
  140. package/themes/layout-theme.css +94 -0
  141. package/themes/light.css +51 -0
  142. package/themes/material-theme.css +23 -0
  143. package/themes/md-typescale-styles.css +100 -0
  144. package/themes/oops-theme.css +22 -0
  145. package/themes/report-theme.css +47 -0
  146. package/themes/spacing.css +23 -0
  147. package/themes/state-color.css +6 -0
  148. package/themes/tooltip-theme.css +11 -0
  149. package/translations/en.json +723 -0
  150. package/translations/ja.json +727 -0
  151. package/translations/ko.json +727 -0
  152. package/translations/ms.json +609 -0
  153. package/translations/zh.json +726 -0
  154. package/tsconfig.json +25 -0
  155. package/web-dev-server.config.mjs +27 -0
  156. package/web-test-runner.config.mjs +41 -0
@@ -0,0 +1,321 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import '@operato/input/ox-input-angle.js'
6
+ import '@operato/input/ox-buttons-radio.js'
7
+ import '@material/web/icon/icon.js'
8
+ import '@operato/i18n/ox-i18n.js'
9
+ import '@operato/help/ox-title-with-help.js'
10
+
11
+ import { css, html } from 'lit'
12
+ import { property, state } from 'lit/decorators.js'
13
+ import { keyed } from 'lit/directives/keyed.js'
14
+
15
+ import { BOUNDS, Component, Properties } from '@hatiolab/things-scene'
16
+ import { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'
17
+ import { BoxPaddingEditorStyles } from '@operato/styles/box-padding-editor-styles.js'
18
+
19
+ import { AbstractProperty } from '../abstract-property.js'
20
+
21
+ export class PropertyShapes extends AbstractProperty {
22
+ static styles = [PropertyGridStyles, BoxPaddingEditorStyles]
23
+
24
+ @property({ type: Object }) value?: Properties
25
+ @property({ type: Object }) bounds: BOUNDS | null = null
26
+ @property({ type: Array }) selected: Component[] = []
27
+
28
+ @state() private _3dExpanded: boolean = false
29
+
30
+ firstUpdated() {
31
+ this.renderRoot.addEventListener('change', this.onValueChange.bind(this))
32
+ }
33
+
34
+ render() {
35
+ const value = this.value || {}
36
+ const { width, height } = this.bounds || {}
37
+
38
+ return html`
39
+ <fieldset>
40
+ <div class="property-grid">
41
+ ${this._isIdentifiable(this.selected)
42
+ ? html`
43
+ <label> <ox-i18n msgid="label.id">ID</ox-i18n> </label>
44
+ <input value-key="id" .value=${value.id || ''} />
45
+ `
46
+ : html``}
47
+ ${this._isClassIdentifiable(this.selected)
48
+ ? html`
49
+ <label> <ox-i18n msgid="label.class">Class</ox-i18n> </label>
50
+ <input value-key="class" .value=${value.class || ''} />
51
+ `
52
+ : html``}
53
+ ${this._hasTextProperty(this.selected)
54
+ ? html`
55
+ <label> <ox-i18n msgid="label.text">Text</ox-i18n> </label>
56
+ <input value-key="text" .value=${value.text || ''} />
57
+ <label> <ox-i18n msgid="label.text-format">Text Format</ox-i18n> </label>
58
+ <input value-key="textFormat" .value=${value.textFormat || ''} list="format-list" />
59
+ <datalist id="format-list">
60
+ <option value="#,###."></option>
61
+ <option value="#,###.#"></option>
62
+ <option value="#,###.0"></option>
63
+ <option value="#,##0.#"></option>
64
+ <option value="#,##0.0"></option>
65
+ <option value="#,##0.0%"></option>
66
+ </datalist>
67
+ `
68
+ : html``}
69
+ ${this._hasProperties(this.selected)
70
+ ? html`
71
+ <input id="checkbox-hidden" value-key="hidden" type="checkbox" .checked=${value.hidden} />
72
+ <label for="checkbox-hidden"> <ox-i18n msgid="label.item-hidden">Item Hidden</ox-i18n> </label>
73
+
74
+ <input id="checkbox-locked" value-key="locked" type="checkbox" .checked=${value.locked} />
75
+ <label for="checkbox-locked"> <ox-i18n msgid="label.locked">Locked</ox-i18n> </label>
76
+ `
77
+ : html``}
78
+ </div>
79
+ </fieldset>
80
+
81
+ ${!this._isLine(this.selected)
82
+ ? keyed(
83
+ this.selected,
84
+ html`
85
+ <fieldset class="icon-label unit ratio">
86
+ <legend>
87
+ <ox-title-with-help topic="board-modeller/shapes/size" msgid="label.size">size</ox-title-with-help>
88
+ </legend>
89
+
90
+ <div class="property-grid">
91
+ <label class="width"> <ox-i18n msgid="label.width">width</ox-i18n> </label>
92
+ <input type="number" value-key="bounds.width" .value=${String(width)} />
93
+ <label class="height"> <ox-i18n msgid="label.height">height</ox-i18n> </label>
94
+ <input type="number" value-key="bounds.height" .value=${String(height)} />
95
+
96
+ ${this.selected.length && this.selected[0].isRootModel()
97
+ ? html``
98
+ : html`
99
+ <label class="rotate"> <ox-i18n msgid="label.rotate">rotate</ox-i18n> </label>
100
+ <ox-input-angle value-key="rotation" .value=${value.rotation}> </ox-input-angle>
101
+ `}
102
+ </div>
103
+ </fieldset>
104
+ `
105
+ )
106
+ : html``}
107
+ ${this._is3dish(this.selected)
108
+ ? html`
109
+ <fieldset class="icon-label unit ratio" collapsable ?collapsed=${!this._3dExpanded}>
110
+ <legend>
111
+ <ox-title-with-help topic="board-modeller/shapes/3dish" msgid="label.3dish">3D</ox-title-with-help>
112
+ <md-icon
113
+ @click=${(e: Event) => {
114
+ this._3dExpanded = !this._3dExpanded
115
+ }}
116
+ >${this._3dExpanded ? 'expand_less' : 'expand_more'}</md-icon
117
+ >
118
+ </legend>
119
+
120
+ <div class="property-grid">
121
+ <label class="zPos"> <ox-i18n msgid="label.z-pos">pos. Z</ox-i18n> </label>
122
+ <input type="number" value-key="zPos" .value=${value.zPos} />
123
+ <label class="depth"> <ox-i18n msgid="label.depth">depth</ox-i18n> </label>
124
+ <input type="number" value-key="depth" .value=${value.depth} />
125
+
126
+ <label class="rotationX"> <ox-i18n msgid="label.rotation-x">rot. X</ox-i18n> </label>
127
+ <ox-input-angle value-key="rotationX" .value=${value.rotationX}> </ox-input-angle>
128
+
129
+ <label class="rotationY"> <ox-i18n msgid="label.rotation-y">rot. Y</ox-i18n> </label>
130
+ <ox-input-angle value-key="rotationY" .value=${value.rotationY}> </ox-input-angle>
131
+
132
+ <label class="rotationZ"> <ox-i18n msgid="label.rotation-z">rot. Z</ox-i18n> </label>
133
+ <ox-input-angle value-key="rotation" .value=${value.rotation}> </ox-input-angle>
134
+ </div>
135
+ </fieldset>
136
+ `
137
+ : html``}
138
+ ${this._hasTextProperty(this.selected)
139
+ ? html`
140
+ <fieldset>
141
+ <legend>
142
+ <ox-title-with-help topic="board-modeller/shapes/text-box" msgid="label.text-box"
143
+ >text box</ox-title-with-help
144
+ >
145
+ </legend>
146
+
147
+ <div class="property-grid">
148
+ <label> <ox-i18n msgid="label.horizontal">horizontal</ox-i18n> </label>
149
+ <ox-buttons-radio value-key="textAlign" .value=${value.textAlign}>
150
+ <md-icon data-value="left">format_align_left</md-icon>
151
+ <md-icon data-value="center">format_align_center</md-icon>
152
+ <md-icon data-value="right">format_align_right</md-icon>
153
+ <md-icon data-value="justify">format_align_justify</md-icon>
154
+ </ox-buttons-radio>
155
+
156
+ <label> <ox-i18n msgid="label.vertical">vertical</ox-i18n> </label>
157
+ <ox-buttons-radio value-key="textBaseline" .value=${value.textBaseline}>
158
+ <md-icon data-value="top">align_vertical_top</md-icon>
159
+ <md-icon data-value="middle">align_vertical_center</md-icon>
160
+ <md-icon data-value="bottom">align_vertical_bottom</md-icon>
161
+ </ox-buttons-radio>
162
+
163
+ <input
164
+ id="checkbox-support-markdown"
165
+ type="checkbox"
166
+ value-key="supportMarkdown"
167
+ .checked=${value.supportMarkdown}
168
+ />
169
+ <label for="checkbox-support-markdown">
170
+ <ox-i18n msgid="label.support-markdown">Support Markdown</ox-i18n>
171
+ </label>
172
+
173
+ <input id="checkbox-textwrap" type="checkbox" value-key="textWrap" .checked=${value.textWrap} />
174
+ <label for="checkbox-textwrap"> <ox-i18n msgid="label.text-wrap">Text Wrap</ox-i18n> </label>
175
+
176
+ ${!value.textWrap
177
+ ? html` <label for="checkbox-textOverflow">
178
+ <ox-i18n msgid="label.text-overflow">Text Overflow</ox-i18n>
179
+ </label>
180
+ <select value-key="textOverflow" .value=${value.textOverflow || ''}>
181
+ <option value="" selected>none</option>
182
+ <option value="ellipsis">ellipsis</option>
183
+ <option value="clip">clip</option>
184
+ </select>`
185
+ : ''}
186
+
187
+ <label> <ox-i18n msgid="label.padding">padding</ox-i18n> </label>
188
+ <table class="box-padding">
189
+ <tr>
190
+ <td class="slide1"></td>
191
+ <td class="slide2"></td>
192
+ <td class="slide3"></td>
193
+ </tr>
194
+ <tr>
195
+ <td class="slide4"></td>
196
+ <td class="slide5">
197
+ <input type="number" value-key="paddingTop" .value=${value.paddingTop || 0} />
198
+ <input type="number" value-key="paddingLeft" .value=${value.paddingLeft || 0} />
199
+ <input type="number" value-key="paddingRight" .value=${value.paddingRight || 0} />
200
+ <input type="number" value-key="paddingBottom" .value=${value.paddingBottom || 0} />
201
+ </td>
202
+ <td class="slide6"></td>
203
+ </tr>
204
+ <tr>
205
+ <td class="slide7"></td>
206
+ <td class="slide8"></td>
207
+ <td class="slide9"></td>
208
+ </tr>
209
+ </table>
210
+ </div>
211
+ </fieldset>
212
+ `
213
+ : html``}
214
+ ${this.selected.length && this.selected[0].isRootModel()
215
+ ? html`
216
+ <fieldset class="icon-label">
217
+ <legend>
218
+ <ox-title-with-help topic="board-modeller/shapes/viewer-option" msgid="label.viewer-option"
219
+ >Viewer Option</ox-title-with-help
220
+ >
221
+ </legend>
222
+
223
+ <div class="property-grid">
224
+ <label><ox-i18n msgid="label.fit">Fit</ox-i18n></label>
225
+ <select value-key="fitMode" .value=${value.fitMode || 'ratio'}>
226
+ <option value="none">none</option>
227
+ <option value="center">center</option>
228
+ <option value="ratio" selected>ratio</option>
229
+ <option value="both">both</option>
230
+ <option value="width">width</option>
231
+ <option value="height">height</option>
232
+ </select>
233
+ </div>
234
+ </fieldset>
235
+ <fieldset class="icon-label">
236
+ <legend>
237
+ <ox-title-with-help topic="board-modeller/shapes/print-option" msgid="label.label-print"
238
+ >Print Option</ox-title-with-help
239
+ >
240
+ </legend>
241
+
242
+ <div class="property-grid">
243
+ <label class="rotate"><ox-i18n msgid="label.label-rotation">Label Rotation</ox-i18n></label>
244
+ <select value-key="labelRotation" .value=${value.labelRotation || 'N'}>
245
+ <option value="N" selected>0°</option>
246
+ <option value="B">90°</option>
247
+ <option value="I">180°</option>
248
+ <option value="R">270°</option>
249
+ </select>
250
+ </div>
251
+ </fieldset>
252
+ `
253
+ : html``}
254
+ `
255
+ }
256
+
257
+ onValueChange(e: Event) {
258
+ var element = e.target as HTMLElement
259
+ var key = element.getAttribute('value-key')
260
+
261
+ if (!key) {
262
+ return
263
+ }
264
+
265
+ var value = this.getValueFromEventTarget(element)
266
+
267
+ if (key.indexOf('bounds.') == 0) {
268
+ if (isNaN(value)) return
269
+ this.dispatchEvent(
270
+ new CustomEvent('bounds-change', {
271
+ bubbles: true,
272
+ composed: true,
273
+ detail: {
274
+ [key.substr(7)]: value
275
+ }
276
+ })
277
+ )
278
+ } else {
279
+ this.onAfterValueChange(key, value)
280
+ }
281
+ }
282
+
283
+ _hasTextProperty(selected: Component[]) {
284
+ for (let i = 0; i < selected.length; i++) {
285
+ if (!selected[i].hasTextProperty) return false
286
+ }
287
+
288
+ return true
289
+ }
290
+
291
+ _hasProperties(selected: Component[]) {
292
+ if (!selected || selected.length == 0 || (selected[0] && selected[0].isLayer && selected[0].isLayer())) return false
293
+
294
+ return true
295
+ }
296
+
297
+ _isIdentifiable(selected: Component[]) {
298
+ if (!selected || selected.length == 0 || selected.length > 1 || (selected[0].isLayer && selected[0].isLayer()))
299
+ return false
300
+
301
+ return true
302
+ }
303
+
304
+ _isClassIdentifiable(selected: Component[]) {
305
+ if (!selected || (selected[0] && selected[0].isLayer())) return false
306
+
307
+ return true
308
+ }
309
+
310
+ _isLine(selected: Component[]) {
311
+ if (!selected || !(selected[0] && selected[0].isLine())) return false
312
+
313
+ return true
314
+ }
315
+
316
+ _is3dish(selected: Component[]) {
317
+ if (!selected || !(selected[0] && selected[0].is3dish())) return false
318
+
319
+ return true
320
+ }
321
+ }
@@ -0,0 +1,152 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import '@operato/app/property-editor.js' /* for registering property editors */
6
+
7
+ import { html, LitElement, PropertyValues } from 'lit'
8
+ import { property } from 'lit/decorators.js'
9
+
10
+ import { Properties } from '@hatiolab/things-scene'
11
+ import { OxPropertyEditor, PropertySpec } from '@operato/property-editor'
12
+
13
+ /**
14
+ 모든 에디터들은 change 이벤트를 지원해야 한다. 또한, 모든 에디터들은 value속성에 값을 가져야 한다.
15
+
16
+ Example:
17
+
18
+ <specific-properties-builder value="{{value}}">
19
+ <label>Center X</label>
20
+ <input type="number" .value="${value.cx}">
21
+ <label>Width</label>
22
+ <input type="number" .value="${value.width}">
23
+ </specific-properties-builder>
24
+ */
25
+
26
+ const DEFAULT_VALUE = {
27
+ legend: '',
28
+ // number: 0, // should be undefined
29
+ angle: 0,
30
+ string: '',
31
+ password: '',
32
+ textarea: '',
33
+ checkbox: false,
34
+ select: '',
35
+ color: '#000000',
36
+ 'solidcolor-stops': null,
37
+ 'gradientcolor-stops': null,
38
+ 'gltf-selector': '',
39
+ 'image-selector': '',
40
+ multiplecolor: null,
41
+ editortable: null,
42
+ imageselector: '',
43
+ options: null,
44
+ date: null
45
+ }
46
+
47
+ function convertValue(type: string, value: any) {
48
+ var converted = String(value).trim() == '' ? undefined : value
49
+ switch (type) {
50
+ case 'number':
51
+ case 'angle':
52
+ converted = parseFloat(value)
53
+ converted = isNaN(converted) ? undefined : converted
54
+ break
55
+ }
56
+
57
+ return converted
58
+ }
59
+
60
+ export class SpecificPropertiesBuilder extends LitElement {
61
+ @property({ type: Object }) value: any
62
+ @property({ type: Array }) props: any[] = []
63
+ @property({ type: Object }) propertyEditor: any
64
+
65
+ render() {
66
+ return html`<slot></slot>`
67
+ }
68
+
69
+ firstUpdated() {
70
+ this.addEventListener('change', this.onValueChanged.bind(this))
71
+ }
72
+
73
+ updated(changes: PropertyValues<this>) {
74
+ changes.has('props') && this._onPropsChanged(this.props)
75
+ changes.has('value') && this._setValues()
76
+ }
77
+
78
+ _onPropsChanged(props: any[]) {
79
+ this.textContent = ''
80
+ ;(props || []).forEach((spec: PropertySpec) => {
81
+ const { label, type, placeholder, name, observe, property, editor, quantifier, defaultValue, disabled } = spec
82
+
83
+ let elementType = OxPropertyEditor.getEditor(type)
84
+ if (!elementType) {
85
+ console.warn('Property Editor not defined', type)
86
+ return
87
+ }
88
+ let element = document.createElement(elementType) as OxPropertyEditor
89
+
90
+ element.label = label
91
+ element.type = type
92
+ element.placeholder = placeholder
93
+ element.name = name
94
+ element.setAttribute('name', name)
95
+
96
+ if (observe) {
97
+ element.observeHandler = observe
98
+ }
99
+ element.property = property
100
+ element.editor = editor
101
+ element.quantifier = quantifier
102
+ element.defaultValue = defaultValue
103
+ element.setAttribute('property-editor', 'true')
104
+ element.disabled = disabled
105
+
106
+ this.appendChild(element)
107
+ })
108
+ }
109
+
110
+ _setValues() {
111
+ this.value &&
112
+ Array.from(this.querySelectorAll('[name]')).forEach((prop: Properties) => {
113
+ let name = prop.getAttribute('name')
114
+ if (!name) {
115
+ return
116
+ }
117
+ var convertedValue = convertValue(prop.type, this.value[name])
118
+ if (convertedValue === undefined) {
119
+ convertedValue = (DEFAULT_VALUE as any)[prop.type]
120
+ }
121
+ prop.value = convertedValue
122
+ prop.observe.call(prop, prop.value)
123
+ })
124
+ }
125
+
126
+ onValueChanged(e: Event) {
127
+ e.stopPropagation()
128
+ var target = e.target as Element
129
+
130
+ const prop = target.closest('[property-editor]') as OxPropertyEditor
131
+
132
+ var name = prop.getAttribute('name')
133
+ if (!name) {
134
+ return
135
+ }
136
+
137
+ this.value[name] = prop.value
138
+
139
+ prop.observe(prop.value)
140
+ this._setValues()
141
+
142
+ this.dispatchEvent(
143
+ new CustomEvent('property-change', {
144
+ bubbles: true,
145
+ composed: true,
146
+ detail: {
147
+ [name]: prop.value
148
+ }
149
+ })
150
+ )
151
+ }
152
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import '@operato/help/ox-help-icon.js'
6
+
7
+ import { css, html, LitElement } from 'lit'
8
+ import { property } from 'lit/decorators.js'
9
+
10
+ import { Component, Scene } from '@hatiolab/things-scene'
11
+ import { ScopedElementsMixin } from '@open-wc/scoped-elements'
12
+
13
+ import { i18next } from '@operato/i18n'
14
+ import { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'
15
+
16
+ import { SpecificPropertiesBuilder } from './specific-properties-builder.js'
17
+
18
+ export class PropertySpecific extends ScopedElementsMixin(LitElement) {
19
+ static styles = [
20
+ PropertyGridStyles,
21
+ css`
22
+ label {
23
+ display: block;
24
+ margin: 10px;
25
+
26
+ text-align: right;
27
+ font: bold 14px var(--theme-font);
28
+ color: var(--md-sys-color-on-primary-container);
29
+ text-transform: capitalize;
30
+ }
31
+ `
32
+ ]
33
+
34
+ @property({ type: Object }) value: any
35
+ @property({ type: Object }) scene: Scene | null = null
36
+ @property({ type: Array }) selected: Component[] = []
37
+ @property({ type: Array }) props: any[] = []
38
+ @property({ type: Array }) propertyEditor: any[] = []
39
+
40
+ private boundINeedSelected: any = this.onINeedSelected.bind(this)
41
+
42
+ connectedCallback() {
43
+ super.connectedCallback()
44
+
45
+ this.addEventListener('i-need-selected', this.boundINeedSelected)
46
+ }
47
+
48
+ disconnectedCallback() {
49
+ super.disconnectedCallback()
50
+
51
+ this.removeEventListener('i-need-selected', this.boundINeedSelected)
52
+ }
53
+ static get scopedElements() {
54
+ return {
55
+ 'specific-properties-builder': SpecificPropertiesBuilder
56
+ }
57
+ }
58
+ render() {
59
+ const selected = this.selected && this.selected[0]
60
+ const value = this.value || {}
61
+
62
+ return html`
63
+ <label
64
+ >${i18next.t(`component.${value.type}`)}<ox-help-icon .topic=${selected?.nature?.help}></ox-help-icon
65
+ ></label>
66
+
67
+ <specific-properties-builder .value=${value} .props=${this.props} .propertyEditor=${this.propertyEditor}>
68
+ </specific-properties-builder>
69
+ `
70
+ }
71
+
72
+ private onINeedSelected(e: CustomEvent) {
73
+ e.stopPropagation()
74
+
75
+ var { callback } = e.detail
76
+
77
+ this.scene!.undoableChange(() => {
78
+ callback.call(null, this.selected)
79
+ })
80
+ }
81
+ }