@things-factory/figure-ui 10.1.221 → 10.1.222

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.
@@ -4,7 +4,9 @@ declare const FigureCapabilityPanel_base: (new (...args: any[]) => LitElement) &
4
4
  /**
5
5
  * 자리·능력 — what the figure does on a board: the ladder from drawing only, to
6
6
  * holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,
7
- * so the list is the only way to find one; choosing a row selects its part, where the place is edited.
7
+ * so the list is the only way to find one; choosing a row selects its part, where the place is edited. Whether the
8
+ * figure is the look of an item a holder carries is said here too (ADR-0155 amendment 2): a tag, apart from the ladder,
9
+ * since an item may hold things as well.
8
10
  */
9
11
  export declare class FigureCapabilityPanel extends FigureCapabilityPanel_base {
10
12
  static styles: import("lit").CSSResult[];
@@ -14,6 +16,7 @@ export declare class FigureCapabilityPanel extends FigureCapabilityPanel_base {
14
16
  locked: boolean;
15
17
  render(): import("lit-html").TemplateResult<1> | typeof nothing;
16
18
  private setRung;
19
+ private setItem;
17
20
  private pick;
18
21
  }
19
22
  export {};
@@ -10,7 +10,9 @@ import { placeTerms } from '@things-factory/figure-viewer/dist-client/detail-fac
10
10
  /**
11
11
  * 자리·능력 — what the figure does on a board: the ladder from drawing only, to
12
12
  * holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,
13
- * so the list is the only way to find one; choosing a row selects its part, where the place is edited.
13
+ * so the list is the only way to find one; choosing a row selects its part, where the place is edited. Whether the
14
+ * figure is the look of an item a holder carries is said here too (ADR-0155 amendment 2): a tag, apart from the ladder,
15
+ * since an item may hold things as well.
14
16
  */
15
17
  let FigureCapabilityPanel = class FigureCapabilityPanel extends localize(i18next)(LitElement) {
16
18
  constructor() {
@@ -23,7 +25,8 @@ let FigureCapabilityPanel = class FigureCapabilityPanel extends localize(i18next
23
25
  :host {
24
26
  display: block;
25
27
  }
26
- label[rung] {
28
+ label[rung],
29
+ label[item] {
27
30
  display: flex;
28
31
  gap: 8px;
29
32
  align-items: flex-start;
@@ -32,16 +35,19 @@ let FigureCapabilityPanel = class FigureCapabilityPanel extends localize(i18next
32
35
  border-radius: 8px;
33
36
  cursor: pointer;
34
37
  }
35
- label[rung][on] {
38
+ label[rung][on],
39
+ label[item][on] {
36
40
  border-color: var(--md-sys-color-primary);
37
41
  background: var(--md-sys-color-secondary-container);
38
42
  color: var(--md-sys-color-on-secondary-container);
39
43
  }
40
- label[rung] span {
44
+ label[rung] span,
45
+ label[item] span {
41
46
  display: grid;
42
47
  gap: 2px;
43
48
  }
44
49
  label[rung] em,
50
+ label[item] em,
45
51
  p[hint],
46
52
  small {
47
53
  font-style: normal;
@@ -100,11 +106,24 @@ let FigureCapabilityPanel = class FigureCapabilityPanel extends localize(i18next
100
106
  : html `<p hint>${i18next.t('figure.text.no-places')}</p>`}
101
107
  ${places.length && rung === 'none' ? html `<p hint>${i18next.t('figure.text.place-needs-holding')}</p>` : nothing}
102
108
  </section>
109
+ <section>
110
+ <h3>${i18next.t('figure.label.item')}</h3>
111
+ <label item ?on=${!!asset.item}>
112
+ <input type="checkbox" .checked=${live(!!asset.item)} ?disabled=${this.locked} @change=${(e) => this.setItem(e.target.checked)} />
113
+ <span>
114
+ <strong>${i18next.t('figure.label.is-item')}</strong>
115
+ <em>${i18next.t('figure.text.is-item-note')}</em>
116
+ </span>
117
+ </label>
118
+ </section>
103
119
  `;
104
120
  }
105
121
  setRung(which) {
106
122
  this.dispatchEvent(new CustomEvent('part-edit', { detail: { edit: { kind: 'set-capabilities', names: [...RUNGS[which]] } }, bubbles: true, composed: true }));
107
123
  }
124
+ setItem(item) {
125
+ this.dispatchEvent(new CustomEvent('command', { detail: { action: { kind: 'set-item', item } }, bubbles: true, composed: true }));
126
+ }
108
127
  pick(part) {
109
128
  this.dispatchEvent(new CustomEvent('select-part', { detail: { id: part }, bubbles: true, composed: true }));
110
129
  }
@@ -1 +1 @@
1
- {"version":3,"file":"figure-capability-panel.js","sourceRoot":"","sources":["../../client/modeller/figure-capability-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { figureBindingsOf } from '@hatiolab/figure-model'\nimport type { FigureAsset } from '@hatiolab/figure-model'\nimport { RUNGS, rungOf, type Rung } from '@things-factory/figure-viewer/dist-client/capability-rung.js'\nimport { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'\nimport { placeTerms } from '@things-factory/figure-viewer/dist-client/detail-facts.js'\n\n/**\n * 자리·능력 — what the figure does on a board: the ladder from drawing only, to\n * holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,\n * so the list is the only way to find one; choosing a row selects its part, where the place is edited.\n */\n@customElement('figure-capability-panel')\nexport class FigureCapabilityPanel extends localize(i18next)(LitElement) {\n static styles = [SidePanelStyles, css`\n :host {\n display: block;\n }\n label[rung] {\n display: flex;\n gap: 8px;\n align-items: flex-start;\n padding: 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n cursor: pointer;\n }\n label[rung][on] {\n border-color: var(--md-sys-color-primary);\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n label[rung] span {\n display: grid;\n gap: 2px;\n }\n label[rung] em,\n p[hint],\n small {\n font-style: normal;\n margin: 0;\n color: var(--md-sys-color-on-surface-variant);\n }\n button[place] {\n display: grid;\n gap: 2px;\n text-align: left;\n padding: 6px 8px;\n font: inherit;\n color: inherit;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n background: none;\n cursor: pointer;\n }\n button[place][on] {\n border-color: var(--md-sys-color-primary);\n }\n code {\n font-size: var(--ui-t-small, 11.5px);\n color: var(--md-sys-color-on-surface-variant);\n }\n `]\n\n @property({ attribute: false }) asset?: FigureAsset\n /** The selected part, whose places are marked. */\n @property() selected = ''\n @property({ type: Boolean }) locked = false\n\n render() {\n const asset = this.asset\n if (!asset) return nothing\n const names = asset.document.capabilities.names ?? []\n const rung = rungOf(names)\n const places = figureBindingsOf(asset)\n return html`<section>\n <h3>${i18next.t('figure.label.what-this-does')}</h3>\n ${(['none', 'hold', 'flow'] as const).map(\n which => html`<label rung ?on=${rung === which}>\n <input type=\"radio\" name=\"rung\" .checked=${live(rung === which)} ?disabled=${this.locked} @change=${() => this.setRung(which)} />\n <span>\n <strong>${i18next.t(`figure.label.rung-${which}`)}</strong>\n <em>${i18next.t(`figure.text.rung-${which}-note`)}</em>\n </span>\n </label>`\n )}\n ${rung === null ? html`<p hint>${i18next.t('figure.text.capability-hand-written')}</p>` : nothing}\n ${names.length ? html`<code>${names.join(' · ')}</code>` : nothing}\n </section>\n <section>\n <h3>${i18next.t('figure.label.places')}</h3>\n ${places.length\n ? places.map(\n one => html`<button place ?on=${one.part === this.selected} @click=${() => one.part && this.pick(one.part)}>\n <strong>${one.label}</strong>\n <small>\n ${one.part ?? '?'}${one.face ? ' · ' + i18next.t('figure.label.face-' + one.face) : ''} ·\n ${placeTerms(one, (key, params) => i18next.t(key, params))}\n </small>\n </button>`\n )\n : html`<p hint>${i18next.t('figure.text.no-places')}</p>`}\n ${places.length && rung === 'none' ? html`<p hint>${i18next.t('figure.text.place-needs-holding')}</p>` : nothing}\n </section>\n `\n }\n\n private setRung(which: Rung) {\n this.dispatchEvent(new CustomEvent('part-edit', { detail: { edit: { kind: 'set-capabilities', names: [...RUNGS[which]] } }, bubbles: true, composed: true }))\n }\n\n private pick(part: string) {\n this.dispatchEvent(new CustomEvent('select-part', { detail: { id: part }, bubbles: true, composed: true }))\n }\n}\n"]}
1
+ {"version":3,"file":"figure-capability-panel.js","sourceRoot":"","sources":["../../client/modeller/figure-capability-panel.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAA;AAE7C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAEzD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAa,MAAM,8DAA8D,CAAA;AACvG,OAAO,EAAE,eAAe,EAAE,MAAM,gEAAgE,CAAA;AAChG,OAAO,EAAE,UAAU,EAAE,MAAM,2DAA2D,CAAA;AAEtF;;;;;;GAMG;AAEI,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;IAAjE;;QAwDL,kDAAkD;QACtC,aAAQ,GAAG,EAAE,CAAA;QACI,WAAM,GAAG,KAAK,CAAA;IA6D7C,CAAC;aAtHQ,WAAM,GAAG,CAAC,eAAe,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDpC,CAAC,AApDW,CAoDX;IAOF,MAAM;QACJ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACxB,IAAI,CAAC,KAAK;YAAE,OAAO,OAAO,CAAA;QAC1B,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAA;QACrD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;QAC1B,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;QACtC,OAAO,IAAI,CAAA;YACH,OAAO,CAAC,CAAC,CAAC,6BAA6B,CAAC;QAC3C,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAW,CAAC,GAAG,CACvC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAA,mBAAmB,IAAI,KAAK,KAAK;qDACD,IAAI,CAAC,IAAI,KAAK,KAAK,CAAC,cAAc,IAAI,CAAC,MAAM,YAAY,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;;sBAEjH,OAAO,CAAC,CAAC,CAAC,qBAAqB,KAAK,EAAE,CAAC;kBAC3C,OAAO,CAAC,CAAC,CAAC,oBAAoB,KAAK,OAAO,CAAC;;iBAE5C,CACV;QACC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,WAAW,OAAO,CAAC,CAAC,CAAC,qCAAqC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;QAC/F,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA,SAAS,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO;;;YAG5D,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;QACpC,MAAM,CAAC,MAAM;YACb,CAAC,CAAC,MAAM,CAAC,GAAG,CACR,GAAG,CAAC,EAAE,CAAC,IAAI,CAAA,qBAAqB,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ,WAAW,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;wBAC9F,GAAG,CAAC,KAAK;;kBAEf,GAAG,CAAC,IAAI,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,oBAAoB,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;kBACpF,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;;sBAEpD,CACX;YACH,CAAC,CAAC,IAAI,CAAA,WAAW,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,MAAM;QACzD,MAAM,CAAC,MAAM,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA,WAAW,OAAO,CAAC,CAAC,CAAC,iCAAiC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;;;YAG1G,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC;wBAClB,CAAC,CAAC,KAAK,CAAC,IAAI;0CACM,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,MAAM,YAAY,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAE,CAAC,CAAC,MAA2B,CAAC,OAAO,CAAC;;oBAE/I,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC;gBACrC,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC;;;;KAIhD,CAAA;IACH,CAAC;IAEO,OAAO,CAAC,KAAW;QACzB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC/J,CAAC;IAEO,OAAO,CAAC,IAAa;QAC3B,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IACnI,CAAC;IAEO,IAAI,CAAC,IAAY;QACvB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IAC7G,CAAC;;AA/D+B;IAA/B,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;oDAAoB;AAEvC;IAAX,QAAQ,EAAE;;uDAAc;AACI;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;;qDAAe;AA1DhC,qBAAqB;IADjC,aAAa,CAAC,yBAAyB,CAAC;GAC5B,qBAAqB,CAuHjC","sourcesContent":["import { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { figureBindingsOf } from '@hatiolab/figure-model'\nimport type { FigureAsset } from '@hatiolab/figure-model'\nimport { RUNGS, rungOf, type Rung } from '@things-factory/figure-viewer/dist-client/capability-rung.js'\nimport { SidePanelStyles } from '@things-factory/figure-viewer/dist-client/side-panel-styles.js'\nimport { placeTerms } from '@things-factory/figure-viewer/dist-client/detail-facts.js'\n\n/**\n * 자리·능력 — what the figure does on a board: the ladder from drawing only, to\n * holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,\n * so the list is the only way to find one; choosing a row selects its part, where the place is edited. Whether the\n * figure is the look of an item a holder carries is said here too (ADR-0155 amendment 2): a tag, apart from the ladder,\n * since an item may hold things as well.\n */\n@customElement('figure-capability-panel')\nexport class FigureCapabilityPanel extends localize(i18next)(LitElement) {\n static styles = [SidePanelStyles, css`\n :host {\n display: block;\n }\n label[rung],\n label[item] {\n display: flex;\n gap: 8px;\n align-items: flex-start;\n padding: 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n cursor: pointer;\n }\n label[rung][on],\n label[item][on] {\n border-color: var(--md-sys-color-primary);\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n label[rung] span,\n label[item] span {\n display: grid;\n gap: 2px;\n }\n label[rung] em,\n label[item] em,\n p[hint],\n small {\n font-style: normal;\n margin: 0;\n color: var(--md-sys-color-on-surface-variant);\n }\n button[place] {\n display: grid;\n gap: 2px;\n text-align: left;\n padding: 6px 8px;\n font: inherit;\n color: inherit;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n background: none;\n cursor: pointer;\n }\n button[place][on] {\n border-color: var(--md-sys-color-primary);\n }\n code {\n font-size: var(--ui-t-small, 11.5px);\n color: var(--md-sys-color-on-surface-variant);\n }\n `]\n\n @property({ attribute: false }) asset?: FigureAsset\n /** The selected part, whose places are marked. */\n @property() selected = ''\n @property({ type: Boolean }) locked = false\n\n render() {\n const asset = this.asset\n if (!asset) return nothing\n const names = asset.document.capabilities.names ?? []\n const rung = rungOf(names)\n const places = figureBindingsOf(asset)\n return html`<section>\n <h3>${i18next.t('figure.label.what-this-does')}</h3>\n ${(['none', 'hold', 'flow'] as const).map(\n which => html`<label rung ?on=${rung === which}>\n <input type=\"radio\" name=\"rung\" .checked=${live(rung === which)} ?disabled=${this.locked} @change=${() => this.setRung(which)} />\n <span>\n <strong>${i18next.t(`figure.label.rung-${which}`)}</strong>\n <em>${i18next.t(`figure.text.rung-${which}-note`)}</em>\n </span>\n </label>`\n )}\n ${rung === null ? html`<p hint>${i18next.t('figure.text.capability-hand-written')}</p>` : nothing}\n ${names.length ? html`<code>${names.join(' · ')}</code>` : nothing}\n </section>\n <section>\n <h3>${i18next.t('figure.label.places')}</h3>\n ${places.length\n ? places.map(\n one => html`<button place ?on=${one.part === this.selected} @click=${() => one.part && this.pick(one.part)}>\n <strong>${one.label}</strong>\n <small>\n ${one.part ?? '?'}${one.face ? ' · ' + i18next.t('figure.label.face-' + one.face) : ''} ·\n ${placeTerms(one, (key, params) => i18next.t(key, params))}\n </small>\n </button>`\n )\n : html`<p hint>${i18next.t('figure.text.no-places')}</p>`}\n ${places.length && rung === 'none' ? html`<p hint>${i18next.t('figure.text.place-needs-holding')}</p>` : nothing}\n </section>\n <section>\n <h3>${i18next.t('figure.label.item')}</h3>\n <label item ?on=${!!asset.item}>\n <input type=\"checkbox\" .checked=${live(!!asset.item)} ?disabled=${this.locked} @change=${(e: Event) => this.setItem((e.target as HTMLInputElement).checked)} />\n <span>\n <strong>${i18next.t('figure.label.is-item')}</strong>\n <em>${i18next.t('figure.text.is-item-note')}</em>\n </span>\n </label>\n </section>\n `\n }\n\n private setRung(which: Rung) {\n this.dispatchEvent(new CustomEvent('part-edit', { detail: { edit: { kind: 'set-capabilities', names: [...RUNGS[which]] } }, bubbles: true, composed: true }))\n }\n\n private setItem(item: boolean) {\n this.dispatchEvent(new CustomEvent('command', { detail: { action: { kind: 'set-item', item } }, bubbles: true, composed: true }))\n }\n\n private pick(part: string) {\n this.dispatchEvent(new CustomEvent('select-part', { detail: { id: part }, bubbles: true, composed: true }))\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { figureShapeBoundsOf, type FigureAsset, type SlotLayout, type SlotPresetSize } from '@hatiolab/figure-model';
1
+ import { type FigureAsset, type SlotLayout, type SlotPresetSize } from '@hatiolab/figure-model';
2
2
  import type { FigureRenderPart } from './renderer.js';
3
3
  export type SlotAnchorFace = 'top' | 'bottom';
4
4
  export interface SlotAnchor {
@@ -18,20 +18,13 @@ export interface SlotEditorIssue {
18
18
  path: string;
19
19
  params?: Record<string, string | number>;
20
20
  }
21
- type Body = {
22
- id: string;
23
- shape?: Parameters<typeof figureShapeBoundsOf>[0];
24
- };
25
21
  /** The figure's layout as the form and the layout, or a form to start one from on the selected part's top. */
26
22
  export declare function slotLayoutFormOf(asset: FigureAsset, part: string): {
27
23
  form: SlotLayoutForm;
28
24
  layout?: SlotLayout;
29
25
  };
30
- /** How big each anchor's face is, along the part's own X (width) and Z (depth): what the editor checks slots against. */
31
- export declare function anchorFacesOf(anchors: readonly SlotAnchor[], geometry: readonly Body[]): Record<string, {
32
- width: number;
33
- depth: number;
34
- }>;
26
+ /** How big each anchor's face is: things-scene's, the one a board's placed figure is measured with too. */
27
+ export { figureAnchorFacesOf as anchorFacesOf } from '@hatiolab/things-scene';
35
28
  /**
36
29
  * Where an author starts: the equipment presets (figure-model, ADR-0118 decision 8), laid out on this figure's anchors --
37
30
  * a one-anchor preset on the first, a twin fork on the first two. A single slot stands on a top and hangs from a bottom.
@@ -76,4 +69,3 @@ type Evaluated = {
76
69
  * place -- or hanging from it, for a tier that hangs things -- so an author sees where every slot of the rule falls.
77
70
  */
78
71
  export declare function slotMarksOf(places: readonly Evaluated[], layout: SlotLayout | undefined): FigureRenderPart[];
79
- export {};
@@ -8,7 +8,7 @@
8
8
  *
9
9
  * Kept free of Lit, i18n and the editor's element so node tests read it directly.
10
10
  */
11
- import { figureShapeBoundsOf, figureSlotLayoutOf, figureSlotLayoutIssues, slotLayoutPreset, SLOT_LAYOUT_PRESET_KEYS, SLOT_LAYOUT_PRESET_PARAMS } from '@hatiolab/figure-model';
11
+ import { figureSlotLayoutOf, figureSlotLayoutIssues, slotLayoutPreset, SLOT_LAYOUT_PRESET_KEYS, SLOT_LAYOUT_PRESET_PARAMS } from '@hatiolab/figure-model';
12
12
  /** The figure's layout as the form and the layout, or a form to start one from on the selected part's top. */
13
13
  export function slotLayoutFormOf(asset, part) {
14
14
  const had = figureSlotLayoutOf(asset);
@@ -16,18 +16,8 @@ export function slotLayoutFormOf(asset, part) {
16
16
  return { form: { label: had.label, role: had.role, anchors: had.anchors.map(a => ({ ...a, face: a.face })) }, layout: had.layout };
17
17
  return { form: { label: '', role: 'seat', anchors: part ? [{ id: part, part, face: 'top' }] : [] } };
18
18
  }
19
- /** How big each anchor's face is, along the part's own X (width) and Z (depth): what the editor checks slots against. */
20
- export function anchorFacesOf(anchors, geometry) {
21
- const out = {};
22
- for (const a of anchors) {
23
- const body = geometry.find(g => g.id === a.part);
24
- if (!body?.shape)
25
- continue;
26
- const b = figureShapeBoundsOf(body.shape);
27
- out[a.id] = { width: b.x.max - b.x.min, depth: b.z.max - b.z.min };
28
- }
29
- return out;
30
- }
19
+ /** How big each anchor's face is: things-scene's, the one a board's placed figure is measured with too. */
20
+ export { figureAnchorFacesOf as anchorFacesOf } from '@hatiolab/things-scene';
31
21
  /**
32
22
  * Where an author starts: the equipment presets (figure-model, ADR-0118 decision 8), laid out on this figure's anchors --
33
23
  * a one-anchor preset on the first, a twin fork on the first two. A single slot stands on a top and hangs from a bottom.
@@ -1 +1 @@
1
- {"version":3,"file":"slot-layout-host.js","sourceRoot":"","sources":["../../client/modeller/slot-layout-host.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What the Figure modeller gives the shared slot layout editor (`@operato/slot-layout-editor`, the one fmsim hosts too),\n * and what it makes of the editor's result (ADR-0118). The editor edits tiers and slots; the modeller owns the anchors\n * -- a part's top or bottom face, named -- and sends the whole layout as one `set-slot-layout` command.\n *\n * A figure's released slot layout is the only one there is (ADR-0118 decision 8, user): no scene or run overrides it, so\n * this host offers no \"use default\" and no per-instance value.\n *\n * Kept free of Lit, i18n and the editor's element so node tests read it directly.\n */\nimport {\n figureShapeBoundsOf,\n figureSlotLayoutOf,\n figureSlotLayoutIssues,\n slotLayoutPreset,\n SLOT_LAYOUT_PRESET_KEYS,\n SLOT_LAYOUT_PRESET_PARAMS,\n type FigureAsset,\n type SlotLayout,\n type SlotPresetSize\n} from '@hatiolab/figure-model'\nimport type { FigureRenderPart } from './renderer.js'\n\nexport type SlotAnchorFace = 'top' | 'bottom'\nexport interface SlotAnchor {\n id: string\n part: string\n face: SlotAnchorFace\n}\n/** What the panel edits besides the tiers: the layout's name, what its slots are, and the anchors they stand on. */\nexport interface SlotLayoutForm {\n label: string\n role: 'seat' | 'grip'\n anchors: SlotAnchor[]\n}\n/** A layout problem as the editor shows it: a code, where, and its values. */\nexport interface SlotEditorIssue {\n code: string\n path: string\n params?: Record<string, string | number>\n}\n\ntype Body = { id: string; shape?: Parameters<typeof figureShapeBoundsOf>[0] }\n\n/** The figure's layout as the form and the layout, or a form to start one from on the selected part's top. */\nexport function slotLayoutFormOf(asset: FigureAsset, part: string): { form: SlotLayoutForm; layout?: SlotLayout } {\n const had = figureSlotLayoutOf(asset as never)\n if (had) return { form: { label: had.label, role: had.role, anchors: had.anchors.map(a => ({ ...a, face: a.face as SlotAnchorFace })) }, layout: had.layout }\n return { form: { label: '', role: 'seat', anchors: part ? [{ id: part, part, face: 'top' }] : [] } }\n}\n\n/** How big each anchor's face is, along the part's own X (width) and Z (depth): what the editor checks slots against. */\nexport function anchorFacesOf(anchors: readonly SlotAnchor[], geometry: readonly Body[]): Record<string, { width: number; depth: number }> {\n const out: Record<string, { width: number; depth: number }> = {}\n for (const a of anchors) {\n const body = geometry.find(g => g.id === a.part)\n if (!body?.shape) continue\n const b = figureShapeBoundsOf(body.shape)\n out[a.id] = { width: b.x.max - b.x.min, depth: b.z.max - b.z.min }\n }\n return out\n}\n\n/**\n * Where an author starts: the equipment presets (figure-model, ADR-0118 decision 8), laid out on this figure's anchors --\n * a one-anchor preset on the first, a twin fork on the first two. A single slot stands on a top and hangs from a bottom.\n * The editor's own controls then make it what the equipment is.\n */\nexport function slotPresetsOf(anchors: readonly SlotAnchor[]) {\n const first = anchors[0]\n const on = { ...(first ? { anchor: first.id } : {}), ...(anchors.length >= 2 ? { forks: [anchors[0]!.id, anchors[1]!.id] as [string, string] } : {}) }\n const mount = first?.face === 'bottom' ? ('HANG' as const) : ('ON' as const)\n return SLOT_LAYOUT_PRESET_KEYS.map(key => ({\n key,\n /* The editor names a preset and its values from their keys (@operato/slot-layout-editor's own words). */\n params: SLOT_LAYOUT_PRESET_PARAMS[key].map(p => ({ key: p.key, integer: p.integer })),\n build: (size: SlotPresetSize, params: Record<string, number>) => slotLayoutPreset(key, size, params, { ...on, mount })\n }))\n}\n\n/*\n * What figure-model asks beyond the editor's own checks: every slot names the types it takes (ADR-0118 decision 5) -- the\n * editor's \"any type\" is a board's, not a figure's. The kernel's own check (`figureSlotLayoutIssues`, the one a\n * placement's override is held to as well), said before Apply rather than refused after it; the editor already shows the\n * common findings, so only the figure's own are added.\n */\nexport function figureSlotIssues(layout: SlotLayout, anchors: readonly string[] = layout.tiers.map(t => t.anchorId)): SlotEditorIssue[] {\n return figureSlotLayoutIssues(layout, anchors).filter(issue => issue.code === 'ACCEPTS_REQUIRED')\n}\n\n/** The command the panel sends: the whole layout, its anchors and its name, as one step of the history. */\nexport function slotLayoutCommandOf(form: SlotLayoutForm, layout: SlotLayout, fallbackLabel: string) {\n return {\n kind: 'set-slot-layout' as const,\n label: form.label.trim() || fallbackLabel,\n role: form.role,\n anchors: form.anchors.map(a => ({ id: a.id.trim(), part: a.part, face: a.face })),\n layout: structuredClone(layout)\n }\n}\n\n/** A new anchor's id: the part's, or the part's with a number when that is taken. */\nexport function anchorIdFor(part: string, taken: readonly string[]): string {\n if (!taken.includes(part)) return part\n let n = 2\n while (taken.includes(`${part}_${n}`)) n++\n return `${part}_${n}`\n}\n\n/* The token the canvas draws slots in: translucent, never picked, never saved. */\nexport const SLOT_MARK = '__slot'\n\ntype Evaluated = { id: string; pose: { r: number[][]; t: number[] }; region: { dimensions: number[] } | null }\n\n/**\n * The unfolded slots as boxes the canvas draws (ADR-0118 decision 4): each as big as what it allows, standing on its\n * place -- or hanging from it, for a tier that hangs things -- so an author sees where every slot of the rule falls.\n */\nexport function slotMarksOf(places: readonly Evaluated[], layout: SlotLayout | undefined) {\n if (!layout) return []\n const mountOf = new Map(layout.tiers.map(t => [t.tierNo, t.mount]))\n const marks: FigureRenderPart[] = []\n for (const p of places) {\n const slot = /^t(\\d+)_s\\d+$/.exec(p.id)\n if (!slot || !p.region) continue\n const [width, height, depth] = p.region.dimensions as [number, number, number]\n const down = mountOf.get(Number(slot[1])) === 'HANG'\n marks.push({\n id: `${SLOT_MARK}:${p.id}`,\n shape: {\n provider: 'extrude',\n dimensions: { width, height, depth },\n extrusion: { axis: 'y', section: { kind: 'rectangle', size: { x: width, z: depth } }, start: down ? -height : 0, end: down ? 0 : height }\n },\n pose: p.pose,\n material: { token: SLOT_MARK, transparent: true }\n })\n }\n return marks\n}\n"]}
1
+ {"version":3,"file":"slot-layout-host.js","sourceRoot":"","sources":["../../client/modeller/slot-layout-host.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What the Figure modeller gives the shared slot layout editor (`@operato/slot-layout-editor`, the one fmsim hosts too),\n * and what it makes of the editor's result (ADR-0118). The editor edits tiers and slots; the modeller owns the anchors\n * -- a part's top or bottom face, named -- and sends the whole layout as one `set-slot-layout` command.\n *\n * A figure's released slot layout is the only one there is (ADR-0118 decision 8, user): no scene or run overrides it, so\n * this host offers no \"use default\" and no per-instance value.\n *\n * Kept free of Lit, i18n and the editor's element so node tests read it directly.\n */\nimport {\n figureSlotLayoutOf,\n figureSlotLayoutIssues,\n slotLayoutPreset,\n SLOT_LAYOUT_PRESET_KEYS,\n SLOT_LAYOUT_PRESET_PARAMS,\n type FigureAsset,\n type SlotLayout,\n type SlotPresetSize\n} from '@hatiolab/figure-model'\nimport type { FigureRenderPart } from './renderer.js'\n\nexport type SlotAnchorFace = 'top' | 'bottom'\nexport interface SlotAnchor {\n id: string\n part: string\n face: SlotAnchorFace\n}\n/** What the panel edits besides the tiers: the layout's name, what its slots are, and the anchors they stand on. */\nexport interface SlotLayoutForm {\n label: string\n role: 'seat' | 'grip'\n anchors: SlotAnchor[]\n}\n/** A layout problem as the editor shows it: a code, where, and its values. */\nexport interface SlotEditorIssue {\n code: string\n path: string\n params?: Record<string, string | number>\n}\n\n/** The figure's layout as the form and the layout, or a form to start one from on the selected part's top. */\nexport function slotLayoutFormOf(asset: FigureAsset, part: string): { form: SlotLayoutForm; layout?: SlotLayout } {\n const had = figureSlotLayoutOf(asset as never)\n if (had) return { form: { label: had.label, role: had.role, anchors: had.anchors.map(a => ({ ...a, face: a.face as SlotAnchorFace })) }, layout: had.layout }\n return { form: { label: '', role: 'seat', anchors: part ? [{ id: part, part, face: 'top' }] : [] } }\n}\n\n/** How big each anchor's face is: things-scene's, the one a board's placed figure is measured with too. */\nexport { figureAnchorFacesOf as anchorFacesOf } from '@hatiolab/things-scene'\n\n/**\n * Where an author starts: the equipment presets (figure-model, ADR-0118 decision 8), laid out on this figure's anchors --\n * a one-anchor preset on the first, a twin fork on the first two. A single slot stands on a top and hangs from a bottom.\n * The editor's own controls then make it what the equipment is.\n */\nexport function slotPresetsOf(anchors: readonly SlotAnchor[]) {\n const first = anchors[0]\n const on = { ...(first ? { anchor: first.id } : {}), ...(anchors.length >= 2 ? { forks: [anchors[0]!.id, anchors[1]!.id] as [string, string] } : {}) }\n const mount = first?.face === 'bottom' ? ('HANG' as const) : ('ON' as const)\n return SLOT_LAYOUT_PRESET_KEYS.map(key => ({\n key,\n /* The editor names a preset and its values from their keys (@operato/slot-layout-editor's own words). */\n params: SLOT_LAYOUT_PRESET_PARAMS[key].map(p => ({ key: p.key, integer: p.integer })),\n build: (size: SlotPresetSize, params: Record<string, number>) => slotLayoutPreset(key, size, params, { ...on, mount })\n }))\n}\n\n/*\n * What figure-model asks beyond the editor's own checks: every slot names the types it takes (ADR-0118 decision 5) -- the\n * editor's \"any type\" is a board's, not a figure's. The kernel's own check (`figureSlotLayoutIssues`, the one a\n * placement's override is held to as well), said before Apply rather than refused after it; the editor already shows the\n * common findings, so only the figure's own are added.\n */\nexport function figureSlotIssues(layout: SlotLayout, anchors: readonly string[] = layout.tiers.map(t => t.anchorId)): SlotEditorIssue[] {\n return figureSlotLayoutIssues(layout, anchors).filter(issue => issue.code === 'ACCEPTS_REQUIRED')\n}\n\n/** The command the panel sends: the whole layout, its anchors and its name, as one step of the history. */\nexport function slotLayoutCommandOf(form: SlotLayoutForm, layout: SlotLayout, fallbackLabel: string) {\n return {\n kind: 'set-slot-layout' as const,\n label: form.label.trim() || fallbackLabel,\n role: form.role,\n anchors: form.anchors.map(a => ({ id: a.id.trim(), part: a.part, face: a.face })),\n layout: structuredClone(layout)\n }\n}\n\n/** A new anchor's id: the part's, or the part's with a number when that is taken. */\nexport function anchorIdFor(part: string, taken: readonly string[]): string {\n if (!taken.includes(part)) return part\n let n = 2\n while (taken.includes(`${part}_${n}`)) n++\n return `${part}_${n}`\n}\n\n/* The token the canvas draws slots in: translucent, never picked, never saved. */\nexport const SLOT_MARK = '__slot'\n\ntype Evaluated = { id: string; pose: { r: number[][]; t: number[] }; region: { dimensions: number[] } | null }\n\n/**\n * The unfolded slots as boxes the canvas draws (ADR-0118 decision 4): each as big as what it allows, standing on its\n * place -- or hanging from it, for a tier that hangs things -- so an author sees where every slot of the rule falls.\n */\nexport function slotMarksOf(places: readonly Evaluated[], layout: SlotLayout | undefined) {\n if (!layout) return []\n const mountOf = new Map(layout.tiers.map(t => [t.tierNo, t.mount]))\n const marks: FigureRenderPart[] = []\n for (const p of places) {\n const slot = /^t(\\d+)_s\\d+$/.exec(p.id)\n if (!slot || !p.region) continue\n const [width, height, depth] = p.region.dimensions as [number, number, number]\n const down = mountOf.get(Number(slot[1])) === 'HANG'\n marks.push({\n id: `${SLOT_MARK}:${p.id}`,\n shape: {\n provider: 'extrude',\n dimensions: { width, height, depth },\n extrusion: { axis: 'y', section: { kind: 'rectangle', size: { x: width, z: depth } }, start: down ? -height : 0, end: down ? 0 : height }\n },\n pose: p.pose,\n material: { token: SLOT_MARK, transparent: true }\n })\n }\n return marks\n}\n"]}