@operato/property-panel 10.20.0 → 10.23.0

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 (32) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/src/ox-property-panel.d.ts +1 -0
  3. package/dist/src/ox-property-panel.js +15 -0
  4. package/dist/src/ox-property-panel.js.map +1 -1
  5. package/dist/src/property-panel/data-binding/data-binding-mapper.js +20 -7
  6. package/dist/src/property-panel/data-binding/data-binding-mapper.js.map +1 -1
  7. package/dist/src/property-panel/data-binding/data-binding.d.ts +4 -0
  8. package/dist/src/property-panel/data-binding/data-binding.js +167 -56
  9. package/dist/src/property-panel/data-binding/data-binding.js.map +1 -1
  10. package/dist/src/property-panel/event-handlers/event-handlers-mapper.js +37 -16
  11. package/dist/src/property-panel/event-handlers/event-handlers-mapper.js.map +1 -1
  12. package/dist/src/property-panel/event-handlers/event-handlers-popup.d.ts +1 -0
  13. package/dist/src/property-panel/event-handlers/event-handlers-popup.js +48 -0
  14. package/dist/src/property-panel/event-handlers/event-handlers-popup.js.map +1 -1
  15. package/dist/src/property-panel/event-handlers/event-handlers.d.ts +3 -0
  16. package/dist/src/property-panel/event-handlers/event-handlers.js +173 -86
  17. package/dist/src/property-panel/event-handlers/event-handlers.js.map +1 -1
  18. package/dist/src/property-panel/shapes/shapes.d.ts +2 -0
  19. package/dist/src/property-panel/shapes/shapes.js +78 -29
  20. package/dist/src/property-panel/shapes/shapes.js.map +1 -1
  21. package/dist/src/property-panel/specifics/specifics.js +62 -6
  22. package/dist/src/property-panel/specifics/specifics.js.map +1 -1
  23. package/dist/src/property-panel/styles/styles.js +61 -31
  24. package/dist/src/property-panel/styles/styles.js.map +1 -1
  25. package/dist/src/property-panel/threed/property-material3d.js +10 -9
  26. package/dist/src/property-panel/threed/property-material3d.js.map +1 -1
  27. package/dist/src/property-panel/threed/property-scene3d.js +11 -9
  28. package/dist/src/property-panel/threed/property-scene3d.js.map +1 -1
  29. package/dist/src/property-panel/threed/threed.js +41 -18
  30. package/dist/src/property-panel/threed/threed.js.map +1 -1
  31. package/dist/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +6 -6
@@ -7,7 +7,7 @@ import '@operato/help/ox-title-with-help.js';
7
7
  import '@operato/input/ox-buttons-radio.js';
8
8
  import '@operato/input/ox-input-data.js';
9
9
  import '@operato/i18n/ox-i18n.js';
10
- import { css, html } from 'lit';
10
+ import { css, html, nothing } from 'lit';
11
11
  import { property, query, state } from 'lit/decorators.js';
12
12
  import { ScopedElementsMixin } from '@open-wc/scoped-elements';
13
13
  import { PropertyGridStyles } from '@operato/styles/property-grid-styles.js';
