@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
@@ -1,10 +1,13 @@
1
1
  import './editors/ox-property-editor-figure-data.js';
2
- import './editors/ox-property-editor-figure-status.js';
2
+ import './editors/ox-property-editor-figure-legends.js';
3
3
  /**
4
4
  * The editors the board's property panel needs for the properties a placed figure names: its data -- shape, each value
5
- * and where it came from (`figure-data`) --, its status template and each code's look (`figure-status`, ADR-0051 2.3)
6
- * and its slot layout, which a placement may override (`slot-layout`, ADR-0118 decision 8). Registered here, where every
7
- * app that places library figures on its boards loads this module; the scene component list does not carry figure
8
- * packages, and without these the panel skips the three properties.
5
+ * and where it came from (`figure-data`) --, the legend each of its table roles shows by (`figure-legends`, ADR-0166
6
+ * 11) and its slot layout, which a placement may override (`slot-layout`, ADR-0118 decision 8). Registered here, where
7
+ * every app that places library figures on its boards loads this module; the scene component list does not carry
8
+ * figure packages, and without these the panel skips the three properties.
9
+ *
10
+ * And the one legend editor, a grist editor `legend-looks`: a legend theme's looks -- colour, effect, values, a motion
11
+ * group's clip, speed and pause (ADR-0166 11). The board's 「테마」 list uses it for its legend kinds when it is here.
9
12
  */
10
13
  export default function bootstrap(): void;
@@ -1,17 +1,23 @@
1
+ import { registerEditor } from '@operato/data-grist';
1
2
  import { OxPropertyEditor } from '@operato/property-editor';
2
3
  import { SLOT_LAYOUT_EDITORS } from '@operato/slot-layout-editor';
4
+ import { LegendLooksEditor } from './legend-looks/legend-looks-editor.js';
3
5
  import './editors/ox-property-editor-figure-data.js';
4
- import './editors/ox-property-editor-figure-status.js';
6
+ import './editors/ox-property-editor-figure-legends.js';
5
7
  /**
6
8
  * The editors the board's property panel needs for the properties a placed figure names: its data -- shape, each value
7
- * and where it came from (`figure-data`) --, its status template and each code's look (`figure-status`, ADR-0051 2.3)
8
- * and its slot layout, which a placement may override (`slot-layout`, ADR-0118 decision 8). Registered here, where every
9
- * app that places library figures on its boards loads this module; the scene component list does not carry figure
10
- * packages, and without these the panel skips the three properties.
9
+ * and where it came from (`figure-data`) --, the legend each of its table roles shows by (`figure-legends`, ADR-0166
10
+ * 11) and its slot layout, which a placement may override (`slot-layout`, ADR-0118 decision 8). Registered here, where
11
+ * every app that places library figures on its boards loads this module; the scene component list does not carry
12
+ * figure packages, and without these the panel skips the three properties.
13
+ *
14
+ * And the one legend editor, a grist editor `legend-looks`: a legend theme's looks -- colour, effect, values, a motion
15
+ * group's clip, speed and pause (ADR-0166 11). The board's 「테마」 list uses it for its legend kinds when it is here.
11
16
  */
12
17
  export default function bootstrap() {
13
18
  OxPropertyEditor.register({ 'figure-data': 'ox-property-editor-figure-data' });
14
- OxPropertyEditor.register({ 'figure-status': 'ox-property-editor-figure-status' });
19
+ OxPropertyEditor.register({ 'figure-legends': 'ox-property-editor-figure-legends' });
20
+ registerEditor('legend-looks', LegendLooksEditor);
15
21
  OxPropertyEditor.register(Object.fromEntries(SLOT_LAYOUT_EDITORS.map(e => [e.type, e.element])));
16
22
  }
17
23
  //# sourceMappingURL=bootstrap.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../client/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjE,OAAO,6CAA6C,CAAA;AACpD,OAAO,+CAA+C,CAAA;AAEtD;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS;IAC/B,gBAAgB,CAAC,QAAQ,CAAC,EAAE,aAAa,EAAE,gCAAgC,EAAE,CAAC,CAAA;IAC9E,gBAAgB,CAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,kCAAkC,EAAE,CAAC,CAAA;IAClF,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AAClG,CAAC","sourcesContent":["import { OxPropertyEditor } from '@operato/property-editor'\nimport { SLOT_LAYOUT_EDITORS } from '@operato/slot-layout-editor'\n\nimport './editors/ox-property-editor-figure-data.js'\nimport './editors/ox-property-editor-figure-status.js'\n\n/**\n * The editors the board's property panel needs for the properties a placed figure names: its data -- shape, each value\n * and where it came from (`figure-data`) --, its status template and each code's look (`figure-status`, ADR-0051 2.3)\n * and its slot layout, which a placement may override (`slot-layout`, ADR-0118 decision 8). Registered here, where every\n * app that places library figures on its boards loads this module; the scene component list does not carry figure\n * packages, and without these the panel skips the three properties.\n */\nexport default function bootstrap() {\n OxPropertyEditor.register({ 'figure-data': 'ox-property-editor-figure-data' })\n OxPropertyEditor.register({ 'figure-status': 'ox-property-editor-figure-status' })\n OxPropertyEditor.register(Object.fromEntries(SLOT_LAYOUT_EDITORS.map(e => [e.type, e.element])))\n}\n"]}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../client/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAEzE,OAAO,6CAA6C,CAAA;AACpD,OAAO,gDAAgD,CAAA;AAEvD;;;;;;;;;GASG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS;IAC/B,gBAAgB,CAAC,QAAQ,CAAC,EAAE,aAAa,EAAE,gCAAgC,EAAE,CAAC,CAAA;IAC9E,gBAAgB,CAAC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,mCAAmC,EAAE,CAAC,CAAA;IACpF,cAAc,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAA;IACjD,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AAClG,CAAC","sourcesContent":["import { registerEditor } from '@operato/data-grist'\nimport { OxPropertyEditor } from '@operato/property-editor'\nimport { SLOT_LAYOUT_EDITORS } from '@operato/slot-layout-editor'\n\nimport { LegendLooksEditor } from './legend-looks/legend-looks-editor.js'\n\nimport './editors/ox-property-editor-figure-data.js'\nimport './editors/ox-property-editor-figure-legends.js'\n\n/**\n * The editors the board's property panel needs for the properties a placed figure names: its data -- shape, each value\n * and where it came from (`figure-data`) --, the legend each of its table roles shows by (`figure-legends`, ADR-0166\n * 11) and its slot layout, which a placement may override (`slot-layout`, ADR-0118 decision 8). Registered here, where\n * every app that places library figures on its boards loads this module; the scene component list does not carry\n * figure packages, and without these the panel skips the three properties.\n *\n * And the one legend editor, a grist editor `legend-looks`: a legend theme's looks -- colour, effect, values, a motion\n * group's clip, speed and pause (ADR-0166 11). The board's 「테마」 list uses it for its legend kinds when it is here.\n */\nexport default function bootstrap() {\n OxPropertyEditor.register({ 'figure-data': 'ox-property-editor-figure-data' })\n OxPropertyEditor.register({ 'figure-legends': 'ox-property-editor-figure-legends' })\n registerEditor('legend-looks', LegendLooksEditor)\n OxPropertyEditor.register(Object.fromEntries(SLOT_LAYOUT_EDITORS.map(e => [e.type, e.element])))\n}\n"]}
