@platforma-sdk/model 1.61.0 → 1.62.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.
Files changed (74) hide show
  1. package/dist/block_model.cjs +19 -10
  2. package/dist/block_model.cjs.map +1 -1
  3. package/dist/block_model.d.ts +22 -5
  4. package/dist/block_model.js +18 -10
  5. package/dist/block_model.js.map +1 -1
  6. package/dist/columns/column_collection_builder.cjs +26 -14
  7. package/dist/columns/column_collection_builder.cjs.map +1 -1
  8. package/dist/columns/column_collection_builder.d.ts +9 -8
  9. package/dist/columns/column_collection_builder.js +26 -14
  10. package/dist/columns/column_collection_builder.js.map +1 -1
  11. package/dist/columns/ctx_column_sources.cjs.map +1 -1
  12. package/dist/columns/ctx_column_sources.d.ts +1 -1
  13. package/dist/columns/ctx_column_sources.js.map +1 -1
  14. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +93 -89
  15. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
  16. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +2 -2
  17. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +93 -89
  18. package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
  19. package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
  20. package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -1
  21. package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
  22. package/dist/index.cjs +7 -0
  23. package/dist/index.d.ts +7 -3
  24. package/dist/index.js +4 -1
  25. package/dist/package.cjs +1 -1
  26. package/dist/package.js +1 -1
  27. package/dist/platforma.d.ts +9 -3
  28. package/dist/plugin_handle.cjs.map +1 -1
  29. package/dist/plugin_handle.d.ts +13 -7
  30. package/dist/plugin_handle.js.map +1 -1
  31. package/dist/plugin_model.cjs +84 -12
  32. package/dist/plugin_model.cjs.map +1 -1
  33. package/dist/plugin_model.d.ts +121 -41
  34. package/dist/plugin_model.js +84 -12
  35. package/dist/plugin_model.js.map +1 -1
  36. package/dist/render/api.cjs +17 -31
  37. package/dist/render/api.cjs.map +1 -1
  38. package/dist/render/api.d.ts +12 -18
  39. package/dist/render/api.js +17 -31
  40. package/dist/render/api.js.map +1 -1
  41. package/dist/render/internal.cjs.map +1 -1
  42. package/dist/render/internal.d.ts +3 -14
  43. package/dist/render/internal.js.map +1 -1
  44. package/dist/services/block_services.cjs +18 -0
  45. package/dist/services/block_services.cjs.map +1 -0
  46. package/dist/services/block_services.d.ts +18 -0
  47. package/dist/services/block_services.js +16 -0
  48. package/dist/services/block_services.js.map +1 -0
  49. package/dist/services/index.cjs +2 -0
  50. package/dist/services/index.d.ts +3 -0
  51. package/dist/services/index.js +2 -0
  52. package/dist/services/service_bridge.cjs +35 -0
  53. package/dist/services/service_bridge.cjs.map +1 -0
  54. package/dist/services/service_bridge.d.ts +18 -0
  55. package/dist/services/service_bridge.js +33 -0
  56. package/dist/services/service_bridge.js.map +1 -0
  57. package/dist/services/service_resolve.d.ts +13 -0
  58. package/package.json +6 -6
  59. package/src/block_model.ts +49 -14
  60. package/src/columns/column_collection_builder.test.ts +23 -2
  61. package/src/columns/column_collection_builder.ts +38 -30
  62. package/src/columns/ctx_column_sources.ts +2 -2
  63. package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +159 -153
  64. package/src/components/PlDataTable/createPlDataTable/index.ts +5 -4
  65. package/src/index.ts +2 -0
  66. package/src/platforma.ts +14 -2
  67. package/src/plugin_handle.ts +24 -6
  68. package/src/plugin_model.ts +321 -82
  69. package/src/render/api.ts +55 -57
  70. package/src/render/internal.ts +3 -38
  71. package/src/services/block_services.ts +17 -0
  72. package/src/services/index.ts +3 -0
  73. package/src/services/service_bridge.ts +71 -0
  74. package/src/services/service_resolve.ts +71 -0
