@platforma-sdk/ui-vue 1.79.34 → 1.80.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 (51) hide show
  1. package/.turbo/turbo-build.log +19 -19
  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 +23 -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.map +1 -1
  9. package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js +124 -113
  10. package/dist/components/PlAdvancedFilter/FilterEditor.vue2.js.map +1 -1
  11. package/dist/components/PlAdvancedFilter/types.d.ts +1 -1
  12. package/dist/components/PlAdvancedFilter/types.d.ts.map +1 -1
  13. package/dist/components/PlAdvancedFilter/utils.d.ts +1 -1
  14. package/dist/components/PlAdvancedFilter/utils.d.ts.map +1 -1
  15. package/dist/components/PlAdvancedFilter/utils.js.map +1 -1
  16. package/dist/components/PlAgDataTable/PlAgDataTableV2.js.map +1 -1
  17. package/dist/components/PlAgDataTable/PlAgDataTableV2.style.js.map +1 -1
  18. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue.d.ts.map +1 -1
  19. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js +125 -121
  20. package/dist/components/PlAgDataTable/PlAgDataTableV2.vue2.js.map +1 -1
  21. package/dist/components/PlAgDataTable/compositions/useFilterableColumns.d.ts +4 -4
  22. package/dist/components/PlAgDataTable/sources/table-source-v2.d.ts +40 -4
  23. package/dist/components/PlAgDataTable/sources/table-source-v2.d.ts.map +1 -1
  24. package/dist/components/PlAgDataTable/sources/table-source-v2.js +91 -56
  25. package/dist/components/PlAgDataTable/sources/table-source-v2.js.map +1 -1
  26. package/dist/components/PlAgDataTable/sources/table-state-v2.d.ts.map +1 -1
  27. package/dist/components/PlAgDataTable/sources/table-state-v2.js +64 -64
  28. package/dist/components/PlAgDataTable/sources/table-state-v2.js.map +1 -1
  29. package/dist/components/PlAgDataTable/sources/value-rendering.d.ts +3 -3
  30. package/dist/components/PlAgDataTable/sources/value-rendering.d.ts.map +1 -1
  31. package/dist/components/PlAgDataTable/sources/value-rendering.js +12 -12
  32. package/dist/components/PlAgDataTable/sources/value-rendering.js.map +1 -1
  33. package/dist/components/PlTableFilters/PlTableFiltersV2.js.map +1 -1
  34. package/dist/components/PlTableFilters/PlTableFiltersV2.style.js.map +1 -1
  35. package/dist/components/PlTableFilters/PlTableFiltersV2.vue.d.ts.map +1 -1
  36. package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js +42 -45
  37. package/dist/components/PlTableFilters/PlTableFiltersV2.vue2.js.map +1 -1
  38. package/dist/internal/service_factories.d.ts +4 -3
  39. package/dist/internal/service_factories.d.ts.map +1 -1
  40. package/dist/internal/service_factories.js +6 -4
  41. package/dist/internal/service_factories.js.map +1 -1
  42. package/package.json +8 -7
  43. package/src/components/PlAdvancedFilter/FilterEditor.vue +39 -10
  44. package/src/components/PlAdvancedFilter/types.ts +3 -2
  45. package/src/components/PlAdvancedFilter/utils.ts +1 -1
  46. package/src/components/PlAgDataTable/PlAgDataTableV2.vue +21 -5
  47. package/src/components/PlAgDataTable/sources/table-source-v2.ts +132 -31
  48. package/src/components/PlAgDataTable/sources/table-state-v2.ts +5 -7
  49. package/src/components/PlAgDataTable/sources/value-rendering.ts +7 -7
  50. package/src/components/PlTableFilters/PlTableFiltersV2.vue +9 -13
  51. package/src/internal/service_factories.ts +2 -0
@@ -1,11 +1,11 @@
1
1
  import e from "../PlAdvancedFilter/PlAdvancedFilter.js";
2
2
  import "../PlAdvancedFilter/index.js";
3
3
  import { Fragment as t, Teleport as n, computed as r, createBlock as i, createCommentVNode as a, createElementBlock as o, createElementVNode as s, createTextVNode as c, createVNode as l, defineComponent as u, normalizeClass as d, openBlock as f, ref as p, unref as m, withCtx as h, withModifiers as g } from "vue";
4
- import { Annotation as _, Domain as v, canonicalizeJson as y, getPTableColumnId as b, getUniqueSourceValuesWithLabels as x, parseJson as S, readAnnotation as C, readDomain as w } from "@platforma-sdk/model";
5
- import { isFunction as T, isNil as E } from "es-toolkit";
6
- import { PlBtnGhost as D, PlSlideModal as O, usePlBlockPageTitleTeleportTarget as k } from "@milaboratories/uikit";
4
+ import { Annotation as _, Domain as v, extractPObjectId as y, getPTableColumnId as b, getUniqueSourceValuesWithLabels as x, readAnnotation as S, readDomain as C } from "@platforma-sdk/model";
5
+ import { isFunction as w, isNil as T } from "es-toolkit";
6
+ import { PlBtnGhost as E, PlSlideModal as D, usePlBlockPageTitleTeleportTarget as O } from "@milaboratories/uikit";
7
7
  //#region src/components/PlTableFilters/PlTableFiltersV2.vue?vue&type=script&setup=true&lang.ts
