@platforma-sdk/ui-vue 1.64.0 → 1.65.3

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 (63) hide show
  1. package/.turbo/turbo-build.log +25 -25
  2. package/.turbo/turbo-formatter$colon$check.log +2 -2
  3. package/.turbo/turbo-linter$colon$check.log +2 -2
  4. package/.turbo/turbo-types$colon$check.log +1 -1
  5. package/CHANGELOG.md +19 -0
  6. package/dist/components/PlAdvancedFilter/FilterEditor.js.map +1 -1
  7. package/dist/components/PlAdvancedFilter/FilterEditor.style.js.map +1 -1
  8. package/dist/components/PlAdvancedFilter/FilterEditor.vue.d.ts +3 -8
  9. package/dist/components/PlAdvancedFilter/FilterEditor.vue.d.ts.map +1 -1
  10. package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js +164 -151
  11. package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js.map +1 -1
  12. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.js.map +1 -1
  13. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.style.js +8 -7
  14. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.style.js.map +1 -1
  15. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue.css +1 -1
  16. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue.d.ts +24 -8
  17. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue.d.ts.map +1 -1
  18. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js +176 -110
  19. package/dist/components/PlAdvancedFilter/PlAdvancedFilter.vue2.js.map +1 -1
  20. package/dist/components/PlAdvancedFilter/types.d.ts +2 -0
  21. package/dist/components/PlAdvancedFilter/types.d.ts.map +1 -1
  22. package/dist/components/PlAgDataTable/PlAgDataTableV2.js.map +1 -1
  23. package/dist/components/PlAgDataTable/PlAgDataTableV2.style.js.map +1 -1
  24. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue.d.ts.map +1 -1
  25. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js +116 -109
  26. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js.map +1 -1
  27. package/dist/components/PlAgDataTable/sources/table-source-v2.d.ts +6 -5
  28. package/dist/components/PlAgDataTable/sources/table-source-v2.d.ts.map +1 -1
  29. package/dist/components/PlAgDataTable/sources/table-source-v2.js +26 -26
  30. package/dist/components/PlAgDataTable/sources/table-source-v2.js.map +1 -1
  31. package/dist/components/PlAgDataTable/sources/table-state-v2.d.ts +6 -3
  32. package/dist/components/PlAgDataTable/sources/table-state-v2.d.ts.map +1 -1
  33. package/dist/components/PlAgDataTable/sources/table-state-v2.js +182 -97
  34. package/dist/components/PlAgDataTable/sources/table-state-v2.js.map +1 -1
  35. package/dist/components/PlAnnotations/components/FilterSidebar.js.map +1 -1
  36. package/dist/components/PlAnnotations/components/FilterSidebar.style.js.map +1 -1
  37. package/dist/components/PlAnnotations/components/FilterSidebar.vue.d.ts.map +1 -1
  38. package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js +7 -4
  39. package/dist/components/PlAnnotations/components/FilterSidebar.vue2.js.map +1 -1
  40. package/dist/components/PlTableFilters/PlTableFiltersV2.js.map +1 -1
  41. package/dist/components/PlTableFilters/PlTableFiltersV2.style.js +5 -1
  42. package/dist/components/PlTableFilters/PlTableFiltersV2.style.js.map +1 -1
  43. package/dist/components/PlTableFilters/PlTableFiltersV2.vue.css +1 -1
  44. package/dist/components/PlTableFilters/PlTableFiltersV2.vue.d.ts +7 -9
  45. package/dist/components/PlTableFilters/PlTableFiltersV2.vue.d.ts.map +1 -1
  46. package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js +73 -42
  47. package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js.map +1 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +2 -0
  50. package/dist/index.js.map +1 -1
  51. package/dist/lib/util/helpers/dist/functions.js.map +1 -1
  52. package/dist/lib/util/helpers/dist/objects.js +4 -1
  53. package/dist/lib/util/helpers/dist/objects.js.map +1 -1
  54. package/package.json +7 -6
  55. package/src/components/PlAdvancedFilter/FilterEditor.vue +99 -55
  56. package/src/components/PlAdvancedFilter/PlAdvancedFilter.vue +163 -95
  57. package/src/components/PlAdvancedFilter/types.ts +6 -1
  58. package/src/components/PlAgDataTable/PlAgDataTableV2.vue +24 -6
  59. package/src/components/PlAgDataTable/sources/table-source-v2.ts +11 -9
  60. package/src/components/PlAgDataTable/sources/table-state-v2.ts +249 -64
  61. package/src/components/PlAnnotations/components/FilterSidebar.vue +3 -2
  62. package/src/components/PlTableFilters/PlTableFiltersV2.vue +75 -21
  63. package/src/index.ts +4 -0
