@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
@@ -104,7 +104,6 @@
104
104
  "figure.label.board-data-behavior-motion-clip": "{name} 片段",
105
105
  "figure.label.board-data-behavior-motion-speed": "{name} 倍速",
106
106
  "figure.label.board-data-behavior-motion-paused": "{name} 暂停",
107
- "figure.label.board-data-behavior-status": "状态显示 {name}",
108
107
  "figure.label.board-data-behavior-pose": "位置 {name}",
109
108
  "figure.label.board-data-behavior-items": "物品 {name}",
110
109
  "figure.text.board-data-held": "看板的状态值正在设定 {controls},因此此数据不会驱动它。",
@@ -142,46 +141,47 @@
142
141
  "figure-library.item-types.issue.code": "代码为空、前后有空格或超过 64 个字符",
143
142
  "figure-library.item-types.issue.figure": "Figure 应为完整名称",
144
143
  "figure-library.item-types.issue.duplicate": "第 {rows} 行有相同代码",
145
- "label.figure-status": "状态表现",
146
- "figure.text.status-select-one": "选择一个图形时显示。",
147
- "figure.text.status-checked-in-3d": "未接受的部分在 3D 绘制时检查并显示在此。",
148
- "figure.label.status-template": "状态模板",
149
- "figure.label.status-template-board": "看板默认",
150
- "figure.label.status-template-none": "无",
151
- "figure.label.status-template-own": "此放置的模板",
152
- "figure.label.status-template-name": "新模板名称",
153
- "figure.button.status-template-new": "新模板",
154
- "figure.button.status-template-create": "创建",
155
- "figure.button.status-template-cancel": "取消",
156
- "figure.text.status-no-code": "未收到状态",
157
- "figure.label.status-source-resolver": "应用图例",
158
- "figure.label.status-source-placement": "放置模板",
159
- "figure.label.status-source-board": "看板模板",
160
- "figure.label.status-source-none": "不显示",
161
- "figure.text.status-resolver-note": "此端口的外观由应用图例决定,请在图例主题中修改。",
162
- "figure.text.status-looks-empty": "模板中没有代码。",
163
- "figure.label.status-code": "状态代码",
164
- "figure.button.status-add-code": "添加代码",
165
- "figure.button.status-add-default": "添加其他代码",
166
- "figure.button.status-add-value": "添加状态值",
167
- "figure.label.status-color": "颜色",
168
- "figure.label.status-color-none": "无颜色",
169
- "figure.label.status-default-code": "其他代码",
170
- "figure.label.status-now": "当前",
171
- "figure.button.status-clear-color": "清除颜色",
172
- "figure.button.status-remove-code": "删除代码",
173
- "figure.label.status-effect": "效果",
174
- "figure.label.status-effect-none": "无",
175
- "figure.label.status-effect-blink": "闪烁",
176
- "figure.label.status-effect-glow": "发光",
177
- "figure.label.status-effect-hz": "闪烁频率(Hz)",
178
- "figure.label.status-clip": "剪辑",
179
- "figure.label.status-clip-none": "看板设置",
180
- "figure.text.status-issue-not-a-number": "{name}: 不是数字,未接受 ({value})。",
181
- "figure.text.status-issue-out-of-range": "{name}: 超出范围 {range},未接受 ({value})。",
182
- "figure.text.status-issue-not-a-clip": "{name}: 不是该组的剪辑,未接受 ({value})。",
183
- "figure.text.status-issue-not-a-color": "颜色不是 #RRGGBB,未接受 ({value})。",
184
- "figure.text.status-issue-not-an-effect": "效果不是闪烁或发光,或频率不是大于 0 的数,未接受 ({value})。",
185
- "figure.text.status-issue-not-a-record": "状态值(values)不是对象,未接受 ({value})。",
186
- "figure.text.status-issue-failed": "应用图例查询失败,由模板代为回答 ({value})。"
144
+ "label.figure-legends": "图例",
145
+ "figure.button.legend-add-code": "添加代码",
146
+ "figure.button.legend-add-default": "添加其他代码",
147
+ "figure.button.legend-add-value": "添加值",
148
+ "figure.button.legend-board-default": "设为看板默认",
149
+ "figure.button.legend-clear-color": "清除颜色",
150
+ "figure.button.legend-remove-code": "删除代码",
151
+ "figure.label.legend-absent": "场景中没有",
152
+ "figure.label.legend-board": "看板默认",
153
+ "figure.label.legend-clip": "片段",
154
+ "figure.label.legend-clip-none": "看板设置",
155
+ "figure.label.legend-code": "代码",
156
+ "figure.label.legend-color": "颜色",
157
+ "figure.label.legend-color-none": "无颜色",
158
+ "figure.label.legend-count": "{count} 个代码",
159
+ "figure.label.legend-default-code": "其他代码",
160
+ "figure.label.legend-domain": "同名图例",
161
+ "figure.label.legend-edit": "图例",
162
+ "figure.label.legend-effect": "效果",
163
+ "figure.label.legend-effect-none": "无",
164
+ "figure.label.legend-effect-blink": "闪烁",
165
+ "figure.label.legend-effect-glow": "发光",
166
+ "figure.label.legend-effect-hz": "闪烁频率(Hz)",
167
+ "figure.label.legend-figure-table": "人偶自身的表",
168
+ "figure.label.legend-input-name": "值名称",
169
+ "figure.label.legend-paused": "暂停",
170
+ "figure.label.legend-paused-none": "看板设置",
171
+ "figure.label.legend-paused-false": "播放",
172
+ "figure.label.legend-paused-true": "暂停",
173
+ "figure.label.legend-row-none": "无对应行",
174
+ "figure.label.legend-speed": "倍速",
175
+ "figure.text.legend-looks-empty": "图例中没有代码。",
176
+ "figure.text.legend-make-board-default": "将此放置的选择设为看板此角色的默认值。",
177
+ "figure.text.legend-no-value": "无值",
178
+ "figure.text.legend-select-one": "选择一个人偶即可查看。",
179
+ "figure.text.legend-note-legend-absent": "所选图例 {legend} 不在场景中,已按下一顺序显示。",
180
+ "figure.text.legend-note-resolver-failed": "应用未能选择图例({value})。",
181
+ "figure.text.legend-note-not-a-table": "图例 {legend} 不是表,按人偶自身的表显示。",
182
+ "figure.text.legend-note-not-an-interval": "{key} 不是区间。",
183
+ "figure.text.legend-note-code-unmatched": "图例中没有与值 {value} 对应的行。",
184
+ "figure.text.legend-note-not-a-look": "无法读取 {key} 行({value})。",
185
+ "figure.text.legend-note-not-taken": "{key} 行的 {column} {value} 未被采用。",
186
+ "figure.label.board-data-behavior-table": "表 {name}"
187
187
  }
