@things-factory/figure-ui 10.1.42 → 10.1.44
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/v3-editor.ts +43 -1
- package/dist-client/modeller/v3-editor.d.ts +5 -0
- package/dist-client/modeller/v3-editor.js +44 -1
- package/dist-client/modeller/v3-editor.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/test/v3-parts-wiring.test.ts +10 -0
- package/translations/en.json +2 -0
- package/translations/ja.json +7 -1
- package/translations/ko.json +2 -0
- package/translations/ms.json +7 -1
- package/translations/zh.json +7 -1
|
@@ -114,6 +114,12 @@ export class FigureV3Editor extends LitElement {
|
|
|
114
114
|
color: var(--md-sys-color-on-secondary-container);
|
|
115
115
|
border-color: var(--md-sys-color-primary);
|
|
116
116
|
}
|
|
117
|
+
label[name-field] {
|
|
118
|
+
margin: 0 0 8px;
|
|
119
|
+
}
|
|
120
|
+
label[name-field] input {
|
|
121
|
+
font-weight: 600;
|
|
122
|
+
}
|
|
117
123
|
div[tools] {
|
|
118
124
|
display: flex;
|
|
119
125
|
flex-wrap: wrap;
|
|
@@ -387,6 +393,33 @@ export class FigureV3Editor extends LitElement {
|
|
|
387
393
|
${tool('snap', 'grid_on', 'figure.button.snap', 'figure.text.snap-explained')}
|
|
388
394
|
</div>`
|
|
389
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* A part's name — the V2 part name field. It renames every value the part owns, and what refers to them follows
|
|
398
|
+
* (figure-model's rename-part), as one step of the history.
|
|
399
|
+
*/
|
|
400
|
+
private renamePart(input: HTMLInputElement) {
|
|
401
|
+
const name = input.value.trim()
|
|
402
|
+
const from = this.selected
|
|
403
|
+
if (!name || name === from) {
|
|
404
|
+
input.value = from
|
|
405
|
+
return
|
|
406
|
+
}
|
|
407
|
+
try {
|
|
408
|
+
this.session!.edit({ kind: 'rename-part', target: from, name })
|
|
409
|
+
this.selected = name
|
|
410
|
+
this.error = ''
|
|
411
|
+
this.changed()
|
|
412
|
+
} catch (error) {
|
|
413
|
+
input.value = from
|
|
414
|
+
const code = (error as { code?: string })?.code
|
|
415
|
+
this.error =
|
|
416
|
+
code === 'PART_ID'
|
|
417
|
+
? i18next.t(/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name) ? 'figure.text.part-name-taken' : 'figure.text.part-name-invalid', { name })
|
|
418
|
+
: error instanceof Error
|
|
419
|
+
? error.message
|
|
420
|
+
: String(error)
|
|
421
|
+
}
|
|
422
|
+
}
|
|
390
423
|
private changeField(field: { id: string; unit: V3InputChange['unit']; role?: string }, event: Event) {
|
|
391
424
|
const input = event.target as HTMLInputElement,
|
|
392
425
|
value = input.valueAsNumber
|
|
@@ -461,7 +494,16 @@ export class FigureV3Editor extends LitElement {
|
|
|
461
494
|
}}
|
|
462
495
|
></figure-v3-canvas>
|
|
463
496
|
<aside>
|
|
464
|
-
|
|
497
|
+
${this.selected && part
|
|
498
|
+
? html`<label name-field
|
|
499
|
+
><span>${i18next.t('figure.label.name')}</span
|
|
500
|
+
><input
|
|
501
|
+
aria-label=${i18next.t('figure.label.name')}
|
|
502
|
+
.value=${this.selected}
|
|
503
|
+
?disabled=${unavailable}
|
|
504
|
+
@change=${(e: Event) => this.renamePart(e.target as HTMLInputElement)}
|
|
505
|
+
/></label>`
|
|
506
|
+
: html`<h3>${this.selected || '모델 입력'}</h3>`}
|
|
465
507
|
${this.renderTools(unavailable)}
|
|
466
508
|
${fields.map(field => html`<label><span>${fieldLabel(field.id)} (${field.unit})${field.role === 'state' ? ' · 동작' : ''}</span><input aria-label=${field.id} type="number" step="any" .value=${String(field.value)} ?disabled=${unavailable} @change=${(e: Event) => this.changeField(field, e)} /></label>`)}
|
|
467
509
|
${
|
|
@@ -38,6 +38,11 @@ export declare class FigureV3Editor extends LitElement {
|
|
|
38
38
|
/** A mirrored copy: duplicate, then place the copy on the other side — two steps, as the V2 list makes it. */
|
|
39
39
|
private mirror;
|
|
40
40
|
private renderTools;
|
|
41
|
+
/**
|
|
42
|
+
* A part's name — the V2 part name field. It renames every value the part owns, and what refers to them follows
|
|
43
|
+
* (figure-model's rename-part), as one step of the history.
|
|
44
|
+
*/
|
|
45
|
+
private renamePart;
|
|
41
46
|
private changeField;
|
|
42
47
|
render(): import("lit-html").TemplateResult<1>;
|
|
43
48
|
}
|
|
@@ -120,6 +120,12 @@ let FigureV3Editor = class FigureV3Editor extends LitElement {
|
|
|
120
120
|
color: var(--md-sys-color-on-secondary-container);
|
|
121
121
|
border-color: var(--md-sys-color-primary);
|
|
122
122
|
}
|
|
123
|
+
label[name-field] {
|
|
124
|
+
margin: 0 0 8px;
|
|
125
|
+
}
|
|
126
|
+
label[name-field] input {
|
|
127
|
+
font-weight: 600;
|
|
128
|
+
}
|
|
123
129
|
div[tools] {
|
|
124
130
|
display: flex;
|
|
125
131
|
flex-wrap: wrap;
|
|
@@ -400,6 +406,34 @@ let FigureV3Editor = class FigureV3Editor extends LitElement {
|
|
|
400
406
|
${tool('snap', 'grid_on', 'figure.button.snap', 'figure.text.snap-explained')}
|
|
401
407
|
</div>`;
|
|
402
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* A part's name — the V2 part name field. It renames every value the part owns, and what refers to them follows
|
|
411
|
+
* (figure-model's rename-part), as one step of the history.
|
|
412
|
+
*/
|
|
413
|
+
renamePart(input) {
|
|
414
|
+
const name = input.value.trim();
|
|
415
|
+
const from = this.selected;
|
|
416
|
+
if (!name || name === from) {
|
|
417
|
+
input.value = from;
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
try {
|
|
421
|
+
this.session.edit({ kind: 'rename-part', target: from, name });
|
|
422
|
+
this.selected = name;
|
|
423
|
+
this.error = '';
|
|
424
|
+
this.changed();
|
|
425
|
+
}
|
|
426
|
+
catch (error) {
|
|
427
|
+
input.value = from;
|
|
428
|
+
const code = error?.code;
|
|
429
|
+
this.error =
|
|
430
|
+
code === 'PART_ID'
|
|
431
|
+
? i18next.t(/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name) ? 'figure.text.part-name-taken' : 'figure.text.part-name-invalid', { name })
|
|
432
|
+
: error instanceof Error
|
|
433
|
+
? error.message
|
|
434
|
+
: String(error);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
403
437
|
changeField(field, event) {
|
|
404
438
|
const input = event.target, value = input.valueAsNumber;
|
|
405
439
|
this.run(() => this.session.apply([
|
|
@@ -469,7 +503,16 @@ let FigureV3Editor = class FigureV3Editor extends LitElement {
|
|
|
469
503
|
}}
|
|
470
504
|
></figure-v3-canvas>
|
|
471
505
|
<aside>
|
|
472
|
-
|
|
506
|
+
${this.selected && part
|
|
507
|
+
? html `<label name-field
|
|
508
|
+
><span>${i18next.t('figure.label.name')}</span
|
|
509
|
+
><input
|
|
510
|
+
aria-label=${i18next.t('figure.label.name')}
|
|
511
|
+
.value=${this.selected}
|
|
512
|
+
?disabled=${unavailable}
|
|
513
|
+
@change=${(e) => this.renamePart(e.target)}
|
|
514
|
+
/></label>`
|
|
515
|
+
: html `<h3>${this.selected || '모델 입력'}</h3>`}
|
|
473
516
|
${this.renderTools(unavailable)}
|
|
474
517
|
${fields.map(field => html `<label><span>${fieldLabel(field.id)} (${field.unit})${field.role === 'state' ? ' · 동작' : ''}</span><input aria-label=${field.id} type="number" step="any" .value=${String(field.value)} ?disabled=${unavailable} @change=${(e) => this.changeField(field, e)} /></label>`)}
|
|
475
518
|
${part
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v3-editor.js","sourceRoot":"","sources":["../../client/modeller/v3-editor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAuB,MAAM,KAAK,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAGlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,gBAAgB,CAAA;AACvB,OAAO,sBAAsB,CAAA;AAC7B,OAAO,yBAAyB,CAAA;AAChC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAqC,MAAM,eAAe,CAAA;AAC7F,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAkB,MAAM,eAAe,CAAA;AAItF,MAAM,KAAK,GAA2B;IACpC,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;IACd,IAAI,EAAE,IAAI;IACV,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,QAAQ;IACf,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,KAAK;IACb,GAAG,EAAE,IAAI;IACT,WAAW,EAAE,QAAQ;IACrB,YAAY,EAAE,SAAS;IACvB,UAAU,EAAE,QAAQ;CACrB,CAAA;AACD,SAAS,UAAU,CAAC,EAAU;IAC5B,OAAO,EAAE;SACN,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;SACrC,IAAI,CAAC,KAAK,CAAC,CAAA;AAChB,CAAC;AAED,kGAAkG;AAE3F,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,UAAU;IAAvC;;QA4JuB,aAAQ,GAAG,CAAC,CAAA;QACvB,aAAQ,GAAG,EAAE,CAAA;QACb,UAAK,GAAG,EAAE,CAAA;QAC3B;;;WAGG;QACc,gBAAW,GAAG,IAAI,GAAG,EAAU,CAAA;QACxC,gBAAW,GAAkB,IAAI,CAAA;IAsR3C,CAAC;aAzbQ,WAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyJlB,AAzJY,CAyJZ;IAWS,UAAU,CAAC,QAAwB;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAA;QACjC,IAAI,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,CAAC,WAAW,GAAG,IAAI,EAAE,OAAO,IAAI,IAAI,CAAA;YACxC,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;YAClB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;YACf,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAA;QAC9B,CAAC;QACD,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC;YAAE,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;IAClF,CAAC;IACO,GAAG,CAAC,MAAqB;QAC/B,IAAI,CAAC;YACH,MAAM,EAAE,CAAA;YACR,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;YACf,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACrE,CAAC;IACH,CAAC;IACO,OAAO;QACb,IAAI,CAAC,aAAa,EAAE,CAAA;QACpB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IACtF,CAAC;IACO,KAAK,CAAC,IAAI;QAChB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,IAAI,CAAC;YACH;;;;cAIE;YACF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;YAChC,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;YACpG,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;YAChD,IAAI,CAAC,OAAO,EAAE,CAAA;YACd,MAAM,OAAO,CAAA;YACb,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACrE,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;IACH,CAAC;IACO,GAAG,CAAC,IAAiC;QAC3C,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;YACZ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACjE,IAAI,CAAC,GAAG,CAAC,CAAA;YACT,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;gBAAE,CAAC,EAAE,CAAA;YACnC,MAAM,MAAM,GAAG,EAAE,EAAE,EAAE,GAAG,IAAI,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAA;YACtE,MAAM,IAAI,GACR,IAAI,KAAK,KAAK;gBACZ,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBAC1E,CAAC,CAAC,IAAI,KAAK,UAAU;oBACnB,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE;oBAC9D,CAAC,CAAC,IAAI,KAAK,aAAa;wBACtB,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;wBACrF,CAAC,CAAC;4BACE,GAAG,MAAM;4BACT,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;4BAC9B,IAAI,EAAE,QAAQ;4BACd,UAAU,EAAE;gCACV,IAAI,EAAE,CAAC,GAAG;gCACV,KAAK,EAAE,GAAG;gCACV,MAAM,EAAE,CAAC;gCACT,GAAG,EAAE,GAAG;gCACR,WAAW,EAAE,CAAC,EAAE;gCAChB,YAAY,EAAE,EAAE;gCAChB,UAAU,EAAE,GAAG;gCACf,KAAK,EAAE,EAAE;6BACV;yBACF,CAAA;YACX,IAAI,CAAC,OAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACvB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAA;QACzB,CAAC,CAAC,CAAA;IACJ,CAAC;IACD;;;OAGG;IACK,aAAa,CAAC,EAAU;QAC9B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;YACZ,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACpE,IAAI,CAAC,OAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;YAC1D,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAA;QACtF,CAAC,CAAC,CAAA;IACJ,CAAC;IACO,QAAQ,CAAC,EAAU,EAAE,EAAU;QACrC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;IAC3E,CAAC;IACO,UAAU,CAAC,EAAU;QAC3B,IAAI,CAAC;YACH,IAAI,CAAC,OAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;YACvD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;YACf,IAAI,IAAI,CAAC,QAAQ,KAAK,EAAE;gBAAE,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;YAC5C,IAAI,CAAC,OAAO,EAAE,CAAA;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gHAAgH;YAChH,IAAI,CAAC,KAAK;gBACP,KAA2B,EAAE,IAAI,KAAK,iBAAiB;oBACtD,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gCAAgC,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;oBAC3D,CAAC,CAAC,KAAK,YAAY,KAAK;wBACtB,CAAC,CAAC,KAAK,CAAC,OAAO;wBACf,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACvB,CAAC;IACH,CAAC;IACO,gBAAgB,CAAC,EAAU;QACjC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACtC,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;;YAC5B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACjB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAA;IACzB,CAAC;IACD,wFAAwF;IAChF,OAAO,CAAC,EAAU;QACxB,MAAM,IAAI,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;QAC9D,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAA;QACrC,IAAI,CAAC;YACH,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IACD,wGAAwG;IAChG,WAAW,CAAC,EAAU,EAAE,MAAmB;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAQ,CAAC,IAAI,EAAE,CAAA;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,KAAe,CAAC,CAAC,CAAC,CAAA;QAC7F,MAAM,OAAO,GAAG,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;QACjE,IAAI,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;;YAC3D,IAAI,CAAC,aAAa,EAAE,CAAA;IAC3B,CAAC;IACD,qFAAqF;IAC7E,KAAK,CAAC,IAAe;QAC3B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;YACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;YAChD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAA;YACrF,IAAI,OAAO,CAAC,MAAM;gBAAE,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAClD,CAAC,CAAC,CAAA;IACJ,CAAC;IACD,8GAA8G;IACtG,MAAM,CAAC,IAAe;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE;YACZ,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAA;YACxB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,OAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACpE,IAAI,CAAC,OAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;YAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAA;YAC3E,IAAI,CAAC,IAAI;gBAAE,OAAM;YACjB,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;YACtF,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;QACtB,CAAC,CAAC,CAAA;IACJ,CAAC;IACO,WAAW,CAAC,WAAoB;QACtC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACzC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS;YAAE,OAAO,IAAI,CAAA;QACnD,IAAI,KAAc,CAAA;QAClB,IAAI,CAAC;YACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;QAC5C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,IAAe,EAAE,IAAY,EAAE,KAAa,EAAE,KAAa,EAAE,EAAE,CAC3E,IAAI,CAAA,qBAAqB,WAAW,eAAe,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;mBACjH,IAAI;gBACP,CAAA;QACZ,OAAO,IAAI,CAAA,oBAAoB,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;QACnE,IAAI,CAAC,UAAU,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,yBAAyB,CAAC;QAC9F,IAAI,CAAC,UAAU,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,yBAAyB,CAAC;QAC9F,IAAI,CAAC,OAAO,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,0BAA0B,CAAC;QAC3F,CAAC,GAAG,EAAE,GAAG,CAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACjC,MAAM,IAAI,GAAG,SAAS,CAAC,KAAc,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;YAClE,OAAO,IAAI,CAAA;sBACG,WAAW,IAAI,CAAC,IAAI;uBACnB,OAAO,CAAC,CAAC,CAAC,uBAAuB,GAAG,IAAI,CAAC;kBAC9C,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,kCAAkC,CAAC;mBACpF,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;;qBAErB,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,qBAAqB;kBAChD,CAAA;QACZ,CAAC,CAAC;QACA,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,oBAAoB,EAAE,4BAA4B,CAAC;WACxE,CAAA;IACT,CAAC;IACO,WAAW,CAAC,KAAiE,EAAE,KAAY;QACjG,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B,EAC5C,KAAK,GAAG,KAAK,CAAC,aAAa,CAAA;QAC7B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CACZ,IAAI,CAAC,OAAQ,CAAC,KAAK,CAAC;YAClB,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;SACxG,CAAC,CACH,CAAA;QACD,gEAAgE;QAChE,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAE,CAAC,KAAK,CAAC,CAAA;IACvF,CAAC;IACD,MAAM;QACJ,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAA;QACjC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA,qBAAqB,CAAA;QAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAA;QAChF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAA;QAC5D,wEAAwE;QACxE,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAA;QAC1F,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;QAC7F,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAA;QAChE,OAAO,IAAI,CAAA;;4BAEa,WAAW,IAAI,CAAC,IAAI,CAAC,OAAO,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAQ,CAAC,IAAI,EAAE,CAAC;;;4BAGjF,WAAW,IAAI,CAAC,IAAI,CAAC,OAAO,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAQ,CAAC,IAAI,EAAE,CAAC;;;yBAGpF,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAiB,kBAAkB,CAAC,EAAE,GAAG,EAAE;;;;aAI1F,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK;;4BAE3E,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,IAAI,CAAC,IAAI;;QAEjF,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAA,mCAAmC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI;;;mBAG9F,IAAI,CAAC,QAAQ,CAAC,GAAG,CACxB,CAAC,CAAC,EAAa,EAAE,CAAC,CAAC;YACjB,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,QAAQ,EAAG,CAAuC,CAAC,KAAK,EAAE,QAAQ,IAAI,EAAE;YACxE,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAClC,SAAS,EAAG,CAA2B,CAAC,OAAO,KAAK,KAAK;SAC1D,CAAC,CACH;sBACW,IAAI,CAAC,QAAQ;oBACf,WAAW;sBACT,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;yBACxC,CAAC,CAAc,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;gCAC1C,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;kCACpD,CAAC,CAAc,EAAE,EAAE,CACzC,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;0BAC1E,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;4BACzD,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;4BAC3D,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;yBACtD,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;;;mBAGtD,eAAe,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAE,IAAuB,CAAC,EAAE,CAAC,CAAC;qBACrG,IAAI,CAAC,OAAO,IAAI,EAAE;qBAClB,IAAI,CAAC,OAAO,IAAI,EAAE;sBACjB,IAAI,CAAC,QAAQ;mBAChB,WAAW,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;8BAClF,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;2BACrE,CAAC,CAAsB,EAAE,EAAE;YAC1C,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAA;QAC1B,CAAC;0BACe,CAAC,CAAqB,EAAE,EAAE;YACxC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAA;QAC/B,CAAC;;;gBAGK,IAAI,CAAC,QAAQ,IAAI,OAAO;YAC5B,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;YAC7B,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAA,gBAAgB,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,4BAA4B,KAAK,CAAC,EAAE,oCAAoC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,WAAW,YAAY,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,aAAa,CAAC;YAE1S,IAAI;YACF,CAAC,CAAC,IAAI,CAAA;0BACM,IAAI;6BACD,IAAI,CAAC,OAAO,IAAI,EAAE;4BACnB,WAAW;kCACL,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;uCAChE;YACzB,CAAC,CAAC,IACN;YAEE,IAAI,CAAC,QAAQ,CAAC,MAAM;YAClB,CAAC,CAAC,IAAI,CAAA;oBACA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAA,MAAM,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,EAAE;YACnE,CAAC,CAAC,IACN;;cAEI,CAAA;IACZ,CAAC;;AA9R+B;IAA/B,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;+CAA2B;AAC9B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;gDAAa;AACvB;IAAhB,KAAK,EAAE;;gDAAsB;AACb;IAAhB,KAAK,EAAE;;6CAAmB;AAKV;IAAhB,KAAK,EAAE;;mDAAwC;AAnKrC,cAAc;IAD1B,aAAa,CAAC,kBAAkB,CAAC;GACrB,cAAc,CA0b1B","sourcesContent":["import { LitElement, html, css, type PropertyValues } from 'lit'\nimport { i18next } from '@operato/i18n'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport type { V3InputChange, V3PrimitiveCreation } from '@hatiolab/figure-model'\nimport type { V3ProductSession } from './v3-product-session.js'\nimport { captureV3Thumbnail } from './v3-thumbnail.js'\nimport { drawableV3Parts } from './v3-renderer.js'\nimport './v3-canvas.js'\nimport './figure-v3-parts.js'\nimport './figure-v3-material.js'\nimport { gizmoChanges, gizmoReachOf, type GizmoReach, type GizmoResult } from './v3-gizmo.js'\nimport { alignChanges, canMirror, mirrorChanges, type AlignTool } from './v3-align.js'\nimport type { V3PartRow } from './figure-v3-parts.js'\nimport type { FigureV3Canvas } from './v3-canvas.js'\n\nconst names: Record<string, string> = {\n position: '위치',\n rotation: '회전',\n size: '크기',\n dimension: '치수',\n width: '너비',\n height: '높이',\n depth: '깊이',\n radius: '반지름',\n length: '길이',\n round: '모서리 반경',\n left: '왼쪽',\n right: '오른쪽',\n bottom: '아랫면',\n top: '윗면',\n openingLeft: '개구부 왼쪽',\n openingRight: '개구부 오른쪽',\n openingTop: '개구부 윗면'\n}\nfunction fieldLabel(id: string) {\n return id\n .split('.')\n .map(p => names[p] ?? p.toUpperCase())\n .join(' · ')\n}\n\n/** Product editor surface. The injected session is shared by page persistence and AI commands. */\n@customElement('figure-v3-editor')\nexport class FigureV3Editor extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n height: 100%;\n /*\n The editor folds by the width it is given, not the window's. The rail (208 open, 56 closed) and the page's\n 320 side take their share first, so a window rule was wrong whenever either was there: at 945 with the rail\n open the editor had 417 and still drew its 660 of columns, over the side (UX ruling, 2026-09-24).\n */\n container-type: inline-size;\n font: 13px sans-serif;\n color: var(--md-sys-color-on-surface, #22343f);\n }\n header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n flex-wrap: wrap;\n }\n main {\n flex: 1;\n min-height: 0;\n display: grid;\n grid-template-columns: 180px minmax(180px, 1fr) 300px;\n }\n aside {\n padding: 12px;\n overflow: auto;\n background: var(--md-sys-color-surface, #fff);\n }\n figure-v3-parts {\n min-height: 0;\n }\n aside:last-child {\n border-left: 1px solid var(--md-sys-color-outline-variant);\n }\n h3 {\n font-size: var(--ui-t-body, 13px);\n margin: 22px 0 10px;\n }\n h3:first-child {\n margin-top: 0;\n }\n button,\n input,\n select {\n font: inherit;\n box-sizing: border-box;\n height: 34px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: var(--md-sys-color-surface, #fff);\n color: inherit;\n padding: 0 8px;\n min-width: 0;\n }\n button {\n cursor: pointer;\n }\n button:disabled {\n opacity: 0.45;\n cursor: default;\n }\n button[aria-pressed='true'] {\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n border-color: var(--md-sys-color-primary);\n }\n div[tools] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin: 0 0 8px;\n }\n div[tools] button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n padding: 0;\n }\n div[tools] md-icon {\n font-size: 18px;\n width: 18px;\n height: 18px;\n }\n .parts {\n display: grid;\n gap: 6px;\n }\n .recipes {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px;\n }\n label {\n display: grid;\n grid-template-columns: 112px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n margin: 8px 0;\n }\n label span {\n overflow-wrap: anywhere;\n }\n .error {\n padding: 10px;\n background: var(--md-sys-color-error-container);\n color: var(--md-sys-color-on-error-container);\n white-space: pre-wrap;\n }\n .status {\n margin-left: auto;\n }\n .hint {\n color: var(--md-sys-color-on-surface-variant);\n line-height: 1.5;\n }\n /* 660 and over: parts | canvas | inputs. Below that the sum of the columns' least widths no longer fits. */\n @container (max-width: 659px) {\n main {\n grid-template-columns: 140px minmax(160px, 1fr);\n }\n aside:last-child {\n grid-column: 1/-1;\n max-height: 260px;\n border-left: none;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n }\n /* Under 420: one column. The canvas first — seeing what is being made comes before the lists — and main scrolls. */\n @container (max-width: 419px) {\n main {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(240px, 45%);\n grid-auto-rows: auto;\n overflow-y: auto;\n }\n figure-v3-canvas {\n order: -1;\n }\n figure-v3-parts {\n border-right: none;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n aside:last-child {\n max-height: none;\n }\n }\n `\n @property({ attribute: false }) session?: V3ProductSession\n @property({ type: Number }) revision = 0\n @state() private selected = ''\n @state() private error = ''\n /**\n * Parts hidden on the workbench — the author's view while working, not the asset's visibility. Not saved, as in\n * the V2 modeller: a part hidden here is still in the figure, still checked, still drawn on a board.\n */\n @state() private hiddenParts = new Set<string>()\n private lastContext: string | null = null\n protected willUpdate(_changed: PropertyValues) {\n const view = this.session?.read()\n if (view?.context !== this.lastContext) {\n this.lastContext = view?.context ?? null\n this.selected = ''\n this.error = ''\n this.hiddenParts = new Set()\n }\n if (view && !view.geometry.some(g => g.id === this.selected)) this.selected = ''\n }\n private run(action: () => unknown) {\n try {\n action()\n this.error = ''\n this.changed()\n } catch (error) {\n this.error = error instanceof Error ? error.message : String(error)\n }\n }\n private changed() {\n this.requestUpdate()\n this.dispatchEvent(new CustomEvent('v3-changed', { bubbles: true, composed: true }))\n }\n private async save() {\n if (!this.session) return\n try {\n /*\n The card's picture is taken before the save starts, from a canvas of its own at the card's size —\n not from the one on screen, which stands wherever the author left it turned. A picture that cannot\n be taken is not an error: the save goes on without it (see `v3-thumbnail.ts`).\n */\n const view = this.session.read()\n const thumbnail = await captureV3Thumbnail(drawableV3Parts(view.geometry ?? []), view.palette ?? {})\n const promise = this.session.save({ thumbnail })\n this.changed()\n await promise\n this.error = ''\n } catch (error) {\n this.error = error instanceof Error ? error.message : String(error)\n } finally {\n this.changed()\n }\n }\n private add(kind: V3PrimitiveCreation['kind']) {\n if (!this.session) return\n this.run(() => {\n const ids = new Set(this.session!.read().geometry.map(g => g.id))\n let n = 1\n while (ids.has(`${kind}-${n}`)) n++\n const common = { id: `${kind}-${n}`, position: { x: 0, y: 50, z: 0 } }\n const part: V3PrimitiveCreation =\n kind === 'box'\n ? { ...common, kind, dimensions: { width: 100, height: 100, depth: 100 } }\n : kind === 'cylinder'\n ? { ...common, kind, dimensions: { radius: 50, length: 100 } }\n : kind === 'rounded-box'\n ? { ...common, kind, dimensions: { width: 100, height: 100, depth: 100, round: 10 } }\n : {\n ...common,\n position: { x: 0, y: 0, z: 0 },\n kind: 'portal',\n dimensions: {\n left: -100,\n right: 100,\n bottom: 0,\n top: 200,\n openingLeft: -70,\n openingRight: 70,\n openingTop: 170,\n depth: 30\n }\n }\n this.session!.add(part)\n this.selected = part.id\n })\n }\n /**\n * The list's own operations, as V3 part edits — each one step of the session's history. The copy and the moved\n * part stay selected, as they do in the V2 list.\n */\n private duplicatePart(id: string) {\n this.run(() => {\n const before = new Set(this.session!.read().geometry.map(g => g.id))\n this.session!.edit({ kind: 'duplicate-part', target: id })\n this.selected = this.session!.read().geometry.find(g => !before.has(g.id))?.id ?? id\n })\n }\n private movePart(id: string, to: number) {\n this.run(() => this.session!.edit({ kind: 'move-part', target: id, to }))\n }\n private removePart(id: string) {\n try {\n this.session!.edit({ kind: 'remove-part', target: id })\n this.error = ''\n if (this.selected === id) this.selected = ''\n this.changed()\n } catch (error) {\n /* The refusal a person meets most: another part stands on this one or follows its size. Said in their words. */\n this.error =\n (error as { code?: string })?.code === 'PART_REFERENCED'\n ? i18next.t('figure.text.part-is-referenced', { part: id })\n : error instanceof Error\n ? error.message\n : String(error)\n }\n }\n private toggleHiddenPart(id: string) {\n const next = new Set(this.hiddenParts)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n this.hiddenParts = next\n }\n /** What the gizmo may write for the selected part — read off the asset being edited. */\n private reachOf(id: string): GizmoReach {\n const none = { translate: false, rotate: false, scale: false }\n if (!id || !this.session) return none\n try {\n return gizmoReachOf(JSON.parse(this.session.source()), id)\n } catch {\n return none\n }\n }\n /** A drag, written back as the part's own inputs — one step of the history, like typing the numbers. */\n private transformed(id: string, result: GizmoResult) {\n const view = this.session!.read()\n const sizes = Object.fromEntries(view.fields.map(field => [field.id, field.value as number]))\n const changes = gizmoChanges(id, this.reachOf(id), result, sizes)\n if (changes.length) this.run(() => this.session!.apply(changes))\n else this.requestUpdate()\n }\n /** 맞추기 — one tool, one step of the history, through the same inputs as the gizmo. */\n private align(tool: AlignTool) {\n this.run(() => {\n const asset = JSON.parse(this.session!.source())\n const changes = alignChanges(asset, this.selected, this.reachOf(this.selected), tool)\n if (changes.length) this.session!.apply(changes)\n })\n }\n /** A mirrored copy: duplicate, then place the copy on the other side — two steps, as the V2 list makes it. */\n private mirror(axis: 'x' | 'z') {\n this.run(() => {\n const id = this.selected\n const before = new Set(this.session!.read().geometry.map(g => g.id))\n this.session!.edit({ kind: 'duplicate-part', target: id })\n const copy = this.session!.read().geometry.find(g => !before.has(g.id))?.id\n if (!copy) return\n this.session!.apply(mirrorChanges(JSON.parse(this.session!.source()), id, copy, axis))\n this.selected = copy\n })\n }\n private renderTools(unavailable: boolean) {\n const reach = this.reachOf(this.selected)\n if (!this.selected || !reach.translate) return null\n let asset: unknown\n try {\n asset = JSON.parse(this.session!.source())\n } catch {\n return null\n }\n const tool = (name: AlignTool, icon: string, label: string, title: string) =>\n html`<button ?disabled=${unavailable} aria-label=${i18next.t(label)} title=${i18next.t(title)} @click=${() => this.align(name)}>\n <md-icon>${icon}</md-icon>\n </button>`\n return html`<div tools title=${i18next.t('figure.text.tools-explained')}>\n ${tool('centre-x', 'horizontal_distribute', 'figure.button.center-x', 'figure.text.center-on-x')}\n ${tool('centre-z', 'vertical_align_center', 'figure.button.center-z', 'figure.text.center-on-z')}\n ${tool('floor', 'vertical_align_bottom', 'figure.button.to-floor', 'figure.text.put-on-floor')}\n ${(['x', 'z'] as const).map(axis => {\n const able = canMirror(asset as never, this.selected, axis, reach)\n return html`<button\n ?disabled=${unavailable || !able}\n aria-label=${i18next.t('figure.button.mirror-' + axis)}\n title=${i18next.t(able ? 'figure.text.mirror-explained' : 'figure.text.mirror-would-overlap')}\n @click=${() => this.mirror(axis)}\n >\n <md-icon>${axis === 'x' ? 'flip' : 'flip_camera_android'}</md-icon>\n </button>`\n })}\n ${tool('snap', 'grid_on', 'figure.button.snap', 'figure.text.snap-explained')}\n </div>`\n }\n private changeField(field: { id: string; unit: V3InputChange['unit']; role?: string }, event: Event) {\n const input = event.target as HTMLInputElement,\n value = input.valueAsNumber\n this.run(() =>\n this.session!.apply([\n { kind: field.role === 'state' ? 'set-state' : 'set-design', input: field.id, unit: field.unit, value }\n ])\n )\n // Rejected edits must also restore the displayed numeric value.\n input.value = String(this.session!.read().fields.find(i => i.id === field.id)!.value)\n }\n render() {\n const view = this.session?.read()\n if (!view) return html`<p>모델을 여는 중입니다.</p>`\n const unavailable = view.loading || !!view.error || view.saving || !view.context\n const part = view.geometry.find(g => g.id === this.selected)\n // Shared/root parameters remain available even when a part is selected.\n const own = view.fields.filter(i => this.selected && i.id.startsWith(this.selected + '.'))\n const common = view.fields.filter(i => !view.geometry.some(g => i.id.startsWith(g.id + '.')))\n const fields = this.selected ? [...own, ...common] : view.fields\n return html` <header>\n <strong>V3 모델링</strong>\n <button ?disabled=${unavailable || !view.canUndo} @click=${() => this.run(() => this.session!.undo())}>\n 실행 취소\n </button>\n <button ?disabled=${unavailable || !view.canRedo} @click=${() => this.run(() => this.session!.redo())}>\n 다시 실행\n </button>\n <button @click=${() => this.renderRoot.querySelector<FigureV3Canvas>('figure-v3-canvas')?.fit()}>\n 전체 보기\n </button>\n <span class=\"status\" role=\"status\"\n >${view.loading ? '불러오는 중' : view.saving ? '저장 중' : view.dirty || !view.id ? '저장 안 됨' : '저장됨'}</span\n >\n <button ?disabled=${unavailable || (!view.dirty && !!view.id)} @click=${this.save}>저장</button>\n </header>\n ${this.error || view.error ? html`<div role=\"alert\" class=\"error\">${this.error || view.error}</div>` : null}\n <main>\n <figure-v3-parts\n .parts=${view.geometry.map(\n (g): V3PartRow => ({\n id: g.id,\n provider: (g as { shape?: { provider?: string } }).shape?.provider ?? '',\n hidden: this.hiddenParts.has(g.id),\n invisible: (g as { visible?: boolean }).visible === false\n })\n )}\n .selected=${this.selected}\n ?locked=${unavailable}\n @add-part=${(e: CustomEvent) => this.add(e.detail.kind)}\n @select-part=${(e: CustomEvent) => (this.selected = e.detail.id)}\n @toggle-part-hidden=${(e: CustomEvent) => this.toggleHiddenPart(e.detail.id)}\n @set-all-parts-hidden=${(e: CustomEvent) =>\n (this.hiddenParts = e.detail.hidden ? new Set(view.geometry.map(g => g.id)) : new Set())}\n @move-part-up=${(e: CustomEvent) => this.movePart(e.detail.id, e.detail.to)}\n @move-part-down=${(e: CustomEvent) => this.movePart(e.detail.id, e.detail.to)}\n @duplicate-part=${(e: CustomEvent) => this.duplicatePart(e.detail.id)}\n @remove-part=${(e: CustomEvent) => this.removePart(e.detail.id)}\n ></figure-v3-parts>\n <figure-v3-canvas\n .parts=${drawableV3Parts(view.geometry ?? []).filter(body => !this.hiddenParts.has((body as { id: string }).id))}\n .palette=${view.palette ?? {}}\n .context=${view.context ?? ''}\n .selected=${this.selected}\n .reach=${unavailable ? { translate: false, rotate: false, scale: false } : this.reachOf(this.selected)}\n @part-transformed=${(e: CustomEvent) => this.transformed(e.detail.id, e.detail.result)}\n @part-selected=${(e: CustomEvent<string>) => {\n this.selected = e.detail\n }}\n @render-error=${(e: CustomEvent<Error>) => {\n this.error = e.detail.message\n }}\n ></figure-v3-canvas>\n <aside>\n <h3>${this.selected || '모델 입력'}</h3>\n ${this.renderTools(unavailable)}\n ${fields.map(field => html`<label><span>${fieldLabel(field.id)} (${field.unit})${field.role === 'state' ? ' · 동작' : ''}</span><input aria-label=${field.id} type=\"number\" step=\"any\" .value=${String(field.value)} ?disabled=${unavailable} @change=${(e: Event) => this.changeField(field, e)} /></label>`)}\n ${\n part\n ? html`<figure-v3-material\n .body=${part}\n .palette=${view.palette ?? {}}\n ?locked=${unavailable}\n @v3-part-edit=${(e: CustomEvent) => this.run(() => this.session!.edit(e.detail.edit))}\n ></figure-v3-material>`\n : null\n }\n ${\n view.bindings.length\n ? html`<h3>배치 연결점</h3>\n ${view.bindings.map(b => html`<p>${b.label} · ${b.role}</p>`)}`\n : null\n }\n </aside>\n </main>`\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"v3-editor.js","sourceRoot":"","sources":["../../client/modeller/v3-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css, type PropertyValues } from 'lit'\nimport { i18next } from '@operato/i18n'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport type { V3InputChange, V3PrimitiveCreation } from '@hatiolab/figure-model'\nimport type { V3ProductSession } from './v3-product-session.js'\nimport { captureV3Thumbnail } from './v3-thumbnail.js'\nimport { drawableV3Parts } from './v3-renderer.js'\nimport './v3-canvas.js'\nimport './figure-v3-parts.js'\nimport './figure-v3-material.js'\nimport { gizmoChanges, gizmoReachOf, type GizmoReach, type GizmoResult } from './v3-gizmo.js'\nimport { alignChanges, canMirror, mirrorChanges, type AlignTool } from './v3-align.js'\nimport type { V3PartRow } from './figure-v3-parts.js'\nimport type { FigureV3Canvas } from './v3-canvas.js'\n\nconst names: Record<string, string> = {\n position: '위치',\n rotation: '회전',\n size: '크기',\n dimension: '치수',\n width: '너비',\n height: '높이',\n depth: '깊이',\n radius: '반지름',\n length: '길이',\n round: '모서리 반경',\n left: '왼쪽',\n right: '오른쪽',\n bottom: '아랫면',\n top: '윗면',\n openingLeft: '개구부 왼쪽',\n openingRight: '개구부 오른쪽',\n openingTop: '개구부 윗면'\n}\nfunction fieldLabel(id: string) {\n return id\n .split('.')\n .map(p => names[p] ?? p.toUpperCase())\n .join(' · ')\n}\n\n/** Product editor surface. The injected session is shared by page persistence and AI commands. */\n@customElement('figure-v3-editor')\nexport class FigureV3Editor extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n height: 100%;\n /*\n The editor folds by the width it is given, not the window's. The rail (208 open, 56 closed) and the page's\n 320 side take their share first, so a window rule was wrong whenever either was there: at 945 with the rail\n open the editor had 417 and still drew its 660 of columns, over the side (UX ruling, 2026-09-24).\n */\n container-type: inline-size;\n font: 13px sans-serif;\n color: var(--md-sys-color-on-surface, #22343f);\n }\n header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n flex-wrap: wrap;\n }\n main {\n flex: 1;\n min-height: 0;\n display: grid;\n grid-template-columns: 180px minmax(180px, 1fr) 300px;\n }\n aside {\n padding: 12px;\n overflow: auto;\n background: var(--md-sys-color-surface, #fff);\n }\n figure-v3-parts {\n min-height: 0;\n }\n aside:last-child {\n border-left: 1px solid var(--md-sys-color-outline-variant);\n }\n h3 {\n font-size: var(--ui-t-body, 13px);\n margin: 22px 0 10px;\n }\n h3:first-child {\n margin-top: 0;\n }\n button,\n input,\n select {\n font: inherit;\n box-sizing: border-box;\n height: 34px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: var(--md-sys-color-surface, #fff);\n color: inherit;\n padding: 0 8px;\n min-width: 0;\n }\n button {\n cursor: pointer;\n }\n button:disabled {\n opacity: 0.45;\n cursor: default;\n }\n button[aria-pressed='true'] {\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n border-color: var(--md-sys-color-primary);\n }\n label[name-field] {\n margin: 0 0 8px;\n }\n label[name-field] input {\n font-weight: 600;\n }\n div[tools] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin: 0 0 8px;\n }\n div[tools] button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n padding: 0;\n }\n div[tools] md-icon {\n font-size: 18px;\n width: 18px;\n height: 18px;\n }\n .parts {\n display: grid;\n gap: 6px;\n }\n .recipes {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px;\n }\n label {\n display: grid;\n grid-template-columns: 112px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n margin: 8px 0;\n }\n label span {\n overflow-wrap: anywhere;\n }\n .error {\n padding: 10px;\n background: var(--md-sys-color-error-container);\n color: var(--md-sys-color-on-error-container);\n white-space: pre-wrap;\n }\n .status {\n margin-left: auto;\n }\n .hint {\n color: var(--md-sys-color-on-surface-variant);\n line-height: 1.5;\n }\n /* 660 and over: parts | canvas | inputs. Below that the sum of the columns' least widths no longer fits. */\n @container (max-width: 659px) {\n main {\n grid-template-columns: 140px minmax(160px, 1fr);\n }\n aside:last-child {\n grid-column: 1/-1;\n max-height: 260px;\n border-left: none;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n }\n /* Under 420: one column. The canvas first — seeing what is being made comes before the lists — and main scrolls. */\n @container (max-width: 419px) {\n main {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(240px, 45%);\n grid-auto-rows: auto;\n overflow-y: auto;\n }\n figure-v3-canvas {\n order: -1;\n }\n figure-v3-parts {\n border-right: none;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n aside:last-child {\n max-height: none;\n }\n }\n `\n @property({ attribute: false }) session?: V3ProductSession\n @property({ type: Number }) revision = 0\n @state() private selected = ''\n @state() private error = ''\n /**\n * Parts hidden on the workbench — the author's view while working, not the asset's visibility. Not saved, as in\n * the V2 modeller: a part hidden here is still in the figure, still checked, still drawn on a board.\n */\n @state() private hiddenParts = new Set<string>()\n private lastContext: string | null = null\n protected willUpdate(_changed: PropertyValues) {\n const view = this.session?.read()\n if (view?.context !== this.lastContext) {\n this.lastContext = view?.context ?? null\n this.selected = ''\n this.error = ''\n this.hiddenParts = new Set()\n }\n if (view && !view.geometry.some(g => g.id === this.selected)) this.selected = ''\n }\n private run(action: () => unknown) {\n try {\n action()\n this.error = ''\n this.changed()\n } catch (error) {\n this.error = error instanceof Error ? error.message : String(error)\n }\n }\n private changed() {\n this.requestUpdate()\n this.dispatchEvent(new CustomEvent('v3-changed', { bubbles: true, composed: true }))\n }\n private async save() {\n if (!this.session) return\n try {\n /*\n The card's picture is taken before the save starts, from a canvas of its own at the card's size —\n not from the one on screen, which stands wherever the author left it turned. A picture that cannot\n be taken is not an error: the save goes on without it (see `v3-thumbnail.ts`).\n */\n const view = this.session.read()\n const thumbnail = await captureV3Thumbnail(drawableV3Parts(view.geometry ?? []), view.palette ?? {})\n const promise = this.session.save({ thumbnail })\n this.changed()\n await promise\n this.error = ''\n } catch (error) {\n this.error = error instanceof Error ? error.message : String(error)\n } finally {\n this.changed()\n }\n }\n private add(kind: V3PrimitiveCreation['kind']) {\n if (!this.session) return\n this.run(() => {\n const ids = new Set(this.session!.read().geometry.map(g => g.id))\n let n = 1\n while (ids.has(`${kind}-${n}`)) n++\n const common = { id: `${kind}-${n}`, position: { x: 0, y: 50, z: 0 } }\n const part: V3PrimitiveCreation =\n kind === 'box'\n ? { ...common, kind, dimensions: { width: 100, height: 100, depth: 100 } }\n : kind === 'cylinder'\n ? { ...common, kind, dimensions: { radius: 50, length: 100 } }\n : kind === 'rounded-box'\n ? { ...common, kind, dimensions: { width: 100, height: 100, depth: 100, round: 10 } }\n : {\n ...common,\n position: { x: 0, y: 0, z: 0 },\n kind: 'portal',\n dimensions: {\n left: -100,\n right: 100,\n bottom: 0,\n top: 200,\n openingLeft: -70,\n openingRight: 70,\n openingTop: 170,\n depth: 30\n }\n }\n this.session!.add(part)\n this.selected = part.id\n })\n }\n /**\n * The list's own operations, as V3 part edits — each one step of the session's history. The copy and the moved\n * part stay selected, as they do in the V2 list.\n */\n private duplicatePart(id: string) {\n this.run(() => {\n const before = new Set(this.session!.read().geometry.map(g => g.id))\n this.session!.edit({ kind: 'duplicate-part', target: id })\n this.selected = this.session!.read().geometry.find(g => !before.has(g.id))?.id ?? id\n })\n }\n private movePart(id: string, to: number) {\n this.run(() => this.session!.edit({ kind: 'move-part', target: id, to }))\n }\n private removePart(id: string) {\n try {\n this.session!.edit({ kind: 'remove-part', target: id })\n this.error = ''\n if (this.selected === id) this.selected = ''\n this.changed()\n } catch (error) {\n /* The refusal a person meets most: another part stands on this one or follows its size. Said in their words. */\n this.error =\n (error as { code?: string })?.code === 'PART_REFERENCED'\n ? i18next.t('figure.text.part-is-referenced', { part: id })\n : error instanceof Error\n ? error.message\n : String(error)\n }\n }\n private toggleHiddenPart(id: string) {\n const next = new Set(this.hiddenParts)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n this.hiddenParts = next\n }\n /** What the gizmo may write for the selected part — read off the asset being edited. */\n private reachOf(id: string): GizmoReach {\n const none = { translate: false, rotate: false, scale: false }\n if (!id || !this.session) return none\n try {\n return gizmoReachOf(JSON.parse(this.session.source()), id)\n } catch {\n return none\n }\n }\n /** A drag, written back as the part's own inputs — one step of the history, like typing the numbers. */\n private transformed(id: string, result: GizmoResult) {\n const view = this.session!.read()\n const sizes = Object.fromEntries(view.fields.map(field => [field.id, field.value as number]))\n const changes = gizmoChanges(id, this.reachOf(id), result, sizes)\n if (changes.length) this.run(() => this.session!.apply(changes))\n else this.requestUpdate()\n }\n /** 맞추기 — one tool, one step of the history, through the same inputs as the gizmo. */\n private align(tool: AlignTool) {\n this.run(() => {\n const asset = JSON.parse(this.session!.source())\n const changes = alignChanges(asset, this.selected, this.reachOf(this.selected), tool)\n if (changes.length) this.session!.apply(changes)\n })\n }\n /** A mirrored copy: duplicate, then place the copy on the other side — two steps, as the V2 list makes it. */\n private mirror(axis: 'x' | 'z') {\n this.run(() => {\n const id = this.selected\n const before = new Set(this.session!.read().geometry.map(g => g.id))\n this.session!.edit({ kind: 'duplicate-part', target: id })\n const copy = this.session!.read().geometry.find(g => !before.has(g.id))?.id\n if (!copy) return\n this.session!.apply(mirrorChanges(JSON.parse(this.session!.source()), id, copy, axis))\n this.selected = copy\n })\n }\n private renderTools(unavailable: boolean) {\n const reach = this.reachOf(this.selected)\n if (!this.selected || !reach.translate) return null\n let asset: unknown\n try {\n asset = JSON.parse(this.session!.source())\n } catch {\n return null\n }\n const tool = (name: AlignTool, icon: string, label: string, title: string) =>\n html`<button ?disabled=${unavailable} aria-label=${i18next.t(label)} title=${i18next.t(title)} @click=${() => this.align(name)}>\n <md-icon>${icon}</md-icon>\n </button>`\n return html`<div tools title=${i18next.t('figure.text.tools-explained')}>\n ${tool('centre-x', 'horizontal_distribute', 'figure.button.center-x', 'figure.text.center-on-x')}\n ${tool('centre-z', 'vertical_align_center', 'figure.button.center-z', 'figure.text.center-on-z')}\n ${tool('floor', 'vertical_align_bottom', 'figure.button.to-floor', 'figure.text.put-on-floor')}\n ${(['x', 'z'] as const).map(axis => {\n const able = canMirror(asset as never, this.selected, axis, reach)\n return html`<button\n ?disabled=${unavailable || !able}\n aria-label=${i18next.t('figure.button.mirror-' + axis)}\n title=${i18next.t(able ? 'figure.text.mirror-explained' : 'figure.text.mirror-would-overlap')}\n @click=${() => this.mirror(axis)}\n >\n <md-icon>${axis === 'x' ? 'flip' : 'flip_camera_android'}</md-icon>\n </button>`\n })}\n ${tool('snap', 'grid_on', 'figure.button.snap', 'figure.text.snap-explained')}\n </div>`\n }\n /**\n * A part's name — the V2 part name field. It renames every value the part owns, and what refers to them follows\n * (figure-model's rename-part), as one step of the history.\n */\n private renamePart(input: HTMLInputElement) {\n const name = input.value.trim()\n const from = this.selected\n if (!name || name === from) {\n input.value = from\n return\n }\n try {\n this.session!.edit({ kind: 'rename-part', target: from, name })\n this.selected = name\n this.error = ''\n this.changed()\n } catch (error) {\n input.value = from\n const code = (error as { code?: string })?.code\n this.error =\n code === 'PART_ID'\n ? i18next.t(/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name) ? 'figure.text.part-name-taken' : 'figure.text.part-name-invalid', { name })\n : error instanceof Error\n ? error.message\n : String(error)\n }\n }\n private changeField(field: { id: string; unit: V3InputChange['unit']; role?: string }, event: Event) {\n const input = event.target as HTMLInputElement,\n value = input.valueAsNumber\n this.run(() =>\n this.session!.apply([\n { kind: field.role === 'state' ? 'set-state' : 'set-design', input: field.id, unit: field.unit, value }\n ])\n )\n // Rejected edits must also restore the displayed numeric value.\n input.value = String(this.session!.read().fields.find(i => i.id === field.id)!.value)\n }\n render() {\n const view = this.session?.read()\n if (!view) return html`<p>모델을 여는 중입니다.</p>`\n const unavailable = view.loading || !!view.error || view.saving || !view.context\n const part = view.geometry.find(g => g.id === this.selected)\n // Shared/root parameters remain available even when a part is selected.\n const own = view.fields.filter(i => this.selected && i.id.startsWith(this.selected + '.'))\n const common = view.fields.filter(i => !view.geometry.some(g => i.id.startsWith(g.id + '.')))\n const fields = this.selected ? [...own, ...common] : view.fields\n return html` <header>\n <strong>V3 모델링</strong>\n <button ?disabled=${unavailable || !view.canUndo} @click=${() => this.run(() => this.session!.undo())}>\n 실행 취소\n </button>\n <button ?disabled=${unavailable || !view.canRedo} @click=${() => this.run(() => this.session!.redo())}>\n 다시 실행\n </button>\n <button @click=${() => this.renderRoot.querySelector<FigureV3Canvas>('figure-v3-canvas')?.fit()}>\n 전체 보기\n </button>\n <span class=\"status\" role=\"status\"\n >${view.loading ? '불러오는 중' : view.saving ? '저장 중' : view.dirty || !view.id ? '저장 안 됨' : '저장됨'}</span\n >\n <button ?disabled=${unavailable || (!view.dirty && !!view.id)} @click=${this.save}>저장</button>\n </header>\n ${this.error || view.error ? html`<div role=\"alert\" class=\"error\">${this.error || view.error}</div>` : null}\n <main>\n <figure-v3-parts\n .parts=${view.geometry.map(\n (g): V3PartRow => ({\n id: g.id,\n provider: (g as { shape?: { provider?: string } }).shape?.provider ?? '',\n hidden: this.hiddenParts.has(g.id),\n invisible: (g as { visible?: boolean }).visible === false\n })\n )}\n .selected=${this.selected}\n ?locked=${unavailable}\n @add-part=${(e: CustomEvent) => this.add(e.detail.kind)}\n @select-part=${(e: CustomEvent) => (this.selected = e.detail.id)}\n @toggle-part-hidden=${(e: CustomEvent) => this.toggleHiddenPart(e.detail.id)}\n @set-all-parts-hidden=${(e: CustomEvent) =>\n (this.hiddenParts = e.detail.hidden ? new Set(view.geometry.map(g => g.id)) : new Set())}\n @move-part-up=${(e: CustomEvent) => this.movePart(e.detail.id, e.detail.to)}\n @move-part-down=${(e: CustomEvent) => this.movePart(e.detail.id, e.detail.to)}\n @duplicate-part=${(e: CustomEvent) => this.duplicatePart(e.detail.id)}\n @remove-part=${(e: CustomEvent) => this.removePart(e.detail.id)}\n ></figure-v3-parts>\n <figure-v3-canvas\n .parts=${drawableV3Parts(view.geometry ?? []).filter(body => !this.hiddenParts.has((body as { id: string }).id))}\n .palette=${view.palette ?? {}}\n .context=${view.context ?? ''}\n .selected=${this.selected}\n .reach=${unavailable ? { translate: false, rotate: false, scale: false } : this.reachOf(this.selected)}\n @part-transformed=${(e: CustomEvent) => this.transformed(e.detail.id, e.detail.result)}\n @part-selected=${(e: CustomEvent<string>) => {\n this.selected = e.detail\n }}\n @render-error=${(e: CustomEvent<Error>) => {\n this.error = e.detail.message\n }}\n ></figure-v3-canvas>\n <aside>\n ${this.selected && part\n ? html`<label name-field\n ><span>${i18next.t('figure.label.name')}</span\n ><input\n aria-label=${i18next.t('figure.label.name')}\n .value=${this.selected}\n ?disabled=${unavailable}\n @change=${(e: Event) => this.renamePart(e.target as HTMLInputElement)}\n /></label>`\n : html`<h3>${this.selected || '모델 입력'}</h3>`}\n ${this.renderTools(unavailable)}\n ${fields.map(field => html`<label><span>${fieldLabel(field.id)} (${field.unit})${field.role === 'state' ? ' · 동작' : ''}</span><input aria-label=${field.id} type=\"number\" step=\"any\" .value=${String(field.value)} ?disabled=${unavailable} @change=${(e: Event) => this.changeField(field, e)} /></label>`)}\n ${\n part\n ? html`<figure-v3-material\n .body=${part}\n .palette=${view.palette ?? {}}\n ?locked=${unavailable}\n @v3-part-edit=${(e: CustomEvent) => this.run(() => this.session!.edit(e.detail.edit))}\n ></figure-v3-material>`\n : null\n }\n ${\n view.bindings.length\n ? html`<h3>배치 연결점</h3>\n ${view.bindings.map(b => html`<p>${b.label} · ${b.role}</p>`)}`\n : null\n }\n </aside>\n </main>`\n }\n}\n"]}
|
package/dist-client/route.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function route(page: string): "figure-
|
|
1
|
+
export default function route(page: string): "figure-v3-modeller" | "figure-modeller" | "figure-list" | undefined;
|