@platforma-sdk/ui-vue 1.45.35 → 1.45.37

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 (180) hide show
  1. package/.turbo/turbo-build.log +204 -235
  2. package/.turbo/turbo-type-check.log +1 -1
  3. package/CHANGELOG.md +13 -0
  4. package/dist/AgGridVue/useAgGridOptions.js +2 -3
  5. package/dist/AgGridVue/useAgGridOptions.js.map +1 -1
  6. package/dist/components/BlockLayout.vue2.js +3 -3
  7. package/dist/components/BlockLayout.vue2.js.map +1 -1
  8. package/dist/components/BlockLoader.vue.js.map +1 -1
  9. package/dist/components/LoaderPage.vue.js +2 -2
  10. package/dist/components/LoaderPage.vue.js.map +1 -1
  11. package/dist/components/NotFound.vue.js +3 -3
  12. package/dist/components/NotFound.vue.js.map +1 -1
  13. package/dist/components/PlAdvancedFilter/OperandButton.vue2.js.map +1 -1
  14. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js +73 -73
  15. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js.map +1 -1
  16. package/dist/components/PlAdvancedFilter/SingleFilter.vue2.js +100 -100
  17. package/dist/components/PlAdvancedFilter/SingleFilter.vue2.js.map +1 -1
  18. package/dist/components/PlAgCellFile/PlAgCellFile.vue.js.map +1 -1
  19. package/dist/components/PlAgCellProgress/PlAgCellProgress.vue.js.map +1 -1
  20. package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue.js +6 -6
  21. package/dist/components/PlAgCellStatusTag/PlAgCellStatusTag.vue.js.map +1 -1
  22. package/dist/components/PlAgChartHistogramCell/PlAgChartHistogramCell.vue.js.map +1 -1
  23. package/dist/components/PlAgChartStackedBarCell/PlAgChartStackedBarCell.vue.js.map +1 -1
  24. package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue.js +22 -22
  25. package/dist/components/PlAgColumnHeader/PlAgColumnHeader.vue.js.map +1 -1
  26. package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.js +3 -3
  27. package/dist/components/PlAgCsvExporter/PlAgCsvExporter.vue.js.map +1 -1
  28. package/dist/components/PlAgDataTable/PlAgDataTableSheets.vue2.js.map +1 -1
  29. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js +50 -50
  30. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js.map +1 -1
  31. package/dist/components/PlAgDataTable/PlAgOverlayLoading.vue.js.map +1 -1
  32. package/dist/components/PlAgDataTable/PlAgOverlayNoRows.vue.js.map +1 -1
  33. package/dist/components/PlAgDataTable/PlAgRowCount.vue.js +7 -8
  34. package/dist/components/PlAgDataTable/PlAgRowCount.vue.js.map +1 -1
  35. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js +35 -35
  36. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js.map +1 -1
  37. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js +16 -17
  38. package/dist/components/PlAgRowNumCheckbox/PlAgRowNumCheckbox.vue.js.map +1 -1
  39. package/dist/components/PlAgRowNumHeader.vue.js +14 -15
  40. package/dist/components/PlAgRowNumHeader.vue.js.map +1 -1
  41. package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue.js +16 -16
  42. package/dist/components/PlAgTextAndButtonCell/PlAgTextAndButtonCell.vue.js.map +1 -1
  43. package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js +6 -6
  44. package/dist/components/PlAnnotations/components/AnnotationsSidebar.vue2.js.map +1 -1
  45. package/dist/components/PlAnnotations/components/DynamicForm.vue2.js +57 -57
  46. package/dist/components/PlAnnotations/components/DynamicForm.vue2.js.map +1 -1
  47. package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js +6 -6
  48. package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js.map +1 -1
  49. package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
  50. package/dist/components/PlAnnotations/components/PlAnnotationsModal.vue2.js.map +1 -1
  51. package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue.js +7 -7
  52. package/dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue.js.map +1 -1
  53. package/dist/components/PlBtnExportArchive/Item.vue2.js +23 -23
  54. package/dist/components/PlBtnExportArchive/Item.vue2.js.map +1 -1
  55. package/dist/components/PlBtnExportArchive/PlBtnExportArchive.vue2.js.map +1 -1
  56. package/dist/components/PlBtnExportArchive/Summary.vue2.js +22 -22
  57. package/dist/components/PlBtnExportArchive/Summary.vue2.js.map +1 -1
  58. package/dist/components/PlTableFilters/PlTableAddFilterV2.vue.js +9 -9
  59. package/dist/components/PlTableFilters/PlTableAddFilterV2.vue.js.map +1 -1
  60. package/dist/components/PlTableFilters/PlTableFilterEntryV2.vue.js +3 -3
  61. package/dist/components/PlTableFilters/PlTableFilterEntryV2.vue.js.map +1 -1
  62. package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js +9 -9
  63. package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js.map +1 -1
  64. package/dist/components/ValueOrErrorsComponent.vue.js.map +1 -1
  65. package/dist/index.js +48 -50
  66. package/dist/index.js.map +1 -1
  67. package/dist/lib.d.ts +0 -1
  68. package/dist/plugins/Monetization/EndOfPeriod.vue2.js +9 -9
  69. package/dist/plugins/Monetization/EndOfPeriod.vue2.js.map +1 -1
  70. package/dist/plugins/Monetization/LimitCard.vue2.js +40 -40
  71. package/dist/plugins/Monetization/LimitCard.vue2.js.map +1 -1
  72. package/dist/plugins/Monetization/MonetizationSidebar.vue.js +3 -3
  73. package/dist/plugins/Monetization/MonetizationSidebar.vue.js.map +1 -1
  74. package/dist/plugins/Monetization/RunStatus.vue2.js +12 -12
  75. package/dist/plugins/Monetization/RunStatus.vue2.js.map +1 -1
  76. package/dist/plugins/Monetization/UserCabinetCard.vue2.js +22 -22
  77. package/dist/plugins/Monetization/UserCabinetCard.vue2.js.map +1 -1
  78. package/package.json +7 -8
  79. package/src/lib.ts +0 -2
  80. package/dist/assets/multi-sequence-alignment.worker-Cm0gZp19.js +0 -6
  81. package/dist/assets/multi-sequence-alignment.worker-Cm0gZp19.js.map +0 -1
  82. package/dist/assets/phylogenetic-tree.worker-4CrExYEo.js +0 -5
  83. package/dist/assets/phylogenetic-tree.worker-4CrExYEo.js.map +0 -1
  84. package/dist/components/PlMultiSequenceAlignment/Consensus.vue.d.ts +0 -9
  85. package/dist/components/PlMultiSequenceAlignment/Consensus.vue.js +0 -10
  86. package/dist/components/PlMultiSequenceAlignment/Consensus.vue.js.map +0 -1
  87. package/dist/components/PlMultiSequenceAlignment/Consensus.vue2.js +0 -122
  88. package/dist/components/PlMultiSequenceAlignment/Consensus.vue2.js.map +0 -1
  89. package/dist/components/PlMultiSequenceAlignment/Consensus.vue3.js +0 -9
  90. package/dist/components/PlMultiSequenceAlignment/Consensus.vue3.js.map +0 -1
  91. package/dist/components/PlMultiSequenceAlignment/Legend.vue.d.ts +0 -6
  92. package/dist/components/PlMultiSequenceAlignment/Legend.vue.js +0 -10
  93. package/dist/components/PlMultiSequenceAlignment/Legend.vue.js.map +0 -1
  94. package/dist/components/PlMultiSequenceAlignment/Legend.vue2.js +0 -28
  95. package/dist/components/PlMultiSequenceAlignment/Legend.vue2.js.map +0 -1
  96. package/dist/components/PlMultiSequenceAlignment/Legend.vue3.js +0 -13
  97. package/dist/components/PlMultiSequenceAlignment/Legend.vue3.js.map +0 -1
  98. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.d.ts +0 -25
  99. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.js +0 -10
  100. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue.js.map +0 -1
  101. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue2.js +0 -138
  102. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue2.js.map +0 -1
  103. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue3.js +0 -31
  104. package/dist/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue3.js.map +0 -1
  105. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.d.ts +0 -8
  106. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.js +0 -10
  107. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue.js.map +0 -1
  108. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue2.js +0 -77
  109. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue2.js.map +0 -1
  110. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue3.js +0 -9
  111. package/dist/components/PlMultiSequenceAlignment/PhylogeneticTree.vue3.js.map +0 -1
  112. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.d.ts +0 -71
  113. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.js +0 -10
  114. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue.js.map +0 -1
  115. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue2.js +0 -224
  116. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue2.js.map +0 -1
  117. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue3.js +0 -9
  118. package/dist/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue3.js.map +0 -1
  119. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.d.ts +0 -8
  120. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.js +0 -10
  121. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue.js.map +0 -1
  122. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue2.js +0 -127
  123. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue2.js.map +0 -1
  124. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue3.js +0 -9
  125. package/dist/components/PlMultiSequenceAlignment/SeqLogo.vue3.js.map +0 -1
  126. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue.d.ts +0 -16
  127. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue.js +0 -10
  128. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue.js.map +0 -1
  129. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue2.js +0 -228
  130. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue2.js.map +0 -1
  131. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue3.js +0 -19
  132. package/dist/components/PlMultiSequenceAlignment/Toolbar.vue3.js.map +0 -1
  133. package/dist/components/PlMultiSequenceAlignment/cell-size.d.ts +0 -4
  134. package/dist/components/PlMultiSequenceAlignment/cell-size.js +0 -8
  135. package/dist/components/PlMultiSequenceAlignment/cell-size.js.map +0 -1
  136. package/dist/components/PlMultiSequenceAlignment/chemical-properties.d.ts +0 -44
  137. package/dist/components/PlMultiSequenceAlignment/chemical-properties.js +0 -132
  138. package/dist/components/PlMultiSequenceAlignment/chemical-properties.js.map +0 -1
  139. package/dist/components/PlMultiSequenceAlignment/data.d.ts +0 -61
  140. package/dist/components/PlMultiSequenceAlignment/data.js +0 -370
  141. package/dist/components/PlMultiSequenceAlignment/data.js.map +0 -1
  142. package/dist/components/PlMultiSequenceAlignment/index.d.ts +0 -1
  143. package/dist/components/PlMultiSequenceAlignment/markup.d.ts +0 -16
  144. package/dist/components/PlMultiSequenceAlignment/markup.js +0 -84
  145. package/dist/components/PlMultiSequenceAlignment/markup.js.map +0 -1
  146. package/dist/components/PlMultiSequenceAlignment/migrations.d.ts +0 -3
  147. package/dist/components/PlMultiSequenceAlignment/migrations.js +0 -24
  148. package/dist/components/PlMultiSequenceAlignment/migrations.js.map +0 -1
  149. package/dist/components/PlMultiSequenceAlignment/multi-sequence-alignment.worker.d.ts +0 -6
  150. package/dist/components/PlMultiSequenceAlignment/phylogenetic-tree.worker.d.ts +0 -7
  151. package/dist/components/PlMultiSequenceAlignment/residue-counts.d.ts +0 -2
  152. package/dist/components/PlMultiSequenceAlignment/residue-counts.js +0 -13
  153. package/dist/components/PlMultiSequenceAlignment/residue-counts.js.map +0 -1
  154. package/dist/components/PlMultiSequenceAlignment/settings.d.ts +0 -2
  155. package/dist/components/PlMultiSequenceAlignment/settings.js +0 -9
  156. package/dist/components/PlMultiSequenceAlignment/settings.js.map +0 -1
  157. package/dist/components/PlMultiSequenceAlignment/types.d.ts +0 -5
  158. package/dist/components/PlMultiSequenceAlignment/useMiPlots.d.ts +0 -4
  159. package/dist/components/PlMultiSequenceAlignment/useMiPlots.js +0 -19
  160. package/dist/components/PlMultiSequenceAlignment/useMiPlots.js.map +0 -1
  161. package/src/components/PlMultiSequenceAlignment/Consensus.vue +0 -165
  162. package/src/components/PlMultiSequenceAlignment/Legend.vue +0 -44
  163. package/src/components/PlMultiSequenceAlignment/MultiSequenceAlignmentView.vue +0 -299
  164. package/src/components/PlMultiSequenceAlignment/PhylogeneticTree.vue +0 -110
  165. package/src/components/PlMultiSequenceAlignment/PlMultiSequenceAlignment.vue +0 -314
  166. package/src/components/PlMultiSequenceAlignment/README.md +0 -216
  167. package/src/components/PlMultiSequenceAlignment/SeqLogo.vue +0 -166
  168. package/src/components/PlMultiSequenceAlignment/Toolbar.vue +0 -228
  169. package/src/components/PlMultiSequenceAlignment/cell-size.ts +0 -4
  170. package/src/components/PlMultiSequenceAlignment/chemical-properties.ts +0 -199
  171. package/src/components/PlMultiSequenceAlignment/data.ts +0 -661
  172. package/src/components/PlMultiSequenceAlignment/index.ts +0 -1
  173. package/src/components/PlMultiSequenceAlignment/markup.ts +0 -141
  174. package/src/components/PlMultiSequenceAlignment/migrations.ts +0 -46
  175. package/src/components/PlMultiSequenceAlignment/multi-sequence-alignment.worker.ts +0 -54
  176. package/src/components/PlMultiSequenceAlignment/phylogenetic-tree.worker.ts +0 -89
  177. package/src/components/PlMultiSequenceAlignment/residue-counts.ts +0 -124
  178. package/src/components/PlMultiSequenceAlignment/settings.ts +0 -7
  179. package/src/components/PlMultiSequenceAlignment/types.ts +0 -3
  180. package/src/components/PlMultiSequenceAlignment/useMiPlots.ts +0 -23
