@things-factory/figure-ui 10.1.45 → 10.1.46

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.45",
3
+ "version": "10.1.46",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "@things-factory:registry": "https://registry.npmjs.org"
@@ -26,7 +26,7 @@
26
26
  "clean": "npm run clean:server && npm run clean:client"
27
27
  },
28
28
  "dependencies": {
29
- "@hatiolab/figure-model": "^0.1.47",
29
+ "@hatiolab/figure-model": "^0.1.48",
30
30
  "@hatiolab/things-scene": "^10.1.26",
31
31
  "@material/web": "^2.0.0",
32
32
  "@operato/data-grist": "^10.0.0",
@@ -37,8 +37,8 @@
37
37
  "@operato/shell": "^10.0.0",
38
38
  "@operato/styles": "^10.0.0",
39
39
  "@operato/utils": "^10.0.0",
40
- "@things-factory/figure-service": "^10.1.45",
40
+ "@things-factory/figure-service": "^10.1.46",
41
41
  "three": "^0.185.1"
42
42
  },
43
- "gitHead": "d72e1fd1285797fcd7839d97a18e31f5bf076ae3"
43
+ "gitHead": "d3467cde550453f3348fed0ed6c79a12a6ba0db4"
44
44
  }
@@ -10,7 +10,7 @@ import assert from 'node:assert/strict'
10
10
  import { addV3Box, addV3Primitive, applyV3Authoring, createV3Asset } from '@hatiolab/figure-model'
11
11
  import type { V3Asset } from '@hatiolab/figure-model'
12
12
 
13
- import { canFasten, canFollow, fastenedTo, followOf, hasInstanceSize, motionOf, positionsWorkedOut } from '../client/modeller/v3-links.ts'
13
+ import { acceptsOf, canFasten, canFollow, fastenedTo, followOf, hasInstanceSize, holdsThings, motionOf, placeFacesOf, placeIdFor, placesOn, positionsWorkedOut } from '../client/modeller/v3-links.ts'
14
14
 
15
15
  const pair = (): V3Asset => {
16
16
  let asset = createV3Asset('Pair')
@@ -104,7 +104,7 @@ test('세 칸의 말은 다섯 말 모두에 있다', () => {
104
104
  const keys = [...links.matchAll(/'(figure\.[a-z.-]*[a-z])'/g)].map(m => m[1])
105
105
  for (const lang of ['ko', 'en', 'ja', 'zh', 'ms']) {
106
106
  const table = JSON.parse(read(`../translations/${lang}.json`))
107
- for (const key of [...keys, 'figure.text.follow-would-loop', 'figure.text.fasten-would-loop', 'figure.label.motion-slide', 'figure.label.motion-turn'])
107
+ for (const key of [...keys, 'figure.text.follow-would-loop', 'figure.text.fasten-would-loop', 'figure.label.motion-slide', 'figure.label.motion-turn', 'figure.label.place-grip', 'figure.label.place-seat'])
108
108
  assert.ok(table[key], `${lang}: ${key}`)
109
109
  }
110
110
  })
@@ -121,3 +121,43 @@ test('도형 크기를 따라 움직이는 자리를 가려 읽고, 여기에
121
121
  assert.deepEqual(positionsWorkedOut(fixed, 'lamp'), [])
122
122
  assert.equal(fixed.designInputs['lamp.position.y'], 110, '지금 자리 그대로 — 100 + 10')
123
123
  })