@@ -47,7 +47,15 @@ export class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {
47
47
  constructor() {
48
48
  super(...arguments);
49
49
  this.mappingIndex = 0;
50
+ /*
51
+ * A mapping is written to the model only once it names a property. Until then the mapper's
52
+ * edits (rule, source, target...) live here, per tab, so the choice does not snap back to the
53
+ * empty mapping on the next render. Cleared when another shape is selected.
54
+ */
55
+ this._drafts = {};
50
56
  this._dataExpanded = false;
57
+ /* True while a new mapping is being composed and is not yet in the model (no property chosen). */
58
+ this._composing = false;
51
59
  this.mapping = {};
52
60
  }
53
61
  get mappings() {
@@ -56,13 +64,20 @@ export class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {
56
64
  }
57
65
  firstUpdated() {
58
66
  this.renderRoot.addEventListener('change', this.onValueChange.bind(this));
59
- this.tabContainer.addEventListener('scroll', () => {
60
- this._onTabScroll();
61
- });
67
+ /* The tab strip only exists once there is a mapping, so listen from the root (scroll does not
68
+ * bubble; capture catches it) instead of on an element that may not be there yet. */
69
+ this.renderRoot.addEventListener('scroll', e => e.target.id === 'tabs' && this._onTabScroll(), true);
62
70
  }
63
71
  updated(changes) {
72
+ var _a, _b;
64
73
  if (changes.has('value')) {
65
74
  this.onValueChanged();
75
+ const selected = (_b = (_a = this.scene) === null || _a === void 0 ? void 0 : _a.selected) === null || _b === void 0 ? void 0 : _b[0];
76
+ if (selected !== this._draftsFor) {
77
+ this._draftsFor = selected;
78
+ this._drafts = {};
79
+ this._composing = false;
80
+ }
66
81
  }
67
82
  }
68
83
  static get scopedElements() {
@@ -128,20 +143,23 @@ export class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {
128
143
  <ox-title-with-help topic="board-modeller/data-spread" msgid="label.data-spread"
129
144
  >Data Spread</ox-title-with-help
130
145
  >
146
+ ${this.mappings.length ? html `<span class="count">${this.mappings.length}</span>` : nothing}
131
147
  <md-icon
132
- style="float:right;font-size:medium;margin:0;cursor:pointer"
148
+ class="open-popup"
133
149
  @click=${() => this._openBindingPopup()}
134
150
  title="open in popup (D)"
135
151
  >open_in_new</md-icon
136
152
  >
137
153
  </legend>
138
154
 
155
+ ${this.mappings.length || this._composing
156
+ ? html `
139
157
  <div id="tab-header">
140
158
  <md-icon
141
159
  id="tab-nav-left-button"
142
160
  @click=${() => {
143
- this._onTabScrollNavLeft();
144
- }}
161
+ this._onTabScrollNavLeft();
162
+ }}
145
163
  disabled
146
164
  >chevron_left</md-icon
147
165
  >
@@ -150,25 +168,26 @@ export class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {
150
168
  id="tabs"
151
169
  .value=${String(this.mappingIndex)}
152
170
  @change=${(e) => {
153
- e.stopPropagation();
154
- this._setMappingIndex(e.target.value);
155
- }}
171
+ e.stopPropagation();
172
+ this._setMappingIndex(e.target.value);
173
+ }}
156
174
  >
157
175
  ${this.mappings.map((m, i) => html ` <div data-value=${i} data-mapping>${i + 1}</div> `)}
158
- <div data-value=${this.mappings.length} data-mapping disabled>${this.mappings.length + 1}</div>
176
+ <div data-value=${this.mappings.length} class="add-tab" title="add" @click=${() => (this._composing = true)}>
177
+ +
178
+ </div>
159
179
  </ox-buttons-radio>
160
180
 
161
181
  <md-icon
162
182
  id="tab-nav-right-button"
163
183
  @click=${(e) => {
164
- this._onTabScrollNavRight();
165
- }}
184
+ this._onTabScrollNavRight();
185
+ }}
166
186
  disabled
167
187
  >chevron_right</md-icon
168
188
  >
169
- </div>
170
189
 
171
- <div binding>
190
+ <div binding>
172
191
  <md-icon style="font-size:19px" @click=${() => this._clearDataBindingMapper()} title="delete current tab"
173
192
  >delete_forever</md-icon
174
193
  >
@@ -176,18 +195,30 @@ export class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {
176
195
  <md-icon style="font-size:17px" @click=${() => this._copyDataBindingMapper()} title="copy current tab"
177
196
  >content_copy</md-icon
178
197
  >
198
+ </div>
179
199
  </div>
180
200
 
201
+
181
202
  <data-binding-mapper
182
203
  @value-change=${(e) => this._onMappingChanged(e)}
183
204
  .scene=${this.scene}
184
- .mapping=${(value.mappings && value.mappings[this.mappingIndex]) || {}}
205
+ .mapping=${(value.mappings && value.mappings[this.mappingIndex]) || this._drafts[this.mappingIndex] || {}}
185
206
  .properties=${PROPS}
186
207
  >
187
208
  </data-binding-mapper>
209
+ `
210
+ : html `
211
+ <button class="add" @click=${() => this._startMapping()}>
212
+ <md-icon>add</md-icon>${i18next.t('button.add-mapping', { defaultValue: 'Add a mapping' })}
213
+ </button>
214
+ `}
188
215
  </fieldset>
189
216
  `;
190
217
  }
218
+ _startMapping() {
219
+ this._composing = true;
220
+ this.mappingIndex = this.mappings.length;
221
+ }
191
222
  _setMappingIndex(idx) {
192
223
  this.mappingIndex = isNaN(Number(idx)) ? 0 : Number(idx);
193
224
  this._onTabScroll();
@@ -275,6 +306,9 @@ export class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {
275
306
  /* mapping의 모든 속성이 편집되면, 모델에 반영한다. */
276
307
  var mappings = [...(((_a = this.value) === null || _a === void 0 ? void 0 : _a.mappings) || [])];
277
308
  if (mapping.property) {
309
+ const drafts = { ...this._drafts };
310
+ delete drafts[this.mappingIndex];
311
+ this._drafts = drafts;
278
312
  mappings[this.mappingIndex] = mapping;
279
313
  var mappingIdx = this.mappingIndex;
280
314
  this._afterRender = () => {
@@ -290,7 +324,12 @@ export class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {
290
324
  }));
291
325
  await this.requestUpdate();
292
326
  }
293
- else if (!mapping.target && !mapping.property) {
327
+ else {
328
+ /* Not complete yet: keep what has been chosen so far for this tab. */
329
+ this._drafts = { ...this._drafts, [this.mappingIndex]: mapping };
330
+ }
331
+ /* Only a mapping the model already holds can be "cleared"; an unfinished draft is just unfinished. */
332
+ if (!mapping.property && !mapping.target && mappings[this.mappingIndex]) {
294
333
  const { accessor, source } = ((_b = e.detail) === null || _b === void 0 ? void 0 : _b.changed) || {};
295
334
  // accessor나 source를 입력중인 경우 tabIndex Change 방지
296
335
  if (!accessor && !source) {
@@ -310,6 +349,8 @@ export class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {
310
349
  }
311
350
  }
312
351
  _onTabScroll() {
352
+ if (!this.tabContainer || !this.tabNavLeftButton)
353
+ return;
313
354
  if (this.tabContainer.clientWidth == this.tabContainer.scrollWidth) {
314
355
  this.tabNavLeftButton.setAttribute('disabled', '');
315
356
  this.tabNavRightButton.setAttribute('disabled', '');
@@ -343,19 +384,86 @@ export class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {
343
384
  PropertyDataBinding.styles = [
344
385
  PropertyGridStyles,
345
386
  css `
387
+ /* The "open in popup" action is the last thing on the title line, at the far right. */
388
+ legend > md-icon.open-popup {
389
+ margin-left: auto;
390
+ --md-icon-size: 16px;
391
+ color: var(--md-sys-color-outline);
392
+ opacity: 0.6;
393
+ cursor: pointer;
394
+ }
395
+
396
+ legend > md-icon.open-popup:hover {
397
+ color: var(--md-sys-color-on-surface);
398
+ }
399
+
346
400
  #tab-header {
347
401
  display: flex;
348
402
  align-items: center;
349
403
  justify-content: space-between;
350
404
  }
351
405
 
406
+ #tab-header {
407
+ display: flex;
408
+ align-items: center;
409
+ gap: 2px;
410
+ margin-bottom: 6px;
411
+ }
412
+
352
413
  #tab-header > md-icon {
353
414
  padding: 0;
354
415
  margin: 0;
355
- width: 25px;
356
- height: 25px;
357
- font-size: x-large;
358
- border-bottom: 1px solid rgba(0, 0, 0, 0.2);
416
+ --md-icon-size: 18px;
417
+ color: var(--md-sys-color-outline);
418
+ }
419
+
420
+ #tab-header > md-icon[disabled] {
421
+ opacity: 0.3;
422
+ }
423
+
424
+ /* How many there are, as a small muted count next to the title. */
425
+ legend > .count {
426
+ margin-left: 6px;
427
+ padding: 0 6px;
428
+ border-radius: 999px;
429
+ font-size: 0.66rem;
430
+ font-weight: 500;
431
+ line-height: 16px;
432
+ color: var(--md-sys-color-on-surface-variant);
433
+ background: var(--md-sys-color-surface-container-high);
434
+ }
435
+
436
+ /* Nothing yet: one quiet way in, instead of an empty form for a handler that does not exist. */
437
+ button.add {
438
+ display: inline-flex;
439
+ align-items: center;
440
+ gap: 4px;
441
+ height: 26px;
442
+ padding: 0 10px 0 6px;
443
+ border: 1px dashed var(--md-sys-color-outline-variant);
444
+ border-radius: 999px;
445
+ background: transparent;
446
+ color: var(--md-sys-color-on-surface-variant);
447
+ font: inherit;
448
+ font-size: 0.74rem;
449
+ cursor: pointer;
450
+ }
451
+
452
+ button.add md-icon {
453
+ --md-icon-size: 16px;
454
+ }
455
+
456
+ button.add:hover {
457
+ color: var(--md-sys-color-on-surface);
458
+ border-color: var(--md-sys-color-outline);
459
+ background: var(--md-sys-color-surface-container-high);
460
+ }
461
+
462
+ /* The "+" chip is an offer until it is pressed; pressed, it is the same chip as the numbered ones. */
463
+ ox-buttons-radio > div.add-tab:not([active]) {
464
+ line-height: 20px;
465
+ border: 1px dashed var(--md-sys-color-outline-variant);
466
+ background: transparent;
359
467
  }
360
468
 
