@platforma-sdk/ui-vue 1.68.8 → 1.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/.turbo/turbo-build.log +13 -13
  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 +22 -0
  6. package/dist/components/PlAgDataTable/sources/table-source-v2.js +3 -3
  7. package/dist/components/PlAgDataTable/sources/table-source-v2.js.map +1 -1
  8. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.js.map +1 -1
  9. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.style.js +5 -1
  10. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.style.js.map +1 -1
  11. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue.css +1 -1
  12. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue.d.ts.map +1 -1
  13. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js +40 -23
  14. package/dist/components/PlAgGridColumnManager/PlAgGridColumnManager.vue2.js.map +1 -1
  15. package/dist/components/PlAnnotations/components/PlAnnotations.vue2.js.map +1 -1
  16. package/dist/components/PlDatasetSelector/PlDatasetSelector.js +1 -1
  17. package/dist/components/PlDatasetSelector/PlDatasetSelector.js.map +1 -1
  18. package/dist/components/PlDatasetSelector/PlDatasetSelector.style.css +1 -1
  19. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue.d.ts +9 -19
  20. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue.d.ts.map +1 -1
  21. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js +22 -23
  22. package/dist/components/PlDatasetSelector/PlDatasetSelector.vue2.js.map +1 -1
  23. package/package.json +6 -6
  24. package/src/components/PlAgDataTable/sources/table-source-v2.ts +10 -6
  25. package/src/components/PlAgGridColumnManager/PlAgGridColumnManager.vue +51 -1
  26. package/src/components/PlDatasetSelector/PlDatasetSelector.vue +24 -23
  27. package/src/components/PlDatasetSelector/__tests__/PlDatasetSelector.jsdomtest.ts +70 -72
@@ -1 +1 @@
1
- .pl-dataset-selector[data-v-b52c3499]{flex-direction:column;gap:12px;display:flex}
1
+ .pl-dataset-selector[data-v-95f2adf4]{flex-direction:column;gap:12px;display:flex}
@@ -1,17 +1,17 @@
1
- import { DatasetOption, PlRef, PrimaryRef } from '@platforma-sdk/model';
1
+ import { DatasetOption, DatasetSelection } from '@platforma-sdk/model';
2
2
  /**
3
- * Select a dataset and (optionally) a filter column, emitting a `PrimaryRef`.
3
+ * Select a dataset and (optionally) a filter column, emitting a {@link DatasetSelection}.
4
4
  *
5
5
  * Behaves like {@link PlDropdownRef} when none of the offered datasets carry
6
6
  * filter options. When the selected dataset has compatible filters, a second
7
7
  * dropdown appears with the filters plus a "No filter" entry.
8
8
  *
9
- * Accepts `PrimaryRef | PlRef | undefined` as `modelValue` (a plain `PlRef`
10
- * is treated as an unfiltered dataset), but always emits `PrimaryRef`
11
- * (or `undefined` when cleared).
9
+ * The emitted value bundles the user's pick (`primary`) with the auto-attached
10
+ * `enrichments` payload from the matching `DatasetOption`. Enrichments are
11
+ * opaque to the UI — block authors unbundle them inside their args resolver.
12
12
  */
13
13
  declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
14
- modelValue?: PrimaryRef | PlRef | undefined;
14
+ modelValue?: DatasetSelection | undefined;
15
15
  } & {
16
16
  /** Available datasets, each optionally carrying compatible filter choices. */
17
17
  options?: Readonly<DatasetOption[]>;
@@ -38,14 +38,9 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
38
38
  /** Disable all interaction. */
39
39
  disabled?: boolean;
40
40
  }, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
