@things-factory/figure-ui 10.1.104 → 10.1.105

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/figure-ui",
3
- "version": "10.1.104",
3
+ "version": "10.1.105",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "@things-factory:registry": "https://registry.npmjs.org"
@@ -27,7 +27,7 @@
27
27
  "clean": "npm run clean:server && npm run clean:client"
28
28
  },
29
29
  "dependencies": {
30
- "@hatiolab/figure-model": "^0.2.4",
30
+ "@hatiolab/figure-model": "^0.2.5",
31
31
  "@hatiolab/things-scene": "^10.1.64",
32
32
  "@material/web": "^2.0.0",
33
33
  "@operato/data-grist": "^10.0.0",
@@ -41,8 +41,8 @@
41
41
  "@operato/styles": "^10.0.0",
42
42
  "@operato/utils": "^10.0.0",
43
43
  "@things-factory/ai-assistant": "^10.1.104",
44
- "@things-factory/figure-service": "^10.1.84",
44
+ "@things-factory/figure-service": "^10.1.105",
45
45
  "three": "^0.185.1"
46
46
  },
47
- "gitHead": "0d05c7573220c6da2dec2654a4b86d7bd8e3c4fb"
47
+ "gitHead": "c8ad9b40d57709beefd5e3d6167fd9cab6efea3a"
48
48
  }
@@ -61,7 +61,11 @@ test('커널이 거절할 모양은 보내지 않고 까닭을 말한다 — 끄
61
61
  })
62
62
 
