@things-factory/figure-ui 10.1.193 → 10.1.194

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.193",
3
+ "version": "10.1.194",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "@things-factory:registry": "https://registry.npmjs.org"
@@ -18,7 +18,7 @@
18
18
  "scripts": {
19
19
  "build": "npm run build:server && npm run build:client",
20
20
  "test": "FIGURE_FREEZE_COMPILED=1 node --import ./test/resolve-ts-siblings.mjs --test test/*.test.ts",
21
- "test:browser": "node --test test/browser/build.check.mjs test/browser/modeller.check.mjs test/browser/modeller-revision.check.mjs test/browser/editing.check.mjs test/browser/links.check.mjs test/browser/section.check.mjs test/browser/screen.check.mjs test/browser/product-page.check.mjs test/browser/parts.check.mjs test/browser/places-mesh.check.mjs test/browser/part-ids.check.mjs test/browser/fix-alignment.check.mjs test/browser/mesh-select.check.mjs test/browser/row-preview.check.mjs test/browser/detail-tabs.check.mjs test/browser/props.check.mjs test/browser/retire.check.mjs test/browser/namespace.check.mjs test/browser/public.check.mjs test/browser/category.check.mjs test/browser/property-section.check.mjs",
21
+ "test:browser": "node --test test/browser/build.check.mjs test/browser/modeller.check.mjs test/browser/modeller-revision.check.mjs test/browser/editing.check.mjs test/browser/links.check.mjs test/browser/section.check.mjs test/browser/screen.check.mjs test/browser/product-page.check.mjs test/browser/parts.check.mjs test/browser/places-mesh.check.mjs test/browser/part-ids.check.mjs test/browser/fix-alignment.check.mjs test/browser/mesh-select.check.mjs test/browser/row-preview.check.mjs test/browser/detail-tabs.check.mjs test/browser/props.check.mjs test/browser/retire.check.mjs test/browser/namespace.check.mjs test/browser/public.check.mjs test/browser/category.check.mjs test/browser/property-section.check.mjs test/browser/list.check.mjs",
22
22
  "copy:files": "copyfiles -e \"./client/**/*.{ts,js,json}\" -u 1 \"./client/**/*\" dist-client",
23
23
  "build:client": "npm run copy:files && npx tsc --p ./client/tsconfig.json",
24
24
  "build:server": "npx tsc --p ./server/tsconfig.json",
@@ -48,5 +48,5 @@
48
48
  "@things-factory/setting-base": "^10.1.192",
49
49
  "three": "^0.185.1"
50
50
  },
51
- "gitHead": "193f04828369c453b43da82f4b6b46789696255f"
51
+ "gitHead": "489dd836ae99063bfed6706367ea1d7cd7ed004a"
52
52
  }