124
+
125
+ test('자리 — 부품의 면에 둔 집는 자리·놓는 자리를 그 부품에서 읽는다', () => {
126
+ let asset = pair()
127
+ asset = addV3Primitive(asset, { id: 'drum', kind: 'cylinder', dimensions: { radius: 100, length: 300 }, position: { x: 0, y: 400, z: 0 } } as never)
128
+ assert.deepEqual(placeFacesOf(asset, 'block'), ['left', 'right', 'bottom', 'top', 'back', 'front'])
129
+ assert.deepEqual(placeFacesOf(asset, 'drum'), [], '둥근 몸에는 자리를 권하지 않는다 — 명령이 거절할 것이다')
130
+
131
+ assert.equal(placeIdFor(asset, 'block', 'grip'), 'block-grip')
132
+ asset = applyV3Authoring(asset, { kind: 'add-binding', id: placeIdFor(asset, 'block', 'grip'), label: '집는 자리', role: 'grip', part: 'block', face: 'top', accepts: acceptsOf(' BOX, TOTE,, BOX '), capacity: 2 })
133
+ assert.equal(placeIdFor(asset, 'block', 'grip'), 'block-grip-2', '같은 부품에 둘째 자리는 다른 id')
134
+ assert.deepEqual(
135
+ placesOn(asset, 'block').map(p => [p.id, p.role, p.face, p.accepts, p.capacity]),
136
+ [['block-grip', 'grip', 'top', ['BOX', 'TOTE'], 2]]
137
+ )
138
+ assert.deepEqual(placesOn(asset, 'plate'), [], '다른 부품의 자리는 안 섞인다')
139
+ })
140
+
141
+ test('담는 능력이 없는 도형은 자리가 있어도 보드가 아무것도 넘기지 않는다 — 화면이 그것을 말한다', () => {
142
+ const asset = pair()
143
+ assert.equal(holdsThings(asset), false)
144
+ asset.document.capabilities.names = ['Capacity', 'Holdable']
145
+ assert.equal(holdsThings(asset), true)
146
+ asset.document.capabilities.names = ['FlowNode']
147
+ assert.equal(holdsThings(asset), true, 'FlowNode 는 Capacity 를 품는다')
148
+
149
+ const links = read('../client/modeller/figure-v3-links.ts')
150
+ assert.match(links, /holdsThings\(asset\)/)
151
+ assert.match(links, /kind: 'set-capabilities', names/)
152
+ const editor = read('../client/modeller/v3-editor.ts')
153
+ /* A slice and `includes`, not a lazy regex over the whole editor: that hangs when it does not match. */
154
+ const start = editor.indexOf('<figure-v3-links')
155
+ const block = editor.slice(start, editor.indexOf('</figure-v3-links>', start))
156
+ assert.ok(start >= 0 && block.includes('@v3-part-edit=${(e: CustomEvent) => this.run(() => this.session!.edit(e.detail.edit))}'), '자리 절의 능력 선언이 편집기에 닿는다')
157
+ })
158
+
159
+ test('받는 종류가 없으면 자리를 만들지 않는다 — 형식에 「아무거나」가 없다', () => {
160
+ const links = read('../client/modeller/figure-v3-links.ts')
161
+ assert.match(links, /\?disabled=\$\{this\.locked \|\| !accepts\.length \|\| !capacityOk\}/)
162
+ assert.deepEqual(acceptsOf(' , ,'), [])
163
+ })
@@ -565,5 +565,19 @@
565
565
  "figure.label.state-inputs": "state inputs",
566
566
  "figure.label.design-inputs": "design inputs",
567
567
  "figure.text.release-blocked": "Release is blocked — {count}",
568
- "figure.text.release-ready": "Ready to release"
568
+ "figure.text.release-ready": "Ready to release",
569
+ "figure.label.places": "Places",
570
+ "figure.text.places-need-a-box": "A place sits on a face of a box-shaped part.",
571
+ "figure.label.place-grip": "Grip",
572
+ "figure.label.place-seat": "Seat",
573
+ "figure.label.place-holds": "up to {count}",
574
+ "figure.button.remove-place": "Remove place",
575
+ "figure.text.place-explained": "Where a board sets or holds things on this part. When the part moves, what it holds moves with it.",
576
+ "figure.text.place-needs-holding": "This figure does not declare that it holds things, so a board hands nothing to its places.",
577
+ "figure.button.declare-holding": "Make it hold things",
578
+ "figure.label.place-name": "Name",
579
+ "figure.label.place-accepts": "Takes",
580
+ "figure.label.place-capacity": "How many",
581
+ "figure.text.place-accepts-needed": "Name at least one type it takes, separated by commas.",
582
+ "figure.button.add-place": "Add place"
569
583
  }
@@ -565,5 +565,19 @@
565
565
  "figure.button.keep-changed-appearance": "調整したモデル幅で公開",
566
566
  "figure.button.restore-released-base": "以前のモデル幅に戻す",
567
567
  "figure.text.appearance-choice-explained": "戻すと X と Z を直前の公開値に戻し、Y とほかの編集はそのまま残します。調整した幅で公開すると、今のモデルの外形を残します。",
568
- "figure.text.choose-appearance-change": "調整したモデル幅の扱いを選んでください"
568
+ "figure.text.choose-appearance-change": "調整したモデル幅の扱いを選んでください",
569
+ "figure.label.places": "置き場所",
570
+ "figure.text.places-need-a-box": "置き場所は箱形の部品の面に置きます。",
571
+ "figure.label.place-grip": "つかむ場所",
572
+ "figure.label.place-seat": "載せる場所",
573
+ "figure.label.place-holds": "{count}個まで",
574
+ "figure.button.remove-place": "置き場所を削除",
575
+ "figure.text.place-explained": "ボード上で物をこの部品のどの面に載せるか、つかむかを決めます。部品が動くと物も一緒に動きます。",
576
+ "figure.text.place-needs-holding": "この図形は物を保持すると宣言していないため、置き場所を作ってもボードは物を渡しません。",
577
+ "figure.button.declare-holding": "物を保持する図形にする",
578
+ "figure.label.place-name": "名前",
579
+ "figure.label.place-accepts": "受け取る種類",
580
+ "figure.label.place-capacity": "最大個数",
581
+ "figure.text.place-accepts-needed": "受け取る種類を一つ以上、カンマ区切りで入力してください。",
582
+ "figure.button.add-place": "置き場所を追加"
569
583
  }
@@ -565,5 +565,19 @@
565
565
  "figure.label.state-inputs": "상태 입력",
566
566
  "figure.label.design-inputs": "설계 입력",
567
567
  "figure.text.release-blocked": "발행이 막힙니다 — {count}건",
