@things-factory/figure-ui 10.1.271 → 10.1.273

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 (112) hide show
  1. package/client/modeller/canvas.ts +4 -2
  2. package/client/modeller/clips.ts +74 -4
  3. package/client/modeller/data-interface.ts +30 -18
  4. package/client/modeller/editor-styles.ts +17 -6
  5. package/client/modeller/editor.ts +2 -0
  6. package/client/modeller/fasten-form.ts +81 -6
  7. package/client/modeller/fasten-geometry.ts +5 -3
  8. package/client/modeller/figure-cavity-drawing.ts +1 -3
  9. package/client/modeller/figure-clips.ts +101 -8
  10. package/client/modeller/figure-data-panel.ts +384 -200
  11. package/client/modeller/figure-fasten-dialog.ts +41 -30
  12. package/client/modeller/figure-fasten-drawing.ts +24 -14
  13. package/client/modeller/figure-first-save.ts +4 -3
  14. package/client/modeller/figure-links.ts +109 -37
  15. package/client/modeller/figure-parts.ts +7 -11
  16. package/client/modeller/figure-preview.ts +299 -79
  17. package/client/modeller/figure-size-editor.ts +7 -2
  18. package/client/modeller/first-save.ts +8 -0
  19. package/client/modeller/focus-on-render.ts +4 -0
  20. package/client/modeller/pivot.ts +76 -0
  21. package/client/modeller/size-response.ts +14 -0
  22. package/client/modeller/stage-model.ts +50 -6
  23. package/dist-client/modeller/canvas.d.ts +1 -0
  24. package/dist-client/modeller/canvas.js +3 -2
  25. package/dist-client/modeller/canvas.js.map +1 -1
  26. package/dist-client/modeller/clips.d.ts +17 -3
  27. package/dist-client/modeller/clips.js +69 -4
  28. package/dist-client/modeller/clips.js.map +1 -1
  29. package/dist-client/modeller/data-interface.d.ts +11 -8
  30. package/dist-client/modeller/data-interface.js +27 -17
  31. package/dist-client/modeller/data-interface.js.map +1 -1
  32. package/dist-client/modeller/editor-styles.js +17 -6
  33. package/dist-client/modeller/editor-styles.js.map +1 -1
  34. package/dist-client/modeller/editor.js +2 -0
  35. package/dist-client/modeller/editor.js.map +1 -1
  36. package/dist-client/modeller/fasten-form.d.ts +13 -0
  37. package/dist-client/modeller/fasten-form.js +72 -7
  38. package/dist-client/modeller/fasten-form.js.map +1 -1
  39. package/dist-client/modeller/fasten-geometry.d.ts +3 -2
  40. package/dist-client/modeller/fasten-geometry.js +5 -3
  41. package/dist-client/modeller/fasten-geometry.js.map +1 -1
  42. package/dist-client/modeller/figure-cavity-drawing.js +1 -3
  43. package/dist-client/modeller/figure-cavity-drawing.js.map +1 -1
  44. package/dist-client/modeller/figure-clips.d.ts +9 -0
  45. package/dist-client/modeller/figure-clips.js +104 -8
  46. package/dist-client/modeller/figure-clips.js.map +1 -1
  47. package/dist-client/modeller/figure-data-panel.d.ts +10 -19
  48. package/dist-client/modeller/figure-data-panel.js +382 -190
  49. package/dist-client/modeller/figure-data-panel.js.map +1 -1
  50. package/dist-client/modeller/figure-fasten-dialog.js +39 -24
  51. package/dist-client/modeller/figure-fasten-dialog.js.map +1 -1
  52. package/dist-client/modeller/figure-fasten-drawing.js +24 -14
  53. package/dist-client/modeller/figure-fasten-drawing.js.map +1 -1
  54. package/dist-client/modeller/figure-first-save.js +4 -3
  55. package/dist-client/modeller/figure-first-save.js.map +1 -1
  56. package/dist-client/modeller/figure-links.d.ts +9 -0
  57. package/dist-client/modeller/figure-links.js +120 -51
  58. package/dist-client/modeller/figure-links.js.map +1 -1
  59. package/dist-client/modeller/figure-parts.js +7 -11
  60. package/dist-client/modeller/figure-parts.js.map +1 -1
  61. package/dist-client/modeller/figure-preview.d.ts +13 -0
  62. package/dist-client/modeller/figure-preview.js +296 -80
  63. package/dist-client/modeller/figure-preview.js.map +1 -1
  64. package/dist-client/modeller/figure-size-editor.js +7 -3
  65. package/dist-client/modeller/figure-size-editor.js.map +1 -1
  66. package/dist-client/modeller/first-save.d.ts +5 -0
  67. package/dist-client/modeller/first-save.js +7 -0
  68. package/dist-client/modeller/first-save.js.map +1 -1
  69. package/dist-client/modeller/focus-on-render.d.ts +2 -0
  70. package/dist-client/modeller/focus-on-render.js +4 -0
  71. package/dist-client/modeller/focus-on-render.js.map +1 -0
  72. package/dist-client/modeller/pivot.d.ts +12 -0
  73. package/dist-client/modeller/pivot.js +59 -0
  74. package/dist-client/modeller/pivot.js.map +1 -0
  75. package/dist-client/modeller/size-response.d.ts +6 -0
  76. package/dist-client/modeller/size-response.js +14 -0
  77. package/dist-client/modeller/size-response.js.map +1 -1
  78. package/dist-client/modeller/stage-model.d.ts +17 -3
  79. package/dist-client/modeller/stage-model.js +44 -6
  80. package/dist-client/modeller/stage-model.js.map +1 -1
  81. package/dist-client/tsconfig.tsbuildinfo +1 -1
  82. package/package.json +8 -7
  83. package/test/browser/editing-page.js +1 -1
  84. package/test/browser/editing.check.mjs +6 -5
  85. package/test/browser/links.check.mjs +30 -0
  86. package/test/browser/modeller.check.mjs +2 -2
  87. package/test/browser/parts-page.js +4 -0
  88. package/test/browser/parts.check.mjs +16 -10
  89. package/test/browser/screen-page.js +12 -1
  90. package/test/browser/screen.check.mjs +142 -11
  91. package/test/browser/section.check.mjs +21 -0
  92. package/test/browser/serve-response.mjs +5 -2
  93. package/test/browser/side-panel-sweep.check.mjs +171 -10
  94. package/test/clips.test.ts +49 -4
  95. package/test/data-motion.test.ts +39 -8
  96. package/test/fasten-form.test.ts +69 -0
  97. package/test/fasten-geometry.test.ts +13 -0
  98. package/test/first-save.test.ts +11 -1
  99. package/test/pivot.test.ts +57 -0
  100. package/test/size-response.test.ts +10 -2
  101. package/test/stage-model.test.ts +23 -1
  102. package/translations/en.json +31 -11
  103. package/translations/es.json +30 -10
  104. package/translations/ja.json +30 -10
  105. package/translations/ko.json +32 -12
  106. package/translations/ms.json +30 -10
  107. package/translations/zh.json +30 -10
  108. package/tutorial/humanoid/README.md +22 -0
  109. package/tutorial/humanoid/chapters.mjs +247 -0
  110. package/tutorial/humanoid/encode.mjs +26 -0
  111. package/tutorial/humanoid/lib.mjs +197 -0
  112. package/tutorial/humanoid/record.mjs +65 -0
