@things-factory/figure-ui 10.1.15 โ 10.1.17
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/figure-animations.ts +12 -12
- package/client/modeller/figure-canvas.ts +32 -48
- package/client/modeller/figure-capabilities.ts +10 -10
- package/client/modeller/figure-inspector.ts +39 -28
- package/client/modeller/figure-parts.ts +1 -1
- package/client/modeller/figure-preview.ts +122 -25
- package/client/modeller/figure-report.ts +24 -6
- package/client/modeller/figure-settings.ts +45 -2
- package/client/modeller/figure-side.ts +6 -6
- package/client/modeller/figure-source.ts +84 -38
- package/client/modeller/figure-thumbnail.ts +5 -5
- package/client/modeller/figure-view.ts +53 -0
- package/client/modeller/part-edits.ts +36 -36
- package/client/modeller/proposal.ts +25 -4
- package/client/pages/figure-modeller-page.ts +142 -98
- package/dist-client/modeller/figure-animations.d.ts +4 -4
- package/dist-client/modeller/figure-animations.js +10 -10
- package/dist-client/modeller/figure-animations.js.map +1 -1
- package/dist-client/modeller/figure-canvas.d.ts +7 -7
- package/dist-client/modeller/figure-canvas.js +27 -40
- package/dist-client/modeller/figure-canvas.js.map +1 -1
- package/dist-client/modeller/figure-capabilities.d.ts +2 -2
- package/dist-client/modeller/figure-capabilities.js +9 -9
- package/dist-client/modeller/figure-capabilities.js.map +1 -1
- package/dist-client/modeller/figure-inspector.d.ts +16 -5
- package/dist-client/modeller/figure-inspector.js +38 -27
- package/dist-client/modeller/figure-inspector.js.map +1 -1
- package/dist-client/modeller/figure-parts.d.ts +1 -1
- package/dist-client/modeller/figure-parts.js +1 -1
- package/dist-client/modeller/figure-parts.js.map +1 -1
- package/dist-client/modeller/figure-preview.d.ts +39 -0
- package/dist-client/modeller/figure-preview.js +112 -23
- package/dist-client/modeller/figure-preview.js.map +1 -1
- package/dist-client/modeller/figure-report.d.ts +9 -0
- package/dist-client/modeller/figure-report.js +23 -5
- package/dist-client/modeller/figure-report.js.map +1 -1
- package/dist-client/modeller/figure-settings.js +42 -2
- package/dist-client/modeller/figure-settings.js.map +1 -1
- package/dist-client/modeller/figure-side.d.ts +2 -2
- package/dist-client/modeller/figure-side.js +5 -5
- package/dist-client/modeller/figure-side.js.map +1 -1
- package/dist-client/modeller/figure-source.d.ts +38 -23
- package/dist-client/modeller/figure-source.js +40 -21
- package/dist-client/modeller/figure-source.js.map +1 -1
- package/dist-client/modeller/figure-thumbnail.d.ts +2 -2
- package/dist-client/modeller/figure-thumbnail.js +3 -3
- package/dist-client/modeller/figure-thumbnail.js.map +1 -1
- package/dist-client/modeller/figure-view.d.ts +45 -0
- package/dist-client/modeller/figure-view.js +27 -0
- package/dist-client/modeller/figure-view.js.map +1 -1
- package/dist-client/modeller/part-edits.d.ts +16 -16
- package/dist-client/modeller/part-edits.js +35 -35
- package/dist-client/modeller/part-edits.js.map +1 -1
- package/dist-client/modeller/proposal.d.ts +1 -1
- package/dist-client/modeller/proposal.js +15 -3
- package/dist-client/modeller/proposal.js.map +1 -1
- package/dist-client/pages/figure-modeller-page.d.ts +44 -9
- package/dist-client/pages/figure-modeller-page.js +134 -92
- package/dist-client/pages/figure-modeller-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/test/ai-proposal-contract.test.ts +393 -12
- package/test/expect.ts +55 -0
- package/test/figure-source.test.ts +562 -0
- package/test/i18n-prefix-guard.test.ts +1 -1
- package/{client/modeller โ test}/part-edits.test.ts +50 -45
- package/translations/en.json +31 -28
- package/translations/ja.json +16 -21
- package/translations/ko.json +41 -38
- package/translations/ms.json +16 -21
- package/translations/zh.json +16 -21
- package/client/modeller/figure-ask.ts +0 -265
- package/client/modeller/figure-source.test.ts +0 -352
- package/dist-client/modeller/figure-ask.d.ts +0 -40
- package/dist-client/modeller/figure-ask.js +0 -282
- package/dist-client/modeller/figure-ask.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-inspector.js","sourceRoot":"","sources":["../../client/modeller/figure-inspector.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement, nothing, svg } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport {\n EXTRUDE_PRIMITIVES,\n MATERIAL_PRESETS,\n PRIMITIVE_KINDS,\n SEGMENTED_PRIMITIVES,\n SEGMENT_PRESETS,\n SIZING_RULES,\n FIGURE_PLACEMENTS,\n trianglesOf\n} from '@hatiolab/figure-model'\nimport { ANCHOR_RULES, PART_ROLES, REPEAT_LIMIT, anchorOfPart, repeatPlanOfPart } from '@hatiolab/figure-model'\nimport type { AnchorRule, Axis, FigurePart, FigurePlacement, MaterialPreset, PartRole, PrimitiveKind } from '@hatiolab/figure-model'\nimport { activePalette } from '@hatiolab/things-scene'\n\nimport { partToFigure, partFromFigure } from './figure-source.js'\nimport type { BoardModel, PartModel } from './figure-source.js'\nimport { canMirror } from './part-edits.js'\n\n/**\n * ๊ณ ๋ฅธ ๋ถํ์ ์์ฑ.\n *\n * ## ์ฌ๊ธฐ๊ฐ ์ฌ์ฉ์ ์ฉ์ด๋ก ๋ณด์ฌ ์ฃผ๋ ์๋ฆฌ๋ค\n *\n * ๋ชจ๋ธ๋ฌ ํ์ด์ง๊ฐ ๊ฐ๊ณ ์๋ ๊ฒ์ **์ฌ ๋ชจ๋ธ**์ด๋ค โ ๋ณด๋ ์์ ๋ถํ ์ปดํฌ๋ํธ๊ฐ ๋์ธ ์ํ.\n * ๊ทธ๋ฐ๋ฐ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ผ ํ๋ ๊ฒ์ ์ฌ ์์ฑ ์ด๋ฆ(`left`ยท`top`ยท`zPos`)์ด ์๋๋ผ\n * **XยทYยทZ** ๋ค. ๋ค๋ฅธ 3D ๋๊ตฌ๊ฐ ๋ชจ๋ ๊ทธ๋ ๊ฒ ๋ถ๋ฅด๊ณ , ์์น๋ ๋ถํ์ **์ค์ฌ**์ผ๋ก ์ฝ๋๋ค.\n *\n * ๊ทธ๋์ ์ด ํจ๋์ ๋ฐ์ ๋ถํ์ FigureSource ํํ๋ก **๋ณํํด์ ๋ณด์ฌ ์ฃผ๊ณ , ์์ ํ ๊ฒ์\n * ๋ค์ ์ฌ ๋ชจ๋ธ๋ก ๋๋๋ ค ์๋ฆฐ๋ค.** ๋ณํ์ `figure-source.ts` ๊ฐ ํ๋ค โ ์ฌ๊ธฐ์ ์ถ์ ๋ค์ ๊ณ์ฐํ์ง\n * ์๋๋ค.\n *\n * ## ์๋ ๊ฒ๋ง ๋ณด์ฌ ์ค๋ค\n *\n * ๋ถํ ์๋ ๊ณก๋ฉด์ด ์๋ ๋ํ์๋ง, ๋ชจ์๋ฆฌ ๊ตด๋ฆผ์ ๋จ๋ฉด์ ๋ฝ๋ ๋ํ์๋ง ๋ป์ด ์๋ค.\n * ๋ป ์๋ ์นธ์ ํ์์ผ๋ก ๋์ด๋์ผ๋ฉด ์ ์์๊ฐ ใ์ ์ ๋จน์งใ๋ฅผ ๊ณ ๋ฏผํ๊ฒ ๋๋ค โ\n * ์์ ๋ด์ง ์๋๋ค.\n *\n * ## ์ด๋ฆ์ ์ ์ฅ๋๋ ์๋ณ์๋ค\n *\n * `FigurePart.name` ์ ๋ฐ์ธ๋ฉยท์ ๋๋ฉ์ด์
ยท์ฌ๋กฏ์ด ๊ฐ๋ฆฌํค๋ ์ด๋ฆ์ด๋ค. ๊ณ ์น๋ฉด ๋ฐฐ์น๋\n * ์ธ์คํด์ค์ ๋ฐ์ธ๋ฉ์ด **์กฐ์ฉํ** ๋๊ธด๋ค. ๊ทธ๋์ ์ด๋ฆ ์นธ์๋ง ๊ฒฝ๊ณ ๋ฅผ ๋ถ์ธ๋ค.\n *\n * ## ใ์ํ ์์ด ๋ถ๋ ์๋ฆฌใ๋ฅผ ๊ฑท์๋ค\n *\n * `FigurePart.materialSlot`(๋น์ ์ด๋ฆ์ `slot`) ์ ๊ณ ๋ฅด๋ ์นธ์ด ์์๋๋ฐ **์๋ฌด ์ผ๋ ํ์ง ์์๋ค.** things-scene ์\n * figure ๋ฐํ์์ด `slot` ์ ์ฝ์ง ์๋๋ค โ ์ ์ธ ํ ์ค์ด ์ ๋ถ๋ค. ๋๋ ์ค ์๊ณ ๋ง๋ค์๊ณ ,\n * ํ์ธํ์ง ์์ ๊ฒ์ด ์๋ชป์ด๋ค.\n *\n * ๊ทธ๋ฆฌ๊ณ ๋๊ฒ ๋ง๋ค๋๋ผ๋ ์ด ๋ชจ์์ด ์๋๋ค. ์ํ ์์ ํน๋ณํ ๊ฒ์ด ์๋๋ผ **์์ฑ ํ๋**์ด๊ณ ,\n * ํดํยท๋ผ๋ฒจยทํ์ ์ฌ๋ถ์ ๊ฐ์ ์๋ฆฌ์์ ๋ค๋ค์ ธ์ผ ํ๋ค. ๊ทธ ์ค๊ณ๊ฐ ์ ํด์ง๋ฉด(figure-model#2)\n * ์ด ์๋ฆฌ์ **์์ฑ ์ ์ธ๊ณผ ๋ถํ ๋ฐ์ธ๋ฉ** ํธ์ง๊ธฐ๊ฐ ๋ค์ด์จ๋ค.\n *\n * ๊ทธ๋๊น์ง ๋น ์ฝ์์ ๋์ง ์๋๋ค. ์๋ฌด ์ผ๋ ์ ํ๋ ์นธ์ ์๋๋๋ง ๋ชปํ๋ค.\n *\n * ## ๊ณ ์น์ง ์๋๋ค\n *\n * ์ ๋ณธ ํ ๋ฒ์ ์ ์๋ฉด์ด ๊ฐ๋๋ค. ์ฌ๊ธฐ์๋ ๋ฐ๋ ๋ถํ์ ์๋ฆด ๋ฟ์ด๋ค.\n */\n@customElement('figure-inspector')\nexport class FigureInspector extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n --figure-control-height: 30px;\n overflow-y: auto;\n background-color: var(--md-sys-color-surface-container-lowest);\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n /*\n ์ด ํจ๋์ ๋ณธ๋ฌธ ํฌ๊ธฐ๋ฅผ ์ฌ๊ธฐ์ ํ ๋ฒ ์ ํ๋ค.\n\n ์ ์๋ ๊ท์น๋ง๋ค ๋ฐ๋ก ์ ์๋ค. ๊ทธ๋ฌ๋ฉด ๋น ๋จ๋ฆฐ ๊ท์น์ด ๋ณธ๋ฌธ ๊ธฐ๋ณธ ํฌ๊ธฐ(1rem)๋ฅผ\n ๋ฌผ๋ ค๋ฐ์ ๊ทธ ์ค๋ง ์ ๋ชฉ์ฒ๋ผ ์ปค์ง๋ค. ์ค๋ฅ๊ฐ ์๋๋ผ์ ํ๋ฉด์ ๋์ ๋ด์ผ ์๋ค.\n ์ด ํ์ผ์์๋ง ๋ ๋ฒ ๋ฌ๋ค.\n\n form ์์(input ยท select ยท button)๋ ๊ธ๊ผด์ ๋ฌผ๋ ค๋ฐ์ง ์์ผ๋ฏ๋ก ๊ฐ์ ์ ์ด์ผ ํ๋ค.\n ๊ทธ๊ฒ ๋ง๊ณ ๋ ์ฌ๊ธฐ ๊ฐ์ ๋ฐ๋ฅธ๋ค.\n */\n font-size: 0.76rem;\n }\n\n /*\n โโ ์๋ฆฌ๋ฅผ ์๋ผ๋ ํ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n ์์ฑ์ ์์ผ๋ก ๋ ๋์ด๋๋ค(๋ฅ๋ ฅ ยท ํฌํธ ยท ์ ๋๋ฉ์ด์
ยท ๊ธฐ์ค์ ๋ณด). ์ง๊ธ ์ฌ๋ฐฑ์ ๊ทธ๋๋ก ๋๋ฉด\n ๊ทธ๊ฒ๋ค์ด ๋ค์ด์ฌ ์๋ฆฌ๊ฐ ์๋ค. ์ ์ฌ๋ฐฑ์ 6/10 ์ผ๋ก, ์ ๋ชฉ ์๋๋ฅผ 4px ๋ก ์ค์๋ค โ ๊ธ์ ํฌ๊ธฐ์\n ์นธ ๋์ด๋ ๊ฑด๋๋ฆฌ์ง ์๋๋ค(์๊ฒ ๋ง๋๋ ๊ฒ์ด ์๋๋ผ **๋น ๊ณณ์ ์ค์ด๋ ๊ฒ**์ด๋ค).\n */\n section {\n padding: 8px 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n /* ์
๋ ฅ ํ์ ์ด์ดํ๊ฒ, ์๋ก ๋ค๋ฅธ ํธ์ง ์๋ ์ฌ์ด์๋ ํธํก์ ๋๋ค. */\n section + section {\n margin-top: 6px;\n }\n section[collapsible] {\n padding: 0;\n }\n details[group] > summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 34px;\n padding: 0 10px;\n cursor: pointer;\n list-style: none;\n }\n details[group] > summary::-webkit-details-marker {\n display: none;\n }\n details[group] > summary h3 {\n margin: 0;\n }\n details[group] > summary md-icon {\n --md-icon-size: 16px;\n color: var(--md-sys-color-on-surface-variant);\n }\n details[group] > div[group-content] {\n padding: 4px 10px 8px;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n h3 {\n display: flex;\n align-items: center;\n gap: 4px;\n margin: 0 0 4px 0;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* ์์ฐ ๋ฉํ๋ฐ์ดํฐ๋ ๋ถํ์ ๊ณ ์น๋ค๋ ํ์ฌ ๋ฌธ๋งฅ์์๋ ์์ฝ์ผ๋ก๋ง ๋๋ค. */\n details[asset] {\n margin: -1px 0;\n }\n details[asset] summary {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 26px;\n cursor: pointer;\n list-style: none;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n details[asset] summary::-webkit-details-marker {\n display: none;\n }\n details[asset] summary::before {\n content: 'โบ';\n font-size: 1.1rem;\n line-height: 1;\n transition: transform 120ms ease;\n }\n details[asset][open] summary::before {\n transform: rotate(90deg);\n }\n details[asset] summary b {\n font-size: var(--ui-t-micro, 11px);\n letter-spacing: 0.04em;\n }\n details[asset] summary small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 0.7rem;\n }\n\n label {\n display: flex;\n align-items: center;\n gap: 3px;\n margin-bottom: 2px;\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /*\n ๋์๋ง ๋ฌผ์ํ. **๊ธ์ ์ค์ ํ๋ ๋จน์ง ์๋๋ค** โ ๋ผ๋ฒจยท์ ๋ชฉ ์ค์ ๋จ๋ ํญ์ ์นํ๋ค.\n ์์ด์ฝ๋ง ๋๊ณ ํ
๋๋ฆฌ๋ฅผ ์ ๋๋ ์ด์ ๋ ์ด๊ฒ์ด ๋๋ฅผ ๊ฒ์ด๋ผ๊ธฐ๋ณด๋ค ใ๋ ์๋คใ๋ ํ์๋ผ์๋ค.\n */\n button[help] {\n display: inline-flex;\n align-items: center;\n padding: 0;\n margin: 0;\n color: var(--md-sys-color-outline);\n background: none;\n border: none;\n cursor: pointer;\n }\n button[help] md-icon {\n --md-icon-size: 13px;\n font-size: 13px;\n }\n button[help]:hover,\n button[help][aria-expanded='true'] {\n color: var(--md-sys-color-primary);\n }\n\n /* ํธ ๋์๋ง. ๋ผ๋ฒจ ์๋ ํ ์นธ ๋ค์ฌ ๋ถ์ธ๋ค โ ๋ฌด์์ ๋ธ๋ฆฐ ๋ง์ธ์ง ๋ณด์ด๊ฒ. */\n p[hint] {\n margin: 2px 0 4px 0;\n padding-left: 6px;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n border-left: 2px solid var(--md-sys-color-outline-variant);\n }\n\n input,\n select {\n width: 100%;\n min-height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 4px 7px;\n font: var(--input-field-font, inherit);\n font-size: 0.76rem;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n input:focus,\n select:focus {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n }\n\n /*\n ์ซ์ ์นธ โ ๋ผ๋ฒจ์ ์นธ **์** ์ผ์ชฝ์ ๋๋ค.\n\n ๋ฒกํฐ ์ ์๋๊ตฌ(SketchยทFigma)๊ฐ XยทYยทWยทH ๋ฅผ ์ด๋ ๊ฒ ๋๋ค. ๋ผ๋ฒจ์ ์์ ์น์ผ๋ฉด ์ค๋ง๋ค\n ๋ ์ค์ ๋จน์ด์, ์๋ฆฌยทํฌ๊ธฐยทํ์ ์ํ ์นธ์ด ํ๋ฉด ์ ๋ฐ์ ์ฐจ์งํ๋ค. ์์ ๋๋ฉด ํ ์ค์\n ์
์ด ๋ค์ด๊ฐ๊ณ ๋ฌด์์ด ๋ฌด์์ธ์ง๋ ๋ถ์ด ์ฝํ๋ค.\n */\n div[cell] {\n display: flex;\n box-sizing: border-box;\n height: var(--figure-control-height);\n min-height: var(--figure-control-height);\n align-items: center;\n gap: 2px;\n padding-left: 6px;\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n div[cell]:focus-within {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n border-color: transparent;\n }\n div[cell] span[axis] {\n flex: none;\n font-size: 0.64rem;\n letter-spacing: 0.02em;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n div[cell] input {\n min-width: 0;\n min-height: 0;\n height: calc(var(--figure-control-height) - 2px);\n padding: 4px 6px 4px 2px;\n font-family: var(--mono-font, monospace);\n text-align: right;\n background: none;\n border: none;\n border-radius: 0;\n }\n div[cell] input:focus {\n outline: none;\n }\n\n /* ์ถ ์
์ ํ ์ค์ โ ์ขํ๋ ์
์ด ๊ฐ์ด ์ฝํ์ผ ํ๋ค */\n div[triple] {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 4px;\n }\n div[field] + div[field],\n div[triple] + div[field],\n div[field] + div[triple],\n div[inline-field] + div[inline-field],\n div[inline-field] + div[field],\n div[field] + div[inline-field],\n div[vector-row] + div[vector-row],\n div[vector-row] + div[field],\n div[field] + div[vector-row] {\n /* ์นธ ์ฌ์ด 7 โ 5. ์นธ ์์ฒด๋ ๊ทธ๋๋ก ๋๊ณ ์ฌ์ด๋ง ์ขํ๋ค. */\n margin-top: 5px;\n }\n\n /* ์งง์ ๋ผ๋ฒจ๊ณผ ๋จ์ผ ๊ฐ์ ๊ฐ์ ์ค์์ ์ฝ๋๋ค. ๋ณต์กํ ์ ํ๊ธฐ์๋ ์ฐ์ง ์๋๋ค. */\n div[inline-field] {\n display: grid;\n /* ๊ฐ์ ํธ์ง ๋ฐ๋ ์์์๋ ์
๋ ฅ ์์์ ์ ๋ง์ถ๋ค. ๋ผ๋ฒจ ๊ธธ์ด๊ฐ ์นธ ํญ์ ํ๋ค๋ฉด ์ ๋๋ค. */\n grid-template-columns: 64px minmax(0, 1fr);\n align-items: center;\n gap: 7px;\n }\n div[inline-field] > label {\n margin: 0;\n white-space: nowrap;\n }\n /* ํ ์ค ์
๋ ฅ์ ์ค๋ช
์ ์
๋ ฅ์นธ์ ๋ฐ์ด๋ด์ง ์๊ณ ๋ฐ๋ก ์๋ ์ ํญ์์ ์ฝ๋๋ค. */\n div[inline-field] > p[hint] {\n grid-column: 1 / -1;\n margin: -2px 0 1px;\n }\n div[inline-field] > code[fixed] {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* XยทYยทZ๋ ํจ๊ป ๋น๊ตํ๋ ๊ฐ์ด๋ฏ๋ก, ๋ฌถ์ ์ ๋ชฉ๋ง ์ผ์ชฝ์ ๋๊ณ ์
๋ ฅ์ ํ ํ์ ๋๋ค. */\n div[vector-row] {\n display: grid;\n grid-template-columns: 64px minmax(0, 1fr);\n align-items: center;\n gap: 7px;\n }\n div[vector-row] > label {\n margin: 0;\n white-space: nowrap;\n }\n div[vector-row] > p[hint] {\n grid-column: 1 / -1;\n margin: -2px 0 1px;\n }\n div[sizing-choices] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 5px;\n }\n button[sizing-choice] {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 2px;\n min-height: 52px;\n padding: 7px 8px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 7px;\n text-align: left;\n cursor: pointer;\n }\n button[sizing-choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[sizing-choice] b {\n font-size: 0.74rem;\n }\n button[sizing-choice] small {\n font-size: 0.64rem;\n line-height: 1.35;\n opacity: 0.8;\n }\n div[anchor-rows] {\n display: grid;\n gap: 6px;\n }\n div[anchor-row] {\n display: grid;\n grid-template-columns: 46px minmax(0, 1fr);\n align-items: start;\n gap: 8px;\n padding: 6px 7px;\n background: var(--md-sys-color-surface-container);\n border-radius: 7px;\n }\n div[anchor-row] label {\n margin: 0;\n font-size: 0.7rem;\n font-weight: 700;\n }\n div[anchor-options] {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n }\n button[anchor-choice] {\n min-width: 0;\n height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 4px 3px;\n overflow: hidden;\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n font-size: 0.63rem;\n line-height: 1.2;\n text-overflow: ellipsis;\n white-space: nowrap;\n background: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 5px;\n cursor: pointer;\n }\n button[anchor-choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n details[anchor-advanced] {\n grid-column: 2;\n margin-top: 4px;\n }\n details[anchor-advanced] summary {\n cursor: pointer;\n font-size: 0.62rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n details[anchor-advanced] div[anchor-options] {\n margin-top: 4px;\n }\n div[palette-meaning] {\n display: grid;\n gap: 2px;\n margin-top: 7px;\n padding: 6px 8px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container);\n border-radius: 7px;\n }\n div[palette-meaning] b {\n font-size: 0.72rem;\n }\n div[palette-meaning] small {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 0.64rem;\n line-height: 1.35;\n }\n\n /*\n ์ ๋ฐ ์ ์ ๋๊ตฌ.\n\n ๋ณด๋ ํธ์ง๊ธฐ๋ ์์ฐ์ ๋ฐฐ์นํ๋ ๊ณณ์ด๋ผ ๋์ถฉ ๋์๋ ๋์ง๋ง, ์ฌ๊ธฐ๋ ์์ฐ์ ๋ง๋๋\n ๊ณณ์ด๋ค. ใ๋ชธํต ํ๊ฐ์ด๋ฐใยทใ๋ฐ๋ฅ์ ๋ถ์ด๊ธฐใยทใ๋ฐ๋์ชฝ์๋ ํ๋ใ๋ฅผ ์์ผ๋ก ๊ณ์ฐํ๋ฉด\n ๋ ์กฐ๊ธ์ฉ ์ด๊ธ๋๊ณ , ๊ธฐ์ค ์น์๋ฅผ ๋ฐ๊พธ๋ฉด ์ ๋ถ ๋ค์ ํด์ผ ํ๋ค.\n */\n div[tools] {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 4px;\n }\n div[tools] button {\n display: grid;\n place-items: center;\n min-width: 0;\n height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 0;\n font: var(--label-font, inherit);\n font-size: 0.7rem;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n div[tools] button md-icon {\n font-size: 17px;\n }\n div[tools] button[disabled] {\n opacity: 0.35;\n cursor: default;\n }\n div[tools] button:hover:not([disabled]) {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /* ์ง๊ธ ์ด๋ ์ถ์ด ๋์ด๋๋ โ ํฌ๊ธฐ๋ฅผ ๊ณ ์น๋ฉด ๋ฐ๋ ์ ์์ด์ ๊ฐ์ผ๋ก ์ ๋๋ค */\n p[axis-now] {\n margin: 4px 0 0 0;\n font-size: 0.7rem;\n color: var(--md-sys-color-primary);\n }\n /* ์ด ์ ํ์ด ๋ฌด์์ ๋ฌด๋์ง โ ์ฑ์๋์ ๋ฌถ์ ์์ ๊ทธ๋๋ก ์กํ๋ค */\n p[cost] {\n margin: 4px 0 0 0;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* ์ด๋ฆ์ ๋ฐ๊พธ๋ฉด ๋ฌด์์ด ๋๊ธฐ๋์ง ๋งํ๋ค */\n p[warn] {\n margin: 4px 0 0 0;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-tertiary);\n }\n\n /* ๋ถํ ์ ํ๋ฆฌ์
โ ์์ ์
๋ ฅ๋ณด๋ค ์ด ์
์ ๊ถํ๋ค */\n div[presets] {\n display: flex;\n gap: 4px;\n margin-top: 4px;\n }\n div[presets] button {\n flex: 1;\n padding: 3px 0;\n font: var(--label-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: 6px;\n cursor: pointer;\n }\n div[presets] button[on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /*\n ๋ถํ ์ ์ ํ โ ๋ชจ์๊ณผ ์ผ๊ฐํ ์๋ฅผ **ํจ๊ป** ๋ณด์ฌ ์ค๋ค.\n\n ์ซ์๋ง ๋์ด๋์ผ๋ฉด 8 ๊ณผ 16 ์ด ๋ฌด์์ด ๋ค๋ฅธ์ง ์ ์ ์๋ค. ๋ก์ฐํด๋ฆฌ์์ ์ด ์ ํ์ด\n ๊ณง ใ๋ช ๊ฐ๊น์ง ํธํ๊ฒ ๋์ ์ ์๋ใ๋ฅผ ์ ํ๋ฏ๋ก, ๊ฐ์ง๋ ์ ๋์ ๊ทธ ๊ฐ์ด ๋ฌด๋\n ์ผ๊ฐํ ์๋ฅผ ํ์๋ฆฌ์์ ๋ณด์์ผ ํ๋ค.\n\n ์ค๋ฃจ์ฃ์ ์ง์ด๋ธ ๊ทธ๋ฆผ์ด ์๋๋ค โ ๊ณก๋ฉด ํ๋ฆฌ๋ฏธํฐ๋ธ๋ฅผ ์์์ ๋ณธ ์ค๊ณฝ์ด ์ ํํ\n ์ n๊ฐํ์ด๋ค. ์ผ๊ฐํ ์๋ ํ๋ฉด์ด ์
ํ์ง ์๊ณ figure-model ์ trianglesOf ๊ฐ ๋ธ๋ค.\n */\n div[segments] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 4px;\n }\n /* ์ ์ ์ง ยท ๋๊ธฐ โ ๊ณ ๋ฅด๋ ๊ฐ์ด๋ผ ๋ถํ ์์ ๊ฐ์ ๋ชจ์์ผ๋ก ๋๋ค */\n div[choices] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 4px;\n }\n button[choice] {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 1px;\n padding: 6px 8px;\n text-align: left;\n font: var(--label-font, inherit);\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n button[choice]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n button[choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[choice] small {\n opacity: 0.75;\n }\n button[seg] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1px;\n padding: 6px 2px 4px 2px;\n font: var(--label-font, inherit);\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n button[seg]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n button[seg][on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[seg] svg {\n display: block;\n /* ์์ผ๋ฉด 12 ์ 16 ์ด ๋ ๋ค ๋๊ทธ๋ผ๋ฏธ๋ก ๋ณด์ธ๋ค โ ๊ฐ์ด ์ฝํ ๋งํผ์ ํค์ด๋ค */\n width: 32px;\n height: 32px;\n }\n button[seg] svg polygon {\n fill: var(--md-sys-color-surface-container-highest);\n stroke: currentColor;\n stroke-width: 1.1;\n stroke-linejoin: miter;\n }\n button[seg][on] svg polygon {\n fill: var(--md-sys-color-surface-container-lowest);\n }\n button[seg] b {\n font-size: 0.8rem;\n font-weight: 700;\n line-height: 1.1;\n }\n button[seg] small {\n font-size: 0.62rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n button[seg][on] small {\n color: inherit;\n }\n /* ์ฑ๋ฅยท์ค๋ฃจ์ฃ ๊ฒ์ฆ์ ๋ง์น ํ๋ฆฌ์
๋ง ๊ณ ๋ฅธ๋ค. */\n details[free] {\n margin-top: 6px;\n }\n details[free] summary {\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n cursor: pointer;\n }\n details[free] div[cell] {\n margin-top: 4px;\n }\n\n /*\n ์ ๊ฒฌ๋ณธ.\n\n ํ ํฐ์ ๊ธ์๋ก ๋ฐ์ง ์๋๋ค. things-scene ์ ํ๋ ํธ ์ ์ธ์ด ใ์ฌ๊ธฐ ๋ ์ด๋ฆ์ด ์ ์์์\n ๊ณ ๋ฅผ ์ ์๋ ์ ๋ถ์ด๊ณ , ์์ ์์ ํ์ฉํ์ง ์๋ ๊ฒ์ด ๊ฐ๊ฐ์ ์ธ ๋ก์ฐํด๋ฆฌ์ ์ฒซ ๊ท์นใ\n ์ด๋ผ๊ณ ๋ชป๋ฐ๊ณ ์๋ค. ๊ธ์ ์นธ์ผ๋ก ๋๋ฉด ๊ทธ ๊ท์น์ด ํ๋ฉด์์ ์ฌ๋ผ์ง๊ณ , ์คํ ํ๋๋ก\n resolveToken ์ด ๋์ง๋ค.\n */\n div[swatches] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n /*\n ๋ ๋ฌด๋ฆฌ์ ๊ฒฝ๊ณ. ใ์น ํ ์ใ๊ณผ ใ์ผ์ง ์ใ์ด ํ ์ค์ ์์ด๋ฉด accent(์ฃผํฉ)์\n status-warning(์ฃผํฉ)์ด ๋๋ํ ๋์ฌ ๋ฌด์์ด ๋ฌด์์ธ์ง ์ ์ ์๋ค.\n */\n label[group] {\n margin-top: 8px;\n padding-top: 8px;\n font-size: var(--ui-t-micro, 11px);\n letter-spacing: 0.03em;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n\n /* ๊ฐ์ด ์์ ๋ถ์ด์ผ ๋๋ฉด์ ์ผ๋ง์ธ์ง ์๋ค */\n div[slider] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n div[slider] input[type='range'] {\n flex: 1;\n accent-color: var(--md-sys-color-primary);\n cursor: pointer;\n }\n div[slider] output {\n flex: none;\n width: 2.6em;\n text-align: right;\n font: var(--mono-font, ui-monospace, monospace);\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n button[swatch] {\n width: 26px;\n height: 26px;\n padding: 0;\n background-color: var(--swatch);\n border: 1px solid rgba(0, 0, 0, 0.16);\n border-radius: 50%;\n cursor: pointer;\n }\n button[swatch][on] {\n /* ๊ณ ๋ฅธ ๊ฒ์ ํ
๋๋ฆฌ๊ฐ ์๋๋ผ ๊ณ ๋ฆฌ๋ก ํ์ํ๋ค โ ์ ์์ฒด๋ฅผ ๊ฐ๋ฆฌ์ง ์์ผ๋ ค๊ณ */\n box-shadow:\n 0 0 0 2px var(--md-sys-color-surface-container-lowest),\n 0 0 0 4px var(--md-sys-color-primary);\n }\n span[token] {\n display: block;\n margin-top: 6px;\n font-family: var(--mono-font, monospace);\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 7px 0 0 0;\n font-size: 0.74rem;\n color: var(--md-sys-color-on-surface);\n cursor: pointer;\n }\n label[toggle] input {\n width: auto;\n }\n div[role-choices] {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n }\n div[role-choices] label[toggle] {\n justify-content: center;\n min-height: 30px;\n margin: 0;\n padding: 2px 4px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n font-size: 0.68rem;\n text-align: center;\n }\n div[role-choices] label[toggle]:has(input:checked) {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n p[quiet] {\n margin: 0;\n font-size: 0.76rem;\n line-height: 1.6;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /*\n ๊ณ ์น ์ ์๋ ๊ฐ โ ์
๋ ฅ์นธ์ฒ๋ผ ๋ณด์ด์ง ์๊ฒ ํ๋ค.\n\n ์ ์๋ ๊ทธ๋ฅ ๊ธ์์๊ณ , ์์ ์ด๋ฆ ์นธ๊ณผ ๋๋ํ ์์ผ๋ ๋๋ฌ๋ ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์๋ค. ์๋ฌผ์ ์\n ์นธ ์๋ ๋ฐํ์ด ใ์ฝ๋ ๊ฐใ์ด๋ผ๊ณ ๋จผ์ ๋งํ๋ค.\n */\n code[fixed] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 6px;\n background-color: var(--md-sys-color-surface-container-high, rgba(0, 0, 0, 0.05));\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n font-family: var(--mono-font, monospace);\n font-size: 0.76rem;\n }\n\n code[fixed] md-icon {\n --md-icon-size: 13px;\n opacity: 0.7;\n }\n `\n ]\n\n /** ๋ํ์ DB ์๋ณ์. ๋น์ด ์์ผ๋ฉด ๋ฏธ์ ์ฅ ์ ๊ท ๋ชจ๋ธ์ด๋ค. */\n @property({ type: String }) figureId = ''\n /** ๋ํ์ ํ์ ์ด๋ฆ. ์ ๋ณธ์ ์ ์๋ฉด์ด ๋ค๊ณ , ์ฌ๊ธฐ์๋ ๋ณด์ฌ ์ฃผ๊ณ ๋ฐ๊พผ๋ค(`figure-rename` ์ผ๋ก ์๋ฆฐ๋ค). */\n @property({ type: String }) figureName = ''\n /** ๋ถ๋ฅ ํ๋ โ ํ๋ ํธ์์ ๋ฌถ๋ ๊ธฐ์ค. */\n @property({ type: String }) figureCategory?: string\n /** ํ๊ทธ ์ฌ๋ฟ โ ๋ถ๋ฅ๋ก๋ ๋ชป ํ๋ ์ฐพ๊ธฐ. */\n @property({ type: Array }) figureTags?: string[]\n\n /** ํด ๋ ๋์๋ง. ๋ถํ์ ๋ฐ๊ฟ๋ ์ ์ง๋๋ค โ ๋งค๋ฒ ๋ค์ ํด๊ฒ ํ์ง ์๋๋ค. */\n @state() private opened = new Set<string>()\n\n @property({ type: Object }) board?: BoardModel\n /** ๋ณด๋ ์์ ๋ถํ๋ค. ์ฌ ๋ชจ๋ธ ๊ทธ๋๋ก๋ค. */\n @property({ type: Array }) parts: PartModel[] = []\n @property({ type: Number }) selected = -1\n\n /** `part` ๋ HTMLElement ์ ์์ฑ(DOMTokenList)์ด๋ค โ ๊ฐ๋ฆฌ๋ฉด ํ์ด ์ด๊ธ๋๋ค. */\n private get chosen(): PartModel | undefined {\n return this.parts?.[this.selected]\n }\n\n render() {\n const part = this.chosen\n if (!part || !this.board) {\n return html`\n ${this.renderFigure(false)}\n <section>\n <h3>${i18next.t('figure.label.properties')}</h3>\n <p quiet>${i18next.t('figure.text.select-a-part-to-edit')}</p>\n </section>\n `\n }\n\n // ์ฌ๊ธฐ๋ถํฐ๋ ์ฌ์ฉ์ ์ฉ์ด๋ค โ XยทYยทZ, ์์น๋ ๋ถํ ์ค์ฌ, ํ์ ์ ๋(degree).\n const shown = partToFigure(part, this.board)\n\n /*\n ์ญํ ์ ๋จผ์ ๋ฌป๋๋ค.\n\n ์๋ฆฌ(slot)๋ก ์ง์ ํ ๋ถํ์ **๊ทธ๋ ค์ง์ง ์๋๋ค.** ๊ทธ ์ฌ์ค์ ๋ชจ๋ฅธ ์ฑ ์ฌ์ง๋ถํฐ ๊ณ ๋ฅด๋ฉด ์ ์ฐ์ผ\n ์์ ๊ณ ๋ฅด๊ฒ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๋ฆฌ๋ ๋ํ์ด ๋ฅ๋ ฅ์ ์ง ๋๋ง ๋ป์ด ์์ผ๋ฏ๋ก, ๋ฅ๋ ฅ์ด ์์ผ๋ฉด ์ด\n ๋ฌถ์์ ์์ ๋์ค์ง ์๋๋ค โ ํด ๋ฌ๋ ์๋ฌด ์ผ๋ ์ ์ผ์ด๋๋ ์นธ์ ๋ณด์ฌ ์ฃผ์ง ์๋๋ค.\n */\n return html`\n ${this.renderFigure(true)} ${this.renderIdentity(shown)} ${this.renderRole(shown)}\n ${this.renderPlacement(shown)} ${this.renderShape(shown)} ${this.renderMaterial(shown)}\n ${this.renderBehaviour(shown)}\n `\n }\n\n /**\n * โโ ์ด ๋ถํ์ด ๋ฅ๋ ฅ์์ ๋งก๋ ์๋ฆฌ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ใ๋ฅ๋ ฅใ ํญ์ด ๋ํ ์ ์ฒด๊ฐ ๋ฌด์์ ํ๋์ง ์ ํ๊ณ , ์ด๋ ๋ถํ์ด ๊ทธ๊ฒ์ ๋ฐ์ณ ์ฃผ๋์ง๋ ์ฌ๊ธฐ์\n * ์ ํ๋ค. **๋ถํ์ ๊ณ ์น๋ ๊ณณ์ด ํ ๊ตฐ๋ฐ์ฌ์ผ** ํ๊ธฐ ๋๋ฌธ์ด๋ค โ ๋ชฉ๋ก์ ๋ฐ๋ก ๋๋ฉด ๊ฐ์ ๋ถํ์\n * ๋ ํ๋ฉด์์ ๊ณ ์น๊ฒ ๋๊ณ , ์ ์์๋ ์ด๋ ์ชฝ์ด ์ด๊ธฐ๋์ง ๋งค๋ฒ ์๊ฐํด์ผ ํ๋ค.\n *\n * ์นธ ์๋ `repeat` ๊ฐ ์์ผ๋ฉด ๋ฐ์ง ์๋๋ค. ๋ฐ๋ณตํ๋ ์๋ฆฌ์ ์นธ ์๋ **์ธ์คํด์ค ํฌ๊ธฐ**๊ฐ ์ ํ๋ค โ\n * ์ปจ๋ฒ ์ด์ด๊ฐ ๊ธธ์ด์ง๋ฉด ์ค์ ์๋ฆฌ๊ฐ ๋์ด๋๋ ๊ฒ์ด ๊ทธ๊ฒ์ด๊ณ , ์ฌ๊ธฐ ์ ์ ๊ฐ์ ์ ์ฐ์ธ๋ค.\n */\n private renderRole(part: FigurePart) {\n if (!this.board?.capabilities?.length) return nothing\n\n const roles = part.capability?.roles ?? []\n const repeats = part.sizing === 'repeat' && !!part.repeat\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.role-in-capability')}${this.help('figure.text.anchors-are-not-drawn')}</h3>\n\n <div role-choices>\n ${(PART_ROLES as readonly PartRole[]).map(\n one => html`\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${live(roles.includes(one))}\n @change=${(e: Event) => this.toggleRole(one, (e.target as HTMLInputElement).checked)}\n />\n ${i18next.t('figure.label.role-' + one)}\n </label>\n `\n )}\n </div>\n ${roles.length === 0 ? html`<p quiet>${i18next.t('figure.text.role-none-means-drawn')}</p>` : nothing}\n\n ${roles.includes('slot')\n ? html`\n <div field>\n <label>${i18next.t('figure.label.accepts')}${this.help('figure.text.accepts-explained')}</label>\n <input\n .value=${(part.capability?.accepts ?? []).join(', ')}\n placeholder=${i18next.t('figure.text.accepts-anything')}\n @change=${(e: Event) => this.setAccepts((e.target as HTMLInputElement).value)}\n />\n </div>\n <div field>\n <label>${i18next.t('figure.label.slot-capacity')}</label>\n ${repeats\n ? html`<p quiet>${i18next.t('figure.text.capacity-from-repeat')}</p>`\n : this.number('', part.capability?.capacity ?? 1, value => this.setCapacity(value), 1)}\n </div>\n `\n : nothing}\n </section>\n `\n }\n\n /**\n * ์ญํ ํ๋๋ฅผ ์ผ๊ณ ๋๋ค.\n *\n * **์ฌ๋ฟ์ ํจ๊ป ๋งก์ ์ ์๋ค.** AGV ์ ์ํ์ ๋ฌผ๊ฑด์ ๋๋ ์๋ฆฌ์ด๋ฉด์ ๊ทธ ์๋ฆฌ๋ก ๋ฌผ๊ฑด์ด\n * ๋ค์ด์ค๊ณ ๋๊ฐ๋ค. ๊ทธ๋์ ํ๋๋ฅผ ๊ณ ๋ฅด๋ ์ ํ ์์๊ฐ ์๋๋ผ ํ์ธ ์์๋ค.\n *\n * ๋ง์ง๋ง ์ญํ ์ ๋๋ฉด `capability` ๋ฅผ ํต์งธ๋ก ์ง์ด๋ค. ๋น ๋ฐฐ์ด์ ๋จ๊ธฐ๋ฉด ํ์์ด ์ค๋ฅ๋ก ๋ณด๊ณ ,\n * ์ ์์๊ฐ ๋ณด๊ธฐ์๋ ์๋ฌด ์ญํ ๋ ์๋ ํ๋ฒํ ๋ถํ์ธ๋ฐ ๋ฐํ์ด ๋งํ๋ค.\n */\n private toggleRole(role: PartRole, on: boolean) {\n this.change(part => {\n const roles = (part.capability?.roles ?? []).filter(one => one !== role)\n if (on) roles.push(role)\n\n if (roles.length === 0) {\n const { capability, ...rest } = part\n return rest as FigurePart\n }\n\n // ํ์์ด ์ ์ ์์๋ฅผ ์งํจ๋ค โ ์ผ ์์๋๋ก ๋๋ฉด ๊ฐ์ ๋ป์ด ๋ค๋ฅธ ๊ฐ์ผ๋ก ์ ์ฅ๋๋ค.\n const ordered = (PART_ROLES as readonly PartRole[]).filter(one => roles.includes(one))\n return { ...part, capability: { ...part.capability, roles: ordered } }\n })\n }\n\n private setAccepts(raw: string) {\n const accepts = raw\n .split(',')\n .map(one => one.trim())\n .filter(one => one.length > 0)\n\n this.change(part => {\n const spec = { ...part.capability, roles: part.capability?.roles ?? ['slot' as PartRole] }\n // ๋น ๋ชฉ๋ก์ ์ ํํ์ง ์๋๋ค๋ ๋ป์ด๋ค. ๋น ๋ฐฐ์ด์ ์ ์ฅํ๋ฉด ์๋ฌด๊ฒ๋ ๋ชป ๋ฐ๋ ๊ฒ์ผ๋ก ์ฝํ๋ค.\n if (accepts.length > 0) spec.accepts = accepts\n else delete spec.accepts\n return { ...part, capability: spec as NonNullable<FigurePart['capability']> }\n })\n }\n\n private setCapacity(value: number) {\n this.change(part => {\n const spec = { ...part.capability, roles: part.capability?.roles ?? ['slot' as PartRole] }\n if (Number.isFinite(value) && value >= 1) spec.capacity = Math.floor(value)\n else delete spec.capacity\n return { ...part, capability: spec as NonNullable<FigurePart['capability']> }\n })\n }\n\n /**\n * ๋ํ ์์ฒด โ ์ด๋ฆ๊ณผ ํ์
.\n *\n * ## ์ ๋จธ๋ฆฌ์ค์ด ์๋๋ผ ์ฌ๊ธฐ์ธ๊ฐ\n *\n * ์ ์๋ฉด ์์ ์ค์ ํ๋ ๋ ๋๊ณ ์ด๋ฆ ์นธ์ ๋์์๋ค. ์ฑ์์๋ ์
ธ์ด ํ์ด์ง ์ ๋ชฉ์ผ๋ก ๊ทธ ์ด๋ฆ์\n * ์ด๋ฏธ ๊ทธ๋ฆฌ๋ฏ๋ก ๊ฐ์ ๊ธ์๊ฐ ๋ ๋ฒ ๋์ค๊ณ , ์บ๋ฒ์ค๊ฐ ์ฃผ์ธ๊ณต์ธ ํ๋ฉด์์ ๊ทธ ์ค๋งํผ ๋์ด๋ฅผ ์์๋ค.\n * ์์ฑ ํจ๋์ ใ์ด ๋ํ์ด ๋ฌด์์ธ๊ฐใ๋ฅผ ๋ค๋ฃจ๋ ์๋ฆฌ์ด๋ฏ๋ก ์ด๋ฆ๋ ์ฌ๊ธฐ ์ฐ๋ค.\n *\n * ## ํ์
์ ์ฝ๊ธฐ๋ง ํ๋ค\n *\n * ์ ์ฅ๋๋ ์๋ณ์๋ค. ๋ฐฐ์น๋ ๋ณด๋๊ฐ ์ด ์ด๋ฆ์ผ๋ก ํ์
์ ์ฐพ์ผ๋ฏ๋ก ๋ง๋ ๋ค์๋ ๋ชป ๋ฐ๊พผ๋ค.\n */\n private renderFigure(compact = false) {\n const fields = html`\n <div inline-field>\n <label>${i18next.t('figure.label.name')}</label>\n <input\n .value=${this.figureName}\n placeholder=${i18next.t('figure.text.figure-display-name')}\n @change=${(e: Event) =>\n this.dispatchEvent(\n new CustomEvent('figure-rename', {\n detail: { name: (e.target as HTMLInputElement).value },\n bubbles: true,\n composed: true\n })\n )}\n />\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.figure-type')}${this.figureId ? this.helpButton('figure.text.type-name-cannot-change') : nothing}</label>\n ${!this.figureId\n ? html`<input\n .value=${this.board?.figureType ?? ''}\n placeholder=${i18next.t('figure.text.figure-type-placeholder', { defaultValue: '๋ํ ์๋ณ ํ์
(์: OHT)' })}\n @change=${(e: Event) =>\n this.dispatchEvent(\n new CustomEvent('figure-type-change', {\n detail: { type: (e.target as HTMLInputElement).value.trim().toUpperCase() },\n bubbles: true,\n composed: true\n })\n )}\n />`\n : html`<code fixed title=${i18next.t('figure.text.type-name-cannot-change')}>\n <md-icon>lock</md-icon>${this.board?.figureType ?? ''}\n </code>\n ${this.helpHint('figure.text.type-name-cannot-change')}`}\n </div>\n <!--\n ์ ๋ชป ๊ณ ์น๋์ง **์ ์ด ๋๋ค.** ์ ์๋ tooltip ์๋ง ์์๊ณ , ๊ทธ๋ฌ๋ฉด ๋๋ฌ ๋ณด๊ณ ์ ๋๋ ๊ฒ์\n ์๊ฒ ๋๋ค โ ํ๋ฉด์ด ์ ๋๋ ์ด์ ๋ฅผ ๋งํ์ง ์์ผ๋ฉด ์ฌ์ฉ์๊ฐ ์๊ธฐ ์ค์๋ผ๊ณ ์๊ฐํ๋ค.\n -->\n\n <div inline-field>\n <label>${i18next.t('figure.label.figure-placement')}${this.helpButton('figure.text.placement-explained')}</label>\n <select\n .value=${this.board?.placement ?? 'floor'}\n @change=${(e: Event) => this.setPlacement((e.target as HTMLSelectElement).value as FigurePlacement)}\n >\n <option value=\"floor\" ?selected=${(this.board?.placement ?? 'floor') === 'floor'}>\n ${i18next.t('figure.label.placement-floor')}\n </option>\n <option value=\"ceiling\" ?selected=${this.board?.placement === 'ceiling'}>\n ${i18next.t('figure.label.placement-ceiling')}\n </option>\n <option value=\"center\" ?selected=${this.board?.placement === 'center'}>\n ${i18next.t('figure.label.placement-center')}\n </option>\n </select>\n ${this.helpHint('figure.text.placement-explained')}\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.category')}${this.helpButton('figure.text.category-explained')}</label>\n <input\n .value=${this.figureCategory ?? ''}\n placeholder=${i18next.t('figure.text.category-placeholder')}\n @change=${(e: Event) => this.tellCatalog({ category: (e.target as HTMLInputElement).value.trim() || undefined })}\n />\n ${this.helpHint('figure.text.category-explained')}\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.tags')}${this.helpButton('figure.text.tags-explained')}</label>\n <input\n .value=${(this.figureTags ?? []).join(', ')}\n placeholder=${i18next.t('figure.text.tags-placeholder')}\n @change=${(e: Event) => this.tellTags((e.target as HTMLInputElement).value)}\n />\n ${this.helpHint('figure.text.tags-explained')}\n </div>\n `\n\n if (compact) {\n return html`\n <section>\n <details asset>\n <summary>\n <b>${i18next.t('figure.label.figure')}</b>\n <small>${this.figureName || this.board?.figureType || ''}</small>\n </summary>\n ${fields}\n </details>\n </section>\n `\n }\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.figure')}</h3>\n ${fields}\n </section>\n `\n }\n\n /**\n * ํ๊ทธ ์ค์ ๋ชฉ๋ก์ผ๋ก.\n *\n * ์ผํ๋ก ๊ฐ๋ฅด๊ณ `#` ์ ๋ผ์ด ๋ธ๋ค โ ์ฌ๋์ `#๋ฐ์ถ` ์ด๋ผ๊ณ ์ ๊ณ , ์ ์ฅ๋๋ ๊ฒ์ `๋ฐ์ถ` ์ด๋ค.\n * ๊ฒน์น ๊ฒ์ ํ ๋ฒ๋ง ๋จ๊ธด๋ค. ๋น ์ค์ **๋น ๋ฐฐ์ด**์ด์ง `undefined` ๊ฐ ์๋๋ค โ ์ ๋ถ ์ง์ฐ๋ ค๋\n * ์ ์์๊ฐ ์ง์ธ ๋ฐฉ๋ฒ์ ์์ง ์๊ฒ.\n */\n private tellTags(raw: string) {\n const tags = [\n ...new Set(\n raw\n .split(',')\n .map(one => one.trim().replace(/^#+/, '').trim())\n .filter(one => one.length > 0)\n )\n ]\n\n this.tellCatalog({ tags })\n }\n\n /** ์นดํ๋ก๊ทธ ๊ฐ์ด ๋ฐ๋์๋ค๊ณ ์๋ฆฐ๋ค. ์ ๋ณธ์ ์ ์๋ฉด์ด ๋ ๋ค โ ์ฌ๊ธฐ์๋ ์๋ฆฌ๊ธฐ๋ง ํ๋ค. */\n private tellCatalog(patch: { category?: string; tags?: string[] }) {\n this.dispatchEvent(new CustomEvent('figure-catalog', { detail: patch, bubbles: true, composed: true }))\n }\n\n /** 3D ๋ฐฐ์น ๊ธฐ์ค๋ฉด์ ๋ฐ๊พผ๋ค ('floor' | 'ceiling' | 'center'). */\n private setPlacement(placement: FigurePlacement) {\n if (!this.board) return\n const board = { ...this.board, placement }\n this.dispatchEvent(new CustomEvent('update-board', { detail: { board }, bubbles: true, composed: true }))\n }\n\n private renderIdentity(part: FigurePart) {\n return html`\n <section>\n <h3>${i18next.t('figure.label.part')}</h3>\n <div inline-field>\n <label>${i18next.t('figure.label.name')}${this.helpButton('figure.text.renaming-a-part-breaks-bindings')}</label>\n <input\n .value=${part.name}\n @change=${(e: Event) => this.put({ name: (e.target as HTMLInputElement).value })}\n />\n ${this.helpHint('figure.text.renaming-a-part-breaks-bindings')}\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.shape')}</label>\n <select @change=${(e: Event) => this.changePrimitive((e.target as HTMLSelectElement).value as PrimitiveKind)}>\n ${PRIMITIVE_KINDS.map(\n kind => html`\n <option value=${kind} ?selected=${kind === part.primitive}>\n ${i18next.t('figure.label.primitive-' + kind)}\n </option>\n `\n )}\n </select>\n </div>\n </section>\n `\n }\n\n private renderPlacement(part: FigurePart) {\n const t = part.transform\n const rotation = t.rotation ?? {}\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.placement')}</h3>\n\n <div vector-row>\n <label>${i18next.t('figure.label.part-position')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), t.position[axis], value =>\n this.putTransform({ position: { ...t.position, [axis]: value } })\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.part-size')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(\n axis.toUpperCase(),\n t.size[axis],\n value => this.putTransform({ size: { ...t.size, [axis]: value } }),\n 1\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.rotation-degrees')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), rotation[axis] ?? 0, value =>\n this.putTransform({ rotation: { ...rotation, [axis]: value } })\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.tools')}${this.helpButton('figure.text.tools-explained')}</label>\n <div tools>\n <button\n aria-label=${i18next.t('figure.button.center-x')}\n title=${i18next.t('figure.text.center-on-x')}\n @click=${() => this.ask('center', 'x')}\n >\n <md-icon>horizontal_distribute</md-icon>\n </button>\n <button\n aria-label=${i18next.t('figure.button.center-z')}\n title=${i18next.t('figure.text.center-on-z')}\n @click=${() => this.ask('center', 'z')}\n >\n <md-icon>vertical_align_center</md-icon>\n </button>\n <button\n aria-label=${i18next.t('figure.button.to-floor')}\n title=${i18next.t('figure.text.put-on-floor')}\n @click=${() => this.ask('floor', 'y')}\n >\n <md-icon>vertical_align_bottom</md-icon>\n </button>\n ${(['x', 'z'] as const).map(axis => {\n // ์ด๋ฏธ ๊ฐ์ด๋ฐ๋ฉด ๋์นญ์ด ์ ์๋ฆฌ๋ค โ ๊ฒน์น ๋ถํ์ด ์กฐ์ฉํ ์๊ธฐ์ง ์๊ฒ ๋ง๋๋ค\n const able = this.board ? canMirror(this.board, this.parts, this.selected, axis) : false\n return html`\n <button\n ?disabled=${!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.ask('mirror', axis)}\n >\n <md-icon>${axis === 'x' ? 'flip' : 'flip_camera_android'}</md-icon>\n </button>\n `\n })}\n <button\n aria-label=${i18next.t('figure.button.snap')}\n title=${i18next.t('figure.text.snap-explained')}\n @click=${() => this.ask('snap', 'x')}\n >\n <md-icon>grid_on</md-icon>\n </button>\n </div>\n ${this.helpHint('figure.text.tools-explained')}\n </div>\n </section>\n `\n }\n\n /** ๋ถํ ์์ ๋ชจ์๋ฆฌ ๊ตด๋ฆผ โ ํด๋นํ๋ ๋ํ์๋ง ๋ธ๋ค. */\n private renderShape(part: FigurePart) {\n const segmented = SEGMENTED_PRIMITIVES.includes(part.primitive)\n const extruded = EXTRUDE_PRIMITIVES.includes(part.primitive)\n if (!segmented && !extruded) return nothing\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.shape-detail')}</h3>\n ${segmented ? this.renderSegments(part) : nothing}\n ${segmented ? this.renderKeepRound(part) : nothing}\n ${extruded ? this.renderExtruded(part) : nothing}\n </section>\n `\n }\n\n /**\n * ๋ฏผ ๋จ๋ฉด โ ๋ชจ์๋ฆฌ์ **์์ ํ๋ ๋๊ป.**\n *\n * ๋ฒฝ ๋๊ป๋ฅผ 0 ์ผ๋ก ๋๋ฉด ํต์ง๋ค. 0 ๋ณด๋ค ํฌ๋ฉด ๊ทธ๋งํผ ์์ผ๋ก ๋ค์ด์จ ํ
๊ฐ ์๊ธฐ๊ณ , ๊ทธ๊ฒ์ด\n * ํธ๋ ์ด ยท ํ ํธ ยท ํต ยท ์ผ์ด์ค๊ฐ ๋๋ ์๋ฆฌ๋ค. ๋ฐ๋ฅ์ ๋น์ ๋๋ฉด ๋ฒฝ๊ณผ ๊ฐ๊ณ , 0 ์ผ๋ก ๋๋ฉด\n * ์์๋๊ฐ ๋ค ๋ซ๋ฆฐ ํ
๋๋ฆฌ๊ฐ ๋๋ค.\n */\n private renderExtruded(part: FigurePart) {\n const hollow = part.shape?.hollow\n const wall = hollow?.wall ?? 0\n\n const reshape = (over: Record<string, unknown>) =>\n this.put({ shape: { ...(part.shape ?? {}), ...over } })\n\n return html`\n <div inline-field>\n <label>${i18next.t('figure.label.corner-round')}</label>\n ${this.number('', part.shape?.round ?? 0, value => reshape({ round: value }))}\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.hollow-wall')}</label>\n ${this.number('', wall, value =>\n reshape({ hollow: value > 0 ? { ...(hollow ?? {}), wall: value } : undefined })\n )}\n </div>\n ${wall > 0\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.hollow-floor')}</label>\n ${this.number('', hollow?.floor ?? wall, value => reshape({ hollow: { ...hollow, wall, floor: value } }))}\n </div>\n `\n : nothing}\n `\n }\n\n /**\n * ๋ถํ ์ โ ๋ชจ์๊ณผ ๋ฌด๊ฒ๋ฅผ ํจ๊ป ๊ณ ๋ฅธ๋ค.\n *\n * ์ผ๊ฐํ ์๋ ํ๋ฉด์ด ์
ํ์ง ์๋๋ค. `trianglesOf` ์ ๊ทธ ๋ถํ ์๋ฅผ ๊ฐ์ง ๋ถํ์ ์ฃผ๊ณ \n * ๋ฌผ์ด๋ณธ๋ค โ ํ๋ฉด์ด ์ ๋๋ฆ์ ๊ณต์์ ๋ค๋ฉด figure-model ์ด ๊ท์น์ ๋ฐ๊ฟ๋ ํ๋ฉด๋ง\n * ์ ๋ต์ ๊ณ์ ๋ธ๋ค.\n */\n /**\n * ์ํต์ ์ํต์ผ๋ก ๋๊น โ **๊ณ ๋ฅด๋ ๊ฐ์ด๊ณ , ๊ฐ์ ์น๋ฅธ๋ค.**\n *\n * ์ธ์คํด์ค๊ฐ ์ถ๋ง๋ค ๋ค๋ฅธ ๋ฐฐ์จ์ ๋ฐ์ผ๋ฉด ์๊ธฐ๋ฅ์ด ํ์ ๊ธฐ๋ฅ์ด ๋๋ค. ์งํค๋ ค๋ฉด ์ ๋ณํ์ด\n * ์์ด์ผ ํ๊ณ , ํฉ์น ํ์์ ๋ณํ์ ํ๋๋ง ๋ฐ์ผ๋ฏ๋ก ์งํค๋ ๊ณก๋ฉด ๋ถํ ํ๋๊ฐ draw call\n * ํ๋๋ค. ์ ์์๊ฐ ๊ทธ ๋๊ฐ๋ฅผ ๋ชจ๋ฅด๊ณ ๊ณ ๋ฅด๋ฉด ์ ๋๋ฏ๋ก ๊ทธ ์๋ฆฌ์ ์ ๋๋ค.\n */\n private renderKeepRound(part: FigurePart) {\n const on = part.keepRound !== false\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.keep-round')}</label>\n <div choices>\n <button choice ?on=${on} @click=${() => this.put({ keepRound: undefined })}>\n <b>${i18next.t('figure.text.keep-round-on')}</b>\n <small>${i18next.t('figure.text.keep-round-cost')}</small>\n </button>\n <button choice ?on=${!on} @click=${() => this.put({ keepRound: false })}>\n <b>${i18next.t('figure.text.keep-round-off')}</b>\n <small>${i18next.t('figure.text.keep-round-merged')}</small>\n </button>\n </div>\n </div>\n `\n }\n\n private renderSegments(part: FigurePart) {\n const current = part.segments ?? SEGMENT_PRESETS[1]\n const common = SEGMENT_PRESETS.slice(0, 4)\n const advanced = SEGMENT_PRESETS.slice(4)\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.segments')}</label>\n <div segments>\n ${common.map(preset => {\n const triangles = trianglesOf({ ...part, segments: preset })\n return html`\n <button seg ?on=${current === preset} @click=${() => this.put({ segments: preset })}>\n ${this.silhouette(preset)}\n <b>${preset}</b>\n <small>${i18next.t('figure.text.n-triangles', { count: triangles })}</small>\n </button>\n `\n })}\n </div>\n\n <details free ?open=${advanced.includes(current)}>\n <summary>${i18next.t('figure.text.more-segment-options')}</summary>\n <div presets>\n ${advanced.map(preset => html`\n <button ?on=${current === preset} @click=${() => this.put({ segments: preset })}>${preset}</button>\n `)}\n </div>\n </details>\n </div>\n `\n }\n\n /**\n * ๋ถํ ์์ ์ค๋ฃจ์ฃ.\n *\n * ๊ณก๋ฉด ํ๋ฆฌ๋ฏธํฐ๋ธ๋ฅผ ์์์ ๋ณธ ์ค๊ณฝ์ด ์ ํํ ์ n๊ฐํ์ด๋ค โ ์๊ธฐ๋ฅ์ ๋จ๋ฉด๋, ๊ตฌ์\n * ์ ๋๋. ๊ทธ๋ฆผ์ ์ง์ด๋ด๋ ๊ฒ์ด ์๋๋ผ ์ค์ ๋ก ๋ง๋ค์ด์ง๋ ๋ชจ์์ด๋ค.\n */\n private silhouette(segments: number) {\n const points: string[] = []\n for (let i = 0; i < segments; i++) {\n // ๊ผญ์ง์ ํ๋๊ฐ ์๋ก ์ค๊ฒ -90๋์์ ์์ํ๋ค\n const angle = -Math.PI / 2 + (i * 2 * Math.PI) / segments\n points.push(`${(16 + 13 * Math.cos(angle)).toFixed(2)},${(16 + 13 * Math.sin(angle)).toFixed(2)}`)\n }\n\n return svg`\n <svg viewBox=\"0 0 32 32\" aria-hidden=\"true\">\n <polygon points=${points.join(' ')}></polygon>\n </svg>\n `\n }\n\n /** ๊ฒฌ๋ณธ ํ ์ค. ๋ฌด๋ฆฌ๋ง๋ค ๋ถ๋ฅธ๋ค. */\n private palettePurpose(token?: string) {\n const purposes: Record<string, string> = {\n 'palette.primary': 'primary',\n 'palette.accent': 'accent',\n 'palette.neutral': 'neutral',\n 'palette.dark': 'dark',\n 'palette.light': 'light',\n 'palette.surface': 'surface',\n 'palette.status-danger': 'danger',\n 'palette.status-warning': 'warning',\n 'palette.status-info': 'info',\n 'palette.status-success': 'success'\n }\n\n return i18next.t(`figure.label.palette-purpose-${purposes[token ?? ''] ?? 'registered'}`)\n }\n\n private swatches(entries: [string, string][], chosen?: string) {\n return entries.map(\n ([token, color]) => {\n const purpose = this.palettePurpose(token)\n return html`\n <button\n swatch\n ?on=${token === chosen}\n aria-label=${purpose}\n title=${purpose}\n style=\"--swatch:${color}\"\n @click=${() => this.putMaterial({ token })}\n ></button>\n `\n }\n )\n }\n\n private renderMaterial(part: FigurePart) {\n const material = part.material ?? {}\n const palette = activePalette() as Record<string, string>\n\n /*\n ๋ ๋ฌด๋ฆฌ๋ก ๋๋ ๋ณด์ธ๋ค โ **์น ํ ์**๊ณผ **์ผ์ง ์**.\n\n `palette.status-*` ๋ ๋จํ ยท ํ์๋ฑ์ ์ฐ๋ผ๊ณ ์๋ ์์ด๋ค. ํ ์ค์ ์์ด ๋๋ฉด\n `accent`(์ฃผํฉ)์ `status-warning`(์ฃผํฉ)์ด ๋๋ํ ๋์ฌ ๋ฌด์์ด ๋ฌด์์ธ์ง ์ ์\n ์๋ค. ๊ฐ์ ๋นํ์ด ๋ฒ๋ฆฌ๋ ๋์ **๊ณ ๋ฅด๋ ์๋ฆฌ์์ ๊ฒฝ๊ณ๋ฅผ ๊ธ๋๋ค.**\n */\n const entries = Object.entries(palette)\n const painted = entries.filter(([token]) => !token.startsWith('palette.status-'))\n const lit = entries.filter(([token]) => token.startsWith('palette.status-'))\n\n /** ์์ฒด๋ฐ๊ด. ์์ผ๋ฉด ์ ๋น๋๋ ๋ถํ์ด๋ค. */\n const glow = material.emissive\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.part-material')}</h3>\n\n <div field>\n <label>${i18next.t('figure.label.palette-role')}</label>\n <div swatches>\n ${this.swatches(painted, material.token)}\n </div>\n ${lit.length\n ? html`\n <label group>${i18next.t('figure.label.status-colors')}</label>\n <div swatches>\n ${this.swatches(lit, material.token)}\n </div>\n `\n : ''}\n <div palette-meaning>\n <b>${material.token ? this.palettePurpose(material.token) : i18next.t('figure.label.no-color-chosen')}</b>\n <small>${i18next.t('figure.text.palette-purpose-explained')}</small>\n </div>\n </div>\n\n <div field>\n <label>${i18next.t('figure.label.preset')}</label>\n <select\n @change=${(e: Event) => {\n const value = (e.target as HTMLSelectElement).value\n this.putMaterial({ preset: (value || undefined) as MaterialPreset | undefined })\n }}\n >\n <option value=\"\" ?selected=${!material.preset}>${i18next.t('figure.label.none')}</option>\n ${MATERIAL_PRESETS.map(\n preset => html`\n <option value=${preset} ?selected=${preset === material.preset}>\n ${i18next.t('figure.label.preset-' + preset)}\n </option>\n `\n )}\n </select>\n </div>\n\n <!-- ๊ฐ์ด ์์ผ๋ฉด ๊ฐ์ง๊ฒ ๊ทธ๋ฆฐ๋ค โ ํ์์ด ๊ทธ๋ ๊ฒ ๋ชป ๋ฐ์๋ค. ์ฒดํฌ์์๋ ๊ทธ๋๋ก ๋ณด์ธ๋ค -->\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${material.flatShading ?? true}\n @change=${(e: Event) => this.putMaterial({ flatShading: (e.target as HTMLInputElement).checked })}\n />\n ${i18next.t('figure.label.flat-shading')}\n </label>\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${!!material.transparent}\n @change=${(e: Event) => this.putMaterial({ transparent: (e.target as HTMLInputElement).checked })}\n />\n ${i18next.t('figure.label.transparent')}\n </label>\n\n <div field>\n <label>${i18next.t('figure.label.emissive')}${this.help('figure.text.emissive-explained')}</label>\n\n <div slider>\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n .value=${String(glow?.intensity ?? 0)}\n @input=${(e: Event) => this.putEmissive(Number((e.target as HTMLInputElement).value))}\n />\n <output>${(glow?.intensity ?? 0).toFixed(2)}</output>\n </div>\n </div>\n\n ${glow\n ? html`\n <div field>\n <label>${i18next.t('figure.label.emissive-color')}</label>\n <div swatches>\n <button\n swatch\n same\n ?on=${!glow.token}\n title=${i18next.t('figure.label.same-as-off')}\n style=\"--swatch:${(material.token && palette[material.token]) || palette['palette.neutral']}\"\n @click=${() => this.putMaterial({ emissive: { ...glow, token: undefined } })}\n ></button>\n ${lit.map(\n ([token, color]) => html`\n <button\n swatch\n ?on=${token === glow.token}\n title=${token}\n style=\"--swatch:${color}\"\n @click=${() => this.putMaterial({ emissive: { ...glow, token } })}\n ></button>\n `\n )}\n </div>\n <span token>${glow.token ?? i18next.t('figure.label.same-as-off')}</span>\n </div>\n\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${!!glow.on}\n @change=${(e: Event) =>\n this.putMaterial({ emissive: { ...glow, on: (e.target as HTMLInputElement).checked } })}\n />\n ${i18next.t('figure.label.on-by-default')}\n </label>\n ${this.help('figure.text.on-by-default-explained')}\n `\n : ''}\n\n </section>\n `\n }\n\n /**\n * ์ธ์คํด์ค ํฌ๊ธฐ๊ฐ ๋ฐ๋ ๋ ์ด ๋ถํ์ด ์ด๋ป๊ฒ ๋ณํ๋.\n *\n * ## ๋์ด๋๋ ์ถ์ ์์ง ๋ชป ๋ณด์ฌ ์ค๋ค\n *\n * `stretch` ๋ ํ์์ ์ถ์ ์ ๋ ์๋ฆฌ๊ฐ ์์ด์ ๊ทธ๋ฆฌ๋ ์ชฝ์ด **๊ฐ์ฅ ๊ธธ๊ฒ ๋ป์ ์ถ**์ผ๋ก\n * ์ ํ๋ค. ๊ทธ ๋ต์ ํ๋ฉด์ ์ ์ด ์ฃผ๋ ค๋ฉด ๊ท์น์ ๊ฐ์ง ์ชฝ์ ๋ฌผ์ด์ผ ํ๋๋ฐ, ๊ทธ ํจ์\n * (`stretchAxisOf` ยท `stretchAxis`)๊ฐ ์์ง ๋ฐฐํฌ๋ ํ์ ์๋ค.\n *\n * ํ๋ฉด์ด ์ ๋๋ฆ๋๋ก ๊ณ์ฐํ์ง ์๋๋ค. ๊ท์น์ด ๋ ๋ฒ์ด ๋๋ฉด ๋ณด์ด๋ ์ถ๊ณผ ์ค์ ๋ก ๋์ด๋๋\n * ์ถ์ด ๊ฐ๋ฆฌ๊ณ , ๊ทธ ์ด๊ธ๋จ์ ํ๋ฉด์ ๋ฏฟ๊ฒ ๋ง๋ ๋ค์์ ๋๋ฌ๋๋ค. ๋ฐฐํฌ๋๋ฉด ์๋๋ค.\n *\n * ## ๊ฐ์ด ์๋ ๊ฒ์ ๋ฐํ๋ค\n *\n * `scale` ์ด ์๋ ๋ถํ์ ํฉ์ณ ๊ทธ๋ฆด ์ ์์ด draw call ์ ํ๋ ๋ ์ด๋ค. ๊ทธ ๋น์ฉ์ด\n * ์ฑ์๋์ ๋ฌถ์ ์์ ๊ทธ๋๋ก ์กํ๋ค. ๊ณ ๋ฅด๋ ์๋ฆฌ์์ ๋ฏธ๋ฆฌ ๋งํด ์ค๋ค.\n */\n private renderBehaviour(part: FigurePart) {\n const sizing = part.sizing ?? 'scale'\n const repeat = part.repeat ?? { axis: 'x' as Axis, pitch: 0 }\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.sizing-rule')}${this.help('figure.text.sizing-' + sizing + '-explained')}</h3>\n <div sizing-choices>\n ${SIZING_RULES.map(\n rule => html`\n <button sizing-choice ?on=${rule === sizing} @click=${() => this.put({ sizing: rule })}>\n <b>${i18next.t('figure.label.sizing-' + rule)}</b>\n <small>${i18next.t('figure.text.sizing-' + rule + '-explained')}</small>\n </button>\n `\n )}\n </div>\n ${sizing === 'scale'\n ? nothing\n : html`<p cost>${i18next.t('figure.text.sizing-costs-one-draw-call')}</p>`}\n\n ${this.renderAnchors(part)}\n\n ${sizing === 'repeat'\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.repeat-axis')}</label>\n <select\n @change=${(e: Event) =>\n this.put({ repeat: { ...repeat, axis: (e.target as HTMLSelectElement).value as Axis } })}\n >\n ${(['x', 'y', 'z'] as const).map(\n axis => html`<option value=${axis} ?selected=${axis === repeat.axis}>${axis}</option>`\n )}\n </select>\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.repeat-pitch')}${this.helpButton('figure.text.repeat-pitch-explained')}</label>\n ${this.number('', repeat.pitch, value => this.put({ repeat: { ...repeat, pitch: value } }), 1)}\n ${this.helpHint('figure.text.repeat-pitch-explained')}\n </div>\n ${this.renderRepeatCount(part)}\n `\n : nothing}\n </section>\n `\n }\n\n /**\n * โโ ๋ช ๊ฐ๊ฐ ๋๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ์ ์ ํ๋ฉด์ ์ถ๊ณผ ํผ์น๋ง ๋ฐ๊ณ ์์๋ค. ํ์์ด ๊ฐ์ง ๋ฐ๋ณต ์ค์ ์ด ๊ทธ ๋๋ฟ์ด๋ฏ๋ก ํธ์งํ ๊ฒ์\n * ๋ค ์์๋๋ฐ, **๊ฒฐ๊ณผ์ธ ๊ฐ์๋ฅผ ์ด๋์๋ ํ์ํ์ง ์์๋ค.** ํผ์น 300 ์ ์ ์ ์ ์์๊ฐ ๋ช ๊ฐ๊ฐ\n * ๋๋์ง ์๋ ค๋ฉด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์ธ์ด์ผ ํ๋ค.\n *\n * ๊ฐ์๋ ๊ทธ๋ฆฌ๋ ์ชฝ์ด ์ฐ๋ `repeatPlan` ์ ๊ทธ๋๋ก ๋ถ๋ฌ ์ป๋๋ค. ์ฌ๊ธฐ์ ๋ค์ ๊ณ์ฐํ๋ฉด ํ๋ฉด์ด\n * ๋งํ๋ ๊ฐ์์ ์ค์ ๋ก ๊ทธ๋ ค์ง๋ ๊ฐ์๊ฐ ๋ฌ๋ผ์ง๋ค.\n *\n * ## ๋ ๊ฐ์ง ๋ฐ๋ณต์ด ์๋ค\n *\n * ์ปจ๋ฒ ์ด์ด์ ๋กค๋ฌ๋ ๊ธธ์ด์ง๋ฉด **๊ฐ์๊ฐ ๋๊ณ ** ํ ์นธ ๊ฐ๊ฒฉ์ ๊ทธ๋๋ก๋ค. ์
ํธ๋ ์ด์ ์
์ ์ปค์ง๋ฉด\n * **์
์ด ์ปค์ง๊ณ ** ๊ฐ์๋ ๊ทธ๋๋ก๋ค โ ๋ช ์
์ง๋ฆฌ ํธ๋ ์ด๋๋ ํ๋ฉด ํฌ๊ธฐ์ ๋ฌด๊ดํ๋ค. ๊ทธ ๊ฐ๋ฆผ์\n * ์ด ์ถ์ anchor ๊ฐ ์ ํ๋๋ฐ ํ๋ฉด์๋ ๊ทธ ๋ง์ด ์์๋ค. ๊ทธ๋์ ์ด๋ ์ชฝ์ธ์ง ํจ๊ป ์ ๋๋ค.\n */\n private renderRepeatCount(part: FigurePart) {\n const board = this.board\n if (!board) return nothing\n\n const base = { x: board.width, y: board.depth, z: board.height }\n const plan = repeatPlanOfPart(part, { x: 1, y: 1, z: 1 }, base)\n if (!plan) return nothing\n\n const grows = anchorOfPart(part, base, plan.axis) !== 'scale'\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.repeat-count')}</label>\n <p quiet>\n ${i18next.t('figure.text.repeat-count-now', { count: plan.count })}\n ${plan.count >= REPEAT_LIMIT\n ? html`<br />${i18next.t('figure.text.repeat-count-capped', { limit: REPEAT_LIMIT })}`\n : ''}\n <br />${i18next.t(grows ? 'figure.text.repeat-grows-with-instance' : 'figure.text.repeat-keeps-count')}\n </p>\n </div>\n `\n }\n\n /**\n * โโ ์ด๋ ๋ฉด์ ๋ถ์ก๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * **์ด ์๋ฆฌ๊ฐ ์์๋ค.** ํ์์ ์ถ๋ง๋ค `anchor` ๋ฅผ ์ง๊ณ ๋ค๋๊ณ (`figure-source.ts` ๊ฐ ์๋ณต์ํจ๋ค),\n * ๋ฐํ ๊ฒ์ดํธ๋ ใvalve-wheel ์ anchor.z ๋ฅผ max ๋ก ๋๋ผใ๊ณ ์ฌ์ ๊น์ง ๋งํ๋๋ฐ, ์ ์๋ฉด์๋ ๊ทธ\n * ๊ฐ์ ๋ฐ๊ฟ ์๋ฆฌ๊ฐ ์์๋ค โ ๊ณ ์น๋ผ๋ ๋ง๋ง ์๊ณ ๊ณ ์น ๋ฌธ์ด ์์๋ค.\n *\n * ## ใ์๋ใ์ด ๊ธฐ๋ณธ์ด๋ค\n *\n * ํ์์์ `anchor` ๋ ์ ์ง ์์๋ ๋๋ค. ์ ์ ์ผ๋ฉด **๊ฐ๊น์ด ๋ฉด**์ ๋ถ์ก๊ณ , ํ๋ณธ ์ด๋ท ์ค ์ด๋\n * ๊ฒ๋ ์ด ๊ฐ์ ์ ์ง ์๊ณ ์ ๋๋ก ์ ๋ค. ๊ทธ๋์ ์ถ๋ง๋ค ์ฒซ ํญ๋ชฉ์ด ใ์๋ใ์ด๊ณ , ์ง๊ธ ์๋์ด ๋ฌด์์ผ๋ก\n * ์ฝํ๋์ง๋ฅผ **ํจ๊ป ๋ณด์ฌ ์ค๋ค** โ ๊ทธ๊ฒ์ ๋ชจ๋ฅด๋ฉด ๋ฌด์์ ๋ฐ๊พธ๋์ง ๋ชจ๋ฅธ ์ฑ ๊ณ ๋ฅด๊ฒ ๋๋ค.\n *\n * ์๋์ด ๋ฌด์์ธ์ง๋ ํ์์๊ฒ ๋ฌป๋๋ค(`anchorOfPart`). ์ฌ๊ธฐ์ ใ์ ์ ๋ฐ์ด๋ฉด maxใ๋ฅผ ๋ค์ ์ธ๋ฉด\n * ํ๋ฉด์ด ๋งํ๋ ๋ฉด๊ณผ ์ค์ ๋ก ๊ทธ๋ ค์ง๋ ๋ฉด์ด ๊ฐ๋ฆฐ๋ค.\n *\n * ## `scale` ์ธ ๋ถํ์๋ ๋ณด์ฌ ์ค๋ค\n *\n * ์ฒ์์๋ ๊ฐ์ท๋ค โ ํ์ ์ฃผ์์ ใ`sizing` ์ด `scale` ์ธ ๋ถํ์๋ ๋ป์ด ์๋คใ๊ณ ์ ํ ์์ด์๋ค.\n * **๊ทธ ๋ฌธ์ฅ์ ๊ธฐ๋ณธ๊ฐ์ ๋ํ ๊ฒ์ด๋ค.** `anchorOf` ๋ ์ ํ ๊ฐ์ ๊ฐ์ฅ ๋จผ์ ๋ณด๊ณ (`if (said) return\n * said`), ๊ทธ ๋ค์์ผ `sizing` ์ ๋ณธ๋ค. ์ฆ `scale` ๋ถํ์๋ ๋ฉด์ ์ ์ผ๋ฉด ๊ทธ๊ฒ์ด ์ด๊ธด๋ค.\n *\n * ๊ฐ์ถฐ ๋๋ฉด ์ด๊ธ๋จ์ด ๋๋ค: ๋ฐํ ๊ฒ์ดํธ๊ฐ ๋ง๋ MIXER ์ `valve-wheel` ์ด `scale` ๋ถํ์ด๊ณ ,\n * ๊ฒ์ดํธ์ ์ฌ์ ๋ ใ๊ทธ ๋ถํ์ anchor.z ๋ฅผ max ๋ก ๋๋ผใ๋ค. ๊ณ ์น๋ผ๋ ์๋ฆฌ์ ๋ฌธ์ ๋ซ์ ๋ ์
์ด์๋ค.\n *\n * ๋์ `scale` ์ผ ๋๋ ์๋์ด ๋ฌด์์ธ์ง๊ฐ ใํจ๊ป ์ปค์ง๋คใ๋ก ๋ณด์ด๋ฏ๋ก, ์ ์์๊ฐ ๊ทธ๊ฒ์ ๋ฐ๊พธ๋\n * ๊ฒ์์ ์ ์ ์๋ค.\n */\n /**\n * โโ ๋์๋ง์ ์๋ฆฌ๋ฅผ ๋จน์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ์ค๋ช
๋ฌธ๋จ์ด ์ด ์ค ์์๊ณ ๊ทธ ์ค๋ค์ด ํจ๋ ๋์ด์ ์๋น ๋ถ๋ถ์ด์๋ค. ์์ฑ์ ์์ผ๋ก ๋ ๋์ด๋๋ค\n * (๋ฅ๋ ฅ ยท ํฌํธ ยท ์ ๋๋ฉ์ด์
ยท ๊ธฐ์ค์ ๋ณด) โ ๋ ๋ณด์ด๋ ์ค๋ช
์ ๊ทธ ์๋ฆฌ๋ฅผ ๋จผ์ ๋จน๋๋ค.\n *\n * ๊ทธ๋์ ๋ฌผ์ํ๋ก ์ ๋๋ค. **์ง์ฐ์ง ์๋๋ค** โ ๊ทธ ๋ฌธ์ฅ๋ค์ ใ์ด๊ฑธ ๊ณ ๋ฅด๋ฉด ๋ฌด์์ด ๋ฌ๋ผ์ง๋ใ๋ฅผ\n * ๋งํ๋ ๊ฒ์ด๊ณ , ์์ผ๋ฉด ๋ซํ ๋ชฉ๋ก์ ๊ณ ๋ฅผ ์ ์๋ค. ํ ๋ฒ ์ฝ์ผ๋ฉด ๋๋ ๊ฒ์ด๋ผ ์ ์ด ๋๋ ๊ฒ์ด ๋ง๋ค.\n *\n * ํธ ๊ฒ์ **๋ถํ์ ๋ฐ๊ฟ๋ ๊ทธ๋๋ก ๋๋ค**(`opened` ๋ ๋ถํ์ ๋ธ๋ฆฐ ์ํ๊ฐ ์๋๋ค). ๊ฐ์ ๊ฒ์\n * ๊ณ์ ๊ณ ์น๋ ์ฌ๋์ด ๋งค๋ฒ ๋ค์ ํด์ผ ํ๋ฉด ์ ์ ๊ฒ์ด ๋๋ ๋ฐฉํด๊ฐ ๋๋ค.\n */\n private help(key: string) {\n return html`${this.helpButton(key)}${this.helpHint(key)}`\n }\n\n private helpButton(key: string) {\n const shown = this.opened.has(key)\n\n return html`\n <button\n help\n aria-label=${i18next.t('figure.label.help')}\n aria-expanded=${shown ? 'true' : 'false'}\n @click=${() => {\n shown ? this.opened.delete(key) : this.opened.add(key)\n this.requestUpdate()\n }}\n >\n <md-icon>${shown ? 'help' : 'help_outline'}</md-icon>\n </button>\n `\n }\n\n private helpHint(key: string) {\n return this.opened.has(key) ? html`<p hint>${i18next.t(key)}</p>` : nothing\n }\n\n private renderAnchors(part: FigurePart) {\n const base = this.board\n ? { x: this.board.width, y: this.board.height, z: this.board.depth }\n : { x: 0, y: 0, z: 0 }\n const nameOf = (rule: string, axis: Axis) =>\n `${i18next.t(rule === 'min' || rule === 'max' ? `figure.label.anchor-${rule}-${axis}` : `figure.label.anchor-${rule}`)} (${rule})`\n const setAnchor = (axis: Axis, rule?: AnchorRule) => {\n const anchor = { ...(part.anchor ?? {}) }\n /* ใ์๋ใ์ ์นธ์ ์ง์ฐ๋ ๊ฒ์ด๋ค โ ๋น ๊ฐ์ ๋ฃ์ด ๋๋ฉด ํ์์ด ๊ทธ๊ฒ์ ๊ฐ์ผ๋ก ์ฝ๋๋ค. */\n if (rule) anchor[axis] = rule\n else delete anchor[axis]\n this.put({ anchor: Object.keys(anchor).length ? anchor : undefined })\n }\n const shortNameOf = (rule: AnchorRule | 'auto', axis: Axis) => {\n if (rule === 'auto') return i18next.t('figure.label.anchor-choice-auto')\n if (rule === 'min' || rule === 'max') return i18next.t(`figure.label.anchor-choice-${rule}-${axis}`)\n return i18next.t(`figure.label.anchor-choice-${rule}`)\n }\n\n return html`\n <div field>\n <!-- ์ ์ฅ ํค(anchor)๋ ๋จ๊ธฐ๋, ์ฌ์ฉ์๋ ์ถ๋ง๋ค ์ด๋ ๋ฉด์ ๊ธฐ์ค์ผ๋ก ์ผ๋์ง ์ฝ๋๋ค. -->\n <label>${i18next.t('figure.label.anchor')} (anchor)${this.help('figure.text.anchor-explained')}</label>\n <div anchor-rows>\n ${(['x', 'y', 'z'] as const).map(axis => {\n const said = part.anchor?.[axis]\n const auto = anchorOfPart(part, base, axis)\n\n /*\n **๋ฉด ์ด๋ฆ์ ์ถ๋ง๋ค ๋ค๋ฅด๋ค.** ์ฒ์์๋ min ์ ใ์๋ยท์ผ์ชฝยท๋ค ๋ฉดใ์ผ๋ก ํ ์ค์ ๋ค ์ ์๋๋ฐ,\n x ์ค์์ ใ์๋ใ์ ใ๋คใ๋ ๊ด๊ณ๊ฐ ์์ด ์ฝ๋ ์ฌ๋์ด ๋ฌด์์ ๊ณ ๋ฅด๋์ง ๋ชฐ๋๋ค.\n\n ๊ทธ๋ฆฌ๊ณ ์ด๋ฆ์จ๊ฐ ์๋๋ผ **๋์**์ผ๋ก ์ ๋๋ค โ ใ์ค๋ฅธ์ชฝ ๋ฉดใ์ด ์๋๋ผ ใ์ค๋ฅธ์ชฝ ๋ฉด์ ๋ถ์ด\n ์๋๋คใ๋ค. ใanchor.x ๋ฅผ max ๋ก ๋๋คใ๊ฐ ๋ฌด์จ ๋ป์ธ์ง ๋ชจ๋ฅด๊ฒ ๋ค๋ ๋ง์ด ๊ทธ ์๋ฆฌ์์ ๋์๋ค.\n */\n /*\n **๊ฐ ์ด๋ฆ์ ํจ๊ป ๋ณด์ธ๋ค.** ๋์๋ง ์ ์๋๋(ใ์ค๋ฅธ์ชฝ ๋ฉด์ ๋ถ์ด ์๋๋คยป) ๋ฐํ ๊ฒ์ดํธ๊ฐ\n ใanchor.x ๋ฅผ max ๋ก ๋๋ผใ๊ณ ๋งํ ๋ ํ๋ฉด์์ ๊ทธ ๋ฑ๋ง์ ์ฐพ์ ์ ์์๋ค โ ์ฌ์ฉ์๊ฐ\n ๊ทธ ์๋ฆฌ์์ ์ง์ ํ๋ค.\n\n `max` ๋ ์ ๋ณธ์ ์ ์ฅ๋๋ ์ด๋ฆ์ด๊ณ ์๋ฒ ์ค๋ฅยทํ์ ๋ฌธ์ยท๊ฒ์ดํธ ์ฌ์ ๊ฐ ๋ค ๊ทธ ์ด๋ฆ์ ์ด๋ค.\n ์จ๊ธฐ๋ฉด ์ ๋๋ ์ข
๋ฅ๋ค. ๋์์ด ๋จผ์ ๊ณ ์ด๋ฆ์ด ๊ดํธ๋ก ๋ฐ๋ผ์จ๋ค.\n */\n return html`\n <div anchor-row>\n <label>${axis.toUpperCase()}์ถ</label>\n <div anchor-options>\n ${(['auto', 'scale', 'min', 'center', 'max', 'span'] as const).map(rule => {\n const selected = rule === 'auto' ? !said : rule === said\n const fullName = rule === 'auto' ? i18next.t('figure.label.anchor-auto', { rule: nameOf(auto, axis) }) : nameOf(rule, axis)\n return html`\n <button\n anchor-choice\n ?on=${selected}\n aria-pressed=${selected ? 'true' : 'false'}\n title=${fullName}\n @click=${() => setAnchor(axis, rule === 'auto' ? undefined : rule)}\n >${shortNameOf(rule, axis)}</button>\n `\n })}\n </div>\n <details anchor-advanced>\n <summary>${i18next.t('figure.label.anchor-advanced')}</summary>\n <div anchor-options>\n ${ANCHOR_RULES.filter(rule => rule.startsWith('aspect-')).map(rule => html`\n <button\n anchor-choice\n ?on=${rule === said}\n aria-pressed=${rule === said ? 'true' : 'false'}\n title=${nameOf(rule, axis)}\n @click=${() => setAnchor(axis, rule)}\n >${i18next.t(`figure.label.anchor-choice-${rule}`)}</button>\n `)}\n </div>\n </details>\n </div>\n `\n })}\n </div>\n </div>\n `\n }\n\n /**\n * ์ซ์ ์นธ.\n *\n * ๋น ์นธ์ด๋ ๊ธ์๋ฅผ ๋ฃ์์ ๋ 0 ์ผ๋ก ๋ฐ๊ฟ์น์ง ์๋๋ค โ ์ ์์๊ฐ ์ง์ฐ๋ ์ค์ผ ์ ์๊ณ ,\n * ์กฐ์ฉํ 0 ์ด ๋๋ฉด ๋ถํ์ด ์ฌ๋ผ์ง ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค. ์ซ์๊ฐ ์๋๋ฉด ๊ทธ๋ฅ ์ ๋ฐ๋๋ค.\n */\n private number(label: string, value: number, set: (value: number) => void, min?: number) {\n return html`\n <div cell>\n ${label ? html`<span axis>${label}</span>` : nothing}\n <input\n type=\"number\"\n .value=${String(value)}\n min=${min ?? nothing}\n @change=${(e: Event) => {\n const raw = (e.target as HTMLInputElement).value\n const parsed = Number(raw)\n if (raw === '' || !Number.isFinite(parsed)) {\n // ๋๋๋ ค ๋๋๋ค. ์ ๊ทธ๋ฌ๋ฉด ํ๋ฉด๊ณผ ์ ๋ณธ์ด ๊ฐ๋ฆฐ๋ค.\n ;(e.target as HTMLInputElement).value = String(value)\n return\n }\n set(parsed)\n }}\n />\n </div>\n `\n }\n\n /**\n * ๋ํ์ ๋ฐ๊พผ๋ค.\n *\n * ๋ํ์ด ๋ฐ๋๋ฉด ๊ทธ ๋ํ์ ๋ป ์๋ ๊ฐ์ด ๋จ๋๋ค. ๋จ๊ฒจ ๋๋ฉด ๊ฒ์ฆ์ด ใ๋ฌด์๋จใ ์๋ฐ์\n * ๋ด๋ฏ๋ก ์ฌ๊ธฐ์ ๊ฑท๋๋ค.\n */\n private changePrimitive(primitive: PrimitiveKind) {\n this.change(part => {\n const next: FigurePart = { ...part, primitive }\n if (!SEGMENTED_PRIMITIVES.includes(primitive)) delete next.segments\n if (!EXTRUDE_PRIMITIVES.includes(primitive)) delete next.shape\n if (SEGMENTED_PRIMITIVES.includes(primitive) && next.segments === undefined) {\n next.segments = SEGMENT_PRESETS[1]\n }\n return next\n })\n }\n\n private put(patch: Partial<FigurePart>) {\n this.change(part => ({ ...part, ...patch }))\n }\n\n private putTransform(patch: Record<string, unknown>) {\n this.change(part => ({ ...part, transform: { ...part.transform, ...patch } as FigurePart['transform'] }))\n }\n\n /**\n * ๋ฐ๊ด ์ธ๊ธฐ๋ฅผ ๊ณ ์น๋ค. **0 ์ด๋ฉด ๋ธ๋ก์ ํต์งธ๋ก ์ง์ด๋ค.**\n *\n * ์ธ๊ธฐ 0 ์ธ ๋ฐ๊ด์ ๋จ๊ฒจ ๋๋ฉด ใ์ ๋น๋๋๋ฐ ๋จํ์ธ ๊ฒใ์ด ๋์ด, ์ฌ์ง ํค๊ฐ ๊ฐ๋ ค ๋ฌถ์์ด\n * ํ๋์ด ํ๋ ๋๋ค. 0 ์ ใ๋จํ๊ฐ ์๋๋คใ๋ก ์ฝ๋ ๊ฒ์ด ๋ง๋ค.\n *\n * `Number(value) || undefined` ๋ฅผ ์ฐ๋ฉด ์ ๋๋ค โ 0 ์ด falsy ๋ผ ๋ณ๊ฒฝ์ผ๋ก ์ ์กํ ์\n * ๊ฐ์ด ๊ทธ๋๋ก ๋จ๋๋ค. ์ค์ ๋ก ๋จํ๊ฐ ์ ๊บผ์ก๋ค.\n */\n private putEmissive(intensity: number) {\n // `chosen` ์ ์ฌ ๋ชจ๋ธ์ด๋ค. ํ์์ผ๋ก ์ฎ๊ธด ๊ฐ์ `partToFigure` ์ด ๋ง๋ ๊ฒ์ด๋ผ ์ฌ๊ธฐ์ ๋ค์ ๊บผ๋ธ๋ค.\n const glow = this.board && this.chosen ? partToFigure(this.chosen, this.board).material?.emissive : undefined\n\n this.putMaterial({ emissive: intensity > 0 ? { ...glow, intensity } : undefined })\n }\n\n private putMaterial(patch: Record<string, unknown>) {\n this.change(part => ({\n ...part,\n material: { ...(part.material ?? {}), ...patch } as FigurePart['material']\n }))\n }\n\n /**\n * ์์ ํ ๊ฒ์ ์ฌ ๋ชจ๋ธ๋ก ๋๋๋ ค ์๋ฆฐ๋ค.\n *\n * ์ฌ์ฉ์๋ XยทYยทZ ๋ก ์์ ํ๊ณ , ๋ชจ๋ธ๋ฌ ํ์ด์ง๋ ์ฌ ๋ชจ๋ธ์ ๊ฐ๋๋ค. ๊ทธ ์ฌ์ด๋ฅผ ์ฌ๊ธฐ์\n * ์๋๋ค โ ๋ณํํด์ ์์ ํ๊ณ ๋ค์ ๋๋๋ฆฐ๋ค. **์๋ณต ๋ณํ์ด ๋ฌด์์ค์ด๋ผ์ผ** ์์น ํ๋\n * ๊ณ ์ณค์ ๋ฟ์ธ๋ฐ ํ์ ๊ฐ์ด ์กฐ๊ธ์ฉ ๋ฐ๋ฆฌ๋ ์ผ์ด ์๋ค(`fold.test.ts` ๊ฐ ์ด๋ฅผ ํ์ธํ๋ค).\n */\n private change(edit: (part: FigurePart) => FigurePart) {\n const part = this.chosen\n const board = this.board\n if (!part || !board) return\n\n this.emit(partFromFigure(edit(partToFigure(part, board)), board))\n }\n\n /** ์ ๋ฐ ๋๊ตฌ๋ฅผ ์ํจ๋ค. ์ ๋ณธ์ ์ ์๋ฉด์ด ๊ฐ๋๋ค โ ์ฌ๊ธฐ์๋ ์๋ฆฌ๊ธฐ๋ง ํ๋ค. */\n private ask(what: string, axis: string) {\n this.dispatchEvent(\n new CustomEvent('part-tool', {\n detail: { index: this.selected, tool: what, axis },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private emit(part: PartModel) {\n this.dispatchEvent(\n new CustomEvent('update-part', { detail: { index: this.selected, part }, bubbles: true, composed: true })\n )\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-inspector.js","sourceRoot":"","sources":["../../client/modeller/figure-inspector.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement, nothing, svg } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport {\n EXTRUDE_PRIMITIVES,\n MATERIAL_PRESETS,\n PRIMITIVE_KINDS,\n SEGMENTED_PRIMITIVES,\n SEGMENT_PRESETS,\n SIZING_RULES,\n FIGURE_PLACEMENTS,\n trianglesOf\n} from '@hatiolab/figure-model'\nimport { ANCHOR_RULES, PART_ROLES, REPEAT_LIMIT, anchorOfPart, repeatPlanOfPart } from '@hatiolab/figure-model'\nimport type { AnchorRule, Axis, FigurePart, FigurePlacement, MaterialPreset, PartRole, PrimitiveKind } from '@hatiolab/figure-model'\nimport { activePalette } from '@hatiolab/things-scene'\n\nimport { partToFigure, partFromFigure } from './figure-source.js'\nimport type { FigureDraft, PartModel } from './figure-source.js'\nimport { canMirror } from './part-edits.js'\n\n/**\n * ๊ณ ๋ฅธ ๋ถํ์ ์์ฑ.\n *\n * ## ์ฌ๊ธฐ๊ฐ ์ฌ์ฉ์ ์ฉ์ด๋ก ๋ณด์ฌ ์ฃผ๋ ์๋ฆฌ๋ค\n *\n * ๋ชจ๋ธ๋ฌ ํ์ด์ง๊ฐ ๊ฐ๊ณ ์๋ ๊ฒ์ **์ฌ ๋ชจ๋ธ**์ด๋ค โ ๊ธฐ์ค ์์ ์์ ๋ถํ ์ปดํฌ๋ํธ๊ฐ ๋์ธ ์ํ.\n * ๊ทธ๋ฐ๋ฐ ์ฌ์ฉ์์๊ฒ ๋ณด์ฌ์ผ ํ๋ ๊ฒ์ ์ฌ ์์ฑ ์ด๋ฆ(`left`ยท`top`ยท`zPos`)์ด ์๋๋ผ\n * **XยทYยทZ** ๋ค. ๋ค๋ฅธ 3D ๋๊ตฌ๊ฐ ๋ชจ๋ ๊ทธ๋ ๊ฒ ๋ถ๋ฅด๊ณ , ์์น๋ ๋ถํ์ **์ค์ฌ**์ผ๋ก ์ฝ๋๋ค.\n *\n * ๊ทธ๋์ ์ด ํจ๋์ ๋ฐ์ ๋ถํ์ FigureSource ํํ๋ก **๋ณํํด์ ๋ณด์ฌ ์ฃผ๊ณ , ์์ ํ ๊ฒ์\n * ๋ค์ ์ฌ ๋ชจ๋ธ๋ก ๋๋๋ ค ์๋ฆฐ๋ค.** ๋ณํ์ `figure-source.ts` ๊ฐ ํ๋ค โ ์ฌ๊ธฐ์ ์ถ์ ๋ค์ ๊ณ์ฐํ์ง\n * ์๋๋ค.\n *\n * ## ์๋ ๊ฒ๋ง ๋ณด์ฌ ์ค๋ค\n *\n * ๋ถํ ์๋ ๊ณก๋ฉด์ด ์๋ ๋ํ์๋ง, ๋ชจ์๋ฆฌ ๊ตด๋ฆผ์ ๋จ๋ฉด์ ๋ฝ๋ ๋ํ์๋ง ๋ป์ด ์๋ค.\n * ๋ป ์๋ ์นธ์ ํ์์ผ๋ก ๋์ด๋์ผ๋ฉด ์ ์์๊ฐ ใ์ ์ ๋จน์งใ๋ฅผ ๊ณ ๋ฏผํ๊ฒ ๋๋ค โ\n * ์์ ๋ด์ง ์๋๋ค.\n *\n * ## ์ด๋ฆ์ ์ ์ฅ๋๋ ์๋ณ์๋ค\n *\n * `FigurePart.name` ์ ๋ฐ์ธ๋ฉยท์ ๋๋ฉ์ด์
ยท์ฌ๋กฏ์ด ๊ฐ๋ฆฌํค๋ ์ด๋ฆ์ด๋ค. ๊ณ ์น๋ฉด ๋ฐฐ์น๋\n * ์ธ์คํด์ค์ ๋ฐ์ธ๋ฉ์ด **์กฐ์ฉํ** ๋๊ธด๋ค. ๊ทธ๋์ ์ด๋ฆ ์นธ์๋ง ๊ฒฝ๊ณ ๋ฅผ ๋ถ์ธ๋ค.\n *\n * ## ใ์ํ ์์ด ๋ถ๋ ์๋ฆฌใ๋ฅผ ๊ฑท์๋ค\n *\n * `FigurePart.materialSlot`(๋น์ ์ด๋ฆ์ `slot`) ์ ๊ณ ๋ฅด๋ ์นธ์ด ์์๋๋ฐ **์๋ฌด ์ผ๋ ํ์ง ์์๋ค.** things-scene ์\n * figure ๋ฐํ์์ด `slot` ์ ์ฝ์ง ์๋๋ค โ ์ ์ธ ํ ์ค์ด ์ ๋ถ๋ค. ๋๋ ์ค ์๊ณ ๋ง๋ค์๊ณ ,\n * ํ์ธํ์ง ์์ ๊ฒ์ด ์๋ชป์ด๋ค.\n *\n * ๊ทธ๋ฆฌ๊ณ ๋๊ฒ ๋ง๋ค๋๋ผ๋ ์ด ๋ชจ์์ด ์๋๋ค. ์ํ ์์ ํน๋ณํ ๊ฒ์ด ์๋๋ผ **์์ฑ ํ๋**์ด๊ณ ,\n * ํดํยท๋ผ๋ฒจยทํ์ ์ฌ๋ถ์ ๊ฐ์ ์๋ฆฌ์์ ๋ค๋ค์ ธ์ผ ํ๋ค. ๊ทธ ์ค๊ณ๊ฐ ์ ํด์ง๋ฉด(figure-model#2)\n * ์ด ์๋ฆฌ์ **์์ฑ ์ ์ธ๊ณผ ๋ถํ ๋ฐ์ธ๋ฉ** ํธ์ง๊ธฐ๊ฐ ๋ค์ด์จ๋ค.\n *\n * ๊ทธ๋๊น์ง ๋น ์ฝ์์ ๋์ง ์๋๋ค. ์๋ฌด ์ผ๋ ์ ํ๋ ์นธ์ ์๋๋๋ง ๋ชปํ๋ค.\n *\n * ## ๊ณ ์น์ง ์๋๋ค\n *\n * ์ ๋ณธ ํ ๋ฒ์ ์ ์๋ฉด์ด ๊ฐ๋๋ค. ์ฌ๊ธฐ์๋ ๋ฐ๋ ๋ถํ์ ์๋ฆด ๋ฟ์ด๋ค.\n */\n@customElement('figure-inspector')\nexport class FigureInspector extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n --figure-control-height: 30px;\n overflow-y: auto;\n background-color: var(--md-sys-color-surface-container-lowest);\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n /*\n ์ด ํจ๋์ ๋ณธ๋ฌธ ํฌ๊ธฐ๋ฅผ ์ฌ๊ธฐ์ ํ ๋ฒ ์ ํ๋ค.\n\n ์ ์๋ ๊ท์น๋ง๋ค ๋ฐ๋ก ์ ์๋ค. ๊ทธ๋ฌ๋ฉด ๋น ๋จ๋ฆฐ ๊ท์น์ด ๋ณธ๋ฌธ ๊ธฐ๋ณธ ํฌ๊ธฐ(1rem)๋ฅผ\n ๋ฌผ๋ ค๋ฐ์ ๊ทธ ์ค๋ง ์ ๋ชฉ์ฒ๋ผ ์ปค์ง๋ค. ์ค๋ฅ๊ฐ ์๋๋ผ์ ํ๋ฉด์ ๋์ ๋ด์ผ ์๋ค.\n ์ด ํ์ผ์์๋ง ๋ ๋ฒ ๋ฌ๋ค.\n\n form ์์(input ยท select ยท button)๋ ๊ธ๊ผด์ ๋ฌผ๋ ค๋ฐ์ง ์์ผ๋ฏ๋ก ๊ฐ์ ์ ์ด์ผ ํ๋ค.\n ๊ทธ๊ฒ ๋ง๊ณ ๋ ์ฌ๊ธฐ ๊ฐ์ ๋ฐ๋ฅธ๋ค.\n */\n font-size: 0.76rem;\n }\n\n /*\n โโ ์๋ฆฌ๋ฅผ ์๋ผ๋ ํ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n ์์ฑ์ ์์ผ๋ก ๋ ๋์ด๋๋ค(๋ฅ๋ ฅ ยท ํฌํธ ยท ์ ๋๋ฉ์ด์
ยท ๊ธฐ์ค์ ๋ณด). ์ง๊ธ ์ฌ๋ฐฑ์ ๊ทธ๋๋ก ๋๋ฉด\n ๊ทธ๊ฒ๋ค์ด ๋ค์ด์ฌ ์๋ฆฌ๊ฐ ์๋ค. ์ ์ฌ๋ฐฑ์ 6/10 ์ผ๋ก, ์ ๋ชฉ ์๋๋ฅผ 4px ๋ก ์ค์๋ค โ ๊ธ์ ํฌ๊ธฐ์\n ์นธ ๋์ด๋ ๊ฑด๋๋ฆฌ์ง ์๋๋ค(์๊ฒ ๋ง๋๋ ๊ฒ์ด ์๋๋ผ **๋น ๊ณณ์ ์ค์ด๋ ๊ฒ**์ด๋ค).\n */\n section {\n padding: 8px 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n /* ์
๋ ฅ ํ์ ์ด์ดํ๊ฒ, ์๋ก ๋ค๋ฅธ ํธ์ง ์๋ ์ฌ์ด์๋ ํธํก์ ๋๋ค. */\n section + section {\n margin-top: 6px;\n }\n section[collapsible] {\n padding: 0;\n }\n details[group] > summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 34px;\n padding: 0 10px;\n cursor: pointer;\n list-style: none;\n }\n details[group] > summary::-webkit-details-marker {\n display: none;\n }\n details[group] > summary h3 {\n margin: 0;\n }\n details[group] > summary md-icon {\n --md-icon-size: 16px;\n color: var(--md-sys-color-on-surface-variant);\n }\n details[group] > div[group-content] {\n padding: 4px 10px 8px;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n h3 {\n display: flex;\n align-items: center;\n gap: 4px;\n margin: 0 0 4px 0;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* ์์ฐ ๋ฉํ๋ฐ์ดํฐ๋ ๋ถํ์ ๊ณ ์น๋ค๋ ํ์ฌ ๋ฌธ๋งฅ์์๋ ์์ฝ์ผ๋ก๋ง ๋๋ค. */\n details[asset] {\n margin: -1px 0;\n }\n details[asset] summary {\n display: flex;\n align-items: center;\n gap: 6px;\n min-height: 26px;\n cursor: pointer;\n list-style: none;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n details[asset] summary::-webkit-details-marker {\n display: none;\n }\n details[asset] summary::before {\n content: 'โบ';\n font-size: 1.1rem;\n line-height: 1;\n transition: transform 120ms ease;\n }\n details[asset][open] summary::before {\n transform: rotate(90deg);\n }\n details[asset] summary b {\n font-size: var(--ui-t-micro, 11px);\n letter-spacing: 0.04em;\n }\n details[asset] summary small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 0.7rem;\n }\n\n label {\n display: flex;\n align-items: center;\n gap: 3px;\n margin-bottom: 2px;\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /*\n ๋์๋ง ๋ฌผ์ํ. **๊ธ์ ์ค์ ํ๋ ๋จน์ง ์๋๋ค** โ ๋ผ๋ฒจยท์ ๋ชฉ ์ค์ ๋จ๋ ํญ์ ์นํ๋ค.\n ์์ด์ฝ๋ง ๋๊ณ ํ
๋๋ฆฌ๋ฅผ ์ ๋๋ ์ด์ ๋ ์ด๊ฒ์ด ๋๋ฅผ ๊ฒ์ด๋ผ๊ธฐ๋ณด๋ค ใ๋ ์๋คใ๋ ํ์๋ผ์๋ค.\n */\n button[help] {\n display: inline-flex;\n align-items: center;\n padding: 0;\n margin: 0;\n color: var(--md-sys-color-outline);\n background: none;\n border: none;\n cursor: pointer;\n }\n button[help] md-icon {\n --md-icon-size: 13px;\n font-size: 13px;\n }\n button[help]:hover,\n button[help][aria-expanded='true'] {\n color: var(--md-sys-color-primary);\n }\n\n /* ํธ ๋์๋ง. ๋ผ๋ฒจ ์๋ ํ ์นธ ๋ค์ฌ ๋ถ์ธ๋ค โ ๋ฌด์์ ๋ธ๋ฆฐ ๋ง์ธ์ง ๋ณด์ด๊ฒ. */\n p[hint] {\n margin: 2px 0 4px 0;\n padding-left: 6px;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n border-left: 2px solid var(--md-sys-color-outline-variant);\n }\n\n input,\n select {\n width: 100%;\n min-height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 4px 7px;\n font: var(--input-field-font, inherit);\n font-size: 0.76rem;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n input:focus,\n select:focus {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n }\n\n /*\n ์ซ์ ์นธ โ ๋ผ๋ฒจ์ ์นธ **์** ์ผ์ชฝ์ ๋๋ค.\n\n ๋ฒกํฐ ์ ์๋๊ตฌ(SketchยทFigma)๊ฐ XยทYยทWยทH ๋ฅผ ์ด๋ ๊ฒ ๋๋ค. ๋ผ๋ฒจ์ ์์ ์น์ผ๋ฉด ์ค๋ง๋ค\n ๋ ์ค์ ๋จน์ด์, ์๋ฆฌยทํฌ๊ธฐยทํ์ ์ํ ์นธ์ด ํ๋ฉด ์ ๋ฐ์ ์ฐจ์งํ๋ค. ์์ ๋๋ฉด ํ ์ค์\n ์
์ด ๋ค์ด๊ฐ๊ณ ๋ฌด์์ด ๋ฌด์์ธ์ง๋ ๋ถ์ด ์ฝํ๋ค.\n */\n div[cell] {\n display: flex;\n box-sizing: border-box;\n height: var(--figure-control-height);\n min-height: var(--figure-control-height);\n align-items: center;\n gap: 2px;\n padding-left: 6px;\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n div[cell]:focus-within {\n outline: 2px solid var(--md-sys-color-primary);\n outline-offset: -1px;\n border-color: transparent;\n }\n div[cell] span[axis] {\n flex: none;\n font-size: 0.64rem;\n letter-spacing: 0.02em;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n div[cell] input {\n min-width: 0;\n min-height: 0;\n height: calc(var(--figure-control-height) - 2px);\n padding: 4px 6px 4px 2px;\n font-family: var(--mono-font, monospace);\n text-align: right;\n background: none;\n border: none;\n border-radius: 0;\n }\n div[cell] input:focus {\n outline: none;\n }\n\n /* ์ถ ์
์ ํ ์ค์ โ ์ขํ๋ ์
์ด ๊ฐ์ด ์ฝํ์ผ ํ๋ค */\n div[triple] {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 4px;\n }\n div[field] + div[field],\n div[triple] + div[field],\n div[field] + div[triple],\n div[inline-field] + div[inline-field],\n div[inline-field] + div[field],\n div[field] + div[inline-field],\n div[vector-row] + div[vector-row],\n div[vector-row] + div[field],\n div[field] + div[vector-row] {\n /* ์นธ ์ฌ์ด 7 โ 5. ์นธ ์์ฒด๋ ๊ทธ๋๋ก ๋๊ณ ์ฌ์ด๋ง ์ขํ๋ค. */\n margin-top: 5px;\n }\n\n /* ์งง์ ๋ผ๋ฒจ๊ณผ ๋จ์ผ ๊ฐ์ ๊ฐ์ ์ค์์ ์ฝ๋๋ค. ๋ณต์กํ ์ ํ๊ธฐ์๋ ์ฐ์ง ์๋๋ค. */\n div[inline-field] {\n display: grid;\n /* ๊ฐ์ ํธ์ง ๋ฐ๋ ์์์๋ ์
๋ ฅ ์์์ ์ ๋ง์ถ๋ค. ๋ผ๋ฒจ ๊ธธ์ด๊ฐ ์นธ ํญ์ ํ๋ค๋ฉด ์ ๋๋ค. */\n grid-template-columns: 64px minmax(0, 1fr);\n align-items: center;\n gap: 7px;\n }\n div[inline-field] > label {\n margin: 0;\n white-space: nowrap;\n }\n /* ํ ์ค ์
๋ ฅ์ ์ค๋ช
์ ์
๋ ฅ์นธ์ ๋ฐ์ด๋ด์ง ์๊ณ ๋ฐ๋ก ์๋ ์ ํญ์์ ์ฝ๋๋ค. */\n div[inline-field] > p[hint] {\n grid-column: 1 / -1;\n margin: -2px 0 1px;\n }\n div[inline-field] > code[fixed] {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* XยทYยทZ๋ ํจ๊ป ๋น๊ตํ๋ ๊ฐ์ด๋ฏ๋ก, ๋ฌถ์ ์ ๋ชฉ๋ง ์ผ์ชฝ์ ๋๊ณ ์
๋ ฅ์ ํ ํ์ ๋๋ค. */\n div[vector-row] {\n display: grid;\n grid-template-columns: 64px minmax(0, 1fr);\n align-items: center;\n gap: 7px;\n }\n div[vector-row] > label {\n margin: 0;\n white-space: nowrap;\n }\n div[vector-row] > p[hint] {\n grid-column: 1 / -1;\n margin: -2px 0 1px;\n }\n div[sizing-choices] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 5px;\n }\n button[sizing-choice] {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 2px;\n min-height: 52px;\n padding: 7px 8px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 7px;\n text-align: left;\n cursor: pointer;\n }\n button[sizing-choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[sizing-choice] b {\n font-size: 0.74rem;\n }\n button[sizing-choice] small {\n font-size: 0.64rem;\n line-height: 1.35;\n opacity: 0.8;\n }\n div[anchor-rows] {\n display: grid;\n gap: 6px;\n }\n div[anchor-row] {\n display: grid;\n grid-template-columns: 46px minmax(0, 1fr);\n align-items: start;\n gap: 8px;\n padding: 6px 7px;\n background: var(--md-sys-color-surface-container);\n border-radius: 7px;\n }\n div[anchor-row] label {\n margin: 0;\n font-size: 0.7rem;\n font-weight: 700;\n }\n div[anchor-options] {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n }\n button[anchor-choice] {\n min-width: 0;\n height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 4px 3px;\n overflow: hidden;\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n font-size: 0.63rem;\n line-height: 1.2;\n text-overflow: ellipsis;\n white-space: nowrap;\n background: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 5px;\n cursor: pointer;\n }\n button[anchor-choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n details[anchor-advanced] {\n grid-column: 2;\n margin-top: 4px;\n }\n details[anchor-advanced] summary {\n cursor: pointer;\n font-size: 0.62rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n details[anchor-advanced] div[anchor-options] {\n margin-top: 4px;\n }\n div[palette-meaning] {\n display: grid;\n gap: 2px;\n margin-top: 7px;\n padding: 6px 8px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface-container);\n border-radius: 7px;\n }\n div[palette-meaning] b {\n font-size: 0.72rem;\n }\n div[palette-meaning] small {\n color: var(--md-sys-color-on-surface-variant);\n font-size: 0.64rem;\n line-height: 1.35;\n }\n\n /*\n ์ ๋ฐ ์ ์ ๋๊ตฌ.\n\n ๋ณด๋ ํธ์ง๊ธฐ๋ ์์ฐ์ ๋ฐฐ์นํ๋ ๊ณณ์ด๋ผ ๋์ถฉ ๋์๋ ๋์ง๋ง, ์ฌ๊ธฐ๋ ์์ฐ์ ๋ง๋๋\n ๊ณณ์ด๋ค. ใ๋ชธํต ํ๊ฐ์ด๋ฐใยทใ๋ฐ๋ฅ์ ๋ถ์ด๊ธฐใยทใ๋ฐ๋์ชฝ์๋ ํ๋ใ๋ฅผ ์์ผ๋ก ๊ณ์ฐํ๋ฉด\n ๋ ์กฐ๊ธ์ฉ ์ด๊ธ๋๊ณ , ๊ธฐ์ค ์น์๋ฅผ ๋ฐ๊พธ๋ฉด ์ ๋ถ ๋ค์ ํด์ผ ํ๋ค.\n */\n div[tools] {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 4px;\n }\n div[tools] button {\n display: grid;\n place-items: center;\n min-width: 0;\n height: var(--figure-control-height);\n box-sizing: border-box;\n padding: 0;\n font: var(--label-font, inherit);\n font-size: 0.7rem;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n div[tools] button md-icon {\n font-size: 17px;\n }\n div[tools] button[disabled] {\n opacity: 0.35;\n cursor: default;\n }\n div[tools] button:hover:not([disabled]) {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /* ์ง๊ธ ์ด๋ ์ถ์ด ๋์ด๋๋ โ ํฌ๊ธฐ๋ฅผ ๊ณ ์น๋ฉด ๋ฐ๋ ์ ์์ด์ ๊ฐ์ผ๋ก ์ ๋๋ค */\n p[axis-now] {\n margin: 4px 0 0 0;\n font-size: 0.7rem;\n color: var(--md-sys-color-primary);\n }\n /* ์ด ์ ํ์ด ๋ฌด์์ ๋ฌด๋์ง โ ์ฑ์๋์ ๋ฌถ์ ์์ ๊ทธ๋๋ก ์กํ๋ค */\n p[cost] {\n margin: 4px 0 0 0;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* ์ด๋ฆ์ ๋ฐ๊พธ๋ฉด ๋ฌด์์ด ๋๊ธฐ๋์ง ๋งํ๋ค */\n p[warn] {\n margin: 4px 0 0 0;\n font-size: 0.68rem;\n line-height: 1.5;\n color: var(--md-sys-color-tertiary);\n }\n\n /* ๋ถํ ์ ํ๋ฆฌ์
โ ์์ ์
๋ ฅ๋ณด๋ค ์ด ์
์ ๊ถํ๋ค */\n div[presets] {\n display: flex;\n gap: 4px;\n margin-top: 4px;\n }\n div[presets] button {\n flex: 1;\n padding: 3px 0;\n font: var(--label-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: 6px;\n cursor: pointer;\n }\n div[presets] button[on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /*\n ๋ถํ ์ ์ ํ โ ๋ชจ์๊ณผ ์ผ๊ฐํ ์๋ฅผ **ํจ๊ป** ๋ณด์ฌ ์ค๋ค.\n\n ์ซ์๋ง ๋์ด๋์ผ๋ฉด 8 ๊ณผ 16 ์ด ๋ฌด์์ด ๋ค๋ฅธ์ง ์ ์ ์๋ค. ๋ก์ฐํด๋ฆฌ์์ ์ด ์ ํ์ด\n ๊ณง ใ๋ช ๊ฐ๊น์ง ํธํ๊ฒ ๋์ ์ ์๋ใ๋ฅผ ์ ํ๋ฏ๋ก, ๊ฐ์ง๋ ์ ๋์ ๊ทธ ๊ฐ์ด ๋ฌด๋\n ์ผ๊ฐํ ์๋ฅผ ํ์๋ฆฌ์์ ๋ณด์์ผ ํ๋ค.\n\n ์ค๋ฃจ์ฃ์ ์ง์ด๋ธ ๊ทธ๋ฆผ์ด ์๋๋ค โ ๊ณก๋ฉด ํ๋ฆฌ๋ฏธํฐ๋ธ๋ฅผ ์์์ ๋ณธ ์ค๊ณฝ์ด ์ ํํ\n ์ n๊ฐํ์ด๋ค. ์ผ๊ฐํ ์๋ ํ๋ฉด์ด ์
ํ์ง ์๊ณ figure-model ์ trianglesOf ๊ฐ ๋ธ๋ค.\n */\n div[segments] {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 4px;\n }\n /* ์ ์ ์ง ยท ๋๊ธฐ โ ๊ณ ๋ฅด๋ ๊ฐ์ด๋ผ ๋ถํ ์์ ๊ฐ์ ๋ชจ์์ผ๋ก ๋๋ค */\n div[choices] {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 4px;\n }\n button[choice] {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 1px;\n padding: 6px 8px;\n text-align: left;\n font: var(--label-font, inherit);\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n button[choice]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n button[choice][on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[choice] small {\n opacity: 0.75;\n }\n button[seg] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1px;\n padding: 6px 2px 4px 2px;\n font: var(--label-font, inherit);\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n button[seg]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n button[seg][on] {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n button[seg] svg {\n display: block;\n /* ์์ผ๋ฉด 12 ์ 16 ์ด ๋ ๋ค ๋๊ทธ๋ผ๋ฏธ๋ก ๋ณด์ธ๋ค โ ๊ฐ์ด ์ฝํ ๋งํผ์ ํค์ด๋ค */\n width: 32px;\n height: 32px;\n }\n button[seg] svg polygon {\n fill: var(--md-sys-color-surface-container-highest);\n stroke: currentColor;\n stroke-width: 1.1;\n stroke-linejoin: miter;\n }\n button[seg][on] svg polygon {\n fill: var(--md-sys-color-surface-container-lowest);\n }\n button[seg] b {\n font-size: 0.8rem;\n font-weight: 700;\n line-height: 1.1;\n }\n button[seg] small {\n font-size: 0.62rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n button[seg][on] small {\n color: inherit;\n }\n /* ์ฑ๋ฅยท์ค๋ฃจ์ฃ ๊ฒ์ฆ์ ๋ง์น ํ๋ฆฌ์
๋ง ๊ณ ๋ฅธ๋ค. */\n details[free] {\n margin-top: 6px;\n }\n details[free] summary {\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n cursor: pointer;\n }\n details[free] div[cell] {\n margin-top: 4px;\n }\n\n /*\n ์ ๊ฒฌ๋ณธ.\n\n ํ ํฐ์ ๊ธ์๋ก ๋ฐ์ง ์๋๋ค. things-scene ์ ํ๋ ํธ ์ ์ธ์ด ใ์ฌ๊ธฐ ๋ ์ด๋ฆ์ด ์ ์์์\n ๊ณ ๋ฅผ ์ ์๋ ์ ๋ถ์ด๊ณ , ์์ ์์ ํ์ฉํ์ง ์๋ ๊ฒ์ด ๊ฐ๊ฐ์ ์ธ ๋ก์ฐํด๋ฆฌ์ ์ฒซ ๊ท์นใ\n ์ด๋ผ๊ณ ๋ชป๋ฐ๊ณ ์๋ค. ๊ธ์ ์นธ์ผ๋ก ๋๋ฉด ๊ทธ ๊ท์น์ด ํ๋ฉด์์ ์ฌ๋ผ์ง๊ณ , ์คํ ํ๋๋ก\n resolveToken ์ด ๋์ง๋ค.\n */\n div[swatches] {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n /*\n ๋ ๋ฌด๋ฆฌ์ ๊ฒฝ๊ณ. ใ์น ํ ์ใ๊ณผ ใ์ผ์ง ์ใ์ด ํ ์ค์ ์์ด๋ฉด accent(์ฃผํฉ)์\n status-warning(์ฃผํฉ)์ด ๋๋ํ ๋์ฌ ๋ฌด์์ด ๋ฌด์์ธ์ง ์ ์ ์๋ค.\n */\n label[group] {\n margin-top: 8px;\n padding-top: 8px;\n font-size: var(--ui-t-micro, 11px);\n letter-spacing: 0.03em;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n\n /* ๊ฐ์ด ์์ ๋ถ์ด์ผ ๋๋ฉด์ ์ผ๋ง์ธ์ง ์๋ค */\n div[slider] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n div[slider] input[type='range'] {\n flex: 1;\n accent-color: var(--md-sys-color-primary);\n cursor: pointer;\n }\n div[slider] output {\n flex: none;\n width: 2.6em;\n text-align: right;\n font: var(--mono-font, ui-monospace, monospace);\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n button[swatch] {\n width: 26px;\n height: 26px;\n padding: 0;\n background-color: var(--swatch);\n border: 1px solid rgba(0, 0, 0, 0.16);\n border-radius: 50%;\n cursor: pointer;\n }\n button[swatch][on] {\n /* ๊ณ ๋ฅธ ๊ฒ์ ํ
๋๋ฆฌ๊ฐ ์๋๋ผ ๊ณ ๋ฆฌ๋ก ํ์ํ๋ค โ ์ ์์ฒด๋ฅผ ๊ฐ๋ฆฌ์ง ์์ผ๋ ค๊ณ */\n box-shadow:\n 0 0 0 2px var(--md-sys-color-surface-container-lowest),\n 0 0 0 4px var(--md-sys-color-primary);\n }\n span[token] {\n display: block;\n margin-top: 6px;\n font-family: var(--mono-font, monospace);\n font-size: 0.68rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 7px 0 0 0;\n font-size: 0.74rem;\n color: var(--md-sys-color-on-surface);\n cursor: pointer;\n }\n label[toggle] input {\n width: auto;\n }\n div[role-choices] {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n }\n div[role-choices] label[toggle] {\n justify-content: center;\n min-height: 30px;\n margin: 0;\n padding: 2px 4px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n font-size: 0.68rem;\n text-align: center;\n }\n div[role-choices] label[toggle]:has(input:checked) {\n color: var(--md-sys-color-on-primary-container);\n background: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n p[quiet] {\n margin: 0;\n font-size: 0.76rem;\n line-height: 1.6;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /*\n ๊ณ ์น ์ ์๋ ๊ฐ โ ์
๋ ฅ์นธ์ฒ๋ผ ๋ณด์ด์ง ์๊ฒ ํ๋ค.\n\n ์ ์๋ ๊ทธ๋ฅ ๊ธ์์๊ณ , ์์ ์ด๋ฆ ์นธ๊ณผ ๋๋ํ ์์ผ๋ ๋๋ฌ๋ ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์๋ค. ์๋ฌผ์ ์\n ์นธ ์๋ ๋ฐํ์ด ใ์ฝ๋ ๊ฐใ์ด๋ผ๊ณ ๋จผ์ ๋งํ๋ค.\n */\n code[fixed] {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n border-radius: 6px;\n background-color: var(--md-sys-color-surface-container-high, rgba(0, 0, 0, 0.05));\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n font-family: var(--mono-font, monospace);\n font-size: 0.76rem;\n }\n\n code[fixed] md-icon {\n --md-icon-size: 13px;\n opacity: 0.7;\n }\n `\n ]\n\n /** ๋ํ์ DB ์๋ณ์. ๋น์ด ์์ผ๋ฉด ๋ฏธ์ ์ฅ ์ ๊ท ๋ชจ๋ธ์ด๋ค. */\n @property({ type: String }) figureId = ''\n /** ๋ํ์ ํ์ ์ด๋ฆ. ์ ๋ณธ์ ์ ์๋ฉด์ด ๋ค๊ณ , ์ฌ๊ธฐ์๋ ๋ณด์ฌ ์ฃผ๊ณ ๋ฐ๊พผ๋ค(`figure-rename` ์ผ๋ก ์๋ฆฐ๋ค). */\n @property({ type: String }) figureName = ''\n /** ๋ถ๋ฅ ํ๋ โ ํ๋ ํธ์์ ๋ฌถ๋ ๊ธฐ์ค. */\n @property({ type: String }) figureCategory?: string\n /** ํ๊ทธ ์ฌ๋ฟ โ ๋ถ๋ฅ๋ก๋ ๋ชป ํ๋ ์ฐพ๊ธฐ. */\n @property({ type: Array }) figureTags?: string[]\n\n /** ํด ๋ ๋์๋ง. ๋ถํ์ ๋ฐ๊ฟ๋ ์ ์ง๋๋ค โ ๋งค๋ฒ ๋ค์ ํด๊ฒ ํ์ง ์๋๋ค. */\n @state() private opened = new Set<string>()\n\n @property({ type: Object }) draft?: FigureDraft\n /** ์ด์ ์์ ๋ถํ๋ค. ์ฌ ๋ชจ๋ธ ๊ทธ๋๋ก๋ค. */\n @property({ type: Array }) parts: PartModel[] = []\n @property({ type: Number }) selected = -1\n\n /** `part` ๋ HTMLElement ์ ์์ฑ(DOMTokenList)์ด๋ค โ ๊ฐ๋ฆฌ๋ฉด ํ์ด ์ด๊ธ๋๋ค. */\n private get chosen(): PartModel | undefined {\n return this.parts?.[this.selected]\n }\n\n render() {\n const part = this.chosen\n if (!part || !this.draft) {\n return html`\n ${this.renderFigure(false)}\n <section>\n <h3>${i18next.t('figure.label.properties')}</h3>\n <p quiet>${i18next.t('figure.text.select-a-part-to-edit')}</p>\n </section>\n `\n }\n\n // ์ฌ๊ธฐ๋ถํฐ๋ ์ฌ์ฉ์ ์ฉ์ด๋ค โ XยทYยทZ, ์์น๋ ๋ถํ ์ค์ฌ, ํ์ ์ ๋(degree).\n const shown = partToFigure(part, this.draft)\n\n /*\n ์ญํ ์ ๋จผ์ ๋ฌป๋๋ค.\n\n ์๋ฆฌ(slot)๋ก ์ง์ ํ ๋ถํ์ **๊ทธ๋ ค์ง์ง ์๋๋ค.** ๊ทธ ์ฌ์ค์ ๋ชจ๋ฅธ ์ฑ ์ฌ์ง๋ถํฐ ๊ณ ๋ฅด๋ฉด ์ ์ฐ์ผ\n ์์ ๊ณ ๋ฅด๊ฒ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์๋ฆฌ๋ ๋ํ์ด ๋ฅ๋ ฅ์ ์ง ๋๋ง ๋ป์ด ์์ผ๋ฏ๋ก, ๋ฅ๋ ฅ์ด ์์ผ๋ฉด ์ด\n ๋ฌถ์์ ์์ ๋์ค์ง ์๋๋ค โ ํด ๋ฌ๋ ์๋ฌด ์ผ๋ ์ ์ผ์ด๋๋ ์นธ์ ๋ณด์ฌ ์ฃผ์ง ์๋๋ค.\n */\n return html`\n ${this.renderFigure(true)} ${this.renderIdentity(shown)} ${this.renderRole(shown)}\n ${this.renderPlacement(shown)} ${this.renderShape(shown)} ${this.renderMaterial(shown)}\n ${this.renderBehaviour(shown)}\n `\n }\n\n /**\n * โโ ์ด ๋ถํ์ด ๋ฅ๋ ฅ์์ ๋งก๋ ์๋ฆฌ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ใ๋ฅ๋ ฅใ ํญ์ด ๋ํ ์ ์ฒด๊ฐ ๋ฌด์์ ํ๋์ง ์ ํ๊ณ , ์ด๋ ๋ถํ์ด ๊ทธ๊ฒ์ ๋ฐ์ณ ์ฃผ๋์ง๋ ์ฌ๊ธฐ์\n * ์ ํ๋ค. **๋ถํ์ ๊ณ ์น๋ ๊ณณ์ด ํ ๊ตฐ๋ฐ์ฌ์ผ** ํ๊ธฐ ๋๋ฌธ์ด๋ค โ ๋ชฉ๋ก์ ๋ฐ๋ก ๋๋ฉด ๊ฐ์ ๋ถํ์\n * ๋ ํ๋ฉด์์ ๊ณ ์น๊ฒ ๋๊ณ , ์ ์์๋ ์ด๋ ์ชฝ์ด ์ด๊ธฐ๋์ง ๋งค๋ฒ ์๊ฐํด์ผ ํ๋ค.\n *\n * ์นธ ์๋ `repeat` ๊ฐ ์์ผ๋ฉด ๋ฐ์ง ์๋๋ค. ๋ฐ๋ณตํ๋ ์๋ฆฌ์ ์นธ ์๋ **์ธ์คํด์ค ํฌ๊ธฐ**๊ฐ ์ ํ๋ค โ\n * ์ปจ๋ฒ ์ด์ด๊ฐ ๊ธธ์ด์ง๋ฉด ์ค์ ์๋ฆฌ๊ฐ ๋์ด๋๋ ๊ฒ์ด ๊ทธ๊ฒ์ด๊ณ , ์ฌ๊ธฐ ์ ์ ๊ฐ์ ์ ์ฐ์ธ๋ค.\n */\n private renderRole(part: FigurePart) {\n if (!this.draft?.capabilities?.length) return nothing\n\n const roles = part.capability?.roles ?? []\n const repeats = part.sizing === 'repeat' && !!part.repeat\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.role-in-capability')}${this.help('figure.text.anchors-are-not-drawn')}</h3>\n\n <div role-choices>\n ${(PART_ROLES as readonly PartRole[]).map(\n one => html`\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${live(roles.includes(one))}\n @change=${(e: Event) => this.toggleRole(one, (e.target as HTMLInputElement).checked)}\n />\n ${i18next.t('figure.label.role-' + one)}\n </label>\n `\n )}\n </div>\n ${roles.length === 0 ? html`<p quiet>${i18next.t('figure.text.role-none-means-drawn')}</p>` : nothing}\n\n ${roles.includes('slot')\n ? html`\n <div field>\n <label>${i18next.t('figure.label.accepts')}${this.help('figure.text.accepts-explained')}</label>\n <input\n .value=${(part.capability?.accepts ?? []).join(', ')}\n placeholder=${i18next.t('figure.text.accepts-anything')}\n @change=${(e: Event) => this.setAccepts((e.target as HTMLInputElement).value)}\n />\n </div>\n <div field>\n <label>${i18next.t('figure.label.slot-capacity')}</label>\n ${repeats\n ? html`<p quiet>${i18next.t('figure.text.capacity-from-repeat')}</p>`\n : this.number('', part.capability?.capacity ?? 1, value => this.setCapacity(value), 1)}\n </div>\n `\n : nothing}\n </section>\n `\n }\n\n /**\n * ์ญํ ํ๋๋ฅผ ์ผ๊ณ ๋๋ค.\n *\n * **์ฌ๋ฟ์ ํจ๊ป ๋งก์ ์ ์๋ค.** AGV ์ ์ํ์ ๋ฌผ๊ฑด์ ๋๋ ์๋ฆฌ์ด๋ฉด์ ๊ทธ ์๋ฆฌ๋ก ๋ฌผ๊ฑด์ด\n * ๋ค์ด์ค๊ณ ๋๊ฐ๋ค. ๊ทธ๋์ ํ๋๋ฅผ ๊ณ ๋ฅด๋ ์ ํ ์์๊ฐ ์๋๋ผ ํ์ธ ์์๋ค.\n *\n * ๋ง์ง๋ง ์ญํ ์ ๋๋ฉด `capability` ๋ฅผ ํต์งธ๋ก ์ง์ด๋ค. ๋น ๋ฐฐ์ด์ ๋จ๊ธฐ๋ฉด ํ์์ด ์ค๋ฅ๋ก ๋ณด๊ณ ,\n * ์ ์์๊ฐ ๋ณด๊ธฐ์๋ ์๋ฌด ์ญํ ๋ ์๋ ํ๋ฒํ ๋ถํ์ธ๋ฐ ๋ฐํ์ด ๋งํ๋ค.\n */\n private toggleRole(role: PartRole, on: boolean) {\n this.change(part => {\n const roles = (part.capability?.roles ?? []).filter(one => one !== role)\n if (on) roles.push(role)\n\n if (roles.length === 0) {\n const { capability, ...rest } = part\n return rest as FigurePart\n }\n\n // ํ์์ด ์ ์ ์์๋ฅผ ์งํจ๋ค โ ์ผ ์์๋๋ก ๋๋ฉด ๊ฐ์ ๋ป์ด ๋ค๋ฅธ ๊ฐ์ผ๋ก ์ ์ฅ๋๋ค.\n const ordered = (PART_ROLES as readonly PartRole[]).filter(one => roles.includes(one))\n return { ...part, capability: { ...part.capability, roles: ordered } }\n })\n }\n\n private setAccepts(raw: string) {\n const accepts = raw\n .split(',')\n .map(one => one.trim())\n .filter(one => one.length > 0)\n\n this.change(part => {\n const spec = { ...part.capability, roles: part.capability?.roles ?? ['slot' as PartRole] }\n // ๋น ๋ชฉ๋ก์ ์ ํํ์ง ์๋๋ค๋ ๋ป์ด๋ค. ๋น ๋ฐฐ์ด์ ์ ์ฅํ๋ฉด ์๋ฌด๊ฒ๋ ๋ชป ๋ฐ๋ ๊ฒ์ผ๋ก ์ฝํ๋ค.\n if (accepts.length > 0) spec.accepts = accepts\n else delete spec.accepts\n return { ...part, capability: spec as NonNullable<FigurePart['capability']> }\n })\n }\n\n private setCapacity(value: number) {\n this.change(part => {\n const spec = { ...part.capability, roles: part.capability?.roles ?? ['slot' as PartRole] }\n if (Number.isFinite(value) && value >= 1) spec.capacity = Math.floor(value)\n else delete spec.capacity\n return { ...part, capability: spec as NonNullable<FigurePart['capability']> }\n })\n }\n\n /**\n * ๋ํ ์์ฒด โ ์ด๋ฆ๊ณผ ํ์
.\n *\n * ## ์ ๋จธ๋ฆฌ์ค์ด ์๋๋ผ ์ฌ๊ธฐ์ธ๊ฐ\n *\n * ์ ์๋ฉด ์์ ์ค์ ํ๋ ๋ ๋๊ณ ์ด๋ฆ ์นธ์ ๋์์๋ค. ์ฑ์์๋ ์
ธ์ด ํ์ด์ง ์ ๋ชฉ์ผ๋ก ๊ทธ ์ด๋ฆ์\n * ์ด๋ฏธ ๊ทธ๋ฆฌ๋ฏ๋ก ๊ฐ์ ๊ธ์๊ฐ ๋ ๋ฒ ๋์ค๊ณ , ์บ๋ฒ์ค๊ฐ ์ฃผ์ธ๊ณต์ธ ํ๋ฉด์์ ๊ทธ ์ค๋งํผ ๋์ด๋ฅผ ์์๋ค.\n * ์์ฑ ํจ๋์ ใ์ด ๋ํ์ด ๋ฌด์์ธ๊ฐใ๋ฅผ ๋ค๋ฃจ๋ ์๋ฆฌ์ด๋ฏ๋ก ์ด๋ฆ๋ ์ฌ๊ธฐ ์ฐ๋ค.\n *\n * ## ํ์
์ ์ฝ๊ธฐ๋ง ํ๋ค\n *\n * ์ ์ฅ๋๋ ์๋ณ์๋ค. ๋ฐฐ์น๋ ๋ณด๋๊ฐ ์ด ์ด๋ฆ์ผ๋ก ํ์
์ ์ฐพ์ผ๋ฏ๋ก ๋ง๋ ๋ค์๋ ๋ชป ๋ฐ๊พผ๋ค.\n */\n private renderFigure(compact = false) {\n const fields = html`\n <div inline-field>\n <label>${i18next.t('figure.label.name')}</label>\n <input\n .value=${this.figureName}\n placeholder=${i18next.t('figure.text.figure-display-name')}\n @change=${(e: Event) =>\n this.dispatchEvent(\n new CustomEvent('figure-rename', {\n detail: { name: (e.target as HTMLInputElement).value },\n bubbles: true,\n composed: true\n })\n )}\n />\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.figure-type')}${this.figureId ? this.helpButton('figure.text.type-name-cannot-change') : nothing}</label>\n ${!this.figureId\n ? html`<input\n .value=${this.draft?.figureType ?? ''}\n placeholder=${i18next.t('figure.text.figure-type-placeholder', { defaultValue: '๋ํ ์๋ณ ํ์
(์: OHT)' })}\n @change=${(e: Event) =>\n this.dispatchEvent(\n new CustomEvent('figure-type-change', {\n detail: { type: (e.target as HTMLInputElement).value.trim().toUpperCase() },\n bubbles: true,\n composed: true\n })\n )}\n />`\n : html`<code fixed title=${i18next.t('figure.text.type-name-cannot-change')}>\n <md-icon>lock</md-icon>${this.draft?.figureType ?? ''}\n </code>\n ${this.helpHint('figure.text.type-name-cannot-change')}`}\n </div>\n <!--\n ์ ๋ชป ๊ณ ์น๋์ง **์ ์ด ๋๋ค.** ์ ์๋ tooltip ์๋ง ์์๊ณ , ๊ทธ๋ฌ๋ฉด ๋๋ฌ ๋ณด๊ณ ์ ๋๋ ๊ฒ์\n ์๊ฒ ๋๋ค โ ํ๋ฉด์ด ์ ๋๋ ์ด์ ๋ฅผ ๋งํ์ง ์์ผ๋ฉด ์ฌ์ฉ์๊ฐ ์๊ธฐ ์ค์๋ผ๊ณ ์๊ฐํ๋ค.\n -->\n\n <div inline-field>\n <label>${i18next.t('figure.label.figure-placement')}${this.helpButton('figure.text.placement-explained')}</label>\n <select\n .value=${this.draft?.placement ?? 'floor'}\n @change=${(e: Event) => this.setPlacement((e.target as HTMLSelectElement).value as FigurePlacement)}\n >\n <option value=\"floor\" ?selected=${(this.draft?.placement ?? 'floor') === 'floor'}>\n ${i18next.t('figure.label.placement-floor')}\n </option>\n <option value=\"ceiling\" ?selected=${this.draft?.placement === 'ceiling'}>\n ${i18next.t('figure.label.placement-ceiling')}\n </option>\n <option value=\"center\" ?selected=${this.draft?.placement === 'center'}>\n ${i18next.t('figure.label.placement-center')}\n </option>\n </select>\n ${this.helpHint('figure.text.placement-explained')}\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.category')}${this.helpButton('figure.text.category-explained')}</label>\n <input\n .value=${this.figureCategory ?? ''}\n placeholder=${i18next.t('figure.text.category-placeholder')}\n @change=${(e: Event) => this.tellCatalog({ category: (e.target as HTMLInputElement).value.trim() || undefined })}\n />\n ${this.helpHint('figure.text.category-explained')}\n </div>\n\n <div inline-field>\n <label>${i18next.t('figure.label.tags')}${this.helpButton('figure.text.tags-explained')}</label>\n <input\n .value=${(this.figureTags ?? []).join(', ')}\n placeholder=${i18next.t('figure.text.tags-placeholder')}\n @change=${(e: Event) => this.tellTags((e.target as HTMLInputElement).value)}\n />\n ${this.helpHint('figure.text.tags-explained')}\n </div>\n `\n\n if (compact) {\n return html`\n <section>\n <details asset>\n <summary>\n <b>${i18next.t('figure.label.figure')}</b>\n <small>${this.figureName || this.draft?.figureType || ''}</small>\n </summary>\n ${fields}\n </details>\n </section>\n `\n }\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.figure')}</h3>\n ${fields}\n </section>\n `\n }\n\n /**\n * ํ๊ทธ ์ค์ ๋ชฉ๋ก์ผ๋ก.\n *\n * ์ผํ๋ก ๊ฐ๋ฅด๊ณ `#` ์ ๋ผ์ด ๋ธ๋ค โ ์ฌ๋์ `#๋ฐ์ถ` ์ด๋ผ๊ณ ์ ๊ณ , ์ ์ฅ๋๋ ๊ฒ์ `๋ฐ์ถ` ์ด๋ค.\n * ๊ฒน์น ๊ฒ์ ํ ๋ฒ๋ง ๋จ๊ธด๋ค. ๋น ์ค์ **๋น ๋ฐฐ์ด**์ด์ง `undefined` ๊ฐ ์๋๋ค โ ์ ๋ถ ์ง์ฐ๋ ค๋\n * ์ ์์๊ฐ ์ง์ธ ๋ฐฉ๋ฒ์ ์์ง ์๊ฒ.\n */\n private tellTags(raw: string) {\n const tags = [\n ...new Set(\n raw\n .split(',')\n .map(one => one.trim().replace(/^#+/, '').trim())\n .filter(one => one.length > 0)\n )\n ]\n\n this.tellCatalog({ tags })\n }\n\n /** ์นดํ๋ก๊ทธ ๊ฐ์ด ๋ฐ๋์๋ค๊ณ ์๋ฆฐ๋ค. ์ ๋ณธ์ ์ ์๋ฉด์ด ๋ ๋ค โ ์ฌ๊ธฐ์๋ ์๋ฆฌ๊ธฐ๋ง ํ๋ค. */\n private tellCatalog(patch: { category?: string; tags?: string[] }) {\n this.dispatchEvent(new CustomEvent('figure-catalog', { detail: patch, bubbles: true, composed: true }))\n }\n\n /**\n * 3D ๋ฐฐ์น ๊ธฐ์ค๋ฉด์ ๋ฐ๊พผ๋ค ('floor' | 'ceiling' | 'center').\n *\n * **๋ถํ์ ๊ฑด๋๋ฆฌ์ง ์๋๋ค.** ์ด ๊ฐ์ ใ์ด ์ข
๋ฅ๋ ์ด๋ ๋ฉด์ ๋ถ๋๊ฐใ๋ฅผ ๋งํ ๋ฟ์ด๊ณ ,\n * ์ ์ํ ๋ชจ์์ ๊ทธ๊ฒ๊ณผ ๋ฌด๊ดํ๋ค. ํ์์ด ๋ถํ์ ์์ ์ค์ฌ์์ ์ฌ๋ฏ๋ก, ๋ฐฐ์น๊ฐ ๋ฌ๋ผ๋\n * `parts` ๋ ํ ๊ธ์๋ ์ ๋ฐ๋๋ค.\n *\n * ํ๋์ ์ฌ๊ธฐ์ `zPos` ๋ฅผ ๋ค์ ๊ณ์ฐํ๋ค. ํธ์ง ์บ๋ฒ์ค๊ฐ ์ด ๊ฐ์ ์ฌ์ ์ขํ ๋ชจ๋๋ก\n * ํ๋ ค๋ณด๋ด๋ ๋์ ์ผ์ธ๋ฐ, ๊ทธ๋ฌ๋ฉด ๋ฐฐ์น๋ฅผ ๊ณ ๋ฅผ ๋๋ง๋ค ์ ์์๊ฐ ์ ์ด ๋ ๋์ด๊ฐ ์ ๋ถ\n * ๋ค๋ฅธ ์ซ์๋ก ๋ณด์๋ค โ ์ ์ฅ๋๋ ๊ฒ์ ๊ทธ๋๋ก์ธ๋ฐ. ์ขํ ๋ชจ๋๋ ์ด์ ๋ณด๊ธฐ ์ค์ ์ด๊ณ \n * (`figure-view.ts`), ํธ์ง ์บ๋ฒ์ค๋ ๋ ์์ ๊ธฐ์ค์ด๋ค.\n */\n private setPlacement(placement: FigurePlacement) {\n if (!this.draft) return\n const draft = { ...this.draft, placement }\n this.dispatchEvent(new CustomEvent('update-draft', { detail: { draft }, bubbles: true, composed: true }))\n }\n\n private renderIdentity(part: FigurePart) {\n return html`\n <section>\n <h3>${i18next.t('figure.label.part')}</h3>\n <div inline-field>\n <label>${i18next.t('figure.label.name')}${this.helpButton('figure.text.renaming-a-part-breaks-bindings')}</label>\n <input\n .value=${part.name}\n @change=${(e: Event) => this.put({ name: (e.target as HTMLInputElement).value })}\n />\n ${this.helpHint('figure.text.renaming-a-part-breaks-bindings')}\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.shape')}</label>\n <select @change=${(e: Event) => this.changePrimitive((e.target as HTMLSelectElement).value as PrimitiveKind)}>\n ${PRIMITIVE_KINDS.map(\n kind => html`\n <option value=${kind} ?selected=${kind === part.primitive}>\n ${i18next.t('figure.label.primitive-' + kind)}\n </option>\n `\n )}\n </select>\n </div>\n </section>\n `\n }\n\n private renderPlacement(part: FigurePart) {\n const t = part.transform\n const rotation = t.rotation ?? {}\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.placement')}</h3>\n\n <div vector-row>\n <label>${i18next.t('figure.label.part-position')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), t.position[axis], value =>\n this.putTransform({ position: { ...t.position, [axis]: value } })\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.part-size')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(\n axis.toUpperCase(),\n t.size[axis],\n value => this.putTransform({ size: { ...t.size, [axis]: value } }),\n 1\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.rotation-degrees')}</label>\n <div triple>\n ${(['x', 'y', 'z'] as const).map(axis =>\n this.number(axis.toUpperCase(), rotation[axis] ?? 0, value =>\n this.putTransform({ rotation: { ...rotation, [axis]: value } })\n )\n )}\n </div>\n </div>\n\n <div vector-row>\n <label>${i18next.t('figure.label.tools')}${this.helpButton('figure.text.tools-explained')}</label>\n <div tools>\n <button\n aria-label=${i18next.t('figure.button.center-x')}\n title=${i18next.t('figure.text.center-on-x')}\n @click=${() => this.ask('center', 'x')}\n >\n <md-icon>horizontal_distribute</md-icon>\n </button>\n <button\n aria-label=${i18next.t('figure.button.center-z')}\n title=${i18next.t('figure.text.center-on-z')}\n @click=${() => this.ask('center', 'z')}\n >\n <md-icon>vertical_align_center</md-icon>\n </button>\n <button\n aria-label=${i18next.t('figure.button.to-floor')}\n title=${i18next.t('figure.text.put-on-floor')}\n @click=${() => this.ask('floor', 'y')}\n >\n <md-icon>vertical_align_bottom</md-icon>\n </button>\n ${(['x', 'z'] as const).map(axis => {\n // ์ด๋ฏธ ๊ฐ์ด๋ฐ๋ฉด ๋์นญ์ด ์ ์๋ฆฌ๋ค โ ๊ฒน์น ๋ถํ์ด ์กฐ์ฉํ ์๊ธฐ์ง ์๊ฒ ๋ง๋๋ค\n const able = this.draft ? canMirror(this.draft, this.parts, this.selected, axis) : false\n return html`\n <button\n ?disabled=${!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.ask('mirror', axis)}\n >\n <md-icon>${axis === 'x' ? 'flip' : 'flip_camera_android'}</md-icon>\n </button>\n `\n })}\n <button\n aria-label=${i18next.t('figure.button.snap')}\n title=${i18next.t('figure.text.snap-explained')}\n @click=${() => this.ask('snap', 'x')}\n >\n <md-icon>grid_on</md-icon>\n </button>\n </div>\n ${this.helpHint('figure.text.tools-explained')}\n </div>\n </section>\n `\n }\n\n /** ๋ถํ ์์ ๋ชจ์๋ฆฌ ๊ตด๋ฆผ โ ํด๋นํ๋ ๋ํ์๋ง ๋ธ๋ค. */\n private renderShape(part: FigurePart) {\n const segmented = SEGMENTED_PRIMITIVES.includes(part.primitive)\n const extruded = EXTRUDE_PRIMITIVES.includes(part.primitive)\n if (!segmented && !extruded) return nothing\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.shape-detail')}</h3>\n ${segmented ? this.renderSegments(part) : nothing}\n ${segmented ? this.renderKeepRound(part) : nothing}\n ${extruded ? this.renderExtruded(part) : nothing}\n </section>\n `\n }\n\n /**\n * ๋ฏผ ๋จ๋ฉด โ ๋ชจ์๋ฆฌ์ **์์ ํ๋ ๋๊ป.**\n *\n * ๋ฒฝ ๋๊ป๋ฅผ 0 ์ผ๋ก ๋๋ฉด ํต์ง๋ค. 0 ๋ณด๋ค ํฌ๋ฉด ๊ทธ๋งํผ ์์ผ๋ก ๋ค์ด์จ ํ
๊ฐ ์๊ธฐ๊ณ , ๊ทธ๊ฒ์ด\n * ํธ๋ ์ด ยท ํ ํธ ยท ํต ยท ์ผ์ด์ค๊ฐ ๋๋ ์๋ฆฌ๋ค. ๋ฐ๋ฅ์ ๋น์ ๋๋ฉด ๋ฒฝ๊ณผ ๊ฐ๊ณ , 0 ์ผ๋ก ๋๋ฉด\n * ์์๋๊ฐ ๋ค ๋ซ๋ฆฐ ํ
๋๋ฆฌ๊ฐ ๋๋ค.\n */\n private renderExtruded(part: FigurePart) {\n const hollow = part.shape?.hollow\n const wall = hollow?.wall ?? 0\n\n const reshape = (over: Record<string, unknown>) =>\n this.put({ shape: { ...(part.shape ?? {}), ...over } })\n\n return html`\n <div inline-field>\n <label>${i18next.t('figure.label.corner-round')}</label>\n ${this.number('', part.shape?.round ?? 0, value => reshape({ round: value }))}\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.hollow-wall')}</label>\n ${this.number('', wall, value =>\n reshape({ hollow: value > 0 ? { ...(hollow ?? {}), wall: value } : undefined })\n )}\n </div>\n ${wall > 0\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.hollow-floor')}</label>\n ${this.number('', hollow?.floor ?? wall, value => reshape({ hollow: { ...hollow, wall, floor: value } }))}\n </div>\n `\n : nothing}\n `\n }\n\n /**\n * ๋ถํ ์ โ ๋ชจ์๊ณผ ๋ฌด๊ฒ๋ฅผ ํจ๊ป ๊ณ ๋ฅธ๋ค.\n *\n * ์ผ๊ฐํ ์๋ ํ๋ฉด์ด ์
ํ์ง ์๋๋ค. `trianglesOf` ์ ๊ทธ ๋ถํ ์๋ฅผ ๊ฐ์ง ๋ถํ์ ์ฃผ๊ณ \n * ๋ฌผ์ด๋ณธ๋ค โ ํ๋ฉด์ด ์ ๋๋ฆ์ ๊ณต์์ ๋ค๋ฉด figure-model ์ด ๊ท์น์ ๋ฐ๊ฟ๋ ํ๋ฉด๋ง\n * ์ ๋ต์ ๊ณ์ ๋ธ๋ค.\n */\n /**\n * ์ํต์ ์ํต์ผ๋ก ๋๊น โ **๊ณ ๋ฅด๋ ๊ฐ์ด๊ณ , ๊ฐ์ ์น๋ฅธ๋ค.**\n *\n * ์ธ์คํด์ค๊ฐ ์ถ๋ง๋ค ๋ค๋ฅธ ๋ฐฐ์จ์ ๋ฐ์ผ๋ฉด ์๊ธฐ๋ฅ์ด ํ์ ๊ธฐ๋ฅ์ด ๋๋ค. ์งํค๋ ค๋ฉด ์ ๋ณํ์ด\n * ์์ด์ผ ํ๊ณ , ํฉ์น ํ์์ ๋ณํ์ ํ๋๋ง ๋ฐ์ผ๋ฏ๋ก ์งํค๋ ๊ณก๋ฉด ๋ถํ ํ๋๊ฐ draw call\n * ํ๋๋ค. ์ ์์๊ฐ ๊ทธ ๋๊ฐ๋ฅผ ๋ชจ๋ฅด๊ณ ๊ณ ๋ฅด๋ฉด ์ ๋๋ฏ๋ก ๊ทธ ์๋ฆฌ์ ์ ๋๋ค.\n */\n private renderKeepRound(part: FigurePart) {\n const on = part.keepRound !== false\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.keep-round')}</label>\n <div choices>\n <button choice ?on=${on} @click=${() => this.put({ keepRound: undefined })}>\n <b>${i18next.t('figure.text.keep-round-on')}</b>\n <small>${i18next.t('figure.text.keep-round-cost')}</small>\n </button>\n <button choice ?on=${!on} @click=${() => this.put({ keepRound: false })}>\n <b>${i18next.t('figure.text.keep-round-off')}</b>\n <small>${i18next.t('figure.text.keep-round-merged')}</small>\n </button>\n </div>\n </div>\n `\n }\n\n private renderSegments(part: FigurePart) {\n const current = part.segments ?? SEGMENT_PRESETS[1]\n const common = SEGMENT_PRESETS.slice(0, 4)\n const advanced = SEGMENT_PRESETS.slice(4)\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.segments')}</label>\n <div segments>\n ${common.map(preset => {\n const triangles = trianglesOf({ ...part, segments: preset })\n return html`\n <button seg ?on=${current === preset} @click=${() => this.put({ segments: preset })}>\n ${this.silhouette(preset)}\n <b>${preset}</b>\n <small>${i18next.t('figure.text.n-triangles', { count: triangles })}</small>\n </button>\n `\n })}\n </div>\n\n <details free ?open=${advanced.includes(current)}>\n <summary>${i18next.t('figure.text.more-segment-options')}</summary>\n <div presets>\n ${advanced.map(preset => html`\n <button ?on=${current === preset} @click=${() => this.put({ segments: preset })}>${preset}</button>\n `)}\n </div>\n </details>\n </div>\n `\n }\n\n /**\n * ๋ถํ ์์ ์ค๋ฃจ์ฃ.\n *\n * ๊ณก๋ฉด ํ๋ฆฌ๋ฏธํฐ๋ธ๋ฅผ ์์์ ๋ณธ ์ค๊ณฝ์ด ์ ํํ ์ n๊ฐํ์ด๋ค โ ์๊ธฐ๋ฅ์ ๋จ๋ฉด๋, ๊ตฌ์\n * ์ ๋๋. ๊ทธ๋ฆผ์ ์ง์ด๋ด๋ ๊ฒ์ด ์๋๋ผ ์ค์ ๋ก ๋ง๋ค์ด์ง๋ ๋ชจ์์ด๋ค.\n */\n private silhouette(segments: number) {\n const points: string[] = []\n for (let i = 0; i < segments; i++) {\n // ๊ผญ์ง์ ํ๋๊ฐ ์๋ก ์ค๊ฒ -90๋์์ ์์ํ๋ค\n const angle = -Math.PI / 2 + (i * 2 * Math.PI) / segments\n points.push(`${(16 + 13 * Math.cos(angle)).toFixed(2)},${(16 + 13 * Math.sin(angle)).toFixed(2)}`)\n }\n\n return svg`\n <svg viewBox=\"0 0 32 32\" aria-hidden=\"true\">\n <polygon points=${points.join(' ')}></polygon>\n </svg>\n `\n }\n\n /** ๊ฒฌ๋ณธ ํ ์ค. ๋ฌด๋ฆฌ๋ง๋ค ๋ถ๋ฅธ๋ค. */\n private palettePurpose(token?: string) {\n const purposes: Record<string, string> = {\n 'palette.primary': 'primary',\n 'palette.accent': 'accent',\n 'palette.neutral': 'neutral',\n 'palette.dark': 'dark',\n 'palette.light': 'light',\n 'palette.surface': 'surface',\n 'palette.status-danger': 'danger',\n 'palette.status-warning': 'warning',\n 'palette.status-info': 'info',\n 'palette.status-success': 'success'\n }\n\n return i18next.t(`figure.label.palette-purpose-${purposes[token ?? ''] ?? 'registered'}`)\n }\n\n private swatches(entries: [string, string][], chosen?: string) {\n return entries.map(\n ([token, color]) => {\n const purpose = this.palettePurpose(token)\n return html`\n <button\n swatch\n ?on=${token === chosen}\n aria-label=${purpose}\n title=${purpose}\n style=\"--swatch:${color}\"\n @click=${() => this.putMaterial({ token })}\n ></button>\n `\n }\n )\n }\n\n private renderMaterial(part: FigurePart) {\n const material = part.material ?? {}\n const palette = activePalette() as Record<string, string>\n\n /*\n ๋ ๋ฌด๋ฆฌ๋ก ๋๋ ๋ณด์ธ๋ค โ **์น ํ ์**๊ณผ **์ผ์ง ์**.\n\n `palette.status-*` ๋ ๋จํ ยท ํ์๋ฑ์ ์ฐ๋ผ๊ณ ์๋ ์์ด๋ค. ํ ์ค์ ์์ด ๋๋ฉด\n `accent`(์ฃผํฉ)์ `status-warning`(์ฃผํฉ)์ด ๋๋ํ ๋์ฌ ๋ฌด์์ด ๋ฌด์์ธ์ง ์ ์\n ์๋ค. ๊ฐ์ ๋นํ์ด ๋ฒ๋ฆฌ๋ ๋์ **๊ณ ๋ฅด๋ ์๋ฆฌ์์ ๊ฒฝ๊ณ๋ฅผ ๊ธ๋๋ค.**\n */\n const entries = Object.entries(palette)\n const painted = entries.filter(([token]) => !token.startsWith('palette.status-'))\n const lit = entries.filter(([token]) => token.startsWith('palette.status-'))\n\n /** ์์ฒด๋ฐ๊ด. ์์ผ๋ฉด ์ ๋น๋๋ ๋ถํ์ด๋ค. */\n const glow = material.emissive\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.part-material')}</h3>\n\n <div field>\n <label>${i18next.t('figure.label.palette-role')}</label>\n <div swatches>\n ${this.swatches(painted, material.token)}\n </div>\n ${lit.length\n ? html`\n <label group>${i18next.t('figure.label.status-colors')}</label>\n <div swatches>\n ${this.swatches(lit, material.token)}\n </div>\n `\n : ''}\n <div palette-meaning>\n <b>${material.token ? this.palettePurpose(material.token) : i18next.t('figure.label.no-color-chosen')}</b>\n <small>${i18next.t('figure.text.palette-purpose-explained')}</small>\n </div>\n </div>\n\n <div field>\n <label>${i18next.t('figure.label.preset')}</label>\n <select\n @change=${(e: Event) => {\n const value = (e.target as HTMLSelectElement).value\n this.putMaterial({ preset: (value || undefined) as MaterialPreset | undefined })\n }}\n >\n <option value=\"\" ?selected=${!material.preset}>${i18next.t('figure.label.none')}</option>\n ${MATERIAL_PRESETS.map(\n preset => html`\n <option value=${preset} ?selected=${preset === material.preset}>\n ${i18next.t('figure.label.preset-' + preset)}\n </option>\n `\n )}\n </select>\n </div>\n\n <!-- ๊ฐ์ด ์์ผ๋ฉด ๊ฐ์ง๊ฒ ๊ทธ๋ฆฐ๋ค โ ํ์์ด ๊ทธ๋ ๊ฒ ๋ชป ๋ฐ์๋ค. ์ฒดํฌ์์๋ ๊ทธ๋๋ก ๋ณด์ธ๋ค -->\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${material.flatShading ?? true}\n @change=${(e: Event) => this.putMaterial({ flatShading: (e.target as HTMLInputElement).checked })}\n />\n ${i18next.t('figure.label.flat-shading')}\n </label>\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${!!material.transparent}\n @change=${(e: Event) => this.putMaterial({ transparent: (e.target as HTMLInputElement).checked })}\n />\n ${i18next.t('figure.label.transparent')}\n </label>\n\n <div field>\n <label>${i18next.t('figure.label.emissive')}${this.help('figure.text.emissive-explained')}</label>\n\n <div slider>\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n .value=${String(glow?.intensity ?? 0)}\n @input=${(e: Event) => this.putEmissive(Number((e.target as HTMLInputElement).value))}\n />\n <output>${(glow?.intensity ?? 0).toFixed(2)}</output>\n </div>\n </div>\n\n ${glow\n ? html`\n <div field>\n <label>${i18next.t('figure.label.emissive-color')}</label>\n <div swatches>\n <button\n swatch\n same\n ?on=${!glow.token}\n title=${i18next.t('figure.label.same-as-off')}\n style=\"--swatch:${(material.token && palette[material.token]) || palette['palette.neutral']}\"\n @click=${() => this.putMaterial({ emissive: { ...glow, token: undefined } })}\n ></button>\n ${lit.map(\n ([token, color]) => html`\n <button\n swatch\n ?on=${token === glow.token}\n title=${token}\n style=\"--swatch:${color}\"\n @click=${() => this.putMaterial({ emissive: { ...glow, token } })}\n ></button>\n `\n )}\n </div>\n <span token>${glow.token ?? i18next.t('figure.label.same-as-off')}</span>\n </div>\n\n <label toggle>\n <input\n type=\"checkbox\"\n .checked=${!!glow.on}\n @change=${(e: Event) =>\n this.putMaterial({ emissive: { ...glow, on: (e.target as HTMLInputElement).checked } })}\n />\n ${i18next.t('figure.label.on-by-default')}\n </label>\n ${this.help('figure.text.on-by-default-explained')}\n `\n : ''}\n\n </section>\n `\n }\n\n /**\n * ์ธ์คํด์ค ํฌ๊ธฐ๊ฐ ๋ฐ๋ ๋ ์ด ๋ถํ์ด ์ด๋ป๊ฒ ๋ณํ๋.\n *\n * ## ๋์ด๋๋ ์ถ์ ์์ง ๋ชป ๋ณด์ฌ ์ค๋ค\n *\n * `stretch` ๋ ํ์์ ์ถ์ ์ ๋ ์๋ฆฌ๊ฐ ์์ด์ ๊ทธ๋ฆฌ๋ ์ชฝ์ด **๊ฐ์ฅ ๊ธธ๊ฒ ๋ป์ ์ถ**์ผ๋ก\n * ์ ํ๋ค. ๊ทธ ๋ต์ ํ๋ฉด์ ์ ์ด ์ฃผ๋ ค๋ฉด ๊ท์น์ ๊ฐ์ง ์ชฝ์ ๋ฌผ์ด์ผ ํ๋๋ฐ, ๊ทธ ํจ์\n * (`stretchAxisOf` ยท `stretchAxis`)๊ฐ ์์ง ๋ฐฐํฌ๋ ํ์ ์๋ค.\n *\n * ํ๋ฉด์ด ์ ๋๋ฆ๋๋ก ๊ณ์ฐํ์ง ์๋๋ค. ๊ท์น์ด ๋ ๋ฒ์ด ๋๋ฉด ๋ณด์ด๋ ์ถ๊ณผ ์ค์ ๋ก ๋์ด๋๋\n * ์ถ์ด ๊ฐ๋ฆฌ๊ณ , ๊ทธ ์ด๊ธ๋จ์ ํ๋ฉด์ ๋ฏฟ๊ฒ ๋ง๋ ๋ค์์ ๋๋ฌ๋๋ค. ๋ฐฐํฌ๋๋ฉด ์๋๋ค.\n *\n * ## ๊ฐ์ด ์๋ ๊ฒ์ ๋ฐํ๋ค\n *\n * `scale` ์ด ์๋ ๋ถํ์ ํฉ์ณ ๊ทธ๋ฆด ์ ์์ด draw call ์ ํ๋ ๋ ์ด๋ค. ๊ทธ ๋น์ฉ์ด\n * ์ฑ์๋์ ๋ฌถ์ ์์ ๊ทธ๋๋ก ์กํ๋ค. ๊ณ ๋ฅด๋ ์๋ฆฌ์์ ๋ฏธ๋ฆฌ ๋งํด ์ค๋ค.\n */\n private renderBehaviour(part: FigurePart) {\n const sizing = part.sizing ?? 'scale'\n const repeat = part.repeat ?? { axis: 'x' as Axis, pitch: 0 }\n\n return html`\n <section>\n <h3>${i18next.t('figure.label.sizing-rule')}${this.help('figure.text.sizing-' + sizing + '-explained')}</h3>\n <div sizing-choices>\n ${SIZING_RULES.map(\n rule => html`\n <button sizing-choice ?on=${rule === sizing} @click=${() => this.put({ sizing: rule })}>\n <b>${i18next.t('figure.label.sizing-' + rule)}</b>\n <small>${i18next.t('figure.text.sizing-' + rule + '-explained')}</small>\n </button>\n `\n )}\n </div>\n ${sizing === 'scale'\n ? nothing\n : html`<p cost>${i18next.t('figure.text.sizing-costs-one-draw-call')}</p>`}\n\n ${this.renderAnchors(part)}\n\n ${sizing === 'repeat'\n ? html`\n <div inline-field>\n <label>${i18next.t('figure.label.repeat-axis')}</label>\n <select\n @change=${(e: Event) =>\n this.put({ repeat: { ...repeat, axis: (e.target as HTMLSelectElement).value as Axis } })}\n >\n ${(['x', 'y', 'z'] as const).map(\n axis => html`<option value=${axis} ?selected=${axis === repeat.axis}>${axis}</option>`\n )}\n </select>\n </div>\n <div inline-field>\n <label>${i18next.t('figure.label.repeat-pitch')}${this.helpButton('figure.text.repeat-pitch-explained')}</label>\n ${this.number('', repeat.pitch, value => this.put({ repeat: { ...repeat, pitch: value } }), 1)}\n ${this.helpHint('figure.text.repeat-pitch-explained')}\n </div>\n ${this.renderRepeatCount(part)}\n `\n : nothing}\n </section>\n `\n }\n\n /**\n * โโ ๋ช ๊ฐ๊ฐ ๋๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ์ ์ ํ๋ฉด์ ์ถ๊ณผ ํผ์น๋ง ๋ฐ๊ณ ์์๋ค. ํ์์ด ๊ฐ์ง ๋ฐ๋ณต ์ค์ ์ด ๊ทธ ๋๋ฟ์ด๋ฏ๋ก ํธ์งํ ๊ฒ์\n * ๋ค ์์๋๋ฐ, **๊ฒฐ๊ณผ์ธ ๊ฐ์๋ฅผ ์ด๋์๋ ํ์ํ์ง ์์๋ค.** ํผ์น 300 ์ ์ ์ ์ ์์๊ฐ ๋ช ๊ฐ๊ฐ\n * ๋๋์ง ์๋ ค๋ฉด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์ธ์ด์ผ ํ๋ค.\n *\n * ๊ฐ์๋ ๊ทธ๋ฆฌ๋ ์ชฝ์ด ์ฐ๋ `repeatPlan` ์ ๊ทธ๋๋ก ๋ถ๋ฌ ์ป๋๋ค. ์ฌ๊ธฐ์ ๋ค์ ๊ณ์ฐํ๋ฉด ํ๋ฉด์ด\n * ๋งํ๋ ๊ฐ์์ ์ค์ ๋ก ๊ทธ๋ ค์ง๋ ๊ฐ์๊ฐ ๋ฌ๋ผ์ง๋ค.\n *\n * ## ๋ ๊ฐ์ง ๋ฐ๋ณต์ด ์๋ค\n *\n * ์ปจ๋ฒ ์ด์ด์ ๋กค๋ฌ๋ ๊ธธ์ด์ง๋ฉด **๊ฐ์๊ฐ ๋๊ณ ** ํ ์นธ ๊ฐ๊ฒฉ์ ๊ทธ๋๋ก๋ค. ์
ํธ๋ ์ด์ ์
์ ์ปค์ง๋ฉด\n * **์
์ด ์ปค์ง๊ณ ** ๊ฐ์๋ ๊ทธ๋๋ก๋ค โ ๋ช ์
์ง๋ฆฌ ํธ๋ ์ด๋๋ ํ๋ฉด ํฌ๊ธฐ์ ๋ฌด๊ดํ๋ค. ๊ทธ ๊ฐ๋ฆผ์\n * ์ด ์ถ์ anchor ๊ฐ ์ ํ๋๋ฐ ํ๋ฉด์๋ ๊ทธ ๋ง์ด ์์๋ค. ๊ทธ๋์ ์ด๋ ์ชฝ์ธ์ง ํจ๊ป ์ ๋๋ค.\n */\n private renderRepeatCount(part: FigurePart) {\n const draft = this.draft\n if (!draft) return nothing\n\n const base = { x: draft.width, y: draft.depth, z: draft.height }\n const plan = repeatPlanOfPart(part, { x: 1, y: 1, z: 1 }, base)\n if (!plan) return nothing\n\n const grows = anchorOfPart(part, base, plan.axis) !== 'scale'\n\n return html`\n <div field>\n <label>${i18next.t('figure.label.repeat-count')}</label>\n <p quiet>\n ${i18next.t('figure.text.repeat-count-now', { count: plan.count })}\n ${plan.count >= REPEAT_LIMIT\n ? html`<br />${i18next.t('figure.text.repeat-count-capped', { limit: REPEAT_LIMIT })}`\n : ''}\n <br />${i18next.t(grows ? 'figure.text.repeat-grows-with-instance' : 'figure.text.repeat-keeps-count')}\n </p>\n </div>\n `\n }\n\n /**\n * โโ ์ด๋ ๋ฉด์ ๋ถ์ก๋ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * **์ด ์๋ฆฌ๊ฐ ์์๋ค.** ํ์์ ์ถ๋ง๋ค `anchor` ๋ฅผ ์ง๊ณ ๋ค๋๊ณ (`figure-source.ts` ๊ฐ ์๋ณต์ํจ๋ค),\n * ๋ฐํ ๊ฒ์ดํธ๋ ใvalve-wheel ์ anchor.z ๋ฅผ max ๋ก ๋๋ผใ๊ณ ์ฌ์ ๊น์ง ๋งํ๋๋ฐ, ์ ์๋ฉด์๋ ๊ทธ\n * ๊ฐ์ ๋ฐ๊ฟ ์๋ฆฌ๊ฐ ์์๋ค โ ๊ณ ์น๋ผ๋ ๋ง๋ง ์๊ณ ๊ณ ์น ๋ฌธ์ด ์์๋ค.\n *\n * ## ใ์๋ใ์ด ๊ธฐ๋ณธ์ด๋ค\n *\n * ํ์์์ `anchor` ๋ ์ ์ง ์์๋ ๋๋ค. ์ ์ ์ผ๋ฉด **๊ฐ๊น์ด ๋ฉด**์ ๋ถ์ก๊ณ , ํ๋ณธ ์ด๋ท ์ค ์ด๋\n * ๊ฒ๋ ์ด ๊ฐ์ ์ ์ง ์๊ณ ์ ๋๋ก ์ ๋ค. ๊ทธ๋์ ์ถ๋ง๋ค ์ฒซ ํญ๋ชฉ์ด ใ์๋ใ์ด๊ณ , ์ง๊ธ ์๋์ด ๋ฌด์์ผ๋ก\n * ์ฝํ๋์ง๋ฅผ **ํจ๊ป ๋ณด์ฌ ์ค๋ค** โ ๊ทธ๊ฒ์ ๋ชจ๋ฅด๋ฉด ๋ฌด์์ ๋ฐ๊พธ๋์ง ๋ชจ๋ฅธ ์ฑ ๊ณ ๋ฅด๊ฒ ๋๋ค.\n *\n * ์๋์ด ๋ฌด์์ธ์ง๋ ํ์์๊ฒ ๋ฌป๋๋ค(`anchorOfPart`). ์ฌ๊ธฐ์ ใ์ ์ ๋ฐ์ด๋ฉด maxใ๋ฅผ ๋ค์ ์ธ๋ฉด\n * ํ๋ฉด์ด ๋งํ๋ ๋ฉด๊ณผ ์ค์ ๋ก ๊ทธ๋ ค์ง๋ ๋ฉด์ด ๊ฐ๋ฆฐ๋ค.\n *\n * ## `scale` ์ธ ๋ถํ์๋ ๋ณด์ฌ ์ค๋ค\n *\n * ์ฒ์์๋ ๊ฐ์ท๋ค โ ํ์ ์ฃผ์์ ใ`sizing` ์ด `scale` ์ธ ๋ถํ์๋ ๋ป์ด ์๋คใ๊ณ ์ ํ ์์ด์๋ค.\n * **๊ทธ ๋ฌธ์ฅ์ ๊ธฐ๋ณธ๊ฐ์ ๋ํ ๊ฒ์ด๋ค.** `anchorOf` ๋ ์ ํ ๊ฐ์ ๊ฐ์ฅ ๋จผ์ ๋ณด๊ณ (`if (said) return\n * said`), ๊ทธ ๋ค์์ผ `sizing` ์ ๋ณธ๋ค. ์ฆ `scale` ๋ถํ์๋ ๋ฉด์ ์ ์ผ๋ฉด ๊ทธ๊ฒ์ด ์ด๊ธด๋ค.\n *\n * ๊ฐ์ถฐ ๋๋ฉด ์ด๊ธ๋จ์ด ๋๋ค: ๋ฐํ ๊ฒ์ดํธ๊ฐ ๋ง๋ MIXER ์ `valve-wheel` ์ด `scale` ๋ถํ์ด๊ณ ,\n * ๊ฒ์ดํธ์ ์ฌ์ ๋ ใ๊ทธ ๋ถํ์ anchor.z ๋ฅผ max ๋ก ๋๋ผใ๋ค. ๊ณ ์น๋ผ๋ ์๋ฆฌ์ ๋ฌธ์ ๋ซ์ ๋ ์
์ด์๋ค.\n *\n * ๋์ `scale` ์ผ ๋๋ ์๋์ด ๋ฌด์์ธ์ง๊ฐ ใํจ๊ป ์ปค์ง๋คใ๋ก ๋ณด์ด๋ฏ๋ก, ์ ์์๊ฐ ๊ทธ๊ฒ์ ๋ฐ๊พธ๋\n * ๊ฒ์์ ์ ์ ์๋ค.\n */\n /**\n * โโ ๋์๋ง์ ์๋ฆฌ๋ฅผ ๋จน์ง ์๋๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n *\n * ์ค๋ช
๋ฌธ๋จ์ด ์ด ์ค ์์๊ณ ๊ทธ ์ค๋ค์ด ํจ๋ ๋์ด์ ์๋น ๋ถ๋ถ์ด์๋ค. ์์ฑ์ ์์ผ๋ก ๋ ๋์ด๋๋ค\n * (๋ฅ๋ ฅ ยท ํฌํธ ยท ์ ๋๋ฉ์ด์
ยท ๊ธฐ์ค์ ๋ณด) โ ๋ ๋ณด์ด๋ ์ค๋ช
์ ๊ทธ ์๋ฆฌ๋ฅผ ๋จผ์ ๋จน๋๋ค.\n *\n * ๊ทธ๋์ ๋ฌผ์ํ๋ก ์ ๋๋ค. **์ง์ฐ์ง ์๋๋ค** โ ๊ทธ ๋ฌธ์ฅ๋ค์ ใ์ด๊ฑธ ๊ณ ๋ฅด๋ฉด ๋ฌด์์ด ๋ฌ๋ผ์ง๋ใ๋ฅผ\n * ๋งํ๋ ๊ฒ์ด๊ณ , ์์ผ๋ฉด ๋ซํ ๋ชฉ๋ก์ ๊ณ ๋ฅผ ์ ์๋ค. ํ ๋ฒ ์ฝ์ผ๋ฉด ๋๋ ๊ฒ์ด๋ผ ์ ์ด ๋๋ ๊ฒ์ด ๋ง๋ค.\n *\n * ํธ ๊ฒ์ **๋ถํ์ ๋ฐ๊ฟ๋ ๊ทธ๋๋ก ๋๋ค**(`opened` ๋ ๋ถํ์ ๋ธ๋ฆฐ ์ํ๊ฐ ์๋๋ค). ๊ฐ์ ๊ฒ์\n * ๊ณ์ ๊ณ ์น๋ ์ฌ๋์ด ๋งค๋ฒ ๋ค์ ํด์ผ ํ๋ฉด ์ ์ ๊ฒ์ด ๋๋ ๋ฐฉํด๊ฐ ๋๋ค.\n */\n private help(key: string) {\n return html`${this.helpButton(key)}${this.helpHint(key)}`\n }\n\n private helpButton(key: string) {\n const shown = this.opened.has(key)\n\n return html`\n <button\n help\n aria-label=${i18next.t('figure.label.help')}\n aria-expanded=${shown ? 'true' : 'false'}\n @click=${() => {\n shown ? this.opened.delete(key) : this.opened.add(key)\n this.requestUpdate()\n }}\n >\n <md-icon>${shown ? 'help' : 'help_outline'}</md-icon>\n </button>\n `\n }\n\n private helpHint(key: string) {\n return this.opened.has(key) ? html`<p hint>${i18next.t(key)}</p>` : nothing\n }\n\n private renderAnchors(part: FigurePart) {\n const base = this.draft\n ? { x: this.draft.width, y: this.draft.height, z: this.draft.depth }\n : { x: 0, y: 0, z: 0 }\n const nameOf = (rule: string, axis: Axis) =>\n `${i18next.t(rule === 'min' || rule === 'max' ? `figure.label.anchor-${rule}-${axis}` : `figure.label.anchor-${rule}`)} (${rule})`\n const setAnchor = (axis: Axis, rule?: AnchorRule) => {\n const anchor = { ...(part.anchor ?? {}) }\n /* ใ์๋ใ์ ์นธ์ ์ง์ฐ๋ ๊ฒ์ด๋ค โ ๋น ๊ฐ์ ๋ฃ์ด ๋๋ฉด ํ์์ด ๊ทธ๊ฒ์ ๊ฐ์ผ๋ก ์ฝ๋๋ค. */\n if (rule) anchor[axis] = rule\n else delete anchor[axis]\n this.put({ anchor: Object.keys(anchor).length ? anchor : undefined })\n }\n const shortNameOf = (rule: AnchorRule | 'auto', axis: Axis) => {\n if (rule === 'auto') return i18next.t('figure.label.anchor-choice-auto')\n if (rule === 'min' || rule === 'max') return i18next.t(`figure.label.anchor-choice-${rule}-${axis}`)\n return i18next.t(`figure.label.anchor-choice-${rule}`)\n }\n\n return html`\n <div field>\n <!-- ์ ์ฅ ํค(anchor)๋ ๋จ๊ธฐ๋, ์ฌ์ฉ์๋ ์ถ๋ง๋ค ์ด๋ ๋ฉด์ ๊ธฐ์ค์ผ๋ก ์ผ๋์ง ์ฝ๋๋ค. -->\n <label>${i18next.t('figure.label.anchor')} (anchor)${this.help('figure.text.anchor-explained')}</label>\n <div anchor-rows>\n ${(['x', 'y', 'z'] as const).map(axis => {\n const said = part.anchor?.[axis]\n const auto = anchorOfPart(part, base, axis)\n\n /*\n **๋ฉด ์ด๋ฆ์ ์ถ๋ง๋ค ๋ค๋ฅด๋ค.** ์ฒ์์๋ min ์ ใ์๋ยท์ผ์ชฝยท๋ค ๋ฉดใ์ผ๋ก ํ ์ค์ ๋ค ์ ์๋๋ฐ,\n x ์ค์์ ใ์๋ใ์ ใ๋คใ๋ ๊ด๊ณ๊ฐ ์์ด ์ฝ๋ ์ฌ๋์ด ๋ฌด์์ ๊ณ ๋ฅด๋์ง ๋ชฐ๋๋ค.\n\n ๊ทธ๋ฆฌ๊ณ ์ด๋ฆ์จ๊ฐ ์๋๋ผ **๋์**์ผ๋ก ์ ๋๋ค โ ใ์ค๋ฅธ์ชฝ ๋ฉดใ์ด ์๋๋ผ ใ์ค๋ฅธ์ชฝ ๋ฉด์ ๋ถ์ด\n ์๋๋คใ๋ค. ใanchor.x ๋ฅผ max ๋ก ๋๋คใ๊ฐ ๋ฌด์จ ๋ป์ธ์ง ๋ชจ๋ฅด๊ฒ ๋ค๋ ๋ง์ด ๊ทธ ์๋ฆฌ์์ ๋์๋ค.\n */\n /*\n **๊ฐ ์ด๋ฆ์ ํจ๊ป ๋ณด์ธ๋ค.** ๋์๋ง ์ ์๋๋(ใ์ค๋ฅธ์ชฝ ๋ฉด์ ๋ถ์ด ์๋๋คยป) ๋ฐํ ๊ฒ์ดํธ๊ฐ\n ใanchor.x ๋ฅผ max ๋ก ๋๋ผใ๊ณ ๋งํ ๋ ํ๋ฉด์์ ๊ทธ ๋ฑ๋ง์ ์ฐพ์ ์ ์์๋ค โ ์ฌ์ฉ์๊ฐ\n ๊ทธ ์๋ฆฌ์์ ์ง์ ํ๋ค.\n\n `max` ๋ ์ ๋ณธ์ ์ ์ฅ๋๋ ์ด๋ฆ์ด๊ณ ์๋ฒ ์ค๋ฅยทํ์ ๋ฌธ์ยท๊ฒ์ดํธ ์ฌ์ ๊ฐ ๋ค ๊ทธ ์ด๋ฆ์ ์ด๋ค.\n ์จ๊ธฐ๋ฉด ์ ๋๋ ์ข
๋ฅ๋ค. ๋์์ด ๋จผ์ ๊ณ ์ด๋ฆ์ด ๊ดํธ๋ก ๋ฐ๋ผ์จ๋ค.\n */\n return html`\n <div anchor-row>\n <label>${axis.toUpperCase()}์ถ</label>\n <div anchor-options>\n ${(['auto', 'scale', 'min', 'center', 'max', 'span'] as const).map(rule => {\n const selected = rule === 'auto' ? !said : rule === said\n const fullName = rule === 'auto' ? i18next.t('figure.label.anchor-auto', { rule: nameOf(auto, axis) }) : nameOf(rule, axis)\n return html`\n <button\n anchor-choice\n ?on=${selected}\n aria-pressed=${selected ? 'true' : 'false'}\n title=${fullName}\n @click=${() => setAnchor(axis, rule === 'auto' ? undefined : rule)}\n >${shortNameOf(rule, axis)}</button>\n `\n })}\n </div>\n <details anchor-advanced>\n <summary>${i18next.t('figure.label.anchor-advanced')}</summary>\n <div anchor-options>\n ${ANCHOR_RULES.filter(rule => rule.startsWith('aspect-')).map(rule => html`\n <button\n anchor-choice\n ?on=${rule === said}\n aria-pressed=${rule === said ? 'true' : 'false'}\n title=${nameOf(rule, axis)}\n @click=${() => setAnchor(axis, rule)}\n >${i18next.t(`figure.label.anchor-choice-${rule}`)}</button>\n `)}\n </div>\n </details>\n </div>\n `\n })}\n </div>\n </div>\n `\n }\n\n /**\n * ์ซ์ ์นธ.\n *\n * ๋น ์นธ์ด๋ ๊ธ์๋ฅผ ๋ฃ์์ ๋ 0 ์ผ๋ก ๋ฐ๊ฟ์น์ง ์๋๋ค โ ์ ์์๊ฐ ์ง์ฐ๋ ์ค์ผ ์ ์๊ณ ,\n * ์กฐ์ฉํ 0 ์ด ๋๋ฉด ๋ถํ์ด ์ฌ๋ผ์ง ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค. ์ซ์๊ฐ ์๋๋ฉด ๊ทธ๋ฅ ์ ๋ฐ๋๋ค.\n */\n private number(label: string, value: number, set: (value: number) => void, min?: number) {\n return html`\n <div cell>\n ${label ? html`<span axis>${label}</span>` : nothing}\n <input\n type=\"number\"\n .value=${String(value)}\n min=${min ?? nothing}\n @change=${(e: Event) => {\n const raw = (e.target as HTMLInputElement).value\n const parsed = Number(raw)\n if (raw === '' || !Number.isFinite(parsed)) {\n // ๋๋๋ ค ๋๋๋ค. ์ ๊ทธ๋ฌ๋ฉด ํ๋ฉด๊ณผ ์ ๋ณธ์ด ๊ฐ๋ฆฐ๋ค.\n ;(e.target as HTMLInputElement).value = String(value)\n return\n }\n set(parsed)\n }}\n />\n </div>\n `\n }\n\n /**\n * ๋ํ์ ๋ฐ๊พผ๋ค.\n *\n * ๋ํ์ด ๋ฐ๋๋ฉด ๊ทธ ๋ํ์ ๋ป ์๋ ๊ฐ์ด ๋จ๋๋ค. ๋จ๊ฒจ ๋๋ฉด ๊ฒ์ฆ์ด ใ๋ฌด์๋จใ ์๋ฐ์\n * ๋ด๋ฏ๋ก ์ฌ๊ธฐ์ ๊ฑท๋๋ค.\n */\n private changePrimitive(primitive: PrimitiveKind) {\n this.change(part => {\n const next: FigurePart = { ...part, primitive }\n if (!SEGMENTED_PRIMITIVES.includes(primitive)) delete next.segments\n if (!EXTRUDE_PRIMITIVES.includes(primitive)) delete next.shape\n if (SEGMENTED_PRIMITIVES.includes(primitive) && next.segments === undefined) {\n next.segments = SEGMENT_PRESETS[1]\n }\n return next\n })\n }\n\n private put(patch: Partial<FigurePart>) {\n this.change(part => ({ ...part, ...patch }))\n }\n\n private putTransform(patch: Record<string, unknown>) {\n this.change(part => ({ ...part, transform: { ...part.transform, ...patch } as FigurePart['transform'] }))\n }\n\n /**\n * ๋ฐ๊ด ์ธ๊ธฐ๋ฅผ ๊ณ ์น๋ค. **0 ์ด๋ฉด ๋ธ๋ก์ ํต์งธ๋ก ์ง์ด๋ค.**\n *\n * ์ธ๊ธฐ 0 ์ธ ๋ฐ๊ด์ ๋จ๊ฒจ ๋๋ฉด ใ์ ๋น๋๋๋ฐ ๋จํ์ธ ๊ฒใ์ด ๋์ด, ์ฌ์ง ํค๊ฐ ๊ฐ๋ ค ๋ฌถ์์ด\n * ํ๋์ด ํ๋ ๋๋ค. 0 ์ ใ๋จํ๊ฐ ์๋๋คใ๋ก ์ฝ๋ ๊ฒ์ด ๋ง๋ค.\n *\n * `Number(value) || undefined` ๋ฅผ ์ฐ๋ฉด ์ ๋๋ค โ 0 ์ด falsy ๋ผ ๋ณ๊ฒฝ์ผ๋ก ์ ์กํ ์\n * ๊ฐ์ด ๊ทธ๋๋ก ๋จ๋๋ค. ์ค์ ๋ก ๋จํ๊ฐ ์ ๊บผ์ก๋ค.\n */\n private putEmissive(intensity: number) {\n // `chosen` ์ ์ฌ ๋ชจ๋ธ์ด๋ค. ํ์์ผ๋ก ์ฎ๊ธด ๊ฐ์ `partToFigure` ์ด ๋ง๋ ๊ฒ์ด๋ผ ์ฌ๊ธฐ์ ๋ค์ ๊บผ๋ธ๋ค.\n const glow = this.draft && this.chosen ? partToFigure(this.chosen, this.draft).material?.emissive : undefined\n\n this.putMaterial({ emissive: intensity > 0 ? { ...glow, intensity } : undefined })\n }\n\n private putMaterial(patch: Record<string, unknown>) {\n this.change(part => ({\n ...part,\n material: { ...(part.material ?? {}), ...patch } as FigurePart['material']\n }))\n }\n\n /**\n * ์์ ํ ๊ฒ์ ์ฌ ๋ชจ๋ธ๋ก ๋๋๋ ค ์๋ฆฐ๋ค.\n *\n * ์ฌ์ฉ์๋ XยทYยทZ ๋ก ์์ ํ๊ณ , ๋ชจ๋ธ๋ฌ ํ์ด์ง๋ ์ฌ ๋ชจ๋ธ์ ๊ฐ๋๋ค. ๊ทธ ์ฌ์ด๋ฅผ ์ฌ๊ธฐ์\n * ์๋๋ค โ ๋ณํํด์ ์์ ํ๊ณ ๋ค์ ๋๋๋ฆฐ๋ค. **์๋ณต ๋ณํ์ด ๋ฌด์์ค์ด๋ผ์ผ** ์์น ํ๋\n * ๊ณ ์ณค์ ๋ฟ์ธ๋ฐ ํ์ ๊ฐ์ด ์กฐ๊ธ์ฉ ๋ฐ๋ฆฌ๋ ์ผ์ด ์๋ค(`fold.test.ts` ๊ฐ ์ด๋ฅผ ํ์ธํ๋ค).\n */\n private change(edit: (part: FigurePart) => FigurePart) {\n const part = this.chosen\n const draft = this.draft\n if (!part || !draft) return\n\n this.emit(partFromFigure(edit(partToFigure(part, draft)), draft))\n }\n\n /** ์ ๋ฐ ๋๊ตฌ๋ฅผ ์ํจ๋ค. ์ ๋ณธ์ ์ ์๋ฉด์ด ๊ฐ๋๋ค โ ์ฌ๊ธฐ์๋ ์๋ฆฌ๊ธฐ๋ง ํ๋ค. */\n private ask(what: string, axis: string) {\n this.dispatchEvent(\n new CustomEvent('part-tool', {\n detail: { index: this.selected, tool: what, axis },\n bubbles: true,\n composed: true\n })\n )\n }\n\n private emit(part: PartModel) {\n this.dispatchEvent(\n new CustomEvent('update-part', { detail: { index: this.selected, part }, bubbles: true, composed: true })\n )\n }\n}\n"]}
|
|
@@ -24,7 +24,7 @@ declare const FigureParts_base: (new (...args: any[]) => LitElement) & typeof Li
|
|
|
24
24
|
export declare class FigureParts extends FigureParts_base {
|
|
25
25
|
static styles: import("lit").CSSResult[];
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* ์ด์ ์์ ๋ถํ๋ค. **์ฌ ๋ชจ๋ธ ๊ทธ๋๋ก ๋ฐ๋๋ค.**
|
|
28
28
|
*
|
|
29
29
|
* ์ด ํจ๋์ ์ด๋ฆ๊ณผ ๋ํ๋ง ์ฝ์ผ๋ฏ๋ก ์ด๋ ์ชฝ ํํ๋ก ๋ฐ์๋ ํ๋ฉด์ ๊ฐ๋ค. ๊ทธ๋๋ ์ฌ
|
|
30
30
|
* ๋ชจ๋ธ๋ก ๋ฐ๋ ๊ฒ์ ๋ชจ๋ธ๋ฌ ํ์ด์ง๊ฐ ๋ฐ์ดํฐ๋ฅผ **ํ ๋ฒ๋ง** ๊ฐ๊ฒ ํ๊ธฐ ์ํด์๋ค. ์ฌ๊ธฐ๋ง
|
|
@@ -36,7 +36,7 @@ let FigureParts = class FigureParts extends localize(i18next)(LitElement) {
|
|
|
36
36
|
constructor() {
|
|
37
37
|
super(...arguments);
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
39
|
+
* ์ด์ ์์ ๋ถํ๋ค. **์ฌ ๋ชจ๋ธ ๊ทธ๋๋ก ๋ฐ๋๋ค.**
|
|
40
40
|
*
|
|
41
41
|
* ์ด ํจ๋์ ์ด๋ฆ๊ณผ ๋ํ๋ง ์ฝ์ผ๋ฏ๋ก ์ด๋ ์ชฝ ํํ๋ก ๋ฐ์๋ ํ๋ฉด์ ๊ฐ๋ค. ๊ทธ๋๋ ์ฌ
|
|
42
42
|
* ๋ชจ๋ธ๋ก ๋ฐ๋ ๊ฒ์ ๋ชจ๋ธ๋ฌ ํ์ด์ง๊ฐ ๋ฐ์ดํฐ๋ฅผ **ํ ๋ฒ๋ง** ๊ฐ๊ฒ ํ๊ธฐ ์ํด์๋ค. ์ฌ๊ธฐ๋ง
|