pict-section-picker 1.1.0 → 1.3.0

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.
package/README.md CHANGED
@@ -117,6 +117,62 @@ Entity-source configuration:
117
117
 
118
118
  The lower-level builders are also exposed: `createEntityDataProvider(cfg)` and `createEntityResolveValue(cfg)` return the raw functions if you want to wire them yourself.
119
119
 
120
+ ## Joined display (parent-entity context)
121
+
122
+ Sometimes a searched entity is ambiguous on its own — a `LineItem` only makes sense next to its `Project`, a `Review` next to its `Book`. Set `JoinEntity` and the picker renders a **compound** label by joining each searched row to a parent entity through a foreign key the row carries:
123
+
124
+ ```javascript
125
+ tmpPicker.createEntityPicker('ReviewPicker',
126
+ {
127
+ Entity: 'Review',
128
+ SearchFields: [ 'Summary' ],
129
+ JoinEntity: 'Book', // the parent entity to join
130
+ JoinField: 'IDBook', // the FK on the Review row -> Book
131
+ JoinEntityDisplayField: 'Title', // the Book field to show
132
+ DestinationAddress: '#ReviewPicker',
133
+ ValueAddress: 'AppData.Form.IDReview',
134
+ });
135
+ // options render as "Neuromancer - Loved it"; the Value is still IDReview.
136
+ ```
137
+
138
+ Meadow can't join in a single read, so this is **fetch-then-merge**: after each search page the picker collects the rows' unique FK ids and issues **one** `FBL~ID{JoinEntity}~INN~<ids>` request, then stitches the joined display onto every row (also exposed as `Record.JoinName` / `Record.JoinRecord` for `MapRecord` / templates). The same join resolves a pre-bound value's label on first render.
139
+
140
+ | Option | Default | Purpose |
141
+ |---|---|---|
142
+ | `JoinEntity` | — | Parent entity to join for the compound display. Setting it enables the feature. |
143
+ | `JoinField` | `ID<JoinEntity>` | The FK column **on the searched row** pointing at `JoinEntity`. |
144
+ | `JoinEntityValueField` | `ID<JoinEntity>` | The PK column on `JoinEntity` to match (the `INN` column). |
145
+ | `JoinEntityDisplayField` | `'Name'` | The `JoinEntity` field shown in the compound label. |
146
+ | `JoinEntityFirst` | `true` | `true` → `Parent - Row`; `false` → `Row - Parent`. |
147
+ | `JoinSeparator` | `' - '` | Separator between the two parts. |
148
+
149
+ The same options ride through the form-input adapter (`PictForm.JoinEntity`, …) and the pict-section-recordset entity filters (set `JoinEntity` on the clause) — so an entity filter can show parent context for its options with no host code, layered on top of either the 1:1 (direct-FK / `InternalJoin`) or 1:many (junction / `ExternalJoin`) filter relationship.
150
+
151
+ ## Tag badge (EntityTag)
152
+
153
+ Show a small code/number badge next to each option — the select2 `EntitySelector` "tag" parity. For entity pickers, `EntityTag` names the record field to badge; the picker renders it as a pill beside the label:
154
+
155
+ ```javascript
156
+ tmpPicker.createEntityPicker('PayItemPicker',
157
+ {
158
+ Entity: 'PayItem',
159
+ SearchFields: [ 'Name' ],
160
+ EntityTag: 'ItemCode', // each option shows its ItemCode as a badge
161
+ DestinationAddress: '#PayItemPicker',
162
+ ValueAddress: 'AppData.Form.IDPayItem',
163
+ });
164
+ // options render as badge + label, e.g. [201-1] Excavation
165
+ ```
166
+
167
+ Static options can carry a `Tag` directly (`{ Value, Text, Tag }`). The badge rides on the dropdown options, the selected single value, and multi-select chips alike. It composes with JoinEntity — the join folds into the label, the tag stays a separate pill.
168
+
169
+ | Option | Default | Purpose |
170
+ |---|---|---|
171
+ | `EntityTag` | — | (entity pickers) record field whose value becomes each option's `Tag` badge. |
172
+ | `TagLast` | `false` | `false` → badge before the label; `true` → after. |
173
+
174
+ Through the form-input adapter + the recordset entity filters these are `PictForm.EntityTag` / `PictForm.EntityTagLast`.
175
+
120
176
  ## Categories
121
177
 
122
178
  Give option rows an optional `Group` field and the list renders headered sections (preserving order; rows without a `Group` fall into a leading unlabeled section):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pict-section-picker",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Pict-native themeable searchable select / combobox — single & multi select, server pagination, categorized groups and creatable entries, driven by a host-agnostic async DataProvider (with a built-in Meadow EntityProvider adapter). A jQuery/select2-free replacement.",
5
5
  "main": "source/Pict-Section-Picker.js",
6
6
  "types": "types/Pict-Section-Picker.d.ts",
@@ -117,6 +117,17 @@ class PictInputTypePicker extends libPictInputExtension
117
117
  TextField: tmpPF.TextField,
118
118
  PageSize: tmpPF.PageSize || 20,
119
119
  Options: tmpPF.Options || [],
120
+ // JoinEntity compound display (1:1 / 1:many parent-entity context) — passed straight through
121
+ // to the picker's entity adapter, which fetch-then-merges the join. No-op when JoinEntity unset.
122
+ JoinEntity: tmpPF.JoinEntity,
123
+ JoinField: tmpPF.JoinField,
124
+ JoinEntityValueField: tmpPF.JoinEntityValueField,
125
+ JoinEntityDisplayField: tmpPF.JoinEntityDisplayField,
126
+ JoinEntityFirst: tmpPF.JoinEntityFirst,
127
+ JoinSeparator: tmpPF.JoinSeparator,
128
+ // EntityTag badge: the record field whose value becomes a Tag pill, ordered by EntityTagLast.
129
+ EntityTag: tmpPF.EntityTag,
130
+ TagLast: tmpPF.EntityTagLast,
120
131
  // Per-search contextual scope — the generic hook the host fills.
121
132
  BaseFilter: () => this.getContextualSearchFilters(pInput),
122
133
  OnChange: fOnChange,
