@things-factory/figure-ui 10.1.104 → 10.1.105
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 +2 -2
- package/client/modeller/fields.ts +7 -1
- package/client/modeller/figure-cavity-drawing.ts +65 -9
- package/client/modeller/figure-material-panel.ts +0 -1
- package/client/modeller/figure-section-panel.ts +15 -103
- package/dist-client/modeller/clips.d.ts +1 -1
- package/dist-client/modeller/editor.js +2 -2
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/fields.js +7 -1
- package/dist-client/modeller/fields.js.map +1 -1
- package/dist-client/modeller/figure-cavity-drawing.d.ts +6 -0
- package/dist-client/modeller/figure-cavity-drawing.js +68 -9
- package/dist-client/modeller/figure-cavity-drawing.js.map +1 -1
- package/dist-client/modeller/figure-material-panel.js +0 -1
- package/dist-client/modeller/figure-material-panel.js.map +1 -1
- package/dist-client/modeller/figure-section-panel.d.ts +0 -1
- package/dist-client/modeller/figure-section-panel.js +14 -73
- package/dist-client/modeller/figure-section-panel.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/test/cavity-drawing.test.ts +5 -1
- package/test/section-editor.test.ts +3 -1
- package/test/section-panel.test.ts +5 -3
- package/translations/en.json +0 -1
- package/translations/ja.json +0 -1
- package/translations/ko.json +0 -1
- package/translations/ms.json +0 -1
- package/translations/zh.json +0 -1
|
@@ -7,7 +7,7 @@ import { i18next, localize } from '@operato/i18n';
|
|
|
7
7
|
import { SidePanelStyles } from './side-panel-styles.js';
|
|
8
8
|
import { drawnOf } from './section-drawing.js';
|
|
9
9
|
import './figure-cavity-drawing.js';
|
|
10
|
-
import {
|
|
10
|
+
import { cavityDepthOf, cavityRequestOf, cavityResultOf, cornerLimitOf, cornerRefusalOf, mm, sameOf } from './section-controls.js';
|
|
11
11
|
/**
|
|
12
12
|
* 단면 — a pushed part's rounded corners and its inside (ADR-0100 §3.3).
|
|
13
13
|
*
|
|
@@ -91,7 +91,7 @@ let FigureSectionPanel = class FigureSectionPanel extends localize(i18next)(LitE
|
|
|
91
91
|
</div>`
|
|
92
92
|
: nothing}
|
|
93
93
|
${kind === 'rectangle' ? this.renderCorner(body) : nothing}
|
|
94
|
-
${ /* No inside for a drawn section: the control is not there, rather than a line saying so. */kind === 'rectangle' || kind === 'ellipse' ? this.renderCavity(body
|
|
94
|
+
${ /* No inside for a drawn section: the control is not there, rather than a line saying so. */kind === 'rectangle' || kind === 'ellipse' ? this.renderCavity(body) : nothing}
|
|
95
95
|
</section>`;
|
|
96
96
|
}
|
|
97
97
|
renderCorner(body) {
|
|
@@ -117,28 +117,13 @@ let FigureSectionPanel = class FigureSectionPanel extends localize(i18next)(LitE
|
|
|
117
117
|
</div>
|
|
118
118
|
</div>`;
|
|
119
119
|
}
|
|
120
|
-
|
|
120
|
+
/*
|
|
121
|
+
* The inside: made or taken away here, and drawn -- walls dragged or their number pressed and typed, ends pressed
|
|
122
|
+
* open or closed (figure-cavity-drawing). The number fields under the drawing went (user 2026-10-01): they said the
|
|
123
|
+
* drawing again.
|
|
124
|
+
*/
|
|
125
|
+
renderCavity(body) {
|
|
121
126
|
const cavity = body.shape.cavity;
|
|
122
|
-
const request = (patch) => cavityRequestOf(body.shape, patch);
|
|
123
|
-
const said = (ask) => !ask
|
|
124
|
-
? ''
|
|
125
|
-
: ask.code === 'not-positive'
|
|
126
|
-
? i18next.t('figure.text.section-not-positive')
|
|
127
|
-
: i18next.t(`figure.text.section-${ask.code === 'wall-too-thick' ? 'wall' : 'ends'}-over`, { max: String(ask.max) });
|
|
128
|
-
const cavityField = (key, now, patch) => this.number(key, now, {
|
|
129
|
-
min: 0,
|
|
130
|
-
ask: value => {
|
|
131
|
-
if (!(value > 0))
|
|
132
|
-
return i18next.t('figure.text.section-not-positive');
|
|
133
|
-
const ask = cavityRefusalOf(body.shape, request(patch(value)));
|
|
134
|
-
/* One side too thick: the most it can be is the width across less the wall opposite, not the even limit. */
|
|
135
|
-
const side = key.startsWith('wall.') ? key.slice(5) : undefined;
|
|
136
|
-
if (ask?.code === 'wall-too-thick' && side && cavity)
|
|
137
|
-
return said({ code: 'wall-too-thick', max: mm(sideWallLimitOf(body.shape, cavity.wall, side)) });
|
|
138
|
-
return said(ask);
|
|
139
|
-
},
|
|
140
|
-
action: value => ({ kind: 'set-cavity', part: body.id, cavity: request(patch(value)) })
|
|
141
|
-
});
|
|
142
127
|
return html `<div field>
|
|
143
128
|
<label toggle>
|
|
144
129
|
<input
|
|
@@ -148,7 +133,7 @@ let FigureSectionPanel = class FigureSectionPanel extends localize(i18next)(LitE
|
|
|
148
133
|
@change=${(ev) => {
|
|
149
134
|
const on = ev.target.checked;
|
|
150
135
|
ev.target.checked = !!cavity;
|
|
151
|
-
this.command({ kind: 'set-cavity', part: body.id, cavity: on ?
|
|
136
|
+
this.command({ kind: 'set-cavity', part: body.id, cavity: on ? cavityRequestOf(body.shape, {}) : null });
|
|
152
137
|
}}
|
|
153
138
|
/>
|
|
154
139
|
${i18next.t('figure.label.section-cavity')}
|
|
@@ -162,58 +147,14 @@ let FigureSectionPanel = class FigureSectionPanel extends localize(i18next)(LitE
|
|
|
162
147
|
</small>`
|
|
163
148
|
: nothing}
|
|
164
149
|
</div>
|
|
165
|
-
${cavity ? html `<figure-cavity-drawing .body=${body} .perSide=${this.perSide} ?locked=${this.locked}></figure-cavity-drawing>` : nothing}
|
|
166
150
|
${cavity
|
|
167
|
-
? html `<
|
|
168
|
-
|
|
169
|
-
<
|
|
170
|
-
${
|
|
171
|
-
|
|
172
|
-
${[...sidesOf(axis)].sort((a, b) => a[0].localeCompare(b[0]) || (a[1] === '-' ? -1 : 1)).map(side => html `<label>
|
|
173
|
-
<span>${i18next.t('figure.label.face-' + SIDE_FACE[side])}</span>
|
|
174
|
-
${cavityField(`wall.${side}`, cavity.wall[side], value => ({ wall: { ...cavity.wall, [side]: value } }))}
|
|
175
|
-
</label>`)}
|
|
176
|
-
</div>`
|
|
177
|
-
: cavityField('wall', sameOf(Object.values(cavity.wall)), value => ({ wall: value }))}
|
|
178
|
-
${this.perSide || this.refusals.wall
|
|
179
|
-
? nothing
|
|
180
|
-
: html `<small>${i18next.t('figure.text.section-wall-at-most', { max: String(mm(wallLimitOf(body.shape))) })}</small>`}
|
|
181
|
-
<label toggle>
|
|
182
|
-
<input
|
|
183
|
-
type="checkbox"
|
|
184
|
-
.checked=${live(this.perSide)}
|
|
185
|
-
?disabled=${this.locked}
|
|
186
|
-
@change=${(ev) => (this.perSide = ev.target.checked)}
|
|
187
|
-
/>
|
|
188
|
-
${i18next.t('figure.label.section-wall-per-side')}
|
|
189
|
-
</label>
|
|
190
|
-
</div>
|
|
191
|
-
</div>
|
|
192
|
-
${['start', 'end'].map(end => this.renderEnd(body, axis, end, cavity[end], request, cavityField))}`
|
|
151
|
+
? html `<figure-cavity-drawing .body=${body} .perSide=${this.perSide} ?locked=${this.locked}></figure-cavity-drawing>
|
|
152
|
+
<label toggle>
|
|
153
|
+
<input type="checkbox" .checked=${live(this.perSide)} ?disabled=${this.locked} @change=${(ev) => (this.perSide = ev.target.checked)} />
|
|
154
|
+
${i18next.t('figure.label.section-wall-per-side')}
|
|
155
|
+
</label>`
|
|
193
156
|
: nothing}`;
|
|
194
157
|
}
|
|
195
|
-
renderEnd(body, axis, end, now, request, cavityField) {
|
|
196
|
-
const closed = now !== 'open';
|
|
197
|
-
return html `<div form>
|
|
198
|
-
<label>${i18next.t('figure.label.face-' + END_FACE(axis, end))}</label>
|
|
199
|
-
<div row>
|
|
200
|
-
<select
|
|
201
|
-
.value=${live(closed ? 'closed' : 'open')}
|
|
202
|
-
?disabled=${this.locked}
|
|
203
|
-
@change=${(ev) => {
|
|
204
|
-
const select = ev.target;
|
|
205
|
-
const want = select.value;
|
|
206
|
-
select.value = closed ? 'closed' : 'open';
|
|
207
|
-
this.command({ kind: 'set-cavity', part: body.id, cavity: request({ [end]: want === 'open' ? 'open' : { closed: defaultWallOf(body.shape) } }) });
|
|
208
|
-
}}
|
|
209
|
-
>
|
|
210
|
-
<option value="closed">${i18next.t('figure.label.section-end-closed')}</option>
|
|
211
|
-
<option value="open">${i18next.t('figure.label.section-end-open')}</option>
|
|
212
|
-
</select>
|
|
213
|
-
${closed ? cavityField(`closed.${end}`, now.closed, value => ({ [end]: { closed: value } })) : html `<span></span>`}
|
|
214
|
-
</div>
|
|
215
|
-
</div>`;
|
|
216
|
-
}
|
|
217
158
|
/**
|
|
218
159
|
* A millimetre field. Typing draws the value (or, if the kernel would refuse it, says why under the field and draws the
|
|
219
160
|
* figure as it stands); Enter or leaving sends it once; Esc puts the value back.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-section-panel.js","sourceRoot":"","sources":["../../client/modeller/figure-section-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport { css, html, LitElement, nothing, type PropertyValues } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport type { FigureAuthoringAction, FigureCavityRequest, FigureEvaluatedShape } from '@hatiolab/figure-model'\nimport { SidePanelStyles } from './side-panel-styles.js'\nimport { drawnOf } from './section-drawing.js'\nimport './figure-cavity-drawing.js'\nimport {\n END_FACE,\n SIDE_FACE,\n cavityDepthOf,\n cavityRefusalOf,\n cavityRequestOf,\n cavityResultOf,\n cornerLimitOf,\n cornerRefusalOf,\n defaultWallOf,\n mm,\n sameOf,\n sidesOf,\n sideWallLimitOf,\n wallLimitOf,\n type FigureCavityAsk\n} from './section-controls.js'\n\ntype Axis = 'x' | 'y' | 'z'\ntype End = 'start' | 'end'\ntype Body = { id: string; shape: FigureEvaluatedShape }\n\n/**\n * 단면 — a pushed part's rounded corners and its inside (ADR-0100 §3.3).\n *\n * Corners for a rectangle; an inside for a rectangle or an ellipse, with its walls (one thickness, or one per side when\n * asked for), its two ends open or closed, and what that makes of the part and how deep. A drawn section says beside\n * the inside why it has none. A turned body shows nothing here.\n *\n * A value being typed is drawn at once and recorded nowhere (`command-live`); a value the kernel would refuse is said\n * under its field with the most it can be, and is not sent. Enter or leaving the field sends the one `command`, one step\n * of the undo history; Esc puts the value back.\n */\n@customElement('figure-section-panel')\nexport class FigureSectionPanel extends localize(i18next)(LitElement) {\n static styles = [SidePanelStyles, css`\n :host {\n display: block;\n }\n div[row] {\n display: flex;\n gap: 6px;\n align-items: center;\n }\n div[row] > * {\n flex: 1;\n min-width: 0;\n }\n div[sides] {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 6px;\n /* A side's refusal under its field lengthens its cell only: the field beside it stays level. */\n align-items: start;\n }\n div[sides] > label {\n display: grid;\n gap: 2px;\n }\n small[refusal] {\n color: var(--md-sys-color-error);\n }\n input[aria-invalid='true'] {\n outline: 2px solid var(--md-sys-color-error);\n }\n `]\n\n @property({ attribute: false }) body?: Body\n @property({ type: Boolean }) locked = false\n /** What each field would not take, by field, said under it. */\n @state() private refusals: Record<string, string> = {}\n /** What is typed in a field and not yet sent, by field: the figure drawn with it must not type over it. */\n @state() private typed: Record<string, string> = {}\n /** Walls one per side, asked for or because they already differ. */\n @state() private perSide = false\n\n protected willUpdate(changed: PropertyValues<this>) {\n const before = changed.get('body') as Body | undefined\n if (changed.has('body') && before?.id !== this.body?.id) {\n this.refusals = {}\n this.typed = {}\n /* A part whose walls already differ opens with them one per side. */\n const walls = this.body?.shape.cavity?.wall\n this.perSide = !!walls && sameOf(Object.values(walls)) === undefined\n }\n }\n\n render() {\n const body = this.body\n /* A push, or a pyramid: a drawn section drawn to one point, which has no corners and no inside. */\n const e = body?.shape ? drawnOf(body.shape) : undefined\n if (!body || !e) return nothing\n const kind = e.section.kind\n return html`<section>\n <h3>${i18next.t('figure.label.group-section')}</h3>\n ${body.shape.dimensions.jamb === undefined\n ? html`<div field>\n <button act ?disabled=${this.locked} @click=${() => this.dispatchEvent(new CustomEvent('section-editor-open', { bubbles: true, composed: true }))}>\n <md-icon>edit</md-icon>${i18next.t('figure.button.section-editor-open')}\n </button>\n ${e.section.kind === 'polygon'\n ? html`<small>${i18next.t(e.apex ? 'figure.text.section-points-apex' : 'figure.text.section-points', { points: String(e.section.points.length) })}</small>`\n : nothing}\n </div>`\n : nothing}\n ${kind === 'rectangle' ? this.renderCorner(body) : nothing}\n ${/* No inside for a drawn section: the control is not there, rather than a line saying so. */ kind === 'rectangle' || kind === 'ellipse' ? this.renderCavity(body, e.axis) : nothing}\n </section>`\n }\n\n private renderCorner(body: Body) {\n const d = body.shape.dimensions\n const reaches = Object.keys(d)\n .filter(k => k.startsWith('corner.'))\n .map(k => d[k])\n const now = reaches.length ? sameOf(reaches) : 0\n const max = cornerLimitOf(body.shape)\n return html`<div form>\n <label for=\"corner\">${i18next.t('figure.label.section-corner')}</label>\n <div>\n ${this.number('corner', now, {\n min: 0,\n ask: value => {\n const r = cornerRefusalOf(body.shape, value)\n return r ? i18next.t('figure.text.section-corner-over', { max: String(mm(r.max)) }) : ''\n },\n action: value => ({ kind: 'set-section-corner', part: body.id, corner: value > 0 ? value : null }),\n placeholder: now === undefined ? i18next.t('figure.text.section-corner-differs') : ''\n })}\n ${this.refusals.corner ? nothing : max !== undefined ? html`<small>${i18next.t('figure.text.section-at-most', { max: String(mm(max)) })}</small>` : nothing}\n </div>\n </div>`\n }\n\n private renderCavity(body: Body, axis: Axis) {\n const cavity = body.shape.cavity\n const request = (patch: Partial<FigureCavityRequest>) => cavityRequestOf(body.shape, patch)\n const said = (ask: FigureCavityAsk | null) =>\n !ask\n ? ''\n : ask.code === 'not-positive'\n ? i18next.t('figure.text.section-not-positive')\n : i18next.t(`figure.text.section-${ask.code === 'wall-too-thick' ? 'wall' : 'ends'}-over`, { max: String(ask.max) })\n const cavityField = (key: string, now: number | undefined, patch: (value: number) => Partial<FigureCavityRequest>) =>\n this.number(key, now, {\n min: 0,\n ask: value => {\n if (!(value > 0)) return i18next.t('figure.text.section-not-positive')\n const ask = cavityRefusalOf(body.shape, request(patch(value)))\n /* One side too thick: the most it can be is the width across less the wall opposite, not the even limit. */\n const side = key.startsWith('wall.') ? key.slice(5) : undefined\n if (ask?.code === 'wall-too-thick' && side && cavity)\n return said({ code: 'wall-too-thick', max: mm(sideWallLimitOf(body.shape, cavity.wall, side)) })\n return said(ask)\n },\n action: value => ({ kind: 'set-cavity', part: body.id, cavity: request(patch(value)) })\n })\n return html`<div field>\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${live(!!cavity)}\n ?disabled=${this.locked}\n @change=${(ev: Event) => {\n const on = (ev.target as HTMLInputElement).checked\n ;(ev.target as HTMLInputElement).checked = !!cavity\n this.command({ kind: 'set-cavity', part: body.id, cavity: on ? request({}) : null })\n }}\n />\n ${i18next.t('figure.label.section-cavity')}\n </label>\n ${cavity\n ? html`<small result>\n ${i18next.t('figure.text.section-depth', {\n result: i18next.t(`figure.label.section-result-${cavityResultOf(cavity)}`),\n depth: String(cavityDepthOf(body.shape))\n })}\n </small>`\n : nothing}\n </div>\n ${cavity ? html`<figure-cavity-drawing .body=${body} .perSide=${this.perSide} ?locked=${this.locked}></figure-cavity-drawing>` : nothing}\n ${cavity\n ? html`<div form>\n <label>${i18next.t('figure.label.section-wall')}</label>\n <div>\n ${this.perSide\n ? html`<div sides>\n ${[...sidesOf(axis)].sort((a, b) => a[0]!.localeCompare(b[0]!) || (a[1] === '-' ? -1 : 1)).map(\n side => html`<label>\n <span>${i18next.t('figure.label.face-' + SIDE_FACE[side])}</span>\n ${cavityField(`wall.${side}`, cavity.wall[side], value => ({ wall: { ...cavity.wall, [side]: value } }))}\n </label>`\n )}\n </div>`\n : cavityField('wall', sameOf(Object.values(cavity.wall)), value => ({ wall: value }))}\n ${this.perSide || this.refusals.wall\n ? nothing\n : html`<small>${i18next.t('figure.text.section-wall-at-most', { max: String(mm(wallLimitOf(body.shape))) })}</small>`}\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${live(this.perSide)}\n ?disabled=${this.locked}\n @change=${(ev: Event) => (this.perSide = (ev.target as HTMLInputElement).checked)}\n />\n ${i18next.t('figure.label.section-wall-per-side')}\n </label>\n </div>\n </div>\n ${(['start', 'end'] as const).map(end => this.renderEnd(body, axis, end, cavity[end], request, cavityField))}`\n : nothing}`\n }\n\n private renderEnd(\n body: Body,\n axis: Axis,\n end: End,\n now: 'open' | { closed: number },\n request: (patch: Partial<FigureCavityRequest>) => FigureCavityRequest,\n cavityField: (key: string, now: number | undefined, patch: (value: number) => Partial<FigureCavityRequest>) => unknown\n ) {\n const closed = now !== 'open'\n return html`<div form>\n <label>${i18next.t('figure.label.face-' + END_FACE(axis, end))}</label>\n <div row>\n <select\n .value=${live(closed ? 'closed' : 'open')}\n ?disabled=${this.locked}\n @change=${(ev: Event) => {\n const select = ev.target as HTMLSelectElement\n const want = select.value\n select.value = closed ? 'closed' : 'open'\n this.command({ kind: 'set-cavity', part: body.id, cavity: request({ [end]: want === 'open' ? 'open' : { closed: defaultWallOf(body.shape) } }) })\n }}\n >\n <option value=\"closed\">${i18next.t('figure.label.section-end-closed')}</option>\n <option value=\"open\">${i18next.t('figure.label.section-end-open')}</option>\n </select>\n ${closed ? cavityField(`closed.${end}`, now.closed, value => ({ [end]: { closed: value } })) : html`<span></span>`}\n </div>\n </div>`\n }\n\n /**\n * A millimetre field. Typing draws the value (or, if the kernel would refuse it, says why under the field and draws the\n * figure as it stands); Enter or leaving sends it once; Esc puts the value back.\n */\n private number(\n key: string,\n now: number | undefined,\n o: { min: number; ask: (value: number) => string; action: (value: number) => FigureAuthoringAction; placeholder?: string }\n ) {\n const shown = now === undefined ? '' : String(mm(now))\n const done = () => {\n const { [key]: _, ...rest } = this.typed\n this.typed = rest\n }\n const read = (input: HTMLInputElement) => (input.value === '' ? NaN : Number(input.value))\n const judge = (input: HTMLInputElement) => {\n const value = read(input)\n const refusal = !Number.isFinite(value) || value < o.min ? '' : o.ask(value)\n this.refusals = { ...this.refusals, [key]: refusal }\n return Number.isFinite(value) && value >= o.min && !refusal ? value : undefined\n }\n return html`<input\n id=${key}\n type=\"number\"\n min=${o.min}\n step=\"any\"\n inputmode=\"decimal\"\n .value=${live(this.typed[key] ?? shown)}\n placeholder=${o.placeholder ?? ''}\n aria-invalid=${this.refusals[key] ? 'true' : 'false'}\n aria-describedby=${`${key}-refusal`}\n ?disabled=${this.locked}\n @input=${(ev: Event) => {\n this.typed = { ...this.typed, [key]: (ev.target as HTMLInputElement).value }\n const value = judge(ev.target as HTMLInputElement)\n this.preview(value === undefined ? null : o.action(value))\n }}\n @change=${(ev: Event) => {\n const input = ev.target as HTMLInputElement\n if (input.value === shown) return done(), this.preview(null)\n const value = judge(input)\n /* A refused value stays typed with its reason under it, to be corrected; nothing is sent. */\n if (value === undefined) return this.preview(null)\n done()\n this.command(o.action(value))\n }}\n @keydown=${(ev: KeyboardEvent) => {\n if (ev.key !== 'Escape') return\n const input = ev.target as HTMLInputElement\n input.value = shown\n done()\n this.refusals = { ...this.refusals, [key]: '' }\n this.preview(null)\n }}\n />\n ${this.refusals[key] ? html`<small refusal id=${`${key}-refusal`} role=\"alert\">${this.refusals[key]}</small>` : nothing}`\n }\n\n private preview(action: FigureAuthoringAction | null) {\n this.dispatchEvent(new CustomEvent('command-live', { detail: { action }, bubbles: true, composed: true }))\n }\n\n private command(action: FigureAuthoringAction) {\n this.dispatchEvent(new CustomEvent('command', { detail: { action }, bubbles: true, composed: true }))\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-section-panel.js","sourceRoot":"","sources":["../../client/modeller/figure-section-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport { css, html, LitElement, nothing, type PropertyValues } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport type { FigureAuthoringAction, FigureEvaluatedShape } from '@hatiolab/figure-model'\nimport { SidePanelStyles } from './side-panel-styles.js'\nimport { drawnOf } from './section-drawing.js'\nimport './figure-cavity-drawing.js'\nimport { cavityDepthOf, cavityRequestOf, cavityResultOf, cornerLimitOf, cornerRefusalOf, mm, sameOf } from './section-controls.js'\n\ntype Body = { id: string; shape: FigureEvaluatedShape }\n\n/**\n * 단면 — a pushed part's rounded corners and its inside (ADR-0100 §3.3).\n *\n * Corners for a rectangle; an inside for a rectangle or an ellipse, with its walls (one thickness, or one per side when\n * asked for), its two ends open or closed, and what that makes of the part and how deep. A drawn section says beside\n * the inside why it has none. A turned body shows nothing here.\n *\n * A value being typed is drawn at once and recorded nowhere (`command-live`); a value the kernel would refuse is said\n * under its field with the most it can be, and is not sent. Enter or leaving the field sends the one `command`, one step\n * of the undo history; Esc puts the value back.\n */\n@customElement('figure-section-panel')\nexport class FigureSectionPanel extends localize(i18next)(LitElement) {\n static styles = [SidePanelStyles, css`\n :host {\n display: block;\n }\n div[row] {\n display: flex;\n gap: 6px;\n align-items: center;\n }\n div[row] > * {\n flex: 1;\n min-width: 0;\n }\n div[sides] {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 6px;\n /* A side's refusal under its field lengthens its cell only: the field beside it stays level. */\n align-items: start;\n }\n div[sides] > label {\n display: grid;\n gap: 2px;\n }\n small[refusal] {\n color: var(--md-sys-color-error);\n }\n input[aria-invalid='true'] {\n outline: 2px solid var(--md-sys-color-error);\n }\n `]\n\n @property({ attribute: false }) body?: Body\n @property({ type: Boolean }) locked = false\n /** What each field would not take, by field, said under it. */\n @state() private refusals: Record<string, string> = {}\n /** What is typed in a field and not yet sent, by field: the figure drawn with it must not type over it. */\n @state() private typed: Record<string, string> = {}\n /** Walls one per side, asked for or because they already differ. */\n @state() private perSide = false\n\n protected willUpdate(changed: PropertyValues<this>) {\n const before = changed.get('body') as Body | undefined\n if (changed.has('body') && before?.id !== this.body?.id) {\n this.refusals = {}\n this.typed = {}\n /* A part whose walls already differ opens with them one per side. */\n const walls = this.body?.shape.cavity?.wall\n this.perSide = !!walls && sameOf(Object.values(walls)) === undefined\n }\n }\n\n render() {\n const body = this.body\n /* A push, or a pyramid: a drawn section drawn to one point, which has no corners and no inside. */\n const e = body?.shape ? drawnOf(body.shape) : undefined\n if (!body || !e) return nothing\n const kind = e.section.kind\n return html`<section>\n <h3>${i18next.t('figure.label.group-section')}</h3>\n ${body.shape.dimensions.jamb === undefined\n ? html`<div field>\n <button act ?disabled=${this.locked} @click=${() => this.dispatchEvent(new CustomEvent('section-editor-open', { bubbles: true, composed: true }))}>\n <md-icon>edit</md-icon>${i18next.t('figure.button.section-editor-open')}\n </button>\n ${e.section.kind === 'polygon'\n ? html`<small>${i18next.t(e.apex ? 'figure.text.section-points-apex' : 'figure.text.section-points', { points: String(e.section.points.length) })}</small>`\n : nothing}\n </div>`\n : nothing}\n ${kind === 'rectangle' ? this.renderCorner(body) : nothing}\n ${/* No inside for a drawn section: the control is not there, rather than a line saying so. */ kind === 'rectangle' || kind === 'ellipse' ? this.renderCavity(body) : nothing}\n </section>`\n }\n\n private renderCorner(body: Body) {\n const d = body.shape.dimensions\n const reaches = Object.keys(d)\n .filter(k => k.startsWith('corner.'))\n .map(k => d[k])\n const now = reaches.length ? sameOf(reaches) : 0\n const max = cornerLimitOf(body.shape)\n return html`<div form>\n <label for=\"corner\">${i18next.t('figure.label.section-corner')}</label>\n <div>\n ${this.number('corner', now, {\n min: 0,\n ask: value => {\n const r = cornerRefusalOf(body.shape, value)\n return r ? i18next.t('figure.text.section-corner-over', { max: String(mm(r.max)) }) : ''\n },\n action: value => ({ kind: 'set-section-corner', part: body.id, corner: value > 0 ? value : null }),\n placeholder: now === undefined ? i18next.t('figure.text.section-corner-differs') : ''\n })}\n ${this.refusals.corner ? nothing : max !== undefined ? html`<small>${i18next.t('figure.text.section-at-most', { max: String(mm(max)) })}</small>` : nothing}\n </div>\n </div>`\n }\n\n /*\n * The inside: made or taken away here, and drawn -- walls dragged or their number pressed and typed, ends pressed\n * open or closed (figure-cavity-drawing). The number fields under the drawing went (user 2026-10-01): they said the\n * drawing again.\n */\n private renderCavity(body: Body) {\n const cavity = body.shape.cavity\n return html`<div field>\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${live(!!cavity)}\n ?disabled=${this.locked}\n @change=${(ev: Event) => {\n const on = (ev.target as HTMLInputElement).checked\n ;(ev.target as HTMLInputElement).checked = !!cavity\n this.command({ kind: 'set-cavity', part: body.id, cavity: on ? cavityRequestOf(body.shape, {}) : null })\n }}\n />\n ${i18next.t('figure.label.section-cavity')}\n </label>\n ${cavity\n ? html`<small result>\n ${i18next.t('figure.text.section-depth', {\n result: i18next.t(`figure.label.section-result-${cavityResultOf(cavity)}`),\n depth: String(cavityDepthOf(body.shape))\n })}\n </small>`\n : nothing}\n </div>\n ${cavity\n ? html`<figure-cavity-drawing .body=${body} .perSide=${this.perSide} ?locked=${this.locked}></figure-cavity-drawing>\n <label toggle>\n <input type=\"checkbox\" .checked=${live(this.perSide)} ?disabled=${this.locked} @change=${(ev: Event) => (this.perSide = (ev.target as HTMLInputElement).checked)} />\n ${i18next.t('figure.label.section-wall-per-side')}\n </label>`\n : nothing}`\n }\n\n /**\n * A millimetre field. Typing draws the value (or, if the kernel would refuse it, says why under the field and draws the\n * figure as it stands); Enter or leaving sends it once; Esc puts the value back.\n */\n private number(\n key: string,\n now: number | undefined,\n o: { min: number; ask: (value: number) => string; action: (value: number) => FigureAuthoringAction; placeholder?: string }\n ) {\n const shown = now === undefined ? '' : String(mm(now))\n const done = () => {\n const { [key]: _, ...rest } = this.typed\n this.typed = rest\n }\n const read = (input: HTMLInputElement) => (input.value === '' ? NaN : Number(input.value))\n const judge = (input: HTMLInputElement) => {\n const value = read(input)\n const refusal = !Number.isFinite(value) || value < o.min ? '' : o.ask(value)\n this.refusals = { ...this.refusals, [key]: refusal }\n return Number.isFinite(value) && value >= o.min && !refusal ? value : undefined\n }\n return html`<input\n id=${key}\n type=\"number\"\n min=${o.min}\n step=\"any\"\n inputmode=\"decimal\"\n .value=${live(this.typed[key] ?? shown)}\n placeholder=${o.placeholder ?? ''}\n aria-invalid=${this.refusals[key] ? 'true' : 'false'}\n aria-describedby=${`${key}-refusal`}\n ?disabled=${this.locked}\n @input=${(ev: Event) => {\n this.typed = { ...this.typed, [key]: (ev.target as HTMLInputElement).value }\n const value = judge(ev.target as HTMLInputElement)\n this.preview(value === undefined ? null : o.action(value))\n }}\n @change=${(ev: Event) => {\n const input = ev.target as HTMLInputElement\n if (input.value === shown) return done(), this.preview(null)\n const value = judge(input)\n /* A refused value stays typed with its reason under it, to be corrected; nothing is sent. */\n if (value === undefined) return this.preview(null)\n done()\n this.command(o.action(value))\n }}\n @keydown=${(ev: KeyboardEvent) => {\n if (ev.key !== 'Escape') return\n const input = ev.target as HTMLInputElement\n input.value = shown\n done()\n this.refusals = { ...this.refusals, [key]: '' }\n this.preview(null)\n }}\n />\n ${this.refusals[key] ? html`<small refusal id=${`${key}-refusal`} role=\"alert\">${this.refusals[key]}</small>` : nothing}`\n }\n\n private preview(action: FigureAuthoringAction | null) {\n this.dispatchEvent(new CustomEvent('command-live', { detail: { action }, bubbles: true, composed: true }))\n }\n\n private command(action: FigureAuthoringAction) {\n this.dispatchEvent(new CustomEvent('command', { detail: { action }, bubbles: true, composed: true }))\n }\n}\n"]}
|