@things-factory/figure-library 10.1.256 → 10.1.258

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.
@@ -9,11 +9,10 @@ export declare class OxItemTypesInput extends LitElement {
9
9
  /** The rows as typed; the popup's own copy (see the note in ox-popup-value-map-input on re-rendered popups). */
10
10
  rows: ItemTypeRow[];
11
11
  confirmCallback?: (rows: ItemTypeRow[]) => void;
12
- /** The domain's item figures; null until they are read, empty when the library cannot be read or marks none. */
13
- private figures;
12
+ private itemFigures;
13
+ private choices?;
14
14
  /** Thumbnails that could not be drawn: the empty mark in their place, not a broken image. */
15
15
  private unreadThumbnails;
16
- connectedCallback(): void;
17
16
  render(): import("lit-html").TemplateResult<1>;
18
17
  private renderRow;
19
18
  updated(): void;
@@ -23,6 +22,6 @@ export declare class OxItemTypesInput extends LitElement {
23
22
  private onRemove;
24
23
  private onCancel;
25
24
  private onConfirm;
26
- /** The names the domain's library marks as items, by display name. None when the library cannot be read. */
27
- private fetchFigures;
25
+ /** The domain's item figures by display name; null until they are read, empty when the library cannot be read or marks none. */
26
+ private get figures();
28
27
  }
@@ -15,7 +15,7 @@ import '@operato/popup/ox-popup-actions.js';
15
15
  import gql from 'graphql-tag';
16
16
  import { css, html, LitElement, nothing } from 'lit';
17
17
  import { customElement, property, state } from 'lit/decorators.js';
18
- import { client } from '@operato/graphql';
18
+ import { QueryController } from '@operato/graphql';
19
19
  import { i18next } from '@operato/i18n';
20
20
  import { closePopup } from '@operato/popup';
21
21
  import { CommonPopupStyles, FormFieldStyles, PopupBodyStyles } from '@operato/styles';
@@ -48,8 +48,10 @@ let OxItemTypesInput = class OxItemTypesInput extends LitElement {
48
48
  super(...arguments);
49
49
  /** The rows as typed; the popup's own copy (see the note in ox-popup-value-map-input on re-rendered popups). */
50
50
  this.rows = [];
51
- /** The domain's item figures; null until they are read, empty when the library cannot be read or marks none. */
52
- this.figures = null;
51
+ /* The domain's item figures (ADR-0190). */
52
+ this.itemFigures = new QueryController(this, ITEM_FIGURES, {
53
+ variables: () => ({ filters: [{ name: 'item', operator: 'eq', value: true }], pagination: { page: 1, limit: ITEM_FIGURE_LIMIT } })
54
+ });
53
55
  /** Thumbnails that could not be drawn: the empty mark in their place, not a broken image. */
54
56
  this.unreadThumbnails = new Set();
55
57
  }
@@ -161,10 +163,6 @@ let OxItemTypesInput = class OxItemTypesInput extends LitElement {
161
163
  }
162
164
  `
163
165
  ]; }
164
- connectedCallback() {
165
- super.connectedCallback();
166
- this.fetchFigures();
167
- }
168
166
  render() {
169
167
  const issues = rowIssues(this.rows);
170
168
  return html `
@@ -270,27 +268,26 @@ let OxItemTypesInput = class OxItemTypesInput extends LitElement {
270
268
  this.confirmCallback?.(this.rows);
271
269
  closePopup(this);
272
270
  }
273
- /** The names the domain's library marks as items, by display name. None when the library cannot be read. */
274
- async fetchFigures() {
275
- try {
276
- const { data } = await client.query({
277
- query: ITEM_FIGURES,
278
- variables: { filters: [{ name: 'item', operator: 'eq', value: true }], pagination: { page: 1, limit: ITEM_FIGURE_LIMIT } },
279
- fetchPolicy: 'network-only'
280
- });
271
+ /** The domain's item figures by display name; null until they are read, empty when the library cannot be read or marks none. */
272
+ get figures() {
273
+ if (this.itemFigures.error)
274
+ return [];
275
+ const data = this.itemFigures.data;
276
+ if (!data)
277
+ return null;
278
+ if (this.choices?.of !== data) {
281
279
  const { contextPath } = getPathInfo(location.pathname);
282
- const items = data?.figureLibraryFigures?.items ?? [];
280
+ const items = data.figureLibraryFigures?.items ?? [];
283
281
  const labels = figureChoiceLabels(items.map((item) => ({ name: item.name, display: item.release?.name })));
284
- this.figures = items
282
+ const figures = items
285
283
  .map((item) => {
286
284
  const hash = item.release?.dependencies?.find((d) => d.role === 'thumbnail')?.hash;
287
285
  return { name: item.name, label: labels.get(item.name), thumbnail: hash ? `${contextPath}/figure-library-file/${hash}` : '' };
288
286
  })
289
287
  .sort((a, b) => a.label.localeCompare(b.label));
288
+ this.choices = { of: data, figures };
290
289
  }
291
- catch {
292
- this.figures = [];
293
- }
290
+ return this.choices.figures;
294
291
  }
295
292
  };
296
293
  __decorate([
@@ -301,10 +298,6 @@ __decorate([
301
298
  property({ type: Object }),
302
299
  __metadata("design:type", Function)
303
300
  ], OxItemTypesInput.prototype, "confirmCallback", void 0);
304
- __decorate([
305
- state(),
306
- __metadata("design:type", Object)
307
- ], OxItemTypesInput.prototype, "figures", void 0);
308
301
  __decorate([
309
302
  state(),
310
303
  __metadata("design:type", Object)
@@ -1 +1 @@
1
- {"version":3,"file":"ox-item-types-input.js","sourceRoot":"","sources":["../../client/item-types/ox-item-types-input.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AACH,OAAO,uCAAuC,CAAA;AAC9C,OAAO,qCAAqC,CAAA;AAC5C,OAAO,4BAA4B,CAAA;AACnC,OAAO,oCAAoC,CAAA;AAE3C,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAG5C,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,SAAS,EAAoB,MAAM,sBAAsB,CAAA;AAEhG,sGAAsG;AACtG,MAAM,YAAY,GAAG,GAAG,CAAA;;;;;;;;;;;;CAYvB,CAAA;AAED,yFAAyF;AACzF,MAAM,iBAAiB,GAAG,GAAG,CAAA;AAQ7B,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,OAAiC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,GAAG,EAAE,EAAE,OAAO,CAAC,CAAA;AAEpH;;;;GAIG;AAEI,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,UAAU;IAAzC;;QA8GL,gHAAgH;QACrF,SAAI,GAAkB,EAAE,CAAA;QAGnD,gHAAgH;QAC/F,YAAO,GAAwB,IAAI,CAAA;QACpD,6FAA6F;QAC5E,qBAAgB,GAAG,IAAI,GAAG,EAAU,CAAA;IA4IvD,CAAC;aAhQQ,WAAM,GAAG;QACd,iBAAiB;QACjB,eAAe;QACf,eAAe;QACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsGF;KACF,AA3GY,CA2GZ;IAWD,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAA;QACzB,IAAI,CAAC,YAAY,EAAE,CAAA;IACrB,CAAC;IAED,MAAM;QACJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,OAAO,IAAI,CAAA;;UAEL,IAAI,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,qBAAqB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;;;;;yBAK7E,CAAC,CAAC,MAAM,CAAC;yBACT,CAAC,CAAC,MAAM,CAAC;oBACd,CAAC,CAAC,QAAQ,CAAC;;;;;cAKjB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;;;yDAG3B,IAAI,CAAC,KAAK,0BAA0B,CAAC,CAAC,KAAK,CAAC;;;;UAI3F,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,wBAAwB,CAAC,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;;;+CAG5D,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;qDACrC,MAAM,CAAC,IAAI,GAAG,CAAC,WAAW,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;;KAEvH,CAAA;IACH,CAAC;IAEO,SAAS,CAAC,GAAgB,EAAE,CAAS,EAAE,MAAuB;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,CAAA;QACvD,qGAAqG;QACrG,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,MAAM,CAAA;QACjE,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3G,OAAO,IAAI,CAAA;;;YAGH,SAAS;YACT,CAAC,CAAC,IAAI,CAAA,YAAY,SAAS,kBAAkB,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK;YAChI,CAAC,CAAC,IAAI,CAAA,wBAAwB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;2BAChE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,aAAa;sBACvD;;uCAEiB,GAAG,CAAC,IAAI,aAAa,CAAC,2BAA2B,IAAI,CAAC,OAAO;uCAC7D,GAAG,CAAC,IAAI,aAAa,CAAC,2BAA2B,IAAI,CAAC,OAAO;;mCAEjE,CAAC,4BAA4B,GAAG,CAAC,MAAM,YAAY,IAAI,CAAC,OAAO;yCACzD,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,aAAa,CAAC;cAC1D,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,iBAAiB,GAAG,CAAC,MAAM,aAAa,GAAG,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC,OAAO;cACtF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,WAAW,CAAC;;;;uCAI7E,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,IAAI,CAAC,QAAQ;;;QAG1G,MAAM,CAAC,MAAM,IAAI,QAAQ;YACzB,CAAC,CAAC,IAAI,CAAA;;;gBAGE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAA,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC;gBACpE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,gBAAgB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;;gBAErE;YACR,CAAC,CAAC,OAAO;KACZ,CAAA;IACH,CAAC;IAED,sIAAsI;IACtI,OAAO;QACL,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAmB,wBAAwB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAC3F,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;YACjD,KAAK,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACpE,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,SAAS,CAAC,KAAoB;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB;YAAE,OAAO,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACpH,OAAO,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3D,CAAC;IAEO,OAAO,CAAC,CAAQ;QACtB,MAAM,KAAK,GAAG,CAAC,CAAC,MAA8C,CAAA;QAC9D,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACnC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAwB,CAAA;QAClD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACnF,CAAC;IAEO,KAAK;QACX,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;IACxC,CAAC;IAEO,QAAQ,CAAC,CAAQ;QACvB,MAAM,CAAC,GAAG,MAAM,CAAE,CAAC,CAAC,aAA6B,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC9D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IACjD,CAAC;IAEO,QAAQ;QACd,UAAU,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IAEO,SAAS;QACf,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI;YAAE,OAAM;QACrC,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjC,UAAU,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IAED,4GAA4G;IACpG,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC;YACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;gBAClC,KAAK,EAAE,YAAY;gBACnB,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE;gBAC1H,WAAW,EAAE,cAAc;aAC5B,CAAC,CAAA;YACF,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YACtD,MAAM,KAAK,GAAG,IAAI,EAAE,oBAAoB,EAAE,KAAK,IAAI,EAAE,CAAA;YACrD,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;YAC/G,IAAI,CAAC,OAAO,GAAG,KAAK;iBACjB,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE;gBACjB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,IAAI,CAAA;gBACvF,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAE,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,WAAW,wBAAwB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;YAChI,CAAC,CAAC;iBACD,IAAI,CAAC,CAAC,CAAa,EAAE,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;QAC3E,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QACnB,CAAC;IACH,CAAC;;AAjJ0B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;8CAAyB;AACvB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;yDAAgD;AAG1D;IAAhB,KAAK,EAAE;;iDAA4C;AAEnC;IAAhB,KAAK,EAAE;;0DAA6C;AArH1C,gBAAgB;IAD5B,aAAa,CAAC,qBAAqB,CAAC;GACxB,gBAAgB,CAiQ5B","sourcesContent":["/*\n * The item type table of a domain (ADR-0155), edited in a popup from a theme of type item-types (fmsim: carrier-types):\n * one row per type -- code, name, the figure it is drawn by. A type has no size; an item is drawn at the size of the\n * place it sits in (amendment 1). The figure is chosen from the names the domain's library marks as items (amendment\n * 1 E · F), shown with their thumbnails. What does not hold is said on its row by things-scene's rule and the table is\n * not confirmed until it holds; a figure written before that is no longer marked is told on its row and does not stop it.\n *\n * The words are the module's translations; an app whose items are called otherwise (fmsim: carriers) says them its own way.\n */\nimport '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\nimport '@material/web/icon/icon.js'\nimport '@operato/popup/ox-popup-actions.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { client } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { closePopup } from '@operato/popup'\nimport { CommonPopupStyles, FormFieldStyles, PopupBodyStyles } from '@operato/styles'\nimport { getPathInfo } from '@operato/utils'\nimport type { ItemTypeIssue } from '@hatiolab/things-scene'\n\nimport { emptyRow, figureChoiceLabels, rowIssues, type ItemTypeRow } from './item-types-rows.js'\n\n/* The names the domain draws as items, with the name and thumbnail of the release each draws with. */\nconst ITEM_FIGURES = gql`\n query ($filters: [Filter!], $pagination: Pagination) {\n figureLibraryFigures(filters: $filters, pagination: $pagination) {\n items {\n name\n release {\n name\n dependencies\n }\n }\n }\n }\n`\n\n/** As many item figures as one domain is expected to have; the picker lists them all. */\nconst ITEM_FIGURE_LIMIT = 500\n\ninterface ItemFigure {\n name: string\n label: string\n thumbnail: string\n}\n\nconst t = (key: string, options?: Record<string, unknown>) => i18next.t(`figure-library.item-types.${key}`, options)\n\n/*\n * The house popup (operato-application design/ui/page-standard.md 7 · 8): CommonPopupStyles' card, only the body\n * scrolls (PopupBodyStyles), native fields at the table height (FormFieldStyles small), each row's problems right under\n * it, the row's own button at its end, and cancel · confirm in ox-popup-actions.\n */\n@customElement('ox-item-types-input')\nexport class OxItemTypesInput extends LitElement {\n static styles = [\n CommonPopupStyles,\n PopupBodyStyles,\n FormFieldStyles,\n css`\n :host {\n width: 100%;\n height: 100%;\n max-height: none;\n --popup-min-width: 0;\n }\n table {\n width: 100%;\n border-collapse: collapse;\n }\n th {\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--ui-bg, #ffffff);\n text-align: left;\n font-weight: normal;\n font-size: var(--popup-font-size-small);\n color: var(--ui-muted, #57676f);\n padding: 0 var(--spacing-small, 4px) var(--spacing-small, 4px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n white-space: nowrap;\n }\n td {\n padding: var(--spacing-small, 4px);\n vertical-align: middle;\n }\n tr[type] td {\n border-top: 1px solid var(--ui-line-soft, #eef1f3);\n }\n tr[issues] td {\n padding-top: 0;\n }\n /*\n Widths by what they hold (page-standard 7): a code is an identifier such as FORMATION_TRAY, wider than a\n quantity; a type's name is a few words; the figure takes the rest.\n */\n th[code],\n td[code] {\n width: 160px;\n }\n th[name],\n td[name] {\n width: 200px;\n }\n input,\n select {\n width: 100%;\n }\n td[thumb] {\n width: 32px;\n padding-right: 0;\n }\n [thumb] img,\n [thumb] [no-thumb] {\n display: grid;\n place-items: center;\n box-sizing: border-box;\n width: 32px;\n height: 32px;\n object-fit: contain;\n border-radius: var(--md-sys-shape-corner-small, 4px);\n background: var(--md-sys-color-surface-container, #eef1f3);\n color: var(--ui-muted, #57676f);\n --md-icon-size: 16px;\n }\n td[end] {\n width: 1%;\n text-align: right;\n }\n /* A row's own button: quiet, an icon with its name in the tooltip (page-standard 8). */\n button[quiet] {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-small, 4px);\n height: var(--form-element-height-small, 26px);\n padding: 0 var(--spacing-small, 4px);\n border: 0;\n border-radius: var(--md-sys-shape-corner-small, 4px);\n background: transparent;\n color: var(--ui-muted, #57676f);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n --md-icon-size: 16px;\n }\n button[quiet]:hover {\n background: var(--ui-line-soft, #eef1f3);\n color: var(--ui-ink, #17242c);\n }\n button[quiet][add] md-icon {\n color: var(--md-sys-color-primary);\n }\n [issue] {\n color: var(--ui-crit, var(--md-sys-color-error));\n font-size: var(--popup-font-size-small);\n }\n [warning] {\n color: var(--ui-muted, #57676f);\n font-size: var(--popup-font-size-small);\n }\n `\n ]\n\n /** The rows as typed; the popup's own copy (see the note in ox-popup-value-map-input on re-rendered popups). */\n @property({ type: Array }) rows: ItemTypeRow[] = []\n @property({ type: Object }) confirmCallback?: (rows: ItemTypeRow[]) => void\n\n /** The domain's item figures; null until they are read, empty when the library cannot be read or marks none. */\n @state() private figures: ItemFigure[] | null = null\n /** Thumbnails that could not be drawn: the empty mark in their place, not a broken image. */\n @state() private unreadThumbnails = new Set<string>()\n\n connectedCallback() {\n super.connectedCallback()\n this.fetchFigures()\n }\n\n render() {\n const issues = rowIssues(this.rows)\n return html`\n <div class=\"body\">\n ${this.figures?.length === 0 ? html`<div class=\"note\">${t('no-item-figures')}</div>` : nothing}\n <table>\n <thead>\n <tr>\n <th></th>\n <th code>${t('code')}</th>\n <th name>${t('name')}</th>\n <th>${t('figure')}</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n ${this.rows.map((row, i) => this.renderRow(row, i, issues.get(i) ?? []))}\n <tr>\n <td></td>\n <td colspan=\"4\"><button quiet add @click=${this.onAdd}><md-icon>add</md-icon>${t('add')}</button></td>\n </tr>\n </tbody>\n </table>\n ${issues.size ? html`<div class=\"failure\">${t('fix-rows', { count: issues.size })}</div>` : nothing}\n </div>\n <ox-popup-actions>\n <md-text-button slot=\"cancel\" @click=${this.onCancel}>${i18next.t('button.cancel')}</md-text-button>\n <md-filled-button slot=\"confirm\" ?disabled=${issues.size > 0} @click=${this.onConfirm}>${i18next.t('button.confirm')}</md-filled-button>\n </ox-popup-actions>\n `\n }\n\n private renderRow(row: ItemTypeRow, i: number, issues: ItemTypeIssue[]) {\n const figures = this.figures ?? []\n const chosen = figures.find(f => f.name === row.figure)\n /* A figure written before that the library no longer marks as an item: kept as written, and told. */\n const unmarked = !!row.figure && this.figures !== null && !chosen\n const thumbnail = chosen?.thumbnail && !this.unreadThumbnails.has(chosen.thumbnail) ? chosen.thumbnail : ''\n return html`\n <tr type>\n <td thumb>\n ${thumbnail\n ? html`<img src=${thumbnail} alt=\"\" @error=${() => (this.unreadThumbnails = new Set([...this.unreadThumbnails, thumbnail]))} />`\n : html`<span no-thumb title=${row.figure ? t('no-thumbnail') : t('figure-none')}>\n <md-icon>${row.figure ? 'image_not_supported' : 'inventory_2'}</md-icon>\n </span>`}\n </td>\n <td code><input small .value=${row.code} data-row=${i} data-key=\"code\" @input=${this.onInput} /></td>\n <td name><input small .value=${row.name} data-row=${i} data-key=\"name\" @input=${this.onInput} /></td>\n <td>\n <select small data-row=${i} data-key=\"figure\" title=${row.figure} @change=${this.onInput}>\n <option value=\"\" ?selected=${!row.figure}>${t('figure-none')}</option>\n ${unmarked ? html`<option value=${row.figure} selected>${row.figure}</option>` : nothing}\n ${figures.map(f => html`<option value=${f.name} ?selected=${f.name === row.figure}>${f.label}</option>`)}\n </select>\n </td>\n <td end>\n <button quiet remove title=${t('remove')} aria-label=${t('remove')} data-row=${i} @click=${this.onRemove}><md-icon>delete</md-icon></button>\n </td>\n </tr>\n ${issues.length || unmarked\n ? html`<tr issues>\n <td></td>\n <td colspan=\"4\">\n ${issues.map(issue => html`<div issue>${this.issueText(issue)}</div>`)}\n ${unmarked ? html`<div warning>${t('figure-not-item')}</div>` : nothing}\n </td>\n </tr>`\n : nothing}\n `\n }\n\n /* A code that does not hold is invalid to the browser too: the shared field style outlines it once it is typed in (:user-invalid). */\n updated() {\n const issues = rowIssues(this.rows)\n this.renderRoot.querySelectorAll<HTMLInputElement>('input[data-key=\"code\"]').forEach(input => {\n const row = issues.get(Number(input.dataset.row))\n input.setCustomValidity(row?.length ? this.issueText(row[0]) : '')\n })\n }\n\n private issueText(issue: ItemTypeIssue): string {\n if (issue.code === 'item-type-duplicate') return t('issue.duplicate', { rows: issue.at.map(n => n + 1).join(', ') })\n return t(`issue.${issue.code.replace('item-type-', '')}`)\n }\n\n private onInput(e: Event) {\n const input = e.target as HTMLInputElement | HTMLSelectElement\n const i = Number(input.dataset.row)\n const key = input.dataset.key as keyof ItemTypeRow\n this.rows = this.rows.map((r, n) => (n === i ? { ...r, [key]: input.value } : r))\n }\n\n private onAdd() {\n this.rows = [...this.rows, emptyRow()]\n }\n\n private onRemove(e: Event) {\n const i = Number((e.currentTarget as HTMLElement).dataset.row)\n this.rows = this.rows.filter((_, n) => n !== i)\n }\n\n private onCancel() {\n closePopup(this)\n }\n\n private onConfirm() {\n if (rowIssues(this.rows).size) return\n this.confirmCallback?.(this.rows)\n closePopup(this)\n }\n\n /** The names the domain's library marks as items, by display name. None when the library cannot be read. */\n private async fetchFigures() {\n try {\n const { data } = await client.query({\n query: ITEM_FIGURES,\n variables: { filters: [{ name: 'item', operator: 'eq', value: true }], pagination: { page: 1, limit: ITEM_FIGURE_LIMIT } },\n fetchPolicy: 'network-only'\n })\n const { contextPath } = getPathInfo(location.pathname)\n const items = data?.figureLibraryFigures?.items ?? []\n const labels = figureChoiceLabels(items.map((item: any) => ({ name: item.name, display: item.release?.name })))\n this.figures = items\n .map((item: any) => {\n const hash = item.release?.dependencies?.find((d: any) => d.role === 'thumbnail')?.hash\n return { name: item.name, label: labels.get(item.name)!, thumbnail: hash ? `${contextPath}/figure-library-file/${hash}` : '' }\n })\n .sort((a: ItemFigure, b: ItemFigure) => a.label.localeCompare(b.label))\n } catch {\n this.figures = []\n }\n }\n}\n"]}
1
+ {"version":3,"file":"ox-item-types-input.js","sourceRoot":"","sources":["../../client/item-types/ox-item-types-input.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AACH,OAAO,uCAAuC,CAAA;AAC9C,OAAO,qCAAqC,CAAA;AAC5C,OAAO,4BAA4B,CAAA;AACnC,OAAO,oCAAoC,CAAA;AAE3C,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAG5C,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,SAAS,EAAoB,MAAM,sBAAsB,CAAA;AAEhG,sGAAsG;AACtG,MAAM,YAAY,GAAG,GAAG,CAAA;;;;;;;;;;;;CAYvB,CAAA;AAED,yFAAyF;AACzF,MAAM,iBAAiB,GAAG,GAAG,CAAA;AAQ7B,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,OAAiC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,6BAA6B,GAAG,EAAE,EAAE,OAAO,CAAC,CAAA;AAEpH;;;;GAIG;AAEI,IAAM,gBAAgB,GAAtB,MAAM,gBAAiB,SAAQ,UAAU;IAAzC;;QA8GL,gHAAgH;QACrF,SAAI,GAAkB,EAAE,CAAA;QAGnD,2CAA2C;QACnC,gBAAW,GAAG,IAAI,eAAe,CAAC,IAAI,EAAE,YAAY,EAAE;YAC5D,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,CAAC;SACnI,CAAC,CAAA;QAEF,6FAA6F;QAC5E,qBAAgB,GAAG,IAAI,GAAG,EAAU,CAAA;IAqIvD,CAAC;aA5PQ,WAAM,GAAG;QACd,iBAAiB;QACjB,eAAe;QACf,eAAe;QACf,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsGF;KACF,AA3GY,CA2GZ;IAcD,MAAM;QACJ,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,OAAO,IAAI,CAAA;;UAEL,IAAI,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,qBAAqB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;;;;;yBAK7E,CAAC,CAAC,MAAM,CAAC;yBACT,CAAC,CAAC,MAAM,CAAC;oBACd,CAAC,CAAC,QAAQ,CAAC;;;;;cAKjB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;;;yDAG3B,IAAI,CAAC,KAAK,0BAA0B,CAAC,CAAC,KAAK,CAAC;;;;UAI3F,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,wBAAwB,CAAC,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;;;+CAG5D,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;qDACrC,MAAM,CAAC,IAAI,GAAG,CAAC,WAAW,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;;KAEvH,CAAA;IACH,CAAC;IAEO,SAAS,CAAC,GAAgB,EAAE,CAAS,EAAE,MAAuB;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAA;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,CAAC,CAAA;QACvD,qGAAqG;QACrG,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,MAAM,CAAA;QACjE,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3G,OAAO,IAAI,CAAA;;;YAGH,SAAS;YACT,CAAC,CAAC,IAAI,CAAA,YAAY,SAAS,kBAAkB,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK;YAChI,CAAC,CAAC,IAAI,CAAA,wBAAwB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;2BAChE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,aAAa;sBACvD;;uCAEiB,GAAG,CAAC,IAAI,aAAa,CAAC,2BAA2B,IAAI,CAAC,OAAO;uCAC7D,GAAG,CAAC,IAAI,aAAa,CAAC,2BAA2B,IAAI,CAAC,OAAO;;mCAEjE,CAAC,4BAA4B,GAAG,CAAC,MAAM,YAAY,IAAI,CAAC,OAAO;yCACzD,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,aAAa,CAAC;cAC1D,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,iBAAiB,GAAG,CAAC,MAAM,aAAa,GAAG,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC,OAAO;cACtF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,WAAW,CAAC;;;;uCAI7E,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,IAAI,CAAC,QAAQ;;;QAG1G,MAAM,CAAC,MAAM,IAAI,QAAQ;YACzB,CAAC,CAAC,IAAI,CAAA;;;gBAGE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAA,cAAc,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC;gBACpE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAA,gBAAgB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;;gBAErE;YACR,CAAC,CAAC,OAAO;KACZ,CAAA;IACH,CAAC;IAED,sIAAsI;IACtI,OAAO;QACL,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAmB,wBAAwB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAC3F,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;YACjD,KAAK,CAAC,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACpE,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,SAAS,CAAC,KAAoB;QACpC,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB;YAAE,OAAO,CAAC,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACpH,OAAO,CAAC,CAAC,SAAS,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3D,CAAC;IAEO,OAAO,CAAC,CAAQ;QACtB,MAAM,KAAK,GAAG,CAAC,CAAC,MAA8C,CAAA;QAC9D,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACnC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAwB,CAAA;QAClD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACnF,CAAC;IAEO,KAAK;QACX,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;IACxC,CAAC;IAEO,QAAQ,CAAC,CAAQ;QACvB,MAAM,CAAC,GAAG,MAAM,CAAE,CAAC,CAAC,aAA6B,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC9D,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;IACjD,CAAC;IAEO,QAAQ;QACd,UAAU,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IAEO,SAAS;QACf,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI;YAAE,OAAM;QACrC,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjC,UAAU,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IAED,gIAAgI;IAChI,IAAY,OAAO;QACjB,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK;YAAE,OAAO,EAAE,CAAA;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAA;QAClC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QACtB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC;YAC9B,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE,CAAA;YACpD,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;YAC/G,MAAM,OAAO,GAAG,KAAK;iBAClB,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE;gBACjB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,EAAE,IAAI,CAAA;gBACvF,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAE,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,WAAW,wBAAwB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;YAChI,CAAC,CAAC;iBACD,IAAI,CAAC,CAAC,CAAa,EAAE,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;YACzE,IAAI,CAAC,OAAO,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAA;QACtC,CAAC;QACD,OAAO,IAAI,CAAC,OAAQ,CAAC,OAAO,CAAA;IAC9B,CAAC;;AA7I0B;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;;8CAAyB;AACvB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;yDAAgD;AAQ1D;IAAhB,KAAK,EAAE;;0DAA6C;AAxH1C,gBAAgB;IAD5B,aAAa,CAAC,qBAAqB,CAAC;GACxB,gBAAgB,CA6P5B","sourcesContent":["/*\n * The item type table of a domain (ADR-0155), edited in a popup from a theme of type item-types (fmsim: carrier-types):\n * one row per type -- code, name, the figure it is drawn by. A type has no size; an item is drawn at the size of the\n * place it sits in (amendment 1). The figure is chosen from the names the domain's library marks as items (amendment\n * 1 E · F), shown with their thumbnails. What does not hold is said on its row by things-scene's rule and the table is\n * not confirmed until it holds; a figure written before that is no longer marked is told on its row and does not stop it.\n *\n * The words are the module's translations; an app whose items are called otherwise (fmsim: carriers) says them its own way.\n */\nimport '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\nimport '@material/web/icon/icon.js'\nimport '@operato/popup/ox-popup-actions.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { QueryController } from '@operato/graphql'\nimport { i18next } from '@operato/i18n'\nimport { closePopup } from '@operato/popup'\nimport { CommonPopupStyles, FormFieldStyles, PopupBodyStyles } from '@operato/styles'\nimport { getPathInfo } from '@operato/utils'\nimport type { ItemTypeIssue } from '@hatiolab/things-scene'\n\nimport { emptyRow, figureChoiceLabels, rowIssues, type ItemTypeRow } from './item-types-rows.js'\n\n/* The names the domain draws as items, with the name and thumbnail of the release each draws with. */\nconst ITEM_FIGURES = gql`\n query ($filters: [Filter!], $pagination: Pagination) {\n figureLibraryFigures(filters: $filters, pagination: $pagination) {\n items {\n name\n release {\n name\n dependencies\n }\n }\n }\n }\n`\n\n/** As many item figures as one domain is expected to have; the picker lists them all. */\nconst ITEM_FIGURE_LIMIT = 500\n\ninterface ItemFigure {\n name: string\n label: string\n thumbnail: string\n}\n\nconst t = (key: string, options?: Record<string, unknown>) => i18next.t(`figure-library.item-types.${key}`, options)\n\n/*\n * The house popup (operato-application design/ui/page-standard.md 7 · 8): CommonPopupStyles' card, only the body\n * scrolls (PopupBodyStyles), native fields at the table height (FormFieldStyles small), each row's problems right under\n * it, the row's own button at its end, and cancel · confirm in ox-popup-actions.\n */\n@customElement('ox-item-types-input')\nexport class OxItemTypesInput extends LitElement {\n static styles = [\n CommonPopupStyles,\n PopupBodyStyles,\n FormFieldStyles,\n css`\n :host {\n width: 100%;\n height: 100%;\n max-height: none;\n --popup-min-width: 0;\n }\n table {\n width: 100%;\n border-collapse: collapse;\n }\n th {\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--ui-bg, #ffffff);\n text-align: left;\n font-weight: normal;\n font-size: var(--popup-font-size-small);\n color: var(--ui-muted, #57676f);\n padding: 0 var(--spacing-small, 4px) var(--spacing-small, 4px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n white-space: nowrap;\n }\n td {\n padding: var(--spacing-small, 4px);\n vertical-align: middle;\n }\n tr[type] td {\n border-top: 1px solid var(--ui-line-soft, #eef1f3);\n }\n tr[issues] td {\n padding-top: 0;\n }\n /*\n Widths by what they hold (page-standard 7): a code is an identifier such as FORMATION_TRAY, wider than a\n quantity; a type's name is a few words; the figure takes the rest.\n */\n th[code],\n td[code] {\n width: 160px;\n }\n th[name],\n td[name] {\n width: 200px;\n }\n input,\n select {\n width: 100%;\n }\n td[thumb] {\n width: 32px;\n padding-right: 0;\n }\n [thumb] img,\n [thumb] [no-thumb] {\n display: grid;\n place-items: center;\n box-sizing: border-box;\n width: 32px;\n height: 32px;\n object-fit: contain;\n border-radius: var(--md-sys-shape-corner-small, 4px);\n background: var(--md-sys-color-surface-container, #eef1f3);\n color: var(--ui-muted, #57676f);\n --md-icon-size: 16px;\n }\n td[end] {\n width: 1%;\n text-align: right;\n }\n /* A row's own button: quiet, an icon with its name in the tooltip (page-standard 8). */\n button[quiet] {\n display: inline-flex;\n align-items: center;\n gap: var(--spacing-small, 4px);\n height: var(--form-element-height-small, 26px);\n padding: 0 var(--spacing-small, 4px);\n border: 0;\n border-radius: var(--md-sys-shape-corner-small, 4px);\n background: transparent;\n color: var(--ui-muted, #57676f);\n font: inherit;\n font-weight: 600;\n cursor: pointer;\n --md-icon-size: 16px;\n }\n button[quiet]:hover {\n background: var(--ui-line-soft, #eef1f3);\n color: var(--ui-ink, #17242c);\n }\n button[quiet][add] md-icon {\n color: var(--md-sys-color-primary);\n }\n [issue] {\n color: var(--ui-crit, var(--md-sys-color-error));\n font-size: var(--popup-font-size-small);\n }\n [warning] {\n color: var(--ui-muted, #57676f);\n font-size: var(--popup-font-size-small);\n }\n `\n ]\n\n /** The rows as typed; the popup's own copy (see the note in ox-popup-value-map-input on re-rendered popups). */\n @property({ type: Array }) rows: ItemTypeRow[] = []\n @property({ type: Object }) confirmCallback?: (rows: ItemTypeRow[]) => void\n\n /* The domain's item figures (ADR-0190). */\n private itemFigures = new QueryController(this, ITEM_FIGURES, {\n variables: () => ({ filters: [{ name: 'item', operator: 'eq', value: true }], pagination: { page: 1, limit: ITEM_FIGURE_LIMIT } })\n })\n private choices?: { of: unknown; figures: ItemFigure[] }\n /** Thumbnails that could not be drawn: the empty mark in their place, not a broken image. */\n @state() private unreadThumbnails = new Set<string>()\n\n render() {\n const issues = rowIssues(this.rows)\n return html`\n <div class=\"body\">\n ${this.figures?.length === 0 ? html`<div class=\"note\">${t('no-item-figures')}</div>` : nothing}\n <table>\n <thead>\n <tr>\n <th></th>\n <th code>${t('code')}</th>\n <th name>${t('name')}</th>\n <th>${t('figure')}</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n ${this.rows.map((row, i) => this.renderRow(row, i, issues.get(i) ?? []))}\n <tr>\n <td></td>\n <td colspan=\"4\"><button quiet add @click=${this.onAdd}><md-icon>add</md-icon>${t('add')}</button></td>\n </tr>\n </tbody>\n </table>\n ${issues.size ? html`<div class=\"failure\">${t('fix-rows', { count: issues.size })}</div>` : nothing}\n </div>\n <ox-popup-actions>\n <md-text-button slot=\"cancel\" @click=${this.onCancel}>${i18next.t('button.cancel')}</md-text-button>\n <md-filled-button slot=\"confirm\" ?disabled=${issues.size > 0} @click=${this.onConfirm}>${i18next.t('button.confirm')}</md-filled-button>\n </ox-popup-actions>\n `\n }\n\n private renderRow(row: ItemTypeRow, i: number, issues: ItemTypeIssue[]) {\n const figures = this.figures ?? []\n const chosen = figures.find(f => f.name === row.figure)\n /* A figure written before that the library no longer marks as an item: kept as written, and told. */\n const unmarked = !!row.figure && this.figures !== null && !chosen\n const thumbnail = chosen?.thumbnail && !this.unreadThumbnails.has(chosen.thumbnail) ? chosen.thumbnail : ''\n return html`\n <tr type>\n <td thumb>\n ${thumbnail\n ? html`<img src=${thumbnail} alt=\"\" @error=${() => (this.unreadThumbnails = new Set([...this.unreadThumbnails, thumbnail]))} />`\n : html`<span no-thumb title=${row.figure ? t('no-thumbnail') : t('figure-none')}>\n <md-icon>${row.figure ? 'image_not_supported' : 'inventory_2'}</md-icon>\n </span>`}\n </td>\n <td code><input small .value=${row.code} data-row=${i} data-key=\"code\" @input=${this.onInput} /></td>\n <td name><input small .value=${row.name} data-row=${i} data-key=\"name\" @input=${this.onInput} /></td>\n <td>\n <select small data-row=${i} data-key=\"figure\" title=${row.figure} @change=${this.onInput}>\n <option value=\"\" ?selected=${!row.figure}>${t('figure-none')}</option>\n ${unmarked ? html`<option value=${row.figure} selected>${row.figure}</option>` : nothing}\n ${figures.map(f => html`<option value=${f.name} ?selected=${f.name === row.figure}>${f.label}</option>`)}\n </select>\n </td>\n <td end>\n <button quiet remove title=${t('remove')} aria-label=${t('remove')} data-row=${i} @click=${this.onRemove}><md-icon>delete</md-icon></button>\n </td>\n </tr>\n ${issues.length || unmarked\n ? html`<tr issues>\n <td></td>\n <td colspan=\"4\">\n ${issues.map(issue => html`<div issue>${this.issueText(issue)}</div>`)}\n ${unmarked ? html`<div warning>${t('figure-not-item')}</div>` : nothing}\n </td>\n </tr>`\n : nothing}\n `\n }\n\n /* A code that does not hold is invalid to the browser too: the shared field style outlines it once it is typed in (:user-invalid). */\n updated() {\n const issues = rowIssues(this.rows)\n this.renderRoot.querySelectorAll<HTMLInputElement>('input[data-key=\"code\"]').forEach(input => {\n const row = issues.get(Number(input.dataset.row))\n input.setCustomValidity(row?.length ? this.issueText(row[0]) : '')\n })\n }\n\n private issueText(issue: ItemTypeIssue): string {\n if (issue.code === 'item-type-duplicate') return t('issue.duplicate', { rows: issue.at.map(n => n + 1).join(', ') })\n return t(`issue.${issue.code.replace('item-type-', '')}`)\n }\n\n private onInput(e: Event) {\n const input = e.target as HTMLInputElement | HTMLSelectElement\n const i = Number(input.dataset.row)\n const key = input.dataset.key as keyof ItemTypeRow\n this.rows = this.rows.map((r, n) => (n === i ? { ...r, [key]: input.value } : r))\n }\n\n private onAdd() {\n this.rows = [...this.rows, emptyRow()]\n }\n\n private onRemove(e: Event) {\n const i = Number((e.currentTarget as HTMLElement).dataset.row)\n this.rows = this.rows.filter((_, n) => n !== i)\n }\n\n private onCancel() {\n closePopup(this)\n }\n\n private onConfirm() {\n if (rowIssues(this.rows).size) return\n this.confirmCallback?.(this.rows)\n closePopup(this)\n }\n\n /** The domain's item figures by display name; null until they are read, empty when the library cannot be read or marks none. */\n private get figures(): ItemFigure[] | null {\n if (this.itemFigures.error) return []\n const data = this.itemFigures.data\n if (!data) return null\n if (this.choices?.of !== data) {\n const { contextPath } = getPathInfo(location.pathname)\n const items = data.figureLibraryFigures?.items ?? []\n const labels = figureChoiceLabels(items.map((item: any) => ({ name: item.name, display: item.release?.name })))\n const figures = items\n .map((item: any) => {\n const hash = item.release?.dependencies?.find((d: any) => d.role === 'thumbnail')?.hash\n return { name: item.name, label: labels.get(item.name)!, thumbnail: hash ? `${contextPath}/figure-library-file/${hash}` : '' }\n })\n .sort((a: ItemFigure, b: ItemFigure) => a.label.localeCompare(b.label))\n this.choices = { of: data, figures }\n }\n return this.choices!.figures\n }\n}\n"]}