@@ -0,0 +1,34 @@
1
+ import { type PropertyValues } from 'lit';
2
+ import { OxPropertyEditor, type PropertySpec } from '@operato/property-editor';
3
+ /**
4
+ * 「범례」 on the board's property panel for a figure whose tables a legend may take (ADR-0166 7, 11): per legend role,
5
+ * the legend this placement shows the role's tables by -- the board's default, one of the scene's legends of the
6
+ * kind that fits (a code map for a code table, a range map for a range table), or the figure's own table -- and the
7
+ * board's default for the role, set from here. Under each role, what its tables show now: the value, the row it
8
+ * matched, and the table it came from; what of a legend was not taken.
9
+ *
10
+ * The property is the placement's `legends` (role → legend name); the board's default is the board's `legends`,
11
+ * written in the same undoable change. Legends are edited where they live, in the domain's legend themes.
12
+ */
13
+ export declare class OxPropertyEditorFigureLegends extends OxPropertyEditor {
14
+ static styles: import("lit").CSSResult[];
15
+ private watched?;
16
+ private readonly refresh;
17
+ private asked;
18
+ disconnectedCallback(): void;
19
+ willUpdate(changed: PropertyValues<this>): void;
20
+ editorTemplate(value: unknown, _spec: PropertySpec): import("lit-html").TemplateResult<1>;
21
+ private renderRole;
22
+ _valueChanged(e: Event): void;
23
+ /** The board's default for the role, this placement's choice, in one undoable change; the placement then follows it. */
24
+ private makeBoardDefault;
25
+ private selectedFigure;
26
+ /** The one selected figure, given to `use` inside the panel's undoable change; none for a selection of several. */
27
+ private withSelected;
28
+ private watch;
29
+ }
30
+ declare global {
31
+ interface HTMLElementTagNameMap {
32
+ 'ox-property-editor-figure-legends': OxPropertyEditorFigureLegends;
33
+ }
34
+ }
@@ -0,0 +1,236 @@
1
+ import { __decorate } from "tslib";
2
+ import { css, html, nothing } from 'lit';
3
+ import { customElement } from 'lit/decorators.js';
4
+ import { FIGURE_OWN_TABLE } from '@hatiolab/things-scene';
5
+ import { i18next } from '@operato/i18n';
6
+ import { OxPropertyEditor } from '@operato/property-editor';
7
+ import { legendFits, legendTablesOf } from '../legend-looks/legend-looks.js';
8
+ const BOARD = '';
9
+ const OWN = FIGURE_OWN_TABLE;
10
+ /**
11
+ * 「범례」 on the board's property panel for a figure whose tables a legend may take (ADR-0166 7, 11): per legend role,
12
+ * the legend this placement shows the role's tables by -- the board's default, one of the scene's legends of the
13
+ * kind that fits (a code map for a code table, a range map for a range table), or the figure's own table -- and the
14
+ * board's default for the role, set from here. Under each role, what its tables show now: the value, the row it
15
+ * matched, and the table it came from; what of a legend was not taken.
16
+ *
17
+ * The property is the placement's `legends` (role → legend name); the board's default is the board's `legends`,
18
+ * written in the same undoable change. Legends are edited where they live, in the domain's legend themes.
19
+ */
20
+ let OxPropertyEditorFigureLegends = class OxPropertyEditorFigureLegends extends OxPropertyEditor {
21
+ constructor() {
22
+ super(...arguments);
23
+ this.refresh = () => this.requestUpdate();
24
+ /*
25
+ Whether the selected figure was asked for since the value last came. The panel answers inside an undoable change,
26
+ and each answer leaves a snapshot to undo to even when nothing changed: the figure is asked for when the panel gives
27
+ a value (a new selection makes a new section), not again for each change the figure says.
28
+ */
29
+ this.asked = false;
30
+ }
31
+ static { this.styles = [
32
+ ...OxPropertyEditor.styles,
33
+ css `
34
+ [body] {
35
+ grid-column: 1 / -1;
36
+ display: grid;
37
+ gap: 8px;
38
+ font-size: var(--ui-t-small, 11.5px);
39
+ }
40
+ section {
41
+ display: grid;
42
+ gap: 4px;
43
+ }
44
+ [role] {
45
+ display: flex;
46
+ gap: 6px;
47
+ align-items: baseline;
48
+ }
49
+ [role] small {
50
+ color: var(--md-sys-color-on-surface-variant);
51
+ }
52
+ [choose] {
53
+ display: flex;
54
+ gap: 4px;
55
+ align-items: center;
56
+ }
57
+ [choose] select {
58
+ flex: 1;
59
+ min-width: 0;
60
+ }
61
+ [choose] button {
62
+ height: 24px;
63
+ padding: 0 8px;
64
+ font: inherit;
65
+ color: var(--md-sys-color-primary);
66
+ border: none;
67
+ border-radius: 6px;
68
+ background: transparent;
69
+ cursor: pointer;
70
+ white-space: nowrap;
71
+ }
72
+ [choose] button:hover {
73
+ background: var(--md-sys-color-surface-container-high);
74
+ }
75
+ [choose] button:disabled {
76
+ color: var(--md-sys-color-on-surface-variant);
77
+ cursor: default;
78
+ }
79
+ ul {
80
+ margin: 0;
81
+ padding: 0;
82
+ list-style: none;
83
+ display: grid;
84
+ gap: 2px;
85
+ }
86
+ li {
87
+ display: flex;
88
+ flex-wrap: wrap;
89
+ gap: 0 6px;
90
+ align-items: baseline;
91
+ }
92
+ li [meta] {
93
+ margin-left: auto;
94
+ display: flex;
95
+ gap: 4px;
96
+ align-items: baseline;
97
+ }
98
+ [source] {
99
+ padding: 0 4px;
100
+ border-radius: 4px;
101
+ background: var(--md-sys-color-surface-container-high);
102
+ color: var(--md-sys-color-on-surface-variant);
103
+ }
104
+ [hint] {
105
+ width: 100%;
106
+ margin: 0;
107
+ color: var(--md-sys-color-on-surface-variant);
108
+ }
109
+ [warn] {
110
+ width: 100%;
111
+ margin: 0;
112
+ color: var(--md-sys-color-error);
113
+ }
114
+ `
115
+ ]; }
116
+ disconnectedCallback() {
117
+ super.disconnectedCallback();
118
+ this.watch(undefined);
119
+ }
120
+ willUpdate(changed) {
121
+ if (changed.has('value'))
122
+ this.asked = false;
123
+ }
124
+ editorTemplate(value, _spec) {
125
+ const figure = this.asked ? this.watched?.figure : this.selectedFigure();
126
+ this.asked = true;
127
+ const inputs = figure?.figureInputs;
128
+ this.watch(figure);
129
+ if (!figure || !inputs)
130
+ return html `<div body><p hint>${i18next.t('figure.text.legend-select-one')}</p></div>`;
131
+ const chosen = (value && typeof value === 'object' ? value : {});
132
+ const board = figure.rootModel?.state?.legends ?? {};
133
+ const style = figure.root?.style ?? {};
134
+ const tables = legendTablesOf(inputs.asset);
135
+ const roles = [...new Set(tables.map(t => t.legend.role))];
136
+ const notes = inputs.diagnostics().filter(d => d.severity === 'note');
137
+ return html `<div body>
138
+ ${roles.map(role => this.renderRole(role, tables.filter(t => t.legend.role === role), chosen, board, style, inputs.tableUses, notes))}
139
+ </div>`;
140
+ }
141
+ renderRole(role, tables, chosen, board, style, uses, notes) {
142
+ const lookup = tables[0].lookup;
143
+ /* The scene's legends of the kind that fits: a code table a code map, a range table a range map. */
144
+ const fitting = Object.keys(style).filter(name => legendFits(lookup, style[name]));
145
+ const own = chosen[role];
146
+ if (own && !fitting.includes(own))
147
+ fitting.push(own);
148
+ const boardDefault = board[role];
149
+ const domain = Object.prototype.hasOwnProperty.call(style, role);
150
+ const fallback = boardDefault ? `${i18next.t('figure.label.legend-board')} · ${boardDefault}` : domain ? `${i18next.t('figure.label.legend-domain')} · ${role}` : i18next.t('figure.label.legend-figure-table');
151
+ return html `<section>
152
+ <div role><b>${role}</b><small>${tables.map(t => t.label ?? t.accessor).join(', ')}</small></div>
153
+ <div choose>
154
+ <select data-role=${role} aria-label=${role}>
155
+ <option value=${BOARD} ?selected=${!own}>${fallback}</option>
156
+ ${fitting.map(name => html `<option value=${name} ?selected=${own === name}>${name}${Object.prototype.hasOwnProperty.call(style, name) ? '' : ` · ${i18next.t('figure.label.legend-absent')}`}</option>`)}
157
+ <option value=${OWN} ?selected=${own === OWN}>${i18next.t('figure.label.legend-figure-table')}</option>
158
+ </select>
159
+ <button ?disabled=${!own || own === boardDefault} title=${i18next.t('figure.text.legend-make-board-default')} @click=${() => this.makeBoardDefault(role, own)}>
160
+ ${i18next.t('figure.button.legend-board-default')}
161
+ </button>
162
+ </div>
163
+ <ul>
164
+ ${tables.map(t => {
165
+ const use = uses[t.id];
166
+ const row = !use || use.value === undefined ? undefined : use.key === null ? i18next.t('figure.label.legend-row-none') : use.key === 'default' ? i18next.t('figure.label.legend-default-code') : use.key;
167
+ return html `<li>
168
+ <span>${t.label ?? t.accessor}</span>
169
+ <span meta>
170
+ ${use?.value === undefined ? html `<span hint>${i18next.t('figure.text.legend-no-value')}</span>` : html `<b>${String(use.value)}</b> → ${row}`}
171
+ ${use ? html `<span source>${use.source === 'figure' ? i18next.t('figure.label.legend-figure-table') : (use.legend ?? use.source)}</span>` : nothing}
172
+ </span>
173
+ </li>`;
174
+ })}
175
+ </ul>
176
+ ${notes
177
+ .filter(n => tables.some(t => t.id === n.binding))
178
+ .map(n => html `<p warn>${i18next.t('figure.text.legend-note-' + n.reason, { key: n.key ?? '', column: n.column ?? '', legend: n.legend ?? '', value: typeof n.value === 'string' ? n.value : JSON.stringify(n.value ?? '') })}</p>`)}
179
+ </section>`;
180
+ }
181
+ _valueChanged(e) {
182
+ e.stopPropagation();
183
+ const select = e.target;
184
+ const role = select.getAttribute?.('data-role');
185
+ if (!role)
186
+ return;
187
+ const next = { ...(this.value && typeof this.value === 'object' ? this.value : {}) };
188
+ if (select.value === BOARD)
189
+ delete next[role];
190
+ else
191
+ next[role] = select.value;
192
+ this.value = Object.keys(next).length ? next : undefined;
193
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }));
194
+ }
195
+ /** The board's default for the role, this placement's choice, in one undoable change; the placement then follows it. */
196
+ makeBoardDefault(role, name) {
197
+ this.withSelected(figure => {
198
+ const board = { ...(figure.rootModel?.state?.legends ?? {}) };
199
+ if (name)
200
+ board[role] = name;
201
+ else
202
+ delete board[role];
203
+ figure.rootModel?.set({ legends: board });
204
+ const own = { ...(figure.state?.legends ?? {}) };
205
+ delete own[role];
206
+ figure.set({ legends: Object.keys(own).length ? own : undefined });
207
+ });
208
+ }
209
+ selectedFigure() {
210
+ let figure;
211
+ this.withSelected(f => (figure = f), false);
212
+ return figure;
213
+ }
214
+ /** The one selected figure, given to `use` inside the panel's undoable change; none for a selection of several. */
215
+ withSelected(use, write = true) {
216
+ let selected;
217
+ this.dispatchEvent(new CustomEvent('i-need-selected', { bubbles: true, composed: true, detail: { callback: (s) => ((selected = s), write && s?.length === 1 && use(s[0])) } }));
218
+ if (!write && selected?.length === 1)
219
+ use(selected[0]);
220
+ }
221
+ /* The data's codes and the board's choices change outside this section (live data, undo): it reads them again. */
222
+ watch(figure) {
223
+ if (this.watched?.figure === figure)
224
+ return;
225
+ this.watched?.figure.off?.('change', this.refresh);
226
+ this.watched?.board?.off?.('change', this.refresh);
227
+ this.watched = figure ? { figure, board: figure.rootModel } : undefined;
228
+ figure?.on?.('change', this.refresh);
229
+ figure?.rootModel?.on?.('change', this.refresh);
230
+ }
231
+ };
232
+ OxPropertyEditorFigureLegends = __decorate([
233
+ customElement('ox-property-editor-figure-legends')
234
+ ], OxPropertyEditorFigureLegends);
235
+ export { OxPropertyEditorFigureLegends };
236
+ //# sourceMappingURL=ox-property-editor-figure-legends.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ox-property-editor-figure-legends.js","sourceRoot":"","sources":["../../client/editors/ox-property-editor-figure-legends.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, nothing, type PropertyValues } from 'lit'\nimport { customElement } from 'lit/decorators.js'\n\nimport { FIGURE_OWN_TABLE } from '@hatiolab/things-scene'\nimport { i18next } from '@operato/i18n'\nimport { OxPropertyEditor, type PropertySpec } from '@operato/property-editor'\nimport type { FigureAsset, FigureDataTableBinding } from '@hatiolab/figure-model'\n\nimport { legendFits, legendTablesOf } from '../legend-looks/legend-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?: { legends?: Record<string, string> }\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 /** The board: its default legend for each role (`legends`). */\n rootModel?: PlacedFigure & { state?: { legends?: Record<string, string> } }\n /** The scene's root container: the legends the scene was given, by name (`style`). */\n root?: { style?: Record<string, unknown> }\n figureInputs?: {\n asset: FigureAsset\n tableUses: Readonly<Record<string, { value: unknown; key: string | null; source: string; legend?: string }>>\n diagnostics(): ReadonlyArray<{ severity: string; reason: string; binding?: string; key?: string; column?: string; legend?: string; value?: unknown }>\n }\n}\n\nconst BOARD = ''\nconst OWN = FIGURE_OWN_TABLE\n\n/**\n * 「범례」 on the board's property panel for a figure whose tables a legend may take (ADR-0166 7, 11): per legend role,\n * the legend this placement shows the role's tables by -- the board's default, one of the scene's legends of the\n * kind that fits (a code map for a code table, a range map for a range table), or the figure's own table -- and the\n * board's default for the role, set from here. Under each role, what its tables show now: the value, the row it\n * matched, and the table it came from; what of a legend was not taken.\n *\n * The property is the placement's `legends` (role → legend name); the board's default is the board's `legends`,\n * written in the same undoable change. Legends are edited where they live, in the domain's legend themes.\n */\n@customElement('ox-property-editor-figure-legends')\nexport class OxPropertyEditorFigureLegends extends OxPropertyEditor {\n static styles = [\n ...OxPropertyEditor.styles,\n css`\n [body] {\n grid-column: 1 / -1;\n display: grid;\n gap: 8px;\n font-size: var(--ui-t-small, 11.5px);\n }\n section {\n display: grid;\n gap: 4px;\n }\n [role] {\n display: flex;\n gap: 6px;\n align-items: baseline;\n }\n [role] small {\n color: var(--md-sys-color-on-surface-variant);\n }\n [choose] {\n display: flex;\n gap: 4px;\n align-items: center;\n }\n [choose] select {\n flex: 1;\n min-width: 0;\n }\n [choose] 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 [choose] button:disabled {\n color: var(--md-sys-color-on-surface-variant);\n cursor: default;\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 [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 `\n ]\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 change the figure says.\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.legend-select-one')}</p></div>`\n const chosen = (value && typeof value === 'object' ? value : {}) as Record<string, string>\n const board = figure.rootModel?.state?.legends ?? {}\n const style = figure.root?.style ?? {}\n const tables = legendTablesOf(inputs.asset)\n const roles = [...new Set(tables.map(t => t.legend!.role))]\n const notes = inputs.diagnostics().filter(d => d.severity === 'note')\n return html`<div body>\n ${roles.map(role => this.renderRole(role, tables.filter(t => t.legend!.role === role), chosen, board, style, inputs.tableUses, notes))}\n </div>`\n }\n\n private renderRole(\n role: string,\n tables: FigureDataTableBinding[],\n chosen: Record<string, string>,\n board: Record<string, string>,\n style: Record<string, unknown>,\n uses: NonNullable<PlacedFigure['figureInputs']>['tableUses'],\n notes: ReturnType<NonNullable<PlacedFigure['figureInputs']>['diagnostics']>\n ) {\n const lookup = tables[0]!.lookup\n /* The scene's legends of the kind that fits: a code table a code map, a range table a range map. */\n const fitting = Object.keys(style).filter(name => legendFits(lookup, style[name]))\n const own = chosen[role]\n if (own && !fitting.includes(own)) fitting.push(own)\n const boardDefault = board[role]\n const domain = Object.prototype.hasOwnProperty.call(style, role)\n const fallback = boardDefault ? `${i18next.t('figure.label.legend-board')} · ${boardDefault}` : domain ? `${i18next.t('figure.label.legend-domain')} · ${role}` : i18next.t('figure.label.legend-figure-table')\n return html`<section>\n <div role><b>${role}</b><small>${tables.map(t => t.label ?? t.accessor).join(', ')}</small></div>\n <div choose>\n <select data-role=${role} aria-label=${role}>\n <option value=${BOARD} ?selected=${!own}>${fallback}</option>\n ${fitting.map(name => html`<option value=${name} ?selected=${own === name}>${name}${Object.prototype.hasOwnProperty.call(style, name) ? '' : ` · ${i18next.t('figure.label.legend-absent')}`}</option>`)}\n <option value=${OWN} ?selected=${own === OWN}>${i18next.t('figure.label.legend-figure-table')}</option>\n </select>\n <button ?disabled=${!own || own === boardDefault} title=${i18next.t('figure.text.legend-make-board-default')} @click=${() => this.makeBoardDefault(role, own)}>\n ${i18next.t('figure.button.legend-board-default')}\n </button>\n </div>\n <ul>\n ${tables.map(t => {\n const use = uses[t.id]\n const row = !use || use.value === undefined ? undefined : use.key === null ? i18next.t('figure.label.legend-row-none') : use.key === 'default' ? i18next.t('figure.label.legend-default-code') : use.key\n return html`<li>\n <span>${t.label ?? t.accessor}</span>\n <span meta>\n ${use?.value === undefined ? html`<span hint>${i18next.t('figure.text.legend-no-value')}</span>` : html`<b>${String(use.value)}</b> → ${row}`}\n ${use ? html`<span source>${use.source === 'figure' ? i18next.t('figure.label.legend-figure-table') : (use.legend ?? use.source)}</span>` : nothing}\n </span>\n </li>`\n })}\n </ul>\n ${notes\n .filter(n => tables.some(t => t.id === n.binding))\n .map(n => html`<p warn>${i18next.t('figure.text.legend-note-' + n.reason, { key: n.key ?? '', column: n.column ?? '', legend: n.legend ?? '', value: typeof n.value === 'string' ? n.value : JSON.stringify(n.value ?? '') })}</p>`)}\n </section>`\n }\n\n override _valueChanged(e: Event) {\n e.stopPropagation()\n const select = e.target as HTMLSelectElement\n const role = select.getAttribute?.('data-role')\n if (!role) return\n const next = { ...((this.value && typeof this.value === 'object' ? this.value : {}) as Record<string, string>) }\n if (select.value === BOARD) delete next[role]\n else next[role] = select.value\n this.value = Object.keys(next).length ? next : undefined\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))\n }\n\n /** The board's default for the role, this placement's choice, in one undoable change; the placement then follows it. */\n private makeBoardDefault(role: string, name: string | undefined) {\n this.withSelected(figure => {\n const board = { ...(figure.rootModel?.state?.legends ?? {}) }\n if (name) board[role] = name\n else delete board[role]\n figure.rootModel?.set({ legends: board })\n const own = { ...(figure.state?.legends ?? {}) }\n delete own[role]\n figure.set({ legends: Object.keys(own).length ? own : undefined })\n })\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 choices 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\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ox-property-editor-figure-legends': OxPropertyEditorFigureLegends\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { FigureAsset, FigureDataBehavior, FigureDataNode, FigureDataValue, FigureDataValueIssue } from '@hatiolab/figure-model';
1
+ import type { FigureAsset, FigureDataBehavior, FigureDataNode, FigureDataTargets, FigureDataValue, FigureDataValueIssue } from '@hatiolab/figure-model';
2
2
  /** Where a value came from, as things-scene's figure inputs say. */
