@platforma-sdk/model 1.68.4 → 1.68.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/columns/column_collection_builder.cjs +8 -2
  2. package/dist/columns/column_collection_builder.cjs.map +1 -1
  3. package/dist/columns/column_collection_builder.d.ts +14 -3
  4. package/dist/columns/column_collection_builder.d.ts.map +1 -1
  5. package/dist/columns/column_collection_builder.js +8 -2
  6. package/dist/columns/column_collection_builder.js.map +1 -1
  7. package/dist/columns/ctx_column_sources.d.ts +1 -1
  8. package/dist/columns/index.d.ts +1 -1
  9. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs +3 -5
  10. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs.map +1 -1
  11. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js +3 -5
  12. package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js.map +1 -1
  13. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +48 -49
  14. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
  15. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +5 -10
  16. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -1
  17. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +48 -49
  18. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
  19. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +16 -17
  20. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -1
  21. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts +4 -4
  22. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts.map +1 -1
  23. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js +16 -17
  24. package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -1
  25. package/dist/components/PlDataTable/createPlDataTable/utils.cjs +8 -2
  26. package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -1
  27. package/dist/components/PlDataTable/createPlDataTable/utils.js +8 -2
  28. package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -1
  29. package/dist/components/PlDatasetSelector/filter_discovery.d.ts +1 -1
  30. package/dist/index.d.ts +6 -6
  31. package/dist/labels/derive_distinct_labels.cjs +121 -50
  32. package/dist/labels/derive_distinct_labels.cjs.map +1 -1
  33. package/dist/labels/derive_distinct_labels.d.ts +30 -14
  34. package/dist/labels/derive_distinct_labels.d.ts.map +1 -1
  35. package/dist/labels/derive_distinct_labels.js +121 -50
  36. package/dist/labels/derive_distinct_labels.js.map +1 -1
  37. package/dist/labels/derive_distinct_tooltips.cjs +0 -10
  38. package/dist/labels/derive_distinct_tooltips.cjs.map +1 -1
  39. package/dist/labels/derive_distinct_tooltips.d.ts +2 -3
  40. package/dist/labels/derive_distinct_tooltips.d.ts.map +1 -1
  41. package/dist/labels/derive_distinct_tooltips.js +0 -10
  42. package/dist/labels/derive_distinct_tooltips.js.map +1 -1
  43. package/dist/labels/index.d.ts +1 -1
  44. package/dist/package.cjs +1 -1
  45. package/dist/package.js +1 -1
  46. package/package.json +5 -5
  47. package/src/columns/column_collection_builder.test.ts +0 -2
  48. package/src/columns/column_collection_builder.ts +26 -3
  49. package/src/components/PlDataTable/createPlDataTable/createPTableDefV3.ts +7 -5
  50. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +91 -76
  51. package/src/components/PlDataTable/createPlDataTable/discoverColumns.ts +31 -34
  52. package/src/components/PlDataTable/createPlDataTable/utils.test.ts +1 -1
  53. package/src/components/PlDataTable/createPlDataTable/utils.ts +11 -4
  54. package/src/labels/derive_distinct_labels.test.ts +396 -52
  55. package/src/labels/derive_distinct_labels.ts +205 -103
  56. package/src/labels/derive_distinct_tooltips.test.ts +1 -22
  57. package/src/labels/derive_distinct_tooltips.ts +1 -18
@@ -20,13 +20,7 @@ import { isEmpty } from "es-toolkit/compat";
20
20
  import type { PlDataTableFilters, PlDataTableFilterSpecLeaf, PlDataTableModel } from "../typesV5";
21
21
  import { upgradePlDataTableStateV2 } from "../state-migration";
22
22
  import type { PlDataTableStateV2 } from "../state-migration";
23
- import type {
24
- ColumnSelector,
25
- ColumnSnapshot,
26
- MatchingMode,
27
- MatchQualifications,
28
- MatchVariant,
29
- } from "../../../columns";
23
+ import type { ColumnSelector, ColumnSnapshot, ColumnVariant, MatchingMode } from "../../../columns";
30
24
  import { getAllLabelColumns, getMatchingLabelColumns } from "../labels";
31
25
  import type { DeriveLabelsOptions } from "../../../labels/derive_distinct_labels";
