@things-factory/figure-ui 10.1.46 → 10.1.47
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/angle-dial.ts +70 -0
- package/client/modeller/figure-settings.ts +328 -0
- package/client/modeller/figure-v3-capability.ts +137 -0
- package/client/modeller/figure-v3-clips.ts +253 -0
- package/client/modeller/figure-v3-controls.ts +212 -0
- package/client/modeller/figure-v3-links.ts +61 -81
- package/client/modeller/figure-v3-material.ts +108 -35
- package/client/modeller/figure-v3-parts.ts +96 -3
- package/client/modeller/figure-v3-preview.ts +326 -0
- package/client/modeller/figure-v3-properties.ts +29 -57
- package/client/modeller/figure-v3-verdict.ts +598 -60
- package/client/modeller/figure-view.ts +152 -0
- package/client/modeller/side-panel-styles.ts +326 -0
- package/client/modeller/v3-canvas.ts +221 -263
- package/client/modeller/v3-clips.ts +89 -0
- package/client/modeller/v3-controls.ts +54 -0
- package/client/modeller/v3-editor.ts +531 -223
- package/client/modeller/v3-fields.ts +62 -0
- package/client/modeller/v3-help.ts +41 -0
- package/client/modeller/v3-keys.ts +34 -0
- package/client/modeller/v3-links.ts +93 -9
- package/client/modeller/v3-live.ts +79 -0
- package/client/modeller/v3-maturity.ts +415 -0
- package/client/modeller/v3-palette.ts +45 -0
- package/client/modeller/v3-preview-model.ts +54 -0
- package/client/modeller/v3-stage-model.ts +159 -0
- package/client/pages/figure-list-page.ts +4 -4
- package/client/pages/figure-v3-modeller-page.ts +66 -134
- package/dist-client/modeller/angle-dial.d.ts +32 -0
- package/dist-client/modeller/angle-dial.js +41 -0
- package/dist-client/modeller/angle-dial.js.map +1 -0
- package/dist-client/modeller/figure-settings.d.ts +39 -0
- package/dist-client/modeller/figure-settings.js +317 -0
- package/dist-client/modeller/figure-settings.js.map +1 -0
- package/dist-client/modeller/figure-v3-capability.d.ts +22 -0
- package/dist-client/modeller/figure-v3-capability.js +141 -0
- package/dist-client/modeller/figure-v3-capability.js.map +1 -0
- package/dist-client/modeller/figure-v3-clips.d.ts +31 -0
- package/dist-client/modeller/figure-v3-clips.js +268 -0
- package/dist-client/modeller/figure-v3-clips.js.map +1 -0
- package/dist-client/modeller/figure-v3-controls.d.ts +36 -0
- package/dist-client/modeller/figure-v3-controls.js +226 -0
- package/dist-client/modeller/figure-v3-controls.js.map +1 -0
- package/dist-client/modeller/figure-v3-links.d.ts +5 -2
- package/dist-client/modeller/figure-v3-links.js +64 -82
- package/dist-client/modeller/figure-v3-links.js.map +1 -1
- package/dist-client/modeller/figure-v3-material.d.ts +5 -2
- package/dist-client/modeller/figure-v3-material.js +109 -35
- package/dist-client/modeller/figure-v3-material.js.map +1 -1
- package/dist-client/modeller/figure-v3-parts.d.ts +10 -0
- package/dist-client/modeller/figure-v3-parts.js +88 -3
- package/dist-client/modeller/figure-v3-parts.js.map +1 -1
- package/dist-client/modeller/figure-v3-preview.d.ts +34 -0
- package/dist-client/modeller/figure-v3-preview.js +322 -0
- package/dist-client/modeller/figure-v3-preview.js.map +1 -0
- package/dist-client/modeller/figure-v3-properties.d.ts +2 -2
- package/dist-client/modeller/figure-v3-properties.js +29 -57
- package/dist-client/modeller/figure-v3-properties.js.map +1 -1
- package/dist-client/modeller/figure-v3-verdict.d.ts +31 -17
- package/dist-client/modeller/figure-v3-verdict.js +579 -59
- package/dist-client/modeller/figure-v3-verdict.js.map +1 -1
- package/dist-client/modeller/figure-view.d.ts +118 -0
- package/dist-client/modeller/figure-view.js +78 -0
- package/dist-client/modeller/figure-view.js.map +1 -0
- package/dist-client/modeller/side-panel-styles.d.ts +23 -0
- package/dist-client/modeller/side-panel-styles.js +326 -0
- package/dist-client/modeller/side-panel-styles.js.map +1 -0
- package/dist-client/modeller/v3-canvas.d.ts +29 -37
- package/dist-client/modeller/v3-canvas.js +188 -260
- package/dist-client/modeller/v3-canvas.js.map +1 -1
- package/dist-client/modeller/v3-clips.d.ts +39 -0
- package/dist-client/modeller/v3-clips.js +58 -0
- package/dist-client/modeller/v3-clips.js.map +1 -0
- package/dist-client/modeller/v3-controls.d.ts +28 -0
- package/dist-client/modeller/v3-controls.js +28 -0
- package/dist-client/modeller/v3-controls.js.map +1 -0
- package/dist-client/modeller/v3-editor.d.ts +58 -1
- package/dist-client/modeller/v3-editor.js +555 -218
- package/dist-client/modeller/v3-editor.js.map +1 -1
- package/dist-client/modeller/v3-fields.d.ts +30 -0
- package/dist-client/modeller/v3-fields.js +46 -0
- package/dist-client/modeller/v3-fields.js.map +1 -0
- package/dist-client/modeller/v3-help.d.ts +18 -0
- package/dist-client/modeller/v3-help.js +37 -0
- package/dist-client/modeller/v3-help.js.map +1 -0
- package/dist-client/modeller/v3-keys.d.ts +14 -0
- package/dist-client/modeller/v3-keys.js +23 -0
- package/dist-client/modeller/v3-keys.js.map +1 -0
- package/dist-client/modeller/v3-links.d.ts +30 -1
- package/dist-client/modeller/v3-links.js +94 -8
- package/dist-client/modeller/v3-links.js.map +1 -1
- package/dist-client/modeller/v3-live.d.ts +31 -0
- package/dist-client/modeller/v3-live.js +58 -0
- package/dist-client/modeller/v3-live.js.map +1 -0
- package/dist-client/modeller/v3-maturity.d.ts +120 -0
- package/dist-client/modeller/v3-maturity.js +317 -0
- package/dist-client/modeller/v3-maturity.js.map +1 -0
- package/dist-client/modeller/v3-palette.d.ts +7 -0
- package/dist-client/modeller/v3-palette.js +42 -0
- package/dist-client/modeller/v3-palette.js.map +1 -0
- package/dist-client/modeller/v3-preview-model.d.ts +32 -0
- package/dist-client/modeller/v3-preview-model.js +48 -0
- package/dist-client/modeller/v3-preview-model.js.map +1 -0
- package/dist-client/modeller/v3-stage-model.d.ts +31 -0
- package/dist-client/modeller/v3-stage-model.js +121 -0
- package/dist-client/modeller/v3-stage-model.js.map +1 -0
- package/dist-client/pages/figure-list-page.js +4 -4
- package/dist-client/pages/figure-list-page.js.map +1 -1
- package/dist-client/pages/figure-v3-modeller-page.d.ts +2 -6
- package/dist-client/pages/figure-v3-modeller-page.js +64 -136
- package/dist-client/pages/figure-v3-modeller-page.js.map +1 -1
- package/dist-client/tsconfig.chk.tsbuildinfo +1 -0
- package/dist-client/tsconfig.scratch-fm.tsbuildinfo +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/test/v3-clips.test.ts +70 -0
- package/test/v3-controls.test.ts +68 -0
- package/test/v3-fields.test.ts +62 -0
- package/test/v3-gizmo.test.ts +3 -5
- package/test/v3-keys.test.ts +37 -0
- package/test/v3-layout.test.ts +78 -0
- package/test/v3-links.test.ts +77 -6
- package/test/v3-live.test.ts +99 -0
- package/test/v3-material.test.ts +6 -0
- package/test/v3-maturity.test.ts +268 -0
- package/test/v3-parts-wiring.test.ts +3 -1
- package/test/v3-preview.test.ts +42 -0
- package/test/v3-properties.test.ts +4 -2
- package/test/v3-scene-canvas.test.ts +85 -0
- package/test/v3-stage-model.test.ts +25 -0
- package/test/v3-theme.test.ts +16 -25
- package/test/v3-verdict.test.ts +12 -6
- package/test/v3-view.test.ts +20 -0
- package/translations/en.json +84 -5
- package/translations/ja.json +86 -7
- package/translations/ko.json +84 -5
- package/translations/ms.json +86 -7
- package/translations/zh.json +86 -7
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { driverValue } from '@hatiolab/figure-model';
|
|
2
|
+
const round = (n) => Math.round(n * 1000) / 1000;
|
|
3
|
+
export function clipsOf(asset) {
|
|
4
|
+
const inputs = new Map(asset.document.model.inputs.map(i => [i.id, i]));
|
|
5
|
+
const clips = new Map();
|
|
6
|
+
for (const d of asset.drivers ?? []) {
|
|
7
|
+
const input = inputs.get(d.state);
|
|
8
|
+
const clip = clips.get(d.clip) ?? { name: d.clip, duration: d.time.duration, tracks: [] };
|
|
9
|
+
clip.tracks.push({
|
|
10
|
+
state: d.state,
|
|
11
|
+
label: asset.stateInputs?.[d.state]?.label ?? d.state,
|
|
12
|
+
unit: input?.unit ?? '',
|
|
13
|
+
min: input?.min ?? 0,
|
|
14
|
+
max: input?.max ?? 0,
|
|
15
|
+
keys: d.keys.map(k => ({ seconds: round(k.at * d.time.duration), value: k.value })),
|
|
16
|
+
interpolation: d.interpolation,
|
|
17
|
+
loop: d.loop,
|
|
18
|
+
accumulates: d.accumulates
|
|
19
|
+
});
|
|
20
|
+
clips.set(d.clip, clip);
|
|
21
|
+
}
|
|
22
|
+
return [...clips.values()];
|
|
23
|
+
}
|
|
24
|
+
/** The controls no clip plays yet -- the ones a new track can take. One driver per control. */
|
|
25
|
+
export function undrivenOf(asset) {
|
|
26
|
+
const driven = new Set((asset.drivers ?? []).map(d => d.state));
|
|
27
|
+
return asset.document.model.inputs.filter(i => i.role === 'state' && !driven.has(i.id)).map(i => i.id);
|
|
28
|
+
}
|
|
29
|
+
/** The pose a clip gives at a moment, as one batch of state changes -- one step of the history. */
|
|
30
|
+
export function poseAt(asset, clip, seconds) {
|
|
31
|
+
const units = new Map(asset.document.model.inputs.map(i => [i.id, i.unit]));
|
|
32
|
+
return (asset.drivers ?? [])
|
|
33
|
+
.filter((d) => d.clip === clip)
|
|
34
|
+
.map(d => {
|
|
35
|
+
const unit = units.get(d.state);
|
|
36
|
+
return { kind: 'set-state', input: d.state, unit, value: driverValue(d, seconds, unit === 'deg' || unit === 'rad' ? unit : 'other') };
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/** A key added at a moment, replacing one already there; the keys stay in time order. */
|
|
40
|
+
export function withKey(keys, key) {
|
|
41
|
+
return [...keys.filter(k => k.seconds !== key.seconds), key].sort((a, b) => a.seconds - b.seconds);
|
|
42
|
+
}
|
|
43
|
+
/** A track's keys without one; a track keeps at least its two ends, as the format asks. */
|
|
44
|
+
export function withoutKey(keys, index) {
|
|
45
|
+
if (keys.length <= 2 || index === 0)
|
|
46
|
+
return null;
|
|
47
|
+
return keys.filter((_, i) => i !== index);
|
|
48
|
+
}
|
|
49
|
+
/** The edit that writes a track back. */
|
|
50
|
+
export const trackEdit = (clip, track, patch = {}) => ({
|
|
51
|
+
kind: 'set-driver',
|
|
52
|
+
state: track.state,
|
|
53
|
+
clip: clip.name,
|
|
54
|
+
keys: patch.keys ?? track.keys,
|
|
55
|
+
loop: patch.loop ?? track.loop,
|
|
56
|
+
interpolation: patch.interpolation ?? track.interpolation
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=v3-clips.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v3-clips.js","sourceRoot":"","sources":["../../client/modeller/v3-clips.ts"],"names":[],"mappings":"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","sourcesContent":["import { driverValue } from '@hatiolab/figure-model'\nimport type { V3Asset, V3Driver, V3InputChange } from '@hatiolab/figure-model'\n\n/*\n * The figure's clips -- V2's animations: controls played by keys over time, grouped into clips that each run on one\n * clock. Kept apart from the element so the reading is tested without a browser.\n */\nexport interface ClipKey {\n seconds: number\n value: number\n}\nexport interface ClipTrack {\n state: string\n label: string\n unit: string\n min: number\n max: number\n keys: ClipKey[]\n interpolation: 'linear' | 'step'\n loop: 'wrap' | 'hold'\n accumulates: boolean\n}\nexport interface Clip {\n name: string\n duration: number\n tracks: ClipTrack[]\n}\n\nconst round = (n: number) => Math.round(n * 1000) / 1000\n\nexport function clipsOf(asset: V3Asset): Clip[] {\n const inputs = new Map(asset.document.model.inputs.map(i => [i.id, i]))\n const clips = new Map<string, Clip>()\n for (const d of asset.drivers ?? []) {\n const input = inputs.get(d.state)\n const clip = clips.get(d.clip) ?? { name: d.clip, duration: d.time.duration, tracks: [] }\n clip.tracks.push({\n state: d.state,\n label: asset.stateInputs?.[d.state]?.label ?? d.state,\n unit: input?.unit ?? '',\n min: input?.min ?? 0,\n max: input?.max ?? 0,\n keys: d.keys.map(k => ({ seconds: round(k.at * d.time.duration), value: k.value })),\n interpolation: d.interpolation,\n loop: d.loop,\n accumulates: d.accumulates\n })\n clips.set(d.clip, clip)\n }\n return [...clips.values()]\n}\n\n/** The controls no clip plays yet -- the ones a new track can take. One driver per control. */\nexport function undrivenOf(asset: V3Asset): string[] {\n const driven = new Set((asset.drivers ?? []).map(d => d.state))\n return asset.document.model.inputs.filter(i => i.role === 'state' && !driven.has(i.id)).map(i => i.id)\n}\n\n/** The pose a clip gives at a moment, as one batch of state changes -- one step of the history. */\nexport function poseAt(asset: V3Asset, clip: string, seconds: number): V3InputChange[] {\n const units = new Map(asset.document.model.inputs.map(i => [i.id, i.unit]))\n return (asset.drivers ?? [])\n .filter((d: V3Driver) => d.clip === clip)\n .map(d => {\n const unit = units.get(d.state)!\n return { kind: 'set-state' as const, input: d.state, unit, value: driverValue(d, seconds, unit === 'deg' || unit === 'rad' ? unit : 'other') }\n })\n}\n\n/** A key added at a moment, replacing one already there; the keys stay in time order. */\nexport function withKey(keys: readonly ClipKey[], key: ClipKey): ClipKey[] {\n return [...keys.filter(k => k.seconds !== key.seconds), key].sort((a, b) => a.seconds - b.seconds)\n}\n\n/** A track's keys without one; a track keeps at least its two ends, as the format asks. */\nexport function withoutKey(keys: readonly ClipKey[], index: number): ClipKey[] | null {\n if (keys.length <= 2 || index === 0) return null\n return keys.filter((_, i) => i !== index)\n}\n\n/** The edit that writes a track back. */\nexport const trackEdit = (clip: Clip, track: ClipTrack, patch: Partial<Pick<ClipTrack, 'keys' | 'loop' | 'interpolation'>> = {}) => ({\n kind: 'set-driver' as const,\n state: track.state,\n clip: clip.name,\n keys: patch.keys ?? track.keys,\n loop: patch.loop ?? track.loop,\n interpolation: patch.interpolation ?? track.interpolation\n})\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { V3Asset } from '@hatiolab/figure-model';
|
|
2
|
+
export interface Control {
|
|
3
|
+
id: string;
|
|
4
|
+
/** The name a person reads, or the id when none is given. */
|
|
5
|
+
label: string;
|
|
6
|
+
named: boolean;
|
|
7
|
+
unit: string;
|
|
8
|
+
min: number;
|
|
9
|
+
max: number;
|
|
10
|
+
/** Where it stands in the editor now -- the pose being looked at, not yet the default. */
|
|
11
|
+
value: number;
|
|
12
|
+
/** Where it starts when the figure is placed: the default pose. */
|
|
13
|
+
start: number;
|
|
14
|
+
/** Seconds to travel the whole range, 0 when it moves at once. */
|
|
15
|
+
sweep: number;
|
|
16
|
+
/** A slider step: one degree for an angle, else a hundredth of the range. */
|
|
17
|
+
step: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function controlsOf(asset: V3Asset, values?: Record<string, number>): Control[];
|
|
20
|
+
/** Whether the pose being looked at differs from the default pose -- only then is there a pose to keep. */
|
|
21
|
+
export declare const poseDiffers: (controls: readonly Control[]) => boolean;
|
|
22
|
+
/** The current pose as the defaults: one `set-state-defaults` edit. */
|
|
23
|
+
export declare const poseAsDefault: (controls: readonly Control[]) => {
|
|
24
|
+
kind: "set-state-defaults";
|
|
25
|
+
values: {
|
|
26
|
+
[k: string]: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function controlsOf(asset, values = {}) {
|
|
2
|
+
return asset.document.model.inputs
|
|
3
|
+
.filter(input => input.role === 'state')
|
|
4
|
+
.map(input => {
|
|
5
|
+
const policy = asset.stateInputs?.[input.id];
|
|
6
|
+
const start = asset.stateDefaults[input.id] ?? input.min;
|
|
7
|
+
return {
|
|
8
|
+
id: input.id,
|
|
9
|
+
label: policy?.label ?? input.id,
|
|
10
|
+
named: !!policy?.label,
|
|
11
|
+
unit: input.unit,
|
|
12
|
+
min: input.min,
|
|
13
|
+
max: input.max,
|
|
14
|
+
value: values[input.id] ?? start,
|
|
15
|
+
start,
|
|
16
|
+
sweep: policy?.sweep ?? 0,
|
|
17
|
+
step: input.unit === 'deg' ? 1 : (input.max - input.min) / 100
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/** Whether the pose being looked at differs from the default pose -- only then is there a pose to keep. */
|
|
22
|
+
export const poseDiffers = (controls) => controls.some(c => c.value !== c.start);
|
|
23
|
+
/** The current pose as the defaults: one `set-state-defaults` edit. */
|
|
24
|
+
export const poseAsDefault = (controls) => ({
|
|
25
|
+
kind: 'set-state-defaults',
|
|
26
|
+
values: Object.fromEntries(controls.map(c => [c.id, c.value]))
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=v3-controls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v3-controls.js","sourceRoot":"","sources":["../../client/modeller/v3-controls.ts"],"names":[],"mappings":"AAyBA,MAAM,UAAU,UAAU,CAAC,KAAc,EAAE,SAAiC,EAAE;IAC5E,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM;SAC/B,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;SACvC,GAAG,CAAC,KAAK,CAAC,EAAE;QACX,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,GAAG,CAAA;QACxD,OAAO;YACL,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,KAAK,CAAC,EAAE;YAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,KAAK;YAChC,KAAK;YACL,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;YACzB,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG;SAC/D,CAAA;IACH,CAAC,CAAC,CAAA;AACN,CAAC;AAED,2GAA2G;AAC3G,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAA4B,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,CAAC,CAAA;AAEpG,uEAAuE;AACvE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAA4B,EAAE,EAAE,CAAC,CAAC;IAC9D,IAAI,EAAE,oBAA6B;IACnC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;CAC/D,CAAC,CAAA","sourcesContent":["import type { V3Asset } from '@hatiolab/figure-model'\n\n/*\n * The figure's controls -- its state inputs, what V2 called parameters: the values a board or a connector sets to pose\n * the figure (a lift height, a joint angle, a gripper opening). Kept apart from the element so the reading is tested\n * without a browser.\n */\nexport interface Control {\n id: string\n /** The name a person reads, or the id when none is given. */\n label: string\n named: boolean\n unit: string\n min: number\n max: number\n /** Where it stands in the editor now -- the pose being looked at, not yet the default. */\n value: number\n /** Where it starts when the figure is placed: the default pose. */\n start: number\n /** Seconds to travel the whole range, 0 when it moves at once. */\n sweep: number\n /** A slider step: one degree for an angle, else a hundredth of the range. */\n step: number\n}\n\nexport function controlsOf(asset: V3Asset, values: Record<string, number> = {}): Control[] {\n return asset.document.model.inputs\n .filter(input => input.role === 'state')\n .map(input => {\n const policy = asset.stateInputs?.[input.id]\n const start = asset.stateDefaults[input.id] ?? input.min\n return {\n id: input.id,\n label: policy?.label ?? input.id,\n named: !!policy?.label,\n unit: input.unit,\n min: input.min,\n max: input.max,\n value: values[input.id] ?? start,\n start,\n sweep: policy?.sweep ?? 0,\n step: input.unit === 'deg' ? 1 : (input.max - input.min) / 100\n }\n })\n}\n\n/** Whether the pose being looked at differs from the default pose -- only then is there a pose to keep. */\nexport const poseDiffers = (controls: readonly Control[]) => controls.some(c => c.value !== c.start)\n\n/** The current pose as the defaults: one `set-state-defaults` edit. */\nexport const poseAsDefault = (controls: readonly Control[]) => ({\n kind: 'set-state-defaults' as const,\n values: Object.fromEntries(controls.map(c => [c.id, c.value]))\n})\n"]}
|
|
@@ -1,24 +1,57 @@
|
|
|
1
1
|
import { LitElement, type PropertyValues } from 'lit';
|
|
2
|
+
import '@operato/layout';
|
|
2
3
|
import type { V3ProductSession } from './v3-product-session.js';
|
|
3
4
|
import './v3-canvas.js';
|
|
4
5
|
import './figure-v3-parts.js';
|
|
5
6
|
import './figure-v3-material.js';
|
|
6
7
|
import './figure-v3-links.js';
|
|
8
|
+
import './figure-v3-controls.js';
|
|
9
|
+
import './figure-v3-clips.js';
|
|
10
|
+
import './figure-v3-preview.js';
|
|
11
|
+
import './figure-settings.js';
|
|
12
|
+
import './figure-v3-capability.js';
|
|
13
|
+
import type { V3BudgetLine } from './v3-maturity.js';
|
|
7
14
|
/** Product editor surface. The injected session is shared by page persistence and AI commands. */
|
|
8
15
|
export declare class FigureV3Editor extends LitElement {
|
|
9
|
-
static styles: import("lit").CSSResult;
|
|
16
|
+
static styles: import("lit").CSSResult[];
|
|
10
17
|
session?: V3ProductSession;
|
|
11
18
|
revision: number;
|
|
19
|
+
/** The verdict's count, drawn on its tab so it stays in sight while another tab is open (V2's badge). */
|
|
20
|
+
instances?: number;
|
|
21
|
+
/** The cost line the parts list shows, from the maturity report. */
|
|
22
|
+
budget?: V3BudgetLine;
|
|
12
23
|
private selected;
|
|
13
24
|
private error;
|
|
25
|
+
private tab;
|
|
26
|
+
/** The frame the bar folds - found after the first render, since the bar is drawn before it. */
|
|
27
|
+
private panes?;
|
|
28
|
+
/** What the middle shows: the parts being edited, or the figure placed on a board at eight sizes (V2's two modes). */
|
|
29
|
+
private middle;
|
|
30
|
+
/**
|
|
31
|
+
* How the workbench shows the figure -- V2's view settings, the board's own state names. The viewer's, kept in
|
|
32
|
+
* their browser, never in the figure.
|
|
33
|
+
*/
|
|
34
|
+
private view;
|
|
35
|
+
private static storedView;
|
|
36
|
+
private setView;
|
|
14
37
|
/**
|
|
15
38
|
* Parts hidden on the workbench — the author's view while working, not the asset's visibility. Not saved, as in
|
|
16
39
|
* the V2 modeller: a part hidden here is still in the figure, still checked, still drawn on a board.
|
|
17
40
|
*/
|
|
18
41
|
private hiddenParts;
|
|
42
|
+
/** A value in hand -- typed, held on a spinner, scrubbed, dragged -- drawn at once and recorded on release. */
|
|
43
|
+
private live;
|
|
19
44
|
private lastContext;
|
|
45
|
+
/** The modeller's keys (`v3-keys.ts`): undo, redo, duplicate, remove, back to the whole figure. */
|
|
46
|
+
private onKey;
|
|
47
|
+
connectedCallback(): void;
|
|
48
|
+
disconnectedCallback(): void;
|
|
20
49
|
protected willUpdate(_changed: PropertyValues): void;
|
|
21
50
|
private run;
|
|
51
|
+
/** What the canvas draws: the figure with the value in hand when there is one, and without the parts hidden on the workbench. */
|
|
52
|
+
private drawnParts;
|
|
53
|
+
/** A value in hand: an input's value (design or pose) or a part edit. Nothing is recorded. */
|
|
54
|
+
private hold;
|
|
22
55
|
private changed;
|
|
23
56
|
private save;
|
|
24
57
|
private add;
|
|
@@ -46,8 +79,32 @@ export declare class FigureV3Editor extends LitElement {
|
|
|
46
79
|
private renamePart;
|
|
47
80
|
/** Size response, fastening and motion for the selected part (parity ④ ⑤ ⑥), as authoring commands. */
|
|
48
81
|
private renderLinks;
|
|
82
|
+
/** The figure's controls: try a value, name it, set its range and travel time, keep the pose (parity row ⑥). */
|
|
83
|
+
private renderControls;
|
|
49
84
|
/** One command, one step of the history. A refusal a person can meet here is said in their words. */
|
|
50
85
|
private linkCommand;
|
|
51
86
|
private changeField;
|
|
87
|
+
/** Typing or a held spinner: each number on the way is drawn; the field's change records it. */
|
|
88
|
+
private typing;
|
|
89
|
+
/**
|
|
90
|
+
* Drag a field's label (or an axis letter) sideways to scrub its value, as vector tools do: the figure follows the
|
|
91
|
+
* pointer, and the release records one step. The field's number follows too, so the value in hand is always read.
|
|
92
|
+
*/
|
|
93
|
+
private scrub;
|
|
94
|
+
/** The measured range, kept for the revision it was measured at: measuring evaluates the figure at its edges. */
|
|
95
|
+
private range?;
|
|
96
|
+
/** The sizes a board may give the figure, and the way to measure them again after its parts changed. */
|
|
97
|
+
private renderInstanceRange;
|
|
98
|
+
/** Choose a part, from the list, the canvas or a place row. A figure-level tab gives way to the part's properties. */
|
|
99
|
+
private choose;
|
|
100
|
+
private asset;
|
|
101
|
+
private renderTab;
|
|
102
|
+
updated(changed: PropertyValues<this>): void;
|
|
103
|
+
/** Which part the panel speaks of, with the way back to the whole figure. */
|
|
104
|
+
private renderSubject;
|
|
52
105
|
render(): import("lit-html").TemplateResult<1>;
|
|
106
|
+
/** Position, rotation and size as rows of three cells; the shape's own measures one to a line, under their title. */
|
|
107
|
+
private renderGroups;
|
|
108
|
+
private renderVector;
|
|
109
|
+
private renderSingle;
|
|
53
110
|
}
|