@things-factory/figure-ui 10.1.28 โ 10.1.29
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/angle-dial.ts +70 -0
- package/client/modeller/figure-animations.ts +9 -9
- package/client/modeller/figure-canvas.ts +6 -3
- package/client/modeller/figure-inspector.ts +18 -3
- package/client/modeller/figure-preview.ts +55 -3
- package/client/modeller/figure-report.ts +11 -28
- package/client/modeller/figure-side.ts +1 -0
- package/client/modeller/joint-gizmo.ts +63 -1
- package/client/modeller/part-edits.ts +75 -9
- package/client/pages/figure-modeller-page.ts +20 -2
- package/client/types.ts +2 -0
- package/dist-client/modeller/angle-dial.d.ts +32 -0
- package/dist-client/modeller/angle-dial.js +41 -0
- package/dist-client/modeller/angle-dial.js.map +1 -0
- package/dist-client/modeller/figure-animations.d.ts +4 -4
- package/dist-client/modeller/figure-animations.js +9 -9
- package/dist-client/modeller/figure-animations.js.map +1 -1
- package/dist-client/modeller/figure-canvas.js +6 -3
- package/dist-client/modeller/figure-canvas.js.map +1 -1
- package/dist-client/modeller/figure-inspector.d.ts +11 -0
- package/dist-client/modeller/figure-inspector.js +20 -3
- package/dist-client/modeller/figure-inspector.js.map +1 -1
- package/dist-client/modeller/figure-preview.d.ts +11 -0
- package/dist-client/modeller/figure-preview.js +53 -3
- package/dist-client/modeller/figure-preview.js.map +1 -1
- package/dist-client/modeller/figure-report.d.ts +8 -4
- package/dist-client/modeller/figure-report.js +11 -31
- package/dist-client/modeller/figure-report.js.map +1 -1
- package/dist-client/modeller/figure-side.js +1 -0
- package/dist-client/modeller/figure-side.js.map +1 -1
- package/dist-client/modeller/joint-gizmo.d.ts +4 -1
- package/dist-client/modeller/joint-gizmo.js +54 -0
- package/dist-client/modeller/joint-gizmo.js.map +1 -1
- package/dist-client/modeller/part-edits.d.ts +29 -4
- package/dist-client/modeller/part-edits.js +61 -9
- package/dist-client/modeller/part-edits.js.map +1 -1
- package/dist-client/pages/figure-modeller-page.d.ts +7 -0
- package/dist-client/pages/figure-modeller-page.js +20 -2
- package/dist-client/pages/figure-modeller-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/types.d.ts +2 -0
- package/dist-client/types.js.map +1 -1
- package/package.json +5 -5
- package/test/angle-dial.test.ts +78 -0
- package/test/base-box.test.ts +11 -0
- package/test/expect.ts +2 -0
- package/test/i18n-prefix-guard.test.ts +17 -0
- package/test/joint-needle.test.ts +162 -0
- package/test/part-edits.test.ts +100 -0
- package/test/scene-budget.test.ts +29 -0
- package/translations/en.json +3 -7
- package/translations/ja.json +3 -7
- package/translations/ko.json +3 -7
- package/translations/ms.json +3 -7
- package/translations/zh.json +3 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-modeller-page.js","sourceRoot":"","sources":["../../client/pages/figure-modeller-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '../modeller/figure-side.js'\nimport '../modeller/figure-canvas.js'\nimport { captureThumbnail } from '../modeller/figure-thumbnail.js'\nimport '../modeller/figure-preview.js'\nimport { shouldStartNewFigure } from '../modeller/new-figure-entry.js'\nimport '../modeller/figure-parts.js'\nimport '../modeller/figure-inspector.js'\n\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { consumePendingFigureProposal } from '../modeller/figure-ai-target.js'\nimport { contractChanges, isPlaceholderType, placeholderType, TYPE_LENGTH, TYPE_PATTERN, validate } from '@hatiolab/figure-model'\nimport type { ContractChange, DetailLevel, FigureSource, PrimitiveKind } from '@hatiolab/figure-model'\n\nimport * as edits from '../modeller/part-edits.js'\nimport * as proposals from '../modeller/proposal.js'\nimport * as proposalSessions from '../modeller/proposal-session.js'\nimport type { ProposalSession } from '../modeller/proposal-session.js'\nimport { toFigureSource, fromFigureSource } from '../modeller/figure-source.js'\nimport type { FigureDraft, PartModel, PlaneAxis } from '../modeller/figure-source.js'\nimport { jointOf } from '../modeller/joint-edits.js'\nimport { poseAsDefaults } from '../modeller/pose-defaults.js'\nimport { gizmoPart } from '../modeller/joint-gizmo.js'\nimport { DEFAULT_VIEW } from '../modeller/figure-view.js'\nimport type { ViewSettings } from '../modeller/figure-view.js'\nimport { createFigure, fetchFigure, fetchFigureTypeNames, fetchReleasedSource, updateFigure } from '../graphql/index.js'\nimport type { Figure, FigureFinding, FigureGateFix, FigureProposal, ProposalFeedback } from '../types.js'\n\nconst FigureModellerPageBase = localize(i18next)(PageView) as typeof PageView\n\n/**\n * ์ด๋ ์นธ์ด ์ ํ ์๋. ์ผ์ชฝ์ ๋ถํ ๋ชฉ๋ก, ์ค๋ฅธ์ชฝ์ ์์ฑยทํ์ ยท์ค์ ์ด๋ค.\n *\n * ์ด๋ฆ์ fold ๋ฅผ ์ ์ด๋ค. ์ด ํ์ผ์์ ๊ทธ ๋ฑ๋ง์ ์ด๋ฏธ fold.ts ์ ๊ฒ์ด๋ค โ ํธ์ง ์ํ๋ฅผ\n * ์ ์ฅ ํ์์ผ๋ก ์ ๋๋ค๋ ๋ป์ด๋ผ ์นธ์ ์ ๋ ๊ฒ๊ณผ ์๋ฌด ์๊ด์ด ์๋ค. ํ ํ์ผ์์ ํ ๋ฑ๋ง์ด\n * ๋ ๊ฐ์ง๋ฅผ ๋ปํ๋ฉด ์ฝ๋ ์ฌ๋์ด ๋งค๋ฒ ์ด๋ ์ชฝ์ธ์ง ๊ฐ๋ ค์ผ ํ๋ค.\n */\ninterface Panes {\n left: boolean\n right: boolean\n}\n\n/**\n * ์ ์ด ๋ ๊ฒ์ **์ด ๋ธ๋ผ์ฐ์ ์๋ง** ๋จ๋๋ค.\n *\n * ์ ์ํ Figure ์ ์ค๋ฆฌ๋ ๊ฐ์ด ์๋๋ค. ํ๋ฉด์ ์ด๋ป๊ฒ ๋ฒ๋ ค ๋๊ณ ์ผํ๋๋๋ ์ฌ๋๋ง๋ค\n * ๋ค๋ฅด๊ณ , ๊ฐ์ Figure ๋ฅผ ๋ค๋ฅธ ์ฌ๋์ด ์ด์์ ๋ ๋ด ํ๋ฉด ๋ฐฐ์น๊ฐ ๋ฐ๋ผ๊ฐ๋ฉด ๊ณค๋ํ๋ค.\n * ํ๋ฉด ์ค์ (`figure-view`)์ ์ ์ฅํ์ง ์๋ ๊ฒ๊ณผ ๊ฐ์ ์ด์ ๋ค.\n *\n * ์ํฌ๋ฆฟ ์ฐฝ์ด๋ ์ฌ์ดํธ ๋ฐ์ดํฐ๋ฅผ ๋ง์ ๋ธ๋ผ์ฐ์ ์์๋ **์ฝ๋ ๊ฒ ์์ฒด๊ฐ ๋์ง๋ค.** ๊ทธ๋๋\n * ๋ ๋ค ํด์ง ์ฑ๋ก ์์ํ๋ค โ ์ ์๋ฉด์ด ์ ๋จ๋ ๊ฒ๋ณด๋ค ๋ซ๋ค.\n */\nconst PANES_KEY = 'figure-modeller.collapsed'\n\nfunction recallPanes(): Panes {\n try {\n const said = JSON.parse(localStorage.getItem(PANES_KEY) ?? 'null')\n return { left: said?.left === true, right: said?.right === true }\n } catch {\n return { left: false, right: false }\n }\n}\n\nfunction rememberPanes(panes: Panes): void {\n try {\n localStorage.setItem(PANES_KEY, JSON.stringify(panes))\n } catch {\n // ๋ชป ์ ์ด๋ ์ด๋ฒ ํ๋ฉด์ ๊ทธ๋๋ก ๋์ํ๋ค. ๋ค์์ ์ด ๋ ํด์ ธ ์์ ๋ฟ์ด๋ค.\n }\n}\n\n/**\n * ์๋ก ๋ง๋ Figure ์ ์์ ์ํ โ **๋น ์์ ํ๋๋ฟ์ด๋ค.**\n *\n * ์ ์๋ ๋ถํ(300 ์์)์ ํ๋ ๋์ ์ฃผ์๋ค. ํ์์ด ๋ถํ 0๊ฐ๋ฅผ ์ค๋ฅ๋ก ๋ณด๊ธฐ ๋๋ฌธ์ด๋ค\n * (`missing-parts` โ parts ๊ฐ ์๋ค). ๊ทธ๋์ ์๋ฌด๊ฒ๋ ์ ํ๋๋ฐ ๋ถ์ ํ์ ์ด ๋จ๋ ๊ฒ์ ํผํ๋ ค๊ณ \n * ์์๋ฅผ ๊น์๋ค.\n *\n * **๊ทธ๋ฐ๋ฐ ใ๋ฌด์กฐ๊ฑด ์์ใ๋ ๋๊ฐ ์ฒซ ๋์์ด ๊ทธ๊ฒ์ ์ง์ฐ๋ ์ผ์ด ๋๋ค** โ ์ปจ๋ฒ ์ด์ด๋ฅผ ๋ง๋ค ์ฌ๋๋,\n * ์๊ทธ๋ํ์๋ฅผ ๋ง๋ค ์ฌ๋๋ ์์๋ถํฐ ์น์ด๋ค. ๊ทธ๋์ ๋น์ด๋ค. ํ์์ ๊ทธ๋๋ก ๋๊ณ (๋ถํ ์๋ ๊ฒ์\n * ๋ฐํํ ์ ์๋ ๊ฒ์ด ๋ง๋ค) **ํ๋ฉด์ด ใ์์ง ์ ์ ์ ํจใ๊ณผ ใํ์์ ์ด๊นใ์ ๊ฐ๋ฅธ๋ค.**\n *\n * ๋น ํ๋ฉด์ด ๊ฐ๋ฅด์น๋ ์๋ฆฌ๋ค: ๋ถํ ๋ชฉ๋ก์ด ใ์์์ ๋ํ์ ๊ณจ๋ผ ์์ํ์ธ์ใ๋ฅผ ์ด๋ฏธ ๋งํ๊ณ ํ๋ ํธ๊ฐ\n * ๋ฐ๋ก ๊ทธ ์์ ์๋ค(`figure-parts`).\n */\nfunction startingModel(type: string): { draft: FigureDraft; parts: PartModel[] } {\n return {\n draft: { width: 300, height: 300, depth: 300, figureType: type, detailLevel: 'M' },\n parts: []\n }\n}\n\n/**\n * Figure ์ ์๋ฉด.\n *\n * ## ์ธ ์นธ์ด๋ค\n *\n * ์ผ์ชฝ ๋ํ ํ๋ ํธ ยท ๋ถํ ๋ชฉ๋ก ยท ์์ฑ\n * ๊ฐ์ด๋ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ โ `FigureInstance` ๋ฅผ ์ค์ ๋ก ์ธ์ด๋ค\n * ์ค๋ฅธ์ชฝ ํ๋จ โ ๋ ๋ ์๋ค\n *\n * ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ฌ ์์์ ์ค์ ๋ก ๋์ํ๋ ๊ฒ์ด ์ด ๋๊ตฌ์ ์ ์ ๋ค. **ํธ์งํ ๊ฒ์ด ๊ณง ์ค์ ๊ฒฐ๊ณผ๋ฌผ**์ด๋ผ์ผ\n * \"๋ชจ๋ธ๋ฌ์์๋ ๋๋๋ฐ ๋๋ฉด์์๋ ๋ค๋ฅด๋ค\"๊ฐ ์๊ธฐ์ง ์๋๋ค.\n *\n * ## ํธ์ง ๋ฐ์ดํฐ๋ ์ฌ ๋ชจ๋ธ ํ๋๋ฟ์ด๋ค\n *\n * ์ด ํ์ด์ง๊ฐ ๊ฐ๋ ๊ฒ์ ์ด์ ํ๋์ ๋ถํ ๋ชฉ๋ก โ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ ๊ทธ๋๋ก ์ธ์์ง๋ ์ฌ ๋ชจ๋ธ์ด๋ค.\n * ์ ์ฅ ํ์(`FigureSource`)์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ์ **๊ฒฝ๊ณ์์๋ง** ํ๋ค: ์ ์ฅํ ๋, ํ๋จํ ๋,\n * AI ํ๋ณด์ ๋น๊ตํ ๋. ๊ทธ ๋ณํ์ `figure-source.ts` ํ ๊ณณ์์๋ง ์ผ์ด๋๋ค.\n *\n * ํ๋ ํธ๋ ์์ฑ ํธ์ง๊ธฐ๋ ์ด ๋ฐ์ดํฐ๋ฅผ ์ง์ ์์ ํ์ง ์๋๋ค. ๋ฌด์์ ํ๊ฒ ๋ค๋ ๊ฒ๋ง ์๋ฆฌ๊ณ ,\n * ๋ฐ๊พธ๋ ๊ฒ์ ์ด ํ์ด์ง๋ค. ๋ ๊ณณ์์ ๊ณ ์น๋ฉด ์คํ ์ทจ์๋ ์ ์ฅ๋ ์ด๋ ์ชฝ์ด ๋ง๋์ง ์ ์\n * ์๊ฒ ๋๋ค.\n */\n/**\n * Whether this name could be released, by the format's own rules (`type-not-identifier`,\n * `type-is-placeholder`). Saving is not blocked, but the type cannot change after creation, so the\n * author has to hear it now to avoid a draft that can never be released.\n */\nfunction releasableType(type: string): boolean {\n return (\n !isPlaceholderType(type) &&\n TYPE_PATTERN.test(type) &&\n type.length >= TYPE_LENGTH.min &&\n type.length <= TYPE_LENGTH.max\n )\n}\n\n@customElement('figure-modeller-page')\nexport class FigureModellerPage extends FigureModellerPageBase {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background-color: var(--md-sys-color-surface);\n color: var(--md-sys-color-on-surface);\n /*\n ์ด ํ๋ฉด์ ๊ธ์ ํฌ๊ธฐ๋ฅผ ์ฌ๊ธฐ์ ์ ํ๋ค.\n\n ์ ์ ์ด ๋๋ฉด ๋ธ๋ผ์ฐ์ ๊ธฐ๋ณธ ํฌ๊ธฐ(16px)๋ฅผ ๋ฌผ๋ ค๋ฐ๋๋ค. ์๋ ํจ๋๋ค์ ์ ๋ถ 12px\n ์ธ์ ๋ฆฌ๋ผ ์ ๋ ์ค๋ง ์ปค ๋ณด์ด๊ณ , ๋ฒํผ์ด ํ๋ฉด ์ ์ฒด์ ๋ฐ๋ก ๋์๋ค.\n\n form ์์(input ยท button)๋ ๊ธ๊ผด์ ๋ฌผ๋ ค๋ฐ์ง ์์ผ๋ฏ๋ก ๊ฐ์ ์ ์ด์ผ ํ๋ค.\n */\n font-size: 0.76rem;\n }\n\n /* ์ธ ์นธ. 3D ๋ฅผ ๊ฐ์ฅ ํฌ๊ฒ ๋๋ค โ ์ด ๋๊ตฌ์ ์ฃผ์ด๋ ํ์์ด์ง ์์ฑํ๊ฐ ์๋๋ค */\n div[edits] {\n flex: 1;\n display: grid;\n grid-template-columns: 220px 1fr 320px;\n min-height: 0;\n overflow: hidden;\n }\n\n /*\n **์ธ ์นธ์ ์๋ฆฌ๋ฅผ ๋ชป ๋ฐ๋๋ค.**\n\n ์ด๊ฒ์ด ์์ผ๋ฉด ์ผ์ชฝ์ ์ ์์ ๋ ์ค๋ฅธ์ชฝ ์นธ์ด ๊ฐ์ด๋ฐ ์๋ฆฌ๋ก ๋ฐ๋ ค ๋ค์ด์ ์บ๋ฒ์ค๊ฐ\n ํต์งธ๋ก ์ฌ๋ผ์ง๋ค. display none ์ธ ํ์ ๋ ๊ทธ๋ฆฌ๋ ์๋ฆฌ๋ฅผ ์ฐจ์งํ์ง ์์ผ๋ฏ๋ก, ์ฒซ์งธ๊ฐ\n ๋น ์ง๋ฉด ๋๋จธ์ง๊ฐ ํ ์นธ์ฉ ๋น๊ฒจ์ง๋ค. ์ค๋ฅธ์ชฝ์ ๋ง์ง๋ง์ด๋ผ ๋น ์ ธ๋ ๋ฐ ๊ฒ์ด ์์ด์\n ๋ฉ์ฉกํ๋ค โ ํ์ชฝ๋ง ๊ณ ์ฅ ๋๋ ์ข
๋ฅ๋ค.\n\n ์ด ํ์ผ์ด ์ด๋ฏธ ํ ๋ฒ ์ ์ด ๋ ํจ์ ์ด๋ค. ์๋ div[lanes] ์ฃผ์์ ๊ฐ์ ๋ง์ด ์๋ค.\n */\n div[edits] > figure-parts {\n grid-column: 1;\n }\n div[edits] > div[middle] {\n grid-column: 2;\n }\n div[edits] > figure-side {\n grid-column: 3;\n }\n\n /*\n ์ ํ ์นธ์ **์๋ฆฌ๋ฅผ ์์ ์ ์ด๋ค.**\n\n ํญ๋ง 0 ์ผ๋ก ์ค์ด๋ฉด ์์ชฝ์ด ๋์ณ ๋์ ๊ฐ์ด๋ฐ๋ฅผ ๋ฎ๋๋ค. ๊ทธ๋ ๋ค๊ณ ๋ผ์ด ๋ด๋ฉด ์ค๋ฅธ์ชฝ\n ์นธ์ด ํผ์ณ ๋ ์ถ์ด ๊ทธ๋ฆผ ๊ฐ์ ์ํ๋ฅผ ์๋๋ค โ figure-side ๊ฐ ํญ์ ๊ฐ์ถ ๋๋ DOM ์๋\n ๋จ๊ธฐ๋ ๊ฒ๊ณผ ๊ฐ์ ์ด์ ๋ค. display none ์ด ๋์ ๋ค ์งํจ๋ค.\n\n ๊ฐ์ด๋ฐ๋ ์ ์ ๋๋ง๋ค ๋์ด๊ฐ ๋ฐ๋๋๋ฐ, ํธ์ง ์บ๋ฒ์ค์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ๊ฐ์ ResizeObserver\n ๋ฅผ ๊ฐ๊ณ ์์ด 3D ๊ฐ ์์์ ๋ฐ๋ผ์จ๋ค.\n */\n div[edits][collapse-left] {\n grid-template-columns: 0 1fr 320px;\n }\n div[edits][collapse-right] {\n grid-template-columns: 220px 1fr 0;\n }\n div[edits][collapse-left][collapse-right] {\n grid-template-columns: 0 1fr 0;\n }\n div[edits][collapse-left] > figure-parts,\n div[edits][collapse-right] > figure-side {\n display: none;\n }\n\n div[spacer] {\n flex: 1;\n }\n\n /*\n ์นธ์ ๋ฒกํฐ ์ ์๋๊ตฌ์ ๊ด๋ก๋๋ก ๋๋๋ค โ ์ผ์ชฝ์ ๋ฌด์์ด ์๋(๋ ์ด์ด), ์ค๋ฅธ์ชฝ์\n ๊ณ ๋ฅธ ๊ฒ์ ์์ฑ. ์ฐ๋ ์ฌ๋์ด ์ด๋ฏธ ์๋ ์๋ฆฌ๋ผ ๋ฐฐ์ธ ๊ฒ์ด ํ๋ ์ค์ด๋ ๋ค.\n ์ฐจ๋ณ์ฑ์ ๋ฐฐ์น๊ฐ ์๋๋ผ ๊ฐ์ด๋ฐ์ ๋ก์ฐํด๋ฆฌ 3D ์ ์์ผ๋ฏ๋ก, ๋ฐฐ์น๋ก ๋ฏ์ค๊ฒ ํ์ง\n ์๋๋ค.\n\n ์ค๋ฅธ์ชฝ์ figure-side ๊ฐ ์์ฑ๊ณผ ํ๋จ์ ํญ์ผ๋ก ๊ฒน์ณ ๋๋ค. ์์๋๋ก ๋๋๋ฉด ๋ ๋ค\n ์๋ ค์ ์์ฑ์ ์ฌ์ง๊น์ง, ํ๋จ์ ๋ฌด๊ฒ๊น์ง ๋ชป ๋ด๋ ค๊ฐ๋ค. ๊ฐ์๋ ํญ ์ด๋ฆํ์ ๋จ์\n ํ๋จ์ ๋ฎ์ด ๋์ด๋ ๋ณด์ธ๋ค.\n */\n figure-side {\n min-height: 0;\n }\n\n figure-canvas,\n figure-preview {\n min-width: 0;\n min-height: 0;\n }\n\n /*\n ํธ์ง ยท ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ ํ ๋ฐ ์กฐ์ ๋ .\n\n ๊ฐ์ด๋ฐ ์นธ ์์ ์๊ฒ ๋๋ค. ๋ฌด์์ ๋ณด๊ณ ์๋์ง๊ฐ ๋ ๋ณด์ฌ์ผ ํ๊ณ , ๋ ํ๋ฉด์ด ๊ฐ์\n ์๋ฆฌ๋ฅผ ์ฐ๋ฏ๋ก ์ด๋ ์ชฝ์ธ์ง ๋ชจ๋ฅด๋ฉด ํธ์ง์ด ์ ๋จน๋ ๊ฒ์ฒ๋ผ ์ฝํ๋ค.\n */\n div[modes] {\n display: flex;\n align-items: center;\n flex: none;\n gap: 2px;\n padding: 4px var(--spacing-medium, 8px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n div[modes] button[mode] {\n padding: 3px 12px;\n font: var(--label-font, inherit);\n font-size: 0.74rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n background: none;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n }\n div[modes] button[mode]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n div[modes] button[mode][on] {\n font-weight: 700;\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n }\n div[modes] div[separator] {\n width: 1px;\n height: 16px;\n margin: 0 4px;\n background-color: var(--md-sys-color-outline-variant);\n }\n div[modes] button[history] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n padding: 0;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n background: none;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n }\n div[modes] button[history]:hover:not([disabled]) {\n background-color: var(--md-sys-color-surface-container);\n color: var(--md-sys-color-on-surface);\n }\n div[modes] button[history][disabled] {\n opacity: 0.3;\n cursor: default;\n }\n div[modes] button[history] md-icon {\n --md-icon-size: 18px;\n }\n div[modes] button[collapse] {\n display: flex;\n align-items: center;\n flex: none;\n padding: 2px 3px;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n background: none;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n }\n div[modes] button[collapse]:hover {\n background-color: var(--md-sys-color-surface-container);\n }\n div[modes] button[collapse] md-icon {\n --md-icon-size: 18px;\n }\n div[modes] span[dirty] {\n align-self: center;\n margin-right: 6px;\n font: var(--label-font, inherit);\n font-size: 0.72rem;\n color: var(--md-sys-color-tertiary);\n }\n div[modes] span[save-failed] {\n align-self: center;\n max-width: 240px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin-right: 6px;\n padding: 3px 7px;\n font: var(--label-font, inherit);\n font-size: 0.7rem;\n color: var(--md-sys-color-on-error-container, var(--md-sys-color-on-surface));\n background-color: var(--md-sys-color-error-container);\n border-radius: 4px;\n }\n div[modes] button[save] {\n padding: 4px 14px;\n margin-right: 4px;\n font: var(--label-font, inherit);\n font-size: 0.74rem;\n font-weight: 600;\n color: var(--md-sys-color-on-primary, #fff);\n background-color: var(--md-sys-color-primary);\n border: none;\n border-radius: 6px;\n cursor: pointer;\n }\n div[modes] button[save]:hover:not([disabled]) {\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n }\n div[modes] button[save][disabled] {\n opacity: 0.35;\n cursor: default;\n }\n /*\n ํ๋ณด๊ฐ ์ค๋ฉด ๊ฐ์ด๋ฐ๋ฅผ ๋๋ก ๋๋๋ค.\n\n ์ซ์์ JSON ์ผ๋ก ์น๋์ ๋ฐ์ง ์๋๋ค โ ์ ์ํ ๊ฒ์ด ๊ณง ์ค๋ฌผ์ด๋ฏ๋ก **๋ ๋ค ์ธ์\n ๋๊ณ ** ๊ณ ๋ฅด๊ฒ ํ๋ค. ๋๋ํ ๋์ง ์์ผ๋ฉด ๋ฌด์์ด ๋ฌ๋ผ์ก๋์ง ๊ธฐ์ต์ผ๋ก ๊ฒฌ์ค์ผ ํ๋ค.\n */\n /*\n ์ธ๋ก๋ก ์์ ๋๋ค. ๊ทธ๋ฆฌ๋๋ก ๋์๋๋ ํ๋ณด๊ฐ ์์ ๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ฒซ ์ค(auto)์\n ๋จ์ด์ ธ **๋์ด๊ฐ 0** ์ด ๋๋ค โ 3D ๊ฐ ํต์งธ๋ก ์ฌ๋ผ์ก๋ค. display:none ์ธ ํ์ ๋\n ๊ทธ๋ฆฌ๋ ์๋ฆฌ๋ฅผ ์ฐจ์งํ์ง ์๋๋ค.\n */\n div[middle] {\n display: flex;\n flex-direction: column;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n }\n /*\n ๊ฐ์ด๋ฐ๋ฅผ ์ฑ์ด๋ค. ๋ ๋ค ์ ์ด์ผ ํ๋ค โ ํ๋๋ง ์ ์ผ๋ฉด ๊ฐ์ถฐ์ก๋ค ๋ํ๋ ์ชฝ์ด ๋์ด 0 ์ด\n ๋์ด ํ๋ฉด์ด ํ์๊ฒ ๋ฌ๋ค. ์ค์ ๋ก ๊ทธ๋ ๊ฒ ๋ฌ๋ค.\n */\n div[middle] > figure-canvas,\n div[middle] > figure-preview {\n flex: 1;\n }\n div[lanes] {\n flex: 1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1px;\n min-height: 0;\n background-color: var(--md-sys-color-outline-variant);\n }\n div[lane] {\n display: grid;\n grid-template-rows: auto 1fr;\n min-width: 0;\n min-height: 0;\n background-color: var(--md-sys-color-surface);\n }\n div[lane] h4 {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 5px var(--spacing-medium, 8px);\n font: var(--label-font, inherit);\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 div[lane][candidate] h4 {\n color: var(--md-sys-color-primary);\n }\n div[lane] h4 small {\n font-weight: 400;\n letter-spacing: 0;\n text-transform: none;\n }\n\n /* ๋ฐ๊ฑฐ๋ ๋ฒ๋ฆฐ๋ค. ๊ทธ ์ฌ์ด์ ๋ค๋ฅธ ๊ฒ์ ์๋ค */\n div[decide] {\n display: flex;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n background-color: var(--md-sys-color-primary-container);\n color: var(--md-sys-color-on-primary-container);\n font-size: 0.76rem;\n }\n div[decide] div[spacer] {\n flex: 1;\n }\n div[decide] button {\n padding: 5px 14px;\n font: var(--label-font, inherit);\n border-radius: 6px;\n cursor: pointer;\n }\n button[take] {\n color: var(--md-sys-color-on-primary, #fff);\n background-color: var(--md-sys-color-primary);\n border: none;\n }\n button[drop] {\n color: inherit;\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n }\n button[take][disabled] {\n opacity: 0.4;\n cursor: default;\n }\n\n /* AI์ ํ๊ฐ๋ ํ์ ๋ฌธ์ด ์๋๋ผ ์๋ฝ ์ ์ ์ฝ์ ๊ทผ๊ฑฐ๋ค. ์จ๊ธฐ์ง ์๊ณ ๋ณ๊ฒฝ ์นฉ ์์ ๋๋ค. */\n div[quality-review] {\n padding: 7px var(--spacing-large, 12px);\n background-color: var(--md-sys-color-primary-container);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n color: var(--md-sys-color-on-primary-container);\n font-size: 0.72rem;\n line-height: 1.45;\n }\n div[quality-review][review] {\n background-color: var(--md-sys-color-tertiary-container);\n color: var(--md-sys-color-on-tertiary-container);\n }\n div[quality-review] strong { display: block; font-size: 0.74rem; }\n div[quality-review] ul { margin: 4px 0 0; padding-left: 18px; }\n div[proposal-note] {\n padding: 6px var(--spacing-large, 12px) 8px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n background-color: var(--md-sys-color-surface-container-low);\n }\n div[proposal-note] label { display: block; font-size: 0.71rem; color: var(--md-sys-color-on-surface-variant); }\n div[proposal-note] input {\n box-sizing: border-box;\n width: 100%;\n margin-top: 4px;\n padding: 5px 7px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 5px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface);\n font: inherit;\n }\n\n /*\n ๋ฌด์์ ๋ฐ๊พธ์๋ ๊ฒ์ธ๊ฐ โ ์นฉ ํ๋๊ฐ ๋ณ๊ฒฝ ํ๋๋ค.\n\n ํต์งธ๋ก๋ง ๋ฐ๊ฒ ๋๋ฉด ใ๋ชธํต์ ์ข์๋ฐ ๋ชจํฐ ์๋ฆฌ๊ฐ ํ๋ ธ๋คใ์ ๋ตํ ์ ์๋ค. ๊ทธ๊ฒ\n ๊ฐ์ฅ ํํ ๋ฐ์์ด๋ค. ์ฒ์์๋ ์ ๋ถ ๊ณจ๋ผ ๋๋ค โ ํต์งธ๋ก ๋ฐ๋ ๊ฒ์ด ๋ณดํต์ ๊ธธ์ด๊ณ ,\n ๋นผ๊ณ ์ถ์ ๊ฒ๋ง ๋๋ฉด ๋๋ค.\n */\n div[changes] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n padding: 0 var(--spacing-large, 12px) var(--spacing-medium, 8px) var(--spacing-large, 12px);\n background-color: var(--md-sys-color-primary-container);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n button[change] {\n display: flex;\n align-items: center;\n gap: 3px;\n padding: 2px 9px 2px 5px;\n font: var(--label-font, inherit);\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface-variant, 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: 999em;\n cursor: pointer;\n }\n button[change][on] {\n color: var(--md-sys-color-on-primary, #fff);\n background-color: var(--md-sys-color-primary);\n border-color: transparent;\n }\n button[change] md-icon {\n --md-icon-size: 14px;\n }\n /* ์ ๊ณ ๋ฅธ ๊ฒ์ ๊ธ์์ ์ค์ ๊ทธ์ด ใ์ ๋ฐ๋๋คใ๋ฅผ ๋งํ๋ค */\n button[change]:not([on]) span[key] {\n text-decoration: line-through;\n }\n\n /* ๊ณ ๋ฅธ ์กฐํฉ์ด ํ์์ ์ด๊ธฐ๋ฉด ๋ฏธ๋ฆฌ ์๋ฆฐ๋ค. ์ ํํ ๋ค์ ๊ฑฐ์ ๋นํ๋ ๊ฒ๋ณด๋ค ๋ซ๋ค */\n /* ์ ์ฑ
์ ๋์ ๊ฒ์ ๋ง์ง ์๋๋ค โ ์๋ฆฌ๊ธฐ๋ง ํ๋ค. ์์ผ๋ก ๊ฐ๋ผ ๋๋ค */\n p[blocked][warn] {\n color: var(--md-sys-color-tertiary);\n }\n p[blocked] {\n margin: 0;\n padding: 0 var(--spacing-large, 12px) var(--spacing-medium, 8px) var(--spacing-large, 12px);\n background-color: var(--md-sys-color-primary-container);\n font-size: 0.72rem;\n line-height: 1.5;\n color: var(--md-sys-color-error);\n }\n .save-modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n }\n .save-modal-card {\n background: var(--md-sys-color-surface-container-high, #fff);\n color: var(--md-sys-color-on-surface, #1f1f1f);\n border-radius: 12px;\n padding: 24px;\n width: 380px;\n max-width: 90vw;\n box-shadow: 0 12px 36px rgba(0, 0, 0, 0.28);\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n .save-modal-title {\n margin: 0;\n font-size: 1.15rem;\n font-weight: 700;\n }\n .save-modal-desc {\n margin: 0;\n font-size: 0.8rem;\n color: var(--md-sys-color-on-surface-variant, #666);\n }\n .save-modal-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n .save-modal-field label {\n font-size: 0.76rem;\n font-weight: 600;\n color: var(--md-sys-color-on-surface-variant, #555);\n }\n .save-modal-field input {\n padding: 8px 10px;\n border: 1px solid var(--md-sys-color-outline, #ccc);\n border-radius: 6px;\n font-size: 0.88rem;\n background: var(--md-sys-color-surface, #fff);\n color: inherit;\n }\n .save-modal-error {\n color: var(--md-sys-color-error, #b00020);\n font-size: 0.78rem;\n }\n .save-modal-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 8px;\n }\n .save-modal-actions button {\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 0.82rem;\n cursor: pointer;\n border: none;\n }\n .save-modal-actions .btn-cancel {\n background: none;\n color: var(--md-sys-color-on-surface, inherit);\n }\n .save-modal-actions .btn-confirm {\n background: var(--md-sys-color-primary, #0066cc);\n color: var(--md-sys-color-on-primary, #fff);\n font-weight: 600;\n }\n .save-modal-actions .btn-confirm:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n `\n\n /** ํธ์ง ์ค์ธ Figure. ์๋ก ๋ง๋๋ ์ค์ด๋ฉด `id` ๊ฐ ์๋ค. */\n @state() private figure?: Figure\n /** ํธ์ง ๋ฐ์ดํฐ โ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ ๊ทธ๋๋ก ์ธ์์ง๋ ์ฌ ๋ชจ๋ธ์ด๋ค. */\n @state() private draft?: FigureDraft\n @state() private parts: PartModel[] = []\n @state() private selected = -1\n /*\n ์ ์ ํ๋ฉด์ **๋ณด๊ธฐ ์ค์ **. ์กฐ๋ช
ยท ๋ฐ๋ฅ ยท ์ถ ๊ฐ์ด๋ ๊ฐ์ ๊ฒ์ด๋ค.\n\n ์์ฐ์ด ์๋๋ผ ์์
๋๋ผ ์ ์ฅ๋์ง ์๋๋ค โ `toFigureSource` ๊ฐ ์ง์ด ๊ฐ์ง ์๋๋ค.\n ์์ธํ ๊ฒ์ `modeller/figure-view.ts` ๋ฅผ ๋ณด๋ผ.\n */\n @state() private view: ViewSettings = DEFAULT_VIEW\n /**\n * ๊ฐ์ด๋ฐ ์นธ์ด ๋ฌด์์ ๋ณด์ด๋.\n *\n * ํธ์ง ์บ๋ฒ์ค๋ ๋ ๊ธฐ์ค ํฌ๊ธฐ๋ค. ๊ทธ๋ฐ๋ฐ ์ด ํ์์ ๊ฐ ์ ๋ฐ์ ํฌ๊ธฐ๊ฐ ๋ฌ๋ผ์ก์ ๋ ์ด๋ป๊ฒ\n * ๋ฐ์ํ๋๊ฐ์ ์๋ค. ๊ทธ๊ฒ์ ๋ณผ ์๋ฆฌ๊ฐ ์์๋ค.\n */\n @state() private mode: 'edit' | 'preview' = 'edit'\n /**\n * ์ด๋ ์นธ์ด ์ ํ ์๋.\n *\n * ํต์งธ๋ก ๊ฐ์ ๋ผ์ด๋ค โ ์์ชฝ ๊ฐ๋ง ๋ฐ๊พธ๋ฉด Lit ์ด ๊ฐ์ ๊ฐ์ฒด๋ก ๋ณด๊ณ ๋ค์ ๊ทธ๋ฆฌ์ง ์๋๋ค.\n */\n @state() private collapsed: Panes = recallPanes()\n @state() private dirty = false\n @state() private saving = false\n @state() private violations: FigureFinding[] = []\n /**\n * ์ ์ฅ์ด ์ ์ ๋๋.\n *\n * **`save()` ์ `catch` ๊ฐ ์์๋ค.** `try โฆ finally` ๋ฟ์ด๋ผ ์๋ฒ๊ฐ ๊ฑฐ์ ํ๋ฉด(ํ์ ์๋ฐ ยท ํ์
์ด๋ฆ\n * ์ค๋ณต ยท ๊ถํ ์์ ยท ๋คํธ์ํฌ) ๋จ์ถ๋ง ๋ฉ์ถ๊ณ ํ๋ฉด์ **์๋ฌด ๋ง๋ ํ์ง ์์๋ค.** ์ ์์๋ ๋๋ ๋๋ฐ\n * ์๋ฌด ์ผ๋ ์ ๋ ๊ฒ์ผ๋ก ๋ณด๊ณ , ์ ์ฅ๋๋์ง ์๋์ง๋ ์ ์ ์์๋ค.\n *\n * ๋ฏธ์ ์ฅ ํ์(`dirty`)๋ ๊ทธ๋๋ก ๋จ์ผ๋ฏ๋ก ๋ฐ์ดํฐ๋ฅผ ์์ง๋ ์์๋ค. ์์ ๊ฒ์ **์ฌ์ **๋ค.\n */\n @state() private saveFailure = ''\n @state() private showSaveModal = false\n @state() private saveModalType = ''\n @state() private saveModalName = ''\n @state() private saveModalError = ''\n /** ์ ์ ๋ณด์กฐ ๋๋ ๋ฐํ ๊ฒ์ดํธ๊ฐ ์ฐ ํ๋ณด ๊ฒํ ์ธ์
. ๋ฐ๊ธฐ ์ ์๋ ์ ๋ณธ์ด ์๋๋ค. */\n @state() private proposalSession?: ProposalSession\n /** ์ธ๋ผ์ธ ์์ฒญ์ฐฝ๊ณผ AI ๋ํฌ๊ฐ ํจ๊ป ์ฐ๋ ํ์ฌ Figure์ ์ ํ๋ ์ธ์
ํผ๋๋ฐฑ. */\n @state() private proposalFeedback: ProposalFeedback[] = []\n\n @state() private undoStack: { draft?: FigureDraft; parts: PartModel[]; selected: number }[] = []\n @state() private redoStack: { draft?: FigureDraft; parts: PartModel[]; selected: number }[] = []\n @state() private sceneRevision = 0\n private lastCoalesceKey?: string\n private lastHistoryTime = 0\n\n /**\n * ์ ์ฅ ํ์์ผ๋ก ๋ณํํ ๊ฒ. ์ฌ ๋ชจ๋ธ์ด ๋ฐ๋ ๋๋ง ๋ค์ ๋ง๋ ๋ค.\n *\n * ์ ์ฅยทํ๋จยทAI ํ๋ณด ๋น๊ต๊ฐ ์ด๊ฒ์ ์ด๋ค. ๋ ๋๋งํ ๋๋ง๋ค ์๋ก ๋ง๋ค๋ฉด ํ๋จ ํจ๋์ด ๋งค๋ฒ\n * ๋ค์ ๊ณ์ฐํ๋ฏ๋ก, ๋ณํ์ `willUpdate` ์์ ํ ๋ฒ๋ง ํ๋ค.\n */\n private folded?: FigureSource\n\n /**\n * ์ง์ ๋ฐํํ์ ์ ๋ณธ. ํ ๋ฒ๋ ๋ฐํ ์ ํ ๋ํ์๋ ์๋ค.\n *\n * ๋ฐํ๋ ๋ํ์ ๊ณ ์น๋ ๋์ ใ์ด ๊ณ ์นจ์ด ์ด๋ฏธ ๋์ธ ๊ฒ์ ๊นจ๋ใ๋ฅผ ๊ฒฌ์ฃผ๋ ค๋ฉด ์ด๊ฒ์ด ์์ด์ผ ํ๋ค.\n * ์ ์ฅ ์ ์ด์์ ์๋ฒ๊ฐ ๋ชจ๋ฅด๋ฏ๋ก ํ์ ๋ ์ฌ๊ธฐ์ ํ๋ค โ ํ์์ ๊ฐ์ ํจ์๋ฅผ ์ด๋ค(ADR-0063 ๊ฒฐ์ 3).\n */\n @state() private releasedSource?: FigureSource\n\n /** ์ง๊ธ ๊ณ ์น ๊ฒ์ด ๋์ธ ๊ฒ์ ๋ฌด์์ ํ๋. ๋ฐํ ์ ์๋ ๋น์ด ์๋ค. */\n @state() private contract: ContractChange[] = []\n\n /** ๊ฒฌ์ฃผ์ง ๋ชปํ ๊น๋ญ. **๋น์ด ์๋ ๋ชฉ๋ก๊ณผ ๋ค๋ฅด๋ค** โ ใ๊นจ์ง ์๋๋คใ๊ฐ ์๋๋ผ ใ๋ชจ๋ฅธ๋คใ๋ค. */\n @state() private contractFailure?: string\n\n willUpdate(changed: Map<string, unknown>) {\n if (changed.has('draft') || changed.has('parts') || changed.has('releasedSource')) {\n this.folded = this.draft ? toFigureSource(this.draft, this.parts) : undefined\n this.contract = this.compareWithReleased()\n }\n }\n\n /**\n * ๊ณ ์น๋ ์ค์ ์ ๋ณธ์ **์ ๊น ํ์์ ๋ชป ์ง๋ ์ ์๋ค** โ ๋ถํ ์ด๋ฆ์ ์ง์ ๋ค๊ฐ ๋ค์ ์ ๋ ์ฌ์ด๊ฐ\n * ๊ทธ๋ ๋ค. ๊ทธ๋ ๊ฒฌ์ฃผ๊ธฐ๊ฐ ๋์ง๋ฉด ํ๋ฉด์ด ํต์งธ๋ก ๋ฉ์ถ๋ฏ๋ก ๋ชฉ๋ก์ ๋น์ด๋ค.\n *\n * **๋น ๋ชฉ๋ก์ ใ๊นจ์ง ์๋๋คใ๋ก ๋ณด์ด๊ฒ ๋์ง ์๋๋ค.** ๊น๋ญ์ ํจ๊ป ๋ค๊ณ ์๋ค๊ฐ ํ๋ฉด์ด ใํ์ธํ์ง\n * ๋ชปํ๋คใ๋ก ๋งํ๋ค. ์กฐ์ฉํ ๋น์ฐ๋ฉด ์ ์์๋ ์์ ํ๋ค๊ณ ์ฝ๋๋ค โ ์ค์ ๋ก ๊ทธ๋ฐ ์ผ์ด ๋ฌ๋ค: ์ฑ์\n * ๋ ํ์์ด ์ ํ์ด๋ผ ๊ฒฌ์ฃผ๋ ํจ์ ์์ฒด๊ฐ ์์๋๋ฐ, ํ๋ฉด์ ์๋ฌด ๋ง๋ ์ ํ๊ณ ์กฐ์ฉํ๋ค.\n */\n private compareWithReleased(): ContractChange[] {\n this.contractFailure = undefined\n if (!this.releasedSource || !this.folded) return []\n\n try {\n return contractChanges(this.releasedSource, this.folded)\n } catch (e) {\n this.contractFailure = (e as Error).message\n return []\n }\n }\n\n /**\n * ํ์ด์ง ๋ฐ AI ๋ํฌ์๋ **์ง๊ธ ์์ ๋ ์ ๋ณธ**์ ์๋ ค ์ค๋ค.\n *\n * asidebar ๋ํฌ๋ ์ฃผ์์ id๋ง\n * ์์์ผ๋ฏ๋ก DB์ ์ ์ฅ๋ ์ ํ์ ์ฝ์๋ค. ์ ์ฅ ์ ๋ณ๊ฒฝ์ ๋๊ณ \"์ ๋ฐํ์ด ์ ๋๋\" ๋๋\n * \"์ด ๋ถํ์ ์ค์ฌ ๋ฌ๋ผ\"๊ณ ๋ฌผ์ผ๋ฉด ๋ํ๊ฐ ์๋ฑํ ํ์ ๋ณด๊ฒ ๋๋ ๊ฒฐํจ์ด์๋ค.\n *\n * ์ด ์ด๋ฒคํธ๋ ์ ์ฅํ์ง ์๋๋ค. ๋ํฌ๊ฐ ๋ํ ์ธ์๋ก๋ง ์ ์ ๋ค๊ณ ์๊ณ , ์๋ฒ ๋๊ตฌ๋ ๋๋ฉ์ธ ์์\n * Figure๋ฅผ ๋จผ์ ํ์ธํ ๋ค์๋ง ์ด source๋ฅผ ์ฌ์ฉํ๋ค. ํ์ด์ง๋ฅผ ๋ ๋ ๋๋ ์๋์์ ์ง์ ์ค๋๋\n * ์ด์์ด ๋ค์ Figure์ ์์ด์ง ์๊ฒ ํ๋ค.\n */\n updated(changed: Map<string, unknown>) {\n if (changed.has('figure') && (changed.get('figure') as Figure | undefined)?.id !== this.figure?.id) {\n this.proposalFeedback = []\n }\n if (changed.has('draft') || changed.has('parts') || changed.has('figure')) {\n window.dispatchEvent(\n new CustomEvent('figure-ai-context', {\n detail: { figureId: this.figure?.id, source: this.folded }\n })\n )\n }\n }\n\n private announceAiContext = () => {\n if (!this.active) return\n window.dispatchEvent(new CustomEvent('figure-ai-context', {\n detail: { figureId: this.figure?.id, source: this.folded }\n }))\n }\n\n /*\n `detail.staged` is the dock's answer to \"did anything actually happen to my candidate\". The\n listener is synchronous, so the dock reads it right after dispatching and only then tells the\n chat card to say so. It used to be called `accepted`, which claimed more than it knew โ the\n page had put the candidate somewhere, not the person had agreed to it.\n */\n private receiveDockProposal = (event: Event) => {\n const detail = (event as CustomEvent).detail\n if (!detail) return\n\n const source =\n detail?.source ||\n (detail?.proposal?.source\n ? typeof detail.proposal.source === 'string'\n ? JSON.parse(detail.proposal.source)\n : detail.proposal.source\n : undefined)\n\n if (source) {\n detail.staged = this.openProposalForReview(source, detail.proposal)\n }\n }\n\n private onFigureAiStage = (event: Event) => {\n const detail = (event as CustomEvent).detail\n const source = detail?.source || (detail?.proposal?.source ? (typeof detail.proposal.source === 'string' ? JSON.parse(detail.proposal.source) : detail.proposal.source) : undefined)\n if (source) {\n this.openProposalForReview(source, detail.proposal)\n }\n }\n\n /**\n * A candidate from the dock opens the review lane. It does not become the draft.\n *\n * This used to write `draft` and `parts` straight onto the working draft and then set\n * `proposalSession = undefined` โ the dock's candidate overwrote what the author had open and\n * erased the lane built to review it. There was no moment where the person said yes, and a\n * draft has no version history to go back to, so the previous work was simply gone.\n *\n * `ai-client-base`'s analysis contract states this as a literal type: `approvalRequired: true`,\n * and of `proposal`, \"It is never an instruction to mutate canonical state.\" The in-page\n * The in-page entrance honoured this through `openAiProposal` before it was removed, and the dock\n * entrance is now the same door. Applying is what the take button does, from the lane, per change.\n *\n * ## Why the overwrite was there โ so it does not come back\n *\n * The dock opened the review lane originally. Before `c42a0b63df` this handler read:\n *\n * if (!this.active || (detail?.figureId ?? '') !== (this.figure?.id ?? '')) return\n * if (detail?.draftType && detail.draftType !== this.folded?.type) return\n * if (detail?.baseSource && detail.baseSource !== JSON.stringify(this.folded)) return\n * this.receive(detail.proposal)\n *\n * Three guards, each a silent `return`, and the last compared a serialized source byte for byte.\n * Any difference that changed nothing at all dropped the candidate with no message, so the dock\n * would report a candidate and the screen would show none.\n *\n * The `ox-assistant-chat` migration fixed that by replacing the path rather than the guards, and\n * the review lane went out with them โ `applySourceDirectly` wrote straight to the draft, and\n * cleared `proposalSession` on the way past. **Nobody decided that reviews were unwanted here.**\n * It was the cost of loosening a guard by deleting what stood around it.\n *\n * So the guards are gone and stay gone, and the lane is back. If a candidate ever seems not to\n * arrive, the thing to look for is a silent `return` on this path โ not the lane.\n *\n * Returns whether the lane opened, so the dock can tell the chat whether to say it staged.\n */\n private openProposalForReview(rawSource: any, proposal?: any): boolean {\n const source = typeof rawSource === 'string' ? JSON.parse(rawSource) : rawSource\n if (!source || !Array.isArray(source.parts)) return false\n\n try {\n /*\n The dock sends a FigureProposal whose metrics sit at the top level; the staged-on-navigate\n path carries the raw tool result, which nests them under score/cost. Read both rather than\n making one of the two entrances reshape its payload.\n */\n this.proposalSession = proposalSessions.openAiProposal(this.folded, {\n source: JSON.stringify(source),\n grade: proposal?.grade ?? proposal?.score?.grade,\n triangles: proposal?.triangles ?? proposal?.cost?.triangles,\n groups: proposal?.groups ?? proposal?.cost?.groups,\n attempts: proposal?.attempts,\n quality: proposal?.quality\n } as FigureProposal)\n\n this.mode = 'edit'\n this.requestUpdate()\n return true\n } catch (e) {\n console.error('[FigureModeller] Failed to open the AI candidate for review:', e)\n return false\n }\n }\n\n private proposalBaseSource?: string\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('figure-ai-context-request', this.announceAiContext)\n window.addEventListener('figure-ai-review', this.receiveDockProposal)\n window.addEventListener('figure-ai-stage', this.onFigureAiStage)\n window.addEventListener('figure-save-request', this.onSaveRequest)\n window.addEventListener('keydown', this.handleKeyDown)\n }\n\n disconnectedCallback() {\n window.removeEventListener('keydown', this.handleKeyDown)\n window.removeEventListener('figure-save-request', this.onSaveRequest)\n window.removeEventListener('figure-ai-stage', this.onFigureAiStage)\n window.removeEventListener('figure-ai-context-request', this.announceAiContext)\n window.removeEventListener('figure-ai-review', this.receiveDockProposal)\n window.dispatchEvent(new CustomEvent('figure-ai-context', { detail: undefined }))\n super.disconnectedCallback()\n }\n\n private onSaveRequest = () => {\n if (this.active) this.save()\n }\n\n private handleKeyDown = (e: KeyboardEvent) => {\n if (!this.active || this.mode !== 'edit' || this.proposalSession) return\n const target = e.composedPath()[0] as HTMLElement | undefined\n const tag = target?.tagName?.toLowerCase()\n if (tag === 'input' || tag === 'textarea' || target?.isContentEditable) return\n\n if ((e.metaKey || e.ctrlKey) && !e.altKey) {\n if (e.key === 'z' && !e.shiftKey) {\n e.preventDefault()\n this.undo()\n } else if ((e.key === 'z' && e.shiftKey) || e.key === 'y') {\n e.preventDefault()\n this.redo()\n }\n }\n }\n\n get context() {\n return {\n title: this.figure?.name ?? i18next.t('figure.title.new-figure'),\n /*\n **์ ๋ชฉ ์ค์ ๋๋ค.** ์ด๋ฆ์ ๊ทธ๋๋ก ๋๋ค.\n\n ์ด ํ๋ฉด์ ์ฃผ์ธ๊ณต์ ์บ๋ฒ์ค๋ค. ์ด๋ฆ์ ์์ฑ ํจ๋์์ ๋ณด๊ณ ๊ณ ์น๊ณ , ๋ธ๋ผ์ฐ์ ํญ์๋\n ใoperato figure ยท ์์
์ใ๋ก ๋์จ๋ค. ๊ทธ ์์ ์ ๋ชฉ ์ค์ ํ ๊ฒน ๋ ์น์ผ๋ฉด ๊ฐ์ ๋ง์ด ์ธ ๋ฒ์ด๊ณ ,\n ๊ทธ๋งํผ ์บ๋ฒ์ค๊ฐ ๋ฎ์์ง๋ค.\n\n `title` ์ ๋น์ฐ๋ ๊ฒ์ผ๋ก ๋์ง ์๋ ์ด์ ๋ ๊ทธ ๊ฐ์ MDI ํญ๋ ์ฝ๊ธฐ ๋๋ฌธ์ด๋ค โ ๋น์ฐ๋ฉด ํญ ์ด๋ฆ์ด\n ํจ๊ป ์ฌ๋ผ์ง๋ค. ์ด๋ฆ์ ํ๋์ด๊ณ ๊ทธ๋ฆฌ๋ ์๋ฆฌ๋ง๋ค ์ผ๊ณ ๋๋ค(`ox-page-title-bar`).\n */\n heading: false\n }\n }\n\n render() {\n const source = this.folded\n\n return html`\n <div\n edits\n ?collapse-left=${this.collapsed.left}\n ?collapse-right=${this.collapsed.right}\n @figure-rename=${(e: CustomEvent) => this.rename(e.detail.name)}\n @figure-type-change=${(e: CustomEvent) => this.typeChanged(e.detail.type)}\n @figure-catalog=${(e: CustomEvent) => this.catalog(e.detail)}\n @figure-released=${(e: CustomEvent) => this.released(e.detail.figure)}\n @figure-reverted=${() => this.figure?.id && this.load(this.figure.id)}\n @preview-sizing-fix=${(e: CustomEvent) => this.previewSizingFix(e.detail)}\n @apply-sizing-fix=${(e: CustomEvent) => this.applySizingFix(e.detail)}\n @add-part=${(e: CustomEvent) => this.addPart(e.detail.primitive)}\n @select-part=${(e: CustomEvent) => (this.selected = e.detail.index)}\n @remove-part=${(e: CustomEvent) => this.removePart(e.detail.index)}\n @duplicate-part=${(e: CustomEvent) => this.duplicatePart(e.detail.index)}\n @move-part-up=${(e: CustomEvent) => this.movePart(e.detail.index, e.detail.to)}\n @move-part-down=${(e: CustomEvent) => this.movePart(e.detail.index, e.detail.to)}\n @update-part=${(e: CustomEvent) => this.updatePart(e.detail.index, e.detail.part)}\n @part-changed=${(e: CustomEvent) => this.partChanged(e.detail.name, e.detail.part)}\n @toggle-part-hidden=${(e: CustomEvent) => this.toggleHidden(e.detail.index)}\n @set-all-parts-hidden=${(e: CustomEvent) => this.setAllHidden(e.detail.hidden)}\n @change-detail-level=${(e: CustomEvent) => this.changeDetailLevel(e.detail.level)}\n @update-draft=${(e: CustomEvent) => this.updateDraft(e.detail.draft)}\n @resize-base=${(e: CustomEvent) => this.resizeBase(e.detail.draft, e.detail.parts)}\n @part-tool=${(e: CustomEvent) => this.runTool(e.detail.index, e.detail.tool, e.detail.axis)}\n @pick-part=${(e: CustomEvent) => this.pickPart(e.detail.name)}\n >\n <figure-parts\n .parts=${this.parts}\n .level=${(this.draft?.detailLevel ?? 'M') as DetailLevel}\n .selected=${this.selected}\n ></figure-parts>\n\n <div middle>\n ${this.renderBar()}\n ${this.proposalSession ? this.renderDecision() : ''}\n ${this.proposalSession\n ? html`\n <div lanes>\n <div lane>\n <h4>${i18next.t('figure.label.now')}</h4>\n <figure-canvas\n .figureId=${this.figure?.id || this.figure?.type}\n .draft=${this.draft}\n .parts=${this.parts}\n .picked=${this.pickedName}\n .view=${this.view}\n .revision=${this.sceneRevision}\n ></figure-canvas>\n </div>\n <div lane candidate>\n <h4>\n ${i18next.t('figure.label.proposed')}\n ${this.proposalSession.metrics\n ? html`<small>\n ${this.proposalSession.metrics.grade} ยท\n ${i18next.t('figure.text.n-triangles', { count: this.proposalSession.metrics.triangles })}\n ${this.proposalSession.metrics.quality ? html` ยท ${this.proposalSession.metrics.quality.summary}` : ''}\n </small>`\n : ''}\n </h4>\n ${this.renderProposed()}\n </div>\n </div>\n `\n : this.mode === 'preview'\n ? html`<figure-preview\n .source=${source}\n .draft=${this.draft}\n .view=${this.view}\n @pose-as-default=${(e: CustomEvent) => this.poseAsDefault(e.detail.values)}\n ></figure-preview>`\n : html`<figure-canvas\n .figureId=${this.figure?.id || this.figure?.type}\n .draft=${this.draft}\n .parts=${this.parts}\n .picked=${this.pickedName}\n .gizmo=${this.jointGizmo}\n .view=${this.view}\n .revision=${this.sceneRevision}\n ></figure-canvas>`}\n </div>\n\n <figure-side\n .figureName=${this.figure?.name ?? ''}\n .figureCategory=${this.figure?.category}\n .figureTags=${this.figure?.tags}\n .figureId=${this.figure?.id ?? ''}\n .figureState=${this.figure?.state}\n .figureVersion=${this.figure?.version ?? 0}\n .dirty=${this.dirty}\n .draft=${this.draft}\n .parts=${this.parts}\n .source=${source}\n .contract=${this.contract}\n .contractFailure=${this.contractFailure}\n .selected=${this.selected}\n .view=${this.view}\n @update-view=${(e: CustomEvent) => (this.view = e.detail.view)}\n ></figure-side>\n </div>\n ${this.renderSaveModal()}\n `\n }\n\n /**\n * ๊ฐ์ด๋ฐ ์นธ ์์ ๋ โ ๋ฌด์์ ๋ณด๊ณ ์๋์, ์์ชฝ ์นธ์ ์ ๋ ์์ก์ด.\n *\n * ## ๋ฌด์์ ๋ณด๊ณ ์๋\n *\n * ํธ์ง๊ณผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ ๊ฐ์ ์๋ฆฌ๋ฅผ ๋๊ณ ๋คํฌ์ง ์๋๋ค. ๋ ๋ค ๋์ด๊ฐ ํ์ํ๊ณ , ๋์์\n * ๋ด์ผ ํ ์ผ์ด ์๋ค. ๋ถํ์ ๊ณ ์น๋ ๋์์๋ ํธ์ง๋ง ๋ณด๋ฉด ๋๊ณ , ๋ค ๊ณ ์น ๋ค์ ๋๋ฉด์์\n * ์ด๋ป๊ฒ ๋๋์ง ๋ณด๋ฉด ๋๋ค.\n *\n * ํ๋ณด๊ฐ ์ ์์ ๋๋ ๊ทธ ๋ ๋จ์ถ๋ฅผ ๋ด์ง ์๋๋ค. ๊ทธ๋๋ ๊ฐ์ด๋ฐ๊ฐ ์ด๋ฏธ ๋๋ก ๋๋์ด\n * ์๋ค.\n *\n * ## ๋ ๋ ๋ ์๋ค\n *\n * ์์ก์ด๊ฐ ์ฌ๊ธฐ ์๊ธฐ ๋๋ฌธ์ด๋ค. ํ๋ณด๊ฐ ์๋ค๊ณ ๋ ๋ฅผ ํต์งธ๋ก ๊ฐ์ถ๋ฉด, ์นธ์ ์ ์ด ๋ ์ฑ๋ก\n * ํ๋ณด๋ฅผ ๋ฐ์ผ๋ฉด ๋๋๋ฆด ๋ฐฉ๋ฒ์ด ์์ด์ง๋ค.\n */\n private renderBar() {\n const one = (mode: 'edit' | 'preview') => html`\n <button\n mode\n ?on=${this.mode === mode}\n title=${i18next.t('figure.text.mode-' + mode + '-explained')}\n @click=${() => (this.mode = mode)}\n >\n ${i18next.t('figure.label.mode-' + mode)}\n </button>\n `\n\n return html`<div modes>\n ${this.renderCollapse('left')}${this.proposalSession ? '' : html`${one('edit')}${one('preview')}`}\n ${this.mode === 'edit' && !this.proposalSession\n ? html`\n <div separator></div>\n <button\n history\n ?disabled=${this.undoStack.length === 0}\n title=\"${i18next.t('figure.button.undo')} (Ctrl+Z)\"\n @click=${() => this.undo()}\n >\n <md-icon>undo</md-icon>\n </button>\n <button\n history\n ?disabled=${this.redoStack.length === 0}\n title=\"${i18next.t('figure.button.redo')} (Ctrl+Y)\"\n @click=${() => this.redo()}\n >\n <md-icon>redo</md-icon>\n </button>\n `\n : ''}\n <div spacer></div>\n <!--\n AI ๋ฅผ ์ฌ๋ ๋จ์ถ๋ ์ฌ๊ธฐ ๋์ง ์๋๋ค. ์ฑ ๋จธ๋ฆฌ์ค์ ์ด๋ฏธ ์๊ณ ๊ฐ์ dock ์ ์ฐ๋ค โ ํ ํ๋ฉด์\n ๊ฐ์ ๊ณณ์ผ๋ก ๊ฐ๋ ๋ฌธ์ด ๋์ด๋ฉด ์ฌ๋์ด ๋์ ์ฐจ์ด๋ฅผ ์ฐพ๋๋ค. ์ด๋ฆฐ ๋ํ์ dock ์ ๋๊ธฐ๋ ์ผ์\n ๋จ์ถ๊ฐ ํ๋ ๊ฒ์ด ์๋๋ค: dock ์ด ์ด๋ฆด ๋ figure-ai-context-request ๋ก ๋ฌป๊ณ ์ด ํ๋ฉด์ด\n ์ ์ฅ ์ ์ ๋ณธ ๊ทธ๋๋ก ๋ตํ๋ค.\n -->\n ${this.saveFailure ? html`<span save-failed title=${this.saveFailure}>${this.saveFailure}</span>` : ''}\n ${this.dirty ? html`<span dirty>${i18next.t('figure.text.unsaved-changes')}</span>` : ''}\n <button save ?disabled=${!this.canSave} @click=${() => this.save()}>\n ${this.saving ? i18next.t('figure.text.saving-figure') : i18next.t('figure.button.save')}\n </button>\n ${this.renderCollapse('right')}\n </div>`\n }\n\n /**\n * ํ์ชฝ ์นธ์ ์ ๊ณ ํด๋ ์์ก์ด.\n *\n * ํ์ดํ๋ **๋๋ฅด๋ฉด ๋ฌด์์ด ์ผ์ด๋๋์ง**๋ฅผ ๊ฐ๋ฆฌํจ๋ค โ ํด์ ธ ์์ผ๋ฉด ์นธ์ด ์ฌ๋ผ์ง ์ชฝ,\n * ์ ํ ์์ผ๋ฉด ์นธ์ด ๋์์ฌ ์ชฝ. ์ง๊ธ ์ํ๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ๋ฉด ๋ฐ๋๋ก ์ฝํ๋ค.\n */\n private renderCollapse(side: keyof Panes) {\n const gone = this.collapsed[side]\n const shut = side === 'left' ? 'chevron_left' : 'chevron_right'\n const back = side === 'left' ? 'chevron_right' : 'chevron_left'\n const pane = side === 'left' ? 'parts' : 'properties'\n\n return html`\n <button\n collapse\n title=${i18next.t(`figure.text.${gone ? 'expand' : 'collapse'}-${pane}-pane`)}\n @click=${() => this.toggleCollapse(side)}\n >\n <md-icon>${gone ? back : shut}</md-icon>\n </button>\n `\n }\n\n private toggleCollapse(side: keyof Panes): void {\n this.collapsed = { ...this.collapsed, [side]: !this.collapsed[side] }\n rememberPanes(this.collapsed)\n }\n\n /**\n * AI ํ๋ณด๋ฅผ ์ค์ ๋ฐฐ์น ํฌ๊ธฐ์์๋ ๋ณธ๋ค.\n *\n * ํธ์ง ์บ๋ฒ์ค ํ ์ฅ์ผ๋ก๋ `repeat`ยท`fixed`ยท`anchor`๊ฐ ๋ง๋์ง ์ ์ ์๋ค. ํ๋ณด๋ ์์ง\n * ์ ๋ณธ์ด ์๋๋ฏ๋ก ์ ์ฅํ์ง ์๊ณ , `figure-preview`๊ฐ ๊ฐ์ FigureSource๋ฅผ ๊ธฐ์ค ํฌ๊ธฐ์\n * ์ผ๊ณฑ ๊ฐ์ง ํ์ฅ ์ถ์์ ์ค์ FigureInstance๋ก ์ธ์ด๋ค. ๋ฐ๋ผ์ ์ ์์๋ \"์ข์ ๋ณด์ด๋\n * ํ ์ฅ\"์ด ์๋๋ผ ๋ฐฐ์น๋ ๋๋ ๋ถ์ด ์๋์ง๋ฅผ ๋ณด๊ณ ์๋ฝํ๋ค.\n */\n private renderProposed() {\n if (!this.proposalSession) return ''\n\n return html`<figure-preview .source=${this.proposalSession.source} .view=${this.view}></figure-preview>`\n }\n\n /**\n * ๋ฌด์์ ๋ฐ์์ง ๊ณ ๋ฅธ๋ค.\n *\n * ํต์งธ๋ก๋ง ๋ฐ๊ฒ ๋๋ฉด ใ๋ชธํต์ ์ข์๋ฐ ๋ชจํฐ ์๋ฆฌ๊ฐ ํ๋ ธ๋คใ์ ๋ตํ ์ ์๋ค โ ๊ทธ๊ฒ\n * ๊ฐ์ฅ ํํ ๋ฐ์์ด๋ค. ๋ณ๊ฒฝ ํ๋๊ฐ ์นฉ ํ๋์ด๊ณ , ์ฒ์์๋ ์ ๋ถ ๊ณจ๋ผ ๋๋ค. ํต์งธ๋ก\n * ๋ฐ๋ ๊ฒ์ด ๋ณดํต์ ๊ธธ์ด๋ฏ๋ก ๊ทธ๊ฒ์ด ํ ๋ฒ ๋๋ฅด๊ธฐ์ฌ์ผ ํ๋ค.\n *\n * ๊ณ ๋ฅธ ์กฐํฉ์ **๋ฐ๊ธฐ ์ ์ ์ฌ ๋ณธ๋ค.** ํ์์ ์ด๊ธฐ๋ฉด ๋ชป ๋๋ฅด๊ฒ ํ๊ณ , ์ ์ฑ
์ ๋์ผ๋ฉด\n * ์๋ฆฐ๋ค. ๊ณจ๋ผ ๋ฐ์ผ๋ฉด ํ๋ณด๋ฅผ ๋ผ ๋์ ๋ค๋ฅธ ์กฐํฉ์ด ๋๋ฏ๋ก ํ๋ณด์ ์ ์๋ฅผ ๊ทธ๋๋ก\n * ๋ฏฟ์ ์ ์๋ค โ ์๋ฅผ ๋ค์ด ๋ฑ๊ธ์ ์ ๋ฐ๊ณ ๋ถํ๋ง ๋ฐ์ผ๋ฉด ๋ถํ ์ ํ๋๋ฅผ ๋๋๋ค.\n *\n * ํ์ ์ค๋ฅ๊ฐ ์ค์ ๋ก ๋๋ ์กฐํฉ์ ์์ง ๋ณด์ง ๋ชปํ๋ค. ๊ทธ๋๋ ๋๋ ๊ฒ์ ๊ฐ์ด ๊ฑฐ์\n * ์ ๋ค๊ณ , ์ฐ๋ฆฌ๊ฐ ์๊ฐ ๋ชป ํ ์กฐํฉ์ ๋ง์ ์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.\n */\n private renderDecision() {\n if (!this.proposalSession) return ''\n\n const stale = this.proposalBaseSource !== undefined && this.proposalBaseSource !== JSON.stringify(this.folded)\n\n const changes = proposals.diffProposal(this.folded, this.proposalSession.source)\n const picked = proposals.applyProposal(this.folded, this.proposalSession.source, this.proposalSession.picked)\n const { errors, violations } = validate(picked)\n\n return html`\n <div decide>\n <span>${this.proposalTitle(this.proposalSession)}</span>\n <div spacer></div>\n <button drop @click=${() => this.discard()}>${i18next.t('figure.button.discard')}</button>\n ${stale ? html`<span role=\"alert\">${i18next.t('figure.text.source-changed-ask-again')}</span>` : ''}\n <button take ?disabled=${stale || errors.length > 0 || this.proposalSession.picked.size === 0} @click=${() => this.take()}>\n ${i18next.t('figure.button.take-n-changes', { n: this.proposalSession.picked.size })}\n </button>\n </div>\n\n ${this.renderQualityReview()}\n <div proposal-note>\n <label>\n ${i18next.t('figure.text.proposal-feedback-note')}\n <input\n maxlength=\"500\"\n .value=${this.proposalSession.note}\n placeholder=${i18next.t('figure.text.proposal-feedback-placeholder')}\n @input=${(event: Event) => (this.proposalSession = { ...this.proposalSession!, note: (event.target as HTMLInputElement).value })}\n />\n </label>\n </div>\n\n ${changes.length > 0\n ? html`\n <div changes>\n ${changes.map(change => this.renderChange(change))}\n </div>\n `\n : ''}\n ${errors.length > 0\n ? html`<p blocked>${i18next.t('figure.text.picked-changes-do-not-validate')} โ ${errors[0].message}</p>`\n : violations.length > 0\n ? html`<p blocked warn>${violations[0].message}</p>`\n : ''}\n `\n }\n\n /** ํ๋ณด ํ์ง ํ๋จ์ ๊ทผ๊ฑฐ๋ฅผ ์๋ฝ ์ ์ ์ ๋ถ ๋ณด์ฌ ์ค๋ค. */\n private renderQualityReview() {\n const quality = this.proposalSession?.metrics?.quality\n if (!quality) return ''\n\n return html`\n <div quality-review ?review=${quality.status === 'review'}>\n <strong>${i18next.t('figure.label.candidate-review')}</strong>\n <span>${quality.summary}</span>\n <span> ยท top-view ${Math.round(quality.visualReadability * 100)}% ยท ${quality.visualRegions} regions</span>\n ${quality.findings.length > 0\n ? html`<ul>\n ${quality.findings.map(finding => html`<li><code>${finding.dimension}</code> โ ${finding.message}</li>`)}\n </ul>`\n : ''}\n </div>\n `\n }\n\n /** ๋ณ๊ฒฝ ํ๋. ๋ฌด์์ ํ๊ฒ ๋ค๋ ๊ฒ์ธ์ง ๋ถํธ๋ก ๋จผ์ ๋งํ๋ค. */\n private renderChange(change: proposals.ProposalChange) {\n /*\n Every ChangeKind needs a row here. A kind the map does not answer draws an empty icon and a\n key with no name beside it, which reads as a broken row rather than a missing case โ the\n `satisfies` makes the compiler say so instead.\n */\n const icon = ({\n added: 'add',\n changed: 'edit',\n removed: 'remove',\n base: 'aspect_ratio',\n placement: 'vertical_align_bottom',\n detail: 'tune',\n styleKit: 'palette',\n animations: 'animation',\n parameters: 'tune',\n capabilities: 'hub',\n joints: 'settings_input_component'\n } satisfies Record<proposals.ChangeKind, string>)[change.kind]\n\n const on = this.proposalSession?.picked.has(change.key)\n\n return html`\n <button\n change\n ?on=${on}\n title=${i18next.t('figure.text.change-' + change.kind)}\n @click=${() => this.toggle(change.key)}\n >\n <md-icon>${icon}</md-icon>\n <span key>${change.key}</span>\n </button>\n `\n }\n\n private toggle(key: string) {\n if (this.proposalSession) this.proposalSession = proposalSessions.toggleProposalChange(this.proposalSession, key)\n }\n\n /**\n * ํ๋ณด๊ฐ ์๋ค.\n *\n * ์๋ณธ ๋ฐ์ดํฐ์ ๋ฃ์ง ์๋๋ค. ๋๋ํ ๋๊ณ ์ ์์๊ฐ ๊ณ ๋ฅธ๋ค. AI ๊ฐ ์๋ณธ ๋ฐ์ดํฐ์ ์ง์ ์ฐ๋ฉด\n * ๋ฌด์์ด ์๊ธฐ ๊ฒ์ด๊ณ ๋ฌด์์ด ๊ธฐ๊ณ ๊ฒ์ธ์ง ๋ชจ๋ฅด๊ฒ ๋๋ค.\n */\n private receive(proposal: FigureProposal) {\n this.proposalBaseSource = JSON.stringify(this.folded)\n this.proposalSession = proposalSessions.openAiProposal(this.folded, proposal)\n }\n\n /**\n * ๋ฐํ ๊ฒ์ดํธ์ ๊ตฌ์กฐํ๋ ์์ ์ ํ๋๋ฅผ ํ์ฌ ์์
์ฌ๋ณธ์๋ง ๊ฒน์ณ ๋ณธ๋ค. ์๋ฒ๊ฐ ์ค ๊ฐ์\n * `part.anchor.axis = to`๋ผ๋ ๋ฐ์ดํฐ์ด์ง ์ฌ๋์ด ์ฝ์ ๋ฌธ์ฅ์ ๋ค์ ํด์ํ ๊ฒฐ๊ณผ๊ฐ ์๋๋ค.\n * ์๋ณธ `draft`/`parts`๋ ์ฌ๊ธฐ์ ์ ํ ๋ฐ๊พธ์ง ์๊ณ , ์๋์ `take()`๋ง ๋ฐ๊พผ ์ฌ๋ณธ์ ์ ์ฉํ๋ค.\n */\n private previewSizingFix(fix: FigureGateFix) {\n if (!this.folded) return\n this.proposalBaseSource = JSON.stringify(this.folded)\n this.proposalSession = proposalSessions.openSizingFix(this.folded, fix)\n }\n\n /**\n * ์ํด๋ฆญ ์ ์ฉ์ ์๋ฒ๊ฐ ๋ชจ๋ ํฌ๊ธฐ ๋ณ๊ฒฝ case๋ฅผ ์ฌ๊ฒ์ฌํด ์์ ํ๋ค๊ณ ํ์ํ ํ-์ต์ปค ํ๋ณด์๋ง ์ฐ๋ค.\n * ๊ทธ๋๋ ์ ์ฅ์ ์ ์์์ ๋ณ๋ ํ์๋ค. ์๋ชป ๋๋ฌ๋ DB ์ ๋ณธ์ด๋ ๋ฐํํ์ ๋ฐ๋์ง ์๋๋ค.\n */\n private applySizingFix(fix: FigureGateFix) {\n if (!fix.safe || !this.folded) return\n this.previewSizingFix(fix)\n if (!this.proposalSession) return\n this.take()\n }\n\n /**\n * ๊ณ ๋ฅธ ๋ณ๊ฒฝ์ ๋ฐ์๋ค์ธ๋ค.\n *\n * ํ๋ณด ๋น๊ต๋ ์ ์ฅ ํ์์ผ๋ก ํ๋ค โ ๋ถํ ์ด๋ฆ์ผ๋ก ์ง์ง๊ณ ๊ธฐ์ค ์น์ยท๋ฑ๊ธ๊น์ง ํจ๊ป ๋ด์ผ\n * ํ๋ฏ๋ก ๊ทธ์ชฝ์ด ์์ฐ์ค๋ฝ๋ค. ๋ฐ์๋ค์ธ ๊ฒฐ๊ณผ๋ ๋ค์ ์ฌ ๋ชจ๋ธ๋ก ๋๋๋ ค ํธ์ง์ ์ด์ด๊ฐ๋ค.\n */\n private take() {\n if (!this.proposalSession) return\n if (this.proposalBaseSource !== undefined && this.proposalBaseSource !== JSON.stringify(this.folded)) return\n\n this.recordHistory()\n const taken = proposals.applyProposal(this.folded, this.proposalSession.source, this.proposalSession.picked)\n const { draft, parts } = fromFigureSource(taken)\n\n this.draft = draft\n this.parts = parts\n this.selected = parts.length ? 0 : -1\n this.dirty = true\n this.reportProposalFeedback('accepted')\n this.discard(false)\n }\n\n /**\n * ํ๋ณด์ ๋ํ ์ฌ๋์ ๊ฒฐ์ ์ ๋ํฌ์๋ง ์๋ฆฐ๋ค.\n *\n * ์ด ๊ธฐ๋ก์ ๋ถ์ ์ด๋ฒคํธ๋ Figure ์์ฑ์ด ์๋๋ค. ๊ฐ์ ๋ชจ๋ธ๋ฌ ์ธ์
์์ ๋ค์ ์์ฒญ์ ๋ ์\n * ์ดํด์ํค๋ ์งง์ ์ ํธ์ผ ๋ฟ์ด๋ค. ์๋ณธ source๋ ์ฌ๋์ ์์
๋ด์ฉ์ ๋ค์ ๋ณด๋ด์ง ์๊ณ , ์ฌ๋์ด\n * ํ๋ณด ๋ณ๊ฒฝ ์ค ๋ช ๊ฐ๋ฅผ ๋ฐ์๋ค์๋์ง์ ์ด๋ฏธ ํ๋ฉด์ ๋ณด์๋ ํ์ง ํ์ ๋ง ๋ณด๋ธ๋ค.\n */\n private reportProposalFeedback(outcome: 'accepted' | 'discarded') {\n if (!this.proposalSession) return\n\n const feedback = proposalSessions.feedbackFromSession(this.folded, this.proposalSession, outcome)\n if (!feedback) return\n this.proposalFeedback = [...this.proposalFeedback, feedback].slice(-5)\n window.dispatchEvent(\n new CustomEvent('figure-ai-feedback', {\n detail: {\n figureId: this.figure?.id,\n ...feedback\n }\n })\n )\n }\n\n private discard(reportFeedback = true) {\n if (reportFeedback) this.reportProposalFeedback('discarded')\n this.proposalSession = undefined\n this.proposalBaseSource = undefined\n }\n\n /**\n * ์ ์ฅํ ์ ์๋.\n *\n * ํ์์ ์ด๊ธด ์๋ณธ ๋ฐ์ดํฐ๋ก๋ ์ ์ฅ์ ๋๋ฅผ ์ ์๊ฒ ํ๋ค. ๋๋ ๋ค๊ฐ ์๋ฒ๊ฐ ๋ฐ์์ฃผ์ง ์๋ ๊ฒ๋ณด๋ค,\n * ๋๋ฅผ ์ ์๋ ์ด์ ๊ฐ ํ๋จ ํจ๋์ ๋ ์๋ ๊ฒ์ด ๋ซ๋ค.\n *\n * ## ๋ฐ๋ ๊ฒ์ด ์์ผ๋ฉด ๋๋ฅผ ์ ์๋ค\n *\n * **`dirty` ๋ฅผ ์ ๋ณด๊ณ ์์๋ค.** ์ ์ฅํ ์งํ์๋ ๋จ์ถ๊ฐ ์ด์ ์์ด ๊ฐ์ ์ ๋ณธ์ ๋ช ๋ฒ์ด๊ณ ๋ค์ ์ธ\n * ์ ์์๊ณ , ์ ์ฅ๋ง๋ค ์ธ๋ค์ผ์ ์๋ก ์ฐ์ด 20KB ๋ฅผ ๋ค์ ๋ฃ๊ณ `thumbnailUpdatedAt` ์ ์ฌ๋ ธ๋ค โ\n * ๊ทธ๋ฆผ ์ฃผ์์ ํ์ด ๋ฐ๋๋ฏ๋ก ๋ธ๋ผ์ฐ์ ์บ์๋ ํจ๊ป ๋ฒ๋ ค์ง๋ค. ๋ฐ๋ ๊ฒ์ด ์๋๋ฐ ์ผ์ด๋ ์ผ์ด ์๋๋ค.\n *\n * ์๋ก ๋ง๋๋ ์ค์ธ ๊ฒ์ `startNew` ๊ฐ `dirty` ๋ก ์์ํ๋ฏ๋ก ์ฒซ ์ ์ฅ์ด ๋งํ์ง ์๋๋ค.\n * ์ ์ฅ์ด ๊ฑฐ์ ๋๋ฉด `dirty` ๋ฅผ ๊ทธ๋๋ก ๋๋ฏ๋ก ๋ค์ ๋๋ฅผ ์ ์๋ค.\n */\n private get canSave(): boolean {\n if (this.saving || !this.dirty || !this.folded) {\n return false\n }\n // ๊ธฐ์กด ์ ์ฅ๋ ๋ชจ๋ธ์ ์ด๋ฆ์ด ์์ด์ผ ๋ฐ๋ก ์ ์ฅ ๊ฐ๋ฅ. ์ ๊ท ๋ชจ๋ธ์ ์ ์ฅ ํ์
์์ ์ด๋ฆ์ ์
๋ ฅํ ์ ์์\n if (this.figure?.id && !this.figure?.name) {\n return false\n }\n return validate(this.folded).errors.length === 0\n }\n\n async pageUpdated(changes: Record<string, unknown>, lifecycle: { resourceId?: string }) {\n if (!this.active) {\n ++this.loadGeneration\n return\n }\n\n const id = lifecycle?.resourceId\n\n if (id) {\n if (changes.active || id !== this.figure?.id) {\n await this.load(id)\n }\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n return\n }\n\n /*\n โโ id ์์ด ๋ค์ด์จ ๊ฒ์ ใ์๋ก ๋ง๋ ๋คใ๋ ๋ป์ด๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n ์ ์๋ `!this.figure` ์ผ ๋๋ง ์๋ก ์์ํ๋ค. ์
ธ์ ํ์ด์ง๋ฅผ ์ด๋ ค ๋๋ฏ๋ก(MDI ํญ) ์นดํ๋ก๊ทธ์์\n ํ๋ ์ด์ด ๋ณธ ๋ค์๋ ์ด ํ์ด์ง๊ฐ ๊ทธ ๋ํ์ ๊ณ์ ๋ค๊ณ ์๊ณ , ๊ทธ๋์ ใ์ figureใ๊ฐ **์๋ฌด ์ผ๋\n ํ์ง ์์๋ค.**\n\n ๊ทธ๊ฒ๋ณด๋ค ๋์ ๊ฒ์ด ์์๋ค โ ํ๋ฉด์๋ ์ ๋ํ์ด ๊ทธ๋๋ก ์์ผ๋ ์ฌ๋์ ์ ๊ฒ์ธ ์ค ์๊ณ ๊ณ ์น๊ณ \n ์ ์ฅํ๋ค. ๊ทธ๋ฌ๋ฉด **์ด๋ ค ์๋ ๋ํ์ ๋ฎ์ด์ด๋ค.** ใ์ ์ด๋ฆฐ๋คใ๋ก ๋ณด์ด๋ ๊ฒ์ด ์ค์ ๊ทธ ๋ฌธ์ด์๋ค.\n\n ๋ค๊ณ ์๋ ๊ฒ์ด **์ ์ฅ๋ ๋ํ์ด๋ฉด**(id ๊ฐ ์์ผ๋ฉด) ์๋ก ์์ํ๋ค. ์์ง ์ ์ฅ ์ ํ ์ ๋ํ์\n ๋ค๊ณ ์์ผ๋ฉด ๊ทธ๋๋ก ๋๋ค โ ํ์ด์ง๋ฅผ ๋ค์ ๋ค๋ ๋ค๊ณ ์ ์ ์ค์ธ ๊ฒ์ ๋ฒ๋ฆฌ์ง ์๋๋ค.\n */\n if (!this.figure) {\n this.startNew()\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n return\n }\n\n if (this.figure.id) {\n this.startNew()\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n return\n }\n\n if (shouldStartNewFigure(changes, !!this.figure, this.figure?.id)) {\n this.startNew()\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n return\n }\n\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n }\n\n private loadGeneration = 0\n private async load(id: string) {\n const generation = ++this.loadGeneration\n const figure = await fetchFigure(id)\n if (generation !== this.loadGeneration || !this.active) return\n\n this.proposalSession = undefined\n this.proposalBaseSource = undefined\n this.figure = figure\n\n /*\n ๊ทธ๋ฆผ์ด ์์ผ๋ฉด ์ด ์๋ฆฌ์์ ์ฑ์ด๋ค(์๋ `fillThumbnail`). ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค โ ํ๋ฉด์ด ๋จผ์ ๋ค.\n\n **`thumbnail` ์ด ์๋๋ผ `thumbnailUpdatedAt` ์ผ๋ก ํ์ ํ๋ค.** ๊ทธ๋ฆผ ์์ฒด๋ ๋ชฉ๋กยท๋ฑ๊ฐ ์ง์๊ฐ\n ๊ฐ์ ธ์ค์ง ์๋๋ค(base64 ๋ผ์ ๋ฌด๊ฒ๊ณ ์บ์๊ฐ ์ ๋๋ค โ ์ฃผ์๋ก ๋ถ๋ฅธ๋ค). ์๋ ์นธ์ผ๋ก ํ์ ํ๋ฉด\n ๋ ใ๊ทธ๋ฆผ์ด ์๋คใ๊ฐ ๋์ด ์ ์๋ฉด์ ์ด ๋๋ง๋ค ๋ค์ ์ฐ์ด ์ ์ฅํ๊ฒ ๋๋ค.\n */\n if (!figure.thumbnailUpdatedAt && figure.id) {\n void this.fillThumbnail(figure.id)\n }\n\n // ์๋ฒ๊ฐ ์ค ๊ฒ์ ๊ทธ๋๋ก ์ด๋ค. ์ฝ์ง ๋ชปํ๋ฉด ์ค๋ฅ๋ณด๊ณ ์์ด ๋น ์ํ๋ก ๋ฐ๊พธ์ง ์๋๋ค.\n // ๊ทธ๋ฌ๋ฉด ์ฌ์ฉ์๊ฐ ์ ์ฅ์ ์ ํํด ์๋ณธ์ ๋ฎ์ด์ด๋ค.\n const model = figure.source ? fromFigureSource(JSON.parse(figure.source) as FigureSource) : undefined\n this.draft = model?.draft\n this.parts = model?.parts ?? []\n\n /*\n ๋ฐํ๋ ์ ์ด ์์ผ๋ฉด ๊ทธ ํ์ ๊ฐ์ ธ๋ค ๋๋ค โ ๊ณ ์น๋ ๋์ ๊ฒฌ์ค ์๋๋ค. ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค:\n ๋ํ์ ์ด๋ฏธ ํ๋ฉด์ ์๊ณ , ํ์ ์ ๋์ฐฉํ๋ ๋๋ก ๋ถ๋๋ค.\n */\n this.releasedSource = undefined\n if (figure.id && (figure.version ?? 0) > 0) {\n void this.loadReleased(figure.id, generation)\n }\n\n /*\n **์๋ฌด๊ฒ๋ ๊ณ ๋ฅด์ง ์์ ์ฑ๋ก ์ฐ๋ค.**\n\n ์ ์๋ ์ฒซ ๋ถํ์ ์ก์ ๋์๋ค. ๊ทธ๋ฌ๋ฉด ์ฌ์ฉ์๊ฐ ๊ณ ๋ฅธ ์ ์๋ ๋ถํ์ ์์ฑ์ด ๋ ์๊ณ ,\n ์บ๋ฒ์ค์๋ ๊ทธ ๋ถํ์ ์ค๊ณฝ์ ์ด ๊ทธ๋ ค์ง๋ค. ๋ชจ๋ธ ์ ์ฒด๋ฅผ ๋ณด๋ ค๋ฉด ๋จผ์ ์ ํ์ ํ์ด์ผ ํ๋ค.\n\n ์์ฑ ํจ๋์ ๋น ์ํ๋ ๊ทธ๋์ **์ด์์ ๋ ํ ๋ฒ๋ ์ ๋ณด์๋ค.** ์ฒ์ ์ฌ๋ ์ฌ๋์๊ฒ\n ใ์ผ์ชฝ์์ ๋ถํ์ ๊ณ ๋ฅด๋ ๋๊ตฌใ๋ผ๊ณ ์๋ ค ์ค ์๋ฆฌ๊ฐ ๊ทธ ํ๋ฉด์ด๋ค.\n\n ์๋ก ๋ง๋ค ๋(`startNew`)๋ ๋ค๋ฅด๋ค. ๋ฐฉ๊ธ ๋ถํ์ ๋ง๋ค์์ผ๋ ๋ฐ๋ก ํธ์งํ๋ ค๋ ๊ฒ์ด ๋ง๋ค.\n */\n this.selected = -1\n this.dirty = false\n this.violations = []\n this.undoStack = []\n this.redoStack = []\n this.lastCoalesceKey = undefined\n }\n\n /** ์ง์ ๋ฐํํ์ ๊ฐ์ ธ๋ค ๋๋ค. ๋ชป ์ฝ์ผ๋ฉด ๊ฒฌ์ฃผ์ง ์๋๋ค โ ์๋ ํ์ ์ ์ง์ด๋ด์ง ์๋๋ค. */\n private async loadReleased(id: string, generation: number) {\n try {\n const source = await fetchReleasedSource(id)\n if (generation !== this.loadGeneration || !this.active) return\n this.releasedSource = source ? (JSON.parse(source) as FigureSource) : undefined\n } catch (e) {\n console.warn(`[figure] ์ง์ ๋ฐํํ์ ์ฝ์ง ๋ชปํ์ต๋๋ค โ ${(e as Error).message}`)\n }\n }\n\n private startNew() {\n ++this.loadGeneration\n this.proposalSession = undefined\n this.proposalBaseSource = undefined\n this.proposalFeedback = []\n this.mode = 'edit'\n // ํ์
์ด๋ฆ์ ์ฌ๋์ด ์ ํ๊ธฐ ์ ๊น์ง๋ ์์ ์ด๋ฆ์ ์ด๋ค. ์ ์ฅํ ๋ ํ์ ํ๋ค.\n const draftType = placeholderType()\n const { draft, parts } = startingModel(draftType)\n\n this.figure = { id: '', type: draftType, name: '' } as Figure\n this.draft = draft\n this.parts = parts\n /* ๊ณ ๋ฅธ ๊ฒ์ด ์๋ค โ ๋ถํ์ด ์์ผ๋ ์์ฑ ํจ๋๋ ๊ณ ๋ฅผ ๊ฒ์ ๊ธฐ๋ค๋ฆฐ๋ค. */\n this.selected = -1\n this.dirty = true\n this.violations = []\n this.undoStack = []\n this.redoStack = []\n this.lastCoalesceKey = undefined\n }\n\n private rename(name: string) {\n if (!this.figure) return\n\n this.figure = { ...this.figure, name }\n this.dirty = true\n }\n\n private typeChanged(type: string) {\n if (!type || this.figure?.id) return\n const sanitized = type.replace(/[^A-Za-z0-9_]/g, '_').toUpperCase()\n if (this.draft) this.draft.figureType = sanitized\n this.figure = { ...this.figure, type: sanitized } as Figure\n this.folded = this.draft ? toFigureSource(this.draft, this.parts) : undefined\n this.dirty = true\n }\n\n /**\n * ๋ถ๋ฅ์ ํ๊ทธ๋ฅผ ๊ณ ์น๋ค.\n *\n * ์ ๋ณธ(`source`)์ด ์๋๋ผ **์นดํ๋ก๊ทธ์ ๊ฐ**์ด๋ค โ ๋ํ์ด ๋ฌด์์ผ๋ก ์๊ฒผ๋์ง๊ฐ ์๋๋ผ ์ด๋์\n * ๊ฑธ๋ฆฌ๋์ง๋ค. ๊ทธ๋์ ์ ์๋ ๋ฐํ๋ ํ๋ค๋ฆฌ์ง ์๋๋ค.\n */\n private catalog(patch: { category?: string; tags?: string[] }) {\n if (!this.figure) return\n\n this.figure = { ...this.figure, ...patch }\n this.dirty = true\n }\n\n private snapshotState(): { draft?: FigureDraft; parts: PartModel[]; selected: number } {\n return {\n draft: this.draft ? structuredClone(this.draft) : undefined,\n parts: structuredClone(this.parts),\n selected: this.selected\n }\n }\n\n private recordHistory(coalesceKey?: string) {\n const now = Date.now()\n if (coalesceKey && this.lastCoalesceKey === coalesceKey && now - this.lastHistoryTime < 600) {\n this.lastHistoryTime = now\n return\n }\n\n this.lastCoalesceKey = coalesceKey\n this.lastHistoryTime = now\n\n this.undoStack = [...this.undoStack.slice(-49), this.snapshotState()]\n this.redoStack = []\n }\n\n private undo() {\n if (this.undoStack.length === 0) return\n const prev = this.undoStack[this.undoStack.length - 1]\n this.undoStack = this.undoStack.slice(0, -1)\n this.redoStack = [this.snapshotState(), ...this.redoStack.slice(0, 49)]\n\n this.draft = prev.draft ? structuredClone(prev.draft) : undefined\n this.parts = structuredClone(prev.parts)\n this.selected = this.parts.length ? Math.max(-1, Math.min(prev.selected, this.parts.length - 1)) : -1\n this.dirty = true\n this.lastCoalesceKey = undefined\n }\n\n private redo() {\n if (this.redoStack.length === 0) return\n const next = this.redoStack[0]\n this.redoStack = this.redoStack.slice(1)\n this.undoStack = [...this.undoStack.slice(-49), this.snapshotState()]\n\n this.draft = next.draft ? structuredClone(next.draft) : undefined\n this.parts = structuredClone(next.parts)\n this.selected = this.parts.length ? Math.max(-1, Math.min(next.selected, this.parts.length - 1)) : -1\n this.dirty = true\n this.lastCoalesceKey = undefined\n }\n\n /**\n * ๋ถํ ๋ชฉ๋ก์ ๊ฐ์ ๋ผ์ด๋ค.\n *\n * ํธ์ง ๊ท์น์ `part-edits` ๊ฐ ๊ฐ๋๋ค โ ํ๋ฉด๊ณผ ํ
์คํธ๊ฐ ๊ฐ์ ๊ฒ์ ์ฐ๊ฒ ํ๋ ค๊ณ ๋ผ์ด\n * ๋์๋ค. ์ฌ๊ธฐ์๋ ๊ฒฐ๊ณผ๋ฅผ ๋ด๊ณ ์ ํ ์ธ๋ฑ์ค๋ฅผ ์ ๋ฆฌํ๋ค.\n */\n private put(parts: PartModel[], selected = this.selected, coalesceKey?: string) {\n this.recordHistory(coalesceKey)\n this.parts = parts\n this.selected = Math.min(selected, parts.length - 1)\n this.dirty = true\n }\n\n private addPart(primitive: PrimitiveKind) {\n if (!this.draft) return\n // ์ถ๊ฐํ ๊ฒ์ ๋ฐ๋ก ์์ ํ ์ ์๊ฒ ์ ํ ์ํ๋ก ๋๋ค.\n this.put(edits.addPart(this.draft, this.parts, primitive), this.parts.length)\n }\n\n private removePart(index: number) {\n this.put(edits.removePart(this.parts, index), Math.max(0, index - 1))\n }\n\n private duplicatePart(index: number) {\n this.put(edits.duplicatePart(this.parts, index), index + 1)\n }\n\n private movePart(index: number, to: number) {\n this.put(edits.movePart(this.parts, index, to), to)\n }\n\n private updatePart(index: number, part: PartModel) {\n this.put(edits.updatePart(this.parts, index, part), this.selected, `part:${part.name || index}`)\n }\n\n /**\n * ํ ์์ฒด์ ๊ฐ์ ๊ฐ์ ๋ผ์ด๋ค โ ๋ฅ๋ ฅ์ฒ๋ผ ๋ถํ๋ณด๋ค ์์ ์๋ ๊ฒ๋ค.\n *\n * ๋ถํ ๋ชฉ๋ก์ ๊ฑด๋๋ฆฌ์ง ์๋๋ค. `put` ์ ๋ถํ์ ํจ๊ป ๋ฐ์ผ๋ฏ๋ก ์ฌ๊ธฐ์ ์ฐ๋ฉด ๋ฅ๋ ฅ ํ๋๋ฅผ\n * ๊ณ ์น ๋๋ง๋ค ๋ถํ ๋ชฉ๋ก์ด ์ ๋ฐฐ์ด์ด ๋๊ณ , ๊ทธ๋ฆฌ๋ ์ชฝ์ด ์ ๋ถ ๋ค์ ๊ทธ๋ฆฐ๋ค.\n */\n /**\n * ๋ฏธ๋ฆฌ๋ณด๊ธฐ์์ ์ธ์ด ์์ธ๋ฅผ ํ๋ผ๋ฏธํฐ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ํ๋ค.\n *\n * ๊ด์ ์ด ์๋ ๋ํ์ ๊ฐ์ด 0 ์ธ ์์ธ(ํด์ง ์์ธ)๊ฐ ๊ณง๊ฒ ์ ๊ธฐ๋ฅ์ด๋ผ, ๊ธฐ๋ณธ๊ฐ์ด ์์ผ๋ฉด ๋ชฉ๋ก๊ณผ\n * ๋๋ฉด์์ ๊ทธ ๋ชจ์์ผ๋ก ์ ๋ค. ์ ์์๊ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์์ ๋ง์ถ ์์ธ๊ฐ ๊ณง ๊ทธ ๋ต์ด๋ค.\n */\n private poseAsDefault(values: Record<string, number>) {\n if (!this.draft) return\n\n const next = poseAsDefaults(this.draft, values)\n /* ์ํ ๊ฒ์ด ์์ผ๋ฉด ์ด์์ด ๊ทธ๋๋ก ์จ๋ค. ๊ทธ๋ ๋๋๋ฆฌ๊ธฐ ์นธ๊ณผ ใ์ ์ฅ ์ ๋จใ์ ๋ง๋ค์ง ์๋๋ค. */\n if (next !== this.draft) this.updateDraft(next)\n }\n\n /**\n * ๊ธฐ์ค ์์๋ฅผ ๊ณ ์น๋ค โ ์ด์๊ณผ ๋ถํ์ด **ํ ๊ฑธ์์ผ๋ก** ๋ฐ๋๋ค.\n *\n * ์์๊ฐ ์ปค์ง๋ฉด ํ๊ฐ์ด๋ฐ๊ฐ ์ฎ๊ฒจ ๊ฐ๋ฏ๋ก ๋ถํ์ ๊ทธ๋งํผ ๋๋ฐ์ด์ผ ์ ์ฅ๋๋ ์๋ฆฌ๊ฐ ์ ์ง๋๋ค\n * (`base-box.ts`). ๊ทธ ๋์ ๋ฐ๋ก ๊ธฐ๋กํ๋ฉด ํ ๋ฒ ๋๋๋ ธ์ ๋ ๋ถํ์ด ๋ฐ์ฏค ๋ฐ๋ฆฐ ํ๋ฉด์ด ๋จ๋๋ค.\n */\n private resizeBase(draft: FigureDraft, parts: PartModel[]) {\n this.recordHistory('base')\n this.draft = draft\n this.parts = parts\n this.dirty = true\n }\n\n private updateDraft(draft: FigureDraft) {\n this.recordHistory('draft')\n this.draft = draft\n this.dirty = true\n }\n\n /**\n * ๋ํ
์ผ ๋ฑ๊ธ์ ๋ฐ๊พผ๋ค.\n *\n * ์ด ๊ฐ์ ๋ถํ ์ ํ๋๋ฅผ ์ ํ๊ณ ์ฑ์๋์ ํ ์ถ์ด ๋๋ค. ๋ถํ๋ณด๋ค ์์ ์๋ ๊ฐ์ด๋ผ\n * ์ด์์ ๋ด๋๋ค.\n *\n * ํ๋๋ฅผ ๋ด๋ ค์ ์ด๋ฏธ ๋ฃ์ ๋ถํ ์๋ณด๋ค ์์์ง ์ ์๋ค. ๊ทธ๋ ๋ถํ์ ์ง์ฐ์ง ์๋๋ค.\n * ๊ฒ์ฆ์ด ์๋ฐ์ผ๋ก ์๋ฆฌ๊ณ , ์ฑ์๋๊ฐ ๋ฑ๊ธ์ ์ ๋ง๋๋ค๊ณ ๋งํ๋ค. ์ ์์๊ฐ ๋ฌด์์ ๋บ์ง\n * ์ ํ ์ผ์ด์ง ๋๊ตฌ๊ฐ ์ ํ ์ผ์ด ์๋๋ค.\n */\n private changeDetailLevel(level: DetailLevel) {\n if (!this.draft) return\n\n this.recordHistory('detailLevel')\n this.draft = { ...this.draft, detailLevel: level }\n this.dirty = true\n }\n\n /**\n * ๋ถํ์ ์ ๊น ๊ฐ๋ฆฐ๋ค.\n *\n * ์ฌ์ด ์ด๋ฏธ ๊ฐ๊ณ ์๋ ์ํ๋ฅผ ์ผ๊ณ ๋๋ ๊ฒ๋ฟ์ด๋ค โ ํธ์ง ๋ชจ๋์์๋ faint ๋ก ๋ณด์ด๊ณ \n * ๋ทฐ ๋ชจ๋์์๋ ์ ๊ทธ๋ ค์ง๋ค. ์ ์ฅ ํ์์๋ ์ค๋ฆฌ์ง ์์ผ๋ฏ๋ก ๋ค์ ์ด๋ฉด ์ ๋ถ ๋ณด์ธ๋ค.\n *\n * `dirty` ๋ก ์น์ง ์๋๋ค. ์ ์ฅ๋ ๊ฒ์ด ํ๋๋ ๋ฐ๋์ง ์์๋๋ฐ \"์ ์ฅํ์ง ์์ ๋ณ๊ฒฝ\"์ด\n * ๋จ๋ฉด, ์ ์ฅ ๋ฒํผ์ด ๋ฌด์์ ์ ์ฅํ๊ฒ ๋ค๋ ๊ฒ์ธ์ง ์ ์ ์๋ค.\n */\n private toggleHidden(index: number) {\n const part = this.parts[index]\n if (!part) return\n\n this.parts = edits.updatePart(this.parts, index, { ...part, hidden: !part.hidden })\n }\n\n /**\n * ํ๊บผ๋ฒ์ ๊ฐ์ถ๊ฑฐ๋ ๋๋๋ฆฐ๋ค.\n *\n * ๋ถํ ์ค๋ฌผ์ง๋ฆฌ์์ ์์ชฝ ํ๋๋ฅผ ๋ณด๋ ค๊ณ ์ด์ํ์ ๋๋ฅด๋ ๊ฒ์ ์์ค๋ค. ํ ๋ฒ์ ๋ฐ๊พธ๋ฏ๋ก\n * ๋ชฉ๋ก์ ํ ๋ฒ๋ง ๊ฐ์ ๋ผ์ด๋ค โ ํ๋์ฉ ์ค๋ฌด ๋ฒ ๊ฐ๋ฉด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ค๋ฌด ๋ฒ ๋ค์ ์ ๋ค.\n */\n private setAllHidden(hidden: boolean) {\n this.parts = this.parts.map(part => (part.hidden === hidden ? part : { ...part, hidden }))\n }\n\n /**\n * ๋ฏธ๋ฆฌ๋ณด๊ธฐ์์ ๊ธฐ์ฆ๋ชจ๋ก ์ฎ๊ธฐ๊ฑฐ๋ 2D ์์ ๋์๋ค.\n *\n * ์๋ ค ์ค๋ ๊ฒ์ ๋ถํ **์ด๋ฆ**์ด๋ค. ๋ชฉ๋ก์ ๋ช ๋ฒ์งธ์ธ์ง๋ ์ฌ๊ธฐ์ ์ฐพ๋๋ค โ ์ด๋ฒคํธ๊ฐ\n * ์ค๋ ์ฌ์ด์ ๋ชฉ๋ก์ด ๋ฐ๋์์ผ๋ฉด ์ฐพ์ง ๋ชปํ๊ณ , ๊ทธ๋๋ ์๋ฌด๊ฒ๋ ํ์ง ์๋๋ค.\n */\n private partChanged(name: string, part: PartModel) {\n const at = this.parts.findIndex(item => item.name === name)\n if (at >= 0) this.put(edits.updatePart(this.parts, at, part), this.selected, `drag:${name}`)\n }\n\n /**\n * ์ ๋ฐ ๋ฐฐ์น ๋๊ตฌ.\n *\n * ๊ท์น์ `part-edits` ๊ฐ ๊ฐ๋๋ค. ์ฌ๊ธฐ์๋ ์ด๋ ๊ฒ์ ๋ถ๋ฅผ์ง๋ง ์ ํ๋ค.\n */\n private runTool(index: number, tool: string, axis: PlaneAxis) {\n const draft = this.draft\n if (!draft) return\n\n if (tool === 'center') this.put(edits.centerPart(draft, this.parts, index, axis))\n else if (tool === 'floor') this.put(edits.alignPartToStart(this.parts, index, axis))\n else if (tool === 'snap') this.put(edits.snapPart(draft, this.parts, index))\n // ๋์นญ ๋ณต์ ๋ ๋ถํ์ด ํ๋ ๋์ด๋๋ค โ ์๋ก ์๊ธด ๊ฒ์ ์ ํ ์ํ๋ก ๋๋ค\n else if (tool === 'mirror') this.put(edits.mirrorPart(draft, this.parts, index, axis), index + 1)\n }\n\n /**\n * ์บ๋ฒ์ค์์ ๋ถํ์ ์ ํํ๋ค.\n *\n * ์บ๋ฒ์ค๊ฐ ์๋ฆฌ๋ ๊ฒ์ **์ด๋ฆ**์ด๋ค. ๋ชฉ๋ก์ ๋ช ๋ฒ์งธ์ธ์ง๋ ์ฌ๊ธฐ์ ์ฐพ๋๋ค โ ์๋ฆผ์ด\n * ์ค๋ ์ฌ์ด์ ๋ชฉ๋ก์ด ๋ฐ๋์์ผ๋ฉด ๋ชป ์ฐพ๊ณ , ๊ทธ๋๋ ๊ณ ๋ฅธ ๊ฒ์ ๋ฐ๊พธ์ง ์๋๋ค.\n * ์๋ ์๋ฆฌ๋ฅผ ๊ณ ๋ฅด๋ฉด ์์ฑ ์นธ์ด ๋น ์ฑ๋ก ์ด๋ ค ใ์ฌ๋ผ์ก๋ใ๋ก ์ฝํ๋ค.\n */\n /** ์ง๊ธ ๊ณ ๋ฅธ ๋ถํ ์ด๋ฆ. ์บ๋ฒ์ค๊ฐ ์ธ๋ฑ์ค๊ฐ ์๋๋ผ ์ด๋ฆ์ ๋ฐ๋๋ค. */\n private get pickedName(): string | undefined {\n return this.parts[this.selected]?.name\n }\n\n /**\n * ๊ณ ๋ฅธ ๋ถํ์ ๊ด์ ์ด ์์ผ๋ฉด **๊ทธ ๊ด์ ์ด ๋๋ ์๋ฆฌ**๋ฅผ ์ ์๋ฉด์ ํจ๊ป ๊ทธ๋ฆฐ๋ค(`joint-gizmo.ts`).\n *\n * ์ถ์ ๊ณ ๋ฅด๋ ์นธ์ ์ด ํ๋ฉด์ ์๋๋ฐ ๋๋ ๋ชจ์ต์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์๋ง ์์๋ค. ๊ณ ๋ฅด๋ ์๋ฆฌ์ ๋ณด์ด๋\n * ์๋ฆฌ๊ฐ ๊ฐ๋ฆฌ๋ฉด ์ฌ๋์ ์๋ณตํ๋ฉฐ ๋ง์ถ๋ค โ ์ฌ์ฏ ์ถ์ง๋ฆฌ ๋ก๋ด์ด๋ฉด ์ฌ์ฏ ๋ฒ์ด๋ค.\n */\n private get jointGizmo(): PartModel | undefined {\n const name = this.pickedName\n if (!name || !this.draft) return undefined\n\n const joint = jointOf(this.draft, name)\n if (!joint) return undefined\n\n return gizmoPart(joint, this.parts.find(part => part.name === name), this.draft)\n }\n\n private pickPart(name: string) {\n const at = this.parts.findIndex(part => part.name === name)\n if (at >= 0) this.selected = at\n }\n\n /**\n * ๊ทธ๋ฆผ์ด ์๋ ๋ํ์ **์ด์์ ๋ ํ ๋ฒ** ์ฐ์ด ์ฑ์ด๋ค.\n *\n * ## ์ ์ฌ๊ธฐ์ธ๊ฐ\n *\n * ๋๋ฉด์ ์ ์ฅํ ๋ ์๋ฒ๊ฐ ์ฐ๋๋ค. ๊ทธ๋ฐ๋ฐ ๋ฐฑ์๋์ GPU ๊ฐ ์๋ ๋ฐฐํฌ๊ฐ ๋ง์ ํค๋๋ฆฌ์ค๋ก 3D ๋ฅผ ์ฐ๋\n * ๊ฒ์ด ์์ฃผ ์คํจํ๋ค. ๋ํ์ ๊ทธ๋ฆฌ๋ GPU ๋ ์ด๋ฏธ ๋ณด๋ ์ฌ๋ ์์ ์๊ณ , ์ฌ์ ์ง๊ธ ์ฌ๊ธฐ ์ ์๋ค.\n *\n * ์ ์๋ฉด์ ๊ฑฐ์น์ง ์๊ณ ์๊ธด ๊ฒ๋ค์ด ๊ทธ๋ฆผ์ด ์๋ค โ ์จ์์ผ๋ก ๋ฃ์ ํ๋ณธ, AI ๊ฐ ๋ธ ํ๋ณด, ๋ฐ์
ํ ์์ฐ.\n * ๊ทธ๊ฒ๋ค์ ํ ๋ฒ ์ด์ด ๋ณด๋ฉด ๊ทธ๋ ์ฑ์์ง๋ค.\n *\n * ## ์ ์ฅ์ด ์๋๋ค\n *\n * ๊ทธ๋ฆผ๋ง ๋ณด๋ธ๋ค. ์ ๋ณธ์ ๊ฑด๋๋ฆฌ์ง ์์ผ๋ฏ๋ก ๋ฏธ์ ์ฅ ํ์๋ ์ผ์ง ์๋๋ค โ ์ด์ด ๋ดค๋ค๋ ๊ฒ์ด ๊ณ ์ณค๋ค๋\n * ๋ป์ด ๋๋ฉด ์ ์์๊ฐ ์ ์ฅํ ์ง ๋ง์ง๋ฅผ ๋งค๋ฒ ๊ณ ๋ฏผํ๋ค.\n */\n /**\n * ๋ฐํ๋์๋ค โ **์ ๋ณธ์ ๋ ์๋ฆฌ๊ฐ ๊ทธ ์ฌ์ค์ ๋ฐ๋๋ค.**\n *\n * ์ด๋ ฅ ํจ๋์ ๋ฐํ์ ์ํค๊ณ ๊ฒฐ๊ณผ๋ฅผ ์๋ฆด ๋ฟ, ์ด ํ์ด์ง์ ์ํ๋ฅผ ๊ณ ์ณ ์ฐ์ง ์๋๋ค. ํ ๋ฒํธ์ ์ํ๊ฐ\n * ์ฌ๊ธฐ์ ๊ฐฑ์ ๋์ด์ผ ๋จธ๋ฆฌ์คยท์ด๋ ฅ ํญ์ด ๊ฐ์ ๊ฒ์ ๋ณธ๋ค.\n *\n * ์ ๋ณธ(source)์ ๋ฐํ์ด ๊ฑด๋๋ฆฌ์ง ์์ผ๋ฏ๋ก ๋ค์ ๋ถ๋ฌ์ค์ง ์๋๋ค โ ์ ์ ์ค์ธ ํ๋ฉด์ ๋๊ฐ์ง ์๋๋ค.\n */\n private released(figure: Figure): void {\n if (!this.figure || figure?.id !== this.figure.id) {\n return\n }\n\n this.figure = { ...this.figure, version: figure.version, state: figure.state, updatedAt: figure.updatedAt }\n }\n\n private async fillThumbnail(id: string): Promise<void> {\n await this.updateComplete\n\n const thumbnail = await captureThumbnail(this.draft, this.parts)\n if (!thumbnail || this.figure?.id !== id) {\n return\n }\n\n try {\n const { figure } = await updateFigure(id, { thumbnail })\n /* ์๋ฒ๊ฐ ์ฐ์ ์๊ฐ์ ๊ทธ๋๋ก ๋ฐ๋๋ค โ ์ด ๊ฐ์ด ๊ทธ๋ฆผ์ ๋ถ๋ฅด๋ ์ฃผ์์ ํ ๋ฒํธ๊ฐ ๋๋ค. */\n this.figure = { ...this.figure, thumbnailUpdatedAt: figure?.thumbnailUpdatedAt }\n } catch (e) {\n /* ๋ณผ ๊ถํ๋ง ์๋ ์ฌ๋์ผ ์ ์๋ค. ํ๋ฉด์ ๊ทธ๋๋ก ๋๊ณ ์กฐ์ฉํ ๋์ด๊ฐ๋ค. */\n console.warn(`[thumbnail] ${id} ๋ฅผ ์ฑ์ฐ์ง ๋ชปํ์ต๋๋ค โ ${(e as Error).message}`)\n }\n }\n\n private save() {\n if (!this.canSave || !this.folded || !this.figure) {\n return\n }\n\n if (!this.figure.id) {\n // ์ ๊ท ์ ์ฅ: ํ์
์ฝ๋์ ํ์ ์ด๋ฆ์ ๋ช
ํํ ํ์
์ผ๋ก ํ์ธ/์
๋ ฅ๋ฐ์\n let defaultType = this.draft?.figureType || this.figure.type || ''\n /*\n A placeholder is not prefilled. This used to prefill 'FIGURE', inviting the author to confirm a\n meaningless name that cannot change later and that the release gate refuses.\n */\n if (!defaultType || isPlaceholderType(defaultType)) {\n defaultType = ''\n }\n this.saveModalType = defaultType\n this.saveModalName = this.figure.name || ''\n this.saveModalError = ''\n this.showSaveModal = true\n return\n }\n\n void this.doSave()\n }\n\n private async doSave() {\n if (!this.folded || !this.figure) return\n\n this.saving = true\n this.saveFailure = ''\n this.saveModalError = ''\n\n try {\n if (!this.figure.id) {\n const typeToSave = (this.saveModalType || this.draft?.figureType || this.figure.type || 'FIGURE').trim().toUpperCase()\n const nameToSave = (this.saveModalName || this.figure.name || typeToSave).trim()\n\n if (!typeToSave) {\n throw new Error(i18next.t('figure.text.enter-a-type-name'))\n }\n\n const taken = await fetchFigureTypeNames()\n if (taken.includes(typeToSave)) {\n throw new Error(i18next.t('figure.text.type-name-already-taken', { type: typeToSave }))\n }\n\n if (this.draft) this.draft.figureType = typeToSave\n this.figure = { ...this.figure, type: typeToSave, name: nameToSave }\n this.folded = { ...this.folded, type: typeToSave }\n const sourceJson = JSON.stringify(this.folded)\n const thumbnail = await captureThumbnail(this.draft, this.parts)\n\n const result = await createFigure({\n type: typeToSave,\n name: nameToSave,\n category: this.figure.category,\n tags: this.figure.tags,\n source: sourceJson,\n thumbnail\n })\n\n this.figure = result.figure\n this.violations = result.violations\n this.showSaveModal = false\n this.dirty = false\n navigate(`figure-modeller/${result.figure.id}`)\n return\n }\n\n // ๊ธฐ์กด ๋ชจ๋ธ ์
๋ฐ์ดํธ: folded.type์ด figure.type๊ณผ ์ผ์นํ๋๋ก ๋ณด์ฅ\n if (this.figure.type && this.folded.type !== this.figure.type) {\n this.folded = { ...this.folded, type: this.figure.type }\n if (this.draft) this.draft.figureType = this.figure.type\n }\n const sourceJson = JSON.stringify(this.folded)\n const thumbnail = await captureThumbnail(this.draft, this.parts)\n\n const result = await updateFigure(this.figure.id, {\n name: this.figure.name,\n category: this.figure.category,\n tags: this.figure.tags,\n source: sourceJson,\n thumbnail\n })\n this.figure = result.figure\n this.violations = result.violations\n this.dirty = false\n } catch (e) {\n const msg = (e as Error).message\n this.saveFailure = msg\n this.saveModalError = msg\n } finally {\n this.saving = false\n }\n }\n\n /** Title of the candidate bar. A candidate opened from a release-check fix is described by translating that fix here. */\n private proposalTitle(session: proposalSessions.ProposalSession): string {\n const fix = session.fix\n if (fix) {\n return i18next.t('figure.text.release-check-fix', {\n part: fix.part,\n axis: fix.axis.toUpperCase(),\n from: fix.from ?? 'auto',\n to: fix.to\n })\n }\n return session.title || i18next.t('figure.text.assistant-proposed-a-figure')\n }\n\n private renderSaveModal() {\n if (!this.showSaveModal) return nothing\n\n return html`\n <div class=\"save-modal-backdrop\" @click=${(e: Event) => { if (e.target === e.currentTarget) this.showSaveModal = false }}>\n <div class=\"save-modal-card\" role=\"dialog\" aria-modal=\"true\">\n <h3 class=\"save-modal-title\">${i18next.t('figure.title.save-new-figure')}</h3>\n <p class=\"save-modal-desc\">${i18next.t('figure.text.save-new-figure-desc')}</p>\n\n <div class=\"save-modal-field\">\n <label>${i18next.t('figure.label.figure-type')}</label>\n <input\n .value=${this.saveModalType}\n placeholder=${i18next.t('figure.text.figure-type-example')}\n @input=${(e: Event) => (this.saveModalType = (e.target as HTMLInputElement).value.trim().toUpperCase())}\n />\n ${this.saveModalType && !releasableType(this.saveModalType)\n ? html`<div class=\"save-modal-error\">${i18next.t('figure.text.type-name-will-not-release')}</div>`\n : nothing}\n </div>\n\n <div class=\"save-modal-field\">\n <label>${i18next.t('figure.label.name')}</label>\n <input\n .value=${this.saveModalName}\n placeholder=${i18next.t('figure.text.figure-name-example')}\n @input=${(e: Event) => (this.saveModalName = (e.target as HTMLInputElement).value)}\n />\n </div>\n\n ${this.saveModalError ? html`<div class=\"save-modal-error\">${this.saveModalError}</div>` : nothing}\n\n <div class=\"save-modal-actions\">\n <button class=\"btn-cancel\" @click=${() => (this.showSaveModal = false)}>\n ${i18next.t('figure.button.cancel')}\n </button>\n <button class=\"btn-confirm\" ?disabled=${this.saving || !this.saveModalType} @click=${() => this.doSave()}>\n ${this.saving ? i18next.t('figure.text.saving-figure') : i18next.t('figure.button.save')}\n </button>\n </div>\n </div>\n </div>\n `\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-modeller-page.js","sourceRoot":"","sources":["../../client/pages/figure-modeller-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '../modeller/figure-side.js'\nimport '../modeller/figure-canvas.js'\nimport { captureThumbnail } from '../modeller/figure-thumbnail.js'\nimport '../modeller/figure-preview.js'\nimport { shouldStartNewFigure } from '../modeller/new-figure-entry.js'\nimport '../modeller/figure-parts.js'\nimport '../modeller/figure-inspector.js'\n\nimport { css, html, nothing } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { navigate, PageView } from '@operato/shell'\nimport { consumePendingFigureProposal } from '../modeller/figure-ai-target.js'\nimport { contractChanges, isPlaceholderType, placeholderType, TYPE_LENGTH, TYPE_PATTERN, validate } from '@hatiolab/figure-model'\nimport type { ContractChange, DetailLevel, FigureSource, PrimitiveKind } from '@hatiolab/figure-model'\n\nimport * as edits from '../modeller/part-edits.js'\nimport * as proposals from '../modeller/proposal.js'\nimport * as proposalSessions from '../modeller/proposal-session.js'\nimport type { ProposalSession } from '../modeller/proposal-session.js'\nimport { toFigureSource, fromFigureSource } from '../modeller/figure-source.js'\nimport type { FigureDraft, PartModel, PlaneAxis } from '../modeller/figure-source.js'\nimport { jointOf } from '../modeller/joint-edits.js'\nimport { poseAsDefaults } from '../modeller/pose-defaults.js'\nimport { gizmoPart } from '../modeller/joint-gizmo.js'\nimport { DEFAULT_VIEW } from '../modeller/figure-view.js'\nimport type { ViewSettings } from '../modeller/figure-view.js'\nimport { createFigure, fetchFigure, fetchFigureTypeNames, fetchReleasedSource, updateFigure } from '../graphql/index.js'\nimport type { Figure, FigureFinding, FigureGateFix, FigureProposal, ProposalFeedback } from '../types.js'\n\nconst FigureModellerPageBase = localize(i18next)(PageView) as typeof PageView\n\n/**\n * ์ด๋ ์นธ์ด ์ ํ ์๋. ์ผ์ชฝ์ ๋ถํ ๋ชฉ๋ก, ์ค๋ฅธ์ชฝ์ ์์ฑยทํ์ ยท์ค์ ์ด๋ค.\n *\n * ์ด๋ฆ์ fold ๋ฅผ ์ ์ด๋ค. ์ด ํ์ผ์์ ๊ทธ ๋ฑ๋ง์ ์ด๋ฏธ fold.ts ์ ๊ฒ์ด๋ค โ ํธ์ง ์ํ๋ฅผ\n * ์ ์ฅ ํ์์ผ๋ก ์ ๋๋ค๋ ๋ป์ด๋ผ ์นธ์ ์ ๋ ๊ฒ๊ณผ ์๋ฌด ์๊ด์ด ์๋ค. ํ ํ์ผ์์ ํ ๋ฑ๋ง์ด\n * ๋ ๊ฐ์ง๋ฅผ ๋ปํ๋ฉด ์ฝ๋ ์ฌ๋์ด ๋งค๋ฒ ์ด๋ ์ชฝ์ธ์ง ๊ฐ๋ ค์ผ ํ๋ค.\n */\ninterface Panes {\n left: boolean\n right: boolean\n}\n\n/**\n * ์ ์ด ๋ ๊ฒ์ **์ด ๋ธ๋ผ์ฐ์ ์๋ง** ๋จ๋๋ค.\n *\n * ์ ์ํ Figure ์ ์ค๋ฆฌ๋ ๊ฐ์ด ์๋๋ค. ํ๋ฉด์ ์ด๋ป๊ฒ ๋ฒ๋ ค ๋๊ณ ์ผํ๋๋๋ ์ฌ๋๋ง๋ค\n * ๋ค๋ฅด๊ณ , ๊ฐ์ Figure ๋ฅผ ๋ค๋ฅธ ์ฌ๋์ด ์ด์์ ๋ ๋ด ํ๋ฉด ๋ฐฐ์น๊ฐ ๋ฐ๋ผ๊ฐ๋ฉด ๊ณค๋ํ๋ค.\n * ํ๋ฉด ์ค์ (`figure-view`)์ ์ ์ฅํ์ง ์๋ ๊ฒ๊ณผ ๊ฐ์ ์ด์ ๋ค.\n *\n * ์ํฌ๋ฆฟ ์ฐฝ์ด๋ ์ฌ์ดํธ ๋ฐ์ดํฐ๋ฅผ ๋ง์ ๋ธ๋ผ์ฐ์ ์์๋ **์ฝ๋ ๊ฒ ์์ฒด๊ฐ ๋์ง๋ค.** ๊ทธ๋๋\n * ๋ ๋ค ํด์ง ์ฑ๋ก ์์ํ๋ค โ ์ ์๋ฉด์ด ์ ๋จ๋ ๊ฒ๋ณด๋ค ๋ซ๋ค.\n */\nconst PANES_KEY = 'figure-modeller.collapsed'\n\nfunction recallPanes(): Panes {\n try {\n const said = JSON.parse(localStorage.getItem(PANES_KEY) ?? 'null')\n return { left: said?.left === true, right: said?.right === true }\n } catch {\n return { left: false, right: false }\n }\n}\n\nfunction rememberPanes(panes: Panes): void {\n try {\n localStorage.setItem(PANES_KEY, JSON.stringify(panes))\n } catch {\n // ๋ชป ์ ์ด๋ ์ด๋ฒ ํ๋ฉด์ ๊ทธ๋๋ก ๋์ํ๋ค. ๋ค์์ ์ด ๋ ํด์ ธ ์์ ๋ฟ์ด๋ค.\n }\n}\n\n/**\n * ์๋ก ๋ง๋ Figure ์ ์์ ์ํ โ **๋น ์์ ํ๋๋ฟ์ด๋ค.**\n *\n * ์ ์๋ ๋ถํ(300 ์์)์ ํ๋ ๋์ ์ฃผ์๋ค. ํ์์ด ๋ถํ 0๊ฐ๋ฅผ ์ค๋ฅ๋ก ๋ณด๊ธฐ ๋๋ฌธ์ด๋ค\n * (`missing-parts` โ parts ๊ฐ ์๋ค). ๊ทธ๋์ ์๋ฌด๊ฒ๋ ์ ํ๋๋ฐ ๋ถ์ ํ์ ์ด ๋จ๋ ๊ฒ์ ํผํ๋ ค๊ณ \n * ์์๋ฅผ ๊น์๋ค.\n *\n * **๊ทธ๋ฐ๋ฐ ใ๋ฌด์กฐ๊ฑด ์์ใ๋ ๋๊ฐ ์ฒซ ๋์์ด ๊ทธ๊ฒ์ ์ง์ฐ๋ ์ผ์ด ๋๋ค** โ ์ปจ๋ฒ ์ด์ด๋ฅผ ๋ง๋ค ์ฌ๋๋,\n * ์๊ทธ๋ํ์๋ฅผ ๋ง๋ค ์ฌ๋๋ ์์๋ถํฐ ์น์ด๋ค. ๊ทธ๋์ ๋น์ด๋ค. ํ์์ ๊ทธ๋๋ก ๋๊ณ (๋ถํ ์๋ ๊ฒ์\n * ๋ฐํํ ์ ์๋ ๊ฒ์ด ๋ง๋ค) **ํ๋ฉด์ด ใ์์ง ์ ์ ์ ํจใ๊ณผ ใํ์์ ์ด๊นใ์ ๊ฐ๋ฅธ๋ค.**\n *\n * ๋น ํ๋ฉด์ด ๊ฐ๋ฅด์น๋ ์๋ฆฌ๋ค: ๋ถํ ๋ชฉ๋ก์ด ใ์์์ ๋ํ์ ๊ณจ๋ผ ์์ํ์ธ์ใ๋ฅผ ์ด๋ฏธ ๋งํ๊ณ ํ๋ ํธ๊ฐ\n * ๋ฐ๋ก ๊ทธ ์์ ์๋ค(`figure-parts`).\n */\nfunction startingModel(type: string): { draft: FigureDraft; parts: PartModel[] } {\n return {\n draft: { width: 300, height: 300, depth: 300, figureType: type, detailLevel: 'M' },\n parts: []\n }\n}\n\n/**\n * Figure ์ ์๋ฉด.\n *\n * ## ์ธ ์นธ์ด๋ค\n *\n * ์ผ์ชฝ ๋ํ ํ๋ ํธ ยท ๋ถํ ๋ชฉ๋ก ยท ์์ฑ\n * ๊ฐ์ด๋ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ โ `FigureInstance` ๋ฅผ ์ค์ ๋ก ์ธ์ด๋ค\n * ์ค๋ฅธ์ชฝ ํ๋จ โ ๋ ๋ ์๋ค\n *\n * ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ฌ ์์์ ์ค์ ๋ก ๋์ํ๋ ๊ฒ์ด ์ด ๋๊ตฌ์ ์ ์ ๋ค. **ํธ์งํ ๊ฒ์ด ๊ณง ์ค์ ๊ฒฐ๊ณผ๋ฌผ**์ด๋ผ์ผ\n * \"๋ชจ๋ธ๋ฌ์์๋ ๋๋๋ฐ ๋๋ฉด์์๋ ๋ค๋ฅด๋ค\"๊ฐ ์๊ธฐ์ง ์๋๋ค.\n *\n * ## ํธ์ง ๋ฐ์ดํฐ๋ ์ฌ ๋ชจ๋ธ ํ๋๋ฟ์ด๋ค\n *\n * ์ด ํ์ด์ง๊ฐ ๊ฐ๋ ๊ฒ์ ์ด์ ํ๋์ ๋ถํ ๋ชฉ๋ก โ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ ๊ทธ๋๋ก ์ธ์์ง๋ ์ฌ ๋ชจ๋ธ์ด๋ค.\n * ์ ์ฅ ํ์(`FigureSource`)์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ์ **๊ฒฝ๊ณ์์๋ง** ํ๋ค: ์ ์ฅํ ๋, ํ๋จํ ๋,\n * AI ํ๋ณด์ ๋น๊ตํ ๋. ๊ทธ ๋ณํ์ `figure-source.ts` ํ ๊ณณ์์๋ง ์ผ์ด๋๋ค.\n *\n * ํ๋ ํธ๋ ์์ฑ ํธ์ง๊ธฐ๋ ์ด ๋ฐ์ดํฐ๋ฅผ ์ง์ ์์ ํ์ง ์๋๋ค. ๋ฌด์์ ํ๊ฒ ๋ค๋ ๊ฒ๋ง ์๋ฆฌ๊ณ ,\n * ๋ฐ๊พธ๋ ๊ฒ์ ์ด ํ์ด์ง๋ค. ๋ ๊ณณ์์ ๊ณ ์น๋ฉด ์คํ ์ทจ์๋ ์ ์ฅ๋ ์ด๋ ์ชฝ์ด ๋ง๋์ง ์ ์\n * ์๊ฒ ๋๋ค.\n */\n/**\n * Whether this name could be released, by the format's own rules (`type-not-identifier`,\n * `type-is-placeholder`). Saving is not blocked, but the type cannot change after creation, so the\n * author has to hear it now to avoid a draft that can never be released.\n */\nfunction releasableType(type: string): boolean {\n return (\n !isPlaceholderType(type) &&\n TYPE_PATTERN.test(type) &&\n type.length >= TYPE_LENGTH.min &&\n type.length <= TYPE_LENGTH.max\n )\n}\n\n@customElement('figure-modeller-page')\nexport class FigureModellerPage extends FigureModellerPageBase {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background-color: var(--md-sys-color-surface);\n color: var(--md-sys-color-on-surface);\n /*\n ์ด ํ๋ฉด์ ๊ธ์ ํฌ๊ธฐ๋ฅผ ์ฌ๊ธฐ์ ์ ํ๋ค.\n\n ์ ์ ์ด ๋๋ฉด ๋ธ๋ผ์ฐ์ ๊ธฐ๋ณธ ํฌ๊ธฐ(16px)๋ฅผ ๋ฌผ๋ ค๋ฐ๋๋ค. ์๋ ํจ๋๋ค์ ์ ๋ถ 12px\n ์ธ์ ๋ฆฌ๋ผ ์ ๋ ์ค๋ง ์ปค ๋ณด์ด๊ณ , ๋ฒํผ์ด ํ๋ฉด ์ ์ฒด์ ๋ฐ๋ก ๋์๋ค.\n\n form ์์(input ยท button)๋ ๊ธ๊ผด์ ๋ฌผ๋ ค๋ฐ์ง ์์ผ๋ฏ๋ก ๊ฐ์ ์ ์ด์ผ ํ๋ค.\n */\n font-size: 0.76rem;\n }\n\n /* ์ธ ์นธ. 3D ๋ฅผ ๊ฐ์ฅ ํฌ๊ฒ ๋๋ค โ ์ด ๋๊ตฌ์ ์ฃผ์ด๋ ํ์์ด์ง ์์ฑํ๊ฐ ์๋๋ค */\n div[edits] {\n flex: 1;\n display: grid;\n grid-template-columns: 220px 1fr 320px;\n min-height: 0;\n overflow: hidden;\n }\n\n /*\n **์ธ ์นธ์ ์๋ฆฌ๋ฅผ ๋ชป ๋ฐ๋๋ค.**\n\n ์ด๊ฒ์ด ์์ผ๋ฉด ์ผ์ชฝ์ ์ ์์ ๋ ์ค๋ฅธ์ชฝ ์นธ์ด ๊ฐ์ด๋ฐ ์๋ฆฌ๋ก ๋ฐ๋ ค ๋ค์ด์ ์บ๋ฒ์ค๊ฐ\n ํต์งธ๋ก ์ฌ๋ผ์ง๋ค. display none ์ธ ํ์ ๋ ๊ทธ๋ฆฌ๋ ์๋ฆฌ๋ฅผ ์ฐจ์งํ์ง ์์ผ๋ฏ๋ก, ์ฒซ์งธ๊ฐ\n ๋น ์ง๋ฉด ๋๋จธ์ง๊ฐ ํ ์นธ์ฉ ๋น๊ฒจ์ง๋ค. ์ค๋ฅธ์ชฝ์ ๋ง์ง๋ง์ด๋ผ ๋น ์ ธ๋ ๋ฐ ๊ฒ์ด ์์ด์\n ๋ฉ์ฉกํ๋ค โ ํ์ชฝ๋ง ๊ณ ์ฅ ๋๋ ์ข
๋ฅ๋ค.\n\n ์ด ํ์ผ์ด ์ด๋ฏธ ํ ๋ฒ ์ ์ด ๋ ํจ์ ์ด๋ค. ์๋ div[lanes] ์ฃผ์์ ๊ฐ์ ๋ง์ด ์๋ค.\n */\n div[edits] > figure-parts {\n grid-column: 1;\n }\n div[edits] > div[middle] {\n grid-column: 2;\n }\n div[edits] > figure-side {\n grid-column: 3;\n }\n\n /*\n ์ ํ ์นธ์ **์๋ฆฌ๋ฅผ ์์ ์ ์ด๋ค.**\n\n ํญ๋ง 0 ์ผ๋ก ์ค์ด๋ฉด ์์ชฝ์ด ๋์ณ ๋์ ๊ฐ์ด๋ฐ๋ฅผ ๋ฎ๋๋ค. ๊ทธ๋ ๋ค๊ณ ๋ผ์ด ๋ด๋ฉด ์ค๋ฅธ์ชฝ\n ์นธ์ด ํผ์ณ ๋ ์ถ์ด ๊ทธ๋ฆผ ๊ฐ์ ์ํ๋ฅผ ์๋๋ค โ figure-side ๊ฐ ํญ์ ๊ฐ์ถ ๋๋ DOM ์๋\n ๋จ๊ธฐ๋ ๊ฒ๊ณผ ๊ฐ์ ์ด์ ๋ค. display none ์ด ๋์ ๋ค ์งํจ๋ค.\n\n ๊ฐ์ด๋ฐ๋ ์ ์ ๋๋ง๋ค ๋์ด๊ฐ ๋ฐ๋๋๋ฐ, ํธ์ง ์บ๋ฒ์ค์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ๊ฐ์ ResizeObserver\n ๋ฅผ ๊ฐ๊ณ ์์ด 3D ๊ฐ ์์์ ๋ฐ๋ผ์จ๋ค.\n */\n div[edits][collapse-left] {\n grid-template-columns: 0 1fr 320px;\n }\n div[edits][collapse-right] {\n grid-template-columns: 220px 1fr 0;\n }\n div[edits][collapse-left][collapse-right] {\n grid-template-columns: 0 1fr 0;\n }\n div[edits][collapse-left] > figure-parts,\n div[edits][collapse-right] > figure-side {\n display: none;\n }\n\n div[spacer] {\n flex: 1;\n }\n\n /*\n ์นธ์ ๋ฒกํฐ ์ ์๋๊ตฌ์ ๊ด๋ก๋๋ก ๋๋๋ค โ ์ผ์ชฝ์ ๋ฌด์์ด ์๋(๋ ์ด์ด), ์ค๋ฅธ์ชฝ์\n ๊ณ ๋ฅธ ๊ฒ์ ์์ฑ. ์ฐ๋ ์ฌ๋์ด ์ด๋ฏธ ์๋ ์๋ฆฌ๋ผ ๋ฐฐ์ธ ๊ฒ์ด ํ๋ ์ค์ด๋ ๋ค.\n ์ฐจ๋ณ์ฑ์ ๋ฐฐ์น๊ฐ ์๋๋ผ ๊ฐ์ด๋ฐ์ ๋ก์ฐํด๋ฆฌ 3D ์ ์์ผ๋ฏ๋ก, ๋ฐฐ์น๋ก ๋ฏ์ค๊ฒ ํ์ง\n ์๋๋ค.\n\n ์ค๋ฅธ์ชฝ์ figure-side ๊ฐ ์์ฑ๊ณผ ํ๋จ์ ํญ์ผ๋ก ๊ฒน์ณ ๋๋ค. ์์๋๋ก ๋๋๋ฉด ๋ ๋ค\n ์๋ ค์ ์์ฑ์ ์ฌ์ง๊น์ง, ํ๋จ์ ๋ฌด๊ฒ๊น์ง ๋ชป ๋ด๋ ค๊ฐ๋ค. ๊ฐ์๋ ํญ ์ด๋ฆํ์ ๋จ์\n ํ๋จ์ ๋ฎ์ด ๋์ด๋ ๋ณด์ธ๋ค.\n */\n figure-side {\n min-height: 0;\n }\n\n figure-canvas,\n figure-preview {\n min-width: 0;\n min-height: 0;\n }\n\n /*\n ํธ์ง ยท ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ ํ ๋ฐ ์กฐ์ ๋ .\n\n ๊ฐ์ด๋ฐ ์นธ ์์ ์๊ฒ ๋๋ค. ๋ฌด์์ ๋ณด๊ณ ์๋์ง๊ฐ ๋ ๋ณด์ฌ์ผ ํ๊ณ , ๋ ํ๋ฉด์ด ๊ฐ์\n ์๋ฆฌ๋ฅผ ์ฐ๋ฏ๋ก ์ด๋ ์ชฝ์ธ์ง ๋ชจ๋ฅด๋ฉด ํธ์ง์ด ์ ๋จน๋ ๊ฒ์ฒ๋ผ ์ฝํ๋ค.\n */\n div[modes] {\n display: flex;\n align-items: center;\n flex: none;\n gap: 2px;\n padding: 4px var(--spacing-medium, 8px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n div[modes] button[mode] {\n padding: 3px 12px;\n font: var(--label-font, inherit);\n font-size: 0.74rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n background: none;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n }\n div[modes] button[mode]:hover:not([on]) {\n background-color: var(--md-sys-color-surface-container);\n }\n div[modes] button[mode][on] {\n font-weight: 700;\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n }\n div[modes] div[separator] {\n width: 1px;\n height: 16px;\n margin: 0 4px;\n background-color: var(--md-sys-color-outline-variant);\n }\n div[modes] button[history] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 26px;\n height: 26px;\n padding: 0;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n background: none;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n }\n div[modes] button[history]:hover:not([disabled]) {\n background-color: var(--md-sys-color-surface-container);\n color: var(--md-sys-color-on-surface);\n }\n div[modes] button[history][disabled] {\n opacity: 0.3;\n cursor: default;\n }\n div[modes] button[history] md-icon {\n --md-icon-size: 18px;\n }\n div[modes] button[collapse] {\n display: flex;\n align-items: center;\n flex: none;\n padding: 2px 3px;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n background: none;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n }\n div[modes] button[collapse]:hover {\n background-color: var(--md-sys-color-surface-container);\n }\n div[modes] button[collapse] md-icon {\n --md-icon-size: 18px;\n }\n div[modes] span[dirty] {\n align-self: center;\n margin-right: 6px;\n font: var(--label-font, inherit);\n font-size: 0.72rem;\n color: var(--md-sys-color-tertiary);\n }\n div[modes] span[save-failed] {\n align-self: center;\n max-width: 240px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin-right: 6px;\n padding: 3px 7px;\n font: var(--label-font, inherit);\n font-size: 0.7rem;\n color: var(--md-sys-color-on-error-container, var(--md-sys-color-on-surface));\n background-color: var(--md-sys-color-error-container);\n border-radius: 4px;\n }\n div[modes] button[save] {\n padding: 4px 14px;\n margin-right: 4px;\n font: var(--label-font, inherit);\n font-size: 0.74rem;\n font-weight: 600;\n color: var(--md-sys-color-on-primary, #fff);\n background-color: var(--md-sys-color-primary);\n border: none;\n border-radius: 6px;\n cursor: pointer;\n }\n div[modes] button[save]:hover:not([disabled]) {\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n }\n div[modes] button[save][disabled] {\n opacity: 0.35;\n cursor: default;\n }\n /*\n ํ๋ณด๊ฐ ์ค๋ฉด ๊ฐ์ด๋ฐ๋ฅผ ๋๋ก ๋๋๋ค.\n\n ์ซ์์ JSON ์ผ๋ก ์น๋์ ๋ฐ์ง ์๋๋ค โ ์ ์ํ ๊ฒ์ด ๊ณง ์ค๋ฌผ์ด๋ฏ๋ก **๋ ๋ค ์ธ์\n ๋๊ณ ** ๊ณ ๋ฅด๊ฒ ํ๋ค. ๋๋ํ ๋์ง ์์ผ๋ฉด ๋ฌด์์ด ๋ฌ๋ผ์ก๋์ง ๊ธฐ์ต์ผ๋ก ๊ฒฌ์ค์ผ ํ๋ค.\n */\n /*\n ์ธ๋ก๋ก ์์ ๋๋ค. ๊ทธ๋ฆฌ๋๋ก ๋์๋๋ ํ๋ณด๊ฐ ์์ ๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ฒซ ์ค(auto)์\n ๋จ์ด์ ธ **๋์ด๊ฐ 0** ์ด ๋๋ค โ 3D ๊ฐ ํต์งธ๋ก ์ฌ๋ผ์ก๋ค. display:none ์ธ ํ์ ๋\n ๊ทธ๋ฆฌ๋ ์๋ฆฌ๋ฅผ ์ฐจ์งํ์ง ์๋๋ค.\n */\n div[middle] {\n display: flex;\n flex-direction: column;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n }\n /*\n ๊ฐ์ด๋ฐ๋ฅผ ์ฑ์ด๋ค. ๋ ๋ค ์ ์ด์ผ ํ๋ค โ ํ๋๋ง ์ ์ผ๋ฉด ๊ฐ์ถฐ์ก๋ค ๋ํ๋ ์ชฝ์ด ๋์ด 0 ์ด\n ๋์ด ํ๋ฉด์ด ํ์๊ฒ ๋ฌ๋ค. ์ค์ ๋ก ๊ทธ๋ ๊ฒ ๋ฌ๋ค.\n */\n div[middle] > figure-canvas,\n div[middle] > figure-preview {\n flex: 1;\n }\n div[lanes] {\n flex: 1;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1px;\n min-height: 0;\n background-color: var(--md-sys-color-outline-variant);\n }\n div[lane] {\n display: grid;\n grid-template-rows: auto 1fr;\n min-width: 0;\n min-height: 0;\n background-color: var(--md-sys-color-surface);\n }\n div[lane] h4 {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0;\n padding: 5px var(--spacing-medium, 8px);\n font: var(--label-font, inherit);\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 div[lane][candidate] h4 {\n color: var(--md-sys-color-primary);\n }\n div[lane] h4 small {\n font-weight: 400;\n letter-spacing: 0;\n text-transform: none;\n }\n\n /* ๋ฐ๊ฑฐ๋ ๋ฒ๋ฆฐ๋ค. ๊ทธ ์ฌ์ด์ ๋ค๋ฅธ ๊ฒ์ ์๋ค */\n div[decide] {\n display: flex;\n align-items: center;\n gap: var(--spacing-medium, 8px);\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n background-color: var(--md-sys-color-primary-container);\n color: var(--md-sys-color-on-primary-container);\n font-size: 0.76rem;\n }\n div[decide] div[spacer] {\n flex: 1;\n }\n div[decide] button {\n padding: 5px 14px;\n font: var(--label-font, inherit);\n border-radius: 6px;\n cursor: pointer;\n }\n button[take] {\n color: var(--md-sys-color-on-primary, #fff);\n background-color: var(--md-sys-color-primary);\n border: none;\n }\n button[drop] {\n color: inherit;\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n }\n button[take][disabled] {\n opacity: 0.4;\n cursor: default;\n }\n\n /* AI์ ํ๊ฐ๋ ํ์ ๋ฌธ์ด ์๋๋ผ ์๋ฝ ์ ์ ์ฝ์ ๊ทผ๊ฑฐ๋ค. ์จ๊ธฐ์ง ์๊ณ ๋ณ๊ฒฝ ์นฉ ์์ ๋๋ค. */\n div[quality-review] {\n padding: 7px var(--spacing-large, 12px);\n background-color: var(--md-sys-color-primary-container);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n color: var(--md-sys-color-on-primary-container);\n font-size: 0.72rem;\n line-height: 1.45;\n }\n div[quality-review][review] {\n background-color: var(--md-sys-color-tertiary-container);\n color: var(--md-sys-color-on-tertiary-container);\n }\n div[quality-review] strong { display: block; font-size: 0.74rem; }\n div[quality-review] ul { margin: 4px 0 0; padding-left: 18px; }\n div[proposal-note] {\n padding: 6px var(--spacing-large, 12px) 8px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n background-color: var(--md-sys-color-surface-container-low);\n }\n div[proposal-note] label { display: block; font-size: 0.71rem; color: var(--md-sys-color-on-surface-variant); }\n div[proposal-note] input {\n box-sizing: border-box;\n width: 100%;\n margin-top: 4px;\n padding: 5px 7px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 5px;\n color: var(--md-sys-color-on-surface);\n background: var(--md-sys-color-surface);\n font: inherit;\n }\n\n /*\n ๋ฌด์์ ๋ฐ๊พธ์๋ ๊ฒ์ธ๊ฐ โ ์นฉ ํ๋๊ฐ ๋ณ๊ฒฝ ํ๋๋ค.\n\n ํต์งธ๋ก๋ง ๋ฐ๊ฒ ๋๋ฉด ใ๋ชธํต์ ์ข์๋ฐ ๋ชจํฐ ์๋ฆฌ๊ฐ ํ๋ ธ๋คใ์ ๋ตํ ์ ์๋ค. ๊ทธ๊ฒ\n ๊ฐ์ฅ ํํ ๋ฐ์์ด๋ค. ์ฒ์์๋ ์ ๋ถ ๊ณจ๋ผ ๋๋ค โ ํต์งธ๋ก ๋ฐ๋ ๊ฒ์ด ๋ณดํต์ ๊ธธ์ด๊ณ ,\n ๋นผ๊ณ ์ถ์ ๊ฒ๋ง ๋๋ฉด ๋๋ค.\n */\n div[changes] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n padding: 0 var(--spacing-large, 12px) var(--spacing-medium, 8px) var(--spacing-large, 12px);\n background-color: var(--md-sys-color-primary-container);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n button[change] {\n display: flex;\n align-items: center;\n gap: 3px;\n padding: 2px 9px 2px 5px;\n font: var(--label-font, inherit);\n font-size: 0.72rem;\n color: var(--md-sys-color-on-surface-variant, 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: 999em;\n cursor: pointer;\n }\n button[change][on] {\n color: var(--md-sys-color-on-primary, #fff);\n background-color: var(--md-sys-color-primary);\n border-color: transparent;\n }\n button[change] md-icon {\n --md-icon-size: 14px;\n }\n /* ์ ๊ณ ๋ฅธ ๊ฒ์ ๊ธ์์ ์ค์ ๊ทธ์ด ใ์ ๋ฐ๋๋คใ๋ฅผ ๋งํ๋ค */\n button[change]:not([on]) span[key] {\n text-decoration: line-through;\n }\n\n /* ๊ณ ๋ฅธ ์กฐํฉ์ด ํ์์ ์ด๊ธฐ๋ฉด ๋ฏธ๋ฆฌ ์๋ฆฐ๋ค. ์ ํํ ๋ค์ ๊ฑฐ์ ๋นํ๋ ๊ฒ๋ณด๋ค ๋ซ๋ค */\n /* ์ ์ฑ
์ ๋์ ๊ฒ์ ๋ง์ง ์๋๋ค โ ์๋ฆฌ๊ธฐ๋ง ํ๋ค. ์์ผ๋ก ๊ฐ๋ผ ๋๋ค */\n p[blocked][warn] {\n color: var(--md-sys-color-tertiary);\n }\n p[blocked] {\n margin: 0;\n padding: 0 var(--spacing-large, 12px) var(--spacing-medium, 8px) var(--spacing-large, 12px);\n background-color: var(--md-sys-color-primary-container);\n font-size: 0.72rem;\n line-height: 1.5;\n color: var(--md-sys-color-error);\n }\n .save-modal-backdrop {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1000;\n }\n .save-modal-card {\n background: var(--md-sys-color-surface-container-high, #fff);\n color: var(--md-sys-color-on-surface, #1f1f1f);\n border-radius: 12px;\n padding: 24px;\n width: 380px;\n max-width: 90vw;\n box-shadow: 0 12px 36px rgba(0, 0, 0, 0.28);\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n .save-modal-title {\n margin: 0;\n font-size: 1.15rem;\n font-weight: 700;\n }\n .save-modal-desc {\n margin: 0;\n font-size: 0.8rem;\n color: var(--md-sys-color-on-surface-variant, #666);\n }\n .save-modal-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n .save-modal-field label {\n font-size: 0.76rem;\n font-weight: 600;\n color: var(--md-sys-color-on-surface-variant, #555);\n }\n .save-modal-field input {\n padding: 8px 10px;\n border: 1px solid var(--md-sys-color-outline, #ccc);\n border-radius: 6px;\n font-size: 0.88rem;\n background: var(--md-sys-color-surface, #fff);\n color: inherit;\n }\n .save-modal-error {\n color: var(--md-sys-color-error, #b00020);\n font-size: 0.78rem;\n }\n .save-modal-actions {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 8px;\n }\n .save-modal-actions button {\n padding: 6px 14px;\n border-radius: 6px;\n font-size: 0.82rem;\n cursor: pointer;\n border: none;\n }\n .save-modal-actions .btn-cancel {\n background: none;\n color: var(--md-sys-color-on-surface, inherit);\n }\n .save-modal-actions .btn-confirm {\n background: var(--md-sys-color-primary, #0066cc);\n color: var(--md-sys-color-on-primary, #fff);\n font-weight: 600;\n }\n .save-modal-actions .btn-confirm:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n `\n\n /** ํธ์ง ์ค์ธ Figure. ์๋ก ๋ง๋๋ ์ค์ด๋ฉด `id` ๊ฐ ์๋ค. */\n @state() private figure?: Figure\n /** ํธ์ง ๋ฐ์ดํฐ โ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์ ๊ทธ๋๋ก ์ธ์์ง๋ ์ฌ ๋ชจ๋ธ์ด๋ค. */\n @state() private draft?: FigureDraft\n @state() private parts: PartModel[] = []\n @state() private selected = -1\n /*\n ์ ์ ํ๋ฉด์ **๋ณด๊ธฐ ์ค์ **. ์กฐ๋ช
ยท ๋ฐ๋ฅ ยท ์ถ ๊ฐ์ด๋ ๊ฐ์ ๊ฒ์ด๋ค.\n\n ์์ฐ์ด ์๋๋ผ ์์
๋๋ผ ์ ์ฅ๋์ง ์๋๋ค โ `toFigureSource` ๊ฐ ์ง์ด ๊ฐ์ง ์๋๋ค.\n ์์ธํ ๊ฒ์ `modeller/figure-view.ts` ๋ฅผ ๋ณด๋ผ.\n */\n @state() private view: ViewSettings = DEFAULT_VIEW\n /**\n * ๊ฐ์ด๋ฐ ์นธ์ด ๋ฌด์์ ๋ณด์ด๋.\n *\n * ํธ์ง ์บ๋ฒ์ค๋ ๋ ๊ธฐ์ค ํฌ๊ธฐ๋ค. ๊ทธ๋ฐ๋ฐ ์ด ํ์์ ๊ฐ ์ ๋ฐ์ ํฌ๊ธฐ๊ฐ ๋ฌ๋ผ์ก์ ๋ ์ด๋ป๊ฒ\n * ๋ฐ์ํ๋๊ฐ์ ์๋ค. ๊ทธ๊ฒ์ ๋ณผ ์๋ฆฌ๊ฐ ์์๋ค.\n */\n @state() private mode: 'edit' | 'preview' = 'edit'\n /**\n * ์ด๋ ์นธ์ด ์ ํ ์๋.\n *\n * ํต์งธ๋ก ๊ฐ์ ๋ผ์ด๋ค โ ์์ชฝ ๊ฐ๋ง ๋ฐ๊พธ๋ฉด Lit ์ด ๊ฐ์ ๊ฐ์ฒด๋ก ๋ณด๊ณ ๋ค์ ๊ทธ๋ฆฌ์ง ์๋๋ค.\n */\n @state() private collapsed: Panes = recallPanes()\n @state() private dirty = false\n @state() private saving = false\n @state() private violations: FigureFinding[] = []\n /**\n * ์ ์ฅ์ด ์ ์ ๋๋.\n *\n * **`save()` ์ `catch` ๊ฐ ์์๋ค.** `try โฆ finally` ๋ฟ์ด๋ผ ์๋ฒ๊ฐ ๊ฑฐ์ ํ๋ฉด(ํ์ ์๋ฐ ยท ํ์
์ด๋ฆ\n * ์ค๋ณต ยท ๊ถํ ์์ ยท ๋คํธ์ํฌ) ๋จ์ถ๋ง ๋ฉ์ถ๊ณ ํ๋ฉด์ **์๋ฌด ๋ง๋ ํ์ง ์์๋ค.** ์ ์์๋ ๋๋ ๋๋ฐ\n * ์๋ฌด ์ผ๋ ์ ๋ ๊ฒ์ผ๋ก ๋ณด๊ณ , ์ ์ฅ๋๋์ง ์๋์ง๋ ์ ์ ์์๋ค.\n *\n * ๋ฏธ์ ์ฅ ํ์(`dirty`)๋ ๊ทธ๋๋ก ๋จ์ผ๋ฏ๋ก ๋ฐ์ดํฐ๋ฅผ ์์ง๋ ์์๋ค. ์์ ๊ฒ์ **์ฌ์ **๋ค.\n */\n @state() private saveFailure = ''\n @state() private showSaveModal = false\n @state() private saveModalType = ''\n @state() private saveModalName = ''\n @state() private saveModalError = ''\n /** ์ ์ ๋ณด์กฐ ๋๋ ๋ฐํ ๊ฒ์ดํธ๊ฐ ์ฐ ํ๋ณด ๊ฒํ ์ธ์
. ๋ฐ๊ธฐ ์ ์๋ ์ ๋ณธ์ด ์๋๋ค. */\n @state() private proposalSession?: ProposalSession\n /** ์ธ๋ผ์ธ ์์ฒญ์ฐฝ๊ณผ AI ๋ํฌ๊ฐ ํจ๊ป ์ฐ๋ ํ์ฌ Figure์ ์ ํ๋ ์ธ์
ํผ๋๋ฐฑ. */\n @state() private proposalFeedback: ProposalFeedback[] = []\n\n @state() private undoStack: { draft?: FigureDraft; parts: PartModel[]; selected: number }[] = []\n @state() private redoStack: { draft?: FigureDraft; parts: PartModel[]; selected: number }[] = []\n @state() private sceneRevision = 0\n private lastCoalesceKey?: string\n private lastHistoryTime = 0\n\n /**\n * ์ ์ฅ ํ์์ผ๋ก ๋ณํํ ๊ฒ. ์ฌ ๋ชจ๋ธ์ด ๋ฐ๋ ๋๋ง ๋ค์ ๋ง๋ ๋ค.\n *\n * ์ ์ฅยทํ๋จยทAI ํ๋ณด ๋น๊ต๊ฐ ์ด๊ฒ์ ์ด๋ค. ๋ ๋๋งํ ๋๋ง๋ค ์๋ก ๋ง๋ค๋ฉด ํ๋จ ํจ๋์ด ๋งค๋ฒ\n * ๋ค์ ๊ณ์ฐํ๋ฏ๋ก, ๋ณํ์ `willUpdate` ์์ ํ ๋ฒ๋ง ํ๋ค.\n */\n private folded?: FigureSource\n\n /**\n * ์ง์ ๋ฐํํ์ ์ ๋ณธ. ํ ๋ฒ๋ ๋ฐํ ์ ํ ๋ํ์๋ ์๋ค.\n *\n * ๋ฐํ๋ ๋ํ์ ๊ณ ์น๋ ๋์ ใ์ด ๊ณ ์นจ์ด ์ด๋ฏธ ๋์ธ ๊ฒ์ ๊นจ๋ใ๋ฅผ ๊ฒฌ์ฃผ๋ ค๋ฉด ์ด๊ฒ์ด ์์ด์ผ ํ๋ค.\n * ์ ์ฅ ์ ์ด์์ ์๋ฒ๊ฐ ๋ชจ๋ฅด๋ฏ๋ก ํ์ ๋ ์ฌ๊ธฐ์ ํ๋ค โ ํ์์ ๊ฐ์ ํจ์๋ฅผ ์ด๋ค(ADR-0063 ๊ฒฐ์ 3).\n */\n @state() private releasedSource?: FigureSource\n\n /** ์ง๊ธ ๊ณ ์น ๊ฒ์ด ๋์ธ ๊ฒ์ ๋ฌด์์ ํ๋. ๋ฐํ ์ ์๋ ๋น์ด ์๋ค. */\n @state() private contract: ContractChange[] = []\n\n /** ๊ฒฌ์ฃผ์ง ๋ชปํ ๊น๋ญ. **๋น์ด ์๋ ๋ชฉ๋ก๊ณผ ๋ค๋ฅด๋ค** โ ใ๊นจ์ง ์๋๋คใ๊ฐ ์๋๋ผ ใ๋ชจ๋ฅธ๋คใ๋ค. */\n @state() private contractFailure?: string\n\n willUpdate(changed: Map<string, unknown>) {\n if (changed.has('draft') || changed.has('parts') || changed.has('releasedSource')) {\n this.folded = this.draft ? toFigureSource(this.draft, this.parts) : undefined\n this.contract = this.compareWithReleased()\n }\n }\n\n /**\n * ๊ณ ์น๋ ์ค์ ์ ๋ณธ์ **์ ๊น ํ์์ ๋ชป ์ง๋ ์ ์๋ค** โ ๋ถํ ์ด๋ฆ์ ์ง์ ๋ค๊ฐ ๋ค์ ์ ๋ ์ฌ์ด๊ฐ\n * ๊ทธ๋ ๋ค. ๊ทธ๋ ๊ฒฌ์ฃผ๊ธฐ๊ฐ ๋์ง๋ฉด ํ๋ฉด์ด ํต์งธ๋ก ๋ฉ์ถ๋ฏ๋ก ๋ชฉ๋ก์ ๋น์ด๋ค.\n *\n * **๋น ๋ชฉ๋ก์ ใ๊นจ์ง ์๋๋คใ๋ก ๋ณด์ด๊ฒ ๋์ง ์๋๋ค.** ๊น๋ญ์ ํจ๊ป ๋ค๊ณ ์๋ค๊ฐ ํ๋ฉด์ด ใํ์ธํ์ง\n * ๋ชปํ๋คใ๋ก ๋งํ๋ค. ์กฐ์ฉํ ๋น์ฐ๋ฉด ์ ์์๋ ์์ ํ๋ค๊ณ ์ฝ๋๋ค โ ์ค์ ๋ก ๊ทธ๋ฐ ์ผ์ด ๋ฌ๋ค: ์ฑ์\n * ๋ ํ์์ด ์ ํ์ด๋ผ ๊ฒฌ์ฃผ๋ ํจ์ ์์ฒด๊ฐ ์์๋๋ฐ, ํ๋ฉด์ ์๋ฌด ๋ง๋ ์ ํ๊ณ ์กฐ์ฉํ๋ค.\n */\n private compareWithReleased(): ContractChange[] {\n this.contractFailure = undefined\n if (!this.releasedSource || !this.folded) return []\n\n try {\n return contractChanges(this.releasedSource, this.folded)\n } catch (e) {\n this.contractFailure = (e as Error).message\n return []\n }\n }\n\n /**\n * ํ์ด์ง ๋ฐ AI ๋ํฌ์๋ **์ง๊ธ ์์ ๋ ์ ๋ณธ**์ ์๋ ค ์ค๋ค.\n *\n * asidebar ๋ํฌ๋ ์ฃผ์์ id๋ง\n * ์์์ผ๋ฏ๋ก DB์ ์ ์ฅ๋ ์ ํ์ ์ฝ์๋ค. ์ ์ฅ ์ ๋ณ๊ฒฝ์ ๋๊ณ \"์ ๋ฐํ์ด ์ ๋๋\" ๋๋\n * \"์ด ๋ถํ์ ์ค์ฌ ๋ฌ๋ผ\"๊ณ ๋ฌผ์ผ๋ฉด ๋ํ๊ฐ ์๋ฑํ ํ์ ๋ณด๊ฒ ๋๋ ๊ฒฐํจ์ด์๋ค.\n *\n * ์ด ์ด๋ฒคํธ๋ ์ ์ฅํ์ง ์๋๋ค. ๋ํฌ๊ฐ ๋ํ ์ธ์๋ก๋ง ์ ์ ๋ค๊ณ ์๊ณ , ์๋ฒ ๋๊ตฌ๋ ๋๋ฉ์ธ ์์\n * Figure๋ฅผ ๋จผ์ ํ์ธํ ๋ค์๋ง ์ด source๋ฅผ ์ฌ์ฉํ๋ค. ํ์ด์ง๋ฅผ ๋ ๋ ๋๋ ์๋์์ ์ง์ ์ค๋๋\n * ์ด์์ด ๋ค์ Figure์ ์์ด์ง ์๊ฒ ํ๋ค.\n */\n updated(changed: Map<string, unknown>) {\n if (changed.has('figure') && (changed.get('figure') as Figure | undefined)?.id !== this.figure?.id) {\n this.proposalFeedback = []\n }\n if (changed.has('draft') || changed.has('parts') || changed.has('figure')) {\n window.dispatchEvent(\n new CustomEvent('figure-ai-context', {\n detail: { figureId: this.figure?.id, source: this.folded }\n })\n )\n }\n }\n\n private announceAiContext = () => {\n if (!this.active) return\n window.dispatchEvent(new CustomEvent('figure-ai-context', {\n detail: { figureId: this.figure?.id, source: this.folded }\n }))\n }\n\n /*\n `detail.staged` is the dock's answer to \"did anything actually happen to my candidate\". The\n listener is synchronous, so the dock reads it right after dispatching and only then tells the\n chat card to say so. It used to be called `accepted`, which claimed more than it knew โ the\n page had put the candidate somewhere, not the person had agreed to it.\n */\n private receiveDockProposal = (event: Event) => {\n const detail = (event as CustomEvent).detail\n if (!detail) return\n\n const source =\n detail?.source ||\n (detail?.proposal?.source\n ? typeof detail.proposal.source === 'string'\n ? JSON.parse(detail.proposal.source)\n : detail.proposal.source\n : undefined)\n\n if (source) {\n detail.staged = this.openProposalForReview(source, detail.proposal)\n }\n }\n\n private onFigureAiStage = (event: Event) => {\n const detail = (event as CustomEvent).detail\n const source = detail?.source || (detail?.proposal?.source ? (typeof detail.proposal.source === 'string' ? JSON.parse(detail.proposal.source) : detail.proposal.source) : undefined)\n if (source) {\n this.openProposalForReview(source, detail.proposal)\n }\n }\n\n /**\n * A candidate from the dock opens the review lane. It does not become the draft.\n *\n * This used to write `draft` and `parts` straight onto the working draft and then set\n * `proposalSession = undefined` โ the dock's candidate overwrote what the author had open and\n * erased the lane built to review it. There was no moment where the person said yes, and a\n * draft has no version history to go back to, so the previous work was simply gone.\n *\n * `ai-client-base`'s analysis contract states this as a literal type: `approvalRequired: true`,\n * and of `proposal`, \"It is never an instruction to mutate canonical state.\" The in-page\n * The in-page entrance honoured this through `openAiProposal` before it was removed, and the dock\n * entrance is now the same door. Applying is what the take button does, from the lane, per change.\n *\n * ## Why the overwrite was there โ so it does not come back\n *\n * The dock opened the review lane originally. Before `c42a0b63df` this handler read:\n *\n * if (!this.active || (detail?.figureId ?? '') !== (this.figure?.id ?? '')) return\n * if (detail?.draftType && detail.draftType !== this.folded?.type) return\n * if (detail?.baseSource && detail.baseSource !== JSON.stringify(this.folded)) return\n * this.receive(detail.proposal)\n *\n * Three guards, each a silent `return`, and the last compared a serialized source byte for byte.\n * Any difference that changed nothing at all dropped the candidate with no message, so the dock\n * would report a candidate and the screen would show none.\n *\n * The `ox-assistant-chat` migration fixed that by replacing the path rather than the guards, and\n * the review lane went out with them โ `applySourceDirectly` wrote straight to the draft, and\n * cleared `proposalSession` on the way past. **Nobody decided that reviews were unwanted here.**\n * It was the cost of loosening a guard by deleting what stood around it.\n *\n * So the guards are gone and stay gone, and the lane is back. If a candidate ever seems not to\n * arrive, the thing to look for is a silent `return` on this path โ not the lane.\n *\n * Returns whether the lane opened, so the dock can tell the chat whether to say it staged.\n */\n private openProposalForReview(rawSource: any, proposal?: any): boolean {\n const source = typeof rawSource === 'string' ? JSON.parse(rawSource) : rawSource\n if (!source || !Array.isArray(source.parts)) return false\n\n try {\n /*\n The dock sends a FigureProposal whose metrics sit at the top level; the staged-on-navigate\n path carries the raw tool result, which nests them under score/cost. Read both rather than\n making one of the two entrances reshape its payload.\n */\n this.proposalSession = proposalSessions.openAiProposal(this.folded, {\n source: JSON.stringify(source),\n grade: proposal?.grade ?? proposal?.score?.grade,\n triangles: proposal?.triangles ?? proposal?.cost?.triangles,\n groups: proposal?.groups ?? proposal?.cost?.groups,\n attempts: proposal?.attempts,\n quality: proposal?.quality\n } as FigureProposal)\n\n this.mode = 'edit'\n this.requestUpdate()\n return true\n } catch (e) {\n console.error('[FigureModeller] Failed to open the AI candidate for review:', e)\n return false\n }\n }\n\n private proposalBaseSource?: string\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('figure-ai-context-request', this.announceAiContext)\n window.addEventListener('figure-ai-review', this.receiveDockProposal)\n window.addEventListener('figure-ai-stage', this.onFigureAiStage)\n window.addEventListener('figure-save-request', this.onSaveRequest)\n window.addEventListener('keydown', this.handleKeyDown)\n }\n\n disconnectedCallback() {\n window.removeEventListener('keydown', this.handleKeyDown)\n window.removeEventListener('figure-save-request', this.onSaveRequest)\n window.removeEventListener('figure-ai-stage', this.onFigureAiStage)\n window.removeEventListener('figure-ai-context-request', this.announceAiContext)\n window.removeEventListener('figure-ai-review', this.receiveDockProposal)\n window.dispatchEvent(new CustomEvent('figure-ai-context', { detail: undefined }))\n super.disconnectedCallback()\n }\n\n private onSaveRequest = () => {\n if (this.active) this.save()\n }\n\n private handleKeyDown = (e: KeyboardEvent) => {\n if (!this.active || this.mode !== 'edit' || this.proposalSession) return\n const target = e.composedPath()[0] as HTMLElement | undefined\n const tag = target?.tagName?.toLowerCase()\n if (tag === 'input' || tag === 'textarea' || target?.isContentEditable) return\n\n if ((e.metaKey || e.ctrlKey) && !e.altKey) {\n if (e.key === 'z' && !e.shiftKey) {\n e.preventDefault()\n this.undo()\n } else if ((e.key === 'z' && e.shiftKey) || e.key === 'y') {\n e.preventDefault()\n this.redo()\n }\n }\n }\n\n get context() {\n return {\n title: this.figure?.name ?? i18next.t('figure.title.new-figure'),\n /*\n **์ ๋ชฉ ์ค์ ๋๋ค.** ์ด๋ฆ์ ๊ทธ๋๋ก ๋๋ค.\n\n ์ด ํ๋ฉด์ ์ฃผ์ธ๊ณต์ ์บ๋ฒ์ค๋ค. ์ด๋ฆ์ ์์ฑ ํจ๋์์ ๋ณด๊ณ ๊ณ ์น๊ณ , ๋ธ๋ผ์ฐ์ ํญ์๋\n ใoperato figure ยท ์์
์ใ๋ก ๋์จ๋ค. ๊ทธ ์์ ์ ๋ชฉ ์ค์ ํ ๊ฒน ๋ ์น์ผ๋ฉด ๊ฐ์ ๋ง์ด ์ธ ๋ฒ์ด๊ณ ,\n ๊ทธ๋งํผ ์บ๋ฒ์ค๊ฐ ๋ฎ์์ง๋ค.\n\n `title` ์ ๋น์ฐ๋ ๊ฒ์ผ๋ก ๋์ง ์๋ ์ด์ ๋ ๊ทธ ๊ฐ์ MDI ํญ๋ ์ฝ๊ธฐ ๋๋ฌธ์ด๋ค โ ๋น์ฐ๋ฉด ํญ ์ด๋ฆ์ด\n ํจ๊ป ์ฌ๋ผ์ง๋ค. ์ด๋ฆ์ ํ๋์ด๊ณ ๊ทธ๋ฆฌ๋ ์๋ฆฌ๋ง๋ค ์ผ๊ณ ๋๋ค(`ox-page-title-bar`).\n */\n heading: false\n }\n }\n\n render() {\n const source = this.folded\n\n return html`\n <div\n edits\n ?collapse-left=${this.collapsed.left}\n ?collapse-right=${this.collapsed.right}\n @figure-rename=${(e: CustomEvent) => this.rename(e.detail.name)}\n @figure-type-change=${(e: CustomEvent) => this.typeChanged(e.detail.type)}\n @figure-catalog=${(e: CustomEvent) => this.catalog(e.detail)}\n @figure-released=${(e: CustomEvent) => this.released(e.detail.figure)}\n @figure-reverted=${() => this.figure?.id && this.load(this.figure.id)}\n @preview-sizing-fix=${(e: CustomEvent) => this.previewSizingFix(e.detail)}\n @apply-sizing-fix=${(e: CustomEvent) => this.applySizingFix(e.detail)}\n @add-part=${(e: CustomEvent) => this.addPart(e.detail.primitive)}\n @select-part=${(e: CustomEvent) => (this.selected = e.detail.index)}\n @remove-part=${(e: CustomEvent) => this.removePart(e.detail.index)}\n @duplicate-part=${(e: CustomEvent) => this.duplicatePart(e.detail.index)}\n @move-part-up=${(e: CustomEvent) => this.movePart(e.detail.index, e.detail.to)}\n @move-part-down=${(e: CustomEvent) => this.movePart(e.detail.index, e.detail.to)}\n @update-part=${(e: CustomEvent) => this.updatePart(e.detail.index, e.detail.part)}\n @part-changed=${(e: CustomEvent) => this.partChanged(e.detail.name, e.detail.part)}\n @toggle-part-hidden=${(e: CustomEvent) => this.toggleHidden(e.detail.index)}\n @set-all-parts-hidden=${(e: CustomEvent) => this.setAllHidden(e.detail.hidden)}\n @change-detail-level=${(e: CustomEvent) => this.changeDetailLevel(e.detail.level)}\n @update-draft=${(e: CustomEvent) => this.updateDraft(e.detail.draft)}\n @resize-base=${(e: CustomEvent) => this.resizeBase(e.detail.draft, e.detail.parts)}\n @part-tool=${(e: CustomEvent) => this.runTool(e.detail.index, e.detail.tool, e.detail.axis)}\n @pick-part=${(e: CustomEvent) => this.pickPart(e.detail.name)}\n >\n <figure-parts\n .parts=${this.parts}\n .level=${(this.draft?.detailLevel ?? 'M') as DetailLevel}\n .selected=${this.selected}\n ></figure-parts>\n\n <div middle>\n ${this.renderBar()}\n ${this.proposalSession ? this.renderDecision() : ''}\n ${this.proposalSession\n ? html`\n <div lanes>\n <div lane>\n <h4>${i18next.t('figure.label.now')}</h4>\n <figure-canvas\n .figureId=${this.figure?.id || this.figure?.type}\n .draft=${this.draft}\n .parts=${this.parts}\n .picked=${this.pickedName}\n .view=${this.view}\n .revision=${this.sceneRevision}\n ></figure-canvas>\n </div>\n <div lane candidate>\n <h4>\n ${i18next.t('figure.label.proposed')}\n ${this.proposalSession.metrics\n ? html`<small>\n ${this.proposalSession.metrics.grade} ยท\n ${i18next.t('figure.text.n-triangles', { count: this.proposalSession.metrics.triangles })}\n ${this.proposalSession.metrics.quality ? html` ยท ${this.proposalSession.metrics.quality.summary}` : ''}\n </small>`\n : ''}\n </h4>\n ${this.renderProposed()}\n </div>\n </div>\n `\n : this.mode === 'preview'\n ? html`<figure-preview\n .source=${source}\n .draft=${this.draft}\n .view=${this.view}\n @pose-as-default=${(e: CustomEvent) => this.poseAsDefault(e.detail.values)}\n ></figure-preview>`\n : html`<figure-canvas\n .figureId=${this.figure?.id || this.figure?.type}\n .draft=${this.draft}\n .parts=${this.parts}\n .picked=${this.pickedName}\n .gizmo=${this.jointGizmo}\n .view=${this.view}\n .revision=${this.sceneRevision}\n ></figure-canvas>`}\n </div>\n\n <figure-side\n .figureName=${this.figure?.name ?? ''}\n .figureCategory=${this.figure?.category}\n .figureTags=${this.figure?.tags}\n .figureId=${this.figure?.id ?? ''}\n .figureState=${this.figure?.state}\n .figureVersion=${this.figure?.version ?? 0}\n .dirty=${this.dirty}\n .draft=${this.draft}\n .parts=${this.parts}\n .source=${source}\n .contract=${this.contract}\n .contractFailure=${this.contractFailure}\n .selected=${this.selected}\n .view=${this.view}\n @update-view=${(e: CustomEvent) => (this.view = e.detail.view)}\n ></figure-side>\n </div>\n ${this.renderSaveModal()}\n `\n }\n\n /**\n * ๊ฐ์ด๋ฐ ์นธ ์์ ๋ โ ๋ฌด์์ ๋ณด๊ณ ์๋์, ์์ชฝ ์นธ์ ์ ๋ ์์ก์ด.\n *\n * ## ๋ฌด์์ ๋ณด๊ณ ์๋\n *\n * ํธ์ง๊ณผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ ๊ฐ์ ์๋ฆฌ๋ฅผ ๋๊ณ ๋คํฌ์ง ์๋๋ค. ๋ ๋ค ๋์ด๊ฐ ํ์ํ๊ณ , ๋์์\n * ๋ด์ผ ํ ์ผ์ด ์๋ค. ๋ถํ์ ๊ณ ์น๋ ๋์์๋ ํธ์ง๋ง ๋ณด๋ฉด ๋๊ณ , ๋ค ๊ณ ์น ๋ค์ ๋๋ฉด์์\n * ์ด๋ป๊ฒ ๋๋์ง ๋ณด๋ฉด ๋๋ค.\n *\n * ํ๋ณด๊ฐ ์ ์์ ๋๋ ๊ทธ ๋ ๋จ์ถ๋ฅผ ๋ด์ง ์๋๋ค. ๊ทธ๋๋ ๊ฐ์ด๋ฐ๊ฐ ์ด๋ฏธ ๋๋ก ๋๋์ด\n * ์๋ค.\n *\n * ## ๋ ๋ ๋ ์๋ค\n *\n * ์์ก์ด๊ฐ ์ฌ๊ธฐ ์๊ธฐ ๋๋ฌธ์ด๋ค. ํ๋ณด๊ฐ ์๋ค๊ณ ๋ ๋ฅผ ํต์งธ๋ก ๊ฐ์ถ๋ฉด, ์นธ์ ์ ์ด ๋ ์ฑ๋ก\n * ํ๋ณด๋ฅผ ๋ฐ์ผ๋ฉด ๋๋๋ฆด ๋ฐฉ๋ฒ์ด ์์ด์ง๋ค.\n */\n private renderBar() {\n const one = (mode: 'edit' | 'preview') => html`\n <button\n mode\n ?on=${this.mode === mode}\n title=${i18next.t('figure.text.mode-' + mode + '-explained')}\n @click=${() => (this.mode = mode)}\n >\n ${i18next.t('figure.label.mode-' + mode)}\n </button>\n `\n\n return html`<div modes>\n ${this.renderCollapse('left')}${this.proposalSession ? '' : html`${one('edit')}${one('preview')}`}\n ${this.mode === 'edit' && !this.proposalSession\n ? html`\n <div separator></div>\n <button\n history\n ?disabled=${this.undoStack.length === 0}\n title=\"${i18next.t('figure.button.undo')} (Ctrl+Z)\"\n @click=${() => this.undo()}\n >\n <md-icon>undo</md-icon>\n </button>\n <button\n history\n ?disabled=${this.redoStack.length === 0}\n title=\"${i18next.t('figure.button.redo')} (Ctrl+Y)\"\n @click=${() => this.redo()}\n >\n <md-icon>redo</md-icon>\n </button>\n `\n : ''}\n <div spacer></div>\n <!--\n AI ๋ฅผ ์ฌ๋ ๋จ์ถ๋ ์ฌ๊ธฐ ๋์ง ์๋๋ค. ์ฑ ๋จธ๋ฆฌ์ค์ ์ด๋ฏธ ์๊ณ ๊ฐ์ dock ์ ์ฐ๋ค โ ํ ํ๋ฉด์\n ๊ฐ์ ๊ณณ์ผ๋ก ๊ฐ๋ ๋ฌธ์ด ๋์ด๋ฉด ์ฌ๋์ด ๋์ ์ฐจ์ด๋ฅผ ์ฐพ๋๋ค. ์ด๋ฆฐ ๋ํ์ dock ์ ๋๊ธฐ๋ ์ผ์\n ๋จ์ถ๊ฐ ํ๋ ๊ฒ์ด ์๋๋ค: dock ์ด ์ด๋ฆด ๋ figure-ai-context-request ๋ก ๋ฌป๊ณ ์ด ํ๋ฉด์ด\n ์ ์ฅ ์ ์ ๋ณธ ๊ทธ๋๋ก ๋ตํ๋ค.\n -->\n ${this.saveFailure ? html`<span save-failed title=${this.saveFailure}>${this.saveFailure}</span>` : ''}\n ${this.dirty ? html`<span dirty>${i18next.t('figure.text.unsaved-changes')}</span>` : ''}\n <button save ?disabled=${!this.canSave} @click=${() => this.save()}>\n ${this.saving ? i18next.t('figure.text.saving-figure') : i18next.t('figure.button.save')}\n </button>\n ${this.renderCollapse('right')}\n </div>`\n }\n\n /**\n * ํ์ชฝ ์นธ์ ์ ๊ณ ํด๋ ์์ก์ด.\n *\n * ํ์ดํ๋ **๋๋ฅด๋ฉด ๋ฌด์์ด ์ผ์ด๋๋์ง**๋ฅผ ๊ฐ๋ฆฌํจ๋ค โ ํด์ ธ ์์ผ๋ฉด ์นธ์ด ์ฌ๋ผ์ง ์ชฝ,\n * ์ ํ ์์ผ๋ฉด ์นธ์ด ๋์์ฌ ์ชฝ. ์ง๊ธ ์ํ๋ฅผ ๊ฐ๋ฆฌํค๊ฒ ํ๋ฉด ๋ฐ๋๋ก ์ฝํ๋ค.\n */\n private renderCollapse(side: keyof Panes) {\n const gone = this.collapsed[side]\n const shut = side === 'left' ? 'chevron_left' : 'chevron_right'\n const back = side === 'left' ? 'chevron_right' : 'chevron_left'\n const pane = side === 'left' ? 'parts' : 'properties'\n\n return html`\n <button\n collapse\n title=${i18next.t(`figure.text.${gone ? 'expand' : 'collapse'}-${pane}-pane`)}\n @click=${() => this.toggleCollapse(side)}\n >\n <md-icon>${gone ? back : shut}</md-icon>\n </button>\n `\n }\n\n private toggleCollapse(side: keyof Panes): void {\n this.collapsed = { ...this.collapsed, [side]: !this.collapsed[side] }\n rememberPanes(this.collapsed)\n }\n\n /**\n * AI ํ๋ณด๋ฅผ ์ค์ ๋ฐฐ์น ํฌ๊ธฐ์์๋ ๋ณธ๋ค.\n *\n * ํธ์ง ์บ๋ฒ์ค ํ ์ฅ์ผ๋ก๋ `repeat`ยท`fixed`ยท`anchor`๊ฐ ๋ง๋์ง ์ ์ ์๋ค. ํ๋ณด๋ ์์ง\n * ์ ๋ณธ์ด ์๋๋ฏ๋ก ์ ์ฅํ์ง ์๊ณ , `figure-preview`๊ฐ ๊ฐ์ FigureSource๋ฅผ ๊ธฐ์ค ํฌ๊ธฐ์\n * ์ผ๊ณฑ ๊ฐ์ง ํ์ฅ ์ถ์์ ์ค์ FigureInstance๋ก ์ธ์ด๋ค. ๋ฐ๋ผ์ ์ ์์๋ \"์ข์ ๋ณด์ด๋\n * ํ ์ฅ\"์ด ์๋๋ผ ๋ฐฐ์น๋ ๋๋ ๋ถ์ด ์๋์ง๋ฅผ ๋ณด๊ณ ์๋ฝํ๋ค.\n */\n private renderProposed() {\n if (!this.proposalSession) return ''\n\n return html`<figure-preview .source=${this.proposalSession.source} .view=${this.view}></figure-preview>`\n }\n\n /**\n * ๋ฌด์์ ๋ฐ์์ง ๊ณ ๋ฅธ๋ค.\n *\n * ํต์งธ๋ก๋ง ๋ฐ๊ฒ ๋๋ฉด ใ๋ชธํต์ ์ข์๋ฐ ๋ชจํฐ ์๋ฆฌ๊ฐ ํ๋ ธ๋คใ์ ๋ตํ ์ ์๋ค โ ๊ทธ๊ฒ\n * ๊ฐ์ฅ ํํ ๋ฐ์์ด๋ค. ๋ณ๊ฒฝ ํ๋๊ฐ ์นฉ ํ๋์ด๊ณ , ์ฒ์์๋ ์ ๋ถ ๊ณจ๋ผ ๋๋ค. ํต์งธ๋ก\n * ๋ฐ๋ ๊ฒ์ด ๋ณดํต์ ๊ธธ์ด๋ฏ๋ก ๊ทธ๊ฒ์ด ํ ๋ฒ ๋๋ฅด๊ธฐ์ฌ์ผ ํ๋ค.\n *\n * ๊ณ ๋ฅธ ์กฐํฉ์ **๋ฐ๊ธฐ ์ ์ ์ฌ ๋ณธ๋ค.** ํ์์ ์ด๊ธฐ๋ฉด ๋ชป ๋๋ฅด๊ฒ ํ๊ณ , ์ ์ฑ
์ ๋์ผ๋ฉด\n * ์๋ฆฐ๋ค. ๊ณจ๋ผ ๋ฐ์ผ๋ฉด ํ๋ณด๋ฅผ ๋ผ ๋์ ๋ค๋ฅธ ์กฐํฉ์ด ๋๋ฏ๋ก ํ๋ณด์ ์ ์๋ฅผ ๊ทธ๋๋ก\n * ๋ฏฟ์ ์ ์๋ค โ ์๋ฅผ ๋ค์ด ๋ฑ๊ธ์ ์ ๋ฐ๊ณ ๋ถํ๋ง ๋ฐ์ผ๋ฉด ๋ถํ ์ ํ๋๋ฅผ ๋๋๋ค.\n *\n * ํ์ ์ค๋ฅ๊ฐ ์ค์ ๋ก ๋๋ ์กฐํฉ์ ์์ง ๋ณด์ง ๋ชปํ๋ค. ๊ทธ๋๋ ๋๋ ๊ฒ์ ๊ฐ์ด ๊ฑฐ์\n * ์ ๋ค๊ณ , ์ฐ๋ฆฌ๊ฐ ์๊ฐ ๋ชป ํ ์กฐํฉ์ ๋ง์ ์ฃผ๊ธฐ ๋๋ฌธ์ด๋ค.\n */\n private renderDecision() {\n if (!this.proposalSession) return ''\n\n const stale = this.proposalBaseSource !== undefined && this.proposalBaseSource !== JSON.stringify(this.folded)\n\n const changes = proposals.diffProposal(this.folded, this.proposalSession.source)\n const picked = proposals.applyProposal(this.folded, this.proposalSession.source, this.proposalSession.picked)\n const { errors, violations } = validate(picked)\n\n return html`\n <div decide>\n <span>${this.proposalTitle(this.proposalSession)}</span>\n <div spacer></div>\n <button drop @click=${() => this.discard()}>${i18next.t('figure.button.discard')}</button>\n ${stale ? html`<span role=\"alert\">${i18next.t('figure.text.source-changed-ask-again')}</span>` : ''}\n <button take ?disabled=${stale || errors.length > 0 || this.proposalSession.picked.size === 0} @click=${() => this.take()}>\n ${i18next.t('figure.button.take-n-changes', { n: this.proposalSession.picked.size })}\n </button>\n </div>\n\n ${this.renderQualityReview()}\n <div proposal-note>\n <label>\n ${i18next.t('figure.text.proposal-feedback-note')}\n <input\n maxlength=\"500\"\n .value=${this.proposalSession.note}\n placeholder=${i18next.t('figure.text.proposal-feedback-placeholder')}\n @input=${(event: Event) => (this.proposalSession = { ...this.proposalSession!, note: (event.target as HTMLInputElement).value })}\n />\n </label>\n </div>\n\n ${changes.length > 0\n ? html`\n <div changes>\n ${changes.map(change => this.renderChange(change))}\n </div>\n `\n : ''}\n ${errors.length > 0\n ? html`<p blocked>${i18next.t('figure.text.picked-changes-do-not-validate')} โ ${errors[0].message}</p>`\n : violations.length > 0\n ? html`<p blocked warn>${violations[0].message}</p>`\n : ''}\n `\n }\n\n /** ํ๋ณด ํ์ง ํ๋จ์ ๊ทผ๊ฑฐ๋ฅผ ์๋ฝ ์ ์ ์ ๋ถ ๋ณด์ฌ ์ค๋ค. */\n private renderQualityReview() {\n const quality = this.proposalSession?.metrics?.quality\n if (!quality) return ''\n\n return html`\n <div quality-review ?review=${quality.status === 'review'}>\n <strong>${i18next.t('figure.label.candidate-review')}</strong>\n <span>${quality.summary}</span>\n <span> ยท top-view ${Math.round(quality.visualReadability * 100)}% ยท ${quality.visualRegions} regions</span>\n ${quality.findings.length > 0\n ? html`<ul>\n ${quality.findings.map(finding => html`<li><code>${finding.dimension}</code> โ ${finding.message}</li>`)}\n </ul>`\n : ''}\n </div>\n `\n }\n\n /** ๋ณ๊ฒฝ ํ๋. ๋ฌด์์ ํ๊ฒ ๋ค๋ ๊ฒ์ธ์ง ๋ถํธ๋ก ๋จผ์ ๋งํ๋ค. */\n private renderChange(change: proposals.ProposalChange) {\n /*\n Every ChangeKind needs a row here. A kind the map does not answer draws an empty icon and a\n key with no name beside it, which reads as a broken row rather than a missing case โ the\n `satisfies` makes the compiler say so instead.\n */\n const icon = ({\n added: 'add',\n changed: 'edit',\n removed: 'remove',\n base: 'aspect_ratio',\n placement: 'vertical_align_bottom',\n detail: 'tune',\n styleKit: 'palette',\n animations: 'animation',\n parameters: 'tune',\n capabilities: 'hub',\n joints: 'settings_input_component'\n } satisfies Record<proposals.ChangeKind, string>)[change.kind]\n\n const on = this.proposalSession?.picked.has(change.key)\n\n return html`\n <button\n change\n ?on=${on}\n title=${i18next.t('figure.text.change-' + change.kind)}\n @click=${() => this.toggle(change.key)}\n >\n <md-icon>${icon}</md-icon>\n <span key>${change.key}</span>\n </button>\n `\n }\n\n private toggle(key: string) {\n if (this.proposalSession) this.proposalSession = proposalSessions.toggleProposalChange(this.proposalSession, key)\n }\n\n /**\n * ํ๋ณด๊ฐ ์๋ค.\n *\n * ์๋ณธ ๋ฐ์ดํฐ์ ๋ฃ์ง ์๋๋ค. ๋๋ํ ๋๊ณ ์ ์์๊ฐ ๊ณ ๋ฅธ๋ค. AI ๊ฐ ์๋ณธ ๋ฐ์ดํฐ์ ์ง์ ์ฐ๋ฉด\n * ๋ฌด์์ด ์๊ธฐ ๊ฒ์ด๊ณ ๋ฌด์์ด ๊ธฐ๊ณ ๊ฒ์ธ์ง ๋ชจ๋ฅด๊ฒ ๋๋ค.\n */\n private receive(proposal: FigureProposal) {\n this.proposalBaseSource = JSON.stringify(this.folded)\n this.proposalSession = proposalSessions.openAiProposal(this.folded, proposal)\n }\n\n /**\n * ๋ฐํ ๊ฒ์ดํธ์ ๊ตฌ์กฐํ๋ ์์ ์ ํ๋๋ฅผ ํ์ฌ ์์
์ฌ๋ณธ์๋ง ๊ฒน์ณ ๋ณธ๋ค. ์๋ฒ๊ฐ ์ค ๊ฐ์\n * `part.anchor.axis = to`๋ผ๋ ๋ฐ์ดํฐ์ด์ง ์ฌ๋์ด ์ฝ์ ๋ฌธ์ฅ์ ๋ค์ ํด์ํ ๊ฒฐ๊ณผ๊ฐ ์๋๋ค.\n * ์๋ณธ `draft`/`parts`๋ ์ฌ๊ธฐ์ ์ ํ ๋ฐ๊พธ์ง ์๊ณ , ์๋์ `take()`๋ง ๋ฐ๊พผ ์ฌ๋ณธ์ ์ ์ฉํ๋ค.\n */\n private previewSizingFix(fix: FigureGateFix) {\n if (!this.folded) return\n this.proposalBaseSource = JSON.stringify(this.folded)\n this.proposalSession = proposalSessions.openSizingFix(this.folded, fix)\n }\n\n /**\n * ์ํด๋ฆญ ์ ์ฉ์ ์๋ฒ๊ฐ ๋ชจ๋ ํฌ๊ธฐ ๋ณ๊ฒฝ case๋ฅผ ์ฌ๊ฒ์ฌํด ์์ ํ๋ค๊ณ ํ์ํ ํ-์ต์ปค ํ๋ณด์๋ง ์ฐ๋ค.\n * ๊ทธ๋๋ ์ ์ฅ์ ์ ์์์ ๋ณ๋ ํ์๋ค. ์๋ชป ๋๋ฌ๋ DB ์ ๋ณธ์ด๋ ๋ฐํํ์ ๋ฐ๋์ง ์๋๋ค.\n */\n private applySizingFix(fix: FigureGateFix) {\n if (!fix.safe || !this.folded) return\n this.previewSizingFix(fix)\n if (!this.proposalSession) return\n this.take()\n }\n\n /**\n * ๊ณ ๋ฅธ ๋ณ๊ฒฝ์ ๋ฐ์๋ค์ธ๋ค.\n *\n * ํ๋ณด ๋น๊ต๋ ์ ์ฅ ํ์์ผ๋ก ํ๋ค โ ๋ถํ ์ด๋ฆ์ผ๋ก ์ง์ง๊ณ ๊ธฐ์ค ์น์ยท๋ฑ๊ธ๊น์ง ํจ๊ป ๋ด์ผ\n * ํ๋ฏ๋ก ๊ทธ์ชฝ์ด ์์ฐ์ค๋ฝ๋ค. ๋ฐ์๋ค์ธ ๊ฒฐ๊ณผ๋ ๋ค์ ์ฌ ๋ชจ๋ธ๋ก ๋๋๋ ค ํธ์ง์ ์ด์ด๊ฐ๋ค.\n */\n private take() {\n if (!this.proposalSession) return\n if (this.proposalBaseSource !== undefined && this.proposalBaseSource !== JSON.stringify(this.folded)) return\n\n this.recordHistory()\n const taken = proposals.applyProposal(this.folded, this.proposalSession.source, this.proposalSession.picked)\n const { draft, parts } = fromFigureSource(taken)\n\n this.draft = draft\n this.parts = parts\n this.selected = parts.length ? 0 : -1\n this.dirty = true\n this.reportProposalFeedback('accepted')\n this.discard(false)\n }\n\n /**\n * ํ๋ณด์ ๋ํ ์ฌ๋์ ๊ฒฐ์ ์ ๋ํฌ์๋ง ์๋ฆฐ๋ค.\n *\n * ์ด ๊ธฐ๋ก์ ๋ถ์ ์ด๋ฒคํธ๋ Figure ์์ฑ์ด ์๋๋ค. ๊ฐ์ ๋ชจ๋ธ๋ฌ ์ธ์
์์ ๋ค์ ์์ฒญ์ ๋ ์\n * ์ดํด์ํค๋ ์งง์ ์ ํธ์ผ ๋ฟ์ด๋ค. ์๋ณธ source๋ ์ฌ๋์ ์์
๋ด์ฉ์ ๋ค์ ๋ณด๋ด์ง ์๊ณ , ์ฌ๋์ด\n * ํ๋ณด ๋ณ๊ฒฝ ์ค ๋ช ๊ฐ๋ฅผ ๋ฐ์๋ค์๋์ง์ ์ด๋ฏธ ํ๋ฉด์ ๋ณด์๋ ํ์ง ํ์ ๋ง ๋ณด๋ธ๋ค.\n */\n private reportProposalFeedback(outcome: 'accepted' | 'discarded') {\n if (!this.proposalSession) return\n\n const feedback = proposalSessions.feedbackFromSession(this.folded, this.proposalSession, outcome)\n if (!feedback) return\n this.proposalFeedback = [...this.proposalFeedback, feedback].slice(-5)\n window.dispatchEvent(\n new CustomEvent('figure-ai-feedback', {\n detail: {\n figureId: this.figure?.id,\n ...feedback\n }\n })\n )\n }\n\n private discard(reportFeedback = true) {\n if (reportFeedback) this.reportProposalFeedback('discarded')\n this.proposalSession = undefined\n this.proposalBaseSource = undefined\n }\n\n /**\n * ์ ์ฅํ ์ ์๋.\n *\n * ํ์์ ์ด๊ธด ์๋ณธ ๋ฐ์ดํฐ๋ก๋ ์ ์ฅ์ ๋๋ฅผ ์ ์๊ฒ ํ๋ค. ๋๋ ๋ค๊ฐ ์๋ฒ๊ฐ ๋ฐ์์ฃผ์ง ์๋ ๊ฒ๋ณด๋ค,\n * ๋๋ฅผ ์ ์๋ ์ด์ ๊ฐ ํ๋จ ํจ๋์ ๋ ์๋ ๊ฒ์ด ๋ซ๋ค.\n *\n * ## ๋ฐ๋ ๊ฒ์ด ์์ผ๋ฉด ๋๋ฅผ ์ ์๋ค\n *\n * **`dirty` ๋ฅผ ์ ๋ณด๊ณ ์์๋ค.** ์ ์ฅํ ์งํ์๋ ๋จ์ถ๊ฐ ์ด์ ์์ด ๊ฐ์ ์ ๋ณธ์ ๋ช ๋ฒ์ด๊ณ ๋ค์ ์ธ\n * ์ ์์๊ณ , ์ ์ฅ๋ง๋ค ์ธ๋ค์ผ์ ์๋ก ์ฐ์ด 20KB ๋ฅผ ๋ค์ ๋ฃ๊ณ `thumbnailUpdatedAt` ์ ์ฌ๋ ธ๋ค โ\n * ๊ทธ๋ฆผ ์ฃผ์์ ํ์ด ๋ฐ๋๋ฏ๋ก ๋ธ๋ผ์ฐ์ ์บ์๋ ํจ๊ป ๋ฒ๋ ค์ง๋ค. ๋ฐ๋ ๊ฒ์ด ์๋๋ฐ ์ผ์ด๋ ์ผ์ด ์๋๋ค.\n *\n * ์๋ก ๋ง๋๋ ์ค์ธ ๊ฒ์ `startNew` ๊ฐ `dirty` ๋ก ์์ํ๋ฏ๋ก ์ฒซ ์ ์ฅ์ด ๋งํ์ง ์๋๋ค.\n * ์ ์ฅ์ด ๊ฑฐ์ ๋๋ฉด `dirty` ๋ฅผ ๊ทธ๋๋ก ๋๋ฏ๋ก ๋ค์ ๋๋ฅผ ์ ์๋ค.\n */\n private get canSave(): boolean {\n if (this.saving || !this.dirty || !this.folded) {\n return false\n }\n // ๊ธฐ์กด ์ ์ฅ๋ ๋ชจ๋ธ์ ์ด๋ฆ์ด ์์ด์ผ ๋ฐ๋ก ์ ์ฅ ๊ฐ๋ฅ. ์ ๊ท ๋ชจ๋ธ์ ์ ์ฅ ํ์
์์ ์ด๋ฆ์ ์
๋ ฅํ ์ ์์\n if (this.figure?.id && !this.figure?.name) {\n return false\n }\n return validate(this.folded).errors.length === 0\n }\n\n async pageUpdated(changes: Record<string, unknown>, lifecycle: { resourceId?: string }) {\n if (!this.active) {\n ++this.loadGeneration\n return\n }\n\n const id = lifecycle?.resourceId\n\n if (id) {\n if (changes.active || id !== this.figure?.id) {\n await this.load(id)\n }\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n return\n }\n\n /*\n โโ id ์์ด ๋ค์ด์จ ๊ฒ์ ใ์๋ก ๋ง๋ ๋คใ๋ ๋ป์ด๋ค โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ\n ์ ์๋ `!this.figure` ์ผ ๋๋ง ์๋ก ์์ํ๋ค. ์
ธ์ ํ์ด์ง๋ฅผ ์ด๋ ค ๋๋ฏ๋ก(MDI ํญ) ์นดํ๋ก๊ทธ์์\n ํ๋ ์ด์ด ๋ณธ ๋ค์๋ ์ด ํ์ด์ง๊ฐ ๊ทธ ๋ํ์ ๊ณ์ ๋ค๊ณ ์๊ณ , ๊ทธ๋์ ใ์ figureใ๊ฐ **์๋ฌด ์ผ๋\n ํ์ง ์์๋ค.**\n\n ๊ทธ๊ฒ๋ณด๋ค ๋์ ๊ฒ์ด ์์๋ค โ ํ๋ฉด์๋ ์ ๋ํ์ด ๊ทธ๋๋ก ์์ผ๋ ์ฌ๋์ ์ ๊ฒ์ธ ์ค ์๊ณ ๊ณ ์น๊ณ \n ์ ์ฅํ๋ค. ๊ทธ๋ฌ๋ฉด **์ด๋ ค ์๋ ๋ํ์ ๋ฎ์ด์ด๋ค.** ใ์ ์ด๋ฆฐ๋คใ๋ก ๋ณด์ด๋ ๊ฒ์ด ์ค์ ๊ทธ ๋ฌธ์ด์๋ค.\n\n ๋ค๊ณ ์๋ ๊ฒ์ด **์ ์ฅ๋ ๋ํ์ด๋ฉด**(id ๊ฐ ์์ผ๋ฉด) ์๋ก ์์ํ๋ค. ์์ง ์ ์ฅ ์ ํ ์ ๋ํ์\n ๋ค๊ณ ์์ผ๋ฉด ๊ทธ๋๋ก ๋๋ค โ ํ์ด์ง๋ฅผ ๋ค์ ๋ค๋ ๋ค๊ณ ์ ์ ์ค์ธ ๊ฒ์ ๋ฒ๋ฆฌ์ง ์๋๋ค.\n */\n if (!this.figure) {\n this.startNew()\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n return\n }\n\n if (this.figure.id) {\n this.startNew()\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n return\n }\n\n if (shouldStartNewFigure(changes, !!this.figure, this.figure?.id)) {\n this.startNew()\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n return\n }\n\n const pending = consumePendingFigureProposal()\n if (pending?.source) {\n this.openProposalForReview(pending.source, pending.proposal)\n }\n }\n\n private loadGeneration = 0\n private async load(id: string) {\n const generation = ++this.loadGeneration\n const figure = await fetchFigure(id)\n if (generation !== this.loadGeneration || !this.active) return\n\n this.proposalSession = undefined\n this.proposalBaseSource = undefined\n this.figure = figure\n\n /*\n ๊ทธ๋ฆผ์ด ์์ผ๋ฉด ์ด ์๋ฆฌ์์ ์ฑ์ด๋ค(์๋ `fillThumbnail`). ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค โ ํ๋ฉด์ด ๋จผ์ ๋ค.\n\n **`thumbnail` ์ด ์๋๋ผ `thumbnailUpdatedAt` ์ผ๋ก ํ์ ํ๋ค.** ๊ทธ๋ฆผ ์์ฒด๋ ๋ชฉ๋กยท๋ฑ๊ฐ ์ง์๊ฐ\n ๊ฐ์ ธ์ค์ง ์๋๋ค(base64 ๋ผ์ ๋ฌด๊ฒ๊ณ ์บ์๊ฐ ์ ๋๋ค โ ์ฃผ์๋ก ๋ถ๋ฅธ๋ค). ์๋ ์นธ์ผ๋ก ํ์ ํ๋ฉด\n ๋ ใ๊ทธ๋ฆผ์ด ์๋คใ๊ฐ ๋์ด ์ ์๋ฉด์ ์ด ๋๋ง๋ค ๋ค์ ์ฐ์ด ์ ์ฅํ๊ฒ ๋๋ค.\n */\n if (!figure.thumbnailUpdatedAt && figure.id) {\n void this.fillThumbnail(figure.id)\n }\n\n // ์๋ฒ๊ฐ ์ค ๊ฒ์ ๊ทธ๋๋ก ์ด๋ค. ์ฝ์ง ๋ชปํ๋ฉด ์ค๋ฅ๋ณด๊ณ ์์ด ๋น ์ํ๋ก ๋ฐ๊พธ์ง ์๋๋ค.\n // ๊ทธ๋ฌ๋ฉด ์ฌ์ฉ์๊ฐ ์ ์ฅ์ ์ ํํด ์๋ณธ์ ๋ฎ์ด์ด๋ค.\n const model = figure.source ? fromFigureSource(JSON.parse(figure.source) as FigureSource) : undefined\n this.draft = model?.draft\n this.parts = model?.parts ?? []\n\n /*\n ๋ฐํ๋ ์ ์ด ์์ผ๋ฉด ๊ทธ ํ์ ๊ฐ์ ธ๋ค ๋๋ค โ ๊ณ ์น๋ ๋์ ๊ฒฌ์ค ์๋๋ค. ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค:\n ๋ํ์ ์ด๋ฏธ ํ๋ฉด์ ์๊ณ , ํ์ ์ ๋์ฐฉํ๋ ๋๋ก ๋ถ๋๋ค.\n */\n this.releasedSource = undefined\n if (figure.id && (figure.version ?? 0) > 0) {\n void this.loadReleased(figure.id, generation)\n }\n\n /*\n **์๋ฌด๊ฒ๋ ๊ณ ๋ฅด์ง ์์ ์ฑ๋ก ์ฐ๋ค.**\n\n ์ ์๋ ์ฒซ ๋ถํ์ ์ก์ ๋์๋ค. ๊ทธ๋ฌ๋ฉด ์ฌ์ฉ์๊ฐ ๊ณ ๋ฅธ ์ ์๋ ๋ถํ์ ์์ฑ์ด ๋ ์๊ณ ,\n ์บ๋ฒ์ค์๋ ๊ทธ ๋ถํ์ ์ค๊ณฝ์ ์ด ๊ทธ๋ ค์ง๋ค. ๋ชจ๋ธ ์ ์ฒด๋ฅผ ๋ณด๋ ค๋ฉด ๋จผ์ ์ ํ์ ํ์ด์ผ ํ๋ค.\n\n ์์ฑ ํจ๋์ ๋น ์ํ๋ ๊ทธ๋์ **์ด์์ ๋ ํ ๋ฒ๋ ์ ๋ณด์๋ค.** ์ฒ์ ์ฌ๋ ์ฌ๋์๊ฒ\n ใ์ผ์ชฝ์์ ๋ถํ์ ๊ณ ๋ฅด๋ ๋๊ตฌใ๋ผ๊ณ ์๋ ค ์ค ์๋ฆฌ๊ฐ ๊ทธ ํ๋ฉด์ด๋ค.\n\n ์๋ก ๋ง๋ค ๋(`startNew`)๋ ๋ค๋ฅด๋ค. ๋ฐฉ๊ธ ๋ถํ์ ๋ง๋ค์์ผ๋ ๋ฐ๋ก ํธ์งํ๋ ค๋ ๊ฒ์ด ๋ง๋ค.\n */\n this.selected = -1\n this.dirty = false\n this.violations = []\n this.undoStack = []\n this.redoStack = []\n this.lastCoalesceKey = undefined\n }\n\n /** ์ง์ ๋ฐํํ์ ๊ฐ์ ธ๋ค ๋๋ค. ๋ชป ์ฝ์ผ๋ฉด ๊ฒฌ์ฃผ์ง ์๋๋ค โ ์๋ ํ์ ์ ์ง์ด๋ด์ง ์๋๋ค. */\n private async loadReleased(id: string, generation: number) {\n try {\n const source = await fetchReleasedSource(id)\n if (generation !== this.loadGeneration || !this.active) return\n this.releasedSource = source ? (JSON.parse(source) as FigureSource) : undefined\n } catch (e) {\n console.warn(`[figure] ์ง์ ๋ฐํํ์ ์ฝ์ง ๋ชปํ์ต๋๋ค โ ${(e as Error).message}`)\n }\n }\n\n private startNew() {\n ++this.loadGeneration\n this.proposalSession = undefined\n this.proposalBaseSource = undefined\n this.proposalFeedback = []\n this.mode = 'edit'\n // ํ์
์ด๋ฆ์ ์ฌ๋์ด ์ ํ๊ธฐ ์ ๊น์ง๋ ์์ ์ด๋ฆ์ ์ด๋ค. ์ ์ฅํ ๋ ํ์ ํ๋ค.\n const draftType = placeholderType()\n const { draft, parts } = startingModel(draftType)\n\n this.figure = { id: '', type: draftType, name: '' } as Figure\n this.draft = draft\n this.parts = parts\n /* ๊ณ ๋ฅธ ๊ฒ์ด ์๋ค โ ๋ถํ์ด ์์ผ๋ ์์ฑ ํจ๋๋ ๊ณ ๋ฅผ ๊ฒ์ ๊ธฐ๋ค๋ฆฐ๋ค. */\n this.selected = -1\n this.dirty = true\n this.violations = []\n this.undoStack = []\n this.redoStack = []\n this.lastCoalesceKey = undefined\n }\n\n private rename(name: string) {\n if (!this.figure) return\n\n this.figure = { ...this.figure, name }\n this.dirty = true\n }\n\n /**\n * ํ์
์ ๊ณ ์น๋ค โ **๋ฐํ ์ ๊น์ง๋ง**(ADR-0063 ๊ฒฐ์ 4).\n *\n * ์ ์๋ ์ ์ฅ๋ ๋ํ์ด๋ฉด ๋ฌด์กฐ๊ฑด ๋์์ฐ๋ค. ๊ทธ๋์ ๊ธฐ๊ณ๊ฐ ์ง์ ์ด๋ฆ์ด ๊ทธ๋๋ก ๊ตณ์๋ค. ๋ฐํ๋\n * ๋ค์๋ ๋ฌธ์ด ๊ฑฐ์ ํ๋ฏ๋ก ์ฌ๊ธฐ์๋ ๋ง๋๋ค โ ๋๋ฌ์ ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๊ณ ์ ์ฅ์์ ์คํจํ๋ฉด\n * ์ ์์๊ฐ ๋ฌด์์ ์๋ชปํ๋์ง ๋ชป ์ฝ๋๋ค.\n */\n private typeChanged(type: string) {\n if (!type || (this.figure?.version ?? 0) > 0) return\n const sanitized = type.replace(/[^A-Za-z0-9_]/g, '_').toUpperCase()\n if (this.draft) this.draft.figureType = sanitized\n this.figure = { ...this.figure, type: sanitized } as Figure\n this.folded = this.draft ? toFigureSource(this.draft, this.parts) : undefined\n this.dirty = true\n }\n\n /**\n * ๋ถ๋ฅ์ ํ๊ทธ๋ฅผ ๊ณ ์น๋ค.\n *\n * ์ ๋ณธ(`source`)์ด ์๋๋ผ **์นดํ๋ก๊ทธ์ ๊ฐ**์ด๋ค โ ๋ํ์ด ๋ฌด์์ผ๋ก ์๊ฒผ๋์ง๊ฐ ์๋๋ผ ์ด๋์\n * ๊ฑธ๋ฆฌ๋์ง๋ค. ๊ทธ๋์ ์ ์๋ ๋ฐํ๋ ํ๋ค๋ฆฌ์ง ์๋๋ค.\n */\n private catalog(patch: { category?: string; tags?: string[] }) {\n if (!this.figure) return\n\n this.figure = { ...this.figure, ...patch }\n this.dirty = true\n }\n\n private snapshotState(): { draft?: FigureDraft; parts: PartModel[]; selected: number } {\n return {\n draft: this.draft ? structuredClone(this.draft) : undefined,\n parts: structuredClone(this.parts),\n selected: this.selected\n }\n }\n\n private recordHistory(coalesceKey?: string) {\n const now = Date.now()\n if (coalesceKey && this.lastCoalesceKey === coalesceKey && now - this.lastHistoryTime < 600) {\n this.lastHistoryTime = now\n return\n }\n\n this.lastCoalesceKey = coalesceKey\n this.lastHistoryTime = now\n\n this.undoStack = [...this.undoStack.slice(-49), this.snapshotState()]\n this.redoStack = []\n }\n\n private undo() {\n if (this.undoStack.length === 0) return\n const prev = this.undoStack[this.undoStack.length - 1]\n this.undoStack = this.undoStack.slice(0, -1)\n this.redoStack = [this.snapshotState(), ...this.redoStack.slice(0, 49)]\n\n this.draft = prev.draft ? structuredClone(prev.draft) : undefined\n this.parts = structuredClone(prev.parts)\n this.selected = this.parts.length ? Math.max(-1, Math.min(prev.selected, this.parts.length - 1)) : -1\n this.dirty = true\n this.lastCoalesceKey = undefined\n }\n\n private redo() {\n if (this.redoStack.length === 0) return\n const next = this.redoStack[0]\n this.redoStack = this.redoStack.slice(1)\n this.undoStack = [...this.undoStack.slice(-49), this.snapshotState()]\n\n this.draft = next.draft ? structuredClone(next.draft) : undefined\n this.parts = structuredClone(next.parts)\n this.selected = this.parts.length ? Math.max(-1, Math.min(next.selected, this.parts.length - 1)) : -1\n this.dirty = true\n this.lastCoalesceKey = undefined\n }\n\n /**\n * ๋ถํ ๋ชฉ๋ก์ ๊ฐ์ ๋ผ์ด๋ค.\n *\n * ํธ์ง ๊ท์น์ `part-edits` ๊ฐ ๊ฐ๋๋ค โ ํ๋ฉด๊ณผ ํ
์คํธ๊ฐ ๊ฐ์ ๊ฒ์ ์ฐ๊ฒ ํ๋ ค๊ณ ๋ผ์ด\n * ๋์๋ค. ์ฌ๊ธฐ์๋ ๊ฒฐ๊ณผ๋ฅผ ๋ด๊ณ ์ ํ ์ธ๋ฑ์ค๋ฅผ ์ ๋ฆฌํ๋ค.\n */\n private put(parts: PartModel[], selected = this.selected, coalesceKey?: string) {\n this.recordHistory(coalesceKey)\n this.parts = parts\n this.selected = Math.min(selected, parts.length - 1)\n this.dirty = true\n }\n\n private addPart(primitive: PrimitiveKind) {\n if (!this.draft) return\n /*\n ๊ณ ๋ฅธ ๋ถํ ์์ ์น๋๋ค โ ๊ทธ ์๋ฆฌ์์ ๋ณด์ด๊ณ , ๊ด์ ์ ๊ฑธ๋ฉด ๋ง๋ฟ๋ ๋ฉด์ด ํ์ ์ค์ฌ์ด ๋๋ค.\n ๊ณ ๋ฅธ ๊ฒ์ด ์์ผ๋ฉด `newPart` ๊ฐ ๋ฐ๋ฅ ํ๊ฐ์ด๋ฐ๋ก ๋๋๋ค.\n */\n const onTopOf = this.parts[this.selected]\n // ์ถ๊ฐํ ๊ฒ์ ๋ฐ๋ก ์์ ํ ์ ์๊ฒ ์ ํ ์ํ๋ก ๋๋ค.\n this.put(edits.addPart(this.draft, this.parts, primitive, onTopOf), this.parts.length)\n }\n\n private removePart(index: number) {\n this.put(edits.removePart(this.parts, index), Math.max(0, index - 1))\n }\n\n private duplicatePart(index: number) {\n this.put(edits.duplicatePart(this.parts, index), index + 1)\n }\n\n private movePart(index: number, to: number) {\n this.put(edits.movePart(this.parts, index, to), to)\n }\n\n private updatePart(index: number, part: PartModel) {\n this.put(edits.updatePart(this.parts, index, part), this.selected, `part:${part.name || index}`)\n }\n\n /**\n * ํ ์์ฒด์ ๊ฐ์ ๊ฐ์ ๋ผ์ด๋ค โ ๋ฅ๋ ฅ์ฒ๋ผ ๋ถํ๋ณด๋ค ์์ ์๋ ๊ฒ๋ค.\n *\n * ๋ถํ ๋ชฉ๋ก์ ๊ฑด๋๋ฆฌ์ง ์๋๋ค. `put` ์ ๋ถํ์ ํจ๊ป ๋ฐ์ผ๋ฏ๋ก ์ฌ๊ธฐ์ ์ฐ๋ฉด ๋ฅ๋ ฅ ํ๋๋ฅผ\n * ๊ณ ์น ๋๋ง๋ค ๋ถํ ๋ชฉ๋ก์ด ์ ๋ฐฐ์ด์ด ๋๊ณ , ๊ทธ๋ฆฌ๋ ์ชฝ์ด ์ ๋ถ ๋ค์ ๊ทธ๋ฆฐ๋ค.\n */\n /**\n * ๋ฏธ๋ฆฌ๋ณด๊ธฐ์์ ์ธ์ด ์์ธ๋ฅผ ํ๋ผ๋ฏธํฐ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ํ๋ค.\n *\n * ๊ด์ ์ด ์๋ ๋ํ์ ๊ฐ์ด 0 ์ธ ์์ธ(ํด์ง ์์ธ)๊ฐ ๊ณง๊ฒ ์ ๊ธฐ๋ฅ์ด๋ผ, ๊ธฐ๋ณธ๊ฐ์ด ์์ผ๋ฉด ๋ชฉ๋ก๊ณผ\n * ๋๋ฉด์์ ๊ทธ ๋ชจ์์ผ๋ก ์ ๋ค. ์ ์์๊ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์์ ๋ง์ถ ์์ธ๊ฐ ๊ณง ๊ทธ ๋ต์ด๋ค.\n */\n private poseAsDefault(values: Record<string, number>) {\n if (!this.draft) return\n\n const next = poseAsDefaults(this.draft, values)\n /* ์ํ ๊ฒ์ด ์์ผ๋ฉด ์ด์์ด ๊ทธ๋๋ก ์จ๋ค. ๊ทธ๋ ๋๋๋ฆฌ๊ธฐ ์นธ๊ณผ ใ์ ์ฅ ์ ๋จใ์ ๋ง๋ค์ง ์๋๋ค. */\n if (next !== this.draft) this.updateDraft(next)\n }\n\n /**\n * ๊ธฐ์ค ์์๋ฅผ ๊ณ ์น๋ค โ ์ด์๊ณผ ๋ถํ์ด **ํ ๊ฑธ์์ผ๋ก** ๋ฐ๋๋ค.\n *\n * ์์๊ฐ ์ปค์ง๋ฉด ํ๊ฐ์ด๋ฐ๊ฐ ์ฎ๊ฒจ ๊ฐ๋ฏ๋ก ๋ถํ์ ๊ทธ๋งํผ ๋๋ฐ์ด์ผ ์ ์ฅ๋๋ ์๋ฆฌ๊ฐ ์ ์ง๋๋ค\n * (`base-box.ts`). ๊ทธ ๋์ ๋ฐ๋ก ๊ธฐ๋กํ๋ฉด ํ ๋ฒ ๋๋๋ ธ์ ๋ ๋ถํ์ด ๋ฐ์ฏค ๋ฐ๋ฆฐ ํ๋ฉด์ด ๋จ๋๋ค.\n */\n private resizeBase(draft: FigureDraft, parts: PartModel[]) {\n this.recordHistory('base')\n this.draft = draft\n this.parts = parts\n this.dirty = true\n }\n\n private updateDraft(draft: FigureDraft) {\n this.recordHistory('draft')\n this.draft = draft\n this.dirty = true\n }\n\n /**\n * ๋ํ
์ผ ๋ฑ๊ธ์ ๋ฐ๊พผ๋ค.\n *\n * ์ด ๊ฐ์ ๋ถํ ์ ํ๋๋ฅผ ์ ํ๊ณ ์ฑ์๋์ ํ ์ถ์ด ๋๋ค. ๋ถํ๋ณด๋ค ์์ ์๋ ๊ฐ์ด๋ผ\n * ์ด์์ ๋ด๋๋ค.\n *\n * ํ๋๋ฅผ ๋ด๋ ค์ ์ด๋ฏธ ๋ฃ์ ๋ถํ ์๋ณด๋ค ์์์ง ์ ์๋ค. ๊ทธ๋ ๋ถํ์ ์ง์ฐ์ง ์๋๋ค.\n * ๊ฒ์ฆ์ด ์๋ฐ์ผ๋ก ์๋ฆฌ๊ณ , ์ฑ์๋๊ฐ ๋ฑ๊ธ์ ์ ๋ง๋๋ค๊ณ ๋งํ๋ค. ์ ์์๊ฐ ๋ฌด์์ ๋บ์ง\n * ์ ํ ์ผ์ด์ง ๋๊ตฌ๊ฐ ์ ํ ์ผ์ด ์๋๋ค.\n */\n private changeDetailLevel(level: DetailLevel) {\n if (!this.draft) return\n\n this.recordHistory('detailLevel')\n this.draft = { ...this.draft, detailLevel: level }\n this.dirty = true\n }\n\n /**\n * ๋ถํ์ ์ ๊น ๊ฐ๋ฆฐ๋ค.\n *\n * ์ฌ์ด ์ด๋ฏธ ๊ฐ๊ณ ์๋ ์ํ๋ฅผ ์ผ๊ณ ๋๋ ๊ฒ๋ฟ์ด๋ค โ ํธ์ง ๋ชจ๋์์๋ faint ๋ก ๋ณด์ด๊ณ \n * ๋ทฐ ๋ชจ๋์์๋ ์ ๊ทธ๋ ค์ง๋ค. ์ ์ฅ ํ์์๋ ์ค๋ฆฌ์ง ์์ผ๋ฏ๋ก ๋ค์ ์ด๋ฉด ์ ๋ถ ๋ณด์ธ๋ค.\n *\n * `dirty` ๋ก ์น์ง ์๋๋ค. ์ ์ฅ๋ ๊ฒ์ด ํ๋๋ ๋ฐ๋์ง ์์๋๋ฐ \"์ ์ฅํ์ง ์์ ๋ณ๊ฒฝ\"์ด\n * ๋จ๋ฉด, ์ ์ฅ ๋ฒํผ์ด ๋ฌด์์ ์ ์ฅํ๊ฒ ๋ค๋ ๊ฒ์ธ์ง ์ ์ ์๋ค.\n */\n private toggleHidden(index: number) {\n const part = this.parts[index]\n if (!part) return\n\n this.parts = edits.updatePart(this.parts, index, { ...part, hidden: !part.hidden })\n }\n\n /**\n * ํ๊บผ๋ฒ์ ๊ฐ์ถ๊ฑฐ๋ ๋๋๋ฆฐ๋ค.\n *\n * ๋ถํ ์ค๋ฌผ์ง๋ฆฌ์์ ์์ชฝ ํ๋๋ฅผ ๋ณด๋ ค๊ณ ์ด์ํ์ ๋๋ฅด๋ ๊ฒ์ ์์ค๋ค. ํ ๋ฒ์ ๋ฐ๊พธ๋ฏ๋ก\n * ๋ชฉ๋ก์ ํ ๋ฒ๋ง ๊ฐ์ ๋ผ์ด๋ค โ ํ๋์ฉ ์ค๋ฌด ๋ฒ ๊ฐ๋ฉด ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์ค๋ฌด ๋ฒ ๋ค์ ์ ๋ค.\n */\n private setAllHidden(hidden: boolean) {\n this.parts = this.parts.map(part => (part.hidden === hidden ? part : { ...part, hidden }))\n }\n\n /**\n * ๋ฏธ๋ฆฌ๋ณด๊ธฐ์์ ๊ธฐ์ฆ๋ชจ๋ก ์ฎ๊ธฐ๊ฑฐ๋ 2D ์์ ๋์๋ค.\n *\n * ์๋ ค ์ค๋ ๊ฒ์ ๋ถํ **์ด๋ฆ**์ด๋ค. ๋ชฉ๋ก์ ๋ช ๋ฒ์งธ์ธ์ง๋ ์ฌ๊ธฐ์ ์ฐพ๋๋ค โ ์ด๋ฒคํธ๊ฐ\n * ์ค๋ ์ฌ์ด์ ๋ชฉ๋ก์ด ๋ฐ๋์์ผ๋ฉด ์ฐพ์ง ๋ชปํ๊ณ , ๊ทธ๋๋ ์๋ฌด๊ฒ๋ ํ์ง ์๋๋ค.\n */\n private partChanged(name: string, part: PartModel) {\n const at = this.parts.findIndex(item => item.name === name)\n if (at >= 0) this.put(edits.updatePart(this.parts, at, part), this.selected, `drag:${name}`)\n }\n\n /**\n * ์ ๋ฐ ๋ฐฐ์น ๋๊ตฌ.\n *\n * ๊ท์น์ `part-edits` ๊ฐ ๊ฐ๋๋ค. ์ฌ๊ธฐ์๋ ์ด๋ ๊ฒ์ ๋ถ๋ฅผ์ง๋ง ์ ํ๋ค.\n */\n private runTool(index: number, tool: string, axis: PlaneAxis) {\n const draft = this.draft\n if (!draft) return\n\n if (tool === 'center') this.put(edits.centerPart(draft, this.parts, index, axis))\n else if (tool === 'floor') this.put(edits.alignPartToStart(this.parts, index, axis))\n else if (tool === 'snap') this.put(edits.snapPart(draft, this.parts, index))\n // ๋์นญ ๋ณต์ ๋ ๋ถํ์ด ํ๋ ๋์ด๋๋ค โ ์๋ก ์๊ธด ๊ฒ์ ์ ํ ์ํ๋ก ๋๋ค\n else if (tool === 'mirror') this.put(edits.mirrorPart(draft, this.parts, index, axis), index + 1)\n }\n\n /**\n * ์บ๋ฒ์ค์์ ๋ถํ์ ์ ํํ๋ค.\n *\n * ์บ๋ฒ์ค๊ฐ ์๋ฆฌ๋ ๊ฒ์ **์ด๋ฆ**์ด๋ค. ๋ชฉ๋ก์ ๋ช ๋ฒ์งธ์ธ์ง๋ ์ฌ๊ธฐ์ ์ฐพ๋๋ค โ ์๋ฆผ์ด\n * ์ค๋ ์ฌ์ด์ ๋ชฉ๋ก์ด ๋ฐ๋์์ผ๋ฉด ๋ชป ์ฐพ๊ณ , ๊ทธ๋๋ ๊ณ ๋ฅธ ๊ฒ์ ๋ฐ๊พธ์ง ์๋๋ค.\n * ์๋ ์๋ฆฌ๋ฅผ ๊ณ ๋ฅด๋ฉด ์์ฑ ์นธ์ด ๋น ์ฑ๋ก ์ด๋ ค ใ์ฌ๋ผ์ก๋ใ๋ก ์ฝํ๋ค.\n */\n /** ์ง๊ธ ๊ณ ๋ฅธ ๋ถํ ์ด๋ฆ. ์บ๋ฒ์ค๊ฐ ์ธ๋ฑ์ค๊ฐ ์๋๋ผ ์ด๋ฆ์ ๋ฐ๋๋ค. */\n private get pickedName(): string | undefined {\n return this.parts[this.selected]?.name\n }\n\n /**\n * ๊ณ ๋ฅธ ๋ถํ์ ๊ด์ ์ด ์์ผ๋ฉด **๊ทธ ๊ด์ ์ด ๋๋ ์๋ฆฌ**๋ฅผ ์ ์๋ฉด์ ํจ๊ป ๊ทธ๋ฆฐ๋ค(`joint-gizmo.ts`).\n *\n * ์ถ์ ๊ณ ๋ฅด๋ ์นธ์ ์ด ํ๋ฉด์ ์๋๋ฐ ๋๋ ๋ชจ์ต์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์๋ง ์์๋ค. ๊ณ ๋ฅด๋ ์๋ฆฌ์ ๋ณด์ด๋\n * ์๋ฆฌ๊ฐ ๊ฐ๋ฆฌ๋ฉด ์ฌ๋์ ์๋ณตํ๋ฉฐ ๋ง์ถ๋ค โ ์ฌ์ฏ ์ถ์ง๋ฆฌ ๋ก๋ด์ด๋ฉด ์ฌ์ฏ ๋ฒ์ด๋ค.\n */\n private get jointGizmo(): PartModel | undefined {\n const name = this.pickedName\n if (!name || !this.draft) return undefined\n\n const joint = jointOf(this.draft, name)\n if (!joint) return undefined\n\n return gizmoPart(joint, this.parts.find(part => part.name === name), this.draft)\n }\n\n private pickPart(name: string) {\n const at = this.parts.findIndex(part => part.name === name)\n if (at >= 0) this.selected = at\n }\n\n /**\n * ๊ทธ๋ฆผ์ด ์๋ ๋ํ์ **์ด์์ ๋ ํ ๋ฒ** ์ฐ์ด ์ฑ์ด๋ค.\n *\n * ## ์ ์ฌ๊ธฐ์ธ๊ฐ\n *\n * ๋๋ฉด์ ์ ์ฅํ ๋ ์๋ฒ๊ฐ ์ฐ๋๋ค. ๊ทธ๋ฐ๋ฐ ๋ฐฑ์๋์ GPU ๊ฐ ์๋ ๋ฐฐํฌ๊ฐ ๋ง์ ํค๋๋ฆฌ์ค๋ก 3D ๋ฅผ ์ฐ๋\n * ๊ฒ์ด ์์ฃผ ์คํจํ๋ค. ๋ํ์ ๊ทธ๋ฆฌ๋ GPU ๋ ์ด๋ฏธ ๋ณด๋ ์ฌ๋ ์์ ์๊ณ , ์ฌ์ ์ง๊ธ ์ฌ๊ธฐ ์ ์๋ค.\n *\n * ์ ์๋ฉด์ ๊ฑฐ์น์ง ์๊ณ ์๊ธด ๊ฒ๋ค์ด ๊ทธ๋ฆผ์ด ์๋ค โ ์จ์์ผ๋ก ๋ฃ์ ํ๋ณธ, AI ๊ฐ ๋ธ ํ๋ณด, ๋ฐ์
ํ ์์ฐ.\n * ๊ทธ๊ฒ๋ค์ ํ ๋ฒ ์ด์ด ๋ณด๋ฉด ๊ทธ๋ ์ฑ์์ง๋ค.\n *\n * ## ์ ์ฅ์ด ์๋๋ค\n *\n * ๊ทธ๋ฆผ๋ง ๋ณด๋ธ๋ค. ์ ๋ณธ์ ๊ฑด๋๋ฆฌ์ง ์์ผ๋ฏ๋ก ๋ฏธ์ ์ฅ ํ์๋ ์ผ์ง ์๋๋ค โ ์ด์ด ๋ดค๋ค๋ ๊ฒ์ด ๊ณ ์ณค๋ค๋\n * ๋ป์ด ๋๋ฉด ์ ์์๊ฐ ์ ์ฅํ ์ง ๋ง์ง๋ฅผ ๋งค๋ฒ ๊ณ ๋ฏผํ๋ค.\n */\n /**\n * ๋ฐํ๋์๋ค โ **์ ๋ณธ์ ๋ ์๋ฆฌ๊ฐ ๊ทธ ์ฌ์ค์ ๋ฐ๋๋ค.**\n *\n * ์ด๋ ฅ ํจ๋์ ๋ฐํ์ ์ํค๊ณ ๊ฒฐ๊ณผ๋ฅผ ์๋ฆด ๋ฟ, ์ด ํ์ด์ง์ ์ํ๋ฅผ ๊ณ ์ณ ์ฐ์ง ์๋๋ค. ํ ๋ฒํธ์ ์ํ๊ฐ\n * ์ฌ๊ธฐ์ ๊ฐฑ์ ๋์ด์ผ ๋จธ๋ฆฌ์คยท์ด๋ ฅ ํญ์ด ๊ฐ์ ๊ฒ์ ๋ณธ๋ค.\n *\n * ์ ๋ณธ(source)์ ๋ฐํ์ด ๊ฑด๋๋ฆฌ์ง ์์ผ๋ฏ๋ก ๋ค์ ๋ถ๋ฌ์ค์ง ์๋๋ค โ ์ ์ ์ค์ธ ํ๋ฉด์ ๋๊ฐ์ง ์๋๋ค.\n */\n private released(figure: Figure): void {\n if (!this.figure || figure?.id !== this.figure.id) {\n return\n }\n\n this.figure = { ...this.figure, version: figure.version, state: figure.state, updatedAt: figure.updatedAt }\n }\n\n private async fillThumbnail(id: string): Promise<void> {\n await this.updateComplete\n\n const thumbnail = await captureThumbnail(this.draft, this.parts)\n if (!thumbnail || this.figure?.id !== id) {\n return\n }\n\n try {\n const { figure } = await updateFigure(id, { thumbnail })\n /* ์๋ฒ๊ฐ ์ฐ์ ์๊ฐ์ ๊ทธ๋๋ก ๋ฐ๋๋ค โ ์ด ๊ฐ์ด ๊ทธ๋ฆผ์ ๋ถ๋ฅด๋ ์ฃผ์์ ํ ๋ฒํธ๊ฐ ๋๋ค. */\n this.figure = { ...this.figure, thumbnailUpdatedAt: figure?.thumbnailUpdatedAt }\n } catch (e) {\n /* ๋ณผ ๊ถํ๋ง ์๋ ์ฌ๋์ผ ์ ์๋ค. ํ๋ฉด์ ๊ทธ๋๋ก ๋๊ณ ์กฐ์ฉํ ๋์ด๊ฐ๋ค. */\n console.warn(`[thumbnail] ${id} ๋ฅผ ์ฑ์ฐ์ง ๋ชปํ์ต๋๋ค โ ${(e as Error).message}`)\n }\n }\n\n private save() {\n if (!this.canSave || !this.folded || !this.figure) {\n return\n }\n\n if (!this.figure.id) {\n // ์ ๊ท ์ ์ฅ: ํ์
์ฝ๋์ ํ์ ์ด๋ฆ์ ๋ช
ํํ ํ์
์ผ๋ก ํ์ธ/์
๋ ฅ๋ฐ์\n let defaultType = this.draft?.figureType || this.figure.type || ''\n /*\n A placeholder is not prefilled. This used to prefill 'FIGURE', inviting the author to confirm a\n meaningless name that cannot change later and that the release gate refuses.\n */\n if (!defaultType || isPlaceholderType(defaultType)) {\n defaultType = ''\n }\n this.saveModalType = defaultType\n this.saveModalName = this.figure.name || ''\n this.saveModalError = ''\n this.showSaveModal = true\n return\n }\n\n void this.doSave()\n }\n\n private async doSave() {\n if (!this.folded || !this.figure) return\n\n this.saving = true\n this.saveFailure = ''\n this.saveModalError = ''\n\n try {\n if (!this.figure.id) {\n const typeToSave = (this.saveModalType || this.draft?.figureType || this.figure.type || 'FIGURE').trim().toUpperCase()\n const nameToSave = (this.saveModalName || this.figure.name || typeToSave).trim()\n\n if (!typeToSave) {\n throw new Error(i18next.t('figure.text.enter-a-type-name'))\n }\n\n const taken = await fetchFigureTypeNames()\n if (taken.includes(typeToSave)) {\n throw new Error(i18next.t('figure.text.type-name-already-taken', { type: typeToSave }))\n }\n\n if (this.draft) this.draft.figureType = typeToSave\n this.figure = { ...this.figure, type: typeToSave, name: nameToSave }\n this.folded = { ...this.folded, type: typeToSave }\n const sourceJson = JSON.stringify(this.folded)\n const thumbnail = await captureThumbnail(this.draft, this.parts)\n\n const result = await createFigure({\n type: typeToSave,\n name: nameToSave,\n category: this.figure.category,\n tags: this.figure.tags,\n source: sourceJson,\n thumbnail\n })\n\n this.figure = result.figure\n this.violations = result.violations\n this.showSaveModal = false\n this.dirty = false\n navigate(`figure-modeller/${result.figure.id}`)\n return\n }\n\n // ๊ธฐ์กด ๋ชจ๋ธ ์
๋ฐ์ดํธ: folded.type์ด figure.type๊ณผ ์ผ์นํ๋๋ก ๋ณด์ฅ\n if (this.figure.type && this.folded.type !== this.figure.type) {\n this.folded = { ...this.folded, type: this.figure.type }\n if (this.draft) this.draft.figureType = this.figure.type\n }\n const sourceJson = JSON.stringify(this.folded)\n const thumbnail = await captureThumbnail(this.draft, this.parts)\n\n const result = await updateFigure(this.figure.id, {\n /*\n ํ์
์ ํจ๊ป ๋ณด๋ธ๋ค. ์ ๋ณธ ์์ `type` ๋ง ๊ณ ์น๊ณ ํ์ ์ ๊ณ ์น๋ฉด ์ ์ฅ๋ JSON ๊ณผ ํ์ด\n ๋ค๋ฅธ ์ด๋ฆ์ ๋งํ๊ณ , ๋ฐํํ ๋ ์ด๋ ์ชฝ์ด ๋๋ฉด์ ์ ํ๋์ง๊ฐ ๊ฐ๋ฆฐ๋ค. ๋ฐํ๋ ๋ค๋ผ๋ฉด\n ๋ฌธ์ด ๊ฑฐ์ ํ๊ณ ๊ทธ ์ฌ์ ๊ฐ ํ๋ฉด์ ๊ทธ๋๋ก ๋ฌ๋ค.\n */\n type: this.figure.type,\n name: this.figure.name,\n category: this.figure.category,\n tags: this.figure.tags,\n source: sourceJson,\n thumbnail\n })\n this.figure = result.figure\n this.violations = result.violations\n this.dirty = false\n } catch (e) {\n const msg = (e as Error).message\n this.saveFailure = msg\n this.saveModalError = msg\n } finally {\n this.saving = false\n }\n }\n\n /** Title of the candidate bar. A candidate opened from a release-check fix is described by translating that fix here. */\n private proposalTitle(session: proposalSessions.ProposalSession): string {\n const fix = session.fix\n if (fix) {\n return i18next.t('figure.text.release-check-fix', {\n part: fix.part,\n axis: fix.axis.toUpperCase(),\n from: fix.from ?? 'auto',\n to: fix.to\n })\n }\n return session.title || i18next.t('figure.text.assistant-proposed-a-figure')\n }\n\n private renderSaveModal() {\n if (!this.showSaveModal) return nothing\n\n return html`\n <div class=\"save-modal-backdrop\" @click=${(e: Event) => { if (e.target === e.currentTarget) this.showSaveModal = false }}>\n <div class=\"save-modal-card\" role=\"dialog\" aria-modal=\"true\">\n <h3 class=\"save-modal-title\">${i18next.t('figure.title.save-new-figure')}</h3>\n <p class=\"save-modal-desc\">${i18next.t('figure.text.save-new-figure-desc')}</p>\n\n <div class=\"save-modal-field\">\n <label>${i18next.t('figure.label.figure-type')}</label>\n <input\n .value=${this.saveModalType}\n placeholder=${i18next.t('figure.text.figure-type-example')}\n @input=${(e: Event) => (this.saveModalType = (e.target as HTMLInputElement).value.trim().toUpperCase())}\n />\n ${this.saveModalType && !releasableType(this.saveModalType)\n ? html`<div class=\"save-modal-error\">${i18next.t('figure.text.type-name-will-not-release')}</div>`\n : nothing}\n </div>\n\n <div class=\"save-modal-field\">\n <label>${i18next.t('figure.label.name')}</label>\n <input\n .value=${this.saveModalName}\n placeholder=${i18next.t('figure.text.figure-name-example')}\n @input=${(e: Event) => (this.saveModalName = (e.target as HTMLInputElement).value)}\n />\n </div>\n\n ${this.saveModalError ? html`<div class=\"save-modal-error\">${this.saveModalError}</div>` : nothing}\n\n <div class=\"save-modal-actions\">\n <button class=\"btn-cancel\" @click=${() => (this.showSaveModal = false)}>\n ${i18next.t('figure.button.cancel')}\n </button>\n <button class=\"btn-confirm\" ?disabled=${this.saving || !this.saveModalType} @click=${() => this.doSave()}>\n ${this.saving ? i18next.t('figure.text.saving-figure') : i18next.t('figure.button.save')}\n </button>\n </div>\n </div>\n </div>\n `\n }\n}\n"]}
|