@things-factory/figure-ui 10.1.76 → 10.1.78
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/editor.ts +42 -23
- package/dist-client/modeller/editor.d.ts +9 -0
- package/dist-client/modeller/editor.js +50 -24
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/test/browser/modeller.check.mjs +18 -12
- package/test/links.test.ts +1 -1
- package/test/parts-wiring.test.ts +13 -0
- package/test/refusals.test.ts +6 -3
- package/test/theme.test.ts +2 -4
- package/translations/en.json +2 -2
- package/translations/ja.json +2 -2
- package/translations/ko.json +2 -2
- package/translations/ms.json +2 -2
- package/translations/zh.json +2 -2
- package/dist-client/graphql/v3-store.d.ts +0 -3
- package/dist-client/graphql/v3-store.js +0 -39
- package/dist-client/graphql/v3-store.js.map +0 -1
- package/dist-client/modeller/figure-v3-capability.d.ts +0 -22
- package/dist-client/modeller/figure-v3-capability.js +0 -141
- package/dist-client/modeller/figure-v3-capability.js.map +0 -1
- package/dist-client/modeller/figure-v3-clips.d.ts +0 -31
- package/dist-client/modeller/figure-v3-clips.js +0 -268
- package/dist-client/modeller/figure-v3-clips.js.map +0 -1
- package/dist-client/modeller/figure-v3-controls.d.ts +0 -36
- package/dist-client/modeller/figure-v3-controls.js +0 -226
- package/dist-client/modeller/figure-v3-controls.js.map +0 -1
- package/dist-client/modeller/figure-v3-first-save.d.ts +0 -20
- package/dist-client/modeller/figure-v3-first-save.js +0 -118
- package/dist-client/modeller/figure-v3-first-save.js.map +0 -1
- package/dist-client/modeller/figure-v3-links.d.ts +0 -77
- package/dist-client/modeller/figure-v3-links.js +0 -649
- package/dist-client/modeller/figure-v3-links.js.map +0 -1
- package/dist-client/modeller/figure-v3-material.d.ts +0 -39
- package/dist-client/modeller/figure-v3-material.js +0 -323
- package/dist-client/modeller/figure-v3-material.js.map +0 -1
- package/dist-client/modeller/figure-v3-parts.d.ts +0 -69
- package/dist-client/modeller/figure-v3-parts.js +0 -559
- package/dist-client/modeller/figure-v3-parts.js.map +0 -1
- package/dist-client/modeller/figure-v3-preview.d.ts +0 -34
- package/dist-client/modeller/figure-v3-preview.js +0 -346
- package/dist-client/modeller/figure-v3-preview.js.map +0 -1
- package/dist-client/modeller/figure-v3-properties.d.ts +0 -45
- package/dist-client/modeller/figure-v3-properties.js +0 -239
- package/dist-client/modeller/figure-v3-properties.js.map +0 -1
- package/dist-client/modeller/figure-v3-recipe-catalog.d.ts +0 -38
- package/dist-client/modeller/figure-v3-recipe-catalog.js +0 -399
- package/dist-client/modeller/figure-v3-recipe-catalog.js.map +0 -1
- package/dist-client/modeller/figure-v3-verdict.d.ts +0 -64
- package/dist-client/modeller/figure-v3-verdict.js +0 -787
- package/dist-client/modeller/figure-v3-verdict.js.map +0 -1
- package/dist-client/modeller/v3-ai-proposal.d.ts +0 -51
- package/dist-client/modeller/v3-ai-proposal.js +0 -64
- package/dist-client/modeller/v3-ai-proposal.js.map +0 -1
- package/dist-client/modeller/v3-align.d.ts +0 -30
- package/dist-client/modeller/v3-align.js +0 -75
- package/dist-client/modeller/v3-align.js.map +0 -1
- package/dist-client/modeller/v3-canvas.d.ts +0 -72
- package/dist-client/modeller/v3-canvas.js +0 -379
- package/dist-client/modeller/v3-canvas.js.map +0 -1
- package/dist-client/modeller/v3-clips.d.ts +0 -39
- package/dist-client/modeller/v3-clips.js +0 -58
- package/dist-client/modeller/v3-clips.js.map +0 -1
- package/dist-client/modeller/v3-controls.d.ts +0 -28
- package/dist-client/modeller/v3-controls.js +0 -28
- package/dist-client/modeller/v3-controls.js.map +0 -1
- package/dist-client/modeller/v3-editor.d.ts +0 -203
- package/dist-client/modeller/v3-editor.js +0 -1526
- package/dist-client/modeller/v3-editor.js.map +0 -1
- package/dist-client/modeller/v3-fields.d.ts +0 -45
- package/dist-client/modeller/v3-fields.js +0 -83
- package/dist-client/modeller/v3-fields.js.map +0 -1
- package/dist-client/modeller/v3-figure-facts.d.ts +0 -35
- package/dist-client/modeller/v3-figure-facts.js +0 -55
- package/dist-client/modeller/v3-figure-facts.js.map +0 -1
- package/dist-client/modeller/v3-first-save.d.ts +0 -17
- package/dist-client/modeller/v3-first-save.js +0 -26
- package/dist-client/modeller/v3-first-save.js.map +0 -1
- package/dist-client/modeller/v3-gizmo.d.ts +0 -72
- package/dist-client/modeller/v3-gizmo.js +0 -111
- package/dist-client/modeller/v3-gizmo.js.map +0 -1
- package/dist-client/modeller/v3-help.d.ts +0 -18
- package/dist-client/modeller/v3-help.js +0 -37
- package/dist-client/modeller/v3-help.js.map +0 -1
- package/dist-client/modeller/v3-joint-drag.d.ts +0 -19
- package/dist-client/modeller/v3-joint-drag.js +0 -97
- package/dist-client/modeller/v3-joint-drag.js.map +0 -1
- package/dist-client/modeller/v3-joint-fan.d.ts +0 -9
- package/dist-client/modeller/v3-joint-fan.js +0 -276
- package/dist-client/modeller/v3-joint-fan.js.map +0 -1
- package/dist-client/modeller/v3-keys.d.ts +0 -22
- package/dist-client/modeller/v3-keys.js +0 -26
- package/dist-client/modeller/v3-keys.js.map +0 -1
- package/dist-client/modeller/v3-links.d.ts +0 -267
- package/dist-client/modeller/v3-links.js +0 -480
- package/dist-client/modeller/v3-links.js.map +0 -1
- package/dist-client/modeller/v3-live.d.ts +0 -37
- package/dist-client/modeller/v3-live.js +0 -68
- package/dist-client/modeller/v3-live.js.map +0 -1
- package/dist-client/modeller/v3-maturity.d.ts +0 -120
- package/dist-client/modeller/v3-maturity.js +0 -313
- package/dist-client/modeller/v3-maturity.js.map +0 -1
- package/dist-client/modeller/v3-occupancy.d.ts +0 -18
- package/dist-client/modeller/v3-occupancy.js +0 -24
- package/dist-client/modeller/v3-occupancy.js.map +0 -1
- package/dist-client/modeller/v3-palette.d.ts +0 -7
- package/dist-client/modeller/v3-palette.js +0 -46
- package/dist-client/modeller/v3-palette.js.map +0 -1
- package/dist-client/modeller/v3-preview-model.d.ts +0 -47
- package/dist-client/modeller/v3-preview-model.js +0 -68
- package/dist-client/modeller/v3-preview-model.js.map +0 -1
- package/dist-client/modeller/v3-product-session.d.ts +0 -510
- package/dist-client/modeller/v3-product-session.js +0 -157
- package/dist-client/modeller/v3-product-session.js.map +0 -1
- package/dist-client/modeller/v3-recipe-source.d.ts +0 -8
- package/dist-client/modeller/v3-recipe-source.js +0 -14
- package/dist-client/modeller/v3-recipe-source.js.map +0 -1
- package/dist-client/modeller/v3-recipes.d.ts +0 -37
- package/dist-client/modeller/v3-recipes.js +0 -103
- package/dist-client/modeller/v3-recipes.js.map +0 -1
- package/dist-client/modeller/v3-refusals.d.ts +0 -68
- package/dist-client/modeller/v3-refusals.js +0 -142
- package/dist-client/modeller/v3-refusals.js.map +0 -1
- package/dist-client/modeller/v3-renderer.d.ts +0 -40
- package/dist-client/modeller/v3-renderer.js +0 -73
- package/dist-client/modeller/v3-renderer.js.map +0 -1
- package/dist-client/modeller/v3-stage-model.d.ts +0 -39
- package/dist-client/modeller/v3-stage-model.js +0 -147
- package/dist-client/modeller/v3-stage-model.js.map +0 -1
- package/dist-client/modeller/v3-thumbnail.d.ts +0 -3
- package/dist-client/modeller/v3-thumbnail.js +0 -75
- package/dist-client/modeller/v3-thumbnail.js.map +0 -1
- package/dist-client/pages/figure-v3-modeller-page.d.ts +0 -102
- package/dist-client/pages/figure-v3-modeller-page.js +0 -548
- package/dist-client/pages/figure-v3-modeller-page.js.map +0 -1
- package/dist-client/tsconfig.chk.tsbuildinfo +0 -1
- package/dist-client/tsconfig.fui.tsbuildinfo +0 -1
- package/dist-client/tsconfig.scratch-fm.tsbuildinfo +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/figure-ui",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.78",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"@things-factory:registry": "https://registry.npmjs.org"
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"@things-factory/figure-service": "^10.1.76",
|
|
45
45
|
"three": "^0.185.1"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "88661a25f49880139a5e05554861acdd691e44e5"
|
|
48
48
|
}
|
|
@@ -432,6 +432,11 @@ describe('a figure made in the modeller is given its size from its parts (user 2
|
|
|
432
432
|
assert.ok(await width.evaluate(s => !!s), 'the width can follow the figure size')
|
|
433
433
|
await width.select('instance:x')
|
|
434
434
|
await sleep(600)
|
|
435
|
+
/* Refusals and notices go to the app's notification: heard here as the event it is. */
|
|
436
|
+
await page().evaluate(() => {
|
|
437
|
+
window.__told = []
|
|
438
|
+
document.addEventListener('notify', e => window.__told.push(e.detail))
|
|
439
|
+
})
|
|
435
440
|
const plus = await handle('input')
|
|
436
441
|
assert.ok(await plus.evaluate(i => !!i), 'a following width offers its difference')
|
|
437
442
|
await plus.evaluate(i => i.scrollIntoView({ block: 'center' }))
|
|
@@ -441,15 +446,15 @@ describe('a figure made in the modeller is given its size from its parts (user 2
|
|
|
441
446
|
await sleep(600)
|
|
442
447
|
/* The declared sizes start at 1 mm: less 50 the box would be gone below 50, so the link is refused -- with the way on. */
|
|
443
448
|
assert.match((await state()).error, /figure.text.link-needs-smaller-range/, 'refused, said in words')
|
|
444
|
-
const
|
|
445
|
-
const
|
|
446
|
-
return
|
|
449
|
+
const told = await read(() => {
|
|
450
|
+
const last = window.__told.at(-1)
|
|
451
|
+
return last && { level: last.level, message: last.message, label: last.option?.action?.label }
|
|
447
452
|
})
|
|
448
|
-
assert.
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
+
assert.equal(told?.level, 'error', 'said in the app\'s notification')
|
|
454
|
+
assert.match(told?.message ?? '', /figure.text.link-needs-smaller-range/)
|
|
455
|
+
assert.match(told?.label ?? '', /figure.button.narrow-range-from/, 'the same link is offered with the sizes narrowed')
|
|
456
|
+
await read(() => window.__told.at(-1).option.action.callback())
|
|
457
|
+
await sleep(600)
|
|
453
458
|
assert.equal((await state()).error, '', 'taken')
|
|
454
459
|
assert.equal((await body('box')).dimensions.width, 350, 'the figure\'s 400 less 50')
|
|
455
460
|
})
|
|
@@ -658,16 +663,17 @@ describe('a part follows the figure size in one step (follow-size, 2026-09-26)',
|
|
|
658
663
|
return { x: r.left + r.width / 2, y: r.top + r.height / 2 }
|
|
659
664
|
})
|
|
660
665
|
assert.ok(at, 'the button is offered for a box that follows nothing')
|
|
666
|
+
await page().evaluate(() => {
|
|
667
|
+
window.__told = []
|
|
668
|
+
document.addEventListener('notify', e => window.__told.push(e.detail))
|
|
669
|
+
})
|
|
661
670
|
const start = await state()
|
|
662
671
|
await click(at)
|
|
663
672
|
const after = await state()
|
|
664
673
|
assert.equal(after.error, '', 'not refused')
|
|
665
674
|
assert.equal(after.revision, start.revision + 1, 'one step')
|
|
666
675
|
assert.deepEqual(await read(() => probe.fields('size.')), { 'size.x': 400, 'size.y': 400, 'size.z': 400 }, 'the size is the box as it stands')
|
|
667
|
-
const notice = await
|
|
668
|
-
const deep = (root = document) => [...root.querySelectorAll('.notice')].concat(...[...root.querySelectorAll('*')].filter(e => e.shadowRoot).map(e => deep(e.shadowRoot)))
|
|
669
|
-
return deep()[0]?.textContent?.trim() ?? null
|
|
670
|
-
})
|
|
676
|
+
const notice = await read(() => (window.__told ?? []).filter(n => n.level === 'info').at(-1)?.message ?? null)
|
|
671
677
|
assert.ok(notice?.includes('figure.text.size-declared-to-follow'), `a line says so: ${notice}`)
|
|
672
678
|
const grown = await read(() => {
|
|
673
679
|
const editor = document.querySelector('figure-editor')
|
package/test/links.test.ts
CHANGED
|
@@ -614,7 +614,7 @@ test('치수 칸 — 「도형 크기를 따라감」 단추는 follow-size 한
|
|
|
614
614
|
assert.ok(dims.includes("followOf(asset, this.partId, axis).of === 'instance'"), '다 따르면 단추가 없다')
|
|
615
615
|
const editor = read('../client/modeller/editor.ts')
|
|
616
616
|
assert.ok(editor.includes("if (action.kind === 'follow-size' && !hadSize)"), '크기를 대신 정했을 때만')
|
|
617
|
-
assert.ok(editor.includes('
|
|
617
|
+
assert.ok(editor.includes("notify({ level: 'info', message: this.notice })"), '그 한 줄은 앱의 알림으로')
|
|
618
618
|
const ko = JSON.parse(read('../translations/ko.json'))
|
|
619
619
|
assert.match(ko['figure.text.size-declared-to-follow'], /\{x\} × \{y\} × \{z\} mm/)
|
|
620
620
|
})
|
|
@@ -72,3 +72,16 @@ test('부품 이름은 figure-model 의 rename-part 로 바꾸고, 거절은 까
|
|
|
72
72
|
for (const key of ['figure.text.part-name-taken', 'figure.text.part-name-invalid']) assert.ok(table[key]?.includes('{name}'), `${lang}: ${key}`)
|
|
73
73
|
}
|
|
74
74
|
})
|
|
75
|
+
|
|
76
|
+
test('거절은 앱의 알림(notify)이나 확인 창(OxPrompt)으로 — 모델러가 따로 그리는 띠는 없다 (2026-09-27)', () => {
|
|
77
|
+
assert.doesNotMatch(editor, /role="alert" class="error"/, '따로 그리던 빨간 띠가 없다')
|
|
78
|
+
assert.doesNotMatch(editor, /class="notice"/, '따로 그리던 알림 줄이 없다')
|
|
79
|
+
const tell = editor.slice(editor.indexOf(' private tell('), editor.indexOf(' protected willUpdate('))
|
|
80
|
+
assert.match(tell, /else notify\(\{ level: 'error', message: this\.error \}\)/, '길이 없는 거절은 error 알림 — 닫을 때까지 남는다')
|
|
81
|
+
assert.match(tell, /if \(retry\) this\.ask\(this\.error, retry\)/, '이어 할 길이 있으면 묻는다')
|
|
82
|
+
const ask = editor.slice(editor.indexOf(' private async ask('), editor.indexOf(' protected willUpdate('))
|
|
83
|
+
assert.match(ask, /OxPrompt\.open\(\{[\s\S]*confirmButton: \{ text: retry\.label \}/, '앱의 확인 창에서, 그 길의 이름으로')
|
|
84
|
+
assert.match(ask, /if \(!agreed\) return[\s\S]*retry\.run\(\)/, '확인하면 바로 진행한다')
|
|
85
|
+
assert.match(tell, /notify\(\{ level: 'info', message: this\.notice \}\)/, '지우며 풀어 준 것은 info 로')
|
|
86
|
+
assert.match(editor, /updated\(changed: PropertyValues<this>\) \{\s*super\.updated\?\.\(changed\)\s*this\.tell\(changed\)/)
|
|
87
|
+
})
|
package/test/refusals.test.ts
CHANGED
|
@@ -98,7 +98,7 @@ test('지우기는 매단 것 · 따라 움직이는 것을 풀어 남기고 그
|
|
|
98
98
|
assert.doesNotMatch(unknown, /something in English/)
|
|
99
99
|
})
|
|
100
100
|
|
|
101
|
-
test('공간 선언에 든 부품 —
|
|
101
|
+
test('공간 선언에 든 부품 — 한 번 눌러 지우고, 공간은 남은 부품에 다시 맞추며 그렇다고 한 줄 말한다(묻지 않는다, 2026-09-27)', async () => {
|
|
102
102
|
const { inDeclaredRoom } = await import('../client/modeller/refusals.ts')
|
|
103
103
|
const fm = await import('@hatiolab/figure-model')
|
|
104
104
|
let a = fm.addFigureBox(fm.createFigureAsset('Gate'), { id: 'housing', size: { x: 300, y: 1000, z: 300 }, position: { x: 0, y: 0, z: 0 } })
|
|
@@ -118,8 +118,11 @@ test('공간 선언에 든 부품 — 지우고 공간을 남은 부품에 맞
|
|
|
118
118
|
assert.equal(after.document.model.nodes.some(n => n.id === 'stray'), false)
|
|
119
119
|
assert.ok(after.occupancy?.bounds, '공간은 남은 부품으로 다시 선언된다')
|
|
120
120
|
const editor = readFileSync(fileURLToPath(new URL('../client/modeller/editor.ts', import.meta.url)), 'utf8')
|
|
121
|
-
|
|
122
|
-
assert.
|
|
121
|
+
const remove = editor.slice(editor.indexOf(' private removePart('), editor.indexOf(' private toggleHiddenPart('))
|
|
122
|
+
assert.match(remove, /if \(!refitRoom && inDeclaredRoom\(error\)\) \{\s*this\.removePart\(id, true\)/, '거절 없이 곧바로 다시 맞춰 지운다')
|
|
123
|
+
assert.match(remove, /figure\.text\.removal-space-refitted/, '그렇다고 한 줄')
|
|
124
|
+
assert.doesNotMatch(remove, /this\.retry = \{/, '묻거나 권하지 않는다')
|
|
125
|
+
assert.ok(ko['figure.text.removal-space-refitted'])
|
|
123
126
|
})
|
|
124
127
|
|
|
125
128
|
test('배치를 바꿀 수 없는 까닭 — 평면에 붙은 부품과 새 평면이 받는 면을 말한다(벽 배치, 09-25)', async () => {
|
package/test/theme.test.ts
CHANGED
|
@@ -30,14 +30,12 @@ test('캔버스 바탕은 작업대 회색 — 판의 하늘색이라 환경 탭
|
|
|
30
30
|
assert.match(read('../client/modeller/figure-view.ts'), /skyColor: WORKBENCH/)
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
-
test('눌린
|
|
33
|
+
test('눌린 단추는 셸이 두 테마 대비를 맞춘 칸을 쓴다 — 오류는 앱의 알림이 그린다 (2026-09-27)', () => {
|
|
34
34
|
const pressed = editor.slice(editor.indexOf("button[aria-pressed='true']"), editor.indexOf('}', editor.indexOf("button[aria-pressed='true']")))
|
|
35
35
|
assert.match(pressed, /--md-sys-color-secondary-container\)/)
|
|
36
36
|
assert.match(pressed, /--md-sys-color-on-secondary-container\)/)
|
|
37
37
|
assert.match(pressed, /border-color: var\(--md-sys-color-primary\)/)
|
|
38
|
-
|
|
39
|
-
assert.match(error, /--md-sys-color-error-container\)/)
|
|
40
|
-
assert.match(error, /--md-sys-color-on-error-container\)/)
|
|
38
|
+
assert.equal(editor.includes('.error {'), false, '모델러가 따로 칠하는 오류 칸이 없다')
|
|
41
39
|
})
|
|
42
40
|
|
|
43
41
|
test('편집기는 창이 아니라 자기 폭으로 접는다 — 레일이 폭을 먼저 가져간다', () => {
|
package/translations/en.json
CHANGED
|
@@ -640,7 +640,6 @@
|
|
|
640
640
|
"figure.text.proportion-to-follow": "{count} lengths still have their own number. made to follow, they grow by the figure's ratio.",
|
|
641
641
|
"figure.button.follow-size-in-proportion": "make every part follow",
|
|
642
642
|
"figure.text.proportion-kept": "keeps its own number: {what}",
|
|
643
|
-
"figure.button.remove-and-refit-room": "delete {part} and fit the space to the parts left",
|
|
644
643
|
"figure.text.preview-clamped": "{axis} {asked} → {used}",
|
|
645
644
|
"figure.label.placement-wall": "wall (wall)",
|
|
646
645
|
"figure.text.placement-plane-refused": "{parts} cannot go on a {placement} by the face fastened to the mounting plane. detach it or fasten it by its {faces} first.",
|
|
@@ -663,5 +662,6 @@
|
|
|
663
662
|
"figure.text.removal-mounting-face": "The mounting face is released.",
|
|
664
663
|
"figure.text.edit-refused": "This edit cannot be made. ({code})",
|
|
665
664
|
"figure.text.edit-refused-node-limit": "The figure is too large to add more. It holds up to {max} nodes.",
|
|
666
|
-
"figure.text.recipe-step-refused": "Stopped at step {step} of the recipe. {why} ({code})"
|
|
665
|
+
"figure.text.recipe-step-refused": "Stopped at step {step} of the recipe. {why} ({code})",
|
|
666
|
+
"figure.text.removal-space-refitted": "The space is fitted to the parts left."
|
|
667
667
|
}
|
package/translations/ja.json
CHANGED
|
@@ -640,7 +640,6 @@
|
|
|
640
640
|
"figure.text.proportion-to-follow": "長さ {count} 個がまだ固有の数値です。追従させると図形と同じ比率で大きくなります。",
|
|
641
641
|
"figure.button.follow-size-in-proportion": "すべての部品を追従させる",
|
|
642
642
|
"figure.text.proportion-kept": "固有の数値のまま: {what}",
|
|
643
|
-
"figure.button.remove-and-refit-room": "「{part}」を削除し、空間を残りの部品に合わせる",
|
|
644
643
|
"figure.text.preview-clamped": "{axis} {asked} → {used}",
|
|
645
644
|
"figure.label.placement-wall": "壁基準 (wall)",
|
|
646
645
|
"figure.text.placement-plane-refused": "{parts} は取付平面に付いている面では {placement} に付けられません。外すか {faces} 面で付け直してから変更してください。",
|
|
@@ -663,5 +662,6 @@
|
|
|
663
662
|
"figure.text.removal-mounting-face": "取付面が外れました。",
|
|
664
663
|
"figure.text.edit-refused": "この編集はできません。({code})",
|
|
665
664
|
"figure.text.edit-refused-node-limit": "図形が大きいためこれ以上追加できません。ノードは {max} 個までです。",
|
|
666
|
-
"figure.text.recipe-step-refused": "レシピの {step} 番目の手順で止まりました。{why} ({code})"
|
|
665
|
+
"figure.text.recipe-step-refused": "レシピの {step} 番目の手順で止まりました。{why} ({code})",
|
|
666
|
+
"figure.text.removal-space-refitted": "空間を残りの部品に合わせ直しました。"
|
|
667
667
|
}
|
package/translations/ko.json
CHANGED
|
@@ -640,7 +640,6 @@
|
|
|
640
640
|
"figure.text.proportion-to-follow": "길이 {count}개가 아직 자기 숫자입니다. 따라가게 하면 도형과 같은 비율로 커집니다.",
|
|
641
641
|
"figure.button.follow-size-in-proportion": "모든 부품이 따라가게",
|
|
642
642
|
"figure.text.proportion-kept": "자기 숫자로 남는 것: {what}",
|
|
643
|
-
"figure.button.remove-and-refit-room": "'{part}' 지우고 공간을 남은 부품에 맞추기",
|
|
644
643
|
"figure.text.preview-clamped": "{axis} {asked} → {used}",
|
|
645
644
|
"figure.label.placement-wall": "벽 기반 (wall)",
|
|
646
645
|
"figure.text.placement-plane-refused": "{parts} 가 장착 평면에 붙은 면으로는 {placement} 에 붙일 수 없습니다. 떼거나 {faces} 면으로 다시 붙인 뒤 바꾸세요.",
|
|
@@ -663,5 +662,6 @@
|
|
|
663
662
|
"figure.text.removal-mounting-face": "장착면이 풀렸습니다.",
|
|
664
663
|
"figure.text.edit-refused": "이 편집은 할 수 없습니다. ({code})",
|
|
665
664
|
"figure.text.edit-refused-node-limit": "도형이 커서 더 넣을 수 없습니다. 노드는 {max} 개까지입니다.",
|
|
666
|
-
"figure.text.recipe-step-refused": "레시피의 {step} 번째 단계에서 막혔습니다. {why} ({code})"
|
|
665
|
+
"figure.text.recipe-step-refused": "레시피의 {step} 번째 단계에서 막혔습니다. {why} ({code})",
|
|
666
|
+
"figure.text.removal-space-refitted": "공간을 남은 부품에 다시 맞췄습니다."
|
|
667
667
|
}
|
package/translations/ms.json
CHANGED
|
@@ -640,7 +640,6 @@
|
|
|
640
640
|
"figure.text.proportion-to-follow": "{count} panjang masih mempunyai nombor sendiri. apabila dijadikan mengikut, ia membesar mengikut nisbah rajah.",
|
|
641
641
|
"figure.button.follow-size-in-proportion": "jadikan semua bahagian mengikut",
|
|
642
642
|
"figure.text.proportion-kept": "kekal dengan nombor sendiri: {what}",
|
|
643
|
-
"figure.button.remove-and-refit-room": "padam '{part}' dan muatkan ruang pada bahagian yang tinggal",
|
|
644
643
|
"figure.text.preview-clamped": "{axis} {asked} → {used}",
|
|
645
644
|
"figure.label.placement-wall": "dinding (wall)",
|
|
646
645
|
"figure.text.placement-plane-refused": "{parts} tidak boleh dipasang pada {placement} dengan muka yang dipasang pada satah pemasangan. tanggalkan atau pasang semula dengan muka {faces} dahulu.",
|
|
@@ -663,5 +662,6 @@
|
|
|
663
662
|
"figure.text.removal-mounting-face": "Muka pemasangan dilepaskan.",
|
|
664
663
|
"figure.text.edit-refused": "Suntingan ini tidak boleh dibuat. ({code})",
|
|
665
664
|
"figure.text.edit-refused-node-limit": "Rajah terlalu besar untuk ditambah. Ia memuatkan sehingga {max} nod.",
|
|
666
|
-
"figure.text.recipe-step-refused": "Terhenti pada langkah {step} resipi. {why} ({code})"
|
|
665
|
+
"figure.text.recipe-step-refused": "Terhenti pada langkah {step} resipi. {why} ({code})",
|
|
666
|
+
"figure.text.removal-space-refitted": "Ruang dipadankan semula dengan bahagian yang tinggal."
|
|
667
667
|
}
|
package/translations/zh.json
CHANGED
|
@@ -640,7 +640,6 @@
|
|
|
640
640
|
"figure.text.proportion-to-follow": "还有 {count} 个长度是自身数值。设为跟随后,将按图形的同一比例变大。",
|
|
641
641
|
"figure.button.follow-size-in-proportion": "让所有部件跟随",
|
|
642
642
|
"figure.text.proportion-kept": "保留自身数值: {what}",
|
|
643
|
-
"figure.button.remove-and-refit-room": "删除 '{part}' 并使空间适配剩余部件",
|
|
644
643
|
"figure.text.preview-clamped": "{axis} {asked} → {used}",
|
|
645
644
|
"figure.label.placement-wall": "墙面基准 (wall)",
|
|
646
645
|
"figure.text.placement-plane-refused": "{parts} 贴在安装平面上的面不能用于 {placement}。请先拆下或改用 {faces} 面贴合后再更改。",
|
|
@@ -663,5 +662,6 @@
|
|
|
663
662
|
"figure.text.removal-mounting-face": "安装面已解除。",
|
|
664
663
|
"figure.text.edit-refused": "无法进行此编辑。({code})",
|
|
665
664
|
"figure.text.edit-refused-node-limit": "图形过大,无法再添加。节点上限为 {max} 个。",
|
|
666
|
-
"figure.text.recipe-step-refused": "配方在第 {step} 步停止。{why} ({code})"
|
|
665
|
+
"figure.text.recipe-step-refused": "配方在第 {step} 步停止。{why} ({code})",
|
|
666
|
+
"figure.text.removal-space-refitted": "空间已重新贴合剩余部件。"
|
|
667
667
|
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import gql from 'graphql-tag';
|
|
2
|
-
import { client } from '@operato/graphql';
|
|
3
|
-
import { fetchFigure } from './index.js';
|
|
4
|
-
/** V3 source is sent intact. No conversion into the old parts/base authoring representation. */
|
|
5
|
-
export const v3ProductStore = {
|
|
6
|
-
async load(id) {
|
|
7
|
-
const record = await fetchFigure(id);
|
|
8
|
-
if (!record?.source)
|
|
9
|
-
throw Error('Figure 정본이 없습니다.');
|
|
10
|
-
return { id: record.id, source: record.source };
|
|
11
|
-
},
|
|
12
|
-
async save(request) {
|
|
13
|
-
const response = await client.mutate({
|
|
14
|
-
mutation: gql `
|
|
15
|
-
mutation SaveFigureV3($source: String!, $id: String, $expectedSource: String, $creationId: String, $thumbnail: String, $type: String) {
|
|
16
|
-
saveFigureV3(
|
|
17
|
-
source: $source
|
|
18
|
-
id: $id
|
|
19
|
-
expectedSource: $expectedSource
|
|
20
|
-
creationId: $creationId
|
|
21
|
-
thumbnail: $thumbnail
|
|
22
|
-
type: $type
|
|
23
|
-
) {
|
|
24
|
-
id
|
|
25
|
-
source
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
`,
|
|
29
|
-
variables: request
|
|
30
|
-
});
|
|
31
|
-
if (response.errors?.length)
|
|
32
|
-
throw Error(response.errors.map(e => e.message).join('\n'));
|
|
33
|
-
const result = response.data?.saveFigureV3;
|
|
34
|
-
if (!result?.id || !result.source)
|
|
35
|
-
throw Error('서버가 저장 결과를 돌려주지 않았습니다.');
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
//# sourceMappingURL=v3-store.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"v3-store.js","sourceRoot":"","sources":["../../client/graphql/v3-store.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGxC,gGAAgG;AAChG,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,KAAK,CAAC,IAAI,CAAC,EAAE;QACX,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,CAAA;QACpC,IAAI,CAAC,MAAM,EAAE,MAAM;YAAE,MAAM,KAAK,CAAC,kBAAkB,CAAC,CAAA;QACpD,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;IACjD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAO;QAChB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;YACnC,QAAQ,EAAE,GAAG,CAAA;;;;;;;;;;;;;;OAcZ;YACD,SAAS,EAAE,OAAO;SACnB,CAAC,CAAA;QACF,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM;YAAE,MAAM,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;QACxF,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,YAA2C,CAAA;QACzE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,MAAM,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACxE,OAAO,MAAM,CAAA;IACf,CAAC;CACF,CAAA","sourcesContent":["import gql from 'graphql-tag'\nimport { client } from '@operato/graphql'\nimport { fetchFigure } from './index.js'\nimport type { V3ProductStore, V3ProductRecord } from '../modeller/v3-product-session.js'\n\n/** V3 source is sent intact. No conversion into the old parts/base authoring representation. */\nexport const v3ProductStore: V3ProductStore = {\n async load(id) {\n const record = await fetchFigure(id)\n if (!record?.source) throw Error('Figure 정본이 없습니다.')\n return { id: record.id, source: record.source }\n },\n async save(request) {\n const response = await client.mutate({\n mutation: gql`\n mutation SaveFigureV3($source: String!, $id: String, $expectedSource: String, $creationId: String, $thumbnail: String, $type: String) {\n saveFigureV3(\n source: $source\n id: $id\n expectedSource: $expectedSource\n creationId: $creationId\n thumbnail: $thumbnail\n type: $type\n ) {\n id\n source\n }\n }\n `,\n variables: request\n })\n if (response.errors?.length) throw Error(response.errors.map(e => e.message).join('\\n'))\n const result = response.data?.saveFigureV3 as V3ProductRecord | undefined\n if (!result?.id || !result.source) throw Error('서버가 저장 결과를 돌려주지 않았습니다.')\n return result\n }\n}\n"]}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { LitElement, nothing } from 'lit';
|
|
2
|
-
import type { V3Asset } from '@hatiolab/figure-model';
|
|
3
|
-
type Rung = 'none' | 'hold' | 'flow';
|
|
4
|
-
/** Which rung a set of names is, or null when it is none of them -- not invented. */
|
|
5
|
-
export declare function rungOf(names: readonly string[] | undefined): Rung | null;
|
|
6
|
-
declare const FigureV3Capability_base: (new (...args: any[]) => LitElement) & typeof LitElement;
|
|
7
|
-
/**
|
|
8
|
-
* 자리·능력 — what the figure does on a board: the ladder from drawing only, to
|
|
9
|
-
* holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,
|
|
10
|
-
* so the list is the only way to find one; choosing a row selects its part, where the place is edited.
|
|
11
|
-
*/
|
|
12
|
-
export declare class FigureV3Capability extends FigureV3Capability_base {
|
|
13
|
-
static styles: import("lit").CSSResult[];
|
|
14
|
-
asset?: V3Asset;
|
|
15
|
-
/** The selected part, whose places are marked. */
|
|
16
|
-
selected: string;
|
|
17
|
-
locked: boolean;
|
|
18
|
-
render(): import("lit-html").TemplateResult<1> | typeof nothing;
|
|
19
|
-
private setRung;
|
|
20
|
-
private pick;
|
|
21
|
-
}
|
|
22
|
-
export {};
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { __decorate, __metadata } from "tslib";
|
|
2
|
-
import { css, html, LitElement, nothing } from 'lit';
|
|
3
|
-
import { customElement, property } from 'lit/decorators.js';
|
|
4
|
-
import { live } from 'lit/directives/live.js';
|
|
5
|
-
import { i18next, localize } from '@operato/i18n';
|
|
6
|
-
import { v3BindingsOf } from '@hatiolab/figure-model';
|
|
7
|
-
import { SidePanelStyles } from './side-panel-styles.js';
|
|
8
|
-
const RUNGS = Object.freeze({
|
|
9
|
-
none: [],
|
|
10
|
-
hold: ['Capacity', 'Holdable'],
|
|
11
|
-
flow: ['FlowNode']
|
|
12
|
-
});
|
|
13
|
-
/** Which rung a set of names is, or null when it is none of them -- not invented. */
|
|
14
|
-
export function rungOf(names) {
|
|
15
|
-
const has = new Set(names ?? []);
|
|
16
|
-
if (has.size === 0)
|
|
17
|
-
return 'none';
|
|
18
|
-
for (const [rung, wanted] of Object.entries(RUNGS))
|
|
19
|
-
if (wanted.length === has.size && wanted.every(name => has.has(name)))
|
|
20
|
-
return rung;
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* 자리·능력 — what the figure does on a board: the ladder from drawing only, to
|
|
25
|
-
* holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,
|
|
26
|
-
* so the list is the only way to find one; choosing a row selects its part, where the place is edited.
|
|
27
|
-
*/
|
|
28
|
-
let FigureV3Capability = class FigureV3Capability extends localize(i18next)(LitElement) {
|
|
29
|
-
constructor() {
|
|
30
|
-
super(...arguments);
|
|
31
|
-
/** The selected part, whose places are marked. */
|
|
32
|
-
this.selected = '';
|
|
33
|
-
this.locked = false;
|
|
34
|
-
}
|
|
35
|
-
static { this.styles = [SidePanelStyles, css `
|
|
36
|
-
:host {
|
|
37
|
-
display: block;
|
|
38
|
-
}
|
|
39
|
-
label[rung] {
|
|
40
|
-
display: flex;
|
|
41
|
-
gap: 8px;
|
|
42
|
-
align-items: flex-start;
|
|
43
|
-
padding: 8px;
|
|
44
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
45
|
-
border-radius: 8px;
|
|
46
|
-
cursor: pointer;
|
|
47
|
-
}
|
|
48
|
-
label[rung][on] {
|
|
49
|
-
border-color: var(--md-sys-color-primary);
|
|
50
|
-
background: var(--md-sys-color-secondary-container);
|
|
51
|
-
color: var(--md-sys-color-on-secondary-container);
|
|
52
|
-
}
|
|
53
|
-
label[rung] span {
|
|
54
|
-
display: grid;
|
|
55
|
-
gap: 2px;
|
|
56
|
-
}
|
|
57
|
-
label[rung] em,
|
|
58
|
-
p[hint],
|
|
59
|
-
small {
|
|
60
|
-
font-style: normal;
|
|
61
|
-
margin: 0;
|
|
62
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
63
|
-
}
|
|
64
|
-
button[place] {
|
|
65
|
-
display: grid;
|
|
66
|
-
gap: 2px;
|
|
67
|
-
text-align: left;
|
|
68
|
-
padding: 6px 8px;
|
|
69
|
-
font: inherit;
|
|
70
|
-
color: inherit;
|
|
71
|
-
border: 1px solid var(--md-sys-color-outline-variant);
|
|
72
|
-
border-radius: 8px;
|
|
73
|
-
background: none;
|
|
74
|
-
cursor: pointer;
|
|
75
|
-
}
|
|
76
|
-
button[place][on] {
|
|
77
|
-
border-color: var(--md-sys-color-primary);
|
|
78
|
-
}
|
|
79
|
-
code {
|
|
80
|
-
font-size: 0.9em;
|
|
81
|
-
color: var(--md-sys-color-on-surface-variant);
|
|
82
|
-
}
|
|
83
|
-
`]; }
|
|
84
|
-
render() {
|
|
85
|
-
const asset = this.asset;
|
|
86
|
-
if (!asset)
|
|
87
|
-
return nothing;
|
|
88
|
-
const names = asset.document.capabilities.names ?? [];
|
|
89
|
-
const rung = rungOf(names);
|
|
90
|
-
const places = v3BindingsOf(asset);
|
|
91
|
-
return html `<section>
|
|
92
|
-
<h3>${i18next.t('figure.label.what-this-does')}</h3>
|
|
93
|
-
${['none', 'hold', 'flow'].map(which => html `<label rung ?on=${rung === which}>
|
|
94
|
-
<input type="radio" name="rung" .checked=${live(rung === which)} ?disabled=${this.locked} @change=${() => this.setRung(which)} />
|
|
95
|
-
<span>
|
|
96
|
-
<strong>${i18next.t(`figure.label.rung-${which}`)}</strong>
|
|
97
|
-
<em>${i18next.t(`figure.text.rung-${which}-note`)}</em>
|
|
98
|
-
</span>
|
|
99
|
-
</label>`)}
|
|
100
|
-
${rung === null ? html `<p hint>${i18next.t('figure.text.capability-hand-written')}</p>` : nothing}
|
|
101
|
-
${names.length ? html `<code>${names.join(' · ')}</code>` : nothing}
|
|
102
|
-
</section>
|
|
103
|
-
<section>
|
|
104
|
-
<h3>${i18next.t('figure.label.places')}</h3>
|
|
105
|
-
${places.length
|
|
106
|
-
? places.map(one => html `<button place ?on=${one.part === this.selected} @click=${() => one.part && this.pick(one.part)}>
|
|
107
|
-
<strong>${one.label}</strong>
|
|
108
|
-
<small>
|
|
109
|
-
${i18next.t('figure.label.place-' + one.role)} · ${one.part ?? '?'}${one.face ? ' · ' + i18next.t('figure.label.face-' + one.face) : ''} ·
|
|
110
|
-
${one.accepts.join(', ')} · ${i18next.t('figure.label.place-holds', { count: one.capacity })}
|
|
111
|
-
</small>
|
|
112
|
-
</button>`)
|
|
113
|
-
: html `<p hint>${i18next.t('figure.text.no-places')}</p>`}
|
|
114
|
-
${places.length && rung === 'none' ? html `<p hint>${i18next.t('figure.text.place-needs-holding')}</p>` : nothing}
|
|
115
|
-
</section>
|
|
116
|
-
`;
|
|
117
|
-
}
|
|
118
|
-
setRung(which) {
|
|
119
|
-
this.dispatchEvent(new CustomEvent('v3-part-edit', { detail: { edit: { kind: 'set-capabilities', names: [...RUNGS[which]] } }, bubbles: true, composed: true }));
|
|
120
|
-
}
|
|
121
|
-
pick(part) {
|
|
122
|
-
this.dispatchEvent(new CustomEvent('select-part', { detail: { id: part }, bubbles: true, composed: true }));
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
__decorate([
|
|
126
|
-
property({ attribute: false }),
|
|
127
|
-
__metadata("design:type", Object)
|
|
128
|
-
], FigureV3Capability.prototype, "asset", void 0);
|
|
129
|
-
__decorate([
|
|
130
|
-
property(),
|
|
131
|
-
__metadata("design:type", Object)
|
|
132
|
-
], FigureV3Capability.prototype, "selected", void 0);
|
|
133
|
-
__decorate([
|
|
134
|
-
property({ type: Boolean }),
|
|
135
|
-
__metadata("design:type", Object)
|
|
136
|
-
], FigureV3Capability.prototype, "locked", void 0);
|
|
137
|
-
FigureV3Capability = __decorate([
|
|
138
|
-
customElement('figure-v3-capability')
|
|
139
|
-
], FigureV3Capability);
|
|
140
|
-
export { FigureV3Capability };
|
|
141
|
-
//# sourceMappingURL=figure-v3-capability.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"figure-v3-capability.js","sourceRoot":"","sources":["../../client/modeller/figure-v3-capability.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { v3BindingsOf } from '@hatiolab/figure-model'\nimport type { FigureCapability, V3Asset } from '@hatiolab/figure-model'\nimport { SidePanelStyles } from './side-panel-styles.js'\n\n/*\n One rung per set of the format's capability names. Typed as the format's names, so a misspelt rung does not pass\n (ADR-0051 ④).\n*/\ntype Rung = 'none' | 'hold' | 'flow'\nconst RUNGS: Readonly<Record<Rung, readonly FigureCapability[]>> = Object.freeze({\n none: [],\n hold: ['Capacity', 'Holdable'],\n flow: ['FlowNode']\n})\n\n/** Which rung a set of names is, or null when it is none of them -- not invented. */\nexport function rungOf(names: readonly string[] | undefined): Rung | null {\n const has = new Set(names ?? [])\n if (has.size === 0) return 'none'\n for (const [rung, wanted] of Object.entries(RUNGS) as [Rung, readonly FigureCapability[]][])\n if (wanted.length === has.size && wanted.every(name => has.has(name))) return rung\n return null\n}\n\n/**\n * 자리·능력 — what the figure does on a board: the ladder from drawing only, to\n * holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,\n * so the list is the only way to find one; choosing a row selects its part, where the place is edited.\n */\n@customElement('figure-v3-capability')\nexport class FigureV3Capability extends localize(i18next)(LitElement) {\n static styles = [SidePanelStyles, css`\n :host {\n display: block;\n }\n label[rung] {\n display: flex;\n gap: 8px;\n align-items: flex-start;\n padding: 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n cursor: pointer;\n }\n label[rung][on] {\n border-color: var(--md-sys-color-primary);\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n label[rung] span {\n display: grid;\n gap: 2px;\n }\n label[rung] em,\n p[hint],\n small {\n font-style: normal;\n margin: 0;\n color: var(--md-sys-color-on-surface-variant);\n }\n button[place] {\n display: grid;\n gap: 2px;\n text-align: left;\n padding: 6px 8px;\n font: inherit;\n color: inherit;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n background: none;\n cursor: pointer;\n }\n button[place][on] {\n border-color: var(--md-sys-color-primary);\n }\n code {\n font-size: 0.9em;\n color: var(--md-sys-color-on-surface-variant);\n }\n `]\n\n @property({ attribute: false }) asset?: V3Asset\n /** The selected part, whose places are marked. */\n @property() selected = ''\n @property({ type: Boolean }) locked = false\n\n render() {\n const asset = this.asset\n if (!asset) return nothing\n const names = asset.document.capabilities.names ?? []\n const rung = rungOf(names)\n const places = v3BindingsOf(asset)\n return html`<section>\n <h3>${i18next.t('figure.label.what-this-does')}</h3>\n ${(['none', 'hold', 'flow'] as const).map(\n which => html`<label rung ?on=${rung === which}>\n <input type=\"radio\" name=\"rung\" .checked=${live(rung === which)} ?disabled=${this.locked} @change=${() => this.setRung(which)} />\n <span>\n <strong>${i18next.t(`figure.label.rung-${which}`)}</strong>\n <em>${i18next.t(`figure.text.rung-${which}-note`)}</em>\n </span>\n </label>`\n )}\n ${rung === null ? html`<p hint>${i18next.t('figure.text.capability-hand-written')}</p>` : nothing}\n ${names.length ? html`<code>${names.join(' · ')}</code>` : nothing}\n </section>\n <section>\n <h3>${i18next.t('figure.label.places')}</h3>\n ${places.length\n ? places.map(\n one => html`<button place ?on=${one.part === this.selected} @click=${() => one.part && this.pick(one.part)}>\n <strong>${one.label}</strong>\n <small>\n ${i18next.t('figure.label.place-' + one.role)} · ${one.part ?? '?'}${one.face ? ' · ' + i18next.t('figure.label.face-' + one.face) : ''} ·\n ${one.accepts.join(', ')} · ${i18next.t('figure.label.place-holds', { count: one.capacity })}\n </small>\n </button>`\n )\n : html`<p hint>${i18next.t('figure.text.no-places')}</p>`}\n ${places.length && rung === 'none' ? html`<p hint>${i18next.t('figure.text.place-needs-holding')}</p>` : nothing}\n </section>\n `\n }\n\n private setRung(which: Rung) {\n this.dispatchEvent(new CustomEvent('v3-part-edit', { detail: { edit: { kind: 'set-capabilities', names: [...RUNGS[which]] } }, bubbles: true, composed: true }))\n }\n\n private pick(part: string) {\n this.dispatchEvent(new CustomEvent('select-part', { detail: { id: part }, bubbles: true, composed: true }))\n }\n}\n"]}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import '@material/web/icon/icon.js';
|
|
2
|
-
import { LitElement, nothing } from 'lit';
|
|
3
|
-
import type { V3Asset } from '@hatiolab/figure-model';
|
|
4
|
-
declare const FigureV3Clips_base: (new (...args: any[]) => LitElement) & typeof LitElement;
|
|
5
|
-
/**
|
|
6
|
-
* 클립 — controls played by keys over time. A clip is one clock; each track plays one
|
|
7
|
-
* control. Scrubbing a clip shows its pose at that moment (one batch of input changes, not saved as the default); a key
|
|
8
|
-
* is added at the scrubbed moment with the control's value there, so a pose is made with the controls' sliders and
|
|
9
|
-
* then kept as a key. Every change is one part edit.
|
|
10
|
-
*/
|
|
11
|
-
export declare class FigureV3Clips extends FigureV3Clips_base {
|
|
12
|
-
private readonly help;
|
|
13
|
-
static styles: import("lit").CSSResult[];
|
|
14
|
-
asset?: V3Asset;
|
|
15
|
-
/** The values the editor holds now, by input id -- what a new key takes. */
|
|
16
|
-
values: Record<string, number>;
|
|
17
|
-
locked: boolean;
|
|
18
|
-
/** Where each clip is scrubbed to, in seconds. */
|
|
19
|
-
private at;
|
|
20
|
-
private adding;
|
|
21
|
-
render(): import("lit-html").TemplateResult<1> | typeof nothing;
|
|
22
|
-
private renderClip;
|
|
23
|
-
private renderTrack;
|
|
24
|
-
private renderAdd;
|
|
25
|
-
/** Show the clip's pose at a moment: one batch of input changes, not saved as the default. */
|
|
26
|
-
/** Show the clip's pose at a moment. While the bar is dragged the pose is live (drawn, not recorded); the release
|
|
27
|
-
* applies it as one batch of input changes. */
|
|
28
|
-
private scrub;
|
|
29
|
-
private edit;
|
|
30
|
-
}
|
|
31
|
-
export {};
|