@platforma-sdk/ui-vue 1.42.53 → 1.43.1

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 (84) hide show
  1. package/.turbo/turbo-build.log +213 -207
  2. package/.turbo/turbo-type-check.log +1 -1
  3. package/CHANGELOG.md +20 -0
  4. package/dist/AgGridVue/useAgGridOptions.js +2 -3
  5. package/dist/AgGridVue/useAgGridOptions.js.map +1 -1
  6. package/dist/assets/multi-sequence-alignment.worker-Cm0gZp19.js +6 -0
  7. package/dist/assets/multi-sequence-alignment.worker-Cm0gZp19.js.map +1 -0
  8. package/dist/assets/phylogenetic-tree.worker-4CrExYEo.js +5 -0
  9. package/dist/assets/phylogenetic-tree.worker-4CrExYEo.js.map +1 -0
  10. package/dist/components/PlAgDataTable/PlAgRowCount.vue.js +2 -3
  11. package/dist/components/PlAgDataTable/PlAgRowCount.vue.js.map +1 -1
  12. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js +11 -12
  13. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js.map +1 -1
  14. package/dist/components/PlAgRowNumHeader.vue.js +8 -9
  15. package/dist/components/PlAgRowNumHeader.vue.js.map +1 -1
  16. package/dist/components/PlMultiSequenceAlignment/Consensus.vue.d.ts +1 -0
  17. package/dist/components/PlMultiSequenceAlignment/Consensus.vue2.js +48 -46
  18. package/dist/components/PlMultiSequenceAlignment/Consensus.vue2.js.map +1 -1
  19. package/dist/components/PlMultiSequenceAlignment/Consensus.vue3.js +5 -7
  20. package/dist/components/PlMultiSequenceAlignment/Consensus.vue3.js.map +1 -1
  21. package/dist/components/PlMultiSequenceAlignment/Legend.vue2.js +14 -13
  22. package/dist/components/PlMultiSequenceAlignment/Legend.vue2.js.map +1 -1
  23. package/dist/components/PlMultiSequenceAlignment/Legend.vue3.js +9 -8
  24. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.d.ts +16 -9
  25. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue2.js +117 -85
  26. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue2.js.map +1 -1
  27. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue3.js +25 -18
  28. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue3.js.map +1 -1
  29. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.d.ts +8 -0
  30. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.js +10 -0
  31. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.js.map +1 -0
  32. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue2.js +77 -0
  33. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue2.js.map +1 -0
  34. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue3.js +9 -0
  35. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue3.js.map +1 -0
  36. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.d.ts +26 -18
  37. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue2.js +119 -120
  38. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue2.js.map +1 -1
  39. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.js +7 -124
  40. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.js.map +1 -1
  41. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue2.js +124 -2
  42. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue2.js.map +1 -1
  43. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue3.js +9 -0
  44. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue3.js.map +1 -0
  45. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue2.js +90 -90
  46. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue2.js.map +1 -1
  47. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue3.js +9 -7
  48. package/dist/components/PlMultiSequenceAlignment/cell-size.d.ts +4 -0
  49. package/dist/components/PlMultiSequenceAlignment/cell-size.js +8 -0
  50. package/dist/components/PlMultiSequenceAlignment/cell-size.js.map +1 -0
  51. package/dist/components/PlMultiSequenceAlignment/data.d.ts +15 -10
  52. package/dist/components/PlMultiSequenceAlignment/data.js +309 -202
  53. package/dist/components/PlMultiSequenceAlignment/data.js.map +1 -1
  54. package/dist/components/PlMultiSequenceAlignment/markup.js +9 -7
  55. package/dist/components/PlMultiSequenceAlignment/markup.js.map +1 -1
  56. package/dist/components/PlMultiSequenceAlignment/migrations.js +15 -13
  57. package/dist/components/PlMultiSequenceAlignment/migrations.js.map +1 -1
  58. package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.worker.d.ts +6 -0
  59. package/dist/components/PlMultiSequenceAlignment/phylogenetic-tree.worker.d.ts +7 -0
  60. package/dist/components/PlMultiSequenceAlignment/settings.js +3 -4
  61. package/dist/components/PlMultiSequenceAlignment/settings.js.map +1 -1
  62. package/dist/index.js +25 -27
  63. package/dist/index.js.map +1 -1
  64. package/dist/lib.d.ts +1 -2
  65. package/package.json +6 -6
  66. package/src/components/PlMultiSequenceAlignment/Consensus.vue +38 -39
  67. package/src/components/PlMultiSequenceAlignment/Legend.vue +9 -9
  68. package/src/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue +222 -126
  69. package/src/components/PlMultiSequenceAlignment/PhylogeneticTree.vue +110 -0
  70. package/src/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue +28 -22
  71. package/src/components/PlMultiSequenceAlignment/SeqLogo.vue +77 -69
  72. package/src/components/PlMultiSequenceAlignment/Toolbar.vue +47 -39
  73. package/src/components/PlMultiSequenceAlignment/cell-size.ts +4 -0
  74. package/src/components/PlMultiSequenceAlignment/data.ts +361 -149
  75. package/src/components/PlMultiSequenceAlignment/markup.ts +10 -8
  76. package/src/components/PlMultiSequenceAlignment/migrations.ts +6 -1
  77. package/src/components/PlMultiSequenceAlignment/multi-sequence-alignment.worker.ts +54 -0
  78. package/src/components/PlMultiSequenceAlignment/phylogenetic-tree.worker.ts +89 -0
  79. package/src/components/PlMultiSequenceAlignment/settings.ts +1 -2
  80. package/src/lib.ts +1 -3
  81. package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.d.ts +0 -7
  82. package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.js +0 -51
  83. package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.js.map +0 -1
  84. package/src/components/PlMultiSequenceAlignment/multi-sequence-alignment.ts +0 -101
