@things-factory/figure-ui 10.1.76 → 10.1.77
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.
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/dist-client/graphql/v3-store.d.ts +0 -3
- package/dist-client/graphql/v3-store.js +0 -39
- package/dist-client/graphql/v3-store.js.map +0 -1
- package/dist-client/modeller/figure-v3-capability.d.ts +0 -22
- package/dist-client/modeller/figure-v3-capability.js +0 -141
- package/dist-client/modeller/figure-v3-capability.js.map +0 -1
- package/dist-client/modeller/figure-v3-clips.d.ts +0 -31
- package/dist-client/modeller/figure-v3-clips.js +0 -268
- package/dist-client/modeller/figure-v3-clips.js.map +0 -1
- package/dist-client/modeller/figure-v3-controls.d.ts +0 -36
- package/dist-client/modeller/figure-v3-controls.js +0 -226
- package/dist-client/modeller/figure-v3-controls.js.map +0 -1
- package/dist-client/modeller/figure-v3-first-save.d.ts +0 -20
- package/dist-client/modeller/figure-v3-first-save.js +0 -118
- package/dist-client/modeller/figure-v3-first-save.js.map +0 -1
- package/dist-client/modeller/figure-v3-links.d.ts +0 -77
- package/dist-client/modeller/figure-v3-links.js +0 -649
- package/dist-client/modeller/figure-v3-links.js.map +0 -1
- package/dist-client/modeller/figure-v3-material.d.ts +0 -39
- package/dist-client/modeller/figure-v3-material.js +0 -323
- package/dist-client/modeller/figure-v3-material.js.map +0 -1
- package/dist-client/modeller/figure-v3-parts.d.ts +0 -69
- package/dist-client/modeller/figure-v3-parts.js +0 -559
- package/dist-client/modeller/figure-v3-parts.js.map +0 -1
- package/dist-client/modeller/figure-v3-preview.d.ts +0 -34
- package/dist-client/modeller/figure-v3-preview.js +0 -346
- package/dist-client/modeller/figure-v3-preview.js.map +0 -1
- package/dist-client/modeller/figure-v3-properties.d.ts +0 -45
- package/dist-client/modeller/figure-v3-properties.js +0 -239
- package/dist-client/modeller/figure-v3-properties.js.map +0 -1
- package/dist-client/modeller/figure-v3-recipe-catalog.d.ts +0 -38
- package/dist-client/modeller/figure-v3-recipe-catalog.js +0 -399
- package/dist-client/modeller/figure-v3-recipe-catalog.js.map +0 -1
- package/dist-client/modeller/figure-v3-verdict.d.ts +0 -64
- package/dist-client/modeller/figure-v3-verdict.js +0 -787
- package/dist-client/modeller/figure-v3-verdict.js.map +0 -1
- package/dist-client/modeller/v3-ai-proposal.d.ts +0 -51
- package/dist-client/modeller/v3-ai-proposal.js +0 -64
- package/dist-client/modeller/v3-ai-proposal.js.map +0 -1
- package/dist-client/modeller/v3-align.d.ts +0 -30
- package/dist-client/modeller/v3-align.js +0 -75
- package/dist-client/modeller/v3-align.js.map +0 -1
- package/dist-client/modeller/v3-canvas.d.ts +0 -72
- package/dist-client/modeller/v3-canvas.js +0 -379
- package/dist-client/modeller/v3-canvas.js.map +0 -1
- package/dist-client/modeller/v3-clips.d.ts +0 -39
- package/dist-client/modeller/v3-clips.js +0 -58
- package/dist-client/modeller/v3-clips.js.map +0 -1
- package/dist-client/modeller/v3-controls.d.ts +0 -28
- package/dist-client/modeller/v3-controls.js +0 -28
- package/dist-client/modeller/v3-controls.js.map +0 -1
- package/dist-client/modeller/v3-editor.d.ts +0 -203
- package/dist-client/modeller/v3-editor.js +0 -1526
- package/dist-client/modeller/v3-editor.js.map +0 -1
- package/dist-client/modeller/v3-fields.d.ts +0 -45
- package/dist-client/modeller/v3-fields.js +0 -83
- package/dist-client/modeller/v3-fields.js.map +0 -1
- package/dist-client/modeller/v3-figure-facts.d.ts +0 -35
- package/dist-client/modeller/v3-figure-facts.js +0 -55
- package/dist-client/modeller/v3-figure-facts.js.map +0 -1
- package/dist-client/modeller/v3-first-save.d.ts +0 -17
- package/dist-client/modeller/v3-first-save.js +0 -26
- package/dist-client/modeller/v3-first-save.js.map +0 -1
- package/dist-client/modeller/v3-gizmo.d.ts +0 -72
- package/dist-client/modeller/v3-gizmo.js +0 -111
- package/dist-client/modeller/v3-gizmo.js.map +0 -1
- package/dist-client/modeller/v3-help.d.ts +0 -18
- package/dist-client/modeller/v3-help.js +0 -37
- package/dist-client/modeller/v3-help.js.map +0 -1
- package/dist-client/modeller/v3-joint-drag.d.ts +0 -19
- package/dist-client/modeller/v3-joint-drag.js +0 -97
- package/dist-client/modeller/v3-joint-drag.js.map +0 -1
- package/dist-client/modeller/v3-joint-fan.d.ts +0 -9
- package/dist-client/modeller/v3-joint-fan.js +0 -276
- package/dist-client/modeller/v3-joint-fan.js.map +0 -1
- package/dist-client/modeller/v3-keys.d.ts +0 -22
- package/dist-client/modeller/v3-keys.js +0 -26
- package/dist-client/modeller/v3-keys.js.map +0 -1
- package/dist-client/modeller/v3-links.d.ts +0 -267
- package/dist-client/modeller/v3-links.js +0 -480
- package/dist-client/modeller/v3-links.js.map +0 -1
- package/dist-client/modeller/v3-live.d.ts +0 -37
- package/dist-client/modeller/v3-live.js +0 -68
- package/dist-client/modeller/v3-live.js.map +0 -1
- package/dist-client/modeller/v3-maturity.d.ts +0 -120
- package/dist-client/modeller/v3-maturity.js +0 -313
- package/dist-client/modeller/v3-maturity.js.map +0 -1
- package/dist-client/modeller/v3-occupancy.d.ts +0 -18
- package/dist-client/modeller/v3-occupancy.js +0 -24
- package/dist-client/modeller/v3-occupancy.js.map +0 -1
- package/dist-client/modeller/v3-palette.d.ts +0 -7
- package/dist-client/modeller/v3-palette.js +0 -46
- package/dist-client/modeller/v3-palette.js.map +0 -1
- package/dist-client/modeller/v3-preview-model.d.ts +0 -47
- package/dist-client/modeller/v3-preview-model.js +0 -68
- package/dist-client/modeller/v3-preview-model.js.map +0 -1
- package/dist-client/modeller/v3-product-session.d.ts +0 -510
- package/dist-client/modeller/v3-product-session.js +0 -157
- package/dist-client/modeller/v3-product-session.js.map +0 -1
- package/dist-client/modeller/v3-recipe-source.d.ts +0 -8
- package/dist-client/modeller/v3-recipe-source.js +0 -14
- package/dist-client/modeller/v3-recipe-source.js.map +0 -1
- package/dist-client/modeller/v3-recipes.d.ts +0 -37
- package/dist-client/modeller/v3-recipes.js +0 -103
- package/dist-client/modeller/v3-recipes.js.map +0 -1
- package/dist-client/modeller/v3-refusals.d.ts +0 -68
- package/dist-client/modeller/v3-refusals.js +0 -142
- package/dist-client/modeller/v3-refusals.js.map +0 -1
- package/dist-client/modeller/v3-renderer.d.ts +0 -40
- package/dist-client/modeller/v3-renderer.js +0 -73
- package/dist-client/modeller/v3-renderer.js.map +0 -1
- package/dist-client/modeller/v3-stage-model.d.ts +0 -39
- package/dist-client/modeller/v3-stage-model.js +0 -147
- package/dist-client/modeller/v3-stage-model.js.map +0 -1
- package/dist-client/modeller/v3-thumbnail.d.ts +0 -3
- package/dist-client/modeller/v3-thumbnail.js +0 -75
- package/dist-client/modeller/v3-thumbnail.js.map +0 -1
- package/dist-client/pages/figure-v3-modeller-page.d.ts +0 -102
- package/dist-client/pages/figure-v3-modeller-page.js +0 -548
- package/dist-client/pages/figure-v3-modeller-page.js.map +0 -1
- package/dist-client/tsconfig.chk.tsbuildinfo +0 -1
- package/dist-client/tsconfig.fui.tsbuildinfo +0 -1
- package/dist-client/tsconfig.scratch-fm.tsbuildinfo +0 -1
|
@@ -1,399 +0,0 @@
|
|
|
1
|
-
import { __decorate, __metadata } from "tslib";
|
|
2
|
-
import '@material/web/icon/icon.js';
|
|
3
|
-
import '@operato/markdown';
|
|
4
|
-
import { css, html, LitElement, nothing } from 'lit';
|
|
5
|
-
import { customElement, property, state } from 'lit/decorators.js';
|
|
6
|
-
import { i18next, localize } from '@operato/i18n';
|
|
7
|
-
import { ScrollbarStyles } from '@operato/styles';
|
|
8
|
-
import { describeV3Recipe } from '@hatiolab/figure-model';
|
|
9
|
-
import { recipeFieldOf, recipeReady, recipeValueOf, recipeWord, recipeWorkings, recipesMatching } from './v3-recipes.js';
|
|
10
|
-
/**
|
|
11
|
-
* The recipe catalog (ADR-0095): the templates the product ships, by category, found by words, each told in full --
|
|
12
|
-
* what it puts in, how many parts, how they move, what each value does, and how to use it -- and put onto the chosen
|
|
13
|
-
* part in one step. The numbers and the ways of moving are worked out from the recipe (`describeV3Recipe`), so they say
|
|
14
|
-
* what it does; only the descriptions and the guide are written.
|
|
15
|
-
*/
|
|
16
|
-
let FigureV3RecipeCatalog = class FigureV3RecipeCatalog extends localize(i18next)(LitElement) {
|
|
17
|
-
constructor() {
|
|
18
|
-
super(...arguments);
|
|
19
|
-
this.templates = [];
|
|
20
|
-
/** The part it would be put onto. */
|
|
21
|
-
this.selected = '';
|
|
22
|
-
this.locked = false;
|
|
23
|
-
/** Why the last one put in was refused, in the kernel's words. */
|
|
24
|
-
this.error = '';
|
|
25
|
-
this.category = '';
|
|
26
|
-
this.query = '';
|
|
27
|
-
this.chosen = '';
|
|
28
|
-
this.values = {};
|
|
29
|
-
/*
|
|
30
|
-
The guide as a page \`ox-markdown\` can read: it renders what its src points to, not text, and given the text it
|
|
31
|
-
fetched it as a path and drew the app's own page in its place (seen on :3300, 2026-09-26). A blob of type
|
|
32
|
-
text/markdown is read as markdown.
|
|
33
|
-
*/
|
|
34
|
-
this.guide = '';
|
|
35
|
-
}
|
|
36
|
-
static { this.styles = [
|
|
37
|
-
ScrollbarStyles,
|
|
38
|
-
css `
|
|
39
|
-
:host {
|
|
40
|
-
position: fixed;
|
|
41
|
-
inset: 0;
|
|
42
|
-
z-index: 20;
|
|
43
|
-
display: grid;
|
|
44
|
-
place-items: center;
|
|
45
|
-
background: color-mix(in srgb, var(--md-sys-color-scrim, #000) 32%, transparent);
|
|
46
|
-
font-size: 0.82rem;
|
|
47
|
-
color: var(--md-sys-color-on-surface);
|
|
48
|
-
}
|
|
49
|
-
div[panel] {
|
|
50
|
-
display: grid;
|
|
51
|
-
grid-template-rows: auto 1fr;
|
|
52
|
-
width: min(1100px, calc(100vw - 32px));
|
|
53
|
-
height: min(720px, calc(100vh - 32px));
|
|
54
|
-
background: var(--md-sys-color-surface);
|
|
55
|
-
border-radius: 12px;
|
|
56
|
-
overflow: hidden;
|
|
57
|
-
box-shadow: 0 8px 28px rgba(0, 0, 0, 0.28);
|
|
58
|
-
}
|
|
59
|
-
header {
|
|
60
|
-
display: flex;
|
|
61
|
-
align-items: center;
|
|
62
|
-
gap: 8px;
|
|
63
|
-
padding: 8px 12px;
|
|
64
|
-
border-bottom: 1px solid var(--md-sys-color-outline-variant);
|
|
65
|
-
}
|
|
66
|
-
header h2 {
|
|
67
|
-
margin: 0;
|
|
68
|
-
font-size: var(--ui-t-title, 16px);
|
|
69
|
-
flex: 1;
|
|
70
|
-
}
|
|
71
|
-
header input {
|
|
72
|
-
width: 220px;
|
|
73
|
-
padding: 4px 8px;
|
|
74
|
-
font: inherit;
|
|
75
|
-
}
|
|
76
|
-
button[close] {
|
|
77
|
-
display: inline-grid;
|
|
78
|
-
place-items: center;
|
|
79
|
-
width: 32px;
|
|
80
|
-
height: 32px;
|
|
81
|
-
border: none;
|
|
82
|
-
border-radius: 8px;
|
|
83
|
-
background: none;
|
|
84
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
85
|
-
cursor: pointer;
|
|
86
|
-
}
|
|
87
|
-
div[body] {
|
|
88
|
-
display: grid;
|
|
89
|
-
grid-template-columns: 170px minmax(0, 1fr) minmax(300px, 380px);
|
|
90
|
-
min-height: 0;
|
|
91
|
-
}
|
|
92
|
-
@media (max-width: 760px) {
|
|
93
|
-
div[body] {
|
|
94
|
-
grid-template-columns: 1fr;
|
|
95
|
-
overflow: auto;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
nav,
|
|
99
|
-
section[list],
|
|
100
|
-
section[detail] {
|
|
101
|
-
overflow: auto;
|
|
102
|
-
min-height: 0;
|
|
103
|
-
padding: 8px;
|
|
104
|
-
}
|
|
105
|
-
nav {
|
|
106
|
-
border-right: 1px solid var(--md-sys-color-outline-variant);
|
|
107
|
-
}
|
|
108
|
-
section[detail] {
|
|
109
|
-
border-left: 1px solid var(--md-sys-color-outline-variant);
|
|
110
|
-
display: grid;
|
|
111
|
-
gap: 10px;
|
|
112
|
-
align-content: start;
|
|
113
|
-
}
|
|
114
|
-
button[category] {
|
|
115
|
-
display: flex;
|
|
116
|
-
justify-content: space-between;
|
|
117
|
-
width: 100%;
|
|
118
|
-
padding: 6px 8px;
|
|
119
|
-
font: inherit;
|
|
120
|
-
color: inherit;
|
|
121
|
-
background: none;
|
|
122
|
-
border: none;
|
|
123
|
-
border-radius: 6px;
|
|
124
|
-
text-align: left;
|
|
125
|
-
cursor: pointer;
|
|
126
|
-
}
|
|
127
|
-
button[category][on],
|
|
128
|
-
button[card][on] {
|
|
129
|
-
background: var(--md-sys-color-secondary-container);
|
|
130
|
-
color: var(--md-sys-color-on-secondary-container);
|
|
131
|
-
}
|
|
132
|
-
section[list] {
|
|
133
|
-
display: grid;
|
|
134
|
-
grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
|
|
135
|
-
gap: 8px;
|
|
136
|
-
align-content: start;
|
|
137
|
-
}
|
|
138
|
-
button[card] {
|
|
139
|
-
display: grid;
|
|
140
|
-
gap: 4px;
|
|
141
|
-
padding: 8px;
|
|
142
|
-
font: inherit;
|
|
143
|
-
color: inherit;
|
|
144
|
-
text-align: left;
|
|
145
|
-
background: none;
|
|
146
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
147
|
-
border-radius: 8px;
|
|
148
|
-
cursor: pointer;
|
|
149
|
-
}
|
|
150
|
-
button[card] img {
|
|
151
|
-
width: 100%;
|
|
152
|
-
aspect-ratio: 4 / 3;
|
|
153
|
-
object-fit: contain;
|
|
154
|
-
background: var(--md-sys-color-surface-container);
|
|
155
|
-
border-radius: 4px;
|
|
156
|
-
}
|
|
157
|
-
button[card] small,
|
|
158
|
-
p[muted] {
|
|
159
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
160
|
-
}
|
|
161
|
-
h3 {
|
|
162
|
-
margin: 0;
|
|
163
|
-
font-size: var(--ui-t-body, 14px);
|
|
164
|
-
}
|
|
165
|
-
p {
|
|
166
|
-
margin: 0;
|
|
167
|
-
line-height: 1.5;
|
|
168
|
-
}
|
|
169
|
-
ul {
|
|
170
|
-
margin: 0;
|
|
171
|
-
padding-left: 18px;
|
|
172
|
-
line-height: 1.6;
|
|
173
|
-
}
|
|
174
|
-
table {
|
|
175
|
-
border-collapse: collapse;
|
|
176
|
-
width: 100%;
|
|
177
|
-
}
|
|
178
|
-
th,
|
|
179
|
-
td {
|
|
180
|
-
text-align: left;
|
|
181
|
-
vertical-align: top;
|
|
182
|
-
padding: 3px 4px;
|
|
183
|
-
border-bottom: 1px solid var(--md-sys-color-outline-variant);
|
|
184
|
-
}
|
|
185
|
-
td small {
|
|
186
|
-
display: block;
|
|
187
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
188
|
-
}
|
|
189
|
-
div[form] {
|
|
190
|
-
display: grid;
|
|
191
|
-
gap: 6px;
|
|
192
|
-
padding: 8px;
|
|
193
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
194
|
-
border-radius: 8px;
|
|
195
|
-
}
|
|
196
|
-
div[form] label {
|
|
197
|
-
display: grid;
|
|
198
|
-
gap: 2px;
|
|
199
|
-
}
|
|
200
|
-
div[form] label[toggle] {
|
|
201
|
-
display: flex;
|
|
202
|
-
align-items: center;
|
|
203
|
-
gap: 6px;
|
|
204
|
-
}
|
|
205
|
-
div[form] input,
|
|
206
|
-
div[form] select {
|
|
207
|
-
font: inherit;
|
|
208
|
-
min-width: 0;
|
|
209
|
-
}
|
|
210
|
-
button[insert] {
|
|
211
|
-
justify-self: start;
|
|
212
|
-
display: inline-flex;
|
|
213
|
-
align-items: center;
|
|
214
|
-
gap: 4px;
|
|
215
|
-
padding: 6px 14px;
|
|
216
|
-
font: inherit;
|
|
217
|
-
white-space: nowrap;
|
|
218
|
-
color: var(--md-sys-color-on-primary);
|
|
219
|
-
background: var(--md-sys-color-primary);
|
|
220
|
-
border: none;
|
|
221
|
-
border-radius: 999em;
|
|
222
|
-
cursor: pointer;
|
|
223
|
-
}
|
|
224
|
-
button[insert]:disabled {
|
|
225
|
-
opacity: 0.38;
|
|
226
|
-
cursor: default;
|
|
227
|
-
}
|
|
228
|
-
p[role='alert'] {
|
|
229
|
-
padding: 6px;
|
|
230
|
-
white-space: pre-wrap;
|
|
231
|
-
color: var(--md-sys-color-on-error-container);
|
|
232
|
-
background: var(--md-sys-color-error-container);
|
|
233
|
-
border-radius: 6px;
|
|
234
|
-
}
|
|
235
|
-
ox-markdown {
|
|
236
|
-
display: block;
|
|
237
|
-
}
|
|
238
|
-
`
|
|
239
|
-
]; }
|
|
240
|
-
set guideText(text) {
|
|
241
|
-
if (this.guide)
|
|
242
|
-
URL.revokeObjectURL(this.guide);
|
|
243
|
-
this.guide = text ? URL.createObjectURL(new Blob([text], { type: 'text/markdown' })) : '';
|
|
244
|
-
}
|
|
245
|
-
disconnectedCallback() {
|
|
246
|
-
super.disconnectedCallback();
|
|
247
|
-
this.guideText = '';
|
|
248
|
-
}
|
|
249
|
-
render() {
|
|
250
|
-
const language = i18next.language || 'en';
|
|
251
|
-
const categories = [...new Set(this.templates.map(t => t.category))].sort();
|
|
252
|
-
const shown = recipesMatching(this.templates, this.category, this.query);
|
|
253
|
-
const chosen = this.templates.find(t => t.name === this.chosen) ?? shown[0];
|
|
254
|
-
return html `<div panel role="dialog" aria-modal="true" aria-label=${i18next.t('figure.label.recipe-catalog')}>
|
|
255
|
-
<header>
|
|
256
|
-
<h2>${i18next.t('figure.label.recipe-catalog')}</h2>
|
|
257
|
-
<input search type="search" placeholder=${i18next.t('figure.text.recipe-search')} .value=${this.query} @input=${(e) => (this.query = e.target.value)} />
|
|
258
|
-
<button close aria-label=${i18next.t('figure.button.close')} @click=${() => this.dispatchEvent(new CustomEvent('close-catalog', { bubbles: true, composed: true }))}>
|
|
259
|
-
<md-icon>close</md-icon>
|
|
260
|
-
</button>
|
|
261
|
-
</header>
|
|
262
|
-
<div body>
|
|
263
|
-
<nav>
|
|
264
|
-
<button category ?on=${!this.category} @click=${() => (this.category = '')}>
|
|
265
|
-
<span>${i18next.t('figure.label.recipe-all')}</span><small>${this.templates.length}</small>
|
|
266
|
-
</button>
|
|
267
|
-
${categories.map(c => html `<button category=${c} ?on=${this.category === c} @click=${() => (this.category = c)}>
|
|
268
|
-
<span>${i18next.t('figure.label.recipe-category-' + c)}</span><small>${this.templates.filter(t => t.category === c).length}</small>
|
|
269
|
-
</button>`)}
|
|
270
|
-
</nav>
|
|
271
|
-
<section list>
|
|
272
|
-
${shown.map(t => html `<button card=${t.name} ?on=${t.name === chosen?.name} @click=${() => this.choose(t)}>
|
|
273
|
-
${t.hasThumbnail && this.thumbnailOf ? html `<img alt="" loading="lazy" src=${this.thumbnailOf(t.name)} />` : nothing}
|
|
274
|
-
<b>${t.title}</b>
|
|
275
|
-
<small>${t.description}</small>
|
|
276
|
-
</button>`)}
|
|
277
|
-
</section>
|
|
278
|
-
<section detail>${chosen ? this.renderDetail(chosen, language) : nothing}</section>
|
|
279
|
-
</div>
|
|
280
|
-
</div>`;
|
|
281
|
-
}
|
|
282
|
-
choose(t) {
|
|
283
|
-
if (this.chosen === t.name)
|
|
284
|
-
return;
|
|
285
|
-
this.chosen = t.name;
|
|
286
|
-
this.values = Object.fromEntries(t.recipe.params.map(p => [p.name, p.default]));
|
|
287
|
-
this.guideText = '';
|
|
288
|
-
this.guideOf?.(t.name)
|
|
289
|
-
.then(text => this.chosen === t.name && (this.guideText = text))
|
|
290
|
-
.catch(() => { });
|
|
291
|
-
}
|
|
292
|
-
willUpdate() {
|
|
293
|
-
/*
|
|
294
|
-
The first card shown is chosen while none of those shown is, so the detail is never empty and never of a card the
|
|
295
|
-
search or the category has taken away (the air cylinder stayed told under a search for rollers, :3300, 2026-09-26).
|
|
296
|
-
*/
|
|
297
|
-
const shown = recipesMatching(this.templates, this.category, this.query);
|
|
298
|
-
if (!shown.some(t => t.name === this.chosen) && shown[0])
|
|
299
|
-
this.choose(shown[0]);
|
|
300
|
-
}
|
|
301
|
-
renderDetail(t, language) {
|
|
302
|
-
const d = describeV3Recipe(t.recipe);
|
|
303
|
-
const count = d.parts.min === d.parts.max ? String(d.parts.min) : `${d.parts.min}–${d.parts.max}`;
|
|
304
|
-
const ready = recipeReady(t.recipe, this.selected);
|
|
305
|
-
return html `
|
|
306
|
-
<h3>${t.title}</h3>
|
|
307
|
-
<p>${t.description}</p>
|
|
308
|
-
<div>
|
|
309
|
-
<h3>${i18next.t('figure.label.recipe-adds')}</h3>
|
|
310
|
-
<ul>
|
|
311
|
-
<li parts=${count}>${i18next.t("figure.text.recipe-parts", { parts: count })}</li>
|
|
312
|
-
${recipeWorkings(t.recipe).map(line => html `<li>${i18next.t(line.key, line.words)}</li>`)}
|
|
313
|
-
<li>${i18next.t(t.recipe.target === 'part' ? 'figure.text.recipe-onto-chosen' : 'figure.text.recipe-onto-figure')}</li>
|
|
314
|
-
</ul>
|
|
315
|
-
</div>
|
|
316
|
-
${t.recipe.params.length ? this.renderForm(t.recipe, language) : nothing}
|
|
317
|
-
${this.error ? html `<p role="alert">${this.error}</p>` : nothing}
|
|
318
|
-
${ready ? nothing : html `<p muted>${i18next.t('figure.text.recipe-needs-a-part')}</p>`}
|
|
319
|
-
<button insert ?disabled=${this.locked || !ready} @click=${() => this.dispatchEvent(new CustomEvent('insert-recipe', { detail: { recipe: t.recipe, values: this.values }, bubbles: true, composed: true }))}>
|
|
320
|
-
<md-icon>add</md-icon>${this.selected && t.recipe.target === 'part' ? i18next.t('figure.button.insert-recipe-onto', { part: this.selected }) : i18next.t('figure.button.insert-recipe')}
|
|
321
|
-
</button>
|
|
322
|
-
${this.guide ? html `<ox-markdown .src=${this.guide}></ox-markdown>` : nothing}
|
|
323
|
-
`;
|
|
324
|
-
}
|
|
325
|
-
/** Each value: its name, what it does, and the field to set it -- a share typed as a percentage. */
|
|
326
|
-
renderForm(recipe, language) {
|
|
327
|
-
const set = (name, value) => (this.values = { ...this.values, [name]: value });
|
|
328
|
-
return html `<div form>
|
|
329
|
-
<h3>${i18next.t('figure.label.recipe-values')}</h3>
|
|
330
|
-
${recipe.params.map(param => {
|
|
331
|
-
const label = recipeWord(param.label, language) || param.name;
|
|
332
|
-
const hint = recipeWord(param.hint, language);
|
|
333
|
-
const value = this.values[param.name] ?? param.default;
|
|
334
|
-
const help = hint ? html `<small>${hint}</small>` : nothing;
|
|
335
|
-
if (param.kind === 'flag')
|
|
336
|
-
return html `<label toggle><input type="checkbox" param=${param.name} .checked=${value === true} @change=${(e) => set(param.name, e.target.checked)} />${label}</label>${help}`;
|
|
337
|
-
if (param.kind === 'choice' || param.kind === 'face')
|
|
338
|
-
return html `<label><span>${label}</span>
|
|
339
|
-
<select param=${param.name} @change=${(e) => set(param.name, recipeValueOf(param, e.target.value))}>
|
|
340
|
-
${(param.options ?? []).map(o => html `<option value=${String(o)} ?selected=${o === value}>${String(o)}</option>`)}
|
|
341
|
-
</select></label
|
|
342
|
-
>${help}`;
|
|
343
|
-
const range = param.kind === 'ratio' ? `${recipeFieldOf(param, param.min ?? 0)}–${recipeFieldOf(param, param.max ?? 1)} %` : `${param.min ?? ''}–${param.max ?? ''} mm`;
|
|
344
|
-
return html `<label><span>${label} (${range})</span>
|
|
345
|
-
<input type="number" step="any" param=${param.name} .value=${recipeFieldOf(param, value)} @change=${(e) => set(param.name, recipeValueOf(param, e.target.value))} /></label
|
|
346
|
-
>${help}`;
|
|
347
|
-
})}
|
|
348
|
-
</div>`;
|
|
349
|
-
}
|
|
350
|
-
};
|
|
351
|
-
__decorate([
|
|
352
|
-
property({ attribute: false }),
|
|
353
|
-
__metadata("design:type", Array)
|
|
354
|
-
], FigureV3RecipeCatalog.prototype, "templates", void 0);
|
|
355
|
-
__decorate([
|
|
356
|
-
property({ type: String }),
|
|
357
|
-
__metadata("design:type", Object)
|
|
358
|
-
], FigureV3RecipeCatalog.prototype, "selected", void 0);
|
|
359
|
-
__decorate([
|
|
360
|
-
property({ type: Boolean }),
|
|
361
|
-
__metadata("design:type", Object)
|
|
362
|
-
], FigureV3RecipeCatalog.prototype, "locked", void 0);
|
|
363
|
-
__decorate([
|
|
364
|
-
property({ type: String }),
|
|
365
|
-
__metadata("design:type", Object)
|
|
366
|
-
], FigureV3RecipeCatalog.prototype, "error", void 0);
|
|
367
|
-
__decorate([
|
|
368
|
-
property({ attribute: false }),
|
|
369
|
-
__metadata("design:type", Function)
|
|
370
|
-
], FigureV3RecipeCatalog.prototype, "guideOf", void 0);
|
|
371
|
-
__decorate([
|
|
372
|
-
property({ attribute: false }),
|
|
373
|
-
__metadata("design:type", Function)
|
|
374
|
-
], FigureV3RecipeCatalog.prototype, "thumbnailOf", void 0);
|
|
375
|
-
__decorate([
|
|
376
|
-
state(),
|
|
377
|
-
__metadata("design:type", Object)
|
|
378
|
-
], FigureV3RecipeCatalog.prototype, "category", void 0);
|
|
379
|
-
__decorate([
|
|
380
|
-
state(),
|
|
381
|
-
__metadata("design:type", Object)
|
|
382
|
-
], FigureV3RecipeCatalog.prototype, "query", void 0);
|
|
383
|
-
__decorate([
|
|
384
|
-
state(),
|
|
385
|
-
__metadata("design:type", Object)
|
|
386
|
-
], FigureV3RecipeCatalog.prototype, "chosen", void 0);
|
|
387
|
-
__decorate([
|
|
388
|
-
state(),
|
|
389
|
-
__metadata("design:type", Object)
|
|
390
|
-
], FigureV3RecipeCatalog.prototype, "values", void 0);
|
|
391
|
-
__decorate([
|
|
392
|
-
state(),
|
|
393
|
-
__metadata("design:type", Object)
|
|
394
|
-
], FigureV3RecipeCatalog.prototype, "guide", void 0);
|
|
395
|
-
FigureV3RecipeCatalog = __decorate([
|
|
396
|
-
customElement('figure-v3-recipe-catalog')
|
|
397
|
-
], FigureV3RecipeCatalog);
|
|
398
|
-
export { FigureV3RecipeCatalog };
|
|
399
|
-
//# sourceMappingURL=figure-v3-recipe-catalog.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"figure-v3-recipe-catalog.js","sourceRoot":"","sources":["../../client/modeller/figure-v3-recipe-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/markdown'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { describeV3Recipe } from '@hatiolab/figure-model'\nimport type { V3Recipe, V3RecipeValue } from '@hatiolab/figure-model'\n\nimport { recipeFieldOf, recipeReady, recipeValueOf, recipeWord, recipeWorkings, recipesMatching, type RecipeTemplate } from './v3-recipes.js'\n\n/**\n * The recipe catalog (ADR-0095): the templates the product ships, by category, found by words, each told in full --\n * what it puts in, how many parts, how they move, what each value does, and how to use it -- and put onto the chosen\n * part in one step. The numbers and the ways of moving are worked out from the recipe (`describeV3Recipe`), so they say\n * what it does; only the descriptions and the guide are written.\n */\n@customElement('figure-v3-recipe-catalog')\nexport class FigureV3RecipeCatalog extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n position: fixed;\n inset: 0;\n z-index: 20;\n display: grid;\n place-items: center;\n background: color-mix(in srgb, var(--md-sys-color-scrim, #000) 32%, transparent);\n font-size: 0.82rem;\n color: var(--md-sys-color-on-surface);\n }\n div[panel] {\n display: grid;\n grid-template-rows: auto 1fr;\n width: min(1100px, calc(100vw - 32px));\n height: min(720px, calc(100vh - 32px));\n background: var(--md-sys-color-surface);\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 8px 28px rgba(0, 0, 0, 0.28);\n }\n header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n header h2 {\n margin: 0;\n font-size: var(--ui-t-title, 16px);\n flex: 1;\n }\n header input {\n width: 220px;\n padding: 4px 8px;\n font: inherit;\n }\n button[close] {\n display: inline-grid;\n place-items: center;\n width: 32px;\n height: 32px;\n border: none;\n border-radius: 8px;\n background: none;\n color: var(--md-sys-color-on-surface-variant);\n cursor: pointer;\n }\n div[body] {\n display: grid;\n grid-template-columns: 170px minmax(0, 1fr) minmax(300px, 380px);\n min-height: 0;\n }\n @media (max-width: 760px) {\n div[body] {\n grid-template-columns: 1fr;\n overflow: auto;\n }\n }\n nav,\n section[list],\n section[detail] {\n overflow: auto;\n min-height: 0;\n padding: 8px;\n }\n nav {\n border-right: 1px solid var(--md-sys-color-outline-variant);\n }\n section[detail] {\n border-left: 1px solid var(--md-sys-color-outline-variant);\n display: grid;\n gap: 10px;\n align-content: start;\n }\n button[category] {\n display: flex;\n justify-content: space-between;\n width: 100%;\n padding: 6px 8px;\n font: inherit;\n color: inherit;\n background: none;\n border: none;\n border-radius: 6px;\n text-align: left;\n cursor: pointer;\n }\n button[category][on],\n button[card][on] {\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n section[list] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));\n gap: 8px;\n align-content: start;\n }\n button[card] {\n display: grid;\n gap: 4px;\n padding: 8px;\n font: inherit;\n color: inherit;\n text-align: left;\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n cursor: pointer;\n }\n button[card] img {\n width: 100%;\n aspect-ratio: 4 / 3;\n object-fit: contain;\n background: var(--md-sys-color-surface-container);\n border-radius: 4px;\n }\n button[card] small,\n p[muted] {\n color: var(--md-sys-color-on-surface-variant);\n }\n h3 {\n margin: 0;\n font-size: var(--ui-t-body, 14px);\n }\n p {\n margin: 0;\n line-height: 1.5;\n }\n ul {\n margin: 0;\n padding-left: 18px;\n line-height: 1.6;\n }\n table {\n border-collapse: collapse;\n width: 100%;\n }\n th,\n td {\n text-align: left;\n vertical-align: top;\n padding: 3px 4px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n td small {\n display: block;\n color: var(--md-sys-color-on-surface-variant);\n }\n div[form] {\n display: grid;\n gap: 6px;\n padding: 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n }\n div[form] label {\n display: grid;\n gap: 2px;\n }\n div[form] label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n div[form] input,\n div[form] select {\n font: inherit;\n min-width: 0;\n }\n button[insert] {\n justify-self: start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 6px 14px;\n font: inherit;\n white-space: nowrap;\n color: var(--md-sys-color-on-primary);\n background: var(--md-sys-color-primary);\n border: none;\n border-radius: 999em;\n cursor: pointer;\n }\n button[insert]:disabled {\n opacity: 0.38;\n cursor: default;\n }\n p[role='alert'] {\n padding: 6px;\n white-space: pre-wrap;\n color: var(--md-sys-color-on-error-container);\n background: var(--md-sys-color-error-container);\n border-radius: 6px;\n }\n ox-markdown {\n display: block;\n }\n `\n ]\n\n @property({ attribute: false }) templates: RecipeTemplate[] = []\n /** The part it would be put onto. */\n @property({ type: String }) selected = ''\n @property({ type: Boolean }) locked = false\n /** Why the last one put in was refused, in the kernel's words. */\n @property({ type: String }) error = ''\n /** Reads a template's guide; absent, no guide is shown. */\n @property({ attribute: false }) guideOf?: (name: string) => Promise<string>\n /** Where a template's thumbnail is read from; absent, cards show no picture. */\n @property({ attribute: false }) thumbnailOf?: (name: string) => string\n\n @state() private category = ''\n @state() private query = ''\n @state() private chosen = ''\n @state() private values: Record<string, V3RecipeValue> = {}\n /*\n The guide as a page \\`ox-markdown\\` can read: it renders what its src points to, not text, and given the text it\n fetched it as a path and drew the app's own page in its place (seen on :3300, 2026-09-26). A blob of type\n text/markdown is read as markdown.\n */\n @state() private guide = ''\n\n private set guideText(text: string) {\n if (this.guide) URL.revokeObjectURL(this.guide)\n this.guide = text ? URL.createObjectURL(new Blob([text], { type: 'text/markdown' })) : ''\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.guideText = ''\n }\n\n render() {\n const language = i18next.language || 'en'\n const categories = [...new Set(this.templates.map(t => t.category))].sort()\n const shown = recipesMatching(this.templates, this.category, this.query)\n const chosen = this.templates.find(t => t.name === this.chosen) ?? shown[0]\n return html`<div panel role=\"dialog\" aria-modal=\"true\" aria-label=${i18next.t('figure.label.recipe-catalog')}>\n <header>\n <h2>${i18next.t('figure.label.recipe-catalog')}</h2>\n <input search type=\"search\" placeholder=${i18next.t('figure.text.recipe-search')} .value=${this.query} @input=${(e: Event) => (this.query = (e.target as HTMLInputElement).value)} />\n <button close aria-label=${i18next.t('figure.button.close')} @click=${() => this.dispatchEvent(new CustomEvent('close-catalog', { bubbles: true, composed: true }))}>\n <md-icon>close</md-icon>\n </button>\n </header>\n <div body>\n <nav>\n <button category ?on=${!this.category} @click=${() => (this.category = '')}>\n <span>${i18next.t('figure.label.recipe-all')}</span><small>${this.templates.length}</small>\n </button>\n ${categories.map(\n c => html`<button category=${c} ?on=${this.category === c} @click=${() => (this.category = c)}>\n <span>${i18next.t('figure.label.recipe-category-' + c)}</span><small>${this.templates.filter(t => t.category === c).length}</small>\n </button>`\n )}\n </nav>\n <section list>\n ${shown.map(\n t => html`<button card=${t.name} ?on=${t.name === chosen?.name} @click=${() => this.choose(t)}>\n ${t.hasThumbnail && this.thumbnailOf ? html`<img alt=\"\" loading=\"lazy\" src=${this.thumbnailOf(t.name)} />` : nothing}\n <b>${t.title}</b>\n <small>${t.description}</small>\n </button>`\n )}\n </section>\n <section detail>${chosen ? this.renderDetail(chosen, language) : nothing}</section>\n </div>\n </div>`\n }\n\n private choose(t: RecipeTemplate) {\n if (this.chosen === t.name) return\n this.chosen = t.name\n this.values = Object.fromEntries(t.recipe.params.map(p => [p.name, p.default]))\n this.guideText = ''\n this.guideOf?.(t.name)\n .then(text => this.chosen === t.name && (this.guideText = text))\n .catch(() => {})\n }\n\n protected willUpdate() {\n /*\n The first card shown is chosen while none of those shown is, so the detail is never empty and never of a card the\n search or the category has taken away (the air cylinder stayed told under a search for rollers, :3300, 2026-09-26).\n */\n const shown = recipesMatching(this.templates, this.category, this.query)\n if (!shown.some(t => t.name === this.chosen) && shown[0]) this.choose(shown[0])\n }\n\n private renderDetail(t: RecipeTemplate, language: string) {\n const d = describeV3Recipe(t.recipe)\n const count = d.parts.min === d.parts.max ? String(d.parts.min) : `${d.parts.min}–${d.parts.max}`\n const ready = recipeReady(t.recipe, this.selected)\n return html`\n <h3>${t.title}</h3>\n <p>${t.description}</p>\n <div>\n <h3>${i18next.t('figure.label.recipe-adds')}</h3>\n <ul>\n <li parts=${count}>${i18next.t(\"figure.text.recipe-parts\", { parts: count })}</li>\n ${recipeWorkings(t.recipe).map(line => html`<li>${i18next.t(line.key, line.words)}</li>`)}\n <li>${i18next.t(t.recipe.target === 'part' ? 'figure.text.recipe-onto-chosen' : 'figure.text.recipe-onto-figure')}</li>\n </ul>\n </div>\n ${t.recipe.params.length ? this.renderForm(t.recipe, language) : nothing}\n ${this.error ? html`<p role=\"alert\">${this.error}</p>` : nothing}\n ${ready ? nothing : html`<p muted>${i18next.t('figure.text.recipe-needs-a-part')}</p>`}\n <button insert ?disabled=${this.locked || !ready} @click=${() => this.dispatchEvent(new CustomEvent('insert-recipe', { detail: { recipe: t.recipe, values: this.values }, bubbles: true, composed: true }))}>\n <md-icon>add</md-icon>${this.selected && t.recipe.target === 'part' ? i18next.t('figure.button.insert-recipe-onto', { part: this.selected }) : i18next.t('figure.button.insert-recipe')}\n </button>\n ${this.guide ? html`<ox-markdown .src=${this.guide}></ox-markdown>` : nothing}\n `\n }\n\n /** Each value: its name, what it does, and the field to set it -- a share typed as a percentage. */\n private renderForm(recipe: V3Recipe, language: string) {\n const set = (name: string, value: V3RecipeValue) => (this.values = { ...this.values, [name]: value })\n return html`<div form>\n <h3>${i18next.t('figure.label.recipe-values')}</h3>\n ${recipe.params.map(param => {\n const label = recipeWord(param.label, language) || param.name\n const hint = recipeWord(param.hint, language)\n const value = this.values[param.name] ?? param.default\n const help = hint ? html`<small>${hint}</small>` : nothing\n if (param.kind === 'flag')\n return html`<label toggle><input type=\"checkbox\" param=${param.name} .checked=${value === true} @change=${(e: Event) => set(param.name, (e.target as HTMLInputElement).checked)} />${label}</label>${help}`\n if (param.kind === 'choice' || param.kind === 'face')\n return html`<label><span>${label}</span>\n <select param=${param.name} @change=${(e: Event) => set(param.name, recipeValueOf(param, (e.target as HTMLSelectElement).value))}>\n ${(param.options ?? []).map(o => html`<option value=${String(o)} ?selected=${o === value}>${String(o)}</option>`)}\n </select></label\n >${help}`\n const range = param.kind === 'ratio' ? `${recipeFieldOf(param, param.min ?? 0)}–${recipeFieldOf(param, param.max ?? 1)} %` : `${param.min ?? ''}–${param.max ?? ''} mm`\n return html`<label><span>${label} (${range})</span>\n <input type=\"number\" step=\"any\" param=${param.name} .value=${recipeFieldOf(param, value)} @change=${(e: Event) => set(param.name, recipeValueOf(param, (e.target as HTMLInputElement).value))} /></label\n >${help}`\n })}\n </div>`\n }\n}\n"]}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import '@material/web/icon/icon.js';
|
|
2
|
-
import { LitElement } from 'lit';
|
|
3
|
-
/** How long an edit settles before the server is asked again. One question per pause, not one per keystroke. */
|
|
4
|
-
export declare const VERDICT_SETTLE_MS = 400;
|
|
5
|
-
declare const FigureV3Verdict_base: (new (...args: any[]) => LitElement) & typeof LitElement;
|
|
6
|
-
export declare class FigureV3Verdict extends FigureV3Verdict_base {
|
|
7
|
-
static styles: import("lit").CSSResult[];
|
|
8
|
-
/** The source being edited, serialised. Every change of it is a new question. */
|
|
9
|
-
source?: string;
|
|
10
|
-
/** The saved row, if any — the server reads its type and last release from it. */
|
|
11
|
-
figureId?: string;
|
|
12
|
-
/** Changing the type changes the verdict (a temporary type is refused), so it is a reason to ask again. */
|
|
13
|
-
figureType?: string;
|
|
14
|
-
/** The report over the source being edited. Absent when nothing is drawn, or the format refuses the source. */
|
|
15
|
-
private report?;
|
|
16
|
-
/** Bodies in the asset, drawn or hidden. With none there is nothing to fit the space to, so the button is not offered. */
|
|
17
|
-
private bodies;
|
|
18
|
-
/** Whether the trend chart is open at its own size. */
|
|
19
|
-
private expanded;
|
|
20
|
-
private inspection?;
|
|
21
|
-
private failure;
|
|
22
|
-
private asking;
|
|
23
|
-
private timer?;
|
|
24
|
-
/** Answers can come back out of order; only the newest question's answer is shown. */
|
|
25
|
-
private asked;
|
|
26
|
-
disconnectedCallback(): void;
|
|
27
|
-
updated(changes: Map<string, unknown>): void;
|
|
28
|
-
private measure;
|
|
29
|
-
private schedule;
|
|
30
|
-
private ask;
|
|
31
|
-
render(): import("lit-html").TemplateResult<1>;
|
|
32
|
-
/**
|
|
33
|
-
* The head — how many fit, with the grade beside it, the budget that decided it, the scale, and the basis.
|
|
34
|
-
*
|
|
35
|
-
* The count's denominator is measured (2026-09-18, Apple M5) and says so with the machine and the date; the
|
|
36
|
-
* triangle side is still the design document's target and says that.
|
|
37
|
-
*/
|
|
38
|
-
private renderVerdict;
|
|
39
|
-
/** A · B · C · D and where this figure stands, drawn from the bounds the grade is computed with. */
|
|
40
|
-
private renderGradeScale;
|
|
41
|
-
/**
|
|
42
|
-
* Maturity by axis — a radar of the measured axes, a line naming the unmeasured ones, and the list.
|
|
43
|
-
*
|
|
44
|
-
* Scale is left out of the list: it leads the tab, and the same number twice reads as two different things.
|
|
45
|
-
*/
|
|
46
|
-
private renderAxes;
|
|
47
|
-
/** The radar: rings at a third, two thirds and full, short names so the left edge is not cut. */
|
|
48
|
-
private renderRadar;
|
|
49
|
-
private renderAxis;
|
|
50
|
-
/** The budget bars. The one closest to its limit is coloured — it decided the grade. */
|
|
51
|
-
private renderBudgets;
|
|
52
|
-
private renderMetrics;
|
|
53
|
-
private renderCurve;
|
|
54
|
-
/**
|
|
55
|
-
* The trend at its own size: both axes logarithmic, the growing lines against the flat ones, and a
|
|
56
|
-
* legend with each line's value at the last count.
|
|
57
|
-
*/
|
|
58
|
-
private renderSheet;
|
|
59
|
-
private renderGate;
|
|
60
|
-
/** The same way out the release panel offers for the same two findings — declare the space from the parts. */
|
|
61
|
-
private actionsFor;
|
|
62
|
-
private fit;
|
|
63
|
-
}
|
|
64
|
-
export {};
|