@@ -1,314 +0,0 @@
1
- <script lang="ts" setup>
2
- import { isJsonEqual } from '@milaboratories/helpers';
3
- import {
4
- type ListOptionNormalized,
5
- PlAlert,
6
- PlSplash,
7
- } from '@milaboratories/uikit';
8
- import {
9
- getRawPlatformaInstance,
10
- type PColumnPredicate,
11
- type PFrameHandle,
12
- type PlMultiSequenceAlignmentColorSchemeOption,
13
- type PlMultiSequenceAlignmentModel,
14
- type PlMultiSequenceAlignmentSettings,
15
- type PlSelectionModel,
16
- } from '@platforma-sdk/model';
17
- import {
18
- computed,
19
- onBeforeMount,
20
- onUnmounted,
21
- reactive,
22
- useCssModule,
23
- useTemplateRef,
24
- watchEffect,
25
- } from 'vue';
26
- import {
27
- SEQUENCE_LIMIT,
28
- useLabelColumnsOptions,
29
- useMarkupColumnsOptions,
30
- useMultipleAlignmentData,
31
- useSequenceColumnsOptions,
32
- } from './data';
33
- import { runMigrations } from './migrations';
34
- import MultiSequenceAlignmentView from './MultiSequenceAlignmentView.vue';
35
- import { defaultSettings } from './settings';
36
- import Toolbar from './Toolbar.vue';
37
-
38
- const model = defineModel<PlMultiSequenceAlignmentModel>({ default: {} });
39
-
40
- onBeforeMount(() => {
41
- runMigrations(model);
42
- });
43
-
44
- const settings = reactive<PlMultiSequenceAlignmentSettings>({
45
- ...defaultSettings,
46
- });
47
-
48
- const props = defineProps<{
49
- /**
50
- * Handle to PFrame created using `createPFrameForGraphs`.
51
- * Should contain all desired sequence and label columns.
52
- */
53
- readonly pFrame: PFrameHandle | undefined;
54
- /**
55
- * Return true if column should be shown in sequence columns dropdown.
56
- * By default, all sequence columns are selected.
57
- */
58
- readonly sequenceColumnPredicate: PColumnPredicate;
59
- /**
60
- * Row selection model (from `PlAgDataTableV2` or `GraphMaker`).
61
- * If not provided or empty, all rows will be considered selected.
62
- * Warning: should be forwarded as a field of `reactive` object
63
- */
64
- readonly selection?: PlSelectionModel;
65
- }>();
66
-
67
- const classes = useCssModule();
68
-
69
- const sequenceColumns = reactive(useSequenceColumnsOptions(() => ({
70
- pFrame: props.pFrame,
71
- sequenceColumnPredicate: props.sequenceColumnPredicate,
72
- })));
73
-
74
- const labelColumns = reactive(useLabelColumnsOptions(() => ({
75
- pFrame: props.pFrame,
76
- sequenceColumnIds: settings.sequenceColumnIds,
77
- })));
78
-
79
- const markupColumns = reactive(useMarkupColumnsOptions(() => ({
80
- pFrame: props.pFrame,
81
- sequenceColumnIds: settings.sequenceColumnIds,
82
- })));
83
-
84
- const multipleAlignmentData = reactive(useMultipleAlignmentData(() => ({
85
- pFrame: props.pFrame,
86
- sequenceColumnIds: settings.sequenceColumnIds,
87
- labelColumnIds: settings.labelColumnIds,
88
- selection: props.selection,
89
- colorScheme: settings.colorScheme,
90
- alignmentParams: settings.alignmentParams,
91
- shouldBuildPhylogeneticTree: settings.widgets.includes('tree'),
92
- })));
93
-
94
- const formatNumber = new Intl.NumberFormat('en').format;
95
-
96
- const colorSchemeOptions = computed<
97
- ListOptionNormalized<PlMultiSequenceAlignmentColorSchemeOption>[]
98
- >(
99
- () => [
100
- {
101
- label: 'Chemical Properties',
102
- value: { type: 'chemical-properties' },
103
- },
104
- {
105
- label: 'No Color',
106
- value: { type: 'no-color' },
107
- },
108
- ...(markupColumns.data ?? []).map(({ label, value }) => ({
109
- label,
110
- value: {
111
- type: 'markup' as const,
112
- columnIds: value,
113
- },
114
- })),
115
- ],
116
- );
117
-
118
- const error = computed(() =>
119
- sequenceColumns.error
120
- ?? labelColumns.error
121
- ?? markupColumns.error
122
- ?? multipleAlignmentData.error,
123
- );
124
-
125
- function applySettings(
126
- settingsPatch: Partial<PlMultiSequenceAlignmentSettings>,
127
- ) {
128
- model.value = Object.fromEntries(
129
- Object.entries({ ...model.value, ...settingsPatch })
130
- .filter(([_key, value]) => value !== undefined),
131
- );
132
- }
133
-
134
- watchEffect(() => {
135
- const patch: Partial<PlMultiSequenceAlignmentSettings> = Object.fromEntries(
136
- Object.entries({
137
- ...defaultSettings,
138
- sequenceColumnIds: sequenceColumns.data?.defaults,
139
- labelColumnIds: labelColumns.data?.defaults,
140
- ...model.value,
141
- }).filter(([key, value]) =>
142
- !isJsonEqual(
143
- settings[key as keyof PlMultiSequenceAlignmentSettings],
144
- value,
145
- ),
146
- ),
147
- );
148
- Object.assign(settings, patch);
149
- });
150
-
151
- // Reset stale settings
152
- watchEffect(() => {
153
- const settingsToReset: (keyof PlMultiSequenceAlignmentSettings)[] = [];
154
- if (
155
- !sequenceColumns.isLoading
156
- && settings.sequenceColumnIds?.some((id) =>
157
- (sequenceColumns.data?.options ?? []).every(
158
- ({ value }) => !isJsonEqual(value, id),
159
- ),
160
- )
161
- ) {
162
- settingsToReset.push('sequenceColumnIds');
163
- }
164
- if (
165
- !labelColumns.isLoading
166
- && settings.labelColumnIds?.some((id) =>
167
- (labelColumns.data?.options ?? []).every(
168
- ({ value }) => !isJsonEqual(value, id),
169
- ),
170
- )
171
- ) {
172
- settingsToReset.push('labelColumnIds');
173
- }
174
-
175
- const markupColumnIds = settings.colorScheme?.type === 'markup'
176
- ? settings.colorScheme.columnIds
177
- : undefined;
178
-
179
- if (
180
- !markupColumns.isLoading
181
- && markupColumnIds
182
- && (markupColumns.data ?? []).every(
183
- ({ value }) => !isJsonEqual(value, markupColumnIds),
184
- )
185
- ) {
186
- settingsToReset.push('colorScheme');
187
- }
188
- if (settingsToReset.length) {
189
- applySettings(Object.fromEntries(
190
- settingsToReset.map((key) => [key, undefined]),
191
- ));
192
- }
193
- });
194
-
195
- const msaEl = useTemplateRef('msa');
196
-
197
- async function exportPdf() {
198
- const exportToPdf = getRawPlatformaInstance()?.lsDriver
199
- ?.exportToPdf;
200
- if (!exportToPdf) {
201
- return console.error(
202
- 'API getPlatformaRawInstance().lsDriver.exportToPdf is not available',
203
- );
204
- }
205
- const msaRoot = msaEl.value?.rootEl;
206
- if (!msaRoot) {
207
- throw new Error('MSA element is not available.');
208
- }
209
- const printTarget = document.createElement('div');
210
- printTarget.id = `print-target-${crypto.randomUUID()}`;
211
- const printStyleSheet = new CSSStyleSheet();
212
- document.adoptedStyleSheets.push(printStyleSheet);
213
- printStyleSheet.insertRule(`
214
- @media screen {
215
- #${printTarget.id} {
216
- visibility: hidden;
217
- position: fixed;
218
- }
219
- }`);
220
- const msaClone = msaRoot.cloneNode(true) as HTMLElement;
221
- msaClone.dataset.prePrint = '';
222
- printTarget.replaceChildren(msaClone);
223
- document.body.appendChild(printTarget);
224
- const { height, width } = printTarget.getBoundingClientRect();
225
- const margin = CSS.cm(1);
226
- const pageSize = [width, height]
227
- .map((value) => CSS.px(value).add(margin.mul(2)))
228
- .join(' ');
229
- printStyleSheet.insertRule(`
230
- @media print {
231
- @page {
232
- size: ${pageSize};
233
- margin: ${margin};
234
- }
235
- body > :not(#${printTarget.id}) {
236
- display: none;
237
- }
238
- }`);
239
- try {
240
- await exportToPdf();
241
- } catch (error) {
242
- console.error(error);
243
- } finally {
244
- document.body.removeChild(printTarget);
245
- const index = document.adoptedStyleSheets.indexOf(printStyleSheet);
246
- if (index >= 0) {
247
- document.adoptedStyleSheets.splice(index, 1);
248
- }
249
- }
250
- }
251
-
252
- onUnmounted(() => {
253
- multipleAlignmentData.data = undefined;
254
- });
255
- </script>
256
-
257
- <template>
258
- <Toolbar
259
- :settings="settings"
260
- :sequence-column-options="sequenceColumns.data?.options"
261
- :label-column-options="labelColumns.data?.options"
262
- :color-scheme-options="colorSchemeOptions"
263
- @update-settings="applySettings"
264
- @export="exportPdf"
265
- />
266
- <PlAlert v-if="error" type="error">
267
- {{ error }}
268
- </PlAlert>
269
- <PlAlert
270
- v-else-if="!multipleAlignmentData.isLoading && !multipleAlignmentData.data"
271
- type="warn"
272
- icon
273
- >
274
- Please select at least one sequence column and two or more rows to run
275
- alignment
276
- </PlAlert>
277
- <template v-else>
278
- <PlAlert
279
- v-if="multipleAlignmentData.data?.exceedsLimit"
280
- type="warn"
281
- icon
282
- label="Visualization is limited"
283
- >
284
- MSA visualization supports {{ formatNumber(2) }} to
285
- {{ formatNumber(SEQUENCE_LIMIT) }} sequences. Only the first
286
- {{ formatNumber(SEQUENCE_LIMIT) }} will be displayed.
287
- </PlAlert>
288
- <PlSplash
289
- type="transparent"
290
- :class="classes.splash"
291
- :loading="multipleAlignmentData.isLoading"
292
- >
293
- <MultiSequenceAlignmentView
294
- v-if="multipleAlignmentData.data"
295
- ref="msa"
296
- :sequences="multipleAlignmentData.data.sequences"
297
- :labels="multipleAlignmentData.data.labels"
298
- :highlight-legend="multipleAlignmentData.data.highlightLegend"
299
- :phylogenetic-tree="multipleAlignmentData.data.phylogeneticTree"
300
- :widgets="settings.widgets"
301
- />
302
- </PlSplash>
303
- </template>
304
- </template>
305
-
306
- <style module>
307
- .splash {
308
- flex: 1;
309
- display: flex;
310
- flex-direction: column;
311
- gap: 12px;
312
- overflow: hidden;
313
- }
314
- </style>
@@ -1,216 +0,0 @@
1
- # `PlMultiSequenceAlignment`
2
-
3
- The name of the component is usually shortened to MSA.
4
-
5
- For the design, see
6
- https://www.figma.com/design/pndFzfW2eqdIWfA8IoraMg/%F0%9F%A7%AC-MSA?t=LRoRiHQhyga7Ndzx-0.
7
-
8
- ## Structure
9
-
10
- ### PlMultiSequenceAlignment
11
-
12
- Defined in `PlMultiSequenceAlignment.vue`.
13
-
14
- This component is a "wrapper" that takes supplied data, runs data fetchers from
15
- `data.ts` and draws `<MultiSequenceAlignmentView />`. It also draws a
16
- `<Toolbar />` and is responsible for loading and error states.
17
-
18
- The inputs are:
19
-
20
- - `pFrame`
21
- - `sequenceColumnPredicate`: predicate function by which the component filters
22
- the columns to find only the sequence columns
23
- - `selection`: `PlSelectionModel` that is returned from GraphMaker,
24
- PlAgDataTable or potentially some other component, indicates which rows should
25
- be selected from the columns
26
- - `modelValue`: a storage for MSA settings
27
-
28
- The settings for MSA are derived from `modelValue`, filling the `undefined` gaps
29
- with default settings (defined in `settings.ts`).
30
-
31
- ### MultiSequenceAlignmentView
32
-
33
- Defined in `MultiSequenceAlignmentView.vue`.
34
-
35
- This is the presentational part, where most of the rendering is happening. It's
36
- meant to have as little logic as possible to prevent the out-of-sync states. The
37
- rendering is optimized to be as much monospace text-only as possible, with
38
- [highlighting](#highlighting-color-scheme) implemented as a background image. A
39
- lot of the rendering relies on the specific dimensions of the font. Gaps between
40
- letters are implemented with `letter-spacing`.
41
-
42
- ### Data
43
-
44
- Defined in `data.ts`.
45
-
46
- This is MSA data fetcher that is split between 4 Vue composables:
47
-
48
- - `useSequenceColumnsOptions`
49
- - `useLabelColumnsOptions`
50
- - `useMarkupColumnsOptions`
51
- - `useMultipleAlignmentData`
52
-
53
- First 3 composable are very similar. They take a list of columns from
54
- `pFrameDriver.listColumns(pFrame)` and return all the options that would be
55
- reasonable for the user to be able to choose from.
56
-
57
- `useSequenceColumnsOptions` and `useLabelColumnsOptions` specifically also
58
- return a list of default options that are preselected for the user.
59
-
60
- `useMultipleAlignmentData` does the actual computation. It runs
61
- `pFrameDriver.calculateTableData`, `multiSequenceAlignment`, highlighting and
62
- returns data in this format:
63
-
64
- - `sequences`: list of sequences rows, aligned and concatenated with a single
65
- whitespace (`["<r0c0> <r0c1>", "<r1c0> <r1c1>", ...]`; "r"—row, "c"—column);
66
- every row is the same length
67
- - `sequenceNames`: list of sequence names, should match the names of the options
68
- in a dropdown, which user selected
69
- - `labelRows`: list of lists of labels,
70
- (`[["<r0l0>", "<r0l1>", ...], ["<r1l0>", "<r1l1>", ...]]`, "r"—row, "l"—label)
71
- - `residueCounts`: see [Residue counts](#residue-counts)
72
- - `highlightImage`: optional, see [Highlighting](#highlighting-color-scheme)
73
- - `exceedsLimit`: see [Row limit](#row-limit)
74
-
75
- Most of the data generated by it is in the format that is useful for
76
- `<MultiSequenceAlignmentView />`.
77
-
78
- ### Highlighting (Color Scheme)
79
-
80
- There are two ways to colorize the MSA output. Both output a
81
- [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) that is an SVG
82
- file which is later scaled up to fit the table layout. Current implementation
83
- uses <path> tags to group multiple runs of the same color. The viewbox is
84
- doubled in one of the directions to use SVG strokes without resorting to
85
- fractional positions.
86
-
87
- There's also an option to not colorize the output at all.
88
-
89
- #### Chemical properties
90
-
91
- Defined in `chemical-properties.ts`.
92
-
93
- This is an implementation of Clustal X color scheme. See
94
- https://www.jalview.org/help/html/colourSchemes/clustal.html and
95
- https://www.rbvi.ucsf.edu/chimera/1.2065/docs/ContributedSoftware/multalignviewer/cxcolor.html
96
- for reference.
97
-
98
- #### Markup
99
-
100
- Defined in `markup.ts`.
101
-
102
- This color scheme highlights the parts of sequences that have a special meaning.
103
- Markup format looks like `<id_0>:<start_0>+<length_0>|<id_1>:<start_1>|...`,
104
- where `start` and `length` are encoded as base-36 numbers. `length` is optional,
105
- and is 1 by default. Markup entries can overlap, although right now it's not
106
- really handled in the UI. IDs bear no special meaning, and can be used in the UI
107
- directly, or the labels can be looked up in the
108
- `pl7.app/sequence/annotation/mapping` annotation of the markup column.
109
-
110
- For example, a string `1:P+A|2:1G+7|3:2O+D` encodes this markup:
111
-
112
- | id | start | length |
113
- | -- | ----- | ------ |
114
- | 1 | 25 | 10 |
115
- | 2 | 52 | 7 |
116
- | 3 | 96 | 13 |
117
-
118
- Note that the markup itself is for an original sequence, not an aligned one. So
119
- it needs to be adjusted for an aligned sequence (see function
120
- `markupAlignedSequence`).
121
-
122
- ### Alignment
123
-
124
- Defined in `multi-sequence-alignment.ts`.
125
-
126
- To run the actual alignment, MSA component uses
127
- (kalign)[https://github.com/TimoLassmann/kalign]. It is used as a WASM binary
128
- through a (Web
129
- Worker)[https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker].
130
- Currently, the source is (biowasm)[https://biowasm.com/cdn/v3/kalign/3.3.1],
131
- which we repackaged to work bundled and without a CDN.
132
-
133
- The worker is reused between multiple calls. The results are cached by input
134
- sequences and alignment params.
135
-
136
- ### Widgets
137
-
138
- #### Consensus
139
-
140
- Defined in `Consensus.vue`.
141
-
142
- This widget visualizes the most used residue in a column using `miplots4`'s
143
- `discrete` plot with a `bar` layer.
144
-
145
- #### SeqLogo
146
-
147
- Defined in `SeqLogo.vue`.
148
-
149
- For reference, see https://ivanek.github.io/seqLogo/articles/seqLogo.html. This
150
- is rendered using `miplots4`'s `discrete` plot with a `logo` layer.
151
-
152
- #### Legend
153
-
154
- Defined in `Legend.vue`.
155
-
156
- Legend for a selected color scheme.
157
-
158
- ### Toolbar
159
-
160
- Defined in `Toolbar.vue`.
161
-
162
- Displays the current (settings)[#settings]. Updates to settings are applied to
163
- model, from which the settings are re-derived afterwards.
164
-
165
- ### Residue counts
166
-
167
- Defined in `residue-counts.ts`.
168
-
169
- Supplemental data for [chemical properties](#chemical-properties) color scheme,
170
- [Consensus](#consensus) and [SeqLogo](#seqlogo) widgets. Simply counts how many
171
- times each residue was used in a column.
172
-
173
- ### Settings
174
-
175
- Defined in `settings.ts`.
176
-
177
- Derived from the `PlMultiSequenceAlignmentModel`, providing defaults for
178
- `undefined` fields in a model.
179
-
180
- - `sequenceColumnIds`: defines which sequence columns should be displayed
181
- - `labelColumnIds`: defines which label columns should be displayed
182
- - `colorScheme`: defined which [Color scheme](#highlighting-color-scheme) should
183
- be used for output highlighting
184
- - `widgets`: defines which [Widgets](#widgets) to display
185
- - `alignmentParams`: params that are used for [kalign](#alignment); currently
186
- `gpo`, `gpe` and `tgpe`
187
-
188
- Technically, `sequenceColumnIds` and `labelColumnIds` shouldn't be optional, but
189
- they are implemented as such because the defaults are fetched when the
190
- `PlMultiSequenceAlignment` component renders.
191
-
192
- ### Migrations
193
-
194
- Defined in `migrations.ts`.
195
-
196
- Defines migrations to run for the MSA model before anything is rendered. Useful
197
- when model format is changed and to upgrade an empty model to one with a
198
- version. Also, the simplest way to reset all the MSA settings would be to set
199
- the model to `{}` and run migrations.
200
-
201
- ### `useMiPlots.ts`
202
-
203
- A helper to import `miplots4` dependency dynamically to avoid blowing up the
204
- bundle. Probably should be moved outside this component at some point.
205
-
206
- ## Notes
207
-
208
- ### Row limit
209
-
210
- There's an agreed upon limit of 1,000 rows, over which the alignment won't be
211
- run. This limit is artificial, but it prevents a user from running a computation
212
- that might be too heavy, especially given that at the moment there's no way to
213
- terminate the alignment process.
214
-
215
- This limit is imposed on `useMultipleAlignmentData`
216
- /`pFrameDriver.calculateTableData` level.
@@ -1,166 +0,0 @@
1
- <script lang="ts" setup>
2
- import type {
3
- ChartInterface,
4
- DataByColumns,
5
- Settings,
6
- } from '@milaboratories/miplots4';
7
- import { PlAlert } from '@milaboratories/uikit';
8
- import {
9
- computed,
10
- onBeforeUnmount,
11
- shallowRef,
12
- useCssModule,
13
- useTemplateRef,
14
- watchEffect,
15
- } from 'vue';
16
- import { cellSize } from './cell-size';
17
- import type { ResidueCounts } from './types';
18
- import { useMiPlots } from './useMiPlots';
19
-
20
- const props = defineProps<{
21
- residueCounts: ResidueCounts;
22
- }>();
23
-
24
- const classes = useCssModule();
25
-
26
- const plotEl = useTemplateRef('plotEl');
27
-
28
- const palette = {
29
- blue: '#549EE7',
30
- red: '#E85456',
31
- green: '#65BF65',
32
- magenta: '#9178E1',
33
- pink: '#D568D5',
34
- orange: '#C59445',
35
- cyan: '#62C7CC',
36
- yellow: '#D5D549',
37
- black: '#000000',
38
- };
39
-
40
- const residueColors = {
41
- A: palette.blue,
42
- R: palette.red,
43
- N: palette.green,
44
- D: palette.magenta,
45
- C: palette.pink,
46
- Q: palette.green,
47
- E: palette.magenta,
48
- G: palette.orange,
49
- H: palette.cyan,
50
- I: palette.blue,
51
- L: palette.blue,
52
- K: palette.red,
53
- M: palette.blue,
54
- F: palette.blue,
55
- P: palette.yellow,
56
- S: palette.green,
57
- T: palette.green,
58
- W: palette.blue,
59
- Y: palette.cyan,
60
- V: palette.blue,
61
- B: palette.black,
62
- X: palette.black,
63
- Z: palette.black,
64
- };
65
-
66
- const settings = computed(() => ({
67
- type: 'discrete',
68
- title: {
69
- name: '',
70
- show: false,
71
- },
72
- size: {
73
- width: props.residueCounts.length * cellSize.inline,
74
- height: 80,
75
- innerOffset: 0,
76
- outerOffset: 0,
77
- },
78
- frame: {
79
- type: 'empty',
80
- },
81
- xAxis: {
82
- title: '',
83
- showGrid: false,
84
- showTicks: false,
85
- hiddenLabels: true,
86
- },
87
- yAxis: {
88
- title: '',
89
- showGrid: false,
90
- showTicks: false,
91
- hiddenLabels: true,
92
- },
93
- y: {
94
- type: 'column',
95
- value: 'countKey',
96
- },
97
- primaryGrouping: {
98
- columnName: {
99
- type: 'column',
100
- value: 'columnKey',
101
- },
102
- },
103
- secondaryGrouping: {
104
- columnName: {
105
- type: 'column',
106
- value: 'residueKey',
107
- },
108
- },
109
- layers: [{
110
- type: 'logo',
111
- aes: { fillColor: residueColors },
112
- }],
113
- } satisfies Settings));
114
-
115
- const data = computed<DataByColumns>(() => {
116
- const countKey: number[] = [];
117
- const columnKey: number[] = [];
118
- const residueKey: string[] = [];
119
- for (const [columnIndex, column] of props.residueCounts.entries()) {
120
- for (const [residue, count] of Object.entries(column)) {
121
- if (residue === '-') continue;
122
- countKey.push(count);
123
- columnKey.push(columnIndex);
124
- residueKey.push(residue);
125
- }
126
- }
127
- return ({
128
- type: 'columns',
129
- id: `seq-logo-${crypto.randomUUID()}`,
130
- values: { countKey, columnKey, residueKey },
131
- });
132
- });
133
-
134
- const { miplots, error } = useMiPlots();
135
-
136
- const plot = shallowRef<ChartInterface>();
137
-
138
- watchEffect(async () => {
139
- if (!plotEl.value || !miplots.value) return;
140
- if (!plot.value) {
141
- plot.value = miplots.value.newPlot(data.value, settings.value);
142
- plot.value.mount(plotEl.value);
143
- } else {
144
- plot.value.updateSettingsAndData(data.value, settings.value);
145
- }
146
- });
147
-
148
- onBeforeUnmount(() => {
149
- plot.value?.unmount();
150
- });
151
- </script>
152
-
153
- <template>
154
- <PlAlert v-if="error" type="error">
155
- {{ error.message }}
156
- </PlAlert>
157
- <div v-else ref="plotEl" :class="classes.container" />
158
- </template>
159
-
160
- <style module>
161
- .container {
162
- svg {
163
- display: block;
164
- }
165
- }
166
- </style>