@@ -6,9 +6,12 @@ import type {
6
6
  BlockCodeKnownFeatureFlags,
7
7
  BlockConfigContainer,
8
8
  } from "@milaboratories/pl-model-common";
9
+ import { resolveRequiredServices } from "@milaboratories/pl-model-common";
9
10
  import { getPlatformaInstance, isInUI, createAndRegisterRenderLambda } from "./internal";
10
11
  import type { DataModel } from "./block_migrations";
11
12
  import type { PlatformaV3 } from "./platforma";
13
+ import type { BlockDefaultUiServices } from "./services/service_resolve";
14
+ import { blockServiceNames, BLOCK_SERVICE_FLAGS } from "./services/block_services";
12
15
  import type { InferRenderFunctionReturn, RenderFunction } from "./render";
13
16
  import { BlockRenderCtx, PluginRenderCtx } from "./render";
14
17
  import type { PluginData, PluginModel, PluginOutputs, PluginParams } from "./plugin_model";
@@ -87,8 +90,10 @@ export type PluginRecord<
87
90
  Data extends PluginData = PluginData,
88
91
  Params extends PluginParams = undefined,
89
92
  Outputs extends PluginOutputs = PluginOutputs,
93
+ ModelServices = unknown,
94
+ UiServices = unknown,
90
95
  > = {
91
- readonly model: PluginModel<Data, Params, Outputs>;
96
+ readonly model: PluginModel<Data, Params, Outputs, ModelServices, UiServices>;
92
97
  readonly inputs: ParamsInputErased;
93
98
  };
94
99
 
@@ -128,13 +133,17 @@ export class BlockModelV3<
128
133
  private readonly config: BlockModelV3Config<OutputsCfg, Data, Plugins, Transfers>,
129
134
  ) {}
130
135
 
131
- public static readonly INITIAL_BLOCK_FEATURE_FLAGS: BlockCodeKnownFeatureFlags = {
136
+ public static readonly FEATURE_FLAGS = {
132
137
  supportsLazyState: true,
133
138
  supportsPframeQueryRanking: true,
134
139
  requiresUIAPIVersion: 3,
135
140
  requiresModelAPIVersion: BLOCK_STORAGE_FACADE_VERSION,
136
141
  requiresCreatePTable: 2,
137
- };
142
+ ...BLOCK_SERVICE_FLAGS,
143
+ } satisfies BlockCodeKnownFeatureFlags;
144
+
145
+ /** @deprecated Use FEATURE_FLAGS */
146
+ public static readonly INITIAL_BLOCK_FEATURE_FLAGS = BlockModelV3.FEATURE_FLAGS;
138
147
 
