@things-factory/figure-ui 10.1.154 → 10.1.156
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/canvas.ts +1 -1
- package/client/modeller/editor.ts +2 -2
- package/client/modeller/figure-capability-panel.ts +6 -24
- package/client/modeller/figure-carrier.ts +1 -1
- package/client/modeller/figure-clips.ts +1 -1
- package/client/modeller/figure-controls.ts +2 -2
- package/client/modeller/figure-face-mapping.ts +1 -1
- package/client/modeller/figure-links.ts +3 -2
- package/client/modeller/figure-material-panel.ts +1 -1
- package/client/modeller/figure-preview.ts +2 -2
- package/client/modeller/figure-properties.ts +1 -1
- package/client/modeller/figure-section-editor.ts +1 -1
- package/client/modeller/figure-section-panel.ts +1 -1
- package/client/modeller/figure-settings.ts +2 -2
- package/client/modeller/figure-verdict.ts +1 -1
- package/client/pages/figure-list-page.ts +7 -1
- package/client/viewparts/figure-detail-dock.ts +90 -41
- package/client/viewparts/figure-thumb.ts +2 -22
- package/dist-client/modeller/canvas.d.ts +1 -1
- package/dist-client/modeller/canvas.js +1 -1
- package/dist-client/modeller/canvas.js.map +1 -1
- package/dist-client/modeller/editor.js +2 -2
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-capability-panel.d.ts +0 -3
- package/dist-client/modeller/figure-capability-panel.js +5 -18
- package/dist-client/modeller/figure-capability-panel.js.map +1 -1
- package/dist-client/modeller/figure-carrier.js +1 -1
- package/dist-client/modeller/figure-carrier.js.map +1 -1
- package/dist-client/modeller/figure-clips.js +1 -1
- package/dist-client/modeller/figure-clips.js.map +1 -1
- package/dist-client/modeller/figure-controls.js +2 -2
- package/dist-client/modeller/figure-controls.js.map +1 -1
- package/dist-client/modeller/figure-face-mapping.js +1 -1
- package/dist-client/modeller/figure-face-mapping.js.map +1 -1
- package/dist-client/modeller/figure-links.js +3 -2
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-material-panel.js +1 -1
- package/dist-client/modeller/figure-material-panel.js.map +1 -1
- package/dist-client/modeller/figure-preview.d.ts +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.js +1 -1
- package/dist-client/modeller/figure-properties.js.map +1 -1
- package/dist-client/modeller/figure-section-editor.js +1 -1
- package/dist-client/modeller/figure-section-editor.js.map +1 -1
- package/dist-client/modeller/figure-section-panel.js +1 -1
- package/dist-client/modeller/figure-section-panel.js.map +1 -1
- package/dist-client/modeller/figure-settings.d.ts +1 -1
- package/dist-client/modeller/figure-settings.js +1 -1
- package/dist-client/modeller/figure-settings.js.map +1 -1
- package/dist-client/modeller/figure-verdict.js +1 -1
- package/dist-client/modeller/figure-verdict.js.map +1 -1
- package/dist-client/pages/figure-list-page.d.ts +1 -0
- package/dist-client/pages/figure-list-page.js +11 -1
- package/dist-client/pages/figure-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/viewparts/figure-detail-dock.d.ts +10 -1
- package/dist-client/viewparts/figure-detail-dock.js +93 -41
- package/dist-client/viewparts/figure-detail-dock.js.map +1 -1
- package/dist-client/viewparts/figure-thumb.d.ts +1 -0
- package/dist-client/viewparts/figure-thumb.js +2 -22
- package/dist-client/viewparts/figure-thumb.js.map +1 -1
- package/package.json +5 -4
- package/test/browser/detail-page.js +10 -2
- package/test/browser/product-page.check.mjs +1 -1
- package/test/browser/screen-page.js +1 -1
- package/test/browser/serve-detail.mjs +7 -2
- package/test/figure-controls-keys.test.ts +19 -0
- package/test/i18n-prefix-guard.test.ts +4 -1
- package/test/layout.test.ts +4 -3
- package/test/links.test.ts +5 -4
- package/test/properties.test.ts +2 -1
- package/test/refusals.test.ts +2 -1
- package/test/theme.test.ts +1 -1
- package/test/verdict.test.ts +2 -1
- package/test/words.ts +20 -0
- package/translations/en.json +2 -33
- package/translations/es.json +2 -33
- package/translations/ja.json +2 -33
- package/translations/ko.json +2 -33
- package/translations/ms.json +2 -33
- package/translations/zh.json +2 -33
- package/client/modeller/controls.ts +0 -54
- package/client/modeller/figure-view.ts +0 -151
- package/client/modeller/preview-model.ts +0 -89
- package/client/modeller/side-panel-styles.ts +0 -374
- package/client/viewparts/detail-motion.ts +0 -11
- package/client/viewparts/figure-asset-viewer.ts +0 -177
- package/dist-client/modeller/controls.d.ts +0 -28
- package/dist-client/modeller/controls.js +0 -28
- package/dist-client/modeller/controls.js.map +0 -1
- package/dist-client/modeller/figure-view.d.ts +0 -117
- package/dist-client/modeller/figure-view.js +0 -78
- package/dist-client/modeller/figure-view.js.map +0 -1
- package/dist-client/modeller/preview-model.d.ts +0 -54
- package/dist-client/modeller/preview-model.js +0 -79
- package/dist-client/modeller/preview-model.js.map +0 -1
- package/dist-client/modeller/side-panel-styles.d.ts +0 -27
- package/dist-client/modeller/side-panel-styles.js +0 -374
- package/dist-client/modeller/side-panel-styles.js.map +0 -1
- package/dist-client/viewparts/detail-motion.d.ts +0 -6
- package/dist-client/viewparts/detail-motion.js +0 -9
- package/dist-client/viewparts/detail-motion.js.map +0 -1
- package/dist-client/viewparts/figure-asset-viewer.d.ts +0 -31
- package/dist-client/viewparts/figure-asset-viewer.js +0 -198
- package/dist-client/viewparts/figure-asset-viewer.js.map +0 -1
- package/test/controls.test.ts +0 -60
- package/test/detail-motion.test.ts +0 -26
- package/test/preview.test.ts +0 -53
- package/test/view.test.ts +0 -13
|
@@ -4,7 +4,7 @@ import { create, Model, niceGridStep } from '@hatiolab/things-scene'
|
|
|
4
4
|
|
|
5
5
|
import type { GizmoReach } from './gizmo.js'
|
|
6
6
|
import type { FigureRenderPart } from './renderer.js'
|
|
7
|
-
import { DEFAULT_VIEW, sceneLook, WORKBENCH, type ViewSettings } from '
|
|
7
|
+
import { DEFAULT_VIEW, sceneLook, WORKBENCH, type ViewSettings } from '@things-factory/figure-viewer/dist-client/figure-view.js'
|
|
8
8
|
import { boardFor, changedKeys, componentOf, gizmoResultOf, type Board, type ScaleAnchor } from './stage-model.js'
|
|
9
9
|
import { JOINT_FAN } from './joint-fan.js'
|
|
10
10
|
import { SLOT_MARK } from './slot-layout-host.js'
|
|
@@ -26,7 +26,7 @@ import './figure-controls.js'
|
|
|
26
26
|
import './figure-clips.js'
|
|
27
27
|
import './figure-preview.js'
|
|
28
28
|
import './figure-settings.js'
|
|
29
|
-
import { DEFAULT_VIEW, type ViewSettings } from '
|
|
29
|
+
import { DEFAULT_VIEW, type ViewSettings } from '@things-factory/figure-viewer/dist-client/figure-view.js'
|
|
30
30
|
import './figure-capability-panel.js'
|
|
31
31
|
import { gizmoChanges, gizmoReachOf, type GizmoReach, type GizmoResult } from './gizmo.js'
|
|
32
32
|
import type { KeyAction } from './keys.js'
|
|
@@ -35,7 +35,7 @@ import { PaneFold } from './pane-fold.js'
|
|
|
35
35
|
import { PanelMemory } from './panel-memory.js'
|
|
36
36
|
import { RefusalTeller, type Retry } from './refusal-teller.js'
|
|
37
37
|
import { groupFields, ownerOf, partLabelOf, repeatOf, type FieldLike, type FieldGroup } from './fields.js'
|
|
38
|
-
import { SidePanelStyles } from '
|
|
38
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
39
39
|
import { EditorStyles } from './editor-styles.js'
|
|
40
40
|
import { ScrollbarStyles } from '@operato/styles'
|
|
41
41
|
import { alignChanges, canMirror, mirrorChanges, type AlignTool } from './align.js'
|
|
@@ -4,28 +4,10 @@ import { live } from 'lit/directives/live.js'
|
|
|
4
4
|
|
|
5
5
|
import { i18next, localize } from '@operato/i18n'
|
|
6
6
|
import { figureBindingsOf } from '@hatiolab/figure-model'
|
|
7
|
-
import type {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
One rung per set of the format's capability names. Typed as the format's names, so a misspelt rung does not pass
|
|
12
|
-
(ADR-0051 ④).
|
|
13
|
-
*/
|
|
14
|
-
type Rung = 'none' | 'hold' | 'flow'
|
|
15
|
-
const RUNGS: Readonly<Record<Rung, readonly FigureCapability[]>> = Object.freeze({
|
|
16
|
-
none: [],
|
|
17
|
-
hold: ['Capacity', 'Holdable'],
|
|
18
|
-
flow: ['FlowNode']
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
/** Which rung a set of names is, or null when it is none of them -- not invented. */
|
|
22
|
-
export function rungOf(names: readonly string[] | undefined): Rung | null {
|
|
23
|
-
const has = new Set(names ?? [])
|
|
24
|
-
if (has.size === 0) return 'none'
|
|
25
|
-
for (const [rung, wanted] of Object.entries(RUNGS) as [Rung, readonly FigureCapability[]][])
|
|
26
|
-
if (wanted.length === has.size && wanted.every(name => has.has(name))) return rung
|
|
27
|
-
return null
|
|
28
|
-
}
|
|
7
|
+
import type { FigureAsset } from '@hatiolab/figure-model'
|
|
8
|
+
import { RUNGS, rungOf, type Rung } from '@things-factory/figure-viewer/dist-client/capability-rung.js'
|
|
9
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
10
|
+
import { placeTerms } from '@things-factory/figure-viewer/dist-client/detail-facts.js'
|
|
29
11
|
|
|
30
12
|
/**
|
|
31
13
|
* 자리·능력 — what the figure does on a board: the ladder from drawing only, to
|
|
@@ -116,8 +98,8 @@ export class FigureCapabilityPanel extends localize(i18next)(LitElement) {
|
|
|
116
98
|
one => html`<button place ?on=${one.part === this.selected} @click=${() => one.part && this.pick(one.part)}>
|
|
117
99
|
<strong>${one.label}</strong>
|
|
118
100
|
<small>
|
|
119
|
-
${
|
|
120
|
-
${one
|
|
101
|
+
${one.part ?? '?'}${one.face ? ' · ' + i18next.t('figure.label.face-' + one.face) : ''} ·
|
|
102
|
+
${placeTerms(one, (key, params) => i18next.t(key, params))}
|
|
121
103
|
</small>
|
|
122
104
|
</button>`
|
|
123
105
|
)
|
|
@@ -6,7 +6,7 @@ import { i18next, localize } from '@operato/i18n'
|
|
|
6
6
|
import type { FigureAsset, FigureAuthoringAction } from '@hatiolab/figure-model'
|
|
7
7
|
|
|
8
8
|
import { CARRIER_AXES, carrierCommandOf, carrierDraftOf, draftIsDeclared, type CarrierAxis, type CarrierDraft } from './carrier-declaration.js'
|
|
9
|
-
import { SidePanelStyles } from '
|
|
9
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
10
10
|
|
|
11
11
|
const AXIS_LETTER: Record<CarrierAxis, string> = { width: 'W', length: 'L', height: 'H' }
|
|
12
12
|
|
|
@@ -7,7 +7,7 @@ import { i18next, localize } from '@operato/i18n'
|
|
|
7
7
|
import type { FigureAsset } from '@hatiolab/figure-model'
|
|
8
8
|
|
|
9
9
|
import { clipsOf, poseAt, trackEdit, undrivenOf, withKey, withoutKey, type Clip, type ClipTrack } from './clips.js'
|
|
10
|
-
import { SidePanelStyles } from '
|
|
10
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
11
11
|
import { HelpToggles } from './help.js'
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -6,9 +6,9 @@ import { customElement, property, state } from 'lit/decorators.js'
|
|
|
6
6
|
import { i18next, localize } from '@operato/i18n'
|
|
7
7
|
import type { FigureAsset } from '@hatiolab/figure-model'
|
|
8
8
|
|
|
9
|
-
import { controlsOf, poseAsDefault, poseDiffers, type Control } from '
|
|
9
|
+
import { controlsOf, poseAsDefault, poseDiffers, type Control } from '@things-factory/figure-viewer/dist-client/controls.js'
|
|
10
10
|
import { dialShape } from './angle-dial.js'
|
|
11
|
-
import { SidePanelStyles } from '
|
|
11
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* The figure's controls and its pose tools: each value a board sets to pose the figure,
|
|
@@ -4,7 +4,7 @@ import { customElement, property, state } from 'lit/decorators.js'
|
|
|
4
4
|
import { i18next, localize } from '@operato/i18n'
|
|
5
5
|
import type { FigureFaceMappingNeed } from '@hatiolab/figure-model'
|
|
6
6
|
|
|
7
|
-
import { SidePanelStyles } from '
|
|
7
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
8
8
|
import { DETACH, faceMappingRowsOf, remapOf, rowKey } from './face-mapping.js'
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -53,13 +53,14 @@ import {
|
|
|
53
53
|
type Follow,
|
|
54
54
|
type MotionForm
|
|
55
55
|
} from './links.js'
|
|
56
|
-
import { SidePanelStyles } from '
|
|
56
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
57
57
|
import './figure-fasten-drawing.js'
|
|
58
58
|
import type { FastenChange } from './figure-fasten-drawing.js'
|
|
59
59
|
import { faceViewOf, insideAlignmentOf, modeOf, myFaceFor, turnsInPlace, type FaceView, type FastenMode } from './fasten-geometry.js'
|
|
60
60
|
import type { FigureRevision } from './revision.js'
|
|
61
61
|
import { HelpToggles } from './help.js'
|
|
62
62
|
import { jointAxisWord } from './joint-axis.js'
|
|
63
|
+
import { placeTerms } from '@things-factory/figure-viewer/dist-client/detail-facts.js'
|
|
63
64
|
|
|
64
65
|
const FACES = Object.keys(FIGURE_FACES) as FigureFace[]
|
|
65
66
|
/** The target list's entry for the plane the figure stands by. */
|
|
@@ -296,7 +297,7 @@ export class FigureLinks extends localize(i18next)(LitElement) {
|
|
|
296
297
|
one => html`<div pair>
|
|
297
298
|
<span>
|
|
298
299
|
<b bound>${one.label}</b>
|
|
299
|
-
<small>${
|
|
300
|
+
<small>${one.face ? i18next.t('figure.label.face-' + one.face) + ' · ' : ''}${placeTerms(one, (key, params) => i18next.t(key, params))}</small>
|
|
300
301
|
</span>
|
|
301
302
|
<button act ?disabled=${this.locked} @click=${() => this.command({ kind: 'remove-binding', id: one.id })}>
|
|
302
303
|
<md-icon>close</md-icon>${i18next.t('figure.button.remove-place')}
|
|
@@ -5,7 +5,7 @@ import { i18next, localize } from '@operato/i18n'
|
|
|
5
5
|
import { MATERIAL_PRESETS, SEGMENT_PRESETS, figureTrianglesOf } from '@hatiolab/figure-model'
|
|
6
6
|
import { activePalette } from '@hatiolab/things-scene'
|
|
7
7
|
import type { FigureAssetGeometry, FigureMaterial, FigurePartEdit } from '@hatiolab/figure-model'
|
|
8
|
-
import { SidePanelStyles } from '
|
|
8
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
9
9
|
import { isRoundBody } from './starting-shape.js'
|
|
10
10
|
import { glowOf, materialEditOf, offeredPaletteOf } from './material-edit.js'
|
|
11
11
|
|
|
@@ -6,10 +6,10 @@ import { compileFigureAsset } from '@hatiolab/figure-model'
|
|
|
6
6
|
import type { FigureAsset } from '@hatiolab/figure-model'
|
|
7
7
|
import { create, registerFigure, unregisterFigure } from '@hatiolab/things-scene'
|
|
8
8
|
|
|
9
|
-
import { DEFAULT_VIEW, previewBoardDepth, sceneLook, WORKBENCH, type ViewSettings } from '
|
|
9
|
+
import { DEFAULT_VIEW, previewBoardDepth, sceneLook, WORKBENCH, type ViewSettings } from '@things-factory/figure-viewer/dist-client/figure-view.js'
|
|
10
10
|
import { dialShape } from './angle-dial.js'
|
|
11
11
|
import { derivedOf, type FigureRevision } from './revision.js'
|
|
12
|
-
import { authoredSizeOf, PREVIEW_FACTOR, PREVIEW_WAYS, previewClampsOf, previewInstances, previewTypeOf, setupPartOf } from '
|
|
12
|
+
import { authoredSizeOf, PREVIEW_FACTOR, PREVIEW_WAYS, previewClampsOf, previewInstances, previewTypeOf, setupPartOf } from '@things-factory/figure-viewer/dist-client/preview-model.js'
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* The figure placed on a board.
|
|
@@ -13,7 +13,7 @@ import { occupancyFromParts } from './occupancy.js'
|
|
|
13
13
|
import { tagsOf, figureFigureFacts, type Placement, type FigureFigureFacts } from './figure-facts.js'
|
|
14
14
|
import { offeredMountingOf } from './mounting-part.js'
|
|
15
15
|
import type { FigureRevision } from './revision.js'
|
|
16
|
-
import { SidePanelStyles } from '
|
|
16
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
17
17
|
import { ScrollbarStyles } from '@operato/styles'
|
|
18
18
|
|
|
19
19
|
const PLACEMENTS: Placement[] = ['floor', 'ceiling', 'center', 'wall']
|
|
@@ -5,7 +5,7 @@ import { live } from 'lit/directives/live.js'
|
|
|
5
5
|
import { i18next, localize } from '@operato/i18n'
|
|
6
6
|
import { figureCavitySectionOf, figureSectionSidesOf } from '@hatiolab/figure-model'
|
|
7
7
|
import type { FigureAuthoringAction, FigureEvaluatedShape, FigureFaceMappingNeed, FigureSection, FigureSectionMeasure, FigureSectionPoint } from '@hatiolab/figure-model'
|
|
8
|
-
import { SidePanelStyles } from '
|
|
8
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
9
9
|
import { apexOver, cavityKeyOf, drawnOf, insertAfter, markedBy, measureNoteOf, movePoint, pointLabel, removePoint, sectionActionOf, sectionOf, workingIssuesOf, workingOf, workingShapeOf, type SectionWorking } from './section-drawing.js'
|
|
10
10
|
import { cavityDepthOf, cavityRequestOf, cavityResultOf, hollowableOf, sameOf, sidesOf } from './section-controls.js'
|
|
11
11
|
import './figure-cavity-drawing.js'
|
|
@@ -5,7 +5,7 @@ import { live } from 'lit/directives/live.js'
|
|
|
5
5
|
|
|
6
6
|
import { i18next, localize } from '@operato/i18n'
|
|
7
7
|
import type { FigureAuthoringAction, FigureEvaluatedShape, FigureFaceMappingNeed } from '@hatiolab/figure-model'
|
|
8
|
-
import { SidePanelStyles } from '
|
|
8
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
9
9
|
import { drawnOf, sectionPointsWordsOf } from './section-drawing.js'
|
|
10
10
|
import './figure-cavity-drawing.js'
|
|
11
11
|
import './figure-face-mapping.js'
|
|
@@ -4,8 +4,8 @@ import { customElement, property } from 'lit/decorators.js'
|
|
|
4
4
|
import { i18next, localize } from '@operato/i18n'
|
|
5
5
|
import { ScrollbarStyles } from '@operato/styles'
|
|
6
6
|
|
|
7
|
-
import { DEFAULT_VIEW, ENVIRONMENTS, SCENE_REFERENCES } from '
|
|
8
|
-
import type { EnvironmentName, ViewSettings } from '
|
|
7
|
+
import { DEFAULT_VIEW, ENVIRONMENTS, SCENE_REFERENCES } from '@things-factory/figure-viewer/dist-client/figure-view.js'
|
|
8
|
+
import type { EnvironmentName, ViewSettings } from '@things-factory/figure-viewer/dist-client/figure-view.js'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* 저작 화면의 **보기 설정**.
|
|
@@ -12,7 +12,7 @@ import type { FigureInspection } from '../types.js'
|
|
|
12
12
|
import { gateFindingStyles, renderGateFinding } from './gate-findings.js'
|
|
13
13
|
import { MEASURED } from './scene-budget.js'
|
|
14
14
|
import type { FigureRevision } from './revision.js'
|
|
15
|
-
import { SidePanelStyles } from '
|
|
15
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
16
16
|
import { CURVE_SIZE, curveLayout, gradeBoundsOf, shortNumber, verdictMeasureOf } from './maturity.js'
|
|
17
17
|
import { newestAnswer } from './newest-answer.js'
|
|
18
18
|
import type { FigureBudgetUse, FigureMaturityAxis, FigureReport } from './maturity.js'
|
|
@@ -16,7 +16,7 @@ import { capacityFrom } from '../modeller/scene-budget.js'
|
|
|
16
16
|
import { deleteFigure, fetchFigureList } from '../graphql/index.js'
|
|
17
17
|
import type { Figure } from '../types.js'
|
|
18
18
|
import { modellerPathOf } from '../modeller/modeller-route.js'
|
|
19
|
-
import { openFigureDetail } from '../viewparts/figure-detail-dock.js'
|
|
19
|
+
import { FIGURE_THUMBNAIL_CHANGED, openFigureDetail } from '../viewparts/figure-detail-dock.js'
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* 이 값 아래면 점수를 색으로 눈에 띄게 한다.
|
|
@@ -560,6 +560,11 @@ export class FigureListPage extends FigureListPageBase {
|
|
|
560
560
|
}
|
|
561
561
|
}
|
|
562
562
|
auth.on('profile', this.listen)
|
|
563
|
+
/* A picture chosen in the preview: the cards are read again, with the picture's new stamp. */
|
|
564
|
+
window.addEventListener(FIGURE_THUMBNAIL_CHANGED, this.pictureChanged)
|
|
565
|
+
}
|
|
566
|
+
private pictureChanged = () => {
|
|
567
|
+
if (this.active) this.grist?.fetch()
|
|
563
568
|
}
|
|
564
569
|
|
|
565
570
|
disconnectedCallback() {
|
|
@@ -567,6 +572,7 @@ export class FigureListPage extends FigureListPageBase {
|
|
|
567
572
|
auth.off?.('profile', this.listen)
|
|
568
573
|
this.listen = undefined
|
|
569
574
|
}
|
|
575
|
+
window.removeEventListener(FIGURE_THUMBNAIL_CHANGED, this.pictureChanged)
|
|
570
576
|
super.disconnectedCallback()
|
|
571
577
|
}
|
|
572
578
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import '@material/web/icon/icon.js'
|
|
1
2
|
import { css, html, LitElement, nothing } from 'lit'
|
|
2
3
|
import { customElement, property, state } from 'lit/decorators.js'
|
|
3
4
|
import { i18next, localize } from '@operato/i18n'
|
|
@@ -7,13 +8,17 @@ import { ScrollbarStyles } from '@operato/styles'
|
|
|
7
8
|
import { ASSISTANT_DOCK_VIEWPART } from '@things-factory/ai-assistant/dist-client/components/assistant-dock.js'
|
|
8
9
|
import { figureCostOf, parseFigureAsset, type FigureAsset } from '@hatiolab/figure-model'
|
|
9
10
|
import { capacityFrom } from '../modeller/scene-budget.js'
|
|
10
|
-
import {
|
|
11
|
+
import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'
|
|
12
|
+
import { fetchFigure, fetchReleasedFigure, updateFigure } from '../graphql/index.js'
|
|
11
13
|
import { modellerPathOf } from '../modeller/modeller-route.js'
|
|
12
14
|
import { leftOpeningPage } from './detail-route.js'
|
|
13
15
|
import type { Figure } from '../types.js'
|
|
14
|
-
import '
|
|
16
|
+
import '@things-factory/figure-viewer/dist-client/figure-asset-viewer.js'
|
|
17
|
+
import '@things-factory/figure-viewer/dist-client/figure-facts-list.js'
|
|
15
18
|
|
|
16
19
|
const VIEWPART = 'figure-detail'
|
|
20
|
+
/** Said on window when a figure's card picture was replaced from the preview: `{ detail: { id } }`. */
|
|
21
|
+
export const FIGURE_THUMBNAIL_CHANGED = 'figure-thumbnail-changed'
|
|
17
22
|
export interface FigureDetailRecord {
|
|
18
23
|
saved: Figure
|
|
19
24
|
released?: { version: number; source: string }
|
|
@@ -22,23 +27,41 @@ export interface FigureDetailRecord {
|
|
|
22
27
|
/** Catalogue details stay while the catalogue is shown; choosing a size or a pose has no write path. */
|
|
23
28
|
@customElement('figure-detail-dock')
|
|
24
29
|
export class FigureDetailDock extends localize(i18next)(LitElement) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
/*
|
|
31
|
+
The modeller's side panel look (SidePanelStyles). What the preview is opened for sits above the model -- name, type,
|
|
32
|
+
which model is shown, how many fit -- as plain text; the controls are borderless icons and quiet text, so the model
|
|
33
|
+
and its numbers are what the eye meets.
|
|
34
|
+
*/
|
|
35
|
+
static styles = [ScrollbarStyles, SidePanelStyles, css`
|
|
36
|
+
:host { display: flex; flex-direction: column; width: 400px; max-width: 100vw; height: 100%; min-height: 0;
|
|
37
|
+
background: var(--md-sys-color-surface); border-left: 1px solid var(--md-sys-color-outline-variant); }
|
|
38
|
+
header { display: flex; align-items: flex-start; gap: 2px; padding: 12px 8px 4px 16px; }
|
|
39
|
+
[title-block] { flex: 1; min-width: 0; display: grid; gap: 2px; }
|
|
40
|
+
h2 { margin: 0; font-size: var(--ui-t-title, 16px); font-weight: 600; line-height: 1.3; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
41
|
+
code { font-family: var(--mono-font, monospace); color: var(--md-sys-color-on-surface-variant); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
42
|
+
button { font: inherit; color: inherit; cursor: pointer; }
|
|
43
|
+
button:focus-visible { outline: 2px solid var(--md-sys-color-primary); outline-offset: 1px; }
|
|
44
|
+
button[icon] { display: inline-grid; place-items: center; width: 28px; height: 28px; padding: 0; border: none; border-radius: 6px;
|
|
45
|
+
background: transparent; color: var(--md-sys-color-on-surface-variant); }
|
|
46
|
+
button[icon]:hover:not(:disabled) { background: var(--md-sys-color-surface-container-high); color: var(--md-sys-color-on-surface); }
|
|
47
|
+
button[icon]:disabled { opacity: 0.38; cursor: default; }
|
|
48
|
+
button[icon] md-icon { --md-icon-size: 18px; }
|
|
31
49
|
[body] { flex: 1; overflow: auto; min-height: 0; }
|
|
32
|
-
[meta]
|
|
33
|
-
|
|
34
|
-
[
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
[meta] { display: grid; gap: 8px; padding: 0 16px 12px; }
|
|
51
|
+
/* Which model is shown: words that change colour, not boxes. */
|
|
52
|
+
[source] { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; color: var(--md-sys-color-on-surface-variant); }
|
|
53
|
+
[source] button { padding: 0; border: none; background: none; color: var(--md-sys-color-on-surface-variant); }
|
|
54
|
+
[source] button:hover { color: var(--md-sys-color-on-surface); }
|
|
55
|
+
[source] button[aria-pressed='true'] { color: var(--md-sys-color-primary); font-weight: 600; }
|
|
56
|
+
dl { margin: 0; }
|
|
57
|
+
dt { color: var(--md-sys-color-on-surface-variant); }
|
|
58
|
+
dd { margin: 0; color: var(--md-sys-color-on-surface); }
|
|
59
|
+
dl[stats] { display: flex; flex-wrap: wrap; gap: 4px 16px; }
|
|
60
|
+
dl[stats] > div { display: flex; align-items: baseline; gap: 4px; }
|
|
61
|
+
dl[stats] dd { font-weight: 600; font-variant-numeric: tabular-nums; }
|
|
38
62
|
p { margin: 0; line-height: 1.5; }
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
footer button { width: 100%; background: var(--md-sys-color-primary-container); color: var(--md-sys-color-on-primary-container); }
|
|
63
|
+
[description] { color: var(--md-sys-color-on-surface-variant); }
|
|
64
|
+
[status] { display: grid; gap: 8px; justify-items: start; padding: 12px 16px; }
|
|
42
65
|
@media (max-width: 1439.98px) {
|
|
43
66
|
:host { position: fixed; inset: var(--figure-detail-top, 44px) 0 0 auto; height: calc(100dvh - var(--figure-detail-top, 44px)); z-index: 11; box-shadow: -4px 0 16px rgb(0 0 0 / 20%); }
|
|
44
67
|
}
|
|
@@ -48,6 +71,14 @@ export class FigureDetailDock extends localize(i18next)(LitElement) {
|
|
|
48
71
|
if (!saved?.source) throw Error(i18next.t('figure.text.detail-no-source'))
|
|
49
72
|
return { saved, released }
|
|
50
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Keeps the picture taken in the preview as the figure's card picture. A patch of the picture alone does not make a
|
|
76
|
+
* released figure a draft (`updateFigure`). The catalogue is told, and reads its cards again.
|
|
77
|
+
*/
|
|
78
|
+
@property({ attribute: false }) keepThumbnail: (id: string, dataUrl: string) => Promise<unknown> = async (id, dataUrl) => {
|
|
79
|
+
await updateFigure(id, { thumbnail: dataUrl })
|
|
80
|
+
window.dispatchEvent(new CustomEvent(FIGURE_THUMBNAIL_CHANGED, { detail: { id } }))
|
|
81
|
+
}
|
|
51
82
|
@state() private figureId = ''
|
|
52
83
|
@state() private record?: FigureDetailRecord
|
|
53
84
|
@state() private asset?: FigureAsset
|
|
@@ -133,38 +164,56 @@ export class FigureDetailDock extends localize(i18next)(LitElement) {
|
|
|
133
164
|
}
|
|
134
165
|
render() {
|
|
135
166
|
const saved = this.record?.saved
|
|
167
|
+
const released = this.record?.released
|
|
136
168
|
const cost = this.cost
|
|
137
169
|
const capacity = cost ? capacityFrom(cost.groups, cost.triangles) : undefined
|
|
138
|
-
|
|
139
|
-
|
|
170
|
+
const savedLabel = saved
|
|
171
|
+
? `${i18next.t('figure.label.detail-saved')} · ${i18next.t(saved.state === 'released' ? 'figure.label.figure-released' : 'figure.label.draft')}`
|
|
172
|
+
: ''
|
|
173
|
+
return html`<header>
|
|
174
|
+
<div title-block><h2 title=${saved?.name || ''}>${saved?.name || i18next.t('figure.title.detail')}</h2>
|
|
175
|
+
${saved ? html`<code title=${fullName(saved)}>${fullName(saved)}</code>` : nothing}</div>
|
|
176
|
+
<button icon edit aria-label=${i18next.t('figure.button.detail-edit')} title=${i18next.t('figure.button.detail-edit')} ?disabled=${!saved}
|
|
177
|
+
@click=${() => {
|
|
178
|
+
// The modeller shows the figure itself; a preview of it beside the editor only covers the work.
|
|
179
|
+
hideDetail()
|
|
180
|
+
navigate(modellerPathOf(saved))
|
|
181
|
+
}}><md-icon>edit</md-icon></button>
|
|
182
|
+
<button icon aria-label=${i18next.t('figure.button.close')} title=${i18next.t('figure.button.close')} @click=${() => hideDetail()}><md-icon>close</md-icon></button>
|
|
183
|
+
</header>
|
|
140
184
|
<div body>
|
|
141
185
|
${this.loading ? html`<p status role="status">${i18next.t('figure.text.detail-loading')}</p>` : nothing}
|
|
142
|
-
${this.error ? html`<div status role="alert"><p>${this.error}</p><button @click=${() => this.show(this.figureId)}>${i18next.t('figure.button.detail-retry')}</button></div>` : nothing}
|
|
143
|
-
${saved ? html`<section meta
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
</
|
|
150
|
-
${
|
|
186
|
+
${this.error ? html`<div status role="alert"><p>${this.error}</p><button act @click=${() => this.show(this.figureId)}><md-icon>refresh</md-icon>${i18next.t('figure.button.detail-retry')}</button></div>` : nothing}
|
|
187
|
+
${saved ? html`<section meta>
|
|
188
|
+
${released
|
|
189
|
+
? html`<div source role="group" aria-label=${i18next.t('figure.label.detail-source')}>
|
|
190
|
+
<button aria-pressed=${String(this.sourceKind === 'released')} @click=${() => this.choose('released')}>${i18next.t('figure.label.detail-released', { version: released.version })}</button>
|
|
191
|
+
<button aria-pressed=${String(this.sourceKind === 'saved')} @click=${() => this.choose('saved')}>${savedLabel}</button>
|
|
192
|
+
</div>`
|
|
193
|
+
: html`<div source><span title=${i18next.t('figure.text.detail-unreleased')}>${savedLabel}</span></div>`}
|
|
194
|
+
${this.asset ? html`<dl stats>
|
|
195
|
+
<div><dt>${i18next.t('figure.label.placement-limit')}</dt><dd>${capacity
|
|
196
|
+
? i18next.t('figure.text.fits-n-instances', { n: capacity.instances.toLocaleString() })
|
|
197
|
+
: i18next.t('figure.text.not-measured-yet')}</dd></div>
|
|
198
|
+
<div><dt>${i18next.t('figure.label.triangles')}</dt><dd>${cost?.triangles.toLocaleString() ?? '—'}</dd></div>
|
|
199
|
+
<div><dt>${i18next.t('figure.label.budget-groups')}</dt><dd>${cost?.groups ?? '—'}</dd></div>
|
|
200
|
+
<div><dt>${i18next.t('figure.label.budget-parts')}</dt><dd>${this.asset.appearance.length}</dd></div>
|
|
201
|
+
</dl>` : nothing}
|
|
202
|
+
${saved.description ? html`<p description>${saved.description}</p>` : nothing}
|
|
151
203
|
</section>` : nothing}
|
|
152
|
-
${this.asset ? html`<figure-asset-viewer .asset=${this.asset}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
</dl>${capacity ? html`<p>${i18next.t('figure.text.parts-budget', { triangles: cost!.triangles, groups: cost!.groups, instances: capacity.instances })}</p>` : nothing}
|
|
158
|
-
</section>` : nothing}
|
|
159
|
-
</div>
|
|
160
|
-
<footer><button ?disabled=${!saved} @click=${() => {
|
|
161
|
-
// The modeller shows the figure itself; a preview of it beside the editor only covers the work.
|
|
162
|
-
hideDetail()
|
|
163
|
-
navigate(modellerPathOf(saved))
|
|
164
|
-
}}>${i18next.t('figure.button.detail-edit')}</button></footer>`
|
|
204
|
+
${this.asset ? html`<figure-asset-viewer .asset=${this.asset}
|
|
205
|
+
.keepShot=${saved?.id ? (dataUrl: string) => this.keepThumbnail(saved.id, dataUrl) : undefined}>
|
|
206
|
+
${saved ? html`<figure-facts-list slot="facts" .asset=${this.asset} .row=${saved}></figure-facts-list>` : nothing}
|
|
207
|
+
</figure-asset-viewer>` : nothing}
|
|
208
|
+
</div>`
|
|
165
209
|
}
|
|
166
210
|
}
|
|
167
211
|
|
|
212
|
+
/** The name a board stores: `{namespace}/{type}` (ADR-0114). */
|
|
213
|
+
function fullName(figure: Figure): string {
|
|
214
|
+
return figure.namespace ? `${figure.namespace}/${figure.type}` : figure.type
|
|
215
|
+
}
|
|
216
|
+
|
|
168
217
|
function visibleBar(root: Document | ShadowRoot): Element | undefined {
|
|
169
218
|
for (const element of root.querySelectorAll('*')) {
|
|
170
219
|
if (element.tagName === 'OX-CANVAS-BAR' && element.getBoundingClientRect().height > 0) return element
|
|
@@ -4,6 +4,7 @@ import { css, html, LitElement } from 'lit'
|
|
|
4
4
|
import { customElement, property } from 'lit/decorators.js'
|
|
5
5
|
|
|
6
6
|
import { i18next, localize } from '@operato/i18n'
|
|
7
|
+
import '@things-factory/figure-viewer/dist-client/figure-thumb-mark.js'
|
|
7
8
|
import { getPathInfo } from '@operato/utils'
|
|
8
9
|
|
|
9
10
|
import type { Figure } from '../types.js'
|
|
@@ -67,24 +68,6 @@ export class FigureThumb extends localize(i18next)(LitElement) {
|
|
|
67
68
|
object-fit: contain;
|
|
68
69
|
}
|
|
69
70
|
|
|
70
|
-
/* 아직 그림이 없는 것을 빈 사각형으로 두지 않는다 — 왜 없는지 말한다 */
|
|
71
|
-
div[empty] {
|
|
72
|
-
display: flex;
|
|
73
|
-
flex-direction: column;
|
|
74
|
-
align-items: center;
|
|
75
|
-
justify-content: center;
|
|
76
|
-
gap: var(--spacing-tiny, 4px);
|
|
77
|
-
width: 100%;
|
|
78
|
-
height: 100%;
|
|
79
|
-
font: var(--label-font, inherit);
|
|
80
|
-
font-size: 0.7rem;
|
|
81
|
-
color: var(--md-sys-color-outline);
|
|
82
|
-
}
|
|
83
|
-
div[empty] md-icon {
|
|
84
|
-
--md-icon-size: 26px;
|
|
85
|
-
color: var(--md-sys-color-outline-variant);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
71
|
/*
|
|
89
72
|
초안 표시.
|
|
90
73
|
|
|
@@ -208,10 +191,7 @@ export class FigureThumb extends localize(i18next)(LitElement) {
|
|
|
208
191
|
${src
|
|
209
192
|
? html`<img src=${src} alt=${figure.name || ''} loading="lazy" />`
|
|
210
193
|
: html`
|
|
211
|
-
<
|
|
212
|
-
<md-icon>deployed_code</md-icon>
|
|
213
|
-
${i18next.t('figure.text.thumbnail-not-made-yet')}
|
|
214
|
-
</div>
|
|
194
|
+
<figure-thumb-mark .label=${i18next.t('figure.text.thumbnail-not-made-yet')}></figure-thumb-mark>
|
|
215
195
|
`}
|
|
216
196
|
${figure.state === 'released' ? '' : html`<span draft>${i18next.t('figure.label.draft')}</span>`}
|
|
217
197
|
${figure.tags?.length
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LitElement, type PropertyValues } from 'lit';
|
|
2
2
|
import type { GizmoReach } from './gizmo.js';
|
|
3
3
|
import type { FigureRenderPart } from './renderer.js';
|
|
4
|
-
import { type ViewSettings } from '
|
|
4
|
+
import { type ViewSettings } from '@things-factory/figure-viewer/dist-client/figure-view.js';
|
|
5
5
|
import { type ScaleAnchor } from './stage-model.js';
|
|
6
6
|
export declare class FigureCanvas extends LitElement {
|
|
7
7
|
static styles: import("lit").CSSResult;
|
|
@@ -2,7 +2,7 @@ import { __decorate, __metadata } from "tslib";
|
|
|
2
2
|
import { LitElement, html, css, unsafeCSS } from 'lit';
|
|
3
3
|
import { customElement, property, query } from 'lit/decorators.js';
|
|
4
4
|
import { create, Model, niceGridStep } from '@hatiolab/things-scene';
|
|
5
|
-
import { DEFAULT_VIEW, sceneLook, WORKBENCH } from '
|
|
5
|
+
import { DEFAULT_VIEW, sceneLook, WORKBENCH } from '@things-factory/figure-viewer/dist-client/figure-view.js';
|
|
6
6
|
import { boardFor, changedKeys, componentOf, gizmoResultOf } from './stage-model.js';
|
|
7
7
|
import { JOINT_FAN } from './joint-fan.js';
|
|
8
8
|
import { SLOT_MARK } from './slot-layout-host.js';
|