@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.
- package/dist/block_model.cjs +19 -10
- package/dist/block_model.cjs.map +1 -1
- package/dist/block_model.d.ts +22 -5
- package/dist/block_model.js +18 -10
- package/dist/block_model.js.map +1 -1
- package/dist/columns/column_collection_builder.cjs +26 -14
- package/dist/columns/column_collection_builder.cjs.map +1 -1
- package/dist/columns/column_collection_builder.d.ts +9 -8
- package/dist/columns/column_collection_builder.js +26 -14
- package/dist/columns/column_collection_builder.js.map +1 -1
- package/dist/columns/ctx_column_sources.cjs.map +1 -1
- package/dist/columns/ctx_column_sources.d.ts +1 -1
- package/dist/columns/ctx_column_sources.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +93 -89
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +2 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +93 -89
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -1
- package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
- package/dist/index.cjs +7 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +4 -1
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/platforma.d.ts +9 -3
- package/dist/plugin_handle.cjs.map +1 -1
- package/dist/plugin_handle.d.ts +13 -7
- package/dist/plugin_handle.js.map +1 -1
- package/dist/plugin_model.cjs +84 -12
- package/dist/plugin_model.cjs.map +1 -1
- package/dist/plugin_model.d.ts +121 -41
- package/dist/plugin_model.js +84 -12
- package/dist/plugin_model.js.map +1 -1
- package/dist/render/api.cjs +17 -31
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +12 -18
- package/dist/render/api.js +17 -31
- package/dist/render/api.js.map +1 -1
- package/dist/render/internal.cjs.map +1 -1
- package/dist/render/internal.d.ts +3 -14
- package/dist/render/internal.js.map +1 -1
- package/dist/services/block_services.cjs +18 -0
- package/dist/services/block_services.cjs.map +1 -0
- package/dist/services/block_services.d.ts +18 -0
- package/dist/services/block_services.js +16 -0
- package/dist/services/block_services.js.map +1 -0
- package/dist/services/index.cjs +2 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/index.js +2 -0
- package/dist/services/service_bridge.cjs +35 -0
- package/dist/services/service_bridge.cjs.map +1 -0
- package/dist/services/service_bridge.d.ts +18 -0
- package/dist/services/service_bridge.js +33 -0
- package/dist/services/service_bridge.js.map +1 -0
- package/dist/services/service_resolve.d.ts +13 -0
- package/package.json +6 -6
- package/src/block_model.ts +49 -14
- package/src/columns/column_collection_builder.test.ts +23 -2
- package/src/columns/column_collection_builder.ts +38 -30
- package/src/columns/ctx_column_sources.ts +2 -2
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +159 -153
- package/src/components/PlDataTable/createPlDataTable/index.ts +5 -4
- package/src/index.ts +2 -0
- package/src/platforma.ts +14 -2
- package/src/plugin_handle.ts +24 -6
- package/src/plugin_model.ts +321 -82
- package/src/render/api.ts +55 -57
- package/src/render/internal.ts +3 -38
- package/src/services/block_services.ts +17 -0
- package/src/services/index.ts +3 -0
- package/src/services/service_bridge.ts +71 -0
- package/src/services/service_resolve.ts +71 -0
|
@@ -91,100 +91,104 @@ function isColumnOptional(spec) {
|
|
|
91
91
|
function createPlDataTableV3(ctx, options) {
|
|
92
92
|
const providers = options.source ? normalizeSourceList(options.source).filter(require_column_snapshot_provider.isColumnSnapshotProvider) : require_ctx_column_sources.collectCtxColumnSnapshotProviders(ctx);
|
|
93
93
|
if (providers.length === 0) return void 0;
|
|
94
|
-
const builder = new require_column_collection_builder.ColumnCollectionBuilder(ctx).addSources(providers);
|
|
94
|
+
const builder = new require_column_collection_builder.ColumnCollectionBuilder(ctx.services.pframeSpec).addSources(providers);
|
|
95
95
|
const anchors = options.columns.anchors;
|
|
96
96
|
const collection = (0, es_toolkit.isNil)(anchors) ? builder.build() : builder.build({ anchors });
|
|
97
97
|
if (!collection) return void 0;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
98
|
+
try {
|
|
99
|
+
const findOptions = options.columns ? {
|
|
100
|
+
include: options.columns.include,
|
|
101
|
+
exclude: options.columns.exclude,
|
|
102
|
+
mode: options.columns.mode,
|
|
103
|
+
maxHops: options.columns.maxHops
|
|
104
|
+
} : void 0;
|
|
105
|
+
const dataSnapshots = collection.findColumns(findOptions).map((v) => "column" in v ? v.column : v).filter((s) => !isColumnHidden(s.spec));
|
|
106
|
+
if (dataSnapshots.length === 0) return void 0;
|
|
107
|
+
const columns = [];
|
|
108
|
+
for (const snap of dataSnapshots) {
|
|
109
|
+
if (!snap.data) return void 0;
|
|
110
|
+
const data = snap.data.get();
|
|
111
|
+
if (data === void 0) return void 0;
|
|
112
|
+
columns.push({
|
|
113
|
+
id: snap.id,
|
|
114
|
+
spec: snap.spec,
|
|
115
|
+
data
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
const tableStateNormalized = require_state_migration.upgradePlDataTableStateV2(options.state);
|
|
119
|
+
const allLabelColumns = require_labels.getAllLabelColumns(ctx.resultPool);
|
|
120
|
+
if (!allLabelColumns) return void 0;
|
|
121
|
+
const fullLabelColumns = require_labels.getMatchingLabelColumns(columns.map(_milaboratories_pl_model_common.getColumnIdAndSpec), allLabelColumns);
|
|
122
|
+
const fullColumns = [...columns, ...fullLabelColumns];
|
|
123
|
+
const fullColumnsIds = [...(0, _milaboratories_pl_model_common.uniqueBy)(fullColumns.flatMap((c) => c.spec.axesSpec.map((a) => (0, _milaboratories_pl_model_common.getAxisId)(a))), (a) => (0, _milaboratories_pl_model_common.canonicalizeJson)(a)).map((a) => ({
|
|
124
|
+
type: "axis",
|
|
125
|
+
id: a
|
|
126
|
+
})), ...fullColumns.map((c) => ({
|
|
127
|
+
type: "column",
|
|
128
|
+
id: c.id
|
|
129
|
+
}))];
|
|
130
|
+
const fullColumnsIdsSet = new Set(fullColumnsIds.map((c) => (0, _milaboratories_pl_model_common.canonicalizeJson)(c)));
|
|
131
|
+
const isValidColumnId = (id) => fullColumnsIdsSet.has(id);
|
|
132
|
+
const stateFilters = tableStateNormalized.pTableParams.filters;
|
|
133
|
+
const opsFilters = options?.filters ?? null;
|
|
134
|
+
const filters = stateFilters != null && opsFilters != null ? {
|
|
135
|
+
type: "and",
|
|
136
|
+
filters: [stateFilters, opsFilters]
|
|
137
|
+
} : stateFilters ?? opsFilters;
|
|
138
|
+
const firstInvalidFilterColumn = (filters ? require_traverse.collectFilterSpecColumns(filters) : []).find((col) => !isValidColumnId(col));
|
|
139
|
+
if (firstInvalidFilterColumn) throw new Error(`Invalid filter column ${firstInvalidFilterColumn}: column reference does not match the table columns`);
|
|
140
|
+
const userSorting = tableStateNormalized.pTableParams.sorting;
|
|
141
|
+
const sorting = ((0, es_toolkit_compat.isEmpty)(userSorting) ? options?.sorting : userSorting) ?? [];
|
|
142
|
+
const firstInvalidSortingColumn = sorting.find((s) => !isValidColumnId((0, _milaboratories_pl_model_common.canonicalizeJson)(s.column)));
|
|
143
|
+
if (firstInvalidSortingColumn) throw new Error(`Invalid sorting column ${JSON.stringify(firstInvalidSortingColumn.column)}: column reference does not match the table columns`);
|
|
144
|
+
const coreJoinType = options?.coreJoinType ?? "full";
|
|
145
|
+
const fullDef = createPTableDef({
|
|
146
|
+
columns,
|
|
147
|
+
labelColumns: fullLabelColumns,
|
|
148
|
+
coreJoinType,
|
|
149
|
+
filters,
|
|
150
|
+
sorting,
|
|
151
|
+
coreColumnPredicate: options?.coreColumnPredicate
|
|
152
|
+
});
|
|
153
|
+
const fullHandle = ctx.createPTableV2(fullDef);
|
|
154
|
+
const pframeHandle = ctx.createPFrame(fullColumns);
|
|
155
|
+
if (!fullHandle || !pframeHandle) return void 0;
|
|
156
|
+
const hiddenColumns = new Set((() => {
|
|
157
|
+
if (coreJoinType === "inner") return [];
|
|
158
|
+
const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;
|
|
159
|
+
if (hiddenColIds) return hiddenColIds;
|
|
160
|
+
return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);
|
|
161
|
+
})());
|
|
162
|
+
columns.filter((c) => (0, _milaboratories_pl_model_common.isLinkerColumn)(c.spec)).forEach((c) => hiddenColumns.delete(c.id));
|
|
163
|
+
const coreColumnPredicate = options?.coreColumnPredicate;
|
|
164
|
+
if (coreColumnPredicate) columns.flatMap((c) => coreColumnPredicate((0, _milaboratories_pl_model_common.getColumnIdAndSpec)(c)) ? [c.id] : []).forEach((c) => hiddenColumns.delete(c));
|
|
165
|
+
sorting.map((s) => s.column).filter((c) => c.type === "column").forEach((c) => hiddenColumns.delete(c.id));
|
|
166
|
+
if (filters) require_traverse.collectFilterSpecColumns(filters).flatMap((c) => {
|
|
167
|
+
const obj = (0, _milaboratories_pl_model_common.parseJson)(c);
|
|
168
|
+
return obj.type === "column" ? [obj.id] : [];
|
|
169
|
+
}).forEach((c) => hiddenColumns.delete(c));
|
|
170
|
+
const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));
|
|
171
|
+
const visibleLabelColumns = require_labels.getMatchingLabelColumns(visibleColumns.map(_milaboratories_pl_model_common.getColumnIdAndSpec), allLabelColumns);
|
|
172
|
+
if (!require_pcolumn_data.allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return void 0;
|
|
173
|
+
const visibleDef = createPTableDef({
|
|
174
|
+
columns: visibleColumns,
|
|
175
|
+
labelColumns: visibleLabelColumns,
|
|
176
|
+
coreJoinType,
|
|
177
|
+
filters,
|
|
178
|
+
sorting,
|
|
179
|
+
coreColumnPredicate
|
|
115
180
|
});
|
|
181
|
+
const visibleHandle = ctx.createPTableV2(visibleDef);
|
|
182
|
+
if (!visibleHandle) return void 0;
|
|
183
|
+
return {
|
|
184
|
+
sourceId: tableStateNormalized.pTableParams.sourceId,
|
|
185
|
+
fullTableHandle: fullHandle,
|
|
186
|
+
fullPframeHandle: pframeHandle,
|
|
187
|
+
visibleTableHandle: visibleHandle
|
|
188
|
+
};
|
|
189
|
+
} finally {
|
|
190
|
+
collection.dispose();
|
|
116
191
|
}
|
|
117
|
-
const tableStateNormalized = require_state_migration.upgradePlDataTableStateV2(options.state);
|
|
118
|
-
const allLabelColumns = require_labels.getAllLabelColumns(ctx.resultPool);
|
|
119
|
-
if (!allLabelColumns) return void 0;
|
|
120
|
-
const fullLabelColumns = require_labels.getMatchingLabelColumns(columns.map(_milaboratories_pl_model_common.getColumnIdAndSpec), allLabelColumns);
|
|
121
|
-
const fullColumns = [...columns, ...fullLabelColumns];
|
|
122
|
-
const fullColumnsIds = [...(0, _milaboratories_pl_model_common.uniqueBy)(fullColumns.flatMap((c) => c.spec.axesSpec.map((a) => (0, _milaboratories_pl_model_common.getAxisId)(a))), (a) => (0, _milaboratories_pl_model_common.canonicalizeJson)(a)).map((a) => ({
|
|
123
|
-
type: "axis",
|
|
124
|
-
id: a
|
|
125
|
-
})), ...fullColumns.map((c) => ({
|
|
126
|
-
type: "column",
|
|
127
|
-
id: c.id
|
|
128
|
-
}))];
|
|
129
|
-
const fullColumnsIdsSet = new Set(fullColumnsIds.map((c) => (0, _milaboratories_pl_model_common.canonicalizeJson)(c)));
|
|
130
|
-
const isValidColumnId = (id) => fullColumnsIdsSet.has(id);
|
|
131
|
-
const stateFilters = tableStateNormalized.pTableParams.filters;
|
|
132
|
-
const opsFilters = options?.filters ?? null;
|
|
133
|
-
const filters = stateFilters != null && opsFilters != null ? {
|
|
134
|
-
type: "and",
|
|
135
|
-
filters: [stateFilters, opsFilters]
|
|
136
|
-
} : stateFilters ?? opsFilters;
|
|
137
|
-
const firstInvalidFilterColumn = (filters ? require_traverse.collectFilterSpecColumns(filters) : []).find((col) => !isValidColumnId(col));
|
|
138
|
-
if (firstInvalidFilterColumn) throw new Error(`Invalid filter column ${firstInvalidFilterColumn}: column reference does not match the table columns`);
|
|
139
|
-
const userSorting = tableStateNormalized.pTableParams.sorting;
|
|
140
|
-
const sorting = ((0, es_toolkit_compat.isEmpty)(userSorting) ? options?.sorting : userSorting) ?? [];
|
|
141
|
-
const firstInvalidSortingColumn = sorting.find((s) => !isValidColumnId((0, _milaboratories_pl_model_common.canonicalizeJson)(s.column)));
|
|
142
|
-
if (firstInvalidSortingColumn) throw new Error(`Invalid sorting column ${JSON.stringify(firstInvalidSortingColumn.column)}: column reference does not match the table columns`);
|
|
143
|
-
const coreJoinType = options?.coreJoinType ?? "full";
|
|
144
|
-
const fullDef = createPTableDef({
|
|
145
|
-
columns,
|
|
146
|
-
labelColumns: fullLabelColumns,
|
|
147
|
-
coreJoinType,
|
|
148
|
-
filters,
|
|
149
|
-
sorting,
|
|
150
|
-
coreColumnPredicate: options?.coreColumnPredicate
|
|
151
|
-
});
|
|
152
|
-
const fullHandle = ctx.createPTableV2(fullDef);
|
|
153
|
-
const pframeHandle = ctx.createPFrame(fullColumns);
|
|
154
|
-
if (!fullHandle || !pframeHandle) return void 0;
|
|
155
|
-
const hiddenColumns = new Set((() => {
|
|
156
|
-
if (coreJoinType === "inner") return [];
|
|
157
|
-
const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;
|
|
158
|
-
if (hiddenColIds) return hiddenColIds;
|
|
159
|
-
return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);
|
|
160
|
-
})());
|
|
161
|
-
columns.filter((c) => (0, _milaboratories_pl_model_common.isLinkerColumn)(c.spec)).forEach((c) => hiddenColumns.delete(c.id));
|
|
162
|
-
const coreColumnPredicate = options?.coreColumnPredicate;
|
|
163
|
-
if (coreColumnPredicate) columns.flatMap((c) => coreColumnPredicate((0, _milaboratories_pl_model_common.getColumnIdAndSpec)(c)) ? [c.id] : []).forEach((c) => hiddenColumns.delete(c));
|
|
164
|
-
sorting.map((s) => s.column).filter((c) => c.type === "column").forEach((c) => hiddenColumns.delete(c.id));
|
|
165
|
-
if (filters) require_traverse.collectFilterSpecColumns(filters).flatMap((c) => {
|
|
166
|
-
const obj = (0, _milaboratories_pl_model_common.parseJson)(c);
|
|
167
|
-
return obj.type === "column" ? [obj.id] : [];
|
|
168
|
-
}).forEach((c) => hiddenColumns.delete(c));
|
|
169
|
-
const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));
|
|
170
|
-
const visibleLabelColumns = require_labels.getMatchingLabelColumns(visibleColumns.map(_milaboratories_pl_model_common.getColumnIdAndSpec), allLabelColumns);
|
|
171
|
-
if (!require_pcolumn_data.allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return void 0;
|
|
172
|
-
const visibleDef = createPTableDef({
|
|
173
|
-
columns: visibleColumns,
|
|
174
|
-
labelColumns: visibleLabelColumns,
|
|
175
|
-
coreJoinType,
|
|
176
|
-
filters,
|
|
177
|
-
sorting,
|
|
178
|
-
coreColumnPredicate
|
|
179
|
-
});
|
|
180
|
-
const visibleHandle = ctx.createPTableV2(visibleDef);
|
|
181
|
-
if (!visibleHandle) return void 0;
|
|
182
|
-
return {
|
|
183
|
-
sourceId: tableStateNormalized.pTableParams.sourceId,
|
|
184
|
-
fullTableHandle: fullHandle,
|
|
185
|
-
fullPframeHandle: pframeHandle,
|
|
186
|
-
visibleTableHandle: visibleHandle
|
|
187
|
-
};
|
|
188
192
|
}
|
|
189
193
|
/** Normalize raw ColumnSource | ColumnSource[] into a flat list of sources. */
|
|
190
194
|
function normalizeSourceList(source) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createPlDataTableV3.cjs","names":["distillFilterSpec","filterSpecToSpecQueryExpr","Annotation","isColumnSnapshotProvider","collectCtxColumnSnapshotProviders","ColumnCollectionBuilder","upgradePlDataTableStateV2","getAllLabelColumns","getMatchingLabelColumns","getColumnIdAndSpec","collectFilterSpecColumns","allPColumnsReady"],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts"],"sourcesContent":["import type {\n AxisId,\n CanonicalizedJson,\n DataInfo,\n PColumn,\n PColumnIdAndSpec,\n PColumnValues,\n PObjectId,\n PTableColumnId,\n PTableColumnIdAxis,\n PTableColumnIdColumn,\n PTableDefV2,\n PTableSorting,\n SpecQuery,\n SingleAxisSelector,\n SpecQueryExpression,\n SpecQueryJoinEntry,\n PColumnSpec,\n PlRef,\n MultiColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n isLinkerColumn,\n readAnnotation,\n isBooleanExpression,\n parseJson,\n uniqueBy,\n} from \"@milaboratories/pl-model-common\";\nimport { filterSpecToSpecQueryExpr } from \"../../../filters\";\nimport { collectFilterSpecColumns } from \"../../../filters/traverse\";\nimport type { RenderCtxBase, TreeNodeAccessor, PColumnDataUniversal } from \"../../../render\";\nimport { allPColumnsReady } from \"../../../render\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport { isEmpty } from \"es-toolkit/compat\";\nimport { distillFilterSpec } from \"../../../filters/distill\";\nimport type { PlDataTableFilters, PlDataTableModel } from \"../typesV5\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport type { ColumnSource, MatchingMode } from \"../../../columns\";\nimport { ColumnCollectionBuilder } from \"../../../columns\";\nimport { isColumnSnapshotProvider } from \"../../../columns/column_snapshot_provider\";\nimport { collectCtxColumnSnapshotProviders } from \"../../../columns/ctx_column_sources\";\nimport { getAllLabelColumns, getMatchingLabelColumns } from \"../labels\";\n\n/** Convert a PTableColumnId to a SpecQueryExpression reference. */\nexport function columnIdToExpr(col: PTableColumnId): SpecQueryExpression {\n if (col.type === \"axis\") {\n return { type: \"axisRef\", value: col.id as SingleAxisSelector };\n }\n return { type: \"columnRef\", value: col.id };\n}\n\n/** Wrap a SpecQuery as a SpecQueryJoinEntry with empty qualifications. */\nexport function joinEntry<C>(input: SpecQuery<C>): SpecQueryJoinEntry<C> {\n return { entry: input, qualifications: [] };\n}\n\nexport function createPTableDef(params: {\n columns: PColumn<PColumnDataUniversal>[];\n labelColumns: PColumn<PColumnDataUniversal>[];\n coreJoinType: \"inner\" | \"full\";\n filters: null | PlDataTableFilters;\n sorting: PTableSorting[];\n coreColumnPredicate?: (spec: PColumnIdAndSpec) => boolean;\n}): PTableDefV2<PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>> {\n let coreColumns = params.columns;\n const secondaryColumns: typeof params.columns = [];\n\n if (isFunction(params.coreColumnPredicate)) {\n coreColumns = [];\n for (const c of params.columns)\n if (params.coreColumnPredicate(getColumnIdAndSpec(c))) coreColumns.push(c);\n else secondaryColumns.push(c);\n }\n\n secondaryColumns.push(...params.labelColumns);\n\n // Build SpecQuery directly from columns\n const coreJoinQuery: SpecQuery<\n PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>\n > = {\n type: params.coreJoinType === \"inner\" ? \"innerJoin\" : \"fullJoin\",\n entries: coreColumns.map((c) => joinEntry({ type: \"column\", column: c })),\n };\n\n let query: SpecQuery<PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>> = {\n type: \"outerJoin\",\n primary: joinEntry(coreJoinQuery),\n secondary: secondaryColumns.map((c) => joinEntry({ type: \"column\", column: c })),\n };\n\n // Apply filters\n if (params.filters !== null) {\n const nonEmpty = distillFilterSpec(params.filters);\n\n if (!isNil(nonEmpty)) {\n const pridicate = filterSpecToSpecQueryExpr(nonEmpty);\n if (!isBooleanExpression(pridicate)) {\n throw new Error(\n `Filter conversion produced a non-boolean expression (got type \"${pridicate.type}\"), expected a boolean predicate for query filtering`,\n );\n }\n query = {\n type: \"filter\",\n input: query,\n predicate: pridicate,\n };\n }\n }\n\n // Apply sorting\n if (params.sorting.length > 0) {\n query = {\n type: \"sort\",\n input: query,\n sortBy: params.sorting.map((s) => ({\n expression: columnIdToExpr(s.column),\n ascending: s.ascending,\n nullsFirst: !s.naAndAbsentAreLeastValues,\n })),\n };\n }\n\n return { query };\n}\n\n/** Check if column should be omitted from the table */\nexport function isColumnHidden(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"hidden\";\n}\n\n/** Check if column is hidden by default */\nexport function isColumnOptional(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"optional\";\n}\n\n/** Structured source config — selectors/anchors instead of raw ColumnSource. */\ntype ColumnsSelectorConfig = {\n include?: MultiColumnSelector | MultiColumnSelector[];\n exclude?: MultiColumnSelector | MultiColumnSelector[];\n anchors?: Record<string, PlRef | PObjectId | PColumnSpec>;\n mode?: MatchingMode;\n maxHops?: number;\n};\n\nexport type createPlDataTableOptionsV3 = {\n source?: ColumnSource | ColumnSource[];\n columns: ColumnsSelectorConfig;\n\n // Existing from V2\n filters?: PlDataTableFilters;\n sorting?: PTableSorting[];\n coreJoinType?: \"inner\" | \"full\";\n coreColumnPredicate?: (spec: PColumnIdAndSpec) => boolean;\n\n state?: PlDataTableStateV2;\n};\n\n// interface ColumnDisplayConfig {\n// /** Column ordering rules. Higher priority = further left. First matching rule wins. */\n// ordering?: ColumnOrderRule[];\n// /** Column visibility rules. First matching rule wins. Unmatched columns use default visibility. */\n// visibility?: ColumnVisibilityRule[];\n// }\n\n// interface ColumnOrderRule {\n// match: ColumnMatcher;\n// /** Higher number = further left in table */\n// priority: number;\n// }\n\n// interface ColumnVisibilityRule {\n// match: ColumnMatcher;\n// visibility: \"default\" | \"optional\" | \"hidden\";\n// }\n\n// type ColumnMatcher =\n// | ((spec: PColumnSpec) => boolean)\n// | { name: string | string[] }\n// | { annotation: Record<string, string> }\n// | { ids: Set<string> };\n\nexport function createPlDataTableV3<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): PlDataTableModel | undefined {\n const providers = options.source\n ? normalizeSourceList(options.source).filter(isColumnSnapshotProvider)\n : collectCtxColumnSnapshotProviders(ctx);\n\n if (providers.length === 0) return undefined;\n\n // Step 1: Build collection from sources\n const builder = new ColumnCollectionBuilder(ctx).addSources(providers);\n const anchors = options.columns.anchors;\n const collection = isNil(anchors) ? builder.build() : builder.build({ anchors });\n\n if (!collection) return undefined;\n\n // Step 2: Get data columns, excluding annotation-hidden ones\n const findOptions = options.columns\n ? {\n include: options.columns.include,\n exclude: options.columns.exclude,\n mode: options.columns.mode,\n maxHops: options.columns.maxHops,\n }\n : undefined;\n const findResult = collection.findColumns(findOptions);\n const snapshots = findResult.map((v) => (\"column\" in v ? v.column : v));\n const dataSnapshots = snapshots.filter((s) => !isColumnHidden(s.spec));\n if (dataSnapshots.length === 0) return undefined;\n\n // Convert snapshots to PColumn<PColumnDataUniversal>[]\n const columns: PColumn<PColumnDataUniversal>[] = [];\n for (const snap of dataSnapshots) {\n if (!snap.data) return undefined;\n const data = snap.data.get();\n if (data === undefined) return undefined;\n columns.push({ id: snap.id, spec: snap.spec, data });\n }\n\n // Step 3: Normalize table state\n const tableStateNormalized = upgradePlDataTableStateV2(options.state);\n\n // Step 4: Get label columns from result pool and match to data columns\n const allLabelColumns = getAllLabelColumns(ctx.resultPool);\n if (!allLabelColumns) return undefined;\n\n const fullLabelColumns = getMatchingLabelColumns(\n columns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n const fullColumns = [...columns, ...fullLabelColumns];\n\n // Step 5: Build column ID set for filter/sorting validation\n const fullColumnsAxes = uniqueBy(\n fullColumns.flatMap((c) => c.spec.axesSpec.map((a) => getAxisId(a))),\n (a) => canonicalizeJson<AxisId>(a),\n );\n const fullColumnsIds: PTableColumnId[] = [\n ...fullColumnsAxes.map((a) => ({ type: \"axis\", id: a }) satisfies PTableColumnIdAxis),\n ...fullColumns.map((c) => ({ type: \"column\", id: c.id }) satisfies PTableColumnIdColumn),\n ];\n const fullColumnsIdsSet = new Set(fullColumnsIds.map((c) => canonicalizeJson<PTableColumnId>(c)));\n const isValidColumnId = (id: string): boolean =>\n fullColumnsIdsSet.has(id as CanonicalizedJson<PTableColumnId>);\n\n // Step 6: Filtering validation\n const stateFilters = tableStateNormalized.pTableParams.filters;\n const opsFilters = options?.filters ?? null;\n const filters: null | PlDataTableFilters =\n stateFilters != null && opsFilters != null\n ? { type: \"and\", filters: [stateFilters, opsFilters] }\n : (stateFilters ?? opsFilters);\n const filterColumns = filters ? collectFilterSpecColumns(filters) : [];\n const firstInvalidFilterColumn = filterColumns.find((col) => !isValidColumnId(col));\n if (firstInvalidFilterColumn)\n throw new Error(\n `Invalid filter column ${firstInvalidFilterColumn}: column reference does not match the table columns`,\n );\n\n // Step 7: Sorting validation\n const userSorting = tableStateNormalized.pTableParams.sorting;\n const sorting = (isEmpty(userSorting) ? options?.sorting : userSorting) ?? [];\n const firstInvalidSortingColumn = sorting.find(\n (s) => !isValidColumnId(canonicalizeJson<PTableColumnId>(s.column)),\n );\n if (firstInvalidSortingColumn)\n throw new Error(\n `Invalid sorting column ${JSON.stringify(firstInvalidSortingColumn.column)}: column reference does not match the table columns`,\n );\n\n // Step 8: Build full table definition and handles\n const coreJoinType = options?.coreJoinType ?? \"full\";\n const fullDef = createPTableDef({\n columns,\n labelColumns: fullLabelColumns,\n coreJoinType,\n filters,\n sorting,\n coreColumnPredicate: options?.coreColumnPredicate,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n const pframeHandle = ctx.createPFrame(fullColumns);\n if (!fullHandle || !pframeHandle) return undefined;\n\n // Step 9: Determine hidden columns\n const hiddenColumns = new Set<PObjectId>(\n ((): PObjectId[] => {\n // Inner join works as a filter — all columns must be present\n if (coreJoinType === \"inner\") return [];\n\n const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;\n if (hiddenColIds) return hiddenColIds;\n\n return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);\n })(),\n );\n\n // Preserve linker columns\n columns.filter((c) => isLinkerColumn(c.spec)).forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve core columns as they change the shape of join\n const coreColumnPredicate = options?.coreColumnPredicate;\n if (coreColumnPredicate) {\n const coreColumns = columns.flatMap((c) =>\n coreColumnPredicate(getColumnIdAndSpec(c)) ? [c.id] : [],\n );\n coreColumns.forEach((c) => hiddenColumns.delete(c));\n }\n\n // Preserve sorted columns from being hidden\n sorting\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve filter columns from being hidden\n if (filters) {\n collectFilterSpecColumns(filters)\n .flatMap((c) => {\n const obj = parseJson(c);\n return obj.type === \"column\" ? [obj.id] : [];\n })\n .forEach((c) => hiddenColumns.delete(c));\n }\n\n // Step 10: Build visible table definition\n const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));\n const visibleLabelColumns = getMatchingLabelColumns(\n visibleColumns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n if (!allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return undefined;\n\n const visibleDef = createPTableDef({\n columns: visibleColumns,\n labelColumns: visibleLabelColumns,\n coreJoinType,\n filters,\n sorting,\n coreColumnPredicate,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n if (!visibleHandle) return undefined;\n\n return {\n sourceId: tableStateNormalized.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n } satisfies PlDataTableModel;\n}\n\n/** Normalize raw ColumnSource | ColumnSource[] into a flat list of sources. */\nfunction normalizeSourceList(source: ColumnSource | ColumnSource[]): ColumnSource[] {\n if (\n Array.isArray(source) &&\n source.length > 0 &&\n (Array.isArray(source[0]) || isColumnSnapshotProvider(source[0]))\n ) {\n return source as ColumnSource[];\n }\n return [source as ColumnSource];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createPlDataTableV3.cjs","names":["distillFilterSpec","filterSpecToSpecQueryExpr","Annotation","isColumnSnapshotProvider","collectCtxColumnSnapshotProviders","ColumnCollectionBuilder","upgradePlDataTableStateV2","getAllLabelColumns","getMatchingLabelColumns","getColumnIdAndSpec","collectFilterSpecColumns","allPColumnsReady"],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts"],"sourcesContent":["import type {\n AxisId,\n CanonicalizedJson,\n DataInfo,\n PColumn,\n PColumnIdAndSpec,\n PColumnValues,\n PObjectId,\n PTableColumnId,\n PTableColumnIdAxis,\n PTableColumnIdColumn,\n PTableDefV2,\n PTableSorting,\n SpecQuery,\n SingleAxisSelector,\n SpecQueryExpression,\n SpecQueryJoinEntry,\n PColumnSpec,\n PlRef,\n MultiColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n isLinkerColumn,\n readAnnotation,\n isBooleanExpression,\n parseJson,\n uniqueBy,\n} from \"@milaboratories/pl-model-common\";\nimport { filterSpecToSpecQueryExpr } from \"../../../filters\";\nimport { collectFilterSpecColumns } from \"../../../filters/traverse\";\nimport type { RenderCtxBase, TreeNodeAccessor, PColumnDataUniversal } from \"../../../render\";\nimport { allPColumnsReady } from \"../../../render\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport { isEmpty } from \"es-toolkit/compat\";\nimport { distillFilterSpec } from \"../../../filters/distill\";\nimport type { PlDataTableFilters, PlDataTableModel } from \"../typesV5\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport type { ColumnSource, MatchingMode } from \"../../../columns\";\nimport { Services, type RequireServices } from \"@milaboratories/pl-model-common\";\nimport { ColumnCollectionBuilder } from \"../../../columns\";\nimport { isColumnSnapshotProvider } from \"../../../columns/column_snapshot_provider\";\nimport { collectCtxColumnSnapshotProviders } from \"../../../columns/ctx_column_sources\";\nimport { getAllLabelColumns, getMatchingLabelColumns } from \"../labels\";\n\n/** Convert a PTableColumnId to a SpecQueryExpression reference. */\nexport function columnIdToExpr(col: PTableColumnId): SpecQueryExpression {\n if (col.type === \"axis\") {\n return { type: \"axisRef\", value: col.id as SingleAxisSelector };\n }\n return { type: \"columnRef\", value: col.id };\n}\n\n/** Wrap a SpecQuery as a SpecQueryJoinEntry with empty qualifications. */\nexport function joinEntry<C>(input: SpecQuery<C>): SpecQueryJoinEntry<C> {\n return { entry: input, qualifications: [] };\n}\n\nexport function createPTableDef(params: {\n columns: PColumn<PColumnDataUniversal>[];\n labelColumns: PColumn<PColumnDataUniversal>[];\n coreJoinType: \"inner\" | \"full\";\n filters: null | PlDataTableFilters;\n sorting: PTableSorting[];\n coreColumnPredicate?: (spec: PColumnIdAndSpec) => boolean;\n}): PTableDefV2<PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>> {\n let coreColumns = params.columns;\n const secondaryColumns: typeof params.columns = [];\n\n if (isFunction(params.coreColumnPredicate)) {\n coreColumns = [];\n for (const c of params.columns)\n if (params.coreColumnPredicate(getColumnIdAndSpec(c))) coreColumns.push(c);\n else secondaryColumns.push(c);\n }\n\n secondaryColumns.push(...params.labelColumns);\n\n // Build SpecQuery directly from columns\n const coreJoinQuery: SpecQuery<\n PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>\n > = {\n type: params.coreJoinType === \"inner\" ? \"innerJoin\" : \"fullJoin\",\n entries: coreColumns.map((c) => joinEntry({ type: \"column\", column: c })),\n };\n\n let query: SpecQuery<PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>> = {\n type: \"outerJoin\",\n primary: joinEntry(coreJoinQuery),\n secondary: secondaryColumns.map((c) => joinEntry({ type: \"column\", column: c })),\n };\n\n // Apply filters\n if (params.filters !== null) {\n const nonEmpty = distillFilterSpec(params.filters);\n\n if (!isNil(nonEmpty)) {\n const pridicate = filterSpecToSpecQueryExpr(nonEmpty);\n if (!isBooleanExpression(pridicate)) {\n throw new Error(\n `Filter conversion produced a non-boolean expression (got type \"${pridicate.type}\"), expected a boolean predicate for query filtering`,\n );\n }\n query = {\n type: \"filter\",\n input: query,\n predicate: pridicate,\n };\n }\n }\n\n // Apply sorting\n if (params.sorting.length > 0) {\n query = {\n type: \"sort\",\n input: query,\n sortBy: params.sorting.map((s) => ({\n expression: columnIdToExpr(s.column),\n ascending: s.ascending,\n nullsFirst: !s.naAndAbsentAreLeastValues,\n })),\n };\n }\n\n return { query };\n}\n\n/** Check if column should be omitted from the table */\nexport function isColumnHidden(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"hidden\";\n}\n\n/** Check if column is hidden by default */\nexport function isColumnOptional(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"optional\";\n}\n\n/** Structured source config — selectors/anchors instead of raw ColumnSource. */\ntype ColumnsSelectorConfig = {\n include?: MultiColumnSelector | MultiColumnSelector[];\n exclude?: MultiColumnSelector | MultiColumnSelector[];\n anchors?: Record<string, PlRef | PObjectId | PColumnSpec>;\n mode?: MatchingMode;\n maxHops?: number;\n};\n\nexport type createPlDataTableOptionsV3 = {\n source?: ColumnSource | ColumnSource[];\n columns: ColumnsSelectorConfig;\n\n // Existing from V2\n filters?: PlDataTableFilters;\n sorting?: PTableSorting[];\n coreJoinType?: \"inner\" | \"full\";\n coreColumnPredicate?: (spec: PColumnIdAndSpec) => boolean;\n\n state?: PlDataTableStateV2;\n};\n\n// interface ColumnDisplayConfig {\n// /** Column ordering rules. Higher priority = further left. First matching rule wins. */\n// ordering?: ColumnOrderRule[];\n// /** Column visibility rules. First matching rule wins. Unmatched columns use default visibility. */\n// visibility?: ColumnVisibilityRule[];\n// }\n\n// interface ColumnOrderRule {\n// match: ColumnMatcher;\n// /** Higher number = further left in table */\n// priority: number;\n// }\n\n// interface ColumnVisibilityRule {\n// match: ColumnMatcher;\n// visibility: \"default\" | \"optional\" | \"hidden\";\n// }\n\n// type ColumnMatcher =\n// | ((spec: PColumnSpec) => boolean)\n// | { name: string | string[] }\n// | { annotation: Record<string, string> }\n// | { ids: Set<string> };\n\nexport function createPlDataTableV3<A, U, S extends RequireServices<typeof Services.PFrameSpec>>(\n ctx: RenderCtxBase<A, U, S>,\n options: createPlDataTableOptionsV3,\n): PlDataTableModel | undefined {\n const providers = options.source\n ? normalizeSourceList(options.source).filter(isColumnSnapshotProvider)\n : collectCtxColumnSnapshotProviders(ctx);\n\n if (providers.length === 0) return undefined;\n\n // Step 1: Build collection from sources\n const builder = new ColumnCollectionBuilder(ctx.services.pframeSpec).addSources(providers);\n const anchors = options.columns.anchors;\n const collection = isNil(anchors) ? builder.build() : builder.build({ anchors });\n\n if (!collection) return undefined;\n try {\n // Step 2: Get data columns, excluding annotation-hidden ones\n const findOptions = options.columns\n ? {\n include: options.columns.include,\n exclude: options.columns.exclude,\n mode: options.columns.mode,\n maxHops: options.columns.maxHops,\n }\n : undefined;\n const findResult = collection.findColumns(findOptions);\n const snapshots = findResult.map((v) => (\"column\" in v ? v.column : v));\n const dataSnapshots = snapshots.filter((s) => !isColumnHidden(s.spec));\n if (dataSnapshots.length === 0) return undefined;\n\n // Convert snapshots to PColumn<PColumnDataUniversal>[]\n const columns: PColumn<PColumnDataUniversal>[] = [];\n for (const snap of dataSnapshots) {\n if (!snap.data) return undefined;\n const data = snap.data.get();\n if (data === undefined) return undefined;\n columns.push({ id: snap.id, spec: snap.spec, data });\n }\n\n // Step 3: Normalize table state\n const tableStateNormalized = upgradePlDataTableStateV2(options.state);\n\n // Step 4: Get label columns from result pool and match to data columns\n const allLabelColumns = getAllLabelColumns(ctx.resultPool);\n if (!allLabelColumns) return undefined;\n\n const fullLabelColumns = getMatchingLabelColumns(\n columns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n const fullColumns = [...columns, ...fullLabelColumns];\n\n // Step 5: Build column ID set for filter/sorting validation\n const fullColumnsAxes = uniqueBy(\n fullColumns.flatMap((c) => c.spec.axesSpec.map((a) => getAxisId(a))),\n (a) => canonicalizeJson<AxisId>(a),\n );\n const fullColumnsIds: PTableColumnId[] = [\n ...fullColumnsAxes.map((a) => ({ type: \"axis\", id: a }) satisfies PTableColumnIdAxis),\n ...fullColumns.map((c) => ({ type: \"column\", id: c.id }) satisfies PTableColumnIdColumn),\n ];\n const fullColumnsIdsSet = new Set(\n fullColumnsIds.map((c) => canonicalizeJson<PTableColumnId>(c)),\n );\n const isValidColumnId = (id: string): boolean =>\n fullColumnsIdsSet.has(id as CanonicalizedJson<PTableColumnId>);\n\n // Step 6: Filtering validation\n const stateFilters = tableStateNormalized.pTableParams.filters;\n const opsFilters = options?.filters ?? null;\n const filters: null | PlDataTableFilters =\n stateFilters != null && opsFilters != null\n ? { type: \"and\", filters: [stateFilters, opsFilters] }\n : (stateFilters ?? opsFilters);\n const filterColumns = filters ? collectFilterSpecColumns(filters) : [];\n const firstInvalidFilterColumn = filterColumns.find((col) => !isValidColumnId(col));\n if (firstInvalidFilterColumn)\n throw new Error(\n `Invalid filter column ${firstInvalidFilterColumn}: column reference does not match the table columns`,\n );\n\n // Step 7: Sorting validation\n const userSorting = tableStateNormalized.pTableParams.sorting;\n const sorting = (isEmpty(userSorting) ? options?.sorting : userSorting) ?? [];\n const firstInvalidSortingColumn = sorting.find(\n (s) => !isValidColumnId(canonicalizeJson<PTableColumnId>(s.column)),\n );\n if (firstInvalidSortingColumn)\n throw new Error(\n `Invalid sorting column ${JSON.stringify(firstInvalidSortingColumn.column)}: column reference does not match the table columns`,\n );\n\n // Step 8: Build full table definition and handles\n const coreJoinType = options?.coreJoinType ?? \"full\";\n const fullDef = createPTableDef({\n columns,\n labelColumns: fullLabelColumns,\n coreJoinType,\n filters,\n sorting,\n coreColumnPredicate: options?.coreColumnPredicate,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n const pframeHandle = ctx.createPFrame(fullColumns);\n if (!fullHandle || !pframeHandle) return undefined;\n\n // Step 9: Determine hidden columns\n const hiddenColumns = new Set<PObjectId>(\n ((): PObjectId[] => {\n // Inner join works as a filter — all columns must be present\n if (coreJoinType === \"inner\") return [];\n\n const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;\n if (hiddenColIds) return hiddenColIds;\n\n return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);\n })(),\n );\n\n // Preserve linker columns\n columns.filter((c) => isLinkerColumn(c.spec)).forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve core columns as they change the shape of join\n const coreColumnPredicate = options?.coreColumnPredicate;\n if (coreColumnPredicate) {\n const coreColumns = columns.flatMap((c) =>\n coreColumnPredicate(getColumnIdAndSpec(c)) ? [c.id] : [],\n );\n coreColumns.forEach((c) => hiddenColumns.delete(c));\n }\n\n // Preserve sorted columns from being hidden\n sorting\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve filter columns from being hidden\n if (filters) {\n collectFilterSpecColumns(filters)\n .flatMap((c) => {\n const obj = parseJson(c);\n return obj.type === \"column\" ? [obj.id] : [];\n })\n .forEach((c) => hiddenColumns.delete(c));\n }\n\n // Step 10: Build visible table definition\n const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));\n const visibleLabelColumns = getMatchingLabelColumns(\n visibleColumns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n if (!allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return undefined;\n\n const visibleDef = createPTableDef({\n columns: visibleColumns,\n labelColumns: visibleLabelColumns,\n coreJoinType,\n filters,\n sorting,\n coreColumnPredicate,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n if (!visibleHandle) return undefined;\n\n return {\n sourceId: tableStateNormalized.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n } satisfies PlDataTableModel;\n } finally {\n collection.dispose();\n }\n}\n\n/** Normalize raw ColumnSource | ColumnSource[] into a flat list of sources. */\nfunction normalizeSourceList(source: ColumnSource | ColumnSource[]): ColumnSource[] {\n if (\n Array.isArray(source) &&\n source.length > 0 &&\n (Array.isArray(source[0]) || isColumnSnapshotProvider(source[0]))\n ) {\n return source as ColumnSource[];\n }\n return [source as ColumnSource];\n}\n"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { PlDataTableStateV2 } from "../state-migration.js";
|
|
|
5
5
|
import { ColumnSource } from "../../../columns/column_snapshot_provider.js";
|
|
6
6
|
import { MatchingMode } from "../../../columns/column_collection_builder.js";
|
|
7
7
|
import "../../../columns/index.js";
|
|
8
|
-
import { Annotation, DataInfo, MultiColumnSelector, PColumn, PColumnIdAndSpec, PColumnSpec, PColumnValues, PObjectId, PTableColumnId, PTableDefV2, PTableSorting, PlRef, SpecQueryExpression } from "@milaboratories/pl-model-common";
|
|
8
|
+
import { Annotation, DataInfo, MultiColumnSelector, PColumn, PColumnIdAndSpec, PColumnSpec, PColumnValues, PObjectId, PTableColumnId, PTableDefV2, PTableSorting, PlRef, RequireServices, Services, SpecQueryExpression } from "@milaboratories/pl-model-common";
|
|
9
9
|
|
|
10
10
|
//#region src/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts
|
|
11
11
|
/** Check if column should be omitted from the table */
|
|
@@ -33,7 +33,7 @@ type createPlDataTableOptionsV3 = {
|
|
|
33
33
|
coreColumnPredicate?: (spec: PColumnIdAndSpec) => boolean;
|
|
34
34
|
state?: PlDataTableStateV2;
|
|
35
35
|
};
|
|
36
|
-
declare function createPlDataTableV3<A, U
|
|
36
|
+
declare function createPlDataTableV3<A, U, S extends RequireServices<typeof Services.PFrameSpec>>(ctx: RenderCtxBase<A, U, S>, options: createPlDataTableOptionsV3): PlDataTableModel | undefined;
|
|
37
37
|
//#endregion
|
|
38
38
|
export { createPlDataTableOptionsV3, createPlDataTableV3, isColumnHidden, isColumnOptional };
|
|
39
39
|
//# sourceMappingURL=createPlDataTableV3.d.ts.map
|
|
@@ -90,100 +90,104 @@ function isColumnOptional(spec) {
|
|
|
90
90
|
function createPlDataTableV3(ctx, options) {
|
|
91
91
|
const providers = options.source ? normalizeSourceList(options.source).filter(isColumnSnapshotProvider) : collectCtxColumnSnapshotProviders(ctx);
|
|
92
92
|
if (providers.length === 0) return void 0;
|
|
93
|
-
const builder = new ColumnCollectionBuilder(ctx).addSources(providers);
|
|
93
|
+
const builder = new ColumnCollectionBuilder(ctx.services.pframeSpec).addSources(providers);
|
|
94
94
|
const anchors = options.columns.anchors;
|
|
95
95
|
const collection = isNil(anchors) ? builder.build() : builder.build({ anchors });
|
|
96
96
|
if (!collection) return void 0;
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
97
|
+
try {
|
|
98
|
+
const findOptions = options.columns ? {
|
|
99
|
+
include: options.columns.include,
|
|
100
|
+
exclude: options.columns.exclude,
|
|
101
|
+
mode: options.columns.mode,
|
|
102
|
+
maxHops: options.columns.maxHops
|
|
103
|
+
} : void 0;
|
|
104
|
+
const dataSnapshots = collection.findColumns(findOptions).map((v) => "column" in v ? v.column : v).filter((s) => !isColumnHidden(s.spec));
|
|
105
|
+
if (dataSnapshots.length === 0) return void 0;
|
|
106
|
+
const columns = [];
|
|
107
|
+
for (const snap of dataSnapshots) {
|
|
108
|
+
if (!snap.data) return void 0;
|
|
109
|
+
const data = snap.data.get();
|
|
110
|
+
if (data === void 0) return void 0;
|
|
111
|
+
columns.push({
|
|
112
|
+
id: snap.id,
|
|
113
|
+
spec: snap.spec,
|
|
114
|
+
data
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const tableStateNormalized = upgradePlDataTableStateV2(options.state);
|
|
118
|
+
const allLabelColumns = getAllLabelColumns(ctx.resultPool);
|
|
119
|
+
if (!allLabelColumns) return void 0;
|
|
120
|
+
const fullLabelColumns = getMatchingLabelColumns(columns.map(getColumnIdAndSpec), allLabelColumns);
|
|
121
|
+
const fullColumns = [...columns, ...fullLabelColumns];
|
|
122
|
+
const fullColumnsIds = [...uniqueBy(fullColumns.flatMap((c) => c.spec.axesSpec.map((a) => getAxisId(a))), (a) => canonicalizeJson(a)).map((a) => ({
|
|
123
|
+
type: "axis",
|
|
124
|
+
id: a
|
|
125
|
+
})), ...fullColumns.map((c) => ({
|
|
126
|
+
type: "column",
|
|
127
|
+
id: c.id
|
|
128
|
+
}))];
|
|
129
|
+
const fullColumnsIdsSet = new Set(fullColumnsIds.map((c) => canonicalizeJson(c)));
|
|
130
|
+
const isValidColumnId = (id) => fullColumnsIdsSet.has(id);
|
|
131
|
+
const stateFilters = tableStateNormalized.pTableParams.filters;
|
|
132
|
+
const opsFilters = options?.filters ?? null;
|
|
133
|
+
const filters = stateFilters != null && opsFilters != null ? {
|
|
134
|
+
type: "and",
|
|
135
|
+
filters: [stateFilters, opsFilters]
|
|
136
|
+
} : stateFilters ?? opsFilters;
|
|
137
|
+
const firstInvalidFilterColumn = (filters ? collectFilterSpecColumns(filters) : []).find((col) => !isValidColumnId(col));
|
|
138
|
+
if (firstInvalidFilterColumn) throw new Error(`Invalid filter column ${firstInvalidFilterColumn}: column reference does not match the table columns`);
|
|
139
|
+
const userSorting = tableStateNormalized.pTableParams.sorting;
|
|
140
|
+
const sorting = (isEmpty(userSorting) ? options?.sorting : userSorting) ?? [];
|
|
141
|
+
const firstInvalidSortingColumn = sorting.find((s) => !isValidColumnId(canonicalizeJson(s.column)));
|
|
142
|
+
if (firstInvalidSortingColumn) throw new Error(`Invalid sorting column ${JSON.stringify(firstInvalidSortingColumn.column)}: column reference does not match the table columns`);
|
|
143
|
+
const coreJoinType = options?.coreJoinType ?? "full";
|
|
144
|
+
const fullDef = createPTableDef({
|
|
145
|
+
columns,
|
|
146
|
+
labelColumns: fullLabelColumns,
|
|
147
|
+
coreJoinType,
|
|
148
|
+
filters,
|
|
149
|
+
sorting,
|
|
150
|
+
coreColumnPredicate: options?.coreColumnPredicate
|
|
151
|
+
});
|
|
152
|
+
const fullHandle = ctx.createPTableV2(fullDef);
|
|
153
|
+
const pframeHandle = ctx.createPFrame(fullColumns);
|
|
154
|
+
if (!fullHandle || !pframeHandle) return void 0;
|
|
155
|
+
const hiddenColumns = new Set((() => {
|
|
156
|
+
if (coreJoinType === "inner") return [];
|
|
157
|
+
const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;
|
|
158
|
+
if (hiddenColIds) return hiddenColIds;
|
|
159
|
+
return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);
|
|
160
|
+
})());
|
|
161
|
+
columns.filter((c) => isLinkerColumn(c.spec)).forEach((c) => hiddenColumns.delete(c.id));
|
|
162
|
+
const coreColumnPredicate = options?.coreColumnPredicate;
|
|
163
|
+
if (coreColumnPredicate) columns.flatMap((c) => coreColumnPredicate(getColumnIdAndSpec(c)) ? [c.id] : []).forEach((c) => hiddenColumns.delete(c));
|
|
164
|
+
sorting.map((s) => s.column).filter((c) => c.type === "column").forEach((c) => hiddenColumns.delete(c.id));
|
|
165
|
+
if (filters) collectFilterSpecColumns(filters).flatMap((c) => {
|
|
166
|
+
const obj = parseJson(c);
|
|
167
|
+
return obj.type === "column" ? [obj.id] : [];
|
|
168
|
+
}).forEach((c) => hiddenColumns.delete(c));
|
|
169
|
+
const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));
|
|
170
|
+
const visibleLabelColumns = getMatchingLabelColumns(visibleColumns.map(getColumnIdAndSpec), allLabelColumns);
|
|
171
|
+
if (!allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return void 0;
|
|
172
|
+
const visibleDef = createPTableDef({
|
|
173
|
+
columns: visibleColumns,
|
|
174
|
+
labelColumns: visibleLabelColumns,
|
|
175
|
+
coreJoinType,
|
|
176
|
+
filters,
|
|
177
|
+
sorting,
|
|
178
|
+
coreColumnPredicate
|
|
114
179
|
});
|
|
180
|
+
const visibleHandle = ctx.createPTableV2(visibleDef);
|
|
181
|
+
if (!visibleHandle) return void 0;
|
|
182
|
+
return {
|
|
183
|
+
sourceId: tableStateNormalized.pTableParams.sourceId,
|
|
184
|
+
fullTableHandle: fullHandle,
|
|
185
|
+
fullPframeHandle: pframeHandle,
|
|
186
|
+
visibleTableHandle: visibleHandle
|
|
187
|
+
};
|
|
188
|
+
} finally {
|
|
189
|
+
collection.dispose();
|
|
115
190
|
}
|
|
116
|
-
const tableStateNormalized = upgradePlDataTableStateV2(options.state);
|
|
117
|
-
const allLabelColumns = getAllLabelColumns(ctx.resultPool);
|
|
118
|
-
if (!allLabelColumns) return void 0;
|
|
119
|
-
const fullLabelColumns = getMatchingLabelColumns(columns.map(getColumnIdAndSpec), allLabelColumns);
|
|
120
|
-
const fullColumns = [...columns, ...fullLabelColumns];
|
|
121
|
-
const fullColumnsIds = [...uniqueBy(fullColumns.flatMap((c) => c.spec.axesSpec.map((a) => getAxisId(a))), (a) => canonicalizeJson(a)).map((a) => ({
|
|
122
|
-
type: "axis",
|
|
123
|
-
id: a
|
|
124
|
-
})), ...fullColumns.map((c) => ({
|
|
125
|
-
type: "column",
|
|
126
|
-
id: c.id
|
|
127
|
-
}))];
|
|
128
|
-
const fullColumnsIdsSet = new Set(fullColumnsIds.map((c) => canonicalizeJson(c)));
|
|
129
|
-
const isValidColumnId = (id) => fullColumnsIdsSet.has(id);
|
|
130
|
-
const stateFilters = tableStateNormalized.pTableParams.filters;
|
|
131
|
-
const opsFilters = options?.filters ?? null;
|
|
132
|
-
const filters = stateFilters != null && opsFilters != null ? {
|
|
133
|
-
type: "and",
|
|
134
|
-
filters: [stateFilters, opsFilters]
|
|
135
|
-
} : stateFilters ?? opsFilters;
|
|
136
|
-
const firstInvalidFilterColumn = (filters ? collectFilterSpecColumns(filters) : []).find((col) => !isValidColumnId(col));
|
|
137
|
-
if (firstInvalidFilterColumn) throw new Error(`Invalid filter column ${firstInvalidFilterColumn}: column reference does not match the table columns`);
|
|
138
|
-
const userSorting = tableStateNormalized.pTableParams.sorting;
|
|
139
|
-
const sorting = (isEmpty(userSorting) ? options?.sorting : userSorting) ?? [];
|
|
140
|
-
const firstInvalidSortingColumn = sorting.find((s) => !isValidColumnId(canonicalizeJson(s.column)));
|
|
141
|
-
if (firstInvalidSortingColumn) throw new Error(`Invalid sorting column ${JSON.stringify(firstInvalidSortingColumn.column)}: column reference does not match the table columns`);
|
|
142
|
-
const coreJoinType = options?.coreJoinType ?? "full";
|
|
143
|
-
const fullDef = createPTableDef({
|
|
144
|
-
columns,
|
|
145
|
-
labelColumns: fullLabelColumns,
|
|
146
|
-
coreJoinType,
|
|
147
|
-
filters,
|
|
148
|
-
sorting,
|
|
149
|
-
coreColumnPredicate: options?.coreColumnPredicate
|
|
150
|
-
});
|
|
151
|
-
const fullHandle = ctx.createPTableV2(fullDef);
|
|
152
|
-
const pframeHandle = ctx.createPFrame(fullColumns);
|
|
153
|
-
if (!fullHandle || !pframeHandle) return void 0;
|
|
154
|
-
const hiddenColumns = new Set((() => {
|
|
155
|
-
if (coreJoinType === "inner") return [];
|
|
156
|
-
const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;
|
|
157
|
-
if (hiddenColIds) return hiddenColIds;
|
|
158
|
-
return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);
|
|
159
|
-
})());
|
|
160
|
-
columns.filter((c) => isLinkerColumn(c.spec)).forEach((c) => hiddenColumns.delete(c.id));
|
|
161
|
-
const coreColumnPredicate = options?.coreColumnPredicate;
|
|
162
|
-
if (coreColumnPredicate) columns.flatMap((c) => coreColumnPredicate(getColumnIdAndSpec(c)) ? [c.id] : []).forEach((c) => hiddenColumns.delete(c));
|
|
163
|
-
sorting.map((s) => s.column).filter((c) => c.type === "column").forEach((c) => hiddenColumns.delete(c.id));
|
|
164
|
-
if (filters) collectFilterSpecColumns(filters).flatMap((c) => {
|
|
165
|
-
const obj = parseJson(c);
|
|
166
|
-
return obj.type === "column" ? [obj.id] : [];
|
|
167
|
-
}).forEach((c) => hiddenColumns.delete(c));
|
|
168
|
-
const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));
|
|
169
|
-
const visibleLabelColumns = getMatchingLabelColumns(visibleColumns.map(getColumnIdAndSpec), allLabelColumns);
|
|
170
|
-
if (!allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return void 0;
|
|
171
|
-
const visibleDef = createPTableDef({
|
|
172
|
-
columns: visibleColumns,
|
|
173
|
-
labelColumns: visibleLabelColumns,
|
|
174
|
-
coreJoinType,
|
|
175
|
-
filters,
|
|
176
|
-
sorting,
|
|
177
|
-
coreColumnPredicate
|
|
178
|
-
});
|
|
179
|
-
const visibleHandle = ctx.createPTableV2(visibleDef);
|
|
180
|
-
if (!visibleHandle) return void 0;
|
|
181
|
-
return {
|
|
182
|
-
sourceId: tableStateNormalized.pTableParams.sourceId,
|
|
183
|
-
fullTableHandle: fullHandle,
|
|
184
|
-
fullPframeHandle: pframeHandle,
|
|
185
|
-
visibleTableHandle: visibleHandle
|
|
186
|
-
};
|
|
187
191
|
}
|
|
188
192
|
/** Normalize raw ColumnSource | ColumnSource[] into a flat list of sources. */
|
|
189
193
|
function normalizeSourceList(source) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createPlDataTableV3.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts"],"sourcesContent":["import type {\n AxisId,\n CanonicalizedJson,\n DataInfo,\n PColumn,\n PColumnIdAndSpec,\n PColumnValues,\n PObjectId,\n PTableColumnId,\n PTableColumnIdAxis,\n PTableColumnIdColumn,\n PTableDefV2,\n PTableSorting,\n SpecQuery,\n SingleAxisSelector,\n SpecQueryExpression,\n SpecQueryJoinEntry,\n PColumnSpec,\n PlRef,\n MultiColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n isLinkerColumn,\n readAnnotation,\n isBooleanExpression,\n parseJson,\n uniqueBy,\n} from \"@milaboratories/pl-model-common\";\nimport { filterSpecToSpecQueryExpr } from \"../../../filters\";\nimport { collectFilterSpecColumns } from \"../../../filters/traverse\";\nimport type { RenderCtxBase, TreeNodeAccessor, PColumnDataUniversal } from \"../../../render\";\nimport { allPColumnsReady } from \"../../../render\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport { isEmpty } from \"es-toolkit/compat\";\nimport { distillFilterSpec } from \"../../../filters/distill\";\nimport type { PlDataTableFilters, PlDataTableModel } from \"../typesV5\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport type { ColumnSource, MatchingMode } from \"../../../columns\";\nimport { ColumnCollectionBuilder } from \"../../../columns\";\nimport { isColumnSnapshotProvider } from \"../../../columns/column_snapshot_provider\";\nimport { collectCtxColumnSnapshotProviders } from \"../../../columns/ctx_column_sources\";\nimport { getAllLabelColumns, getMatchingLabelColumns } from \"../labels\";\n\n/** Convert a PTableColumnId to a SpecQueryExpression reference. */\nexport function columnIdToExpr(col: PTableColumnId): SpecQueryExpression {\n if (col.type === \"axis\") {\n return { type: \"axisRef\", value: col.id as SingleAxisSelector };\n }\n return { type: \"columnRef\", value: col.id };\n}\n\n/** Wrap a SpecQuery as a SpecQueryJoinEntry with empty qualifications. */\nexport function joinEntry<C>(input: SpecQuery<C>): SpecQueryJoinEntry<C> {\n return { entry: input, qualifications: [] };\n}\n\nexport function createPTableDef(params: {\n columns: PColumn<PColumnDataUniversal>[];\n labelColumns: PColumn<PColumnDataUniversal>[];\n coreJoinType: \"inner\" | \"full\";\n filters: null | PlDataTableFilters;\n sorting: PTableSorting[];\n coreColumnPredicate?: (spec: PColumnIdAndSpec) => boolean;\n}): PTableDefV2<PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>> {\n let coreColumns = params.columns;\n const secondaryColumns: typeof params.columns = [];\n\n if (isFunction(params.coreColumnPredicate)) {\n coreColumns = [];\n for (const c of params.columns)\n if (params.coreColumnPredicate(getColumnIdAndSpec(c))) coreColumns.push(c);\n else secondaryColumns.push(c);\n }\n\n secondaryColumns.push(...params.labelColumns);\n\n // Build SpecQuery directly from columns\n const coreJoinQuery: SpecQuery<\n PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>\n > = {\n type: params.coreJoinType === \"inner\" ? \"innerJoin\" : \"fullJoin\",\n entries: coreColumns.map((c) => joinEntry({ type: \"column\", column: c })),\n };\n\n let query: SpecQuery<PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>> = {\n type: \"outerJoin\",\n primary: joinEntry(coreJoinQuery),\n secondary: secondaryColumns.map((c) => joinEntry({ type: \"column\", column: c })),\n };\n\n // Apply filters\n if (params.filters !== null) {\n const nonEmpty = distillFilterSpec(params.filters);\n\n if (!isNil(nonEmpty)) {\n const pridicate = filterSpecToSpecQueryExpr(nonEmpty);\n if (!isBooleanExpression(pridicate)) {\n throw new Error(\n `Filter conversion produced a non-boolean expression (got type \"${pridicate.type}\"), expected a boolean predicate for query filtering`,\n );\n }\n query = {\n type: \"filter\",\n input: query,\n predicate: pridicate,\n };\n }\n }\n\n // Apply sorting\n if (params.sorting.length > 0) {\n query = {\n type: \"sort\",\n input: query,\n sortBy: params.sorting.map((s) => ({\n expression: columnIdToExpr(s.column),\n ascending: s.ascending,\n nullsFirst: !s.naAndAbsentAreLeastValues,\n })),\n };\n }\n\n return { query };\n}\n\n/** Check if column should be omitted from the table */\nexport function isColumnHidden(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"hidden\";\n}\n\n/** Check if column is hidden by default */\nexport function isColumnOptional(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"optional\";\n}\n\n/** Structured source config — selectors/anchors instead of raw ColumnSource. */\ntype ColumnsSelectorConfig = {\n include?: MultiColumnSelector | MultiColumnSelector[];\n exclude?: MultiColumnSelector | MultiColumnSelector[];\n anchors?: Record<string, PlRef | PObjectId | PColumnSpec>;\n mode?: MatchingMode;\n maxHops?: number;\n};\n\nexport type createPlDataTableOptionsV3 = {\n source?: ColumnSource | ColumnSource[];\n columns: ColumnsSelectorConfig;\n\n // Existing from V2\n filters?: PlDataTableFilters;\n sorting?: PTableSorting[];\n coreJoinType?: \"inner\" | \"full\";\n coreColumnPredicate?: (spec: PColumnIdAndSpec) => boolean;\n\n state?: PlDataTableStateV2;\n};\n\n// interface ColumnDisplayConfig {\n// /** Column ordering rules. Higher priority = further left. First matching rule wins. */\n// ordering?: ColumnOrderRule[];\n// /** Column visibility rules. First matching rule wins. Unmatched columns use default visibility. */\n// visibility?: ColumnVisibilityRule[];\n// }\n\n// interface ColumnOrderRule {\n// match: ColumnMatcher;\n// /** Higher number = further left in table */\n// priority: number;\n// }\n\n// interface ColumnVisibilityRule {\n// match: ColumnMatcher;\n// visibility: \"default\" | \"optional\" | \"hidden\";\n// }\n\n// type ColumnMatcher =\n// | ((spec: PColumnSpec) => boolean)\n// | { name: string | string[] }\n// | { annotation: Record<string, string> }\n// | { ids: Set<string> };\n\nexport function createPlDataTableV3<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: createPlDataTableOptionsV3,\n): PlDataTableModel | undefined {\n const providers = options.source\n ? normalizeSourceList(options.source).filter(isColumnSnapshotProvider)\n : collectCtxColumnSnapshotProviders(ctx);\n\n if (providers.length === 0) return undefined;\n\n // Step 1: Build collection from sources\n const builder = new ColumnCollectionBuilder(ctx).addSources(providers);\n const anchors = options.columns.anchors;\n const collection = isNil(anchors) ? builder.build() : builder.build({ anchors });\n\n if (!collection) return undefined;\n\n // Step 2: Get data columns, excluding annotation-hidden ones\n const findOptions = options.columns\n ? {\n include: options.columns.include,\n exclude: options.columns.exclude,\n mode: options.columns.mode,\n maxHops: options.columns.maxHops,\n }\n : undefined;\n const findResult = collection.findColumns(findOptions);\n const snapshots = findResult.map((v) => (\"column\" in v ? v.column : v));\n const dataSnapshots = snapshots.filter((s) => !isColumnHidden(s.spec));\n if (dataSnapshots.length === 0) return undefined;\n\n // Convert snapshots to PColumn<PColumnDataUniversal>[]\n const columns: PColumn<PColumnDataUniversal>[] = [];\n for (const snap of dataSnapshots) {\n if (!snap.data) return undefined;\n const data = snap.data.get();\n if (data === undefined) return undefined;\n columns.push({ id: snap.id, spec: snap.spec, data });\n }\n\n // Step 3: Normalize table state\n const tableStateNormalized = upgradePlDataTableStateV2(options.state);\n\n // Step 4: Get label columns from result pool and match to data columns\n const allLabelColumns = getAllLabelColumns(ctx.resultPool);\n if (!allLabelColumns) return undefined;\n\n const fullLabelColumns = getMatchingLabelColumns(\n columns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n const fullColumns = [...columns, ...fullLabelColumns];\n\n // Step 5: Build column ID set for filter/sorting validation\n const fullColumnsAxes = uniqueBy(\n fullColumns.flatMap((c) => c.spec.axesSpec.map((a) => getAxisId(a))),\n (a) => canonicalizeJson<AxisId>(a),\n );\n const fullColumnsIds: PTableColumnId[] = [\n ...fullColumnsAxes.map((a) => ({ type: \"axis\", id: a }) satisfies PTableColumnIdAxis),\n ...fullColumns.map((c) => ({ type: \"column\", id: c.id }) satisfies PTableColumnIdColumn),\n ];\n const fullColumnsIdsSet = new Set(fullColumnsIds.map((c) => canonicalizeJson<PTableColumnId>(c)));\n const isValidColumnId = (id: string): boolean =>\n fullColumnsIdsSet.has(id as CanonicalizedJson<PTableColumnId>);\n\n // Step 6: Filtering validation\n const stateFilters = tableStateNormalized.pTableParams.filters;\n const opsFilters = options?.filters ?? null;\n const filters: null | PlDataTableFilters =\n stateFilters != null && opsFilters != null\n ? { type: \"and\", filters: [stateFilters, opsFilters] }\n : (stateFilters ?? opsFilters);\n const filterColumns = filters ? collectFilterSpecColumns(filters) : [];\n const firstInvalidFilterColumn = filterColumns.find((col) => !isValidColumnId(col));\n if (firstInvalidFilterColumn)\n throw new Error(\n `Invalid filter column ${firstInvalidFilterColumn}: column reference does not match the table columns`,\n );\n\n // Step 7: Sorting validation\n const userSorting = tableStateNormalized.pTableParams.sorting;\n const sorting = (isEmpty(userSorting) ? options?.sorting : userSorting) ?? [];\n const firstInvalidSortingColumn = sorting.find(\n (s) => !isValidColumnId(canonicalizeJson<PTableColumnId>(s.column)),\n );\n if (firstInvalidSortingColumn)\n throw new Error(\n `Invalid sorting column ${JSON.stringify(firstInvalidSortingColumn.column)}: column reference does not match the table columns`,\n );\n\n // Step 8: Build full table definition and handles\n const coreJoinType = options?.coreJoinType ?? \"full\";\n const fullDef = createPTableDef({\n columns,\n labelColumns: fullLabelColumns,\n coreJoinType,\n filters,\n sorting,\n coreColumnPredicate: options?.coreColumnPredicate,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n const pframeHandle = ctx.createPFrame(fullColumns);\n if (!fullHandle || !pframeHandle) return undefined;\n\n // Step 9: Determine hidden columns\n const hiddenColumns = new Set<PObjectId>(\n ((): PObjectId[] => {\n // Inner join works as a filter — all columns must be present\n if (coreJoinType === \"inner\") return [];\n\n const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;\n if (hiddenColIds) return hiddenColIds;\n\n return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);\n })(),\n );\n\n // Preserve linker columns\n columns.filter((c) => isLinkerColumn(c.spec)).forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve core columns as they change the shape of join\n const coreColumnPredicate = options?.coreColumnPredicate;\n if (coreColumnPredicate) {\n const coreColumns = columns.flatMap((c) =>\n coreColumnPredicate(getColumnIdAndSpec(c)) ? [c.id] : [],\n );\n coreColumns.forEach((c) => hiddenColumns.delete(c));\n }\n\n // Preserve sorted columns from being hidden\n sorting\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve filter columns from being hidden\n if (filters) {\n collectFilterSpecColumns(filters)\n .flatMap((c) => {\n const obj = parseJson(c);\n return obj.type === \"column\" ? [obj.id] : [];\n })\n .forEach((c) => hiddenColumns.delete(c));\n }\n\n // Step 10: Build visible table definition\n const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));\n const visibleLabelColumns = getMatchingLabelColumns(\n visibleColumns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n if (!allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return undefined;\n\n const visibleDef = createPTableDef({\n columns: visibleColumns,\n labelColumns: visibleLabelColumns,\n coreJoinType,\n filters,\n sorting,\n coreColumnPredicate,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n if (!visibleHandle) return undefined;\n\n return {\n sourceId: tableStateNormalized.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n } satisfies PlDataTableModel;\n}\n\n/** Normalize raw ColumnSource | ColumnSource[] into a flat list of sources. */\nfunction normalizeSourceList(source: ColumnSource | ColumnSource[]): ColumnSource[] {\n if (\n Array.isArray(source) &&\n source.length > 0 &&\n (Array.isArray(source[0]) || isColumnSnapshotProvider(source[0]))\n ) {\n return source as ColumnSource[];\n }\n return [source as ColumnSource];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createPlDataTableV3.js","names":[],"sources":["../../../../src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts"],"sourcesContent":["import type {\n AxisId,\n CanonicalizedJson,\n DataInfo,\n PColumn,\n PColumnIdAndSpec,\n PColumnValues,\n PObjectId,\n PTableColumnId,\n PTableColumnIdAxis,\n PTableColumnIdColumn,\n PTableDefV2,\n PTableSorting,\n SpecQuery,\n SingleAxisSelector,\n SpecQueryExpression,\n SpecQueryJoinEntry,\n PColumnSpec,\n PlRef,\n MultiColumnSelector,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n isLinkerColumn,\n readAnnotation,\n isBooleanExpression,\n parseJson,\n uniqueBy,\n} from \"@milaboratories/pl-model-common\";\nimport { filterSpecToSpecQueryExpr } from \"../../../filters\";\nimport { collectFilterSpecColumns } from \"../../../filters/traverse\";\nimport type { RenderCtxBase, TreeNodeAccessor, PColumnDataUniversal } from \"../../../render\";\nimport { allPColumnsReady } from \"../../../render\";\nimport { isFunction, isNil } from \"es-toolkit\";\nimport { isEmpty } from \"es-toolkit/compat\";\nimport { distillFilterSpec } from \"../../../filters/distill\";\nimport type { PlDataTableFilters, PlDataTableModel } from \"../typesV5\";\nimport { upgradePlDataTableStateV2 } from \"../state-migration\";\nimport type { PlDataTableStateV2 } from \"../state-migration\";\nimport type { ColumnSource, MatchingMode } from \"../../../columns\";\nimport { Services, type RequireServices } from \"@milaboratories/pl-model-common\";\nimport { ColumnCollectionBuilder } from \"../../../columns\";\nimport { isColumnSnapshotProvider } from \"../../../columns/column_snapshot_provider\";\nimport { collectCtxColumnSnapshotProviders } from \"../../../columns/ctx_column_sources\";\nimport { getAllLabelColumns, getMatchingLabelColumns } from \"../labels\";\n\n/** Convert a PTableColumnId to a SpecQueryExpression reference. */\nexport function columnIdToExpr(col: PTableColumnId): SpecQueryExpression {\n if (col.type === \"axis\") {\n return { type: \"axisRef\", value: col.id as SingleAxisSelector };\n }\n return { type: \"columnRef\", value: col.id };\n}\n\n/** Wrap a SpecQuery as a SpecQueryJoinEntry with empty qualifications. */\nexport function joinEntry<C>(input: SpecQuery<C>): SpecQueryJoinEntry<C> {\n return { entry: input, qualifications: [] };\n}\n\nexport function createPTableDef(params: {\n columns: PColumn<PColumnDataUniversal>[];\n labelColumns: PColumn<PColumnDataUniversal>[];\n coreJoinType: \"inner\" | \"full\";\n filters: null | PlDataTableFilters;\n sorting: PTableSorting[];\n coreColumnPredicate?: (spec: PColumnIdAndSpec) => boolean;\n}): PTableDefV2<PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>> {\n let coreColumns = params.columns;\n const secondaryColumns: typeof params.columns = [];\n\n if (isFunction(params.coreColumnPredicate)) {\n coreColumns = [];\n for (const c of params.columns)\n if (params.coreColumnPredicate(getColumnIdAndSpec(c))) coreColumns.push(c);\n else secondaryColumns.push(c);\n }\n\n secondaryColumns.push(...params.labelColumns);\n\n // Build SpecQuery directly from columns\n const coreJoinQuery: SpecQuery<\n PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>\n > = {\n type: params.coreJoinType === \"inner\" ? \"innerJoin\" : \"fullJoin\",\n entries: coreColumns.map((c) => joinEntry({ type: \"column\", column: c })),\n };\n\n let query: SpecQuery<PColumn<TreeNodeAccessor | PColumnValues | DataInfo<TreeNodeAccessor>>> = {\n type: \"outerJoin\",\n primary: joinEntry(coreJoinQuery),\n secondary: secondaryColumns.map((c) => joinEntry({ type: \"column\", column: c })),\n };\n\n // Apply filters\n if (params.filters !== null) {\n const nonEmpty = distillFilterSpec(params.filters);\n\n if (!isNil(nonEmpty)) {\n const pridicate = filterSpecToSpecQueryExpr(nonEmpty);\n if (!isBooleanExpression(pridicate)) {\n throw new Error(\n `Filter conversion produced a non-boolean expression (got type \"${pridicate.type}\"), expected a boolean predicate for query filtering`,\n );\n }\n query = {\n type: \"filter\",\n input: query,\n predicate: pridicate,\n };\n }\n }\n\n // Apply sorting\n if (params.sorting.length > 0) {\n query = {\n type: \"sort\",\n input: query,\n sortBy: params.sorting.map((s) => ({\n expression: columnIdToExpr(s.column),\n ascending: s.ascending,\n nullsFirst: !s.naAndAbsentAreLeastValues,\n })),\n };\n }\n\n return { query };\n}\n\n/** Check if column should be omitted from the table */\nexport function isColumnHidden(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"hidden\";\n}\n\n/** Check if column is hidden by default */\nexport function isColumnOptional(spec: { annotations?: Annotation }): boolean {\n return readAnnotation(spec, Annotation.Table.Visibility) === \"optional\";\n}\n\n/** Structured source config — selectors/anchors instead of raw ColumnSource. */\ntype ColumnsSelectorConfig = {\n include?: MultiColumnSelector | MultiColumnSelector[];\n exclude?: MultiColumnSelector | MultiColumnSelector[];\n anchors?: Record<string, PlRef | PObjectId | PColumnSpec>;\n mode?: MatchingMode;\n maxHops?: number;\n};\n\nexport type createPlDataTableOptionsV3 = {\n source?: ColumnSource | ColumnSource[];\n columns: ColumnsSelectorConfig;\n\n // Existing from V2\n filters?: PlDataTableFilters;\n sorting?: PTableSorting[];\n coreJoinType?: \"inner\" | \"full\";\n coreColumnPredicate?: (spec: PColumnIdAndSpec) => boolean;\n\n state?: PlDataTableStateV2;\n};\n\n// interface ColumnDisplayConfig {\n// /** Column ordering rules. Higher priority = further left. First matching rule wins. */\n// ordering?: ColumnOrderRule[];\n// /** Column visibility rules. First matching rule wins. Unmatched columns use default visibility. */\n// visibility?: ColumnVisibilityRule[];\n// }\n\n// interface ColumnOrderRule {\n// match: ColumnMatcher;\n// /** Higher number = further left in table */\n// priority: number;\n// }\n\n// interface ColumnVisibilityRule {\n// match: ColumnMatcher;\n// visibility: \"default\" | \"optional\" | \"hidden\";\n// }\n\n// type ColumnMatcher =\n// | ((spec: PColumnSpec) => boolean)\n// | { name: string | string[] }\n// | { annotation: Record<string, string> }\n// | { ids: Set<string> };\n\nexport function createPlDataTableV3<A, U, S extends RequireServices<typeof Services.PFrameSpec>>(\n ctx: RenderCtxBase<A, U, S>,\n options: createPlDataTableOptionsV3,\n): PlDataTableModel | undefined {\n const providers = options.source\n ? normalizeSourceList(options.source).filter(isColumnSnapshotProvider)\n : collectCtxColumnSnapshotProviders(ctx);\n\n if (providers.length === 0) return undefined;\n\n // Step 1: Build collection from sources\n const builder = new ColumnCollectionBuilder(ctx.services.pframeSpec).addSources(providers);\n const anchors = options.columns.anchors;\n const collection = isNil(anchors) ? builder.build() : builder.build({ anchors });\n\n if (!collection) return undefined;\n try {\n // Step 2: Get data columns, excluding annotation-hidden ones\n const findOptions = options.columns\n ? {\n include: options.columns.include,\n exclude: options.columns.exclude,\n mode: options.columns.mode,\n maxHops: options.columns.maxHops,\n }\n : undefined;\n const findResult = collection.findColumns(findOptions);\n const snapshots = findResult.map((v) => (\"column\" in v ? v.column : v));\n const dataSnapshots = snapshots.filter((s) => !isColumnHidden(s.spec));\n if (dataSnapshots.length === 0) return undefined;\n\n // Convert snapshots to PColumn<PColumnDataUniversal>[]\n const columns: PColumn<PColumnDataUniversal>[] = [];\n for (const snap of dataSnapshots) {\n if (!snap.data) return undefined;\n const data = snap.data.get();\n if (data === undefined) return undefined;\n columns.push({ id: snap.id, spec: snap.spec, data });\n }\n\n // Step 3: Normalize table state\n const tableStateNormalized = upgradePlDataTableStateV2(options.state);\n\n // Step 4: Get label columns from result pool and match to data columns\n const allLabelColumns = getAllLabelColumns(ctx.resultPool);\n if (!allLabelColumns) return undefined;\n\n const fullLabelColumns = getMatchingLabelColumns(\n columns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n const fullColumns = [...columns, ...fullLabelColumns];\n\n // Step 5: Build column ID set for filter/sorting validation\n const fullColumnsAxes = uniqueBy(\n fullColumns.flatMap((c) => c.spec.axesSpec.map((a) => getAxisId(a))),\n (a) => canonicalizeJson<AxisId>(a),\n );\n const fullColumnsIds: PTableColumnId[] = [\n ...fullColumnsAxes.map((a) => ({ type: \"axis\", id: a }) satisfies PTableColumnIdAxis),\n ...fullColumns.map((c) => ({ type: \"column\", id: c.id }) satisfies PTableColumnIdColumn),\n ];\n const fullColumnsIdsSet = new Set(\n fullColumnsIds.map((c) => canonicalizeJson<PTableColumnId>(c)),\n );\n const isValidColumnId = (id: string): boolean =>\n fullColumnsIdsSet.has(id as CanonicalizedJson<PTableColumnId>);\n\n // Step 6: Filtering validation\n const stateFilters = tableStateNormalized.pTableParams.filters;\n const opsFilters = options?.filters ?? null;\n const filters: null | PlDataTableFilters =\n stateFilters != null && opsFilters != null\n ? { type: \"and\", filters: [stateFilters, opsFilters] }\n : (stateFilters ?? opsFilters);\n const filterColumns = filters ? collectFilterSpecColumns(filters) : [];\n const firstInvalidFilterColumn = filterColumns.find((col) => !isValidColumnId(col));\n if (firstInvalidFilterColumn)\n throw new Error(\n `Invalid filter column ${firstInvalidFilterColumn}: column reference does not match the table columns`,\n );\n\n // Step 7: Sorting validation\n const userSorting = tableStateNormalized.pTableParams.sorting;\n const sorting = (isEmpty(userSorting) ? options?.sorting : userSorting) ?? [];\n const firstInvalidSortingColumn = sorting.find(\n (s) => !isValidColumnId(canonicalizeJson<PTableColumnId>(s.column)),\n );\n if (firstInvalidSortingColumn)\n throw new Error(\n `Invalid sorting column ${JSON.stringify(firstInvalidSortingColumn.column)}: column reference does not match the table columns`,\n );\n\n // Step 8: Build full table definition and handles\n const coreJoinType = options?.coreJoinType ?? \"full\";\n const fullDef = createPTableDef({\n columns,\n labelColumns: fullLabelColumns,\n coreJoinType,\n filters,\n sorting,\n coreColumnPredicate: options?.coreColumnPredicate,\n });\n\n const fullHandle = ctx.createPTableV2(fullDef);\n const pframeHandle = ctx.createPFrame(fullColumns);\n if (!fullHandle || !pframeHandle) return undefined;\n\n // Step 9: Determine hidden columns\n const hiddenColumns = new Set<PObjectId>(\n ((): PObjectId[] => {\n // Inner join works as a filter — all columns must be present\n if (coreJoinType === \"inner\") return [];\n\n const hiddenColIds = tableStateNormalized.pTableParams.hiddenColIds;\n if (hiddenColIds) return hiddenColIds;\n\n return columns.filter((c) => isColumnOptional(c.spec)).map((c) => c.id);\n })(),\n );\n\n // Preserve linker columns\n columns.filter((c) => isLinkerColumn(c.spec)).forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve core columns as they change the shape of join\n const coreColumnPredicate = options?.coreColumnPredicate;\n if (coreColumnPredicate) {\n const coreColumns = columns.flatMap((c) =>\n coreColumnPredicate(getColumnIdAndSpec(c)) ? [c.id] : [],\n );\n coreColumns.forEach((c) => hiddenColumns.delete(c));\n }\n\n // Preserve sorted columns from being hidden\n sorting\n .map((s) => s.column)\n .filter((c): c is PTableColumnIdColumn => c.type === \"column\")\n .forEach((c) => hiddenColumns.delete(c.id));\n\n // Preserve filter columns from being hidden\n if (filters) {\n collectFilterSpecColumns(filters)\n .flatMap((c) => {\n const obj = parseJson(c);\n return obj.type === \"column\" ? [obj.id] : [];\n })\n .forEach((c) => hiddenColumns.delete(c));\n }\n\n // Step 10: Build visible table definition\n const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));\n const visibleLabelColumns = getMatchingLabelColumns(\n visibleColumns.map(getColumnIdAndSpec),\n allLabelColumns,\n );\n\n if (!allPColumnsReady([...visibleColumns, ...visibleLabelColumns])) return undefined;\n\n const visibleDef = createPTableDef({\n columns: visibleColumns,\n labelColumns: visibleLabelColumns,\n coreJoinType,\n filters,\n sorting,\n coreColumnPredicate,\n });\n const visibleHandle = ctx.createPTableV2(visibleDef);\n\n if (!visibleHandle) return undefined;\n\n return {\n sourceId: tableStateNormalized.pTableParams.sourceId,\n fullTableHandle: fullHandle,\n fullPframeHandle: pframeHandle,\n visibleTableHandle: visibleHandle,\n } satisfies PlDataTableModel;\n } finally {\n collection.dispose();\n }\n}\n\n/** Normalize raw ColumnSource | ColumnSource[] into a flat list of sources. */\nfunction normalizeSourceList(source: ColumnSource | ColumnSource[]): ColumnSource[] {\n if (\n Array.isArray(source) &&\n source.length > 0 &&\n (Array.isArray(source[0]) || isColumnSnapshotProvider(source[0]))\n ) {\n return source as ColumnSource[];\n }\n return [source as ColumnSource];\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["createPlDataTableV2","createPlDataTableV3"],"sources":["../../../../src/components/PlDataTable/createPlDataTable/index.ts"],"sourcesContent":["import type { RenderCtxBase } from \"../../../render\";\nimport type { PlDataTableModel } from \"../typesV5\";\nimport { createPlDataTableOptionsV2, createPlDataTableV2 } from \"./createPlDataTableV2\";\nimport { createPlDataTableV3 } from \"./createPlDataTableV3\";\nimport type { createPlDataTableOptionsV3 } from \"./createPlDataTableV3\";\n\nexport function createPlDataTable<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: { version: \"v2\" } & createPlDataTableOptionsV2,\n): ReturnType<typeof createPlDataTableV2>;\nexport function createPlDataTable<A, U
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["createPlDataTableV2","createPlDataTableV3"],"sources":["../../../../src/components/PlDataTable/createPlDataTable/index.ts"],"sourcesContent":["import { Services, type RequireServices } from \"@milaboratories/pl-model-common\";\nimport type { RenderCtxBase } from \"../../../render\";\nimport type { PlDataTableModel } from \"../typesV5\";\nimport { createPlDataTableOptionsV2, createPlDataTableV2 } from \"./createPlDataTableV2\";\nimport { createPlDataTableV3 } from \"./createPlDataTableV3\";\nimport type { createPlDataTableOptionsV3 } from \"./createPlDataTableV3\";\n\nexport function createPlDataTable<A, U>(\n ctx: RenderCtxBase<A, U>,\n options: { version: \"v2\" } & createPlDataTableOptionsV2,\n): ReturnType<typeof createPlDataTableV2>;\nexport function createPlDataTable<A, U, S extends RequireServices<typeof Services.PFrameSpec>>(\n ctx: RenderCtxBase<A, U, S>,\n options: { version?: \"v3\" } & createPlDataTableOptionsV3,\n): ReturnType<typeof createPlDataTableV3>;\nexport function createPlDataTable<A, U, S extends RequireServices<typeof Services.PFrameSpec>>(\n ctx: RenderCtxBase<A, U, S>,\n options:\n | ({ version: \"v2\" } & createPlDataTableOptionsV2)\n | ({ version?: \"v3\" } & createPlDataTableOptionsV3),\n): PlDataTableModel | undefined {\n if (options.version === \"v2\") {\n return createPlDataTableV2(ctx, options.columns, options.tableState, options.options);\n } else {\n // default version is last (v3 at the moment)\n return createPlDataTableV3(ctx, options);\n }\n}\n"],"mappings":";;;;AAeA,SAAgB,kBACd,KACA,SAG8B;AAC9B,KAAI,QAAQ,YAAY,KACtB,QAAOA,gDAAoB,KAAK,QAAQ,SAAS,QAAQ,YAAY,QAAQ,QAAQ;KAGrF,QAAOC,gDAAoB,KAAK,QAAQ"}
|
|
@@ -2,12 +2,13 @@ import { RenderCtxBase } from "../../../render/api.js";
|
|
|
2
2
|
import "../../../render/index.js";
|
|
3
3
|
import { createPlDataTableOptionsV2, createPlDataTableV2 } from "./createPlDataTableV2.js";
|
|
4
4
|
import { createPlDataTableOptionsV3, createPlDataTableV3 } from "./createPlDataTableV3.js";
|
|
5
|
+
import { RequireServices, Services } from "@milaboratories/pl-model-common";
|
|
5
6
|
|
|
6
7
|
//#region src/components/PlDataTable/createPlDataTable/index.d.ts
|
|
7
8
|
declare function createPlDataTable<A, U>(ctx: RenderCtxBase<A, U>, options: {
|
|
8
9
|
version: "v2";
|
|
9
10
|
} & createPlDataTableOptionsV2): ReturnType<typeof createPlDataTableV2>;
|
|
10
|
-
declare function createPlDataTable<A, U
|
|
11
|
+
declare function createPlDataTable<A, U, S extends RequireServices<typeof Services.PFrameSpec>>(ctx: RenderCtxBase<A, U, S>, options: {
|
|
11
12
|
version?: "v3";
|
|
12
13
|
} & createPlDataTableOptionsV3): ReturnType<typeof createPlDataTableV3>;
|
|
13
14
|
//#endregion
|