@@ -31,6 +31,16 @@ const _PickerCSS = /*css*/`
31
31
  .pps-chip-x { flex: 0 0 auto; display: inline-flex; align-items: center; cursor: pointer; font-size: 0.78rem; border-radius: 4px; padding: 0.1rem; opacity: 0.7; }
32
32
  .pps-chip-x:hover { opacity: 1; background: color-mix(in srgb, var(--theme-color-brand-primary, #156dd1) 22%, transparent); }
33
33
 
34
+ /* EntityTag badge — a small code/number pill shown next to an option / chip / selected value (the
35
+ select2 EntitySelector "tag" parity). Ordering (before/after the label) is driven by the TagLast
36
+ option in the view's render state. */
37
+ .pps-tag { flex: 0 0 auto; display: inline-flex; align-items: center; font-size: 0.74rem; font-weight: 600; line-height: 1.25;
38
+ padding: 0.05rem 0.4rem; border-radius: 5px; white-space: nowrap;
39
+ background: var(--theme-color-background-tertiary, #eceef2); color: var(--theme-color-text-secondary, #45596b); }
40
+ .pps-valuebox { display: flex; align-items: center; gap: 0.4rem; min-width: 0; }
41
+ .pps-valuebox .pps-value { min-width: 0; }
42
+ .pps-option-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
43
+
34
44
  /* Transparent full-viewport backdrop: closes on outside click (no document listener). Only present
35
45
  while OPEN — otherwise a fixed full-viewport layer would swallow every click on the page. When open,
36
46
  the control is raised above it so its chips/× stay clickable; the dropdown sits above both. */
@@ -174,6 +184,20 @@ class PictProviderPicker extends libPictProvider
174
184
  * evaluated on every search — the generic hook for host-injected CONTEXTUAL scoping (project,
175
185
  * tenant, spec-year, …). The module stays agnostic; the host supplies the closure.
176
186
  * - MapRecord {function} - optional `(record) => {Value, Text}` mapper (overrides Value/TextField).
187
+ * - JoinEntity {string} - optional second entity to JOIN for a compound display (e.g. a `LineItem`
188
+ * shown with its `Project`). Each searched row must carry the FK (`JoinField`). Because Meadow
189
+ * can't join in one read, this is fetch-then-merge: after the primary page resolves, the unique
190
+ * FK ids drive ONE `FBL~ID{JoinEntity}~INN~<ids>` request, and the joined display field is
191
+ * stitched onto each row (as `Record.JoinName` / `Record.JoinRecord`) + composed into the Text.
192
+ * - JoinField {string} - the FK column ON THE SEARCHED ROW pointing at JoinEntity (default `ID{JoinEntity}`).
193
+ * - JoinEntityValueField {string} - the PK column on JoinEntity to match (default `ID{JoinEntity}`).
194
+ * - JoinEntityDisplayField {string} - the JoinEntity field to display (default `Name`).
195
+ * - JoinEntityFirst {boolean} - put the joined value first in the compound (default `true`):
196
+ * `JoinName - baseText`; when `false`, `baseText - JoinName`.
197
+ * - JoinSeparator {string} - the compound separator (default `' - '`).
198
+ * - EntityTag {string} - optional record field whose value becomes a `Tag` badge on each option
199
+ * (e.g. a `LineItem`'s `ItemNumber`). The picker view renders it as a styled badge alongside the
200
+ * label (ordering via the picker's `TagLast` option). Composes with JoinEntity (tag is outermost).
177
201
  * @return {(pSearchTerm: string, pPage: number) => Promise<{results: Array<any>, hasMore: boolean}>}
178
202
  */
179
203
  createEntityDataProvider(pConfig)
@@ -186,6 +210,8 @@ class PictProviderPicker extends libPictProvider
186
210
  const tmpSort = pConfig.Sort || false;
187
211
  const tmpBaseFilterConfig = pConfig.BaseFilter || '';
188
212
  const tmpMapRecord = (typeof pConfig.MapRecord === 'function') ? pConfig.MapRecord : false;
213
+ const tmpJoinConfig = this._resolveJoinConfig(pConfig);
214
+ const tmpEntityTagField = pConfig.EntityTag || false;
189
215
 
190
216
  return (pSearchTerm, pPage) => new Promise((resolve, reject) =>
191
217
  {
@@ -217,11 +243,117 @@ class PictProviderPicker extends libPictProvider
217
243
  {
218
244
  if (pError) { return reject(pError); }
219
245
  const tmpList = Array.isArray(pRecords) ? pRecords : [];
220
- const tmpResults = tmpList.map((pRecord) => tmpMapRecord
221
- ? tmpMapRecord(pRecord)
222
- : { Value: pRecord[tmpValueField], Text: pRecord[tmpTextField], Record: pRecord });
223
- // hasMore: a full page came back, so there is (probably) another. Avoids a Count round-trip.
224
- return resolve({ results: tmpResults, hasMore: (tmpList.length >= tmpPageSize) });
246
+ // JoinEntity (when configured): one INN fetch for the joined rows, stitched onto each
247
+ // searched row, before mapping — so the option Text can show the compound display.
248
+ this._decorateRecordsWithJoin(tmpList, tmpJoinConfig).then((pDecorated) =>
249
+ {
250
+ const tmpResults = pDecorated.map((pRecord) => tmpMapRecord
251
+ ? tmpMapRecord(pRecord)
252
+ : this._composeOption(pRecord, tmpValueField, tmpTextField, tmpJoinConfig, tmpEntityTagField));
253
+ // hasMore: a full page came back, so there is (probably) another. Avoids a Count round-trip.
254
+ return resolve({ results: tmpResults, hasMore: (tmpList.length >= tmpPageSize) });
255
+ });
256
+ });
257
+ });
258
+ }
259
+
260
+ /**
261
+ * Resolve the JoinEntity options off an entity-source config into a normalized internal shape, or
262
+ * `false` when no JoinEntity is configured. Centralizes the defaults so the DataProvider and the
263
+ * ResolveValue builders agree.
264
+ *
265
+ * @param {Record<string, any>} pConfig
266
+ * @return {false | {Entity:string, FKColumn:string, PKColumn:string, DisplayField:string, First:boolean, Separator:string}}
267
+ */
268
+ _resolveJoinConfig(pConfig)
269
+ {
270
+ if (!pConfig || !pConfig.JoinEntity) { return false; }
271
+ return {
272
+ Entity: pConfig.JoinEntity,
273
+ // The FK on the SEARCHED row, and the PK it points at on the join entity (the INN column).
274
+ FKColumn: pConfig.JoinField || `ID${pConfig.JoinEntity}`,
275
+ PKColumn: pConfig.JoinEntityValueField || `ID${pConfig.JoinEntity}`,
276
+ DisplayField: pConfig.JoinEntityDisplayField || 'Name',
277
+ // Default join-first (mirrors the documented select2 EntitySelector default).
278
+ First: (pConfig.JoinEntityFirst !== false),
279
+ Separator: (typeof pConfig.JoinSeparator === 'string') ? pConfig.JoinSeparator : ' - ',
280
+ };
281
+ }
282
+
283
+ /**
284
+ * Compose a compound display from a base text + a joined value, honoring ordering + separator.
285
+ * Falls back to just the base text when there is no joined value.
286
+ *
287
+ * @param {any} pBaseText @param {any} pJoinText @param {boolean} pFirst @param {string} pSeparator
288
+ * @return {any}
289
+ */
290
+ _composeJoinedText(pBaseText, pJoinText, pFirst, pSeparator)
291
+ {
292
+ if (pJoinText === undefined || pJoinText === null || pJoinText === '') { return pBaseText; }
293
+ const tmpBase = (pBaseText === undefined || pBaseText === null) ? '' : pBaseText;
294
+ return pFirst ? `${pJoinText}${pSeparator}${tmpBase}` : `${tmpBase}${pSeparator}${pJoinText}`;
295
+ }
296
+
297
+ /**
298
+ * Build the picker option `{ Value, Text, Record[, Tag] }` from a (possibly join-decorated) record:
299
+ * the Text honors any JoinEntity compound, and a Tag badge is added from `pTagField` when set. Shared
300
+ * by the DataProvider (per page row) and the ResolveValue (pre-bound value) so they stay consistent.
301
+ *
302
+ * @param {any} pRecord @param {string} pValueField @param {string} pTextField
303
+ * @param {false | Record<string, any>} pJoinConfig @param {string|false} pTagField
304
+ * @return {{Value:any, Text:any, Record:any, Tag?:any}}
305
+ */
306
+ _composeOption(pRecord, pValueField, pTextField, pJoinConfig, pTagField)
307
+ {
308
+ const tmpText = pJoinConfig
309
+ ? this._composeJoinedText(pRecord[pTextField], pRecord.JoinName, pJoinConfig.First, pJoinConfig.Separator)
310
+ : pRecord[pTextField];
311
+ const tmpOption = { Value: pRecord[pValueField], Text: tmpText, Record: pRecord };
312
+ if (pTagField) { tmpOption.Tag = pRecord[pTagField]; }
313
+ return tmpOption;
314
+ }
315
+
316
+ /**
317
+ * Fetch-then-merge the join entity for a page of searched records. Collects the unique FK ids the
318
+ * rows carry (`JoinConfig.FKColumn`), issues ONE `FBL~{PKColumn}~INN~<ids>` request against the join
319
+ * entity, and stitches `JoinRecord` + `JoinName` onto each searched row. Resolves the (mutated) same
320
+ * array; on any error or when there's nothing to join, resolves the records un-decorated (the Text
321
+ * gracefully degrades to the base field).
322
+ *
323
+ * @param {Array<any>} pRecords @param {false | Record<string, any>} pJoinConfig
324
+ * @return {Promise<Array<any>>}
325
+ */
326
+ _decorateRecordsWithJoin(pRecords, pJoinConfig)
327
+ {
328
+ return new Promise((resolve) =>
329
+ {
330
+ if (!pJoinConfig || !Array.isArray(pRecords) || pRecords.length < 1 || !this.pict.EntityProvider) { return resolve(pRecords); }
331
+ const tmpIDs = [];
332
+ const tmpSeen = {};
333
+ for (let i = 0; i < pRecords.length; i++)
334
+ {
335
+ const tmpID = pRecords[i][pJoinConfig.FKColumn];
336
+ if (tmpID !== undefined && tmpID !== null && tmpID !== '' && !tmpSeen[tmpID]) { tmpSeen[tmpID] = true; tmpIDs.push(tmpID); }
337
+ }
338
+ if (tmpIDs.length < 1) { return resolve(pRecords); }
339
+ const tmpFilter = `FBL~${pJoinConfig.PKColumn}~INN~${tmpIDs.join(',')}`;
340
+ this.pict.EntityProvider.getEntitySetPage(pJoinConfig.Entity, tmpFilter, 0, tmpIDs.length,
341
+ (pError, pJoinRecords) =>
342
+ {
343
+ if (pError)
344
+ {
345
+ this.pict.log.warn(`Pict-Section-Picker [${pJoinConfig.Entity}] join fetch failed; showing un-joined text.`, pError);
346
+ return resolve(pRecords);
347
+ }
348
+ const tmpMap = {};
349
+ const tmpJoinList = Array.isArray(pJoinRecords) ? pJoinRecords : [];
350
+ for (let i = 0; i < tmpJoinList.length; i++) { tmpMap[tmpJoinList[i][pJoinConfig.PKColumn]] = tmpJoinList[i]; }
351
+ for (let i = 0; i < pRecords.length; i++)
352
+ {
353
+ const tmpJoinRecord = tmpMap[pRecords[i][pJoinConfig.FKColumn]];
354
+ if (tmpJoinRecord) { pRecords[i].JoinRecord = tmpJoinRecord; pRecords[i].JoinName = tmpJoinRecord[pJoinConfig.DisplayField]; }
355
+ }
356
+ return resolve(pRecords);
225
357
  });
226
358
  });
227
359
  }
@@ -239,6 +371,8 @@ class PictProviderPicker extends libPictProvider
239
371
  const tmpValueField = pConfig.ValueField || `ID${tmpEntity}`;
240
372
  const tmpTextField = pConfig.TextField || 'Name';
241
373
  const tmpMapRecord = (typeof pConfig.MapRecord === 'function') ? pConfig.MapRecord : false;
374
+ const tmpJoinConfig = this._resolveJoinConfig(pConfig);
375
+ const tmpEntityTagField = pConfig.EntityTag || false;
242
376
 
243
377
  return (pValue) => new Promise((resolve) =>
244
378
  {
@@ -250,7 +384,20 @@ class PictProviderPicker extends libPictProvider
250
384
  (pError, pRecord) =>
251
385
  {
252
386
  if (pError || !pRecord) { return resolve(null); }
253
- return resolve(tmpMapRecord ? tmpMapRecord(pRecord) : { Value: pRecord[tmpValueField], Text: pRecord[tmpTextField], Record: pRecord });
387
+ const fFinish = () =>
388
+ {
389
+ if (tmpMapRecord) { return resolve(tmpMapRecord(pRecord)); }
390
+ return resolve(this._composeOption(pRecord, tmpValueField, tmpTextField, tmpJoinConfig, tmpEntityTagField));
391
+ };
392
+ // JoinEntity: resolve the single joined record (cached getEntity) for the compound label.
393
+ const tmpFK = tmpJoinConfig ? pRecord[tmpJoinConfig.FKColumn] : null;
394
+ if (!tmpJoinConfig || tmpFK === undefined || tmpFK === null || tmpFK === '') { return fFinish(); }
395
+ this.pict.EntityProvider.getEntity(tmpJoinConfig.Entity, tmpFK,
396
+ (pJoinError, pJoinRecord) =>
397
+ {
398
+ if (!pJoinError && pJoinRecord) { pRecord.JoinRecord = pJoinRecord; pRecord.JoinName = pJoinRecord[tmpJoinConfig.DisplayField]; }
399
+ return fFinish();
400
+ });
254
401
  });
255
402
  });
256
403
  }
@@ -20,6 +20,10 @@ const _DEFAULT_CONFIGURATION =
20
20
  Placeholder: 'Select…',
21
21
  Searchable: true,
22
22
  Options: [],
23
+ // EntityTag badge ordering: false → badge before the label (the select2 default), true → after.
24
+ // The per-option Tag value rides on each source row (`{Value, Text, Tag}`); the entity adapter
25
+ // stamps it from an `EntityTag` field name. With no Tag on a row, no badge renders.
26
+ TagLast: false,
23
27
  // Async data source (Phase 2): DataProvider(searchTerm, page) => Promise<{ results:[{Value,Text}], hasMore }>.
24
28
  // When a function, the widget searches + paginates through it instead of the static Options list.
25
29
  DataProvider: false,
@@ -74,7 +78,7 @@ const _DEFAULT_CONFIGURATION =
74
78
  {
75
79
  Hash: 'Pict-Section-Picker-Single',
76
80
  Template: /*html*/`
