@things-factory/figure-ui 10.1.46 → 10.1.47

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 (138) hide show
  1. package/client/modeller/angle-dial.ts +70 -0
  2. package/client/modeller/figure-settings.ts +328 -0
  3. package/client/modeller/figure-v3-capability.ts +137 -0
  4. package/client/modeller/figure-v3-clips.ts +253 -0
  5. package/client/modeller/figure-v3-controls.ts +212 -0
  6. package/client/modeller/figure-v3-links.ts +61 -81
  7. package/client/modeller/figure-v3-material.ts +108 -35
  8. package/client/modeller/figure-v3-parts.ts +96 -3
  9. package/client/modeller/figure-v3-preview.ts +326 -0
  10. package/client/modeller/figure-v3-properties.ts +29 -57
  11. package/client/modeller/figure-v3-verdict.ts +598 -60
  12. package/client/modeller/figure-view.ts +152 -0
  13. package/client/modeller/side-panel-styles.ts +326 -0
  14. package/client/modeller/v3-canvas.ts +221 -263
  15. package/client/modeller/v3-clips.ts +89 -0
  16. package/client/modeller/v3-controls.ts +54 -0
  17. package/client/modeller/v3-editor.ts +531 -223
  18. package/client/modeller/v3-fields.ts +62 -0
  19. package/client/modeller/v3-help.ts +41 -0
  20. package/client/modeller/v3-keys.ts +34 -0
  21. package/client/modeller/v3-links.ts +93 -9
  22. package/client/modeller/v3-live.ts +79 -0
  23. package/client/modeller/v3-maturity.ts +415 -0
  24. package/client/modeller/v3-palette.ts +45 -0
  25. package/client/modeller/v3-preview-model.ts +54 -0
  26. package/client/modeller/v3-stage-model.ts +159 -0
  27. package/client/pages/figure-list-page.ts +4 -4
  28. package/client/pages/figure-v3-modeller-page.ts +66 -134
  29. package/dist-client/modeller/angle-dial.d.ts +32 -0
  30. package/dist-client/modeller/angle-dial.js +41 -0
  31. package/dist-client/modeller/angle-dial.js.map +1 -0
  32. package/dist-client/modeller/figure-settings.d.ts +39 -0
  33. package/dist-client/modeller/figure-settings.js +317 -0
  34. package/dist-client/modeller/figure-settings.js.map +1 -0
  35. package/dist-client/modeller/figure-v3-capability.d.ts +22 -0
  36. package/dist-client/modeller/figure-v3-capability.js +141 -0
  37. package/dist-client/modeller/figure-v3-capability.js.map +1 -0
  38. package/dist-client/modeller/figure-v3-clips.d.ts +31 -0
  39. package/dist-client/modeller/figure-v3-clips.js +268 -0
  40. package/dist-client/modeller/figure-v3-clips.js.map +1 -0
  41. package/dist-client/modeller/figure-v3-controls.d.ts +36 -0
  42. package/dist-client/modeller/figure-v3-controls.js +226 -0
  43. package/dist-client/modeller/figure-v3-controls.js.map +1 -0
  44. package/dist-client/modeller/figure-v3-links.d.ts +5 -2
  45. package/dist-client/modeller/figure-v3-links.js +64 -82
  46. package/dist-client/modeller/figure-v3-links.js.map +1 -1
  47. package/dist-client/modeller/figure-v3-material.d.ts +5 -2
  48. package/dist-client/modeller/figure-v3-material.js +109 -35
  49. package/dist-client/modeller/figure-v3-material.js.map +1 -1
  50. package/dist-client/modeller/figure-v3-parts.d.ts +10 -0
  51. package/dist-client/modeller/figure-v3-parts.js +88 -3
  52. package/dist-client/modeller/figure-v3-parts.js.map +1 -1
  53. package/dist-client/modeller/figure-v3-preview.d.ts +34 -0
  54. package/dist-client/modeller/figure-v3-preview.js +322 -0
  55. package/dist-client/modeller/figure-v3-preview.js.map +1 -0
  56. package/dist-client/modeller/figure-v3-properties.d.ts +2 -2
  57. package/dist-client/modeller/figure-v3-properties.js +29 -57
  58. package/dist-client/modeller/figure-v3-properties.js.map +1 -1
  59. package/dist-client/modeller/figure-v3-verdict.d.ts +31 -17
  60. package/dist-client/modeller/figure-v3-verdict.js +579 -59
  61. package/dist-client/modeller/figure-v3-verdict.js.map +1 -1
  62. package/dist-client/modeller/figure-view.d.ts +118 -0
  63. package/dist-client/modeller/figure-view.js +78 -0
  64. package/dist-client/modeller/figure-view.js.map +1 -0
  65. package/dist-client/modeller/side-panel-styles.d.ts +23 -0
  66. package/dist-client/modeller/side-panel-styles.js +326 -0
  67. package/dist-client/modeller/side-panel-styles.js.map +1 -0
  68. package/dist-client/modeller/v3-canvas.d.ts +29 -37
  69. package/dist-client/modeller/v3-canvas.js +188 -260
  70. package/dist-client/modeller/v3-canvas.js.map +1 -1
  71. package/dist-client/modeller/v3-clips.d.ts +39 -0
  72. package/dist-client/modeller/v3-clips.js +58 -0
  73. package/dist-client/modeller/v3-clips.js.map +1 -0
  74. package/dist-client/modeller/v3-controls.d.ts +28 -0
  75. package/dist-client/modeller/v3-controls.js +28 -0
  76. package/dist-client/modeller/v3-controls.js.map +1 -0
  77. package/dist-client/modeller/v3-editor.d.ts +58 -1
  78. package/dist-client/modeller/v3-editor.js +555 -218
  79. package/dist-client/modeller/v3-editor.js.map +1 -1
  80. package/dist-client/modeller/v3-fields.d.ts +30 -0
  81. package/dist-client/modeller/v3-fields.js +46 -0
  82. package/dist-client/modeller/v3-fields.js.map +1 -0
  83. package/dist-client/modeller/v3-help.d.ts +18 -0
  84. package/dist-client/modeller/v3-help.js +37 -0
  85. package/dist-client/modeller/v3-help.js.map +1 -0
  86. package/dist-client/modeller/v3-keys.d.ts +14 -0
  87. package/dist-client/modeller/v3-keys.js +23 -0
  88. package/dist-client/modeller/v3-keys.js.map +1 -0
  89. package/dist-client/modeller/v3-links.d.ts +30 -1
  90. package/dist-client/modeller/v3-links.js +94 -8
  91. package/dist-client/modeller/v3-links.js.map +1 -1
  92. package/dist-client/modeller/v3-live.d.ts +31 -0
  93. package/dist-client/modeller/v3-live.js +58 -0
  94. package/dist-client/modeller/v3-live.js.map +1 -0
  95. package/dist-client/modeller/v3-maturity.d.ts +120 -0
  96. package/dist-client/modeller/v3-maturity.js +317 -0
  97. package/dist-client/modeller/v3-maturity.js.map +1 -0
  98. package/dist-client/modeller/v3-palette.d.ts +7 -0
  99. package/dist-client/modeller/v3-palette.js +42 -0
  100. package/dist-client/modeller/v3-palette.js.map +1 -0
  101. package/dist-client/modeller/v3-preview-model.d.ts +32 -0
  102. package/dist-client/modeller/v3-preview-model.js +48 -0
  103. package/dist-client/modeller/v3-preview-model.js.map +1 -0
  104. package/dist-client/modeller/v3-stage-model.d.ts +31 -0
  105. package/dist-client/modeller/v3-stage-model.js +121 -0
  106. package/dist-client/modeller/v3-stage-model.js.map +1 -0
  107. package/dist-client/pages/figure-list-page.js +4 -4
  108. package/dist-client/pages/figure-list-page.js.map +1 -1
  109. package/dist-client/pages/figure-v3-modeller-page.d.ts +2 -6
  110. package/dist-client/pages/figure-v3-modeller-page.js +64 -136
  111. package/dist-client/pages/figure-v3-modeller-page.js.map +1 -1
  112. package/dist-client/tsconfig.chk.tsbuildinfo +1 -0
  113. package/dist-client/tsconfig.scratch-fm.tsbuildinfo +1 -1
  114. package/dist-client/tsconfig.tsbuildinfo +1 -1
  115. package/package.json +6 -6
  116. package/test/v3-clips.test.ts +70 -0
  117. package/test/v3-controls.test.ts +68 -0
  118. package/test/v3-fields.test.ts +62 -0
  119. package/test/v3-gizmo.test.ts +3 -5
  120. package/test/v3-keys.test.ts +37 -0
  121. package/test/v3-layout.test.ts +78 -0
  122. package/test/v3-links.test.ts +77 -6
  123. package/test/v3-live.test.ts +99 -0
  124. package/test/v3-material.test.ts +6 -0
  125. package/test/v3-maturity.test.ts +268 -0
  126. package/test/v3-parts-wiring.test.ts +3 -1
  127. package/test/v3-preview.test.ts +42 -0
  128. package/test/v3-properties.test.ts +4 -2
  129. package/test/v3-scene-canvas.test.ts +85 -0
  130. package/test/v3-stage-model.test.ts +25 -0
  131. package/test/v3-theme.test.ts +16 -25
  132. package/test/v3-verdict.test.ts +12 -6
  133. package/test/v3-view.test.ts +20 -0
  134. package/translations/en.json +84 -5
  135. package/translations/ja.json +86 -7
  136. package/translations/ko.json +84 -5
  137. package/translations/ms.json +86 -7
  138. package/translations/zh.json +86 -7