63
63
  test('단면 칸에 그림이 들어간다: 속 공간이 있을 때, 면마다 벽 토글을 따른다', () => {
64
- has(panel, /cavity \? html`<figure-cavity-drawing \.body=\$\{body\} \.perSide=\$\{this\.perSide\} \?locked=\$\{this\.locked\}><\/figure-cavity-drawing>` : nothing/)
64
+ has(panel, /\? html`<figure-cavity-drawing \.body=\$\{body\} \.perSide=\$\{this\.perSide\} \?locked=\$\{this\.locked\}><\/figure-cavity-drawing>/)
65
+ /* The number fields under the drawing went: a wall's number or a closed end's is pressed and typed in the drawing. */
66
+ assert.ok(!panel.includes("cavityField(") && !panel.includes('renderEnd('), 'no number fields repeating the drawing')
67
+ has(drawing, /@pointerdown=\$\{\(ev: PointerEvent\) => this\.type\(ev, \{ kind: 'wall', side \}, 'top', w\.wall\[side\]!\)\}/)
68
+ has(drawing, /!open && this\.type\(ev, \{ kind: 'end', end \}, 'side'/)
65
69
  for (const lang of ['ko', 'en', 'ja', 'zh', 'ms']) {
66
70
  const t = JSON.parse(read(`../translations/${lang}.json`)) as Record<string, string>
67
71
  for (const key of ['figure.label.section-cavity-top', 'figure.label.section-cavity-side']) assert.ok(t[key], `${lang} ${key}`)
@@ -181,7 +181,9 @@ test('편집 창이 열린 동안 모델러의 키는 비켜선다 — Esc 가
181
181
  test('속성의 형상 치수에는 점·꼭짓점 칸이 없다 (사용자 10-01) — 높이만 남고, 단면 칸이 점 개수를 말한다', async () => {
182
182
  const { groupFields } = await import('../client/modeller/fields.ts')
183
183
  const f = (id: string) => ({ id, value: 0, unit: 'mm' })
184
- const ids = ['tip.dimension.height', 'tip.point.p1.x', 'tip.point.p1.z', 'tip.point.p12.x', 'tip.apex.x', 'tip.apex.z', 'tip.position.x']
184
+ const ids = ['tip.dimension.height', 'tip.point.p1.x', 'tip.point.p1.z', 'tip.point.p12.x', 'tip.apex.x', 'tip.apex.z', 'tip.position.x',
185
+ /* A tote's corners and inside are the 단면 group's too, not the shape's list under inner names. */
186
+ 'tip.dimension.round', 'tip.dimension.wall', 'tip.dimension.closed.start', 'tip.dimension.wallX', 'tip.corner.x', 'tip.wall.x-']
185
187
  const { singles } = groupFields(ids.map(f) as never, 'tip')
186
188
  assert.deepEqual(singles.map(g => (g as { field: { id: string } }).field.id), ['tip.dimension.height'])
187
189
  has(sectionPanel, /e\.apex \? 'figure\.text\.section-points-apex' : 'figure\.text\.section-points', \{ points: String\(e\.section\.points\.length\) \}/)
@@ -30,6 +30,8 @@ const read = (path: string) => readFileSync(fileURLToPath(new URL(path, import.m
30
30
  const has = (source: string, re: RegExp, message?: string) => assert.ok(re.test(source), message ?? `missing: ${re}`)
31
31
  const hasNot = (source: string, re: RegExp, message?: string) => assert.ok(!re.test(source), message ?? `present: ${re}`)
32
32
  const panel = read('../client/modeller/figure-section-panel.ts')
33
+ /* The inside is drawn and typed in its own element (user 2026-10-01): its words and limits are read there. */
34
+ const drawing = read('../client/modeller/figure-cavity-drawing.ts')
33
35
  const editor = read('../client/modeller/editor.ts')
34
36
  const ko = JSON.parse(read('../translations/ko.json')) as Record<string, string>
35
37
 
@@ -92,7 +94,7 @@ test('편집기는 단면 칸의 명령을 세션의 이력 하나로 돌리고,
92
94
  has(editor, /private linkCommand\(action: FigureAuthoringAction\) \{\s*\/\*[^*]*\*\/\s*this\.holdAction\(null\)/, 'a command sent lets go of the one in hand')
93
95
  for (const lang of ['ko', 'en', 'ja', 'zh', 'ms']) {
94
96
  const words = JSON.parse(read(`../translations/${lang}.json`)) as Record<string, string>
95
- const used = [...new Set([...panel.matchAll(/'(figure\.(?:label|text)\.section-[\w-]+|figure\.label\.group-section)'/g)].map(m => m[1]!))]
97
+ const used = [...new Set([...(panel + drawing).matchAll(/'(figure\.(?:label|text)\.section-[\w-]+|figure\.label\.group-section)'/g)].map(m => m[1]!))]
96
98
  /* The keys the panel builds: each result, and the wall's and the ends' over-limit words. */
97
99
  used.push(...['pipe', 'container', 'sealed'].map(r => `figure.label.section-result-${r}`), 'figure.text.section-wall-over', 'figure.text.section-ends-over')
98
100
  assert.ok(used.length >= 16)
@@ -150,7 +152,7 @@ test('치는 동안의 값은 사본에 그려지고 원본은 그대로다 —
150
152
 
151
153
  test('다각 단면에는 속 공간을 만들 수 없다고 그 자리에서 말한다', () => {
152
154
  /* A drawn section has no inside control at all, rather than a line saying it cannot have one (user 2026-10-01). */
153
- has(panel, /kind === 'rectangle' \|\| kind === 'ellipse' \? this\.renderCavity\(body, e\.axis\) : nothing/)
155
+ has(panel, /kind === 'rectangle' \|\| kind === 'ellipse' \? this\.renderCavity\(body\) : nothing/)
154
156
  })
155
157
 
156
158
  test('붙어 있는 것이 기대는 면을 없애는 편집은 거절되고, 그 면을 사람의 말로 부른다', () => {
@@ -191,5 +193,5 @@ test('한 면의 벽 한도는 그 방향의 너비에서 맞은편 벽을 뺀
191
193
  /* The kernel agrees: just under takes, the limit refuses. */
192
194
  assert.equal(cavityRefusalOf(shape, cavityRequestOf(shape, { wall: { ...walls, 'x-': 359 } })), null)
193
195
  assert.equal(cavityRefusalOf(shape, cavityRequestOf(shape, { wall: { ...walls, 'x-': 360 } }))!.code, 'wall-too-thick')
194
- has(panel, /sideWallLimitOf\(body\.shape, cavity\.wall, side\)/)
196
+ has(drawing, /this\.perSide && side \? mm\(sideWallLimitOf\(this\.body!\.shape, w\.wall, side\)\) : ask\.max/)
195
197
  })
@@ -467,7 +467,6 @@
467
467
  "figure.text.nothing-released-yet": "nothing released yet.",
468
468
  "figure.text.on-by-default-explained": "the starting state when placed on a drawing. a value set on the instance takes priority.",
469
469
  "figure.text.other-segment-count": "enter a value",
470
- "figure.text.palette-purpose-explained": "choose the color role this part plays on screen.",
471
470
  "figure.text.part-limit-reached": "the detail level allows no more parts — raise the level or remove a part.",
472
471
  "figure.text.part-limit-reached-short": "level {level} allows {limit} parts. raise the level or remove a part.",
473
472
  "figure.text.part-name-cannot-be-empty": "give the part a name.",
@@ -467,7 +467,6 @@
467
467
  "figure.text.nothing-released-yet": "まだ発行したバージョンがありません。",
468
468
  "figure.text.on-by-default-explained": "図面に置いたときの最初の状態です。インスタンスで切り替えた値が優先されます。",
469
469
  "figure.text.other-segment-count": "enter a value",
470
- "figure.text.palette-purpose-explained": "この部品が画面で担う色の役割を選びます。",
471
470
  "figure.text.part-limit-reached": "the detail level allows no more parts — raise the level or remove a part.",
472
471
  "figure.text.part-limit-reached-short": "level {level} allows {limit} parts. Raise the level or remove a part.",
473
472
  "figure.text.part-name-cannot-be-empty": "部品に名前を付けてください。",
@@ -467,7 +467,6 @@
467
467
  "figure.text.nothing-released-yet": "아직 발행한 버전이 없습니다.",
468
468
  "figure.text.on-by-default-explained": "도면에 놓았을 때의 처음 상태입니다. 인스턴스에서 켜고 끈 값이 우선합니다.",
469
469
  "figure.text.other-segment-count": "직접 입력",
470
- "figure.text.palette-purpose-explained": "이 부품이 화면에서 맡을 색 역할을 고릅니다.",
471
470
  "figure.text.part-limit-reached": "디테일 등급이 허용하는 부품 수를 모두 사용했습니다. 등급을 올리거나 부품을 삭제하세요.",
472
471
  "figure.text.part-limit-reached-short": "{level} 등급은 부품 {limit}개까지입니다. 등급을 올리거나 부품을 삭제하세요.",
473
472
  "figure.text.part-name-cannot-be-empty": "부품 이름을 입력해 주세요.",
@@ -467,7 +467,6 @@
467
467
  "figure.text.nothing-released-yet": "belum ada yang diterbitkan.",
468
468
  "figure.text.on-by-default-explained": "keadaan permulaan apabila diletakkan pada lukisan. nilai yang ditetapkan pada instans diutamakan.",
469
469
  "figure.text.other-segment-count": "enter a value",
470
- "figure.text.palette-purpose-explained": "pilih peranan warna yang dimainkan bahagian ini pada skrin.",
471
470
  "figure.text.part-limit-reached": "the detail level allows no more parts — raise the level or remove a part.",
472
471
  "figure.text.part-limit-reached-short": "level {level} allows {limit} parts. Raise the level or remove a part.",
473
472
  "figure.text.part-name-cannot-be-empty": "beri nama kepada bahagian.",
@@ -467,7 +467,6 @@
467
467
  "figure.text.nothing-released-yet": "还没有已发布的版本。",
468
468
  "figure.text.on-by-default-explained": "放置到图面时的初始状态。实例上设置的值优先。",
469
469
  "figure.text.other-segment-count": "enter a value",
470
- "figure.text.palette-purpose-explained": "选择此部件在画面上承担的颜色角色。",
471
470
  "figure.text.part-limit-reached": "the detail level allows no more parts — raise the level or remove a part.",
472
471
  "figure.text.part-limit-reached-short": "level {level} allows {limit} parts. Raise the level or remove a part.",
473
472
  "figure.text.part-name-cannot-be-empty": "请为部件命名。",