@things-factory/figure-ui 10.1.76 → 10.1.77

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.
Files changed (125) hide show
  1. package/dist-client/tsconfig.tsbuildinfo +1 -1
  2. package/package.json +2 -2
  3. package/dist-client/graphql/v3-store.d.ts +0 -3
  4. package/dist-client/graphql/v3-store.js +0 -39
  5. package/dist-client/graphql/v3-store.js.map +0 -1
  6. package/dist-client/modeller/figure-v3-capability.d.ts +0 -22
  7. package/dist-client/modeller/figure-v3-capability.js +0 -141
  8. package/dist-client/modeller/figure-v3-capability.js.map +0 -1
  9. package/dist-client/modeller/figure-v3-clips.d.ts +0 -31
  10. package/dist-client/modeller/figure-v3-clips.js +0 -268
  11. package/dist-client/modeller/figure-v3-clips.js.map +0 -1
  12. package/dist-client/modeller/figure-v3-controls.d.ts +0 -36
  13. package/dist-client/modeller/figure-v3-controls.js +0 -226
  14. package/dist-client/modeller/figure-v3-controls.js.map +0 -1
  15. package/dist-client/modeller/figure-v3-first-save.d.ts +0 -20
  16. package/dist-client/modeller/figure-v3-first-save.js +0 -118
  17. package/dist-client/modeller/figure-v3-first-save.js.map +0 -1
  18. package/dist-client/modeller/figure-v3-links.d.ts +0 -77
  19. package/dist-client/modeller/figure-v3-links.js +0 -649
  20. package/dist-client/modeller/figure-v3-links.js.map +0 -1
  21. package/dist-client/modeller/figure-v3-material.d.ts +0 -39
  22. package/dist-client/modeller/figure-v3-material.js +0 -323
  23. package/dist-client/modeller/figure-v3-material.js.map +0 -1
  24. package/dist-client/modeller/figure-v3-parts.d.ts +0 -69
  25. package/dist-client/modeller/figure-v3-parts.js +0 -559
  26. package/dist-client/modeller/figure-v3-parts.js.map +0 -1
  27. package/dist-client/modeller/figure-v3-preview.d.ts +0 -34
  28. package/dist-client/modeller/figure-v3-preview.js +0 -346
  29. package/dist-client/modeller/figure-v3-preview.js.map +0 -1
  30. package/dist-client/modeller/figure-v3-properties.d.ts +0 -45
  31. package/dist-client/modeller/figure-v3-properties.js +0 -239
  32. package/dist-client/modeller/figure-v3-properties.js.map +0 -1
  33. package/dist-client/modeller/figure-v3-recipe-catalog.d.ts +0 -38
  34. package/dist-client/modeller/figure-v3-recipe-catalog.js +0 -399
  35. package/dist-client/modeller/figure-v3-recipe-catalog.js.map +0 -1
  36. package/dist-client/modeller/figure-v3-verdict.d.ts +0 -64
  37. package/dist-client/modeller/figure-v3-verdict.js +0 -787
  38. package/dist-client/modeller/figure-v3-verdict.js.map +0 -1
  39. package/dist-client/modeller/v3-ai-proposal.d.ts +0 -51
  40. package/dist-client/modeller/v3-ai-proposal.js +0 -64
  41. package/dist-client/modeller/v3-ai-proposal.js.map +0 -1
  42. package/dist-client/modeller/v3-align.d.ts +0 -30
  43. package/dist-client/modeller/v3-align.js +0 -75
  44. package/dist-client/modeller/v3-align.js.map +0 -1
  45. package/dist-client/modeller/v3-canvas.d.ts +0 -72
  46. package/dist-client/modeller/v3-canvas.js +0 -379
  47. package/dist-client/modeller/v3-canvas.js.map +0 -1
  48. package/dist-client/modeller/v3-clips.d.ts +0 -39
  49. package/dist-client/modeller/v3-clips.js +0 -58
  50. package/dist-client/modeller/v3-clips.js.map +0 -1
  51. package/dist-client/modeller/v3-controls.d.ts +0 -28
  52. package/dist-client/modeller/v3-controls.js +0 -28
  53. package/dist-client/modeller/v3-controls.js.map +0 -1
  54. package/dist-client/modeller/v3-editor.d.ts +0 -203
  55. package/dist-client/modeller/v3-editor.js +0 -1526
  56. package/dist-client/modeller/v3-editor.js.map +0 -1
  57. package/dist-client/modeller/v3-fields.d.ts +0 -45
  58. package/dist-client/modeller/v3-fields.js +0 -83
  59. package/dist-client/modeller/v3-fields.js.map +0 -1
  60. package/dist-client/modeller/v3-figure-facts.d.ts +0 -35
  61. package/dist-client/modeller/v3-figure-facts.js +0 -55
  62. package/dist-client/modeller/v3-figure-facts.js.map +0 -1
  63. package/dist-client/modeller/v3-first-save.d.ts +0 -17
  64. package/dist-client/modeller/v3-first-save.js +0 -26
  65. package/dist-client/modeller/v3-first-save.js.map +0 -1
  66. package/dist-client/modeller/v3-gizmo.d.ts +0 -72
  67. package/dist-client/modeller/v3-gizmo.js +0 -111
  68. package/dist-client/modeller/v3-gizmo.js.map +0 -1
  69. package/dist-client/modeller/v3-help.d.ts +0 -18
  70. package/dist-client/modeller/v3-help.js +0 -37
  71. package/dist-client/modeller/v3-help.js.map +0 -1
  72. package/dist-client/modeller/v3-joint-drag.d.ts +0 -19
  73. package/dist-client/modeller/v3-joint-drag.js +0 -97
  74. package/dist-client/modeller/v3-joint-drag.js.map +0 -1
  75. package/dist-client/modeller/v3-joint-fan.d.ts +0 -9
  76. package/dist-client/modeller/v3-joint-fan.js +0 -276
  77. package/dist-client/modeller/v3-joint-fan.js.map +0 -1
  78. package/dist-client/modeller/v3-keys.d.ts +0 -22
  79. package/dist-client/modeller/v3-keys.js +0 -26
  80. package/dist-client/modeller/v3-keys.js.map +0 -1
  81. package/dist-client/modeller/v3-links.d.ts +0 -267
  82. package/dist-client/modeller/v3-links.js +0 -480
  83. package/dist-client/modeller/v3-links.js.map +0 -1
  84. package/dist-client/modeller/v3-live.d.ts +0 -37
  85. package/dist-client/modeller/v3-live.js +0 -68
  86. package/dist-client/modeller/v3-live.js.map +0 -1
  87. package/dist-client/modeller/v3-maturity.d.ts +0 -120
  88. package/dist-client/modeller/v3-maturity.js +0 -313
  89. package/dist-client/modeller/v3-maturity.js.map +0 -1
  90. package/dist-client/modeller/v3-occupancy.d.ts +0 -18
  91. package/dist-client/modeller/v3-occupancy.js +0 -24
  92. package/dist-client/modeller/v3-occupancy.js.map +0 -1
  93. package/dist-client/modeller/v3-palette.d.ts +0 -7
  94. package/dist-client/modeller/v3-palette.js +0 -46
  95. package/dist-client/modeller/v3-palette.js.map +0 -1
  96. package/dist-client/modeller/v3-preview-model.d.ts +0 -47
  97. package/dist-client/modeller/v3-preview-model.js +0 -68
  98. package/dist-client/modeller/v3-preview-model.js.map +0 -1
  99. package/dist-client/modeller/v3-product-session.d.ts +0 -510
  100. package/dist-client/modeller/v3-product-session.js +0 -157
  101. package/dist-client/modeller/v3-product-session.js.map +0 -1
  102. package/dist-client/modeller/v3-recipe-source.d.ts +0 -8
  103. package/dist-client/modeller/v3-recipe-source.js +0 -14
  104. package/dist-client/modeller/v3-recipe-source.js.map +0 -1
  105. package/dist-client/modeller/v3-recipes.d.ts +0 -37
  106. package/dist-client/modeller/v3-recipes.js +0 -103
  107. package/dist-client/modeller/v3-recipes.js.map +0 -1
  108. package/dist-client/modeller/v3-refusals.d.ts +0 -68
  109. package/dist-client/modeller/v3-refusals.js +0 -142
  110. package/dist-client/modeller/v3-refusals.js.map +0 -1
  111. package/dist-client/modeller/v3-renderer.d.ts +0 -40
  112. package/dist-client/modeller/v3-renderer.js +0 -73
  113. package/dist-client/modeller/v3-renderer.js.map +0 -1
  114. package/dist-client/modeller/v3-stage-model.d.ts +0 -39
  115. package/dist-client/modeller/v3-stage-model.js +0 -147
  116. package/dist-client/modeller/v3-stage-model.js.map +0 -1
  117. package/dist-client/modeller/v3-thumbnail.d.ts +0 -3
  118. package/dist-client/modeller/v3-thumbnail.js +0 -75
  119. package/dist-client/modeller/v3-thumbnail.js.map +0 -1
  120. package/dist-client/pages/figure-v3-modeller-page.d.ts +0 -102
  121. package/dist-client/pages/figure-v3-modeller-page.js +0 -548
  122. package/dist-client/pages/figure-v3-modeller-page.js.map +0 -1
  123. package/dist-client/tsconfig.chk.tsbuildinfo +0 -1
  124. package/dist-client/tsconfig.fui.tsbuildinfo +0 -1
  125. package/dist-client/tsconfig.scratch-fm.tsbuildinfo +0 -1