@@ -0,0 +1,35 @@
1
+ /*
2
+ * The catalogue and the public figures, as the rail opens them (user 2026-10-19): the domain's own figures with the
3
+ * new-figure button and the draft · released choice, and other domains' public figures with neither. The server is a
4
+ * stand-in that answers each list with one card and says which list was asked for.
5
+ */
6
+ import 'figure-ui-client/pages/figure-list-page.js'
7
+ import 'figure-ui-client/pages/figure-public-list-page.js'
8
+ import { client } from '@operato/graphql'
9
+
10
+ const asked = []
11
+ const card = { id: 'one', name: 'Mixer', type: 'mixer', namespace: 'acme.example', state: 'released', version: 1, public: true, tags: [] }
12
+ client.query = async ({ query }) => {
13
+ const field = query.definitions.find(d => d.kind === 'OperationDefinition')?.selectionSet.selections[0]?.name.value
14
+ asked.push(field)
15
+ if (field === 'figures' || field === 'publicFigures')
16
+ return { data: { [field]: { items: [field === 'publicFigures' ? { ...card, domain: { id: 'd2', name: 'Other works', subdomain: 'other' } } : card], total: 1 } } }
17
+ /* No kept preferences: the page as it first opens. */
18
+ if (field === 'myPageAllPreferences') return { data: { myPageAllPreferences: [] } }
19
+ return { data: {} }
20
+ }
21
+ client.mutate = async () => ({ data: {} })
22
+
23
+ window.harness = {
24
+ asked,
25
+ mount(tag) {
26
+ document.body.replaceChildren()
27
+ const page = document.createElement(tag)
28
+ page.style.cssText = 'display:block;height:800px'
29
+ /* What the shell gives a page it routes to: the page's name, read for its kept preferences. */
30
+ page.lifecycle = { page: tag === 'figure-public-list-page' ? 'figure-public-list' : 'figure-list' }
31
+ document.body.append(page)
32
+ page.active = true
33
+ return page.localName
34
+ }
35
+ }
@@ -0,0 +1,68 @@
1
+ /*
2
+ * The rail's two lists (user 2026-10-19): the catalogue is where figures are made and changed, the public figures of
3
+ * other domains only looked at. Each is a screen of its own; the catalogue has no switch between them, and the public
4
+ * list offers no new figure and no draft · released choice.
5
+ *
6
+ * Run: node --test test/browser/list.check.mjs
7
+ */
8
+ import { test, describe, before, after } from 'node:test'
9
+ import assert from 'node:assert/strict'
10
+
11
+ import { buildPage } from './build.mjs'
12
+ import { openPage } from './serve.mjs'
13
+
14
+ const sleep = ms => new Promise(done => setTimeout(done, ms))
15
+
16
+ let opened
17
+ before(async () => {
18
+ opened = await openPage(await buildPage('list-page.js'), { width: 1400, height: 900 })
19
+ })
20
+ after(async () => {
21
+ await opened?.close()
22
+ })
23
+
24
+ const page = () => opened.page
25
+ const read = (fn, ...args) => page().evaluate(fn, ...args)
26
+ async function until(fn, what, ms = 15000) {
27
+ const deadline = Date.now() + ms
28
+ for (;;) {
29
+ if (await read(fn).catch(() => false)) return
30
+ if (Date.now() > deadline) assert.fail(`waited for ${what}`)
31
+ await sleep(50)
32
+ }
33
+ }
34
+ /* What a list page shows: its title, its FAB, the choices in its filter bar, a scope switch, and the list it asked for. */
35
+ const look = () =>
36
+ read(() => {
37
+ const host = document.body.firstElementChild
38
+ const root = host.shadowRoot
39
+ const deep = (s, r = root, o = []) => {
40
+ o.push(...r.querySelectorAll(s))
41
+ for (const e of r.querySelectorAll('*')) if (e.shadowRoot) deep(s, e.shadowRoot, o)
42
+ return o
43
+ }
44
+ return {
45
+ title: host.context.title,
46
+ fab: !!root.querySelector('button[fab]'),
47
+ scopeSwitch: !!root.querySelector('button[scope]'),
48
+ stateChoice: deep('ox-input-select-buttons[name=state]').length,
49
+ asked: harness.asked.at(-1)
50
+ }
51
+ })
52
+
53
+ describe('the rail\'s two lists', () => {
54
+ test('the catalogue: its own figures, the new-figure button and the draft · released choice, no switch to the public ones', async () => {
55
+ await read(() => harness.mount('figure-list-page'))
56
+ await until(() => harness.asked.includes('figures'), 'the own list asked for')
57
+ await until(() => !!document.body.firstElementChild.shadowRoot.querySelector('ox-grist'), 'the grid')
58
+ await sleep(500)
59
+ assert.deepEqual(await look(), { title: 'figure.title.figures', fab: true, scopeSwitch: false, stateChoice: 1, asked: 'figures' })
60
+ })
61
+
62
+ test('the public figures: other domains\' list, no new figure, no draft · released choice', async () => {
63
+ await read(() => harness.mount('figure-public-list-page'))
64
+ await until(() => harness.asked.includes('publicFigures'), 'the public list asked for')
65
+ await sleep(500)
66
+ assert.deepEqual(await look(), { title: 'figure.title.public-figures', fab: false, scopeSwitch: false, stateChoice: 0, asked: 'publicFigures' })
67
+ })
68
+ })
@@ -49,6 +49,6 @@ test("another domain's public figure: its card offers no delete and names its do
49
49
  assert.match(thumb, /badge=\$\{this\.readonly \? figure\.domain\?\.name/)
50
50
  for (const lang of ['en', 'ko', 'ja', 'zh', 'ms', 'es']) {
51
51
  const words = JSON.parse(read(`../translations/${lang}.json`))
52
- for (const key of ['figure.label.public', 'figure.button.make-public', 'figure.button.make-private', 'figure.button.public-figures']) assert.ok(words[key], `${lang} ${key}`)
52
+ for (const key of ['figure.label.public', 'figure.button.make-public', 'figure.button.make-private', 'figure.title.public-figures']) assert.ok(words[key], `${lang} ${key}`)
53
53
  }
54
54
  })