@@ -1 +1 @@
1
- {"version":3,"file":"data.js","sources":["../../../src/components/PlMultiSequenceAlignment/data.ts"],"sourcesContent":["import { isJsonEqual } from '@milaboratories/helpers';\nimport type { ListOptionNormalized } from '@milaboratories/uikit';\nimport {\n type CalculateTableDataRequest,\n type CanonicalizedJson,\n canonicalizeJson,\n createRowSelectionColumn,\n ensureError,\n getAxisId,\n getRawPlatformaInstance,\n isLabelColumn,\n isLinkerColumn,\n type JoinEntry,\n matchAxisId,\n parseJson,\n type PColumnIdAndSpec,\n type PFrameHandle,\n type PlMultiSequenceAlignmentColorSchemeOption,\n type PlMultiSequenceAlignmentSettings,\n type PlSelectionModel,\n type PObjectId,\n type PTableColumnId,\n type PTableSorting,\n pTableValue,\n readAnnotation,\n Annotation,\n readAnnotationJson,\n} from '@platforma-sdk/model';\nimport { ref, watch } from 'vue';\nimport { highlightByChemicalProperties } from './chemical-properties';\nimport {\n highlightByMarkup,\n markupAlignedSequence,\n parseMarkup,\n} from './markup';\nimport { multiSequenceAlignment } from './multi-sequence-alignment';\nimport { getResidueCounts } from './residue-counts';\nimport type { HighlightLegend, ResidueCounts } from './types';\n\nconst getPFrameDriver = () => getRawPlatformaInstance().pFrameDriver;\n\nexport const sequenceLimit = 1000;\n\nexport const useSequenceColumnsOptions = refreshOnDeepChange(\n getSequenceColumnsOptions,\n);\n\nexport const useLabelColumnsOptions = refreshOnDeepChange(\n getLabelColumnsOptions,\n);\n\nexport const useMarkupColumnsOptions = refreshOnDeepChange(\n getMarkupColumnsOptions,\n);\n\nexport const useMultipleAlignmentData = refreshOnDeepChange(\n getMultipleAlignmentData,\n);\n\nasync function getSequenceColumnsOptions({\n pFrame,\n sequenceColumnPredicate,\n}: {\n pFrame: PFrameHandle | undefined;\n sequenceColumnPredicate: (column: PColumnIdAndSpec) => boolean;\n}): Promise<OptionsWithDefaults<PObjectId> | undefined> {\n if (!pFrame) return;\n\n const pFrameDriver = getPFrameDriver();\n const columns = await pFrameDriver.listColumns(pFrame);\n const options = columns.values()\n .filter((column) => sequenceColumnPredicate(column))\n .map(({ spec, columnId }) => ({\n label: readAnnotation(spec, Annotation.Label) ?? 'Unlabeled column',\n value: columnId,\n }))\n .toArray();\n const defaults = options.map(({ value }) => value);\n return { options, defaults };\n}\n\nasync function getLabelColumnsOptions({\n pFrame,\n sequenceColumnIds,\n}: {\n pFrame: PFrameHandle | undefined;\n sequenceColumnIds: PObjectId[] | undefined;\n}): Promise<OptionsWithDefaults<PTableColumnId> | undefined> {\n if (!pFrame || !sequenceColumnIds) return;\n\n const pFrameDriver = getPFrameDriver();\n const columns = await pFrameDriver.listColumns(pFrame);\n const optionMap = new Map<CanonicalizedJson<PTableColumnId>, string>();\n\n const sequenceColumnsAxes = new Map(\n sequenceColumnIds.values().flatMap((id) => {\n const column = columns.find(({ columnId }) => columnId === id);\n if (!column) {\n throw new Error(`Couldn't find sequence column (ID: \\`${id}\\`).`);\n }\n return column.spec.axesSpec.values()\n .map((spec) => [canonicalizeJson(getAxisId(spec)), spec]);\n }),\n );\n\n for (const [axisIdJson, axisSpec] of sequenceColumnsAxes.entries()) {\n const axisId = parseJson(axisIdJson);\n const labelColumn = columns.find(({ spec }) =>\n isLabelColumn(spec) && matchAxisId(axisId, getAxisId(spec.axesSpec[0])),\n );\n optionMap.set(\n labelColumn\n ? canonicalizeJson({ type: 'column', id: labelColumn.columnId })\n : canonicalizeJson({ type: 'axis', id: axisId }),\n readAnnotation(labelColumn?.spec, Annotation.Label)\n ?? readAnnotation(axisSpec, Annotation.Label)\n ?? 'Unlabeled axis',\n );\n }\n\n const { hits: compatibleColumns } = await pFrameDriver.findColumns(pFrame, {\n columnFilter: {},\n compatibleWith: sequenceColumnsAxes.keys()\n .map((axisIdJson) => parseJson(axisIdJson))\n .toArray(),\n strictlyCompatible: false,\n });\n\n for (const { columnId, spec } of compatibleColumns) {\n const columnIdJson = canonicalizeJson({ type: 'column', id: columnId } satisfies PTableColumnId);\n if (optionMap.has(columnIdJson)) continue;\n optionMap.set(\n columnIdJson,\n readAnnotation(spec, Annotation.Label) ?? 'Unlabeled column',\n );\n }\n\n const options = optionMap.entries()\n .map(([value, label]) => ({ label, value: parseJson(value) }))\n .toArray();\n\n const defaults = options.values()\n .filter(({ value }) => {\n if (value.type === 'axis') return true;\n const column = columns.find(({ columnId }) => columnId === value.id);\n return column && isLabelColumn(column.spec);\n })\n .map(({ value }) => value)\n .toArray();\n return { options, defaults };\n}\n\nasync function getMarkupColumnsOptions({\n pFrame,\n sequenceColumnIds,\n}: {\n pFrame: PFrameHandle | undefined;\n sequenceColumnIds: PObjectId[] | undefined;\n}): Promise<ListOptionNormalized<PObjectId>[] | undefined> {\n if (!pFrame || sequenceColumnIds?.length !== 1) return;\n\n const pFrameDriver = getPFrameDriver();\n const columns = await pFrameDriver.listColumns(pFrame);\n const sequenceColumn = columns.find((column) =>\n column.columnId === sequenceColumnIds[0],\n );\n if (!sequenceColumn) {\n throw new Error(\n `Couldn't find sequence column (ID: \\`${sequenceColumnIds[0]}\\`).`,\n );\n }\n return columns.values()\n .filter((column) =>\n !!readAnnotationJson(column.spec, Annotation.Sequence.IsAnnotation)\n && isJsonEqual(sequenceColumn.spec.axesSpec, column.spec.axesSpec)\n && Object.entries(sequenceColumn.spec.domain ?? {}).every((\n [key, value],\n ) => column.spec.domain?.[key] === value),\n ).map(({ columnId, spec }) => ({\n value: columnId,\n label: readAnnotation(spec, Annotation.Label) ?? 'Unlabeled column',\n }))\n .toArray();\n}\n\nasync function getMultipleAlignmentData({\n pFrame,\n sequenceColumnIds,\n labelColumnIds,\n selection,\n colorScheme,\n alignmentParams,\n}: {\n pFrame: PFrameHandle | undefined;\n sequenceColumnIds: PObjectId[] | undefined;\n labelColumnIds: PTableColumnId[] | undefined;\n selection: PlSelectionModel | undefined;\n colorScheme: PlMultiSequenceAlignmentColorSchemeOption;\n alignmentParams: PlMultiSequenceAlignmentSettings['alignmentParams'];\n}): Promise<MultipleAlignmentData | undefined> {\n if (!pFrame || !sequenceColumnIds?.length || !labelColumnIds) return;\n\n const pFrameDriver = getPFrameDriver();\n const columns = await pFrameDriver.listColumns(pFrame);\n const linkerColumns = columns.filter((column) => isLinkerColumn(column.spec));\n\n const filterColumn = createRowSelectionColumn({ selection });\n\n // inner join of sequence columns\n let primaryEntry: JoinEntry<PObjectId> = {\n type: 'inner',\n entries: sequenceColumnIds.map((column) => ({\n type: 'column',\n column,\n })),\n };\n\n // if we have linkers, left join them\n if (linkerColumns.length > 0) {\n primaryEntry = {\n type: 'outer',\n primary: primaryEntry,\n secondary: linkerColumns.map(({ columnId }) => ({\n type: 'column',\n column: columnId,\n })),\n };\n }\n\n // inner join with filters\n if (filterColumn) {\n primaryEntry = {\n type: 'inner',\n entries: [\n primaryEntry,\n {\n type: 'inlineColumn',\n column: filterColumn,\n },\n ],\n };\n }\n\n // left join with labels\n const secondaryEntry: JoinEntry<PObjectId>[] = labelColumnIds\n .flatMap((column) => {\n if (column.type !== 'column') return [];\n return { type: 'column', column: column.id };\n });\n\n // and markup\n if (colorScheme.type === 'markup') {\n secondaryEntry.push({ type: 'column', column: colorScheme.columnId });\n }\n\n const sorting: PTableSorting[] = Array.from(\n new Set(\n sequenceColumnIds.values().flatMap((id) => {\n const column = columns.find(({ columnId }) => columnId === id);\n if (!column) {\n throw new Error(`Couldn't find sequence column (ID: ${id})`);\n }\n return column.spec.axesSpec\n .map((spec) => canonicalizeJson(getAxisId(spec)));\n }),\n ),\n )\n .sort()\n .map((id) => ({\n column: { type: 'axis', id: parseJson(id) },\n ascending: true,\n naAndAbsentAreLeastValues: true,\n }));\n\n const request: CalculateTableDataRequest<PObjectId> = {\n src: {\n type: 'outer',\n primary: primaryEntry,\n secondary: secondaryEntry,\n },\n filters: [],\n sorting,\n };\n\n const table = await pFrameDriver.calculateTableData(\n pFrame,\n JSON.parse(JSON.stringify(request)),\n {\n offset: 0,\n // +1 is a hack to check whether the selection is over the limit\n length: sequenceLimit + 1,\n },\n );\n\n let rowCount = table?.[0].data.data.length ?? 0;\n let exceedsLimit = false;\n if (rowCount > sequenceLimit) {\n rowCount = sequenceLimit;\n exceedsLimit = true;\n }\n\n const sequenceColumns = sequenceColumnIds.map((columnId) => {\n const column = table.find(({ spec }) => spec.id === columnId);\n if (!column) {\n throw new Error(`Couldn't find sequence column (ID: \\`${columnId}\\`).`);\n }\n return column;\n });\n\n const labelColumns = labelColumnIds.map((labelColumn) => {\n const column = table.find(({ spec }) => {\n if (labelColumn.type === 'axis' && spec.type === 'axis') {\n return isJsonEqual(labelColumn.id, spec.id);\n }\n if (labelColumn.type === 'column' && spec.type === 'column') {\n return labelColumn.id === spec.id;\n }\n });\n if (!column) {\n throw new Error(`Couldn't find label column (ID: \\`${labelColumn}\\`).`);\n }\n return column;\n });\n\n const alignedSequences = await Promise.all(\n sequenceColumns.map((column) =>\n multiSequenceAlignment(\n Array.from(\n { length: rowCount },\n (_, row) =>\n pTableValue(column.data, row, { na: '', absent: '' })?.toString()\n ?? '',\n ),\n alignmentParams,\n ),\n ),\n );\n\n const sequences = Array.from(\n { length: rowCount },\n (_, row) => alignedSequences.map((column) => column[row]),\n );\n\n const sequenceNames = sequenceColumns.map((column) =>\n readAnnotation(column.spec.spec, Annotation.Label) ?? 'Unlabeled column',\n );\n\n const labels = Array.from(\n { length: rowCount },\n (_, row) =>\n labelColumns.map((column) =>\n pTableValue(column.data, row, { na: '', absent: '' })?.toString() ?? '',\n ),\n );\n\n const concatenatedSequences = sequences.map((row) => row.join(' '));\n const residueCounts = getResidueCounts(concatenatedSequences);\n\n const result: MultipleAlignmentData = {\n sequences: concatenatedSequences,\n sequenceNames,\n labelRows: labels,\n exceedsLimit,\n residueCounts,\n };\n\n if (colorScheme.type === 'chemical-properties') {\n result.highlightImage = highlightByChemicalProperties({\n sequences: concatenatedSequences,\n residueCounts,\n });\n } else if (colorScheme.type === 'markup') {\n const markupColumn = table.find(({ spec }) =>\n spec.id === colorScheme.columnId,\n );\n if (!markupColumn) {\n throw new Error(\n `Couldn't find markup column (ID: \\`${colorScheme.columnId}\\`).`,\n );\n }\n const markupRows = Array.from(\n { length: rowCount },\n (_, row) => {\n const markup = parseMarkup(\n pTableValue(markupColumn.data, row, { na: '', absent: '' })\n ?.toString()\n ?? '',\n );\n return markupAlignedSequence(sequences[row][0], markup);\n },\n );\n const labels = readAnnotationJson(markupColumn.spec.spec, Annotation.Sequence.Annotation.Mapping) ?? {};\n result.highlightImage = highlightByMarkup({\n markupRows,\n columnCount: concatenatedSequences.at(0)?.length ?? 0,\n labels,\n });\n }\n\n return result;\n}\n\nfunction refreshOnDeepChange<T, P>(cb: (params: P) => Promise<T>) {\n const data = ref<T>();\n const isLoading = ref(true);\n const error = ref<Error>();\n let requestId: symbol;\n return (paramsGetter: () => P) => {\n watch(paramsGetter, async (params, prevParams) => {\n if (isJsonEqual(params, prevParams)) return;\n const currentRequestId = requestId = Symbol();\n try {\n error.value = undefined;\n isLoading.value = true;\n const result = await cb(params);\n if (currentRequestId === requestId) {\n data.value = result;\n }\n } catch (err) {\n console.error(err);\n if (currentRequestId === requestId) {\n error.value = ensureError(err);\n }\n } finally {\n if (currentRequestId === requestId) {\n isLoading.value = false;\n }\n }\n }, { immediate: true });\n return { data, isLoading, error };\n };\n}\n\ntype MultipleAlignmentData = {\n sequences: string[];\n sequenceNames: string[];\n labelRows: string[][];\n residueCounts: ResidueCounts;\n highlightImage?: {\n blob: Blob;\n legend: HighlightLegend;\n };\n exceedsLimit: boolean;\n};\n\ntype OptionsWithDefaults<T> = {\n options: ListOptionNormalized<T>[];\n defaults: T[];\n};\n"],"names":["getPFrameDriver","getRawPlatformaInstance","sequenceLimit","useSequenceColumnsOptions","refreshOnDeepChange","getSequenceColumnsOptions","useLabelColumnsOptions","getLabelColumnsOptions","useMarkupColumnsOptions","getMarkupColumnsOptions","useMultipleAlignmentData","getMultipleAlignmentData","pFrame","sequenceColumnPredicate","options","column","spec","columnId","readAnnotation","Annotation","defaults","value","sequenceColumnIds","pFrameDriver","columns","optionMap","sequenceColumnsAxes","id","canonicalizeJson","getAxisId","axisIdJson","axisSpec","axisId","parseJson","labelColumn","isLabelColumn","matchAxisId","compatibleColumns","columnIdJson","label","sequenceColumn","readAnnotationJson","isJsonEqual","key","_a","labelColumnIds","selection","colorScheme","alignmentParams","linkerColumns","isLinkerColumn","filterColumn","createRowSelectionColumn","primaryEntry","secondaryEntry","sorting","request","table","rowCount","exceedsLimit","sequenceColumns","labelColumns","alignedSequences","multiSequenceAlignment","_","row","pTableValue","sequences","sequenceNames","labels","concatenatedSequences","residueCounts","getResidueCounts","result","highlightByChemicalProperties","markupColumn","markupRows","markup","parseMarkup","markupAlignedSequence","highlightByMarkup","cb","data","ref","isLoading","error","requestId","paramsGetter","watch","params","prevParams","currentRequestId","err","ensureError"],"mappings":"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"}
1
+ {"version":3,"file":"data.js","sources":["../../../src/components/PlMultiSequenceAlignment/data.ts"],"sourcesContent":["import { isJsonEqual } from '@milaboratories/helpers';\nimport type { ListOptionNormalized } from '@milaboratories/uikit';\nimport {\n Annotation,\n type CalculateTableDataRequest,\n type CalculateTableDataResponse,\n type CanonicalizedJson,\n canonicalizeJson,\n createRowSelectionColumn,\n ensureError,\n getAxisId,\n getRawPlatformaInstance,\n isLabelColumn,\n isLinkerColumn,\n type JoinEntry,\n matchAxisId,\n parseJson,\n type PColumnIdAndSpec,\n type PFrameHandle,\n type PlMultiSequenceAlignmentColorSchemeOption,\n type PlMultiSequenceAlignmentSettings,\n type PlSelectionModel,\n type PObjectId,\n type PTableColumnId,\n type PTableSorting,\n pTableValue,\n readAnnotation,\n readAnnotationJson,\n} from '@platforma-sdk/model';\nimport { onWatcherCleanup, ref, watch } from 'vue';\nimport { objectHash } from '../../objectHash';\nimport { highlightByChemicalProperties } from './chemical-properties';\nimport type { Markup } from './markup';\nimport {\n highlightByMarkup,\n markupAlignedSequence,\n parseMarkup,\n} from './markup';\nimport type * as MultiSequenceAlignmentWorker from './multi-sequence-alignment.worker';\nimport type * as PhylogeneticTreeWorker from './phylogenetic-tree.worker';\nimport { getResidueCounts } from './residue-counts';\nimport type { HighlightLegend, ResidueCounts } from './types';\n\nconst getPFrameDriver = () => getRawPlatformaInstance().pFrameDriver;\n\nexport const SEQUENCE_LIMIT = 1000;\n\nexport const useSequenceColumnsOptions = refreshOnDeepChange(\n getSequenceColumnsOptions,\n);\n\nexport const useLabelColumnsOptions = refreshOnDeepChange(\n getLabelColumnsOptions,\n);\n\nexport const useMarkupColumnsOptions = refreshOnDeepChange(\n getMarkupColumnsOptions,\n);\n\nexport const useMultipleAlignmentData = refreshOnDeepChange(\n getMultipleAlignmentData,\n);\n\nasync function getSequenceColumnsOptions({ pFrame, sequenceColumnPredicate }: {\n pFrame: PFrameHandle | undefined;\n sequenceColumnPredicate: (column: PColumnIdAndSpec) => boolean;\n}): Promise<OptionsWithDefaults<PObjectId> | undefined> {\n if (!pFrame) return;\n\n const pFrameDriver = getPFrameDriver();\n const columns = await pFrameDriver.listColumns(pFrame);\n\n const options = columns.values()\n .filter((column) => sequenceColumnPredicate(column))\n .map(({ spec, columnId }) => ({\n label: readAnnotation(spec, Annotation.Label) ?? 'Unlabeled column',\n value: columnId,\n }))\n .toArray();\n\n const defaults = options.map(({ value }) => value);\n\n return { options, defaults };\n}\n\nasync function getLabelColumnsOptions({ pFrame, sequenceColumnIds }: {\n pFrame: PFrameHandle | undefined;\n sequenceColumnIds: PObjectId[] | undefined;\n}): Promise<OptionsWithDefaults<PTableColumnId> | undefined> {\n if (!pFrame || !sequenceColumnIds) return;\n\n const pFrameDriver = getPFrameDriver();\n const columns = await pFrameDriver.listColumns(pFrame);\n\n const sequenceColumnsAxes = new Map(\n sequenceColumnIds.values().flatMap((id) => {\n const column = columns.find(({ columnId }) => columnId === id);\n if (!column) {\n throw new Error(`Couldn't find sequence column (ID: \\`${id}\\`).`);\n }\n return column.spec.axesSpec.values()\n .map((spec) => [canonicalizeJson(getAxisId(spec)), spec]);\n }),\n );\n\n const optionMap = new Map<CanonicalizedJson<PTableColumnId>, string>();\n for (const [axisIdJson, axisSpec] of sequenceColumnsAxes.entries()) {\n const axisId = parseJson(axisIdJson);\n const labelColumn = columns.find(({ spec }) =>\n isLabelColumn(spec) && matchAxisId(axisId, getAxisId(spec.axesSpec[0])),\n );\n optionMap.set(\n labelColumn\n ? canonicalizeJson({ type: 'column', id: labelColumn.columnId })\n : canonicalizeJson({ type: 'axis', id: axisId }),\n readAnnotation(labelColumn?.spec, Annotation.Label)\n ?? readAnnotation(axisSpec, Annotation.Label)\n ?? 'Unlabeled axis',\n );\n }\n\n const { hits: compatibleColumns } = await pFrameDriver.findColumns(pFrame, {\n columnFilter: {},\n compatibleWith: sequenceColumnsAxes.keys()\n .map((axisIdJson) => parseJson(axisIdJson))\n .toArray(),\n strictlyCompatible: false,\n });\n\n for (const { columnId, spec } of compatibleColumns) {\n const columnIdJson = canonicalizeJson<PTableColumnId>({\n type: 'column',\n id: columnId,\n });\n if (optionMap.has(columnIdJson)) continue;\n optionMap.set(\n columnIdJson,\n readAnnotation(spec, Annotation.Label) ?? 'Unlabeled column',\n );\n }\n\n const options = optionMap.entries()\n .map(([value, label]) => ({ label, value: parseJson(value) }))\n .toArray();\n\n const defaults = options.values()\n .filter(({ value }) => {\n if (value.type === 'axis') return true;\n const column = columns.find(({ columnId }) => columnId === value.id);\n return column && isLabelColumn(column.spec);\n })\n .map(({ value }) => value)\n .toArray();\n\n return { options, defaults };\n}\n\nasync function getMarkupColumnsOptions({ pFrame, sequenceColumnIds }: {\n pFrame: PFrameHandle | undefined;\n sequenceColumnIds: PObjectId[] | undefined;\n}): Promise<ListOptionNormalized<PObjectId[]>[] | undefined> {\n if (!pFrame || !sequenceColumnIds) return;\n\n const pFrameDriver = getPFrameDriver();\n const columns = await pFrameDriver.listColumns(pFrame);\n\n const sequenceColumns = sequenceColumnIds.map((columnId) => {\n const column = columns.find((column) => column.columnId === columnId);\n if (!column) {\n throw new Error(\n `Couldn't find sequence column (ID: \\`${sequenceColumnIds[0]}\\`).`,\n );\n }\n return column;\n });\n\n const columnPairs = sequenceColumns\n .flatMap((sequenceColumn) =>\n columns\n .filter((column) =>\n readAnnotationJson(column.spec, Annotation.Sequence.IsAnnotation)\n && isJsonEqual(sequenceColumn.spec.axesSpec, column.spec.axesSpec)\n && Object.entries(sequenceColumn.spec.domain ?? {})\n .every(([key, value]) => column.spec.domain?.[key] === value),\n )\n .map((markupColumn) => ({ markupColumn, sequenceColumn })),\n );\n\n const groupedByDomainDiff = Map.groupBy(\n columnPairs,\n ({ markupColumn, sequenceColumn }) => {\n const domainDiff = Object.fromEntries(\n Object.entries(markupColumn.spec.domain ?? {})\n .filter(([key]) => sequenceColumn.spec.domain?.[key] == undefined),\n );\n return canonicalizeJson(domainDiff);\n },\n );\n\n return groupedByDomainDiff.entries()\n .map(([domainDiffJson, columnPairs]) => ({\n label: Object.values(parseJson(domainDiffJson)).join(', '),\n value: columnPairs.map(({ markupColumn }) => markupColumn.columnId),\n }))\n .toArray();\n}\n\nasync function getMultipleAlignmentData(\n {\n pFrame,\n sequenceColumnIds,\n labelColumnIds,\n selection,\n colorScheme,\n alignmentParams,\n shouldBuildPhylogeneticTree,\n }: {\n pFrame: PFrameHandle | undefined;\n sequenceColumnIds: PObjectId[] | undefined;\n labelColumnIds: PTableColumnId[] | undefined;\n selection: PlSelectionModel | undefined;\n colorScheme: PlMultiSequenceAlignmentColorSchemeOption;\n alignmentParams: PlMultiSequenceAlignmentSettings['alignmentParams'];\n shouldBuildPhylogeneticTree: boolean;\n },\n abortSignal: AbortSignal,\n): Promise<MultipleAlignmentData | undefined> {\n if (!pFrame || !sequenceColumnIds?.length || !labelColumnIds) return;\n\n const table = await getTableData({\n pFrame,\n sequenceColumnIds,\n labelColumnIds,\n selection,\n colorScheme,\n });\n\n const rowCount = table.at(0)?.data.data.length ?? 0;\n\n if (rowCount < 2) return;\n\n const exceedsLimit = rowCount > SEQUENCE_LIMIT;\n const rawSequences = extractSequences(sequenceColumnIds, table);\n const labels = extractLabels(labelColumnIds, table);\n const markups = colorScheme.type === 'markup'\n ? extractMarkups(colorScheme.columnIds, table)\n : undefined;\n\n const highlightLegend: HighlightLegend = {};\n\n const alignedSequences = await Promise.all(\n rawSequences.map(async ({ name, rows }) => ({\n name,\n rows: await alignSequences(\n rows,\n JSON.parse(JSON.stringify(alignmentParams)),\n abortSignal,\n ),\n })),\n );\n\n let phylogeneticTree: PhylogeneticTreeWorker.TreeNodeData[] | undefined;\n if (shouldBuildPhylogeneticTree) {\n phylogeneticTree = await buildPhylogeneticTree(\n alignedSequences,\n abortSignal,\n );\n const rowOrder = phylogeneticTree.values()\n .filter(({ id }) => id >= 0)\n .map(({ id }) => id)\n .toArray();\n for (const sequencesColumn of alignedSequences) {\n sequencesColumn.rows = rowOrder.map((i) => sequencesColumn.rows[i]);\n }\n for (const labelsColumn of labels) {\n labelsColumn.rows = rowOrder.map((i) => labelsColumn.rows[i]);\n }\n for (const markupsColumn of markups ?? []) {\n markupsColumn.rows = rowOrder.map((i) => markupsColumn.rows[i]);\n }\n }\n\n const sequences = await Promise.all(\n alignedSequences.map(async ({ name, rows }, index) => {\n const residueCounts = getResidueCounts(rows);\n const image = generateHighlightImage({\n colorScheme,\n sequences: rows,\n residueCounts,\n markup: markups?.at(index),\n });\n if (image) {\n Object.assign(highlightLegend, image.legend);\n }\n return {\n name,\n rows,\n residueCounts,\n ...image && {\n highlightImageUrl: await blobToBase64(image.blob),\n },\n } satisfies MultipleAlignmentData['sequences'][number];\n }),\n );\n\n return {\n sequences,\n labels,\n ...Object.keys(highlightLegend).length && {\n highlightLegend,\n },\n ...phylogeneticTree && {\n phylogeneticTree,\n },\n exceedsLimit,\n };\n}\n\nasync function getTableData(\n { pFrame, sequenceColumnIds, labelColumnIds, selection, colorScheme }: {\n pFrame: PFrameHandle;\n sequenceColumnIds: PObjectId[];\n labelColumnIds: PTableColumnId[];\n selection: PlSelectionModel | undefined;\n colorScheme: PlMultiSequenceAlignmentColorSchemeOption;\n },\n): Promise<CalculateTableDataResponse> {\n const pFrameDriver = getPFrameDriver();\n const columns = await pFrameDriver.listColumns(pFrame);\n const linkerColumns = columns.filter((column) => isLinkerColumn(column.spec));\n\n const filterColumn = createRowSelectionColumn({ selection });\n\n // inner join of sequence columns\n let primaryEntry: JoinEntry<PObjectId> = {\n type: 'inner',\n entries: sequenceColumnIds.map((column) => ({\n type: 'column',\n column,\n })),\n };\n\n // if we have linkers, left join them\n if (linkerColumns.length > 0) {\n primaryEntry = {\n type: 'outer',\n primary: primaryEntry,\n secondary: linkerColumns.map(({ columnId }) => ({\n type: 'column',\n column: columnId,\n })),\n };\n }\n\n // inner join with filters\n if (filterColumn) {\n primaryEntry = {\n type: 'inner',\n entries: [\n primaryEntry,\n {\n type: 'inlineColumn',\n column: filterColumn,\n },\n ],\n };\n }\n\n // left join with labels\n const secondaryEntry: JoinEntry<PObjectId>[] = labelColumnIds\n .flatMap((column) => {\n if (column.type !== 'column') return [];\n return { type: 'column', column: column.id };\n });\n\n // and markup\n if (colorScheme.type === 'markup') {\n for (const column of colorScheme.columnIds) {\n secondaryEntry.push({ type: 'column', column });\n }\n }\n\n const sorting: PTableSorting[] = Array.from(\n new Set(\n sequenceColumnIds.values().flatMap((id) => {\n const column = columns.find(({ columnId }) => columnId === id);\n if (!column) {\n throw new Error(`Couldn't find sequence column (ID: ${id})`);\n }\n return column.spec.axesSpec\n .map((spec) => canonicalizeJson(getAxisId(spec)));\n }),\n ),\n )\n .sort()\n .map((id) => ({\n column: { type: 'axis', id: parseJson(id) },\n ascending: true,\n naAndAbsentAreLeastValues: true,\n }));\n\n const request: CalculateTableDataRequest<PObjectId> = {\n src: {\n type: 'outer',\n primary: primaryEntry,\n secondary: secondaryEntry,\n },\n filters: [],\n sorting,\n };\n\n return pFrameDriver.calculateTableData(\n pFrame,\n JSON.parse(JSON.stringify(request)),\n {\n offset: 0,\n // +1 is a hack to check whether the selection is over the limit\n length: SEQUENCE_LIMIT + 1,\n },\n );\n}\n\nconst extractSequences = (\n columnIds: PObjectId[],\n table: CalculateTableDataResponse,\n): { name: string; rows: string[] }[] =>\n columnIds.map((columnId) => {\n const column = table.find(({ spec }) => spec.id === columnId);\n if (!column) {\n throw new Error(`Couldn't find sequence column (ID: \\`${columnId}\\`).`);\n }\n const name = readAnnotation(column.spec.spec, Annotation.Label)\n ?? 'Unlabeled column';\n const rows = column.data.data\n .keys()\n .take(SEQUENCE_LIMIT)\n .map((row) =>\n pTableValue(column.data, row, { absent: '', na: '' })?.toString()\n ?? '',\n )\n .toArray();\n return { name, rows };\n });\n\nconst extractLabels = (\n columnIds: PTableColumnId[],\n table: CalculateTableDataResponse,\n): { rows: string[] }[] =>\n columnIds.map((columnId) => {\n const column = table.find(({ spec }) => {\n if (columnId.type === 'axis' && spec.type === 'axis') {\n return isJsonEqual(columnId.id, spec.id);\n }\n if (columnId.type === 'column' && spec.type === 'column') {\n return columnId.id === spec.id;\n }\n });\n if (!column) {\n throw new Error(`Couldn't find label column (ID: \\`${columnId}\\`).`);\n }\n const rows = column.data.data\n .keys()\n .take(SEQUENCE_LIMIT)\n .map((row) =>\n pTableValue(column.data, row, { absent: '', na: '' })?.toString()\n ?? '',\n )\n .toArray();\n return { rows };\n });\n\nconst extractMarkups = (\n columnIds: PObjectId[],\n table: CalculateTableDataResponse,\n): { labels: Record<string, string>; rows: Markup[] }[] =>\n columnIds.map((columnId) => {\n const column = table.find(({ spec }) => spec.id === columnId);\n if (!column) {\n throw new Error(`Couldn't find markup column (ID: \\`${columnId}\\`).`);\n }\n const labels = readAnnotationJson(\n column.spec.spec,\n Annotation.Sequence.Annotation.Mapping,\n ) ?? {};\n const rows = column.data.data\n .keys()\n .take(SEQUENCE_LIMIT)\n .map((row) =>\n parseMarkup(\n pTableValue(column.data, row, { absent: '', na: '' })?.toString()\n ?? '',\n ),\n )\n .toArray();\n return { labels, rows };\n });\n\nconst alignSequences = (() => {\n const cache = new Map<string, string[]>();\n return async (\n sequences: string[],\n alignmentParams: PlMultiSequenceAlignmentSettings['alignmentParams'],\n abortSignal: AbortSignal,\n ): Promise<string[]> => {\n const hash = await objectHash([sequences, alignmentParams]);\n let result = cache.get(hash);\n if (result) return result;\n result = await runInWorker<\n MultiSequenceAlignmentWorker.RequestMessage,\n MultiSequenceAlignmentWorker.ResponseMessage\n >(\n new Worker(\n new URL('./multi-sequence-alignment.worker.ts', import.meta.url),\n { type: 'module' },\n ),\n { sequences, params: alignmentParams },\n abortSignal,\n );\n cache.set(hash, result);\n return result;\n };\n})();\n\nfunction generateHighlightImage(\n { colorScheme, sequences, residueCounts, markup }: {\n colorScheme: PlMultiSequenceAlignmentColorSchemeOption;\n sequences: string[];\n residueCounts: ResidueCounts;\n markup: { labels: Record<string, string>; rows: Markup[] } | undefined;\n },\n): { blob: Blob; legend: HighlightLegend } | undefined {\n if (colorScheme.type === 'chemical-properties') {\n return highlightByChemicalProperties({ sequences, residueCounts });\n }\n if (colorScheme.type === 'markup') {\n if (!markup) {\n throw new Error('Missing markup data.');\n }\n return highlightByMarkup({\n markupRows: sequences.map((sequence, row) => {\n const markupRow = markup.rows.at(row);\n if (!markupRow) throw new Error(`Missing markup for row ${row}.`);\n return markupAlignedSequence(sequence, markupRow);\n }),\n columnCount: sequences.at(0)?.length ?? 0,\n labels: markup.labels,\n });\n }\n}\n\nconst blobToBase64 = (blob: Blob): Promise<string> =>\n new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.addEventListener('load', () => resolve(reader.result as string));\n reader.addEventListener('error', () => reject(reader.error));\n reader.readAsDataURL(blob);\n });\n\nconst buildPhylogeneticTree = (() => {\n const cache = new Map<string, PhylogeneticTreeWorker.TreeNodeData[]>();\n return async (data: { rows: string[] }[], abortSignal: AbortSignal) => {\n const concatenatedSequences = data.at(0)?.rows\n .keys()\n .map((row) => data.map((column) => column.rows.at(row) ?? '').join(''))\n .toArray() ?? [];\n const hash = await objectHash(concatenatedSequences);\n let result = cache.get(hash);\n if (result) return result;\n result = await runInWorker<\n PhylogeneticTreeWorker.RequestMessage,\n PhylogeneticTreeWorker.ResponseMessage\n >(\n new Worker(\n new URL('./phylogenetic-tree.worker.ts', import.meta.url),\n { type: 'module' },\n ),\n concatenatedSequences,\n abortSignal,\n );\n cache.set(hash, result);\n return result;\n };\n})();\n\nconst runInWorker = <RequestMessage, ResponseMessage>(\n worker: Worker,\n message: RequestMessage,\n abortSignal: AbortSignal,\n) =>\n new Promise<ResponseMessage>((resolve, reject) => {\n worker.addEventListener('message', ({ data }) => {\n resolve(data);\n worker.terminate();\n });\n worker.addEventListener('error', ({ error, message }) => {\n reject(error ?? message);\n worker.terminate();\n });\n abortSignal.addEventListener('abort', () => {\n reject(abortSignal.reason);\n worker.terminate();\n });\n worker.postMessage(message);\n });\n\nfunction refreshOnDeepChange<T, P>(\n cb: (params: P, abortSignal: AbortSignal) => Promise<T>,\n) {\n const data = ref<T>();\n const isLoading = ref(true);\n const error = ref<Error>();\n let requestId: symbol;\n return (paramsGetter: () => P) => {\n watch(paramsGetter, async (params, prevParams) => {\n if (isJsonEqual(params, prevParams)) return;\n const abortController = new AbortController();\n const currentRequestId = requestId = Symbol();\n onWatcherCleanup(() => {\n abortController.abort();\n });\n try {\n error.value = undefined;\n isLoading.value = true;\n const result = await cb(params, abortController.signal);\n if (currentRequestId === requestId) {\n data.value = result;\n }\n } catch (err) {\n console.error(err);\n if (currentRequestId === requestId) {\n error.value = ensureError(err);\n }\n } finally {\n if (currentRequestId === requestId) {\n isLoading.value = false;\n }\n }\n }, { immediate: true });\n return { data, isLoading, error };\n };\n}\n\ntype MultipleAlignmentData = {\n sequences: {\n name: string;\n rows: string[];\n residueCounts: ResidueCounts;\n highlightImageUrl?: string;\n }[];\n labels: {\n rows: string[];\n }[];\n highlightLegend?: HighlightLegend;\n phylogeneticTree?: PhylogeneticTreeWorker.TreeNodeData[];\n exceedsLimit: boolean;\n};\n\ntype OptionsWithDefaults<T> = {\n options: ListOptionNormalized<T>[];\n defaults: T[];\n};\n"],"names":["getPFrameDriver","getRawPlatformaInstance","SEQUENCE_LIMIT","useSequenceColumnsOptions","refreshOnDeepChange","getSequenceColumnsOptions","useLabelColumnsOptions","getLabelColumnsOptions","useMarkupColumnsOptions","getMarkupColumnsOptions","useMultipleAlignmentData","getMultipleAlignmentData","pFrame","sequenceColumnPredicate","options","column","spec","columnId","readAnnotation","Annotation","defaults","value","sequenceColumnIds","pFrameDriver","columns","sequenceColumnsAxes","id","canonicalizeJson","getAxisId","optionMap","axisIdJson","axisSpec","axisId","parseJson","labelColumn","isLabelColumn","matchAxisId","compatibleColumns","columnIdJson","label","columnPairs","sequenceColumn","readAnnotationJson","isJsonEqual","key","_a","markupColumn","domainDiff","domainDiffJson","labelColumnIds","selection","colorScheme","alignmentParams","shouldBuildPhylogeneticTree","abortSignal","table","getTableData","rowCount","exceedsLimit","rawSequences","extractSequences","labels","extractLabels","markups","extractMarkups","highlightLegend","alignedSequences","name","rows","alignSequences","phylogeneticTree","buildPhylogeneticTree","rowOrder","sequencesColumn","i","labelsColumn","markupsColumn","index","residueCounts","getResidueCounts","image","generateHighlightImage","blobToBase64","linkerColumns","isLinkerColumn","filterColumn","createRowSelectionColumn","primaryEntry","secondaryEntry","sorting","request","columnIds","row","pTableValue","parseMarkup","cache","sequences","hash","objectHash","result","runInWorker","markup","highlightByChemicalProperties","highlightByMarkup","sequence","markupRow","markupAlignedSequence","blob","resolve","reject","reader","data","concatenatedSequences","worker","message","error","cb","ref","isLoading","requestId","paramsGetter","watch","params","prevParams","abortController","currentRequestId","onWatcherCleanup","err","ensureError"],"mappings":";;;;;;;;AA2CA,MAAMA,IAAkB,MAAMC,EAAA,EAA0B,cAE3CC,IAAiB,KAEjBC,KAA4BC;AAAA,EACvCC;AACF,GAEaC,KAAyBF;AAAA,EACpCG;AACF,GAEaC,KAA0BJ;AAAA,EACrCK;AACF,GAEaC,KAA2BN;AAAA,EACtCO;AACF;AAEA,eAAeN,EAA0B,EAAE,QAAAO,GAAQ,yBAAAC,KAGK;AACtD,MAAI,CAACD,EAAQ;AAKb,QAAME,KAFU,MADKd,EAAA,EACc,YAAYY,CAAM,GAE7B,OAAA,EACrB,OAAO,CAACG,MAAWF,EAAwBE,CAAM,CAAC,EAClD,IAAI,CAAC,EAAE,MAAAC,GAAM,UAAAC,SAAgB;AAAA,IAC5B,OAAOC,EAAeF,GAAMG,EAAW,KAAK,KAAK;AAAA,IACjD,OAAOF;AAAA,EAAA,EACP,EACD,QAAA,GAEGG,IAAWN,EAAQ,IAAI,CAAC,EAAE,OAAAO,EAAA,MAAYA,CAAK;AAEjD,SAAO,EAAE,SAAAP,GAAS,UAAAM,EAAA;AACpB;AAEA,eAAeb,EAAuB,EAAE,QAAAK,GAAQ,mBAAAU,KAGa;AAC3D,MAAI,CAACV,KAAU,CAACU,EAAmB;AAEnC,QAAMC,IAAevB,EAAA,GACfwB,IAAU,MAAMD,EAAa,YAAYX,CAAM,GAE/Ca,IAAsB,IAAI;AAAA,IAC9BH,EAAkB,OAAA,EAAS,QAAQ,CAACI,MAAO;AACzC,YAAMX,IAASS,EAAQ,KAAK,CAAC,EAAE,UAAAP,EAAA,MAAeA,MAAaS,CAAE;AAC7D,UAAI,CAACX;AACH,cAAM,IAAI,MAAM,wCAAwCW,CAAE,MAAM;AAElE,aAAOX,EAAO,KAAK,SAAS,OAAA,EACzB,IAAI,CAACC,MAAS,CAACW,EAAiBC,EAAUZ,CAAI,CAAC,GAAGA,CAAI,CAAC;AAAA,IAC5D,CAAC;AAAA,EAAA,GAGGa,wBAAgB,IAAA;AACtB,aAAW,CAACC,GAAYC,CAAQ,KAAKN,EAAoB,WAAW;AAClE,UAAMO,IAASC,EAAUH,CAAU,GAC7BI,IAAcV,EAAQ;AAAA,MAAK,CAAC,EAAE,MAAAR,EAAA,MAClCmB,EAAcnB,CAAI,KAAKoB,EAAYJ,GAAQJ,EAAUZ,EAAK,SAAS,CAAC,CAAC,CAAC;AAAA,IAAA;AAExE,IAAAa,EAAU;AAAA,MACRK,IACIP,EAAiB,EAAE,MAAM,UAAU,IAAIO,EAAY,SAAA,CAAU,IAC7DP,EAAiB,EAAE,MAAM,QAAQ,IAAIK,GAAQ;AAAA,MACjDd,EAAegB,KAAA,gBAAAA,EAAa,MAAMf,EAAW,KAAK,KAC/CD,EAAea,GAAUZ,EAAW,KAAK,KACzC;AAAA,IAAA;AAAA,EAEP;AAEA,QAAM,EAAE,MAAMkB,EAAA,IAAsB,MAAMd,EAAa,YAAYX,GAAQ;AAAA,IACzE,cAAc,CAAA;AAAA,IACd,gBAAgBa,EAAoB,KAAA,EACjC,IAAI,CAACK,MAAeG,EAAUH,CAAU,CAAC,EACzC,QAAA;AAAA,IACH,oBAAoB;AAAA,EAAA,CACrB;AAED,aAAW,EAAE,UAAAb,GAAU,MAAAD,EAAA,KAAUqB,GAAmB;AAClD,UAAMC,IAAeX,EAAiC;AAAA,MACpD,MAAM;AAAA,MACN,IAAIV;AAAA,IAAA,CACL;AACD,IAAIY,EAAU,IAAIS,CAAY,KAC9BT,EAAU;AAAA,MACRS;AAAA,MACApB,EAAeF,GAAMG,EAAW,KAAK,KAAK;AAAA,IAAA;AAAA,EAE9C;AAEA,QAAML,IAAUe,EAAU,QAAA,EACvB,IAAI,CAAC,CAACR,GAAOkB,CAAK,OAAO,EAAE,OAAAA,GAAO,OAAON,EAAUZ,CAAK,EAAA,EAAI,EAC5D,QAAA,GAEGD,IAAWN,EAAQ,OAAA,EACtB,OAAO,CAAC,EAAE,OAAAO,QAAY;AACrB,QAAIA,EAAM,SAAS,OAAQ,QAAO;AAClC,UAAMN,IAASS,EAAQ,KAAK,CAAC,EAAE,UAAAP,QAAeA,MAAaI,EAAM,EAAE;AACnE,WAAON,KAAUoB,EAAcpB,EAAO,IAAI;AAAA,EAC5C,CAAC,EACA,IAAI,CAAC,EAAE,OAAAM,EAAA,MAAYA,CAAK,EACxB,QAAA;AAEH,SAAO,EAAE,SAAAP,GAAS,UAAAM,EAAA;AACpB;AAEA,eAAeX,EAAwB,EAAE,QAAAG,GAAQ,mBAAAU,KAGY;AAC3D,MAAI,CAACV,KAAU,CAACU,EAAmB;AAGnC,QAAME,IAAU,MADKxB,EAAA,EACc,YAAYY,CAAM,GAY/C4B,IAVkBlB,EAAkB,IAAI,CAACL,MAAa;AAC1D,UAAMF,IAASS,EAAQ,KAAK,CAACT,MAAWA,EAAO,aAAaE,CAAQ;AACpE,QAAI,CAACF;AACH,YAAM,IAAI;AAAA,QACR,wCAAwCO,EAAkB,CAAC,CAAC;AAAA,MAAA;AAGhE,WAAOP;AAAA,EACT,CAAC,EAGE;AAAA,IAAQ,CAAC0B,MACRjB,EACG;AAAA,MAAO,CAACT,MACP2B,EAAmB3B,EAAO,MAAMI,EAAW,SAAS,YAAY,KAC7DwB,EAAYF,EAAe,KAAK,UAAU1B,EAAO,KAAK,QAAQ,KAC9D,OAAO,QAAQ0B,EAAe,KAAK,UAAU,CAAA,CAAE,EAC/C,MAAM,CAAC,CAACG,GAAKvB,CAAK;;AAAM,iBAAAwB,IAAA9B,EAAO,KAAK,WAAZ,gBAAA8B,EAAqBD,QAASvB;AAAA,OAAK;AAAA,IAAA,EAE/D,IAAI,CAACyB,OAAkB,EAAE,cAAAA,GAAc,gBAAAL,IAAiB;AAAA,EAAA;AAc/D,SAX4B,IAAI;AAAA,IAC9BD;AAAA,IACA,CAAC,EAAE,cAAAM,GAAc,gBAAAL,QAAqB;AACpC,YAAMM,IAAa,OAAO;AAAA,QACxB,OAAO,QAAQD,EAAa,KAAK,UAAU,CAAA,CAAE,EAC1C,OAAO,CAAC,CAACF,CAAG,MAAA;;AAAM,mBAAAC,IAAAJ,EAAe,KAAK,WAApB,gBAAAI,EAA6BD,OAAQ;AAAA,SAAS;AAAA,MAAA;AAErE,aAAOjB,EAAiBoB,CAAU;AAAA,IACpC;AAAA,EAAA,EAGyB,UACxB,IAAI,CAAC,CAACC,GAAgBR,CAAW,OAAO;AAAA,IACvC,OAAO,OAAO,OAAOP,EAAUe,CAAc,CAAC,EAAE,KAAK,IAAI;AAAA,IACzD,OAAOR,EAAY,IAAI,CAAC,EAAE,cAAAM,EAAA,MAAmBA,EAAa,QAAQ;AAAA,EAAA,EAClE,EACD,QAAA;AACL;AAEA,eAAenC,EACb;AAAA,EACE,QAAAC;AAAA,EACA,mBAAAU;AAAA,EACA,gBAAA2B;AAAA,EACA,WAAAC;AAAA,EACA,aAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,6BAAAC;AACF,GASAC,GAC4C;;AAC5C,MAAI,CAAC1C,KAAU,EAACU,KAAA,QAAAA,EAAmB,WAAU,CAAC2B,EAAgB;AAE9D,QAAMM,IAAQ,MAAMC,GAAa;AAAA,IAC/B,QAAA5C;AAAA,IACA,mBAAAU;AAAA,IACA,gBAAA2B;AAAA,IACA,WAAAC;AAAA,IACA,aAAAC;AAAA,EAAA,CACD,GAEKM,MAAWZ,IAAAU,EAAM,GAAG,CAAC,MAAV,gBAAAV,EAAa,KAAK,KAAK,WAAU;AAElD,MAAIY,IAAW,EAAG;AAElB,QAAMC,IAAeD,IAAWvD,GAC1ByD,IAAeC,GAAiBtC,GAAmBiC,CAAK,GACxDM,IAASC,GAAcb,GAAgBM,CAAK,GAC5CQ,IAAUZ,EAAY,SAAS,WACjCa,GAAeb,EAAY,WAAWI,CAAK,IAC3C,QAEEU,IAAmC,CAAA,GAEnCC,IAAmB,MAAM,QAAQ;AAAA,IACrCP,EAAa,IAAI,OAAO,EAAE,MAAAQ,GAAM,MAAAC,SAAY;AAAA,MAC1C,MAAAD;AAAA,MACA,MAAM,MAAME;AAAA,QACVD;AAAA,QACA,KAAK,MAAM,KAAK,UAAUhB,CAAe,CAAC;AAAA,QAC1CE;AAAA,MAAA;AAAA,IACF,EACA;AAAA,EAAA;AAGJ,MAAIgB;AACJ,MAAIjB,GAA6B;AAC/B,IAAAiB,IAAmB,MAAMC;AAAA,MACvBL;AAAA,MACAZ;AAAA,IAAA;AAEF,UAAMkB,IAAWF,EAAiB,OAAA,EAC/B,OAAO,CAAC,EAAE,IAAA5C,EAAA,MAASA,KAAM,CAAC,EAC1B,IAAI,CAAC,EAAE,IAAAA,QAASA,CAAE,EAClB,QAAA;AACH,eAAW+C,KAAmBP;AAC5B,MAAAO,EAAgB,OAAOD,EAAS,IAAI,CAACE,MAAMD,EAAgB,KAAKC,CAAC,CAAC;AAEpE,eAAWC,KAAgBd;AACzB,MAAAc,EAAa,OAAOH,EAAS,IAAI,CAACE,MAAMC,EAAa,KAAKD,CAAC,CAAC;AAE9D,eAAWE,KAAiBb,KAAW;AACrC,MAAAa,EAAc,OAAOJ,EAAS,IAAI,CAACE,MAAME,EAAc,KAAKF,CAAC,CAAC;AAAA,EAElE;AAyBA,SAAO;AAAA,IACL,WAxBgB,MAAM,QAAQ;AAAA,MAC9BR,EAAiB,IAAI,OAAO,EAAE,MAAAC,GAAM,MAAAC,EAAA,GAAQS,MAAU;AACpD,cAAMC,IAAgBC,EAAiBX,CAAI,GACrCY,IAAQC,GAAuB;AAAA,UACnC,aAAA9B;AAAA,UACA,WAAWiB;AAAA,UACX,eAAAU;AAAA,UACA,QAAQf,KAAA,gBAAAA,EAAS,GAAGc;AAAA,QAAK,CAC1B;AACD,eAAIG,KACF,OAAO,OAAOf,GAAiBe,EAAM,MAAM,GAEtC;AAAA,UACL,MAAAb;AAAA,UACA,MAAAC;AAAA,UACA,eAAAU;AAAA,UACA,GAAGE,KAAS;AAAA,YACV,mBAAmB,MAAME,GAAaF,EAAM,IAAI;AAAA,UAAA;AAAA,QAClD;AAAA,MAEJ,CAAC;AAAA,IAAA;AAAA,IAKD,QAAAnB;AAAA,IACA,GAAG,OAAO,KAAKI,CAAe,EAAE,UAAU;AAAA,MACxC,iBAAAA;AAAA,IAAA;AAAA,IAEF,GAAGK,KAAoB;AAAA,MACrB,kBAAAA;AAAA,IAAA;AAAA,IAEF,cAAAZ;AAAA,EAAA;AAEJ;AAEA,eAAeF,GACb,EAAE,QAAA5C,GAAQ,mBAAAU,GAAmB,gBAAA2B,GAAgB,WAAAC,GAAW,aAAAC,KAOnB;AACrC,QAAM5B,IAAevB,EAAA,GACfwB,IAAU,MAAMD,EAAa,YAAYX,CAAM,GAC/CuE,IAAgB3D,EAAQ,OAAO,CAACT,MAAWqE,EAAerE,EAAO,IAAI,CAAC,GAEtEsE,IAAeC,EAAyB,EAAE,WAAApC,GAAW;AAG3D,MAAIqC,IAAqC;AAAA,IACvC,MAAM;AAAA,IACN,SAASjE,EAAkB,IAAI,CAACP,OAAY;AAAA,MAC1C,MAAM;AAAA,MACN,QAAAA;AAAA,IAAA,EACA;AAAA,EAAA;AAIJ,EAAIoE,EAAc,SAAS,MACzBI,IAAe;AAAA,IACb,MAAM;AAAA,IACN,SAASA;AAAA,IACT,WAAWJ,EAAc,IAAI,CAAC,EAAE,UAAAlE,SAAgB;AAAA,MAC9C,MAAM;AAAA,MACN,QAAQA;AAAA,IAAA,EACR;AAAA,EAAA,IAKFoE,MACFE,IAAe;AAAA,IACb,MAAM;AAAA,IACN,SAAS;AAAA,MACPA;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,QAAQF;AAAA,MAAA;AAAA,IACV;AAAA,EACF;AAKJ,QAAMG,IAAyCvC,EAC5C,QAAQ,CAAClC,MACJA,EAAO,SAAS,WAAiB,CAAA,IAC9B,EAAE,MAAM,UAAU,QAAQA,EAAO,GAAA,CACzC;AAGH,MAAIoC,EAAY,SAAS;AACvB,eAAWpC,KAAUoC,EAAY;AAC/B,MAAAqC,EAAe,KAAK,EAAE,MAAM,UAAU,QAAAzE,GAAQ;AAIlD,QAAM0E,IAA2B,MAAM;AAAA,IACrC,IAAI;AAAA,MACFnE,EAAkB,OAAA,EAAS,QAAQ,CAACI,MAAO;AACzC,cAAMX,IAASS,EAAQ,KAAK,CAAC,EAAE,UAAAP,EAAA,MAAeA,MAAaS,CAAE;AAC7D,YAAI,CAACX;AACH,gBAAM,IAAI,MAAM,sCAAsCW,CAAE,GAAG;AAE7D,eAAOX,EAAO,KAAK,SAChB,IAAI,CAACC,MAASW,EAAiBC,EAAUZ,CAAI,CAAC,CAAC;AAAA,MACpD,CAAC;AAAA,IAAA;AAAA,EACH,EAEC,KAAA,EACA,IAAI,CAACU,OAAQ;AAAA,IACZ,QAAQ,EAAE,MAAM,QAAQ,IAAIO,EAAUP,CAAE,EAAA;AAAA,IACxC,WAAW;AAAA,IACX,2BAA2B;AAAA,EAAA,EAC3B,GAEEgE,IAAgD;AAAA,IACpD,KAAK;AAAA,MACH,MAAM;AAAA,MACN,SAASH;AAAA,MACT,WAAWC;AAAA,IAAA;AAAA,IAEb,SAAS,CAAA;AAAA,IACT,SAAAC;AAAA,EAAA;AAGF,SAAOlE,EAAa;AAAA,IAClBX;AAAA,IACA,KAAK,MAAM,KAAK,UAAU8E,CAAO,CAAC;AAAA,IAClC;AAAA,MACE,QAAQ;AAAA;AAAA,MAER,QAAQxF,IAAiB;AAAA,IAAA;AAAA,EAC3B;AAEJ;AAEA,MAAM0D,KAAmB,CACvB+B,GACApC,MAEAoC,EAAU,IAAI,CAAC1E,MAAa;AAC1B,QAAMF,IAASwC,EAAM,KAAK,CAAC,EAAE,MAAAvC,QAAWA,EAAK,OAAOC,CAAQ;AAC5D,MAAI,CAACF;AACH,UAAM,IAAI,MAAM,wCAAwCE,CAAQ,MAAM;AAExE,QAAMkD,IAAOjD,EAAeH,EAAO,KAAK,MAAMI,EAAW,KAAK,KACzD,oBACCiD,IAAOrD,EAAO,KAAK,KACtB,OACA,KAAKb,CAAc,EACnB;AAAA,IAAI,CAAC0F,MAAA;;AACJ,eAAA/C,IAAAgD,EAAY9E,EAAO,MAAM6E,GAAK,EAAE,QAAQ,IAAI,IAAI,IAAI,MAApD,gBAAA/C,EAAuD,eACpD;AAAA;AAAA,EAAA,EAEJ,QAAA;AACH,SAAO,EAAE,MAAAsB,GAAM,MAAAC,EAAA;AACjB,CAAC,GAEGN,KAAgB,CACpB6B,GACApC,MAEAoC,EAAU,IAAI,CAAC1E,MAAa;AAC1B,QAAMF,IAASwC,EAAM,KAAK,CAAC,EAAE,MAAAvC,QAAW;AACtC,QAAIC,EAAS,SAAS,UAAUD,EAAK,SAAS;AAC5C,aAAO2B,EAAY1B,EAAS,IAAID,EAAK,EAAE;AAEzC,QAAIC,EAAS,SAAS,YAAYD,EAAK,SAAS;AAC9C,aAAOC,EAAS,OAAOD,EAAK;AAAA,EAEhC,CAAC;AACD,MAAI,CAACD;AACH,UAAM,IAAI,MAAM,qCAAqCE,CAAQ,MAAM;AAUrE,SAAO,EAAE,MARIF,EAAO,KAAK,KACtB,OACA,KAAKb,CAAc,EACnB;AAAA,IAAI,CAAC0F,MAAA;;AACJ,eAAA/C,IAAAgD,EAAY9E,EAAO,MAAM6E,GAAK,EAAE,QAAQ,IAAI,IAAI,IAAI,MAApD,gBAAA/C,EAAuD,eACpD;AAAA;AAAA,EAAA,EAEJ,QAAA,EACM;AACX,CAAC,GAEGmB,KAAiB,CACrB2B,GACApC,MAEAoC,EAAU,IAAI,CAAC1E,MAAa;AAC1B,QAAMF,IAASwC,EAAM,KAAK,CAAC,EAAE,MAAAvC,QAAWA,EAAK,OAAOC,CAAQ;AAC5D,MAAI,CAACF;AACH,UAAM,IAAI,MAAM,sCAAsCE,CAAQ,MAAM;AAEtE,QAAM4C,IAASnB;AAAA,IACb3B,EAAO,KAAK;AAAA,IACZI,EAAW,SAAS,WAAW;AAAA,EAAA,KAC5B,CAAA,GACCiD,IAAOrD,EAAO,KAAK,KACtB,OACA,KAAKb,CAAc,EACnB;AAAA,IAAI,CAAC0F,MAAA;;AACJ,aAAAE;AAAA,UACEjD,IAAAgD,EAAY9E,EAAO,MAAM6E,GAAK,EAAE,QAAQ,IAAI,IAAI,IAAI,MAApD,gBAAA/C,EAAuD,eACpD;AAAA,MAAA;AAAA;AAAA,EACL,EAED,QAAA;AACH,SAAO,EAAE,QAAAgB,GAAQ,MAAAO,EAAA;AACnB,CAAC,GAEGC,KAAkB,uBAAM;AAC5B,QAAM0B,wBAAY,IAAA;AAClB,SAAO,OACLC,GACA5C,GACAE,MACsB;AACtB,UAAM2C,IAAO,MAAMC,EAAW,CAACF,GAAW5C,CAAe,CAAC;AAC1D,QAAI+C,IAASJ,EAAM,IAAIE,CAAI;AAC3B,WAAIE,MACJA,IAAS,MAAMC;AAAA,MAIb,IAAI;AAAA,QACF,IAAA;AAAA;AAAA,UAAA,KAAA,IAAA,IAAA,4DAAA,YAAA,GAAA,EAAA;AAAA,UAAA,YAAA;AAAA,QAAA;AAAA,QACA,EAAE,MAAM,SAAA;AAAA,MAAS;AAAA,MAEnB,EAAE,WAAAJ,GAAW,QAAQ5C,EAAA;AAAA,MACrBE;AAAA,IAAA,GAEFyC,EAAM,IAAIE,GAAME,CAAM,GACfA;AAAA,EACT;AACF,GAAA;AAEA,SAASlB,GACP,EAAE,aAAA9B,GAAa,WAAA6C,GAAW,eAAAlB,GAAe,QAAAuB,KAMY;;AACrD,MAAIlD,EAAY,SAAS;AACvB,WAAOmD,EAA8B,EAAE,WAAAN,GAAW,eAAAlB,GAAe;AAEnE,MAAI3B,EAAY,SAAS,UAAU;AACjC,QAAI,CAACkD;AACH,YAAM,IAAI,MAAM,sBAAsB;AAExC,WAAOE,EAAkB;AAAA,MACvB,YAAYP,EAAU,IAAI,CAACQ,GAAUZ,MAAQ;AAC3C,cAAMa,IAAYJ,EAAO,KAAK,GAAGT,CAAG;AACpC,YAAI,CAACa,EAAW,OAAM,IAAI,MAAM,0BAA0Bb,CAAG,GAAG;AAChE,eAAOc,EAAsBF,GAAUC,CAAS;AAAA,MAClD,CAAC;AAAA,MACD,eAAa5D,IAAAmD,EAAU,GAAG,CAAC,MAAd,gBAAAnD,EAAiB,WAAU;AAAA,MACxC,QAAQwD,EAAO;AAAA,IAAA,CAChB;AAAA,EACH;AACF;AAEA,MAAMnB,KAAe,CAACyB,MACpB,IAAI,QAAgB,CAACC,GAASC,MAAW;AACvC,QAAMC,IAAS,IAAI,WAAA;AACnB,EAAAA,EAAO,iBAAiB,QAAQ,MAAMF,EAAQE,EAAO,MAAgB,CAAC,GACtEA,EAAO,iBAAiB,SAAS,MAAMD,EAAOC,EAAO,KAAK,CAAC,GAC3DA,EAAO,cAAcH,CAAI;AAC3B,CAAC,GAEGpC,KAAyB,uBAAM;AACnC,QAAMwB,wBAAY,IAAA;AAClB,SAAO,OAAOgB,GAA4BzD,MAA6B;;AACrE,UAAM0D,MAAwBnE,IAAAkE,EAAK,GAAG,CAAC,MAAT,gBAAAlE,EAAY,KACvC,OACA,IAAI,CAAC+C,MAAQmB,EAAK,IAAI,CAAChG,MAAWA,EAAO,KAAK,GAAG6E,CAAG,KAAK,EAAE,EAAE,KAAK,EAAE,GACpE,cAAa,CAAA,GACVK,IAAO,MAAMC,EAAWc,CAAqB;AACnD,QAAIb,IAASJ,EAAM,IAAIE,CAAI;AAC3B,WAAIE,MACJA,IAAS,MAAMC;AAAA,MAIb,IAAI;AAAA,QACF,IAAA;AAAA;AAAA,UAAA,KAAA,IAAA,IAAA,qDAAA,YAAA,GAAA,EAAA;AAAA,UAAA,YAAA;AAAA,QAAA;AAAA,QACA,EAAE,MAAM,SAAA;AAAA,MAAS;AAAA,MAEnBY;AAAA,MACA1D;AAAA,IAAA,GAEFyC,EAAM,IAAIE,GAAME,CAAM,GACfA;AAAA,EACT;AACF,GAAA,GAEMC,IAAc,CAClBa,GACAC,GACA5D,MAEA,IAAI,QAAyB,CAACsD,GAASC,MAAW;AAChD,EAAAI,EAAO,iBAAiB,WAAW,CAAC,EAAE,MAAAF,QAAW;AAC/C,IAAAH,EAAQG,CAAI,GACZE,EAAO,UAAA;AAAA,EACT,CAAC,GACDA,EAAO,iBAAiB,SAAS,CAAC,EAAE,OAAAE,GAAO,SAAAD,QAAc;AACvD,IAAAL,EAAOM,KAASD,CAAO,GACvBD,EAAO,UAAA;AAAA,EACT,CAAC,GACD3D,EAAY,iBAAiB,SAAS,MAAM;AAC1C,IAAAuD,EAAOvD,EAAY,MAAM,GACzB2D,EAAO,UAAA;AAAA,EACT,CAAC,GACDA,EAAO,YAAYC,CAAO;AAC5B,CAAC;AAEH,SAAS9G,EACPgH,GACA;AACA,QAAML,IAAOM,EAAA,GACPC,IAAYD,EAAI,EAAI,GACpBF,IAAQE,EAAA;AACd,MAAIE;AACJ,SAAO,CAACC,OACNC,EAAMD,GAAc,OAAOE,GAAQC,MAAe;AAChD,QAAIhF,EAAY+E,GAAQC,CAAU,EAAG;AACrC,UAAMC,IAAkB,IAAI,gBAAA,GACtBC,IAAmBN,IAAY,OAAA;AACrC,IAAAO,EAAiB,MAAM;AACrB,MAAAF,EAAgB,MAAA;AAAA,IAClB,CAAC;AACD,QAAI;AACF,MAAAT,EAAM,QAAQ,QACdG,EAAU,QAAQ;AAClB,YAAMnB,IAAS,MAAMiB,EAAGM,GAAQE,EAAgB,MAAM;AACtD,MAAIC,MAAqBN,MACvBR,EAAK,QAAQZ;AAAA,IAEjB,SAAS4B,GAAK;AACZ,cAAQ,MAAMA,CAAG,GACbF,MAAqBN,MACvBJ,EAAM,QAAQa,EAAYD,CAAG;AAAA,IAEjC,UAAA;AACE,MAAIF,MAAqBN,MACvBD,EAAU,QAAQ;AAAA,IAEtB;AAAA,EACF,GAAG,EAAE,WAAW,IAAM,GACf,EAAE,MAAAP,GAAM,WAAAO,GAAW,OAAAH,EAAA;AAE9B;"}
@@ -32,13 +32,15 @@ function C({ markupRows: o, columnCount: l, labels: r }) {
32
32
  i || n.set(s, i = []), i.push({ row: e, start: u, length: c });
33
33
  }