568
- "figure.text.release-ready": "발행할 수 있습니다"
568
+ "figure.text.release-ready": "발행할 수 있습니다",
569
+ "figure.label.places": "자리",
570
+ "figure.text.places-need-a-box": "자리는 상자 모양 부품의 면에 둡니다.",
571
+ "figure.label.place-grip": "집는 자리",
572
+ "figure.label.place-seat": "놓는 자리",
573
+ "figure.label.place-holds": "{count}개까지",
574
+ "figure.button.remove-place": "자리 없애기",
575
+ "figure.text.place-explained": "보드에서 물건을 이 부품의 어느 면에 놓거나 집을지 정합니다. 부품이 움직이면 물건도 따라갑니다.",
576
+ "figure.text.place-needs-holding": "이 도형은 물건을 담는다고 선언하지 않아서, 자리를 만들어도 보드가 여기에 물건을 넘기지 않습니다.",
577
+ "figure.button.declare-holding": "물건을 담는 도형으로",
578
+ "figure.label.place-name": "이름",
579
+ "figure.label.place-accepts": "받는 종류",
580
+ "figure.label.place-capacity": "몇 개까지",
581
+ "figure.text.place-accepts-needed": "받는 종류를 하나 이상 적어야 자리를 만들 수 있습니다. 쉼표로 나눕니다.",
582
+ "figure.button.add-place": "자리 추가"
569
583
  }
@@ -565,5 +565,19 @@
565
565
  "figure.button.keep-changed-appearance": "terbitkan dengan lebar model yang dilaraskan",
566
566
  "figure.button.restore-released-base": "pulihkan lebar model sebelumnya",
567
567
  "figure.text.appearance-choice-explained": "Pulihkan mengembalikan X dan Z kepada nilai terbitan sebelumnya dan mengekalkan Y serta semua suntingan lain. Menerbitkan dengan lebar yang dilaraskan mengekalkan garis luar model semasa.",
568
- "figure.text.choose-appearance-change": "pilih cara mengendalikan lebar model yang dilaraskan"
568
+ "figure.text.choose-appearance-change": "pilih cara mengendalikan lebar model yang dilaraskan",
569
+ "figure.label.places": "Tempat",
570
+ "figure.text.places-need-a-box": "Tempat diletakkan pada muka bahagian berbentuk kotak.",
571
+ "figure.label.place-grip": "Tempat cengkam",
572
+ "figure.label.place-seat": "Tempat letak",
573
+ "figure.label.place-holds": "sehingga {count}",
574
+ "figure.button.remove-place": "Buang tempat",
575
+ "figure.text.place-explained": "Tentukan muka bahagian ini tempat papan meletakkan atau memegang barang. Apabila bahagian bergerak, barang ikut bergerak.",
576
+ "figure.text.place-needs-holding": "Rajah ini tidak mengisytiharkan bahawa ia memegang barang, jadi papan tidak menyerahkan apa-apa ke tempatnya.",
577
+ "figure.button.declare-holding": "Jadikan ia memegang barang",
578
+ "figure.label.place-name": "Nama",
579
+ "figure.label.place-accepts": "Jenis diterima",
580
+ "figure.label.place-capacity": "Berapa banyak",
581
+ "figure.text.place-accepts-needed": "Namakan sekurang-kurangnya satu jenis yang diterima, dipisahkan dengan koma.",
582
+ "figure.button.add-place": "Tambah tempat"
569
583
  }
@@ -565,5 +565,19 @@
565
565
  "figure.button.keep-changed-appearance": "以调整后的模型宽度发布",
566
566
  "figure.button.restore-released-base": "恢复为之前的模型宽度",
567
567
  "figure.text.appearance-choice-explained": "恢复会把 X 和 Z 还原为上次发布的值,并保留 Y 及其他所有编辑。以调整后的宽度发布则保留当前模型轮廓。",
568
- "figure.text.choose-appearance-change": "请选择如何处理调整后的模型宽度"
568
+ "figure.text.choose-appearance-change": "请选择如何处理调整后的模型宽度",
569
+ "figure.label.places": "位置",
570
+ "figure.text.places-need-a-box": "位置设在方盒形部件的面上。",
571
+ "figure.label.place-grip": "夹持位置",
572
+ "figure.label.place-seat": "放置位置",
573
+ "figure.label.place-holds": "最多 {count} 个",
574
+ "figure.button.remove-place": "删除位置",
575
+ "figure.text.place-explained": "决定在看板上物品放在或夹在这个部件的哪个面上。部件移动时,物品也随之移动。",
576
+ "figure.text.place-needs-holding": "这个图形没有声明可以容纳物品,所以即使设了位置,看板也不会把物品交给它。",
577
+ "figure.button.declare-holding": "设为可容纳物品的图形",
578
+ "figure.label.place-name": "名称",
579
+ "figure.label.place-accepts": "接收类型",
580
+ "figure.label.place-capacity": "最多数量",
581
+ "figure.text.place-accepts-needed": "至少填写一个接收类型,用逗号分隔。",
582
+ "figure.button.add-place": "添加位置"
569
583
  }