139
148
  /**
140
149
  * Creates a new BlockModelV3 builder with the specified data model.
@@ -164,7 +173,7 @@ export class BlockModelV3<
164
173
  subtitle: undefined,
165
174
  tags: undefined,
166
175
  enrichmentTargets: undefined,
167
- featureFlags: { ...BlockModelV3.INITIAL_BLOCK_FEATURE_FLAGS },
176
+ featureFlags: { ...BlockModelV3.FEATURE_FLAGS },
168
177
  argsFunction: undefined,
169
178
  prerunArgsFunction: undefined,
170
179
  plugins: {},
@@ -228,7 +237,7 @@ export class BlockModelV3<
228
237
  ...this.config.outputs,
229
238
  [key]: createAndRegisterRenderLambda({
230
239
  handle: `block-output#${key}`,
231
- lambda: () => cfgOrRf(new BlockRenderCtx<Args, Data>()),
240
+ lambda: () => cfgOrRf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
232
241
  ...flags,
233
242
  }),
234
243
  },
@@ -324,7 +333,10 @@ export class BlockModelV3<
324
333
  ...this.config,
325
334
  // Replace the default sections callback with the user-provided one
326
335
  sections: createAndRegisterRenderLambda(
327
- { handle: "sections", lambda: () => rf(new BlockRenderCtx<Args, Data>()) },
336
+ {
337
+ handle: "sections",
338
+ lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
339
+ },
328
340
  true,
329
341
  ),
330
342
  },
@@ -339,7 +351,7 @@ export class BlockModelV3<
339
351
  ...this.config,
340
352
  title: createAndRegisterRenderLambda({
341
353
  handle: "title",
342
- lambda: () => rf(new BlockRenderCtx<Args, Data>()),
354
+ lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
343
355
  }),
344
356
  });
345
357
  }
@@ -351,7 +363,7 @@ export class BlockModelV3<
351
363
  ...this.config,
352
364
  subtitle: createAndRegisterRenderLambda({
353
365
  handle: "subtitle",
354
- lambda: () => rf(new BlockRenderCtx<Args, Data>()),
366
+ lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
355
367
  }),
356
368
  });
357
369
  }
@@ -363,7 +375,7 @@ export class BlockModelV3<
363
375
  ...this.config,
364
376
  tags: createAndRegisterRenderLambda({
365
377
  handle: "tags",
366
- lambda: () => rf(new BlockRenderCtx<Args, Data>()),
378
+ lambda: () => rf(new BlockRenderCtx<Args, Data>(blockServiceNames)),
367
379
  }),
368
380
  });
369
381
  }
@@ -418,6 +430,8 @@ export class BlockModelV3<
418
430
  PParams extends PluginParams,
419
431
  POutputs extends PluginOutputs,
420
432
  PTransferData,
433
+ PluginModelServices,
434
+ PluginUiServices,
421
435
  >(
422
436
  instance: PluginInstanceClass<
423
437
  PluginId &
@@ -432,7 +446,9 @@ export class BlockModelV3<
432
446
  PData,
433
447
  PParams,
434
448
  POutputs,
435
- PTransferData
449
+ PTransferData,
450
+ PluginModelServices,
451
+ PluginUiServices
436
452
  >,
437
453
  params?: ParamsInput<PParams, Args, Data>,
438
454
  ): BlockModelV3<
@@ -440,7 +456,15 @@ export class BlockModelV3<
440
456
  OutputsCfg,
441
457
  Data,
442
458
  Href,
443
- Plugins & { [K in PluginId]: PluginRecord<PData, PParams, POutputs> },
459
+ Plugins & {
460
+ [K in PluginId]: PluginRecord<
461
+ PData,
462
+ PParams,
463
+ POutputs,
464
+ PluginModelServices,
465
+ PluginUiServices
466
+ >;
467
+ },
444
468
  Omit<Transfers, PluginId>
445
469
  >;
446
470
  public plugin(
@@ -489,7 +513,14 @@ export class BlockModelV3<
489
513
  public done(
490
514
  ..._: keyof Transfers extends never ? [] : [never]
491
515
  ): PlatformaExtended<
492
- PlatformaV3<Data, Args, InferOutputsFromLambdas<OutputsCfg>, Href, Plugins>
516
+ PlatformaV3<
517
+ Data,
518
+ Args,
519
+ InferOutputsFromLambdas<OutputsCfg>,
520
+ Href,
521
+ Plugins,
522
+ BlockDefaultUiServices
523
+ >
493
524
  > {
494
525
  if (this.config.argsFunction === undefined) throw new Error("Args rendering function not set.");
495
526
 
@@ -505,6 +536,8 @@ export class BlockModelV3<
505
536
 
506
537
  const { dataModel, argsFunction, prerunArgsFunction } = this.config;
507
538
 
539
+ const mergedServiceNames = resolveRequiredServices(this.config.featureFlags);
540
+
508
541
  function getPlugin(handle: PluginHandle): PluginRecord {
509
542
  const plugin = plugins[handle];
510
543
  if (!plugin) throw new Error(`Plugin model not found for '${handle}'`);
@@ -544,16 +577,18 @@ export class BlockModelV3<
544
577
  // Wrap plugin param lambdas: close over BlockRenderCtx creation
545
578
  const wrappedInputs: Record<string, () => unknown> = {};
546
579
  for (const [paramKey, paramFn] of Object.entries(inputs)) {
547
- wrappedInputs[paramKey] = () => paramFn(new BlockRenderCtx());
580
+ wrappedInputs[paramKey] = () => paramFn(new BlockRenderCtx(mergedServiceNames));
548
581
  }
549
582
 
550
583
  // Register plugin outputs (in config pack, evaluated by middle layer)
551
584
  const outputs = model.outputs as Record<string, (ctx: PluginRenderCtx) => unknown>;
585
+ const { outputFlags } = model;
552
586
  for (const [outputKey, outputFn] of Object.entries(outputs)) {
553
587
  const key = pluginOutputKey(handle, outputKey);
554
588
  pluginOutputs[key] = createAndRegisterRenderLambda({
555
589
  handle: key,
556
- lambda: () => outputFn(new PluginRenderCtx(handle, wrappedInputs)),
590
+ lambda: () => outputFn(new PluginRenderCtx(handle, wrappedInputs, mergedServiceNames)),
591
+ withStatus: outputFlags[outputKey]?.withStatus,
557
592
  });
558
593
  }
559
594
  }
@@ -20,8 +20,8 @@ function createSpecFrameCtx() {
20
20
  return driver;
21
21
  }
22
22
 
23
- afterEach(() => {
24
- for (const driver of drivers) driver.dispose();
23
+ afterEach(async () => {
24
+ for (const driver of drivers) await driver.dispose();
25
25
  drivers.length = 0;
26
26
  });
27
27
 
@@ -166,6 +166,27 @@ describe("ColumnCollection.findColumns", () => {
166
166
  expect(results).toHaveLength(1);
167
167
  expect(results[0].spec.name).toBe("col2");
168
168
  });
169
+
170
+ test("include filters by exact name among disjoint-axis columns", () => {
171
+ const vdjAxis = sampleAxis("pl7.app/vdj/clonotypeKey");
172
+ const itemAxis = sampleAxis("item");
173
+
174
+ const vdjColumns = Array.from({ length: 10 }, (_, i) =>
175
+ createSnapshot(`vdj${i}`, createSpec(`pl7.app/vdj/col${i}`, { axesSpec: [vdjAxis] })),
176
+ );
177
+ const mockScore = createSnapshot("mock", createSpec("mock_score", { axesSpec: [itemAxis] }));
178
+
179
+ const builder = new ColumnCollectionBuilder(createSpecFrameCtx());
180
+ builder.addSource([...vdjColumns, mockScore]);
181
+
182
+ const collection = builder.build()!;
183
+ const results = collection.findColumns({
184
+ include: [{ name: [{ type: "exact", value: "mock_score" }] }],
185
+ });
186
+
187
+ expect(results).toHaveLength(1);
188
+ expect(results[0].spec.name).toBe("mock_score");
189
+ });
169
190
  });
170
191
 
171
192
  describe("dedup by native ID", () => {
@@ -19,13 +19,7 @@ import { createColumnSnapshot } from "./column_snapshot";
19
19
  import type { ColumnSnapshotProvider, ColumnSource } from "./column_snapshot_provider";
20
20
  import { ArrayColumnProvider, toColumnSnapshotProvider } from "./column_snapshot_provider";
21
21
 
22
- import type { GlobalCfgRenderCtxMethods } from "../render/internal";
23
-
24
- /** Subset of render context methods needed for spec frame operations. */
25
- type SpecFrameCtx = Pick<
26
- GlobalCfgRenderCtxMethods,
27
- "createSpecFrame" | "specFrameDiscoverColumns" | "disposeSpecFrame"
28
- >;
22
+ import type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from "@milaboratories/pl-model-common";
29
23
 
