@things-factory/figure-ui 10.1.147 → 10.1.150
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/bootstrap.ts +10 -2
- package/client/graphql/index.ts +20 -0
- package/client/modeller/canvas.ts +6 -2
- package/client/modeller/carrier-declaration.ts +63 -0
- package/client/modeller/editor.ts +62 -27
- package/client/modeller/figure-carrier.ts +117 -0
- package/client/modeller/figure-cavity-drawing.ts +3 -9
- package/client/modeller/figure-first-save.ts +4 -7
- package/client/modeller/figure-history-panel.ts +2 -3
- package/client/modeller/figure-links.ts +46 -60
- package/client/modeller/figure-material-panel.ts +4 -14
- package/client/modeller/figure-mesh-choice.ts +68 -0
- package/client/modeller/figure-parts.ts +23 -1
- package/client/modeller/figure-preview.ts +2 -2
- package/client/modeller/figure-properties.ts +5 -3
- package/client/modeller/figure-section-editor.ts +12 -33
- package/client/modeller/figure-section-panel.ts +6 -7
- package/client/modeller/figure-slot-layout-panel.ts +208 -0
- package/client/modeller/figure-verdict.ts +21 -31
- package/client/modeller/first-save.ts +23 -0
- package/client/modeller/links.ts +52 -1
- package/client/modeller/material-edit.ts +38 -0
- package/client/modeller/maturity.ts +28 -0
- package/client/modeller/mesh-import.ts +77 -0
- package/client/modeller/modeller-route.ts +9 -0
- package/client/modeller/mounting-part.ts +15 -0
- package/client/modeller/newest-answer.ts +21 -0
- package/client/modeller/preview-model.ts +5 -0
- package/client/modeller/refusals.ts +168 -82
- package/client/modeller/section-controls.ts +25 -1
- package/client/modeller/section-drawing.ts +43 -1
- package/client/modeller/slot-layout-host.ts +140 -0
- package/client/pages/figure-modeller-page.ts +6 -5
- package/client/viewparts/detail-route.ts +7 -0
- package/client/viewparts/figure-detail-dock.ts +1 -3
- package/dist-client/bootstrap.d.ts +1 -1
- package/dist-client/bootstrap.js +9 -2
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/graphql/index.d.ts +5 -0
- package/dist-client/graphql/index.js +19 -0
- package/dist-client/graphql/index.js.map +1 -1
- package/dist-client/modeller/canvas.d.ts +2 -0
- package/dist-client/modeller/canvas.js +10 -2
- package/dist-client/modeller/canvas.js.map +1 -1
- package/dist-client/modeller/carrier-declaration.d.ts +31 -0
- package/dist-client/modeller/carrier-declaration.js +53 -0
- package/dist-client/modeller/carrier-declaration.js.map +1 -0
- package/dist-client/modeller/editor.d.ts +13 -0
- package/dist-client/modeller/editor.js +62 -27
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-carrier.d.ts +26 -0
- package/dist-client/modeller/figure-carrier.js +123 -0
- package/dist-client/modeller/figure-carrier.js.map +1 -0
- package/dist-client/modeller/figure-cavity-drawing.js +3 -11
- package/dist-client/modeller/figure-cavity-drawing.js.map +1 -1
- package/dist-client/modeller/figure-first-save.d.ts +4 -0
- package/dist-client/modeller/figure-first-save.js +5 -8
- package/dist-client/modeller/figure-first-save.js.map +1 -1
- package/dist-client/modeller/figure-history-panel.js +2 -4
- package/dist-client/modeller/figure-history-panel.js.map +1 -1
- package/dist-client/modeller/figure-links.d.ts +4 -1
- package/dist-client/modeller/figure-links.js +47 -57
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-material-panel.d.ts +0 -1
- package/dist-client/modeller/figure-material-panel.js +4 -14
- package/dist-client/modeller/figure-material-panel.js.map +1 -1
- package/dist-client/modeller/figure-mesh-choice.d.ts +16 -0
- package/dist-client/modeller/figure-mesh-choice.js +75 -0
- package/dist-client/modeller/figure-mesh-choice.js.map +1 -0
- package/dist-client/modeller/figure-parts.d.ts +1 -1
- package/dist-client/modeller/figure-parts.js +22 -0
- package/dist-client/modeller/figure-parts.js.map +1 -1
- package/dist-client/modeller/figure-preview.js +2 -2
- package/dist-client/modeller/figure-preview.js.map +1 -1
- package/dist-client/modeller/figure-properties.d.ts +2 -1
- package/dist-client/modeller/figure-properties.js +5 -3
- package/dist-client/modeller/figure-properties.js.map +1 -1
- package/dist-client/modeller/figure-section-editor.d.ts +2 -2
- package/dist-client/modeller/figure-section-editor.js +12 -33
- package/dist-client/modeller/figure-section-editor.js.map +1 -1
- package/dist-client/modeller/figure-section-panel.js +6 -7
- package/dist-client/modeller/figure-section-panel.js.map +1 -1
- package/dist-client/modeller/figure-slot-layout-panel.d.ts +36 -0
- package/dist-client/modeller/figure-slot-layout-panel.js +198 -0
- package/dist-client/modeller/figure-slot-layout-panel.js.map +1 -0
- package/dist-client/modeller/figure-verdict.d.ts +1 -1
- package/dist-client/modeller/figure-verdict.js +19 -37
- package/dist-client/modeller/figure-verdict.js.map +1 -1
- package/dist-client/modeller/first-save.d.ts +10 -0
- package/dist-client/modeller/first-save.js +16 -0
- package/dist-client/modeller/first-save.js.map +1 -1
- package/dist-client/modeller/links.d.ts +26 -1
- package/dist-client/modeller/links.js +43 -0
- package/dist-client/modeller/links.js.map +1 -1
- package/dist-client/modeller/material-edit.d.ts +11 -0
- package/dist-client/modeller/material-edit.js +28 -0
- package/dist-client/modeller/material-edit.js.map +1 -0
- package/dist-client/modeller/maturity.d.ts +15 -0
- package/dist-client/modeller/maturity.js +23 -0
- package/dist-client/modeller/maturity.js.map +1 -1
- package/dist-client/modeller/mesh-import.d.ts +47 -0
- package/dist-client/modeller/mesh-import.js +47 -0
- package/dist-client/modeller/mesh-import.js.map +1 -0
- package/dist-client/modeller/modeller-route.d.ts +5 -0
- package/dist-client/modeller/modeller-route.js +9 -0
- package/dist-client/modeller/modeller-route.js.map +1 -1
- package/dist-client/modeller/mounting-part.d.ts +14 -0
- package/dist-client/modeller/mounting-part.js +10 -0
- package/dist-client/modeller/mounting-part.js.map +1 -0
- package/dist-client/modeller/newest-answer.d.ts +12 -0
- package/dist-client/modeller/newest-answer.js +21 -0
- package/dist-client/modeller/newest-answer.js.map +1 -0
- package/dist-client/modeller/preview-model.d.ts +2 -0
- package/dist-client/modeller/preview-model.js +4 -0
- package/dist-client/modeller/preview-model.js.map +1 -1
- package/dist-client/modeller/refusals.d.ts +26 -5
- package/dist-client/modeller/refusals.js +184 -86
- package/dist-client/modeller/refusals.js.map +1 -1
- package/dist-client/modeller/section-controls.d.ts +17 -1
- package/dist-client/modeller/section-controls.js +18 -0
- package/dist-client/modeller/section-controls.js.map +1 -1
- package/dist-client/modeller/section-drawing.d.ts +24 -1
- package/dist-client/modeller/section-drawing.js +42 -0
- package/dist-client/modeller/section-drawing.js.map +1 -1
- package/dist-client/modeller/slot-layout-host.d.ts +81 -0
- package/dist-client/modeller/slot-layout-host.js +105 -0
- package/dist-client/modeller/slot-layout-host.js.map +1 -0
- package/dist-client/pages/figure-modeller-page.js +5 -4
- package/dist-client/pages/figure-modeller-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/viewparts/detail-route.d.ts +5 -0
- package/dist-client/viewparts/detail-route.js +8 -0
- package/dist-client/viewparts/detail-route.js.map +1 -0
- package/dist-client/viewparts/figure-detail-dock.d.ts +0 -1
- package/dist-client/viewparts/figure-detail-dock.js +1 -3
- package/dist-client/viewparts/figure-detail-dock.js.map +1 -1
- package/package.json +9 -8
- package/test/align.test.ts +0 -9
- package/test/browser/assistant-stand-in.js +32 -0
- package/test/browser/build.check.mjs +77 -0
- package/test/browser/build.mjs +31 -6
- package/test/browser/editing-page.js +224 -0
- package/test/browser/editing.check.mjs +550 -0
- package/test/browser/links-page.js +113 -0
- package/test/browser/links.check.mjs +568 -0
- package/test/browser/modeller.check.mjs +21 -0
- package/test/browser/parts-page.js +120 -0
- package/test/browser/parts.check.mjs +328 -0
- package/test/browser/places-mesh-page.js +36 -0
- package/test/browser/places-mesh.check.mjs +239 -0
- package/test/browser/product-page.check.mjs +682 -0
- package/test/browser/product-page.js +276 -0
- package/test/browser/screen-page.js +112 -0
- package/test/browser/screen-product-page.js +62 -0
- package/test/browser/screen.check.mjs +1003 -0
- package/test/browser/section-page.js +256 -0
- package/test/browser/section.check.mjs +719 -0
- package/test/browser/serve.mjs +20 -12
- package/test/carrier-declaration.test.ts +69 -0
- package/test/cavity-drawing.test.ts +2 -18
- package/test/clip-ai-proposal.test.ts +1 -5
- package/test/clip-consent.test.ts +0 -5
- package/test/clips.test.ts +0 -7
- package/test/command-preview.test.ts +0 -68
- package/test/controls.test.ts +0 -9
- package/test/detail-dock.test.ts +6 -25
- package/test/face-mapping.test.ts +1 -20
- package/test/fasten-drawing.test.ts +0 -23
- package/test/fields.test.ts +6 -33
- package/test/figure-assistant-surface.test.ts +32 -38
- package/test/first-minute.test.ts +3 -55
- package/test/first-save-suggest.test.ts +11 -8
- package/test/first-save.test.ts +4 -26
- package/test/gizmo.test.ts +0 -25
- package/test/joint-fan.test.ts +0 -10
- package/test/keys.test.ts +0 -7
- package/test/layout.test.ts +4 -73
- package/test/links.test.ts +48 -67
- package/test/live.test.ts +0 -34
- package/test/material.test.ts +17 -26
- package/test/maturity.test.ts +13 -16
- package/test/mesh-import.test.ts +76 -0
- package/test/modeller-route.test.ts +3 -19
- package/test/package-download.test.ts +6 -7
- package/test/parts-wiring.test.ts +9 -51
- package/test/preview.test.ts +5 -46
- package/test/properties.test.ts +11 -26
- package/test/proposal-record.test.ts +2 -19
- package/test/recipes.test.ts +0 -15
- package/test/refusals.test.ts +257 -151
- package/test/release-entry.test.ts +1 -9
- package/test/release-panel.test.ts +1 -22
- package/test/resize-with-placement.test.ts +0 -32
- package/test/revert-choice.test.ts +1 -22
- package/test/revert-keeping.test.ts +1 -12
- package/test/save-landed.test.ts +16 -14
- package/test/scene-canvas.test.ts +2 -13
- package/test/section-editor.test.ts +30 -83
- package/test/section-panel.test.ts +22 -17
- package/test/slot-layout-host.test.ts +117 -0
- package/test/theme.test.ts +5 -9
- package/test/verdict.test.ts +44 -41
- package/test/view.test.ts +5 -12
- package/translations/en.json +61 -1
- package/translations/es.json +61 -1
- package/translations/ja.json +61 -1
- package/translations/ko.json +61 -1
- package/translations/ms.json +61 -1
- package/translations/zh.json +61 -1
- package/test/thumbnail.test.ts +0 -29
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The page the section check drives: the modeller page's editor (`modeller-page.js`), with the figures the section
|
|
3
|
+
* editor, the section panel, the inside's drawing, the fastening drawing and the face choice are tried on, and what the
|
|
4
|
+
* check reads of them. Only reading here: every change the check makes goes through the mouse and the keyboard.
|
|
5
|
+
*/
|
|
6
|
+
import './modeller-page.js'
|
|
7
|
+
import { html, render } from 'lit'
|
|
8
|
+
import { setOpenPopupImplementation } from '@operato/popup'
|
|
9
|
+
import { addFigureBox, addFigurePrimitive, applyFigureAuthoring, createFigureAsset, serializeFigureAsset } from '@hatiolab/figure-model'
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
* Popups drawn as the layout draws them -- an overlay of their own in the body, the result given when it leaves -- for
|
|
13
|
+
* the section editor's close question: the page has no layout to append it to.
|
|
14
|
+
*/
|
|
15
|
+
let popups = 0
|
|
16
|
+
setOpenPopupImplementation((template, options = {}) => {
|
|
17
|
+
const name = `$popup-${popups++}`
|
|
18
|
+
const fragment = document.createDocumentFragment()
|
|
19
|
+
render(html`<ox-floating-overlay id=${name} name=${name} .backdrop=${!!options.backdrop} .title=${options.title || ''} .size=${options.size || 'small'} .historical=${false}>${template}</ox-floating-overlay>`, fragment)
|
|
20
|
+
document.body.appendChild(fragment)
|
|
21
|
+
const handle = {
|
|
22
|
+
name,
|
|
23
|
+
close: () => {
|
|
24
|
+
const popup = document.getElementById(name)
|
|
25
|
+
if (!popup) return false
|
|
26
|
+
popup.close()
|
|
27
|
+
return true
|
|
28
|
+
},
|
|
29
|
+
closed: false
|
|
30
|
+
}
|
|
31
|
+
document.addEventListener('overlay-closed', function listener(e) {
|
|
32
|
+
if (e.detail !== name) return
|
|
33
|
+
document.removeEventListener('overlay-closed', listener)
|
|
34
|
+
handle.closed = true
|
|
35
|
+
handle.onclosed && handle.onclosed()
|
|
36
|
+
})
|
|
37
|
+
return handle
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const PALETTE = { 'palette.dark': '#2b2b2b', 'palette.neutral': '#9a9a9a', 'palette.primary': '#477b9e', 'palette.accent': '#f79c40', 'palette.light': '#dddddd' }
|
|
41
|
+
|
|
42
|
+
function figure(name) {
|
|
43
|
+
const a = createFigureAsset(name)
|
|
44
|
+
a.palette = { ...a.palette, ...PALETTE }
|
|
45
|
+
return a
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const TRIANGLE = [{ x: -300, z: -200 }, { x: 300, z: -200 }, { x: 0, z: 250 }]
|
|
49
|
+
const polygon = (a, id, points) => addFigurePrimitive(a, { id, kind: 'polygon', dimensions: { height: 200 }, points, position: { x: 0, y: 100, z: 0 } })
|
|
50
|
+
/** A box set beside the part being edited, for picking another part. */
|
|
51
|
+
const beside = a => addFigureBox(a, { id: 'block', size: { x: 200, y: 200, z: 200 }, position: { x: 900, y: 100, z: 0 } })
|
|
52
|
+
|
|
53
|
+
const FIGURES = {
|
|
54
|
+
/* A drawn section of four points, and a box beside it. */
|
|
55
|
+
quad: () => beside(polygon(figure('Quad'), 'wedge', [{ x: -300, z: -200 }, { x: 300, z: -200 }, { x: 300, z: 250 }, { x: -300, z: 250 }])),
|
|
56
|
+
wedge: () => polygon(figure('Wedge'), 'wedge', TRIANGLE),
|
|
57
|
+
/* The triangle with a plate on its top: its end cannot be drawn to one point while the plate stands there (A5-1). */
|
|
58
|
+
'capped-wedge': () => {
|
|
59
|
+
const a = addFigureBox(polygon(figure('Capped'), 'wedge', TRIANGLE), { id: 'cap', size: { x: 100, y: 20, z: 100 }, position: { x: 0, y: 0, z: 0 } })
|
|
60
|
+
return applyFigureAuthoring(a, { kind: 'attach', part: 'cap', face: 'bottom', to: { part: 'wedge', face: 'top' } })
|
|
61
|
+
},
|
|
62
|
+
pyramid: () => applyFigureAuthoring(polygon(figure('Pyramid'), 'wedge', TRIANGLE), { kind: 'set-section', part: 'wedge', apex: { x: 0, z: 0 } }),
|
|
63
|
+
/* A box standing on the floor: a length change keeps its bottom. */
|
|
64
|
+
'floor-box': () => applyFigureAuthoring(addFigureBox(figure('Floor'), { id: 'box', size: { x: 400, y: 200, z: 300 }, position: { x: 0, y: 100, z: 0 } }), { kind: 'set-placement', placement: 'floor' }),
|
|
65
|
+
/* A box whose sizes follow the figure's: none of them is its own to set. */
|
|
66
|
+
follows: () => applyFigureAuthoring(addFigureBox(figure('Follows'), { id: 'box', size: { x: 400, y: 400, z: 400 }, position: { x: 0, y: 200, z: 0 } }), { kind: 'follow-size', part: 'box' }),
|
|
67
|
+
/* A tray: 40 mm walls, a 30 mm floor, open on top; and a box beside it. */
|
|
68
|
+
tray: () =>
|
|
69
|
+
beside(applyFigureAuthoring(addFigureBox(figure('Tray'), { id: 'tray', size: { x: 400, y: 200, z: 300 }, position: { x: 0, y: 100, z: 0 } }), {
|
|
70
|
+
kind: 'set-cavity',
|
|
71
|
+
part: 'tray',
|
|
72
|
+
cavity: { wall: 40, start: { closed: 30 }, end: 'open' }
|
|
73
|
+
})),
|
|
74
|
+
/* A shallow tray, 20 mm deep inside 30: the handles of the two walls across it would stand on each other. */
|
|
75
|
+
'shallow-tray': () =>
|
|
76
|
+
applyFigureAuthoring(addFigureBox(figure('Shallow'), { id: 'tray', size: { x: 400, y: 200, z: 30 }, position: { x: 0, y: 100, z: 0 } }), {
|
|
77
|
+
kind: 'set-cavity',
|
|
78
|
+
part: 'tray',
|
|
79
|
+
cavity: { wall: 5, start: { closed: 10 }, end: 'open' }
|
|
80
|
+
}),
|
|
81
|
+
/* A tote on the floor with a divider standing on its inside floor, and a box beside it (ADR-0100 A8). */
|
|
82
|
+
tote: () => {
|
|
83
|
+
let a = addFigureBox(figure('Tote'), { id: 'bin', size: { x: 600, y: 300, z: 400 }, position: { x: 0, y: 150, z: 0 } })
|
|
84
|
+
a = applyFigureAuthoring(a, { kind: 'attach', part: 'bin', face: 'bottom', to: { plane: 'mounting-plane' } })
|
|
85
|
+
a = applyFigureAuthoring(a, { kind: 'set-cavity', part: 'bin', cavity: { wall: 10, start: { closed: 15 }, end: 'open' } })
|
|
86
|
+
a = addFigureBox(a, { id: 'divider', size: { x: 10, y: 200, z: 380 }, position: { x: 0, y: 0, z: 0 } })
|
|
87
|
+
return beside(applyFigureAuthoring(a, { kind: 'attach', part: 'divider', face: 'bottom', to: { part: 'bin', face: 'inside-bottom' } }))
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Every element matching `selector`, through every shadow root. */
|
|
92
|
+
function deep(selector, root = document) {
|
|
93
|
+
const found = [...root.querySelectorAll(selector)]
|
|
94
|
+
for (const element of root.querySelectorAll('*')) if (element.shadowRoot) found.push(...deep(selector, element.shadowRoot))
|
|
95
|
+
return found
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const words = element => element?.textContent?.replace(/\s+/g, ' ').trim() ?? ''
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The first element matching `selector` (through shadow roots), inside the first `within` when given, whose text is
|
|
102
|
+
* `text` (or holds it, with `has`), or whose aria-label is `label`; `index` picks among several.
|
|
103
|
+
*/
|
|
104
|
+
window.findDeep = (selector, { within, text, has, label, index = 0 } = {}) => {
|
|
105
|
+
const roots = within ? deep(within).map(host => host.shadowRoot ?? host) : [document]
|
|
106
|
+
const all = roots.flatMap(root => deep(selector, root))
|
|
107
|
+
const fit = all.filter(
|
|
108
|
+
e => (text === undefined || words(e) === text) && (has === undefined || words(e).includes(has)) && (label === undefined || e.getAttribute('aria-label') === label)
|
|
109
|
+
)
|
|
110
|
+
return fit[index] ?? null
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const editor = () => document.querySelector('figure-editor')
|
|
114
|
+
const canvas = () => deep('figure-canvas')[0]
|
|
115
|
+
const shapeWords = shape => {
|
|
116
|
+
if (!shape) return null
|
|
117
|
+
const drawn = shape.extrusion ?? shape.loft
|
|
118
|
+
return {
|
|
119
|
+
section: drawn ? JSON.parse(JSON.stringify(drawn.section)) : null,
|
|
120
|
+
apex: shape.loft?.apex ?? null,
|
|
121
|
+
length: drawn ? Math.round(drawn.end - drawn.start) : null,
|
|
122
|
+
cavity: shape.cavity ? JSON.parse(JSON.stringify({ wall: shape.cavity.wall, start: shape.cavity.start, end: shape.cavity.end })) : null
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const box = element => {
|
|
126
|
+
const r = element.getBoundingClientRect()
|
|
127
|
+
return { left: r.left, top: r.top, right: r.right, bottom: r.bottom, width: r.width, height: r.height }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
Object.assign(window.probe, {
|
|
131
|
+
/** A part's section, length and inside as the canvas draws it now -- a value in hand included. */
|
|
132
|
+
drawnShape(id) {
|
|
133
|
+
return shapeWords(canvas()?.parts?.find(p => p.id === id)?.shape)
|
|
134
|
+
},
|
|
135
|
+
/** A part's section, length and inside as the figure holds it. */
|
|
136
|
+
heldShape(id) {
|
|
137
|
+
return shapeWords(editor().session.read().geometry.find(g => g.id === id)?.shape)
|
|
138
|
+
},
|
|
139
|
+
/** The section editor as a person sees it; null when it is not open. */
|
|
140
|
+
sectionEditor() {
|
|
141
|
+
const host = deep('figure-section-editor')[0]
|
|
142
|
+
if (!host) return null
|
|
143
|
+
const root = host.shadowRoot
|
|
144
|
+
const caption = root.querySelector('div[caption]')
|
|
145
|
+
const buttons = [...root.querySelectorAll('footer button')]
|
|
146
|
+
const shown = e => !!e && getComputedStyle(e).display !== 'none'
|
|
147
|
+
const length = root.querySelector('div[sizes] label[mm]')
|
|
148
|
+
const apex = root.querySelector('label[apex]')
|
|
149
|
+
return {
|
|
150
|
+
caption: words(caption),
|
|
151
|
+
lastValid: !!caption?.hasAttribute('last-valid'),
|
|
152
|
+
stale: !!root.querySelector('footer span[grow][stale]'),
|
|
153
|
+
apply: { disabled: buttons.at(-1)?.disabled ?? null, text: words(buttons.at(-1)) },
|
|
154
|
+
points: root.querySelectorAll('ol[points] li').length,
|
|
155
|
+
issues: [...root.querySelectorAll('ul[issues] li')].map(words),
|
|
156
|
+
note: words(root.querySelector('small[role=status]')),
|
|
157
|
+
length: length ? { label: words(length.querySelector('span')), disabled: length.querySelector('input').disabled, note: words(length.querySelector('small')) } : null,
|
|
158
|
+
apex: apex ? { checked: apex.querySelector('input').checked, disabled: apex.querySelector('input').disabled, words: words(apex.querySelector('small')) } : null,
|
|
159
|
+
narrow: host.hasAttribute('narrow'),
|
|
160
|
+
show: host.getAttribute('show'),
|
|
161
|
+
tabs: shown(root.querySelector('nav[tabs]')),
|
|
162
|
+
body: shown(root.querySelector('div[body]')),
|
|
163
|
+
host: box(host),
|
|
164
|
+
room: box(host.parentElement),
|
|
165
|
+
bodyBox: box(root.querySelector('div[body]')),
|
|
166
|
+
footer: buttons.map(box),
|
|
167
|
+
faceMapping: !!root.querySelector('figure-face-mapping'),
|
|
168
|
+
cavityDrawing: !!root.querySelector('figure-cavity-drawing')
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
/** The close question, while it is asked: its words and its buttons. */
|
|
172
|
+
closeChoice() {
|
|
173
|
+
const host = deep('figure-section-close-choice')[0]
|
|
174
|
+
if (!host?.isConnected) return null
|
|
175
|
+
return { words: [...host.shadowRoot.querySelectorAll('p')].map(words), buttons: deep('md-text-button, md-filled-button', host.shadowRoot).map(words) }
|
|
176
|
+
},
|
|
177
|
+
/** The section panel as a person sees it: its words, its own number fields, and what it holds. */
|
|
178
|
+
sectionPanel() {
|
|
179
|
+
const host = deep('figure-section-panel')[0]
|
|
180
|
+
if (!host) return null
|
|
181
|
+
const root = host.shadowRoot
|
|
182
|
+
return {
|
|
183
|
+
edit: !!root.querySelector('button[act]'),
|
|
184
|
+
text: words(root),
|
|
185
|
+
inputs: [...root.querySelectorAll('input[type=number]')].map(i => ({ id: i.id, value: i.value })),
|
|
186
|
+
cavityToggle: !!root.querySelector('label[toggle] input'),
|
|
187
|
+
cavityDrawing: !!root.querySelector('figure-cavity-drawing'),
|
|
188
|
+
faceMapping: !!root.querySelector('figure-face-mapping')
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
/** The inside's drawing in `within`: its refusal, an open number field, its walls' handles and numbers. */
|
|
192
|
+
cavityDrawing(within = 'figure-section-panel') {
|
|
193
|
+
const host = window.findDeep('figure-cavity-drawing', { within })
|
|
194
|
+
if (!host) return null
|
|
195
|
+
const root = host.shadowRoot
|
|
196
|
+
const top = root.querySelector('svg')
|
|
197
|
+
return {
|
|
198
|
+
refusal: words(root.querySelector('small[refusal]')),
|
|
199
|
+
typing: root.querySelector('input') ? { label: root.querySelector('input').getAttribute('aria-label'), focused: root.activeElement === root.querySelector('input') } : null,
|
|
200
|
+
section: box(top.querySelector('rect, ellipse')),
|
|
201
|
+
walls: Object.fromEntries([...top.querySelectorAll('g[wall]')].map(g => [g.getAttribute('wall'), { handle: box(g.querySelector('rect')), number: box(g.querySelector('text')) }])),
|
|
202
|
+
ends: Object.fromEntries([...root.querySelectorAll('g[end]')].map(g => [g.getAttribute('end'), { text: words(g.querySelector('text')), typed: g.querySelector('text').hasAttribute('typed') }]))
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
/** The fastening drawing as a person sees it: the ways offered and the one on, the faces of the target. */
|
|
206
|
+
fastenDrawing() {
|
|
207
|
+
const host = deep('figure-fasten-drawing')[0]
|
|
208
|
+
if (!host) return null
|
|
209
|
+
const root = host.shadowRoot
|
|
210
|
+
return {
|
|
211
|
+
modes: [...root.querySelectorAll('button[mode]')].map(b => b.getAttribute('mode')),
|
|
212
|
+
on: root.querySelector('button[mode][on]')?.getAttribute('mode') ?? null
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
/** The labels before the fastening form's lists, and what each holds. */
|
|
216
|
+
fastenForm() {
|
|
217
|
+
return deep('select')
|
|
218
|
+
.filter(s => s.previousElementSibling)
|
|
219
|
+
.map(s => ({ label: words(s.previousElementSibling), value: s.value, options: [...s.options].map(o => ({ value: o.value, text: words(o) })) }))
|
|
220
|
+
},
|
|
221
|
+
/** The page point of one of a part's buttons in the parts list (`remove-part`, ...). */
|
|
222
|
+
partOp(id, op) {
|
|
223
|
+
const label = deep('span[label]').find(s => s.getAttribute('title') === id)
|
|
224
|
+
let row = label
|
|
225
|
+
while (row && !row.querySelector?.(`button[op="${op}"]`)) row = row.parentElement
|
|
226
|
+
const button = row?.querySelector(`button[op="${op}"]`)
|
|
227
|
+
if (!button) return null
|
|
228
|
+
button.scrollIntoView({ block: 'center' })
|
|
229
|
+
const r = button.getBoundingClientRect()
|
|
230
|
+
return { x: r.left + r.width / 2, y: r.top + r.height / 2 }
|
|
231
|
+
},
|
|
232
|
+
/** Where the keys go: the focused element and the focused ones inside it, through shadow roots, by tag. */
|
|
233
|
+
activePath() {
|
|
234
|
+
const path = []
|
|
235
|
+
for (let e = document.activeElement; e; e = e.shadowRoot?.activeElement) path.push(e.tagName)
|
|
236
|
+
return path
|
|
237
|
+
},
|
|
238
|
+
/** The fastening a part has, as the figure holds it. */
|
|
239
|
+
fastening(part) {
|
|
240
|
+
return (JSON.parse(editor().session.source()).joints ?? []).find(j => j.body1.part === part) ?? null
|
|
241
|
+
},
|
|
242
|
+
/** The face choice, wherever it stands: its rows and whether apply is open. */
|
|
243
|
+
faceMapping() {
|
|
244
|
+
const host = deep('figure-face-mapping')[0]
|
|
245
|
+
if (!host) return null
|
|
246
|
+
const root = host.shadowRoot
|
|
247
|
+
return { rows: root.querySelectorAll('select').length, apply: { disabled: root.querySelector('button[act]').disabled } }
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
window.sectionHarness = {
|
|
252
|
+
/** Mounts one of the figures above, or one of the modeller page's own (`arm`, `door`, `rollers`). */
|
|
253
|
+
mount(name) {
|
|
254
|
+
return FIGURES[name] ? window.harness.mount('box', serializeFigureAsset(FIGURES[name]())) : window.harness.mount(name)
|
|
255
|
+
}
|
|
256
|
+
}
|