@things-factory/figure-ui 10.1.84 → 10.1.86
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/editor.ts +46 -2
- package/client/modeller/figure-parts.ts +4 -4
- package/client/modeller/figure-section-editor.ts +484 -0
- package/client/modeller/figure-section-panel.ts +211 -75
- package/client/modeller/live.ts +13 -4
- package/client/modeller/section-controls.ts +89 -8
- package/client/modeller/section-drawing.ts +97 -0
- package/dist-client/modeller/clips.d.ts +1 -1
- package/dist-client/modeller/editor.d.ts +8 -0
- package/dist-client/modeller/editor.js +51 -1
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-parts.js +1 -3
- package/dist-client/modeller/figure-parts.js.map +1 -1
- package/dist-client/modeller/figure-section-editor.d.ts +62 -0
- package/dist-client/modeller/figure-section-editor.js +495 -0
- package/dist-client/modeller/figure-section-editor.js.map +1 -0
- package/dist-client/modeller/figure-section-panel.d.ts +26 -12
- package/dist-client/modeller/figure-section-panel.js +193 -69
- package/dist-client/modeller/figure-section-panel.js.map +1 -1
- package/dist-client/modeller/live.d.ts +3 -1
- package/dist-client/modeller/live.js +13 -3
- package/dist-client/modeller/live.js.map +1 -1
- package/dist-client/modeller/section-controls.d.ts +33 -0
- package/dist-client/modeller/section-controls.js +71 -7
- package/dist-client/modeller/section-controls.js.map +1 -1
- package/dist-client/modeller/section-drawing.d.ts +33 -0
- package/dist-client/modeller/section-drawing.js +82 -0
- package/dist-client/modeller/section-drawing.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/test/browser/acceptance-page.js +7 -0
- package/test/palette-icons.test.ts +1 -1
- package/test/parts-wiring.test.ts +6 -2
- package/test/section-editor.test.ts +192 -0
- package/test/section-panel.test.ts +108 -6
- package/translations/en.json +37 -2
- package/translations/ja.json +37 -2
- package/translations/ko.json +37 -2
- package/translations/ms.json +37 -2
- package/translations/zh.json +37 -2
|
@@ -7,6 +7,7 @@ import './canvas.js';
|
|
|
7
7
|
import './figure-parts.js';
|
|
8
8
|
import './figure-material-panel.js';
|
|
9
9
|
import './figure-section-panel.js';
|
|
10
|
+
import './figure-section-editor.js';
|
|
10
11
|
import './figure-links.js';
|
|
11
12
|
import './figure-controls.js';
|
|
12
13
|
import './figure-clips.js';
|
|
@@ -73,6 +74,8 @@ export declare class FigureEditor extends LitElement {
|
|
|
73
74
|
private hiddenParts;
|
|
74
75
|
/** A value in hand -- typed, held on a spinner, scrubbed, dragged -- drawn at once and recorded on release. */
|
|
75
76
|
private live;
|
|
77
|
+
/** The part whose drawn section is open in the section editor (ADR-0100 §3.2), or null. */
|
|
78
|
+
private sectionEditing;
|
|
76
79
|
/**
|
|
77
80
|
* A command seen before it is done (ADR-0097 §5.5): worked out on a copy for the figure, version, part and command it
|
|
78
81
|
* names, and shown only while all four are still the ones on screen. Nothing of it is saved or undone.
|
|
@@ -134,6 +137,9 @@ export declare class FigureEditor extends LitElement {
|
|
|
134
137
|
private currentInputs;
|
|
135
138
|
/** A value in hand: an input's value (design or pose) or a part edit. Nothing is recorded. */
|
|
136
139
|
private hold;
|
|
140
|
+
private closeSectionEditor;
|
|
141
|
+
/** A command in hand, drawn and not run; `null` lets go of it and the figure as it stands is drawn again. */
|
|
142
|
+
private holdAction;
|
|
137
143
|
private changed;
|
|
138
144
|
private save;
|
|
139
145
|
private add;
|
|
@@ -287,6 +293,8 @@ export declare class FigureEditor extends LitElement {
|
|
|
287
293
|
* recipe, or an AI draft when the page offers one. Nothing is added until one is chosen; the type, the space, the
|
|
288
294
|
* mounting face and the tags are not asked for first.
|
|
289
295
|
*/
|
|
296
|
+
/** The section editor over the canvas, the figure behind it drawing what the working points make. */
|
|
297
|
+
private renderSectionEditor;
|
|
290
298
|
private renderStart;
|
|
291
299
|
/**
|
|
292
300
|
* Where the panel is, held at its top: the model by its name -- the way back to its settings -- and the part chosen,
|
|
@@ -15,6 +15,7 @@ import './canvas.js';
|
|
|
15
15
|
import './figure-parts.js';
|
|
16
16
|
import './figure-material-panel.js';
|
|
17
17
|
import './figure-section-panel.js';
|
|
18
|
+
import './figure-section-editor.js';
|
|
18
19
|
import { faceHighlightOf, ghostPartsOf, previewWordsOf, rowWordsOf } from './command-preview.js';
|
|
19
20
|
import { motionEndsOf } from './motion-ends.js';
|
|
20
21
|
import './figure-links.js';
|
|
@@ -70,12 +71,20 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
70
71
|
this.hiddenParts = new Set();
|
|
71
72
|
/** A value in hand -- typed, held on a spinner, scrubbed, dragged -- drawn at once and recorded on release. */
|
|
72
73
|
this.live = NOTHING_LIVE;
|
|
74
|
+
/** The part whose drawn section is open in the section editor (ADR-0100 §3.2), or null. */
|
|
75
|
+
this.sectionEditing = null;
|
|
73
76
|
this.lastContext = null;
|
|
74
77
|
/** The modeller's keys (`keys.ts`): undo, redo, duplicate, remove, back to the whole figure, the gizmo's modes. */
|
|
75
78
|
this.onKey = (e) => {
|
|
76
79
|
const view = this.session?.read();
|
|
77
80
|
if (!view || view.loading || view.saving || !view.context || !this.isConnected)
|
|
78
81
|
return;
|
|
82
|
+
/*
|
|
83
|
+
* The section editor open takes the keys for its own: Esc cancels it, Delete deletes a point, Ctrl+Z undoes a point.
|
|
84
|
+
* Heard here first, they deselected the part, deleted the part and undid the figure's last step (2026-09-30).
|
|
85
|
+
*/
|
|
86
|
+
if (this.sectionEditing)
|
|
87
|
+
return;
|
|
79
88
|
const canvas = this.renderRoot.querySelector('figure-canvas');
|
|
80
89
|
const path = e.composedPath();
|
|
81
90
|
const action = keyActionOf({ key: e.key, ctrlKey: e.ctrlKey, metaKey: e.metaKey, shiftKey: e.shiftKey, altKey: e.altKey, target: path[0], inScene: !!canvas && path.includes(canvas) }, this.selected);
|
|
@@ -622,6 +631,12 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
622
631
|
this.selected = '';
|
|
623
632
|
if (_changed.has('selected'))
|
|
624
633
|
this.gizmoMode = undefined;
|
|
634
|
+
/*
|
|
635
|
+
* The section editor is of one part: when the selection moves off it by any way -- another part picked, the scene's
|
|
636
|
+
* own Esc, the part removed, another figure opened -- it closes and lets go of the preview it held.
|
|
637
|
+
*/
|
|
638
|
+
if (this.sectionEditing && this.sectionEditing !== this.selected)
|
|
639
|
+
this.closeSectionEditor();
|
|
625
640
|
}
|
|
626
641
|
/** The scene toggles: the mode already shown takes the gizmo away. */
|
|
627
642
|
useGizmo(mode) {
|
|
@@ -693,6 +708,15 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
693
708
|
hold(values, edit) {
|
|
694
709
|
this.live = { values: { ...this.live.values, ...values }, ...(edit ? { edit } : this.live.edit ? { edit: this.live.edit } : {}) };
|
|
695
710
|
}
|
|
711
|
+
closeSectionEditor() {
|
|
712
|
+
this.sectionEditing = null;
|
|
713
|
+
this.holdAction(null);
|
|
714
|
+
}
|
|
715
|
+
/** A command in hand, drawn and not run; `null` lets go of it and the figure as it stands is drawn again. */
|
|
716
|
+
holdAction(action) {
|
|
717
|
+
const { action: _, ...rest } = this.live;
|
|
718
|
+
this.live = action ? { ...rest, action } : rest;
|
|
719
|
+
}
|
|
696
720
|
changed() {
|
|
697
721
|
this.requestUpdate();
|
|
698
722
|
this.dispatchEvent(new CustomEvent('changed', { bubbles: true, composed: true }));
|
|
@@ -1164,6 +1188,8 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1164
1188
|
}
|
|
1165
1189
|
/** One command, one step of the history. A refusal a person can meet here is said in their words. */
|
|
1166
1190
|
linkCommand(action) {
|
|
1191
|
+
/* Committed or refused, a command in hand is let go of: the figure as it stands is drawn again. */
|
|
1192
|
+
this.holdAction(null);
|
|
1167
1193
|
this.retry = undefined;
|
|
1168
1194
|
this.notice = '';
|
|
1169
1195
|
const hadSize = this.hasSize();
|
|
@@ -1794,6 +1820,19 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1794
1820
|
* recipe, or an AI draft when the page offers one. Nothing is added until one is chosen; the type, the space, the
|
|
1795
1821
|
* mounting face and the tags are not asked for first.
|
|
1796
1822
|
*/
|
|
1823
|
+
/** The section editor over the canvas, the figure behind it drawing what the working points make. */
|
|
1824
|
+
renderSectionEditor(geometry) {
|
|
1825
|
+
const part = geometry.find(g => ownerOf(g.id) === this.selected);
|
|
1826
|
+
if (!part?.shape?.extrusion || part.shape.extrusion.section.kind !== 'polygon')
|
|
1827
|
+
return nothing;
|
|
1828
|
+
return html `<figure-section-editor
|
|
1829
|
+
.body=${{ ...part, id: this.selected }}
|
|
1830
|
+
.revision=${this.session?.read().revision ?? 0}
|
|
1831
|
+
@command=${(e) => this.linkCommand(e.detail.action)}
|
|
1832
|
+
@command-live=${(e) => this.holdAction(e.detail.action)}
|
|
1833
|
+
@section-editor-close=${() => this.closeSectionEditor()}
|
|
1834
|
+
></figure-section-editor>`;
|
|
1835
|
+
}
|
|
1797
1836
|
renderStart() {
|
|
1798
1837
|
const shapes = ['box', 'cylinder', 'plate'];
|
|
1799
1838
|
/* Where it is authored from, chosen before any part (ADR-0097): the figure's own setting, no room made up for it. */
|
|
@@ -2000,6 +2039,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
2000
2039
|
></figure-preview>`
|
|
2001
2040
|
: html `<div middle>
|
|
2002
2041
|
${view.geometry.length === 0 && !unavailable ? this.renderStart() : nothing}
|
|
2042
|
+
${this.sectionEditing && this.sectionEditing === this.selected && !unavailable ? this.renderSectionEditor(view.geometry) : nothing}
|
|
2003
2043
|
<figure-canvas
|
|
2004
2044
|
?startShown=${view.geometry.length === 0 && !unavailable}
|
|
2005
2045
|
.view=${this.view}
|
|
@@ -2053,6 +2093,8 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
2053
2093
|
.body=${{ ...part, id: this.selected }}
|
|
2054
2094
|
?locked=${unavailable}
|
|
2055
2095
|
@command=${(e) => this.linkCommand(e.detail.action)}
|
|
2096
|
+
@command-live=${(e) => this.holdAction(e.detail.action)}
|
|
2097
|
+
@section-editor-open=${() => (this.sectionEditing = this.selected)}
|
|
2056
2098
|
></figure-section-panel>
|
|
2057
2099
|
<figure-material-panel
|
|
2058
2100
|
.body=${{ ...part, id: this.selected }}
|
|
@@ -2213,7 +2255,11 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
2213
2255
|
this.linkCommand(refit.step);
|
|
2214
2256
|
}
|
|
2215
2257
|
renderSingle(name, field, unavailable) {
|
|
2216
|
-
|
|
2258
|
+
/* A drawn section's point is called by its number and axis, as the section editor calls it (ADR-0100 §2.1, Q9). */
|
|
2259
|
+
const point = /^point\.p(\d+)\.([xyz])$/.exec(name);
|
|
2260
|
+
const words = point
|
|
2261
|
+
? [i18next.t('figure.label.section-editor-coordinate', { point: point[1], axis: point[2].toUpperCase() })]
|
|
2262
|
+
: name.split('.').map(part => i18next.t('figure.label.field-' + part, { defaultValue: part }));
|
|
2217
2263
|
return html `<span ?scrub=${!unavailable} @pointerdown=${(e) => this.scrub(field, e, unavailable)}>${words.join(' · ')} (${field.unit})</span
|
|
2218
2264
|
><input
|
|
2219
2265
|
aria-label=${field.id}
|
|
@@ -2322,6 +2368,10 @@ __decorate([
|
|
|
2322
2368
|
state(),
|
|
2323
2369
|
__metadata("design:type", Object)
|
|
2324
2370
|
], FigureEditor.prototype, "live", void 0);
|
|
2371
|
+
__decorate([
|
|
2372
|
+
state(),
|
|
2373
|
+
__metadata("design:type", Object)
|
|
2374
|
+
], FigureEditor.prototype, "sectionEditing", void 0);
|
|
2325
2375
|
__decorate([
|
|
2326
2376
|
state(),
|
|
2327
2377
|
__metadata("design:type", Object)
|