30
24
  // --- FindColumnsOptions ---
31
25
 
@@ -40,7 +34,9 @@ export interface FindColumnsOptions {
40
34
  // --- ColumnCollection ---
41
35
 
42
36
  /** Plain collection — no axis context, selector-based filtering only. */
43
- export interface ColumnCollection {
37
+ export interface ColumnCollection extends Disposable {
38
+ /** Release the underlying spec frame WASM resource. */
39
+ dispose(): void;
44
40
  /** Point lookup by provider-native ID. */
45
41
  getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;
46
42
 
@@ -53,7 +49,9 @@ export interface ColumnCollection {
53
49
  // --- AnchoredColumnCollection ---
54
50
 
55
51
  /** Axis-aware column collection with anchored identity derivation. */
56
- export interface AnchoredColumnCollection {
52
+ export interface AnchoredColumnCollection extends Disposable {
53
+ /** Release the underlying spec frame WASM resource. */
54
+ dispose(): void;
57
55
  /** Point lookup by anchored ID. */
58
56
  getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;
59
57
 
@@ -122,7 +120,7 @@ export interface AnchoredBuildOptions extends BuildOptions {
122
120
  export class ColumnCollectionBuilder {
123
121
  private readonly providers: ColumnSnapshotProvider[] = [];
124
122
 
125
- constructor(private readonly specFrameCtx: SpecFrameCtx) {}
123
+ constructor(private readonly specDriver: PFrameSpecDriver) {}
126
124
 
127
125
  /**
128
126
  * Register a column source. Sources added first take precedence for dedup.
@@ -178,14 +176,14 @@ export class ColumnCollectionBuilder {
178
176
  const anchorSpecs = resolveAnchorSpecs(options.anchors, columnMap);
179
177
  const idDeriver = new AnchoredIdDeriver(anchorSpecs);
180
178
 
181
- return new AnchoredColumnCollectionImpl(this.specFrameCtx, {
179
+ return new AnchoredColumnCollectionImpl(this.specDriver, {
182
180
  columns: columnMap,
183
181
  idDeriver,
184
182
  anchorSpecs,
185
183
  columnListComplete: allowPartial ? allComplete : false,
186
184
  });
187
185
  } else {
188
- return new ColumnCollectionImpl(this.specFrameCtx, {
186
+ return new ColumnCollectionImpl(this.specDriver, {
189
187
  columns: columnMap,
190
188
  columnListComplete: allowPartial ? allComplete : false,
191
189
  });
@@ -230,25 +228,30 @@ interface ColumnCollectionImplOptions {
230
228
  readonly columnListComplete?: boolean;
231
229
  }
232
230
 
233
- class ColumnCollectionImpl implements ColumnCollection {
231
+ class ColumnCollectionImpl implements ColumnCollection, Disposable {
234
232
  private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;
235
- private readonly specFrameHandle: string;
233
+ private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;
236
234
  public readonly columnListComplete: boolean;
237
235
 
238
236
  constructor(
239
- private readonly ctx: SpecFrameCtx,
237
+ private readonly specDriver: PFrameSpecDriver,
240
238
  options: ColumnCollectionImplOptions,
241
239
  ) {
242
240
  this.columns = options.columns;
243
241
  this.columnListComplete = options.columnListComplete ?? false;
244
- this.specFrameHandle = this.ctx.createSpecFrame(
245
- Array.from(this.columns.entries()).reduce(
246
- (acc, [id, col]) => ((acc[id] = col.spec), acc),
247
- {} as Record<string, PColumnSpec>,
248
- ),
242
+ this.specFrameEntry = this.specDriver.createSpecFrame(
243
+ Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])),
249
244
  );
250
245
  }
251
246
 
247
+ dispose(): void {
248
+ this.specFrameEntry.unref();
249
+ }
250
+
251
+ [Symbol.dispose](): void {
252
+ this.dispose();
253
+ }
254
+
252
255
  getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId> {
253
256
  const col = this.columns.get(id);
254
257
  if (col === undefined) return undefined;
@@ -259,7 +262,7 @@ class ColumnCollectionImpl implements ColumnCollection {
259
262
  const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;
260
263
  const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;
261
264
 
262
- const response = this.ctx.specFrameDiscoverColumns(this.specFrameHandle, {
265
+ const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {
263
266
  includeColumns,
264
267
  excludeColumns,
265
268
  axes: [],
@@ -288,17 +291,17 @@ interface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOption
288
291
  readonly anchorSpecs: Record<string, PColumnSpec>;
289
292
  }
290
293
 
291
- class AnchoredColumnCollectionImpl implements AnchoredColumnCollection {
294
+ class AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {
292
295
  private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;
293
296
  private readonly idDeriver: AnchoredIdDeriver;
294
- private readonly specFrameHandle: string;
297
+ private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;
295
298
  private readonly anchorAxes: ColumnAxesWithQualifications[];
296
299
  /** Reverse lookup: SUniversalPColumnId → PObjectId */
297
300
  private readonly idToOriginal: Map<SUniversalPColumnId, PObjectId>;
298
301
  public readonly columnListComplete: boolean;
299
302
 
300
303
  constructor(
301
- private readonly ctx: SpecFrameCtx,
304
+ private readonly specDriver: PFrameSpecDriver,
302
305
  options: AnchoredColumnCollectionImplOptions,
303
306
  ) {
304
307
  this.columns = options.columns;
@@ -306,11 +309,8 @@ class AnchoredColumnCollectionImpl implements AnchoredColumnCollection {
306
309
  this.columnListComplete = options.columnListComplete ?? false;
307
310
 
308
311
  // Create spec frame from all collected columns
309
- this.specFrameHandle = this.ctx.createSpecFrame(
310
- Array.from(this.columns.entries()).reduce(
311
- (acc, [id, col]) => ((acc[id] = col.spec), acc),
312
- {} as Record<string, PColumnSpec>,
313
- ),
312
+ this.specFrameEntry = this.specDriver.createSpecFrame(
313
+ Object.fromEntries(Array.from(this.columns.entries(), ([id, col]) => [id, col.spec])),
314
314
  );
315
315
 
316
316
  // Build anchor axes for discovery requests
@@ -327,6 +327,14 @@ class AnchoredColumnCollectionImpl implements AnchoredColumnCollection {
327
327
  );
328
328
  }
329
329
 
330
+ dispose(): void {
331
+ this.specFrameEntry.unref();
332
+ }
333
+
334
+ [Symbol.dispose](): void {
335
+ this.dispose();
336
+ }
337
+
330
338
  getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {
331
339
  const origId = this.idToOriginal.get(id);
332
340
  if (origId === undefined) return undefined;
@@ -341,7 +349,7 @@ class AnchoredColumnCollectionImpl implements AnchoredColumnCollection {
341
349
  const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;
342
350
  const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;
343
351
 
344
- const response = this.ctx.specFrameDiscoverColumns(this.specFrameHandle, {
352
+ const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {
345
353
  includeColumns,
346
354
  excludeColumns,
347
355
  constraints,
@@ -17,8 +17,8 @@ import type { ValueOf } from "@milaboratories/helpers";
17
17
  *
18
18
  * Returns an array of providers suitable for `ColumnCollectionBuilder.addSource()`.
19
19
  */
20
- export function collectCtxColumnSnapshotProviders<A, U>(
21
- ctx: RenderCtxBase<A, U>,
20
+ export function collectCtxColumnSnapshotProviders<A, U, S>(
21
+ ctx: RenderCtxBase<A, U, S>,
22
22
  ): ColumnSnapshotProvider[] {
23
23
  const providers: ColumnSnapshotProvider[] = [];
24
24