3
3
  export type FigureDataSource = 'live' | 'manual' | 'default' | 'absent';
4
4
  /** A placed figure as the section reads it: its asset, its state, and what its figure inputs worked out. */
@@ -30,11 +30,16 @@ export interface FigureDataReportRow {
30
30
  value?: FigureDataValue;
31
31
  count?: number;
32
32
  source?: FigureDataSource;
33
- /** What the bindings reading it move. */
34
- behaviors: FigureDataBehavior[];
33
+ /** What the bindings reading it move: a behavior each, or a table and its targets. */
34
+ behaviors: FigureDataMove[];
35
35
  /** Controls it moves that the board's state values hold instead. */
36
36
  heldByBoard: string[];
37
37
  }
38
+ /** What one binding moves: a value binding's behavior, or a table's targets (ADR-0166 3). */
39
+ export type FigureDataMove = FigureDataBehavior | {
40
+ kind: 'table';
41
+ targets: FigureDataTargets;
42
+ };
38
43
  export interface FigureDataReport {
39
44
  rows: FigureDataReportRow[];
40
45
  /** Fields the data has that the shape does not name, as paths (`[]` for a list's elements). */
@@ -44,5 +49,5 @@ export interface FigureDataReport {
44
49
  example: Record<string, unknown>;
45
50
  }
46
51
  export declare function figureDataReportOf(s: FigureDataSnapshot): FigureDataReport | null;
47
- /** The thing a behavior moves, as one id: the control, the colour token, the group, the port, the axis, the place. */
48
- export declare const behaviorTargetOf: (b: FigureDataBehavior) => string;
52
+ /** The things a binding moves, as one line: the control, the colour token, the group, the axis, the place; a table's targets. */
53
+ export declare const behaviorTargetOf: (b: FigureDataMove) => string;
@@ -54,8 +54,8 @@ export function figureDataReportOf(s) {
54
54
  const held = new Set(Object.keys(s.parameters ?? {}));
55
55
  const rows = figureDataRows(di).map((row) => {
56
56
  const reading = row.bindings.map(id => bindings.get(id)).filter(b => !!b);
57
- const behaviors = reading.map(b => b.behavior);
58
- const heldByBoard = behaviors.flatMap(b => (b.kind === 'state' && held.has(b.input) ? [b.input] : []));
57
+ const behaviors = reading.map((b) => (b.rule === 'table' ? { kind: 'table', targets: b.targets } : b.behavior));
58
+ const heldByBoard = behaviors.flatMap(b => (b.kind === 'state' ? [b.input] : b.kind === 'table' ? (b.targets.inputs ?? []) : []).filter(input => held.has(input)));
59
59
  const out = { path: row.path, depth: row.depth, name: row.name, ...(row.label ? { label: row.label } : {}), node: row.node, behaviors, heldByBoard };
60
60
  if (row.node.kind === 'list') {
61
61
  const list = row.path.includes('[]') ? undefined : valueAt(s.data, row.path);
@@ -64,7 +64,7 @@ export function figureDataReportOf(s) {
64
64
  }
65
65
  else if (row.node.kind !== 'object') {
66
66
  /* The value a binding read: the first that reads this place and is not an items binding (items read the list). */
67
- const read = reading.find(b => b.behavior.kind !== 'items' && s.values[b.id]);
67
+ const read = reading.find(b => (b.rule === 'table' || b.behavior.kind !== 'items') && s.values[b.id]);
68
68
  if (read) {
69
69
  const { value, source } = s.values[read.id];
70
70
  out.source = source;
@@ -78,6 +78,16 @@ export function figureDataReportOf(s) {
78
78
  unusedOf(s.data, di.schema, '', unused);
79
79
  return { rows, unused: [...unused], refused: s.refused, example: figureDataExample(di) };
80
80
  }
81
- /** The thing a behavior moves, as one id: the control, the colour token, the group, the port, the axis, the place. */
82
- export const behaviorTargetOf = (b) => b.kind === 'state' ? b.input : b.kind === 'palette' ? b.token : b.kind === 'status' ? b.port : b.kind === 'pose' ? b.axis : b.kind === 'items' ? (b.slot ?? '') : b.group;
81
+ /** The things a binding moves, as one line: the control, the colour token, the group, the axis, the place; a table's targets. */
82
+ export const behaviorTargetOf = (b) => b.kind === 'table'
83
+ ? [...(b.targets.parts ?? []), ...(b.targets.inputs ?? []), ...(b.targets.group ? [b.targets.group] : [])].join(', ')
84
+ : b.kind === 'state'
85
+ ? b.input
86
+ : b.kind === 'palette'
87
+ ? b.token
88
+ : b.kind === 'pose'
89
+ ? b.axis
90
+ : b.kind === 'items'
91
+ ? (b.slot ?? '')
92
+ : b.group;
83
93
  //# sourceMappingURL=figure-data-report.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"figure-data-report.js","sourceRoot":"","sources":["../client/figure-data-report.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What the board's 「Figure 데이터」 section shows of a placed figure (data binding design, decision 3): the figure's data\n * shape as a tree, each value now and where it came from -- the component's data, a value saved on the board, the\n * shape's default, or none -- what it moves, a control the board's own state values hold over the data, why data was\n * refused, the fields the data has that the shape does not name, and an example to copy.\n *\n * Nothing here reads data: the values and their sources are things-scene's figure inputs', given in. Kept apart from the\n * element so it is tested without a board.\n */\nimport { figureDataExample, figureDataRows } from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureDataBehavior, FigureDataNode, FigureDataValue, FigureDataValueIssue } from '@hatiolab/figure-model'\n\n/** Where a value came from, as things-scene's figure inputs say. */\nexport type FigureDataSource = 'live' | 'manual' | 'default' | 'absent'\n\n/** A placed figure as the section reads it: its asset, its state, and what its figure inputs worked out. */\nexport interface FigureDataSnapshot {\n asset: FigureAsset\n /** The component's data, as the board's data source or a mapping gave it. */\n data: unknown\n /** The board's own state values (`parameters`), by control. */\n parameters?: Record<string, unknown> | null\n /** Each binding's value now and its source, by binding id (figure inputs' `dataValues`). */\n values: Readonly<Record<string, { value: FigureDataValue | undefined; source: FigureDataSource }>>\n /** Why the last things given were refused (figure inputs' `diagnostics()`). */\n refused: ReadonlyArray<{ source: string; reason: string; issues?: FigureDataValueIssue[] }>\n}\n\nexport interface FigureDataReportRow {\n path: string\n depth: number\n name: string\n label?: string\n node: FigureDataNode\n /** A value field's value now; a list's element count in the data. */\n value?: FigureDataValue\n count?: number\n source?: FigureDataSource\n /** What the bindings reading it move. */\n behaviors: FigureDataBehavior[]\n /** Controls it moves that the board's state values hold instead. */\n heldByBoard: string[]\n}\n\nexport interface FigureDataReport {\n rows: FigureDataReportRow[]\n /** Fields the data has that the shape does not name, as paths (`[]` for a list's elements). */\n unused: string[]\n refused: FigureDataSnapshot['refused']\n /** Data with every field of the shape, to copy. */\n example: Record<string, unknown>\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> => !!v && typeof v === 'object' && !Array.isArray(v)\n\n/** The value at a path with no list in it (`A.B`), or undefined. */\nfunction valueAt(data: unknown, path: string): unknown {\n let at: unknown = data\n for (const name of path.split('.')) {\n if (!isRecord(at)) return undefined\n at = at[name]\n }\n return at\n}\n\n/** Every field path the data has that the shape does not name. A JSON text in place of an object or a list is not looked into. */\nfunction unusedOf(data: unknown, fields: ReadonlyArray<{ name: string } & FigureDataNode>, at: string, out: Set<string>): void {\n if (!isRecord(data)) return\n for (const [key, value] of Object.entries(data)) {\n const path = at ? `${at}.${key}` : key\n const field = fields.find(f => f.name === key)\n if (!field) {\n out.add(path)\n continue\n }\n let node: FigureDataNode = field\n let value_: unknown = value\n let p = path\n while (node.kind === 'list' && Array.isArray(value_)) {\n const item: FigureDataNode = node.item\n p = `${p}[]`\n for (const element of value_) if (item.kind === 'object') unusedOf(element, item.fields, p, out)\n value_ = undefined\n node = item\n }\n if (node.kind === 'object' && isRecord(value_)) unusedOf(value_, node.fields, p, out)\n }\n}\n\nexport function figureDataReportOf(s: FigureDataSnapshot): FigureDataReport | null {\n const di = s.asset.dataInterface\n if (!di) return null\n const bindings = new Map(di.bindings.map(b => [b.id, b] as const))\n const held = new Set(Object.keys(s.parameters ?? {}))\n const rows = figureDataRows(di).map((row): FigureDataReportRow => {\n const reading = row.bindings.map(id => bindings.get(id)).filter(b => !!b)\n const behaviors = reading.map(b => b.behavior)\n const heldByBoard = behaviors.flatMap(b => (b.kind === 'state' && held.has(b.input) ? [b.input] : []))\n const out: FigureDataReportRow = { path: row.path, depth: row.depth, name: row.name, ...(row.label ? { label: row.label } : {}), node: row.node, behaviors, heldByBoard }\n if (row.node.kind === 'list') {\n const list = row.path.includes('[]') ? undefined : valueAt(s.data, row.path)\n if (Array.isArray(list)) out.count = list.length\n } else if (row.node.kind !== 'object') {\n /* The value a binding read: the first that reads this place and is not an items binding (items read the list). */\n const read = reading.find(b => b.behavior.kind !== 'items' && s.values[b.id])\n if (read) {\n const { value, source } = s.values[read.id]!\n out.source = source\n if (value !== undefined) out.value = value\n }\n }\n return out\n })\n const unused = new Set<string>()\n unusedOf(s.data, di.schema, '', unused)\n return { rows, unused: [...unused], refused: s.refused, example: figureDataExample(di) }\n}\n\n/** The thing a behavior moves, as one id: the control, the colour token, the group, the port, the axis, the place. */\nexport const behaviorTargetOf = (b: FigureDataBehavior): string =>\n b.kind === 'state' ? b.input : b.kind === 'palette' ? b.token : b.kind === 'status' ? b.port : b.kind === 'pose' ? b.axis : b.kind === 'items' ? (b.slot ?? '') : b.group\n"]}
1
+ {"version":3,"file":"figure-data-report.js","sourceRoot":"","sources":["../client/figure-data-report.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What the board's 「Figure 데이터」 section shows of a placed figure (data binding design, decision 3): the figure's data\n * shape as a tree, each value now and where it came from -- the component's data, a value saved on the board, the\n * shape's default, or none -- what it moves, a control the board's own state values hold over the data, why data was\n * refused, the fields the data has that the shape does not name, and an example to copy.\n *\n * Nothing here reads data: the values and their sources are things-scene's figure inputs', given in. Kept apart from the\n * element so it is tested without a board.\n */\nimport { figureDataExample, figureDataRows } from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureDataBehavior, FigureDataNode, FigureDataTargets, FigureDataValue, FigureDataValueIssue } from '@hatiolab/figure-model'\n\n/** Where a value came from, as things-scene's figure inputs say. */\nexport type FigureDataSource = 'live' | 'manual' | 'default' | 'absent'\n\n/** A placed figure as the section reads it: its asset, its state, and what its figure inputs worked out. */\nexport interface FigureDataSnapshot {\n asset: FigureAsset\n /** The component's data, as the board's data source or a mapping gave it. */\n data: unknown\n /** The board's own state values (`parameters`), by control. */\n parameters?: Record<string, unknown> | null\n /** Each binding's value now and its source, by binding id (figure inputs' `dataValues`). */\n values: Readonly<Record<string, { value: FigureDataValue | undefined; source: FigureDataSource }>>\n /** Why the last things given were refused (figure inputs' `diagnostics()`). */\n refused: ReadonlyArray<{ source: string; reason: string; issues?: FigureDataValueIssue[] }>\n}\n\nexport interface FigureDataReportRow {\n path: string\n depth: number\n name: string\n label?: string\n node: FigureDataNode\n /** A value field's value now; a list's element count in the data. */\n value?: FigureDataValue\n count?: number\n source?: FigureDataSource\n /** What the bindings reading it move: a behavior each, or a table and its targets. */\n behaviors: FigureDataMove[]\n /** Controls it moves that the board's state values hold instead. */\n heldByBoard: string[]\n}\n\n/** What one binding moves: a value binding's behavior, or a table's targets (ADR-0166 3). */\nexport type FigureDataMove = FigureDataBehavior | { kind: 'table'; targets: FigureDataTargets }\n\nexport interface FigureDataReport {\n rows: FigureDataReportRow[]\n /** Fields the data has that the shape does not name, as paths (`[]` for a list's elements). */\n unused: string[]\n refused: FigureDataSnapshot['refused']\n /** Data with every field of the shape, to copy. */\n example: Record<string, unknown>\n}\n\nconst isRecord = (v: unknown): v is Record<string, unknown> => !!v && typeof v === 'object' && !Array.isArray(v)\n\n/** The value at a path with no list in it (`A.B`), or undefined. */\nfunction valueAt(data: unknown, path: string): unknown {\n let at: unknown = data\n for (const name of path.split('.')) {\n if (!isRecord(at)) return undefined\n at = at[name]\n }\n return at\n}\n\n/** Every field path the data has that the shape does not name. A JSON text in place of an object or a list is not looked into. */\nfunction unusedOf(data: unknown, fields: ReadonlyArray<{ name: string } & FigureDataNode>, at: string, out: Set<string>): void {\n if (!isRecord(data)) return\n for (const [key, value] of Object.entries(data)) {\n const path = at ? `${at}.${key}` : key\n const field = fields.find(f => f.name === key)\n if (!field) {\n out.add(path)\n continue\n }\n let node: FigureDataNode = field\n let value_: unknown = value\n let p = path\n while (node.kind === 'list' && Array.isArray(value_)) {\n const item: FigureDataNode = node.item\n p = `${p}[]`\n for (const element of value_) if (item.kind === 'object') unusedOf(element, item.fields, p, out)\n value_ = undefined\n node = item\n }\n if (node.kind === 'object' && isRecord(value_)) unusedOf(value_, node.fields, p, out)\n }\n}\n\nexport function figureDataReportOf(s: FigureDataSnapshot): FigureDataReport | null {\n const di = s.asset.dataInterface\n if (!di) return null\n const bindings = new Map(di.bindings.map(b => [b.id, b] as const))\n const held = new Set(Object.keys(s.parameters ?? {}))\n const rows = figureDataRows(di).map((row): FigureDataReportRow => {\n const reading = row.bindings.map(id => bindings.get(id)).filter(b => !!b)\n const behaviors = reading.map((b): FigureDataMove => (b.rule === 'table' ? { kind: 'table', targets: b.targets } : b.behavior))\n const heldByBoard = behaviors.flatMap(b => (b.kind === 'state' ? [b.input] : b.kind === 'table' ? (b.targets.inputs ?? []) : []).filter(input => held.has(input)))\n const out: FigureDataReportRow = { path: row.path, depth: row.depth, name: row.name, ...(row.label ? { label: row.label } : {}), node: row.node, behaviors, heldByBoard }\n if (row.node.kind === 'list') {\n const list = row.path.includes('[]') ? undefined : valueAt(s.data, row.path)\n if (Array.isArray(list)) out.count = list.length\n } else if (row.node.kind !== 'object') {\n /* The value a binding read: the first that reads this place and is not an items binding (items read the list). */\n const read = reading.find(b => (b.rule === 'table' || b.behavior.kind !== 'items') && s.values[b.id])\n if (read) {\n const { value, source } = s.values[read.id]!\n out.source = source\n if (value !== undefined) out.value = value\n }\n }\n return out\n })\n const unused = new Set<string>()\n unusedOf(s.data, di.schema, '', unused)\n return { rows, unused: [...unused], refused: s.refused, example: figureDataExample(di) }\n}\n\n/** The things a binding moves, as one line: the control, the colour token, the group, the axis, the place; a table's targets. */\nexport const behaviorTargetOf = (b: FigureDataMove): string =>\n b.kind === 'table'\n ? [...(b.targets.parts ?? []), ...(b.targets.inputs ?? []), ...(b.targets.group ? [b.targets.group] : [])].join(', ')\n : b.kind === 'state'\n ? b.input\n : b.kind === 'palette'\n ? b.token\n : b.kind === 'pose'\n ? b.axis\n : b.kind === 'items'\n ? (b.slot ?? '')\n : b.group\n"]}
@@ -0,0 +1,42 @@
1
+ import '@material/web/icon/icon.js';
2
+ import './ox-legend-looks.js';
3
+ import { LitElement } from 'lit';
4
+ import { OxGristEditor } from '@operato/data-grist';
5
+ import { type LegendLooks, type LookInput } from './legend-looks.js';
6
+ /**
7
+ * A legend theme's value, edited look by look (ADR-0166 11): the board's 「테마」 list opens this for its legend kinds --
8
+ * a code map (`color-map`, `animation-map`) or a range map (`color-ranges`) -- when this module is loaded. Each code's
9
+ * colour, effect, values for named state inputs, and a motion group's clip, speed and pause; what else an entry holds
10
+ * is kept. A look that is a colour alone is written as the colour, as a colour map keeps it.
11
+ */
12
+ export declare class LegendLooksEditor extends OxGristEditor {
13
+ private popup?;
14
+ get editorTemplate(): import("lit-html").TemplateResult<1>;
15
+ _onclick(e: Event): void;
16
+ _onkeydown(e: KeyboardEvent): void;
17
+ /** The value written back as it came -- an object, or text for a store that keeps text. */
18
+ openLooks(): void;
19
+ }
20
+ export declare class LegendLooksPopup extends LitElement {
21
+ static styles: import("lit").CSSResult[];
22
+ draft: {
23
+ looks: LegendLooks;
24
+ };
25
+ confirmCallback: (looks: LegendLooks) => void;
26
+ /** Inputs offered for a value, with name, unit and range (fmsim: those its carrier figures' tables set). */
27
+ addable: LookInput[];
28
+ /**
29
+ * Colour only: no effect, no values, no motion -- fmsim's carrier legend, whose figures take the thickness from their own
30
+ * fixed table (ADR-0167 12). What an entry already holds is kept.
31
+ */
32
+ colourOnly: boolean;
33
+ /** The colour a new code starts with: a colour map's entries have one. */
34
+ defaultColor?: string;
35
+ render(): import("lit-html").TemplateResult<1>;
36
+ }
37
+ declare global {
38
+ interface HTMLElementTagNameMap {
39
+ 'legend-looks-editor': LegendLooksEditor;
40
+ 'legend-looks-popup': LegendLooksPopup;
41
+ }
42
+ }