@@ -1,69 +0,0 @@
1
- import '@material/web/icon/icon.js';
2
- import { LitElement } from 'lit';
3
- import type { V3PrimitiveCreation } from '@hatiolab/figure-model';
4
- import type { V3BudgetLine } from './v3-maturity.js';
5
- /**
6
- * 도형 팔레트와 부품 목록 — V3 자산의 것.
7
- *
8
- * 팔레트는 목록 위에, 눈 단추는 늘 자리를 차지하고, 조작은 고른 줄에서만 보인다.
9
- *
10
- * 부품의 도형은 V3 평가가 준 `provider` 로 읽는다. 「숨김」은 여기서도 **작업대의 것**이다 — 저장되지 않고, 자산의 `visibility`(상태에 따라
11
- * 보이고 안 보이는 것)와는 다른 것이다. 그것은 속성 패널의 몫이다.
12
- *
13
- * 이 컴포넌트는 정본을 만지지 않는다. 무엇을 하겠다는 것만 알린다.
14
- */
15
- /** 한 줄 — V3 평가에서 이 패널이 읽는 것만. */
16
- export interface V3PartRow {
17
- id: string;
18
- provider: string;
19
- /** 작업대에서 잠깐 가린 것. 저장되지 않는다. */
20
- hidden?: boolean;
21
- /** 자산이 지금 상태에서 보이지 않는다고 한 것. 저장되는 것이고, 여기서는 표시만 한다. */
22
- invisible?: boolean;
23
- /** 되풀이한 부품이면 지금 몇 개로 그려지나. 되풀이는 한 부품이다 — 한 줄로 보인다. */
24
- copies?: number;
25
- }
26
- /** 팔레트 — 저작 API 가 만들 수 있는 것만 보인다. */
27
- export type V3PaletteKind = V3PrimitiveCreation['kind'] | 'plate' | 'wall';
28
- declare const FigureV3Parts_base: (new (...args: any[]) => LitElement) & typeof LitElement;
29
- export declare class FigureV3Parts extends FigureV3Parts_base {
30
- static styles: import("lit").CSSResult[];
31
- parts: V3PartRow[];
32
- /** 고른 부품의 id. 자리(index)가 아니다 — V3 부품은 id 로 안정하게 가리킨다. */
33
- selected: string;
34
- /** 편집할 수 없을 때(불러오는 중 · 저장 중) 팔레트와 조작을 잠근다. */
35
- locked: boolean;
36
- /**
37
- * 이 도형이 치르는 값 — 삼각형 · 묶음 · 한 화면에 몇 대 · 등급. 부품을 더하는 바로 그 자리에서 보여야 로우폴리의
38
- * 기준이 저작을 이끈다. 등급이 D 면 무엇이 넘쳤는지를 적는다. 누르면 성숙도 탭이 열린다.
39
- */
40
- budget?: V3BudgetLine;
41
- /**
42
- * 디테일 등급(S/M/L)의 부품 한도(사용자 2026-09-24). 부품을 넣기 **전에** 몇 개 남았는지 보이고, 다 차면 팔레트가
43
- * 잠긴다. 되풀이는 한 부품으로 센다. 등급을 안 정했으면 한도는 없다.
44
- */
45
- partBudget?: {
46
- level: 'S' | 'M' | 'L' | null;
47
- used: number;
48
- limit: number | null;
49
- };
50
- /** How many recipe templates the catalog holds; none, and the section is not drawn. */
51
- recipeCount: number;
52
- render(): import("lit-html").TemplateResult<1>;
53
- /** 디테일 등급 — 고르면 한도가 바뀐다. 목록 머리 아래. */
54
- private renderLevel;
55
- private renderBudget;
56
- /** 한꺼번에 감추고 한꺼번에 되돌린다 — 하나라도 감춰져 있으면 다 되돌리고, 다 보이면 다 감춘다. */
57
- private renderShowAll;
58
- private renderRow;
59
- /** 고른 줄의 조작. 못 하는 것은 빼지 않고 흐리게 둔다 — 자리가 밀리면 연달아 지우다 엉뚱한 것을 누른다. */
60
- private renderOps;
61
- /**
62
- * Recipes (ADR-0095): the catalog of templates -- a door, a roller row -- opened over the modeller, put onto the chosen
63
- * part in one step.
64
- */
65
- private renderRecipes;
66
- /** 정본을 고치지 않는다 — 무엇을 하겠다는 것만 알린다. */
67
- private ask;
68
- }
69
- export {};
@@ -1,559 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import '@material/web/icon/icon.js';
3
- import { css, html, LitElement, nothing } from 'lit';
4
- import { customElement, property } from 'lit/decorators.js';
5
- import { i18next, localize } from '@operato/i18n';
6
- import { ScrollbarStyles } from '@operato/styles';
7
- import { PART_LIMIT } from '@hatiolab/figure-model';
8
- import { partLabelOf } from './v3-fields.js';
9
- /** 제공자마다의 아이콘. Material Symbols 이름이다. */
10
- const PROVIDER_ICON = {
11
- box: 'deployed_code',
12
- cylinder: 'database',
13
- ellipticCylinder: 'database',
14
- frustum: 'change_history',
15
- sphere: 'circle',
16
- roundedBox: 'crop_square',
17
- roundedBoxXZ: 'crop_square',
18
- hollowBox: 'check_box_outline_blank',
19
- hollowBoxXZ: 'check_box_outline_blank',
20
- polygon: 'pentagon',
21
- portal: 'door_front'
22
- };
23
- const RECIPES = [
24
- { kind: 'box', icon: 'deployed_code', label: 'figure.label.primitive-cube' },
25
- { kind: 'cylinder', icon: 'database', label: 'figure.label.primitive-cylinder' },
26
- { kind: 'rounded-box', icon: 'crop_square', label: 'figure.label.primitive-rounded-box' },
27
- { kind: 'sphere', icon: 'circle', label: 'figure.label.primitive-sphere' },
28
- { kind: 'frustum', icon: 'change_history', label: 'figure.label.primitive-frustum' },
29
- { kind: 'polygon', icon: 'hexagon', label: 'figure.label.primitive-polygon' },
30
- { kind: 'plate', icon: 'check_box_outline_blank', label: 'figure.label.primitive-plate' },
31
- { kind: 'wall', icon: 'crop_portrait', label: 'figure.label.primitive-wall' },
32
- { kind: 'portal', icon: 'door_front', label: 'figure.label.primitive-portal' },
33
- { kind: 'hollow-box', icon: 'inventory_2', label: 'figure.label.primitive-hollow-box' }
34
- ];
35
- let FigureV3Parts = class FigureV3Parts extends localize(i18next)(LitElement) {
36
- constructor() {
37
- super(...arguments);
38
- this.parts = [];
39
- /** 고른 부품의 id. 자리(index)가 아니다 — V3 부품은 id 로 안정하게 가리킨다. */
40
- this.selected = '';
41
- /** 편집할 수 없을 때(불러오는 중 · 저장 중) 팔레트와 조작을 잠근다. */
42
- this.locked = false;
43
- /** How many recipe templates the catalog holds; none, and the section is not drawn. */
44
- this.recipeCount = 0;
45
- }
46
- static { this.styles = [
47
- ScrollbarStyles,
48
- css `
49
- :host {
50
- display: flex;
51
- flex-direction: column;
52
- min-height: 0;
53
- overflow: hidden;
54
- background-color: var(--md-sys-color-surface-container-lowest);
55
- /* The divider beside it is the editor's frame's (ox-three-pane). */
56
- color: var(--md-sys-color-on-surface);
57
- font: var(--label-font, inherit);
58
- font-size: 0.76rem;
59
- /* Folds by its own width: the editor gives this column 140 px when it has two columns (UX, 2026-09-24). */
60
- container-type: inline-size;
61
- }
62
- section {
63
- padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);
64
- border-bottom: 1px solid var(--md-sys-color-outline-variant);
65
- }
66
- section[list] {
67
- flex: 1;
68
- min-height: 0;
69
- overflow-y: auto;
70
- }
71
- h3 {
72
- display: flex;
73
- align-items: baseline;
74
- justify-content: space-between;
75
- gap: 6px;
76
- margin: 0 0 6px 0;
77
- font-size: var(--ui-t-micro, 11px);
78
- font-weight: 700;
79
- letter-spacing: 0.04em;
80
- text-transform: uppercase;
81
- color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));
82
- }
83
- /* The cost line: the grade's letter in its colour, then what the figure costs. */
84
- button[budget] {
85
- display: flex;
86
- align-items: flex-start;
87
- gap: 6px;
88
- width: 100%;
89
- margin: 0 0 6px;
90
- padding: 4px 6px;
91
- font: inherit;
92
- font-size: 0.68rem;
93
- line-height: 1.5;
94
- text-align: left;
95
- color: var(--md-sys-color-on-surface-variant);
96
- background: none;
97
- border: 1px solid var(--md-sys-color-outline-variant);
98
- border-radius: 6px;
99
- cursor: pointer;
100
- }
101
- button[budget]:hover {
102
- background: var(--md-sys-color-surface-container);
103
- }
104
- button[budget] b {
105
- flex: none;
106
- min-width: 16px;
107
- text-align: center;
108
- border-radius: 4px;
109
- color: var(--md-sys-color-on-primary-container);
110
- background: var(--md-sys-color-primary-container);
111
- }
112
- button[budget][grade='C'] b {
113
- color: var(--md-sys-color-on-tertiary-container);
114
- background: var(--md-sys-color-tertiary-container);
115
- }
116
- button[budget][grade='D'] {
117
- border-color: var(--md-sys-color-error);
118
- }
119
- button[budget][grade='D'] b {
120
- color: var(--md-sys-color-on-error);
121
- background: var(--md-sys-color-error);
122
- }
123
- button[budget] em {
124
- display: block;
125
- font-style: normal;
126
- color: var(--md-sys-color-error);
127
- }
128
- span[room][full] {
129
- color: var(--md-sys-color-error);
130
- font-weight: 600;
131
- }
132
- p[full] {
133
- margin: 4px 0 0;
134
- font-size: 0.68rem;
135
- color: var(--md-sys-color-error);
136
- }
137
- div[level] {
138
- display: grid;
139
- grid-template-columns: auto minmax(0, 1fr);
140
- align-items: center;
141
- gap: 6px;
142
- margin: 0 0 6px;
143
- font-size: 0.68rem;
144
- color: var(--md-sys-color-on-surface-variant);
145
- }
146
- div[level] select {
147
- min-width: 0;
148
- padding: 2px 4px;
149
- font: inherit;
150
- font-size: 0.7rem;
151
- color: var(--md-sys-color-on-surface);
152
- background: var(--md-sys-color-surface-container-lowest);
153
- border: 1px solid var(--md-sys-color-outline-variant);
154
- border-radius: 6px;
155
- }
156
- small[copies] {
157
- color: var(--md-sys-color-on-surface-variant);
158
- }
159
- span[room] {
160
- font-size: 0.7rem;
161
- font-weight: 400;
162
- letter-spacing: 0;
163
- text-transform: none;
164
- }
165
- /* Three to a row, small (user, 2026-09-24): the palette is reached for, not read -- the list below is what grows. */
166
- div[palette] {
167
- display: grid;
168
- grid-template-columns: repeat(3, minmax(0, 1fr));
169
- gap: 3px;
170
- }
171
- button[shape] {
172
- display: flex;
173
- flex-direction: column;
174
- align-items: center;
175
- gap: 1px;
176
- min-width: 0;
177
- padding: 5px 1px 4px;
178
- font: var(--label-font, inherit);
179
- font-size: 0.6rem;
180
- line-height: 1.2;
181
- text-align: center;
182
- overflow-wrap: anywhere;
183
- color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));
184
- background: none;
185
- border: 1px solid var(--md-sys-color-outline-variant);
186
- border-radius: 6px;
187
- cursor: pointer;
188
- }
189
- button[recipe-catalog] {
190
- display: inline-flex;
191
- align-items: center;
192
- gap: 4px;
193
- padding: 4px 10px;
194
- font: inherit;
195
- font-size: 0.75rem;
196
- color: var(--md-sys-color-on-surface);
197
- background: none;
198
- border: 1px solid var(--md-sys-color-outline-variant);
199
- border-radius: 999em;
200
- cursor: pointer;
201
- }
202
- button[shape]:hover:not([disabled]) {
203
- color: var(--md-sys-color-on-primary-container);
204
- background-color: var(--md-sys-color-primary-container);
205
- border-color: transparent;
206
- }
207
- button[shape][disabled] {
208
- opacity: 0.35;
209
- cursor: default;
210
- }
211
- button[shape] md-icon {
212
- --md-icon-size: 18px;
213
- }
214
- ol {
215
- margin: 0;
216
- padding: 0;
217
- list-style: none;
218
- display: flex;
219
- flex-direction: column;
220
- gap: 2px;
221
- }
222
- li {
223
- display: flex;
224
- align-items: center;
225
- gap: 6px;
226
- padding: 4px 6px;
227
- border-radius: 6px;
228
- cursor: pointer;
229
- }
230
- li:hover {
231
- background-color: var(--md-sys-color-surface-container);
232
- }
233
- li[selected] {
234
- color: var(--md-sys-color-on-primary-container);
235
- background-color: var(--md-sys-color-primary-container);
236
- }
237
- li md-icon {
238
- --md-icon-size: 16px;
239
- flex: none;
240
- color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));
241
- }
242
- button[eye][all] {
243
- margin-left: auto;
244
- opacity: 0.75;
245
- }
246
- button[eye][all]:hover {
247
- opacity: 1;
248
- }
249
- button[eye] {
250
- display: flex;
251
- flex: none;
252
- padding: 1px;
253
- color: inherit;
254
- background: none;
255
- border: none;
256
- border-radius: 4px;
257
- cursor: pointer;
258
- opacity: 0;
259
- }
260
- li:hover button[eye],
261
- li[selected] button[eye],
262
- button[eye][off] {
263
- opacity: 1;
264
- }
265
- button[eye][off] {
266
- color: var(--md-sys-color-tertiary);
267
- }
268
- button[eye] md-icon {
269
- --md-icon-size: 15px;
270
- color: inherit;
271
- }
272
- li[off] span[label],
273
- li[off] > md-icon,
274
- li[invisible] span[label],
275
- li[invisible] > md-icon {
276
- opacity: 0.45;
277
- }
278
- li[selected] md-icon {
279
- color: inherit;
280
- }
281
- span[label] {
282
- flex: 1;
283
- min-width: 0;
284
- overflow: hidden;
285
- text-overflow: ellipsis;
286
- white-space: nowrap;
287
- font-size: 0.78rem;
288
- }
289
- span[label] small {
290
- margin-left: 4px;
291
- font-size: 0.66rem;
292
- color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));
293
- }
294
- div[ops] {
295
- display: none;
296
- gap: 1px;
297
- }
298
- li[selected] div[ops] {
299
- display: flex;
300
- }
301
- div[ops] button {
302
- display: flex;
303
- padding: 2px;
304
- color: inherit;
305
- background: none;
306
- border: none;
307
- border-radius: 4px;
308
- cursor: pointer;
309
- }
310
- div[ops] button:hover:not([disabled]) {
311
- background-color: var(--md-sys-color-surface-container-lowest);
312
- }
313
- div[ops] button[disabled] {
314
- opacity: 0.3;
315
- cursor: default;
316
- }
317
- div[ops] md-icon {
318
- --md-icon-size: 15px;
319
- color: inherit;
320
- }
321
- /*
322
- Under 200 px the selected row's four buttons pushed its name out and the last one past the edge (seen at 140,
323
- 2026-09-24). They go to a line of their own under the name.
324
- */
325
- @container (max-width: 199px) {
326
- li[selected] {
327
- flex-wrap: wrap;
328
- }
329
- li[selected] div[ops] {
330
- flex-basis: 100%;
331
- justify-content: flex-end;
332
- }
333
- }
334
- p[quiet] {
335
- margin: 0;
336
- font-size: 0.76rem;
337
- line-height: 1.6;
338
- color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));
339
- }
340
- `
341
- ]; }
342
- render() {
343
- const b = this.partBudget;
344
- const full = !!b && b.limit !== null && b.used >= b.limit;
345
- return html `
346
- <section>
347
- <h3>${i18next.t('figure.label.shapes')}</h3>
348
- <div palette>
349
- ${RECIPES.map(recipe => html `
350
- <button
351
- shape
352
- ?disabled=${this.locked || full}
353
- title=${full ? i18next.t('figure.text.part-limit-reached') : i18next.t(recipe.label)}
354
- @click=${() => this.ask('add-part', { kind: recipe.kind })}
355
- >
356
- <md-icon>${recipe.icon}</md-icon>
357
- <span>${i18next.t(recipe.label)}</span>
358
- </button>
359
- `)}
360
- </div>
361
- ${full ? html `<p full>${i18next.t('figure.text.part-limit-reached-short', { level: b.level, limit: b.limit })}</p>` : nothing}
362
- </section>
363
- ${this.renderRecipes(full)}
364
-
365
- <section list>
366
- <h3>
367
- <span>${i18next.t('figure.label.parts')}</span>
368
- <span room ?full=${full} title=${i18next.t('figure.text.limit-comes-from-level')}
369
- >${b && b.limit !== null ? i18next.t('figure.text.n-of-limit', { used: b.used, limit: b.limit }) : (b?.used ?? this.parts.length)}</span
370
- >
371
- ${this.renderShowAll()}
372
- </h3>
373
- ${this.renderLevel()}
374
- ${this.renderBudget()}
375
- ${this.parts.length === 0
376
- ? html `<p quiet>${i18next.t('figure.text.no-parts-yet')}</p>`
377
- : html `<ol>
378
- ${this.parts.map((part, index) => this.renderRow(part, index))}
379
- </ol>`}
380
- </section>
381
- `;
382
- }
383
- /** 디테일 등급 — 고르면 한도가 바뀐다. 목록 머리 아래. */
384
- renderLevel() {
385
- const b = this.partBudget;
386
- if (!b)
387
- return nothing;
388
- return html `<div level>
389
- <label for="detail-level">${i18next.t('figure.label.detail-level')}</label>
390
- <select
391
- id="detail-level"
392
- title=${i18next.t('figure.text.detail-level-explained')}
393
- .value=${b.level ?? ''}
394
- ?disabled=${this.locked}
395
- @change=${(e) => {
396
- const value = e.target.value;
397
- this.dispatchEvent(new CustomEvent('set-detail-level', { detail: { level: value || null }, bubbles: true, composed: true }));
398
- }}
399
- >
400
- <option value="" ?selected=${!b.level}>${i18next.t('figure.label.detail-none')}</option>
401
- ${['S', 'M', 'L'].map(one => html `<option value=${one} ?selected=${one === b.level}>
402
- ${one} ${i18next.t('figure.label.detail-' + one)} · ${i18next.t('figure.text.n-parts-at-most', { limit: PART_LIMIT[one] })}
403
- </option>`)}
404
- </select>
405
- </div>`;
406
- }
407
- renderBudget() {
408
- const b = this.budget;
409
- if (!b || !this.parts.length)
410
- return nothing;
411
- const over = b.grade === 'D';
412
- return html `<button
413
- budget
414
- grade=${b.grade}
415
- title=${i18next.t('figure.text.parts-budget-open')}
416
- @click=${() => this.dispatchEvent(new CustomEvent('show-maturity', { bubbles: true, composed: true }))}
417
- >
418
- <b>${b.grade}</b>
419
- <span>
420
- <strong performance-cost>${i18next.t('figure.label.performance-cost')}</strong>
421
- ${i18next.t('figure.text.parts-budget', {
422
- triangles: b.triangles.toLocaleString(),
423
- groups: b.groups.toLocaleString(),
424
- instances: b.instances.toLocaleString()
425
- })}
426
- ${over
427
- ? html `<em
428
- >${i18next.t('figure.text.parts-budget-over', {
429
- budget: i18next.t('figure.label.budget-' + b.tightest.key),
430
- used: b.tightest.used.toLocaleString(),
431
- limit: b.tightest.limit.toLocaleString()
432
- })}</em
433
- >`
434
- : nothing}
435
- </span>
436
- </button>`;
437
- }
438
- /** 한꺼번에 감추고 한꺼번에 되돌린다 — 하나라도 감춰져 있으면 다 되돌리고, 다 보이면 다 감춘다. */
439
- renderShowAll() {
440
- if (this.parts.length === 0)
441
- return nothing;
442
- const anyHidden = this.parts.some(part => part.hidden);
443
- return html `
444
- <button
445
- eye
446
- all
447
- ?off=${!anyHidden}
448
- title=${i18next.t(anyHidden ? 'figure.text.show-all-parts' : 'figure.text.hide-all-parts')}
449
- @click=${(e) => {
450
- e.stopPropagation();
451
- this.ask('set-all-parts-hidden', { hidden: !anyHidden });
452
- }}
453
- >
454
- <md-icon>${anyHidden ? 'visibility' : 'visibility_off'}</md-icon>
455
- </button>
456
- `;
457
- }
458
- renderRow(part, index) {
459
- const selected = part.id === this.selected;
460
- const off = !!part.hidden;
461
- return html `
462
- <li
463
- ?selected=${selected}
464
- ?off=${off}
465
- ?invisible=${!!part.invisible}
466
- @click=${() => this.ask('select-part', { id: part.id })}
467
- >
468
- <button
469
- eye
470
- ?off=${off}
471
- title=${i18next.t(off ? 'figure.text.show-this-part' : 'figure.text.hide-this-part')}
472
- @click=${(e) => {
473
- e.stopPropagation();
474
- this.ask('toggle-part-hidden', { id: part.id });
475
- }}
476
- >
477
- <md-icon>${off ? 'visibility_off' : 'visibility'}</md-icon>
478
- </button>
479
- <md-icon>${PROVIDER_ICON[part.provider] ?? 'deployed_code'}</md-icon>
480
- <span label title=${part.id}
481
- >${partLabelOf(part.id)}${part.copies ? html ` <small copies>× ${part.copies}</small>` : nothing}${part.invisible ? html `<small>${i18next.t('figure.label.state-hidden')}</small>` : nothing}</span
482
- >
483
- ${selected ? this.renderOps(part.id, index) : nothing}
484
- </li>
485
- `;
486
- }
487
- /** 고른 줄의 조작. 못 하는 것은 빼지 않고 흐리게 둔다 — 자리가 밀리면 연달아 지우다 엉뚱한 것을 누른다. */
488
- renderOps(id, index) {
489
- const count = this.parts.length;
490
- const op = (name, icon, detail, enabled = true) => html `
491
- <button
492
- op=${name}
493
- ?disabled=${!enabled || this.locked}
494
- title=${i18next.t('figure.button.' + name)}
495
- @click=${(e) => {
496
- e.stopPropagation();
497
- if (enabled && !this.locked)
498
- this.ask(name, detail);
499
- }}
500
- >
501
- <md-icon>${icon}</md-icon>
502
- </button>
503
- `;
504
- return html `
505
- <div ops>
506
- ${op('move-part-up', 'arrow_upward', { id, to: index - 1 }, index > 0)}
507
- ${op('move-part-down', 'arrow_downward', { id, to: index + 1 }, index < count - 1)}
508
- ${op('duplicate-part', 'content_copy', { id })} ${op('remove-part', 'delete', { id })}
509
- </div>
510
- `;
511
- }
512
- /**
513
- * Recipes (ADR-0095): the catalog of templates -- a door, a roller row -- opened over the modeller, put onto the chosen
514
- * part in one step.
515
- */
516
- renderRecipes(full) {
517
- if (!this.recipeCount)
518
- return nothing;
519
- return html `<section recipes>
520
- <h3>${i18next.t('figure.label.recipes')}</h3>
521
- <button recipe-catalog ?disabled=${this.locked || full} @click=${() => this.ask('open-recipe-catalog', {})}>
522
- <md-icon>widgets</md-icon>${i18next.t('figure.button.open-recipe-catalog', { count: this.recipeCount })}
523
- </button>
524
- </section>`;
525
- }
526
- /** 정본을 고치지 않는다 — 무엇을 하겠다는 것만 알린다. */
527
- ask(what, detail) {
528
- this.dispatchEvent(new CustomEvent(what, { detail, bubbles: true, composed: true }));
529
- }
530
- };
531
- __decorate([
532
- property({ type: Array }),
533
- __metadata("design:type", Array)
534
- ], FigureV3Parts.prototype, "parts", void 0);
535
- __decorate([
536
- property({ type: String }),
537
- __metadata("design:type", Object)
538
- ], FigureV3Parts.prototype, "selected", void 0);
539
- __decorate([
540
- property({ type: Boolean }),
541
- __metadata("design:type", Object)
542
- ], FigureV3Parts.prototype, "locked", void 0);
543
- __decorate([
544
- property({ attribute: false }),
545
- __metadata("design:type", Object)
546
- ], FigureV3Parts.prototype, "budget", void 0);
547
- __decorate([
548
- property({ attribute: false }),
549
- __metadata("design:type", Object)
550
- ], FigureV3Parts.prototype, "partBudget", void 0);
551
- __decorate([
552
- property({ type: Number }),
553
- __metadata("design:type", Object)
554
- ], FigureV3Parts.prototype, "recipeCount", void 0);
555
- FigureV3Parts = __decorate([
556
- customElement('figure-v3-parts')
557
- ], FigureV3Parts);
558
- export { FigureV3Parts };
559
- //# sourceMappingURL=figure-v3-parts.js.map