@things-factory/figure-ui 10.1.171 → 10.1.174

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.
Files changed (56) hide show
  1. package/client/modeller/editor-styles.ts +11 -3
  2. package/client/modeller/editor.ts +11 -5
  3. package/client/modeller/figure-capability-panel.ts +1 -1
  4. package/client/modeller/figure-controls.ts +2 -2
  5. package/client/modeller/figure-data-panel.ts +1 -1
  6. package/client/modeller/figure-first-save.ts +1 -1
  7. package/client/modeller/figure-history-panel.ts +8 -8
  8. package/client/modeller/figure-parts.ts +35 -13
  9. package/client/modeller/figure-preview.ts +8 -6
  10. package/client/modeller/figure-recipe-catalog.ts +1 -1
  11. package/client/modeller/figure-section-editor.ts +5 -5
  12. package/client/modeller/figure-settings.ts +7 -7
  13. package/client/modeller/figure-verdict.ts +16 -15
  14. package/client/modeller/gate-findings.ts +5 -6
  15. package/client/modeller/group-menu.ts +1 -1
  16. package/client/pages/figure-modeller-page.ts +1 -1
  17. package/client/viewparts/figure-detail-dock.ts +1 -1
  18. package/dist-client/modeller/editor-styles.js +11 -3
  19. package/dist-client/modeller/editor-styles.js.map +1 -1
  20. package/dist-client/modeller/editor.js +11 -5
  21. package/dist-client/modeller/editor.js.map +1 -1
  22. package/dist-client/modeller/figure-capability-panel.js +1 -1
  23. package/dist-client/modeller/figure-capability-panel.js.map +1 -1
  24. package/dist-client/modeller/figure-controls.js +2 -2
  25. package/dist-client/modeller/figure-controls.js.map +1 -1
  26. package/dist-client/modeller/figure-data-panel.js +1 -1
  27. package/dist-client/modeller/figure-data-panel.js.map +1 -1
  28. package/dist-client/modeller/figure-first-save.js +1 -1
  29. package/dist-client/modeller/figure-first-save.js.map +1 -1
  30. package/dist-client/modeller/figure-history-panel.js +8 -8
  31. package/dist-client/modeller/figure-history-panel.js.map +1 -1
  32. package/dist-client/modeller/figure-parts.js +35 -13
  33. package/dist-client/modeller/figure-parts.js.map +1 -1
  34. package/dist-client/modeller/figure-preview.js +8 -6
  35. package/dist-client/modeller/figure-preview.js.map +1 -1
  36. package/dist-client/modeller/figure-recipe-catalog.js +1 -1
  37. package/dist-client/modeller/figure-recipe-catalog.js.map +1 -1
  38. package/dist-client/modeller/figure-section-editor.js +5 -5
  39. package/dist-client/modeller/figure-section-editor.js.map +1 -1
  40. package/dist-client/modeller/figure-settings.js +7 -7
  41. package/dist-client/modeller/figure-settings.js.map +1 -1
  42. package/dist-client/modeller/figure-verdict.js +16 -15
  43. package/dist-client/modeller/figure-verdict.js.map +1 -1
  44. package/dist-client/modeller/gate-findings.js +5 -6
  45. package/dist-client/modeller/gate-findings.js.map +1 -1
  46. package/dist-client/modeller/group-menu.js +1 -1
  47. package/dist-client/modeller/group-menu.js.map +1 -1
  48. package/dist-client/pages/figure-modeller-page.js +1 -1
  49. package/dist-client/pages/figure-modeller-page.js.map +1 -1
  50. package/dist-client/tsconfig.tsbuildinfo +1 -1
  51. package/dist-client/viewparts/figure-detail-dock.js +1 -1
  52. package/dist-client/viewparts/figure-detail-dock.js.map +1 -1
  53. package/package.json +4 -4
  54. package/test/browser/props.check.mjs +17 -0
  55. package/test/browser/screen.check.mjs +24 -0
  56. package/test/type-guard.test.ts +133 -0
@@ -48,7 +48,7 @@ let FigurePreview = class FigurePreview extends localize(i18next)(LitElement) {
48
48
  min-height: 0;
49
49
  overflow: hidden;
50
50
  background-color: ${unsafeCSS(WORKBENCH)};
51
- font-size: 0.76rem;
51
+ font-size: var(--ui-t-small, 11.5px);
52
52
  }
