@things-factory/figure-library 10.1.222 → 10.1.224

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 (35) hide show
  1. package/dist-client/bootstrap.d.ts +8 -5
  2. package/dist-client/bootstrap.js +12 -6
  3. package/dist-client/bootstrap.js.map +1 -1
  4. package/dist-client/editors/ox-property-editor-figure-legends.d.ts +34 -0
  5. package/dist-client/editors/ox-property-editor-figure-legends.js +236 -0
  6. package/dist-client/editors/ox-property-editor-figure-legends.js.map +1 -0
  7. package/dist-client/figure-data-report.d.ts +10 -5
  8. package/dist-client/figure-data-report.js +15 -5
  9. package/dist-client/figure-data-report.js.map +1 -1
  10. package/dist-client/legend-looks/legend-looks-editor.d.ts +42 -0
  11. package/dist-client/legend-looks/legend-looks-editor.js +145 -0
  12. package/dist-client/legend-looks/legend-looks-editor.js.map +1 -0
  13. package/dist-client/legend-looks/legend-looks.d.ts +55 -0
  14. package/dist-client/legend-looks/legend-looks.js +110 -0
  15. package/dist-client/legend-looks/legend-looks.js.map +1 -0
  16. package/dist-client/legend-looks/ox-legend-looks.d.ts +57 -0
  17. package/dist-client/{status-looks/ox-figure-status-looks.js → legend-looks/ox-legend-looks.js} +128 -109
  18. package/dist-client/legend-looks/ox-legend-looks.js.map +1 -0
  19. package/dist-client/tsconfig.tsbuildinfo +1 -1
  20. package/dist-server/tsconfig.tsbuildinfo +1 -1
  21. package/package.json +9 -9
  22. package/translations/en.json +43 -43
  23. package/translations/es.json +43 -43
  24. package/translations/ja.json +43 -43
  25. package/translations/ko.json +43 -43
  26. package/translations/ms.json +43 -43
  27. package/translations/zh.json +43 -43
  28. package/dist-client/editors/ox-property-editor-figure-status.d.ts +0 -41
  29. package/dist-client/editors/ox-property-editor-figure-status.js +0 -290
  30. package/dist-client/editors/ox-property-editor-figure-status.js.map +0 -1
  31. package/dist-client/status-looks/ox-figure-status-looks.d.ts +0 -58
  32. package/dist-client/status-looks/ox-figure-status-looks.js.map +0 -1
  33. package/dist-client/status-looks/status-looks.d.ts +0 -99
  34. package/dist-client/status-looks/status-looks.js +0 -134
  35. package/dist-client/status-looks/status-looks.js.map +0 -1
@@ -2,45 +2,44 @@ import { __decorate, __metadata } from "tslib";
2
2
  import { css, html, LitElement, nothing } from 'lit';
3
3
  import { customElement, property, state } from 'lit/decorators.js';
4
4
  import { i18next } from '@operato/i18n';
5
- import { inputsGivenIn, withCode, withLook, withLookValue, withoutCode } from './status-looks.js';
5
+ import { inputsGivenIn, withCode, withLook, withLookValue, withoutCode } from './legend-looks.js';
6
6
  const DEFAULT = 'default';
7
7
  /**
8
- * A status template's looks, one card per code (ADR-0051 2.3): its colour, its effect, a value for each state input a
9
- * figure's port offers -- with the input's name, unit and range -- and the clip of the port's motion group. The code the
10
- * data gives now is marked; a part the figure did not take is said under the card, by the field that gave it. Every
11
- * change sends `looks-change` with the whole looks; the host writes them where the template lives.
8
+ * A legend's looks, one card per code (ADR-0166 7, 11): its colour, its effect, a value for each state input the
9
+ * figures' tables of its role set -- with the input's name, unit and range -- and a clip, speed and pause for a motion
10
+ * group. Every change sends `looks-change` with the whole looks; the host writes them where the legend lives.
12
11
  *
13
- * A value outside its input's range is not taken from the field (as the property panel's number maps); a value written
14
- * elsewhere that the figure refused shows with the reason, to be fixed here. Values for inputs not shown -- another
15
- * figure's, in a table shared by many -- are kept as they are.
12
+ * A value outside its input's range is not taken from the field (as the property panel's number maps). Values for
13
+ * inputs not shown -- another figure's, in a legend shared by many -- are kept as they are, and so is whatever else an
14
+ * entry holds (fmsim's 2D animation).
16
15
  *
17
- * Shared by the board's 「상태 표현」 section and fmsim's legend editor, which shows colour and values only.
16
+ * The one legend editor: the board's legend themes (「테마」) and fmsim's legend editor both write looks through it.
18
17
  */
