@things-factory/figure-ui 10.1.121 → 10.1.122

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.
@@ -3,6 +3,7 @@ import { customElement, property, state } from 'lit/decorators.js'
3
3
  import { i18next, localize } from '@operato/i18n'
4
4
  import { appendViewpart, UPDATE_VIEWPART, VIEWPART_POSITION, VIEWPART_LEVEL } from '@operato/layout'
5
5
  import { navigate, store } from '@operato/shell'
6
+ import { ScrollbarStyles } from '@operato/styles'
6
7
  import { ASSISTANT_DOCK_VIEWPART } from '@things-factory/ai-assistant/dist-client/components/assistant-dock.js'
7
8
  import { figureCostOf, parseFigureAsset, type FigureAsset } from '@hatiolab/figure-model'
8
9
  import { capacityFrom } from '../modeller/scene-budget.js'
@@ -17,10 +18,10 @@ export interface FigureDetailRecord {
17
18
  released?: { version: number; source: string }
18
19
  }
19
20
 
20
- /** Catalogue details outlive the page; choosing a size or a pose has no write path. */
21
+ /** Catalogue details stay while the catalogue is shown; choosing a size or a pose has no write path. */
21
22
  @customElement('figure-detail-dock')
22
23
  export class FigureDetailDock extends localize(i18next)(LitElement) {
23
- static styles = css`
24
+ static styles = [ScrollbarStyles, css`
24
25
  :host { display: flex; flex-direction: column; width: 440px; max-width: 100vw; height: 100%; min-height: 0;
25
26
  color: var(--md-sys-color-on-surface); background: var(--md-sys-color-surface); border-left: 1px solid var(--md-sys-color-outline-variant); font-size: 13px; }
26
27
  header { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--md-sys-color-outline-variant); }
@@ -40,7 +41,7 @@ export class FigureDetailDock extends localize(i18next)(LitElement) {
40
41
  @media (max-width: 1439.98px) {
41
42
  :host { position: fixed; inset: var(--figure-detail-top, 44px) 0 0 auto; height: calc(100dvh - var(--figure-detail-top, 44px)); z-index: 11; box-shadow: -4px 0 16px rgb(0 0 0 / 20%); }
42
43
  }
43
- `
44
+ `]
44
45
  @property({ attribute: false }) load: (id: string) => Promise<FigureDetailRecord> = async id => {
45
46
  const [saved, released] = await Promise.all([fetchFigure(id), fetchReleasedFigure(id)])
46
47
  if (!saved?.source) throw Error(i18next.t('figure.text.detail-no-source'))
@@ -97,9 +98,9 @@ export class FigureDetailDock extends localize(i18next)(LitElement) {
97
98
  window.addEventListener('resize', this.place)
98
99
  window.addEventListener('popstate', this.place)
99
100
  this.unsubscribe = store.subscribe(() => {
100
- const state = store.getState() as { layout?: { viewparts?: Record<string, { show?: boolean }> } }
101
+ const state = store.getState() as { layout?: { viewparts?: Record<string, { show?: boolean }> }; route?: { page?: string } }
101
102
  const parts = state.layout?.viewparts
102
- if (parts?.[ASSISTANT_DOCK_VIEWPART]?.show && parts?.[VIEWPART]?.show) hideDetail()
103
+ if (parts?.[VIEWPART]?.show && (parts?.[ASSISTANT_DOCK_VIEWPART]?.show || leftOpeningPage(openedOn, state.route?.page))) hideDetail()
103
104
  else requestAnimationFrame(this.place)
104
105
  })
105
106
  this.place()
@@ -156,8 +157,9 @@ export class FigureDetailDock extends localize(i18next)(LitElement) {
156
157
  </section>` : nothing}
157
158
  </div>
158
159
  <footer><button ?disabled=${!saved} @click=${() => {
160
+ // The modeller shows the figure itself; a preview of it beside the editor only covers the work.
161
+ hideDetail()
159
162
  navigate(modellerPathOf(saved))
160
- requestAnimationFrame(() => requestAnimationFrame(this.place))
161
163
  }}>${i18next.t('figure.button.detail-edit')}</button></footer>`
162
164
  }
163
165
  }
@@ -173,6 +175,11 @@ function visibleBar(root: Document | ShadowRoot): Element | undefined {
173
175
  }
174
176
 
175
177
  let dock: FigureDetailDock | undefined
178
+ /** The page the preview was opened on; the preview belongs to that page and closes when the shell leaves it. */
179
+ let openedOn: string | undefined
180
+ export function leftOpeningPage(opened: string | undefined, current: string | undefined) {
181
+ return opened !== undefined && current !== opened
182
+ }
176
183
  function hideDetail() {
177
184
  store.dispatch({ type: UPDATE_VIEWPART, name: VIEWPART, override: { show: false } })
178
185
  }
@@ -180,6 +187,7 @@ export function openFigureDetail(figure: Figure) {
180
187
  if (!dock) {
181
188
  dock = document.createElement('figure-detail-dock') as FigureDetailDock
182
189
  }
190
+ openedOn = (store.getState() as { route?: { page?: string } }).route?.page
183
191
  store.dispatch({ type: UPDATE_VIEWPART, name: ASSISTANT_DOCK_VIEWPART, override: { show: false } })
184
192
  appendViewpart({ name: VIEWPART, position: VIEWPART_POSITION.ASIDEBAR,
185
193
  viewpart: { show: true, persistent: true, level: VIEWPART_LEVEL.TOPMOST, template: html`${dock}` } })