41
- "update:modelValue": (value: PrimaryRef | Readonly<{
42
- __isRef: true;
43
- blockId: string;
44
- name: string;
45
- requireEnrichments?: true | undefined;
46
- }> | undefined) => any;
41
+ "update:modelValue": (value: DatasetSelection | undefined) => any;
47
42
  }, string, import('vue').PublicProps, Readonly<{
48
- modelValue?: PrimaryRef | PlRef | undefined;
43
+ modelValue?: DatasetSelection | undefined;
49
44
  } & {
50
45
  /** Available datasets, each optionally carrying compatible filter choices. */
51
46
  options?: Readonly<DatasetOption[]>;
@@ -72,12 +67,7 @@ declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<{
72
67
  /** Disable all interaction. */
73
68
  disabled?: boolean;
74
69
  }> & Readonly<{
75
- "onUpdate:modelValue"?: ((value: PrimaryRef | Readonly<{
76
- __isRef: true;
77
- blockId: string;
78
- name: string;
79
- requireEnrichments?: true | undefined;
80
- }> | undefined) => any) | undefined;
70
+ "onUpdate:modelValue"?: ((value: DatasetSelection | undefined) => any) | undefined;
81
71
  }>, {
82
72
  error: undefined;
83
73
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"PlDatasetSelector.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlDatasetSelector/PlDatasetSelector.vue"],"names":[],"mappings":"AAsKA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAO7E;;;;;;;;;;GAUG;;iBA0HU,UAAU,GAAG,KAAK,GAAG,SAAS;;IA7GvC,8EAA8E;cACpE,QAAQ,CAAC,aAAa,EAAE,CAAC;IACnC,wCAAwC;YAChC,MAAM;IACd,6EAA6E;aACpE,MAAM;IACf,gEAAgE;2BACzC,MAAM;IAC7B,0DAA0D;YAClD,OAAO;IACf,+CAA+C;kBACjC,MAAM;IACpB,uCAAuC;kBACzB,MAAM;IACpB,2CAA2C;wBACvB,MAAM;IAC1B,sEAAsE;oBACtD,MAAM;IACtB,mDAAmD;gBACvC,OAAO;IACnB,6CAA6C;eAClC,OAAO;IAClB,+BAA+B;eACpB,OAAO;;;;;;;;;iBAsFT,UAAU,GAAG,KAAK,GAAG,SAAS;;IA7GvC,8EAA8E;cACpE,QAAQ,CAAC,aAAa,EAAE,CAAC;IACnC,wCAAwC;YAChC,MAAM;IACd,6EAA6E;aACpE,MAAM;IACf,gEAAgE;2BACzC,MAAM;IAC7B,0DAA0D;YAClD,OAAO;IACf,+CAA+C;kBACjC,MAAM;IACpB,uCAAuC;kBACzB,MAAM;IACpB,2CAA2C;wBACvB,MAAM;IAC1B,sEAAsE;oBACtD,MAAM;IACtB,mDAAmD;gBACvC,OAAO;IACnB,6CAA6C;eAClC,OAAO;IAClB,+BAA+B;eACpB,OAAO;;;;;;;;;;WApBV,MAAM;iBAQA,MAAM;aAVV,QAAQ,CAAC,aAAa,EAAE,CAAC;YAI1B,MAAM;0BAEQ,MAAM;eAYjB,OAAO;cAER,OAAO;cAEP,OAAO;iBAVJ,MAAM;uBAEA,MAAM;mBAEV,MAAM;;cA3Bd,MAAM,OAAO;;cAAb,MAAM,OAAO;;AAFzB,wBAmQK;AAcL,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"PlDatasetSelector.vue.d.ts","sourceRoot":"","sources":["../../../src/components/PlDatasetSelector/PlDatasetSelector.vue"],"names":[],"mappings":"AAuKA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAS,MAAM,sBAAsB,CAAC;AAOnF;;;;;;;;;;GAUG;;iBA2HU,gBAAgB,GAAG,SAAS;;IAlHrC,8EAA8E;cACpE,QAAQ,CAAC,aAAa,EAAE,CAAC;IACnC,wCAAwC;YAChC,MAAM;IACd,6EAA6E;aACpE,MAAM;IACf,gEAAgE;2BACzC,MAAM;IAC7B,0DAA0D;YAClD,OAAO;IACf,+CAA+C;kBACjC,MAAM;IACpB,uCAAuC;kBACzB,MAAM;IACpB,2CAA2C;wBACvB,MAAM;IAC1B,sEAAsE;oBACtD,MAAM;IACtB,mDAAmD;gBACvC,OAAO;IACnB,6CAA6C;eAClC,OAAO;IAClB,+BAA+B;eACpB,OAAO;;;;iBA2FT,gBAAgB,GAAG,SAAS;;IAlHrC,8EAA8E;cACpE,QAAQ,CAAC,aAAa,EAAE,CAAC;IACnC,wCAAwC;YAChC,MAAM;IACd,6EAA6E;aACpE,MAAM;IACf,gEAAgE;2BACzC,MAAM;IAC7B,0DAA0D;YAClD,OAAO;IACf,+CAA+C;kBACjC,MAAM;IACpB,uCAAuC;kBACzB,MAAM;IACpB,2CAA2C;wBACvB,MAAM;IAC1B,sEAAsE;oBACtD,MAAM;IACtB,mDAAmD;gBACvC,OAAO;IACnB,6CAA6C;eAClC,OAAO;IAClB,+BAA+B;eACpB,OAAO;;;;;WApBV,MAAM;iBAQA,MAAM;aAVV,QAAQ,CAAC,aAAa,EAAE,CAAC;YAI1B,MAAM;0BAEQ,MAAM;eAYjB,OAAO;cAER,OAAO;cAEP,OAAO;iBAVJ,MAAM;uBAEA,MAAM;mBAEV,MAAM;;cAvBd,MAAM,OAAO;;cAAb,MAAM,OAAO;;AAFzB,wBAqQK;AAcL,KAAK,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IACxC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { computed as e, createBlock as t, createCommentVNode as n, createElementBlock as r, createSlots as i, createVNode as a, defineComponent as o, mergeModels as s, openBlock as c, renderSlot as l, unref as u, useModel as d, useSlots as f, withCtx as p } from "vue";
2
- import { createPrimaryRef as m, isPrimaryRef as h, plRefsEqual as g } from "@platforma-sdk/model";
2
+ import { createDatasetSelection as m, createPrimaryRef as h, plRefsEqual as g } from "@platforma-sdk/model";
3
3
  import { PlDropdown as _, PlDropdownRef as v } from "@milaboratories/uikit";
4
4
  //#region src/components/PlDatasetSelector/PlDatasetSelector.vue?vue&type=script&setup=true&lang.ts
5
5
  var y = { class: "pl-dataset-selector" }, b = /* @__PURE__ */ o({
@@ -32,16 +32,10 @@ var y = { class: "pl-dataset-selector" }, b = /* @__PURE__ */ o({
32
32
  }),
33
33
  emits: ["update:modelValue"],
34
34
  setup(o) {
35
- let s = f(), b = d(o, "modelValue"), x = o, S = e(() => {
36
- let e = b.value;
37
- if (e !== void 0) return h(e) ? e.column : e;
38
- }), C = e(() => {
39
- let e = b.value;
40
- return h(e) ? e.filter : void 0;
41
- }), w = e(() => {
35
+ let s = f(), b = d(o, "modelValue"), x = o, S = e(() => b.value?.primary.column), C = e(() => b.value?.primary.filter), w = e(() => {
42
36
  let e = S.value;
43
- if (e) return x.options?.find((t) => g(t.ref, e, !0));
44
- }), T = e(() => (w.value?.filters?.length ?? 0) > 0), E = e(() => {
37
+ if (e) return x.options?.find((t) => g(t.primary.ref, e, !0));
38
+ }), T = e(() => x.options?.map((e) => e.primary)), E = e(() => (w.value?.filters?.length ?? 0) > 0), D = e(() => {
45
39
  let e = w.value?.filters;
46
40
  return e ? [{
47
41
  label: x.noFilterLabel,
@@ -50,20 +44,25 @@ var y = { class: "pl-dataset-selector" }, b = /* @__PURE__ */ o({
50
44
  label: e.label,
51
45
  value: e.ref
52
46
  }))] : [];
53
- }), D = e(() => C.value ?? null);
54
- function O(e, t) {
55
- b.value = e === void 0 ? void 0 : m(e, t);
56
- }
57
- function k(e) {
58
- O(e, void 0);
47
+ }), O = e(() => C.value ?? null);
48
+ function k(e, t) {
49
+ if (e === void 0) {
50
+ b.value = void 0;
51
+ return;
52
+ }
53
+ let n = x.options?.find((t) => g(t.primary.ref, e, !0));
54
+ b.value = m(h(e, t), n?.enrichments);
59
55
  }
60
56
  function A(e) {
57
+ k(e, void 0);
58
+ }
59
+ function j(e) {
61
60
  let t = S.value;
62
- t && O(t, e ?? void 0);
61
+ t && k(t, e ?? void 0);
63
62
  }
64
63
  return (e, d) => (c(), r("div", y, [a(u(v), {
65
64
  "model-value": S.value,
66
- options: o.options,
65
+ options: T.value,
67
66
  label: o.label,
68
67
  helper: o.helper,
69
68
  "loading-options-helper": o.loadingOptionsHelper,
@@ -72,7 +71,7 @@ var y = { class: "pl-dataset-selector" }, b = /* @__PURE__ */ o({
72
71
  clearable: o.clearable,
73
72
  required: o.required,
74
73
  disabled: o.disabled,
75
- "onUpdate:modelValue": k
74
+ "onUpdate:modelValue": A
76
75
  }, i({ _: 2 }, [s.tooltip ? {
77
76
  name: "tooltip",
78
77
  fn: p(() => [l(e.$slots, "tooltip", {}, void 0, !0)]),
@@ -88,14 +87,14 @@ var y = { class: "pl-dataset-selector" }, b = /* @__PURE__ */ o({
88
87
  "clearable",
89
88
  "required",
90
89
  "disabled"
91
- ]), T.value ? (c(), t(u(_), {
90
+ ]), E.value ? (c(), t(u(_), {
92
91
  key: 0,
93
- "model-value": D.value,
94
- options: E.value,
92
+ "model-value": O.value,
93
+ options: D.value,
95
94
  label: o.filterLabel,
96
95
  placeholder: o.filterPlaceholder,
97
96
  disabled: o.disabled,
98
- "onUpdate:modelValue": A
97
+ "onUpdate:modelValue": j
99
98
  }, null, 8, [
100
99
  "model-value",
101
100
  "options",
@@ -1 +1 @@
1
- {"version":3,"file":"PlDatasetSelector.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlDatasetSelector/PlDatasetSelector.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Select a dataset and (optionally) a filter column, emitting a `PrimaryRef`.\n *\n * Behaves like {@link PlDropdownRef} when none of the offered datasets carry\n * filter options. When the selected dataset has compatible filters, a second\n * dropdown appears with the filters plus a \"No filter\" entry.\n *\n * Accepts `PrimaryRef | PlRef | undefined` as `modelValue` (a plain `PlRef`\n * is treated as an unfiltered dataset), but always emits `PrimaryRef`\n * (or `undefined` when cleared).\n */\nexport default {\n name: \"PlDatasetSelector\",\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport type { DatasetOption, PlRef, PrimaryRef } from \"@platforma-sdk/model\";\nimport { createPrimaryRef, isPrimaryRef, plRefsEqual } from \"@platforma-sdk/model\";\nimport type { ListOption } from \"@milaboratories/uikit\";\nimport { PlDropdown, PlDropdownRef } from \"@milaboratories/uikit\";\nimport { computed } from \"vue\";\n\nconst slots = defineSlots<{\n tooltip?: () => unknown;\n}>();\n\n/**\n * v-model value. Accepts `PrimaryRef`, plain `PlRef` (treated as unfiltered),\n * or `undefined`. Writes always emit `PrimaryRef` or `undefined`.\n */\nconst model = defineModel<PrimaryRef | PlRef | undefined>();\n\nconst props = withDefaults(\n defineProps<{\n /** Available datasets, each optionally carrying compatible filter choices. */\n options?: Readonly<DatasetOption[]>;\n /** Label above the dataset dropdown. */\n label?: string;\n /** Helper text below the dataset dropdown (shown when there is no error). */\n helper?: string;\n /** Helper text shown while `options` is undefined (loading). */\n loadingOptionsHelper?: string;\n /** Error message displayed below the dataset dropdown. */\n error?: unknown;\n /** Placeholder when no dataset is selected. */\n placeholder?: string;\n /** Label above the filter dropdown. */\n filterLabel?: string;\n /** Placeholder for the filter dropdown. */\n filterPlaceholder?: string;\n /** Label of the \"no filter\" entry prepended to the filter options. */\n noFilterLabel?: string;\n /** Show a clear button on the dataset dropdown. */\n clearable?: boolean;\n /** Mark the dataset dropdown as required. */\n required?: boolean;\n /** Disable all interaction. */\n disabled?: boolean;\n }>(),\n {\n options: undefined,\n label: undefined,\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n placeholder: \"...\",\n filterLabel: \"\",\n filterPlaceholder: \"...\",\n noFilterLabel: \"No filter\",\n clearable: false,\n required: false,\n disabled: false,\n },\n);\n\nconst selectedDataset = computed<PlRef | undefined>(() => {\n const v = model.value;\n if (v === undefined) return undefined;\n return isPrimaryRef(v) ? v.column : v;\n});\n\nconst selectedFilter = computed<PlRef | undefined>(() => {\n const v = model.value;\n return isPrimaryRef(v) ? v.filter : undefined;\n});\n\nconst currentDatasetOption = computed<DatasetOption | undefined>(() => {\n const dataset = selectedDataset.value;\n if (!dataset) return undefined;\n return props.options?.find((o) => plRefsEqual(o.ref, dataset, true));\n});\n\nconst hasFilters = computed(() => (currentDatasetOption.value?.filters?.length ?? 0) > 0);\n\n/**\n * Filter dropdown options. The first entry (`null`) is the \"No filter\" choice —\n * null distinguishes it from `undefined` (dropdown clear button, disabled here).\n */\nconst filterOptions = computed<ListOption<PlRef | null>[]>(() => {\n const filters = currentDatasetOption.value?.filters;\n if (!filters) return [];\n return [\n { label: props.noFilterLabel, value: null } as ListOption<PlRef | null>,\n ...filters.map((f) => ({ label: f.label, value: f.ref }) as ListOption<PlRef | null>),\n ];\n});\n\nconst filterValue = computed<PlRef | null>(() => selectedFilter.value ?? null);\n\nfunction emitValue(dataset: PlRef | undefined, filter: PlRef | undefined) {\n model.value = dataset === undefined ? undefined : createPrimaryRef(dataset, filter);\n}\n\nfunction onDatasetChange(dataset: PlRef | undefined) {\n emitValue(dataset, undefined);\n}\n\nfunction onFilterChange(value: PlRef | null | undefined) {\n const dataset = selectedDataset.value;\n if (!dataset) return;\n emitValue(dataset, value ?? undefined);\n}\n</script>\n\n<template>\n <div class=\"pl-dataset-selector\">\n <PlDropdownRef\n :model-value=\"selectedDataset\"\n :options=\"options\"\n :label=\"label\"\n :helper=\"helper\"\n :loading-options-helper=\"loadingOptionsHelper\"\n :error=\"error\"\n :placeholder=\"placeholder\"\n :clearable=\"clearable\"\n :required=\"required\"\n :disabled=\"disabled\"\n @update:model-value=\"onDatasetChange\"\n >\n <template v-if=\"slots.tooltip\" #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlDropdownRef>\n <PlDropdown\n v-if=\"hasFilters\"\n :model-value=\"filterValue\"\n :options=\"filterOptions\"\n :label=\"filterLabel\"\n :placeholder=\"filterPlaceholder\"\n :disabled=\"disabled\"\n @update:model-value=\"onFilterChange\"\n />\n </div>\n</template>\n\n<style scoped>\n.pl-dataset-selector {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n</style>\n"],"mappings":";;;;;CAaE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWR,IAAM,IAAQ,GAEV,EAME,IAAQ,EAA2C,GAAA,aAAE,EAErD,IAAQ,GA2CR,IAAkB,QAAkC;GACxD,IAAM,IAAI,EAAM;AACZ,aAAM,KAAA,EACV,QAAO,EAAa,EAAE,GAAG,EAAE,SAAS;IACpC,EAEI,IAAiB,QAAkC;GACvD,IAAM,IAAI,EAAM;AAChB,UAAO,EAAa,EAAE,GAAG,EAAE,SAAS,KAAA;IACpC,EAEI,IAAuB,QAA0C;GACrE,IAAM,IAAU,EAAgB;AAC3B,SACL,QAAO,EAAM,SAAS,MAAM,MAAM,EAAY,EAAE,KAAK,GAAS,GAAK,CAAC;IACpE,EAEI,IAAa,SAAgB,EAAqB,OAAO,SAAS,UAAU,KAAK,EAAE,EAMnF,IAAgB,QAA2C;GAC/D,IAAM,IAAU,EAAqB,OAAO;AAE5C,UADK,IACE,CACL;IAAE,OAAO,EAAM;IAAe,OAAO;IAAM,EAC3C,GAAG,EAAQ,KAAK,OAAO;IAAE,OAAO,EAAE;IAAO,OAAO,EAAE;IAAK,EAA8B,CACtF,GAJoB,EAAE;IAKvB,EAEI,IAAc,QAA6B,EAAe,SAAS,KAAK;EAE9E,SAAS,EAAU,GAA4B,GAA2B;AACxE,KAAM,QAAQ,MAAY,KAAA,IAAY,KAAA,IAAY,EAAiB,GAAS,EAAO;;EAGrF,SAAS,EAAgB,GAA4B;AACnD,KAAU,GAAS,KAAA,EAAU;;EAG/B,SAAS,EAAe,GAAiC;GACvD,IAAM,IAAU,EAAgB;AAC3B,QACL,EAAU,GAAS,KAAS,KAAA,EAAU;;yBAKtC,EA2BM,OA3BN,GA2BM,CA1BJ,EAgBgB,EAAA,EAAA,EAAA;GAfb,eAAa,EAAA;GACb,SAAS,EAAA;GACT,OAAO,EAAA;GACP,QAAQ,EAAA;GACR,0BAAwB,EAAA;GACxB,OAAO,EAAA;GACP,aAAa,EAAA;GACb,WAAW,EAAA;GACX,UAAU,EAAA;GACV,UAAU,EAAA;GACV,uBAAoB;kBAEL,EAAM,UAAA;SAAU;eACP,CAAvB,EAAuB,EAAA,QAAA,WAAA,EAAA,EAAA,KAAA,GAAA,GAAA,CAAA,CAAA;;;;;;;;;;;;;MAInB,EAAA,SAAA,GAAA,EADR,EAQE,EAAA,EAAA,EAAA;;GANC,eAAa,EAAA;GACb,SAAS,EAAA;GACT,OAAO,EAAA;GACP,aAAa,EAAA;GACb,UAAU,EAAA;GACV,uBAAoB"}
1
+ {"version":3,"file":"PlDatasetSelector.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlDatasetSelector/PlDatasetSelector.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Select a dataset and (optionally) a filter column, emitting a {@link DatasetSelection}.\n *\n * Behaves like {@link PlDropdownRef} when none of the offered datasets carry\n * filter options. When the selected dataset has compatible filters, a second\n * dropdown appears with the filters plus a \"No filter\" entry.\n *\n * The emitted value bundles the user's pick (`primary`) with the auto-attached\n * `enrichments` payload from the matching `DatasetOption`. Enrichments are\n * opaque to the UI block authors unbundle them inside their args resolver.\n */\nexport default {\n name: \"PlDatasetSelector\",\n};\n</script>\n\n<script lang=\"ts\" setup>\nimport type { DatasetOption, DatasetSelection, PlRef } from \"@platforma-sdk/model\";\nimport { createDatasetSelection, createPrimaryRef, plRefsEqual } from \"@platforma-sdk/model\";\nimport type { ListOption } from \"@milaboratories/uikit\";\nimport { PlDropdown, PlDropdownRef } from \"@milaboratories/uikit\";\nimport { computed } from \"vue\";\n\nconst slots = defineSlots<{\n tooltip?: () => unknown;\n}>();\n\nconst model = defineModel<DatasetSelection | undefined>();\n\nconst props = withDefaults(\n defineProps<{\n /** Available datasets, each optionally carrying compatible filter choices. */\n options?: Readonly<DatasetOption[]>;\n /** Label above the dataset dropdown. */\n label?: string;\n /** Helper text below the dataset dropdown (shown when there is no error). */\n helper?: string;\n /** Helper text shown while `options` is undefined (loading). */\n loadingOptionsHelper?: string;\n /** Error message displayed below the dataset dropdown. */\n error?: unknown;\n /** Placeholder when no dataset is selected. */\n placeholder?: string;\n /** Label above the filter dropdown. */\n filterLabel?: string;\n /** Placeholder for the filter dropdown. */\n filterPlaceholder?: string;\n /** Label of the \"no filter\" entry prepended to the filter options. */\n noFilterLabel?: string;\n /** Show a clear button on the dataset dropdown. */\n clearable?: boolean;\n /** Mark the dataset dropdown as required. */\n required?: boolean;\n /** Disable all interaction. */\n disabled?: boolean;\n }>(),\n {\n options: undefined,\n label: undefined,\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n placeholder: \"...\",\n filterLabel: \"\",\n filterPlaceholder: \"...\",\n noFilterLabel: \"No filter\",\n clearable: false,\n required: false,\n disabled: false,\n },\n);\n\nconst selectedDataset = computed<PlRef | undefined>(() => model.value?.primary.column);\n\nconst selectedFilter = computed<PlRef | undefined>(() => model.value?.primary.filter);\n\nconst currentDatasetOption = computed<DatasetOption | undefined>(() => {\n const dataset = selectedDataset.value;\n if (!dataset) return undefined;\n return props.options?.find((o) => plRefsEqual(o.primary.ref, dataset, true));\n});\n\n// PlDropdownRef expects `Option[]`; project the primary out of each entry.\nconst primaryOptions = computed<readonly { ref: PlRef; label: string }[] | undefined>(() =>\n props.options?.map((o) => o.primary),\n);\n\nconst hasFilters = computed(() => (currentDatasetOption.value?.filters?.length ?? 0) > 0);\n\n/**\n * Filter dropdown options. The first entry (`null`) is the \"No filter\" choice —\n * null distinguishes it from `undefined` (dropdown clear button, disabled here).\n */\nconst filterOptions = computed<ListOption<PlRef | null>[]>(() => {\n const filters = currentDatasetOption.value?.filters;\n if (!filters) return [];\n return [\n { label: props.noFilterLabel, value: null } as ListOption<PlRef | null>,\n ...filters.map((f) => ({ label: f.label, value: f.ref }) as ListOption<PlRef | null>),\n ];\n});\n\nconst filterValue = computed<PlRef | null>(() => selectedFilter.value ?? null);\n\nfunction emitValue(dataset: PlRef | undefined, filter: PlRef | undefined) {\n if (dataset === undefined) {\n model.value = undefined;\n return;\n }\n // Resolve from `props.options` directly `currentDatasetOption` may not\n // have recomputed yet when this runs synchronously inside a change handler.\n const option = props.options?.find((o) => plRefsEqual(o.primary.ref, dataset, true));\n model.value = createDatasetSelection(createPrimaryRef(dataset, filter), option?.enrichments);\n}\n\nfunction onDatasetChange(dataset: PlRef | undefined) {\n emitValue(dataset, undefined);\n}\n\nfunction onFilterChange(value: PlRef | null | undefined) {\n const dataset = selectedDataset.value;\n if (!dataset) return;\n emitValue(dataset, value ?? undefined);\n}\n</script>\n\n<template>\n <div class=\"pl-dataset-selector\">\n <PlDropdownRef\n :model-value=\"selectedDataset\"\n :options=\"primaryOptions\"\n :label=\"label\"\n :helper=\"helper\"\n :loading-options-helper=\"loadingOptionsHelper\"\n :error=\"error\"\n :placeholder=\"placeholder\"\n :clearable=\"clearable\"\n :required=\"required\"\n :disabled=\"disabled\"\n @update:model-value=\"onDatasetChange\"\n >\n <template v-if=\"slots.tooltip\" #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlDropdownRef>\n <PlDropdown\n v-if=\"hasFilters\"\n :model-value=\"filterValue\"\n :options=\"filterOptions\"\n :label=\"filterLabel\"\n :placeholder=\"filterPlaceholder\"\n :disabled=\"disabled\"\n @update:model-value=\"onFilterChange\"\n />\n </div>\n</template>\n\n<style scoped>\n.pl-dataset-selector {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n</style>\n"],"mappings":";;;;;CAaE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWR,IAAM,IAAQ,GAEV,EAEE,IAAQ,EAAyC,GAAA,aAAE,EAEnD,IAAQ,GA2CR,IAAkB,QAAkC,EAAM,OAAO,QAAQ,OAAO,EAEhF,IAAiB,QAAkC,EAAM,OAAO,QAAQ,OAAO,EAE/E,IAAuB,QAA0C;GACrE,IAAM,IAAU,EAAgB;AAC3B,SACL,QAAO,EAAM,SAAS,MAAM,MAAM,EAAY,EAAE,QAAQ,KAAK,GAAS,GAAK,CAAC;IAC5E,EAGI,IAAiB,QACrB,EAAM,SAAS,KAAK,MAAM,EAAE,QAAQ,CACrC,EAEK,IAAa,SAAgB,EAAqB,OAAO,SAAS,UAAU,KAAK,EAAE,EAMnF,IAAgB,QAA2C;GAC/D,IAAM,IAAU,EAAqB,OAAO;AAE5C,UADK,IACE,CACL;IAAE,OAAO,EAAM;IAAe,OAAO;IAAM,EAC3C,GAAG,EAAQ,KAAK,OAAO;IAAE,OAAO,EAAE;IAAO,OAAO,EAAE;IAAK,EAA8B,CACtF,GAJoB,EAAE;IAKvB,EAEI,IAAc,QAA6B,EAAe,SAAS,KAAK;EAE9E,SAAS,EAAU,GAA4B,GAA2B;AACxE,OAAI,MAAY,KAAA,GAAW;AACzB,MAAM,QAAQ,KAAA;AACd;;GAIF,IAAM,IAAS,EAAM,SAAS,MAAM,MAAM,EAAY,EAAE,QAAQ,KAAK,GAAS,GAAK,CAAC;AACpF,KAAM,QAAQ,EAAuB,EAAiB,GAAS,EAAO,EAAE,GAAQ,YAAY;;EAG9F,SAAS,EAAgB,GAA4B;AACnD,KAAU,GAAS,KAAA,EAAU;;EAG/B,SAAS,EAAe,GAAiC;GACvD,IAAM,IAAU,EAAgB;AAC3B,QACL,EAAU,GAAS,KAAS,KAAA,EAAU;;yBAKtC,EA2BM,OA3BN,GA2BM,CA1BJ,EAgBgB,EAAA,EAAA,EAAA;GAfb,eAAa,EAAA;GACb,SAAS,EAAA;GACT,OAAO,EAAA;GACP,QAAQ,EAAA;GACR,0BAAwB,EAAA;GACxB,OAAO,EAAA;GACP,aAAa,EAAA;GACb,WAAW,EAAA;GACX,UAAU,EAAA;GACV,UAAU,EAAA;GACV,uBAAoB;kBAEL,EAAM,UAAA;SAAU;eACP,CAAvB,EAAuB,EAAA,QAAA,WAAA,EAAA,EAAA,KAAA,GAAA,GAAA,CAAA,CAAA;;;;;;;;;;;;;MAInB,EAAA,SAAA,GAAA,EADR,EAQE,EAAA,EAAA,EAAA;;GANC,eAAa,EAAA;GACb,SAAS,EAAA;GACT,OAAO,EAAA;GACP,aAAa,EAAA;GACb,UAAU,EAAA;GACV,uBAAoB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/ui-vue",
3
- "version": "1.68.8",
3
+ "version": "1.70.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -26,10 +26,10 @@
26
26
  "lru-cache": "^11.2.2",
27
27
  "vue": "^3.5.24",
28
28
  "zod": "~3.25.76",
29
- "@milaboratories/pf-spec-driver": "1.3.6",
30
- "@milaboratories/uikit": "2.12.15",
31
- "@milaboratories/pl-model-common": "1.36.2",
32
- "@platforma-sdk/model": "1.68.8"
29
+ "@milaboratories/pf-spec-driver": "1.3.7",
30
+ "@milaboratories/pl-model-common": "1.37.0",
31
+ "@platforma-sdk/model": "1.70.0",
32
+ "@milaboratories/uikit": "2.13.1"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@faker-js/faker": "^9.2.0",
@@ -45,9 +45,9 @@
45
45
  "typescript": "~5.9.3",
46
46
  "vite": "^8.0.6",
47
47
  "vitest": "^4.1.3",
48
- "@milaboratories/helpers": "1.14.1",
49
48
  "@milaboratories/build-configs": "2.0.0",
50
49
  "@milaboratories/ts-builder": "1.3.2",
50
+ "@milaboratories/helpers": "1.14.1",
51
51
  "@milaboratories/ts-configs": "1.2.3"
52
52
  },
53
53
  "scripts": {
@@ -126,7 +126,7 @@ export async function calculateGridOptions({
126
126
 
127
127
  // displayable column indices ordered: axes first, then columns by OrderPriority
128
128
  const fields = sortIndicesByTypeAndPriority(
129
- selectDisplayableIndices(tableSpecs, isPartitionedAxis),
129
+ selectDisplayableIndices(tableSpecs, isPartitionedAxis, getLabelColumnIndex),
130
130
  tableSpecs,
131
131
  );
132
132
 
@@ -337,8 +337,6 @@ export function makeColDef(
337
337
  };
338
338
  }
339
339
 
340
- type LabelColumnLookup = (axisId: AxisId) => number;
341
-
342
340
  /** Build index mapping from full tableSpecs to their position in visibleTableSpecs (missing → -1). */
343
341
  function buildSpecsToVisibleSpecsMapping(
344
342
  tableSpecs: PTableColumnSpec[],
@@ -370,7 +368,7 @@ function createPartitionedAxisPredicate(sheets: PlDataTableSheet[]): (axisId: Ax
370
368
  function collectLabelColumnsByAxis(
371
369
  tableSpecs: PTableColumnSpec[],
372
370
  isPartitionedAxis: (axisId: AxisId) => boolean,
373
- ): LabelColumnLookup {
371
+ ): (axisId: AxisId) => number {
374
372
  const labelColumns: { axisId: AxisId; labelColumnIdx: number }[] = [];
375
373
  for (const [i, spec] of tableSpecs.entries()) {
376
374
  if (spec.type !== "column" || !isLabelColumnSpec(spec.spec)) continue;
@@ -390,16 +388,22 @@ function collectLabelColumnsByAxis(
390
388
  function selectDisplayableIndices(
391
389
  tableSpecs: PTableColumnSpec[],
392
390
  isPartitionedAxis: (axisId: AxisId) => boolean,
391
+ getLabelColumnIndex: (axisId: AxisId) => number,
393
392
  ): number[] {
394
393
  return tableSpecs
395
394
  .entries()
396
395
  .filter(([, spec]) => {
397
396
  switch (spec.type) {
398
397
  case "axis":
399
- return !isColumnHidden(spec.spec) && !isPartitionedAxis(spec.id);
398
+ return (
399
+ // show axis if not hidden or if it has a label column
400
+ (!isColumnHidden(spec.spec) ? true : getLabelColumnIndex(spec.id) > -1) &&
401
+ !isPartitionedAxis(spec.id)
402
+ );
400
403
  case "column":
401
404
  return (
402
405
  !isColumnHidden(spec.spec) &&
406
+ // hide label columns (their labeled axes are shown instead)
403
407
  !isLabelColumnSpec(spec.spec) &&
404
408
  !isLinkerColumnSpec(spec.spec)
405
409
  );
@@ -429,7 +433,7 @@ function sortIndicesByTypeAndPriority(indices: number[], tableSpecs: PTableColum
429
433
  function replaceAxesWithLabelColumns(
430
434
  fields: number[],
431
435
  tableSpecs: PTableColumnSpec[],
432
- getLabelColumnIndex: LabelColumnLookup,
436
+ getLabelColumnIndex: (axisId: AxisId) => number,
433
437
  ): number[] {
434
438
  return fields.map((i) => {
435
439
  const spec = tableSpecs[i];
@@ -1,7 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  import {
3
3
  PlBtnGhost,
4
+ PlBtnSecondary,
4
5
  PlElementList,
6
+ PlIcon24,
5
7
  PlSearchField,
6
8
  PlSlideModal,
7
9
  usePlBlockPageTitleTeleportTarget,
@@ -45,6 +47,24 @@ const { filteredItems, segments } = useFilteredItems({
45
47
  query,
46
48
  getStrings: (item) => [item.label],
47
49
  });
50
+
51
+ const toggleableFilteredItems = computed(() =>
52
+ filteredItems.value.filter((item) => item.id !== PlAgDataTableRowNumberColId),
53
+ );
54
+
55
+ const allFilteredHidden = computed(
56
+ () =>
57
+ toggleableFilteredItems.value.length > 0 &&
58
+ toggleableFilteredItems.value.every((item) => !item.column.isVisible()),
59
+ );
60
+
61
+ const toggleAllFiltered = () => {
62
+ if (props.api.isDestroyed()) return;
63
+ const nextVisible = allFilteredHidden.value;
64
+ const cols = toggleableFilteredItems.value.map((item) => item.column);
65
+ if (cols.length === 0) return;
66
+ props.api.setColumnsVisible(cols, nextVisible);
67
+ };
48
68
  </script>
49
69
 
50
70
  <template>
@@ -54,7 +74,17 @@ const { filteredItems, segments } = useFilteredItems({
54
74
 
55
75
  <PlSlideModal v-model="slideModal" :width="width" close-on-outside-click>
56
76
  <template #title>Manage Columns</template>
57
- <PlSearchField v-model="query" clearable />
77
+ <div :class="$style.searchRow">
78
+ <PlSearchField v-model="query" clearable />
79
+ <PlBtnSecondary
80
+ :class="$style.toggleAllBtn"
81
+ :disabled="toggleableFilteredItems.length === 0"
82
+ @click.stop="toggleAllFiltered"
83
+ >
84
+ <PlIcon24 v-if="allFilteredHidden" name="view-show" />
85
+ <PlIcon24 v-else name="view-hide" />
86
+ </PlBtnSecondary>
87
+ </div>
58
88
  <PlElementList
59
89
  :items="filteredItems"
60
90
  :get-item-key="(item) => item.id"
@@ -101,4 +131,24 @@ const { filteredItems, segments } = useFilteredItems({
101
131
  background-color: var(--color-active-select);
102
132
  border-radius: 2px;
103
133
  }
134
+
135
+ .searchRow {
136
+ display: flex;
137
+ align-items: center;
138
+ gap: 8px;
139
+ }
140
+
141
+ .searchRow > :first-child {
142
+ flex: 1;
143
+ }
144
+
145
+ .toggleAllBtn {
146
+ min-width: unset;
147
+ opacity: 0.2;
148
+ transition: opacity 0.3s;
149
+
150
+ &:hover {
151
+ opacity: 1;
152
+ }
153
+ }
104
154
  </style>
@@ -1,14 +1,14 @@
1
1
  <script lang="ts">
2
2
  /**
3
- * Select a dataset and (optionally) a filter column, emitting a `PrimaryRef`.
3
+ * Select a dataset and (optionally) a filter column, emitting a {@link DatasetSelection}.
4
4
  *
5
5
  * Behaves like {@link PlDropdownRef} when none of the offered datasets carry
6
6
  * filter options. When the selected dataset has compatible filters, a second
7
7
  * dropdown appears with the filters plus a "No filter" entry.
8
8
  *
9
- * Accepts `PrimaryRef | PlRef | undefined` as `modelValue` (a plain `PlRef`
10
- * is treated as an unfiltered dataset), but always emits `PrimaryRef`
11
- * (or `undefined` when cleared).
9
+ * The emitted value bundles the user's pick (`primary`) with the auto-attached
10
+ * `enrichments` payload from the matching `DatasetOption`. Enrichments are
11
+ * opaque to the UI — block authors unbundle them inside their args resolver.
12
12
  */
13
13
  export default {
14
14
  name: "PlDatasetSelector",
@@ -16,8 +16,8 @@ export default {
16
16
  </script>
17
17
 
18
18
  <script lang="ts" setup>
19
- import type { DatasetOption, PlRef, PrimaryRef } from "@platforma-sdk/model";
20
- import { createPrimaryRef, isPrimaryRef, plRefsEqual } from "@platforma-sdk/model";
19
+ import type { DatasetOption, DatasetSelection, PlRef } from "@platforma-sdk/model";
20
+ import { createDatasetSelection, createPrimaryRef, plRefsEqual } from "@platforma-sdk/model";
21
21
  import type { ListOption } from "@milaboratories/uikit";
22
22
  import { PlDropdown, PlDropdownRef } from "@milaboratories/uikit";
23
23
  import { computed } from "vue";
@@ -26,11 +26,7 @@ const slots = defineSlots<{
26
26
  tooltip?: () => unknown;
27
27
  }>();
28
28
 
29
- /**
30
- * v-model value. Accepts `PrimaryRef`, plain `PlRef` (treated as unfiltered),
31
- * or `undefined`. Writes always emit `PrimaryRef` or `undefined`.
32
- */
33
- const model = defineModel<PrimaryRef | PlRef | undefined>();
29
+ const model = defineModel<DatasetSelection | undefined>();
34
30
 
35
31
  const props = withDefaults(
36
32
  defineProps<{
@@ -75,23 +71,21 @@ const props = withDefaults(
75
71
  },
76
72
  );
77
73
 
78
- const selectedDataset = computed<PlRef | undefined>(() => {
79
- const v = model.value;
80
- if (v === undefined) return undefined;
81
- return isPrimaryRef(v) ? v.column : v;
82
- });
74
+ const selectedDataset = computed<PlRef | undefined>(() => model.value?.primary.column);
83
75
 
84
- const selectedFilter = computed<PlRef | undefined>(() => {
85
- const v = model.value;
86
- return isPrimaryRef(v) ? v.filter : undefined;
87
- });
76
+ const selectedFilter = computed<PlRef | undefined>(() => model.value?.primary.filter);
88
77
 
89
78
  const currentDatasetOption = computed<DatasetOption | undefined>(() => {
90
79
  const dataset = selectedDataset.value;
91
80
  if (!dataset) return undefined;
92
- return props.options?.find((o) => plRefsEqual(o.ref, dataset, true));
81
+ return props.options?.find((o) => plRefsEqual(o.primary.ref, dataset, true));
93
82
  });
94
83
 
84
+ // PlDropdownRef expects `Option[]`; project the primary out of each entry.
85
+ const primaryOptions = computed<readonly { ref: PlRef; label: string }[] | undefined>(() =>
86
+ props.options?.map((o) => o.primary),
87
+ );
88
+
95
89
  const hasFilters = computed(() => (currentDatasetOption.value?.filters?.length ?? 0) > 0);
96
90
 
97
91
  /**
@@ -110,7 +104,14 @@ const filterOptions = computed<ListOption<PlRef | null>[]>(() => {
110
104
  const filterValue = computed<PlRef | null>(() => selectedFilter.value ?? null);
111
105
 
112
106
  function emitValue(dataset: PlRef | undefined, filter: PlRef | undefined) {
113
- model.value = dataset === undefined ? undefined : createPrimaryRef(dataset, filter);
107
+ if (dataset === undefined) {
108
+ model.value = undefined;
109
+ return;
110
+ }
111
+ // Resolve from `props.options` directly — `currentDatasetOption` may not
112
+ // have recomputed yet when this runs synchronously inside a change handler.
113
+ const option = props.options?.find((o) => plRefsEqual(o.primary.ref, dataset, true));
114
+ model.value = createDatasetSelection(createPrimaryRef(dataset, filter), option?.enrichments);
114
115
  }
115
116
 
116
117
  function onDatasetChange(dataset: PlRef | undefined) {
@@ -128,7 +129,7 @@ function onFilterChange(value: PlRef | null | undefined) {
128
129
  <div class="pl-dataset-selector">
129
130
  <PlDropdownRef
130
131
  :model-value="selectedDataset"
131
- :options="options"
132
+ :options="primaryOptions"
132
133
  :label="label"
133
134
  :helper="helper"
134
135
  :loading-options-helper="loadingOptionsHelper"