19
- let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
18
+ let OxLegendLooks = class OxLegendLooks extends LitElement {
20
19
  constructor() {
21
20
  super(...arguments);
22
21
  this.looks = {};
23
- /** The state inputs shown, one field each: the figure's offered inputs, or those a legend gives values to. */
22
+ /** The state inputs shown, one field each. */
24
23
  this.inputs = [];
25
- /** Inputs that can be added as a field (a legend's editor: the inputs the carrier figures offer). */
24
+ /** Inputs that can be added as a field: those the figures' tables of the legend's role set. */
26
25
  this.addable = [];
27
- /**
28
- * Whether every input a look gives a value to has a field, offered or not: a legend, which no one figure reads. A
29
- * figure's own section leaves the values of inputs it does not offer to the figures that do.
30
- */
26
+ /** Whether every input a look gives a value to has a field, offered or not: a legend, which no one figure reads. */
31
27
  this.showGiven = false;
28
+ /** Whether an input can be added by its name typed, when no figure says which there are. */
29
+ this.nameInputs = false;
32
30
  /** The clips a look may choose; none, no clip field. */
33
31
  this.clips = [];
34
32
  this.effects = false;
35
- /** Whether a look may give no colour (a board's template); a legend's entry always has one. */
33
+ /** Whether a look may give a motion group's speed and pause. */
34
+ this.motion = false;
35
+ /** Whether a look may give no colour; a colour map's entry has one. */
36
36
  this.colorOptional = false;
37
- /** The rows the data gives now, with the ports that read them. */
38
- this.now = {};
39
- /** What the figure did not take, by row. */
40
- this.issues = new Map();
37
+ /** Whether looks give values at all: a legend whose consumer takes colour and effect only (fmsim's carrier legends) gives none. */
38
+ this.noValues = false;
41
39
  this.disabled = false;
42
40
  this.added = [];
43
41
  this.newCode = '';
42
+ this.newInput = '';
44
43
  }
45
44
  static { this.styles = css `
46
45
  :host {
@@ -52,7 +51,7 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
52
51
 
53
52
  [cards] {
54
53
  display: grid;
55
- grid-template-columns: repeat(auto-fill, minmax(var(--status-looks-card-min, 220px), 1fr));
54
+ grid-template-columns: repeat(auto-fill, minmax(var(--legend-looks-card-min, 220px), 1fr));
56
55
  gap: 6px;
57
56
  }
58
57
 
@@ -64,14 +63,6 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
64
63
  border-radius: 6px;
65
64
  }
66
65
 
67
- section[now] {
68
- border-color: var(--md-sys-color-primary);
69
- }
70
-
71
- section[refused] {
72
- border-color: var(--md-sys-color-error);
73
- }
74
-
75
66
  header {
76
67
  display: flex;
77
68
  align-items: center;
@@ -86,15 +77,6 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
86
77
  white-space: nowrap;
87
78
  }
88
79
 
89
- [now-tag] {
90
- padding: 0 4px;
91
- border-radius: 4px;
92
- background: var(--md-sys-color-primary-container);
93
- color: var(--md-sys-color-on-primary-container);
94
- font-size: 0.68rem;
95
- white-space: nowrap;
96
- }
97
-
98
80
  header [end] {
99
81
  margin-left: auto;
100
82
  display: flex;
@@ -193,12 +175,6 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
193
175
  grid-column: 2 / -1;
194
176
  }
195
177
 
196
- [issue] {
197
- margin: 0;
198
- color: var(--md-sys-color-error);
199
- font-size: 0.7rem;
200
- }
201
-
202
178
  button {
203
179
  height: 24px;
204
180
  padding: 0 8px;
@@ -246,25 +222,25 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
246
222
  render() {
247
223
  const codes = Object.keys(this.looks).sort((a, b) => Number(a === DEFAULT) - Number(b === DEFAULT));
248
224
  const shown = this.shownInputs();
249
- const addable = this.addable.filter(a => !shown.some(s => s.input === a.input));
225
+ const addable = this.noValues ? [] : this.addable.filter(a => !shown.some(s => s.input === a.input));
250
226
  return html `
251
227
  ${codes.length
252
228
  ? html `<div cards>${codes.map(code => this.renderCard(code, shown))}</div>`
253
- : html `<p empty>${i18next.t('figure.text.status-looks-empty')}</p>`}
229
+ : html `<p empty>${i18next.t('figure.text.legend-looks-empty')}</p>`}
254
230
  <footer>
255
231
  <input
256
- aria-label=${i18next.t('figure.label.status-code')}
257
- placeholder=${i18next.t('figure.label.status-code')}
232
+ aria-label=${i18next.t('figure.label.legend-code')}
233
+ placeholder=${i18next.t('figure.label.legend-code')}
258
234
  .value=${this.newCode}
259
235
  ?disabled=${this.disabled}
260
236
  @input=${(e) => (this.newCode = e.target.value)}
261
237
  @keydown=${(e) => e.key === 'Enter' && this.addCode(this.newCode)}
262
238
  />
263
- <button ?disabled=${this.disabled || !this.newCode.trim()} @click=${() => this.addCode(this.newCode)}>${i18next.t('figure.button.status-add-code')}</button>
264
- ${DEFAULT in this.looks ? nothing : html `<button ?disabled=${this.disabled} @click=${() => this.addCode(DEFAULT)}>${i18next.t('figure.button.status-add-default')}</button>`}
239
+ <button ?disabled=${this.disabled || !this.newCode.trim()} @click=${() => this.addCode(this.newCode)}>${i18next.t('figure.button.legend-add-code')}</button>
240
+ ${DEFAULT in this.looks ? nothing : html `<button ?disabled=${this.disabled} @click=${() => this.addCode(DEFAULT)}>${i18next.t('figure.button.legend-add-default')}</button>`}
265
241
  ${addable.length
266
242
  ? html `<select
267
- aria-label=${i18next.t('figure.button.status-add-value')}
243
+ aria-label=${i18next.t('figure.button.legend-add-value')}
268
244
  ?disabled=${this.disabled}
269
245
  @change=${(e) => {
270
246
  const select = e.target;
@@ -274,15 +250,27 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
274
250
  select.value = '';
275
251
  }}
276
252
  >
277
- <option value="">${i18next.t('figure.button.status-add-value')}</option>
253
+ <option value="">${i18next.t('figure.button.legend-add-value')}</option>
278
254
  ${addable.map(a => html `<option value=${a.input}>${describeInput(a)}</option>`)}
279
255
  </select>`
280
256
  : nothing}
257
+ ${this.nameInputs && !this.noValues
258
+ ? html `<input
259
+ aria-label=${i18next.t('figure.label.legend-input-name')}
260
+ placeholder=${i18next.t('figure.label.legend-input-name')}
261
+ .value=${this.newInput}
262
+ ?disabled=${this.disabled}
263
+ @input=${(e) => (this.newInput = e.target.value)}
264
+ />
265
+ <button ?disabled=${this.disabled || !this.newInput.trim()} @click=${() => this.addInput(this.newInput)}>${i18next.t('figure.button.legend-add-value')}</button>`
266
+ : nothing}
281
267
  </footer>
282
268
  `;
283
269
  }
284
270
  /** The inputs shown: those given, those added here, and, with `showGiven`, any a look gives a value to. */
285
271
  shownInputs() {
272
+ if (this.noValues)
273
+ return [];
286
274
  const shown = [...this.inputs];
287
275
  for (const one of this.added)
288
276
  if (!shown.some(s => s.input === one.input))
@@ -295,52 +283,46 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
295
283
  }
296
284
  renderCard(code, inputs) {
297
285
  const look = this.looks[code] ?? {};
298
- const issues = this.issues.get(code) ?? [];
299
- const said = (target, id) => issues.filter(i => i.target === target && (id === undefined || i.id === id));
300
- const ports = this.now[code];
301
286
  const values = look.values && typeof look.values === 'object' ? look.values : {};
302
287
  const effect = look.effect && typeof look.effect === 'object' ? look.effect : undefined;
303
- return html `<section ?now=${!!ports} ?refused=${issues.length > 0} data-code=${code}>
288
+ return html `<section data-code=${code}>
304
289
  <header>
305
290
  <input
306
291
  type="color"
307
- aria-label=${i18next.t('figure.label.status-color')}
308
- title=${look.color === undefined ? i18next.t('figure.label.status-color-none') : String(look.color)}
292
+ aria-label=${i18next.t('figure.label.legend-color')}
293
+ title=${look.color === undefined ? i18next.t('figure.label.legend-color-none') : String(look.color)}
309
294
  ?unset=${look.color === undefined}
310
- aria-invalid=${said('color').length ? 'true' : 'false'}
311
295
  .value=${typeof look.color === 'string' ? look.color : '#000000'}
312
296
  ?disabled=${this.disabled}
313
297
  @change=${(e) => this.change(withLook(this.looks, code, { color: e.target.value.toUpperCase() }))}
314
298
  />
315
- <b title=${code}>${code === DEFAULT ? i18next.t('figure.label.status-default-code') : code}</b>
316
- ${ports ? html `<span now-tag title=${ports.join(', ')}>${i18next.t('figure.label.status-now')}</span>` : nothing}
299
+ <b title=${code}>${code === DEFAULT ? i18next.t('figure.label.legend-default-code') : code}</b>
317
300
  <span end>
318
301
  ${this.colorOptional && look.color !== undefined
319
- ? html `<button icon title=${i18next.t('figure.button.status-clear-color')} ?disabled=${this.disabled} @click=${() => this.change(withLook(this.looks, code, { color: undefined }))}>⌀</button>`
302
+ ? html `<button icon title=${i18next.t('figure.button.legend-clear-color')} ?disabled=${this.disabled} @click=${() => this.change(withLook(this.looks, code, { color: undefined }))}>⌀</button>`
320
303
  : nothing}
321
- <button icon title=${i18next.t('figure.button.status-remove-code')} ?disabled=${this.disabled} @click=${() => this.change(withoutCode(this.looks, code))}>×</button>
304
+ <button icon title=${i18next.t('figure.button.legend-remove-code')} ?disabled=${this.disabled} @click=${() => this.change(withoutCode(this.looks, code))}>×</button>
322
305
  </span>
323
306
  </header>
324
307
  <div fields>
325
308
  ${this.effects
326
- ? html `<span name>${i18next.t('figure.label.status-effect')}</span>
309
+ ? html `<span name>${i18next.t('figure.label.legend-effect')}</span>
327
310
  <select
328
311
  ?wide=${effect?.kind !== 'blink'}
329
- aria-label=${i18next.t('figure.label.status-effect')}
330
- aria-invalid=${said('effect').length ? 'true' : 'false'}
312
+ aria-label=${i18next.t('figure.label.legend-effect')}
331
313
  ?disabled=${this.disabled}
332
314
  @change=${(e) => {
333
315
  const kind = e.target.value;
334
316
  this.change(withLook(this.looks, code, { effect: kind === 'blink' ? { kind, hz: effect?.hz ?? 1 } : kind === 'glow' ? { kind } : undefined }));
335
317
  }}
336
318
  >
337
- ${['', 'blink', 'glow'].map(k => html `<option value=${k} ?selected=${(effect?.kind ?? '') === k}>${i18next.t('figure.label.status-effect-' + (k || 'none'))}</option>`)}
319
+ ${['', 'blink', 'glow'].map(k => html `<option value=${k} ?selected=${(effect?.kind ?? '') === k}>${i18next.t('figure.label.legend-effect-' + (k || 'none'))}</option>`)}
338
320
  </select>
339
321
  ${effect?.kind === 'blink'
340
322
  ? html `<input
341
323
  type="number"
342
324
  step="any"
343
- aria-label=${i18next.t('figure.label.status-effect-hz')}
325
+ aria-label=${i18next.t('figure.label.legend-effect-hz')}
344
326
  .value=${String(effect.hz ?? 1)}
345
327
  ?disabled=${this.disabled}
346
328
  @change=${(e) => {
@@ -354,14 +336,12 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
354
336
  : nothing}
355
337
  ${inputs.map(input => {
356
338
  const held = values[input.input];
357
- const refused = said('state', input.input);
358
339
  return html `<span name title=${describeInput(input)}>${input.label}</span>
359
340
  <input
360
341
  type="number"
361
342
  step="any"
362
343
  data-input=${input.input}
363
344
  aria-label=${input.label}
364
- aria-invalid=${refused.length ? 'true' : 'false'}
365
345
  placeholder=${rangeOf(input) ?? ''}
366
346
  .value=${held === undefined ? '' : String(held)}
367
347
  ?disabled=${this.disabled}
@@ -370,20 +350,52 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
370
350
  <span unit>${[input.unit, rangeOf(input)].filter(Boolean).join(' ')}</span>`;
371
351
  })}
372
352
  ${this.clips.length
373
- ? html `<span name>${i18next.t('figure.label.status-clip')}</span>
353
+ ? html `<span name>${i18next.t('figure.label.legend-clip')}</span>
374
354
  <select
375
355
  wide
376
- aria-label=${i18next.t('figure.label.status-clip')}
377
- aria-invalid=${said('motion-clip').length ? 'true' : 'false'}
356
+ aria-label=${i18next.t('figure.label.legend-clip')}
378
357
  ?disabled=${this.disabled}
379
358
  @change=${(e) => this.change(withLook(this.looks, code, { clip: e.target.value || undefined }))}
380
359
  >
381
- <option value="" ?selected=${look.clip === undefined}>${i18next.t('figure.label.status-clip-none')}</option>
360
+ <option value="" ?selected=${look.clip === undefined}>${i18next.t('figure.label.legend-clip-none')}</option>
382
361
  ${[...new Set([...this.clips, ...(look.clip !== undefined && !this.clips.includes(look.clip) ? [look.clip] : [])])].map(clip => html `<option value=${clip} ?selected=${look.clip === clip}>${clip}</option>`)}
383
362
  </select>`
384
363
  : nothing}
364
+ ${this.motion
365
+ ? html `<span name>${i18next.t('figure.label.legend-speed')}</span>
366
+ <input
367
+ type="number"
368
+ step="any"
369
+ min="0"
370
+ max="3"
371
+ aria-label=${i18next.t('figure.label.legend-speed')}
372
+ .value=${typeof look.speed === 'number' ? String(look.speed) : ''}
373
+ ?disabled=${this.disabled}
374
+ @change=${(e) => {
375
+ const field = e.target;
376
+ const speed = field.valueAsNumber;
377
+ if (field.value.trim() === '')
378
+ return this.change(withLook(this.looks, code, { speed: undefined }));
379
+ if (!(speed >= 0 && speed <= 3))
380
+ return this.requestUpdate();
381
+ this.change(withLook(this.looks, code, { speed }));
382
+ }}
383
+ />
384
+ <span unit>0~3</span>
385
+ <span name>${i18next.t('figure.label.legend-paused')}</span>
386
+ <select
387
+ wide
388
+ aria-label=${i18next.t('figure.label.legend-paused')}
389
+ ?disabled=${this.disabled}
390
+ @change=${(e) => {
391
+ const v = e.target.value;
392
+ this.change(withLook(this.looks, code, { paused: v === '' ? undefined : v === 'true' }));
393
+ }}
394
+ >
395
+ ${['', 'false', 'true'].map(v => html `<option value=${v} ?selected=${String(look.paused ?? '') === v}>${i18next.t('figure.label.legend-paused-' + (v || 'none'))}</option>`)}
396
+ </select>`
397
+ : nothing}
385
398
  </div>
386
- ${issues.map(issue => html `<p issue>${issueSentence(issue, inputs)}</p>`)}
387
399
  </section>`;
388
400
  }
389
401
  addCode(code) {
@@ -408,6 +420,14 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
408
420
  }
409
421
  this.change(withLookValue(this.looks, code, input.input, value));
410
422
  }
423
+ /** An input named by hand: a field for it on every card, its values the looks' own. */
424
+ addInput(name) {
425
+ const input = name.trim();
426
+ this.newInput = '';
427
+ if (!input || this.added.some(a => a.input === input) || this.inputs.some(a => a.input === input))
428
+ return;
429
+ this.added = [...this.added, { input, label: input }];
430
+ }
411
431
  change(looks) {
412
432
  this.looks = looks;
413
433
  this.dispatchEvent(new CustomEvent('looks-change', { bubbles: true, composed: true, detail: { looks } }));
@@ -416,74 +436,73 @@ let OxFigureStatusLooks = class OxFigureStatusLooks extends LitElement {
416
436
  __decorate([
417
437
  property({ type: Object }),
418
438
  __metadata("design:type", Object)
419
- ], OxFigureStatusLooks.prototype, "looks", void 0);
439
+ ], OxLegendLooks.prototype, "looks", void 0);
420
440
  __decorate([
421
441
  property({ type: Array }),
422
442
  __metadata("design:type", Array)
423
- ], OxFigureStatusLooks.prototype, "inputs", void 0);
443
+ ], OxLegendLooks.prototype, "inputs", void 0);
424
444
  __decorate([
425
445
  property({ type: Array }),
426
446
  __metadata("design:type", Array)
427
- ], OxFigureStatusLooks.prototype, "addable", void 0);
447
+ ], OxLegendLooks.prototype, "addable", void 0);
428
448
  __decorate([
429
449
  property({ type: Boolean, attribute: 'show-given' }),
430
450
  __metadata("design:type", Object)
431
- ], OxFigureStatusLooks.prototype, "showGiven", void 0);
451
+ ], OxLegendLooks.prototype, "showGiven", void 0);
452
+ __decorate([
453
+ property({ type: Boolean, attribute: 'name-inputs' }),
454
+ __metadata("design:type", Object)
455
+ ], OxLegendLooks.prototype, "nameInputs", void 0);
432
456
  __decorate([
433
457
  property({ type: Array }),
434
458
  __metadata("design:type", Array)
435
- ], OxFigureStatusLooks.prototype, "clips", void 0);
459
+ ], OxLegendLooks.prototype, "clips", void 0);
436
460
  __decorate([
437
461
  property({ type: Boolean }),
438
462
  __metadata("design:type", Object)
439
- ], OxFigureStatusLooks.prototype, "effects", void 0);
463
+ ], OxLegendLooks.prototype, "effects", void 0);
464
+ __decorate([
465
+ property({ type: Boolean }),
466
+ __metadata("design:type", Object)
467
+ ], OxLegendLooks.prototype, "motion", void 0);
440
468
  __decorate([
441
469
  property({ type: Boolean, attribute: 'color-optional' }),
442
470
  __metadata("design:type", Object)
443
- ], OxFigureStatusLooks.prototype, "colorOptional", void 0);
471
+ ], OxLegendLooks.prototype, "colorOptional", void 0);
444
472
  __decorate([
445
473
  property({ type: String, attribute: 'default-color' }),
446
474
  __metadata("design:type", String)
447
- ], OxFigureStatusLooks.prototype, "defaultColor", void 0);
475
+ ], OxLegendLooks.prototype, "defaultColor", void 0);
448
476
  __decorate([
449
- property({ type: Object }),
477
+ property({ type: Boolean, attribute: 'no-values' }),
450
478
  __metadata("design:type", Object)
451
- ], OxFigureStatusLooks.prototype, "now", void 0);
452
- __decorate([
453
- property({ type: Object }),
454
- __metadata("design:type", Map)
455
- ], OxFigureStatusLooks.prototype, "issues", void 0);
479
+ ], OxLegendLooks.prototype, "noValues", void 0);
456
480
  __decorate([
457
481
  property({ type: Boolean }),
458
482
  __metadata("design:type", Object)
459
- ], OxFigureStatusLooks.prototype, "disabled", void 0);
483
+ ], OxLegendLooks.prototype, "disabled", void 0);
460
484
  __decorate([
461
485
  state(),
462
486
  __metadata("design:type", Array)
463
- ], OxFigureStatusLooks.prototype, "added", void 0);
487
+ ], OxLegendLooks.prototype, "added", void 0);
464
488
  __decorate([
465
489
  state(),
466
490
  __metadata("design:type", Object)
467
- ], OxFigureStatusLooks.prototype, "newCode", void 0);
468
- OxFigureStatusLooks = __decorate([
469
- customElement('ox-figure-status-looks')
470
- ], OxFigureStatusLooks);
471
- export { OxFigureStatusLooks };
472
- /** An input as the choice and the tooltip say it: its name, unit and range, and the port that offers it. */
491
+ ], OxLegendLooks.prototype, "newCode", void 0);
492
+ __decorate([
493
+ state(),
494
+ __metadata("design:type", Object)
495
+ ], OxLegendLooks.prototype, "newInput", void 0);
496
+ OxLegendLooks = __decorate([
497
+ customElement('ox-legend-looks')
498
+ ], OxLegendLooks);
499
+ export { OxLegendLooks };
500
+ /** An input as the choice and the tooltip say it: its name, unit and range, and the tables that set it. */
473
501
  export function describeInput(input) {
474
502
  const tail = [input.unit, rangeOf(input)].filter(Boolean).join(' ');
475
- return `${input.label}${tail ? ` (${tail})` : ''}${input.portLabel ? ` · ${input.portLabel}` : ''}`;
503
+ return `${input.label}${tail ? ` (${tail})` : ''}${input.givenBy ? ` · ${input.givenBy}` : ''}`;
476
504
  }
