@things-factory/figure-ui 10.1.93 → 10.1.94
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.
|
@@ -22,6 +22,7 @@ const SEEN: Array<[FigureFace, string]> = [
|
|
|
22
22
|
['right', 'M160 30 L200 10 L200 80 L160 100 Z']
|
|
23
23
|
]
|
|
24
24
|
/** The faces the drawing cannot show on the box, as tags beside it where they are. */
|
|
25
|
+
/* The box is drawn a little left of its picture's middle, and the viewBox shifts it back to the panel's centre. */
|
|
25
26
|
const HIDDEN: Array<[FigureFace, number, number]> = [
|
|
26
27
|
['bottom', 30, 114],
|
|
27
28
|
['left', 24, 62],
|
|
@@ -64,9 +65,15 @@ export class FigureFastenDrawing extends localize(i18next)(LitElement) {
|
|
|
64
65
|
grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
|
|
65
66
|
gap: 6px;
|
|
66
67
|
}
|
|
68
|
+
div[modes] svg {
|
|
69
|
+
width: 64px;
|
|
70
|
+
height: 44px;
|
|
71
|
+
}
|
|
67
72
|
div[modes] button {
|
|
68
73
|
display: grid;
|
|
69
74
|
justify-items: center;
|
|
75
|
+
align-content: center;
|
|
76
|
+
gap: 2px;
|
|
70
77
|
padding: 2px 4px 4px;
|
|
71
78
|
font: inherit;
|
|
72
79
|
font-size: 0.72rem;
|
|
@@ -135,11 +142,8 @@ export class FigureFastenDrawing extends localize(i18next)(LitElement) {
|
|
|
135
142
|
|
|
136
143
|
/** The target box, its faces pressed; or the plane. */
|
|
137
144
|
private renderTarget() {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<path d="M30 80 L110 30 L270 30 L190 80 Z" style="fill:var(--md-sys-color-primary);fill-opacity:.35;stroke:var(--md-sys-color-primary);stroke-width:1.5" />
|
|
141
|
-
<text x="150" y="62" text-anchor="middle" font-size="12" style="fill:var(--md-sys-color-on-primary-container)">${this.planeWord}</text>
|
|
142
|
-
</svg>`
|
|
145
|
+
/* The plane is one face, named in the list and on the face drawn below: nothing to pick, so no picture of it. */
|
|
146
|
+
if (!this.target) return nothing
|
|
143
147
|
const has = (f: string) => this.faces.includes(f)
|
|
144
148
|
/* A press is a whole change, as a drag let go is: the form applies a fastening the part already has. */
|
|
145
149
|
const pick = (f: string) => () => {
|
|
@@ -150,7 +154,7 @@ export class FigureFastenDrawing extends localize(i18next)(LitElement) {
|
|
|
150
154
|
const seen = SEEN.map(([f, d]) => {
|
|
151
155
|
const on = this.face === f
|
|
152
156
|
return svg`<path face=${f} d=${d} @click=${pick(f)}
|
|
153
|
-
style=${`cursor:${has(f) ? 'pointer' : 'default'};fill:${on ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-
|
|
157
|
+
style=${`cursor:${has(f) ? 'pointer' : 'default'};fill:${on ? 'var(--md-sys-color-primary-container)' : 'var(--md-sys-color-surface-container)'};fill-opacity:${has(f) ? 1 : 0.4};stroke:${on ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-outline)'};stroke-width:${on ? 2 : 1}`}>
|
|
154
158
|
<title>${i18next.t('figure.label.face-' + f)}</title></path>`
|
|
155
159
|
})
|
|
156
160
|
const hidden = HIDDEN.map(([f, x, y]) => {
|
|
@@ -163,9 +167,9 @@ export class FigureFastenDrawing extends localize(i18next)(LitElement) {
|
|
|
163
167
|
})
|
|
164
168
|
/* A shape's faces beyond its six outer ones -- a door frame's opening -- are tags of their own under the box. */
|
|
165
169
|
const others = this.faces.filter(f => !SEEN.some(([s]) => s === f) && !HIDDEN.some(([h]) => h === f))
|
|
166
|
-
return html`${svg`<svg viewBox="
|
|
170
|
+
return html`${svg`<svg viewBox="-20 0 ${PANEL_W} 126" role="img" aria-label=${this.target}>
|
|
167
171
|
${seen}
|
|
168
|
-
<text x="110" y="70" text-anchor="middle" font-size="12" pointer-events="none" style="fill:var(--md-sys-color-on-
|
|
172
|
+
<text x="110" y="70" text-anchor="middle" font-size="12" pointer-events="none" style="fill:var(--md-sys-color-on-surface)">${this.target}</text>
|
|
169
173
|
${hidden}
|
|
170
174
|
</svg>`}
|
|
171
175
|
${others.length
|
|
@@ -177,17 +181,19 @@ export class FigureFastenDrawing extends localize(i18next)(LitElement) {
|
|
|
177
181
|
|
|
178
182
|
/** How: three side views; the chosen one's gap is dragged. */
|
|
179
183
|
private renderModes() {
|
|
184
|
+
/* One way only (the plane is set on): the sentence says it; a single choice is not offered as a button. */
|
|
185
|
+
if (this.modes.length < 2) return nothing
|
|
180
186
|
const icon = (m: FastenMode, on: boolean) => {
|
|
181
187
|
const g = on && m !== 'centre' ? Math.min(this.gap / 4, 10) : 0
|
|
182
188
|
const base = svg`<rect x="6" y="30" width="52" height="14" style="fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary)" />`
|
|
183
189
|
const gapDrag = on && !this.locked ? 'ns-resize' : 'pointer'
|
|
184
190
|
if (m === 'meet')
|
|
185
|
-
return svg`<svg
|
|
191
|
+
return svg`<svg viewBox="0 0 64 48">${base}<rect gap x="22" y=${18 - g} width="20" height="12" style=${`fill:var(--md-sys-color-surface);stroke:currentColor;cursor:${gapDrag}`} />
|
|
186
192
|
${g ? svg`<text x="46" y=${26 - g / 2} font-size="10" style="fill:currentColor">${this.gap}</text>` : nothing}</svg>`
|
|
187
193
|
if (m === 'flush')
|
|
188
|
-
return svg`<svg
|
|
194
|
+
return svg`<svg viewBox="0 0 64 48">${base}<rect gap x="22" y=${30 - g} width="20" height="10" style=${`fill:var(--md-sys-color-surface);stroke:currentColor;cursor:${gapDrag}`} />
|
|
189
195
|
<line x1="4" y1="30" x2="60" y2="30" style="stroke:currentColor;stroke-dasharray:2 2" /></svg>`
|
|
190
|
-
return svg`<svg
|
|
196
|
+
return svg`<svg viewBox="0 0 64 48">${base}<circle cx="32" cy="30" r="11" style="fill:var(--md-sys-color-surface);fill-opacity:.85;stroke:currentColor" /><circle cx="32" cy="30" r="2" style="fill:currentColor" /></svg>`
|
|
191
197
|
}
|
|
192
198
|
return html`<div modes>
|
|
193
199
|
${this.modes.map(m => {
|
|
@@ -300,8 +306,8 @@ export class FigureFastenDrawing extends localize(i18next)(LitElement) {
|
|
|
300
306
|
@pointermove=${(ev: PointerEvent) => this.drag(ev, view, cx, cy)}
|
|
301
307
|
@pointerup=${() => this.drop()} @pointercancel=${() => this.drop()}>
|
|
302
308
|
${faceSized
|
|
303
|
-
? svg`<rect x=${fx} y=${fy} width=${fw} height=${fh} rx="
|
|
304
|
-
: svg`<rect x="
|
|
309
|
+
? svg`<rect x=${fx} y=${fy} width=${fw} height=${fh} rx="4" style="fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary);stroke-width:2" />`
|
|
310
|
+
: svg`<rect x="1" y="1" width=${W - 2} height=${H - 2} rx="8" style="fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary);stroke-width:2" />`}
|
|
305
311
|
<text x=${faceSized ? fx + 4 : 10} y=${faceSized ? fy + fh - 6 : 18} font-size="11" pointer-events="none" style="fill:var(--md-sys-color-primary)">${faceName}${sizeWords}</text>
|
|
306
312
|
${guide(h)}${guide(v)}
|
|
307
313
|
<g footprint style=${`cursor:${this.locked ? 'default' : 'grab'}`} @pointerdown=${(ev: PointerEvent) => this.grab(ev, at, caught)}>
|
|
@@ -9,6 +9,7 @@ const SEEN = [
|
|
|
9
9
|
['right', 'M160 30 L200 10 L200 80 L160 100 Z']
|
|
10
10
|
];
|
|
11
11
|
/** The faces the drawing cannot show on the box, as tags beside it where they are. */
|
|
12
|
+
/* The box is drawn a little left of its picture's middle, and the viewBox shifts it back to the panel's centre. */
|
|
12
13
|
const HIDDEN = [
|
|
13
14
|
['bottom', 30, 114],
|
|
14
15
|
['left', 24, 62],
|
|
@@ -68,9 +69,15 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
|
|
|
68
69
|
grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
|
|
69
70
|
gap: 6px;
|
|
70
71
|
}
|
|
72
|
+
div[modes] svg {
|
|
73
|
+
width: 64px;
|
|
74
|
+
height: 44px;
|
|
75
|
+
}
|
|
71
76
|
div[modes] button {
|
|
72
77
|
display: grid;
|
|
73
78
|
justify-items: center;
|
|
79
|
+
align-content: center;
|
|
80
|
+
gap: 2px;
|
|
74
81
|
padding: 2px 4px 4px;
|
|
75
82
|
font: inherit;
|
|
76
83
|
font-size: 0.72rem;
|
|
@@ -112,11 +119,9 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
|
|
|
112
119
|
}
|
|
113
120
|
/** The target box, its faces pressed; or the plane. */
|
|
114
121
|
renderTarget() {
|
|
122
|
+
/* The plane is one face, named in the list and on the face drawn below: nothing to pick, so no picture of it. */
|
|
115
123
|
if (!this.target)
|
|
116
|
-
return
|
|
117
|
-
<path d="M30 80 L110 30 L270 30 L190 80 Z" style="fill:var(--md-sys-color-primary);fill-opacity:.35;stroke:var(--md-sys-color-primary);stroke-width:1.5" />
|
|
118
|
-
<text x="150" y="62" text-anchor="middle" font-size="12" style="fill:var(--md-sys-color-on-primary-container)">${this.planeWord}</text>
|
|
119
|
-
</svg>`;
|
|
124
|
+
return nothing;
|
|
120
125
|
const has = (f) => this.faces.includes(f);
|
|
121
126
|
/* A press is a whole change, as a drag let go is: the form applies a fastening the part already has. */
|
|
122
127
|
const pick = (f) => () => {
|
|
@@ -128,7 +133,7 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
|
|
|
128
133
|
const seen = SEEN.map(([f, d]) => {
|
|
129
134
|
const on = this.face === f;
|
|
130
135
|
return svg `<path face=${f} d=${d} @click=${pick(f)}
|
|
131
|
-
style=${`cursor:${has(f) ? 'pointer' : 'default'};fill:${on ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-
|
|
136
|
+
style=${`cursor:${has(f) ? 'pointer' : 'default'};fill:${on ? 'var(--md-sys-color-primary-container)' : 'var(--md-sys-color-surface-container)'};fill-opacity:${has(f) ? 1 : 0.4};stroke:${on ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-outline)'};stroke-width:${on ? 2 : 1}`}>
|
|
132
137
|
<title>${i18next.t('figure.label.face-' + f)}</title></path>`;
|
|
133
138
|
});
|
|
134
139
|
const hidden = HIDDEN.map(([f, x, y]) => {
|
|
@@ -141,9 +146,9 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
|
|
|
141
146
|
});
|
|
142
147
|
/* A shape's faces beyond its six outer ones -- a door frame's opening -- are tags of their own under the box. */
|
|
143
148
|
const others = this.faces.filter(f => !SEEN.some(([s]) => s === f) && !HIDDEN.some(([h]) => h === f));
|
|
144
|
-
return html `${svg `<svg viewBox="
|
|
149
|
+
return html `${svg `<svg viewBox="-20 0 ${PANEL_W} 126" role="img" aria-label=${this.target}>
|
|
145
150
|
${seen}
|
|
146
|
-
<text x="110" y="70" text-anchor="middle" font-size="12" pointer-events="none" style="fill:var(--md-sys-color-on-
|
|
151
|
+
<text x="110" y="70" text-anchor="middle" font-size="12" pointer-events="none" style="fill:var(--md-sys-color-on-surface)">${this.target}</text>
|
|
147
152
|
${hidden}
|
|
148
153
|
</svg>`}
|
|
149
154
|
${others.length
|
|
@@ -154,17 +159,20 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
|
|
|
154
159
|
}
|
|
155
160
|
/** How: three side views; the chosen one's gap is dragged. */
|
|
156
161
|
renderModes() {
|
|
162
|
+
/* One way only (the plane is set on): the sentence says it; a single choice is not offered as a button. */
|
|
163
|
+
if (this.modes.length < 2)
|
|
164
|
+
return nothing;
|
|
157
165
|
const icon = (m, on) => {
|
|
158
166
|
const g = on && m !== 'centre' ? Math.min(this.gap / 4, 10) : 0;
|
|
159
167
|
const base = svg `<rect x="6" y="30" width="52" height="14" style="fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary)" />`;
|
|
160
168
|
const gapDrag = on && !this.locked ? 'ns-resize' : 'pointer';
|
|
161
169
|
if (m === 'meet')
|
|
162
|
-
return svg `<svg
|
|
170
|
+
return svg `<svg viewBox="0 0 64 48">${base}<rect gap x="22" y=${18 - g} width="20" height="12" style=${`fill:var(--md-sys-color-surface);stroke:currentColor;cursor:${gapDrag}`} />
|
|
163
171
|
${g ? svg `<text x="46" y=${26 - g / 2} font-size="10" style="fill:currentColor">${this.gap}</text>` : nothing}</svg>`;
|
|
164
172
|
if (m === 'flush')
|
|
165
|
-
return svg `<svg
|
|
173
|
+
return svg `<svg viewBox="0 0 64 48">${base}<rect gap x="22" y=${30 - g} width="20" height="10" style=${`fill:var(--md-sys-color-surface);stroke:currentColor;cursor:${gapDrag}`} />
|
|
166
174
|
<line x1="4" y1="30" x2="60" y2="30" style="stroke:currentColor;stroke-dasharray:2 2" /></svg>`;
|
|
167
|
-
return svg `<svg
|
|
175
|
+
return svg `<svg viewBox="0 0 64 48">${base}<circle cx="32" cy="30" r="11" style="fill:var(--md-sys-color-surface);fill-opacity:.85;stroke:currentColor" /><circle cx="32" cy="30" r="2" style="fill:currentColor" /></svg>`;
|
|
168
176
|
};
|
|
169
177
|
return html `<div modes>
|
|
170
178
|
${this.modes.map(m => {
|
|
@@ -278,8 +286,8 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
|
|
|
278
286
|
@pointermove=${(ev) => this.drag(ev, view, cx, cy)}
|
|
279
287
|
@pointerup=${() => this.drop()} @pointercancel=${() => this.drop()}>
|
|
280
288
|
${faceSized
|
|
281
|
-
? svg `<rect x=${fx} y=${fy} width=${fw} height=${fh} rx="
|
|
282
|
-
: svg `<rect x="
|
|
289
|
+
? svg `<rect x=${fx} y=${fy} width=${fw} height=${fh} rx="4" style="fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary);stroke-width:2" />`
|
|
290
|
+
: svg `<rect x="1" y="1" width=${W - 2} height=${H - 2} rx="8" style="fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary);stroke-width:2" />`}
|
|
283
291
|
<text x=${faceSized ? fx + 4 : 10} y=${faceSized ? fy + fh - 6 : 18} font-size="11" pointer-events="none" style="fill:var(--md-sys-color-primary)">${faceName}${sizeWords}</text>
|
|
284
292
|
${guide(h)}${guide(v)}
|
|
285
293
|
<g footprint style=${`cursor:${this.locked ? 'default' : 'grab'}`} @pointerdown=${(ev) => this.grab(ev, at, caught)}>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-fasten-drawing.js","sourceRoot":"","sources":["../../client/modeller/figure-fasten-drawing.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing, svg } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport type { FigureFace } from '@hatiolab/figure-model'\n\nimport { alignmentAt, offsetOf, overhangOf, screenOf, type FaceView, type FastenMode } from './fasten-geometry.js'\nimport type { Alignment } from './links.js'\n\ntype Axis = 'x' | 'y' | 'z'\n\n/** A change the drawing asks of the fastening form. */\nexport type FastenChange =\n | { targetFace: string }\n | { mode: FastenMode }\n | { axis: Axis; how: Alignment; mm?: number }\n | { gap: number }\n\nconst SEEN: Array<[FigureFace, string]> = [\n ['top', 'M60 30 L100 10 L200 10 L160 30 Z'],\n ['front', 'M60 30 L160 30 L160 100 L60 100 Z'],\n ['right', 'M160 30 L200 10 L200 80 L160 100 Z']\n]\n/** The faces the drawing cannot show on the box, as tags beside it where they are. */\nconst HIDDEN: Array<[FigureFace, number, number]> = [\n ['bottom', 30, 114],\n ['left', 24, 62],\n ['back', 236, 14]\n]\nconst PANEL_W = 300\n\n\n/**\n * 붙이기 그림 (user 2026-10-01) — which face of what the part is fastened to, how, and where on it; each of them chosen\n * by pressing or dragging the drawing, none by a list of faces.\n *\n * The target is drawn as a box whose faces are pressed (the three it hides as tags beside it), or as the one plane the\n * figure stands by. How is three small side views -- set on it, flush with it, its centre on it (only for a part that\n * turns about a joint) -- and the chosen one's gap is dragged. Where is the face seen from above with the part's\n * footprint on it: dragged, caught at the centre and at the edges from inside and outside, a guide drawn where it is\n * caught and a dimension where it is not, which is pressed to type the number. It may go past the edges: the part that\n * does is shaded, and a part off the face altogether is said so. Nothing is decided here: every change goes to the form\n * (`fasten-change`), and a press or a drag let go says so (`fasten-release`), for the form to apply a fastening it holds.\n */\n@customElement('figure-fasten-drawing')\nexport class FigureFastenDrawing extends localize(i18next)(LitElement) {\n static styles = css`\n :host {\n display: grid;\n gap: 8px;\n outline: none;\n }\n svg {\n width: 100%;\n display: block;\n touch-action: none;\n user-select: none;\n }\n svg text {\n font: inherit;\n }\n div[modes] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));\n gap: 6px;\n }\n div[modes] button {\n display: grid;\n justify-items: center;\n padding: 2px 4px 4px;\n font: inherit;\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n cursor: pointer;\n }\n div[modes] button[on] {\n border: 1.5px solid var(--md-sys-color-primary);\n background: var(--md-sys-color-primary-container);\n color: var(--md-sys-color-on-primary-container);\n }\n div[where] {\n position: relative;\n }\n div[where] input {\n position: absolute;\n width: 72px;\n font: inherit;\n font-size: 0.75rem;\n }\n small[warn] {\n color: var(--md-sys-color-tertiary);\n }\n small[off] {\n color: var(--md-sys-color-error);\n }\n `\n\n /** The target's name, or empty for the plane the figure stands by. */\n @property() target = ''\n /** The plane's name by the figure's placement: 바닥 · 천장 · 벽 · 중심. */\n @property() planeWord = ''\n @property({ attribute: false }) faces: string[] = []\n @property() face = ''\n @property({ attribute: false }) modes: FastenMode[] = ['meet', 'flush']\n @property() mode: FastenMode = 'meet'\n @property({ attribute: false }) view?: FaceView\n @property({ attribute: false }) align: Partial<Record<Axis, Alignment>> = {}\n @property({ attribute: false }) alignMm: Partial<Record<Axis, number>> = {}\n @property({ type: Number }) gap = 0\n /** The part being fastened (not `part`: that is every element's own). */\n @property() partName = ''\n @property({ type: Boolean }) locked = false\n /** The form already says how the fastening it has lies on the face: the drawing says it only while dragging. */\n @property({ type: Boolean }) said = false\n\n /** Where the footprint is while dragging, and what it is caught by; undefined when nothing is dragged. */\n @state() private dragged?: { at: Record<Axis, number>; caught: Partial<Record<Axis, string>> }\n @state() private typing?: Axis\n private scale = 1\n private gapFrom?: { y: number; gap: number }\n\n private change(detail: FastenChange) {\n this.dispatchEvent(new CustomEvent('fasten-change', { detail, bubbles: true, composed: true }))\n }\n private released() {\n this.dispatchEvent(new CustomEvent('fasten-release', { bubbles: true, composed: true }))\n }\n\n render() {\n return html`${this.renderTarget()}${this.renderModes()}${this.renderWhere()}`\n }\n\n /** The target box, its faces pressed; or the plane. */\n private renderTarget() {\n if (!this.target)\n return svg`<svg viewBox=\"0 0 ${PANEL_W} 90\" role=\"img\" aria-label=${this.planeWord}>\n <path d=\"M30 80 L110 30 L270 30 L190 80 Z\" style=\"fill:var(--md-sys-color-primary);fill-opacity:.35;stroke:var(--md-sys-color-primary);stroke-width:1.5\" />\n <text x=\"150\" y=\"62\" text-anchor=\"middle\" font-size=\"12\" style=\"fill:var(--md-sys-color-on-primary-container)\">${this.planeWord}</text>\n </svg>`\n const has = (f: string) => this.faces.includes(f)\n /* A press is a whole change, as a drag let go is: the form applies a fastening the part already has. */\n const pick = (f: string) => () => {\n if (this.locked || !has(f) || f === this.face) return\n this.change({ targetFace: f })\n this.released()\n }\n const seen = SEEN.map(([f, d]) => {\n const on = this.face === f\n return svg`<path face=${f} d=${d} @click=${pick(f)}\n style=${`cursor:${has(f) ? 'pointer' : 'default'};fill:${on ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-primary-container)'};fill-opacity:${on ? 0.55 : has(f) ? 1 : 0.35};stroke:var(--md-sys-color-primary);stroke-width:1.5`}>\n <title>${i18next.t('figure.label.face-' + f)}</title></path>`\n })\n const hidden = HIDDEN.map(([f, x, y]) => {\n const on = this.face === f\n return svg`<g face=${f} @click=${pick(f)} style=${`cursor:${has(f) ? 'pointer' : 'default'};opacity:${has(f) ? 1 : 0.35}`}>\n <rect x=${x - 26} y=${y - 10} width=\"52\" height=\"20\" rx=\"10\"\n style=${`fill:${on ? 'var(--md-sys-color-primary-container)' : 'transparent'};stroke:${on ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-outline)'};stroke-dasharray:${on ? '' : '3 2'}`} />\n <text x=${x} y=${y + 4} text-anchor=\"middle\" font-size=\"11\" style=${`fill:${on ? 'var(--md-sys-color-on-primary-container)' : 'var(--md-sys-color-on-surface-variant)'}`}>${i18next.t('figure.label.face-' + f)}</text>\n </g>`\n })\n /* A shape's faces beyond its six outer ones -- a door frame's opening -- are tags of their own under the box. */\n const others = this.faces.filter(f => !SEEN.some(([s]) => s === f) && !HIDDEN.some(([h]) => h === f))\n return html`${svg`<svg viewBox=\"0 0 ${PANEL_W} 126\" role=\"img\" aria-label=${this.target}>\n ${seen}\n <text x=\"110\" y=\"70\" text-anchor=\"middle\" font-size=\"12\" pointer-events=\"none\" style=\"fill:var(--md-sys-color-on-primary-container)\">${this.target}</text>\n ${hidden}\n </svg>`}\n ${others.length\n ? html`<div modes>\n ${others.map(f => html`<button ?on=${f === this.face} ?disabled=${this.locked} @click=${pick(f)}>${i18next.t('figure.label.face-' + f, { defaultValue: f })}</button>`)}\n </div>`\n : nothing}`\n }\n\n /** How: three side views; the chosen one's gap is dragged. */\n private renderModes() {\n const icon = (m: FastenMode, on: boolean) => {\n const g = on && m !== 'centre' ? Math.min(this.gap / 4, 10) : 0\n const base = svg`<rect x=\"6\" y=\"30\" width=\"52\" height=\"14\" style=\"fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary)\" />`\n const gapDrag = on && !this.locked ? 'ns-resize' : 'pointer'\n if (m === 'meet')\n return svg`<svg width=\"64\" height=\"48\">${base}<rect gap x=\"22\" y=${18 - g} width=\"20\" height=\"12\" style=${`fill:var(--md-sys-color-surface);stroke:currentColor;cursor:${gapDrag}`} />\n ${g ? svg`<text x=\"46\" y=${26 - g / 2} font-size=\"10\" style=\"fill:currentColor\">${this.gap}</text>` : nothing}</svg>`\n if (m === 'flush')\n return svg`<svg width=\"64\" height=\"48\">${base}<rect gap x=\"22\" y=${30 - g} width=\"20\" height=\"10\" style=${`fill:var(--md-sys-color-surface);stroke:currentColor;cursor:${gapDrag}`} />\n <line x1=\"4\" y1=\"30\" x2=\"60\" y2=\"30\" style=\"stroke:currentColor;stroke-dasharray:2 2\" /></svg>`\n return svg`<svg width=\"64\" height=\"48\">${base}<circle cx=\"32\" cy=\"30\" r=\"11\" style=\"fill:var(--md-sys-color-surface);fill-opacity:.85;stroke:currentColor\" /><circle cx=\"32\" cy=\"30\" r=\"2\" style=\"fill:currentColor\" /></svg>`\n }\n return html`<div modes>\n ${this.modes.map(m => {\n const on = m === this.mode\n return html`<button mode=${m} ?on=${on} ?disabled=${this.locked}\n @click=${() => {\n if (on) return\n this.change({ mode: m })\n this.released()\n }}\n @pointerdown=${(ev: PointerEvent) => {\n if (!on || this.locked || !(ev.target as Element).hasAttribute?.('gap')) return\n ev.preventDefault()\n ;(ev.currentTarget as Element).setPointerCapture(ev.pointerId)\n this.gapFrom = { y: ev.clientY, gap: this.gap }\n }}\n @pointermove=${(ev: PointerEvent) => {\n if (!this.gapFrom) return\n this.change({ gap: Math.max(0, Math.round(this.gapFrom.gap + (this.gapFrom.y - ev.clientY) * 2)) })\n }}\n @pointerup=${() => {\n if (!this.gapFrom) return\n this.gapFrom = undefined\n this.released()\n }}>\n ${icon(m, on)}<span>${i18next.t('figure.label.fasten-mode-' + m)}</span>\n </button>`\n })}\n </div>`\n }\n\n /** Where the part's centre is on each axis now: the drag's, or the form's. */\n private centreOf(view: FaceView): Record<Axis, number> {\n if (this.dragged) return this.dragged.at\n const at = { x: 0, y: 0, z: 0 }\n for (const a of view.axes) at[a] = offsetOf(this.align[a], this.alignMm[a], view.face[a], view.part[a])\n return at\n }\n\n /** What each axis is caught by now: at the centre, level with an edge, touching one from outside, or nothing. */\n private caughtOf(view: FaceView, at: Record<Axis, number>): Partial<Record<Axis, string>> {\n if (this.dragged) return this.dragged.caught\n const out: Partial<Record<Axis, string>> = {}\n for (const a of view.axes) {\n const how = this.align[a] ?? 'centre'\n if (how === 'centre') out[a] = 'centre'\n else if (how === 'min' || how === 'max') out[a] = 'inside'\n else if (view.face[a] !== undefined && Math.abs(Math.abs(at[a]) - (view.face[a]! + view.part[a]) / 2) < 0.5) out[a] = 'outside'\n }\n return out\n }\n\n private renderWhere() {\n const view = this.view\n if (!view) return nothing\n const { h, v, sign } = screenOf(view.axes)\n const W = PANEL_W,\n H = 180\n /* Room around the face for the part to go past its edges by about half itself; a plane with no size, three parts wide. */\n const span = (a: Axis) => (view.face[a] !== undefined ? view.face[a]! + view.part[a] : view.part[a] * 3)\n const k = Math.min((W - 40) / span(h), (H - 40) / span(v))\n this.scale = k\n const cx = W / 2,\n cy = H / 2\n const at = this.centreOf(view)\n const caught = this.caughtOf(view, at)\n const fw = (view.face[h] ?? 0) * k,\n fh = (view.face[v] ?? 0) * k\n const pw = view.part[h] * k,\n ph = view.part[v] * k\n const px = cx + sign[h] * at[h] * k - pw / 2,\n py = cy + sign[v] * at[v] * k - ph / 2\n const faceSized = view.face[h] !== undefined && view.face[v] !== undefined\n const fx = cx - fw / 2,\n fy = cy - fh / 2\n const ix = Math.max(fx, px),\n iy = Math.max(fy, py)\n const iw = Math.min(fx + fw, px + pw) - ix,\n ih = Math.min(fy + fh, py + ph) - iy\n const { touching, sides } = faceSized ? overhangOf(view, at) : { touching: true, sides: [] as ReturnType<typeof overhangOf>['sides'] }\n const round = this.mode === 'centre'\n const guide = (a: Axis) => {\n const c = caught[a]\n if (!c) return nothing\n const along = a === h\n const edge = c === 'centre' ? 0 : Math.sign(at[a]) * (view.face[a] ?? 0) / 2\n const pos = (along ? cx : cy) + sign[a] * edge * k\n const style = `stroke:var(--md-sys-color-primary);stroke-width:${c === 'centre' ? 1 : 2.5};stroke-dasharray:${c === 'centre' ? '4 3' : ''}`\n return along ? svg`<line x1=${pos} y1=\"4\" x2=${pos} y2=${H - 4} style=${style} />` : svg`<line x1=\"4\" y1=${pos} x2=${W - 4} y2=${pos} style=${style} />`\n }\n const dim = (a: Axis) => {\n /* Caught by the centre or an edge, the guide says where it is; a number only where nothing caught it. */\n if (caught[a]) return nothing\n const along = a === h\n const mm = Math.round(at[a])\n const label = `${mm > 0 ? '+' : ''}${mm} mm`\n const to = sign[a] * at[a] * k\n const tx = along ? cx + to / 2 : 8,\n ty = along ? H - 6 : cy + to / 2 + 4\n return svg`${along\n ? svg`<line x1=${cx} y1=${H - 16} x2=${cx + to} y2=${H - 16} style=\"stroke:var(--md-sys-color-on-surface)\" />`\n : svg`<line x1=\"20\" y1=${cy} x2=\"20\" y2=${cy + to} style=\"stroke:var(--md-sys-color-on-surface)\" />`}\n <text dim=${a} x=${tx} y=${ty} font-size=\"11\" text-anchor=${along ? 'middle' : 'start'}\n style=\"fill:var(--md-sys-color-primary);cursor:text;text-decoration:underline dotted\" @click=${() => !this.locked && (this.typing = a)}>${label}</text>`\n }\n const faceName = this.target ? `${this.target} ${i18next.t('figure.label.face-' + this.face)}` : this.planeWord\n const sizeWords = faceSized ? ` ${Math.round(view.face[h]!)} × ${Math.round(view.face[v]!)}` : ''\n return html`<div where tabindex=\"0\" @keydown=${(ev: KeyboardEvent) => this.keys(ev, view)}>\n ${svg`<svg viewBox=\"0 0 ${W} ${H}\" role=\"img\" aria-label=${faceName}\n @pointermove=${(ev: PointerEvent) => this.drag(ev, view, cx, cy)}\n @pointerup=${() => this.drop()} @pointercancel=${() => this.drop()}>\n ${faceSized\n ? svg`<rect x=${fx} y=${fy} width=${fw} height=${fh} rx=\"2\" style=\"fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary);stroke-width:1.5\" />`\n : svg`<rect x=\"4\" y=\"4\" width=${W - 8} height=${H - 8} rx=\"6\" style=\"fill:var(--md-sys-color-primary-container);fill-opacity:.5\" />`}\n <text x=${faceSized ? fx + 4 : 10} y=${faceSized ? fy + fh - 6 : 18} font-size=\"11\" pointer-events=\"none\" style=\"fill:var(--md-sys-color-primary)\">${faceName}${sizeWords}</text>\n ${guide(h)}${guide(v)}\n <g footprint style=${`cursor:${this.locked ? 'default' : 'grab'}`} @pointerdown=${(ev: PointerEvent) => this.grab(ev, at, caught)}>\n <rect x=${px} y=${py} width=${pw} height=${ph} rx=${round ? pw / 2 : 2} style=\"fill:var(--md-sys-color-tertiary-container)\" />\n ${faceSized && iw > 0 && ih > 0\n ? svg`<rect x=${ix} y=${iy} width=${iw} height=${ih} rx=${round ? Math.min(iw, ih) / 2 : 2} style=\"fill:var(--md-sys-color-surface)\" />`\n : !faceSized\n ? svg`<rect x=${px} y=${py} width=${pw} height=${ph} rx=${round ? pw / 2 : 2} style=\"fill:var(--md-sys-color-surface)\" />`\n : nothing}\n <rect x=${px} y=${py} width=${pw} height=${ph} rx=${round ? pw / 2 : 2}\n style=${`fill:none;stroke:var(--md-sys-color-on-surface);stroke-width:1.5;stroke-dasharray:${touching ? '' : '4 3'}`} />\n <text x=${px + pw / 2} y=${py + ph / 2 + 4} text-anchor=\"middle\" font-size=\"12\" pointer-events=\"none\" style=\"fill:var(--md-sys-color-on-surface)\">${this.partName}</text>\n </g>\n ${dim(h)}${dim(v)}\n </svg>`}\n ${this.typing ? this.renderTyping(view, this.typing, at) : nothing}\n </div>\n ${this.said && !this.dragged\n ? nothing\n : !touching\n ? html`<small off role=\"status\">${i18next.t('figure.text.fasten-off-face', { face: faceName })}</small>`\n : sides.length\n ? html`<small warn role=\"status\">${i18next.t('figure.text.fasten-past-edges', {\n sides: sides.map(s => i18next.t(`figure.text.overhang-side-${s.side}`, { axis: s.axis.toUpperCase(), mm: String(s.mm) })).join(' · ')\n })}</small>`\n : nothing}`\n }\n\n private renderTyping(view: FaceView, a: Axis, at: Record<Axis, number>) {\n const along = a === screenOf(view.axes).h\n return html`<input type=\"number\" step=\"1\" aria-label=${`${a.toUpperCase()} mm`} .value=${String(Math.round(at[a]))}\n style=${along ? 'left: calc(50% - 36px); bottom: 0' : 'left: 4px; top: calc(50% - 12px)'}\n @keydown=${(ev: KeyboardEvent) => {\n ev.stopPropagation()\n if (ev.key === 'Escape') this.typing = undefined\n if (ev.key !== 'Enter') return\n const value = Number((ev.target as HTMLInputElement).value)\n this.typing = undefined\n if (!Number.isFinite(value)) return\n this.change({ axis: a, how: 'mm', mm: Math.round(value) })\n this.released()\n }}\n @blur=${() => (this.typing = undefined)} />`\n }\n\n private grab(ev: PointerEvent, at: Record<Axis, number>, caught: Partial<Record<Axis, string>>) {\n if (this.locked) return\n ;(ev.currentTarget as Element).closest('svg')!.setPointerCapture(ev.pointerId)\n this.dragged = { at: { ...at }, caught: { ...caught } }\n }\n\n /** The footprint follows the pointer, caught at the centre and edges within a few pixels. */\n private drag(ev: PointerEvent, view: FaceView, cx: number, cy: number) {\n if (!this.dragged) return\n const svgEl = ev.currentTarget as SVGSVGElement\n const pt = svgEl.createSVGPoint()\n pt.x = ev.clientX\n pt.y = ev.clientY\n const p = pt.matrixTransform(svgEl.getScreenCTM()!.inverse())\n const { h, v, sign } = screenOf(view.axes)\n const at = { ...this.dragged.at },\n caught: Partial<Record<Axis, string>> = {}\n for (const [a, d] of [\n [h, (sign[h] * (p.x - cx)) / this.scale],\n [v, (sign[v] * (p.y - cy)) / this.scale]\n ] as const) {\n const got = alignmentAt(d, view.face[a], view.part[a], view.edges[a], 8 / this.scale)\n at[a] = offsetOf(got.how, got.mm, view.face[a], view.part[a])\n if (got.caught) caught[a] = got.caught\n }\n this.dragged = { at, caught }\n }\n\n private drop() {\n const d = this.dragged\n if (!d || !this.view) return\n this.dragged = undefined\n for (const a of this.view.axes) {\n const got = alignmentAt(d.at[a], this.view.face[a], this.view.part[a], this.view.edges[a], 0.5)\n this.change({ axis: a, how: got.how, ...(got.how === 'mm' ? { mm: got.mm } : {}) })\n }\n this.released()\n }\n\n /** Arrows move the part a millimetre, ten with Shift; the centre and edges still catch it. */\n private keys(ev: KeyboardEvent, view: FaceView) {\n const step = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1] }[ev.key]\n if (!step || this.locked || this.typing) return\n ev.preventDefault()\n ev.stopPropagation()\n const by = ev.shiftKey ? 10 : 1\n const at = this.centreOf(view)\n const { h, v, sign } = screenOf(view.axes)\n ;[h, v].forEach((a, i) => {\n if (!step[i]) return\n /* Up the screen is up the face: a Y that rises goes up with the arrow. */\n const got = alignmentAt(at[a] + sign[a] * step[i]! * by, view.face[a], view.part[a], view.edges[a], by / 2)\n this.change({ axis: a, how: got.how, ...(got.how === 'mm' ? { mm: got.mm } : {}) })\n })\n this.released()\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-fasten-drawing.js","sourceRoot":"","sources":["../../client/modeller/figure-fasten-drawing.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing, svg } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport type { FigureFace } from '@hatiolab/figure-model'\n\nimport { alignmentAt, offsetOf, overhangOf, screenOf, type FaceView, type FastenMode } from './fasten-geometry.js'\nimport type { Alignment } from './links.js'\n\ntype Axis = 'x' | 'y' | 'z'\n\n/** A change the drawing asks of the fastening form. */\nexport type FastenChange =\n | { targetFace: string }\n | { mode: FastenMode }\n | { axis: Axis; how: Alignment; mm?: number }\n | { gap: number }\n\nconst SEEN: Array<[FigureFace, string]> = [\n ['top', 'M60 30 L100 10 L200 10 L160 30 Z'],\n ['front', 'M60 30 L160 30 L160 100 L60 100 Z'],\n ['right', 'M160 30 L200 10 L200 80 L160 100 Z']\n]\n/** The faces the drawing cannot show on the box, as tags beside it where they are. */\n/* The box is drawn a little left of its picture's middle, and the viewBox shifts it back to the panel's centre. */\nconst HIDDEN: Array<[FigureFace, number, number]> = [\n ['bottom', 30, 114],\n ['left', 24, 62],\n ['back', 236, 14]\n]\nconst PANEL_W = 300\n\n\n/**\n * 붙이기 그림 (user 2026-10-01) — which face of what the part is fastened to, how, and where on it; each of them chosen\n * by pressing or dragging the drawing, none by a list of faces.\n *\n * The target is drawn as a box whose faces are pressed (the three it hides as tags beside it), or as the one plane the\n * figure stands by. How is three small side views -- set on it, flush with it, its centre on it (only for a part that\n * turns about a joint) -- and the chosen one's gap is dragged. Where is the face seen from above with the part's\n * footprint on it: dragged, caught at the centre and at the edges from inside and outside, a guide drawn where it is\n * caught and a dimension where it is not, which is pressed to type the number. It may go past the edges: the part that\n * does is shaded, and a part off the face altogether is said so. Nothing is decided here: every change goes to the form\n * (`fasten-change`), and a press or a drag let go says so (`fasten-release`), for the form to apply a fastening it holds.\n */\n@customElement('figure-fasten-drawing')\nexport class FigureFastenDrawing extends localize(i18next)(LitElement) {\n static styles = css`\n :host {\n display: grid;\n gap: 8px;\n outline: none;\n }\n svg {\n width: 100%;\n display: block;\n touch-action: none;\n user-select: none;\n }\n svg text {\n font: inherit;\n }\n div[modes] {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));\n gap: 6px;\n }\n div[modes] svg {\n width: 64px;\n height: 44px;\n }\n div[modes] button {\n display: grid;\n justify-items: center;\n align-content: center;\n gap: 2px;\n padding: 2px 4px 4px;\n font: inherit;\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n cursor: pointer;\n }\n div[modes] button[on] {\n border: 1.5px solid var(--md-sys-color-primary);\n background: var(--md-sys-color-primary-container);\n color: var(--md-sys-color-on-primary-container);\n }\n div[where] {\n position: relative;\n }\n div[where] input {\n position: absolute;\n width: 72px;\n font: inherit;\n font-size: 0.75rem;\n }\n small[warn] {\n color: var(--md-sys-color-tertiary);\n }\n small[off] {\n color: var(--md-sys-color-error);\n }\n `\n\n /** The target's name, or empty for the plane the figure stands by. */\n @property() target = ''\n /** The plane's name by the figure's placement: 바닥 · 천장 · 벽 · 중심. */\n @property() planeWord = ''\n @property({ attribute: false }) faces: string[] = []\n @property() face = ''\n @property({ attribute: false }) modes: FastenMode[] = ['meet', 'flush']\n @property() mode: FastenMode = 'meet'\n @property({ attribute: false }) view?: FaceView\n @property({ attribute: false }) align: Partial<Record<Axis, Alignment>> = {}\n @property({ attribute: false }) alignMm: Partial<Record<Axis, number>> = {}\n @property({ type: Number }) gap = 0\n /** The part being fastened (not `part`: that is every element's own). */\n @property() partName = ''\n @property({ type: Boolean }) locked = false\n /** The form already says how the fastening it has lies on the face: the drawing says it only while dragging. */\n @property({ type: Boolean }) said = false\n\n /** Where the footprint is while dragging, and what it is caught by; undefined when nothing is dragged. */\n @state() private dragged?: { at: Record<Axis, number>; caught: Partial<Record<Axis, string>> }\n @state() private typing?: Axis\n private scale = 1\n private gapFrom?: { y: number; gap: number }\n\n private change(detail: FastenChange) {\n this.dispatchEvent(new CustomEvent('fasten-change', { detail, bubbles: true, composed: true }))\n }\n private released() {\n this.dispatchEvent(new CustomEvent('fasten-release', { bubbles: true, composed: true }))\n }\n\n render() {\n return html`${this.renderTarget()}${this.renderModes()}${this.renderWhere()}`\n }\n\n /** The target box, its faces pressed; or the plane. */\n private renderTarget() {\n /* The plane is one face, named in the list and on the face drawn below: nothing to pick, so no picture of it. */\n if (!this.target) return nothing\n const has = (f: string) => this.faces.includes(f)\n /* A press is a whole change, as a drag let go is: the form applies a fastening the part already has. */\n const pick = (f: string) => () => {\n if (this.locked || !has(f) || f === this.face) return\n this.change({ targetFace: f })\n this.released()\n }\n const seen = SEEN.map(([f, d]) => {\n const on = this.face === f\n return svg`<path face=${f} d=${d} @click=${pick(f)}\n style=${`cursor:${has(f) ? 'pointer' : 'default'};fill:${on ? 'var(--md-sys-color-primary-container)' : 'var(--md-sys-color-surface-container)'};fill-opacity:${has(f) ? 1 : 0.4};stroke:${on ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-outline)'};stroke-width:${on ? 2 : 1}`}>\n <title>${i18next.t('figure.label.face-' + f)}</title></path>`\n })\n const hidden = HIDDEN.map(([f, x, y]) => {\n const on = this.face === f\n return svg`<g face=${f} @click=${pick(f)} style=${`cursor:${has(f) ? 'pointer' : 'default'};opacity:${has(f) ? 1 : 0.35}`}>\n <rect x=${x - 26} y=${y - 10} width=\"52\" height=\"20\" rx=\"10\"\n style=${`fill:${on ? 'var(--md-sys-color-primary-container)' : 'transparent'};stroke:${on ? 'var(--md-sys-color-primary)' : 'var(--md-sys-color-outline)'};stroke-dasharray:${on ? '' : '3 2'}`} />\n <text x=${x} y=${y + 4} text-anchor=\"middle\" font-size=\"11\" style=${`fill:${on ? 'var(--md-sys-color-on-primary-container)' : 'var(--md-sys-color-on-surface-variant)'}`}>${i18next.t('figure.label.face-' + f)}</text>\n </g>`\n })\n /* A shape's faces beyond its six outer ones -- a door frame's opening -- are tags of their own under the box. */\n const others = this.faces.filter(f => !SEEN.some(([s]) => s === f) && !HIDDEN.some(([h]) => h === f))\n return html`${svg`<svg viewBox=\"-20 0 ${PANEL_W} 126\" role=\"img\" aria-label=${this.target}>\n ${seen}\n <text x=\"110\" y=\"70\" text-anchor=\"middle\" font-size=\"12\" pointer-events=\"none\" style=\"fill:var(--md-sys-color-on-surface)\">${this.target}</text>\n ${hidden}\n </svg>`}\n ${others.length\n ? html`<div modes>\n ${others.map(f => html`<button ?on=${f === this.face} ?disabled=${this.locked} @click=${pick(f)}>${i18next.t('figure.label.face-' + f, { defaultValue: f })}</button>`)}\n </div>`\n : nothing}`\n }\n\n /** How: three side views; the chosen one's gap is dragged. */\n private renderModes() {\n /* One way only (the plane is set on): the sentence says it; a single choice is not offered as a button. */\n if (this.modes.length < 2) return nothing\n const icon = (m: FastenMode, on: boolean) => {\n const g = on && m !== 'centre' ? Math.min(this.gap / 4, 10) : 0\n const base = svg`<rect x=\"6\" y=\"30\" width=\"52\" height=\"14\" style=\"fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary)\" />`\n const gapDrag = on && !this.locked ? 'ns-resize' : 'pointer'\n if (m === 'meet')\n return svg`<svg viewBox=\"0 0 64 48\">${base}<rect gap x=\"22\" y=${18 - g} width=\"20\" height=\"12\" style=${`fill:var(--md-sys-color-surface);stroke:currentColor;cursor:${gapDrag}`} />\n ${g ? svg`<text x=\"46\" y=${26 - g / 2} font-size=\"10\" style=\"fill:currentColor\">${this.gap}</text>` : nothing}</svg>`\n if (m === 'flush')\n return svg`<svg viewBox=\"0 0 64 48\">${base}<rect gap x=\"22\" y=${30 - g} width=\"20\" height=\"10\" style=${`fill:var(--md-sys-color-surface);stroke:currentColor;cursor:${gapDrag}`} />\n <line x1=\"4\" y1=\"30\" x2=\"60\" y2=\"30\" style=\"stroke:currentColor;stroke-dasharray:2 2\" /></svg>`\n return svg`<svg viewBox=\"0 0 64 48\">${base}<circle cx=\"32\" cy=\"30\" r=\"11\" style=\"fill:var(--md-sys-color-surface);fill-opacity:.85;stroke:currentColor\" /><circle cx=\"32\" cy=\"30\" r=\"2\" style=\"fill:currentColor\" /></svg>`\n }\n return html`<div modes>\n ${this.modes.map(m => {\n const on = m === this.mode\n return html`<button mode=${m} ?on=${on} ?disabled=${this.locked}\n @click=${() => {\n if (on) return\n this.change({ mode: m })\n this.released()\n }}\n @pointerdown=${(ev: PointerEvent) => {\n if (!on || this.locked || !(ev.target as Element).hasAttribute?.('gap')) return\n ev.preventDefault()\n ;(ev.currentTarget as Element).setPointerCapture(ev.pointerId)\n this.gapFrom = { y: ev.clientY, gap: this.gap }\n }}\n @pointermove=${(ev: PointerEvent) => {\n if (!this.gapFrom) return\n this.change({ gap: Math.max(0, Math.round(this.gapFrom.gap + (this.gapFrom.y - ev.clientY) * 2)) })\n }}\n @pointerup=${() => {\n if (!this.gapFrom) return\n this.gapFrom = undefined\n this.released()\n }}>\n ${icon(m, on)}<span>${i18next.t('figure.label.fasten-mode-' + m)}</span>\n </button>`\n })}\n </div>`\n }\n\n /** Where the part's centre is on each axis now: the drag's, or the form's. */\n private centreOf(view: FaceView): Record<Axis, number> {\n if (this.dragged) return this.dragged.at\n const at = { x: 0, y: 0, z: 0 }\n for (const a of view.axes) at[a] = offsetOf(this.align[a], this.alignMm[a], view.face[a], view.part[a])\n return at\n }\n\n /** What each axis is caught by now: at the centre, level with an edge, touching one from outside, or nothing. */\n private caughtOf(view: FaceView, at: Record<Axis, number>): Partial<Record<Axis, string>> {\n if (this.dragged) return this.dragged.caught\n const out: Partial<Record<Axis, string>> = {}\n for (const a of view.axes) {\n const how = this.align[a] ?? 'centre'\n if (how === 'centre') out[a] = 'centre'\n else if (how === 'min' || how === 'max') out[a] = 'inside'\n else if (view.face[a] !== undefined && Math.abs(Math.abs(at[a]) - (view.face[a]! + view.part[a]) / 2) < 0.5) out[a] = 'outside'\n }\n return out\n }\n\n private renderWhere() {\n const view = this.view\n if (!view) return nothing\n const { h, v, sign } = screenOf(view.axes)\n const W = PANEL_W,\n H = 180\n /* Room around the face for the part to go past its edges by about half itself; a plane with no size, three parts wide. */\n const span = (a: Axis) => (view.face[a] !== undefined ? view.face[a]! + view.part[a] : view.part[a] * 3)\n const k = Math.min((W - 40) / span(h), (H - 40) / span(v))\n this.scale = k\n const cx = W / 2,\n cy = H / 2\n const at = this.centreOf(view)\n const caught = this.caughtOf(view, at)\n const fw = (view.face[h] ?? 0) * k,\n fh = (view.face[v] ?? 0) * k\n const pw = view.part[h] * k,\n ph = view.part[v] * k\n const px = cx + sign[h] * at[h] * k - pw / 2,\n py = cy + sign[v] * at[v] * k - ph / 2\n const faceSized = view.face[h] !== undefined && view.face[v] !== undefined\n const fx = cx - fw / 2,\n fy = cy - fh / 2\n const ix = Math.max(fx, px),\n iy = Math.max(fy, py)\n const iw = Math.min(fx + fw, px + pw) - ix,\n ih = Math.min(fy + fh, py + ph) - iy\n const { touching, sides } = faceSized ? overhangOf(view, at) : { touching: true, sides: [] as ReturnType<typeof overhangOf>['sides'] }\n const round = this.mode === 'centre'\n const guide = (a: Axis) => {\n const c = caught[a]\n if (!c) return nothing\n const along = a === h\n const edge = c === 'centre' ? 0 : Math.sign(at[a]) * (view.face[a] ?? 0) / 2\n const pos = (along ? cx : cy) + sign[a] * edge * k\n const style = `stroke:var(--md-sys-color-primary);stroke-width:${c === 'centre' ? 1 : 2.5};stroke-dasharray:${c === 'centre' ? '4 3' : ''}`\n return along ? svg`<line x1=${pos} y1=\"4\" x2=${pos} y2=${H - 4} style=${style} />` : svg`<line x1=\"4\" y1=${pos} x2=${W - 4} y2=${pos} style=${style} />`\n }\n const dim = (a: Axis) => {\n /* Caught by the centre or an edge, the guide says where it is; a number only where nothing caught it. */\n if (caught[a]) return nothing\n const along = a === h\n const mm = Math.round(at[a])\n const label = `${mm > 0 ? '+' : ''}${mm} mm`\n const to = sign[a] * at[a] * k\n const tx = along ? cx + to / 2 : 8,\n ty = along ? H - 6 : cy + to / 2 + 4\n return svg`${along\n ? svg`<line x1=${cx} y1=${H - 16} x2=${cx + to} y2=${H - 16} style=\"stroke:var(--md-sys-color-on-surface)\" />`\n : svg`<line x1=\"20\" y1=${cy} x2=\"20\" y2=${cy + to} style=\"stroke:var(--md-sys-color-on-surface)\" />`}\n <text dim=${a} x=${tx} y=${ty} font-size=\"11\" text-anchor=${along ? 'middle' : 'start'}\n style=\"fill:var(--md-sys-color-primary);cursor:text;text-decoration:underline dotted\" @click=${() => !this.locked && (this.typing = a)}>${label}</text>`\n }\n const faceName = this.target ? `${this.target} ${i18next.t('figure.label.face-' + this.face)}` : this.planeWord\n const sizeWords = faceSized ? ` ${Math.round(view.face[h]!)} × ${Math.round(view.face[v]!)}` : ''\n return html`<div where tabindex=\"0\" @keydown=${(ev: KeyboardEvent) => this.keys(ev, view)}>\n ${svg`<svg viewBox=\"0 0 ${W} ${H}\" role=\"img\" aria-label=${faceName}\n @pointermove=${(ev: PointerEvent) => this.drag(ev, view, cx, cy)}\n @pointerup=${() => this.drop()} @pointercancel=${() => this.drop()}>\n ${faceSized\n ? svg`<rect x=${fx} y=${fy} width=${fw} height=${fh} rx=\"4\" style=\"fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary);stroke-width:2\" />`\n : svg`<rect x=\"1\" y=\"1\" width=${W - 2} height=${H - 2} rx=\"8\" style=\"fill:var(--md-sys-color-primary-container);stroke:var(--md-sys-color-primary);stroke-width:2\" />`}\n <text x=${faceSized ? fx + 4 : 10} y=${faceSized ? fy + fh - 6 : 18} font-size=\"11\" pointer-events=\"none\" style=\"fill:var(--md-sys-color-primary)\">${faceName}${sizeWords}</text>\n ${guide(h)}${guide(v)}\n <g footprint style=${`cursor:${this.locked ? 'default' : 'grab'}`} @pointerdown=${(ev: PointerEvent) => this.grab(ev, at, caught)}>\n <rect x=${px} y=${py} width=${pw} height=${ph} rx=${round ? pw / 2 : 2} style=\"fill:var(--md-sys-color-tertiary-container)\" />\n ${faceSized && iw > 0 && ih > 0\n ? svg`<rect x=${ix} y=${iy} width=${iw} height=${ih} rx=${round ? Math.min(iw, ih) / 2 : 2} style=\"fill:var(--md-sys-color-surface)\" />`\n : !faceSized\n ? svg`<rect x=${px} y=${py} width=${pw} height=${ph} rx=${round ? pw / 2 : 2} style=\"fill:var(--md-sys-color-surface)\" />`\n : nothing}\n <rect x=${px} y=${py} width=${pw} height=${ph} rx=${round ? pw / 2 : 2}\n style=${`fill:none;stroke:var(--md-sys-color-on-surface);stroke-width:1.5;stroke-dasharray:${touching ? '' : '4 3'}`} />\n <text x=${px + pw / 2} y=${py + ph / 2 + 4} text-anchor=\"middle\" font-size=\"12\" pointer-events=\"none\" style=\"fill:var(--md-sys-color-on-surface)\">${this.partName}</text>\n </g>\n ${dim(h)}${dim(v)}\n </svg>`}\n ${this.typing ? this.renderTyping(view, this.typing, at) : nothing}\n </div>\n ${this.said && !this.dragged\n ? nothing\n : !touching\n ? html`<small off role=\"status\">${i18next.t('figure.text.fasten-off-face', { face: faceName })}</small>`\n : sides.length\n ? html`<small warn role=\"status\">${i18next.t('figure.text.fasten-past-edges', {\n sides: sides.map(s => i18next.t(`figure.text.overhang-side-${s.side}`, { axis: s.axis.toUpperCase(), mm: String(s.mm) })).join(' · ')\n })}</small>`\n : nothing}`\n }\n\n private renderTyping(view: FaceView, a: Axis, at: Record<Axis, number>) {\n const along = a === screenOf(view.axes).h\n return html`<input type=\"number\" step=\"1\" aria-label=${`${a.toUpperCase()} mm`} .value=${String(Math.round(at[a]))}\n style=${along ? 'left: calc(50% - 36px); bottom: 0' : 'left: 4px; top: calc(50% - 12px)'}\n @keydown=${(ev: KeyboardEvent) => {\n ev.stopPropagation()\n if (ev.key === 'Escape') this.typing = undefined\n if (ev.key !== 'Enter') return\n const value = Number((ev.target as HTMLInputElement).value)\n this.typing = undefined\n if (!Number.isFinite(value)) return\n this.change({ axis: a, how: 'mm', mm: Math.round(value) })\n this.released()\n }}\n @blur=${() => (this.typing = undefined)} />`\n }\n\n private grab(ev: PointerEvent, at: Record<Axis, number>, caught: Partial<Record<Axis, string>>) {\n if (this.locked) return\n ;(ev.currentTarget as Element).closest('svg')!.setPointerCapture(ev.pointerId)\n this.dragged = { at: { ...at }, caught: { ...caught } }\n }\n\n /** The footprint follows the pointer, caught at the centre and edges within a few pixels. */\n private drag(ev: PointerEvent, view: FaceView, cx: number, cy: number) {\n if (!this.dragged) return\n const svgEl = ev.currentTarget as SVGSVGElement\n const pt = svgEl.createSVGPoint()\n pt.x = ev.clientX\n pt.y = ev.clientY\n const p = pt.matrixTransform(svgEl.getScreenCTM()!.inverse())\n const { h, v, sign } = screenOf(view.axes)\n const at = { ...this.dragged.at },\n caught: Partial<Record<Axis, string>> = {}\n for (const [a, d] of [\n [h, (sign[h] * (p.x - cx)) / this.scale],\n [v, (sign[v] * (p.y - cy)) / this.scale]\n ] as const) {\n const got = alignmentAt(d, view.face[a], view.part[a], view.edges[a], 8 / this.scale)\n at[a] = offsetOf(got.how, got.mm, view.face[a], view.part[a])\n if (got.caught) caught[a] = got.caught\n }\n this.dragged = { at, caught }\n }\n\n private drop() {\n const d = this.dragged\n if (!d || !this.view) return\n this.dragged = undefined\n for (const a of this.view.axes) {\n const got = alignmentAt(d.at[a], this.view.face[a], this.view.part[a], this.view.edges[a], 0.5)\n this.change({ axis: a, how: got.how, ...(got.how === 'mm' ? { mm: got.mm } : {}) })\n }\n this.released()\n }\n\n /** Arrows move the part a millimetre, ten with Shift; the centre and edges still catch it. */\n private keys(ev: KeyboardEvent, view: FaceView) {\n const step = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, -1], ArrowDown: [0, 1] }[ev.key]\n if (!step || this.locked || this.typing) return\n ev.preventDefault()\n ev.stopPropagation()\n const by = ev.shiftKey ? 10 : 1\n const at = this.centreOf(view)\n const { h, v, sign } = screenOf(view.axes)\n ;[h, v].forEach((a, i) => {\n if (!step[i]) return\n /* Up the screen is up the face: a Y that rises goes up with the arrow. */\n const got = alignmentAt(at[a] + sign[a] * step[i]! * by, view.face[a], view.part[a], view.edges[a], by / 2)\n this.change({ axis: a, how: got.how, ...(got.how === 'mm' ? { mm: got.mm } : {}) })\n })\n this.released()\n }\n}\n"]}
|