361
469
  fieldset[collapsable][collapsed] > :not(legend) {
@@ -364,77 +472,74 @@ PropertyDataBinding.styles = [
364
472
 
365
473
  ox-buttons-radio {
366
474
  flex: 1;
367
- height: 25px;
368
- border: 1px solid rgba(0, 0, 0, 0.2);
369
- border-width: 1px 1px 0 1px;
370
- text-align: center;
371
-
372
475
  display: flex;
476
+ gap: 4px;
373
477
  padding: 0;
374
478
  box-sizing: border-box;
375
-
376
479
  width: 0; /* limit width */
377
480
  overflow-x: hidden;
378
481
  }
379
482
 
483
+ /* Tabs are quiet chips on the strip; the open one is lifted to the card's surface. */
380
484
  ox-buttons-radio > div {
381
- background-color: rgba(0, 0, 0, 0.2);
382
- border: 1px solid rgba(0, 0, 0, 0.07);
383
- border-width: 0 0 2px 0;
485
+ border: 0;
486
+ border-radius: 999px;
384
487
  padding: 0;
385
488
  margin: 0;
386
- color: #fff;
387
- font-size: 13px;
388
- max-width: 25px;
389
- min-width: 25px;
489
+ width: 24px;
490
+ height: 22px;
491
+ line-height: 22px;
492
+ text-align: center;
493
+ font-size: 0.72rem;
494
+ box-sizing: border-box;
495
+ color: var(--md-sys-color-on-surface-variant);
496
+ background-color: var(--md-sys-color-surface-container-high);
497
+ cursor: pointer;
390
498
  }
391
499
 
392
500
  ox-buttons-radio > div[disabled] {
393
- background-color: rgba(0, 0, 0, 0.1);
394
- }
395
-
396
- ox-buttons-radio > div[active] {
397
- border-color: rgb(242, 71, 28);
501
+ opacity: 0.4;
398
502
  }
399
503
 
504
+ ox-buttons-radio > div[active],
400
505
  ox-buttons-radio > div.iron-selected {
401
- background-color: var(--md-sys-color-surface);
402
- color: var(--md-sys-color-on-surface);
506
+ color: var(--md-sys-color-on-secondary-container);
507
+ background-color: var(--md-sys-color-secondary-container);
403
508
  }
404
509
 
405
510
  ox-input-data {
406
- height: 300px;
407
- border-radius: var(--spacing-small);
511
+ height: 220px;
408
512
  }
409
513
 
410
514
  div[binding] {
411
515
  display: flex;
412
516
  flex-direction: row-reverse;
413
- background-color: var(--md-sys-color-surface);
414
- color: var(--md-sys-color-on-surface);
415
- overflow: hidden;
416
- border-style: solid;
417
- border-color: rgba(0, 0, 0, 0.2);
418
- border-image: initial;
419
- border-width: 0px 1px;
420
- padding: 7px 5px 2px 5px;
517
+ gap: 2px;
518
+ margin-left: auto;
519
+ padding-left: 6px;
520
+ }
521
+
522
+ #tab-header > md-icon[disabled] {
523
+ display: none;
421
524
  }
422
525
 
526
+ /* Section actions are offers, not content: outline ink at half strength until hovered. */
423
527
  md-icon {
424
528
  margin-left: 5px;
425
- color: var(--md-sys-color-on-secondary-container);
426
- opacity: 0.8;
529
+ color: var(--md-sys-color-outline);
530
+ opacity: 0.6;
427
531
  cursor: pointer;
428
532
  --md-icon-size: 18px;
429
533
  }
430
534
 
431
535
  md-icon:hover {
432
- color: var(--md-sys-color-on-primary-container);
536
+ color: var(--md-sys-color-on-surface);
433
537
  opacity: 1;
434
538
  }
435
539
 
436
540
  md-icon[disabled] {
437
- color: rgba(0, 0, 0, 0.1);
541
+ color: var(--md-sys-color-outline-variant);
542
+ cursor: default;
438
543
  }
439
544
 
440
545
  data-binding-mapper {
@@ -445,7 +550,7 @@ PropertyDataBinding.styles = [
445
550
  -webkit-border-radius: 4px;
446
551
  -moz-border-radius: 4px;
447
552
  border-radius: 4px;
448
- border: 1px solid rgba(0, 0, 0, 0.15);
553
+ border: 1px solid var(--md-sys-color-outline-variant);
449
554
  font-size: 15px;
450
555
  font-weight: 300;
451
556
  -webkit-appearance: none;
@@ -462,12 +567,18 @@ __decorate([
462
567
  __decorate([
463
568
  state()
464
569
  ], PropertyDataBinding.prototype, "mappingIndex", void 0);
570
+ __decorate([
571
+ state()
572
+ ], PropertyDataBinding.prototype, "_drafts", void 0);
465
573
  __decorate([
466
574
  state()
467
575
  ], PropertyDataBinding.prototype, "_afterRender", void 0);
468
576
  __decorate([
469
577
  state()
470
578
  ], PropertyDataBinding.prototype, "_dataExpanded", void 0);
579
+ __decorate([
580
+ state()
581
+ ], PropertyDataBinding.prototype, "_composing", void 0);
471
582
  __decorate([
472
583
  query('#tabs')
473
584
  ], PropertyDataBinding.prototype, "tabs", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"data-binding.js","sourceRoot":"","sources":["../../../../src/property-panel/data-binding/data-binding.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/icon/icon.js'\nimport '@operato/help/ox-title-with-help.js'\nimport '@operato/input/ox-buttons-radio.js'\nimport '@operato/input/ox-input-data.js'\nimport '@operato/i18n/ox-i18n.js'\n\nimport { css, html, PropertyValues } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\n\nimport { Properties, Scene } from '@hatiolab/things-scene'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\nimport { openPopup } from '@operato/layout'\nimport { i18next } from '@operato/i18n'\n\nimport { AbstractProperty } from '../abstract-property.js'\nimport { DataBindingMapper } from './data-binding-mapper.js'\n\nvar clipboard = '{}'\n\n// `'tap'` / `'(action)'` 는 *Event Handlers panel* 로 이동 — legacy data-binding\n// 기반 핸들러 UI 는 제거. 데이터는 (`state.event`) 안전망으로 유지하되 편집 진입점\n// 은 새 panel 만.\nconst PROPS = [\n '',\n 'text',\n ['fillStyle', 'fill style'],\n ['strokeStyle', 'stroke style'],\n ['fontColor', 'font color'],\n 'value',\n 'data',\n 'source',\n 'hidden',\n 'started',\n 'play',\n ['ref', 'reference'],\n 'action',\n 'options',\n 'rotate',\n 'dimension',\n 'location',\n 'accessor',\n 'appendum',\n 'tag'\n].map(prop => {\n return typeof prop == 'string' ? { name: prop, label: prop } : { name: prop[0], label: prop[1] }\n})\n\nexport class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {\n static styles = [\n PropertyGridStyles,\n css`\n #tab-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n #tab-header > md-icon {\n padding: 0;\n margin: 0;\n width: 25px;\n height: 25px;\n font-size: x-large;\n border-bottom: 1px solid rgba(0, 0, 0, 0.2);\n }\n\n fieldset[collapsable][collapsed] > :not(legend) {\n display: none;\n }\n\n ox-buttons-radio {\n flex: 1;\n height: 25px;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-width: 1px 1px 0 1px;\n text-align: center;\n\n display: flex;\n padding: 0;\n box-sizing: border-box;\n\n width: 0; /* limit width */\n overflow-x: hidden;\n }\n\n ox-buttons-radio > div {\n background-color: rgba(0, 0, 0, 0.2);\n border: 1px solid rgba(0, 0, 0, 0.07);\n border-width: 0 0 2px 0;\n padding: 0;\n margin: 0;\n color: #fff;\n font-size: 13px;\n max-width: 25px;\n min-width: 25px;\n }\n\n ox-buttons-radio > div[disabled] {\n background-color: rgba(0, 0, 0, 0.1);\n }\n\n ox-buttons-radio > div[active] {\n border-color: rgb(242, 71, 28);\n }\n\n ox-buttons-radio > div.iron-selected {\n background-color: var(--md-sys-color-surface);\n color: var(--md-sys-color-on-surface);\n }\n\n ox-input-data {\n height: 300px;\n border-radius: var(--spacing-small);\n }\n\n div[binding] {\n display: flex;\n flex-direction: row-reverse;\n background-color: var(--md-sys-color-surface);\n color: var(--md-sys-color-on-surface);\n overflow: hidden;\n border-style: solid;\n border-color: rgba(0, 0, 0, 0.2);\n border-image: initial;\n border-width: 0px 1px;\n padding: 7px 5px 2px 5px;\n }\n\n md-icon {\n margin-left: 5px;\n color: var(--md-sys-color-on-secondary-container);\n opacity: 0.8;\n cursor: pointer;\n --md-icon-size: 18px;\n }\n\n md-icon:hover {\n color: var(--md-sys-color-on-primary-container);\n opacity: 1;\n }\n\n md-icon[disabled] {\n color: rgba(0, 0, 0, 0.1);\n }\n\n data-binding-mapper {\n --things-select: {\n min-width: 50%;\n margin-bottom: 10px;\n padding: 3px 20px 2px 5px;\n -webkit-border-radius: 4px;\n -moz-border-radius: 4px;\n border-radius: 4px;\n border: 1px solid rgba(0, 0, 0, 0.15);\n font-size: 15px;\n font-weight: 300;\n -webkit-appearance: none;\n };\n }\n `\n ]\n\n @property({ type: Object }) value?: Properties\n @property({ type: Object }) scene?: Scene\n\n @state() mappingIndex: number = 0\n @state() _afterRender?: Function | null\n @state() _dataExpanded: boolean = false\n\n @query('#tabs') tabs!: HTMLElement\n @query('#tab-nav-left-button') tabNavLeftButton!: HTMLElement\n @query('#tab-nav-right-button') tabNavRightButton!: HTMLElement\n\n private mapping: Properties = {}\n\n get mappings() {\n return this.value?.mappings || []\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', this.onValueChange.bind(this))\n\n this.tabContainer.addEventListener('scroll', () => {\n this._onTabScroll()\n })\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('value')) {\n this.onValueChanged()\n }\n }\n\n static get scopedElements() {\n return {\n 'data-binding-mapper': DataBindingMapper\n }\n }\n\n render() {\n const value = this.value || {\n mappings: []\n }\n\n return html`\n <fieldset>\n <legend>\n <ox-title-with-help topic=\"board-modeller/data-binding\" msgid=\"label.identifier\"\n >identifier</ox-title-with-help\n >\n </legend>\n <div class=\"property-grid\">\n <label> <ox-i18n msgid=\"label.id\">ID</ox-i18n> </label>\n <input value-key=\"id\" .value=${value.id || ''} />\n\n <label> <ox-i18n msgid=\"label.class\">Class</ox-i18n> </label>\n <input value-key=\"class\" .value=${value.class || ''} />\n\n <label> <ox-i18n msgid=\"label.tag\">Tag</ox-i18n> </label>\n <input value-key=\"tag\" .value=${value.tag || ''} />\n\n <label> <ox-i18n msgid=\"label.template-prefix\">Template Prefix</ox-i18n> </label>\n <input value-key=\"templatePrefix\" .value=${value.templatePrefix || ''} />\n\n <input id=\"checkbox-ndns\" type=\"checkbox\" value-key=\"ndns\" .checked=${value.ndns} />\n <label for=\"checkbox-ndns\"> <ox-i18n msgid=\"label.ndns\">No Data No Show</ox-i18n> </label>\n\n <input id=\"checkbox-sensitive\" type=\"checkbox\" value-key=\"sensitive\" .checked=${value.sensitive} />\n <label for=\"checkbox-sensitive\">\n <ox-i18n msgid=\"label.intent-sensitive\">Intent Sensitive</ox-i18n>\n </label>\n\n <input id=\"checkbox-persistent\" type=\"checkbox\" value-key=\"persistent\" .checked=${value.persistent} />\n <label for=\"checkbox-persistent\">\n <ox-i18n msgid=\"label.persistent-data\">Persistent Data</ox-i18n>\n </label>\n </div>\n </fieldset>\n\n <fieldset collapsable ?collapsed=${!this._dataExpanded}>\n <legend\n @click=${() => {\n this._dataExpanded = !this._dataExpanded\n }}\n >\n <ox-title-with-help topic=\"board-modeller/initial-data\" msgid=\"label.initial-data\"\n >initial value</ox-title-with-help\n >\n <md-icon>${this._dataExpanded ? 'expand_less' : 'expand_more'}</md-icon>\n </legend>\n <ox-input-data value-key=\"data\" .value=${value.data}> </ox-input-data>\n </fieldset>\n\n <fieldset>\n <legend style=\"box-sizing:border-box;width:100%\">\n <ox-title-with-help topic=\"board-modeller/data-spread\" msgid=\"label.data-spread\"\n >Data Spread</ox-title-with-help\n >\n <md-icon\n style=\"float:right;font-size:medium;margin:0;cursor:pointer\"\n @click=${() => this._openBindingPopup()}\n title=\"open in popup (D)\"\n >open_in_new</md-icon\n >\n </legend>\n\n <div id=\"tab-header\">\n <md-icon\n id=\"tab-nav-left-button\"\n @click=${() => {\n this._onTabScrollNavLeft()\n }}\n disabled\n >chevron_left</md-icon\n >\n\n <ox-buttons-radio\n id=\"tabs\"\n .value=${String(this.mappingIndex)}\n @change=${(e: Event) => {\n e.stopPropagation()\n this._setMappingIndex((e.target as any).value)\n }}\n >\n ${this.mappings.map((m: string, i: number) => html` <div data-value=${i} data-mapping>${i + 1}</div> `)}\n <div data-value=${this.mappings.length} data-mapping disabled>${this.mappings.length + 1}</div>\n </ox-buttons-radio>\n\n <md-icon\n id=\"tab-nav-right-button\"\n @click=${(e: Event) => {\n this._onTabScrollNavRight()\n }}\n disabled\n >chevron_right</md-icon\n >\n </div>\n\n <div binding>\n <md-icon style=\"font-size:19px\" @click=${() => this._clearDataBindingMapper()} title=\"delete current tab\"\n >delete_forever</md-icon\n >\n <md-icon @click=${() => this._pasteDataBindingMapper()} title=\"replace current tab\">content_paste</md-icon>\n <md-icon style=\"font-size:17px\" @click=${() => this._copyDataBindingMapper()} title=\"copy current tab\"\n >content_copy</md-icon\n >\n </div>\n\n <data-binding-mapper\n @value-change=${(e: CustomEvent) => this._onMappingChanged(e)}\n .scene=${this.scene}\n .mapping=${(value.mappings && value.mappings[this.mappingIndex]) || {}}\n .properties=${PROPS}\n >\n </data-binding-mapper>\n </fieldset>\n `\n }\n\n _setMappingIndex(idx: number) {\n this.mappingIndex = isNaN(Number(idx)) ? 0 : Number(idx)\n\n this._onTabScroll()\n }\n\n _openBindingPopup() {\n import('./data-binding-popup.js')\n\n const value = this.value || { mappings: [] }\n\n const template = html`\n <data-binding-popup\n .mappings=${[...(value.mappings || [])]}\n .properties=${PROPS}\n .scene=${this.scene}\n @mappings-change=${(e: CustomEvent) => {\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: { mappings: e.detail.mappings }\n })\n )\n }}\n ></data-binding-popup>\n `\n\n openPopup(template, {\n backdrop: true,\n size: 'large',\n title: i18next.t('label.data-spread')\n })\n }\n\n _clearDataBindingMapper() {\n var mappings = [...(this.value?.mappings || [])]\n mappings.splice(this.mappingIndex, 1)\n this.onAfterValueChange(\n 'mappings',\n mappings.filter(m => !!m)\n )\n }\n\n _copyDataBindingMapper() {\n clipboard = JSON.stringify(this.mappings[this.mappingIndex])\n }\n\n async _pasteDataBindingMapper() {\n var index = this.mappingIndex\n var mappings = [...(this.value?.mappings || [])]\n mappings[this.mappingIndex] = JSON.parse(clipboard)\n\n this.onAfterValueChange('mappings', mappings)\n\n setTimeout(() => {\n this._setMappingIndex(index)\n }, 100)\n }\n\n async onValueChanged() {\n await this.updateComplete\n\n if (this._afterRender) {\n this._afterRender()\n } else {\n this._setMappingIndex(0)\n }\n\n this._afterRender = null\n }\n\n onValueChange(e: Event) {\n var element = e.target as HTMLElement\n var key = element.getAttribute('value-key')\n\n var value = this.getValueFromEventTarget(element)\n\n if (!key) {\n return\n }\n\n this.value = {\n ...this.value,\n [key]: value\n }\n\n this.onAfterValueChange(key, value)\n }\n\n get tabContainer() {\n return this.tabs\n }\n\n async _onMappingChanged(e: CustomEvent) {\n var mapping = (e.target as any).mapping\n\n /* data spread target의 변경이 있는 경우, target 컴포넌트들의 태그를 블링크 시킨다 */\n if (mapping && mapping.target) {\n this.scene &&\n this.scene.findAll(mapping.target, this.scene.selected && this.scene.selected[0]).forEach((c: any, i: any) => {\n if (i == 0) c.trigger('decotagreset')\n c.trigger('decotag', {})\n })\n }\n\n /* mapping의 모든 속성이 편집되면, 모델에 반영한다. */\n var mappings = [...(this.value?.mappings || [])]\n\n if (mapping.property) {\n mappings[this.mappingIndex] = mapping\n\n var mappingIdx = this.mappingIndex\n this._afterRender = () => {\n this._setMappingIndex(mappingIdx)\n this.tabContainer.scrollLeft = this.tabContainer.scrollWidth\n }\n\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: {\n mappings: mappings.filter(m => !!m)\n }\n })\n )\n\n await this.requestUpdate()\n } else if (!mapping.target && !mapping.property) {\n const { accessor, source } = e.detail?.changed || {}\n\n // accessor나 source를 입력중인 경우 tabIndex Change 방지\n if (!accessor && !source) {\n mappings[this.mappingIndex] = null\n var nextMappingIdx = Math.max(this.mappingIndex - 1, 0)\n this._afterRender = () => {\n this._setMappingIndex(nextMappingIdx)\n }\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: {\n mappings: mappings.filter(m => !!m)\n }\n })\n )\n }\n }\n }\n\n _onTabScroll() {\n if (this.tabContainer.clientWidth == this.tabContainer.scrollWidth) {\n this.tabNavLeftButton.setAttribute('disabled', '')\n this.tabNavRightButton.setAttribute('disabled', '')\n }\n // left-end\n else if (this.tabContainer.scrollLeft == 0) {\n this.tabNavLeftButton.setAttribute('disabled', '')\n this.tabNavRightButton.removeAttribute('disabled')\n }\n // right-end\n else if (this.tabContainer.scrollLeft + this.tabContainer.clientWidth >= this.tabContainer.scrollWidth) {\n this.tabNavLeftButton.removeAttribute('disabled')\n this.tabNavRightButton.setAttribute('disabled', '')\n } else {\n this.tabNavLeftButton.removeAttribute('disabled')\n this.tabNavRightButton.removeAttribute('disabled')\n }\n }\n\n _onTabScrollNavLeft() {\n this.tabContainer.style.scrollBehavior = 'smooth'\n this.tabContainer.scrollLeft -= this.tabContainer.clientWidth\n this.tabContainer.style.scrollBehavior = 'auto'\n }\n\n _onTabScrollNavRight() {\n this.tabContainer.style.scrollBehavior = 'smooth'\n this.tabContainer.scrollLeft += this.tabContainer.clientWidth\n this.tabContainer.style.scrollBehavior = 'auto'\n }\n}\n"]}
1
+ {"version":3,"file":"data-binding.js","sourceRoot":"","sources":["../../../../src/property-panel/data-binding/data-binding.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/web/icon/icon.js'\nimport '@operato/help/ox-title-with-help.js'\nimport '@operato/input/ox-buttons-radio.js'\nimport '@operato/input/ox-input-data.js'\nimport '@operato/i18n/ox-i18n.js'\n\nimport { css, html, nothing, PropertyValues } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\n\nimport { Properties, Scene } from '@hatiolab/things-scene'\nimport { ScopedElementsMixin } from '@open-wc/scoped-elements'\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\nimport { openPopup } from '@operato/layout'\nimport { i18next } from '@operato/i18n'\n\nimport { AbstractProperty } from '../abstract-property.js'\nimport { DataBindingMapper } from './data-binding-mapper.js'\n\nvar clipboard = '{}'\n\n// `'tap'` / `'(action)'` 는 *Event Handlers panel* 로 이동 — legacy data-binding\n// 기반 핸들러 UI 는 제거. 데이터는 (`state.event`) 안전망으로 유지하되 편집 진입점\n// 은 새 panel 만.\nconst PROPS = [\n '',\n 'text',\n ['fillStyle', 'fill style'],\n ['strokeStyle', 'stroke style'],\n ['fontColor', 'font color'],\n 'value',\n 'data',\n 'source',\n 'hidden',\n 'started',\n 'play',\n ['ref', 'reference'],\n 'action',\n 'options',\n 'rotate',\n 'dimension',\n 'location',\n 'accessor',\n 'appendum',\n 'tag'\n].map(prop => {\n return typeof prop == 'string' ? { name: prop, label: prop } : { name: prop[0], label: prop[1] }\n})\n\nexport class PropertyDataBinding extends ScopedElementsMixin(AbstractProperty) {\n static styles = [\n PropertyGridStyles,\n css`\n /* The \"open in popup\" action is the last thing on the title line, at the far right. */\n legend > md-icon.open-popup {\n margin-left: auto;\n --md-icon-size: 16px;\n color: var(--md-sys-color-outline);\n opacity: 0.6;\n cursor: pointer;\n }\n\n legend > md-icon.open-popup:hover {\n color: var(--md-sys-color-on-surface);\n }\n\n #tab-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n #tab-header {\n display: flex;\n align-items: center;\n gap: 2px;\n margin-bottom: 6px;\n }\n\n #tab-header > md-icon {\n padding: 0;\n margin: 0;\n --md-icon-size: 18px;\n color: var(--md-sys-color-outline);\n }\n\n #tab-header > md-icon[disabled] {\n opacity: 0.3;\n }\n\n /* How many there are, as a small muted count next to the title. */\n legend > .count {\n margin-left: 6px;\n padding: 0 6px;\n border-radius: 999px;\n font-size: 0.66rem;\n font-weight: 500;\n line-height: 16px;\n color: var(--md-sys-color-on-surface-variant);\n background: var(--md-sys-color-surface-container-high);\n }\n\n /* Nothing yet: one quiet way in, instead of an empty form for a handler that does not exist. */\n button.add {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 26px;\n padding: 0 10px 0 6px;\n border: 1px dashed var(--md-sys-color-outline-variant);\n border-radius: 999px;\n background: transparent;\n color: var(--md-sys-color-on-surface-variant);\n font: inherit;\n font-size: 0.74rem;\n cursor: pointer;\n }\n\n button.add md-icon {\n --md-icon-size: 16px;\n }\n\n button.add:hover {\n color: var(--md-sys-color-on-surface);\n border-color: var(--md-sys-color-outline);\n background: var(--md-sys-color-surface-container-high);\n }\n\n /* The \"+\" chip is an offer until it is pressed; pressed, it is the same chip as the numbered ones. */\n ox-buttons-radio > div.add-tab:not([active]) {\n line-height: 20px;\n border: 1px dashed var(--md-sys-color-outline-variant);\n background: transparent;\n }\n\n fieldset[collapsable][collapsed] > :not(legend) {\n display: none;\n }\n\n ox-buttons-radio {\n flex: 1;\n display: flex;\n gap: 4px;\n padding: 0;\n box-sizing: border-box;\n width: 0; /* limit width */\n overflow-x: hidden;\n }\n\n /* Tabs are quiet chips on the strip; the open one is lifted to the card's surface. */\n ox-buttons-radio > div {\n border: 0;\n border-radius: 999px;\n padding: 0;\n margin: 0;\n width: 24px;\n height: 22px;\n line-height: 22px;\n text-align: center;\n font-size: 0.72rem;\n box-sizing: border-box;\n color: var(--md-sys-color-on-surface-variant);\n background-color: var(--md-sys-color-surface-container-high);\n cursor: pointer;\n }\n\n ox-buttons-radio > div[disabled] {\n opacity: 0.4;\n }\n\n ox-buttons-radio > div[active],\n ox-buttons-radio > div.iron-selected {\n color: var(--md-sys-color-on-secondary-container);\n background-color: var(--md-sys-color-secondary-container);\n }\n\n ox-input-data {\n height: 220px;\n }\n\n div[binding] {\n display: flex;\n flex-direction: row-reverse;\n gap: 2px;\n margin-left: auto;\n padding-left: 6px;\n }\n\n #tab-header > md-icon[disabled] {\n display: none;\n }\n\n /* Section actions are offers, not content: outline ink at half strength until hovered. */\n md-icon {\n margin-left: 5px;\n color: var(--md-sys-color-outline);\n opacity: 0.6;\n cursor: pointer;\n --md-icon-size: 18px;\n }\n\n md-icon:hover {\n color: var(--md-sys-color-on-surface);\n opacity: 1;\n }\n\n md-icon[disabled] {\n color: var(--md-sys-color-outline-variant);\n cursor: default;\n }\n\n data-binding-mapper {\n --things-select: {\n min-width: 50%;\n margin-bottom: 10px;\n padding: 3px 20px 2px 5px;\n -webkit-border-radius: 4px;\n -moz-border-radius: 4px;\n border-radius: 4px;\n border: 1px solid var(--md-sys-color-outline-variant);\n font-size: 15px;\n font-weight: 300;\n -webkit-appearance: none;\n };\n }\n `\n ]\n\n @property({ type: Object }) value?: Properties\n @property({ type: Object }) scene?: Scene\n\n @state() mappingIndex: number = 0\n /*\n * A mapping is written to the model only once it names a property. Until then the mapper's\n * edits (rule, source, target...) live here, per tab, so the choice does not snap back to the\n * empty mapping on the next render. Cleared when another shape is selected.\n */\n @state() private _drafts: Record<number, any> = {}\n private _draftsFor?: unknown\n @state() _afterRender?: Function | null\n @state() _dataExpanded: boolean = false\n /* True while a new mapping is being composed and is not yet in the model (no property chosen). */\n @state() private _composing: boolean = false\n\n @query('#tabs') tabs!: HTMLElement\n @query('#tab-nav-left-button') tabNavLeftButton!: HTMLElement\n @query('#tab-nav-right-button') tabNavRightButton!: HTMLElement\n\n private mapping: Properties = {}\n\n get mappings() {\n return this.value?.mappings || []\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', this.onValueChange.bind(this))\n\n /* The tab strip only exists once there is a mapping, so listen from the root (scroll does not\n * bubble; capture catches it) instead of on an element that may not be there yet. */\n this.renderRoot.addEventListener('scroll', e => (e.target as Element).id === 'tabs' && this._onTabScroll(), true)\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('value')) {\n this.onValueChanged()\n\n const selected = this.scene?.selected?.[0]\n if (selected !== this._draftsFor) {\n this._draftsFor = selected\n this._drafts = {}\n this._composing = false\n }\n }\n }\n\n static get scopedElements() {\n return {\n 'data-binding-mapper': DataBindingMapper\n }\n }\n\n render() {\n const value = this.value || {\n mappings: []\n }\n\n return html`\n <fieldset>\n <legend>\n <ox-title-with-help topic=\"board-modeller/data-binding\" msgid=\"label.identifier\"\n >identifier</ox-title-with-help\n >\n </legend>\n <div class=\"property-grid\">\n <label> <ox-i18n msgid=\"label.id\">ID</ox-i18n> </label>\n <input value-key=\"id\" .value=${value.id || ''} />\n\n <label> <ox-i18n msgid=\"label.class\">Class</ox-i18n> </label>\n <input value-key=\"class\" .value=${value.class || ''} />\n\n <label> <ox-i18n msgid=\"label.tag\">Tag</ox-i18n> </label>\n <input value-key=\"tag\" .value=${value.tag || ''} />\n\n <label> <ox-i18n msgid=\"label.template-prefix\">Template Prefix</ox-i18n> </label>\n <input value-key=\"templatePrefix\" .value=${value.templatePrefix || ''} />\n\n <input id=\"checkbox-ndns\" type=\"checkbox\" value-key=\"ndns\" .checked=${value.ndns} />\n <label for=\"checkbox-ndns\"> <ox-i18n msgid=\"label.ndns\">No Data No Show</ox-i18n> </label>\n\n <input id=\"checkbox-sensitive\" type=\"checkbox\" value-key=\"sensitive\" .checked=${value.sensitive} />\n <label for=\"checkbox-sensitive\">\n <ox-i18n msgid=\"label.intent-sensitive\">Intent Sensitive</ox-i18n>\n </label>\n\n <input id=\"checkbox-persistent\" type=\"checkbox\" value-key=\"persistent\" .checked=${value.persistent} />\n <label for=\"checkbox-persistent\">\n <ox-i18n msgid=\"label.persistent-data\">Persistent Data</ox-i18n>\n </label>\n </div>\n </fieldset>\n\n <fieldset collapsable ?collapsed=${!this._dataExpanded}>\n <legend\n @click=${() => {\n this._dataExpanded = !this._dataExpanded\n }}\n >\n <ox-title-with-help topic=\"board-modeller/initial-data\" msgid=\"label.initial-data\"\n >initial value</ox-title-with-help\n >\n <md-icon>${this._dataExpanded ? 'expand_less' : 'expand_more'}</md-icon>\n </legend>\n <ox-input-data value-key=\"data\" .value=${value.data}> </ox-input-data>\n </fieldset>\n\n <fieldset>\n <legend style=\"box-sizing:border-box;width:100%\">\n <ox-title-with-help topic=\"board-modeller/data-spread\" msgid=\"label.data-spread\"\n >Data Spread</ox-title-with-help\n >\n ${this.mappings.length ? html`<span class=\"count\">${this.mappings.length}</span>` : nothing}\n <md-icon\n class=\"open-popup\"\n @click=${() => this._openBindingPopup()}\n title=\"open in popup (D)\"\n >open_in_new</md-icon\n >\n </legend>\n\n ${this.mappings.length || this._composing\n ? html`\n <div id=\"tab-header\">\n <md-icon\n id=\"tab-nav-left-button\"\n @click=${() => {\n this._onTabScrollNavLeft()\n }}\n disabled\n >chevron_left</md-icon\n >\n\n <ox-buttons-radio\n id=\"tabs\"\n .value=${String(this.mappingIndex)}\n @change=${(e: Event) => {\n e.stopPropagation()\n this._setMappingIndex((e.target as any).value)\n }}\n >\n ${this.mappings.map((m: string, i: number) => html` <div data-value=${i} data-mapping>${i + 1}</div> `)}\n <div data-value=${this.mappings.length} class=\"add-tab\" title=\"add\" @click=${() => (this._composing = true)}>\n +\n </div>\n </ox-buttons-radio>\n\n <md-icon\n id=\"tab-nav-right-button\"\n @click=${(e: Event) => {\n this._onTabScrollNavRight()\n }}\n disabled\n >chevron_right</md-icon\n >\n\n <div binding>\n <md-icon style=\"font-size:19px\" @click=${() => this._clearDataBindingMapper()} title=\"delete current tab\"\n >delete_forever</md-icon\n >\n <md-icon @click=${() => this._pasteDataBindingMapper()} title=\"replace current tab\">content_paste</md-icon>\n <md-icon style=\"font-size:17px\" @click=${() => this._copyDataBindingMapper()} title=\"copy current tab\"\n >content_copy</md-icon\n >\n </div>\n </div>\n\n\n <data-binding-mapper\n @value-change=${(e: CustomEvent) => this._onMappingChanged(e)}\n .scene=${this.scene}\n .mapping=${(value.mappings && value.mappings[this.mappingIndex]) || this._drafts[this.mappingIndex] || {}}\n .properties=${PROPS}\n >\n </data-binding-mapper>\n `\n : html`\n <button class=\"add\" @click=${() => this._startMapping()}>\n <md-icon>add</md-icon>${i18next.t('button.add-mapping', { defaultValue: 'Add a mapping' })}\n </button>\n `}\n </fieldset>\n `\n }\n\n private _startMapping() {\n this._composing = true\n this.mappingIndex = this.mappings.length\n }\n\n _setMappingIndex(idx: number) {\n this.mappingIndex = isNaN(Number(idx)) ? 0 : Number(idx)\n\n this._onTabScroll()\n }\n\n _openBindingPopup() {\n import('./data-binding-popup.js')\n\n const value = this.value || { mappings: [] }\n\n const template = html`\n <data-binding-popup\n .mappings=${[...(value.mappings || [])]}\n .properties=${PROPS}\n .scene=${this.scene}\n @mappings-change=${(e: CustomEvent) => {\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: { mappings: e.detail.mappings }\n })\n )\n }}\n ></data-binding-popup>\n `\n\n openPopup(template, {\n backdrop: true,\n size: 'large',\n title: i18next.t('label.data-spread')\n })\n }\n\n _clearDataBindingMapper() {\n var mappings = [...(this.value?.mappings || [])]\n mappings.splice(this.mappingIndex, 1)\n this.onAfterValueChange(\n 'mappings',\n mappings.filter(m => !!m)\n )\n }\n\n _copyDataBindingMapper() {\n clipboard = JSON.stringify(this.mappings[this.mappingIndex])\n }\n\n async _pasteDataBindingMapper() {\n var index = this.mappingIndex\n var mappings = [...(this.value?.mappings || [])]\n mappings[this.mappingIndex] = JSON.parse(clipboard)\n\n this.onAfterValueChange('mappings', mappings)\n\n setTimeout(() => {\n this._setMappingIndex(index)\n }, 100)\n }\n\n async onValueChanged() {\n await this.updateComplete\n\n if (this._afterRender) {\n this._afterRender()\n } else {\n this._setMappingIndex(0)\n }\n\n this._afterRender = null\n }\n\n onValueChange(e: Event) {\n var element = e.target as HTMLElement\n var key = element.getAttribute('value-key')\n\n var value = this.getValueFromEventTarget(element)\n\n if (!key) {\n return\n }\n\n this.value = {\n ...this.value,\n [key]: value\n }\n\n this.onAfterValueChange(key, value)\n }\n\n get tabContainer() {\n return this.tabs\n }\n\n async _onMappingChanged(e: CustomEvent) {\n var mapping = (e.target as any).mapping\n\n /* data spread target의 변경이 있는 경우, target 컴포넌트들의 태그를 블링크 시킨다 */\n if (mapping && mapping.target) {\n this.scene &&\n this.scene.findAll(mapping.target, this.scene.selected && this.scene.selected[0]).forEach((c: any, i: any) => {\n if (i == 0) c.trigger('decotagreset')\n c.trigger('decotag', {})\n })\n }\n\n /* mapping의 모든 속성이 편집되면, 모델에 반영한다. */\n var mappings = [...(this.value?.mappings || [])]\n\n if (mapping.property) {\n const drafts = { ...this._drafts }\n delete drafts[this.mappingIndex]\n this._drafts = drafts\n\n mappings[this.mappingIndex] = mapping\n\n var mappingIdx = this.mappingIndex\n this._afterRender = () => {\n this._setMappingIndex(mappingIdx)\n this.tabContainer.scrollLeft = this.tabContainer.scrollWidth\n }\n\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: {\n mappings: mappings.filter(m => !!m)\n }\n })\n )\n\n await this.requestUpdate()\n } else {\n /* Not complete yet: keep what has been chosen so far for this tab. */\n this._drafts = { ...this._drafts, [this.mappingIndex]: mapping }\n }\n\n /* Only a mapping the model already holds can be \"cleared\"; an unfinished draft is just unfinished. */\n if (!mapping.property && !mapping.target && mappings[this.mappingIndex]) {\n const { accessor, source } = e.detail?.changed || {}\n\n // accessor나 source를 입력중인 경우 tabIndex Change 방지\n if (!accessor && !source) {\n mappings[this.mappingIndex] = null\n var nextMappingIdx = Math.max(this.mappingIndex - 1, 0)\n this._afterRender = () => {\n this._setMappingIndex(nextMappingIdx)\n }\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: {\n mappings: mappings.filter(m => !!m)\n }\n })\n )\n }\n }\n }\n\n _onTabScroll() {\n if (!this.tabContainer || !this.tabNavLeftButton) return\n if (this.tabContainer.clientWidth == this.tabContainer.scrollWidth) {\n this.tabNavLeftButton.setAttribute('disabled', '')\n this.tabNavRightButton.setAttribute('disabled', '')\n }\n // left-end\n else if (this.tabContainer.scrollLeft == 0) {\n this.tabNavLeftButton.setAttribute('disabled', '')\n this.tabNavRightButton.removeAttribute('disabled')\n }\n // right-end\n else if (this.tabContainer.scrollLeft + this.tabContainer.clientWidth >= this.tabContainer.scrollWidth) {\n this.tabNavLeftButton.removeAttribute('disabled')\n this.tabNavRightButton.setAttribute('disabled', '')\n } else {\n this.tabNavLeftButton.removeAttribute('disabled')\n this.tabNavRightButton.removeAttribute('disabled')\n }\n }\n\n _onTabScrollNavLeft() {\n this.tabContainer.style.scrollBehavior = 'smooth'\n this.tabContainer.scrollLeft -= this.tabContainer.clientWidth\n this.tabContainer.style.scrollBehavior = 'auto'\n }\n\n _onTabScrollNavRight() {\n this.tabContainer.style.scrollBehavior = 'smooth'\n this.tabContainer.scrollLeft += this.tabContainer.clientWidth\n this.tabContainer.style.scrollBehavior = 'auto'\n }\n}\n"]}
@@ -137,14 +137,14 @@ EventHandlersMapper.styles = [
137
137
  display: flex;
138
138
  flex-direction: column;
139
139
  gap: 6px;
140
- padding: 10px 10px 10px 10px;
140
+ padding: 0;
141
141
  /* 카드 외곽 — tabs (위) + toolbar (중간) + mapper (아래) 가 하나의 카드.
142
142
  * 위쪽 1px 는 toolbar 와의 internal divider. radius 6px 으로 통일. */
143
- border: 1px solid rgba(0, 0, 0, 0.18);
144
- border-radius: 0 0 6px 6px;
145
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
146
- line-height: 2;
147
- background: var(--md-sys-color-surface, #fff);
143
+ border: 0;
144
+ border-radius: 0;
145
+ box-shadow: none;
146
+ line-height: normal;
147
+ background: transparent;
148
148
  min-width: 0;
149
149
  width: 100%;
150
150
  box-sizing: border-box;
@@ -162,7 +162,7 @@ EventHandlersMapper.styles = [
162
162
  padding-top: 10px;
163
163
  /* trigger/action/target/value 입력 묶음과 code editor 사이의 구분선.
164
164
  * dashed 대신 solid + 옅은 opacity 로 modern. */
165
- border-top: 1px solid rgba(0, 0, 0, 0.08);
165
+ border-top: 1px solid var(--md-sys-color-outline-variant);
166
166
  }
167
167
 
168
168
  [script-field] > .script-header {
@@ -185,27 +185,48 @@ EventHandlersMapper.styles = [
185
185
  font-size: 10.5px;
186
186
  }
187
187
 
188
+ /* The same label/editor split as the panel grid (9 of 24 columns for the label). */
188
189
  .row {
189
190
  display: grid;
190
- grid-template-columns: 80px 1fr;
191
- gap: 6px;
191
+ grid-template-columns: 9fr 15fr;
192
+ gap: 6px 10px;
192
193
  align-items: center;
193
194
  min-width: 0;
194
195
  }
195
196
 
197
+ .row > label {
198
+ justify-self: end;
199
+ text-align: right;
200
+ font-size: 0.74rem;
201
+ color: var(--md-sys-color-on-surface-variant);
202
+ text-transform: capitalize;
203
+ }
204
+
196
205
  .row > select,
197
206
  .row > input[type='text'] {
198
207
  width: 100%;
199
208
  min-width: 0;
200
209
  box-sizing: border-box;
201
- padding: 3px 6px;
202
- font-size: 13px;
203
- border-radius: 4px;
210
+ min-height: 24px;
211
+ padding: 2px 8px;
212
+ font-size: 0.76rem;
213
+ border-radius: 6px;
204
214
  /* #fff 와 rgba(0,0,0,.15) 는 다크에서 흰 칸 + 안 보이는 테두리가 된다.
205
215
  프레임워크의 --input-field-* 가족을 쓰고, 없을 때도 자립하도록 md 토큰을 기본값으로 둔다. */
206
- border: var(--input-field-border, 1px solid var(--md-sys-color-outline));
207
- background: var(--input-field-background, var(--md-sys-color-surface-container-highest));
208
- color: var(--input-field-color, var(--md-sys-color-on-surface));
216
+ border: 1px solid transparent;
217
+ background: var(--property-input-background, var(--md-sys-color-surface-container-high));
218
+ color: var(--md-sys-color-on-surface);
219
+ outline: none;
220
+ }
221
+
222
+ .row > select:hover,
223
+ .row > input[type='text']:hover {
224
+ border-color: var(--md-sys-color-outline-variant);
225
+ }
226
+
227
+ .row > select:focus,
228
+ .row > input[type='text']:focus {
229
+ border-color: var(--md-sys-color-primary);
209
230
  }
210
231
 
211
232
  ox-input-code {
@@ -218,7 +239,7 @@ EventHandlersMapper.styles = [
218
239
  box-sizing: border-box;
219
240
  overflow: hidden;
220
241
  min-height: 180px;
221
- border: 1px solid rgba(0, 0, 0, 0.15);
242
+ border: 1px solid var(--md-sys-color-outline-variant);
222
243
  border-radius: 4px;
223
244
  /* popup 모드에서 script-field 의 남은 세로 공간을 모두 차지 — 아래 빈공간 X.
224
245
  * inline 모드에서는 script-field 가 grow 하지 않으므로 min-height 180px 만 사용. */