34
34
  const t = Object.fromEntries(
35
- Object.entries(r).filter(([e]) => n.has(e)).map(([e, F], s) => [
36
- e,
37
- {
38
- label: F,
39
- color: g[s % g.length]
40
- }
41
- ])
35
+ Object.entries(r).map(
36
+ ([e, F], s) => [
37
+ e,
38
+ {
39
+ label: F,
40
+ color: g[s % g.length]
41
+ }
42
+ ]
43
+ ).filter(([e]) => n.has(e))
42
44
  );
43
45
  return { blob: new Blob(
44
46
  function* () {
@@ -1 +1 @@
1
- {"version":3,"file":"markup.js","sources":["../../../src/components/PlMultiSequenceAlignment/markup.ts"],"sourcesContent":["import type { HighlightLegend } from './types';\n\nexport type Markup = { id: string; start: number; length: number }[];\n\nexport function parseMarkup(row: string): Markup {\n return Array.from(row.matchAll(\n /(?<id>[^:]*):(?<start>[0-9A-Za-z]*)(?:\\+(?<length>[0-9A-Za-z]*))?\\|?/g,\n )).map((match) => {\n const matchGroups = match.groups as {\n id: string;\n start: string;\n length: string | undefined;\n };\n const start = Number.parseInt(matchGroups.start, 36);\n const length = matchGroups.length\n ? Number.parseInt(matchGroups.length, 36)\n : 0;\n return {\n id: matchGroups.id,\n start,\n length,\n };\n });\n}\n\nexport function markupAlignedSequence(\n alignedSequence: string,\n markup: Markup,\n): Markup {\n const indexMap = alignedSequence.split('').reduce<number[]>(\n (acc, char, index) => {\n if (char !== '-') acc.push(index);\n return acc;\n },\n [],\n );\n const adjusted = markup.map((segment) => {\n const start = indexMap[segment.start];\n const end = indexMap[segment.start + segment.length - 1] + 1;\n return {\n id: segment.id,\n start: start,\n length: end - start,\n };\n });\n return adjusted;\n}\n\nexport function highlightByMarkup(\n { markupRows, columnCount, labels }: {\n markupRows: Markup[];\n columnCount: number;\n labels: Record<string, string>;\n },\n): { blob: Blob; legend: HighlightLegend } {\n const linesById: Map<string, {\n row: number;\n start: number;\n length: number;\n }[]> = new Map();\n for (const [row, markup] of markupRows.entries()) {\n for (const { id, start, length } of markup) {\n let bucket = linesById.get(id);\n if (!bucket) linesById.set(id, bucket = []);\n bucket.push({ row, start, length });\n }\n }\n const legend: HighlightLegend = Object.fromEntries(\n Object.entries(labels)\n .filter(([id]) => linesById.has(id))\n .map(([id, label], index) => [\n id,\n {\n label,\n color: markupColors[index % markupColors.length],\n },\n ]),\n );\n const blob = new Blob(\n (function*() {\n const viewBox = `0 0 ${columnCount} ${markupRows.length * 2}`;\n yield `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${viewBox}\" stroke-width=\"2\" preserveAspectRatio=\"none\">`;\n for (const [id, lines] of linesById) {\n const { color } = legend[id];\n yield `<path stroke=\"${color}\" d=\"`;\n let x = 0, y = 0;\n for (const { row, start, length } of lines) {\n yield `m${start - x},${row * 2 + 1 - y}h${length}`;\n x = start + length;\n y = row * 2 + 1;\n }\n yield '\"/>';\n }\n yield '</svg>';\n })().toArray(),\n { type: 'image/svg+xml' },\n );\n return { blob, legend };\n}\n\nconst markupColors = [\n '#E5F2FF',\n '#FFE8E8',\n '#F0EBFF',\n '#FFFFE3',\n '#E5F7E5',\n '#FEEAFE',\n '#FDEED6',\n '#E8FDFE',\n '#CCDFF2',\n '#F2CCCD',\n '#D5CCF2',\n '#F2F2CC',\n '#CCF2CC',\n '#F2CCF2',\n '#EFDDBF',\n '#DEEEEF',\n];\n\nif (import.meta.vitest) {\n const { test, expect } = import.meta.vitest;\n test('annotateAlignedRow', () => {\n const alignedSequence\n = 'EVRLVESGGALVQPGGSLRLSCVAASGFTFINNWVTWVRQAPGKGLEWVANIKEDGSQKYYVDSVKGRFTISRDNAEKSVYLQMSSLRVDDTAVYYCAR------------GRAV----D---QWGQGTLVTVSS';\n // 0 10 20 30 40 50 60 70 80 90 100 110 120 130\n // EVRLVESGGALVQPGGSLRLSCVAASGFTFINNWVTWVRQAPGKGLEWVANIKEDGSQKYYVDSVKGRFTISRDNAEKSVYLQMSSLRVDDTAVYYCARGRAVDQWGQGTLVTVSS\n const markup = [\n { id: '1', start: 0, length: 99 },\n { id: '2', start: 99, length: 3 },\n { id: '3', start: 102, length: 14 },\n ];\n const alignedMarkup = markupAlignedSequence(alignedSequence, markup);\n expect(alignedMarkup).toEqual([\n { id: '1', start: 0, length: 99 },\n { id: '2', start: 111, length: 3 },\n { id: '3', start: 114, length: 21 },\n ]);\n });\n}\n"],"names":["parseMarkup","row","match","matchGroups","start","length","markupAlignedSequence","alignedSequence","markup","indexMap","acc","char","index","segment","end","highlightByMarkup","markupRows","columnCount","labels","linesById","id","bucket","legend","label","markupColors","lines","color","x","y"],"mappings":"AAIO,SAASA,EAAYC,GAAqB;AAC/C,SAAO,MAAM,KAAKA,EAAI;AAAA,IACpB;AAAA,EAAA,CACD,EAAE,IAAI,CAACC,MAAU;AAChB,UAAMC,IAAcD,EAAM,QAKpBE,IAAQ,OAAO,SAASD,EAAY,OAAO,EAAE,GAC7CE,IAASF,EAAY,SACvB,OAAO,SAASA,EAAY,QAAQ,EAAE,IACtC;AACJ,WAAO;AAAA,MACL,IAAIA,EAAY;AAAA,MAChB,OAAAC;AAAA,MACA,QAAAC;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH;AAEO,SAASC,EACdC,GACAC,GACQ;AACR,QAAMC,IAAWF,EAAgB,MAAM,EAAE,EAAE;AAAA,IACzC,CAACG,GAAKC,GAAMC,OACND,MAAS,OAAKD,EAAI,KAAKE,CAAK,GACzBF;AAAA,IAET,CAAA;AAAA,EAAC;AAWH,SATiBF,EAAO,IAAI,CAACK,MAAY;AACvC,UAAMT,IAAQK,EAASI,EAAQ,KAAK,GAC9BC,IAAML,EAASI,EAAQ,QAAQA,EAAQ,SAAS,CAAC,IAAI;AAC3D,WAAO;AAAA,MACL,IAAIA,EAAQ;AAAA,MACZ,OAAAT;AAAA,MACA,QAAQU,IAAMV;AAAA,IAAA;AAAA,EAElB,CAAC;AAEH;AAEO,SAASW,EACd,EAAE,YAAAC,GAAY,aAAAC,GAAa,QAAAC,KAKc;AACzC,QAAMC,wBAIK,IAAA;AACX,aAAW,CAAClB,GAAKO,CAAM,KAAKQ,EAAW;AACrC,eAAW,EAAE,IAAAI,GAAI,OAAAhB,GAAO,QAAAC,EAAA,KAAYG,GAAQ;AAC1C,UAAIa,IAASF,EAAU,IAAIC,CAAE;AAC7B,MAAKC,KAAQF,EAAU,IAAIC,GAAIC,IAAS,EAAE,GAC1CA,EAAO,KAAK,EAAE,KAAApB,GAAK,OAAAG,GAAO,QAAAC,GAAQ;AAAA,IACpC;AAEF,QAAMiB,IAA0B,OAAO;AAAA,IACrC,OAAO,QAAQJ,CAAM,EAClB,OAAO,CAAC,CAACE,CAAE,MAAMD,EAAU,IAAIC,CAAE,CAAC,EAClC,IAAI,CAAC,CAACA,GAAIG,CAAK,GAAGX,MAAU;AAAA,MAC3BQ;AAAA,MACA;AAAA,QACE,OAAAG;AAAA,QACA,OAAOC,EAAaZ,IAAQY,EAAa,MAAM;AAAA,MAAA;AAAA,IACjD,CACD;AAAA,EAAA;AAqBL,SAAO,EAAE,MAnBI,IAAI;AAAA,IACd,aAAY;AAEX,YAAM,oDADU,OAAOP,CAAW,IAAID,EAAW,SAAS,CAAC,EACM;AACjE,iBAAW,CAACI,GAAIK,CAAK,KAAKN,GAAW;AACnC,cAAM,EAAE,OAAAO,EAAA,IAAUJ,EAAOF,CAAE;AAC3B,cAAM,iBAAiBM,CAAK;AAC5B,YAAIC,IAAI,GAAGC,IAAI;AACf,mBAAW,EAAE,KAAA3B,GAAK,OAAAG,GAAO,QAAAC,EAAA,KAAYoB;AACnC,gBAAM,IAAIrB,IAAQuB,CAAC,IAAI1B,IAAM,IAAI,IAAI2B,CAAC,IAAIvB,CAAM,IAChDsB,IAAIvB,IAAQC,GACZuB,IAAI3B,IAAM,IAAI;AAEhB,cAAM;AAAA,MACR;AACA,YAAM;AAAA,IACR,EAAA,EAAK,QAAA;AAAA,IACL,EAAE,MAAM,gBAAA;AAAA,EAAgB,GAEX,QAAAqB,EAAA;AACjB;AAEA,MAAME,IAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;"}
1
+ {"version":3,"file":"markup.js","sources":["../../../src/components/PlMultiSequenceAlignment/markup.ts"],"sourcesContent":["import type { HighlightLegend } from './types';\n\nexport type Markup = { id: string; start: number; length: number }[];\n\nexport function parseMarkup(row: string): Markup {\n return Array.from(row.matchAll(\n /(?<id>[^:]*):(?<start>[0-9A-Za-z]*)(?:\\+(?<length>[0-9A-Za-z]*))?\\|?/g,\n )).map((match) => {\n const matchGroups = match.groups as {\n id: string;\n start: string;\n length: string | undefined;\n };\n const start = Number.parseInt(matchGroups.start, 36);\n const length = matchGroups.length\n ? Number.parseInt(matchGroups.length, 36)\n : 0;\n return {\n id: matchGroups.id,\n start,\n length,\n };\n });\n}\n\nexport function markupAlignedSequence(\n alignedSequence: string,\n markup: Markup,\n): Markup {\n const indexMap = alignedSequence.split('').reduce<number[]>(\n (acc, char, index) => {\n if (char !== '-') acc.push(index);\n return acc;\n },\n [],\n );\n const adjusted = markup.map((segment) => {\n const start = indexMap[segment.start];\n const end = indexMap[segment.start + segment.length - 1] + 1;\n return {\n id: segment.id,\n start: start,\n length: end - start,\n };\n });\n return adjusted;\n}\n\nexport function highlightByMarkup(\n { markupRows, columnCount, labels }: {\n markupRows: Markup[];\n columnCount: number;\n labels: Record<string, string>;\n },\n): { blob: Blob; legend: HighlightLegend } {\n const linesById: Map<string, {\n row: number;\n start: number;\n length: number;\n }[]> = new Map();\n for (const [row, markup] of markupRows.entries()) {\n for (const { id, start, length } of markup) {\n let bucket = linesById.get(id);\n if (!bucket) linesById.set(id, bucket = []);\n bucket.push({ row, start, length });\n }\n }\n const legend: HighlightLegend = Object.fromEntries(\n Object.entries(labels)\n .map(([id, label], index) =>\n [\n id,\n {\n label,\n color: markupColors[index % markupColors.length],\n },\n ] as const,\n )\n .filter(([id]) => linesById.has(id)),\n );\n const blob = new Blob(\n (function*() {\n const viewBox = `0 0 ${columnCount} ${markupRows.length * 2}`;\n yield `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"${viewBox}\" stroke-width=\"2\" preserveAspectRatio=\"none\">`;\n for (const [id, lines] of linesById) {\n const { color } = legend[id];\n yield `<path stroke=\"${color}\" d=\"`;\n let x = 0, y = 0;\n for (const { row, start, length } of lines) {\n yield `m${start - x},${row * 2 + 1 - y}h${length}`;\n x = start + length;\n y = row * 2 + 1;\n }\n yield '\"/>';\n }\n yield '</svg>';\n })().toArray(),\n { type: 'image/svg+xml' },\n );\n return { blob, legend };\n}\n\nconst markupColors = [\n '#E5F2FF',\n '#FFE8E8',\n '#F0EBFF',\n '#FFFFE3',\n '#E5F7E5',\n '#FEEAFE',\n '#FDEED6',\n '#E8FDFE',\n '#CCDFF2',\n '#F2CCCD',\n '#D5CCF2',\n '#F2F2CC',\n '#CCF2CC',\n '#F2CCF2',\n '#EFDDBF',\n '#DEEEEF',\n];\n\nif (import.meta.vitest) {\n const { test, expect } = import.meta.vitest;\n test('annotateAlignedRow', () => {\n const alignedSequence\n = 'EVRLVESGGALVQPGGSLRLSCVAASGFTFINNWVTWVRQAPGKGLEWVANIKEDGSQKYYVDSVKGRFTISRDNAEKSVYLQMSSLRVDDTAVYYCAR------------GRAV----D---QWGQGTLVTVSS';\n // 0 10 20 30 40 50 60 70 80 90 100 110 120 130\n // EVRLVESGGALVQPGGSLRLSCVAASGFTFINNWVTWVRQAPGKGLEWVANIKEDGSQKYYVDSVKGRFTISRDNAEKSVYLQMSSLRVDDTAVYYCARGRAVDQWGQGTLVTVSS\n const markup = [\n { id: '1', start: 0, length: 99 },\n { id: '2', start: 99, length: 3 },\n { id: '3', start: 102, length: 14 },\n ];\n const alignedMarkup = markupAlignedSequence(alignedSequence, markup);\n expect(alignedMarkup).toEqual([\n { id: '1', start: 0, length: 99 },\n { id: '2', start: 111, length: 3 },\n { id: '3', start: 114, length: 21 },\n ]);\n });\n}\n"],"names":["parseMarkup","row","match","matchGroups","start","length","markupAlignedSequence","alignedSequence","markup","indexMap","acc","char","index","segment","end","highlightByMarkup","markupRows","columnCount","labels","linesById","id","bucket","legend","label","markupColors","lines","color","x","y"],"mappings":"AAIO,SAASA,EAAYC,GAAqB;AAC/C,SAAO,MAAM,KAAKA,EAAI;AAAA,IACpB;AAAA,EAAA,CACD,EAAE,IAAI,CAACC,MAAU;AAChB,UAAMC,IAAcD,EAAM,QAKpBE,IAAQ,OAAO,SAASD,EAAY,OAAO,EAAE,GAC7CE,IAASF,EAAY,SACvB,OAAO,SAASA,EAAY,QAAQ,EAAE,IACtC;AACJ,WAAO;AAAA,MACL,IAAIA,EAAY;AAAA,MAChB,OAAAC;AAAA,MACA,QAAAC;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH;AAEO,SAASC,EACdC,GACAC,GACQ;AACR,QAAMC,IAAWF,EAAgB,MAAM,EAAE,EAAE;AAAA,IACzC,CAACG,GAAKC,GAAMC,OACND,MAAS,OAAKD,EAAI,KAAKE,CAAK,GACzBF;AAAA,IAET,CAAA;AAAA,EAAC;AAWH,SATiBF,EAAO,IAAI,CAACK,MAAY;AACvC,UAAMT,IAAQK,EAASI,EAAQ,KAAK,GAC9BC,IAAML,EAASI,EAAQ,QAAQA,EAAQ,SAAS,CAAC,IAAI;AAC3D,WAAO;AAAA,MACL,IAAIA,EAAQ;AAAA,MACZ,OAAAT;AAAA,MACA,QAAQU,IAAMV;AAAA,IAAA;AAAA,EAElB,CAAC;AAEH;AAEO,SAASW,EACd,EAAE,YAAAC,GAAY,aAAAC,GAAa,QAAAC,KAKc;AACzC,QAAMC,wBAIK,IAAA;AACX,aAAW,CAAClB,GAAKO,CAAM,KAAKQ,EAAW;AACrC,eAAW,EAAE,IAAAI,GAAI,OAAAhB,GAAO,QAAAC,EAAA,KAAYG,GAAQ;AAC1C,UAAIa,IAASF,EAAU,IAAIC,CAAE;AAC7B,MAAKC,KAAQF,EAAU,IAAIC,GAAIC,IAAS,EAAE,GAC1CA,EAAO,KAAK,EAAE,KAAApB,GAAK,OAAAG,GAAO,QAAAC,GAAQ;AAAA,IACpC;AAEF,QAAMiB,IAA0B,OAAO;AAAA,IACrC,OAAO,QAAQJ,CAAM,EAClB;AAAA,MAAI,CAAC,CAACE,GAAIG,CAAK,GAAGX,MACjB;AAAA,QACEQ;AAAA,QACA;AAAA,UACE,OAAAG;AAAA,UACA,OAAOC,EAAaZ,IAAQY,EAAa,MAAM;AAAA,QAAA;AAAA,MACjD;AAAA,IACF,EAED,OAAO,CAAC,CAACJ,CAAE,MAAMD,EAAU,IAAIC,CAAE,CAAC;AAAA,EAAA;AAqBvC,SAAO,EAAE,MAnBI,IAAI;AAAA,IACd,aAAY;AAEX,YAAM,oDADU,OAAOH,CAAW,IAAID,EAAW,SAAS,CAAC,EACM;AACjE,iBAAW,CAACI,GAAIK,CAAK,KAAKN,GAAW;AACnC,cAAM,EAAE,OAAAO,EAAA,IAAUJ,EAAOF,CAAE;AAC3B,cAAM,iBAAiBM,CAAK;AAC5B,YAAIC,IAAI,GAAGC,IAAI;AACf,mBAAW,EAAE,KAAA3B,GAAK,OAAAG,GAAO,QAAAC,EAAA,KAAYoB;AACnC,gBAAM,IAAIrB,IAAQuB,CAAC,IAAI1B,IAAM,IAAI,IAAI2B,CAAC,IAAIvB,CAAM,IAChDsB,IAAIvB,IAAQC,GACZuB,IAAI3B,IAAM,IAAI;AAEhB,cAAM;AAAA,MACR;AACA,YAAM;AAAA,IACR,EAAA,EAAK,QAAA;AAAA,IACL,EAAE,MAAM,gBAAA;AAAA,EAAgB,GAEX,QAAAqB,EAAA;AACjB;AAEA,MAAME,IAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;"}
@@ -1,22 +1,24 @@
1
- import { parseJson as s } from "@platforma-sdk/model";
2
- const e = 1;
3
- function a(r) {
4
- const t = i(r.value);
1
+ import { parseJson as u } from "@platforma-sdk/model";
2
+ const o = 2;
3
+ function l(r) {
4
+ var t;
5
+ const n = s(r.value);
5
6
  try {
6
- if (t < 1) {
7
- const n = r.value.labelColumnIds;
8
- n && (r.value.labelColumnIds = n.map((o) => s(o)));
7
+ if (n < 1) {
8
+ const e = r.value.labelColumnIds;
9
+ e && (r.value.labelColumnIds = e.map((i) => u(i)));
9
10
  }
10
- } catch (n) {
11
- console.error(n), r.value = {};
11
+ n < 2 && ((t = r.value.colorScheme) == null ? void 0 : t.type) === "markup" && delete r.value.colorScheme;
12
+ } catch (e) {
13
+ console.error(e), r.value = {};
12
14
  } finally {
13
- r.value.version = e;
15
+ r.value.version = o;
14
16
  }
15
17
  }
16
- function i(r) {
17
- return r.version !== void 0 ? r.version : Object.keys(r).length ? 0 : e;
18
+ function s(r) {
19
+ return r.version !== void 0 ? r.version : Object.keys(r).length ? 0 : o;
18
20
  }
19
21
  export {
20
- a as runMigrations
22
+ l as runMigrations
21
23
  };
22
24
  //# sourceMappingURL=migrations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"migrations.js","sources":["../../../src/components/PlMultiSequenceAlignment/migrations.ts"],"sourcesContent":["import {\n type CanonicalizedJson,\n parseJson,\n type PlMultiSequenceAlignmentModel,\n type PTableColumnId,\n} from '@platforma-sdk/model';\nimport { type Ref } from 'vue';\n\nconst latestVersion = 1;\n\nexport function runMigrations(model: Ref<PlMultiSequenceAlignmentModel>) {\n const currentVersion = getCurrentVersion(model.value);\n try {\n if (currentVersion < 1) {\n const oldLabelColumnIds = model.value.labelColumnIds as unknown as\n | CanonicalizedJson<PTableColumnId>[]\n | undefined;\n if (oldLabelColumnIds) {\n model.value.labelColumnIds = oldLabelColumnIds\n .map((id) => parseJson(id));\n }\n }\n } catch (error) {\n console.error(error);\n model.value = {};\n } finally {\n model.value.version = latestVersion;\n }\n}\n\n/**\n * If a model has a version, return it.\n * If it doesn't, but contains anything at all, that's version 0,\n * which is a pre-versioning version.\n * Otherwise, emtpy model is treated as the latest model.\n */\nfunction getCurrentVersion(model: PlMultiSequenceAlignmentModel) {\n if (model.version !== undefined) return model.version;\n if (Object.keys(model).length) return 0;\n return latestVersion;\n}\n"],"names":["latestVersion","runMigrations","model","currentVersion","getCurrentVersion","oldLabelColumnIds","id","parseJson","error"],"mappings":";AAQA,MAAMA,IAAgB;AAEf,SAASC,EAAcC,GAA2C;AACvE,QAAMC,IAAiBC,EAAkBF,EAAM,KAAK;AACpD,MAAI;AACF,QAAIC,IAAiB,GAAG;AACtB,YAAME,IAAoBH,EAAM,MAAM;AAGtC,MAAIG,MACFH,EAAM,MAAM,iBAAiBG,EAC1B,IAAI,CAACC,MAAOC,EAAUD,CAAE,CAAC;AAAA,IAEhC;AAAA,EACF,SAASE,GAAO;AACd,YAAQ,MAAMA,CAAK,GACnBN,EAAM,QAAQ,CAAA;AAAA,EAChB,UAAA;AACE,IAAAA,EAAM,MAAM,UAAUF;AAAA,EACxB;AACF;AAQA,SAASI,EAAkBF,GAAsC;AAC/D,SAAIA,EAAM,YAAY,SAAkBA,EAAM,UAC1C,OAAO,KAAKA,CAAK,EAAE,SAAe,IAC/BF;AACT;"}
1
+ {"version":3,"file":"migrations.js","sources":["../../../src/components/PlMultiSequenceAlignment/migrations.ts"],"sourcesContent":["import {\n type CanonicalizedJson,\n parseJson,\n type PlMultiSequenceAlignmentModel,\n type PTableColumnId,\n} from '@platforma-sdk/model';\nimport { type Ref } from 'vue';\n\nconst latestVersion = 2;\n\nexport function runMigrations(model: Ref<PlMultiSequenceAlignmentModel>) {\n const currentVersion = getCurrentVersion(model.value);\n try {\n if (currentVersion < 1) {\n const oldLabelColumnIds = model.value.labelColumnIds as unknown as\n | CanonicalizedJson<PTableColumnId>[]\n | undefined;\n if (oldLabelColumnIds) {\n model.value.labelColumnIds = oldLabelColumnIds\n .map((id) => parseJson(id));\n }\n }\n if (currentVersion < 2) {\n if (model.value.colorScheme?.type === 'markup') {\n delete model.value.colorScheme;\n }\n }\n } catch (error) {\n console.error(error);\n model.value = {};\n } finally {\n model.value.version = latestVersion;\n }\n}\n\n/**\n * If a model has a version, return it.\n * If it doesn't, but contains anything at all, that's version 0,\n * which is a pre-versioning version.\n * Otherwise, emtpy model is treated as the latest model.\n */\nfunction getCurrentVersion(model: PlMultiSequenceAlignmentModel) {\n if (model.version !== undefined) return model.version;\n if (Object.keys(model).length) return 0;\n return latestVersion;\n}\n"],"names":["latestVersion","runMigrations","model","currentVersion","getCurrentVersion","oldLabelColumnIds","id","parseJson","_a","error"],"mappings":";AAQA,MAAMA,IAAgB;AAEf,SAASC,EAAcC,GAA2C;;AACvE,QAAMC,IAAiBC,EAAkBF,EAAM,KAAK;AACpD,MAAI;AACF,QAAIC,IAAiB,GAAG;AACtB,YAAME,IAAoBH,EAAM,MAAM;AAGtC,MAAIG,MACFH,EAAM,MAAM,iBAAiBG,EAC1B,IAAI,CAACC,MAAOC,EAAUD,CAAE,CAAC;AAAA,IAEhC;AACA,IAAIH,IAAiB,OACfK,IAAAN,EAAM,MAAM,gBAAZ,gBAAAM,EAAyB,UAAS,YACpC,OAAON,EAAM,MAAM;AAAA,EAGzB,SAASO,GAAO;AACd,YAAQ,MAAMA,CAAK,GACnBP,EAAM,QAAQ,CAAA;AAAA,EAChB,UAAA;AACE,IAAAA,EAAM,MAAM,UAAUF;AAAA,EACxB;AACF;AAQA,SAASI,EAAkBF,GAAsC;AAC/D,SAAIA,EAAM,YAAY,SAAkBA,EAAM,UAC1C,OAAO,KAAKA,CAAK,EAAE,SAAe,IAC/BF;AACT;"}
@@ -0,0 +1,6 @@
1
+ import { PlMultiSequenceAlignmentSettings } from '@platforma-sdk/model';
2
+ export type RequestMessage = {
3
+ sequences: string[];
4
+ params: PlMultiSequenceAlignmentSettings['alignmentParams'];
5
+ };
6
+ export type ResponseMessage = string[];
@@ -0,0 +1,7 @@
1
+ export type RequestMessage = string[];
2
+ export type ResponseMessage = TreeNodeData[];
3
+ export interface TreeNodeData {
4
+ id: number;
5
+ length?: number;
6
+ parentId?: number;
7
+ }
@@ -1,10 +1,9 @@
1
- import { defaultAlignmentParams as e } from "./multi-sequence-alignment.js";
2
- const o = {
1
+ const e = {
3
2
  colorScheme: { type: "chemical-properties" },
4
3
  widgets: ["seqLogo", "consensus", "legend"],
5
- alignmentParams: e
4
+ alignmentParams: { gpo: 5.5, gpe: 2, tgpe: 1 }
6
5
  };
7
6
  export {
8
- o as defaultSettings
7
+ e as defaultSettings
9
8
  };
10
9
  //# sourceMappingURL=settings.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","sources":["../../../src/components/PlMultiSequenceAlignment/settings.ts"],"sourcesContent":["import type { PlMultiSequenceAlignmentSettings } from '@platforma-sdk/model';\nimport { defaultAlignmentParams } from './multi-sequence-alignment';\n\nexport const defaultSettings: PlMultiSequenceAlignmentSettings = {\n colorScheme: { type: 'chemical-properties' },\n widgets: ['seqLogo', 'consensus', 'legend'],\n alignmentParams: defaultAlignmentParams,\n};\n"],"names":["defaultSettings","defaultAlignmentParams"],"mappings":";AAGO,MAAMA,IAAoD;AAAA,EAC/D,aAAa,EAAE,MAAM,sBAAA;AAAA,EACrB,SAAS,CAAC,WAAW,aAAa,QAAQ;AAAA,EAC1C,iBAAiBC;AACnB;"}
1
+ {"version":3,"file":"settings.js","sources":["../../../src/components/PlMultiSequenceAlignment/settings.ts"],"sourcesContent":["import type { PlMultiSequenceAlignmentSettings } from '@platforma-sdk/model';\n\nexport const defaultSettings: PlMultiSequenceAlignmentSettings = {\n colorScheme: { type: 'chemical-properties' },\n widgets: ['seqLogo', 'consensus', 'legend'],\n alignmentParams: { gpo: 5.5, gpe: 2.0, tgpe: 1.0 },\n};\n"],"names":["defaultSettings"],"mappings":"AAEO,MAAMA,IAAoD;AAAA,EAC/D,aAAa,EAAE,MAAM,sBAAA;AAAA,EACrB,SAAS,CAAC,WAAW,aAAa,QAAQ;AAAA,EAC1C,iBAAiB,EAAE,KAAK,KAAK,KAAK,GAAK,MAAM,EAAA;AAC/C;"}
package/dist/index.js CHANGED
@@ -1,29 +1,29 @@
1
1
  (function(){"use strict";try{if(typeof document<"u"){var r=document.createElement("style");r.appendChild(document.createTextNode(`*{cursor:inherit;box-sizing:border-box;-webkit-font-smoothing:antialiased}.invisible-scrollbar::-webkit-scrollbar{display:none}.block{flex:1;background-color:#fff;max-height:100%;max-width:100%;width:100%;height:100%;position:relative;display:flex;flex-direction:column;--thumb-color: var(--ic-02);overflow-y:auto;overflow-x:auto}.block::-webkit-scrollbar{width:var(--scrollbar-width, 6px);height:5px;background-color:transparent;display:block}.block::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.block::-webkit-scrollbar-thumb:hover{--thumb-color: var(--border-color-focus)}.block__not-found,.block__loader-page{display:flex;flex-direction:column;flex:1;align-items:center;justify-content:center}.block__loader-page .loader-container{display:flex;transform:scale(8)}.block__loader-page .loader-icon{animation:spin 4s linear infinite;background-color:#ccc;margin:auto}.block__layout{padding:0}.block__loader{height:4px;background-color:transparent;position:absolute;z-index:1;top:0;right:0;left:0;overflow:hidden}.block__loader:before{content:"";position:absolute;left:-50%;height:4px;width:33%;background-color:var(--border-color-focus);animation:loader-animation 1.3s linear infinite}.block__progress{--progress-width: 0%;height:4px;background-color:transparent;position:absolute;top:0;right:0;left:0;overflow:hidden}.block__progress:before{content:"";position:absolute;left:0;height:4px;width:var(--progress-width);background-color:var(--border-color-focus);will-change:width;background-image:linear-gradient(90deg,#0000,#fffc,#0000);background-position:0 0;background-size:80px 100%;background-repeat:repeat-y;animation:shine-animation 1.2s linear infinite}@keyframes shine-animation{0%{background-position:-160px 0}to{background-position:calc(100% + 80px) 0}}.block__error{background:var(--txt-error);color:#fff;max-height:50vh;padding:16px 24px;-webkit-user-select:auto;user-select:auto;width:100%;overflow:auto;display:flex;flex-direction:column;--thumb-color: var(--ic-02);overflow-y:auto;overflow-x:auto}.block__error::-webkit-scrollbar{width:var(--scrollbar-width, 6px);height:5px;background-color:transparent;display:block}.block__error::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.block__error::-webkit-scrollbar-thumb:hover{--thumb-color: var(--border-color-focus)}.block__error pre{white-space:pre-wrap;margin:0}.block .scroll-content{height:100%;display:flex;flex-direction:column}.block .scroll-content>div:last-child{flex:1;overflow:auto}@keyframes loader-animation{0%{left:-40%}50%{left:20%;width:38%}to{left:100%;width:50%}}.alert-error{background-color:var(--txt-error);color:#fff;padding:24px}.pl-ag-header-align-center .ag-header-cell-label{justify-content:center}
2
2
  .grid-overlay-container{height:calc(100% - 1px);margin-top:1px;width:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:var(--bg-base-light)}.grid-icon-sad-cat{background-image:url(data:image/png;base64,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);background-repeat:no-repeat}.grid-overlay-container>div{height:300px;width:300px;background-size:contain;background-position:center}.grid-overlay-container>span{color:var(--txt-mask)}
3
3
  .pl-ag-cell-status-tag{height:100%;padding:0 12px}
4
- .pl-ag-chart-stacked-bar-cell{height:100%;display:flex;flex-direction:row;align-items:center}.pl-ag-chart-stacked-bar-cell__not-ready{color:var(--txt-03)!important}
5
- .pl-ag-chart-histogram-cell{height:100%;display:flex;flex-direction:row;align-items:center}.pl-ag-chart-histogram-cell__not-ready{color:var(--txt-03)!important}`)),document.head.appendChild(r)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
4
+ .pl-ag-chart-histogram-cell{height:100%;display:flex;flex-direction:row;align-items:center}.pl-ag-chart-histogram-cell__not-ready{color:var(--txt-03)!important}
5
+ .pl-ag-chart-stacked-bar-cell{height:100%;display:flex;flex-direction:row;align-items:center}.pl-ag-chart-stacked-bar-cell__not-ready{color:var(--txt-03)!important}`)),document.head.appendChild(r)}}catch(o){console.error("vite-plugin-css-injected-by-js",o)}})();
6
6
 
7
7
  import { default as m } from "./components/BlockLayout.vue.js";
8
- import { default as p, default as s } from "./components/PlAgDataTable/PlAgDataTableV2.vue.js";
8
+ import { default as u, default as p } from "./components/PlAgDataTable/PlAgDataTableV2.vue.js";
9
9
  import { default as i } from "./components/PlAgDataTable/PlAgOverlayLoading.vue.js";
10
10
  import { default as x } from "./components/PlAgDataTable/PlAgOverlayNoRows.vue.js";
11
11
 
12
12
  import { default as A } from "./components/ValueOrErrorsComponent.vue.js";
13
13
  import { useAgGridOptions as P } from "./AgGridVue/useAgGridOptions.js";
14
14
  import { createAgGridColDef as b } from "./AgGridVue/createAgGridColDef.js";
15
- import { deselectAll as S, getSelectedRowsCount as w, getTotalRowsCount as R, isSelectionEnabled as T, selectAll as D } from "./AgGridVue/selection.js";
15
+ import { deselectAll as w, getSelectedRowsCount as R, getTotalRowsCount as S, isSelectionEnabled as T, selectAll as D } from "./AgGridVue/selection.js";
16
16
  import { default as M } from "./components/PlAgColumnHeader/PlAgColumnHeader.vue.js";
17
17
  import { default as v } from "./components/PlAgCellFile/PlAgCellFile.vue.js";
18
18
  import { default as N } from "./components/PlAgCellProgress/PlAgCellProgress.vue.js";
19
19
  import { default as k } from "./components/PlAgCellStatusTag/PlAgCellStatusTag.vue.js";
20
20
 
21
- import { default as B } from "./components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue.js";
21
+ import { default as B } from "./components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue.js";
22
22
 
23
- import { default as H } from "./components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue.js";
23
+ import { default as H } from "./components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue.js";
24
24
 
25
- import { usePlDataTableSettingsV2 as I } from "./components/PlAgDataTable/types.js";
26
- import { PlAgDataTableRowNumberColId as Z, autoSizeRowNumberColumn as j, makeRowNumberColDef as z } from "./components/PlAgDataTable/sources/row-number.js";
25
+ import { usePlDataTableSettingsV2 as L } from "./components/PlAgDataTable/types.js";
26
+ import { PlAgDataTableRowNumberColId as j, autoSizeRowNumberColumn as q, makeRowNumberColDef as z } from "./components/PlAgDataTable/sources/row-number.js";
27
27
  import { DeferredCircular as J, ensureNodeVisible as K } from "./components/PlAgDataTable/sources/focus-row.js";
28
28
  import { defaultMainMenuItems as W } from "./components/PlAgDataTable/sources/menu-items.js";
29
29
  import { default as Y } from "./components/PlAgCsvExporter/PlAgCsvExporter.vue.js";
@@ -32,15 +32,14 @@ import { default as re } from "./components/PlAgGridColumnManager/PlAgGridColumn
32
32
  import { default as te } from "./components/PlTableFilters/PlTableFiltersV2.vue.js";
33
33
  import { default as ae } from "./components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.js";
34
34
  import { default as me } from "./components/PlAnnotations/components/PlAnnotationsModal.vue.js";
35
- import { defineApp as pe, useSdkPlugin as se } from "./defineApp.js";
35
+ import { defineApp as ue, useSdkPlugin as pe } from "./defineApp.js";
36
36
  import { createModel as ie } from "./createModel.js";
37
37
  import { defineStore as xe } from "./defineStore.js";
38
38
  import { AgGridTheme as Ae, activateAgGrid as Ce } from "./aggrid.js";
39
- import { MultiError as ce, UnresolvedError as be, ensureError as Ee, formatZodError as Se, identity as we, isDefined as Re, isZodError as Te, unwrapValueOrErrors as De, wrapOptionalResult as Ve, wrapValueOrErrors as Me } from "./utils.js";
39
+ import { MultiError as ce, UnresolvedError as be, ensureError as Ee, formatZodError as we, identity as Re, isDefined as Se, isZodError as Te, unwrapValueOrErrors as De, wrapOptionalResult as Ve, wrapValueOrErrors as Me } from "./utils.js";
40
40
  import { objectHash as ve } from "./objectHash.js";
41
41
  import { computedResult as Ne } from "./computedResult.js";
42
42
  import { ReactiveFileContent as ke } from "./composition/fileContent.js";
43
- import { multiSequenceAlignment as Be } from "./components/PlMultiSequenceAlignment/multi-sequence-alignment.js";
44
43
  export * from "@milaboratories/uikit";
45
44
  export {
46
45
  Ae as AgGridTheme,
@@ -50,49 +49,48 @@ export {
50
49
  v as PlAgCellFile,
51
50
  N as PlAgCellProgress,
52
51
  k as PlAgCellStatusTag,
53
- H as PlAgChartHistogramCell,
54
- B as PlAgChartStackedBarCell,
52
+ B as PlAgChartHistogramCell,
53
+ H as PlAgChartStackedBarCell,
55
54
  M as PlAgColumnHeader,
56
55
  Y as PlAgCsvExporter,
57
- Z as PlAgDataTableRowNumberColId,
58
- p as PlAgDataTableV2,
56
+ j as PlAgDataTableRowNumberColId,
57
+ u as PlAgDataTableV2,
59
58
  re as PlAgGridColumnManager,
60
59
  i as PlAgOverlayLoading,
61
60
  x as PlAgOverlayNoRows,
62
61
  $ as PlAgTextAndButtonCell,
63
62
  me as PlAnnotationsModal,
64
- s as PlDataTableV2,
63
+ p as PlDataTableV2,
65
64
  ae as PlMultiSequenceAlignment,
66
65
  te as PlTableFiltersV2,
67
66
  ke as ReactiveFileContent,
68
67
  be as UnresolvedError,
69
68
  A as ValueOrErrorsComponent,
70
69
  Ce as activateAgGrid,
71
- j as autoSizeRowNumberColumn,
70
+ q as autoSizeRowNumberColumn,
72
71
  Ne as computedResult,
73
72
  b as createAgGridColDef,
74
73
  ie as createModel,
75
74
  W as defaultMainMenuItems,
76
- pe as defineApp,
75
+ ue as defineApp,
77
76
  xe as defineStore,
78
- S as deselectAll,
77
+ w as deselectAll,
79
78
  Ee as ensureError,
80
79
  K as ensureNodeVisible,
81
- Se as formatZodError,
82
- w as getSelectedRowsCount,
83
- R as getTotalRowsCount,
84
- we as identity,
85
- Re as isDefined,
80
+ we as formatZodError,
81
+ R as getSelectedRowsCount,
82
+ S as getTotalRowsCount,
83
+ Re as identity,
84
+ Se as isDefined,
86
85
  T as isSelectionEnabled,
87
86
  Te as isZodError,
88
87
  z as makeRowNumberColDef,
89
- Be as multiSequenceAlignment,
90
88
  ve as objectHash,
91
89
  D as selectAll,
92
90
  De as unwrapValueOrErrors,
93
91
  P as useAgGridOptions,
94
- I as usePlDataTableSettingsV2,
95
- se as useSdkPlugin,
92
+ L as usePlDataTableSettingsV2,
93
+ pe as useSdkPlugin,
96
94
  Ve as wrapOptionalResult,
97
95
  Me as wrapValueOrErrors
98
96
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/lib.d.ts CHANGED
@@ -9,8 +9,8 @@ export * from './components/PlAgColumnHeader';
9
9
  export * from './components/PlAgCellFile';
10
10
  export * from './components/PlAgCellProgress';
11
11
  export * from './components/PlAgCellStatusTag';
12
- export * from './components/PlAgChartStackedBarCell';
13
12
  export * from './components/PlAgChartHistogramCell';
13
+ export * from './components/PlAgChartStackedBarCell';
14
14
  export * from './components/PlAgDataTable';
15
15
  export * from './components/PlAgCsvExporter';
16
16
  export * from './components/PlAgTextAndButtonCell';
@@ -27,6 +27,5 @@ export * from './utils';
27
27
  export * from './objectHash';
28
28
  export * from './computedResult';
29
29
  export * from './composition/fileContent';
30
- export { multiSequenceAlignment } from './components/PlMultiSequenceAlignment/multi-sequence-alignment';
31
30
  export * from '@milaboratories/uikit';
32
31
  export type * from '@milaboratories/uikit';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/ui-vue",
3
- "version": "1.42.53",
3
+ "version": "1.43.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "styles": "dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "@types/node": "~20.16.15",
16
16
  "@types/semver": "^7.7.0",
17
17
  "@types/d3-format": "^3.0.4",
18
- "@milaboratories/miplots4": "^1.0.123",
18
+ "@milaboratories/miplots4": "^1.0.145",
19
19
  "ag-grid-enterprise": "^34.1.2",
20
20
  "ag-grid-vue3": "^34.1.2",
21
21
  "canonicalize": "~2.1.0",
@@ -25,9 +25,9 @@
25
25
  "@vueuse/integrations": "^13.3.0",
26
26
  "d3-format": "^3.1.0",
27
27
  "zod": "~3.23.8",
28
- "@milaboratories/biowasm-tools": "1.1.2",
29
- "@milaboratories/uikit": "2.4.13",
30
- "@platforma-sdk/model": "1.42.51"
28
+ "@milaboratories/biowasm-tools": "2.0.0",
29
+ "@milaboratories/uikit": "2.4.14",
30
+ "@platforma-sdk/model": "1.43.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "happy-dom": "^15.11.7",
@@ -42,8 +42,8 @@
42
42
  "yarpm": "^1.2.0",
43
43
  "fast-json-patch": "^3.1.1",
44
44
  "@faker-js/faker": "^9.2.0",
45
- "@milaboratories/eslint-config": "1.0.4",
46
45
  "@milaboratories/ts-configs": "1.0.6",
46
+ "@milaboratories/eslint-config": "1.0.4",
47
47
  "@milaboratories/build-configs": "1.0.8",
48
48
  "@milaboratories/helpers": "1.8.0",
49
49
  "@milaboratories/ts-builder": "1.0.5"