77
- <span class="pps-value{~NE:Record.NoValue^ pps-placeholder~}">{~D:Record.DisplayText~}</span>
81
+ <span class="pps-valuebox">{~TS:Pict-Section-Picker-Tag:Record.TagBeforeSlot~}<span class="pps-value{~NE:Record.NoValue^ pps-placeholder~}">{~D:Record.DisplayText~}</span>{~TS:Pict-Section-Picker-Tag:Record.TagAfterSlot~}</span>
78
82
  `
79
83
  },
80
84
  {
@@ -95,7 +99,7 @@ const _DEFAULT_CONFIGURATION =
95
99
  // chip never bubbles up to the control's open/close toggle.
96
100
  Hash: 'Pict-Section-Picker-Chip',
97
101
  Template: /*html*/`
98
- <span class="pps-chip"><span class="pps-chip-text">{~D:Record.Text~}</span><span class="pps-chip-x" onclick="event.stopPropagation(); _Pict.views['{~D:Record.PickerHash~}'].removeChip('{~D:Record.ValueKey~}')">{~I:Close~}</span></span>
102
+ <span class="pps-chip">{~TS:Pict-Section-Picker-Tag:Record.TagBeforeSlot~}<span class="pps-chip-text">{~D:Record.Text~}</span>{~TS:Pict-Section-Picker-Tag:Record.TagAfterSlot~}<span class="pps-chip-x" onclick="event.stopPropagation(); _Pict.views['{~D:Record.PickerHash~}'].removeChip('{~D:Record.ValueKey~}')">{~I:Close~}</span></span>
99
103
  `
100
104
  },
101
105
  {
@@ -155,8 +159,16 @@ const _DEFAULT_CONFIGURATION =
155
159
  Template: /*html*/`