8
- var A = { key: 1 }, j = /* @__PURE__ */ u({
8
+ var k = { key: 1 }, A = /* @__PURE__ */ u({
9
9
  __name: "PlTableFiltersV2",
10
10
  props: {
11
11
  columns: {},
@@ -17,29 +17,29 @@ var A = { key: 1 }, j = /* @__PURE__ */ u({
17
17
  onUpdateDefaultFilters: { type: Function }
18
18
  },
19
19
  setup(u) {
20
- let j = u, M = k("PlTableFiltersV2"), N = p(!1), P = r(() => j.filters.filters.length > 0), F = r(() => !E(j.defaultFilters) && j.defaultFilters.filters.length > 0), I = r(() => E(j.defaultFilters) || j.defaultFilters?.filters.length === 0 ? j.filters : {
21
- ...j.filters,
22
- filters: [...j.defaultFilters?.filters ?? [], ...j.filters.filters]
23
- }), L = (e) => {
20
+ let A = u, j = O("PlTableFiltersV2"), M = p(!1), N = r(() => A.filters.filters.length > 0), P = r(() => !T(A.defaultFilters) && A.defaultFilters.filters.length > 0), F = r(() => T(A.defaultFilters) || A.defaultFilters?.filters.length === 0 ? A.filters : {
21
+ ...A.filters,
22
+ filters: [...A.defaultFilters?.filters ?? [], ...A.filters.filters]
23
+ }), I = (e) => {
24
24
  let t = e;
25
- if (E(j.defaultFilters)) return j.onUpdateFilters(t);
25
+ if (T(A.defaultFilters)) return A.onUpdateFilters(t);
26
26
  let [n, ...r] = t.filters;
27
- j.onUpdateFilters({
27
+ A.onUpdateFilters({
28
28
  ...t,
29
29
  filters: r
30
- }), j.onUpdateDefaultFilters?.({
31
- ...j.defaultFilters,
30
+ }), A.onUpdateDefaultFilters?.({
31
+ ...A.defaultFilters,
32
32
  filters: [n]
33
33
  });
34
- }, R = r(() => j.columns.map((e, t) => {
35
- let n = V(e), r = C(e.spec, _.Label)?.trim() ?? `Unlabeled ${e.type} ${t}`, i = w(e.spec, v.Alphabet) ?? C(e.spec, _.Alphabet);
34
+ }, L = r(() => A.columns.map((e, t) => {
35
+ let n = b(e), r = S(e.spec, _.Label)?.trim() ?? `Unlabeled ${e.type} ${t}`, i = C(e.spec, v.Alphabet) ?? S(e.spec, _.Alphabet);
36
36
  return {
37
37
  id: n,
38
38
  label: r,
39
39
  spec: e.spec,
40
40
  alphabet: i ?? void 0
41
41
  };
42
- })), z = [
42
+ })), R = [
43
43
  "isNA",
44
44
  "isNotNA",
45
45
  "greaterThan",
@@ -55,58 +55,55 @@ var A = { key: 1 }, j = /* @__PURE__ */ u({
55
55
  "equal",
56
56
  "notEqual"
57
57
  ];
58
- function B(e) {
59
- if (E(j.pframeHandle)) return console.warn("PFrame handle is not available, cannot fetch suggest options"), [];
60
- let t = e.columnId, n = S(t);
61
- if (n.type !== "column") throw Error("ColumnId should be of type 'column' for suggest options");
62
- return x(j.pframeHandle, {
63
- columnId: n.id,
58
+ function z(e) {
59
+ if (T(A.pframeHandle)) return console.warn("PFrame handle is not available, cannot fetch suggest options"), [];
60
+ let t = e.columnId;
61
+ if (typeof t != "object" || !t || t.type !== "column") throw Error("ColumnId should be of type 'column' for suggest options");
62
+ return x(A.pframeHandle, {
63
+ columnId: y(t.id),
64
64
  axisIdx: e.axisIdx,
65
65
  limit: 100,
66
66
  searchQuery: e.searchType === "label" ? e.searchStr : void 0,
67
67
  searchQueryValue: e.searchType === "value" ? e.searchStr : void 0
68
68
  }).then((e) => e.values);
69
69
  }
70
- function V(e) {
71
- return y(b(e));
72
- }
73
- return (r, u) => (f(), o(t, null, [m(M) ? (f(), i(n, {
70
+ return (r, u) => (f(), o(t, null, [m(j) ? (f(), i(n, {
74
71
  key: 0,
75
- to: m(M)
76
- }, [l(m(D), {
77
- icon: P.value || F.value ? "filter-on" : "filter",
78
- onClick: u[0] ||= g((e) => N.value = !0, ["stop"])
72
+ to: m(j)
73
+ }, [l(m(E), {
74
+ icon: N.value || P.value ? "filter-on" : "filter",
75
+ onClick: u[0] ||= g((e) => M.value = !0, ["stop"])
79
76
  }, {
80
77
  default: h(() => [...u[3] ||= [c(" Filters ", -1)]]),
81
78
  _: 1
82
- }, 8, ["icon"])], 8, ["to"])) : a("", !0), l(m(O), {
83
- modelValue: N.value,
84
- "onUpdate:modelValue": u[2] ||= (e) => N.value = e,
79
+ }, 8, ["icon"])], 8, ["to"])) : a("", !0), l(m(D), {
80
+ modelValue: M.value,
81
+ "onUpdate:modelValue": u[2] ||= (e) => M.value = e,
85
82
  "close-on-outside-click": !1
86
83
  }, {
87
84
  title: h(() => [...u[4] ||= [c("Manage Filters", -1)]]),
88
85
  default: h(() => [s("div", { class: d(r.$style.root) }, [l(m(e), {
89
- filters: I.value,
90
- options: R.value,
91
- "supported-filters": z,
92
- "get-suggest-options": B,
93
- "is-pinned": (e, t) => F.value && t === 0,
94
- "is-removable": (e, t) => F.value ? t > 0 : !0,
95
- "is-draggable": (e, t) => F.value ? t > 0 : !0,
86
+ filters: F.value,
87
+ options: L.value,
88
+ "supported-filters": R,
89
+ "get-suggest-options": z,
90
+ "is-pinned": (e, t) => P.value && t === 0,
91
+ "is-removable": (e, t) => P.value ? t > 0 : !0,
92
+ "is-draggable": (e, t) => P.value ? t > 0 : !0,
96
93
  "enable-dnd": !1,
97
94
  "enable-toggling": !0,
98
95
  "enable-add-group-button": !0,
99
- onUpdateFilters: L
96
+ onUpdateFilters: I
100
97
  }, {
101
- "group-title": h(({ index: e }) => [F.value && e === 0 ? (f(), o("div", {
98
+ "group-title": h(({ index: e }) => [P.value && e === 0 ? (f(), o("div", {
102
99
  key: 0,
103
100
  class: d(r.$style.defaultGroupTitle)
104
- }, [u[5] ||= c(" Default Group ", -1), m(T)(j.onResetDefaultFilters) ? (f(), i(m(D), {
101
+ }, [u[5] ||= c(" Default Group ", -1), m(w)(A.onResetDefaultFilters) ? (f(), i(m(E), {
105
102
  key: 0,
106
103
  icon: "restart",
107
104
  class: d(r.$style.restartBtn),
108
- onClick: u[1] ||= g((e) => j.onResetDefaultFilters(), ["stop"])
109
- }, null, 8, ["class"])) : a("", !0)], 2)) : (f(), o("div", A, "Custom Group"))]),
105
+ onClick: u[1] ||= g((e) => A.onResetDefaultFilters(), ["stop"])
106
+ }, null, 8, ["class"])) : a("", !0)], 2)) : (f(), o("div", k, "Custom Group"))]),
110
107
  _: 1
111
108
  }, 8, [
112
109
  "filters",
@@ -120,6 +117,6 @@ var A = { key: 1 }, j = /* @__PURE__ */ u({
120
117
  }
121
118
  });
122
119
  //#endregion
123
- export { j as default };
120
+ export { A as default };
124
121
 
125
122
  //# sourceMappingURL=PlTableFiltersV2.vue2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PlTableFiltersV2.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type {\n PTableColumnSpec,\n PlDataTableFiltersWithMeta,\n PFrameHandle,\n PTableColumnId,\n CanonicalizedJson,\n} from \"@platforma-sdk/model\";\nimport {\n canonicalizeJson,\n Annotation,\n Domain,\n readAnnotation,\n readDomain,\n getUniqueSourceValuesWithLabels,\n parseJson,\n getPTableColumnId,\n} from \"@platforma-sdk/model\";\nimport { computed, ref } from \"vue\";\nimport { PlBtnGhost, PlSlideModal, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport {\n PlAdvancedFilter,\n PlAdvancedFilterComponent,\n PlAdvancedFilterSupportedFilters,\n type PlAdvancedFilterItem,\n} from \"../PlAdvancedFilter\";\nimport type { PlAdvancedFilterColumnId } from \"../PlAdvancedFilter/types\";\nimport type { Nil } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\n\nconst props = defineProps<{\n columns: PTableColumnSpec[];\n pframeHandle: Nil | PFrameHandle;\n filters: PlDataTableFiltersWithMeta;\n defaultFilters: Nil | PlDataTableFiltersWithMeta;\n onUpdateFilters: (value: PlDataTableFiltersWithMeta) => void;\n onResetDefaultFilters?: () => void;\n onUpdateDefaultFilters?: (value: PlDataTableFiltersWithMeta) => void;\n}>();\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlTableFiltersV2\");\nconst showManager = ref(false);\nconst hasFilters = computed(() => props.filters.filters.length > 0);\nconst hasDefaultFilters = computed(\n () => !isNil(props.defaultFilters) && props.defaultFilters.filters.length > 0,\n);\nconst filters = computed<PlDataTableFiltersWithMeta>(() => {\n if (isNil(props.defaultFilters) || props.defaultFilters?.filters.length === 0) {\n return props.filters;\n }\n\n return {\n ...props.filters,\n filters: [...(props.defaultFilters?.filters ?? []), ...props.filters.filters],\n };\n});\nconst onUpdateFilters = (_value: PlAdvancedFilter) => {\n const value = _value as PlDataTableFiltersWithMeta;\n\n if (isNil(props.defaultFilters)) {\n return props.onUpdateFilters(value);\n }\n\n const [defaults, ...rest] = value.filters;\n props.onUpdateFilters({ ...value, filters: rest });\n props.onUpdateDefaultFilters?.({ ...props.defaultFilters, filters: [defaults] });\n};\n\nconst options = computed<PlAdvancedFilterItem[]>(() => {\n return props.columns.map((col, idx) => {\n const id = makeFilterColumnId(col);\n const label =\n readAnnotation(col.spec, Annotation.Label)?.trim() ?? `Unlabeled ${col.type} ${idx}`;\n const alphabet =\n readDomain(col.spec, Domain.Alphabet) ?? readAnnotation(col.spec, Annotation.Alphabet);\n return {\n id,\n label,\n spec: col.spec,\n alphabet: alphabet ?? undefined,\n };\n });\n});\n\n// Supported filters (same set as FilterSidebar)\nconst supportedFilters = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"patternMatchesRegularExpression\",\n \"patternFuzzyContainSubsequence\",\n \"equal\",\n \"notEqual\",\n] as (typeof PlAdvancedFilterSupportedFilters)[number][];\n\n// getSuggestOptions - provide discrete values from column annotations\nfunction handleSuggestOptions(params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n}) {\n if (isNil(props.pframeHandle)) {\n console.warn(\"PFrame handle is not available, cannot fetch suggest options\");\n return [];\n }\n\n const strId = params.columnId as CanonicalizedJson<PTableColumnId>;\n const tableColumnId = parseJson<PTableColumnId>(strId);\n\n if (tableColumnId.type !== \"column\") {\n throw new Error(\"ColumnId should be of type 'column' for suggest options\");\n }\n\n return getUniqueSourceValuesWithLabels(props.pframeHandle, {\n columnId: tableColumnId.id,\n axisIdx: params.axisIdx,\n limit: 100,\n searchQuery: params.searchType === \"label\" ? params.searchStr : undefined,\n searchQueryValue: params.searchType === \"value\" ? params.searchStr : undefined,\n }).then((v) => v.values);\n}\n\nfunction makeFilterColumnId(spec: PTableColumnSpec): CanonicalizedJson<PTableColumnId> {\n return canonicalizeJson<PTableColumnId>(getPTableColumnId(spec));\n}\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget\" :to=\"teleportTarget\">\n <PlBtnGhost\n :icon=\"hasFilters || hasDefaultFilters ? 'filter-on' : 'filter'\"\n @click.stop=\"showManager = true\"\n >\n Filters\n </PlBtnGhost>\n </Teleport>\n\n <PlSlideModal v-model=\"showManager\" :close-on-outside-click=\"false\">\n <template #title>Manage Filters</template>\n\n <div :class=\"$style.root\">\n <PlAdvancedFilterComponent\n :filters=\"filters as PlAdvancedFilter\"\n :options=\"options\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"handleSuggestOptions\"\n :is-pinned=\"(_, index) => hasDefaultFilters && index === 0\"\n :is-removable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :is-draggable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :enable-dnd=\"false\"\n :enable-toggling=\"true\"\n :enable-add-group-button=\"true\"\n @update-filters=\"onUpdateFilters\"\n >\n <template #group-title=\"{ index }\">\n <div v-if=\"hasDefaultFilters && index === 0\" :class=\"$style.defaultGroupTitle\">\n Default Group\n <PlBtnGhost\n v-if=\"isFunction(props.onResetDefaultFilters)\"\n icon=\"restart\"\n :class=\"$style.restartBtn\"\n @click.stop=\"props.onResetDefaultFilters()\"\n />\n </div>\n <div v-else>Custom Group</div>\n </template>\n </PlAdvancedFilterComponent>\n </div>\n </PlSlideModal>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.defaultGroupTitle {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.restartBtn {\n width: 24px;\n height: 24px;\n padding: 4px;\n --button-width: 24px;\n --btn-min-width: 24px;\n --button-height: 24px;\n --btn-min-height: 24x;\n}\n</style>\n"],"mappings":"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"}
1
+ {"version":3,"file":"PlTableFiltersV2.vue_vue_type_script_setup_true_lang.js","names":["$style"],"sources":["../../../src/components/PlTableFilters/PlTableFiltersV2.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type {\n PTableColumnSpec,\n PlDataTableFiltersWithMeta,\n PFrameHandle,\n PTableColumnId,\n} from \"@platforma-sdk/model\";\nimport {\n Annotation,\n Domain,\n readAnnotation,\n readDomain,\n getUniqueSourceValuesWithLabels,\n extractPObjectId,\n getPTableColumnId,\n} from \"@platforma-sdk/model\";\nimport { computed, ref } from \"vue\";\nimport { PlBtnGhost, PlSlideModal, usePlBlockPageTitleTeleportTarget } from \"@milaboratories/uikit\";\nimport {\n PlAdvancedFilter,\n PlAdvancedFilterComponent,\n PlAdvancedFilterSupportedFilters,\n type PlAdvancedFilterItem,\n} from \"../PlAdvancedFilter\";\nimport type { PlAdvancedFilterColumnId } from \"../PlAdvancedFilter/types\";\nimport type { Nil } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\n\nconst props = defineProps<{\n columns: PTableColumnSpec[];\n pframeHandle: Nil | PFrameHandle;\n filters: PlDataTableFiltersWithMeta;\n defaultFilters: Nil | PlDataTableFiltersWithMeta;\n onUpdateFilters: (value: PlDataTableFiltersWithMeta) => void;\n onResetDefaultFilters?: () => void;\n onUpdateDefaultFilters?: (value: PlDataTableFiltersWithMeta) => void;\n}>();\n\nconst teleportTarget = usePlBlockPageTitleTeleportTarget(\"PlTableFiltersV2\");\nconst showManager = ref(false);\nconst hasFilters = computed(() => props.filters.filters.length > 0);\nconst hasDefaultFilters = computed(\n () => !isNil(props.defaultFilters) && props.defaultFilters.filters.length > 0,\n);\nconst filters = computed<PlDataTableFiltersWithMeta>(() => {\n if (isNil(props.defaultFilters) || props.defaultFilters?.filters.length === 0) {\n return props.filters;\n }\n\n return {\n ...props.filters,\n filters: [...(props.defaultFilters?.filters ?? []), ...props.filters.filters],\n };\n});\nconst onUpdateFilters = (_value: PlAdvancedFilter) => {\n const value = _value as PlDataTableFiltersWithMeta;\n\n if (isNil(props.defaultFilters)) {\n return props.onUpdateFilters(value);\n }\n\n const [defaults, ...rest] = value.filters;\n props.onUpdateFilters({ ...value, filters: rest });\n props.onUpdateDefaultFilters?.({ ...props.defaultFilters, filters: [defaults] });\n};\n\nconst options = computed<PlAdvancedFilterItem[]>(() => {\n return props.columns.map((col, idx) => {\n const id = getPTableColumnId(col);\n const label =\n readAnnotation(col.spec, Annotation.Label)?.trim() ?? `Unlabeled ${col.type} ${idx}`;\n const alphabet =\n readDomain(col.spec, Domain.Alphabet) ?? readAnnotation(col.spec, Annotation.Alphabet);\n return {\n id,\n label,\n spec: col.spec,\n alphabet: alphabet ?? undefined,\n };\n });\n});\n\n// Supported filters (same set as FilterSidebar)\nconst supportedFilters = [\n \"isNA\",\n \"isNotNA\",\n \"greaterThan\",\n \"greaterThanOrEqual\",\n \"lessThan\",\n \"lessThanOrEqual\",\n \"patternEquals\",\n \"patternNotEquals\",\n \"patternContainSubsequence\",\n \"patternNotContainSubsequence\",\n \"patternMatchesRegularExpression\",\n \"patternFuzzyContainSubsequence\",\n \"equal\",\n \"notEqual\",\n] as (typeof PlAdvancedFilterSupportedFilters)[number][];\n\n// getSuggestOptions - provide discrete values from column annotations\nfunction handleSuggestOptions(params: {\n columnId: PlAdvancedFilterColumnId;\n axisIdx?: number;\n searchStr: string;\n searchType: \"value\" | \"label\";\n}) {\n if (isNil(props.pframeHandle)) {\n console.warn(\"PFrame handle is not available, cannot fetch suggest options\");\n return [];\n }\n\n const tableColumnId = params.columnId as PTableColumnId;\n if (\n typeof tableColumnId !== \"object\" ||\n tableColumnId === null ||\n tableColumnId.type !== \"column\"\n ) {\n throw new Error(\"ColumnId should be of type 'column' for suggest options\");\n }\n\n return getUniqueSourceValuesWithLabels(props.pframeHandle, {\n columnId: extractPObjectId(tableColumnId.id),\n axisIdx: params.axisIdx,\n limit: 100,\n searchQuery: params.searchType === \"label\" ? params.searchStr : undefined,\n searchQueryValue: params.searchType === \"value\" ? params.searchStr : undefined,\n }).then((v) => v.values);\n}\n</script>\n\n<template>\n <Teleport v-if=\"teleportTarget\" :to=\"teleportTarget\">\n <PlBtnGhost\n :icon=\"hasFilters || hasDefaultFilters ? 'filter-on' : 'filter'\"\n @click.stop=\"showManager = true\"\n >\n Filters\n </PlBtnGhost>\n </Teleport>\n\n <PlSlideModal v-model=\"showManager\" :close-on-outside-click=\"false\">\n <template #title>Manage Filters</template>\n\n <div :class=\"$style.root\">\n <PlAdvancedFilterComponent\n :filters=\"filters as PlAdvancedFilter\"\n :options=\"options\"\n :supported-filters=\"supportedFilters\"\n :get-suggest-options=\"handleSuggestOptions\"\n :is-pinned=\"(_, index) => hasDefaultFilters && index === 0\"\n :is-removable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :is-draggable=\"(_, index) => (hasDefaultFilters ? index > 0 : true)\"\n :enable-dnd=\"false\"\n :enable-toggling=\"true\"\n :enable-add-group-button=\"true\"\n @update-filters=\"onUpdateFilters\"\n >\n <template #group-title=\"{ index }\">\n <div v-if=\"hasDefaultFilters && index === 0\" :class=\"$style.defaultGroupTitle\">\n Default Group\n <PlBtnGhost\n v-if=\"isFunction(props.onResetDefaultFilters)\"\n icon=\"restart\"\n :class=\"$style.restartBtn\"\n @click.stop=\"props.onResetDefaultFilters()\"\n />\n </div>\n <div v-else>Custom Group</div>\n </template>\n </PlAdvancedFilterComponent>\n </div>\n </PlSlideModal>\n</template>\n\n<style module>\n.root {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.defaultGroupTitle {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n.restartBtn {\n width: 24px;\n height: 24px;\n padding: 4px;\n --button-width: 24px;\n --btn-min-width: 24px;\n --button-height: 24px;\n --btn-min-height: 24x;\n}\n</style>\n"],"mappings":"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"}
@@ -4,8 +4,9 @@ export type UiServiceOptions = {
4
4
  proxy: ServiceProxy;
5
5
  };
6
6
  export declare function createUiServiceRegistry(options: UiServiceOptions): UiServiceRegistry<{
7
- PFrameSpec: import('@milaboratories/pl-model-common').Branded<"pframeSpec", import('@milaboratories/pl-model-common').ServiceTypesLike<import('@milaboratories/pl-model-common').PFrameSpecDriver, import('@milaboratories/pl-model-common').PFrameSpecDriver, "wasm">>;
8
- PFrame: import('@milaboratories/pl-model-common').Branded<"pframe", import('@milaboratories/pl-model-common').ServiceTypesLike<import('@milaboratories/pl-model-common').PFrameModelDriver<import('@milaboratories/pl-model-common').PColumn<string | import('@milaboratories/pl-model-common').PColumnValues | import('@milaboratories/pl-model-common').DataInfo<string>>>, import('@milaboratories/pl-model-common').PFrameDriver, "node">>;
9
- Dialog: import('@milaboratories/pl-model-common').Branded<"dialog", import('@milaboratories/pl-model-common').ServiceTypesLike<Record<string, never>, import('@milaboratories/pl-model-common').DialogService, "main">>;
7
+ PFrameSpec: import('@milaboratories/pl-model-common').Branded<"pframeSpec", import('@milaboratories/pl-model-common').ServiceTypesLike<import('@milaboratories/pl-model-common').PFrameSpecDriver, import('@milaboratories/pl-model-common').PFrameSpecDriver, "wasm", import('@milaboratories/pl-model-common').PFrameSpecDriver, import('@milaboratories/pl-model-common').PFrameSpecDriver>>;
8
+ PFrame: import('@milaboratories/pl-model-common').Branded<"pframe", import('@milaboratories/pl-model-common').ServiceTypesLike<import('@milaboratories/pl-model-common').PFrameModelDriver<import('@milaboratories/pl-model-common').PColumn<string | import('@milaboratories/pl-model-common').PColumnValues | import('@milaboratories/pl-model-common').DataInfo<string>>>, import('@milaboratories/pl-model-common').PFrameDriver, "node", import('@milaboratories/pl-model-common').PFrameModelDriver<import('@milaboratories/pl-model-common').PColumn<string | import('@milaboratories/pl-model-common').PColumnValues | import('@milaboratories/pl-model-common').DataInfo<string>>>, import('@milaboratories/pl-model-common').PFrameDriver>>;
9
+ Dialog: import('@milaboratories/pl-model-common').Branded<"dialog", import('@milaboratories/pl-model-common').ServiceTypesLike<Record<string, never>, import('@milaboratories/pl-model-common').DialogService, "main", Record<string, never>, import('@milaboratories/pl-model-common').DialogService>>;
10
+ ColumnsCollection: import('@milaboratories/pl-model-common').Branded<"columnsCollection", import('@milaboratories/pl-model-common').ServiceTypesLike<import('@milaboratories/pl-model-common').ColumnsCollectionDriverModel, import('@milaboratories/pl-model-common').ColumnsCollectionDriverModel, "wasm", import('@milaboratories/pl-model-common').ColumnsCollectionDriver, import('@milaboratories/pl-model-common').ColumnsCollectionDriver>>;
10
11
  }>;
11
12
  //# sourceMappingURL=service_factories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service_factories.d.ts","sourceRoot":"","sources":["../../src/internal/service_factories.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAY,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAE9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,gBAAgB;;;;GAMhE"}
1
+ {"version":3,"file":"service_factories.d.ts","sourceRoot":"","sources":["../../src/internal/service_factories.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAY,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAG9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,YAAY,CAAC;CACrB,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,gBAAgB;;;;;GAOhE"}
@@ -1,14 +1,16 @@
1
1
  import { Services as e, UiServiceRegistry as t } from "@milaboratories/pl-model-common";
2
2
  import { SpecDriver as n } from "@milaboratories/pf-spec-driver";
3
+ import { ColumnsCollectionDriverImpl as r } from "@milaboratories/columns-collection-driver";
3
4
  //#region src/internal/service_factories.ts
4
- function r(r) {
5
+ function i(i) {
5
6
  return new t(e, {
6
7
  PFrameSpec: () => new n(),
7
- PFrame: () => r.proxy(e.PFrame),
8
- Dialog: () => r.proxy(e.Dialog)
8
+ PFrame: () => i.proxy(e.PFrame),
9
+ Dialog: () => i.proxy(e.Dialog),
10
+ ColumnsCollection: () => new r()
9
11
  });
10
12
  }
11
13
  //#endregion
12
- export { r as createUiServiceRegistry };
14
+ export { i as createUiServiceRegistry };
13
15
 
14
16
  //# sourceMappingURL=service_factories.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"service_factories.js","names":[],"sources":["../../src/internal/service_factories.ts"],"sourcesContent":["/**\n * UI service factories — add a factory for each new service here.\n *\n * Each entry maps a Services key to a factory function that creates the\n * UI-side driver instance:\n * - WASM services: instantiated directly (e.g. SpecDriver)\n * - Node services: proxied via IPC using NodeServiceProxy\n */\n\nimport { Services, UiServiceRegistry } from \"@milaboratories/pl-model-common\";\nimport { SpecDriver } from \"@milaboratories/pf-spec-driver\";\nimport type { ServiceProxy } from \"@platforma-sdk/model\";\n\nexport type UiServiceOptions = {\n proxy: ServiceProxy;\n};\n\nexport function createUiServiceRegistry(options: UiServiceOptions) {\n return new UiServiceRegistry(Services, {\n PFrameSpec: () => new SpecDriver(),\n PFrame: () => options.proxy(Services.PFrame),\n Dialog: () => options.proxy(Services.Dialog),\n });\n}\n"],"mappings":";;;AAiBA,SAAgB,EAAwB,GAA2B;AACjE,QAAO,IAAI,EAAkB,GAAU;EACrC,kBAAkB,IAAI,GAAY;EAClC,cAAc,EAAQ,MAAM,EAAS,OAAO;EAC5C,cAAc,EAAQ,MAAM,EAAS,OAAO;EAC7C,CAAC"}
1
+ {"version":3,"file":"service_factories.js","names":[],"sources":["../../src/internal/service_factories.ts"],"sourcesContent":["/**\n * UI service factories — add a factory for each new service here.\n *\n * Each entry maps a Services key to a factory function that creates the\n * UI-side driver instance:\n * - WASM services: instantiated directly (e.g. SpecDriver)\n * - Node services: proxied via IPC using NodeServiceProxy\n */\n\nimport { Services, UiServiceRegistry } from \"@milaboratories/pl-model-common\";\nimport { SpecDriver } from \"@milaboratories/pf-spec-driver\";\nimport { ColumnsCollectionDriverImpl } from \"@milaboratories/columns-collection-driver\";\nimport type { ServiceProxy } from \"@platforma-sdk/model\";\n\nexport type UiServiceOptions = {\n proxy: ServiceProxy;\n};\n\nexport function createUiServiceRegistry(options: UiServiceOptions) {\n return new UiServiceRegistry(Services, {\n PFrameSpec: () => new SpecDriver(),\n PFrame: () => options.proxy(Services.PFrame),\n Dialog: () => options.proxy(Services.Dialog),\n ColumnsCollection: () => new ColumnsCollectionDriverImpl(),\n });\n}\n"],"mappings":";;;;AAkBA,SAAgB,EAAwB,GAA2B;AACjE,QAAO,IAAI,EAAkB,GAAU;EACrC,kBAAkB,IAAI,GAAY;EAClC,cAAc,EAAQ,MAAM,EAAS,OAAO;EAC5C,cAAc,EAAQ,MAAM,EAAS,OAAO;EAC5C,yBAAyB,IAAI,GAA6B;EAC3D,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/ui-vue",
3
- "version": "1.79.34",
3
+ "version": "1.80.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -26,10 +26,11 @@
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.4.18",
30
- "@milaboratories/pl-model-common": "1.46.4",
31
- "@milaboratories/uikit": "2.15.14",
32
- "@platforma-sdk/model": "1.79.27"
29
+ "@milaboratories/columns-collection-driver": "0.2.0",
30
+ "@milaboratories/pl-model-common": "1.47.0",
31
+ "@milaboratories/uikit": "2.15.15",
32
+ "@platforma-sdk/model": "1.80.0",
33
+ "@milaboratories/pf-spec-driver": "1.4.20"
33
34
  },
34
35
  "devDependencies": {
35
36
  "@faker-js/faker": "^9.2.0",
@@ -47,8 +48,8 @@
47
48
  "vitest": "^4.1.3",
48
49
  "@milaboratories/build-configs": "2.0.0",
49
50
  "@milaboratories/helpers": "1.14.3",
50
- "@milaboratories/ts-configs": "1.3.0",
51
- "@milaboratories/ts-builder": "1.6.0"
51
+ "@milaboratories/ts-builder": "1.6.0",
52
+ "@milaboratories/ts-configs": "1.3.0"
52
53
  },
53
54
  "scripts": {
54
55
  "dev": "ts-builder serve --target browser-lib",
@@ -13,9 +13,11 @@ import type {
13
13
  AnchoredPColumnId,
14
14
  AxisFilterByIdx,
15
15
  AxisFilterValue,
16
+ PTableColumnId,
16
17
  SUniversalPColumnId,
17
18
  } from "@platforma-sdk/model";
18
19
  import {
20
+ canonicalizeJson,
19
21
  isFilteredPColumn,
20
22
  parseColumnId,
21
23
  stringifyColumnId,
@@ -102,7 +104,9 @@ function changeSourceId(newSourceId?: PlAdvancedFilterColumnId) {
102
104
  if (!newSourceId) {
103
105
  return;
104
106
  }
105
- const newSourceInfo = props.columnOptions.find((v) => v.id === getSourceId(newSourceId));
107
+ const newSourceInfo = props.columnOptions.find((v) =>
108
+ columnIdEquals(v.id, getSourceId(newSourceId)),
109
+ );
106
110
  if (!newSourceInfo) {
107
111
  return;
108
112
  }
@@ -119,8 +123,8 @@ function changeSourceId(newSourceId?: PlAdvancedFilterColumnId) {
119
123
  }
120
124
 
121
125
  const inconsistentSourceSelected = computed(() => {
122
- const selectedOption = props.columnOptions.find(
123
- (op) => op.id === getSourceId(props.filter.column),
126
+ const selectedOption = props.columnOptions.find((op) =>
127
+ columnIdEquals(op.id, getSourceId(props.filter.column)),
124
128
  );
125
129
  return selectedOption === undefined;
126
130
  });
@@ -132,7 +136,13 @@ const sourceOptions = computed(() => {
132
136
  return options;
133
137
  });
134
138
 
139
+ function isPTableColumnIdObject(c: PlAdvancedFilterColumnId): c is PTableColumnId {
140
+ return typeof c === "object" && c !== null;
141
+ }
142
+
135
143
  function getSourceId(column: PlAdvancedFilterColumnId): PlAdvancedFilterColumnId {
144
+ // PTableColumnId object form: no axisFilters embedded, return as-is.
145
+ if (isPTableColumnIdObject(column)) return column;
136
146
  try {
137
147
  const parsedColumnId = parseColumnId(column as SUniversalPColumnId);
138
148
  if (isFilteredPColumn(parsedColumnId)) {
@@ -154,7 +164,7 @@ function getColumnAsSourceAndFixedAxes(
154
164
  column: PlAdvancedFilterColumnId,
155
165
  ): ColumnAsSourceAndFixedAxes {
156
166
  const sourceId = getSourceId(column);
157
- const option = props.columnOptions.find((op) => op.id === sourceId);
167
+ const option = props.columnOptions.find((op) => columnIdEquals(op.id, sourceId));
158
168
  const axesToBeFixed = (option?.axesToBeFixed ?? []).reduce(
159
169
  (res, item) => {
160
170
  res[item.idx] = undefined;
@@ -162,15 +172,22 @@ function getColumnAsSourceAndFixedAxes(
162
172
  },
163
173
  {} as Record<number, AxisFilterValue | undefined>,
164
174
  );
175
+ // PTableColumnId object form has no axis filters baked in.
176
+ if (isPTableColumnIdObject(column)) {
177
+ return { source: column, axisFiltersByIndex: axesToBeFixed };
178
+ }
165
179
  try {
166
180
  const parsedColumnId = parseColumnId(column as SUniversalPColumnId);
167
181
  if (isFilteredPColumn(parsedColumnId)) {
168
182
  return {
169
183
  source: sourceId,
170
- axisFiltersByIndex: parsedColumnId.axisFilters.reduce((res, item) => {
171
- res[item[0]] = item[1];
172
- return res;
173
- }, axesToBeFixed),
184
+ axisFiltersByIndex: (parsedColumnId.axisFilters as AxisFilterByIdx[]).reduce(
185
+ (res, item) => {
186
+ res[item[0]] = item[1];
187
+ return res;
188
+ },
189
+ axesToBeFixed,
190
+ ),
174
191
  };
175
192
  }
176
193
  } catch {
@@ -179,12 +196,24 @@ function getColumnAsSourceAndFixedAxes(
179
196
  return { source: column, axisFiltersByIndex: axesToBeFixed };
180
197
  }
181
198
 
199
+ /** Identity comparison for PlAdvancedFilterColumnId values — handles both string
200
+ * and object (PTableColumnId) variants. */
201
+ function columnIdEquals(a: PlAdvancedFilterColumnId, b: PlAdvancedFilterColumnId): boolean {
202
+ if (a === b) return true;
203
+ if (typeof a === "object" && typeof b === "object" && a !== null && b !== null) {
204
+ return canonicalizeJson(a) === canonicalizeJson(b);
205
+ }
206
+ return false;
207
+ }
208
+
182
209
  function stringifyColumn(value: ColumnAsSourceAndFixedAxes): PlAdvancedFilterColumnId {
183
210
  if (Object.keys(value.axisFiltersByIndex).length === 0) {
184
211
  return value.source;
185
212
  }
213
+ // PTableColumnId object form can't carry axisFilters — return as-is.
214
+ if (isPTableColumnIdObject(value.source)) return value.source;
186
215
  return stringifyColumnId({
187
- source: parseColumnId(value.source as SUniversalPColumnId) as AnchoredPColumnId,
216
+ source: parseColumnId(value.source as SUniversalPColumnId) as unknown as AnchoredPColumnId,
188
217
  axisFilters: Object.entries(value.axisFiltersByIndex).map(
189
218
  ([idx, value]) => [Number(idx), value] as AxisFilterByIdx,
190
219
  ),
@@ -207,7 +236,7 @@ function updateAxisFilterValue(idx: number, value: AxisFilterValue | undefined)
207
236
  }
208
237
 
209
238
  const currentOption = computed(() =>
210
- props.columnOptions.find((op) => op.id === columnAsSourceAndFixedAxes.value.source),
239
+ props.columnOptions.find((op) => columnIdEquals(op.id, columnAsSourceAndFixedAxes.value.source)),
211
240
  );
212
241
  const currentSpec = computed(() =>
213
242
  currentOption.value?.spec ? getNormalizedSpec(currentOption.value.spec) : null,
@@ -13,11 +13,12 @@ import { PartialBy, RequiredBy } from "@milaboratories/helpers";
13
13
 
14
14
  export type Operand = "or" | "and";
15
15
 
16
- // Can be any of string type, but for better type safety we use union of specific types
16
+ // Either a string column id (SUniversalPColumnId / canonicalized axis JSON) or
17
+ // a structured PTableColumnId object (axis | column ref).
17
18
  export type PlAdvancedFilterColumnId =
18
19
  | SUniversalPColumnId
19
20
  | CanonicalizedJson<AxisId>
20
- | CanonicalizedJson<PTableColumnId>;
21
+ | PTableColumnId;
21
22
 
22
23
  export type RequiredMeta = {
23
24
  id: number;
@@ -29,7 +29,7 @@ export function getNewId() {
29
29
  return Date.now();
30
30
  }
31
31
 
32
- export function createNewGroup(selectedSourceId: string): NodeFilter {
32
+ export function createNewGroup(selectedSourceId: PlAdvancedFilterColumnId): NodeFilter {
33
33
  return {
34
34
  id: getNewId(),
35
35
  isExpanded: true,
@@ -2,6 +2,7 @@
2
2
  import { promiseTimeout, isJsonEqual } from "@milaboratories/helpers";
3
3
  import type {
4
4
  AxisId,
5
+ PlDataTableColumnsMeta,
5
6
  PlDataTableGridStateCore,
6
7
  PlDataTableStateV2,
7
8
  PlSelectionModel,
@@ -16,7 +17,6 @@ import {
16
17
  getAxisId,
17
18
  canonicalizeJson,
18
19
  isAbortError,
19
- isColumnOptional,
20
20
  } from "@platforma-sdk/model";
21
21
  import type { CellRendererSelectorFunc, GridApi, GridState } from "ag-grid-enterprise";
22
22
  import { AgGridVue } from "ag-grid-vue3";
@@ -30,7 +30,7 @@ import PlAgRowCount from "./PlAgRowCount.vue";
30
30
  import { DeferredCircular, ensureNodeVisible } from "./sources/focus-row";
31
31
  import { PlAgDataTableRowNumberColId } from "./sources/row-number";
32
32
  import type { PlAgCellButtonAxisParams } from "./sources/table-source-v2";
33
- import { calculateGridOptions } from "./sources/table-source-v2";
33
+ import { calculateGridOptions, effectiveVisibility } from "./sources/table-source-v2";
34
34
  import { useTableState } from "./sources/table-state-v2";
35
35
  import type {
36
36
  PlAgDataTableV2Controller,
@@ -133,6 +133,7 @@ gridOptions.value.onGridPreDestroyed = (event) => {
133
133
  makePartialState(event.api.getState()),
134
134
  gridState.value,
135
135
  event.api,
136
+ currentColumnsMeta(),
136
137
  );
137
138
  }
138
139
  gridApi.value = null;
@@ -145,6 +146,7 @@ gridOptions.value.onStateUpdated = (event) => {
145
146
  makePartialState(event.state),
146
147
  gridState.value,
147
148
  event.api,
149
+ currentColumnsMeta(),
148
150
  );
149
151
  // We have to keep initialState synchronized with gridState for gridState recovery after key updating.
150
152
  gridOptions.value.initialState = gridState.value = partialState;
@@ -219,6 +221,7 @@ function normalizeColumnVisibility(
219
221
  partialState: PlDataTableGridStateCore,
220
222
  prevState: PlDataTableGridStateCore,
221
223
  api: GridApi<PlAgDataTableV2Row>,
224
+ columnsMeta: PlDataTableColumnsMeta | undefined,
222
225
  ): PlDataTableGridStateCore {
223
226
  if (partialState.columnVisibility !== undefined) return partialState;
224
227
 
@@ -229,7 +232,7 @@ function normalizeColumnVisibility(
229
232
 
230
233
  // No previous explicit state → compute defaults from current columns
231
234
  // to replicate: hide: hiddenColIds?.includes(colId) ?? isColumnOptional(spec.spec)
232
- const defaultHidden = getDefaultHiddenColIds(api);
235
+ const defaultHidden = getDefaultHiddenColIds(api, columnsMeta);
233
236
  if (defaultHidden.length > 0) {
234
237
  return { ...partialState, columnVisibility: { hiddenColIds: defaultHidden } };
235
238
  }
@@ -237,14 +240,26 @@ function normalizeColumnVisibility(
237
240
  return partialState;
238
241
  }
239
242
 
240
- function getDefaultHiddenColIds(api: GridApi<PlAgDataTableV2Row>): PlTableColumnIdJson[] {
243
+ /** Sidecar display meta is only on the `model` branch of the settings union. */
244
+ function currentColumnsMeta(): PlDataTableColumnsMeta | undefined {
245
+ return "model" in props.settings ? props.settings.model?.columnsMeta : undefined;
246
+ }
247
+
248
+ function getDefaultHiddenColIds(
249
+ api: GridApi<PlAgDataTableV2Row>,
250
+ columnsMeta: PlDataTableColumnsMeta | undefined,
251
+ ): PlTableColumnIdJson[] {
241
252
  const cols = api.getAllGridColumns();
242
253
  if (!cols) return [];
243
254
 
244
255
  return cols
245
256
  .filter((col) => {
246
257
  const spec = col.getColDef().context as PTableColumnSpec | undefined;
247
- return spec !== undefined && spec.type === "column" && isColumnOptional(spec.spec);
258
+ return (
259
+ spec !== undefined &&
260
+ spec.type === "column" &&
261
+ effectiveVisibility(spec, columnsMeta) === "optional"
262
+ );
248
263
  })
249
264
  .map((col) => col.getColId() as PlTableColumnIdJson);
250
265
  }
@@ -426,6 +441,7 @@ watch(
426
441
  pfDriver: getRawPlatformaInstance().pFrameDriver,
427
442
  fullTableHandle: settings.model?.fullTableHandle,
428
443
  visibleTableHandle: settings.model?.visibleTableHandle,
444
+ columnsMeta: settings.model?.columnsMeta,
429
445
  sheets: settings.sheets ?? [],
430
446
  dataRenderedTracker,
431
447
  hiddenColIds: gridState.value.columnVisibility?.hiddenColIds,