32
26
  import {
@@ -48,7 +42,7 @@ import { isNil, isPlainObject, throwError, type Nil } from "@milaboratories/help
48
42
  export type createPlDataTableOptionsV3 = {
49
43
  tableState?: PlDataTableStateV2;
50
44
 
51
- columns: Nil | DiscoverTableColumnOptions | TableColumnSnapshot[];
45
+ columns: Nil | DiscoverTableColumnOptions | TableColumnVariant[];
52
46
  filters?: PlDataTableFilters;
53
47
  sorting?: PTableSorting[];
54
48
  primaryJoinType?: "inner" | "full";
@@ -103,15 +97,16 @@ export function createPlDataTableV3<A, U>(
103
97
  const splited = splitDiscoveredColumns(discovered);
104
98
 
105
99
  const labelColumns = getMatchingLabelColumns(
106
- [...splited.direct, ...splited.linked],
100
+ [...splited.direct, ...splited.linked].map((v) => v.column),
107
101
  getAllLabelColumns(ctx),
108
102
  );
109
103
 
110
104
  const derivedLabels = deriveAllLabels({
111
105
  columns: discovered.map((dc) => ({
112
- id: dc.id,
113
- spec: dc.spec,
114
- linkerPath: dc.linkerPath?.map((lp) => ({ spec: lp.linker.spec })),
106
+ id: dc.column.id,
107
+ spec: dc.column.spec,
108
+ linkerPath: dc.path,
109
+ qualifications: dc.qualifications,
115
110
  })),
116
111
  labelColumns,
117
112
  deriveLabelsOptions: {
@@ -122,12 +117,11 @@ export function createPlDataTableV3<A, U>(
122
117
 
123
118
  const derivedTooltips = deriveAllTooltips({
124
119
  columns: discovered.map((dc) => ({
125
- id: dc.id,
120
+ id: dc.column.id,
126
121
  originalId: dc.originalId,
127
- spec: dc.spec,
128
- linkerPath: dc.linkerPath,
122
+ spec: dc.column.spec,
123
+ linkerPath: dc.path,
129
124
  qualifications: dc.qualifications,
130
- distinctiveQualifications: dc.distinctiveQualifications,
131
125
  })),
132
126
  });
133
127
 
@@ -146,8 +140,8 @@ export function createPlDataTableV3<A, U>(
146
140
  if (primarySnapshots.length === 0) return undefined;
147
141
 
148
142
  const columnIsAvailable = createColumnValidationById([
149
- ...annotated.direct,
150
- ...annotated.linked.flatMap((lc) => [...(lc.linkerPath ?? []).map((s) => s.linker), lc]),
143
+ ...annotated.direct.map((v) => v.column),
144
+ ...annotated.linked.flatMap((lc) => [...lc.path.map((s) => s.linker), lc.column]),
151
145
  ...annotated.labels,
152
146
  ]);
153
147
 
@@ -165,12 +159,17 @@ export function createPlDataTableV3<A, U>(
165
159
  validateSorting(sorting, columnIsAvailable);
166
160
 
167
161
  const primaryEntries: PrimaryEntry<undefined | PColumnDataUniversal>[] = primarySnapshots.map(
168
- (snap) => ({ column: resolveSnapshot(snap) }),
162
+ (v) => ({ column: resolveSnapshot(v.column) }),
163
+ );
164
+ const secondaryGroups: SecondaryGroup<undefined | PColumnDataUniversal>[] = buildSecondaryGroups(
165
+ secondarySnapshots,
166
+ annotated.linked,
167
+ annotated.labels,
169
168
  );
170
169
  const fullDef = createPTableDefV3({
171
170
  primaryJoinType,
172
171
  primary: primaryEntries,
173
- secondary: buildSecondaryGroups(secondarySnapshots, annotated.linked, annotated.labels),
172
+ secondary: secondaryGroups,
174
173
  filters,
175
174
  sorting,
176
175
  });
@@ -179,15 +178,15 @@ export function createPlDataTableV3<A, U>(
179
178
  // TODO: is workaround for dropdown suggestions.
180
179
  // Pframe have not equivalent data for columns relativly to Ptable
181
180
  const pframeHandle = ctx.createPFrame([
182
- ...annotated.direct.map(resolveSnapshot),
183
- ...annotated.linked.map(resolveSnapshot),
181
+ ...annotated.direct.map((v) => resolveSnapshot(v.column)),
182
+ ...annotated.linked.map((v) => resolveSnapshot(v.column)),
184
183
  ...annotated.labels,
185
184
  ...collectLinkerSnapshots(annotated.linked).map(resolveSnapshot),
186
185
  ]);
187
186
 
188
187
  const hiddenSpecs = state.pTableParams.hiddenColIds;
189
188
  const hiddenColumnIds = computeHiddenColumns(
190
- [...annotated.direct, ...annotated.linked],
189
+ [...annotated.direct, ...annotated.linked].map((v) => v.column),
191
190
  sorting,
192
191
  filters,
193
192
  hiddenSpecs,
@@ -216,43 +215,39 @@ export function createPlDataTableV3<A, U>(
216
215
  } satisfies PlDataTableModel;
217
216
  }
218
217
 
219
- /** A single column discovered from sources — normalized from raw ColumnSnapshot/ColumnMatch. */
220
- export type TableColumnSnapshot = ColumnSnapshot<DiscoveredPColumnId> & {
218
+ export type TableColumnVariant = ColumnVariant<DiscoveredPColumnId> & {
221
219
  readonly originalId: PObjectId;
222
220
  readonly isPrimary?: boolean;
223
- readonly linkerPath?: MatchVariant["path"];
224
- readonly qualifications?: MatchQualifications;
225
- readonly distinctiveQualifications?: MatchQualifications;
226
221
  };
227
222
 
228
223
  type SplitDiscoveredColumns = {
229
- readonly direct: TableColumnSnapshot[];
230
- readonly linked: TableColumnSnapshot[];
224
+ readonly direct: TableColumnVariant[];
225
+ readonly linked: TableColumnVariant[];
231
226
  };
232
227
 
233
228
  type AnnotatedColumnGroups = {
234
- readonly direct: TableColumnSnapshot[];
235
- readonly linked: TableColumnSnapshot[];
229
+ readonly direct: TableColumnVariant[];
230
+ readonly linked: TableColumnVariant[];
236
231
  readonly labels: PColumn<PColumnDataUniversal>[];
237
232
  };
238
233
 
239
234
  type VisibleColumns = {
240
- readonly direct: TableColumnSnapshot[];
241
- readonly linked: TableColumnSnapshot[];
235
+ readonly direct: TableColumnVariant[];
236
+ readonly linked: TableColumnVariant[];
242
237
  readonly labels: PColumn<PColumnDataUniversal>[];
243
238
  };
244
239
 
245
240
  /** Split discovered columns into direct (no linker path) and linked (with linker path). */
246
- function splitDiscoveredColumns(columns: TableColumnSnapshot[]): SplitDiscoveredColumns {
247
- const direct = columns.filter((dc) => isNil(dc.linkerPath) || dc.linkerPath.length === 0);
248
- const linked = columns.filter((dc) => !isNil(dc.linkerPath) && dc.linkerPath.length > 0);
241
+ function splitDiscoveredColumns(columns: TableColumnVariant[]): SplitDiscoveredColumns {
242
+ const direct = columns.filter((dc) => dc.path.length === 0);
243
+ const linked = columns.filter((dc) => dc.path.length > 0);
249
244
  return { direct, linked };
250
245
  }
251
246
 
252
247
  /** All linker snapshots across the given linked columns, deduped by id. */
253
- function collectLinkerSnapshots(linked: TableColumnSnapshot[]): ColumnSnapshot<PObjectId>[] {
248
+ function collectLinkerSnapshots(linked: TableColumnVariant[]): ColumnSnapshot<PObjectId>[] {
254
249
  return uniqueBy(
255
- linked.flatMap((lc) => (lc.linkerPath ?? []).map((s) => s.linker)),
250
+ linked.flatMap((lc) => lc.path.map((s) => s.linker)),
256
251
  (c) => c.id,
257
252
  );
258
253
  }
@@ -264,8 +259,8 @@ function collectLinkerSnapshots(linked: TableColumnSnapshot[]): ColumnSnapshot<P
264
259
  * column annotations via `withTableVisualAnnotations`.
265
260
  */
266
261
  function annotateColumnGroups(params: {
267
- direct: TableColumnSnapshot[];
268
- linked: TableColumnSnapshot[];
262
+ direct: TableColumnVariant[];
263
+ linked: TableColumnVariant[];
269
264
  labelColumns: PColumn<PColumnDataUniversal>[];
270
265
  derivedLabels: Record<string, string>;
271
266
  derivedTooltips: Record<string, string>;
@@ -283,8 +278,8 @@ function annotateColumnGroups(params: {
283
278
  } = params;
284
279
 
285
280
  const allColumnsForRules = [
286
- ...direct,
287
- ...linked,
281
+ ...direct.map((v) => v.column),
282
+ ...linked.map((v) => v.column),
288
283
  ...labelColumns,
289
284
  ...collectLinkerSnapshots(linked),
290
285
  ];
@@ -299,20 +294,23 @@ function annotateColumnGroups(params: {
299
294
  pframeSpec,
300
295
  );
301
296
 
302
- const directAnnotated = [
303
- withLabelAnnotations.bind(null, derivedLabels),
304
- withInfoAnnotations.bind(null, derivedTooltips),
305
- withTableVisualAnnotations.bind(null, visibilityByColId, orderByColId),
306
- ].reduce((cols, fn) => fn(cols) as TableColumnSnapshot[], direct);
307
-
308
- const linkedAnnotated = [
309
- withLabelAnnotations.bind(null, derivedLabels),
310
- withInfoAnnotations.bind(null, derivedTooltips),
311
- withHidenAxesAnnotations.bind(null),
312
- withTableVisualAnnotations.bind(null, visibilityByColId, orderByColId),
313
- (cols: TableColumnSnapshot[]) =>
314
- cols.map((lc) => ({ ...lc, linkerPath: annotateLinkerPath(derivedLabels, lc.linkerPath) })),
315
- ].reduce((cols, fn) => fn(cols) as TableColumnSnapshot[], linked);
297
+ const directAnnotated = withVariantColumns(direct, (cols) =>
298
+ withTableVisualAnnotations(
299
+ visibilityByColId,
300
+ orderByColId,
301
+ withInfoAnnotations(derivedTooltips, withLabelAnnotations(derivedLabels, cols)),
302
+ ),
303
+ );
304
+
305
+ const linkedAnnotated = withVariantColumns(linked, (cols) =>
306
+ withTableVisualAnnotations(
307
+ visibilityByColId,
308
+ orderByColId,
309
+ withHidenAxesAnnotations(
310
+ withInfoAnnotations(derivedTooltips, withLabelAnnotations(derivedLabels, cols)),
311
+ ),
312
+ ),
313
+ ).map((lc) => ({ ...lc, path: annotateLinkerPath(derivedLabels, lc.path) }));
316
314
 
317
315
  const labelColumnsAnnotated = withLabelAnnotations(derivedLabels, labelColumns);
318
316
 
@@ -322,11 +320,25 @@ function annotateColumnGroups(params: {
322
320
  labels: labelColumnsAnnotated,
323
321
  };
324
322
  }
323
+
324
+ /** Apply a snapshot-array transformation to the inner `column` of each variant. */
325
+ function withVariantColumns<V extends { readonly column: ColumnSnapshot<DiscoveredPColumnId> }>(
326
+ variants: V[],
327
+ fn: (cols: ColumnSnapshot<DiscoveredPColumnId>[]) => ColumnSnapshot<DiscoveredPColumnId>[],
328
+ ): V[] {
329
+ const cols = fn(variants.map((v) => v.column));
330
+ if (cols.length !== variants.length)
331
+ throw new Error(
332
+ `withVariantColumns: fn must preserve array length (got ${cols.length}, expected ${variants.length})`,
333
+ );
334
+ return variants.map((v, i) => ({ ...v, column: cols[i] }));
335
+ }
336
+
325
337
  function annotateLinkerPath(
326
338
  derivedLabels: Record<string, string>,
327
- path: TableColumnSnapshot["linkerPath"],
328
- ): TableColumnSnapshot["linkerPath"] {
329
- if (isNil(path) || path.length === 0) return path;
339
+ path: TableColumnVariant["path"],
340
+ ): TableColumnVariant["path"] {
341
+ if (path.length === 0) return path;
330
342
  const annotatedLinkers = withHidenAxesAnnotations(
331
343
  withLabelAnnotations(
332
344
  derivedLabels,
@@ -403,27 +415,27 @@ function validateSorting(sorting: PTableSorting[], isValidColumnId: (id: string)
403
415
  }
404
416
 
405
417
  function buildSecondaryGroups(
406
- direct: TableColumnSnapshot[],
407
- linked: TableColumnSnapshot[],
418
+ direct: TableColumnVariant[],
419
+ linked: TableColumnVariant[],
408
420
  labels: PColumn<PColumnDataUniversal>[],
409
421
  ): SecondaryGroup<undefined | PColumnDataUniversal>[] {
410
422
  return [
411
423
  ...direct.map(
412
424
  (c): SecondaryGroup<undefined | PColumnDataUniversal> => ({
413
- entries: [{ column: resolveSnapshot(c), qualifications: c.qualifications?.forHit }],
414
- primaryQualifications: c.qualifications?.forQueries,
425
+ entries: [{ column: resolveSnapshot(c.column), qualifications: c.qualifications.forHit }],
426
+ primaryQualifications: c.qualifications.forQueries,
415
427
  }),
416
428
  ),
417
429
  ...linked.map(
418
430
  (lc): SecondaryGroup<undefined | PColumnDataUniversal> => ({
419
431
  entries: [
420
- ...(lc.linkerPath ?? []).map((s) => ({
432
+ ...lc.path.map((s) => ({
421
433
  column: resolveSnapshot(s.linker),
422
434
  qualifications: s.qualifications,
423
435
  })),
424
- { column: resolveSnapshot(lc), qualifications: lc.qualifications?.forHit },
436
+ { column: resolveSnapshot(lc.column), qualifications: lc.qualifications.forHit },
425
437
  ],
426
- primaryQualifications: lc.qualifications?.forQueries,
438
+ primaryQualifications: lc.qualifications.forQueries,
427
439
  }),
428
440
  ),
429
441
  ...labels.map(
@@ -475,9 +487,12 @@ function buildVisibleColumns(
475
487
  hiddenColumns: Set<PObjectId>,
476
488
  originalLabelColumns: PColumn<PColumnDataUniversal>[],
477
489
  ): VisibleColumns {
478
- const direct = annotated.direct.filter((c) => !hiddenColumns.has(c.id));
479
- const linked = annotated.linked.filter((c) => !hiddenColumns.has(c.id));
480
- const labels = getMatchingLabelColumns([...direct, ...linked], originalLabelColumns);
490
+ const direct = annotated.direct.filter((c) => !hiddenColumns.has(c.column.id));
491
+ const linked = annotated.linked.filter((c) => !hiddenColumns.has(c.column.id));
492
+ const labels = getMatchingLabelColumns(
493
+ [...direct, ...linked].map((v) => v.column),
494
+ originalLabelColumns,
495
+ );
481
496
  return { direct, linked, labels };
482
497
  }
483
498
 
@@ -491,21 +506,21 @@ function resolveSnapshot(
491
506
  /** Remap column references in sorting entries. */
492
507
  function remapSortingColumnIds(
493
508
  sorting: Nil | PTableSorting[],
494
- columns: TableColumnSnapshot[],
509
+ columns: TableColumnVariant[],
495
510
  ): Nil | PTableSorting[] {
496
511
  return sorting?.map((s) => {
497
512
  if (s.column.type === "axis") return s; // Axis references are unaffected by column ID remapping
498
513
 
499
514
  const id = s.column.id;
500
515
  const column =
501
- columns.find((c) => (c.originalId ?? c.id) === id) ??
516
+ columns.find((c) => (c.originalId ?? c.column.id) === id) ??
502
517
  throwError(`Column ID "${id}" in sorting does not match any discovered column`);
503
518
 
504
519
  return {
505
520
  ...s,
506
521
  column: {
507
522
  type: "column",
508
- id: column.id,
523
+ id: column.column.id,
509
524
  },
510
525
  };
511
526
  });
@@ -516,7 +531,7 @@ type PlDataTableFilterNode = FilterSpecNode<PlDataTableFilterSpecLeaf>;
516
531
  /** Remap column references in a filter tree. */
517
532
  function remapFilterColumnIds(
518
533
  filters: Nil | PlDataTableFilters,
519
- columns: TableColumnSnapshot[],
534
+ columns: TableColumnVariant[],
520
535
  ): Nil | PlDataTableFilters {
521
536
  if (isNil(filters)) return filters;
522
537
 
@@ -528,12 +543,12 @@ function remapFilterColumnIds(
528
543
 
529
544
  const originalId = parsed.id;
530
545
  const column =
531
- columns.find((c) => (c.originalId ?? c.id) === originalId) ??
546
+ columns.find((c) => (c.originalId ?? c.column.id) === originalId) ??
532
547
  throwError(`Column ID "${parsed.id}" in filters does not match any discovered column`);
533
548
 
534
549
  return canonicalizeJson<PTableColumnId>({
535
550
  type: "column",
536
- id: column.id,
551
+ id: column.column.id,
537
552
  });
538
553
  };
539
554
 
@@ -3,7 +3,7 @@ import { createDiscoveredPColumnId, isPlRef } from "@milaboratories/pl-model-com
3
3
  import type { RenderCtxBase } from "../../../render";
4
4
  import type {
5
5
  ColumnSource,
6
- ColumnMatch,
6
+ ColumnVariant,
7
7
  RelaxedColumnSelector,
8
8
  ColumnSnapshotProvider,
9
9
  ColumnSnapshot,
@@ -12,7 +12,7 @@ import { ColumnCollectionBuilder } from "../../../columns";
12
12
  import { toColumnSnapshotProvider } from "../../../columns/column_snapshot_provider";
13
13
  import { collectCtxColumnSnapshotProviders } from "../../../columns/ctx_column_sources";
14
14
  import { throwError } from "@milaboratories/helpers";
15
- import type { ColumnsSelectorConfig, TableColumnSnapshot } from "./createPlDataTableV3";
15
+ import type { ColumnsSelectorConfig, TableColumnVariant } from "./createPlDataTableV3";
16
16
  import { isNil } from "es-toolkit";
17
17
 
18
18
  export type DiscoverTableColumnOptions = {
@@ -21,11 +21,11 @@ export type DiscoverTableColumnOptions = {
21
21
  selector: ColumnsSelectorConfig;
22
22
  };
23
23
 
24
- /** Discover columns from sources/anchors and normalize into a flat DiscoveredColumn list. */
24
+ /** Discover columns from sources/anchors and normalize into a flat TableColumnVariant list. */
25
25
  export function discoverTableColumnSnaphots(
26
26
  ctx: RenderCtxBase,
27
27
  options: DiscoverTableColumnOptions,
28
- ): TableColumnSnapshot[] | undefined {
28
+ ): TableColumnVariant[] | undefined {
29
29
  // Resolve PlRef anchors to PColumnSpec
30
30
  const resolvedOptions = {
31
31
  ...options,
@@ -43,7 +43,7 @@ export function discoverTableColumnSnaphots(
43
43
  if (collection === undefined) return undefined;
44
44
 
45
45
  try {
46
- const columns = collection.findColumns({
46
+ const variants = collection.findColumnVariants({
47
47
  ...(resolvedOptions.selector ?? {}),
48
48
  exclude: [
49
49
  ...(Array.isArray(resolvedOptions.selector?.exclude)
@@ -55,7 +55,7 @@ export function discoverTableColumnSnaphots(
55
55
  ],
56
56
  });
57
57
  const anchors = collection.getAnchors();
58
- return mapToDiscoveredColumns(columns, anchors);
58
+ return mapToTableColumnVariants(variants, anchors);
59
59
  } finally {
60
60
  collection.dispose();
61
61
  }
@@ -93,43 +93,40 @@ function resolveProviders(
93
93
  : collectCtxColumnSnapshotProviders(ctx);
94
94
  }
95
95
 
96
- /** Map matched columns into a flat DiscoveredColumn list with deduped IDs. */
97
- function mapToDiscoveredColumns(
98
- matched: readonly ColumnMatch[],
96
+ /** Map column variants into TableColumnVariant list with anchor-derived isPrimary flag. */
97
+ function mapToTableColumnVariants(
98
+ variants: readonly ColumnVariant[],
99
99
  anchors: Map<string, ColumnSnapshot<PObjectId>>,
100
- ): TableColumnSnapshot[] {
100
+ ): TableColumnVariant[] {
101
101
  const columnIdToAnchorName = new Map<PObjectId, string>(
102
102
  Array.from(anchors.entries(), ([key, { id }]) => [id, key] as const),
103
103
  );
104
104
 
105
- return matched.flatMap((match) => {
106
- const snap = match.column;
107
- const isPrimary = columnIdToAnchorName.get(match.column.id) !== undefined;
105
+ return variants.map((variant): TableColumnVariant => {
106
+ const snap = variant.column;
107
+ const isPrimary = columnIdToAnchorName.get(snap.id) !== undefined;
108
108
 
109
- return match.variants.map((variant): TableColumnSnapshot => {
110
- const discoveredId = createDiscoveredPColumnId({
111
- column: snap.id,
112
- path: variant.path.map((p) => ({
113
- type: "linker",
114
- column: p.linker.id,
115
- qualifications: p.qualifications,
116
- })),
117
- columnQualifications: variant.qualifications.forHit,
118
- queriesQualifications: variant.qualifications.forQueries,
119
- });
120
- return {
109
+ const discoveredId = createDiscoveredPColumnId({
110
+ column: snap.id,
111
+ path: variant.path.map((p) => ({
112
+ type: "linker",
113
+ column: p.linker.id,
114
+ qualifications: p.qualifications,
115
+ })),
116
+ columnQualifications: variant.qualifications.forHit,
117
+ queriesQualifications: variant.qualifications.forQueries,
118
+ });
119
+ return {
120
+ column: {
121
121
  id: discoveredId,
122
- isPrimary,
123
-
124
- originalId: snap.id,
125
122
  spec: snap.spec,
126
123
  data: snap.data,
127
124
  dataStatus: snap.dataStatus,
128
-
129
- linkerPath: variant.path,
130
- qualifications: variant.qualifications,
131
- distinctiveQualifications: variant.distinctiveQualifications,
132
- };
133
- });
125
+ },
126
+ path: variant.path,
127
+ qualifications: variant.qualifications,
128
+ originalId: snap.id,
129
+ isPrimary,
130
+ };
134
131
  });
135
132
  }
@@ -239,7 +239,7 @@ describe("deriveAxisLabels via deriveAllLabels", () => {
239
239
  makeLabelableColumn(
240
240
  "c1",
241
241
  { name: "shared", annotations: { [Annotation.Label]: "Cluster size" } },
242
- [{ spec: linkerSpec }],
242
+ [{ linker: { id: "lk" as PObjectId, spec: linkerSpec } as never, qualifications: [] }],
243
243
  ),
244
244
  makeLabelableColumn("c2", {
245
245
  name: "shared",
@@ -229,7 +229,8 @@ export function withHidenAxesAnnotations<T extends { readonly spec: PColumnSpec
229
229
  export type LabelableColumn = {
230
230
  readonly id: PObjectId;
231
231
  readonly spec: PColumnSpec;
232
- readonly linkerPath?: { spec: PColumnSpec }[];
232
+ readonly linkerPath?: MatchVariant["path"];
233
+ readonly qualifications?: MatchQualifications;
233
234
  };
234
235
 
235
236
  /** Derive labels for all table elements: columns via deriveDistinctLabels, axes from label columns. */
@@ -240,7 +241,15 @@ export function deriveAllLabels(options: {
240
241
  }): Record<string, string> {
241
242
  const { columns, labelColumns, deriveLabelsOptions } = options;
242
243
  const axisLabels = deriveAxisLabels(columns, labelColumns);
243
- const columnLabels = deriveDistinctLabels(columns, deriveLabelsOptions).reduce(
244
+ const entries = columns.map((c) => ({
245
+ spec: c.spec,
246
+ linkerPath: c.linkerPath?.map((step) => ({
247
+ spec: step.linker.spec,
248
+ qualifications: step.qualifications,
249
+ })),
250
+ qualifications: c.qualifications,
251
+ }));
252
+ const columnLabels = deriveDistinctLabels(entries, deriveLabelsOptions).reduce(
244
253
  (acc, label, index) => ((acc[columns[index].id] = label), acc),
245
254
  {} as Record<string, string>,
246
255
  );
@@ -273,7 +282,6 @@ export type TooltipableColumn = {
273
282
  readonly originalId: PObjectId;
274
283
  readonly linkerPath?: MatchVariant["path"];
275
284
  readonly qualifications?: MatchQualifications;
276
- readonly distinctiveQualifications?: MatchQualifications;
277
285
  };
278
286
 
279
287
  /** Derive origin tooltips for columns whose qualifications or linker path carry info. */
@@ -297,7 +305,6 @@ export function deriveAllTooltips(options: {
297
305
  spec: c.spec,
298
306
  linkerPath: c.linkerPath,
299
307
  qualifications: c.qualifications,
300
- distinctiveQualifications: c.distinctiveQualifications,
301
308
  variantIndex,
302
309
  variantCount,
303
310
  });