53
53
  div[stage] {
54
54
  position: absolute;
@@ -88,7 +88,7 @@ let FigurePreview = class FigurePreview extends localize(i18next)(LitElement) {
88
88
  color: rgba(255, 255, 255, 0.9);
89
89
  background-color: rgba(28, 28, 30, 0.6);
90
90
  border-radius: 6px;
91
- font-size: 0.72rem;
91
+ font-size: var(--ui-t-micro, 11px);
92
92
  flex-wrap: wrap;
93
93
  max-width: calc(100% - 16px);
94
94
  }
@@ -120,7 +120,7 @@ let FigurePreview = class FigurePreview extends localize(i18next)(LitElement) {
120
120
  color: rgba(255, 255, 255, 0.92);
121
121
  background-color: rgba(28, 28, 30, 0.72);
122
122
  border-radius: 8px;
123
- font-size: 0.72rem;
123
+ font-size: var(--ui-t-micro, 11px);
124
124
  }
125
125
  div[sizes] label {
126
126
  display: grid;
@@ -155,7 +155,7 @@ let FigurePreview = class FigurePreview extends localize(i18next)(LitElement) {
155
155
  color: rgba(255, 255, 255, 0.92);
156
156
  background-color: rgba(28, 28, 30, 0.72);
157
157
  border-radius: 8px;
158
- font-size: 0.72rem;
158
+ font-size: var(--ui-t-micro, 11px);
159
159
  }
160
160
  div[clips] label {
161
161
  display: grid;
@@ -193,7 +193,7 @@ let FigurePreview = class FigurePreview extends localize(i18next)(LitElement) {
193
193
  align-self: stretch;
194
194
  padding: 4px 8px;
195
195
  font: inherit;
196
- font-size: 0.7rem;
196
+ font-size: var(--ui-t-micro, 11px);
197
197
  color: rgba(255, 255, 255, 0.92);
198
198
  background-color: rgba(255, 255, 255, 0.14);
199
199
  border: 1px solid rgba(255, 255, 255, 0.22);
@@ -205,7 +205,7 @@ let FigurePreview = class FigurePreview extends localize(i18next)(LitElement) {
205
205
  }
206
206
  div[clips] span[drive] {
207
207
  opacity: 0.6;
208
- font-size: 0.66rem;
208
+ font-size: var(--ui-t-micro, 11px);
209
209
  }
210
210
  div[clips] input {
211
211
  width: 96px;
@@ -310,6 +310,8 @@ let FigurePreview = class FigurePreview extends localize(i18next)(LitElement) {
310
310
  return;
311
311
  this.way = way;
312
312
  this.standUp();
313
+ /* The content is made again inside the scene standing, which keeps the camera: from one figure to eight it stood inside them. */
314
+ requestAnimationFrame(() => this.fitView());
313
315
  }
314
316
  /** The one figure at another size on an axis, held to what the figure declares, its centre kept on the board's. */
315
317
  tryAxis(axis, value) {
@@ -1 +1 @@
1
- {"version":3,"file":"figure-preview.js","sourceRoot":"","sources":["../../client/modeller/figure-preview.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing, unsafeCSS } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { compileFigureAsset } from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureDataRow, FigureDataValue } from '@hatiolab/figure-model'\nimport { create, registerFigure, unregisterFigure } from '@hatiolab/things-scene'\n\nimport { DEFAULT_VIEW, previewBoardDepth, sceneLook, WORKBENCH, type ViewSettings } from '@things-factory/figure-viewer/dist-client/figure-view.js'\nimport { dialShape } from './angle-dial.js'\nimport { domainOf, motionWrittenByData, typedValueOf, valueRowsOf } from './data-interface.js'\nimport { derivedOf, type FigureRevision } from './revision.js'\nimport { authoredSizeOf, occupancyAtSize, PREVIEW_FACTOR, PREVIEW_WAYS, previewClampsOf, previewInstances, previewOneInstance, previewTypeOf, setupPartOf, sizeRangeOf, sizeWithinRange } from '@things-factory/figure-viewer/dist-client/preview-model.js'\nimport { previewSizeWordsOf } from './preview-size.js'\n\n/**\n * The figure placed on a board.\n *\n * The editing canvas shows the figure at the size it was made. Half of what a figure is lies in how it answers a\n * different size, so here the figure being authored is registered as a board registers it and placed as a\n * `FigureInstance` the author stretches with a slider per axis the figure lets change, its size and its rows' counts\n * said beside it (first 15 minutes, 2026-10-16: eight variants side by side at one scale made a 60 mm roller on a 3 m\n * conveyor a speck). The eight -- the size it was made, and each of the seven ways of growing one, two or three axes\n * twice as large, four to a row -- are a choice in the legend. The board draws them as it will on a real board --\n * placement, lights, environment, the same renderer.\n *\n * The controls: each value that poses the figure with a slider (and a dial for an angle), each clip's\n * speed, and 「이 자세를 기본으로」 to keep the pose as the one it stands in. Nothing here is edited; the canvas edits.\n */\n\ninterface SceneHandle {\n dispose?: () => void\n resize?: () => void\n fit?: (type?: string) => void\n /** The scene's container: it can make the content again while keeping the 3D renderer and the camera (undo and redo use it). */\n rootContainer?: { rebuildContentModel?: (model: unknown, options?: { preserveThreeD?: boolean }) => void }\n root?: {\n set?: (patch: Record<string, unknown>) => void\n fitCameraToModel?: () => void\n components?: { set?: (property: string, value: unknown) => void }[]\n }\n}\n\n@customElement('figure-preview')\nexport class FigurePreview extends localize(i18next)(LitElement) {\n static styles = css`\n :host {\n position: relative;\n display: flex;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n background-color: ${unsafeCSS(WORKBENCH)};\n font-size: 0.76rem;\n }\n div[stage] {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n }\n /*\n The size help and the posing controls share the stage's bottom edge. Each stood in its own corner, so on a narrow\n stage (the 1024 width, both side panels open) the controls lay over the help's button. One row that wraps keeps both\n whole: side by side when there is room, the controls above the help when there is not.\n */\n div[foot] {\n position: absolute;\n left: 8px;\n right: 8px;\n bottom: 8px;\n display: flex;\n flex-wrap: wrap-reverse;\n justify-content: space-between;\n align-items: flex-end;\n gap: 8px;\n pointer-events: none;\n }\n div[foot] > * { pointer-events: auto; }\n div[setup] { max-width: min(320px, 100%); padding: 12px; border-radius: 8px; background: rgba(28,28,30,.9); color: #fff; display: grid; gap: 8px; }\n div[setup] p { margin: 0; line-height: 1.5; }\n div[setup] select, div[setup] button { font: inherit; padding: 8px; min-width: 0; }\n /* Which is which: side by side means nothing without a legend. */\n div[legend] {\n position: absolute;\n top: 8px;\n left: 8px;\n display: flex;\n gap: 6px;\n padding: 4px 8px;\n color: rgba(255, 255, 255, 0.9);\n background-color: rgba(28, 28, 30, 0.6);\n border-radius: 6px;\n font-size: 0.72rem;\n flex-wrap: wrap;\n max-width: calc(100% - 16px);\n }\n /* One figure or eight: two words in the legend, the one shown pressed. */\n div[legend] button[way] {\n padding: 0 6px;\n font: inherit;\n color: inherit;\n background: none;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n opacity: 0.7;\n }\n div[legend] button[way][aria-pressed='true'] {\n opacity: 1;\n background-color: rgba(255, 255, 255, 0.18);\n }\n /* The one figure's size: under the legend, in the controls' look. */\n div[sizes] {\n position: absolute;\n top: 40px;\n left: 8px;\n display: grid;\n gap: 6px;\n padding: 8px 10px;\n max-width: calc(100% - 16px);\n box-sizing: border-box;\n color: rgba(255, 255, 255, 0.92);\n background-color: rgba(28, 28, 30, 0.72);\n border-radius: 8px;\n font-size: 0.72rem;\n }\n div[sizes] label {\n display: grid;\n grid-template-columns: 32px 160px 52px;\n align-items: center;\n gap: 8px;\n }\n div[sizes] input {\n width: 100%;\n accent-color: var(--md-sys-color-primary);\n }\n div[sizes] output {\n font-variant-numeric: tabular-nums;\n text-align: right;\n }\n div[sizes] p[said] {\n margin: 0;\n font-variant-numeric: tabular-nums;\n font-weight: 600;\n }\n /* A variant drawn at another size than it asks: the figure does not declare that size. */\n div[legend] small[clamp] {\n margin-left: 4px;\n color: #ffcc80;\n }\n div[clips] {\n margin-left: auto;\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 8px 10px;\n color: rgba(255, 255, 255, 0.92);\n background-color: rgba(28, 28, 30, 0.72);\n border-radius: 8px;\n font-size: 0.72rem;\n }\n div[clips] label {\n display: grid;\n grid-template-columns: auto 20px 96px 34px;\n align-items: center;\n gap: 8px;\n }\n /* A motion group's clip: as wide as the dial, slider and value together, so its name reads. */\n div[clips] select {\n grid-column: 2 / -1;\n min-width: 0;\n font: inherit;\n color: inherit;\n background-color: rgba(255, 255, 255, 0.14);\n border: 1px solid rgba(255, 255, 255, 0.22);\n border-radius: 5px;\n }\n div[clips] svg[dial] {\n width: 20px;\n height: 20px;\n }\n div[clips] svg[dial] path {\n fill: rgba(255, 255, 255, 0.22);\n }\n div[clips] svg[dial] line {\n stroke: var(--md-sys-color-primary, #7cc6ff);\n stroke-width: 2;\n stroke-linecap: round;\n }\n div[clips] svg[dial] circle {\n fill: none;\n stroke: rgba(255, 255, 255, 0.35);\n }\n div[clips] button[pose] {\n align-self: stretch;\n padding: 4px 8px;\n font: inherit;\n font-size: 0.7rem;\n color: rgba(255, 255, 255, 0.92);\n background-color: rgba(255, 255, 255, 0.14);\n border: 1px solid rgba(255, 255, 255, 0.22);\n border-radius: 5px;\n cursor: pointer;\n }\n div[clips] button[pose]:hover {\n background-color: rgba(255, 255, 255, 0.24);\n }\n div[clips] span[drive] {\n opacity: 0.6;\n font-size: 0.66rem;\n }\n div[clips] input {\n width: 96px;\n accent-color: var(--md-sys-color-primary);\n }\n div[clips] output {\n font-variant-numeric: tabular-nums;\n text-align: right;\n opacity: 0.85;\n }\n div[cannot] {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 12px;\n text-align: center;\n line-height: 1.6;\n color: #f4f4f4;\n background-color: ${unsafeCSS(WORKBENCH)};\n }\n `\n\n /** The figure being authored, as the editor holds it now. */\n @property({ attribute: false }) revision?: FigureRevision\n private get asset(): FigureAsset | undefined {\n return this.revision?.asset\n }\n /** The size the figure was made at, once per version: without a declared size it is measured by evaluating the figure. */\n private authoredSize(): { x: number; y: number; z: number } {\n const shown = this.revision!\n return derivedOf(shown, 'authored-size', () => authoredSizeOf(shown.asset))\n }\n /** Which figure: the type it is registered under here is this one's own, never a real type a board uses. */\n @property() context = ''\n /**\n * In front. Once made, the preview stays standing behind the edit canvas, so coming back to it is not a new 3D scene\n * (about 300 ms): out of sight it does not follow the figure, and when it is shown again it makes its content again\n * inside the scene that stands if the figure changed meanwhile.\n */\n @property({ type: Boolean }) active = true\n private stale = false\n @property({ attribute: false }) view: ViewSettings = DEFAULT_VIEW\n\n @query('div[stage]') private stage!: HTMLDivElement\n @state() private cannot = ''\n /** Clip speeds and control values given here -- the preview's, not the figure's. */\n @state() private driving: Record<string, number> = {}\n @state() private giving: Record<string, number> = {}\n /** Per motion group, the clip played here and how fast (ADR-0051 §3.2) -- the preview's, as a board's \\`motion\\`. */\n @state() private moving: Record<string, { clip: string; speed: number }> = {}\n /** Data values given here by accessor, as a board's saved `figureValues`: what moves a group whose clip or speed the data writes. */\n @state() private valuing: Record<string, FigureDataValue> = {}\n /** Data tried in the data tab: the preview's figures take it as their \\`data\\`, as a board's data source gives it; null when none is. */\n @property({ attribute: false }) sample: unknown = null\n /** The part chosen in the editor. The size help starts on it, so the help speaks of the part the author was working on. */\n @property() selected = ''\n @state() private setupPart = ''\n /** One figure stretched by sliders, or the eight ways of growing side by side. */\n @state() private way: 'one' | 'eight' = 'one'\n /** The size the one figure is tried at; the authored size when the figure stands up. */\n @state() private trying?: { x: number; y: number; z: number }\n private board = { width: 0, height: 0 }\n\n /** What is being tried here now -- clip speeds and control values -- for the AI dock to hear with a request; none when nothing is. */\n tried(): { clips?: Record<string, number>; controls?: Record<string, number> } | undefined {\n const clips = Object.keys(this.driving).length ? { ...this.driving } : undefined\n const controls = Object.keys(this.giving).length ? { ...this.giving } : undefined\n return clips || controls ? { ...(clips ? { clips } : {}), ...(controls ? { controls } : {}) } : undefined\n }\n\n private scene?: SceneHandle\n private standing?: string\n private registered?: string\n private watcher?: ResizeObserver\n\n render() {\n const asset = this.asset\n const controls = asset ? asset.document.model.inputs.filter(i => i.role === 'state') : []\n /* Clips in a motion group are played by the group's choice of clip, not each by its own speed. */\n const grouped = new Set((asset?.motionGroups ?? []).flatMap(g => g.clips))\n const clips = asset ? [...new Set((asset.drivers ?? []).map(d => d.clip))].filter(c => !grouped.has(c)) : []\n let clampsByWay: ReturnType<typeof previewClampsOf> = {}\n try {\n clampsByWay = asset ? previewClampsOf(asset, this.authoredSize()) : {}\n } catch {\n clampsByWay = {}\n }\n /* The part the help speaks of: the one picked in it, else the one chosen in the editor, else the first. */\n const setupPart = setupPartOf(this.setupPart, this.selected, asset?.appearance.map(p => p.target) ?? [])\n return html`<div stage></div>\n ${this.cannot\n ? html`<div cannot>${this.cannot}</div>`\n : html`<div legend>\n ${(['one', 'eight'] as const).map(\n way => html`<button way=${way} aria-pressed=${String(this.way === way)} @click=${() => this.chooseWay(way)}>${i18next.t(`figure.label.preview-way-${way}`)}</button>`\n )}\n ${this.way === 'one' ? nothing : PREVIEW_WAYS.map(way => {\n const clamps = clampsByWay[way.name] ?? []\n return html`<span>\n ${way.axes.length ? way.name : i18next.t('figure.label.preview-base')}\n ${clamps.length\n ? html`<small clamp>${clamps.map(c => i18next.t('figure.text.preview-clamped', { axis: c.axis.toUpperCase(), asked: c.asked.toLocaleString(), used: c.used.toLocaleString() })).join(' · ')}</small>`\n : nothing}\n </span>`\n })}\n </div>\n ${this.way === 'one' && asset && this.trying ? this.renderSizes(asset, this.trying) : nothing}\n <div foot>${asset?.appearance.length ? html`<div setup>\n <p>${i18next.t('figure.text.preview-setup')}</p>\n <select aria-label=${i18next.t('figure.label.resize-part')} @change=${(e: Event) => this.setupPart = (e.target as HTMLSelectElement).value}>\n ${asset.appearance.map(p => html`<option value=${p.target} ?selected=${p.target === setupPart}>${p.target}</option>`)}\n </select>\n <button @click=${() => this.dispatchEvent(new CustomEvent('configure-size', { detail: { part: setupPart }, bubbles: true, composed: true }))}>${i18next.t('figure.button.configure-size')}</button>\n </div>` : nothing}\n ${controls.length + clips.length + (asset?.motionGroups?.length ?? 0) + (asset ? valueRowsOf(asset).length : 0) ? this.renderDrivers(asset!, controls, clips) : nothing}</div>`}`\n }\n\n /** The one figure's size: a slider per axis the figure lets change, and what it is at the size tried. */\n private renderSizes(asset: FigureAsset, size: { x: number; y: number; z: number }) {\n const say = (key: string, params?: Record<string, string>) => i18next.t(key, params)\n /* A board sizes a figure by the space it takes: with none declared, its box folds and no size can be tried. */\n if (!asset.occupancy) return html`<div sizes><p said>${i18next.t('figure.text.preview-needs-space')}</p></div>`\n return html`<div sizes>\n ${(['x', 'y', 'z'] as const).map(axis => {\n const range = sizeRangeOf(asset, axis)\n if (!range) return nothing\n return html`<label>\n <span>${i18next.t(`figure.label.measure-${axis}`)}</span>\n <input type=\"range\" aria-label=${i18next.t(`figure.label.measure-${axis}`)} min=${range.min} max=${range.max} step=\"any\" .value=${String(size[axis])}\n @input=${(e: Event) => this.tryAxis(axis, (e.target as HTMLInputElement).valueAsNumber)}\n @change=${() => this.fitView()} />\n <output>${Math.round(size[axis]).toLocaleString()}</output>\n </label>`\n })}\n <p said>${previewSizeWordsOf(asset, size, say)}</p>\n </div>`\n }\n\n private chooseWay(way: 'one' | 'eight') {\n if (way === this.way) return\n this.way = way\n this.standUp()\n }\n\n /** The one figure at another size on an axis, held to what the figure declares, its centre kept on the board's. */\n private tryAxis(axis: 'x' | 'y' | 'z', value: number) {\n const asset = this.asset\n const used = asset ? sizeWithinRange(asset, axis, value) : undefined\n if (used === undefined || !this.trying) return\n this.trying = { ...this.trying, [axis]: used }\n const instance = this.scene?.root?.components?.[0] as { model?: { width?: number; height?: number }; set(props: Record<string, unknown>): void } | undefined\n /* The instance's box is the space the figure takes at the sizes tried, not the sizes (occupancyAtSize). */\n const box = occupancyAtSize(asset!, this.trying) ?? this.trying\n instance?.set({ width: box.x, depth: box.y, height: box.z })\n const { width = 0, height = 0 } = instance?.model ?? {}\n instance?.set({ left: this.board.width / 2 - width / 2, top: this.board.height / 2 - height / 2 })\n }\n\n /** The figure as stretched, whole in view: done once the slider is let go, so the ground does not slide under a drag. */\n private fitView() {\n this.scene?.fit?.('ratio')\n this.scene?.root?.fitCameraToModel?.()\n }\n\n private renderDrivers(asset: FigureAsset, controls: FigureAsset['document']['model']['inputs'], clips: string[]) {\n const changed = controls.filter(c => this.giving[c.id] !== undefined && this.giving[c.id] !== asset.stateDefaults[c.id])\n return html`<div clips>\n ${changed.length\n ? html`<button pose title=${i18next.t('figure.text.pose-as-default-explained')} @click=${() => this.poseAsDefault()}>\n ${i18next.t('figure.button.pose-as-default')}\n </button>`\n : nothing}\n ${controls.map(control => {\n const value = this.giving[control.id] ?? asset.stateDefaults[control.id] ?? control.min\n const step = Math.max((control.max - control.min) / 100, 0.01)\n const label = asset.stateInputs?.[control.id]?.label ?? control.id\n return html`<label>\n <span>${label} <span drive>${control.unit}</span></span>\n ${this.renderDial(control, value)}\n <input\n type=\"range\"\n min=${control.min}\n max=${control.max}\n step=${step}\n .value=${String(value)}\n @input=${(e: Event) => this.give(control.id, Number((e.target as HTMLInputElement).value))}\n />\n <output>${Math.round(value)}</output>\n </label>`\n })}\n ${clips.map(clip => {\n /*\n A clip nothing has driven stands still, here as on a board: the instances get a speed only from `drive`. The\n slider showed 1.00 over rollers that did not turn (2026-10-03). It shows what plays -- 0 until moved.\n */\n const value = this.driving[clip] ?? 0\n return html`<label>\n <span>${clip} <span drive>${i18next.t('figure.label.playback-speed')}</span></span>\n <span></span>\n <input type=\"range\" min=\"0\" max=\"3\" step=\"0.05\" .value=${String(value)} @input=${(e: Event) => this.drive(clip, Number((e.target as HTMLInputElement).value))} />\n <output>${value.toFixed(2)}</output>\n </label>`\n })}\n ${valueRowsOf(asset).map(row => this.renderDataValue(row))}\n ${(asset.motionGroups ?? []).map(group => {\n const playing = this.moving[group.id] ?? { clip: group.defaultClip, speed: 0 }\n /* A field the data writes wins over the group's own setting, here as on a board: it is moved by the data values above. */\n const byData = motionWrittenByData(asset)[group.id] ?? { clip: false, speed: false }\n return html`${byData.clip\n ? nothing\n : html`<label>\n <span>${group.label} <span drive>${i18next.t('figure.label.clip')}</span></span>\n <select aria-label=${group.label} @change=${(e: Event) => this.move(group.id, { ...playing, clip: (e.target as HTMLSelectElement).value })}>\n ${group.clips.map(c => html`<option value=${c} ?selected=${c === playing.clip}>${c}</option>`)}\n </select>\n </label>`}\n ${byData.speed\n ? nothing\n : html`<label>\n <span>${group.label} <span drive>${i18next.t('figure.label.playback-speed')}</span></span>\n <span></span>\n <input type=\"range\" min=\"0\" max=\"3\" step=\"0.05\" .value=${String(playing.speed)} @input=${(e: Event) => this.move(group.id, { ...playing, speed: Number((e.target as HTMLInputElement).value) })} />\n <output>${playing.speed.toFixed(2)}</output>\n </label>`}`\n })}\n </div>`\n }\n\n /** A value the data's bindings read, as the board's saved values give it: a number on a slider when it has a range, a choice when it is closed. */\n private renderDataValue(row: FigureDataRow) {\n const node = row.node\n const label = row.label ?? row.path\n const fallback = 'default' in node ? node.default : undefined\n const value = this.valuing[row.path] ?? fallback\n if (node.kind === 'number') {\n const ranged = node.min !== undefined && node.max !== undefined && node.max > node.min\n return html`<label>\n <span>${label} <span drive>${node.unit ?? ''}</span></span>\n <span></span>\n ${ranged\n ? html`<input type=\"range\" min=${node.min!} max=${node.max!} step=${Math.max((node.max! - node.min!) / 100, 0.01)} .value=${String(value ?? node.min)} @input=${(e: Event) => this.value(row, (e.target as HTMLInputElement).value)} />\n <output>${value === undefined ? '' : Number(value).toFixed(2)}</output>`\n : html`<input type=\"number\" step=\"any\" .value=${value === undefined ? '' : String(value)} @change=${(e: Event) => this.value(row, (e.target as HTMLInputElement).value)} />\n <span></span>`}\n </label>`\n }\n const domain = domainOf(node)\n if (!domain.length)\n return html`<label>\n <span>${label}</span>\n <input aria-label=${label} .value=${value === undefined ? '' : String(value)} @change=${(e: Event) => this.value(row, (e.target as HTMLInputElement).value)} />\n </label>`\n return html`<label>\n <span>${label}</span>\n <select aria-label=${label} @change=${(e: Event) => this.value(row, (e.target as HTMLSelectElement).value)}>\n ${domain.map(v => html`<option value=${String(v)} ?selected=${v === value}>${typeof v === 'boolean' ? i18next.t(v ? 'figure.label.data-true' : 'figure.label.data-false') : v}</option>`)}\n </select>\n </label>`\n }\n\n private value(row: FigureDataRow, typed: string) {\n const value = typedValueOf(row.node, typed)\n const next = { ...this.valuing }\n if (typeof value === 'number' && Number.isNaN(value)) delete next[row.path]\n else next[row.path] = value\n this.valuing = next\n this.tellInstances('figureValues', this.valuing)\n }\n\n private move(group: string, playing: { clip: string; speed: number }) {\n this.moving = { ...this.moving, [group]: playing }\n this.tellInstances('motion', Object.fromEntries(Object.entries(this.moving).map(([id, m]) => [id, { ...m, paused: false }])))\n }\n\n private renderDial(control: { unit: string; min: number; max: number }, value: number) {\n if (control.unit !== 'deg') return html`<span></span>`\n const dial = dialShape(control.min, control.max, value)\n const span = dial.radius * 2 + 2\n return html`<svg dial viewBox=\"0 0 ${span} ${span}\" aria-hidden=\"true\">\n <path d=${dial.sector}></path>\n <circle cx=${dial.centre.x} cy=${dial.centre.y} r=${dial.radius}></circle>\n <line x1=${dial.centre.x} y1=${dial.centre.y} x2=${dial.needle.x} y2=${dial.needle.y}></line>\n </svg>`\n }\n\n private drive(clip: string, value: number) {\n this.driving = { ...this.driving, [clip]: value }\n this.tellInstances('clips', this.driving)\n }\n\n private give(id: string, value: number) {\n this.giving = { ...this.giving, [id]: value }\n this.tellInstances('parameters', this.giving)\n }\n\n private poseAsDefault() {\n this.dispatchEvent(new CustomEvent('part-edit', { detail: { edit: { kind: 'set-state-defaults', values: { ...this.giving } } }, bubbles: true, composed: true }))\n this.giving = {}\n }\n\n private tellInstances(key: 'clips' | 'parameters' | 'motion' | 'figureValues', values: Record<string, unknown> | null) {\n for (const component of this.scene?.root?.components ?? []) component.set?.(key, values === null ? null : { ...values })\n }\n\n /** The tried data to the figures standing now, as their \\`data\\`: the preview's board is not saved. */\n private tellData(data: unknown) {\n for (const component of this.scene?.root?.components ?? []) component.set?.('data', data === null || data === undefined ? null : structuredClone(data))\n }\n\n\n /** The data sample to the figures standing now. */\n private tellSample() {\n if (this.sample !== null && this.sample !== undefined) this.tellData(this.sample)\n }\n\n willUpdate(changed: Map<string, unknown>) {\n if (changed.has('sample') && this.scene) this.tellData(this.sample)\n if (!this.hasUpdated) return\n if (!this.active) {\n this.stale = true\n return\n }\n if (this.stale || changed.has('active')) {\n this.stale = false\n this.standUp()\n return\n }\n if (changed.has('revision') || changed.has('context')) {\n this.standUp()\n return\n }\n if (!changed.has('view')) return\n const before = changed.get('view') as ViewSettings | undefined\n const now = this.view ?? DEFAULT_VIEW\n if (before?.placement !== now.placement || before?.ceilingHeight !== now.ceilingHeight) this.standUp()\n else this.scene?.root?.set?.(sceneLook(now))\n }\n\n firstUpdated() {\n this.standUp()\n this.watcher = new ResizeObserver(() => {\n if (this.active) this.scene?.resize?.()\n })\n this.watcher.observe(this)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.watcher?.disconnect()\n this.watcher = undefined\n this.teardown()\n }\n\n private standUp() {\n const asset = this.asset\n const view = this.view ?? DEFAULT_VIEW\n if (!asset || !asset.appearance.length) {\n this.cannot = i18next.t('figure.text.preview-needs-a-part')\n this.teardown()\n return\n }\n const signature = JSON.stringify([asset, view.placement, view.ceilingHeight, this.way])\n if (this.scene && this.standing === signature) return\n try {\n compileFigureAsset(asset)\n } catch {\n this.cannot = i18next.t('figure.text.preview-blocked-by-errors')\n this.teardown()\n return\n }\n try {\n /* Registered as a board registers it, under a type of this preview's own: a real type's drawings stay as they are. */\n const type = previewTypeOf(this.context)\n const size = this.authoredSize()\n /*\n The figure changed under a scene that is standing: the same type is registered again and the content made again\n inside the same 3D scene. Making a scene anew costs about a third of a second and its first drawing compiles the\n shaders again -- a value typed beside the preview held the screen for seconds. The scene is made anew only when\n there is none, for another figure, or when the content cannot be made again in place.\n */\n const again = this.scene?.rootContainer?.rebuildContentModel && this.registered === type\n if (!again) this.teardown()\n this.driving = {}\n this.moving = {}\n this.valuing = {}\n registerFigure(type, asset)\n this.registered = type\n /* Each instance stands in the space the figure takes at the size it is asked (occupancyAtSize), as a board reads it. */\n const boxOf = (asked: { x: number; y: number; z: number }) => occupancyAtSize(asset, asked) ?? asked\n const { components, board } = this.way === 'one' ? previewOneInstance(type, boxOf(size)) : previewInstances(type, size, boxOf)\n this.board = board\n this.trying = this.way === 'one' ? { ...size } : undefined\n const model = {\n type: 'model-layer',\n width: board.width,\n height: board.height,\n /* As tall as the figure may grow: twice for the eight, the declared height range's top for the one. */\n depth: previewBoardDepth({ placement: asset.placement, base: { y: size.y } }, view.ceilingHeight, this.way === 'one' ? Math.max(1, (sizeRangeOf(asset, 'y')?.max ?? size.y) / size.y) : PREVIEW_FACTOR),\n threed: true,\n sky: 'color',\n ...sceneLook(view),\n placement: view.placement,\n heights: { floor: 0, ceiling: view.ceilingHeight },\n pixelRatio: Math.min(3, (window.devicePixelRatio || 1) * 2),\n components\n }\n if (again) {\n try {\n this.scene!.rootContainer!.rebuildContentModel!(model, { preserveThreeD: true })\n this.standing = signature\n this.cannot = ''\n this.tellSample()\n return\n } catch {\n this.teardown()\n registerFigure(type, asset)\n this.registered = type\n }\n }\n this.scene = create({\n target: this.stage,\n model,\n mode: 0\n }) as SceneHandle\n this.standing = signature\n this.scene.resize?.()\n this.scene.fit?.('ratio')\n this.scene.root?.fitCameraToModel?.()\n this.cannot = ''\n this.tellSample()\n } catch (error) {\n this.cannot = (error as Error).message\n }\n }\n\n private teardown() {\n this.scene?.dispose?.()\n this.scene = undefined\n this.standing = undefined\n if (this.registered) unregisterFigure(this.registered)\n this.registered = undefined\n }\n}\n"]}
1
+ {"version":3,"file":"figure-preview.js","sourceRoot":"","sources":["../../client/modeller/figure-preview.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing, unsafeCSS } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { compileFigureAsset } from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureDataRow, FigureDataValue } from '@hatiolab/figure-model'\nimport { create, registerFigure, unregisterFigure } from '@hatiolab/things-scene'\n\nimport { DEFAULT_VIEW, previewBoardDepth, sceneLook, WORKBENCH, type ViewSettings } from '@things-factory/figure-viewer/dist-client/figure-view.js'\nimport { dialShape } from './angle-dial.js'\nimport { domainOf, motionWrittenByData, typedValueOf, valueRowsOf } from './data-interface.js'\nimport { derivedOf, type FigureRevision } from './revision.js'\nimport { authoredSizeOf, occupancyAtSize, PREVIEW_FACTOR, PREVIEW_WAYS, previewClampsOf, previewInstances, previewOneInstance, previewTypeOf, setupPartOf, sizeRangeOf, sizeWithinRange } from '@things-factory/figure-viewer/dist-client/preview-model.js'\nimport { previewSizeWordsOf } from './preview-size.js'\n\n/**\n * The figure placed on a board.\n *\n * The editing canvas shows the figure at the size it was made. Half of what a figure is lies in how it answers a\n * different size, so here the figure being authored is registered as a board registers it and placed as a\n * `FigureInstance` the author stretches with a slider per axis the figure lets change, its size and its rows' counts\n * said beside it (first 15 minutes, 2026-10-16: eight variants side by side at one scale made a 60 mm roller on a 3 m\n * conveyor a speck). The eight -- the size it was made, and each of the seven ways of growing one, two or three axes\n * twice as large, four to a row -- are a choice in the legend. The board draws them as it will on a real board --\n * placement, lights, environment, the same renderer.\n *\n * The controls: each value that poses the figure with a slider (and a dial for an angle), each clip's\n * speed, and 「이 자세를 기본으로」 to keep the pose as the one it stands in. Nothing here is edited; the canvas edits.\n */\n\ninterface SceneHandle {\n dispose?: () => void\n resize?: () => void\n fit?: (type?: string) => void\n /** The scene's container: it can make the content again while keeping the 3D renderer and the camera (undo and redo use it). */\n rootContainer?: { rebuildContentModel?: (model: unknown, options?: { preserveThreeD?: boolean }) => void }\n root?: {\n set?: (patch: Record<string, unknown>) => void\n fitCameraToModel?: () => void\n components?: { set?: (property: string, value: unknown) => void }[]\n }\n}\n\n@customElement('figure-preview')\nexport class FigurePreview extends localize(i18next)(LitElement) {\n static styles = css`\n :host {\n position: relative;\n display: flex;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n background-color: ${unsafeCSS(WORKBENCH)};\n font-size: var(--ui-t-small, 11.5px);\n }\n div[stage] {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n }\n /*\n The size help and the posing controls share the stage's bottom edge. Each stood in its own corner, so on a narrow\n stage (the 1024 width, both side panels open) the controls lay over the help's button. One row that wraps keeps both\n whole: side by side when there is room, the controls above the help when there is not.\n */\n div[foot] {\n position: absolute;\n left: 8px;\n right: 8px;\n bottom: 8px;\n display: flex;\n flex-wrap: wrap-reverse;\n justify-content: space-between;\n align-items: flex-end;\n gap: 8px;\n pointer-events: none;\n }\n div[foot] > * { pointer-events: auto; }\n div[setup] { max-width: min(320px, 100%); padding: 12px; border-radius: 8px; background: rgba(28,28,30,.9); color: #fff; display: grid; gap: 8px; }\n div[setup] p { margin: 0; line-height: 1.5; }\n div[setup] select, div[setup] button { font: inherit; padding: 8px; min-width: 0; }\n /* Which is which: side by side means nothing without a legend. */\n div[legend] {\n position: absolute;\n top: 8px;\n left: 8px;\n display: flex;\n gap: 6px;\n padding: 4px 8px;\n color: rgba(255, 255, 255, 0.9);\n background-color: rgba(28, 28, 30, 0.6);\n border-radius: 6px;\n font-size: var(--ui-t-micro, 11px);\n flex-wrap: wrap;\n max-width: calc(100% - 16px);\n }\n /* One figure or eight: two words in the legend, the one shown pressed. */\n div[legend] button[way] {\n padding: 0 6px;\n font: inherit;\n color: inherit;\n background: none;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n opacity: 0.7;\n }\n div[legend] button[way][aria-pressed='true'] {\n opacity: 1;\n background-color: rgba(255, 255, 255, 0.18);\n }\n /* The one figure's size: under the legend, in the controls' look. */\n div[sizes] {\n position: absolute;\n top: 40px;\n left: 8px;\n display: grid;\n gap: 6px;\n padding: 8px 10px;\n max-width: calc(100% - 16px);\n box-sizing: border-box;\n color: rgba(255, 255, 255, 0.92);\n background-color: rgba(28, 28, 30, 0.72);\n border-radius: 8px;\n font-size: var(--ui-t-micro, 11px);\n }\n div[sizes] label {\n display: grid;\n grid-template-columns: 32px 160px 52px;\n align-items: center;\n gap: 8px;\n }\n div[sizes] input {\n width: 100%;\n accent-color: var(--md-sys-color-primary);\n }\n div[sizes] output {\n font-variant-numeric: tabular-nums;\n text-align: right;\n }\n div[sizes] p[said] {\n margin: 0;\n font-variant-numeric: tabular-nums;\n font-weight: 600;\n }\n /* A variant drawn at another size than it asks: the figure does not declare that size. */\n div[legend] small[clamp] {\n margin-left: 4px;\n color: #ffcc80;\n }\n div[clips] {\n margin-left: auto;\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 8px 10px;\n color: rgba(255, 255, 255, 0.92);\n background-color: rgba(28, 28, 30, 0.72);\n border-radius: 8px;\n font-size: var(--ui-t-micro, 11px);\n }\n div[clips] label {\n display: grid;\n grid-template-columns: auto 20px 96px 34px;\n align-items: center;\n gap: 8px;\n }\n /* A motion group's clip: as wide as the dial, slider and value together, so its name reads. */\n div[clips] select {\n grid-column: 2 / -1;\n min-width: 0;\n font: inherit;\n color: inherit;\n background-color: rgba(255, 255, 255, 0.14);\n border: 1px solid rgba(255, 255, 255, 0.22);\n border-radius: 5px;\n }\n div[clips] svg[dial] {\n width: 20px;\n height: 20px;\n }\n div[clips] svg[dial] path {\n fill: rgba(255, 255, 255, 0.22);\n }\n div[clips] svg[dial] line {\n stroke: var(--md-sys-color-primary, #7cc6ff);\n stroke-width: 2;\n stroke-linecap: round;\n }\n div[clips] svg[dial] circle {\n fill: none;\n stroke: rgba(255, 255, 255, 0.35);\n }\n div[clips] button[pose] {\n align-self: stretch;\n padding: 4px 8px;\n font: inherit;\n font-size: var(--ui-t-micro, 11px);\n color: rgba(255, 255, 255, 0.92);\n background-color: rgba(255, 255, 255, 0.14);\n border: 1px solid rgba(255, 255, 255, 0.22);\n border-radius: 5px;\n cursor: pointer;\n }\n div[clips] button[pose]:hover {\n background-color: rgba(255, 255, 255, 0.24);\n }\n div[clips] span[drive] {\n opacity: 0.6;\n font-size: var(--ui-t-micro, 11px);\n }\n div[clips] input {\n width: 96px;\n accent-color: var(--md-sys-color-primary);\n }\n div[clips] output {\n font-variant-numeric: tabular-nums;\n text-align: right;\n opacity: 0.85;\n }\n div[cannot] {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 12px;\n text-align: center;\n line-height: 1.6;\n color: #f4f4f4;\n background-color: ${unsafeCSS(WORKBENCH)};\n }\n `\n\n /** The figure being authored, as the editor holds it now. */\n @property({ attribute: false }) revision?: FigureRevision\n private get asset(): FigureAsset | undefined {\n return this.revision?.asset\n }\n /** The size the figure was made at, once per version: without a declared size it is measured by evaluating the figure. */\n private authoredSize(): { x: number; y: number; z: number } {\n const shown = this.revision!\n return derivedOf(shown, 'authored-size', () => authoredSizeOf(shown.asset))\n }\n /** Which figure: the type it is registered under here is this one's own, never a real type a board uses. */\n @property() context = ''\n /**\n * In front. Once made, the preview stays standing behind the edit canvas, so coming back to it is not a new 3D scene\n * (about 300 ms): out of sight it does not follow the figure, and when it is shown again it makes its content again\n * inside the scene that stands if the figure changed meanwhile.\n */\n @property({ type: Boolean }) active = true\n private stale = false\n @property({ attribute: false }) view: ViewSettings = DEFAULT_VIEW\n\n @query('div[stage]') private stage!: HTMLDivElement\n @state() private cannot = ''\n /** Clip speeds and control values given here -- the preview's, not the figure's. */\n @state() private driving: Record<string, number> = {}\n @state() private giving: Record<string, number> = {}\n /** Per motion group, the clip played here and how fast (ADR-0051 §3.2) -- the preview's, as a board's \\`motion\\`. */\n @state() private moving: Record<string, { clip: string; speed: number }> = {}\n /** Data values given here by accessor, as a board's saved `figureValues`: what moves a group whose clip or speed the data writes. */\n @state() private valuing: Record<string, FigureDataValue> = {}\n /** Data tried in the data tab: the preview's figures take it as their \\`data\\`, as a board's data source gives it; null when none is. */\n @property({ attribute: false }) sample: unknown = null\n /** The part chosen in the editor. The size help starts on it, so the help speaks of the part the author was working on. */\n @property() selected = ''\n @state() private setupPart = ''\n /** One figure stretched by sliders, or the eight ways of growing side by side. */\n @state() private way: 'one' | 'eight' = 'one'\n /** The size the one figure is tried at; the authored size when the figure stands up. */\n @state() private trying?: { x: number; y: number; z: number }\n private board = { width: 0, height: 0 }\n\n /** What is being tried here now -- clip speeds and control values -- for the AI dock to hear with a request; none when nothing is. */\n tried(): { clips?: Record<string, number>; controls?: Record<string, number> } | undefined {\n const clips = Object.keys(this.driving).length ? { ...this.driving } : undefined\n const controls = Object.keys(this.giving).length ? { ...this.giving } : undefined\n return clips || controls ? { ...(clips ? { clips } : {}), ...(controls ? { controls } : {}) } : undefined\n }\n\n private scene?: SceneHandle\n private standing?: string\n private registered?: string\n private watcher?: ResizeObserver\n\n render() {\n const asset = this.asset\n const controls = asset ? asset.document.model.inputs.filter(i => i.role === 'state') : []\n /* Clips in a motion group are played by the group's choice of clip, not each by its own speed. */\n const grouped = new Set((asset?.motionGroups ?? []).flatMap(g => g.clips))\n const clips = asset ? [...new Set((asset.drivers ?? []).map(d => d.clip))].filter(c => !grouped.has(c)) : []\n let clampsByWay: ReturnType<typeof previewClampsOf> = {}\n try {\n clampsByWay = asset ? previewClampsOf(asset, this.authoredSize()) : {}\n } catch {\n clampsByWay = {}\n }\n /* The part the help speaks of: the one picked in it, else the one chosen in the editor, else the first. */\n const setupPart = setupPartOf(this.setupPart, this.selected, asset?.appearance.map(p => p.target) ?? [])\n return html`<div stage></div>\n ${this.cannot\n ? html`<div cannot>${this.cannot}</div>`\n : html`<div legend>\n ${(['one', 'eight'] as const).map(\n way => html`<button way=${way} aria-pressed=${String(this.way === way)} @click=${() => this.chooseWay(way)}>${i18next.t(`figure.label.preview-way-${way}`)}</button>`\n )}\n ${this.way === 'one' ? nothing : PREVIEW_WAYS.map(way => {\n const clamps = clampsByWay[way.name] ?? []\n return html`<span>\n ${way.axes.length ? way.name : i18next.t('figure.label.preview-base')}\n ${clamps.length\n ? html`<small clamp>${clamps.map(c => i18next.t('figure.text.preview-clamped', { axis: c.axis.toUpperCase(), asked: c.asked.toLocaleString(), used: c.used.toLocaleString() })).join(' · ')}</small>`\n : nothing}\n </span>`\n })}\n </div>\n ${this.way === 'one' && asset && this.trying ? this.renderSizes(asset, this.trying) : nothing}\n <div foot>${asset?.appearance.length ? html`<div setup>\n <p>${i18next.t('figure.text.preview-setup')}</p>\n <select aria-label=${i18next.t('figure.label.resize-part')} @change=${(e: Event) => this.setupPart = (e.target as HTMLSelectElement).value}>\n ${asset.appearance.map(p => html`<option value=${p.target} ?selected=${p.target === setupPart}>${p.target}</option>`)}\n </select>\n <button @click=${() => this.dispatchEvent(new CustomEvent('configure-size', { detail: { part: setupPart }, bubbles: true, composed: true }))}>${i18next.t('figure.button.configure-size')}</button>\n </div>` : nothing}\n ${controls.length + clips.length + (asset?.motionGroups?.length ?? 0) + (asset ? valueRowsOf(asset).length : 0) ? this.renderDrivers(asset!, controls, clips) : nothing}</div>`}`\n }\n\n /** The one figure's size: a slider per axis the figure lets change, and what it is at the size tried. */\n private renderSizes(asset: FigureAsset, size: { x: number; y: number; z: number }) {\n const say = (key: string, params?: Record<string, string>) => i18next.t(key, params)\n /* A board sizes a figure by the space it takes: with none declared, its box folds and no size can be tried. */\n if (!asset.occupancy) return html`<div sizes><p said>${i18next.t('figure.text.preview-needs-space')}</p></div>`\n return html`<div sizes>\n ${(['x', 'y', 'z'] as const).map(axis => {\n const range = sizeRangeOf(asset, axis)\n if (!range) return nothing\n return html`<label>\n <span>${i18next.t(`figure.label.measure-${axis}`)}</span>\n <input type=\"range\" aria-label=${i18next.t(`figure.label.measure-${axis}`)} min=${range.min} max=${range.max} step=\"any\" .value=${String(size[axis])}\n @input=${(e: Event) => this.tryAxis(axis, (e.target as HTMLInputElement).valueAsNumber)}\n @change=${() => this.fitView()} />\n <output>${Math.round(size[axis]).toLocaleString()}</output>\n </label>`\n })}\n <p said>${previewSizeWordsOf(asset, size, say)}</p>\n </div>`\n }\n\n private chooseWay(way: 'one' | 'eight') {\n if (way === this.way) return\n this.way = way\n this.standUp()\n /* The content is made again inside the scene standing, which keeps the camera: from one figure to eight it stood inside them. */\n requestAnimationFrame(() => this.fitView())\n }\n\n /** The one figure at another size on an axis, held to what the figure declares, its centre kept on the board's. */\n private tryAxis(axis: 'x' | 'y' | 'z', value: number) {\n const asset = this.asset\n const used = asset ? sizeWithinRange(asset, axis, value) : undefined\n if (used === undefined || !this.trying) return\n this.trying = { ...this.trying, [axis]: used }\n const instance = this.scene?.root?.components?.[0] as { model?: { width?: number; height?: number }; set(props: Record<string, unknown>): void } | undefined\n /* The instance's box is the space the figure takes at the sizes tried, not the sizes (occupancyAtSize). */\n const box = occupancyAtSize(asset!, this.trying) ?? this.trying\n instance?.set({ width: box.x, depth: box.y, height: box.z })\n const { width = 0, height = 0 } = instance?.model ?? {}\n instance?.set({ left: this.board.width / 2 - width / 2, top: this.board.height / 2 - height / 2 })\n }\n\n /** The figure as stretched, whole in view: done once the slider is let go, so the ground does not slide under a drag. */\n private fitView() {\n this.scene?.fit?.('ratio')\n this.scene?.root?.fitCameraToModel?.()\n }\n\n private renderDrivers(asset: FigureAsset, controls: FigureAsset['document']['model']['inputs'], clips: string[]) {\n const changed = controls.filter(c => this.giving[c.id] !== undefined && this.giving[c.id] !== asset.stateDefaults[c.id])\n return html`<div clips>\n ${changed.length\n ? html`<button pose title=${i18next.t('figure.text.pose-as-default-explained')} @click=${() => this.poseAsDefault()}>\n ${i18next.t('figure.button.pose-as-default')}\n </button>`\n : nothing}\n ${controls.map(control => {\n const value = this.giving[control.id] ?? asset.stateDefaults[control.id] ?? control.min\n const step = Math.max((control.max - control.min) / 100, 0.01)\n const label = asset.stateInputs?.[control.id]?.label ?? control.id\n return html`<label>\n <span>${label} <span drive>${control.unit}</span></span>\n ${this.renderDial(control, value)}\n <input\n type=\"range\"\n min=${control.min}\n max=${control.max}\n step=${step}\n .value=${String(value)}\n @input=${(e: Event) => this.give(control.id, Number((e.target as HTMLInputElement).value))}\n />\n <output>${Math.round(value)}</output>\n </label>`\n })}\n ${clips.map(clip => {\n /*\n A clip nothing has driven stands still, here as on a board: the instances get a speed only from `drive`. The\n slider showed 1.00 over rollers that did not turn (2026-10-03). It shows what plays -- 0 until moved.\n */\n const value = this.driving[clip] ?? 0\n return html`<label>\n <span>${clip} <span drive>${i18next.t('figure.label.playback-speed')}</span></span>\n <span></span>\n <input type=\"range\" min=\"0\" max=\"3\" step=\"0.05\" .value=${String(value)} @input=${(e: Event) => this.drive(clip, Number((e.target as HTMLInputElement).value))} />\n <output>${value.toFixed(2)}</output>\n </label>`\n })}\n ${valueRowsOf(asset).map(row => this.renderDataValue(row))}\n ${(asset.motionGroups ?? []).map(group => {\n const playing = this.moving[group.id] ?? { clip: group.defaultClip, speed: 0 }\n /* A field the data writes wins over the group's own setting, here as on a board: it is moved by the data values above. */\n const byData = motionWrittenByData(asset)[group.id] ?? { clip: false, speed: false }\n return html`${byData.clip\n ? nothing\n : html`<label>\n <span>${group.label} <span drive>${i18next.t('figure.label.clip')}</span></span>\n <select aria-label=${group.label} @change=${(e: Event) => this.move(group.id, { ...playing, clip: (e.target as HTMLSelectElement).value })}>\n ${group.clips.map(c => html`<option value=${c} ?selected=${c === playing.clip}>${c}</option>`)}\n </select>\n </label>`}\n ${byData.speed\n ? nothing\n : html`<label>\n <span>${group.label} <span drive>${i18next.t('figure.label.playback-speed')}</span></span>\n <span></span>\n <input type=\"range\" min=\"0\" max=\"3\" step=\"0.05\" .value=${String(playing.speed)} @input=${(e: Event) => this.move(group.id, { ...playing, speed: Number((e.target as HTMLInputElement).value) })} />\n <output>${playing.speed.toFixed(2)}</output>\n </label>`}`\n })}\n </div>`\n }\n\n /** A value the data's bindings read, as the board's saved values give it: a number on a slider when it has a range, a choice when it is closed. */\n private renderDataValue(row: FigureDataRow) {\n const node = row.node\n const label = row.label ?? row.path\n const fallback = 'default' in node ? node.default : undefined\n const value = this.valuing[row.path] ?? fallback\n if (node.kind === 'number') {\n const ranged = node.min !== undefined && node.max !== undefined && node.max > node.min\n return html`<label>\n <span>${label} <span drive>${node.unit ?? ''}</span></span>\n <span></span>\n ${ranged\n ? html`<input type=\"range\" min=${node.min!} max=${node.max!} step=${Math.max((node.max! - node.min!) / 100, 0.01)} .value=${String(value ?? node.min)} @input=${(e: Event) => this.value(row, (e.target as HTMLInputElement).value)} />\n <output>${value === undefined ? '' : Number(value).toFixed(2)}</output>`\n : html`<input type=\"number\" step=\"any\" .value=${value === undefined ? '' : String(value)} @change=${(e: Event) => this.value(row, (e.target as HTMLInputElement).value)} />\n <span></span>`}\n </label>`\n }\n const domain = domainOf(node)\n if (!domain.length)\n return html`<label>\n <span>${label}</span>\n <input aria-label=${label} .value=${value === undefined ? '' : String(value)} @change=${(e: Event) => this.value(row, (e.target as HTMLInputElement).value)} />\n </label>`\n return html`<label>\n <span>${label}</span>\n <select aria-label=${label} @change=${(e: Event) => this.value(row, (e.target as HTMLSelectElement).value)}>\n ${domain.map(v => html`<option value=${String(v)} ?selected=${v === value}>${typeof v === 'boolean' ? i18next.t(v ? 'figure.label.data-true' : 'figure.label.data-false') : v}</option>`)}\n </select>\n </label>`\n }\n\n private value(row: FigureDataRow, typed: string) {\n const value = typedValueOf(row.node, typed)\n const next = { ...this.valuing }\n if (typeof value === 'number' && Number.isNaN(value)) delete next[row.path]\n else next[row.path] = value\n this.valuing = next\n this.tellInstances('figureValues', this.valuing)\n }\n\n private move(group: string, playing: { clip: string; speed: number }) {\n this.moving = { ...this.moving, [group]: playing }\n this.tellInstances('motion', Object.fromEntries(Object.entries(this.moving).map(([id, m]) => [id, { ...m, paused: false }])))\n }\n\n private renderDial(control: { unit: string; min: number; max: number }, value: number) {\n if (control.unit !== 'deg') return html`<span></span>`\n const dial = dialShape(control.min, control.max, value)\n const span = dial.radius * 2 + 2\n return html`<svg dial viewBox=\"0 0 ${span} ${span}\" aria-hidden=\"true\">\n <path d=${dial.sector}></path>\n <circle cx=${dial.centre.x} cy=${dial.centre.y} r=${dial.radius}></circle>\n <line x1=${dial.centre.x} y1=${dial.centre.y} x2=${dial.needle.x} y2=${dial.needle.y}></line>\n </svg>`\n }\n\n private drive(clip: string, value: number) {\n this.driving = { ...this.driving, [clip]: value }\n this.tellInstances('clips', this.driving)\n }\n\n private give(id: string, value: number) {\n this.giving = { ...this.giving, [id]: value }\n this.tellInstances('parameters', this.giving)\n }\n\n private poseAsDefault() {\n this.dispatchEvent(new CustomEvent('part-edit', { detail: { edit: { kind: 'set-state-defaults', values: { ...this.giving } } }, bubbles: true, composed: true }))\n this.giving = {}\n }\n\n private tellInstances(key: 'clips' | 'parameters' | 'motion' | 'figureValues', values: Record<string, unknown> | null) {\n for (const component of this.scene?.root?.components ?? []) component.set?.(key, values === null ? null : { ...values })\n }\n\n /** The tried data to the figures standing now, as their \\`data\\`: the preview's board is not saved. */\n private tellData(data: unknown) {\n for (const component of this.scene?.root?.components ?? []) component.set?.('data', data === null || data === undefined ? null : structuredClone(data))\n }\n\n\n /** The data sample to the figures standing now. */\n private tellSample() {\n if (this.sample !== null && this.sample !== undefined) this.tellData(this.sample)\n }\n\n willUpdate(changed: Map<string, unknown>) {\n if (changed.has('sample') && this.scene) this.tellData(this.sample)\n if (!this.hasUpdated) return\n if (!this.active) {\n this.stale = true\n return\n }\n if (this.stale || changed.has('active')) {\n this.stale = false\n this.standUp()\n return\n }\n if (changed.has('revision') || changed.has('context')) {\n this.standUp()\n return\n }\n if (!changed.has('view')) return\n const before = changed.get('view') as ViewSettings | undefined\n const now = this.view ?? DEFAULT_VIEW\n if (before?.placement !== now.placement || before?.ceilingHeight !== now.ceilingHeight) this.standUp()\n else this.scene?.root?.set?.(sceneLook(now))\n }\n\n firstUpdated() {\n this.standUp()\n this.watcher = new ResizeObserver(() => {\n if (this.active) this.scene?.resize?.()\n })\n this.watcher.observe(this)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.watcher?.disconnect()\n this.watcher = undefined\n this.teardown()\n }\n\n private standUp() {\n const asset = this.asset\n const view = this.view ?? DEFAULT_VIEW\n if (!asset || !asset.appearance.length) {\n this.cannot = i18next.t('figure.text.preview-needs-a-part')\n this.teardown()\n return\n }\n const signature = JSON.stringify([asset, view.placement, view.ceilingHeight, this.way])\n if (this.scene && this.standing === signature) return\n try {\n compileFigureAsset(asset)\n } catch {\n this.cannot = i18next.t('figure.text.preview-blocked-by-errors')\n this.teardown()\n return\n }\n try {\n /* Registered as a board registers it, under a type of this preview's own: a real type's drawings stay as they are. */\n const type = previewTypeOf(this.context)\n const size = this.authoredSize()\n /*\n The figure changed under a scene that is standing: the same type is registered again and the content made again\n inside the same 3D scene. Making a scene anew costs about a third of a second and its first drawing compiles the\n shaders again -- a value typed beside the preview held the screen for seconds. The scene is made anew only when\n there is none, for another figure, or when the content cannot be made again in place.\n */\n const again = this.scene?.rootContainer?.rebuildContentModel && this.registered === type\n if (!again) this.teardown()\n this.driving = {}\n this.moving = {}\n this.valuing = {}\n registerFigure(type, asset)\n this.registered = type\n /* Each instance stands in the space the figure takes at the size it is asked (occupancyAtSize), as a board reads it. */\n const boxOf = (asked: { x: number; y: number; z: number }) => occupancyAtSize(asset, asked) ?? asked\n const { components, board } = this.way === 'one' ? previewOneInstance(type, boxOf(size)) : previewInstances(type, size, boxOf)\n this.board = board\n this.trying = this.way === 'one' ? { ...size } : undefined\n const model = {\n type: 'model-layer',\n width: board.width,\n height: board.height,\n /* As tall as the figure may grow: twice for the eight, the declared height range's top for the one. */\n depth: previewBoardDepth({ placement: asset.placement, base: { y: size.y } }, view.ceilingHeight, this.way === 'one' ? Math.max(1, (sizeRangeOf(asset, 'y')?.max ?? size.y) / size.y) : PREVIEW_FACTOR),\n threed: true,\n sky: 'color',\n ...sceneLook(view),\n placement: view.placement,\n heights: { floor: 0, ceiling: view.ceilingHeight },\n pixelRatio: Math.min(3, (window.devicePixelRatio || 1) * 2),\n components\n }\n if (again) {\n try {\n this.scene!.rootContainer!.rebuildContentModel!(model, { preserveThreeD: true })\n this.standing = signature\n this.cannot = ''\n this.tellSample()\n return\n } catch {\n this.teardown()\n registerFigure(type, asset)\n this.registered = type\n }\n }\n this.scene = create({\n target: this.stage,\n model,\n mode: 0\n }) as SceneHandle\n this.standing = signature\n this.scene.resize?.()\n this.scene.fit?.('ratio')\n this.scene.root?.fitCameraToModel?.()\n this.cannot = ''\n this.tellSample()\n } catch (error) {\n this.cannot = (error as Error).message\n }\n }\n\n private teardown() {\n this.scene?.dispose?.()\n this.scene = undefined\n this.standing = undefined\n if (this.registered) unregisterFigure(this.registered)\n this.registered = undefined\n }\n}\n"]}
@@ -43,7 +43,7 @@ let FigureRecipeCatalog = class FigureRecipeCatalog extends localize(i18next)(Li
43
43
  display: grid;
44
44
  place-items: center;
45
45
  background: color-mix(in srgb, var(--md-sys-color-scrim, #000) 32%, transparent);
46
- font-size: 0.82rem;
46
+ font-size: var(--ui-t-body, 13px);
47
47
  color: var(--md-sys-color-on-surface);
48
48
  }
49
49
  div[panel] {
@@ -1 +1 @@
1
- {"version":3,"file":"figure-recipe-catalog.js","sourceRoot":"","sources":["../../client/modeller/figure-recipe-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/markdown'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { describeFigureRecipe } from '@hatiolab/figure-model'\nimport type { FigureRecipe, FigureRecipeValue } from '@hatiolab/figure-model'\n\nimport { recipeFieldOf, recipeReady, recipeValueOf, recipeWord, recipeWorkings, recipesMatching, type RecipeTemplate } from './recipes.js'\n\n/**\n * The recipe catalog (ADR-0095): the templates the product ships, by category, found by words, each told in full --\n * what it puts in, how many parts, how they move, what each value does, and how to use it -- and put onto the chosen\n * part in one step. The numbers and the ways of moving are worked out from the recipe (`describeFigureRecipe`), so they say\n * what it does; only the descriptions and the guide are written.\n */\n@customElement('figure-recipe-catalog')\nexport class FigureRecipeCatalog extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n position: fixed;\n inset: 0;\n z-index: 20;\n display: grid;\n place-items: center;\n background: color-mix(in srgb, var(--md-sys-color-scrim, #000) 32%, transparent);\n font-size: 0.82rem;\n color: var(--md-sys-color-on-surface);\n }\n div[panel] {\n display: grid;\n grid-template-rows: auto 1fr;\n width: min(1100px, calc(100vw - 32px));\n height: min(720px, calc(100vh - 32px));\n background: var(--md-sys-color-surface);\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 8px 28px rgba(0, 0, 0, 0.28);\n }\n header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n header h2 {\n margin: 0;\n font-size: var(--ui-t-title, 16px);\n flex: 1;\n }\n header input {\n width: 220px;\n padding: 4px 8px;\n font: inherit;\n }\n button[close] {\n display: inline-grid;\n place-items: center;\n width: 32px;\n height: 32px;\n border: none;\n border-radius: 8px;\n background: none;\n color: var(--md-sys-color-on-surface-variant);\n cursor: pointer;\n }\n div[body] {\n display: grid;\n grid-template-columns: 170px minmax(0, 1fr) minmax(300px, 380px);\n min-height: 0;\n }\n @media (max-width: 760px) {\n div[body] {\n grid-template-columns: 1fr;\n overflow: auto;\n }\n }\n nav,\n section[list],\n section[detail] {\n overflow: auto;\n min-height: 0;\n padding: 8px;\n }\n nav {\n border-right: 1px solid var(--md-sys-color-outline-variant);\n }\n section[detail] {\n border-left: 1px solid var(--md-sys-color-outline-variant);\n display: grid;\n gap: 10px;\n align-content: start;\n }\n button[category] {\n display: flex;\n justify-content: space-between;\n width: 100%;\n padding: 6px 8px;\n font: inherit;\n color: inherit;\n background: none;\n border: none;\n border-radius: 6px;\n text-align: left;\n cursor: pointer;\n }\n button[category][on],\n button[card][on] {\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n section[list] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));\n gap: 8px;\n align-content: start;\n }\n button[card] {\n display: grid;\n gap: 4px;\n padding: 8px;\n font: inherit;\n color: inherit;\n text-align: left;\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n cursor: pointer;\n }\n button[card] img {\n width: 100%;\n aspect-ratio: 4 / 3;\n object-fit: contain;\n background: var(--md-sys-color-surface-container);\n border-radius: 4px;\n }\n button[card] small,\n p[muted] {\n color: var(--md-sys-color-on-surface-variant);\n }\n h3 {\n margin: 0;\n font-size: var(--ui-t-body, 14px);\n }\n p {\n margin: 0;\n line-height: 1.5;\n }\n ul {\n margin: 0;\n padding-left: 18px;\n line-height: 1.6;\n }\n table {\n border-collapse: collapse;\n width: 100%;\n }\n th,\n td {\n text-align: left;\n vertical-align: top;\n padding: 3px 4px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n td small {\n display: block;\n color: var(--md-sys-color-on-surface-variant);\n }\n div[form] {\n display: grid;\n gap: 6px;\n padding: 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n }\n div[form] label {\n display: grid;\n gap: 2px;\n }\n div[form] label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n div[form] input,\n div[form] select {\n font: inherit;\n min-width: 0;\n }\n button[insert] {\n justify-self: start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 6px 14px;\n font: inherit;\n white-space: nowrap;\n color: var(--md-sys-color-on-primary);\n background: var(--md-sys-color-primary);\n border: none;\n border-radius: 999em;\n cursor: pointer;\n }\n button[insert]:disabled {\n opacity: 0.38;\n cursor: default;\n }\n p[role='alert'] {\n padding: 6px;\n white-space: pre-wrap;\n color: var(--md-sys-color-on-error-container);\n background: var(--md-sys-color-error-container);\n border-radius: 6px;\n }\n ox-markdown {\n display: block;\n }\n `\n ]\n\n @property({ attribute: false }) templates: RecipeTemplate[] = []\n /** The part it would be put onto. */\n @property({ type: String }) selected = ''\n @property({ type: Boolean }) locked = false\n /** Why the last one put in was refused, in the kernel's words. */\n @property({ type: String }) error = ''\n /** Reads a template's guide; absent, no guide is shown. */\n @property({ attribute: false }) guideOf?: (name: string) => Promise<string>\n /** Where a template's thumbnail is read from; absent, cards show no picture. */\n @property({ attribute: false }) thumbnailOf?: (name: string) => string\n\n @state() private category = ''\n @state() private query = ''\n @state() private chosen = ''\n @state() private values: Record<string, FigureRecipeValue> = {}\n /*\n The guide as a page \\`ox-markdown\\` can read: it renders what its src points to, not text, and given the text it\n fetched it as a path and drew the app's own page in its place (seen on :3300, 2026-09-26). A blob of type\n text/markdown is read as markdown.\n */\n @state() private guide = ''\n\n private set guideText(text: string) {\n if (this.guide) URL.revokeObjectURL(this.guide)\n this.guide = text ? URL.createObjectURL(new Blob([text], { type: 'text/markdown' })) : ''\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.guideText = ''\n }\n\n render() {\n const language = i18next.language || 'en'\n const categories = [...new Set(this.templates.map(t => t.category))].sort()\n const shown = recipesMatching(this.templates, this.category, this.query)\n const chosen = this.templates.find(t => t.name === this.chosen) ?? shown[0]\n return html`<div panel role=\"dialog\" aria-modal=\"true\" aria-label=${i18next.t('figure.label.recipe-catalog')}>\n <header>\n <h2>${i18next.t('figure.label.recipe-catalog')}</h2>\n <input search type=\"search\" placeholder=${i18next.t('figure.text.recipe-search')} .value=${this.query} @input=${(e: Event) => (this.query = (e.target as HTMLInputElement).value)} />\n <button close aria-label=${i18next.t('figure.button.close')} @click=${() => this.dispatchEvent(new CustomEvent('close-catalog', { bubbles: true, composed: true }))}>\n <md-icon>close</md-icon>\n </button>\n </header>\n <div body>\n <nav>\n <button category ?on=${!this.category} @click=${() => (this.category = '')}>\n <span>${i18next.t('figure.label.recipe-all')}</span><small>${this.templates.length}</small>\n </button>\n ${categories.map(\n c => html`<button category=${c} ?on=${this.category === c} @click=${() => (this.category = c)}>\n <span>${i18next.t('figure.label.recipe-category-' + c)}</span><small>${this.templates.filter(t => t.category === c).length}</small>\n </button>`\n )}\n </nav>\n <section list>\n ${shown.map(\n t => html`<button card=${t.name} ?on=${t.name === chosen?.name} @click=${() => this.choose(t)}>\n ${t.hasThumbnail && this.thumbnailOf ? html`<img alt=\"\" loading=\"lazy\" src=${this.thumbnailOf(t.name)} />` : nothing}\n <b>${t.title}</b>\n <small>${t.description}</small>\n </button>`\n )}\n </section>\n <section detail>${chosen ? this.renderDetail(chosen, language) : nothing}</section>\n </div>\n </div>`\n }\n\n private choose(t: RecipeTemplate) {\n if (this.chosen === t.name) return\n this.chosen = t.name\n this.values = Object.fromEntries(t.recipe.params.map(p => [p.name, p.default]))\n this.guideText = ''\n this.guideOf?.(t.name)\n .then(text => this.chosen === t.name && (this.guideText = text))\n .catch(() => {})\n }\n\n protected willUpdate() {\n /*\n The first card shown is chosen while none of those shown is, so the detail is never empty and never of a card the\n search or the category has taken away (the air cylinder stayed told under a search for rollers, :3300, 2026-09-26).\n */\n const shown = recipesMatching(this.templates, this.category, this.query)\n if (!shown.some(t => t.name === this.chosen) && shown[0]) this.choose(shown[0])\n }\n\n private renderDetail(t: RecipeTemplate, language: string) {\n const d = describeFigureRecipe(t.recipe)\n const count = d.parts.min === d.parts.max ? String(d.parts.min) : `${d.parts.min}–${d.parts.max}`\n const ready = recipeReady(t.recipe, this.selected)\n return html`\n <h3>${t.title}</h3>\n <p>${t.description}</p>\n <div>\n <h3>${i18next.t('figure.label.recipe-adds')}</h3>\n <ul>\n <li parts=${count}>${i18next.t(\"figure.text.recipe-parts\", { parts: count })}</li>\n ${recipeWorkings(t.recipe).map(line => html`<li>${i18next.t(line.key, line.words)}</li>`)}\n <li>${i18next.t(t.recipe.target === 'part' ? 'figure.text.recipe-onto-chosen' : 'figure.text.recipe-onto-figure')}</li>\n </ul>\n </div>\n ${t.recipe.params.length ? this.renderForm(t.recipe, language) : nothing}\n ${this.error ? html`<p role=\"alert\">${this.error}</p>` : nothing}\n ${ready ? nothing : html`<p muted>${i18next.t('figure.text.recipe-needs-a-part')}</p>`}\n <button insert ?disabled=${this.locked || !ready} @click=${() => this.dispatchEvent(new CustomEvent('insert-recipe', { detail: { recipe: t.recipe, values: this.values }, bubbles: true, composed: true }))}>\n <md-icon>add</md-icon>${this.selected && t.recipe.target === 'part' ? i18next.t('figure.button.insert-recipe-onto', { part: this.selected }) : i18next.t('figure.button.insert-recipe')}\n </button>\n ${this.guide ? html`<ox-markdown .src=${this.guide}></ox-markdown>` : nothing}\n `\n }\n\n /** Each value: its name, what it does, and the field to set it -- a share typed as a percentage. */\n private renderForm(recipe: FigureRecipe, language: string) {\n const set = (name: string, value: FigureRecipeValue) => (this.values = { ...this.values, [name]: value })\n return html`<div form>\n <h3>${i18next.t('figure.label.recipe-values')}</h3>\n ${recipe.params.map(param => {\n const label = recipeWord(param.label, language) || param.name\n const hint = recipeWord(param.hint, language)\n const value = this.values[param.name] ?? param.default\n const help = hint ? html`<small>${hint}</small>` : nothing\n if (param.kind === 'flag')\n return html`<label toggle><input type=\"checkbox\" param=${param.name} .checked=${value === true} @change=${(e: Event) => set(param.name, (e.target as HTMLInputElement).checked)} />${label}</label>${help}`\n if (param.kind === 'choice' || param.kind === 'face')\n return html`<label><span>${label}</span>\n <select param=${param.name} @change=${(e: Event) => set(param.name, recipeValueOf(param, (e.target as HTMLSelectElement).value))}>\n ${(param.options ?? []).map(o => html`<option value=${String(o)} ?selected=${o === value}>${String(o)}</option>`)}\n </select></label\n >${help}`\n const range = param.kind === 'ratio' ? `${recipeFieldOf(param, param.min ?? 0)}–${recipeFieldOf(param, param.max ?? 1)} %` : `${param.min ?? ''}–${param.max ?? ''} mm`\n return html`<label><span>${label} (${range})</span>\n <input type=\"number\" step=\"any\" param=${param.name} .value=${recipeFieldOf(param, value)} @change=${(e: Event) => set(param.name, recipeValueOf(param, (e.target as HTMLInputElement).value))} /></label\n >${help}`\n })}\n </div>`\n }\n}\n"]}
1
+ {"version":3,"file":"figure-recipe-catalog.js","sourceRoot":"","sources":["../../client/modeller/figure-recipe-catalog.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/markdown'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { describeFigureRecipe } from '@hatiolab/figure-model'\nimport type { FigureRecipe, FigureRecipeValue } from '@hatiolab/figure-model'\n\nimport { recipeFieldOf, recipeReady, recipeValueOf, recipeWord, recipeWorkings, recipesMatching, type RecipeTemplate } from './recipes.js'\n\n/**\n * The recipe catalog (ADR-0095): the templates the product ships, by category, found by words, each told in full --\n * what it puts in, how many parts, how they move, what each value does, and how to use it -- and put onto the chosen\n * part in one step. The numbers and the ways of moving are worked out from the recipe (`describeFigureRecipe`), so they say\n * what it does; only the descriptions and the guide are written.\n */\n@customElement('figure-recipe-catalog')\nexport class FigureRecipeCatalog extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n position: fixed;\n inset: 0;\n z-index: 20;\n display: grid;\n place-items: center;\n background: color-mix(in srgb, var(--md-sys-color-scrim, #000) 32%, transparent);\n font-size: var(--ui-t-body, 13px);\n color: var(--md-sys-color-on-surface);\n }\n div[panel] {\n display: grid;\n grid-template-rows: auto 1fr;\n width: min(1100px, calc(100vw - 32px));\n height: min(720px, calc(100vh - 32px));\n background: var(--md-sys-color-surface);\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 8px 28px rgba(0, 0, 0, 0.28);\n }\n header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n header h2 {\n margin: 0;\n font-size: var(--ui-t-title, 16px);\n flex: 1;\n }\n header input {\n width: 220px;\n padding: 4px 8px;\n font: inherit;\n }\n button[close] {\n display: inline-grid;\n place-items: center;\n width: 32px;\n height: 32px;\n border: none;\n border-radius: 8px;\n background: none;\n color: var(--md-sys-color-on-surface-variant);\n cursor: pointer;\n }\n div[body] {\n display: grid;\n grid-template-columns: 170px minmax(0, 1fr) minmax(300px, 380px);\n min-height: 0;\n }\n @media (max-width: 760px) {\n div[body] {\n grid-template-columns: 1fr;\n overflow: auto;\n }\n }\n nav,\n section[list],\n section[detail] {\n overflow: auto;\n min-height: 0;\n padding: 8px;\n }\n nav {\n border-right: 1px solid var(--md-sys-color-outline-variant);\n }\n section[detail] {\n border-left: 1px solid var(--md-sys-color-outline-variant);\n display: grid;\n gap: 10px;\n align-content: start;\n }\n button[category] {\n display: flex;\n justify-content: space-between;\n width: 100%;\n padding: 6px 8px;\n font: inherit;\n color: inherit;\n background: none;\n border: none;\n border-radius: 6px;\n text-align: left;\n cursor: pointer;\n }\n button[category][on],\n button[card][on] {\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n section[list] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));\n gap: 8px;\n align-content: start;\n }\n button[card] {\n display: grid;\n gap: 4px;\n padding: 8px;\n font: inherit;\n color: inherit;\n text-align: left;\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n cursor: pointer;\n }\n button[card] img {\n width: 100%;\n aspect-ratio: 4 / 3;\n object-fit: contain;\n background: var(--md-sys-color-surface-container);\n border-radius: 4px;\n }\n button[card] small,\n p[muted] {\n color: var(--md-sys-color-on-surface-variant);\n }\n h3 {\n margin: 0;\n font-size: var(--ui-t-body, 14px);\n }\n p {\n margin: 0;\n line-height: 1.5;\n }\n ul {\n margin: 0;\n padding-left: 18px;\n line-height: 1.6;\n }\n table {\n border-collapse: collapse;\n width: 100%;\n }\n th,\n td {\n text-align: left;\n vertical-align: top;\n padding: 3px 4px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n td small {\n display: block;\n color: var(--md-sys-color-on-surface-variant);\n }\n div[form] {\n display: grid;\n gap: 6px;\n padding: 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n }\n div[form] label {\n display: grid;\n gap: 2px;\n }\n div[form] label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n div[form] input,\n div[form] select {\n font: inherit;\n min-width: 0;\n }\n button[insert] {\n justify-self: start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 6px 14px;\n font: inherit;\n white-space: nowrap;\n color: var(--md-sys-color-on-primary);\n background: var(--md-sys-color-primary);\n border: none;\n border-radius: 999em;\n cursor: pointer;\n }\n button[insert]:disabled {\n opacity: 0.38;\n cursor: default;\n }\n p[role='alert'] {\n padding: 6px;\n white-space: pre-wrap;\n color: var(--md-sys-color-on-error-container);\n background: var(--md-sys-color-error-container);\n border-radius: 6px;\n }\n ox-markdown {\n display: block;\n }\n `\n ]\n\n @property({ attribute: false }) templates: RecipeTemplate[] = []\n /** The part it would be put onto. */\n @property({ type: String }) selected = ''\n @property({ type: Boolean }) locked = false\n /** Why the last one put in was refused, in the kernel's words. */\n @property({ type: String }) error = ''\n /** Reads a template's guide; absent, no guide is shown. */\n @property({ attribute: false }) guideOf?: (name: string) => Promise<string>\n /** Where a template's thumbnail is read from; absent, cards show no picture. */\n @property({ attribute: false }) thumbnailOf?: (name: string) => string\n\n @state() private category = ''\n @state() private query = ''\n @state() private chosen = ''\n @state() private values: Record<string, FigureRecipeValue> = {}\n /*\n The guide as a page \\`ox-markdown\\` can read: it renders what its src points to, not text, and given the text it\n fetched it as a path and drew the app's own page in its place (seen on :3300, 2026-09-26). A blob of type\n text/markdown is read as markdown.\n */\n @state() private guide = ''\n\n private set guideText(text: string) {\n if (this.guide) URL.revokeObjectURL(this.guide)\n this.guide = text ? URL.createObjectURL(new Blob([text], { type: 'text/markdown' })) : ''\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.guideText = ''\n }\n\n render() {\n const language = i18next.language || 'en'\n const categories = [...new Set(this.templates.map(t => t.category))].sort()\n const shown = recipesMatching(this.templates, this.category, this.query)\n const chosen = this.templates.find(t => t.name === this.chosen) ?? shown[0]\n return html`<div panel role=\"dialog\" aria-modal=\"true\" aria-label=${i18next.t('figure.label.recipe-catalog')}>\n <header>\n <h2>${i18next.t('figure.label.recipe-catalog')}</h2>\n <input search type=\"search\" placeholder=${i18next.t('figure.text.recipe-search')} .value=${this.query} @input=${(e: Event) => (this.query = (e.target as HTMLInputElement).value)} />\n <button close aria-label=${i18next.t('figure.button.close')} @click=${() => this.dispatchEvent(new CustomEvent('close-catalog', { bubbles: true, composed: true }))}>\n <md-icon>close</md-icon>\n </button>\n </header>\n <div body>\n <nav>\n <button category ?on=${!this.category} @click=${() => (this.category = '')}>\n <span>${i18next.t('figure.label.recipe-all')}</span><small>${this.templates.length}</small>\n </button>\n ${categories.map(\n c => html`<button category=${c} ?on=${this.category === c} @click=${() => (this.category = c)}>\n <span>${i18next.t('figure.label.recipe-category-' + c)}</span><small>${this.templates.filter(t => t.category === c).length}</small>\n </button>`\n )}\n </nav>\n <section list>\n ${shown.map(\n t => html`<button card=${t.name} ?on=${t.name === chosen?.name} @click=${() => this.choose(t)}>\n ${t.hasThumbnail && this.thumbnailOf ? html`<img alt=\"\" loading=\"lazy\" src=${this.thumbnailOf(t.name)} />` : nothing}\n <b>${t.title}</b>\n <small>${t.description}</small>\n </button>`\n )}\n </section>\n <section detail>${chosen ? this.renderDetail(chosen, language) : nothing}</section>\n </div>\n </div>`\n }\n\n private choose(t: RecipeTemplate) {\n if (this.chosen === t.name) return\n this.chosen = t.name\n this.values = Object.fromEntries(t.recipe.params.map(p => [p.name, p.default]))\n this.guideText = ''\n this.guideOf?.(t.name)\n .then(text => this.chosen === t.name && (this.guideText = text))\n .catch(() => {})\n }\n\n protected willUpdate() {\n /*\n The first card shown is chosen while none of those shown is, so the detail is never empty and never of a card the\n search or the category has taken away (the air cylinder stayed told under a search for rollers, :3300, 2026-09-26).\n */\n const shown = recipesMatching(this.templates, this.category, this.query)\n if (!shown.some(t => t.name === this.chosen) && shown[0]) this.choose(shown[0])\n }\n\n private renderDetail(t: RecipeTemplate, language: string) {\n const d = describeFigureRecipe(t.recipe)\n const count = d.parts.min === d.parts.max ? String(d.parts.min) : `${d.parts.min}–${d.parts.max}`\n const ready = recipeReady(t.recipe, this.selected)\n return html`\n <h3>${t.title}</h3>\n <p>${t.description}</p>\n <div>\n <h3>${i18next.t('figure.label.recipe-adds')}</h3>\n <ul>\n <li parts=${count}>${i18next.t(\"figure.text.recipe-parts\", { parts: count })}</li>\n ${recipeWorkings(t.recipe).map(line => html`<li>${i18next.t(line.key, line.words)}</li>`)}\n <li>${i18next.t(t.recipe.target === 'part' ? 'figure.text.recipe-onto-chosen' : 'figure.text.recipe-onto-figure')}</li>\n </ul>\n </div>\n ${t.recipe.params.length ? this.renderForm(t.recipe, language) : nothing}\n ${this.error ? html`<p role=\"alert\">${this.error}</p>` : nothing}\n ${ready ? nothing : html`<p muted>${i18next.t('figure.text.recipe-needs-a-part')}</p>`}\n <button insert ?disabled=${this.locked || !ready} @click=${() => this.dispatchEvent(new CustomEvent('insert-recipe', { detail: { recipe: t.recipe, values: this.values }, bubbles: true, composed: true }))}>\n <md-icon>add</md-icon>${this.selected && t.recipe.target === 'part' ? i18next.t('figure.button.insert-recipe-onto', { part: this.selected }) : i18next.t('figure.button.insert-recipe')}\n </button>\n ${this.guide ? html`<ox-markdown .src=${this.guide}></ox-markdown>` : nothing}\n `\n }\n\n /** Each value: its name, what it does, and the field to set it -- a share typed as a percentage. */\n private renderForm(recipe: FigureRecipe, language: string) {\n const set = (name: string, value: FigureRecipeValue) => (this.values = { ...this.values, [name]: value })\n return html`<div form>\n <h3>${i18next.t('figure.label.recipe-values')}</h3>\n ${recipe.params.map(param => {\n const label = recipeWord(param.label, language) || param.name\n const hint = recipeWord(param.hint, language)\n const value = this.values[param.name] ?? param.default\n const help = hint ? html`<small>${hint}</small>` : nothing\n if (param.kind === 'flag')\n return html`<label toggle><input type=\"checkbox\" param=${param.name} .checked=${value === true} @change=${(e: Event) => set(param.name, (e.target as HTMLInputElement).checked)} />${label}</label>${help}`\n if (param.kind === 'choice' || param.kind === 'face')\n return html`<label><span>${label}</span>\n <select param=${param.name} @change=${(e: Event) => set(param.name, recipeValueOf(param, (e.target as HTMLSelectElement).value))}>\n ${(param.options ?? []).map(o => html`<option value=${String(o)} ?selected=${o === value}>${String(o)}</option>`)}\n </select></label\n >${help}`\n const range = param.kind === 'ratio' ? `${recipeFieldOf(param, param.min ?? 0)}–${recipeFieldOf(param, param.max ?? 1)} %` : `${param.min ?? ''}–${param.max ?? ''} mm`\n return html`<label><span>${label} (${range})</span>\n <input type=\"number\" step=\"any\" param=${param.name} .value=${recipeFieldOf(param, value)} @change=${(e: Event) => set(param.name, recipeValueOf(param, (e.target as HTMLInputElement).value))} /></label\n >${help}`\n })}\n </div>`\n }\n}\n"]}
@@ -137,7 +137,7 @@ let FigureSectionEditor = class FigureSectionEditor extends localize(i18next)(Li
137
137
  font-size: var(--ui-t-body);
138
138
  }
139
139
  header span {
140
- font-size: 0.72rem;
140
+ font-size: var(--ui-t-micro, 11px);
141
141
  color: var(--md-sys-color-on-surface-variant);
142
142
  }
143
143
  nav[tabs] {
@@ -149,7 +149,7 @@ let FigureSectionEditor = class FigureSectionEditor extends localize(i18next)(Li
149
149
  footer button,
150
150
  li button {
151
151
  font: inherit;
152
- font-size: 0.78rem;
152
+ font-size: var(--ui-t-small, 11.5px);
153
153
  min-height: 30px;
154
154
  padding: 0 12px;
155
155
  border-radius: 15px;
@@ -183,7 +183,7 @@ let FigureSectionEditor = class FigureSectionEditor extends localize(i18next)(Li
183
183
  position: absolute;
184
184
  left: 8px;
185
185
  top: 6px;
186
- font-size: 0.68rem;
186
+ font-size: var(--ui-t-micro, 11px);
187
187
  color: var(--md-sys-color-on-surface-variant);
188
188
  pointer-events: none;
189
189
  }
@@ -269,7 +269,7 @@ let FigureSectionEditor = class FigureSectionEditor extends localize(i18next)(Li
269
269
  margin: 8px 0 0;
270
270
  padding: 0 0 0 16px;
271
271
  color: var(--md-sys-color-error);
272
- font-size: 0.76rem;
272
+ font-size: var(--ui-t-small, 11.5px);
273
273
  }
274
274
  small {
275
275
  color: var(--md-sys-color-on-surface-variant);
@@ -283,7 +283,7 @@ let FigureSectionEditor = class FigureSectionEditor extends localize(i18next)(Li
283
283
  }
284
284
  footer span[grow] {
285
285
  flex: 1;
286
- font-size: 0.72rem;
286
+ font-size: var(--ui-t-micro, 11px);
287
287
  color: var(--md-sys-color-on-surface-variant);
288
288
  }
289
289
  footer span[grow][stale] {