@things-factory/figure-ui 10.1.168 → 10.1.170
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/figure-assistant.ts +10 -1
- package/client/modeller/affected-parts.ts +11 -0
- package/client/modeller/ai-proposal.ts +40 -9
- package/client/modeller/canvas.ts +15 -1
- package/client/modeller/editor-styles.ts +98 -6
- package/client/modeller/editor.ts +212 -53
- package/client/modeller/fasten-geometry.ts +19 -0
- package/client/modeller/figure-fasten-drawing.ts +4 -3
- package/client/modeller/figure-links.ts +80 -37
- package/client/modeller/figure-material-panel.ts +20 -1
- package/client/modeller/figure-preview.ts +117 -8
- package/client/modeller/figure-properties.ts +1 -2
- package/client/modeller/figure-section-panel.ts +5 -0
- package/client/modeller/figure-verdict.ts +9 -2
- package/client/modeller/gate-findings.ts +12 -4
- package/client/modeller/group-menu.ts +57 -0
- package/client/modeller/links.ts +22 -1
- package/client/modeller/modeller-keys.ts +6 -0
- package/client/modeller/preview-size.ts +32 -0
- package/client/modeller/product-session.ts +23 -9
- package/client/modeller/refusals.ts +14 -0
- package/client/modeller/stage-model.ts +11 -0
- package/client/pages/figure-modeller-page.ts +15 -6
- package/dist-client/figure-assistant.d.ts +6 -0
- package/dist-client/figure-assistant.js +9 -1
- package/dist-client/figure-assistant.js.map +1 -1
- package/dist-client/modeller/affected-parts.d.ts +6 -0
- package/dist-client/modeller/affected-parts.js +12 -0
- package/dist-client/modeller/affected-parts.js.map +1 -0
- package/dist-client/modeller/ai-proposal.d.ts +15 -5
- package/dist-client/modeller/ai-proposal.js +39 -10
- package/dist-client/modeller/ai-proposal.js.map +1 -1
- package/dist-client/modeller/canvas.d.ts +3 -0
- package/dist-client/modeller/canvas.js +12 -1
- package/dist-client/modeller/canvas.js.map +1 -1
- package/dist-client/modeller/editor-styles.js +98 -6
- package/dist-client/modeller/editor-styles.js.map +1 -1
- package/dist-client/modeller/editor.d.ts +42 -1
- package/dist-client/modeller/editor.js +220 -51
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/fasten-geometry.d.ts +27 -0
- package/dist-client/modeller/fasten-geometry.js +14 -0
- package/dist-client/modeller/fasten-geometry.js.map +1 -1
- package/dist-client/modeller/figure-fasten-drawing.js +4 -3
- package/dist-client/modeller/figure-fasten-drawing.js.map +1 -1
- package/dist-client/modeller/figure-links.d.ts +3 -1
- package/dist-client/modeller/figure-links.js +84 -38
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-material-panel.d.ts +8 -1
- package/dist-client/modeller/figure-material-panel.js +24 -1
- package/dist-client/modeller/figure-material-panel.js.map +1 -1
- package/dist-client/modeller/figure-preview.d.ts +12 -0
- package/dist-client/modeller/figure-preview.js +116 -5
- package/dist-client/modeller/figure-preview.js.map +1 -1
- package/dist-client/modeller/figure-properties.js +1 -2
- package/dist-client/modeller/figure-properties.js.map +1 -1
- package/dist-client/modeller/figure-section-panel.d.ts +1 -1
- package/dist-client/modeller/figure-section-panel.js +5 -0
- package/dist-client/modeller/figure-section-panel.js.map +1 -1
- package/dist-client/modeller/figure-verdict.d.ts +1 -0
- package/dist-client/modeller/figure-verdict.js +8 -2
- package/dist-client/modeller/figure-verdict.js.map +1 -1
- package/dist-client/modeller/gate-findings.d.ts +3 -1
- package/dist-client/modeller/gate-findings.js +8 -4
- package/dist-client/modeller/gate-findings.js.map +1 -1
- package/dist-client/modeller/group-menu.d.ts +18 -0
- package/dist-client/modeller/group-menu.js +52 -0
- package/dist-client/modeller/group-menu.js.map +1 -0
- package/dist-client/modeller/links.d.ts +5 -0
- package/dist-client/modeller/links.js +21 -1
- package/dist-client/modeller/links.js.map +1 -1
- package/dist-client/modeller/modeller-keys.js +7 -0
- package/dist-client/modeller/modeller-keys.js.map +1 -1
- package/dist-client/modeller/preview-size.d.ts +23 -0
- package/dist-client/modeller/preview-size.js +32 -0
- package/dist-client/modeller/preview-size.js.map +1 -0
- package/dist-client/modeller/product-session.d.ts +0 -1
- package/dist-client/modeller/product-session.js +22 -9
- package/dist-client/modeller/product-session.js.map +1 -1
- package/dist-client/modeller/refusals.d.ts +1 -5
- package/dist-client/modeller/refusals.js +14 -1
- package/dist-client/modeller/refusals.js.map +1 -1
- package/dist-client/modeller/stage-model.d.ts +11 -0
- package/dist-client/modeller/stage-model.js +11 -0
- package/dist-client/modeller/stage-model.js.map +1 -1
- package/dist-client/pages/figure-modeller-page.d.ts +3 -0
- package/dist-client/pages/figure-modeller-page.js +18 -5
- package/dist-client/pages/figure-modeller-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/test/ai-proposal.test.ts +43 -4
- package/test/browser/editing-page.js +3 -1
- package/test/browser/editing.check.mjs +2 -1
- package/test/browser/links-page.js +1 -0
- package/test/browser/links.check.mjs +20 -5
- package/test/browser/modeller.check.mjs +6 -0
- package/test/browser/more-open.js +11 -0
- package/test/browser/parts.check.mjs +11 -1
- package/test/browser/places-mesh.check.mjs +9 -3
- package/test/browser/product-page.check.mjs +9 -4
- package/test/browser/props.check.mjs +224 -0
- package/test/browser/screen-page.js +17 -0
- package/test/browser/screen.check.mjs +171 -29
- package/test/browser/section-page.js +1 -0
- package/test/browser/section.check.mjs +6 -0
- package/test/command-preview.test.ts +2 -2
- package/test/fasten-geometry.test.ts +15 -0
- package/test/fields.test.ts +4 -2
- package/test/figure-assistant-surface.test.ts +38 -0
- package/test/first-minute.test.ts +15 -2
- package/test/layout.test.ts +1 -1
- package/test/preview-size.test.ts +33 -0
- package/test/refusals.test.ts +1 -1
- package/test/resize-with-placement.test.ts +1 -1
- package/test/stage-model.test.ts +11 -1
- package/test/verdict.test.ts +7 -0
- package/translations/en.json +43 -27
- package/translations/es.json +24 -8
- package/translations/ja.json +25 -9
- package/translations/ko.json +56 -40
- package/translations/ms.json +25 -9
- package/translations/zh.json +25 -9
|
@@ -46,7 +46,8 @@ const NO_MARKS = [];
|
|
|
46
46
|
import { apexOver, drawnOf } from './section-drawing.js';
|
|
47
47
|
import { END_FACE } from './section-controls.js';
|
|
48
48
|
import { nudgeOf, placementOf } from './stage-model.js';
|
|
49
|
-
import { roomRefitRowsOf } from './occupancy.js';
|
|
49
|
+
import { occupancyFromParts, roomRefitRowsOf } from './occupancy.js';
|
|
50
|
+
import { gateFindingStyles, renderGateFinding } from './gate-findings.js';
|
|
50
51
|
import { editRefusalOf, inDeclaredRoom, narrowingRetryOf, partNameRefusalOf, partRefusalOf, placedRefusalOf, recipeRefusalOf, removalNoticeOf } from './refusals.js';
|
|
51
52
|
import { endPlaceKeyOf, fieldWordsOf, followOf, measureNow, partSummaryOf, instanceRangeOf, instanceRangeToDeclare, proportionToFollow, rangeDiffers, rangeWith, turnsAboutAJoint, valueNow } from './links.js';
|
|
52
53
|
import { jointFanOf } from './joint-fan.js';
|
|
@@ -54,11 +55,20 @@ import { derivedOf } from './revision.js';
|
|
|
54
55
|
import { jointDragOf } from './joint-drag.js';
|
|
55
56
|
import { liveOverSession, NOTHING_LIVE, scrubbed, scrubStep } from './live.js';
|
|
56
57
|
import { startingShapeKindOfBody } from './starting-shape.js';
|
|
58
|
+
import { groupMenu, GroupMenuStyles } from './group-menu.js';
|
|
59
|
+
/** The person's own fold of the properties' 「더 보기」, kept in their browser. */
|
|
60
|
+
const MORE_OPEN_KEY = 'figure-properties-more-open';
|
|
57
61
|
/** Product editor surface. The injected session is shared by page persistence and AI commands. */
|
|
58
62
|
const NO_OVERHANG = { words: NO_WORDS, note: NO_WORDS };
|
|
59
63
|
let FigureEditor = class FigureEditor extends LitElement {
|
|
60
64
|
constructor() {
|
|
61
65
|
super(...arguments);
|
|
66
|
+
/**
|
|
67
|
+
* What blocks release now, as the page's verdict heard it: said beside 「발행」 with the way out at hand, so an author
|
|
68
|
+
* does not find it at the foot of the verdict tab (first 15 minutes, 2026-10-16; chief architect, Q1 B).
|
|
69
|
+
*/
|
|
70
|
+
this.releaseBlockers = [];
|
|
71
|
+
this.blockersOpen = false;
|
|
62
72
|
/** The recipe templates (ADR-0095), read by the page from the server. */
|
|
63
73
|
this.templates = [];
|
|
64
74
|
this.catalogOpen = false;
|
|
@@ -68,6 +78,10 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
68
78
|
this.selected = '';
|
|
69
79
|
this.error = '';
|
|
70
80
|
this.tab = 'properties';
|
|
81
|
+
/** The capability group open: the canvas marks the places only while their group is in sight. */
|
|
82
|
+
this.capabilityOpen = false;
|
|
83
|
+
/** 「더 보기」 open, as this person left it last (chief architect 2026-10-16: kept per person). */
|
|
84
|
+
this.moreOpen = FigureEditor_1.storedMoreOpen();
|
|
71
85
|
/** What the middle shows: the parts being edited, or the figure placed on a board at eight sizes. */
|
|
72
86
|
this.middle = 'edit';
|
|
73
87
|
/** A line saying what a command did besides what was asked; gone at the next command. */
|
|
@@ -124,16 +138,35 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
124
138
|
this.lastAnchors = {};
|
|
125
139
|
/** Data tried in the data tab, given to the preview's figures as their `data`; null when none is (ADR-0051 §8). */
|
|
126
140
|
this.dataSample = null;
|
|
127
|
-
/** To the release that exists: the history
|
|
141
|
+
/** To the release that exists: the history's release section, opened from the bar, not a second one here. */
|
|
128
142
|
this.goRelease = async () => {
|
|
129
|
-
this.
|
|
143
|
+
this.overlay = 'history';
|
|
130
144
|
await this.updateComplete;
|
|
131
145
|
await this.querySelector('figure-history-panel')?.showRelease?.();
|
|
132
146
|
};
|
|
133
147
|
}
|
|
134
148
|
static { FigureEditor_1 = this; }
|
|
135
149
|
/* The operato scrollbar, as every scrolling panel of the app has it -- the side panel scrolled with the browser's own. */
|
|
136
|
-
static { this.styles = [ScrollbarStyles, SidePanelStyles, EditorStyles]; }
|
|
150
|
+
static { this.styles = [ScrollbarStyles, SidePanelStyles, gateFindingStyles, GroupMenuStyles, EditorStyles]; }
|
|
151
|
+
static storedMoreOpen() {
|
|
152
|
+
try {
|
|
153
|
+
return localStorage.getItem(MORE_OPEN_KEY) === '1';
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
setMoreOpen(open) {
|
|
160
|
+
if (open === this.moreOpen)
|
|
161
|
+
return;
|
|
162
|
+
this.moreOpen = open;
|
|
163
|
+
try {
|
|
164
|
+
localStorage.setItem(MORE_OPEN_KEY, open ? '1' : '0');
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
/* A browser that keeps nothing folds it again next time. */
|
|
168
|
+
}
|
|
169
|
+
}
|
|
137
170
|
static storedView() {
|
|
138
171
|
try {
|
|
139
172
|
const stored = JSON.parse(localStorage.getItem('figure-view') ?? 'null');
|
|
@@ -720,7 +753,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
720
753
|
}
|
|
721
754
|
}
|
|
722
755
|
/** Size response, fastening and motion for the selected part, as authoring commands. */
|
|
723
|
-
renderLinks(unavailable, section) {
|
|
756
|
+
renderLinks(unavailable, section, slotted = nothing) {
|
|
724
757
|
const shown = this.shown();
|
|
725
758
|
if (!shown)
|
|
726
759
|
return null;
|
|
@@ -738,7 +771,122 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
738
771
|
@go-fasten=${() => this.goFasten()}
|
|
739
772
|
@preview-command=${(e) => this.commandPreview.ask(e.detail)}
|
|
740
773
|
@part-edit=${(e) => this.run(() => this.session.edit(e.detail.edit))}
|
|
741
|
-
|
|
774
|
+
>${slotted}</figure-links>`;
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* A part's groups in one order whatever its state (chief architect 2026-10-16): its size, its place, its row. The links
|
|
778
|
+
* draw the three groups and their rules; the part's own numbers go into them by slot. A fastened part's place and turn
|
|
779
|
+
* are its fastening's: the place group says it in one line and the locked cells are not drawn (user 2026-10-16).
|
|
780
|
+
*/
|
|
781
|
+
renderPartGroups(shown, geometry, fields, unavailable, held) {
|
|
782
|
+
const groups = this.withSizeRow(groupFields(fields, this.selected), held);
|
|
783
|
+
const size = groups.vectors.filter(g => g.kind === 'vector' && g.name === 'size');
|
|
784
|
+
const place = groups.vectors.filter(g => g.kind === 'vector' && g.name !== 'size');
|
|
785
|
+
const fastened = !!this.asset()?.joints?.some(j => j.body1.part === ownerOf(this.selected));
|
|
786
|
+
const placeLocked = fastened && place.every(g => g.kind === 'vector' && ['x', 'y', 'z'].every(axis => !g.cells[axis]));
|
|
787
|
+
return this.renderLinks(unavailable, 'shape', html `${size.length || groups.singles.length
|
|
788
|
+
? html `<div slot="size" group-fields>
|
|
789
|
+
${size.map(g => this.renderVector(g, unavailable, held))}
|
|
790
|
+
${groups.singles.length
|
|
791
|
+
? html `<div form>${groups.singles.map(g => (g.kind === 'single' ? this.renderSingle(g.name, g.field, unavailable) : nothing))}</div>`
|
|
792
|
+
: nothing}
|
|
793
|
+
</div>`
|
|
794
|
+
: nothing}
|
|
795
|
+
${place.length && !placeLocked
|
|
796
|
+
? html `<div slot="place" group-fields>${place.map(g => this.renderVector(g, unavailable, held))}${this.renderHeldAxes(place)}</div>`
|
|
797
|
+
: nothing}
|
|
798
|
+
${this.renderRepeat(shown, geometry, unavailable)}`);
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* What the figure does -- its places (ADR-0118) -- as a group of the properties, folded: a declaration made once,
|
|
802
|
+
* whose marks on the canvas show while it is open. A verdict that finds it empty still says where it is.
|
|
803
|
+
*/
|
|
804
|
+
renderCapability(asset, unavailable) {
|
|
805
|
+
return html `<section capability>
|
|
806
|
+
<details capability-fold ?open=${this.capabilityOpen} @toggle=${(e) => (this.capabilityOpen = e.target.open)}>
|
|
807
|
+
<summary><h3>${i18next.t('figure.label.tab-capability')}</h3></summary>
|
|
808
|
+
${this.selected ? this.renderLinks(unavailable, 'places') : nothing}
|
|
809
|
+
<figure-capability-panel
|
|
810
|
+
.asset=${asset}
|
|
811
|
+
.selected=${this.selected}
|
|
812
|
+
?locked=${unavailable}
|
|
813
|
+
@select-part=${(e) => this.choose(e.detail.id)}
|
|
814
|
+
@part-edit=${(e) => this.run(() => this.session.edit(e.detail.edit))}
|
|
815
|
+
></figure-capability-panel>
|
|
816
|
+
</details>
|
|
817
|
+
</section>`;
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* 「더 보기」: what few parts need, folded by default and left as this person last left it (chief architect
|
|
821
|
+
* 2026-10-16) -- the section, its corners and inside; transparency, glow and segments; the mirrored copy and the
|
|
822
|
+
* alignment tools.
|
|
823
|
+
*/
|
|
824
|
+
renderMore(part, palette, unavailable) {
|
|
825
|
+
const tools = this.renderTools(unavailable);
|
|
826
|
+
return html `<section more>
|
|
827
|
+
<details more-fold ?open=${this.moreOpen} @toggle=${(e) => this.setMoreOpen(e.target.open)}>
|
|
828
|
+
<summary><h3>${i18next.t('figure.label.group-more')}</h3></summary>
|
|
829
|
+
<div more-body>
|
|
830
|
+
${tools ? html `<div group-fields>${tools}</div>` : nothing}
|
|
831
|
+
<figure-section-panel
|
|
832
|
+
embedded
|
|
833
|
+
.body=${{ ...part, id: this.selected }}
|
|
834
|
+
?locked=${unavailable}
|
|
835
|
+
.faceMapping=${this.faceMapping?.from === 'panel' ? this.faceMapping.need : undefined}
|
|
836
|
+
@face-mapped=${(e) => this.mapFaces(e.detail.remap)}
|
|
837
|
+
@face-mapping-cancel=${() => (this.faceMapping = undefined)}
|
|
838
|
+
@command=${(e) => this.linkCommand(e.detail.action)}
|
|
839
|
+
@command-live=${(e) => this.holdAction(e.detail.action)}
|
|
840
|
+
@section-editor-open=${() => (this.sectionEditing = this.selected)}
|
|
841
|
+
></figure-section-panel>
|
|
842
|
+
<figure-material-panel
|
|
843
|
+
show="more"
|
|
844
|
+
.body=${{ ...part, id: this.selected }}
|
|
845
|
+
.palette=${palette}
|
|
846
|
+
?locked=${unavailable}
|
|
847
|
+
@part-edit=${(e) => this.run(() => this.session.edit(e.detail.edit))}
|
|
848
|
+
@part-live=${(e) => this.hold({}, e.detail.edit)}
|
|
849
|
+
></figure-material-panel>
|
|
850
|
+
</div>
|
|
851
|
+
</details>
|
|
852
|
+
</section>`;
|
|
853
|
+
}
|
|
854
|
+
/** A bar button that opens the view settings or the release history over the work; pressed while it is open. */
|
|
855
|
+
renderOverlayButton(which, icon, label, slot) {
|
|
856
|
+
const open = this.overlay === which;
|
|
857
|
+
return html `<button
|
|
858
|
+
slot=${slot ?? nothing}
|
|
859
|
+
tool
|
|
860
|
+
bar-overlay=${which}
|
|
861
|
+
aria-pressed=${String(open)}
|
|
862
|
+
aria-label=${i18next.t(label)}
|
|
863
|
+
title=${i18next.t(label)}
|
|
864
|
+
@click=${() => (this.overlay = open ? undefined : which)}
|
|
865
|
+
>
|
|
866
|
+
<md-icon>${icon}</md-icon>
|
|
867
|
+
</button>`;
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* The view settings or the release history, over the work under the bar. Both stay drawn, hidden when closed: the
|
|
871
|
+
* history keeps what it read, as the tabs kept it. Esc closes it.
|
|
872
|
+
*/
|
|
873
|
+
renderOverlay() {
|
|
874
|
+
const close = () => (this.overlay = undefined);
|
|
875
|
+
const panel = (which, label, body) => html `<div
|
|
876
|
+
bar-overlay-panel=${which}
|
|
877
|
+
role="dialog"
|
|
878
|
+
aria-label=${i18next.t(label)}
|
|
879
|
+
?off=${this.overlay !== which}
|
|
880
|
+
@keydown=${(e) => e.key === 'Escape' && (e.stopPropagation(), close())}
|
|
881
|
+
>
|
|
882
|
+
<div overlay-head>
|
|
883
|
+
<h3>${i18next.t(label)}</h3>
|
|
884
|
+
<button quiet aria-label=${i18next.t('figure.button.close')} title=${i18next.t('figure.button.close')} @click=${close}><md-icon>close</md-icon></button>
|
|
885
|
+
</div>
|
|
886
|
+
<div overlay-body>${body}</div>
|
|
887
|
+
</div>`;
|
|
888
|
+
return html `${panel('view', 'figure.label.tab-environment', html `<figure-settings .view=${this.view} @update-view=${(e) => this.setView(e.detail.view)}></figure-settings>`)}
|
|
889
|
+
${panel('history', 'figure.label.history', html `<slot name="history"></slot>`)}`;
|
|
742
890
|
}
|
|
743
891
|
/**
|
|
744
892
|
* The face a size drag keeps for the selected part, figure-model's rule (`figureScaleAnchorOf`): the gizmo shows it
|
|
@@ -800,6 +948,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
800
948
|
this.retry = undefined;
|
|
801
949
|
this.notice = '';
|
|
802
950
|
const hadSize = this.hasSize();
|
|
951
|
+
const hadSpace = !!this.shown()?.asset.occupancy;
|
|
803
952
|
try {
|
|
804
953
|
this.session.command(action);
|
|
805
954
|
this.error = '';
|
|
@@ -807,7 +956,9 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
807
956
|
/* What the command did besides what was asked, in one line: the figure's size declared to follow (ADR ruling Q1). */
|
|
808
957
|
if (action.kind === 'follow-size' && !hadSize) {
|
|
809
958
|
const size = this.designValues();
|
|
810
|
-
|
|
959
|
+
/* The same step may have fitted the space the figure takes to its parts (figure-model, ruling 2026-10-16 Q1 A): one line says both. */
|
|
960
|
+
const spaceToo = !hadSpace && !!this.shown()?.asset.occupancy;
|
|
961
|
+
this.notice = i18next.t(spaceToo ? 'figure.text.size-and-space-declared-to-follow' : 'figure.text.size-declared-to-follow', {
|
|
811
962
|
x: Math.round(size['size.x'] ?? 0).toLocaleString(),
|
|
812
963
|
y: Math.round(size['size.y'] ?? 0).toLocaleString(),
|
|
813
964
|
z: Math.round(size['size.z'] ?? 0).toLocaleString()
|
|
@@ -1057,8 +1208,12 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1057
1208
|
const longest = model.inputs.find(i => i.id === lengthRef)?.max;
|
|
1058
1209
|
const limit = model.constants.find(c => c.id === layout?.args[6])?.value;
|
|
1059
1210
|
const field = { id: own, unit: 'mm', role: 'design', value: pitch ?? 0 };
|
|
1060
|
-
|
|
1061
|
-
|
|
1211
|
+
const removable = !!asset.joints?.some(j => j.body1.part === this.selected && j.repeat);
|
|
1212
|
+
return html `<section slot="row" row>
|
|
1213
|
+
<h3>
|
|
1214
|
+
${i18next.t('figure.label.repeat')}
|
|
1215
|
+
${groupMenu([{ label: i18next.t('figure.button.remove-repeat'), icon: 'close', disabled: unavailable || !removable, run: () => this.run(() => this.session.command({ kind: 'remove-repeat', part: this.selected })) }])}
|
|
1216
|
+
</h3>
|
|
1062
1217
|
<div inline-field><label>${i18next.t('figure.label.repeat-axis')}</label><span value>${axis.toUpperCase()}</span></div>
|
|
1063
1218
|
<div inline-field><label>${i18next.t('figure.label.repeat-count')}</label><span value>${repeat.count}</span></div>
|
|
1064
1219
|
<div inline-field>
|
|
@@ -1084,11 +1239,6 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1084
1239
|
: i18next.t(fits ? 'figure.text.repeat-fits-length' : 'figure.text.repeat-fixed-count')}
|
|
1085
1240
|
</p>
|
|
1086
1241
|
${this.renderPublicPitch(asset, pitch ?? 0, unavailable)}
|
|
1087
|
-
${asset.joints?.some(j => j.body1.part === this.selected && j.repeat)
|
|
1088
|
-
? html `<button act ?disabled=${unavailable} @click=${() => this.run(() => this.session.command({ kind: 'remove-repeat', part: this.selected }))}>
|
|
1089
|
-
<md-icon>close</md-icon>${i18next.t('figure.button.remove-repeat')}
|
|
1090
|
-
</button>`
|
|
1091
|
-
: nothing}
|
|
1092
1242
|
</section>`;
|
|
1093
1243
|
}
|
|
1094
1244
|
/** The selected row as it is drawn now, read by figure-model: nothing when it cannot be read. */
|
|
@@ -1218,6 +1368,21 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1218
1368
|
return i18next.t('figure.text.release-state-released', { version: String(version) });
|
|
1219
1369
|
return version > 0 ? i18next.t('figure.text.release-state-draft-over', { version: String(version) }) : i18next.t('figure.text.release-state-draft-new');
|
|
1220
1370
|
}
|
|
1371
|
+
/** The findings that block release, under the bar beside 「발행」, each with the way out the verdict tab offers for it. */
|
|
1372
|
+
renderReleaseBlockers(asset, unavailable) {
|
|
1373
|
+
const parts = (asset?.appearance ?? []).map(look => look.target);
|
|
1374
|
+
const way = (code) => (code === 'occupancy-undeclared' || code === 'part-outside-occupancy') && asset && parts.length
|
|
1375
|
+
? html `<button act ?disabled=${unavailable} @click=${() => this.linkCommand(occupancyFromParts(asset))}>
|
|
1376
|
+
<md-icon>fit_screen</md-icon>${i18next.t('figure.button.fit-base-to-parts')}
|
|
1377
|
+
</button>`
|
|
1378
|
+
: nothing;
|
|
1379
|
+
return html `<div release-blockers role="dialog" aria-label=${i18next.t('figure.text.must-fix-to-release')} @keydown=${(e) => e.key === 'Escape' && (this.blockersOpen = false)}>
|
|
1380
|
+
<ul gate>
|
|
1381
|
+
<li head>${i18next.t('figure.text.must-fix-to-release')}</li>
|
|
1382
|
+
${this.releaseBlockers.map(finding => renderGateFinding(finding, true, way(finding.code), parts))}
|
|
1383
|
+
</ul>
|
|
1384
|
+
</div>`;
|
|
1385
|
+
}
|
|
1221
1386
|
/*
|
|
1222
1387
|
Past the edge of the face a part is fastened to (ADR-0097 §5.5, Q3): the selected part's own, and the parts fastened
|
|
1223
1388
|
to it -- said apart from the room, nothing moved. Read once per version, part and language. The note says it is wider
|
|
@@ -1313,7 +1478,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1313
1478
|
/* A copy on the canvas selects its repeat: the part the author made. */
|
|
1314
1479
|
this.selected = id ? ownerOf(id) : id;
|
|
1315
1480
|
this.faceMapping = undefined;
|
|
1316
|
-
if (id &&
|
|
1481
|
+
if (id && this.tab === 'verdict')
|
|
1317
1482
|
this.tab = 'properties';
|
|
1318
1483
|
}
|
|
1319
1484
|
asset() {
|
|
@@ -1329,6 +1494,9 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1329
1494
|
}
|
|
1330
1495
|
updated(changed) {
|
|
1331
1496
|
super.updated?.(changed);
|
|
1497
|
+
/* Nothing blocks release any more: the list under the bar closes, and opens fresh when something does again. */
|
|
1498
|
+
if (changed.has('releaseBlockers') && !this.releaseBlockers.length && this.blockersOpen)
|
|
1499
|
+
this.blockersOpen = false;
|
|
1332
1500
|
this.refusals.tell(changed);
|
|
1333
1501
|
this.panelMemory.restore(() => this.selected);
|
|
1334
1502
|
const panes = this.renderRoot.querySelector('ox-three-pane') ?? undefined;
|
|
@@ -1408,7 +1576,6 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1408
1576
|
${i18next.t(`figure.label.resize-place-${one}`)}
|
|
1409
1577
|
</button>`)}
|
|
1410
1578
|
</div>
|
|
1411
|
-
<small>${i18next.t('figure.text.placement-is-intent')}</small>
|
|
1412
1579
|
</section>
|
|
1413
1580
|
<section>
|
|
1414
1581
|
<h3>${i18next.t('figure.label.start-shape')}</h3>
|
|
@@ -1527,14 +1694,22 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1527
1694
|
@canvas-fit=${() => this.renderRoot.querySelector('figure-canvas')?.fit()}
|
|
1528
1695
|
>
|
|
1529
1696
|
${this.renderGizmoTools(!unavailable && this.middle === 'edit')}
|
|
1697
|
+
${this.renderOverlayButton('view', 'wb_sunny', 'figure.label.tab-environment')}
|
|
1530
1698
|
${['edit', 'preview'].map(mode => html `<button slot="mode" mode aria-pressed=${String(this.middle === mode)} title=${i18next.t('figure.text.mode-' + mode + '-explained')} @click=${() => (this.middle = mode)}>
|
|
1531
1699
|
${i18next.t('figure.label.mode-' + mode)}
|
|
1532
1700
|
</button>`)}
|
|
1533
1701
|
<span slot="status" class="status" role="status" ?dirty=${status === 'figure.text.unsaved-changes'}>${i18next.t(status)}</span>
|
|
1534
1702
|
<span slot="status" release-state>${this.releaseWords(view)}</span>
|
|
1703
|
+
${this.renderOverlayButton('history', 'history', 'figure.label.history', 'commit')}
|
|
1704
|
+
${this.releaseBlockers.length
|
|
1705
|
+
? html `<button slot="commit" release-blocked aria-expanded=${String(this.blockersOpen)} @click=${() => (this.blockersOpen = !this.blockersOpen)}>
|
|
1706
|
+
<md-icon>error</md-icon>${i18next.t('figure.button.release-blocked', { count: this.releaseBlockers.length })}
|
|
1707
|
+
</button>`
|
|
1708
|
+
: nothing}
|
|
1535
1709
|
<button slot="commit" publish ?disabled=${!view.id} title=${view.id ? '' : i18next.t('figure.text.save-the-figure-before-releasing')} @click=${this.goRelease}>${i18next.t('figure.button.release')}</button>
|
|
1536
1710
|
<button slot="commit" save ?disabled=${unavailable || (!view.dirty && !!view.id)} @click=${this.save}>${i18next.t('figure.button.save')}</button>
|
|
1537
1711
|
</ox-canvas-bar>
|
|
1712
|
+
${this.blockersOpen && this.releaseBlockers.length ? this.renderReleaseBlockers(asset, unavailable) : nothing}
|
|
1538
1713
|
${this.catalogOpen
|
|
1539
1714
|
? html `<figure-recipe-catalog
|
|
1540
1715
|
.templates=${this.templates}
|
|
@@ -1600,7 +1775,7 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1600
1775
|
.fan=${this.fanOf(shown, live)}
|
|
1601
1776
|
.ghost=${this.previewShown().ghost}
|
|
1602
1777
|
.highlight=${this.previewShown().highlight}
|
|
1603
|
-
.marks=${this.tab === '
|
|
1778
|
+
.marks=${this.tab === 'properties' && this.capabilityOpen ? this.slotMarks(view, asset) : NO_MARKS}
|
|
1604
1779
|
.palette=${view.palette ?? {}}
|
|
1605
1780
|
.context=${view.context ?? ''}
|
|
1606
1781
|
.selected=${this.selected}
|
|
@@ -1614,12 +1789,9 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1614
1789
|
<aside slot="end">
|
|
1615
1790
|
<div tabs>
|
|
1616
1791
|
${this.renderTab('properties', 'tune', i18next.t('figure.label.properties'))}
|
|
1617
|
-
${this.renderTab('capability', 'conveyor_belt', i18next.t('figure.label.tab-capability'))}
|
|
1618
1792
|
${this.renderTab('motion', 'animation', i18next.t('figure.label.motion'))}
|
|
1619
1793
|
${this.renderTab('data', 'sensors', i18next.t('figure.label.tab-data'))}
|
|
1620
1794
|
${this.renderTab('verdict', 'insights', i18next.t('figure.label.maturity'), this.instances)}
|
|
1621
|
-
${this.renderTab('view', 'wb_sunny', i18next.t('figure.label.tab-environment'))}
|
|
1622
|
-
${this.renderTab('history', 'history', i18next.t('figure.label.history'))}
|
|
1623
1795
|
</div>
|
|
1624
1796
|
<slot name="notice"></slot>
|
|
1625
1797
|
<div panel ?off=${tab !== 'properties'}>
|
|
@@ -1639,27 +1811,17 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1639
1811
|
</div>
|
|
1640
1812
|
${this.renderRepeatNote(view.geometry)}
|
|
1641
1813
|
</section>
|
|
1642
|
-
${this.
|
|
1643
|
-
${this.renderGroups(this.withSizeRow(groupFields(partFields, this.selected), held), 'figure.label.group-placement-size', 'figure.label.group-shape', unavailable, this.renderTools(unavailable), held)}
|
|
1814
|
+
${this.renderPartGroups(shown, view.geometry, partFields, unavailable, held)}
|
|
1644
1815
|
${roomFields.length ? this.renderRoomOnly(roomFields, unavailable) : nothing}
|
|
1645
|
-
${this.renderLinks(unavailable, 'shape')}
|
|
1646
|
-
<figure-section-panel
|
|
1647
|
-
.body=${{ ...part, id: this.selected }}
|
|
1648
|
-
?locked=${unavailable}
|
|
1649
|
-
.faceMapping=${this.faceMapping?.from === 'panel' ? this.faceMapping.need : undefined}
|
|
1650
|
-
@face-mapped=${(e) => this.mapFaces(e.detail.remap)}
|
|
1651
|
-
@face-mapping-cancel=${() => (this.faceMapping = undefined)}
|
|
1652
|
-
@command=${(e) => this.linkCommand(e.detail.action)}
|
|
1653
|
-
@command-live=${(e) => this.holdAction(e.detail.action)}
|
|
1654
|
-
@section-editor-open=${() => (this.sectionEditing = this.selected)}
|
|
1655
|
-
></figure-section-panel>
|
|
1656
1816
|
<figure-material-panel
|
|
1657
1817
|
.body=${{ ...part, id: this.selected }}
|
|
1658
1818
|
.palette=${view.palette ?? {}}
|
|
1659
1819
|
?locked=${unavailable}
|
|
1660
1820
|
@part-edit=${(e) => this.run(() => this.session.edit(e.detail.edit))}
|
|
1661
1821
|
@part-live=${(e) => this.hold({}, e.detail.edit)}
|
|
1662
|
-
></figure-material-panel
|
|
1822
|
+
></figure-material-panel>
|
|
1823
|
+
${this.renderCapability(asset, unavailable)}
|
|
1824
|
+
${this.renderMore(part, view.palette ?? {}, unavailable)}`
|
|
1663
1825
|
: view.geometry.length === 0
|
|
1664
1826
|
? html `${this.renderSubject()}<section empty-figure>
|
|
1665
1827
|
<p>${i18next.t('figure.text.empty-figure-next')}</p>
|
|
@@ -1670,18 +1832,8 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1670
1832
|
</section>`
|
|
1671
1833
|
: html `${this.renderSubject()}<slot name="figure"></slot>
|
|
1672
1834
|
${this.renderGroups(groupFields(common), 'figure.label.group-figure-size', 'figure.label.design-inputs', unavailable)}
|
|
1673
|
-
${this.renderInstanceRange(shown, unavailable)}
|
|
1674
|
-
|
|
1675
|
-
<div panel ?off=${tab !== 'capability'}>
|
|
1676
|
-
${this.renderSubject()}
|
|
1677
|
-
${this.selected && part ? this.renderLinks(unavailable, 'places') : null}
|
|
1678
|
-
<figure-capability-panel
|
|
1679
|
-
.asset=${asset}
|
|
1680
|
-
.selected=${this.selected}
|
|
1681
|
-
?locked=${unavailable}
|
|
1682
|
-
@select-part=${(e) => this.choose(e.detail.id)}
|
|
1683
|
-
@part-edit=${(e) => this.run(() => this.session.edit(e.detail.edit))}
|
|
1684
|
-
></figure-capability-panel>
|
|
1835
|
+
${this.renderInstanceRange(shown, unavailable)}
|
|
1836
|
+
${this.renderCapability(asset, unavailable)}`}
|
|
1685
1837
|
</div>
|
|
1686
1838
|
<div panel ?off=${tab !== 'motion'}>
|
|
1687
1839
|
${this.renderSubject()}
|
|
@@ -1699,12 +1851,9 @@ let FigureEditor = class FigureEditor extends LitElement {
|
|
|
1699
1851
|
></figure-data-panel>
|
|
1700
1852
|
</div>
|
|
1701
1853
|
<div panel flush ?off=${tab !== 'verdict'}><slot name="verdict"></slot></div>
|
|
1702
|
-
<div panel flush ?off=${tab !== 'view'}>
|
|
1703
|
-
<figure-settings .view=${this.view} @update-view=${(e) => this.setView(e.detail.view)}></figure-settings>
|
|
1704
|
-
</div>
|
|
1705
|
-
<div panel flush ?off=${tab !== 'history'}><slot name="history"></slot></div>
|
|
1706
1854
|
</aside>
|
|
1707
|
-
</ox-three-pane
|
|
1855
|
+
</ox-three-pane>
|
|
1856
|
+
${this.renderOverlay()}`;
|
|
1708
1857
|
}
|
|
1709
1858
|
/** Position, rotation and size as rows of three cells; the shape's own measures one to a line, under their title. */
|
|
1710
1859
|
renderGroups(groups, vectorTitle, singleTitle, unavailable, tools = null, held) {
|
|
@@ -1859,6 +2008,14 @@ __decorate([
|
|
|
1859
2008
|
property({ attribute: false }),
|
|
1860
2009
|
__metadata("design:type", Object)
|
|
1861
2010
|
], FigureEditor.prototype, "releaseState", void 0);
|
|
2011
|
+
__decorate([
|
|
2012
|
+
property({ attribute: false }),
|
|
2013
|
+
__metadata("design:type", Array)
|
|
2014
|
+
], FigureEditor.prototype, "releaseBlockers", void 0);
|
|
2015
|
+
__decorate([
|
|
2016
|
+
state(),
|
|
2017
|
+
__metadata("design:type", Object)
|
|
2018
|
+
], FigureEditor.prototype, "blockersOpen", void 0);
|
|
1862
2019
|
__decorate([
|
|
1863
2020
|
property({ attribute: false }),
|
|
1864
2021
|
__metadata("design:type", Array)
|
|
@@ -1919,6 +2076,18 @@ __decorate([
|
|
|
1919
2076
|
state(),
|
|
1920
2077
|
__metadata("design:type", String)
|
|
1921
2078
|
], FigureEditor.prototype, "tab", void 0);
|
|
2079
|
+
__decorate([
|
|
2080
|
+
state(),
|
|
2081
|
+
__metadata("design:type", String)
|
|
2082
|
+
], FigureEditor.prototype, "overlay", void 0);
|
|
2083
|
+
__decorate([
|
|
2084
|
+
state(),
|
|
2085
|
+
__metadata("design:type", Object)
|
|
2086
|
+
], FigureEditor.prototype, "capabilityOpen", void 0);
|
|
2087
|
+
__decorate([
|
|
2088
|
+
state(),
|
|
2089
|
+
__metadata("design:type", Object)
|
|
2090
|
+
], FigureEditor.prototype, "moreOpen", void 0);
|
|
1922
2091
|
__decorate([
|
|
1923
2092
|
state(),
|
|
1924
2093
|
__metadata("design:type", Function)
|