@@ -0,0 +1,326 @@
1
+ import { css } from 'lit';
2
+ /**
3
+ * The side panel's one look -- V2's inspector, for every element that draws in the V3 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, V2's:
11
+ * section one titled group; the side is a stack of them
12
+ * h3 a group's title -- small capitals
13
+ * div[inline-field] a short label and its one field on one line
14
+ * div[field] a label above a full-width field
15
+ * div[form] short labels beside their fields, the fields starting on one line
16
+ * div[vector-row] a title, then X · Y · Z in one row of cells with the axis inside (`div[triple]` of
17
+ * `div[cell]`) -- three values read together, as vector tools lay them out
18
+ * div[pair] two controls side by side
19
+ * label[toggle] a checkbox and its words
20
+ * p[hint] · small the quiet line under a field
21
+ * button[act] an action under the fields it acts on
22
+ * [scrub] a label dragged sideways to scrub its field
23
+ */
24
+ export const SidePanelStyles = css `
25
+ :host {
26
+ --figure-control-height: 30px;
27
+ font-size: 0.76rem;
28
+ color: var(--md-sys-color-on-surface);
29
+ }
30
+ /* The side is a stack of sections, each a titled group (V2's inspector). */
31
+ section {
32
+ display: grid;
33
+ gap: 6px;
34
+ padding: 8px 10px;
35
+ border-bottom: 1px solid var(--md-sys-color-outline-variant);
36
+ }
37
+ section > h3 {
38
+ margin: 0;
39
+ }
40
+ section div[field] + div[field],
41
+ section div[inline-field] + div[inline-field],
42
+ section div[vector-row] + div[vector-row] {
43
+ margin-top: 0;
44
+ }
45
+ h3 {
46
+ display: flex;
47
+ align-items: center;
48
+ gap: 4px;
49
+ margin: 14px 0 6px;
50
+ font-size: var(--ui-t-micro, 11px);
51
+ font-weight: 700;
52
+ letter-spacing: 0.04em;
53
+ text-transform: uppercase;
54
+ color: var(--md-sys-color-on-surface-variant);
55
+ }
56
+ h3:first-child {
57
+ margin-top: 0;
58
+ }
59
+ label,
60
+ div[form] > span {
61
+ font-size: 0.68rem;
62
+ color: var(--md-sys-color-on-surface-variant);
63
+ }
64
+ div[field] {
65
+ display: grid;
66
+ gap: 2px;
67
+ }
68
+ div[field] + div[field],
69
+ div[field] + div[form],
70
+ div[form] + div[field],
71
+ div[vector-row] + div[vector-row],
72
+ div[vector-row] + div[field],
73
+ div[field] + div[vector-row] {
74
+ margin-top: 5px;
75
+ }
76
+ div[form],
77
+ div[inline-field],
78
+ div[vector-row] {
79
+ display: grid;
80
+ grid-template-columns: 64px minmax(0, 1fr);
81
+ align-items: center;
82
+ gap: 5px 7px;
83
+ }
84
+ div[form] > span,
85
+ div[inline-field] > label,
86
+ div[vector-row] > label {
87
+ overflow-wrap: anywhere;
88
+ white-space: normal;
89
+ }
90
+ div[inline-field] + div[inline-field],
91
+ div[inline-field] + div[vector-row],
92
+ div[vector-row] + div[inline-field] {
93
+ margin-top: 5px;
94
+ }
95
+ /* A row of icon tools (align, mirror, snap), as V2's placement section had them. */
96
+ div[tools] {
97
+ display: flex;
98
+ flex-wrap: wrap;
99
+ gap: 4px;
100
+ }
101
+ div[tools] button {
102
+ display: inline-flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ width: 30px;
106
+ height: 28px;
107
+ padding: 0;
108
+ color: var(--md-sys-color-on-surface);
109
+ background: var(--md-sys-color-surface-container-lowest);
110
+ border: 1px solid var(--md-sys-color-outline-variant);
111
+ border-radius: 6px;
112
+ cursor: pointer;
113
+ }
114
+ div[tools] button:hover:not(:disabled) {
115
+ background: var(--md-sys-color-surface-container);
116
+ }
117
+ div[tools] button:disabled {
118
+ opacity: 0.45;
119
+ cursor: default;
120
+ }
121
+ div[tools] md-icon {
122
+ font-size: 17px;
123
+ width: 17px;
124
+ height: 17px;
125
+ }
126
+ div[pair] {
127
+ display: flex;
128
+ gap: 4px;
129
+ }
130
+ div[pair] > * {
131
+ flex: 1;
132
+ min-width: 0;
133
+ }
134
+ div[triple] {
135
+ display: grid;
136
+ grid-template-columns: repeat(3, minmax(0, 1fr));
137
+ gap: 4px;
138
+ }
139
+ input,
140
+ select {
141
+ width: 100%;
142
+ min-width: 0;
143
+ min-height: var(--figure-control-height);
144
+ box-sizing: border-box;
145
+ padding: 4px 7px;
146
+ font: inherit;
147
+ font-size: 0.76rem;
148
+ color: var(--md-sys-color-on-surface);
149
+ background-color: var(--md-sys-color-surface-container-lowest);
150
+ border: 1px solid var(--md-sys-color-outline-variant);
151
+ border-radius: 6px;
152
+ }
153
+ input[type='checkbox'],
154
+ input[type='radio'] {
155
+ width: auto;
156
+ min-height: 0;
157
+ }
158
+ /* A thin track and a small thumb: a slider is a line to drag along, not a block (user, 2026-09-24). */
159
+ input[type='range'] {
160
+ -webkit-appearance: none;
161
+ appearance: none;
162
+ min-height: 16px;
163
+ height: 16px;
164
+ padding: 0;
165
+ border: none;
166
+ background: transparent;
167
+ cursor: pointer;
168
+ }
169
+ input[type='range']::-webkit-slider-runnable-track {
170
+ height: 3px;
171
+ border-radius: 2px;
172
+ background: var(--md-sys-color-outline-variant);
173
+ }
174
+ input[type='range']::-webkit-slider-thumb {
175
+ -webkit-appearance: none;
176
+ width: 12px;
177
+ height: 12px;
178
+ margin-top: -4.5px;
179
+ border: none;
180
+ border-radius: 50%;
181
+ background: var(--md-sys-color-primary);
182
+ }
183
+ input[type='range']::-moz-range-track {
184
+ height: 3px;
185
+ border-radius: 2px;
186
+ background: var(--md-sys-color-outline-variant);
187
+ }
188
+ input[type='range']::-moz-range-thumb {
189
+ width: 12px;
190
+ height: 12px;
191
+ border: none;
192
+ border-radius: 50%;
193
+ background: var(--md-sys-color-primary);
194
+ }
195
+ input[type='range']:focus {
196
+ outline: none;
197
+ }
198
+ input[type='range']:focus-visible::-webkit-slider-thumb {
199
+ outline: 2px solid var(--md-sys-color-primary);
200
+ outline-offset: 2px;
201
+ }
202
+ input[type='color'] {
203
+ padding: 2px;
204
+ width: 40px;
205
+ }
206
+ input:focus,
207
+ select:focus {
208
+ outline: 2px solid var(--md-sys-color-primary);
209
+ outline-offset: -1px;
210
+ }
211
+ input:disabled,
212
+ select:disabled {
213
+ opacity: 0.6;
214
+ }
215
+ /* A number with its axis inside the cell, on the left. */
216
+ div[cell] {
217
+ display: flex;
218
+ box-sizing: border-box;
219
+ height: var(--figure-control-height);
220
+ align-items: center;
221
+ gap: 2px;
222
+ padding-left: 6px;
223
+ background-color: var(--md-sys-color-surface-container-lowest);
224
+ border: 1px solid var(--md-sys-color-outline-variant);
225
+ border-radius: 6px;
226
+ }
227
+ div[cell]:focus-within {
228
+ outline: 2px solid var(--md-sys-color-primary);
229
+ outline-offset: -1px;
230
+ border-color: transparent;
231
+ }
232
+ /* A label that scrubs its field when dragged sideways (vector tools' way). */
233
+ [scrub] {
234
+ cursor: ew-resize;
235
+ user-select: none;
236
+ touch-action: none;
237
+ }
238
+ div[cell] span[axis] {
239
+ flex: none;
240
+ font-size: 0.64rem;
241
+ letter-spacing: 0.02em;
242
+ color: var(--md-sys-color-on-surface-variant);
243
+ }
244
+ div[cell] input {
245
+ min-height: 0;
246
+ height: calc(var(--figure-control-height) - 2px);
247
+ padding: 4px 6px 4px 2px;
248
+ font-family: var(--mono-font, monospace);
249
+ text-align: right;
250
+ background: none;
251
+ border: none;
252
+ border-radius: 0;
253
+ }
254
+ div[cell] input:focus {
255
+ outline: none;
256
+ }
257
+ label[toggle] {
258
+ display: flex;
259
+ align-items: center;
260
+ gap: 6px;
261
+ font-size: 0.76rem;
262
+ color: var(--md-sys-color-on-surface);
263
+ }
264
+ /* The 「?」 beside a title: no border, it says there is more rather than asking to be pressed (V2). */
265
+ button[help] {
266
+ display: inline-flex;
267
+ align-items: center;
268
+ padding: 0;
269
+ margin: 0;
270
+ color: var(--md-sys-color-outline);
271
+ background: none;
272
+ border: none;
273
+ cursor: pointer;
274
+ }
275
+ button[help] md-icon {
276
+ font-size: 13px;
277
+ width: 13px;
278
+ height: 13px;
279
+ }
280
+ button[help]:hover,
281
+ button[help][aria-expanded='true'] {
282
+ color: var(--md-sys-color-primary);
283
+ }
284
+ p[hint],
285
+ small {
286
+ display: block;
287
+ margin: 2px 0 4px;
288
+ font-size: 0.68rem;
289
+ line-height: 1.5;
290
+ color: var(--md-sys-color-on-surface-variant);
291
+ }
292
+ p[hint] {
293
+ padding-left: 6px;
294
+ border-left: 2px solid var(--md-sys-color-outline-variant);
295
+ }
296
+ button[act] {
297
+ display: inline-flex;
298
+ align-items: center;
299
+ justify-content: center;
300
+ gap: 4px;
301
+ width: 100%;
302
+ margin-top: 4px;
303
+ padding: 3px 8px;
304
+ min-height: 28px;
305
+ font: inherit;
306
+ font-size: 0.72rem;
307
+ color: var(--md-sys-color-on-surface);
308
+ background-color: var(--md-sys-color-surface-container);
309
+ border: 1px solid var(--md-sys-color-outline-variant);
310
+ border-radius: 6px;
311
+ cursor: pointer;
312
+ }
313
+ button[act]:hover:not(:disabled) {
314
+ background-color: var(--md-sys-color-surface-container-high);
315
+ }
316
+ button[act]:disabled {
317
+ opacity: 0.5;
318
+ cursor: default;
319
+ }
320
+ button[act] md-icon {
321
+ font-size: 15px;
322
+ width: 15px;
323
+ height: 15px;
324
+ }
325
+ `;
326
+ //# sourceMappingURL=side-panel-styles.js.map
@@ -0,0 +1 @@
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;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6SjC,CAAA","sourcesContent":["import { css } from 'lit'\n\n/**\n * The side panel's one look -- V2's inspector, for every element that draws in the V3 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, V2's:\n * section one titled group; the side is a stack of them\n * h3 a group's title -- small capitals\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: 0.76rem;\n color: var(--md-sys-color-on-surface);\n }\n /* The side is a stack of sections, each a titled group (V2's inspector). */\n section {\n display: grid;\n gap: 6px;\n padding: 8px 10px;\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-micro, 11px);\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--md-sys-color-on-surface-variant);\n }\n h3:first-child {\n margin-top: 0;\n }\n label,\n div[form] > span {\n font-size: 0.68rem;\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 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 icon tools (align, mirror, snap), as V2's placement section had them. */\n div[tools] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n div[tools] button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 28px;\n padding: 0;\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[tools] md-icon {\n font-size: 17px;\n width: 17px;\n height: 17px;\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 font-size: 0.76rem;\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 input[type='checkbox'],\n input[type='radio'] {\n width: auto;\n min-height: 0;\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: 0.64rem;\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 label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 0.76rem;\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 (V2). */\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: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant);\n }\n p[hint] {\n padding-left: 6px;\n border-left: 2px solid var(--md-sys-color-outline-variant);\n }\n button[act] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n width: 100%;\n margin-top: 4px;\n padding: 3px 8px;\n min-height: 28px;\n font: inherit;\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container);\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-surface-container-high);\n }\n button[act]:disabled {\n opacity: 0.5;\n cursor: default;\n }\n button[act] md-icon {\n font-size: 15px;\n width: 15px;\n height: 15px;\n }\n`\n"]}
@@ -1,52 +1,44 @@
1
1
  import { LitElement, type PropertyValues } from 'lit';
2
2
  import type { GizmoReach } from './v3-gizmo.js';
3
- import { type V3RenderPart } from './v3-renderer.js';
4
- /** Renders evaluated V3 geometry directly. There is no parts/base or things-scene conversion. */
3
+ import type { V3RenderPart } from './v3-renderer.js';
4
+ import { type ViewSettings } from './figure-view.js';
5
5
  export declare class FigureV3Canvas extends LitElement {
6
6
  static styles: import("lit").CSSResult;
7
7
  parts: V3RenderPart[];
8
8
  palette: Record<string, string>;
9
+ /** Which figure is open. Another one stands the board up again. */
9
10
  context: string;
10
- /** The selected part, and what the gizmo may write for it (`gizmoReachOf`). Nothing reachable, no gizmo. */
11
11
  selected: string;
12
+ /** What the gizmo may write for the selected part; a change beyond it is not applied and the part springs back. */
12
13
  reach: GizmoReach;
13
- /** Move · turn · size — W · E · R, as in the V2 modeller. */
14
- mode: 'translate' | 'rotate' | 'scale';
15
- private transform?;
16
- /** What the gizmo holds: a stand-in at the body's origin, so the body's own matrix stays the evaluation's. */
17
- private readonly proxy;
18
- private dragStart?;
19
- /** The pointerup that ends a drag is not a pick — releasing off the body would otherwise deselect it. */
20
- private justDragged;
21
- private renderer?;
22
- private readonly scene;
23
- private readonly group;
24
- private readonly camera;
25
- private controls?;
26
- private observer?;
27
- private themeObserver?;
28
- private initialized;
29
- private contextAtRender;
14
+ view: ViewSettings;
15
+ private stage;
16
+ private scene?;
17
+ private board?;
18
+ private standingFor?;
19
+ private watcher?;
20
+ /** Set while this canvas writes to components, so the scene's echo of it is not taken for a drag. */
21
+ private writing;
30
22
  render(): import("lit-html").TemplateResult<1>;
31
- private key;
32
- protected firstUpdated(): void;
33
- connectedCallback(): void;
34
- private initialize;
23
+ firstUpdated(): void;
35
24
  protected updated(changed: PropertyValues): void;
36
- /** Puts the gizmo on the selected body, in a mode it may write — or takes it away. */
37
- private placeGizmo;
38
- private dragging;
39
- /** While dragging, the body follows the stand-in; the next evaluation replaces it with where the inputs put it. */
40
- private follow;
41
- private updateGeometry;
25
+ disconnectedCallback(): void;
26
+ /** The whole figure in view: the board's fit, then the 3D camera's own, as V2 did. */
42
27
  fit(): void;
43
28
  /**
44
- * The scene's background, taken from the host's computed background — the token resolved and normalised to
45
- * `rgb(r, g, b)`, which THREE.Color reads. The token's own text may use the space-separated form it does not.
29
+ * Stand the board up for this figure, or bring the one standing up to date. A new board only for another figure or
30
+ * one that has outgrown it -- standing up again loses the selection and the camera.
46
31
  */
47
- private paintBackground;
48
- private draw;
49
- private pick;
50
- thumbnail(): any;
51
- disconnectedCallback(): void;
32
+ private standUp;
33
+ private components;
34
+ /** The components standing now, by name. Not held between calls: the scene stands its board up again at times. */
35
+ private standing;
36
+ /** Bring the components to the evaluation: remove the gone, write only what differs, add the new. */
37
+ private sync;
38
+ /** Selection and drags, told out by the part's name -- never by its place in the list, which may change meanwhile. */
39
+ private watchScene;
40
+ private showSelected;
41
+ /** View settings go into the scene as they are: they are the board's own state names. Nothing is stood up again. */
42
+ private applyView;
43
+ private teardown;
52
44
  }