@@ -5,6 +5,7 @@ export default {
5
5
  route,
6
6
  routes: [
7
7
  { tagname: 'figure-list-page', page: 'figure-list' },
8
+ { tagname: 'figure-public-list-page', page: 'figure-public-list' },
8
9
  /* The shell builds the DOM from this table. */
9
10
  { tagname: 'figure-modeller-page', page: 'figure-modeller' }
10
11
  ],
@@ -507,6 +507,7 @@
507
507
  "figure.text.what-a-figure-is": "a Figure is a 3D component you author. compose it from simple shapes and it becomes a component you can place on a drawing, sharing shape and material across every instance.",
508
508
  "figure.text.what-changed-in-this-release": "what changed in this release",
509
509
  "figure.title.figures": "figure catalog",
510
+ "figure.title.public-figures": "public figures",
510
511
  "figure.title.new-figure": "new figure",
511
512
  "figure.title.save-new-figure": "save figure draft",
512
513
  "figure.text.no-parts-yet": "No parts yet. Pick a shape above to place one.",
@@ -1207,7 +1208,6 @@
1207
1208
  "figure.label.public": "public",
1208
1209
  "figure.button.make-public": "make public",
1209
1210
  "figure.button.make-private": "make private",
1210
- "figure.button.public-figures": "public figures of other domains",
1211
1211
  "figure.text.category-choose": "choose a category",
1212
1212
  "figure.text.property-section-failed": "the section {section} could not be drawn: {reason}"
1213
1213
  }
@@ -507,6 +507,7 @@
507
507
  "figure.text.what-a-figure-is": "una Figure es un componente 3D que usted crea. compóngala a partir de formas sencillas y se convierte en un componente que puede colocar en un plano, compartiendo forma y material entre todas las instancias.",
508
508
  "figure.text.what-changed-in-this-release": "qué cambió en esta publicación",
509
509
  "figure.title.figures": "catálogo de figuras",
510
+ "figure.title.public-figures": "figuras públicas",
510
511
  "figure.title.new-figure": "nueva figura",
511
512
  "figure.title.save-new-figure": "guardar borrador de figura",
512
513
  "figure.text.no-parts-yet": "Aún no hay piezas. Elija una forma arriba para colocar una.",
@@ -1207,7 +1208,6 @@
1207
1208
  "figure.label.public": "pública",
1208
1209
  "figure.button.make-public": "hacer pública",
1209
1210
  "figure.button.make-private": "dejar de publicar",
1210
- "figure.button.public-figures": "figuras públicas de otros dominios",
1211
1211
  "figure.text.category-choose": "elegir categoría",
1212
1212
  "figure.text.property-section-failed": "no se pudo dibujar la sección {section}: {reason}"
1213
1213
  }
@@ -507,6 +507,7 @@
507
507
  "figure.text.what-a-figure-is": "a Figure is a 3D component you author. Compose it from simple shapes and it becomes a component you can place on a drawing, sharing shape and material across every instance.",
508
508
  "figure.text.what-changed-in-this-release": "このバージョンで変わったこと",
509
509
  "figure.title.figures": "Figure カタログ",
510
+ "figure.title.public-figures": "公開 Figure",
510
511
  "figure.title.new-figure": "new figure",
511
512
  "figure.title.save-new-figure": "Figure の下書きを保存",
512
513
  "figure.text.no-parts-yet": "No parts yet. Pick a shape above to place one.",