@@ -27,10 +27,10 @@ import { DEFAULT_FILTER_TYPE, DEFAULT_FILTERS } from "./constants";
27
27
  import OperandButton from "./OperandButton.vue";
28
28
  import type { EditableFilter, Operand, PlAdvancedFilterColumnId, SourceOptionInfo } from "./types";
29
29
  import { getFilterInfo, getNormalizedSpec, isNumericFilter, isPositionFilter } from "./utils";
30
-
31
- const filter = defineModel<EditableFilter>("filter", { required: true });
30
+ import { Entries } from "@milaboratories/helpers";
32
31
 
33
32
  const props = defineProps<{
33
+ filter: EditableFilter;
34
34
  isLast: boolean;
35
35
  operand: Operand;
36
36
  enableDnd: boolean;
@@ -43,9 +43,20 @@ const props = defineProps<{
43
43
  searchStr: string;
44
44
  }) => ListOptionBase<string | number>[] | Promise<ListOptionBase<string | number>[]>;
45
45
  onDelete: (columnId: PlAdvancedFilterColumnId) => void;
46
+ onUpdateFilter: (filter: EditableFilter) => void;
46
47
  onChangeOperand: (op: Operand) => void;
47
48
  }>();
48
49
 
50
+ type AllKeys<U> = U extends unknown ? keyof U : never;
51
+ type ValueOf<U, K extends string> = U extends unknown ? (K extends keyof U ? U[K] : never) : never;
52
+
53
+ function updateFilterProp<K extends AllKeys<EditableFilter> & string>(
54
+ key: K,
55
+ v: ValueOf<EditableFilter, K>,
56
+ ) {
57
+ props.onUpdateFilter({ ...props.filter, [key]: v } as EditableFilter);
58
+ }
59
+
49
60
  async function getSuggestOptionsFn(
50
61
  id: PlAdvancedFilterColumnId,
51
62
  type: "value" | "label",
@@ -76,17 +87,21 @@ async function getMultiSuggestOptionsFn(
76
87
  throw new Error("Invalid arguments combination");
77
88
  }
78
89
 
79
- type Entries<T> = { [K in keyof T]: [K, T[K]] }[keyof T][];
80
- function changeFilterType() {
81
- const defaultFilter = DEFAULT_FILTERS[filter.value.type];
82
-
83
- filter.value = (Object.entries(defaultFilter) as Entries<EditableFilter>).reduce(
84
- (res, [key, val]) => {
85
- res[key] = filter.value[key] ?? val;
86
- return res;
87
- },
88
- {} as Record<keyof EditableFilter, EditableFilter[keyof EditableFilter]>,
89
- ) as EditableFilter;
90
+ function changeFilterType(newType: EditableFilter["type"]) {
91
+ const defaultFilter = DEFAULT_FILTERS[newType];
92
+
93
+ props.onUpdateFilter(
94
+ (Object.entries(defaultFilter) as Entries<EditableFilter>).reduce(
95
+ (res, [key, val]) => {
96
+ res[key] = props.filter[key] ?? val;
97
+ return res;
98
+ },
99
+ { ...props.filter, type: newType } as Record<
100
+ keyof EditableFilter,
101
+ EditableFilter[keyof EditableFilter]
102
+ >,
103
+ ) as EditableFilter,
104
+ );
90
105
  }
91
106
 
92
107
  function changeSourceId(newSourceId?: PlAdvancedFilterColumnId) {
@@ -97,30 +112,28 @@ function changeSourceId(newSourceId?: PlAdvancedFilterColumnId) {
97
112
  if (!newSourceInfo) {
98
113
  return;
99
114
  }
100
- const filterInfo = getFilterInfo(filter.value.type);
115
+ const filterInfo = getFilterInfo(props.filter.type);
101
116
  const newSourceSpec = getNormalizedSpec(newSourceInfo?.spec);
102
117
  if (filterInfo.supportedFor(newSourceSpec)) {
103
- // don't do anything except update source id
104
- filter.value.column = newSourceId;
118
+ props.onUpdateFilter({ ...props.filter, column: newSourceId });
105
119
  } else {
106
- // reset to default filter which fits to any column
107
- filter.value = {
120
+ props.onUpdateFilter({
108
121
  ...DEFAULT_FILTERS[DEFAULT_FILTER_TYPE],
109
122
  column: newSourceId,
110
- };
123
+ });
111
124
  }
112
125
  }
113
126
 
114
127
  const inconsistentSourceSelected = computed(() => {
115
128
  const selectedOption = props.columnOptions.find(
116
- (op) => op.id === getSourceId(filter.value.column),
129
+ (op) => op.id === getSourceId(props.filter.column),
117
130
  );
118
131
  return selectedOption === undefined;
119
132
  });
120
133
  const sourceOptions = computed(() => {
121
134
  const options = props.columnOptions.map((v) => ({ value: v.id, label: v.label ?? v }));
122
135
  if (inconsistentSourceSelected.value) {
123
- options.unshift({ value: filter.value.column, label: "Inconsistent value" });
136
+ options.unshift({ value: props.filter.column, label: "Inconsistent value" });
124
137
  }
125
138
  return options;
126
139
  });
@@ -186,10 +199,10 @@ function stringifyColumn(value: ColumnAsSourceAndFixedAxes): PlAdvancedFilterCol
186
199
 
187
200
  const columnAsSourceAndFixedAxes = computed({
188
201
  get: () => {
189
- return getColumnAsSourceAndFixedAxes(filter.value.column);
202
+ return getColumnAsSourceAndFixedAxes(props.filter.column);
190
203
  },
191
204
  set: (value) => {
192
- filter.value.column = stringifyColumn(value);
205
+ props.onUpdateFilter({ ...props.filter, column: stringifyColumn(value) });
193
206
  },
194
207
  });
195
208
  function updateAxisFilterValue(idx: number, value: AxisFilterValue | undefined) {
@@ -214,14 +227,14 @@ const filterTypesOptions = computed(() =>
214
227
  props.supportedFilters
215
228
  .filter(
216
229
  (v) =>
217
- filter.value.type === v ||
230
+ props.filter.type === v ||
218
231
  (currentSpec.value ? getFilterInfo(v).supportedFor(currentSpec.value) : true),
219
232
  )
220
233
  .map((v) => ({ value: v, label: getFilterInfo(v).label })),
221
234
  );
222
235
 
223
236
  const wildcardOptions = computed(() => {
224
- if (filter.value.type !== "patternFuzzyContainSubsequence") {
237
+ if (props.filter.type !== "patternFuzzyContainSubsequence") {
225
238
  return [];
226
239
  }
227
240
  if (currentOption.value?.alphabet === "nucleotide") {
@@ -230,15 +243,15 @@ const wildcardOptions = computed(() => {
230
243
  if (currentOption.value?.alphabet === "aminoacid") {
231
244
  return [{ label: "X", value: "X" }];
232
245
  }
233
- return [...new Set(filter.value.value.split(""))].sort().map((v) => ({ value: v, label: v }));
246
+ return [...new Set(props.filter.value.split(""))].sort().map((v) => ({ value: v, label: v }));
234
247
  });
235
248
 
236
249
  const stringMatchesError = computed(() => {
237
- if (filter.value.type !== "patternMatchesRegularExpression") {
250
+ if (props.filter.type !== "patternMatchesRegularExpression") {
238
251
  return false;
239
252
  }
240
253
  try {
241
- new RegExp(filter.value.value);
254
+ new RegExp(props.filter.value);
242
255
  return false;
243
256
  } catch {
244
257
  return true;
@@ -268,24 +281,24 @@ const stringMatchesError = computed(() => {
268
281
  {{
269
282
  inconsistentSourceSelected
270
283
  ? "Inconsistent value"
271
- : (currentOption?.label ?? filter.column)
284
+ : (currentOption?.label ?? props.filter.column)
272
285
  }}
273
286
  </div>
274
287
  </div>
275
- <div :class="$style.closeIcon" @click="onDelete(filter.column)">
288
+ <div :class="$style.closeIcon" @click="onDelete(props.filter.column)">
276
289
  <PlIcon16 name="close" />
277
290
  </div>
278
291
  </div>
279
292
  <div v-else :class="$style.top">
280
293
  <PlDropdown
281
- v-model="columnAsSourceAndFixedAxes.source"
294
+ :model-value="columnAsSourceAndFixedAxes.source"
282
295
  :errorStatus="currentError"
283
296
  :options="sourceOptions"
284
297
  :style="{ width: '100%' }"
285
298
  group-position="top-left"
286
299
  @update:model-value="changeSourceId"
287
300
  />
288
- <div :class="$style.closeButton" @click="onDelete(filter.column)">
301
+ <div :class="$style.closeButton" @click="onDelete(props.filter.column)">
289
302
  <PlIcon16 name="close" />
290
303
  </div>
291
304
  </div>
@@ -293,7 +306,7 @@ const stringMatchesError = computed(() => {
293
306
  <div v-if="currentOption?.axesToBeFixed?.length" :class="$style.fixedAxesBlock">
294
307
  <template v-for="value in currentOption?.axesToBeFixed" :key="value.idx">
295
308
  <PlAutocomplete
296
- v-model="columnAsSourceAndFixedAxes.axisFiltersByIndex[value.idx]"
309
+ :model-value="columnAsSourceAndFixedAxes.axisFiltersByIndex[value.idx]"
297
310
  :label="value.label"
298
311
  :options-search="
299
312
  (str, type) =>
@@ -308,81 +321,112 @@ const stringMatchesError = computed(() => {
308
321
 
309
322
  <!-- middle - filter type selector - for all filter types -->
310
323
  <div
311
- :class="filter.type === 'isNA' || filter.type === 'isNotNA' ? $style.bottom : $style.middle"
324
+ :class="
325
+ props.filter.type === 'isNA' || props.filter.type === 'isNotNA'
326
+ ? $style.bottom
327
+ : $style.middle
328
+ "
312
329
  >
313
330
  <PlDropdown
314
- v-model="filter.type"
331
+ :model-value="props.filter.type"
315
332
  :options="filterTypesOptions"
316
- :group-position="filter.type === 'isNA' || filter.type === 'isNotNA' ? 'bottom' : 'middle'"
317
- @update:model-value="changeFilterType"
333
+ :group-position="
334
+ props.filter.type === 'isNA' || props.filter.type === 'isNotNA' ? 'bottom' : 'middle'
335
+ "
336
+ @update:model-value="(v) => changeFilterType(v!)"
318
337
  />
319
338
  </div>
320
339
 
321
340
  <!-- middle - for fuzzy contains filter -->
322
- <template v-if="filter.type === 'patternFuzzyContainSubsequence'">
341
+ <template v-if="props.filter.type === 'patternFuzzyContainSubsequence'">
323
342
  <div :class="$style.middle">
324
- <PlTextField v-model="filter.value" placeholder="Substring" group-position="middle" />
343
+ <PlTextField
344
+ :model-value="props.filter.value"
345
+ placeholder="Substring"
346
+ group-position="middle"
347
+ @update:model-value="(v) => updateFilterProp('value', v)"
348
+ />
325
349
  </div>
326
350
  <div :class="$style.innerSection">
327
351
  <Slider
328
- v-model="filter.maxEdits"
352
+ :model-value="props.filter.maxEdits"
329
353
  :max="5"
330
354
  breakpoints
331
355
  label="Maximum number of substitutions and indels"
356
+ @update:model-value="(v) => updateFilterProp('maxEdits', v)"
357
+ />
358
+ <PlToggleSwitch
359
+ :model-value="props.filter.substitutionsOnly"
360
+ label="Substitutions only"
361
+ @update:model-value="(v) => updateFilterProp('substitutionsOnly', v)"
332
362
  />
333
- <PlToggleSwitch v-model="filter.substitutionsOnly" label="Substitutions only" />
334
363
  </div>
335
364
  </template>
336
365
 
337
366
  <!-- bottom element - individual settings for every filter type -->
338
367
  <div :class="$style.bottom">
339
368
  <PlAutocomplete
340
- v-if="filter.type === 'patternEquals' || filter.type === 'patternNotEquals'"
341
- v-model="filter.value"
369
+ v-if="props.filter.type === 'patternEquals' || props.filter.type === 'patternNotEquals'"
370
+ :model-value="props.filter.value"
342
371
  :options-search="
343
372
  (str, type) => getSuggestOptionsFn(columnAsSourceAndFixedAxes.source, type, str)
344
373
  "
345
374
  :clearable="true"
346
375
  group-position="bottom"
376
+ @update:model-value="(v) => updateFilterProp('value', v)"
347
377
  />
348
378
  <PlAutocompleteMulti
349
- v-if="filter.type === 'inSet' || filter.type === 'notInSet'"
350
- v-model="filter.value"
379
+ v-if="props.filter.type === 'inSet' || props.filter.type === 'notInSet'"
380
+ :model-value="props.filter.value"
351
381
  :options-search="
352
382
  (str, type) => getMultiSuggestOptionsFn(columnAsSourceAndFixedAxes.source, type, str)
353
383
  "
354
384
  :disabled="inconsistentSourceSelected"
355
385
  group-position="bottom"
386
+ @update:model-value="(v) => updateFilterProp('value', v)"
387
+ />
388
+ <PlNumberField
389
+ v-if="isNumericFilter(props.filter)"
390
+ :model-value="props.filter.x"
391
+ group-position="bottom"
392
+ @update:model-value="(v) => updateFilterProp('x', v)"
393
+ />
394
+ <PlNumberField
395
+ v-if="isPositionFilter(props.filter)"
396
+ :model-value="props.filter.n"
397
+ group-position="bottom"
398
+ @update:model-value="(v) => updateFilterProp('n', v)"
356
399
  />
357
- <PlNumberField v-if="isNumericFilter(filter)" v-model="filter.x" group-position="bottom" />
358
- <PlNumberField v-if="isPositionFilter(filter)" v-model="filter.n" group-position="bottom" />
359
400
  <PlTextField
360
401
  v-if="
361
- filter.type === 'patternContainSubsequence' ||
362
- filter.type === 'patternNotContainSubsequence'
402
+ props.filter.type === 'patternContainSubsequence' ||
403
+ props.filter.type === 'patternNotContainSubsequence'
363
404
  "
364
- v-model="filter.value"
405
+ :model-value="props.filter.value"
365
406
  placeholder="Substring"
366
407
  group-position="bottom"
408
+ @update:model-value="(v) => updateFilterProp('value', v)"
367
409
  />
368
410
  <PlTextField
369
- v-if="filter.type === 'patternMatchesRegularExpression'"
370
- v-model="filter.value"
411
+ v-if="props.filter.type === 'patternMatchesRegularExpression'"
412
+ :model-value="props.filter.value"
371
413
  :error="stringMatchesError ? 'Regular expression is not valid' : undefined"
372
414
  placeholder="Regular expression"
373
415
  group-position="bottom"
416
+ @update:model-value="(v) => updateFilterProp('value', v)"
374
417
  />
375
418
  <PlDropdown
376
- v-if="filter.type === 'patternFuzzyContainSubsequence'"
377
- v-model="filter.wildcard"
419
+ v-if="props.filter.type === 'patternFuzzyContainSubsequence'"
420
+ :model-value="props.filter.wildcard"
378
421
  clearable
379
422
  placeholder="Wildcard value"
380
423
  :options="wildcardOptions"
381
424
  group-position="bottom"
425
+ @update:model-value="(v) => updateFilterProp('wildcard', v)"
382
426
  />
383
427
  </div>
384
428
  </div>
385
- <OperandButton :active="operand" :disabled="isLast" :on-select="onChangeOperand" />
429
+ <OperandButton :active="operand" :disabled="isLast" @select="onChangeOperand" />
386
430
  </template>
387
431
 
388
432
  <style module>