@things-factory/figure-ui 10.1.153 → 10.1.155
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/client/modeller/canvas.ts +1 -1
- package/client/modeller/editor.ts +2 -2
- package/client/modeller/figure-capability-panel.ts +6 -24
- package/client/modeller/figure-carrier.ts +1 -1
- package/client/modeller/figure-clips.ts +1 -1
- package/client/modeller/figure-controls.ts +2 -2
- package/client/modeller/figure-face-mapping.ts +1 -1
- package/client/modeller/figure-links.ts +3 -2
- package/client/modeller/figure-material-panel.ts +1 -1
- package/client/modeller/figure-preview.ts +2 -2
- package/client/modeller/figure-properties.ts +1 -1
- package/client/modeller/figure-section-editor.ts +1 -1
- package/client/modeller/figure-section-panel.ts +1 -1
- package/client/modeller/figure-settings.ts +2 -2
- package/client/modeller/figure-verdict.ts +1 -1
- package/client/pages/figure-list-page.ts +7 -1
- package/client/viewparts/figure-detail-dock.ts +90 -41
- package/client/viewparts/figure-thumb.ts +2 -22
- package/dist-client/modeller/canvas.d.ts +1 -1
- package/dist-client/modeller/canvas.js +1 -1
- package/dist-client/modeller/canvas.js.map +1 -1
- package/dist-client/modeller/editor.js +2 -2
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-capability-panel.d.ts +0 -3
- package/dist-client/modeller/figure-capability-panel.js +5 -18
- package/dist-client/modeller/figure-capability-panel.js.map +1 -1
- package/dist-client/modeller/figure-carrier.js +1 -1
- package/dist-client/modeller/figure-carrier.js.map +1 -1
- package/dist-client/modeller/figure-clips.js +1 -1
- package/dist-client/modeller/figure-clips.js.map +1 -1
- package/dist-client/modeller/figure-controls.js +2 -2
- package/dist-client/modeller/figure-controls.js.map +1 -1
- package/dist-client/modeller/figure-face-mapping.js +1 -1
- package/dist-client/modeller/figure-face-mapping.js.map +1 -1
- package/dist-client/modeller/figure-links.js +3 -2
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-material-panel.js +1 -1
- package/dist-client/modeller/figure-material-panel.js.map +1 -1
- package/dist-client/modeller/figure-preview.d.ts +1 -1
- package/dist-client/modeller/figure-preview.js +2 -2
- package/dist-client/modeller/figure-preview.js.map +1 -1
- package/dist-client/modeller/figure-properties.js +1 -1
- package/dist-client/modeller/figure-properties.js.map +1 -1
- package/dist-client/modeller/figure-section-editor.js +1 -1
- package/dist-client/modeller/figure-section-editor.js.map +1 -1
- package/dist-client/modeller/figure-section-panel.js +1 -1
- package/dist-client/modeller/figure-section-panel.js.map +1 -1
- package/dist-client/modeller/figure-settings.d.ts +1 -1
- package/dist-client/modeller/figure-settings.js +1 -1
- package/dist-client/modeller/figure-settings.js.map +1 -1
- package/dist-client/modeller/figure-verdict.js +1 -1
- package/dist-client/modeller/figure-verdict.js.map +1 -1
- package/dist-client/pages/figure-list-page.d.ts +1 -0
- package/dist-client/pages/figure-list-page.js +11 -1
- package/dist-client/pages/figure-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/viewparts/figure-detail-dock.d.ts +10 -1
- package/dist-client/viewparts/figure-detail-dock.js +93 -41
- package/dist-client/viewparts/figure-detail-dock.js.map +1 -1
- package/dist-client/viewparts/figure-thumb.d.ts +1 -0
- package/dist-client/viewparts/figure-thumb.js +2 -22
- package/dist-client/viewparts/figure-thumb.js.map +1 -1
- package/package.json +5 -4
- package/test/browser/detail-page.js +10 -2
- package/test/browser/product-page.check.mjs +1 -1
- package/test/browser/screen-page.js +1 -1
- package/test/browser/serve-detail.mjs +7 -2
- package/test/figure-controls-keys.test.ts +19 -0
- package/test/i18n-prefix-guard.test.ts +4 -1
- package/test/layout.test.ts +4 -3
- package/test/links.test.ts +5 -4
- package/test/properties.test.ts +2 -1
- package/test/refusals.test.ts +2 -1
- package/test/theme.test.ts +1 -1
- package/test/verdict.test.ts +2 -1
- package/test/words.ts +20 -0
- package/translations/en.json +2 -33
- package/translations/es.json +2 -33
- package/translations/ja.json +2 -33
- package/translations/ko.json +2 -33
- package/translations/ms.json +2 -33
- package/translations/zh.json +2 -33
- package/client/modeller/controls.ts +0 -54
- package/client/modeller/figure-view.ts +0 -151
- package/client/modeller/preview-model.ts +0 -89
- package/client/modeller/side-panel-styles.ts +0 -374
- package/client/viewparts/detail-motion.ts +0 -11
- package/client/viewparts/figure-asset-viewer.ts +0 -177
- package/dist-client/modeller/controls.d.ts +0 -28
- package/dist-client/modeller/controls.js +0 -28
- package/dist-client/modeller/controls.js.map +0 -1
- package/dist-client/modeller/figure-view.d.ts +0 -117
- package/dist-client/modeller/figure-view.js +0 -78
- package/dist-client/modeller/figure-view.js.map +0 -1
- package/dist-client/modeller/preview-model.d.ts +0 -54
- package/dist-client/modeller/preview-model.js +0 -79
- package/dist-client/modeller/preview-model.js.map +0 -1
- package/dist-client/modeller/side-panel-styles.d.ts +0 -27
- package/dist-client/modeller/side-panel-styles.js +0 -374
- package/dist-client/modeller/side-panel-styles.js.map +0 -1
- package/dist-client/viewparts/detail-motion.d.ts +0 -6
- package/dist-client/viewparts/detail-motion.js +0 -9
- package/dist-client/viewparts/detail-motion.js.map +0 -1
- package/dist-client/viewparts/figure-asset-viewer.d.ts +0 -31
- package/dist-client/viewparts/figure-asset-viewer.js +0 -198
- package/dist-client/viewparts/figure-asset-viewer.js.map +0 -1
- package/test/controls.test.ts +0 -60
- package/test/detail-motion.test.ts +0 -26
- package/test/preview.test.ts +0 -53
- package/test/view.test.ts +0 -13
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
import { css } from 'lit';
|
|
2
|
-
/**
|
|
3
|
-
* The side panel's one look, for every element that draws in the modeller's side.
|
|
4
|
-
*
|
|
5
|
-
* The side is drawn by several elements (the type field, the figure's properties, a part's values, fastening, places,
|
|
6
|
-
* motion, material, controls, clips, the environment) and each had styled its own fields: three label styles and
|
|
7
|
-
* three field heights in one column (user, 2026-09-24: "why are the styles and layout all different?"). They share
|
|
8
|
-
* this sheet now and keep only what is theirs.
|
|
9
|
-
*
|
|
10
|
-
* The vocabulary:
|
|
11
|
-
* section one titled group; the side is a stack of them
|
|
12
|
-
* h3 a group's title
|
|
13
|
-
*
|
|
14
|
-
* Three sizes and two weights (user 2026-10-01, the panel checked for balance: eight sizes, and titles smaller than
|
|
15
|
-
* what they titled): a title at the body token and semibold, everything else at the small token, and a hint at the
|
|
16
|
-
* micro one. Sections are 16 px above their title and 12 px below their last line.
|
|
17
|
-
* div[inline-field] a short label and its one field on one line
|
|
18
|
-
* div[field] a label above a full-width field
|
|
19
|
-
* div[form] short labels beside their fields, the fields starting on one line
|
|
20
|
-
* div[vector-row] a title, then X · Y · Z in one row of cells with the axis inside (`div[triple]` of
|
|
21
|
-
* `div[cell]`) -- three values read together, as vector tools lay them out
|
|
22
|
-
* div[pair] two controls side by side
|
|
23
|
-
* label[toggle] a checkbox and its words
|
|
24
|
-
* p[hint] · small the quiet line under a field
|
|
25
|
-
* button[act] an action under the fields it acts on
|
|
26
|
-
* [scrub] a label dragged sideways to scrub its field
|
|
27
|
-
*/
|
|
28
|
-
export const SidePanelStyles = css `
|
|
29
|
-
:host {
|
|
30
|
-
--figure-control-height: 30px;
|
|
31
|
-
font-size: var(--ui-t-small, 11.5px);
|
|
32
|
-
color: var(--md-sys-color-on-surface);
|
|
33
|
-
}
|
|
34
|
-
/* The side is a stack of sections, each a titled group. */
|
|
35
|
-
section {
|
|
36
|
-
display: grid;
|
|
37
|
-
gap: 8px;
|
|
38
|
-
padding: 16px 12px 12px;
|
|
39
|
-
border-bottom: 1px solid var(--md-sys-color-outline-variant);
|
|
40
|
-
}
|
|
41
|
-
section > h3 {
|
|
42
|
-
margin: 0;
|
|
43
|
-
}
|
|
44
|
-
section div[field] + div[field],
|
|
45
|
-
section div[inline-field] + div[inline-field],
|
|
46
|
-
section div[vector-row] + div[vector-row] {
|
|
47
|
-
margin-top: 0;
|
|
48
|
-
}
|
|
49
|
-
h3 {
|
|
50
|
-
display: flex;
|
|
51
|
-
align-items: center;
|
|
52
|
-
gap: 4px;
|
|
53
|
-
margin: 14px 0 6px;
|
|
54
|
-
font-size: var(--ui-t-body, 13px);
|
|
55
|
-
font-weight: 600;
|
|
56
|
-
color: var(--md-sys-color-on-surface);
|
|
57
|
-
}
|
|
58
|
-
h3:first-child {
|
|
59
|
-
margin-top: 0;
|
|
60
|
-
}
|
|
61
|
-
/* Two weights only: a bold word in a line is the title's weight, not the browser's heavier one. */
|
|
62
|
-
b,
|
|
63
|
-
strong {
|
|
64
|
-
font-weight: 600;
|
|
65
|
-
}
|
|
66
|
-
label,
|
|
67
|
-
div[form] > span {
|
|
68
|
-
font-size: inherit;
|
|
69
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
70
|
-
}
|
|
71
|
-
div[field] {
|
|
72
|
-
display: grid;
|
|
73
|
-
gap: 2px;
|
|
74
|
-
}
|
|
75
|
-
div[field] + div[field],
|
|
76
|
-
div[field] + div[form],
|
|
77
|
-
div[form] + div[field],
|
|
78
|
-
div[vector-row] + div[vector-row],
|
|
79
|
-
div[vector-row] + div[field],
|
|
80
|
-
div[field] + div[vector-row] {
|
|
81
|
-
margin-top: 5px;
|
|
82
|
-
}
|
|
83
|
-
div[form],
|
|
84
|
-
div[inline-field],
|
|
85
|
-
div[vector-row] {
|
|
86
|
-
display: grid;
|
|
87
|
-
grid-template-columns: 64px minmax(0, 1fr);
|
|
88
|
-
align-items: center;
|
|
89
|
-
gap: 5px 7px;
|
|
90
|
-
}
|
|
91
|
-
div[form] > span,
|
|
92
|
-
div[inline-field] > label,
|
|
93
|
-
div[vector-row] > label {
|
|
94
|
-
overflow-wrap: anywhere;
|
|
95
|
-
white-space: normal;
|
|
96
|
-
}
|
|
97
|
-
/* A value read, not edited, beside its label: the field's size and colour, not the page's. */
|
|
98
|
-
div[inline-field] > span[value] {
|
|
99
|
-
font-size: inherit;
|
|
100
|
-
color: var(--md-sys-color-on-surface);
|
|
101
|
-
}
|
|
102
|
-
label span[unit] {
|
|
103
|
-
color: var(--md-sys-color-outline);
|
|
104
|
-
}
|
|
105
|
-
div[inline-field] + div[inline-field],
|
|
106
|
-
div[inline-field] + div[vector-row],
|
|
107
|
-
div[vector-row] + div[inline-field] {
|
|
108
|
-
margin-top: 5px;
|
|
109
|
-
}
|
|
110
|
-
/* A row of worded tools (align, snap; mirror copies). */
|
|
111
|
-
div[tools] {
|
|
112
|
-
display: flex;
|
|
113
|
-
flex-wrap: wrap;
|
|
114
|
-
gap: 4px;
|
|
115
|
-
}
|
|
116
|
-
div[tools] button {
|
|
117
|
-
height: var(--figure-control-height);
|
|
118
|
-
padding: 0 10px;
|
|
119
|
-
font: inherit;
|
|
120
|
-
color: var(--md-sys-color-on-surface);
|
|
121
|
-
background: var(--md-sys-color-surface-container-lowest);
|
|
122
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
123
|
-
border-radius: 6px;
|
|
124
|
-
cursor: pointer;
|
|
125
|
-
}
|
|
126
|
-
div[tools] button:hover:not(:disabled) {
|
|
127
|
-
background: var(--md-sys-color-surface-container);
|
|
128
|
-
}
|
|
129
|
-
div[tools] button:disabled {
|
|
130
|
-
opacity: 0.45;
|
|
131
|
-
cursor: default;
|
|
132
|
-
}
|
|
133
|
-
div[pair] {
|
|
134
|
-
display: flex;
|
|
135
|
-
gap: 4px;
|
|
136
|
-
}
|
|
137
|
-
div[pair] > * {
|
|
138
|
-
flex: 1;
|
|
139
|
-
min-width: 0;
|
|
140
|
-
}
|
|
141
|
-
div[triple] {
|
|
142
|
-
display: grid;
|
|
143
|
-
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
144
|
-
gap: 4px;
|
|
145
|
-
}
|
|
146
|
-
input,
|
|
147
|
-
select {
|
|
148
|
-
width: 100%;
|
|
149
|
-
min-width: 0;
|
|
150
|
-
min-height: var(--figure-control-height);
|
|
151
|
-
box-sizing: border-box;
|
|
152
|
-
padding: 4px 7px;
|
|
153
|
-
font: inherit;
|
|
154
|
-
color: var(--md-sys-color-on-surface);
|
|
155
|
-
background-color: var(--md-sys-color-surface-container-lowest);
|
|
156
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
157
|
-
border-radius: 6px;
|
|
158
|
-
}
|
|
159
|
-
/* The browser's own box and dot, in the panel's colour. */
|
|
160
|
-
input[type='checkbox'],
|
|
161
|
-
input[type='radio'] {
|
|
162
|
-
width: auto;
|
|
163
|
-
min-height: 0;
|
|
164
|
-
margin: 0;
|
|
165
|
-
accent-color: var(--md-sys-color-primary);
|
|
166
|
-
}
|
|
167
|
-
/* A fold: the panel's chevron, not the browser's triangle. */
|
|
168
|
-
summary {
|
|
169
|
-
display: flex;
|
|
170
|
-
align-items: center;
|
|
171
|
-
gap: 6px;
|
|
172
|
-
padding: 6px 0;
|
|
173
|
-
list-style: none;
|
|
174
|
-
cursor: pointer;
|
|
175
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
176
|
-
}
|
|
177
|
-
summary::-webkit-details-marker {
|
|
178
|
-
display: none;
|
|
179
|
-
}
|
|
180
|
-
summary::before {
|
|
181
|
-
content: '';
|
|
182
|
-
flex: none;
|
|
183
|
-
width: 6px;
|
|
184
|
-
height: 6px;
|
|
185
|
-
margin: 0 2px;
|
|
186
|
-
border-right: 1.5px solid currentColor;
|
|
187
|
-
border-bottom: 1.5px solid currentColor;
|
|
188
|
-
transform: rotate(-45deg);
|
|
189
|
-
transition: transform 0.15s;
|
|
190
|
-
}
|
|
191
|
-
details[open] > summary::before {
|
|
192
|
-
transform: rotate(45deg);
|
|
193
|
-
}
|
|
194
|
-
/* A thin track and a small thumb: a slider is a line to drag along, not a block (user, 2026-09-24). */
|
|
195
|
-
input[type='range'] {
|
|
196
|
-
-webkit-appearance: none;
|
|
197
|
-
appearance: none;
|
|
198
|
-
min-height: 16px;
|
|
199
|
-
height: 16px;
|
|
200
|
-
padding: 0;
|
|
201
|
-
border: none;
|
|
202
|
-
background: transparent;
|
|
203
|
-
cursor: pointer;
|
|
204
|
-
}
|
|
205
|
-
input[type='range']::-webkit-slider-runnable-track {
|
|
206
|
-
height: 3px;
|
|
207
|
-
border-radius: 2px;
|
|
208
|
-
background: var(--md-sys-color-outline-variant);
|
|
209
|
-
}
|
|
210
|
-
input[type='range']::-webkit-slider-thumb {
|
|
211
|
-
-webkit-appearance: none;
|
|
212
|
-
width: 12px;
|
|
213
|
-
height: 12px;
|
|
214
|
-
margin-top: -4.5px;
|
|
215
|
-
border: none;
|
|
216
|
-
border-radius: 50%;
|
|
217
|
-
background: var(--md-sys-color-primary);
|
|
218
|
-
}
|
|
219
|
-
input[type='range']::-moz-range-track {
|
|
220
|
-
height: 3px;
|
|
221
|
-
border-radius: 2px;
|
|
222
|
-
background: var(--md-sys-color-outline-variant);
|
|
223
|
-
}
|
|
224
|
-
input[type='range']::-moz-range-thumb {
|
|
225
|
-
width: 12px;
|
|
226
|
-
height: 12px;
|
|
227
|
-
border: none;
|
|
228
|
-
border-radius: 50%;
|
|
229
|
-
background: var(--md-sys-color-primary);
|
|
230
|
-
}
|
|
231
|
-
input[type='range']:focus {
|
|
232
|
-
outline: none;
|
|
233
|
-
}
|
|
234
|
-
input[type='range']:focus-visible::-webkit-slider-thumb {
|
|
235
|
-
outline: 2px solid var(--md-sys-color-primary);
|
|
236
|
-
outline-offset: 2px;
|
|
237
|
-
}
|
|
238
|
-
input[type='color'] {
|
|
239
|
-
padding: 2px;
|
|
240
|
-
width: 40px;
|
|
241
|
-
}
|
|
242
|
-
input:focus,
|
|
243
|
-
select:focus {
|
|
244
|
-
outline: 2px solid var(--md-sys-color-primary);
|
|
245
|
-
outline-offset: -1px;
|
|
246
|
-
}
|
|
247
|
-
input:disabled,
|
|
248
|
-
select:disabled {
|
|
249
|
-
opacity: 0.6;
|
|
250
|
-
}
|
|
251
|
-
/* A number with its axis inside the cell, on the left. */
|
|
252
|
-
div[cell] {
|
|
253
|
-
display: flex;
|
|
254
|
-
box-sizing: border-box;
|
|
255
|
-
height: var(--figure-control-height);
|
|
256
|
-
align-items: center;
|
|
257
|
-
gap: 2px;
|
|
258
|
-
padding-left: 6px;
|
|
259
|
-
background-color: var(--md-sys-color-surface-container-lowest);
|
|
260
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
261
|
-
border-radius: 6px;
|
|
262
|
-
}
|
|
263
|
-
div[cell]:focus-within {
|
|
264
|
-
outline: 2px solid var(--md-sys-color-primary);
|
|
265
|
-
outline-offset: -1px;
|
|
266
|
-
border-color: transparent;
|
|
267
|
-
}
|
|
268
|
-
/* A label that scrubs its field when dragged sideways (vector tools' way). */
|
|
269
|
-
[scrub] {
|
|
270
|
-
cursor: ew-resize;
|
|
271
|
-
user-select: none;
|
|
272
|
-
touch-action: none;
|
|
273
|
-
}
|
|
274
|
-
div[cell] span[axis] {
|
|
275
|
-
flex: none;
|
|
276
|
-
font-size: var(--ui-t-micro, 11px);
|
|
277
|
-
letter-spacing: 0.02em;
|
|
278
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
279
|
-
}
|
|
280
|
-
div[cell] input {
|
|
281
|
-
min-height: 0;
|
|
282
|
-
height: calc(var(--figure-control-height) - 2px);
|
|
283
|
-
padding: 4px 6px 4px 2px;
|
|
284
|
-
font-family: var(--mono-font, monospace);
|
|
285
|
-
text-align: right;
|
|
286
|
-
background: none;
|
|
287
|
-
border: none;
|
|
288
|
-
border-radius: 0;
|
|
289
|
-
}
|
|
290
|
-
div[cell] input:focus {
|
|
291
|
-
outline: none;
|
|
292
|
-
}
|
|
293
|
-
/* An axis a rule sets: its number, read-only, on a quieter ground (ADR-0097). */
|
|
294
|
-
div[cell][held] {
|
|
295
|
-
background-color: var(--md-sys-color-surface-container);
|
|
296
|
-
border-style: dashed;
|
|
297
|
-
}
|
|
298
|
-
div[cell][held] input {
|
|
299
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
300
|
-
font-style: italic;
|
|
301
|
-
}
|
|
302
|
-
p[held-axes] {
|
|
303
|
-
margin: 2px 0 6px;
|
|
304
|
-
}
|
|
305
|
-
label[toggle] {
|
|
306
|
-
display: flex;
|
|
307
|
-
align-items: center;
|
|
308
|
-
gap: 6px;
|
|
309
|
-
color: var(--md-sys-color-on-surface);
|
|
310
|
-
}
|
|
311
|
-
/* The 「?」 beside a title: no border, it says there is more rather than asking to be pressed. */
|
|
312
|
-
button[help] {
|
|
313
|
-
display: inline-flex;
|
|
314
|
-
align-items: center;
|
|
315
|
-
padding: 0;
|
|
316
|
-
margin: 0;
|
|
317
|
-
color: var(--md-sys-color-outline);
|
|
318
|
-
background: none;
|
|
319
|
-
border: none;
|
|
320
|
-
cursor: pointer;
|
|
321
|
-
}
|
|
322
|
-
button[help] md-icon {
|
|
323
|
-
font-size: 13px;
|
|
324
|
-
width: 13px;
|
|
325
|
-
height: 13px;
|
|
326
|
-
}
|
|
327
|
-
button[help]:hover,
|
|
328
|
-
button[help][aria-expanded='true'] {
|
|
329
|
-
color: var(--md-sys-color-primary);
|
|
330
|
-
}
|
|
331
|
-
p[hint],
|
|
332
|
-
small {
|
|
333
|
-
display: block;
|
|
334
|
-
margin: 2px 0 4px;
|
|
335
|
-
font-size: var(--ui-t-micro, 11px);
|
|
336
|
-
line-height: 1.5;
|
|
337
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
338
|
-
}
|
|
339
|
-
/*
|
|
340
|
-
* An action under its fields: as wide as its words, not a band across the panel -- four full-width grey bars read as
|
|
341
|
-
* four walls and none of them as the one to press (user 2026-10-01). Every one carries its icon.
|
|
342
|
-
*/
|
|
343
|
-
button[act] {
|
|
344
|
-
display: inline-flex;
|
|
345
|
-
align-items: center;
|
|
346
|
-
justify-content: center;
|
|
347
|
-
justify-self: start;
|
|
348
|
-
gap: 6px;
|
|
349
|
-
width: auto;
|
|
350
|
-
max-width: 100%;
|
|
351
|
-
margin-top: 4px;
|
|
352
|
-
padding: 0 12px;
|
|
353
|
-
min-height: var(--figure-control-height);
|
|
354
|
-
font: inherit;
|
|
355
|
-
color: var(--md-sys-color-primary);
|
|
356
|
-
background-color: var(--md-sys-color-surface-container-lowest);
|
|
357
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
358
|
-
border-radius: 6px;
|
|
359
|
-
cursor: pointer;
|
|
360
|
-
}
|
|
361
|
-
button[act]:hover:not(:disabled) {
|
|
362
|
-
background-color: var(--md-sys-color-primary-container);
|
|
363
|
-
}
|
|
364
|
-
button[act]:disabled {
|
|
365
|
-
opacity: 0.5;
|
|
366
|
-
cursor: default;
|
|
367
|
-
}
|
|
368
|
-
button[act] md-icon {
|
|
369
|
-
font-size: 16px;
|
|
370
|
-
width: 16px;
|
|
371
|
-
height: 16px;
|
|
372
|
-
}
|
|
373
|
-
`;
|
|
374
|
-
//# sourceMappingURL=side-panel-styles.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"side-panel-styles.js","sourceRoot":"","sources":["../../client/modeller/side-panel-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyVjC,CAAA","sourcesContent":["import { css } from 'lit'\n\n/**\n * The side panel's one look, for every element that draws in the modeller's side.\n *\n * The side is drawn by several elements (the type field, the figure's properties, a part's values, fastening, places,\n * motion, material, controls, clips, the environment) and each had styled its own fields: three label styles and\n * three field heights in one column (user, 2026-09-24: \"why are the styles and layout all different?\"). They share\n * this sheet now and keep only what is theirs.\n *\n * The vocabulary:\n * section one titled group; the side is a stack of them\n * h3 a group's title\n *\n * Three sizes and two weights (user 2026-10-01, the panel checked for balance: eight sizes, and titles smaller than\n * what they titled): a title at the body token and semibold, everything else at the small token, and a hint at the\n * micro one. Sections are 16 px above their title and 12 px below their last line.\n * div[inline-field] a short label and its one field on one line\n * div[field] a label above a full-width field\n * div[form] short labels beside their fields, the fields starting on one line\n * div[vector-row] a title, then X · Y · Z in one row of cells with the axis inside (`div[triple]` of\n * `div[cell]`) -- three values read together, as vector tools lay them out\n * div[pair] two controls side by side\n * label[toggle] a checkbox and its words\n * p[hint] · small the quiet line under a field\n * button[act] an action under the fields it acts on\n * [scrub] a label dragged sideways to scrub its field\n */\nexport const SidePanelStyles = css`\n :host {\n --figure-control-height: 30px;\n font-size: var(--ui-t-small, 11.5px);\n color: var(--md-sys-color-on-surface);\n }\n /* The side is a stack of sections, each a titled group. */\n section {\n display: grid;\n gap: 8px;\n padding: 16px 12px 12px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n section > h3 {\n margin: 0;\n }\n section div[field] + div[field],\n section div[inline-field] + div[inline-field],\n section div[vector-row] + div[vector-row] {\n margin-top: 0;\n }\n h3 {\n display: flex;\n align-items: center;\n gap: 4px;\n margin: 14px 0 6px;\n font-size: var(--ui-t-body, 13px);\n font-weight: 600;\n color: var(--md-sys-color-on-surface);\n }\n h3:first-child {\n margin-top: 0;\n }\n /* Two weights only: a bold word in a line is the title's weight, not the browser's heavier one. */\n b,\n strong {\n font-weight: 600;\n }\n label,\n div[form] > span {\n font-size: inherit;\n color: var(--md-sys-color-on-surface-variant);\n }\n div[field] {\n display: grid;\n gap: 2px;\n }\n div[field] + div[field],\n div[field] + div[form],\n div[form] + div[field],\n div[vector-row] + div[vector-row],\n div[vector-row] + div[field],\n div[field] + div[vector-row] {\n margin-top: 5px;\n }\n div[form],\n div[inline-field],\n div[vector-row] {\n display: grid;\n grid-template-columns: 64px minmax(0, 1fr);\n align-items: center;\n gap: 5px 7px;\n }\n div[form] > span,\n div[inline-field] > label,\n div[vector-row] > label {\n overflow-wrap: anywhere;\n white-space: normal;\n }\n /* A value read, not edited, beside its label: the field's size and colour, not the page's. */\n div[inline-field] > span[value] {\n font-size: inherit;\n color: var(--md-sys-color-on-surface);\n }\n label span[unit] {\n color: var(--md-sys-color-outline);\n }\n div[inline-field] + div[inline-field],\n div[inline-field] + div[vector-row],\n div[vector-row] + div[inline-field] {\n margin-top: 5px;\n }\n /* A row of worded tools (align, snap; mirror copies). */\n div[tools] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n div[tools] button {\n height: var(--figure-control-height);\n padding: 0 10px;\n font: inherit;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n div[tools] button:hover:not(:disabled) {\n background: var(--md-sys-color-surface-container);\n }\n div[tools] button:disabled {\n opacity: 0.45;\n cursor: default;\n }\n div[pair] {\n display: flex;\n gap: 4px;\n }\n div[pair] > * {\n flex: 1;\n min-width: 0;\n }\n div[triple] {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n }\n input,\n select {\n width: 100%;\n min-width: 0;\n min-height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 4px 7px;\n font: inherit;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n /* The browser's own box and dot, in the panel's colour. */\n input[type='checkbox'],\n input[type='radio'] {\n width: auto;\n min-height: 0;\n margin: 0;\n accent-color: var(--md-sys-color-primary);\n }\n /* A fold: the panel's chevron, not the browser's triangle. */\n summary {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 0;\n list-style: none;\n cursor: pointer;\n color: var(--md-sys-color-on-surface-variant);\n }\n summary::-webkit-details-marker {\n display: none;\n }\n summary::before {\n content: '';\n flex: none;\n width: 6px;\n height: 6px;\n margin: 0 2px;\n border-right: 1.5px solid currentColor;\n border-bottom: 1.5px solid currentColor;\n transform: rotate(-45deg);\n transition: transform 0.15s;\n }\n details[open] > summary::before {\n transform: rotate(45deg);\n }\n /* A thin track and a small thumb: a slider is a line to drag along, not a block (user, 2026-09-24). */\n input[type='range'] {\n -webkit-appearance: none;\n appearance: none;\n min-height: 16px;\n height: 16px;\n padding: 0;\n border: none;\n background: transparent;\n cursor: pointer;\n }\n input[type='range']::-webkit-slider-runnable-track {\n height: 3px;\n border-radius: 2px;\n background: var(--md-sys-color-outline-variant);\n }\n input[type='range']::-webkit-slider-thumb {\n -webkit-appearance: none;\n width: 12px;\n height: 12px;\n margin-top: -4.5px;\n border: none;\n border-radius: 50%;\n background: var(--md-sys-color-primary);\n }\n input[type='range']::-moz-range-track {\n height: 3px;\n border-radius: 2px;\n background: var(--md-sys-color-outline-variant);\n }\n input[type='range']::-moz-range-thumb {\n width: 12px;\n height: 12px;\n border: none;\n border-radius: 50%;\n background: var(--md-sys-color-primary);\n }\n input[type='range']:focus {\n outline: none;\n }\n input[type='range']:focus-visible::-webkit-slider-thumb {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: 2px;\n }\n input[type='color'] {\n padding: 2px;\n width: 40px;\n }\n input:focus,\n select:focus {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n }\n input:disabled,\n select:disabled {\n opacity: 0.6;\n }\n /* A number with its axis inside the cell, on the left. */\n div[cell] {\n display: flex;\n box-sizing: border-box;\n height: var(--figure-control-height);\n align-items: center;\n gap: 2px;\n padding-left: 6px;\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n div[cell]:focus-within {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n border-color: transparent;\n }\n /* A label that scrubs its field when dragged sideways (vector tools' way). */\n [scrub] {\n cursor: ew-resize;\n user-select: none;\n touch-action: none;\n }\n div[cell] span[axis] {\n flex: none;\n font-size: var(--ui-t-micro, 11px);\n letter-spacing: 0.02em;\n color: var(--md-sys-color-on-surface-variant);\n }\n div[cell] input {\n min-height: 0;\n height: calc(var(--figure-control-height) - 2px);\n padding: 4px 6px 4px 2px;\n font-family: var(--mono-font, monospace);\n text-align: right;\n background: none;\n border: none;\n border-radius: 0;\n }\n div[cell] input:focus {\n outline: none;\n }\n /* An axis a rule sets: its number, read-only, on a quieter ground (ADR-0097). */\n div[cell][held] {\n background-color: var(--md-sys-color-surface-container);\n border-style: dashed;\n }\n div[cell][held] input {\n color: var(--md-sys-color-on-surface-variant);\n font-style: italic;\n }\n p[held-axes] {\n margin: 2px 0 6px;\n }\n label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--md-sys-color-on-surface);\n }\n /* The 「?」 beside a title: no border, it says there is more rather than asking to be pressed. */\n button[help] {\n display: inline-flex;\n align-items: center;\n padding: 0;\n margin: 0;\n color: var(--md-sys-color-outline);\n background: none;\n border: none;\n cursor: pointer;\n }\n button[help] md-icon {\n font-size: 13px;\n width: 13px;\n height: 13px;\n }\n button[help]:hover,\n button[help][aria-expanded='true'] {\n color: var(--md-sys-color-primary);\n }\n p[hint],\n small {\n display: block;\n margin: 2px 0 4px;\n font-size: var(--ui-t-micro, 11px);\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant);\n }\n /*\n * An action under its fields: as wide as its words, not a band across the panel -- four full-width grey bars read as\n * four walls and none of them as the one to press (user 2026-10-01). Every one carries its icon.\n */\n button[act] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n justify-self: start;\n gap: 6px;\n width: auto;\n max-width: 100%;\n margin-top: 4px;\n padding: 0 12px;\n min-height: var(--figure-control-height);\n font: inherit;\n color: var(--md-sys-color-primary);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n button[act]:hover:not(:disabled) {\n background-color: var(--md-sys-color-primary-container);\n }\n button[act]:disabled {\n opacity: 0.5;\n cursor: default;\n }\n button[act] md-icon {\n font-size: 16px;\n width: 16px;\n height: 16px;\n }\n`\n"]}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { FigureAsset } from '@hatiolab/figure-model';
|
|
2
|
-
/** External values win over drivers; release only the controls owned by the chosen clip. */
|
|
3
|
-
export declare function parametersForClip(asset: FigureAsset, values: Record<string, number>, clip: string): {
|
|
4
|
-
[k: string]: number;
|
|
5
|
-
};
|
|
6
|
-
export declare function clipForControl(asset: FigureAsset, id: string): string | undefined;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/** External values win over drivers; release only the controls owned by the chosen clip. */
|
|
2
|
-
export function parametersForClip(asset, values, clip) {
|
|
3
|
-
const driven = new Set((asset.drivers ?? []).filter(d => d.clip === clip).map(d => d.state));
|
|
4
|
-
return Object.fromEntries(Object.entries(values).filter(([id]) => !driven.has(id)));
|
|
5
|
-
}
|
|
6
|
-
export function clipForControl(asset, id) {
|
|
7
|
-
return asset.drivers?.find(d => d.state === id)?.clip;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=detail-motion.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"detail-motion.js","sourceRoot":"","sources":["../../client/viewparts/detail-motion.ts"],"names":[],"mappings":"AAEA,4FAA4F;AAC5F,MAAM,UAAU,iBAAiB,CAAC,KAAkB,EAAE,MAA8B,EAAE,IAAY;IAChG,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IAC5F,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;AACrF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAkB,EAAE,EAAU;IAC3D,OAAO,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,EAAE,IAAI,CAAA;AACvD,CAAC","sourcesContent":["import type { FigureAsset } from '@hatiolab/figure-model'\n\n/** External values win over drivers; release only the controls owned by the chosen clip. */\nexport function parametersForClip(asset: FigureAsset, values: Record<string, number>, clip: string) {\n const driven = new Set((asset.drivers ?? []).filter(d => d.clip === clip).map(d => d.state))\n return Object.fromEntries(Object.entries(values).filter(([id]) => !driven.has(id)))\n}\n\nexport function clipForControl(asset: FigureAsset, id: string) {\n return asset.drivers?.find(d => d.state === id)?.clip\n}\n"]}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { LitElement, type PropertyValues } from 'lit';
|
|
2
|
-
import { type FigureAsset } from '@hatiolab/figure-model';
|
|
3
|
-
declare const FigureAssetViewer_base: (new (...args: any[]) => LitElement) & typeof LitElement;
|
|
4
|
-
/** A single board instance. Sizes and poses are transient, and never change the asset or call a mutation. */
|
|
5
|
-
export declare class FigureAssetViewer extends FigureAssetViewer_base {
|
|
6
|
-
static styles: import("lit").CSSResult;
|
|
7
|
-
asset?: FigureAsset;
|
|
8
|
-
private stage;
|
|
9
|
-
private sizes;
|
|
10
|
-
private values;
|
|
11
|
-
private playing;
|
|
12
|
-
private error;
|
|
13
|
-
private scene?;
|
|
14
|
-
private registered?;
|
|
15
|
-
private observer?;
|
|
16
|
-
private needsScene;
|
|
17
|
-
private played;
|
|
18
|
-
connectedCallback(): void;
|
|
19
|
-
protected updated(changed: PropertyValues): void;
|
|
20
|
-
firstUpdated(): void;
|
|
21
|
-
disconnectedCallback(): void;
|
|
22
|
-
render(): import("lit-html").TemplateResult<1>;
|
|
23
|
-
private tell;
|
|
24
|
-
private resize;
|
|
25
|
-
private pose;
|
|
26
|
-
private play;
|
|
27
|
-
private reset;
|
|
28
|
-
private standUp;
|
|
29
|
-
private teardown;
|
|
30
|
-
}
|
|
31
|
-
export {};
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import { __decorate, __metadata } from "tslib";
|
|
2
|
-
import { css, html, LitElement, nothing } from 'lit';
|
|
3
|
-
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
4
|
-
import { i18next, localize } from '@operato/i18n';
|
|
5
|
-
import { compileFigureAsset, FIGURE_INSTANCE_SIZE_INPUTS } from '@hatiolab/figure-model';
|
|
6
|
-
import { create, registerFigure, unregisterFigure } from '@hatiolab/things-scene';
|
|
7
|
-
import { authoredSizeOf } from '../modeller/preview-model.js';
|
|
8
|
-
import { controlsOf } from '../modeller/controls.js';
|
|
9
|
-
import { DEFAULT_VIEW, previewBoardDepth, sceneLook } from '../modeller/figure-view.js';
|
|
10
|
-
import { clipForControl, parametersForClip } from './detail-motion.js';
|
|
11
|
-
/** A single board instance. Sizes and poses are transient, and never change the asset or call a mutation. */
|
|
12
|
-
let FigureAssetViewer = class FigureAssetViewer extends localize(i18next)(LitElement) {
|
|
13
|
-
constructor() {
|
|
14
|
-
super(...arguments);
|
|
15
|
-
this.sizes = { x: 1, y: 1, z: 1 };
|
|
16
|
-
this.values = {};
|
|
17
|
-
this.playing = '';
|
|
18
|
-
this.error = '';
|
|
19
|
-
this.needsScene = false;
|
|
20
|
-
this.played = new Set();
|
|
21
|
-
}
|
|
22
|
-
static { this.styles = css `
|
|
23
|
-
:host { display: block; min-width: 0; }
|
|
24
|
-
[viewport] { height: 300px; position: relative; background: #858585; }
|
|
25
|
-
[stage] { position: absolute; inset: 0; width: 100%; height: 100%; }
|
|
26
|
-
section { padding: 12px 16px; border-bottom: 1px solid var(--md-sys-color-outline-variant); }
|
|
27
|
-
h3 { margin: 0 0 10px; font-size: var(--ui-t-body, 13px); }
|
|
28
|
-
label { display: grid; grid-template-columns: 72px minmax(0, 1fr) 90px; align-items: center; gap: 8px; margin: 8px 0; }
|
|
29
|
-
input { min-width: 0; width: 100%; box-sizing: border-box; }
|
|
30
|
-
input[type=number] { padding: 6px; }
|
|
31
|
-
input, button { font: inherit; color: inherit; }
|
|
32
|
-
button { padding: 8px 12px; border: 1px solid var(--md-sys-color-outline); border-radius: 8px; background: var(--md-sys-color-surface); cursor: pointer; }
|
|
33
|
-
[clips] { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
34
|
-
p { font-size: 12px; line-height: 1.5; }
|
|
35
|
-
[error] { color: var(--md-sys-color-error); }
|
|
36
|
-
`; }
|
|
37
|
-
connectedCallback() {
|
|
38
|
-
super.connectedCallback();
|
|
39
|
-
this.needsScene = true;
|
|
40
|
-
if (this.hasUpdated)
|
|
41
|
-
this.observer?.observe(this.stage);
|
|
42
|
-
this.requestUpdate();
|
|
43
|
-
}
|
|
44
|
-
updated(changed) {
|
|
45
|
-
// Reconnection and a new asset can arrive in the same update. Build exactly once.
|
|
46
|
-
if (changed.has('asset') || this.needsScene) {
|
|
47
|
-
this.needsScene = false;
|
|
48
|
-
this.standUp();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
firstUpdated() {
|
|
52
|
-
this.observer = new ResizeObserver(() => this.scene?.resize?.());
|
|
53
|
-
this.observer.observe(this.stage);
|
|
54
|
-
}
|
|
55
|
-
disconnectedCallback() {
|
|
56
|
-
super.disconnectedCallback();
|
|
57
|
-
this.observer?.disconnect();
|
|
58
|
-
this.teardown();
|
|
59
|
-
}
|
|
60
|
-
render() {
|
|
61
|
-
const asset = this.asset;
|
|
62
|
-
return html `<div viewport><div stage></div></div>
|
|
63
|
-
${this.error ? html `<p error role="alert">${this.error}</p>` : nothing}
|
|
64
|
-
${asset ? html `<section>
|
|
65
|
-
<h3>${i18next.t('figure.label.detail-size')}</h3>
|
|
66
|
-
${['x', 'y', 'z'].map(axis => {
|
|
67
|
-
const input = asset.document.model.inputs.find(input => input.id === FIGURE_INSTANCE_SIZE_INPUTS[axis]);
|
|
68
|
-
return html `<label><span>${axis.toUpperCase()} · mm</span>
|
|
69
|
-
<input type="range" aria-label=${`${axis.toUpperCase()} mm`} min=${input?.min ?? this.sizes[axis]} max=${input?.max ?? this.sizes[axis]} step="any"
|
|
70
|
-
.value=${String(this.sizes[axis])} ?disabled=${!input || input.min === input.max}
|
|
71
|
-
@input=${(e) => this.resize(axis, e.target.valueAsNumber)}>
|
|
72
|
-
<input type="number" aria-label=${`${axis.toUpperCase()} mm value`} min=${input?.min ?? this.sizes[axis]} max=${input?.max ?? this.sizes[axis]} step="any"
|
|
73
|
-
.value=${String(this.sizes[axis])} ?disabled=${!input || input.min === input.max}
|
|
74
|
-
@change=${(e) => this.resize(axis, e.target.valueAsNumber)}>
|
|
75
|
-
</label>`;
|
|
76
|
-
})}
|
|
77
|
-
<button @click=${() => this.reset()}>${i18next.t('figure.button.detail-reset')}</button>
|
|
78
|
-
<p>${i18next.t('figure.text.detail-transient')}</p>
|
|
79
|
-
</section>
|
|
80
|
-
<section><h3>${i18next.t('figure.label.motion')}</h3>
|
|
81
|
-
${controlsOf(asset, this.values).map(c => html `<label><span>${c.label} · ${c.unit}</span>
|
|
82
|
-
<input type="range" aria-label=${c.label} min=${c.min} max=${c.max} step=${c.step || 'any'} .value=${String(c.value)}
|
|
83
|
-
?disabled=${!!this.playing && clipForControl(asset, c.id) === this.playing}
|
|
84
|
-
@input=${(e) => this.pose(c.id, e.target.valueAsNumber)}>
|
|
85
|
-
<output>${this.playing && clipForControl(asset, c.id) === this.playing ? i18next.t('figure.text.detail-playing')
|
|
86
|
-
: this.played.has(clipForControl(asset, c.id) ?? '') && !(c.id in this.values) ? i18next.t('figure.text.detail-paused') : Math.round(c.value * 100) / 100}</output></label>`)}
|
|
87
|
-
<div clips>${[...new Set((asset.drivers ?? []).map(d => d.clip))].map(name => html `<button aria-pressed=${String(this.playing === name)}
|
|
88
|
-
@click=${() => this.play(name)}>${this.playing === name ? '⏸' : '▶'} ${name}</button>`)}</div>
|
|
89
|
-
${!controlsOf(asset).length && ![...new Set((asset.drivers ?? []).map(d => d.clip))].length ? html `<p>${i18next.t('figure.text.detail-no-motion')}</p>` : nothing}
|
|
90
|
-
</section>` : nothing}`;
|
|
91
|
-
}
|
|
92
|
-
tell(key, value) {
|
|
93
|
-
this.scene?.root?.components?.[0]?.set(key, value);
|
|
94
|
-
}
|
|
95
|
-
resize(axis, value) {
|
|
96
|
-
const input = this.asset?.document.model.inputs.find(input => input.id === FIGURE_INSTANCE_SIZE_INPUTS[axis]);
|
|
97
|
-
if (!input || !Number.isFinite(value)) {
|
|
98
|
-
this.requestUpdate();
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
const used = Math.min(input.max, Math.max(input.min, value));
|
|
102
|
-
this.sizes = { ...this.sizes, [axis]: used };
|
|
103
|
-
this.tell(axis === 'x' ? 'width' : axis === 'y' ? 'depth' : 'height', used);
|
|
104
|
-
this.scene?.root?.fitCameraToModel?.();
|
|
105
|
-
}
|
|
106
|
-
pose(id, value) {
|
|
107
|
-
if (!Number.isFinite(value))
|
|
108
|
-
return;
|
|
109
|
-
this.values = { ...this.values, [id]: value };
|
|
110
|
-
this.tell('parameters', this.values);
|
|
111
|
-
}
|
|
112
|
-
play(name) {
|
|
113
|
-
this.playing = this.playing === name ? '' : name;
|
|
114
|
-
if (this.playing && this.asset) {
|
|
115
|
-
this.played.add(name);
|
|
116
|
-
this.values = parametersForClip(this.asset, this.values, name);
|
|
117
|
-
this.tell('parameters', this.values);
|
|
118
|
-
}
|
|
119
|
-
this.tell('clips', Object.fromEntries([...new Set((this.asset?.drivers ?? []).map(d => d.clip))].map(key => [key, key === this.playing ? 1 : 0])));
|
|
120
|
-
}
|
|
121
|
-
reset() {
|
|
122
|
-
if (!this.asset)
|
|
123
|
-
return;
|
|
124
|
-
// A new instance also resets driver clocks. Clearing speeds alone freezes the last pose.
|
|
125
|
-
this.standUp();
|
|
126
|
-
}
|
|
127
|
-
standUp() {
|
|
128
|
-
this.teardown();
|
|
129
|
-
this.error = '';
|
|
130
|
-
const asset = this.asset;
|
|
131
|
-
if (!asset)
|
|
132
|
-
return;
|
|
133
|
-
this.values = {};
|
|
134
|
-
this.playing = '';
|
|
135
|
-
this.played.clear();
|
|
136
|
-
try {
|
|
137
|
-
compileFigureAsset(asset);
|
|
138
|
-
if (!asset.appearance.length)
|
|
139
|
-
throw Error(i18next.t('figure.text.preview-needs-a-part'));
|
|
140
|
-
this.sizes = authoredSizeOf(asset);
|
|
141
|
-
const type = `figure-detail-${crypto.randomUUID()}`;
|
|
142
|
-
registerFigure(type, asset);
|
|
143
|
-
this.registered = type;
|
|
144
|
-
const size = this.sizes;
|
|
145
|
-
this.scene = create({ target: this.stage, mode: 0, model: {
|
|
146
|
-
type: 'model-layer', width: size.x * 2, height: size.z * 2,
|
|
147
|
-
depth: previewBoardDepth({ placement: asset.placement, base: { y: size.y } }, DEFAULT_VIEW.ceilingHeight, 1),
|
|
148
|
-
threed: true, sky: 'color', ...sceneLook(DEFAULT_VIEW),
|
|
149
|
-
placement: DEFAULT_VIEW.placement, heights: { floor: 0, ceiling: DEFAULT_VIEW.ceilingHeight },
|
|
150
|
-
pixelRatio: Math.min(3, (window.devicePixelRatio || 1) * 2),
|
|
151
|
-
components: [{ type, id: 'detail-instance', left: size.x / 2, top: size.z / 2, width: size.x, height: size.z, depth: size.y }]
|
|
152
|
-
} });
|
|
153
|
-
this.scene.resize?.();
|
|
154
|
-
this.scene.fit?.('ratio');
|
|
155
|
-
this.scene.root?.fitCameraToModel?.();
|
|
156
|
-
}
|
|
157
|
-
catch (error) {
|
|
158
|
-
this.error = error.message;
|
|
159
|
-
this.teardown();
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
teardown() {
|
|
163
|
-
this.scene?.dispose?.();
|
|
164
|
-
this.scene = undefined;
|
|
165
|
-
if (this.registered)
|
|
166
|
-
unregisterFigure(this.registered);
|
|
167
|
-
this.registered = undefined;
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
__decorate([
|
|
171
|
-
property({ attribute: false }),
|
|
172
|
-
__metadata("design:type", Object)
|
|
173
|
-
], FigureAssetViewer.prototype, "asset", void 0);
|
|
174
|
-
__decorate([
|
|
175
|
-
query('[stage]'),
|
|
176
|
-
__metadata("design:type", HTMLElement)
|
|
177
|
-
], FigureAssetViewer.prototype, "stage", void 0);
|
|
178
|
-
__decorate([
|
|
179
|
-
state(),
|
|
180
|
-
__metadata("design:type", Object)
|
|
181
|
-
], FigureAssetViewer.prototype, "sizes", void 0);
|
|
182
|
-
__decorate([
|
|
183
|
-
state(),
|
|
184
|
-
__metadata("design:type", Object)
|
|
185
|
-
], FigureAssetViewer.prototype, "values", void 0);
|
|
186
|
-
__decorate([
|
|
187
|
-
state(),
|
|
188
|
-
__metadata("design:type", Object)
|
|
189
|
-
], FigureAssetViewer.prototype, "playing", void 0);
|
|
190
|
-
__decorate([
|
|
191
|
-
state(),
|
|
192
|
-
__metadata("design:type", Object)
|
|
193
|
-
], FigureAssetViewer.prototype, "error", void 0);
|
|
194
|
-
FigureAssetViewer = __decorate([
|
|
195
|
-
customElement('figure-asset-viewer')
|
|
196
|
-
], FigureAssetViewer);
|
|
197
|
-
export { FigureAssetViewer };
|
|
198
|
-
//# sourceMappingURL=figure-asset-viewer.js.map
|