@things-factory/figure-ui 10.1.208 → 10.1.210
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/data-interface.ts +5 -5
- package/client/modeller/editor.ts +74 -57
- package/client/modeller/fasten-geometry.ts +2 -1
- package/client/modeller/figure-links.ts +26 -120
- package/client/modeller/figure-size-editor.ts +196 -0
- package/client/modeller/joint-drag.ts +25 -21
- package/client/modeller/joint-fan.ts +4 -3
- package/client/modeller/links.ts +36 -24
- package/client/modeller/motion-ends.ts +10 -6
- package/client/modeller/size-response.ts +95 -0
- package/dist-client/modeller/data-interface.d.ts +1 -1
- package/dist-client/modeller/data-interface.js +5 -5
- package/dist-client/modeller/data-interface.js.map +1 -1
- package/dist-client/modeller/editor.d.ts +9 -1
- package/dist-client/modeller/editor.js +80 -58
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/fasten-geometry.js +1 -1
- package/dist-client/modeller/fasten-geometry.js.map +1 -1
- package/dist-client/modeller/figure-links.d.ts +1 -4
- package/dist-client/modeller/figure-links.js +26 -107
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-size-editor.d.ts +27 -0
- package/dist-client/modeller/figure-size-editor.js +221 -0
- package/dist-client/modeller/figure-size-editor.js.map +1 -0
- package/dist-client/modeller/joint-drag.d.ts +1 -1
- package/dist-client/modeller/joint-drag.js +27 -22
- package/dist-client/modeller/joint-drag.js.map +1 -1
- package/dist-client/modeller/joint-fan.js +4 -3
- package/dist-client/modeller/joint-fan.js.map +1 -1
- package/dist-client/modeller/links.d.ts +9 -6
- package/dist-client/modeller/links.js +33 -21
- package/dist-client/modeller/links.js.map +1 -1
- package/dist-client/modeller/motion-ends.d.ts +4 -1
- package/dist-client/modeller/motion-ends.js +10 -6
- package/dist-client/modeller/motion-ends.js.map +1 -1
- package/dist-client/modeller/size-response.d.ts +29 -0
- package/dist-client/modeller/size-response.js +99 -0
- package/dist-client/modeller/size-response.js.map +1 -0
- package/dist-client/route.d.ts +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/docs/evidence/2026-10-24/current-size-panel.png +0 -0
- package/docs/evidence/2026-10-24/integrated-size.png +0 -0
- package/docs/evidence/2026-10-24/multipart-response.png +0 -0
- package/docs/evidence/2026-10-24/repeat-layout.png +0 -0
- package/docs/evidence/2026-10-24/repeat-shared-style.png +0 -0
- package/docs/evidence/2026-10-24/size-in-layout.png +0 -0
- package/docs/evidence/2026-10-24/size-shared-style.png +0 -0
- package/docs/evidence/2026-10-24/width-preview.png +0 -0
- package/docs/multipart-response-review-2026-10-24.md +77 -0
- package/docs/response-authoring-2026-10-24.md +46 -0
- package/docs/size-and-repeat-ux-2026-10-24.md +67 -0
- package/package.json +7 -7
- package/test/attachment-size-contract.test.ts +47 -0
- package/test/browser/acceptance-page.js +1 -1
- package/test/browser/detail-page.js +1 -1
- package/test/browser/detail-tabs-page.js +1 -1
- package/test/browser/editing-page.js +1 -1
- package/test/browser/editing.check.mjs +28 -14
- package/test/browser/links.check.mjs +41 -22
- package/test/browser/modeller-page.js +1 -1
- package/test/browser/modeller-revision.check.mjs +21 -7
- package/test/browser/modeller.check.mjs +51 -39
- package/test/browser/multipart-response-page.js +8 -0
- package/test/browser/parts.check.mjs +2 -1
- package/test/browser/product-page.js +1 -1
- package/test/browser/props.check.mjs +17 -14
- package/test/browser/response-page.js +12 -0
- package/test/browser/row-preview.check.mjs +3 -3
- package/test/browser/screen.check.mjs +57 -13
- package/test/browser/serve-response.mjs +24 -0
- package/test/clip-ai-proposal.test.ts +1 -1
- package/test/clip-consent.test.ts +2 -2
- package/test/command-preview.test.ts +7 -7
- package/test/joint-drag.test.ts +6 -6
- package/test/joint-frames.test.ts +33 -32
- package/test/joints.ts +1 -6
- package/test/links.test.ts +21 -20
- package/test/multipart-response-fixture.js +17 -0
- package/test/multipart-response.test.ts +37 -0
- package/test/refusals.test.ts +2 -2
- package/test/resize-with-placement.test.ts +23 -1
- package/test/size-response.test.ts +49 -0
- package/test/size-source-pairing.test.ts +66 -0
- package/translations/en.json +44 -10
- package/translations/es.json +44 -10
- package/translations/ja.json +44 -10
- package/translations/ko.json +49 -15
- package/translations/ms.json +44 -10
- package/translations/zh.json +44 -10
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { figureAxisPairsOf, figurePartsExtentOf, figureShapeProviderOf } from '@hatiolab/figure-model';
|
|
2
|
+
import { dimensionNow, followOf, followableAxes, measureNow } from './links.js';
|
|
3
|
+
function editOf(asset, part, axis) {
|
|
4
|
+
const shape = asset.document.model.nodes.find(n => n.id === `${part}.shape`);
|
|
5
|
+
const edit = shape && figureShapeProviderOf(shape)?.edit[axis];
|
|
6
|
+
return shape && edit && !('refused' in edit) ? { shape, edit } : undefined;
|
|
7
|
+
}
|
|
8
|
+
export const measureFactor = (asset, part, axis) => editOf(asset, part, axis)?.edit.k ?? 1;
|
|
9
|
+
/** Only expose direct own inputs (including the canonical identity wrapper). Never overwrite an arbitrary expression. */
|
|
10
|
+
export function sizeInputOf(asset, part, axis) {
|
|
11
|
+
const e = editOf(asset, part, axis);
|
|
12
|
+
if (!e)
|
|
13
|
+
return undefined;
|
|
14
|
+
const model = asset.document.model;
|
|
15
|
+
let ref = e.shape.args[e.edit.arg];
|
|
16
|
+
const seen = new Set();
|
|
17
|
+
while (ref && !seen.has(ref)) {
|
|
18
|
+
seen.add(ref);
|
|
19
|
+
if (model.inputs.some(i => i.id === ref && i.role === 'design' && i.unit === 'mm') && ref.startsWith(`${part}.`))
|
|
20
|
+
return ref;
|
|
21
|
+
const writer = model.nodes.find(n => Object.values(n.outputs).includes(ref));
|
|
22
|
+
if (writer?.op !== 'mul@1' || model.constants.find(c => c.id === writer.args[1])?.value !== 1)
|
|
23
|
+
return undefined;
|
|
24
|
+
ref = writer.args[0];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function sizeRelationOf(revision, part, axis) {
|
|
28
|
+
const f = followOf(revision.asset, part, axis);
|
|
29
|
+
if (f.of === 'own')
|
|
30
|
+
return { mode: 'ratio', variable: false };
|
|
31
|
+
if (f.of !== 'instance' && f.of !== 'part')
|
|
32
|
+
return { mode: 'custom', variable: true };
|
|
33
|
+
const source = f.of === 'instance' ? { of: 'instance', axis: f.axis } : { of: 'part', part: f.part, axis: f.axis };
|
|
34
|
+
const equalFactor = (source.of === 'part' ? measureFactor(revision.asset, source.part, source.axis) : 1) / measureFactor(revision.asset, part, axis);
|
|
35
|
+
const mode = !(f.plus ?? 0) ? 'ratio' : Math.abs((f.times ?? 1) - equalFactor) < 1e-6 ? 'difference' : 'custom';
|
|
36
|
+
return { source, mode, variable: true };
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* What a measure follows when it is first made to follow (ADR-0159 3): what the part hangs from, along the axis its own
|
|
40
|
+
* axis lies on as it stands -- a roller laid on its side follows the frame's depth with its length, not the frame's
|
|
41
|
+
* height (the axes paired by figure-model, `figureAxisPairsOf`, never by their letters). On the mounting plane, or
|
|
42
|
+
* fastened to nothing, the figure's size. Nothing when it lies at an angle, or the parent has no measure along that
|
|
43
|
+
* axis: the author picks. Only a suggestion when a relation is made; a measure that already follows something keeps it.
|
|
44
|
+
*/
|
|
45
|
+
export function suggestedSizeSource(asset, part, axis) {
|
|
46
|
+
const { parent, along } = figureAxisPairsOf(asset, part);
|
|
47
|
+
const on = along[axis]?.axis;
|
|
48
|
+
if (!on)
|
|
49
|
+
return undefined;
|
|
50
|
+
if (!parent)
|
|
51
|
+
return { of: 'instance', axis: on };
|
|
52
|
+
return followableAxes(asset, parent).includes(on) ? { of: 'part', part: parent, axis: on } : undefined;
|
|
53
|
+
}
|
|
54
|
+
/** Whether two sources are one: the same part, or the figure, and the same axis. */
|
|
55
|
+
export const sameSizeSource = (a, b) => !!a && !!b && a.of === b.of && a.axis === b.axis && (a.of !== 'part' || (b.of === 'part' && a.part === b.part));
|
|
56
|
+
/** How long the source is now, in millimetres as the panel shows it (a radius read as a diameter). */
|
|
57
|
+
export function sourceMeasureOf(revision, source) {
|
|
58
|
+
if (source.of === 'instance')
|
|
59
|
+
return revision.asset.designInputs[`size.${source.axis}`] ?? figurePartsExtentOf(revision.asset)[source.axis];
|
|
60
|
+
return measureNow(revision, source.part, source.axis);
|
|
61
|
+
}
|
|
62
|
+
/** Preserve the displayed size when choosing a source or mode. mm edits change only that row's relation. */
|
|
63
|
+
export function sizeRelationSteps(revision, part, axis, source, mode, mm = measureNow(revision, part, axis)) {
|
|
64
|
+
if (!(typeof mm === 'number' && Number.isFinite(mm) && mm > 0))
|
|
65
|
+
throw Error('SIZE_VALUE');
|
|
66
|
+
if (source.of === 'part' && source.part === part)
|
|
67
|
+
throw Error('SIZE_SOURCE');
|
|
68
|
+
const asset = revision.asset;
|
|
69
|
+
const steps = [];
|
|
70
|
+
let raw;
|
|
71
|
+
let sourceFactor = 1;
|
|
72
|
+
if (source.of === 'instance') {
|
|
73
|
+
const declared = asset.document.model.inputs.some(i => i.id === `size.${source.axis}` && i.role === 'design');
|
|
74
|
+
if (declared)
|
|
75
|
+
raw = asset.designInputs[`size.${source.axis}`];
|
|
76
|
+
else {
|
|
77
|
+
// Do not replace an existing partial size declaration while configuring an unrelated axis.
|
|
78
|
+
if (asset.document.model.inputs.some(i => /^size\.[xyz]$/.test(i.id)))
|
|
79
|
+
throw Error('SIZE_SOURCE');
|
|
80
|
+
const at = figurePartsExtentOf(asset);
|
|
81
|
+
steps.push({ kind: 'declare-instance-size', at });
|
|
82
|
+
raw = at[source.axis];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
if (!followableAxes(asset, source.part).includes(source.axis))
|
|
87
|
+
throw Error('SIZE_SOURCE');
|
|
88
|
+
raw = dimensionNow(revision, source.part, source.axis);
|
|
89
|
+
sourceFactor = measureFactor(asset, source.part, source.axis);
|
|
90
|
+
}
|
|
91
|
+
if (!(typeof raw === 'number' && raw > 0 && Number.isFinite(raw)))
|
|
92
|
+
throw Error('SIZE_SOURCE');
|
|
93
|
+
const ownFactor = measureFactor(asset, part, axis);
|
|
94
|
+
const times = mode === 'ratio' ? mm / ownFactor / raw : sourceFactor / ownFactor;
|
|
95
|
+
const plus = mode === 'difference' ? (mm - raw * sourceFactor) / ownFactor : 0;
|
|
96
|
+
steps.push({ kind: 'link-dimension', part, axis, source, times, ...(plus ? { plus } : {}), replace: true });
|
|
97
|
+
return steps;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=size-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"size-response.js","sourceRoot":"","sources":["../../client/modeller/size-response.ts"],"names":[],"mappings":"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","sourcesContent":["import { figureAxisPairsOf, figurePartsExtentOf, figureShapeProviderOf } from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureAuthoringAction, FigureDimensionSource } from '@hatiolab/figure-model'\nimport type { FigureRevision } from './revision.js'\nimport { dimensionNow, followOf, followableAxes, measureNow, type Axis } from './links.js'\n\nexport type SizeMode = 'ratio' | 'difference' | 'custom'\nexport type SizeSource = Extract<FigureDimensionSource, { of: 'instance' | 'part' }>\n\nfunction editOf(asset: FigureAsset, part: string, axis: Axis) {\n const shape = asset.document.model.nodes.find(n => n.id === `${part}.shape`)\n const edit = shape && figureShapeProviderOf(shape)?.edit[axis]\n return shape && edit && !('refused' in edit) ? { shape, edit } : undefined\n}\nexport const measureFactor = (asset: FigureAsset, part: string, axis: Axis) => editOf(asset, part, axis)?.edit.k ?? 1\n\n/** Only expose direct own inputs (including the canonical identity wrapper). Never overwrite an arbitrary expression. */\nexport function sizeInputOf(asset: FigureAsset, part: string, axis: Axis): string | undefined {\n const e = editOf(asset, part, axis)\n if (!e) return undefined\n const model = asset.document.model\n let ref = e.shape.args[e.edit.arg]\n const seen = new Set<string>()\n while (ref && !seen.has(ref)) {\n seen.add(ref)\n if (model.inputs.some(i => i.id === ref && i.role === 'design' && i.unit === 'mm') && ref.startsWith(`${part}.`)) return ref\n const writer = model.nodes.find(n => Object.values(n.outputs).includes(ref!))\n if (writer?.op !== 'mul@1' || model.constants.find(c => c.id === writer.args[1])?.value !== 1) return undefined\n ref = writer.args[0]\n }\n}\nexport function sizeRelationOf(revision: FigureRevision, part: string, axis: Axis): { source?: SizeSource; mode: SizeMode; variable: boolean } {\n const f = followOf(revision.asset, part, axis)\n if (f.of === 'own') return { mode: 'ratio', variable: false }\n if (f.of !== 'instance' && f.of !== 'part') return { mode: 'custom', variable: true }\n const source: SizeSource = f.of === 'instance' ? { of: 'instance', axis: f.axis } : { of: 'part', part: f.part, axis: f.axis }\n const equalFactor = (source.of === 'part' ? measureFactor(revision.asset, source.part, source.axis) : 1) / measureFactor(revision.asset, part, axis)\n const mode = !(f.plus ?? 0) ? 'ratio' : Math.abs((f.times ?? 1) - equalFactor) < 1e-6 ? 'difference' : 'custom'\n return { source, mode, variable: true }\n}\n\n/**\n * What a measure follows when it is first made to follow (ADR-0159 3): what the part hangs from, along the axis its own\n * axis lies on as it stands -- a roller laid on its side follows the frame's depth with its length, not the frame's\n * height (the axes paired by figure-model, `figureAxisPairsOf`, never by their letters). On the mounting plane, or\n * fastened to nothing, the figure's size. Nothing when it lies at an angle, or the parent has no measure along that\n * axis: the author picks. Only a suggestion when a relation is made; a measure that already follows something keeps it.\n */\nexport function suggestedSizeSource(asset: FigureAsset, part: string, axis: Axis): SizeSource | undefined {\n const { parent, along } = figureAxisPairsOf(asset, part)\n const on = along[axis]?.axis\n if (!on) return undefined\n if (!parent) return { of: 'instance', axis: on }\n return followableAxes(asset, parent).includes(on) ? { of: 'part', part: parent, axis: on } : undefined\n}\n\n/** Whether two sources are one: the same part, or the figure, and the same axis. */\nexport const sameSizeSource = (a: SizeSource | undefined, b: SizeSource | undefined) =>\n !!a && !!b && a.of === b.of && a.axis === b.axis && (a.of !== 'part' || (b.of === 'part' && a.part === b.part))\n\n/** How long the source is now, in millimetres as the panel shows it (a radius read as a diameter). */\nexport function sourceMeasureOf(revision: FigureRevision, source: SizeSource): number | undefined {\n if (source.of === 'instance') return revision.asset.designInputs[`size.${source.axis}`] ?? figurePartsExtentOf(revision.asset)[source.axis]\n return measureNow(revision, source.part, source.axis)\n}\n\n/** Preserve the displayed size when choosing a source or mode. mm edits change only that row's relation. */\nexport function sizeRelationSteps(revision: FigureRevision, part: string, axis: Axis, source: SizeSource, mode: Exclude<SizeMode, 'custom'>, mm = measureNow(revision, part, axis)): FigureAuthoringAction[] {\n if (!(typeof mm === 'number' && Number.isFinite(mm) && mm > 0)) throw Error('SIZE_VALUE')\n if (source.of === 'part' && source.part === part) throw Error('SIZE_SOURCE')\n const asset = revision.asset\n const steps: FigureAuthoringAction[] = []\n let raw: number | undefined\n let sourceFactor = 1\n if (source.of === 'instance') {\n const declared = asset.document.model.inputs.some(i => i.id === `size.${source.axis}` && i.role === 'design')\n if (declared) raw = asset.designInputs[`size.${source.axis}`]\n else {\n // Do not replace an existing partial size declaration while configuring an unrelated axis.\n if (asset.document.model.inputs.some(i => /^size\\.[xyz]$/.test(i.id))) throw Error('SIZE_SOURCE')\n const at = figurePartsExtentOf(asset)\n steps.push({ kind: 'declare-instance-size', at })\n raw = at[source.axis]\n }\n } else {\n if (!followableAxes(asset, source.part).includes(source.axis)) throw Error('SIZE_SOURCE')\n raw = dimensionNow(revision, source.part, source.axis)\n sourceFactor = measureFactor(asset, source.part, source.axis)\n }\n if (!(typeof raw === 'number' && raw > 0 && Number.isFinite(raw))) throw Error('SIZE_SOURCE')\n const ownFactor = measureFactor(asset, part, axis)\n const times = mode === 'ratio' ? mm / ownFactor / raw : sourceFactor / ownFactor\n const plus = mode === 'difference' ? (mm - raw * sourceFactor) / ownFactor : 0\n steps.push({ kind: 'link-dimension', part, axis, source, times, ...(plus ? { plus } : {}), replace: true })\n return steps\n}\n"]}
|
package/dist-client/route.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default function route(page: string): "figure-
|
|
1
|
+
export default function route(page: string): "figure-list" | "figure-modeller" | "figure-public-list" | undefined;
|