@things-factory/figure-library 10.1.161 → 10.1.164

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.
@@ -22,6 +22,8 @@ export declare class FigureReleasesPopup extends FigureReleasesPopup_base {
22
22
  private picked;
23
23
  private saving;
24
24
  private failure;
25
+ /** The tab both columns show: choosing one in a column turns the other to it, so both are compared on one view. */
26
+ private tab;
25
27
  private assets;
26
28
  connectedCallback(): Promise<void>;
27
29
  render(): import("lit-html").TemplateResult<1>;
@@ -81,6 +81,8 @@ let FigureReleasesPopup = class FigureReleasesPopup extends localize(i18next)(Li
81
81
  this.picked = '';
82
82
  this.saving = false;
83
83
  this.failure = '';
84
+ /** The tab both columns show: choosing one in a column turns the other to it, so both are compared on one view. */
85
+ this.tab = 'info';
84
86
  this.assets = new Map();
85
87
  this.save = async () => {
86
88
  this.saving = true;
@@ -115,10 +117,15 @@ let FigureReleasesPopup = class FigureReleasesPopup extends localize(i18next)(Li
115
117
  --popup-min-width: 0;
116
118
  }
117
119
 
120
+ /*
121
+ Each column is as tall as the body, so its canvas stays in view while only its tab's body scrolls (user
122
+ 2026-10-15: a clip played at the bottom of a scrolled column moved a figure no longer seen). Stacked, the body
123
+ scrolls from one column to the next.
124
+ */
118
125
  .body {
119
126
  flex: 1;
120
127
  overflow: auto;
121
- container-type: inline-size;
128
+ container-type: size;
122
129
  }
123
130
 
124
131
  .columns {
@@ -132,11 +139,22 @@ let FigureReleasesPopup = class FigureReleasesPopup extends localize(i18next)(Li
132
139
  display: flex;
133
140
  flex-direction: column;
134
141
  min-width: 0;
142
+ height: 100cqh;
143
+ box-sizing: border-box;
135
144
  border: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));
136
145
  border-radius: var(--ui-r, 10px);
137
146
  background: var(--ui-panel, var(--md-sys-color-surface-container-lowest));
138
147
  }
139
148
 
149
+ section.column > * {
150
+ flex: none;
151
+ }
152
+
153
+ section.column > figure-asset-viewer {
154
+ flex: 1;
155
+ min-height: 0;
156
+ }
157
+
140
158
  section.column[picked] {
141
159
  border-color: var(--ui-accent, var(--md-sys-color-primary));
142
160
  box-shadow: inset 0 0 0 1px var(--ui-accent, var(--md-sys-color-primary));
@@ -316,22 +334,23 @@ let FigureReleasesPopup = class FigureReleasesPopup extends localize(i18next)(Li
316
334
  </span>
317
335
  </div>
318
336
  ${asset
319
- ? html `<figure-asset-viewer .asset=${asset}>
337
+ ? html `<figure-asset-viewer .asset=${asset} .tab=${this.tab} @tab-change=${(e) => (this.tab = e.detail.tab)}>
320
338
  <figure-facts-list slot="facts" .asset=${asset} .row=${{ category: release.category }}></figure-facts-list>
339
+ ${this.renderReleaseFacts(release, 'facts')}
321
340
  </figure-asset-viewer>`
322
- : html `<p class="reason" role="note">${i18next.t('figure-library.text.cannot-use-format', { format: release.assetFormat })}</p>`}
323
- ${this.renderReleaseFacts(release)}
341
+ : html `<p class="reason" role="note">${i18next.t('figure-library.text.cannot-use-format', { format: release.assetFormat })}</p>
342
+ ${this.renderReleaseFacts(release)}`}
324
343
  </section>
325
344
  `;
326
345
  }
327
- renderReleaseFacts(release) {
346
+ renderReleaseFacts(release, slot) {
328
347
  const changes = changesOf(release);
329
348
  const carrier = release.carrierType
330
349
  ? `${release.carrierType}${release.carrierDimensions
331
350
  ? ` · ${release.carrierDimensions.width} × ${release.carrierDimensions.length} × ${release.carrierDimensions.height} mm`
332
351
  : ''}`
333
352
  : null;
334
- return html `<dl class="release">
353
+ return html `<dl class="release" slot=${slot ?? nothing}>
335
354
  ${release.comment ? html `<dt>${i18next.t('figure-library.label.release-note')}</dt><dd>${release.comment}</dd>` : nothing}
336
355
  ${release.version > 1
337
356
  ? html `<dt>${i18next.t('figure-library.text.contract-since', { version: versionText(release.version - 1) })}</dt>
@@ -393,6 +412,10 @@ __decorate([
393
412
  state(),
394
413
  __metadata("design:type", Object)
395
414
  ], FigureReleasesPopup.prototype, "failure", void 0);
415
+ __decorate([
416
+ state(),
417
+ __metadata("design:type", Object)
418
+ ], FigureReleasesPopup.prototype, "tab", void 0);
396
419
  FigureReleasesPopup = __decorate([
397
420
  customElement('figure-releases-popup')
398
421
  ], FigureReleasesPopup);
@@ -1 +1 @@
1
- {"version":3,"file":"figure-releases-popup.js","sourceRoot":"","sources":["../../client/viewparts/figure-releases-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/popup/ox-popup-actions.js'\nimport '@things-factory/figure-viewer/dist-client/figure-asset-viewer.js'\nimport '@things-factory/figure-viewer/dist-client/figure-facts-list.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport type { FigureAsset } from '@hatiolab/figure-model'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { closePopup } from '@operato/popup'\nimport { ButtonStyles, CommonPopupStyles, FormFieldStyles, ScrollbarStyles } from '@operato/styles'\n\nimport { versionText } from './figure-version.js'\nimport { defaultPair, SIDE_BY_SIDE } from './release-pair.js'\n\nconst RELEASES_OF = gql`\n query ($name: String!) {\n figureLibraryReleasesOf(name: $name) {\n id\n name\n ref\n version\n category\n source\n formatSupported\n assetFormat\n kernelVersion\n carrierType\n carrierDimensions\n changes\n deprecated\n supersededBy\n comment\n sourceUrl\n releasedAt\n createdAt\n }\n }\n`\n\nconst CHOOSE = gql`\n mutation ($name: String!, $releaseId: String!) {\n chooseFigureRelease(name: $name, releaseId: $releaseId) {\n name\n }\n }\n`\n\ntype Change = { code?: string; values?: Record<string, unknown>; detail?: string; blocking?: boolean }\n\n/** A time in the reader's language (a bare toLocaleString follows the browser, not the app). */\nconst when = (value?: string | null) => (value ? new Date(value).toLocaleString(i18next.language) : '')\n\n/**\n * A contract change in words. figure-model gives a code and values; `detail` is English for logs and is\n * the sentence only when this module has no words for a new code (open question P8 in figure-library.md).\n */\nconst changeText = (change: Change) =>\n change.code\n ? i18next.t(`figure-library.contract.${change.code}`, { ...(change.values ?? {}), defaultValue: change.detail ?? change.code })\n : change.detail ?? ''\n\n/** The contract changes a release carries against its previous release, as the authoring server measured them. */\nconst changesOf = (release: any): Change[] => {\n try {\n const parsed = release.changes ? JSON.parse(release.changes) : []\n return Array.isArray(parsed) ? parsed : []\n } catch {\n return []\n }\n}\n\n/**\n * Two releases of one figure on live canvases, side by side (ADR-0114, amended 2026-10-12): each drawn as a board draws\n * it, sized within its ranges, posed and played, with what it is and its places beside it -- operato-figure's preview\n * (@things-factory/figure-viewer), not a second one. With more releases, each column picks the release it shows; the\n * one in use and the latest stand first. The operator picks the release the figure draws with and saves; save stays\n * off until the pick differs. A release this server cannot read shows why instead of a canvas and cannot be picked.\n */\n@customElement('figure-releases-popup')\nexport class FigureReleasesPopup extends localize(i18next)(LitElement) {\n static styles = [\n CommonPopupStyles,\n ScrollbarStyles,\n ButtonStyles,\n FormFieldStyles,\n css`\n /*\n The popup takes the overlay's width (a share of the window, all of it on a narrow one) and never more: the two\n columns sit side by side when they have room and stack when they do not, and the actions stay in view.\n */\n :host {\n min-height: 0;\n width: 100%;\n --popup-min-width: 0;\n }\n\n .body {\n flex: 1;\n overflow: auto;\n container-type: inline-size;\n }\n\n .columns {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));\n gap: var(--spacing-large, 12px);\n align-items: start;\n }\n\n section.column {\n display: flex;\n flex-direction: column;\n min-width: 0;\n border: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));\n border-radius: var(--ui-r, 10px);\n background: var(--ui-panel, var(--md-sys-color-surface-container-lowest));\n }\n\n section.column[picked] {\n border-color: var(--ui-accent, var(--md-sys-color-primary));\n box-shadow: inset 0 0 0 1px var(--ui-accent, var(--md-sys-color-primary));\n }\n\n /*\n Side by side, which release a column is stays in view while its facts scroll by. Stacked, each column's canvas\n stands right under its own header and the header leaves with its column (below two columns' width).\n */\n .head {\n position: sticky;\n top: 0;\n z-index: 1;\n border-radius: var(--ui-r, 10px) var(--ui-r, 10px) 0 0;\n background: var(--ui-panel, var(--md-sys-color-surface-container-lowest));\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-small, 4px) var(--spacing-medium, 8px);\n padding: var(--spacing-medium, 8px) 16px;\n border-bottom: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));\n }\n\n @container (max-width: 771px) {\n .head {\n position: static;\n }\n }\n\n .head label {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-small, 4px);\n font-weight: 600;\n }\n\n .head select {\n height: var(--form-element-height-small, 26px);\n min-width: 72px;\n font-size: var(--ui-t-body, 13px);\n }\n\n .head strong {\n font-size: var(--ui-t-title, 15px);\n }\n\n .marks {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-small, 4px);\n }\n\n .mark {\n padding: 0 var(--spacing-medium, 8px);\n border: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));\n border-radius: 999px;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n font-size: var(--ui-t-small, 11.5px);\n white-space: nowrap;\n }\n\n .mark.on {\n border-color: var(--ui-accent, var(--md-sys-color-primary));\n color: var(--ui-accent, var(--md-sys-color-primary));\n font-weight: 600;\n }\n\n .mark.crit {\n color: var(--ui-crit, var(--md-sys-color-error));\n }\n\n .reason {\n margin: 0;\n padding: var(--spacing-huge, 24px) 16px;\n color: var(--ui-crit, var(--md-sys-color-error));\n }\n\n /* The release's own facts (note, dates, source, format, contract change) under the figure's. */\n dl.release {\n display: grid;\n grid-template-columns: 96px minmax(0, 1fr);\n gap: 3px 12px;\n margin: 0;\n padding: 10px 16px;\n line-height: 1.45;\n }\n\n dl.release dt {\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n\n dl.release dd {\n margin: 0;\n overflow-wrap: anywhere;\n }\n\n dl.release dd small {\n display: block;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n\n ul {\n margin: 0;\n padding-left: 1.2em;\n }\n\n li.breaking {\n color: var(--ui-crit, var(--md-sys-color-error));\n }\n\n .finding {\n margin: 0 0 var(--spacing-large, 12px);\n padding-left: var(--spacing-large, 12px);\n border-left: 2px solid var(--ui-crit, var(--md-sys-color-error));\n }\n `\n ]\n\n /** The full figure name. */\n @property() name = ''\n /** The id of the release it draws with now; '' when nothing is in use. */\n @property() drawing = ''\n\n @state() private releases: any[] = []\n /** The release each column shows, by id. */\n @state() private shown: string[] = []\n @state() private picked = ''\n @state() private saving = false\n @state() private failure = ''\n\n private assets = new Map<string, FigureAsset | null>()\n\n async connectedCallback() {\n super.connectedCallback()\n this.picked = this.drawing\n const response = await client.query({ query: RELEASES_OF, variables: { name: this.name }, fetchPolicy: 'network-only' })\n this.releases = response.data?.figureLibraryReleasesOf ?? []\n this.shown = defaultPair(this.releases, this.drawing)\n }\n\n render() {\n const changed = !!this.picked && this.picked !== this.drawing\n const byId = new Map(this.releases.map(release => [release.id, release]))\n\n return html`\n <div class=\"body\">\n ${this.failure ? html`<p class=\"finding\" role=\"alert\">${this.failure}</p>` : nothing}\n <div class=\"columns\">\n ${this.shown.map((id, column) => (byId.get(id) ? this.renderColumn(byId.get(id), column) : nothing))}\n </div>\n </div>\n <ox-popup-actions>\n <button slot=\"cancel\" @click=${() => closePopup(this)}>${i18next.t('figure-library.button.cancel')}</button>\n <button slot=\"confirm\" raised ?disabled=${!changed || this.saving} @click=${this.save}>${i18next.t('figure-library.button.save')}</button>\n </ox-popup-actions>\n `\n }\n\n private assetOf(release: any): FigureAsset | null {\n if (!this.assets.has(release.id)) {\n let asset: FigureAsset | null = null\n try {\n asset = release.formatSupported ? (JSON.parse(release.source) as FigureAsset) : null\n } catch {\n asset = null\n }\n this.assets.set(release.id, asset)\n }\n return this.assets.get(release.id)!\n }\n\n private renderColumn(release: any, column: number) {\n const picked = release.id === this.picked\n /* A release this server cannot read is never used: it is shown, not picked (ADR-0114, amended 2026-10-12). */\n const asset = this.assetOf(release)\n const unusable = !asset\n const latest = release.id === this.releases[0]?.id\n const choosable = this.releases.length > SIDE_BY_SIDE\n\n return html`\n <section class=\"column\" ?picked=${picked}>\n <div class=\"head\">\n <label>\n <input type=\"radio\" name=\"release\" .checked=${picked} ?disabled=${unusable} @change=${() => (this.picked = release.id)} />\n ${choosable\n ? html`<select aria-label=${i18next.t('figure-library.label.release-shown')} @change=${(e: Event) => this.show(column, (e.target as HTMLSelectElement).value)}>\n ${this.releases.map(\n other => html`<option value=${other.id} ?selected=${other.id === release.id}>${versionText(other.version)}</option>`\n )}\n </select>`\n : html`<strong>${versionText(release.version)}</strong>`}\n </label>\n <span class=\"marks\">\n ${release.id === this.drawing ? html`<span class=\"mark on\">${i18next.t('figure-library.text.in-use')}</span>` : nothing}\n ${latest ? html`<span class=\"mark\">${i18next.t('figure-library.text.latest')}</span>` : nothing}\n ${unusable ? html`<span class=\"mark crit\">${i18next.t('figure-library.text.format-unsupported')}</span>` : nothing}\n ${release.deprecated ? html`<span class=\"mark\">${i18next.t('figure-library.text.deprecated')}</span>` : nothing}\n </span>\n </div>\n ${asset\n ? html`<figure-asset-viewer .asset=${asset}>\n <figure-facts-list slot=\"facts\" .asset=${asset} .row=${{ category: release.category }}></figure-facts-list>\n </figure-asset-viewer>`\n : html`<p class=\"reason\" role=\"note\">${i18next.t('figure-library.text.cannot-use-format', { format: release.assetFormat })}</p>`}\n ${this.renderReleaseFacts(release)}\n </section>\n `\n }\n\n private renderReleaseFacts(release: any) {\n const changes = changesOf(release)\n const carrier = release.carrierType\n ? `${release.carrierType}${\n release.carrierDimensions\n ? ` · ${release.carrierDimensions.width} × ${release.carrierDimensions.length} × ${release.carrierDimensions.height} mm`\n : ''\n }`\n : null\n\n return html`<dl class=\"release\">\n ${release.comment ? html`<dt>${i18next.t('figure-library.label.release-note')}</dt><dd>${release.comment}</dd>` : nothing}\n ${release.version > 1\n ? html`<dt>${i18next.t('figure-library.text.contract-since', { version: versionText(release.version - 1) })}</dt>\n <dd>\n ${changes.length\n ? html`<ul>\n ${changes.map(\n change => html`<li class=${change.blocking ? 'breaking' : ''}>\n ${changeText(change)}${change.blocking ? html` · ${i18next.t('figure-library.text.breaking')}` : nothing}\n </li>`\n )}\n </ul>`\n : i18next.t('figure-library.text.no-contract-change')}\n </dd>`\n : nothing}\n ${carrier ? html`<dt>${i18next.t('figure-library.label.carrier')}</dt><dd>${carrier}</dd>` : nothing}\n <dt>${i18next.t('figure-library.label.format')}</dt>\n <dd>\n ${release.assetFormat}\n ${release.kernelVersion ? html`<small>${i18next.t('figure-library.text.kernel', { version: release.kernelVersion })}</small>` : nothing}\n </dd>\n <dt>${i18next.t('figure-library.label.released-at')}</dt>\n <dd>${when(release.releasedAt)}</dd>\n <dt>${i18next.t('figure-library.label.imported-at')}</dt>\n <dd>${when(release.createdAt)}</dd>\n <dt>${i18next.t('figure-library.label.source')}</dt>\n <dd>${release.sourceUrl ?? ''}</dd>\n </dl>`\n }\n\n private show(column: number, id: string) {\n const next = [...this.shown]\n next[column] = id\n this.shown = next\n }\n\n private save = async () => {\n this.saving = true\n try {\n const response = await client.mutate({ mutation: CHOOSE, variables: { name: this.name, releaseId: this.picked } })\n if (response.errors?.length) throw new Error(response.errors[0].message)\n this.dispatchEvent(new CustomEvent('saved', { bubbles: true, composed: true }))\n closePopup(this)\n } catch (e: any) {\n this.failure = e?.message ?? ''\n } finally {\n this.saving = false\n }\n }\n}\n"]}
1
+ {"version":3,"file":"figure-releases-popup.js","sourceRoot":"","sources":["../../client/viewparts/figure-releases-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/popup/ox-popup-actions.js'\nimport '@things-factory/figure-viewer/dist-client/figure-asset-viewer.js'\nimport '@things-factory/figure-viewer/dist-client/figure-facts-list.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport type { FigureAsset } from '@hatiolab/figure-model'\nimport { client } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { closePopup } from '@operato/popup'\nimport { ButtonStyles, CommonPopupStyles, FormFieldStyles, ScrollbarStyles } from '@operato/styles'\n\nimport { versionText } from './figure-version.js'\nimport { defaultPair, SIDE_BY_SIDE } from './release-pair.js'\n\nconst RELEASES_OF = gql`\n query ($name: String!) {\n figureLibraryReleasesOf(name: $name) {\n id\n name\n ref\n version\n category\n source\n formatSupported\n assetFormat\n kernelVersion\n carrierType\n carrierDimensions\n changes\n deprecated\n supersededBy\n comment\n sourceUrl\n releasedAt\n createdAt\n }\n }\n`\n\nconst CHOOSE = gql`\n mutation ($name: String!, $releaseId: String!) {\n chooseFigureRelease(name: $name, releaseId: $releaseId) {\n name\n }\n }\n`\n\ntype Change = { code?: string; values?: Record<string, unknown>; detail?: string; blocking?: boolean }\n\n/** A time in the reader's language (a bare toLocaleString follows the browser, not the app). */\nconst when = (value?: string | null) => (value ? new Date(value).toLocaleString(i18next.language) : '')\n\n/**\n * A contract change in words. figure-model gives a code and values; `detail` is English for logs and is\n * the sentence only when this module has no words for a new code (open question P8 in figure-library.md).\n */\nconst changeText = (change: Change) =>\n change.code\n ? i18next.t(`figure-library.contract.${change.code}`, { ...(change.values ?? {}), defaultValue: change.detail ?? change.code })\n : change.detail ?? ''\n\n/** The contract changes a release carries against its previous release, as the authoring server measured them. */\nconst changesOf = (release: any): Change[] => {\n try {\n const parsed = release.changes ? JSON.parse(release.changes) : []\n return Array.isArray(parsed) ? parsed : []\n } catch {\n return []\n }\n}\n\n/**\n * Two releases of one figure on live canvases, side by side (ADR-0114, amended 2026-10-12): each drawn as a board draws\n * it, sized within its ranges, posed and played, with what it is and its places beside it -- operato-figure's preview\n * (@things-factory/figure-viewer), not a second one. With more releases, each column picks the release it shows; the\n * one in use and the latest stand first. The operator picks the release the figure draws with and saves; save stays\n * off until the pick differs. A release this server cannot read shows why instead of a canvas and cannot be picked.\n */\n@customElement('figure-releases-popup')\nexport class FigureReleasesPopup extends localize(i18next)(LitElement) {\n static styles = [\n CommonPopupStyles,\n ScrollbarStyles,\n ButtonStyles,\n FormFieldStyles,\n css`\n /*\n The popup takes the overlay's width (a share of the window, all of it on a narrow one) and never more: the two\n columns sit side by side when they have room and stack when they do not, and the actions stay in view.\n */\n :host {\n min-height: 0;\n width: 100%;\n --popup-min-width: 0;\n }\n\n /*\n Each column is as tall as the body, so its canvas stays in view while only its tab's body scrolls (user\n 2026-10-15: a clip played at the bottom of a scrolled column moved a figure no longer seen). Stacked, the body\n scrolls from one column to the next.\n */\n .body {\n flex: 1;\n overflow: auto;\n container-type: size;\n }\n\n .columns {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr));\n gap: var(--spacing-large, 12px);\n align-items: start;\n }\n\n section.column {\n display: flex;\n flex-direction: column;\n min-width: 0;\n height: 100cqh;\n box-sizing: border-box;\n border: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));\n border-radius: var(--ui-r, 10px);\n background: var(--ui-panel, var(--md-sys-color-surface-container-lowest));\n }\n\n section.column > * {\n flex: none;\n }\n\n section.column > figure-asset-viewer {\n flex: 1;\n min-height: 0;\n }\n\n section.column[picked] {\n border-color: var(--ui-accent, var(--md-sys-color-primary));\n box-shadow: inset 0 0 0 1px var(--ui-accent, var(--md-sys-color-primary));\n }\n\n /*\n Side by side, which release a column is stays in view while its facts scroll by. Stacked, each column's canvas\n stands right under its own header and the header leaves with its column (below two columns' width).\n */\n .head {\n position: sticky;\n top: 0;\n z-index: 1;\n border-radius: var(--ui-r, 10px) var(--ui-r, 10px) 0 0;\n background: var(--ui-panel, var(--md-sys-color-surface-container-lowest));\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--spacing-small, 4px) var(--spacing-medium, 8px);\n padding: var(--spacing-medium, 8px) 16px;\n border-bottom: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));\n }\n\n @container (max-width: 771px) {\n .head {\n position: static;\n }\n }\n\n .head label {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-small, 4px);\n font-weight: 600;\n }\n\n .head select {\n height: var(--form-element-height-small, 26px);\n min-width: 72px;\n font-size: var(--ui-t-body, 13px);\n }\n\n .head strong {\n font-size: var(--ui-t-title, 15px);\n }\n\n .marks {\n display: flex;\n flex-wrap: wrap;\n gap: var(--spacing-small, 4px);\n }\n\n .mark {\n padding: 0 var(--spacing-medium, 8px);\n border: 1px solid var(--ui-line, var(--md-sys-color-outline-variant));\n border-radius: 999px;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n font-size: var(--ui-t-small, 11.5px);\n white-space: nowrap;\n }\n\n .mark.on {\n border-color: var(--ui-accent, var(--md-sys-color-primary));\n color: var(--ui-accent, var(--md-sys-color-primary));\n font-weight: 600;\n }\n\n .mark.crit {\n color: var(--ui-crit, var(--md-sys-color-error));\n }\n\n .reason {\n margin: 0;\n padding: var(--spacing-huge, 24px) 16px;\n color: var(--ui-crit, var(--md-sys-color-error));\n }\n\n /* The release's own facts (note, dates, source, format, contract change) under the figure's. */\n dl.release {\n display: grid;\n grid-template-columns: 96px minmax(0, 1fr);\n gap: 3px 12px;\n margin: 0;\n padding: 10px 16px;\n line-height: 1.45;\n }\n\n dl.release dt {\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n\n dl.release dd {\n margin: 0;\n overflow-wrap: anywhere;\n }\n\n dl.release dd small {\n display: block;\n color: var(--ui-muted, var(--md-sys-color-on-surface-variant));\n }\n\n ul {\n margin: 0;\n padding-left: 1.2em;\n }\n\n li.breaking {\n color: var(--ui-crit, var(--md-sys-color-error));\n }\n\n .finding {\n margin: 0 0 var(--spacing-large, 12px);\n padding-left: var(--spacing-large, 12px);\n border-left: 2px solid var(--ui-crit, var(--md-sys-color-error));\n }\n `\n ]\n\n /** The full figure name. */\n @property() name = ''\n /** The id of the release it draws with now; '' when nothing is in use. */\n @property() drawing = ''\n\n @state() private releases: any[] = []\n /** The release each column shows, by id. */\n @state() private shown: string[] = []\n @state() private picked = ''\n @state() private saving = false\n @state() private failure = ''\n /** The tab both columns show: choosing one in a column turns the other to it, so both are compared on one view. */\n @state() private tab = 'info'\n\n private assets = new Map<string, FigureAsset | null>()\n\n async connectedCallback() {\n super.connectedCallback()\n this.picked = this.drawing\n const response = await client.query({ query: RELEASES_OF, variables: { name: this.name }, fetchPolicy: 'network-only' })\n this.releases = response.data?.figureLibraryReleasesOf ?? []\n this.shown = defaultPair(this.releases, this.drawing)\n }\n\n render() {\n const changed = !!this.picked && this.picked !== this.drawing\n const byId = new Map(this.releases.map(release => [release.id, release]))\n\n return html`\n <div class=\"body\">\n ${this.failure ? html`<p class=\"finding\" role=\"alert\">${this.failure}</p>` : nothing}\n <div class=\"columns\">\n ${this.shown.map((id, column) => (byId.get(id) ? this.renderColumn(byId.get(id), column) : nothing))}\n </div>\n </div>\n <ox-popup-actions>\n <button slot=\"cancel\" @click=${() => closePopup(this)}>${i18next.t('figure-library.button.cancel')}</button>\n <button slot=\"confirm\" raised ?disabled=${!changed || this.saving} @click=${this.save}>${i18next.t('figure-library.button.save')}</button>\n </ox-popup-actions>\n `\n }\n\n private assetOf(release: any): FigureAsset | null {\n if (!this.assets.has(release.id)) {\n let asset: FigureAsset | null = null\n try {\n asset = release.formatSupported ? (JSON.parse(release.source) as FigureAsset) : null\n } catch {\n asset = null\n }\n this.assets.set(release.id, asset)\n }\n return this.assets.get(release.id)!\n }\n\n private renderColumn(release: any, column: number) {\n const picked = release.id === this.picked\n /* A release this server cannot read is never used: it is shown, not picked (ADR-0114, amended 2026-10-12). */\n const asset = this.assetOf(release)\n const unusable = !asset\n const latest = release.id === this.releases[0]?.id\n const choosable = this.releases.length > SIDE_BY_SIDE\n\n return html`\n <section class=\"column\" ?picked=${picked}>\n <div class=\"head\">\n <label>\n <input type=\"radio\" name=\"release\" .checked=${picked} ?disabled=${unusable} @change=${() => (this.picked = release.id)} />\n ${choosable\n ? html`<select aria-label=${i18next.t('figure-library.label.release-shown')} @change=${(e: Event) => this.show(column, (e.target as HTMLSelectElement).value)}>\n ${this.releases.map(\n other => html`<option value=${other.id} ?selected=${other.id === release.id}>${versionText(other.version)}</option>`\n )}\n </select>`\n : html`<strong>${versionText(release.version)}</strong>`}\n </label>\n <span class=\"marks\">\n ${release.id === this.drawing ? html`<span class=\"mark on\">${i18next.t('figure-library.text.in-use')}</span>` : nothing}\n ${latest ? html`<span class=\"mark\">${i18next.t('figure-library.text.latest')}</span>` : nothing}\n ${unusable ? html`<span class=\"mark crit\">${i18next.t('figure-library.text.format-unsupported')}</span>` : nothing}\n ${release.deprecated ? html`<span class=\"mark\">${i18next.t('figure-library.text.deprecated')}</span>` : nothing}\n </span>\n </div>\n ${asset\n ? html`<figure-asset-viewer .asset=${asset} .tab=${this.tab} @tab-change=${(e: CustomEvent<{ tab: string }>) => (this.tab = e.detail.tab)}>\n <figure-facts-list slot=\"facts\" .asset=${asset} .row=${{ category: release.category }}></figure-facts-list>\n ${this.renderReleaseFacts(release, 'facts')}\n </figure-asset-viewer>`\n : html`<p class=\"reason\" role=\"note\">${i18next.t('figure-library.text.cannot-use-format', { format: release.assetFormat })}</p>\n ${this.renderReleaseFacts(release)}`}\n </section>\n `\n }\n\n private renderReleaseFacts(release: any, slot?: string) {\n const changes = changesOf(release)\n const carrier = release.carrierType\n ? `${release.carrierType}${\n release.carrierDimensions\n ? ` · ${release.carrierDimensions.width} × ${release.carrierDimensions.length} × ${release.carrierDimensions.height} mm`\n : ''\n }`\n : null\n\n return html`<dl class=\"release\" slot=${slot ?? nothing}>\n ${release.comment ? html`<dt>${i18next.t('figure-library.label.release-note')}</dt><dd>${release.comment}</dd>` : nothing}\n ${release.version > 1\n ? html`<dt>${i18next.t('figure-library.text.contract-since', { version: versionText(release.version - 1) })}</dt>\n <dd>\n ${changes.length\n ? html`<ul>\n ${changes.map(\n change => html`<li class=${change.blocking ? 'breaking' : ''}>\n ${changeText(change)}${change.blocking ? html` · ${i18next.t('figure-library.text.breaking')}` : nothing}\n </li>`\n )}\n </ul>`\n : i18next.t('figure-library.text.no-contract-change')}\n </dd>`\n : nothing}\n ${carrier ? html`<dt>${i18next.t('figure-library.label.carrier')}</dt><dd>${carrier}</dd>` : nothing}\n <dt>${i18next.t('figure-library.label.format')}</dt>\n <dd>\n ${release.assetFormat}\n ${release.kernelVersion ? html`<small>${i18next.t('figure-library.text.kernel', { version: release.kernelVersion })}</small>` : nothing}\n </dd>\n <dt>${i18next.t('figure-library.label.released-at')}</dt>\n <dd>${when(release.releasedAt)}</dd>\n <dt>${i18next.t('figure-library.label.imported-at')}</dt>\n <dd>${when(release.createdAt)}</dd>\n <dt>${i18next.t('figure-library.label.source')}</dt>\n <dd>${release.sourceUrl ?? ''}</dd>\n </dl>`\n }\n\n private show(column: number, id: string) {\n const next = [...this.shown]\n next[column] = id\n this.shown = next\n }\n\n private save = async () => {\n this.saving = true\n try {\n const response = await client.mutate({ mutation: CHOOSE, variables: { name: this.name, releaseId: this.picked } })\n if (response.errors?.length) throw new Error(response.errors[0].message)\n this.dispatchEvent(new CustomEvent('saved', { bubbles: true, composed: true }))\n closePopup(this)\n } catch (e: any) {\n this.failure = e?.message ?? ''\n } finally {\n this.saving = false\n }\n }\n}\n"]}