156
160
  <button type="button" class="pps-option{~NE:Record.Selected^ pps-selected~}{~NE:Record.Highlight^ pps-highlight~}" onclick="_Pict.views['{~D:Record.PickerHash~}'].select('{~D:Record.ValueKey~}')">
157
161
  <span class="pps-option-check{~NE:Record.NotSelected^ pps-hidden~}">{~I:Check~}</span>
158
- <span>{~D:Record.Text~}</span>
162
+ {~TS:Pict-Section-Picker-Tag:Record.TagBeforeSlot~}<span class="pps-option-label">{~D:Record.Text~}</span>{~TS:Pict-Section-Picker-Tag:Record.TagAfterSlot~}
159
163
  </button>
164
+ `
165
+ },
166
+ {
167
+ // EntityTag badge — a small code/number pill rendered before or after the label via the
168
+ // TagBeforeSlot / TagAfterSlot single-element-array slots on each option / chip / value record.
169
+ Hash: 'Pict-Section-Picker-Tag',
170
+ Template: /*html*/`
171
+ <span class="pps-tag">{~D:Record.Tag~}</span>
160
172
  `
161
173
  },
162
174
  ],
@@ -249,7 +261,7 @@ class PictViewPicker extends libPictView
249
261
  {
250
262
  if (this._isMulti())
251
263
  {
252
- this._selectedRecords[String(pValue)] = { Value: pResolved.Value !== undefined ? pResolved.Value : pValue, Text: pResolved.Text };
264
+ this._selectedRecords[String(pValue)] = { Value: pResolved.Value !== undefined ? pResolved.Value : pValue, Text: pResolved.Text, Tag: pResolved.Tag };
253
265
  this._renderValue();
254
266
  }
255
267
  else
@@ -365,7 +377,7 @@ class PictViewPicker extends libPictView
365
377
  const tmpRow = this._sourceRows().find((pRow) => String(pRow.Value) === String(pVal));
366
378
  if (tmpRow)
367
379
  {
368
- this._selectedRecords[String(pVal)] = { Value: tmpRow.Value, Text: tmpRow.Text };
380
+ this._selectedRecords[String(pVal)] = { Value: tmpRow.Value, Text: tmpRow.Text, Tag: tmpRow.Tag };
369
381
  return;
370
382
  }
371
383
  if (this._isAsync() && typeof this.options.ResolveValue === 'function')
@@ -374,7 +386,7 @@ class PictViewPicker extends libPictView
374
386
  {
375
387
  if (pResolved && pResolved.Text)
376
388
  {
377
- this._selectedRecords[String(pVal)] = { Value: pResolved.Value !== undefined ? pResolved.Value : pVal, Text: pResolved.Text };
389
+ this._selectedRecords[String(pVal)] = { Value: pResolved.Value !== undefined ? pResolved.Value : pVal, Text: pResolved.Text, Tag: pResolved.Tag };
378
390
  if (!this._isMulti()) { this._selectedText = pResolved.Text; }
379
391
  this._renderValue();
380
392
  }
@@ -383,13 +395,29 @@ class PictViewPicker extends libPictView
383
395
  });
384
396
  }
385
397
 
386
- /** @return {Array<{Value:any, Text:string}>} The current option source rows (async results or static Options). */
398
+ /** @return {Array<{Value:any, Text:string, Tag?:any}>} The current option source rows (async results or static Options). */
387
399
  _sourceRows()
388
400
  {
389
401
  if (this._isAsync()) { return this._loadedResults; }
390
402
  return Array.isArray(this.options.Options) ? this.options.Options : [];
391
403
  }
392
404
 
405
+ /**
406
+ * Build the EntityTag before/after render slots for a record. Exactly one slot is populated (per the
407
+ * TagLast option) and only when a tag value is present, so a tag-less row renders no badge.
408
+ * @param {any} pTag @param {boolean} pTagLast
409
+ * @return {{TagBeforeSlot:Array<any>, TagAfterSlot:Array<any>}}
410
+ */
411
+ _tagSlots(pTag, pTagLast)
412
+ {
413
+ const tmpHasTag = (pTag !== undefined && pTag !== null && pTag !== '');
414
+ const tmpSlot = tmpHasTag ? [ { Tag: pTag } ] : [];
415
+ return {
416
+ TagBeforeSlot: (tmpHasTag && !pTagLast) ? tmpSlot : [],
417
+ TagAfterSlot: (tmpHasTag && pTagLast) ? tmpSlot : [],
418
+ };
419
+ }
420
+
393
421
  /**
394
422
  * (Re)compute the picker's render state into AppData: the displayed value / chips + the
395
423
  * (search-filtered) option list with selected/highlight flags.
@@ -413,17 +441,18 @@ class PictViewPicker extends libPictView
413
441
  .filter((pVal) => pVal !== undefined && pVal !== null && pVal !== '')
414
442
  .map((pVal) => String(pVal)));
415
443
 
444
+ const tmpTagLast = !!this.options.TagLast;
416
445
  tmpState.Options = tmpSource.map((pOption, pIndex) =>
417
446
  {
418
447
  const tmpIsSelected = tmpSelectedKeys.has(String(pOption.Value));
419
- return {
448
+ return Object.assign({
420
449
  PickerHash: this.options.PickerHash,
421
450
  ValueKey: String(pOption.Value),
422
451
  Text: pOption.Text,
423
452
  Selected: tmpIsSelected,
424
453
  NotSelected: !tmpIsSelected,
425
454
  Highlight: (pIndex === this._highlight),
426
- };
455
+ }, this._tagSlots(pOption.Tag, tmpTagLast));
427
456
  });
428
457
 
429
458
  // Cluster options into categories (preserving order), keyed by each source row's optional Group.
@@ -468,7 +497,9 @@ class PictViewPicker extends libPictView
468
497
  const tmpChips = tmpValues.map((pVal) =>
469
498
  {
470
499
  const tmpRecord = this._lookupRecord(pVal);
471
- return { PickerHash: this.options.PickerHash, ValueKey: String(pVal), Text: tmpRecord ? tmpRecord.Text : String(pVal) };
500
+ return Object.assign(
501
+ { PickerHash: this.options.PickerHash, ValueKey: String(pVal), Text: tmpRecord ? tmpRecord.Text : String(pVal) },
502
+ this._tagSlots(tmpRecord ? tmpRecord.Tag : undefined, tmpTagLast));
472
503
  });
473
504
  tmpState.SingleSlot = [];
474
505
  tmpState.MultiSlot = [ {
@@ -482,11 +513,11 @@ class PictViewPicker extends libPictView
482
513
  const tmpValue = this.getValue();
483
514
  const tmpHasValue = (tmpValue !== undefined && tmpValue !== null && tmpValue !== '');
484
515
  const tmpSelected = this._lookupRecord(tmpValue);
485
- tmpState.SingleSlot = [ {
516
+ tmpState.SingleSlot = [ Object.assign({
486
517
  PickerHash: this.options.PickerHash,
487
518
  DisplayText: tmpSelected ? tmpSelected.Text : (this._selectedText || (tmpHasValue ? String(tmpValue) : this.options.Placeholder)),
488
519
  NoValue: !tmpHasValue,
489
- } ];
520
+ }, this._tagSlots(tmpSelected ? tmpSelected.Tag : undefined, tmpTagLast)) ];
490
521
  tmpState.MultiSlot = [];
491
522
  }
492
523
  return tmpState;
@@ -496,7 +527,7 @@ class PictViewPicker extends libPictView
496
527
  * Find the {Value,Text} record for a value: the stored selection record (authoritative for chips /
497
528
  * async), else a row in the current source (static Options or loaded results).
498
529
  * @param {any} pValue
499
- * @return {{Value:any, Text:string}|null}
530
+ * @return {{Value:any, Text:string, Tag?:any}|null}
500
531
  */
501
532
  _lookupRecord(pValue)
502
533
  {
@@ -726,6 +757,7 @@ class PictViewPicker extends libPictView
726
757
  if (!this._isMulti())
727
758
  {
728
759
  this._selectedText = tmpOption.Text;
760
+ this._selectedRecords[String(tmpOption.Value)] = { Value: tmpOption.Value, Text: tmpOption.Text, Tag: tmpOption.Tag };
729
761
  this._setValue(tmpOption.Value);
730
762
  this._search = '';
731
763
  this._open = false;
@@ -749,7 +781,7 @@ class PictViewPicker extends libPictView
749
781
  else
750
782
  {
751
783
  tmpValues.push(tmpOption.Value);
752
- this._selectedRecords[String(pValueKey)] = { Value: tmpOption.Value, Text: tmpOption.Text };
784
+ this._selectedRecords[String(pValueKey)] = { Value: tmpOption.Value, Text: tmpOption.Text, Tag: tmpOption.Tag };
753
785
  }
754
786
  this._setValue(tmpValues);
755
787
  this._renderValue();
@@ -789,7 +821,7 @@ class PictViewPicker extends libPictView
789
821
  {
790
822
  this.options.Options.unshift(pRecord);
791
823
  }
792
- this._selectedRecords[String(pRecord.Value)] = { Value: pRecord.Value, Text: pRecord.Text };
824
+ this._selectedRecords[String(pRecord.Value)] = { Value: pRecord.Value, Text: pRecord.Text, Tag: pRecord.Tag };
793
825
 
794
826
  if (this._isMulti())
795
827
  {
@@ -27,6 +27,14 @@ declare class PictInputTypePicker extends PictInputTypePicker_base {
27
27
  TextField: any;
28
28
  PageSize: any;
29
29
  Options: any;
30
+ JoinEntity: any;
31
+ JoinField: any;
32
+ JoinEntityValueField: any;
33
+ JoinEntityDisplayField: any;
34
+ JoinEntityFirst: any;
35
+ JoinSeparator: any;
36
+ EntityTag: any;
37
+ TagLast: any;
30
38
  BaseFilter: () => string | string[];
31
39
  OnChange: any;
32
40
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Pict-Section-Picker-FormInput.d.ts","sourceRoot":"","sources":["../../source/form/Pict-Section-Picker-FormInput.js"],"names":[],"mappings":";;AAsEA;IAEC,2DAKC;IAGD,yCAAmE;IACnE,uCAA4D;IAC5D,gEAAsG;IACtG,8DAA2F;IAC3F,4DAAuG;IAEvG;;;;;;OAMG;IACH,mCAFW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAkB,MAAM,GAAC,KAAK,CAAC,MAAM,CAAC,CAWnE;IAED,4DAA4D;IAC5D;;;;;;;;;;;;;MAkBC;IAED,8FAA8F;IAC9F,wDAWC;IAED;;;;OAIG;IACH,wEAUC;IAED,2FAKC;IAED;;;;;;OAMG;IACH,0GAFY,OAAO,CAUlB;IAID,oIAMC;IAED,sIAYC;IAED,iFAMC;IAID,qEAAqE;IACrE,2EAD0D,OAAO,CAahE;IAED,gJAIC;IAED,kJAQC;IAED,wGAMC;CACD;;;;AAED;;;;;;;;;;;;;;GAcG;AACH,gDAVW,GAAG,aACH,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAOlB,OAAO,CAwBlB;AAzQD;;;;;;;GAOG;AACH,2DAJW,MAAM,iBACN,MAAM,GACL,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAoCrC;AAnDD,kCAAkC;AAClC,sCADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAO5B"}
1
+ {"version":3,"file":"Pict-Section-Picker-FormInput.d.ts","sourceRoot":"","sources":["../../source/form/Pict-Section-Picker-FormInput.js"],"names":[],"mappings":";;AAsEA;IAEC,2DAKC;IAGD,yCAAmE;IACnE,uCAA4D;IAC5D,gEAAsG;IACtG,8DAA2F;IAC3F,4DAAuG;IAEvG;;;;;;OAMG;IACH,mCAFW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAkB,MAAM,GAAC,KAAK,CAAC,MAAM,CAAC,CAWnE;IAED,4DAA4D;IAC5D;;;;;;;;;;;;;;;;;;;;;MA6BC;IAED,8FAA8F;IAC9F,wDAWC;IAED;;;;OAIG;IACH,wEAUC;IAED,2FAKC;IAED;;;;;;OAMG;IACH,0GAFY,OAAO,CAUlB;IAID,oIAMC;IAED,sIAYC;IAED,iFAMC;IAID,qEAAqE;IACrE,2EAD0D,OAAO,CAahE;IAED,gJAIC;IAED,kJAQC;IAED,wGAMC;CACD;;;;AAED;;;;;;;;;;;;;;GAcG;AACH,gDAVW,GAAG,aACH,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAOlB,OAAO,CAwBlB;AApRD;;;;;;;GAOG;AACH,2DAJW,MAAM,iBACN,MAAM,GACL,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAoCrC;AAnDD,kCAAkC;AAClC,sCADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAO5B"}
@@ -51,12 +51,76 @@ declare class PictProviderPicker extends libPictProvider {
51
51
  * evaluated on every search — the generic hook for host-injected CONTEXTUAL scoping (project,
52
52
  * tenant, spec-year, …). The module stays agnostic; the host supplies the closure.
53
53
  * - MapRecord {function} - optional `(record) => {Value, Text}` mapper (overrides Value/TextField).
54
+ * - JoinEntity {string} - optional second entity to JOIN for a compound display (e.g. a `LineItem`
55
+ * shown with its `Project`). Each searched row must carry the FK (`JoinField`). Because Meadow
56
+ * can't join in one read, this is fetch-then-merge: after the primary page resolves, the unique
57
+ * FK ids drive ONE `FBL~ID{JoinEntity}~INN~<ids>` request, and the joined display field is
58
+ * stitched onto each row (as `Record.JoinName` / `Record.JoinRecord`) + composed into the Text.
59
+ * - JoinField {string} - the FK column ON THE SEARCHED ROW pointing at JoinEntity (default `ID{JoinEntity}`).
60
+ * - JoinEntityValueField {string} - the PK column on JoinEntity to match (default `ID{JoinEntity}`).
61
+ * - JoinEntityDisplayField {string} - the JoinEntity field to display (default `Name`).
62
+ * - JoinEntityFirst {boolean} - put the joined value first in the compound (default `true`):
63
+ * `JoinName - baseText`; when `false`, `baseText - JoinName`.
64
+ * - JoinSeparator {string} - the compound separator (default `' - '`).
65
+ * - EntityTag {string} - optional record field whose value becomes a `Tag` badge on each option
66
+ * (e.g. a `LineItem`'s `ItemNumber`). The picker view renders it as a styled badge alongside the
67
+ * label (ordering via the picker's `TagLast` option). Composes with JoinEntity (tag is outermost).
54
68
  * @return {(pSearchTerm: string, pPage: number) => Promise<{results: Array<any>, hasMore: boolean}>}
55
69
  */
56
70
  createEntityDataProvider(pConfig: Record<string, any>): (pSearchTerm: string, pPage: number) => Promise<{
57
71
  results: Array<any>;
58
72
  hasMore: boolean;
59
73
  }>;
74
+ /**
75
+ * Resolve the JoinEntity options off an entity-source config into a normalized internal shape, or
76
+ * `false` when no JoinEntity is configured. Centralizes the defaults so the DataProvider and the
77
+ * ResolveValue builders agree.
78
+ *
79
+ * @param {Record<string, any>} pConfig
80
+ * @return {false | {Entity:string, FKColumn:string, PKColumn:string, DisplayField:string, First:boolean, Separator:string}}
81
+ */
82
+ _resolveJoinConfig(pConfig: Record<string, any>): false | {
83
+ Entity: string;
84
+ FKColumn: string;
85
+ PKColumn: string;
86
+ DisplayField: string;
87
+ First: boolean;
88
+ Separator: string;
89
+ };
90
+ /**
91
+ * Compose a compound display from a base text + a joined value, honoring ordering + separator.
92
+ * Falls back to just the base text when there is no joined value.
93
+ *
94
+ * @param {any} pBaseText @param {any} pJoinText @param {boolean} pFirst @param {string} pSeparator
95
+ * @return {any}
96
+ */
97
+ _composeJoinedText(pBaseText: any, pJoinText: any, pFirst: boolean, pSeparator: string): any;
98
+ /**
99
+ * Build the picker option `{ Value, Text, Record[, Tag] }` from a (possibly join-decorated) record:
100
+ * the Text honors any JoinEntity compound, and a Tag badge is added from `pTagField` when set. Shared
101
+ * by the DataProvider (per page row) and the ResolveValue (pre-bound value) so they stay consistent.
102
+ *
103
+ * @param {any} pRecord @param {string} pValueField @param {string} pTextField
104
+ * @param {false | Record<string, any>} pJoinConfig @param {string|false} pTagField
105
+ * @return {{Value:any, Text:any, Record:any, Tag?:any}}
106
+ */
107
+ _composeOption(pRecord: any, pValueField: string, pTextField: string, pJoinConfig: false | Record<string, any>, pTagField: string | false): {
108
+ Value: any;
109
+ Text: any;
110
+ Record: any;
111
+ Tag?: any;
112
+ };
113
+ /**
114
+ * Fetch-then-merge the join entity for a page of searched records. Collects the unique FK ids the
115
+ * rows carry (`JoinConfig.FKColumn`), issues ONE `FBL~{PKColumn}~INN~<ids>` request against the join
116
+ * entity, and stitches `JoinRecord` + `JoinName` onto each searched row. Resolves the (mutated) same
117
+ * array; on any error or when there's nothing to join, resolves the records un-decorated (the Text
118
+ * gracefully degrades to the base field).
119
+ *
120
+ * @param {Array<any>} pRecords @param {false | Record<string, any>} pJoinConfig
121
+ * @return {Promise<Array<any>>}
122
+ */
123
+ _decorateRecordsWithJoin(pRecords: Array<any>, pJoinConfig: false | Record<string, any>): Promise<Array<any>>;
60
124
  /**
61
125
  * Build a `ResolveValue(value) => Promise<{Value,Text}>` for an entity-backed picker, so a
62
126
  * pre-bound ID resolves to its display text on first render (fetched + cached by `getEntity`).
@@ -1 +1 @@
1
- {"version":3,"file":"Pict-Provider-Picker.d.ts","sourceRoot":"","sources":["../../source/providers/Pict-Provider-Picker.js"],"names":[],"mappings":";AAmFA;;;GAGG;AACH;IAEC,2DASC;IAED;;;;;;;;;;;;;;OAcG;IACH,0BAZW,MAAM,WAEN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAQlB,GAAG,CAqBd;IAED;;;;;;;;;;;OAWG;IACH,iCAJW,KAAK,CAAC,MAAM,CAAC,SACb,MAAM,GACL,MAAM,CAWjB;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,kCAdW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAYlB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAC,CAAC,CAkDnG;IAED;;;;;;OAMG;IACH,kCAHW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAClB,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAsBxC;IAED;;;;;;;;;OASG;IACH,gCAJW,MAAM,WACN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAClB,GAAG,CAQd;CACD;;;;;AAxMD,kCAAkC;AAClC,sCADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAO5B"}
1
+ {"version":3,"file":"Pict-Provider-Picker.d.ts","sourceRoot":"","sources":["../../source/providers/Pict-Provider-Picker.js"],"names":[],"mappings":";AA6FA;;;GAGG;AACH;IAEC,2DASC;IAED;;;;;;;;;;;;;;OAcG;IACH,0BAZW,MAAM,WAEN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAQlB,GAAG,CAqBd;IAED;;;;;;;;;;;OAWG;IACH,iCAJW,KAAK,CAAC,MAAM,CAAC,SACb,MAAM,GACL,MAAM,CAWjB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,kCA5BW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GA0BlB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAC,CAAC,CAyDnG;IAED;;;;;;;OAOG;IACH,4BAHW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAClB,KAAK,GAAG;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,QAAQ,EAAC,MAAM,CAAC;QAAC,QAAQ,EAAC,MAAM,CAAC;QAAC,YAAY,EAAC,MAAM,CAAC;QAAC,KAAK,EAAC,OAAO,CAAC;QAAC,SAAS,EAAC,MAAM,CAAA;KAAC,CAe1H;IAED;;;;;;OAMG;IACH,8BAHW,GAAG,aAAoB,GAAG,UAAoB,OAAO,cAAiB,MAAM,GAC3E,GAAG,CAOd;IAED;;;;;;;;OAQG;IACH,wBAJW,GAAG,eAAkB,MAAM,cAAsB,MAAM,eACvD,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,aAAsB,MAAM,GAAC,KAAK,GAC5D;QAAC,KAAK,EAAC,GAAG,CAAC;QAAC,IAAI,EAAC,GAAG,CAAC;QAAC,MAAM,EAAC,GAAG,CAAC;QAAC,GAAG,CAAC,EAAC,GAAG,CAAA;KAAC,CAUtD;IAED;;;;;;;;;OASG;IACH,mCAHW,KAAK,CAAC,GAAG,CAAC,eAAmB,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACvD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAmC9B;IAED;;;;;;OAMG;IACH,kCAHW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAClB,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAqCxC;IAED;;;;;;;;;OASG;IACH,gCAJW,MAAM,WACN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAClB,GAAG,CAQd;CACD;;;;;AAjVD,kCAAkC;AAClC,sCADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAO5B"}
@@ -48,11 +48,22 @@ declare class PictViewPicker extends libPictView {
48
48
  * @param {Array<any>} pValues
49
49
  */
50
50
  _seedSelectedRecords(pValues: Array<any>): void;
51
- /** @return {Array<{Value:any, Text:string}>} The current option source rows (async results or static Options). */
51
+ /** @return {Array<{Value:any, Text:string, Tag?:any}>} The current option source rows (async results or static Options). */
52
52
  _sourceRows(): Array<{
53
53
  Value: any;
54
54
  Text: string;
55
+ Tag?: any;
55
56
  }>;
57
+ /**
58
+ * Build the EntityTag before/after render slots for a record. Exactly one slot is populated (per the
59
+ * TagLast option) and only when a tag value is present, so a tag-less row renders no badge.
60
+ * @param {any} pTag @param {boolean} pTagLast
61
+ * @return {{TagBeforeSlot:Array<any>, TagAfterSlot:Array<any>}}
62
+ */
63
+ _tagSlots(pTag: any, pTagLast: boolean): {
64
+ TagBeforeSlot: Array<any>;
65
+ TagAfterSlot: Array<any>;
66
+ };
56
67
  /**
57
68
  * (Re)compute the picker's render state into AppData: the displayed value / chips + the
58
69
  * (search-filtered) option list with selected/highlight flags.
@@ -62,11 +73,12 @@ declare class PictViewPicker extends libPictView {
62
73
  * Find the {Value,Text} record for a value: the stored selection record (authoritative for chips /
63
74
  * async), else a row in the current source (static Options or loaded results).
64
75
  * @param {any} pValue
65
- * @return {{Value:any, Text:string}|null}
76
+ * @return {{Value:any, Text:string, Tag?:any}|null}
66
77
  */
67
78
  _lookupRecord(pValue: any): {
68
79
  Value: any;
69
80
  Text: string;
81
+ Tag?: any;
70
82
  } | null;
71
83
  /**
72
84
  * Load a page of results from the async DataProvider, accumulating (append) or replacing the list.
@@ -1 +1 @@
1
- {"version":3,"file":"PictView-Picker.d.ts","sourceRoot":"","sources":["../../source/views/PictView-Picker.js"],"names":[],"mappings":";AA6KA;IAEC,2DA0CC;IAlCA,sBAA2E;IAQ3E,eAAkB;IAClB,gBAAiB;IACjB,mBAAoB;IAEpB,sBAAwB;IACxB,cAAc;IACd,kBAAqB;IACrB,kBAAqB;IACrB,iBAAoB;IACpB,6BAAwB;IACxB,mBAAyB;IAGzB,eAAiB;IACjB,qBAA0B;IAc3B,6FAA6F;IAC7F,YADa,OAAO,CAInB;IAED,8EAA8E;IAC9E,YADa,OAAO,CAInB;IAED,4EAA4E;IAC5E,UADa,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAM/B;IAED,qGAAqG;IACrG,8BA+BC;IAED;;;OAGG;IACH,YAHY,GAAG,CAgBd;IAED;;;;OAIG;IACH,kBAFW,GAAG,QA6Bb;IAvBC,YAAoB;IAyBtB;;;;;;OAMG;IACH,iBAHW,GAAG,GACF,cAAc,CAqBzB;IAED;;;;OAIG;IACH,8BAFW,KAAK,CAAC,GAAG,CAAC,QA0BpB;IAED,kHAAkH;IAClH,eADa,KAAK,CAAC;QAAC,KAAK,EAAC,GAAG,CAAC;QAAC,IAAI,EAAC,MAAM,CAAA;KAAC,CAAC,CAK3C;IAED;;;OAGG;IACH,mCAgGC;IAED;;;;;OAKG;IACH,sBAHW,GAAG,GACF;QAAC,KAAK,EAAC,GAAG,CAAC;QAAC,IAAI,EAAC,MAAM,CAAA;KAAC,GAAC,IAAI,CAQxC;IAED;;;;OAIG;IACH,iBAHW,MAAM,WACN,OAAO,QA4BjB;IAWD,uCAAuC;IACvC,0BAIC;IAED,+EAA+E;IAC/E,gCAWC;IAED,kDAAkD;IAClD,aASC;IAED;;;;OAIG;IACH,qBAgCC;IAED,0DAA0D;IAC1D,iBAMC;IAED,0BAA0B;IAC1B,cAKC;IAED,6DAA6D;IAC7D,mBAIC;IAED,kFAAkF;IAClF,oBAKC;IAED;sGACkG;IAClG,qBAKC;IAED,2EAA2E;IAC3E,eADY,MAAM,QAejB;IAED,iGAAiG;IACjG,+BAgCC;IAED;;;;OAIG;IACH,kBAFW,MAAM,QA4ChB;IAED,sGAAsG;IACtG,sBADa,KAAK,CAAC;QAAC,KAAK,EAAC,GAAG,CAAC;QAAC,IAAI,EAAC,MAAM,CAAA;KAAC,CAAC,CAI3C;IAED;;;;OAIG;IACH,yBA6CC;IAED,oFAAoF;IACpF,iCAWC;CAWD;;;;;AA30BD,kCAAkC;AAClC,sCADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAyK5B"}
1
+ {"version":3,"file":"PictView-Picker.d.ts","sourceRoot":"","sources":["../../source/views/PictView-Picker.js"],"names":[],"mappings":";AAyLA;IAEC,2DA0CC;IAlCA,sBAA2E;IAQ3E,eAAkB;IAClB,gBAAiB;IACjB,mBAAoB;IAEpB,sBAAwB;IACxB,cAAc;IACd,kBAAqB;IACrB,kBAAqB;IACrB,iBAAoB;IACpB,6BAAwB;IACxB,mBAAyB;IAGzB,eAAiB;IACjB,qBAA0B;IAc3B,6FAA6F;IAC7F,YADa,OAAO,CAInB;IAED,8EAA8E;IAC9E,YADa,OAAO,CAInB;IAED,4EAA4E;IAC5E,UADa,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAM/B;IAED,qGAAqG;IACrG,8BA+BC;IAED;;;OAGG;IACH,YAHY,GAAG,CAgBd;IAED;;;;OAIG;IACH,kBAFW,GAAG,QA6Bb;IAvBC,YAAoB;IAyBtB;;;;;;OAMG;IACH,iBAHW,GAAG,GACF,cAAc,CAqBzB;IAED;;;;OAIG;IACH,8BAFW,KAAK,CAAC,GAAG,CAAC,QA0BpB;IAED,4HAA4H;IAC5H,eADa,KAAK,CAAC;QAAC,KAAK,EAAC,GAAG,CAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAC,GAAG,CAAC,EAAC,GAAG,CAAA;KAAC,CAAC,CAKrD;IAED;;;;;OAKG;IACH,gBAHW,GAAG,YAAe,OAAO,GACxB;QAAC,aAAa,EAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAAC,YAAY,EAAC,KAAK,CAAC,GAAG,CAAC,CAAA;KAAC,CAU9D;IAED;;;OAGG;IACH,mCAmGC;IAED;;;;;OAKG;IACH,sBAHW,GAAG,GACF;QAAC,KAAK,EAAC,GAAG,CAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAC,GAAG,CAAC,EAAC,GAAG,CAAA;KAAC,GAAC,IAAI,CAQlD;IAED;;;;OAIG;IACH,iBAHW,MAAM,WACN,OAAO,QA4BjB;IAWD,uCAAuC;IACvC,0BAIC;IAED,+EAA+E;IAC/E,gCAWC;IAED,kDAAkD;IAClD,aASC;IAED;;;;OAIG;IACH,qBAgCC;IAED,0DAA0D;IAC1D,iBAMC;IAED,0BAA0B;IAC1B,cAKC;IAED,6DAA6D;IAC7D,mBAIC;IAED,kFAAkF;IAClF,oBAKC;IAED;sGACkG;IAClG,qBAKC;IAED,2EAA2E;IAC3E,eADY,MAAM,QAejB;IAED,iGAAiG;IACjG,+BAgCC;IAED;;;;OAIG;IACH,kBAFW,MAAM,QA6ChB;IAED,sGAAsG;IACtG,sBADa,KAAK,CAAC;QAAC,KAAK,EAAC,GAAG,CAAC;QAAC,IAAI,EAAC,MAAM,CAAA;KAAC,CAAC,CAI3C;IAED;;;;OAIG;IACH,yBA6CC;IAED,oFAAoF;IACpF,iCAWC;CAWD;;;;;AA32BD,kCAAkC;AAClC,sCADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAqL5B"}