@@ -1207,7 +1208,6 @@
1207
1208
  "figure.label.public": "公開",
1208
1209
  "figure.button.make-public": "公開する",
1209
1210
  "figure.button.make-private": "公開をやめる",
1210
- "figure.button.public-figures": "他ドメインの公開 Figure",
1211
1211
  "figure.text.category-choose": "分類を選ぶ",
1212
1212
  "figure.text.property-section-failed": "{section} の区画を描けませんでした: {reason}"
1213
1213
  }
@@ -507,6 +507,7 @@
507
507
  "figure.text.what-a-figure-is": "Figure 는 직접 저작한 3D 컴포넌트입니다. 단순한 도형을 조합해 만들면 도면에 배치할 수 있는 컴포넌트가 되고, 여러 개를 배치해도 형상과 재질을 공유합니다.",
508
508
  "figure.text.what-changed-in-this-release": "이번 버전에서 바뀐 것",
509
509
  "figure.title.figures": "Figure 카탈로그",
510
+ "figure.title.public-figures": "공개 Figure",
510
511
  "figure.title.new-figure": "새 Figure",
511
512
  "figure.title.save-new-figure": "Figure 초안 저장",
512
513
  "figure.text.no-parts-yet": "아직 부품이 없습니다. 위에서 도형을 선택하여 놓으세요.",
@@ -1207,7 +1208,6 @@
1207
1208
  "figure.label.public": "공개",
1208
1209
  "figure.button.make-public": "공개하기",
1209
1210
  "figure.button.make-private": "공개 끄기",
1210
- "figure.button.public-figures": "다른 도메인의 공개 Figure",
1211
1211
  "figure.text.category-choose": "분류 고르기",
1212
1212
  "figure.text.property-section-failed": "{section} 구역을 그리지 못했습니다: {reason}"
1213
1213
  }
@@ -507,6 +507,7 @@
507
507
  "figure.text.what-a-figure-is": "a Figure is a 3D component you author. Compose it from simple shapes and it becomes a component you can place on a drawing, sharing shape and material across every instance.",
508
508
  "figure.text.what-changed-in-this-release": "apa yang berubah dalam terbitan ini",
509
509
  "figure.title.figures": "katalog figure",
510
+ "figure.title.public-figures": "figure awam",
510
511
  "figure.title.new-figure": "new figure",
511
512
  "figure.title.save-new-figure": "simpan draf figure",
512
513
  "figure.text.no-parts-yet": "No parts yet. Pick a shape above to place one.",
@@ -1207,7 +1208,6 @@
1207
1208
  "figure.label.public": "awam",
1208
1209
  "figure.button.make-public": "jadikan awam",
1209
1210
  "figure.button.make-private": "jadikan peribadi",
1210
- "figure.button.public-figures": "figure awam domain lain",
1211
1211
  "figure.text.category-choose": "pilih kategori",
1212
1212
  "figure.text.property-section-failed": "bahagian {section} tidak dapat dilukis: {reason}"
1213
1213
  }
@@ -507,6 +507,7 @@
507
507
  "figure.text.what-a-figure-is": "a Figure is a 3D component you author. Compose it from simple shapes and it becomes a component you can place on a drawing, sharing shape and material across every instance.",
508
508
  "figure.text.what-changed-in-this-release": "此版本的变更",
509
509
  "figure.title.figures": "Figure 目录",
510
+ "figure.title.public-figures": "公开 Figure",
510
511
  "figure.title.new-figure": "new figure",
511
512
  "figure.title.save-new-figure": "保存 Figure 草稿",
512
513
  "figure.text.no-parts-yet": "No parts yet. Pick a shape above to place one.",
@@ -1207,7 +1208,6 @@
1207
1208
  "figure.label.public": "公开",
1208
1209
  "figure.button.make-public": "公开",
1209
1210
  "figure.button.make-private": "取消公开",
1210
- "figure.button.public-figures": "其他域的公开图形",
1211
1211
  "figure.text.category-choose": "选择分类",
1212
1212
  "figure.text.property-section-failed": "无法绘制 {section} 区块:{reason}"
1213
1213
  }