@@ -122,7 +122,28 @@ let FigureFastenDialog = class FigureFastenDialog extends localize(i18next)(LitE
122
122
  }
123
123
  details[fasten-detail] > div[form] {
124
124
  margin-top: 8px;
125
- max-width: 320px;
125
+ max-width: 420px;
126
+ }
127
+ /* Where across the face, as buttons: a list the system draws is not seen in a recording, nor reached by a key in every browser. */
128
+ div[align-choices] {
129
+ display: flex;
130
+ flex-wrap: wrap;
131
+ gap: 4px;
132
+ }
133
+ div[align-choices] button {
134
+ font: inherit;
135
+ font-size: var(--ui-t-small, 11.5px);
136
+ padding: 3px 8px;
137
+ border-radius: 12px;
138
+ border: 1px solid var(--md-sys-color-outline-variant, #c4c7c5);
139
+ background: transparent;
140
+ color: inherit;
141
+ cursor: pointer;
142
+ }
143
+ div[align-choices] button[aria-pressed='true'] {
144
+ border-color: var(--md-sys-color-primary, #0d8f86);
145
+ background: var(--md-sys-color-primary-container, #cdeeea);
146
+ font-weight: 600;
126
147
  }
127
148
  span[fasten-summary] {
128
149
  opacity: 0.8;
@@ -255,7 +276,7 @@ let FigureFastenDialog = class FigureFastenDialog extends localize(i18next)(LitE
255
276
  <summary>
256
277
  ${i18next.t('figure.label.fasten-detail')}${detail.length ? html ` · <span fasten-summary>${detail.join(' · ')}</span>` : nothing}
257
278
  </summary>
258
- ${plan.alignRows.length ? this.renderAlignment(plan.alignRows) : nothing}
279
+ ${(plan.alignAxes ?? plan.alignRows).length ? this.renderAlignment(plan.alignAxes ?? plan.alignRows) : nothing}
259
280
  <div form>
260
281
  <span>${i18next.t('figure.label.gap')}</span>
261
282
  <input
@@ -380,28 +401,22 @@ let FigureFastenDialog = class FigureFastenDialog extends localize(i18next)(LitE
380
401
  : 'centre'
381
402
  : (f.align[axis] ?? 'centre');
382
403
  return html `<span>${i18next.t('figure.label.align-' + axis)}</span>
383
- <select @change=${(e) => set(axis, e.target.value)}>
384
- <option value="centre" ?selected=${how === 'centre'}>${i18next.t('figure.label.align-centre')}</option>
385
- ${edges
386
- ? html `<option value="min" ?selected=${how === 'min'}>
387
- ${i18next.t(`figure.label.align-${axis}-min`)}
388
- </option>
389
- <option value="max" ?selected=${how === 'max'}>
390
- ${i18next.t(`figure.label.align-${axis}-max`)}
391
- </option>`
392
- : nothing}
393
- ${f.alignInput?.[axis]
394
- ? html `<option value="input" ?selected=${how === 'input'}>
395
- ${i18next.t('figure.label.align-input', { field: fieldWordsOf(f.alignInput[axis], key => i18next.t(key)) })}
396
- </option>`
397
- : nothing}
398
- <option value="mm" ?selected=${how === 'mm'}>${i18next.t('figure.label.align-mm')}</option>
399
- ${this.revision && hasInstanceSize(this.revision.asset, axis)
400
- ? html `<option value="share" ?selected=${how === 'share'}>
401
- ${i18next.t('figure.label.align-share')}
402
- </option>`
403
- : nothing}
404
- </select>
404
+ <div align-choices role="group" aria-label=${i18next.t('figure.label.align-' + axis)}>
405
+ ${[
406
+ { value: 'centre', words: i18next.t('figure.label.align-centre'), shown: true },
407
+ { value: 'min', words: i18next.t(`figure.label.align-${axis}-min`), shown: edges },
408
+ { value: 'max', words: i18next.t(`figure.label.align-${axis}-max`), shown: edges },
409
+ {
410
+ value: 'input',
411
+ words: f.alignInput?.[axis] ? i18next.t('figure.label.align-input', { field: fieldWordsOf(f.alignInput[axis], key => i18next.t(key)) }) : '',
412
+ shown: !!f.alignInput?.[axis]
413
+ },
414
+ { value: 'mm', words: i18next.t('figure.label.align-mm'), shown: true },
415
+ { value: 'share', words: i18next.t('figure.label.align-share'), shown: !!this.revision && hasInstanceSize(this.revision.asset, axis) }
416
+ ]
417
+ .filter(choice => choice.shown)
418
+ .map(choice => html `<button type="button" aria-pressed=${String(how === choice.value)} @click=${() => set(axis, choice.value)}>${choice.words}</button>`)}
419
+ </div>
405
420
  ${how === 'mm' || how === 'share'
406
421
  ? html `<span></span
407
422
  ><input
@@ -1 +1 @@
1
- {"version":3,"file":"figure-fasten-dialog.js","sourceRoot":"","sources":["../../client/modeller/figure-fasten-dialog.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport '@operato/input/ox-input-select-buttons.js'\nimport '@operato/popup/ox-popup-actions.js'\nimport { CommonPopupStyles } from '@operato/styles'\nimport { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'\n\nimport './figure-fasten-drawing.js'\nimport type { FastenChange } from './figure-fasten-drawing.js'\nimport { turnsInPlace, type FastenMode } from './fasten-geometry.js'\nimport {\n aimFasten,\n aimFastenAt,\n keptGapOf,\n fastenChanged,\n fastenDetailWordsOf,\n fastenFormOf,\n fastenPlanOf,\n fastenSentenceOf,\n fastenTargetsOf,\n type FastenForm\n} from './fasten-form.js'\nimport { fieldWordsOf, hasInstanceSize, heldBy, mountingPlaneOf, surfaceOf, type Alignment, type Axis } from './links.js'\nimport type { FigureRevision } from './revision.js'\n\n/** The target list's entry for the plane the figure stands by. */\nconst PLANE = '__plane'\n\n/**\n * 붙이기 창: what the selected part is fastened to, on which face, how -- chosen with room to see it, in the standard\n * popup the editor opens (`openPopup`: its title, its close, moved by its head; no backdrop, so the canvas can be\n * pressed while it is open) (user 2026-10-17: 「속성에는 심플하고 직관적인 결과 위주로, 편집은 팝업에서 넓은 공간을\n * 써서」; 2026-10-18: the standard popup, not a window of its own; put back 2026-10-20).\n *\n * Everything chosen here is tried, not done: the command it comes to is told to the editor as it changes\n * (`preview-command`), and the canvas draws it. 「적용」 sends it once (`fasten-apply`), one step of the history;\n * 「취소」 and Esc close it with nothing written (`fasten-cancel`). A row of the target list under the pointer or the\n * arrows asks the canvas to light that part (`fasten-hover`). The window is the only one telling the preview while it\n * is open; the editor keeps the panel quiet.\n */\n@customElement('figure-fasten-dialog')\nexport class FigureFastenDialog extends localize(i18next)(LitElement) {\n static styles = [\n SidePanelStyles,\n CommonPopupStyles,\n css`\n /*\n The popup holds it at its own height and cuts what is past the screen: the window scrolls itself, within the\n screen less the popup's head and margins, 취소 · 적용 kept at its foot (below).\n */\n :host {\n display: grid;\n gap: 16px;\n padding: var(--popup-padding, 16px);\n overflow: auto;\n max-height: calc(100dvh - 32px - 56px);\n }\n /* The result in one line, at the top: it changes with every choice below it. */\n p[fasten-sentence] {\n margin: 0;\n font-size: var(--ui-t-body, 13px);\n font-weight: 600;\n }\n div[question] {\n display: grid;\n align-content: start;\n gap: 6px;\n }\n h4 {\n margin: 0;\n font-size: var(--ui-t-small, 11.5px);\n font-weight: 600;\n color: var(--md-sys-color-on-surface-variant);\n }\n /* The chips are part names, identifiers: shown as they are written, not capitalized as filter words are. */\n ox-input-select-buttons {\n --ox-input-select-buttons-label-text-transform: none;\n }\n p[loops] {\n margin: 0;\n }\n details[fasten-detail] {\n margin: 0;\n }\n details[fasten-detail] > div[form] {\n margin-top: 8px;\n max-width: 320px;\n }\n span[fasten-summary] {\n opacity: 0.8;\n }\n ul[preview-words] {\n margin: 0;\n padding: 8px 12px 8px 26px;\n border-radius: 6px;\n background: var(--md-sys-color-surface-container, #8881);\n display: grid;\n gap: 4px;\n }\n p[preview-words] {\n margin: 0;\n padding: 8px 12px;\n border-radius: 6px;\n background: var(--md-sys-color-surface-container, #8881);\n }\n p[error] {\n margin: 0;\n color: var(--md-sys-color-error);\n }\n /* 취소 · 적용 stay in sight at the window's foot when what is above them is taller than the screen. */\n ox-popup-actions {\n position: sticky;\n bottom: calc(-1 * var(--popup-padding, 16px));\n margin-bottom: calc(-1 * var(--popup-padding, 16px));\n padding-bottom: var(--popup-padding, 16px);\n background: var(--md-sys-color-surface-container-lowest);\n }\n `\n ]\n\n /** The figure at the version on screen. */\n @property({ attribute: false }) revision?: FigureRevision\n /** The part being fastened. */\n @property() partId = ''\n @property({ type: Boolean }) locked = false\n /** What the command would do, in words (the editor works it out: `command-preview.ts`). */\n @property({ attribute: false }) previewWords: string[] = []\n /** Why the last 「적용」 was refused, in the editor's words. */\n @property() error = ''\n\n @state() private form?: FastenForm\n /** Why a press on the canvas aimed at nothing, or only at the part (ADR-0140 stage 4); cleared by the next choice. */\n @state() private aimNote = ''\n /** The command the part's own fastening comes to, as opened: tried unchanged, nothing new is said of it. */\n private opened?: string\n private told = ''\n private loadedFor?: string\n private hovered: string | null = null\n\n willUpdate() {\n /* Opened on what the part has now; another part is another window's. */\n if (this.revision && this.partId && this.partId !== this.loadedFor) {\n this.loadedFor = this.partId\n this.form = fastenFormOf(this.revision, this.partId)\n this.opened = JSON.stringify(fastenPlanOf(this.revision, this.partId, this.form).action ?? null)\n }\n }\n\n async firstUpdated() {\n /* Into the list, on what is chosen, so the arrows go from there. */\n const list = this.renderRoot.querySelector<HTMLElement & { updateComplete?: Promise<unknown> }>(\n 'ox-input-select-buttons'\n )\n await list?.updateComplete\n const chips = list?.shadowRoot?.querySelectorAll<HTMLElement>('md-filter-chip')\n ;([...(chips ?? [])].find(c => c.hasAttribute('selected')) ?? chips?.[0])?.focus()\n }\n\n updated() {\n const plan = this.revision && this.form ? fastenPlanOf(this.revision, this.partId, this.form) : undefined\n const candidate = plan?.action ? { action: plan.action, ...(plan.face ? { face: plan.face } : {}) } : null\n const said = JSON.stringify(candidate)\n if (said === this.told) return\n this.told = said\n this.dispatchEvent(new CustomEvent('preview-command', { detail: candidate, bubbles: true, composed: true }))\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n /* Closed: what it showed goes with it. */\n if (this.told && this.told !== 'null')\n this.dispatchEvent(new CustomEvent('preview-command', { detail: null, bubbles: true, composed: true }))\n this.told = ''\n this.hover(null)\n }\n\n render() {\n const revision = this.revision\n const f = this.form\n if (!revision || !f) return nothing\n const asset = revision.asset\n const held = !!heldBy(asset, this.partId)\n const plan = fastenPlanOf(revision, this.partId, f)\n const planeWord = i18next.t('figure.label.resize-place-' + (asset.placement ?? 'floor'))\n const modes: FastenMode[] = f.toPlane\n ? mountingPlaneOf(asset).facings\n : ['meet', 'flush', ...(turnsInPlace(asset, this.partId) ? (['centre'] as FastenMode[]) : [])]\n const detail = fastenDetailWordsOf(f, (key, params) => i18next.t(key, params))\n const drawing = (show: 'face' | 'how') =>\n html`<figure-fasten-drawing\n show=${show}\n .target=${f.toPlane ? '' : f.target}\n .planeWord=${planeWord}\n .faces=${plan.theirFaces}\n .drawnFaces=${plan.drawnFaces}\n .face=${plan.targetFace}\n .modes=${modes}\n .mode=${plan.mode}\n .view=${plan.view}\n .align=${f.align}\n .alignMm=${f.alignMm}\n .gap=${f.gap}\n .partName=${this.partId}\n .surfaceForm=${f.toPlane || !f.target ? '' : (surfaceOf(asset, f.target)?.form ?? '')}\n .surface=${plan.surface}\n ?locked=${this.locked}\n @fasten-change=${(e: CustomEvent<FastenChange>) => {\n this.aimNote = ''\n this.form = fastenChanged(revision, this.partId, this.form!, e.detail)\n }}\n ></figure-fasten-drawing>`\n return html`\n ${\n plan.aim || plan.surface\n ? html`<p fasten-sentence role=\"status\">\n ${fastenSentenceOf(f, plan, planeWord, (key, params) => i18next.t(key, params))}\n </p>`\n : html`<p hint fasten-sentence>${i18next.t('figure.text.fasten-target-first')}</p>`\n }\n <div question=\"what\">\n <h4 id=\"what\">${i18next.t('figure.label.fasten-what')}</h4>\n ${this.renderTargets(revision, f, planeWord)}\n </div>\n ${\n plan.aim || plan.surface\n ? html`<div question=\"face\">\n <h4>\n ${\n /* The face asked is the target's, named: the part meets it by its real shape, by no face of its own. */ f.toPlane\n ? i18next.t('figure.label.fasten-face-on-plane', { plane: planeWord })\n : /* A sphere has no face to choose: where on its surface. */ plan.theirFaces.length\n ? i18next.t('figure.label.fasten-face-on-part', { part: f.target })\n : i18next.t('figure.label.fasten-face-on-surface', { part: f.target })\n }\n </h4>\n ${drawing('face')}\n </div>\n ${\n modes.length > 1\n ? html`<div question=\"how\">\n <h4>${i18next.t('figure.label.fasten-how')}</h4>\n ${drawing('how')}\n </div>`\n : nothing\n }\n <div question=\"detail\">\n <details fasten-detail>\n <summary>\n ${i18next.t('figure.label.fasten-detail')}${detail.length ? html` · <span fasten-summary>${detail.join(' · ')}</span>` : nothing}\n </summary>\n ${plan.alignRows.length ? this.renderAlignment(plan.alignRows) : nothing}\n <div form>\n <span>${i18next.t('figure.label.gap')}</span>\n <input\n gap\n type=\"number\"\n step=\"any\"\n .value=${f.gapKept !== undefined ? '' : String(f.gap)}\n placeholder=${f.gapKept !== undefined ? i18next.t('figure.label.follows-expression') : ''}\n @change=${(e: Event) => this.set({ gap: Number((e.target as HTMLInputElement).value) || 0, gapKept: undefined, gapFrom: 'typed' })}\n />\n </div>\n </details>\n </div>\n ${/* The one it has, tried unchanged: that it stays where it is goes without saying. */ JSON.stringify(plan.action ?? null) === this.opened ? nothing : this.renderPreviewWords()}`\n : nothing\n }\n ${this.aimNote ? html`<p hint aim-note role=\"status\">${this.aimNote}</p>` : nothing}\n ${this.error ? html`<p error role=\"alert\">${this.error}</p>` : nothing}\n <ox-popup-actions>\n <md-text-button slot=\"cancel\" cancel @click=${this.cancel}>${i18next.t('figure.button.cancel')}</md-text-button>\n <md-filled-button slot=\"confirm\" apply ?disabled=${this.locked || !plan.action} @click=${this.apply}>\n ${i18next.t(held ? 'figure.button.apply' : 'figure.button.fasten')}\n </md-filled-button>\n </ox-popup-actions>\n `\n }\n\n /**\n * What to fasten to: the plane and the other parts, as the standard choice chips. The arrows move among them and\n * the canvas lights the part under the focus or the pointer; a part hanging from this one is not offered, and why is\n * said under them.\n */\n private renderTargets(revision: FigureRevision, f: FastenForm, planeWord: string) {\n const chosen = f.toPlane ? PLANE : f.target\n const targets = fastenTargetsOf(revision, this.partId)\n const chipOf = (e: Event) =>\n (e.composedPath().find(n => (n as Element).localName === 'md-filter-chip') as Element | undefined)?.getAttribute(\n 'data-value'\n ) ?? null\n return html`<ox-input-select-buttons\n targets\n aria-labelledby=\"what\"\n .options=${[{ value: PLANE, display: planeWord }, ...targets.filter(t => !t.loops).map(t => ({ value: t.part, display: t.part }))]}\n .value=${chosen || undefined}\n ?disabled=${this.locked}\n @change=${(e: CustomEvent) => {\n /* A chip pressed again lets go of it; what to fasten to is always one thing once chosen. */\n if (e.detail) this.aim(e.detail)\n else (e.target as HTMLElement & { value?: string }).value = chosen || undefined\n }}\n @pointerover=${(e: Event) => this.hover(chipOf(e))}\n @pointerleave=${() => this.hover(null)}\n @focusin=${(e: Event) => this.hover(chipOf(e))}\n @keyup=${(e: KeyboardEvent) => {\n /* The arrows move the focus among the chips inside the list, which tells nothing outside it: read where it is. */\n const at = (e.currentTarget as Element).shadowRoot?.activeElement\n if (at?.localName === 'md-filter-chip') this.hover(at.getAttribute('data-value'))\n }}\n ></ox-input-select-buttons>\n ${this.renderLoops(targets.filter(t => t.loops).map(t => t.part))}`\n }\n\n /**\n * The parts that hang from this one, in one line: a line each made a list longer than the chips (2026-10-18, :3300,\n * the robot arm's forearm and the six parts it carries).\n */\n private renderLoops(parts: string[]) {\n if (!parts.length) return nothing\n return html`<p hint loops targets=${parts.join(',')}>\n ${i18next.t('figure.text.target-would-loop', { part: parts.join(', '), mine: this.partId })}\n </p>`\n }\n\n private aim(part: string) {\n if (this.locked || !this.revision || !this.form) return\n this.aimNote = ''\n const chosen = this.form.toPlane ? PLANE : this.form.target\n if (part === chosen) return\n this.form = keptGapOf(this.revision, this.partId, aimFasten(this.revision, this.partId, this.form, part === PLANE ? { plane: true } : { part }))\n }\n\n /**\n * A part pressed on the canvas while the window is open (ADR-0140 stage 4): aimed at, on the face or the point pressed\n * -- the kernel's reading of the press (`figureFastenTargetAt`), the point and normal brought into that part's own\n * frame by the pose it is drawn at. The part itself, or one hanging from it, is not aimed at; and a press on a curve\n * there is no fastening to aims at the part alone. Each is said.\n */\n aimAt(at: { id: string; point?: number[]; normal?: number[] }) {\n if (this.locked || !this.revision || !this.form) return\n const aimed = aimFastenAt(this.revision, this.partId, this.form, at)\n this.aimNote = aimed.note ? i18next.t(`figure.text.${aimed.note}`, { part: aimed.part, mine: this.partId }) : ''\n if (aimed.form) this.form = aimed.form\n }\n\n /** The part under the pointer or the focus in the list, for the canvas to light; the plane lights nothing. */\n private hover(part: string | null) {\n const lit = part && part !== PLANE ? part : null\n if (lit === this.hovered) return\n this.hovered = lit\n const face =\n lit && this.revision && this.form\n ? fastenPlanOf(this.revision, this.partId, aimFasten(this.revision, this.partId, this.form, { part: lit }))\n .targetFace\n : undefined\n this.dispatchEvent(\n new CustomEvent('fasten-hover', { detail: lit ? { part: lit, face } : null, bubbles: true, composed: true })\n )\n }\n\n private set(change: Partial<FastenForm>) {\n this.form = { ...this.form!, ...change }\n }\n\n /**\n * Where on the target face the part sits, on the axes the drawing cannot set: centred, level with the target's edge on\n * either side, a distance off centre, a share of the figure's size, or the position field it follows.\n */\n private renderAlignment(axes: { axis: Axis; edges: boolean }[]) {\n const f = this.form!\n const set = (axis: Axis, how: Alignment) => this.set({ align: { ...f.align, [axis]: how } })\n const setMm = (axis: Axis, mm: number) => this.set({ alignMm: { ...f.alignMm, [axis]: mm } })\n return html`<div form>\n ${axes.map(({ axis, edges }) => {\n const how =\n f.align[axis] === 'min' || f.align[axis] === 'max'\n ? edges\n ? f.align[axis]!\n : 'centre'\n : (f.align[axis] ?? 'centre')\n return html`<span>${i18next.t('figure.label.align-' + axis)}</span>\n <select @change=${(e: Event) => set(axis, (e.target as HTMLSelectElement).value as Alignment)}>\n <option value=\"centre\" ?selected=${how === 'centre'}>${i18next.t('figure.label.align-centre')}</option>\n ${\n edges\n ? html`<option value=\"min\" ?selected=${how === 'min'}>\n ${i18next.t(`figure.label.align-${axis}-min`)}\n </option>\n <option value=\"max\" ?selected=${how === 'max'}>\n ${i18next.t(`figure.label.align-${axis}-max`)}\n </option>`\n : nothing\n }\n ${\n f.alignInput?.[axis]\n ? html`<option value=\"input\" ?selected=${how === 'input'}>\n ${i18next.t('figure.label.align-input', { field: fieldWordsOf(f.alignInput[axis]!, key => i18next.t(key)) })}\n </option>`\n : nothing\n }\n <option value=\"mm\" ?selected=${how === 'mm'}>${i18next.t('figure.label.align-mm')}</option>\n ${\n this.revision && hasInstanceSize(this.revision.asset, axis)\n ? html`<option value=\"share\" ?selected=${how === 'share'}>\n ${i18next.t('figure.label.align-share')}\n </option>`\n : nothing\n }\n </select>\n ${\n how === 'mm' || how === 'share'\n ? html`<span></span\n ><input\n type=\"number\"\n step=\"any\"\n aria-label=${i18next.t('figure.label.align-mm')}\n .value=${String(f.alignMm[axis] ?? 0)}\n @change=${(e: Event) => setMm(axis, Number((e.target as HTMLInputElement).value) || 0)}\n />`\n : nothing\n }`\n })}\n </div>`\n }\n\n private renderPreviewWords() {\n if (this.previewWords.length === 1) return html`<p preview-words role=\"status\">${this.previewWords[0]}</p>`\n return this.previewWords.length\n ? html`<ul preview-words role=\"status\">\n ${this.previewWords.map(line => html`<li>${line}</li>`)}\n </ul>`\n : nothing\n }\n\n /** Enter applies what is chosen, Esc closes with nothing written; a key the window does not take goes on. */\n connectedCallback() {\n super.connectedCallback()\n this.setAttribute('role', 'dialog')\n this.setAttribute('aria-label', i18next.t('figure.label.fastening'))\n this.addEventListener('keydown', this.onKey)\n /* The popup's fitting width is the overlay's own setting; the window asks it for room for the face and the way side by side. */\n this.closest<HTMLElement>('ox-floating-overlay')?.style.setProperty('--overlay-center-fit-width', '640px')\n }\n\n private onKey = async (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n e.preventDefault()\n this.cancel()\n return\n }\n if (e.key !== 'Enter' || e.isComposing) return\n const path = e.composedPath() as Element[]\n const target = path[0] as HTMLElement\n /* On a chip of the list Enter applies, as it does anywhere in the window; a chip is chosen by Space or a press. */\n const onChip = path.some(n => n.localName === 'ox-input-select-buttons')\n /* A button, a fold or a list of options does what Enter does to it. */\n if (\n !onChip &&\n (target.localName === 'button' ||\n target.localName === 'summary' ||\n target.localName === 'select' ||\n /^md-.*button$/.test(target.localName))\n )\n return\n e.preventDefault()\n e.stopPropagation()\n /* A number typed and Enter: the number first, as leaving the field would take it. */\n if (target.localName === 'input') target.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n await this.updateComplete\n this.apply()\n }\n\n private apply = () => {\n const plan = this.revision && this.form ? fastenPlanOf(this.revision, this.partId, this.form) : undefined\n if (this.locked || !plan?.action) return\n this.dispatchEvent(\n new CustomEvent('fasten-apply', { detail: { action: plan.action }, bubbles: true, composed: true })\n )\n }\n\n private cancel = () => {\n this.dispatchEvent(new CustomEvent('fasten-cancel', { bubbles: true, composed: true }))\n }\n}\n"]}
1
+ {"version":3,"file":"figure-fasten-dialog.js","sourceRoot":"","sources":["../../client/modeller/figure-fasten-dialog.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport '@operato/input/ox-input-select-buttons.js'\nimport '@operato/popup/ox-popup-actions.js'\nimport { CommonPopupStyles } from '@operato/styles'\nimport { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'\n\nimport './figure-fasten-drawing.js'\nimport type { FastenChange } from './figure-fasten-drawing.js'\nimport { turnsInPlace, type FastenMode } from './fasten-geometry.js'\nimport {\n aimFasten,\n aimFastenAt,\n keptGapOf,\n fastenChanged,\n fastenDetailWordsOf,\n fastenFormOf,\n fastenPlanOf,\n fastenSentenceOf,\n fastenTargetsOf,\n type FastenForm\n} from './fasten-form.js'\nimport { fieldWordsOf, hasInstanceSize, heldBy, mountingPlaneOf, surfaceOf, type Alignment, type Axis } from './links.js'\nimport type { FigureRevision } from './revision.js'\n\n/** The target list's entry for the plane the figure stands by. */\nconst PLANE = '__plane'\n\n/**\n * 붙이기 창: what the selected part is fastened to, on which face, how -- chosen with room to see it, in the standard\n * popup the editor opens (`openPopup`: its title, its close, moved by its head; no backdrop, so the canvas can be\n * pressed while it is open) (user 2026-10-17: 「속성에는 심플하고 직관적인 결과 위주로, 편집은 팝업에서 넓은 공간을\n * 써서」; 2026-10-18: the standard popup, not a window of its own; put back 2026-10-20).\n *\n * Everything chosen here is tried, not done: the command it comes to is told to the editor as it changes\n * (`preview-command`), and the canvas draws it. 「적용」 sends it once (`fasten-apply`), one step of the history;\n * 「취소」 and Esc close it with nothing written (`fasten-cancel`). A row of the target list under the pointer or the\n * arrows asks the canvas to light that part (`fasten-hover`). The window is the only one telling the preview while it\n * is open; the editor keeps the panel quiet.\n */\n@customElement('figure-fasten-dialog')\nexport class FigureFastenDialog extends localize(i18next)(LitElement) {\n static styles = [\n SidePanelStyles,\n CommonPopupStyles,\n css`\n /*\n The popup holds it at its own height and cuts what is past the screen: the window scrolls itself, within the\n screen less the popup's head and margins, 취소 · 적용 kept at its foot (below).\n */\n :host {\n display: grid;\n gap: 16px;\n padding: var(--popup-padding, 16px);\n overflow: auto;\n max-height: calc(100dvh - 32px - 56px);\n }\n /* The result in one line, at the top: it changes with every choice below it. */\n p[fasten-sentence] {\n margin: 0;\n font-size: var(--ui-t-body, 13px);\n font-weight: 600;\n }\n div[question] {\n display: grid;\n align-content: start;\n gap: 6px;\n }\n h4 {\n margin: 0;\n font-size: var(--ui-t-small, 11.5px);\n font-weight: 600;\n color: var(--md-sys-color-on-surface-variant);\n }\n /* The chips are part names, identifiers: shown as they are written, not capitalized as filter words are. */\n ox-input-select-buttons {\n --ox-input-select-buttons-label-text-transform: none;\n }\n p[loops] {\n margin: 0;\n }\n details[fasten-detail] {\n margin: 0;\n }\n details[fasten-detail] > div[form] {\n margin-top: 8px;\n max-width: 420px;\n }\n /* Where across the face, as buttons: a list the system draws is not seen in a recording, nor reached by a key in every browser. */\n div[align-choices] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n div[align-choices] button {\n font: inherit;\n font-size: var(--ui-t-small, 11.5px);\n padding: 3px 8px;\n border-radius: 12px;\n border: 1px solid var(--md-sys-color-outline-variant, #c4c7c5);\n background: transparent;\n color: inherit;\n cursor: pointer;\n }\n div[align-choices] button[aria-pressed='true'] {\n border-color: var(--md-sys-color-primary, #0d8f86);\n background: var(--md-sys-color-primary-container, #cdeeea);\n font-weight: 600;\n }\n span[fasten-summary] {\n opacity: 0.8;\n }\n ul[preview-words] {\n margin: 0;\n padding: 8px 12px 8px 26px;\n border-radius: 6px;\n background: var(--md-sys-color-surface-container, #8881);\n display: grid;\n gap: 4px;\n }\n p[preview-words] {\n margin: 0;\n padding: 8px 12px;\n border-radius: 6px;\n background: var(--md-sys-color-surface-container, #8881);\n }\n p[error] {\n margin: 0;\n color: var(--md-sys-color-error);\n }\n /* 취소 · 적용 stay in sight at the window's foot when what is above them is taller than the screen. */\n ox-popup-actions {\n position: sticky;\n bottom: calc(-1 * var(--popup-padding, 16px));\n margin-bottom: calc(-1 * var(--popup-padding, 16px));\n padding-bottom: var(--popup-padding, 16px);\n background: var(--md-sys-color-surface-container-lowest);\n }\n `\n ]\n\n /** The figure at the version on screen. */\n @property({ attribute: false }) revision?: FigureRevision\n /** The part being fastened. */\n @property() partId = ''\n @property({ type: Boolean }) locked = false\n /** What the command would do, in words (the editor works it out: `command-preview.ts`). */\n @property({ attribute: false }) previewWords: string[] = []\n /** Why the last 「적용」 was refused, in the editor's words. */\n @property() error = ''\n\n @state() private form?: FastenForm\n /** Why a press on the canvas aimed at nothing, or only at the part (ADR-0140 stage 4); cleared by the next choice. */\n @state() private aimNote = ''\n /** The command the part's own fastening comes to, as opened: tried unchanged, nothing new is said of it. */\n private opened?: string\n private told = ''\n private loadedFor?: string\n private hovered: string | null = null\n\n willUpdate() {\n /* Opened on what the part has now; another part is another window's. */\n if (this.revision && this.partId && this.partId !== this.loadedFor) {\n this.loadedFor = this.partId\n this.form = fastenFormOf(this.revision, this.partId)\n this.opened = JSON.stringify(fastenPlanOf(this.revision, this.partId, this.form).action ?? null)\n }\n }\n\n async firstUpdated() {\n /* Into the list, on what is chosen, so the arrows go from there. */\n const list = this.renderRoot.querySelector<HTMLElement & { updateComplete?: Promise<unknown> }>(\n 'ox-input-select-buttons'\n )\n await list?.updateComplete\n const chips = list?.shadowRoot?.querySelectorAll<HTMLElement>('md-filter-chip')\n ;([...(chips ?? [])].find(c => c.hasAttribute('selected')) ?? chips?.[0])?.focus()\n }\n\n updated() {\n const plan = this.revision && this.form ? fastenPlanOf(this.revision, this.partId, this.form) : undefined\n const candidate = plan?.action ? { action: plan.action, ...(plan.face ? { face: plan.face } : {}) } : null\n const said = JSON.stringify(candidate)\n if (said === this.told) return\n this.told = said\n this.dispatchEvent(new CustomEvent('preview-command', { detail: candidate, bubbles: true, composed: true }))\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n /* Closed: what it showed goes with it. */\n if (this.told && this.told !== 'null')\n this.dispatchEvent(new CustomEvent('preview-command', { detail: null, bubbles: true, composed: true }))\n this.told = ''\n this.hover(null)\n }\n\n render() {\n const revision = this.revision\n const f = this.form\n if (!revision || !f) return nothing\n const asset = revision.asset\n const held = !!heldBy(asset, this.partId)\n const plan = fastenPlanOf(revision, this.partId, f)\n const planeWord = i18next.t('figure.label.resize-place-' + (asset.placement ?? 'floor'))\n const modes: FastenMode[] = f.toPlane\n ? mountingPlaneOf(asset).facings\n : ['meet', 'flush', ...(turnsInPlace(asset, this.partId) ? (['centre'] as FastenMode[]) : [])]\n const detail = fastenDetailWordsOf(f, (key, params) => i18next.t(key, params))\n const drawing = (show: 'face' | 'how') =>\n html`<figure-fasten-drawing\n show=${show}\n .target=${f.toPlane ? '' : f.target}\n .planeWord=${planeWord}\n .faces=${plan.theirFaces}\n .drawnFaces=${plan.drawnFaces}\n .face=${plan.targetFace}\n .modes=${modes}\n .mode=${plan.mode}\n .view=${plan.view}\n .align=${f.align}\n .alignMm=${f.alignMm}\n .gap=${f.gap}\n .partName=${this.partId}\n .surfaceForm=${f.toPlane || !f.target ? '' : (surfaceOf(asset, f.target)?.form ?? '')}\n .surface=${plan.surface}\n ?locked=${this.locked}\n @fasten-change=${(e: CustomEvent<FastenChange>) => {\n this.aimNote = ''\n this.form = fastenChanged(revision, this.partId, this.form!, e.detail)\n }}\n ></figure-fasten-drawing>`\n return html`\n ${\n plan.aim || plan.surface\n ? html`<p fasten-sentence role=\"status\">\n ${fastenSentenceOf(f, plan, planeWord, (key, params) => i18next.t(key, params))}\n </p>`\n : html`<p hint fasten-sentence>${i18next.t('figure.text.fasten-target-first')}</p>`\n }\n <div question=\"what\">\n <h4 id=\"what\">${i18next.t('figure.label.fasten-what')}</h4>\n ${this.renderTargets(revision, f, planeWord)}\n </div>\n ${\n plan.aim || plan.surface\n ? html`<div question=\"face\">\n <h4>\n ${\n /* The face asked is the target's, named: the part meets it by its real shape, by no face of its own. */ f.toPlane\n ? i18next.t('figure.label.fasten-face-on-plane', { plane: planeWord })\n : /* A sphere has no face to choose: where on its surface. */ plan.theirFaces.length\n ? i18next.t('figure.label.fasten-face-on-part', { part: f.target })\n : i18next.t('figure.label.fasten-face-on-surface', { part: f.target })\n }\n </h4>\n ${drawing('face')}\n </div>\n ${\n modes.length > 1\n ? html`<div question=\"how\">\n <h4>${i18next.t('figure.label.fasten-how')}</h4>\n ${drawing('how')}\n </div>`\n : nothing\n }\n <div question=\"detail\">\n <details fasten-detail>\n <summary>\n ${i18next.t('figure.label.fasten-detail')}${detail.length ? html` · <span fasten-summary>${detail.join(' · ')}</span>` : nothing}\n </summary>\n ${(plan.alignAxes ?? plan.alignRows).length ? this.renderAlignment(plan.alignAxes ?? plan.alignRows) : nothing}\n <div form>\n <span>${i18next.t('figure.label.gap')}</span>\n <input\n gap\n type=\"number\"\n step=\"any\"\n .value=${f.gapKept !== undefined ? '' : String(f.gap)}\n placeholder=${f.gapKept !== undefined ? i18next.t('figure.label.follows-expression') : ''}\n @change=${(e: Event) => this.set({ gap: Number((e.target as HTMLInputElement).value) || 0, gapKept: undefined, gapFrom: 'typed' })}\n />\n </div>\n </details>\n </div>\n ${/* The one it has, tried unchanged: that it stays where it is goes without saying. */ JSON.stringify(plan.action ?? null) === this.opened ? nothing : this.renderPreviewWords()}`\n : nothing\n }\n ${this.aimNote ? html`<p hint aim-note role=\"status\">${this.aimNote}</p>` : nothing}\n ${this.error ? html`<p error role=\"alert\">${this.error}</p>` : nothing}\n <ox-popup-actions>\n <md-text-button slot=\"cancel\" cancel @click=${this.cancel}>${i18next.t('figure.button.cancel')}</md-text-button>\n <md-filled-button slot=\"confirm\" apply ?disabled=${this.locked || !plan.action} @click=${this.apply}>\n ${i18next.t(held ? 'figure.button.apply' : 'figure.button.fasten')}\n </md-filled-button>\n </ox-popup-actions>\n `\n }\n\n /**\n * What to fasten to: the plane and the other parts, as the standard choice chips. The arrows move among them and\n * the canvas lights the part under the focus or the pointer; a part hanging from this one is not offered, and why is\n * said under them.\n */\n private renderTargets(revision: FigureRevision, f: FastenForm, planeWord: string) {\n const chosen = f.toPlane ? PLANE : f.target\n const targets = fastenTargetsOf(revision, this.partId)\n const chipOf = (e: Event) =>\n (e.composedPath().find(n => (n as Element).localName === 'md-filter-chip') as Element | undefined)?.getAttribute(\n 'data-value'\n ) ?? null\n return html`<ox-input-select-buttons\n targets\n aria-labelledby=\"what\"\n .options=${[{ value: PLANE, display: planeWord }, ...targets.filter(t => !t.loops).map(t => ({ value: t.part, display: t.part }))]}\n .value=${chosen || undefined}\n ?disabled=${this.locked}\n @change=${(e: CustomEvent) => {\n /* A chip pressed again lets go of it; what to fasten to is always one thing once chosen. */\n if (e.detail) this.aim(e.detail)\n else (e.target as HTMLElement & { value?: string }).value = chosen || undefined\n }}\n @pointerover=${(e: Event) => this.hover(chipOf(e))}\n @pointerleave=${() => this.hover(null)}\n @focusin=${(e: Event) => this.hover(chipOf(e))}\n @keyup=${(e: KeyboardEvent) => {\n /* The arrows move the focus among the chips inside the list, which tells nothing outside it: read where it is. */\n const at = (e.currentTarget as Element).shadowRoot?.activeElement\n if (at?.localName === 'md-filter-chip') this.hover(at.getAttribute('data-value'))\n }}\n ></ox-input-select-buttons>\n ${this.renderLoops(targets.filter(t => t.loops).map(t => t.part))}`\n }\n\n /**\n * The parts that hang from this one, in one line: a line each made a list longer than the chips (2026-10-18, :3300,\n * the robot arm's forearm and the six parts it carries).\n */\n private renderLoops(parts: string[]) {\n if (!parts.length) return nothing\n return html`<p hint loops targets=${parts.join(',')}>\n ${i18next.t('figure.text.target-would-loop', { part: parts.join(', '), mine: this.partId })}\n </p>`\n }\n\n private aim(part: string) {\n if (this.locked || !this.revision || !this.form) return\n this.aimNote = ''\n const chosen = this.form.toPlane ? PLANE : this.form.target\n if (part === chosen) return\n this.form = keptGapOf(this.revision, this.partId, aimFasten(this.revision, this.partId, this.form, part === PLANE ? { plane: true } : { part }))\n }\n\n /**\n * A part pressed on the canvas while the window is open (ADR-0140 stage 4): aimed at, on the face or the point pressed\n * -- the kernel's reading of the press (`figureFastenTargetAt`), the point and normal brought into that part's own\n * frame by the pose it is drawn at. The part itself, or one hanging from it, is not aimed at; and a press on a curve\n * there is no fastening to aims at the part alone. Each is said.\n */\n aimAt(at: { id: string; point?: number[]; normal?: number[] }) {\n if (this.locked || !this.revision || !this.form) return\n const aimed = aimFastenAt(this.revision, this.partId, this.form, at)\n this.aimNote = aimed.note ? i18next.t(`figure.text.${aimed.note}`, { part: aimed.part, mine: this.partId }) : ''\n if (aimed.form) this.form = aimed.form\n }\n\n /** The part under the pointer or the focus in the list, for the canvas to light; the plane lights nothing. */\n private hover(part: string | null) {\n const lit = part && part !== PLANE ? part : null\n if (lit === this.hovered) return\n this.hovered = lit\n const face =\n lit && this.revision && this.form\n ? fastenPlanOf(this.revision, this.partId, aimFasten(this.revision, this.partId, this.form, { part: lit }))\n .targetFace\n : undefined\n this.dispatchEvent(\n new CustomEvent('fasten-hover', { detail: lit ? { part: lit, face } : null, bubbles: true, composed: true })\n )\n }\n\n private set(change: Partial<FastenForm>) {\n this.form = { ...this.form!, ...change }\n }\n\n /**\n * Where on the target face the part sits, on the axes the drawing cannot set: centred, level with the target's edge on\n * either side, a distance off centre, a share of the figure's size, or the position field it follows.\n */\n private renderAlignment(axes: { axis: Axis; edges: boolean }[]) {\n const f = this.form!\n const set = (axis: Axis, how: Alignment) => this.set({ align: { ...f.align, [axis]: how } })\n const setMm = (axis: Axis, mm: number) => this.set({ alignMm: { ...f.alignMm, [axis]: mm } })\n return html`<div form>\n ${axes.map(({ axis, edges }) => {\n const how =\n f.align[axis] === 'min' || f.align[axis] === 'max'\n ? edges\n ? f.align[axis]!\n : 'centre'\n : (f.align[axis] ?? 'centre')\n return html`<span>${i18next.t('figure.label.align-' + axis)}</span>\n <div align-choices role=\"group\" aria-label=${i18next.t('figure.label.align-' + axis)}>\n ${[\n { value: 'centre' as Alignment, words: i18next.t('figure.label.align-centre'), shown: true },\n { value: 'min' as Alignment, words: i18next.t(`figure.label.align-${axis}-min`), shown: edges },\n { value: 'max' as Alignment, words: i18next.t(`figure.label.align-${axis}-max`), shown: edges },\n {\n value: 'input' as Alignment,\n words: f.alignInput?.[axis] ? i18next.t('figure.label.align-input', { field: fieldWordsOf(f.alignInput[axis]!, key => i18next.t(key)) }) : '',\n shown: !!f.alignInput?.[axis]\n },\n { value: 'mm' as Alignment, words: i18next.t('figure.label.align-mm'), shown: true },\n { value: 'share' as Alignment, words: i18next.t('figure.label.align-share'), shown: !!this.revision && hasInstanceSize(this.revision.asset, axis) }\n ]\n .filter(choice => choice.shown)\n .map(\n choice => html`<button type=\"button\" aria-pressed=${String(how === choice.value)} @click=${() => set(axis, choice.value)}>${choice.words}</button>`\n )}\n </div>\n ${\n how === 'mm' || how === 'share'\n ? html`<span></span\n ><input\n type=\"number\"\n step=\"any\"\n aria-label=${i18next.t('figure.label.align-mm')}\n .value=${String(f.alignMm[axis] ?? 0)}\n @change=${(e: Event) => setMm(axis, Number((e.target as HTMLInputElement).value) || 0)}\n />`\n : nothing\n }`\n })}\n </div>`\n }\n\n private renderPreviewWords() {\n if (this.previewWords.length === 1) return html`<p preview-words role=\"status\">${this.previewWords[0]}</p>`\n return this.previewWords.length\n ? html`<ul preview-words role=\"status\">\n ${this.previewWords.map(line => html`<li>${line}</li>`)}\n </ul>`\n : nothing\n }\n\n /** Enter applies what is chosen, Esc closes with nothing written; a key the window does not take goes on. */\n connectedCallback() {\n super.connectedCallback()\n this.setAttribute('role', 'dialog')\n this.setAttribute('aria-label', i18next.t('figure.label.fastening'))\n this.addEventListener('keydown', this.onKey)\n /* The popup's fitting width is the overlay's own setting; the window asks it for room for the face and the way side by side. */\n this.closest<HTMLElement>('ox-floating-overlay')?.style.setProperty('--overlay-center-fit-width', '640px')\n }\n\n private onKey = async (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation()\n e.preventDefault()\n this.cancel()\n return\n }\n if (e.key !== 'Enter' || e.isComposing) return\n const path = e.composedPath() as Element[]\n const target = path[0] as HTMLElement\n /* On a chip of the list Enter applies, as it does anywhere in the window; a chip is chosen by Space or a press. */\n const onChip = path.some(n => n.localName === 'ox-input-select-buttons')\n /* A button, a fold or a list of options does what Enter does to it. */\n if (\n !onChip &&\n (target.localName === 'button' ||\n target.localName === 'summary' ||\n target.localName === 'select' ||\n /^md-.*button$/.test(target.localName))\n )\n return\n e.preventDefault()\n e.stopPropagation()\n /* A number typed and Enter: the number first, as leaving the field would take it. */\n if (target.localName === 'input') target.dispatchEvent(new Event('change', { bubbles: true, composed: true }))\n await this.updateComplete\n this.apply()\n }\n\n private apply = () => {\n const plan = this.revision && this.form ? fastenPlanOf(this.revision, this.partId, this.form) : undefined\n if (this.locked || !plan?.action) return\n this.dispatchEvent(\n new CustomEvent('fasten-apply', { detail: { action: plan.action }, bubbles: true, composed: true })\n )\n }\n\n private cancel = () => {\n this.dispatchEvent(new CustomEvent('fasten-cancel', { bubbles: true, composed: true }))\n }\n}\n"]}
@@ -4,6 +4,7 @@ import { customElement, property, state } from 'lit/decorators.js';
4
4
  import { i18next, localize } from '@operato/i18n';
5
5
  import { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js';
6
6
  import { figureAroundNormalOf, figureAroundOf, figureCaughtAngleOf, figureSurfaceAnglesOf, figureSurfacePlaceOf } from '@hatiolab/figure-model';
7
+ import { focusOnRender } from './focus-on-render.js';
7
8
  import { alignmentAt, drawingSpanOf, fastenLabelsOf, offsetOf, overhangOf, screenOf } from './fasten-geometry.js';
8
9
  const AXES = ['x', 'y', 'z'];
9
10
  const SEEN = [
@@ -76,22 +77,28 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
76
77
  svg text {
77
78
  font: inherit;
78
79
  }
80
+ /*
81
+ The ways on one line, a small side view beside each word: three cards of a drawing over a word made the window
82
+ tall, and the fasten button below went off a laptop's screen (user 2026-11-12). The chosen one's gap is dragged
83
+ on its small view still; the gap's field is in the details.
84
+ */
79
85
  div[modes] {
80
- display: grid;
81
- grid-template-columns: repeat(auto-fit, minmax(72px, 1fr));
82
- gap: 6px;
86
+ display: flex;
87
+ flex-wrap: wrap;
88
+ gap: 4px;
83
89
  }
84
90
  div[modes] svg {
85
- width: 48px;
86
- height: 33px;
91
+ flex: none;
92
+ width: 28px;
93
+ height: 20px;
87
94
  }
88
95
  /* A choice drawn, not a box to press (the side's rule: no boxed buttons): the chosen one on the primary's ground. */
89
96
  div[modes] button {
90
- display: grid;
91
- justify-items: center;
92
- align-content: center;
93
- gap: 2px;
94
- padding: 4px 4px 6px;
97
+ display: inline-flex;
98
+ align-items: center;
99
+ gap: 4px;
100
+ padding: 2px 8px 2px 4px;
101
+ white-space: nowrap;
95
102
  font: inherit;
96
103
  color: var(--md-sys-color-on-surface);
97
104
  background: none;
@@ -126,8 +133,8 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
126
133
  border: 1px solid var(--md-sys-color-primary);
127
134
  }
128
135
  div[modes] button[on] {
129
- background: var(--md-sys-color-primary-container);
130
- color: var(--md-sys-color-on-primary-container);
136
+ background: var(--md-sys-color-primary-container, #d8e2ff);
137
+ color: var(--md-sys-color-on-primary-container, #001a41);
131
138
  }
132
139
  /* The box and the face seen from above side by side, one under the other where the window is narrow. */
133
140
  div[face-row] {
@@ -312,7 +319,9 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
312
319
  return nothing;
313
320
  const { h, v, sign } = screenOf(view.axes);
314
321
  const W = WHERE_W, H = WHERE_H;
315
- const span = (a) => drawingSpanOf(view.face[a], view.part[a]);
322
+ /* Where the part is set, not where it is being dragged: the drawing's scale holds still under the pointer. */
323
+ const set = (a) => offsetOf(this.align[a], this.alignMm[a], view.face[a], view.part[a]);
324
+ const span = (a) => drawingSpanOf(view.face[a], view.part[a], set(a));
316
325
  const k = Math.min((W - 40) / span(h), (H - 40) / span(v));
317
326
  this.scale = k;
318
327
  const cx = W / 2, cy = H / 2;
@@ -408,7 +417,8 @@ let FigureFastenDrawing = class FigureFastenDrawing extends localize(i18next)(Li
408
417
  this.change({ axis: a, how: 'mm', mm: Math.round(value) });
409
418
  this.released();
410
419
  }}
411
- @blur=${() => (this.typing = undefined)} />`;
420
+ @blur=${() => (this.typing = undefined)}
421
+ ${focusOnRender()} />`;
412
422
  }
413
423
  grab(ev, at, caught) {
414
424
  if (this.locked)