@@ -1,41 +0,0 @@
1
- import '../status-looks/ox-figure-status-looks.js';
2
- import { type PropertyValues } from 'lit';
3
- import { OxPropertyEditor, type PropertySpec } from '@operato/property-editor';
4
- /**
5
- * 「상태 표현」 on the board's property panel for a figure with status ports (ADR-0051 2.3, §8): the template this
6
- * placement shows its codes through -- the board's default, one of the board's named templates, or its own -- and,
7
- * per port, the code the data gives now and which source answered it (the app's legend, the placement's template, the
8
- * board's). Below, the template's looks to read and change: colour, effect, a value for each state input the ports
9
- * offer with its unit and range, the clip of a port's motion group. What the figure did not take is said by the field
10
- * that gave it.
11
- *
12
- * The property is the placement's `statusTemplate`; a look of a board template is written on the board, in the same
13
- * undoable change. The figure checks each look when it shows it (things-scene); this section reads what it said.
14
- */
15
- export declare class OxPropertyEditorFigureStatus extends OxPropertyEditor {
16
- static styles: import("lit").CSSResult[];
17
- private naming;
18
- private watched?;
19
- private readonly refresh;
20
- private asked;
21
- disconnectedCallback(): void;
22
- willUpdate(changed: PropertyValues<this>): void;
23
- editorTemplate(value: unknown, spec: PropertySpec): import("lit-html").TemplateResult<1>;
24
- /** Which template: the board's default, one of the board's named ones, or the placement's own; a new named one. */
25
- private renderChooser;
26
- private renderPort;
27
- _valueChanged(e: Event): void;
28
- /** The looks written where the template lives: the placement's own value through the panel, a board's on the board. */
29
- private writeLooks;
30
- /** A new named template on the board, chosen for this placement, in one undoable change. */
31
- private createTemplate;
32
- private selectedFigure;
33
- /** The one selected figure, given to `use` inside the panel's undoable change; none for a selection of several. */
34
- private withSelected;
35
- private watch;
36
- }
37
- declare global {
38
- interface HTMLElementTagNameMap {
39
- 'ox-property-editor-figure-status': OxPropertyEditorFigureStatus;
40
- }
41
- }
@@ -1,290 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import '../status-looks/ox-figure-status-looks.js';
3
- import { css, html, nothing } from 'lit';
4
- import { customElement, state } from 'lit/decorators.js';
5
- import { resolveFigureStatus, resolveLegend } from '@hatiolab/things-scene';
6
- import { i18next } from '@operato/i18n';
7
- import { OxPropertyEditor } from '@operato/property-editor';
8
- import { isFigureColour } from '@hatiolab/figure-model';
9
- import { issueSentence } from '../status-looks/ox-figure-status-looks.js';
10
- import { issuesByRow, looksAt, offeredGroupsOf, offeredInputsOf, templatePlaceOf, withNewTemplate, writeLooksAt } from '../status-looks/status-looks.js';
11
- const OWN = '#own';
12
- /**
13
- * 「상태 표현」 on the board's property panel for a figure with status ports (ADR-0051 2.3, §8): the template this
14
- * placement shows its codes through -- the board's default, one of the board's named templates, or its own -- and,
15
- * per port, the code the data gives now and which source answered it (the app's legend, the placement's template, the
16
- * board's). Below, the template's looks to read and change: colour, effect, a value for each state input the ports
17
- * offer with its unit and range, the clip of a port's motion group. What the figure did not take is said by the field
18
- * that gave it.
19
- *
20
- * The property is the placement's `statusTemplate`; a look of a board template is written on the board, in the same
21
- * undoable change. The figure checks each look when it shows it (things-scene); this section reads what it said.
22
- */
23
- let OxPropertyEditorFigureStatus = class OxPropertyEditorFigureStatus extends OxPropertyEditor {
24
- constructor() {
25
- super(...arguments);
26
- this.naming = null;
27
- this.refresh = () => this.requestUpdate();
28
- /*
29
- Whether the selected figure was asked for since the value last came. The panel answers inside an undoable change,
30
- and each answer leaves a snapshot to undo to even when nothing changed: the figure is asked for when the panel gives
31
- a value (a new selection makes a new section), not again for each code or template the figure says changed.
32
- */
33
- this.asked = false;
34
- }
35
- static { this.styles = [
36
- ...OxPropertyEditor.styles,
37
- css `
38
- [body] {
39
- grid-column: 1 / -1;
40
- display: grid;
41
- gap: 6px;
42
- font-size: var(--ui-t-small, 11.5px);
43
- }
44
- [choose] {
45
- display: flex;
46
- gap: 4px;
47
- align-items: center;
48
- }
49
- [choose] select,
50
- [choose] input {
51
- flex: 1;
52
- min-width: 0;
53
- }
54
- [choose] button,
55
- [ports] button {
56
- height: 24px;
57
- padding: 0 8px;
58
- font: inherit;
59
- color: var(--md-sys-color-primary);
60
- border: none;
61
- border-radius: 6px;
62
- background: transparent;
63
- cursor: pointer;
64
- white-space: nowrap;
65
- }
66
- [choose] button:hover {
67
- background: var(--md-sys-color-surface-container-high);
68
- }
69
- ul {
70
- margin: 0;
71
- padding: 0;
72
- list-style: none;
73
- display: grid;
74
- gap: 2px;
75
- }
76
- li {
77
- display: flex;
78
- flex-wrap: wrap;
79
- gap: 0 6px;
80
- align-items: baseline;
81
- }
82
- li [meta] {
83
- margin-left: auto;
84
- display: flex;
85
- gap: 4px;
86
- align-items: baseline;
87
- }
88
- [source] {
89
- padding: 0 4px;
90
- border-radius: 4px;
91
- background: var(--md-sys-color-surface-container-high);
92
- color: var(--md-sys-color-on-surface-variant);
93
- }
94
- [swatch] {
95
- display: inline-block;
96
- width: 10px;
97
- height: 10px;
98
- border-radius: 2px;
99
- border: 1px solid var(--md-sys-color-outline-variant);
100
- vertical-align: middle;
101
- }
102
- [hint] {
103
- width: 100%;
104
- margin: 0;
105
- color: var(--md-sys-color-on-surface-variant);
106
- }
107
- [warn] {
108
- width: 100%;
109
- margin: 0;
110
- color: var(--md-sys-color-error);
111
- }
112
- ox-figure-status-looks {
113
- --status-looks-card-min: 100%;
114
- }
115
- `
116
- ]; }
117
- disconnectedCallback() {
118
- super.disconnectedCallback();
119
- this.watch(undefined);
120
- }
121
- willUpdate(changed) {
122
- if (changed.has('value'))
123
- this.asked = false;
124
- }
125
- editorTemplate(value, spec) {
126
- const figure = this.asked ? this.watched?.figure : this.selectedFigure();
127
- this.asked = true;
128
- const inputs = figure?.figureInputs;
129
- this.watch(figure);
130
- if (!figure || !inputs)
131
- return html `<div body><p hint>${i18next.t('figure.text.status-select-one')}</p></div>`;
132
- const asset = inputs.asset;
133
- const board = figure.rootModel?.state ?? {};
134
- const place = templatePlaceOf(value, board);
135
- const looks = looksAt(place, value, board);
136
- const source = place.at === 'placement' || (place.at === 'named' && place.chosenBy === 'placement') ? 'placement' : place.at === 'none' ? undefined : 'board';
137
- const ports = asset.dataInterface?.ports ?? [];
138
- const issues = figure._realObject?.statusIssues ?? [];
139
- const rowOf = (code) => {
140
- const found = resolveLegend(code, looks);
141
- return found === undefined ? undefined : Object.keys(looks).find(row => looks[row] === found);
142
- };
143
- const now = {};
144
- const answers = ports.map(port => {
145
- const code = inputs.data.status[port.id];
146
- const found = code === undefined ? undefined : resolveFigureStatus(figure, port, code);
147
- const row = found && found.source === source ? rowOf(code) : undefined;
148
- if (row !== undefined)
149
- now[row] = [...(now[row] ?? []), port.label];
150
- return { port, code, found };
151
- });
152
- const groups = offeredGroupsOf(asset);
153
- return html `<div body>
154
- ${this.renderChooser(value, board, place)}
155
- <ul ports>
156
- ${answers.map(a => this.renderPort(a.port, a.code, a.found, issues))}
157
- </ul>
158
- ${answers.some(a => a.found) && !figure._realObject ? html `<p hint>${i18next.t('figure.text.status-checked-in-3d')}</p>` : nothing}
159
- <ox-figure-status-looks
160
- .looks=${looks}
161
- .inputs=${offeredInputsOf(asset)}
162
- .clips=${[...new Set(groups.flatMap(g => g.clips))]}
163
- effects
164
- color-optional
165
- .now=${now}
166
- .issues=${issuesByRow(issues, source, rowOf)}
167
- @looks-change=${(e) => this.writeLooks(place, e.detail.looks)}
168
- ></ox-figure-status-looks>
169
- </div>`;
170
- }
171
- /** Which template: the board's default, one of the board's named ones, or the placement's own; a new named one. */
172
- renderChooser(value, board, place) {
173
- const names = Object.keys(board.statusTemplates ?? {});
174
- const chosen = typeof value === 'string' ? value : value && typeof value === 'object' ? OWN : '';
175
- if (typeof value === 'string' && value && !names.includes(value))
176
- names.push(value);
177
- const boardDefault = typeof board.statusTemplate === 'string' ? board.statusTemplate : undefined;
178
- if (this.naming !== null)
179
- return html `<div choose>
180
- <input
181
- aria-label=${i18next.t('figure.label.status-template-name')}
182
- placeholder=${i18next.t('figure.label.status-template-name')}
183
- .value=${this.naming}
184
- @input=${(e) => (this.naming = e.target.value)}
185
- @keydown=${(e) => e.key === 'Enter' && this.createTemplate(board)}
186
- />
187
- <button ?disabled=${!withNewTemplate(board, this.naming)} @click=${() => this.createTemplate(board)}>${i18next.t('figure.button.status-template-create')}</button>
188
- <button @click=${() => (this.naming = null)}>${i18next.t('figure.button.status-template-cancel')}</button>
189
- </div>`;
190
- return html `<div choose>
191
- <select data-template aria-label=${i18next.t('figure.label.status-template')}>
192
- <option value="" ?selected=${chosen === ''}>
193
- ${i18next.t('figure.label.status-template-board')}${boardDefault ? ` · ${boardDefault}` : place.at === 'none' ? ` · ${i18next.t('figure.label.status-template-none')}` : ''}
194
- </option>
195
- ${names.map(name => html `<option value=${name} ?selected=${chosen === name}>
196
- ${name}${board.statusTemplates?.[name] ? '' : ` · ${i18next.t('figure.label.status-template-none')}`}
197
- </option>`)}
198
- ${chosen === OWN ? html `<option value=${OWN} selected>${i18next.t('figure.label.status-template-own')}</option>` : nothing}
199
- </select>
200
- <button @click=${() => (this.naming = '')}>${i18next.t('figure.button.status-template-new')}</button>
201
- </div>`;
202
- }
203
- renderPort(port, code, found, issues) {
204
- const own = issues.filter(i => i.port === port.id && i.source === 'resolver');
205
- return html `<li>
206
- <span>${port.label}</span>
207
- <span meta>
208
- ${code === undefined ? html `<span hint>${i18next.t('figure.text.status-no-code')}</span>` : html `<b>${code}</b>`}
209
- ${found
210
- ? html `${found.source === 'resolver' ? lookSummary(found.look) : nothing}<span source>${i18next.t('figure.label.status-source-' + found.source)}</span>`
211
- : code !== undefined
212
- ? html `<span source>${i18next.t('figure.label.status-source-none')}</span>`
213
- : nothing}
214
- </span>
215
- ${found?.source === 'resolver' ? html `<p hint>${i18next.t('figure.text.status-resolver-note')}</p>` : nothing}
216
- ${own.map(issue => html `<p warn>${issueSentence(issue)}</p>`)}
217
- </li>`;
218
- }
219
- _valueChanged(e) {
220
- e.stopPropagation();
221
- const select = e.target;
222
- if (!select.hasAttribute?.('data-template'))
223
- return;
224
- if (select.value === OWN)
225
- return;
226
- this.value = select.value || undefined;
227
- this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }));
228
- this.observe(this.value);
229
- }
230
- /** The looks written where the template lives: the placement's own value through the panel, a board's on the board. */
231
- writeLooks(place, looks) {
232
- this.withSelected(figure => {
233
- const board = figure.rootModel?.state ?? {};
234
- const write = writeLooksAt(place, looks, this.value, board);
235
- if (write.board)
236
- figure.rootModel?.set(write.board);
237
- if (write.placement)
238
- figure.set({ statusTemplate: write.placement });
239
- });
240
- this.requestUpdate();
241
- }
242
- /** A new named template on the board, chosen for this placement, in one undoable change. */
243
- createTemplate(board) {
244
- const name = (this.naming ?? '').trim();
245
- const templates = withNewTemplate(board, name);
246
- if (!templates)
247
- return;
248
- this.withSelected(figure => {
249
- figure.rootModel?.set(templates);
250
- figure.set({ statusTemplate: name });
251
- });
252
- this.naming = null;
253
- }
254
- selectedFigure() {
255
- let figure;
256
- this.withSelected(f => (figure = f), false);
257
- return figure;
258
- }
259
- /** The one selected figure, given to `use` inside the panel's undoable change; none for a selection of several. */
260
- withSelected(use, write = true) {
261
- let selected;
262
- this.dispatchEvent(new CustomEvent('i-need-selected', { bubbles: true, composed: true, detail: { callback: (s) => ((selected = s), write && s?.length === 1 && use(s[0])) } }));
263
- if (!write && selected?.length === 1)
264
- use(selected[0]);
265
- }
266
- /* The data's codes and the board's templates change outside this section (live data, undo): it reads them again. */
267
- watch(figure) {
268
- if (this.watched?.figure === figure)
269
- return;
270
- this.watched?.figure.off?.('change', this.refresh);
271
- this.watched?.board?.off?.('change', this.refresh);
272
- this.watched = figure ? { figure, board: figure.rootModel } : undefined;
273
- figure?.on?.('change', this.refresh);
274
- figure?.rootModel?.on?.('change', this.refresh);
275
- }
276
- };
277
- __decorate([
278
- state(),
279
- __metadata("design:type", Object)
280
- ], OxPropertyEditorFigureStatus.prototype, "naming", void 0);
281
- OxPropertyEditorFigureStatus = __decorate([
282
- customElement('ox-property-editor-figure-status')
283
- ], OxPropertyEditorFigureStatus);
284
- export { OxPropertyEditorFigureStatus };
285
- /** A look the app's legend gave, read only: its colour and its values. */
286
- function lookSummary(look) {
287
- const values = look.values && typeof look.values === 'object' ? Object.entries(look.values).map(([k, v]) => `${k} ${v}`) : [];
288
- return html `${isFigureColour(look.color) ? html `<span swatch style="background:${look.color}" title=${look.color}></span>` : nothing}${values.length ? html `<span>${values.join(' · ')}</span>` : nothing}`;
289
- }
290
- //# sourceMappingURL=ox-property-editor-figure-status.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ox-property-editor-figure-status.js","sourceRoot":"","sources":["../../client/editors/ox-property-editor-figure-status.ts"],"names":[],"mappings":"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","sourcesContent":["import '../status-looks/ox-figure-status-looks.js'\n\nimport { css, html, nothing, type PropertyValues } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { resolveFigureStatus, resolveLegend } from '@hatiolab/things-scene'\nimport { i18next } from '@operato/i18n'\nimport { OxPropertyEditor, type PropertySpec } from '@operato/property-editor'\nimport { isFigureColour, type FigureAsset, type FigureStatusPort } from '@hatiolab/figure-model'\n\nimport { issueSentence } from '../status-looks/ox-figure-status-looks.js'\nimport {\n issuesByRow,\n looksAt,\n offeredGroupsOf,\n offeredInputsOf,\n templatePlaceOf,\n withNewTemplate,\n writeLooksAt,\n type BoardTemplates,\n type StatusIssue,\n type StatusLook,\n type StatusLooks,\n type TemplatePlace\n} from '../status-looks/status-looks.js'\n\n/** The parts of a placed figure the section reads and writes: things-scene's FigureInstance, as the property panel holds it. */\ninterface PlacedFigure {\n state?: { statusTemplate?: unknown }\n set(props: Record<string, unknown>): void\n on?(event: string, listener: (...args: unknown[]) => void): void\n off?(event: string, listener: (...args: unknown[]) => void): void\n rootModel?: PlacedFigure & { state?: BoardTemplates }\n figureInputs?: { asset: FigureAsset; data: { status: Record<string, string> } }\n /** The 3D object, when the board draws in 3D: what its status ports did not take (ADR-0051 2.3, 5). */\n _realObject?: { statusIssues?: StatusIssue[] }\n}\n\nconst OWN = '#own'\n\n/**\n * 「상태 표현」 on the board's property panel for a figure with status ports (ADR-0051 2.3, §8): the template this\n * placement shows its codes through -- the board's default, one of the board's named templates, or its own -- and,\n * per port, the code the data gives now and which source answered it (the app's legend, the placement's template, the\n * board's). Below, the template's looks to read and change: colour, effect, a value for each state input the ports\n * offer with its unit and range, the clip of a port's motion group. What the figure did not take is said by the field\n * that gave it.\n *\n * The property is the placement's `statusTemplate`; a look of a board template is written on the board, in the same\n * undoable change. The figure checks each look when it shows it (things-scene); this section reads what it said.\n */\n@customElement('ox-property-editor-figure-status')\nexport class OxPropertyEditorFigureStatus extends OxPropertyEditor {\n static styles = [\n ...OxPropertyEditor.styles,\n css`\n [body] {\n grid-column: 1 / -1;\n display: grid;\n gap: 6px;\n font-size: var(--ui-t-small, 11.5px);\n }\n [choose] {\n display: flex;\n gap: 4px;\n align-items: center;\n }\n [choose] select,\n [choose] input {\n flex: 1;\n min-width: 0;\n }\n [choose] button,\n [ports] 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 [choose] button:hover {\n background: var(--md-sys-color-surface-container-high);\n }\n ul {\n margin: 0;\n padding: 0;\n list-style: none;\n display: grid;\n gap: 2px;\n }\n li {\n display: flex;\n flex-wrap: wrap;\n gap: 0 6px;\n align-items: baseline;\n }\n li [meta] {\n margin-left: auto;\n display: flex;\n gap: 4px;\n align-items: baseline;\n }\n [source] {\n padding: 0 4px;\n border-radius: 4px;\n background: var(--md-sys-color-surface-container-high);\n color: var(--md-sys-color-on-surface-variant);\n }\n [swatch] {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 2px;\n border: 1px solid var(--md-sys-color-outline-variant);\n vertical-align: middle;\n }\n [hint] {\n width: 100%;\n margin: 0;\n color: var(--md-sys-color-on-surface-variant);\n }\n [warn] {\n width: 100%;\n margin: 0;\n color: var(--md-sys-color-error);\n }\n ox-figure-status-looks {\n --status-looks-card-min: 100%;\n }\n `\n ]\n\n @state() private naming: string | null = null\n\n private watched?: { figure: PlacedFigure; board?: PlacedFigure }\n private readonly refresh = () => this.requestUpdate()\n /*\n Whether the selected figure was asked for since the value last came. The panel answers inside an undoable change,\n and each answer leaves a snapshot to undo to even when nothing changed: the figure is asked for when the panel gives\n a value (a new selection makes a new section), not again for each code or template the figure says changed.\n */\n private asked = false\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.watch(undefined)\n }\n\n willUpdate(changed: PropertyValues<this>) {\n if (changed.has('value')) this.asked = false\n }\n\n editorTemplate(value: unknown, spec: PropertySpec) {\n const figure = this.asked ? this.watched?.figure : this.selectedFigure()\n this.asked = true\n const inputs = figure?.figureInputs\n this.watch(figure)\n if (!figure || !inputs) return html`<div body><p hint>${i18next.t('figure.text.status-select-one')}</p></div>`\n\n const asset = inputs.asset\n const board: BoardTemplates = figure.rootModel?.state ?? {}\n const place = templatePlaceOf(value, board)\n const looks = looksAt(place, value, board)\n const source = place.at === 'placement' || (place.at === 'named' && place.chosenBy === 'placement') ? 'placement' : place.at === 'none' ? undefined : 'board'\n const ports = asset.dataInterface?.ports ?? []\n const issues = figure._realObject?.statusIssues ?? []\n const rowOf = (code: string) => {\n const found = resolveLegend(code, looks)\n return found === undefined ? undefined : Object.keys(looks).find(row => looks[row] === found)\n }\n\n const now: Record<string, string[]> = {}\n const answers = ports.map(port => {\n const code = inputs.data.status[port.id]\n const found = code === undefined ? undefined : resolveFigureStatus(figure, port, code)\n const row = found && found.source === source ? rowOf(code!) : undefined\n if (row !== undefined) now[row] = [...(now[row] ?? []), port.label]\n return { port, code, found }\n })\n const groups = offeredGroupsOf(asset)\n\n return html`<div body>\n ${this.renderChooser(value, board, place)}\n <ul ports>\n ${answers.map(a => this.renderPort(a.port, a.code, a.found, issues))}\n </ul>\n ${answers.some(a => a.found) && !figure._realObject ? html`<p hint>${i18next.t('figure.text.status-checked-in-3d')}</p>` : nothing}\n <ox-figure-status-looks\n .looks=${looks}\n .inputs=${offeredInputsOf(asset)}\n .clips=${[...new Set(groups.flatMap(g => g.clips))]}\n effects\n color-optional\n .now=${now}\n .issues=${issuesByRow(issues, source, rowOf)}\n @looks-change=${(e: CustomEvent<{ looks: StatusLooks }>) => this.writeLooks(place, e.detail.looks)}\n ></ox-figure-status-looks>\n </div>`\n }\n\n /** Which template: the board's default, one of the board's named ones, or the placement's own; a new named one. */\n private renderChooser(value: unknown, board: BoardTemplates, place: TemplatePlace) {\n const names = Object.keys(board.statusTemplates ?? {})\n const chosen = typeof value === 'string' ? value : value && typeof value === 'object' ? OWN : ''\n if (typeof value === 'string' && value && !names.includes(value)) names.push(value)\n const boardDefault = typeof board.statusTemplate === 'string' ? board.statusTemplate : undefined\n if (this.naming !== null)\n return html`<div choose>\n <input\n aria-label=${i18next.t('figure.label.status-template-name')}\n placeholder=${i18next.t('figure.label.status-template-name')}\n .value=${this.naming}\n @input=${(e: Event) => (this.naming = (e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => e.key === 'Enter' && this.createTemplate(board)}\n />\n <button ?disabled=${!withNewTemplate(board, this.naming)} @click=${() => this.createTemplate(board)}>${i18next.t('figure.button.status-template-create')}</button>\n <button @click=${() => (this.naming = null)}>${i18next.t('figure.button.status-template-cancel')}</button>\n </div>`\n return html`<div choose>\n <select data-template aria-label=${i18next.t('figure.label.status-template')}>\n <option value=\"\" ?selected=${chosen === ''}>\n ${i18next.t('figure.label.status-template-board')}${boardDefault ? ` · ${boardDefault}` : place.at === 'none' ? ` · ${i18next.t('figure.label.status-template-none')}` : ''}\n </option>\n ${names.map(\n name =>\n html`<option value=${name} ?selected=${chosen === name}>\n ${name}${board.statusTemplates?.[name] ? '' : ` · ${i18next.t('figure.label.status-template-none')}`}\n </option>`\n )}\n ${chosen === OWN ? html`<option value=${OWN} selected>${i18next.t('figure.label.status-template-own')}</option>` : nothing}\n </select>\n <button @click=${() => (this.naming = '')}>${i18next.t('figure.button.status-template-new')}</button>\n </div>`\n }\n\n private renderPort(port: FigureStatusPort, code: string | undefined, found: { look: StatusLook; source: string } | undefined, issues: readonly StatusIssue[]) {\n const own = issues.filter(i => i.port === port.id && i.source === 'resolver')\n return html`<li>\n <span>${port.label}</span>\n <span meta>\n ${code === undefined ? html`<span hint>${i18next.t('figure.text.status-no-code')}</span>` : html`<b>${code}</b>`}\n ${found\n ? html`${found.source === 'resolver' ? lookSummary(found.look) : nothing}<span source>${i18next.t('figure.label.status-source-' + found.source)}</span>`\n : code !== undefined\n ? html`<span source>${i18next.t('figure.label.status-source-none')}</span>`\n : nothing}\n </span>\n ${found?.source === 'resolver' ? html`<p hint>${i18next.t('figure.text.status-resolver-note')}</p>` : nothing}\n ${own.map(issue => html`<p warn>${issueSentence(issue)}</p>`)}\n </li>`\n }\n\n override _valueChanged(e: Event) {\n e.stopPropagation()\n const select = e.target as HTMLSelectElement\n if (!select.hasAttribute?.('data-template')) return\n if (select.value === OWN) return\n this.value = select.value || undefined\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))\n this.observe(this.value)\n }\n\n /** The looks written where the template lives: the placement's own value through the panel, a board's on the board. */\n private writeLooks(place: TemplatePlace, looks: StatusLooks) {\n this.withSelected(figure => {\n const board: BoardTemplates = figure.rootModel?.state ?? {}\n const write = writeLooksAt(place, looks, this.value, board)\n if (write.board) figure.rootModel?.set(write.board as Record<string, unknown>)\n if (write.placement) figure.set({ statusTemplate: write.placement })\n })\n this.requestUpdate()\n }\n\n /** A new named template on the board, chosen for this placement, in one undoable change. */\n private createTemplate(board: BoardTemplates) {\n const name = (this.naming ?? '').trim()\n const templates = withNewTemplate(board, name)\n if (!templates) return\n this.withSelected(figure => {\n figure.rootModel?.set(templates as Record<string, unknown>)\n figure.set({ statusTemplate: name })\n })\n this.naming = null\n }\n\n private selectedFigure(): PlacedFigure | undefined {\n let figure: PlacedFigure | undefined\n this.withSelected(f => (figure = f), false)\n return figure\n }\n\n /** The one selected figure, given to `use` inside the panel's undoable change; none for a selection of several. */\n private withSelected(use: (figure: PlacedFigure) => void, write = true) {\n let selected: unknown[] | undefined\n this.dispatchEvent(new CustomEvent('i-need-selected', { bubbles: true, composed: true, detail: { callback: (s: unknown[]) => ((selected = s), write && s?.length === 1 && use(s[0] as PlacedFigure)) } }))\n if (!write && selected?.length === 1) use(selected[0] as PlacedFigure)\n }\n\n /* The data's codes and the board's templates change outside this section (live data, undo): it reads them again. */\n private watch(figure: PlacedFigure | undefined) {\n if (this.watched?.figure === figure) return\n this.watched?.figure.off?.('change', this.refresh)\n this.watched?.board?.off?.('change', this.refresh)\n this.watched = figure ? { figure, board: figure.rootModel } : undefined\n figure?.on?.('change', this.refresh)\n figure?.rootModel?.on?.('change', this.refresh)\n }\n}\n\n/** A look the app's legend gave, read only: its colour and its values. */\nfunction lookSummary(look: StatusLook) {\n const values = look.values && typeof look.values === 'object' ? Object.entries(look.values).map(([k, v]) => `${k} ${v}`) : []\n return html`${isFigureColour(look.color) ? html`<span swatch style=\"background:${look.color}\" title=${look.color}></span>` : nothing}${values.length ? html`<span>${values.join(' · ')}</span>` : nothing}`\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ox-property-editor-figure-status': OxPropertyEditorFigureStatus\n }\n}\n"]}
@@ -1,58 +0,0 @@
1
- import { LitElement } from 'lit';
2
- import { type LookInput, type StatusIssue, type StatusLooks } from './status-looks.js';
3
- /**
4
- * A status template's looks, one card per code (ADR-0051 2.3): its colour, its effect, a value for each state input a
5
- * figure's port offers -- with the input's name, unit and range -- and the clip of the port's motion group. The code the
6
- * data gives now is marked; a part the figure did not take is said under the card, by the field that gave it. Every
7
- * change sends `looks-change` with the whole looks; the host writes them where the template lives.
8
- *
9
- * A value outside its input's range is not taken from the field (as the property panel's number maps); a value written
10
- * elsewhere that the figure refused shows with the reason, to be fixed here. Values for inputs not shown -- another
11
- * figure's, in a table shared by many -- are kept as they are.
12
- *
13
- * Shared by the board's 「상태 표현」 section and fmsim's legend editor, which shows colour and values only.
14
- */
15
- export declare class OxFigureStatusLooks extends LitElement {
16
- static styles: import("lit").CSSResult;
17
- looks: StatusLooks;
18
- /** The state inputs shown, one field each: the figure's offered inputs, or those a legend gives values to. */
19
- inputs: LookInput[];
20
- /** Inputs that can be added as a field (a legend's editor: the inputs the carrier figures offer). */
21
- addable: LookInput[];
22
- /**
23
- * Whether every input a look gives a value to has a field, offered or not: a legend, which no one figure reads. A
24
- * figure's own section leaves the values of inputs it does not offer to the figures that do.
25
- */
26
- showGiven: boolean;
27
- /** The clips a look may choose; none, no clip field. */
28
- clips: string[];
29
- effects: boolean;
30
- /** Whether a look may give no colour (a board's template); a legend's entry always has one. */
31
- colorOptional: boolean;
32
- /** The colour a new code starts with (a legend's entry has one from the start). */
33
- defaultColor?: string;
34
- /** The rows the data gives now, with the ports that read them. */
35
- now: Record<string, string[]>;
36
- /** What the figure did not take, by row. */
37
- issues: Map<string, StatusIssue[]>;
38
- disabled: boolean;
39
- private added;
40
- private newCode;
41
- render(): import("lit-html").TemplateResult<1>;
42
- /** The inputs shown: those given, those added here, and, with `showGiven`, any a look gives a value to. */
43
- private shownInputs;
44
- private renderCard;
45
- private addCode;
46
- /** A number in range is taken; an empty field takes the value away (the next source gives it); anything else is not taken. */
47
- private changeValue;
48
- private change;
49
- }
50
- /** An input as the choice and the tooltip say it: its name, unit and range, and the port that offers it. */
51
- export declare function describeInput(input: LookInput): string;
52
- /** Why a part was not taken, in the person's words, with the value refused. */
53
- export declare function issueSentence(issue: StatusIssue, inputs?: readonly LookInput[]): string;
54
- declare global {
55
- interface HTMLElementTagNameMap {
56
- 'ox-figure-status-looks': OxFigureStatusLooks;
57
- }
58
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"ox-figure-status-looks.js","sourceRoot":"","sources":["../../client/status-looks/ox-figure-status-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 LookInput, type StatusIssue, type StatusLooks } from './status-looks.js'\n\nconst DEFAULT = 'default'\n\n/**\n * A status template's looks, one card per code (ADR-0051 2.3): its colour, its effect, a value for each state input a\n * figure's port offers -- with the input's name, unit and range -- and the clip of the port's motion group. The code the\n * data gives now is marked; a part the figure did not take is said under the card, by the field that gave it. Every\n * change sends `looks-change` with the whole looks; the host writes them where the template lives.\n *\n * A value outside its input's range is not taken from the field (as the property panel's number maps); a value written\n * elsewhere that the figure refused shows with the reason, to be fixed here. Values for inputs not shown -- another\n * figure's, in a table shared by many -- are kept as they are.\n *\n * Shared by the board's 「상태 표현」 section and fmsim's legend editor, which shows colour and values only.\n */\n@customElement('ox-figure-status-looks')\nexport class OxFigureStatusLooks 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(--status-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 section[now] {\n border-color: var(--md-sys-color-primary);\n }\n\n section[refused] {\n border-color: var(--md-sys-color-error);\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 [now-tag] {\n padding: 0 4px;\n border-radius: 4px;\n background: var(--md-sys-color-primary-container);\n color: var(--md-sys-color-on-primary-container);\n font-size: 0.68rem;\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 [issue] {\n margin: 0;\n color: var(--md-sys-color-error);\n font-size: 0.7rem;\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: StatusLooks = {}\n /** The state inputs shown, one field each: the figure's offered inputs, or those a legend gives values to. */\n @property({ type: Array }) inputs: LookInput[] = []\n /** Inputs that can be added as a field (a legend's editor: the inputs the carrier figures offer). */\n @property({ type: Array }) addable: LookInput[] = []\n /**\n * Whether every input a look gives a value to has a field, offered or not: a legend, which no one figure reads. A\n * figure's own section leaves the values of inputs it does not offer to the figures that do.\n */\n @property({ type: Boolean, attribute: 'show-given' }) showGiven = 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 no colour (a board's template); a legend's entry always has one. */\n @property({ type: Boolean, attribute: 'color-optional' }) colorOptional = false\n /** The colour a new code starts with (a legend's entry has one from the start). */\n @property({ type: String, attribute: 'default-color' }) defaultColor?: string\n /** The rows the data gives now, with the ports that read them. */\n @property({ type: Object }) now: Record<string, string[]> = {}\n /** What the figure did not take, by row. */\n @property({ type: Object }) issues: Map<string, StatusIssue[]> = new Map()\n @property({ type: Boolean }) disabled = false\n\n @state() private added: LookInput[] = []\n @state() private newCode = ''\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.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.status-looks-empty')}</p>`}\n <footer>\n <input\n aria-label=${i18next.t('figure.label.status-code')}\n placeholder=${i18next.t('figure.label.status-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.status-add-code')}</button>\n ${DEFAULT in this.looks ? nothing : html`<button ?disabled=${this.disabled} @click=${() => this.addCode(DEFAULT)}>${i18next.t('figure.button.status-add-default')}</button>`}\n ${addable.length\n ? html`<select\n aria-label=${i18next.t('figure.button.status-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.status-add-value')}</option>\n ${addable.map(a => html`<option value=${a.input}>${describeInput(a)}</option>`)}\n </select>`\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 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 issues = this.issues.get(code) ?? []\n const said = (target: string, id?: string) => issues.filter(i => i.target === target && (id === undefined || i.id === id))\n const ports = this.now[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 ?now=${!!ports} ?refused=${issues.length > 0} data-code=${code}>\n <header>\n <input\n type=\"color\"\n aria-label=${i18next.t('figure.label.status-color')}\n title=${look.color === undefined ? i18next.t('figure.label.status-color-none') : String(look.color)}\n ?unset=${look.color === undefined}\n aria-invalid=${said('color').length ? 'true' : 'false'}\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.status-default-code') : code}</b>\n ${ports ? html`<span now-tag title=${ports.join(', ')}>${i18next.t('figure.label.status-now')}</span>` : nothing}\n <span end>\n ${this.colorOptional && look.color !== undefined\n ? html`<button icon title=${i18next.t('figure.button.status-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.status-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.status-effect')}</span>\n <select\n ?wide=${effect?.kind !== 'blink'}\n aria-label=${i18next.t('figure.label.status-effect')}\n aria-invalid=${said('effect').length ? 'true' : 'false'}\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.status-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.status-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 const refused = said('state', 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 aria-invalid=${refused.length ? 'true' : 'false'}\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.status-clip')}</span>\n <select\n wide\n aria-label=${i18next.t('figure.label.status-clip')}\n aria-invalid=${said('motion-clip').length ? 'true' : 'false'}\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.status-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 </div>\n ${issues.map(issue => html`<p issue>${issueSentence(issue, inputs)}</p>`)}\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 private change(looks: StatusLooks) {\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 port that offers it. */\nexport function describeInput(input: LookInput): string {\n const tail = [input.unit, rangeOf(input)].filter(Boolean).join(' ')\n return `${input.label}${tail ? ` (${tail})` : ''}${input.portLabel ? ` · ${input.portLabel}` : ''}`\n}\n\nfunction rangeOf(input: LookInput): string | undefined {\n return input.min !== undefined || input.max !== undefined ? `${input.min ?? ''}~${input.max ?? ''}` : undefined\n}\n\n/** Why a part was not taken, in the person's words, with the value refused. */\nexport function issueSentence(issue: StatusIssue, inputs: readonly LookInput[] = []): string {\n const input = issue.id !== undefined ? inputs.find(i => i.input === issue.id) : undefined\n return i18next.t('figure.text.status-issue-' + issue.reason, {\n name: input?.label ?? issue.id ?? '',\n value: typeof issue.value === 'string' ? issue.value : JSON.stringify(issue.value),\n range: input ? (rangeOf(input) ?? '') : ''\n })\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ox-figure-status-looks': OxFigureStatusLooks\n }\n}\n"]}