477
505
  function rangeOf(input) {
478
506
  return input.min !== undefined || input.max !== undefined ? `${input.min ?? ''}~${input.max ?? ''}` : undefined;
479
507
  }
480
- /** Why a part was not taken, in the person's words, with the value refused. */
481
- export function issueSentence(issue, inputs = []) {
482
- const input = issue.id !== undefined ? inputs.find(i => i.input === issue.id) : undefined;
483
- return i18next.t('figure.text.status-issue-' + issue.reason, {
484
- name: input?.label ?? issue.id ?? '',
485
- value: typeof issue.value === 'string' ? issue.value : JSON.stringify(issue.value),
486
- range: input ? (rangeOf(input) ?? '') : ''
487
- });
488
- }
489
- //# sourceMappingURL=ox-figure-status-looks.js.map
508
+ //# sourceMappingURL=ox-legend-looks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ox-legend-looks.js","sourceRoot":"","sources":["../../client/legend-looks/ox-legend-looks.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\n\nimport { inputsGivenIn, withCode, withLook, withLookValue, withoutCode, type LegendLooks, type LookInput } from './legend-looks.js'\n\nconst DEFAULT = 'default'\n\n/**\n * A legend's looks, one card per code (ADR-0166 7, 11): its colour, its effect, a value for each state input the\n * figures' tables of its role set -- with the input's name, unit and range -- and a clip, speed and pause for a motion\n * group. Every change sends `looks-change` with the whole looks; the host writes them where the legend lives.\n *\n * A value outside its input's range is not taken from the field (as the property panel's number maps). Values for\n * inputs not shown -- another figure's, in a legend shared by many -- are kept as they are, and so is whatever else an\n * entry holds (fmsim's 2D animation).\n *\n * The one legend editor: the board's legend themes (「테마」) and fmsim's legend editor both write looks through it.\n */\n@customElement('ox-legend-looks')\nexport class OxLegendLooks extends LitElement {\n static styles = css`\n :host {\n display: grid;\n gap: 6px;\n font: var(--property-editor-field-font, 0.76rem var(--theme-font, Roboto, sans-serif));\n color: var(--md-sys-color-on-surface);\n }\n\n [cards] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(var(--legend-looks-card-min, 220px), 1fr));\n gap: 6px;\n }\n\n section {\n display: grid;\n gap: 3px;\n padding: 4px 6px 6px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n\n header {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 24px;\n }\n\n header b {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n header [end] {\n margin-left: auto;\n display: flex;\n gap: 2px;\n }\n\n input[type='color'] {\n flex: none;\n width: 22px;\n height: 18px;\n padding: 0;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 4px;\n background: none;\n cursor: pointer;\n }\n\n input[type='color']::-webkit-color-swatch-wrapper {\n padding: 1px;\n }\n\n input[type='color']::-webkit-color-swatch {\n border: none;\n border-radius: 3px;\n }\n\n /*\n * No colour given: the swatch is an empty dashed box until one is picked. A colour the field cannot show, it shows\n * black, as the browser does; the figure's refusal says why.\n */\n input[type='color'][unset] {\n border-style: dashed;\n opacity: 0.6;\n }\n\n input[type='color'][unset]::-webkit-color-swatch {\n background: transparent !important;\n }\n\n [fields] {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(56px, 72px) minmax(0, auto);\n gap: 3px 6px;\n align-items: center;\n }\n\n [fields] > [name] {\n color: var(--md-sys-color-on-surface-variant);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n [fields] > [unit] {\n color: var(--md-sys-color-outline);\n font-size: 0.68rem;\n white-space: nowrap;\n }\n\n input:not([type='color']),\n select {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: var(--property-editor-field-height, 24px);\n padding: 0 4px;\n font: inherit;\n color: inherit;\n border: var(--property-editor-border, 1px solid var(--md-sys-color-outline-variant));\n border-radius: var(--property-editor-border-radius, 6px);\n background: var(--property-editor-background, var(--md-sys-color-surface-container-high));\n }\n\n input[type='number'] {\n text-align: right;\n font-variant-numeric: tabular-nums;\n }\n\n input:hover,\n select:hover {\n border-color: var(--property-editor-border-color-hover, var(--md-sys-color-outline-variant));\n }\n\n input:focus,\n select:focus {\n outline: none;\n border-color: var(--property-editor-border-color-focus, var(--md-sys-color-primary));\n }\n\n [aria-invalid='true'] {\n border-color: var(--md-sys-color-error) !important;\n }\n\n /* The effect's choice takes the field and the unit columns; a blink's rate takes the field after it. */\n [fields] > select[wide] {\n grid-column: 2 / -1;\n }\n\n button {\n height: 24px;\n padding: 0 8px;\n font: inherit;\n color: var(--md-sys-color-primary);\n border: none;\n border-radius: 6px;\n background: transparent;\n cursor: pointer;\n white-space: nowrap;\n }\n\n button:hover {\n background: var(--md-sys-color-surface-container-high);\n }\n\n button[icon] {\n width: 22px;\n padding: 0;\n color: var(--md-sys-color-on-surface-variant);\n }\n\n footer {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n align-items: center;\n }\n\n footer input {\n flex: 1 1 80px;\n width: auto;\n }\n\n footer select {\n flex: 1 1 120px;\n width: auto;\n }\n\n [empty] {\n margin: 0;\n color: var(--md-sys-color-on-surface-variant);\n }\n `\n\n @property({ type: Object }) looks: LegendLooks = {}\n /** The state inputs shown, one field each. */\n @property({ type: Array }) inputs: LookInput[] = []\n /** Inputs that can be added as a field: those the figures' tables of the legend's role set. */\n @property({ type: Array }) addable: LookInput[] = []\n /** Whether every input a look gives a value to has a field, offered or not: a legend, which no one figure reads. */\n @property({ type: Boolean, attribute: 'show-given' }) showGiven = false\n /** Whether an input can be added by its name typed, when no figure says which there are. */\n @property({ type: Boolean, attribute: 'name-inputs' }) nameInputs = false\n /** The clips a look may choose; none, no clip field. */\n @property({ type: Array }) clips: string[] = []\n @property({ type: Boolean }) effects = false\n /** Whether a look may give a motion group's speed and pause. */\n @property({ type: Boolean }) motion = false\n /** Whether a look may give no colour; a colour map's entry has one. */\n @property({ type: Boolean, attribute: 'color-optional' }) colorOptional = false\n /** The colour a new code starts with. */\n @property({ type: String, attribute: 'default-color' }) defaultColor?: string\n /** Whether looks give values at all: a legend whose consumer takes colour and effect only (fmsim's carrier legends) gives none. */\n @property({ type: Boolean, attribute: 'no-values' }) noValues = false\n @property({ type: Boolean }) disabled = false\n\n @state() private added: LookInput[] = []\n @state() private newCode = ''\n @state() private newInput = ''\n\n render() {\n const codes = Object.keys(this.looks).sort((a, b) => Number(a === DEFAULT) - Number(b === DEFAULT))\n const shown = this.shownInputs()\n const addable = this.noValues ? [] : this.addable.filter(a => !shown.some(s => s.input === a.input))\n return html`\n ${codes.length\n ? html`<div cards>${codes.map(code => this.renderCard(code, shown))}</div>`\n : html`<p empty>${i18next.t('figure.text.legend-looks-empty')}</p>`}\n <footer>\n <input\n aria-label=${i18next.t('figure.label.legend-code')}\n placeholder=${i18next.t('figure.label.legend-code')}\n .value=${this.newCode}\n ?disabled=${this.disabled}\n @input=${(e: Event) => (this.newCode = (e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => e.key === 'Enter' && this.addCode(this.newCode)}\n />\n <button ?disabled=${this.disabled || !this.newCode.trim()} @click=${() => this.addCode(this.newCode)}>${i18next.t('figure.button.legend-add-code')}</button>\n ${DEFAULT in this.looks ? nothing : html`<button ?disabled=${this.disabled} @click=${() => this.addCode(DEFAULT)}>${i18next.t('figure.button.legend-add-default')}</button>`}\n ${addable.length\n ? html`<select\n aria-label=${i18next.t('figure.button.legend-add-value')}\n ?disabled=${this.disabled}\n @change=${(e: Event) => {\n const select = e.target as HTMLSelectElement\n const picked = addable.find(a => a.input === select.value)\n if (picked) this.added = [...this.added, picked]\n select.value = ''\n }}\n >\n <option value=\"\">${i18next.t('figure.button.legend-add-value')}</option>\n ${addable.map(a => html`<option value=${a.input}>${describeInput(a)}</option>`)}\n </select>`\n : nothing}\n ${this.nameInputs && !this.noValues\n ? html`<input\n aria-label=${i18next.t('figure.label.legend-input-name')}\n placeholder=${i18next.t('figure.label.legend-input-name')}\n .value=${this.newInput}\n ?disabled=${this.disabled}\n @input=${(e: Event) => (this.newInput = (e.target as HTMLInputElement).value)}\n />\n <button ?disabled=${this.disabled || !this.newInput.trim()} @click=${() => this.addInput(this.newInput)}>${i18next.t('figure.button.legend-add-value')}</button>`\n : nothing}\n </footer>\n `\n }\n\n /** The inputs shown: those given, those added here, and, with `showGiven`, any a look gives a value to. */\n private shownInputs(): LookInput[] {\n if (this.noValues) return []\n const shown = [...this.inputs]\n for (const one of this.added) if (!shown.some(s => s.input === one.input)) shown.push(one)\n if (this.showGiven)\n for (const input of inputsGivenIn(this.looks))\n if (!shown.some(s => s.input === input)) shown.push(this.addable.find(a => a.input === input) ?? { input, label: input })\n return shown\n }\n\n private renderCard(code: string, inputs: LookInput[]) {\n const look = this.looks[code] ?? {}\n const values = look.values && typeof look.values === 'object' ? (look.values as Record<string, unknown>) : {}\n const effect = look.effect && typeof look.effect === 'object' ? look.effect : undefined\n return html`<section data-code=${code}>\n <header>\n <input\n type=\"color\"\n aria-label=${i18next.t('figure.label.legend-color')}\n title=${look.color === undefined ? i18next.t('figure.label.legend-color-none') : String(look.color)}\n ?unset=${look.color === undefined}\n .value=${typeof look.color === 'string' ? look.color : '#000000'}\n ?disabled=${this.disabled}\n @change=${(e: Event) => this.change(withLook(this.looks, code, { color: (e.target as HTMLInputElement).value.toUpperCase() }))}\n />\n <b title=${code}>${code === DEFAULT ? i18next.t('figure.label.legend-default-code') : code}</b>\n <span end>\n ${this.colorOptional && look.color !== undefined\n ? html`<button icon title=${i18next.t('figure.button.legend-clear-color')} ?disabled=${this.disabled} @click=${() => this.change(withLook(this.looks, code, { color: undefined }))}>⌀</button>`\n : nothing}\n <button icon title=${i18next.t('figure.button.legend-remove-code')} ?disabled=${this.disabled} @click=${() => this.change(withoutCode(this.looks, code))}>×</button>\n </span>\n </header>\n <div fields>\n ${this.effects\n ? html`<span name>${i18next.t('figure.label.legend-effect')}</span>\n <select\n ?wide=${effect?.kind !== 'blink'}\n aria-label=${i18next.t('figure.label.legend-effect')}\n ?disabled=${this.disabled}\n @change=${(e: Event) => {\n const kind = (e.target as HTMLSelectElement).value\n this.change(withLook(this.looks, code, { effect: kind === 'blink' ? { kind, hz: effect?.hz ?? 1 } : kind === 'glow' ? { kind } : undefined }))\n }}\n >\n ${['', 'blink', 'glow'].map(k => html`<option value=${k} ?selected=${(effect?.kind ?? '') === k}>${i18next.t('figure.label.legend-effect-' + (k || 'none'))}</option>`)}\n </select>\n ${effect?.kind === 'blink'\n ? html`<input\n type=\"number\"\n step=\"any\"\n aria-label=${i18next.t('figure.label.legend-effect-hz')}\n .value=${String(effect.hz ?? 1)}\n ?disabled=${this.disabled}\n @change=${(e: Event) => {\n const hz = (e.target as HTMLInputElement).valueAsNumber\n if (!(Number.isFinite(hz) && hz > 0)) return this.requestUpdate()\n this.change(withLook(this.looks, code, { effect: { kind: 'blink', hz } }))\n }}\n />`\n : nothing}`\n : nothing}\n ${inputs.map(input => {\n const held = values[input.input]\n return html`<span name title=${describeInput(input)}>${input.label}</span>\n <input\n type=\"number\"\n step=\"any\"\n data-input=${input.input}\n aria-label=${input.label}\n placeholder=${rangeOf(input) ?? ''}\n .value=${held === undefined ? '' : String(held)}\n ?disabled=${this.disabled}\n @change=${(e: Event) => this.changeValue(code, input, e.target as HTMLInputElement)}\n />\n <span unit>${[input.unit, rangeOf(input)].filter(Boolean).join(' ')}</span>`\n })}\n ${this.clips.length\n ? html`<span name>${i18next.t('figure.label.legend-clip')}</span>\n <select\n wide\n aria-label=${i18next.t('figure.label.legend-clip')}\n ?disabled=${this.disabled}\n @change=${(e: Event) => this.change(withLook(this.looks, code, { clip: (e.target as HTMLSelectElement).value || undefined }))}\n >\n <option value=\"\" ?selected=${look.clip === undefined}>${i18next.t('figure.label.legend-clip-none')}</option>\n ${[...new Set([...this.clips, ...(look.clip !== undefined && !this.clips.includes(look.clip) ? [look.clip] : [])])].map(\n clip => html`<option value=${clip} ?selected=${look.clip === clip}>${clip}</option>`\n )}\n </select>`\n : nothing}\n ${this.motion\n ? html`<span name>${i18next.t('figure.label.legend-speed')}</span>\n <input\n type=\"number\"\n step=\"any\"\n min=\"0\"\n max=\"3\"\n aria-label=${i18next.t('figure.label.legend-speed')}\n .value=${typeof look.speed === 'number' ? String(look.speed) : ''}\n ?disabled=${this.disabled}\n @change=${(e: Event) => {\n const field = e.target as HTMLInputElement\n const speed = field.valueAsNumber\n if (field.value.trim() === '') return this.change(withLook(this.looks, code, { speed: undefined }))\n if (!(speed >= 0 && speed <= 3)) return this.requestUpdate()\n this.change(withLook(this.looks, code, { speed }))\n }}\n />\n <span unit>0~3</span>\n <span name>${i18next.t('figure.label.legend-paused')}</span>\n <select\n wide\n aria-label=${i18next.t('figure.label.legend-paused')}\n ?disabled=${this.disabled}\n @change=${(e: Event) => {\n const v = (e.target as HTMLSelectElement).value\n this.change(withLook(this.looks, code, { paused: v === '' ? undefined : v === 'true' }))\n }}\n >\n ${['', 'false', 'true'].map(v => html`<option value=${v} ?selected=${String(look.paused ?? '') === v}>${i18next.t('figure.label.legend-paused-' + (v || 'none'))}</option>`)}\n </select>`\n : nothing}\n </div>\n </section>`\n }\n\n private addCode(code: string) {\n const trimmed = code.trim()\n if (!trimmed) return\n this.newCode = ''\n if (trimmed in this.looks) return\n this.change(this.defaultColor ? withLook(this.looks, trimmed, { color: this.defaultColor }) : withCode(this.looks, trimmed))\n }\n\n /** A number in range is taken; an empty field takes the value away (the next source gives it); anything else is not taken. */\n private changeValue(code: string, input: LookInput, field: HTMLInputElement) {\n if (field.value.trim() === '') return this.change(withLookValue(this.looks, code, input.input, undefined))\n const value = field.valueAsNumber\n const outside = !Number.isFinite(value) || (input.min !== undefined && value < input.min) || (input.max !== undefined && value > input.max)\n if (outside) {\n const held = this.looks[code]?.values?.[input.input]\n field.value = held === undefined ? '' : String(held)\n return\n }\n this.change(withLookValue(this.looks, code, input.input, value))\n }\n\n /** An input named by hand: a field for it on every card, its values the looks' own. */\n private addInput(name: string) {\n const input = name.trim()\n this.newInput = ''\n if (!input || this.added.some(a => a.input === input) || this.inputs.some(a => a.input === input)) return\n this.added = [...this.added, { input, label: input }]\n }\n\n private change(looks: LegendLooks) {\n this.looks = looks\n this.dispatchEvent(new CustomEvent('looks-change', { bubbles: true, composed: true, detail: { looks } }))\n }\n}\n\n/** An input as the choice and the tooltip say it: its name, unit and range, and the tables that set it. */\nexport function describeInput(input: LookInput): string {\n const tail = [input.unit, rangeOf(input)].filter(Boolean).join(' ')\n return `${input.label}${tail ? ` (${tail})` : ''}${input.givenBy ? ` · ${input.givenBy}` : ''}`\n}\n\nfunction rangeOf(input: LookInput): string | undefined {\n return input.min !== undefined || input.max !== undefined ? `${input.min ?? ''}~${input.max ?? ''}` : undefined\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ox-legend-looks': OxLegendLooks\n }\n}\n"]}