@platforma-sdk/ui-vue 1.78.6 → 1.78.7

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.
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-sdk/ui-vue@1.78.6 build /home/runner/_work/platforma/platforma/sdk/ui-vue
3
+ > @platforma-sdk/ui-vue@1.78.7 build /home/runner/_work/platforma/platforma/sdk/ui-vue
4
4
  > ts-builder build --target browser-lib
5
5
 
6
6
  Building browser-lib project...
@@ -16,7 +16,7 @@ Building browser-lib project...
16
16
  rendering chunks...
17
17
 
18
18
  [vite:dts] Start generate declaration files...
19
- [vite:dts] Declaration files built in 4607ms.
19
+ [vite:dts] Declaration files built in 5877ms.
20
20
 
21
21
  computing gzip size...
22
22
  dist/components/PlAnnotations/components/PlAnnotations.vue?vue&type=style&index=0&lang.css 0.04 kB │ gzip: 0.06 kB
@@ -201,8 +201,8 @@ dist/components/PlAppErrorNotificationAlert/PlAppErrorNotificationAlert.vue_vue_
201
201
  dist/components/PlAgDataTable/PlAgDataTableSheets.vue_vue_type_script_setup_true_lang.js 2.45 kB │ gzip: 1.17 kB │ map: 5.01 kB
202
202
  dist/components/PlDatasetSelector/PlDatasetSelector.vue_vue_type_script_setup_true_lang.js 2.58 kB │ gzip: 1.07 kB │ map: 6.02 kB
203
203
  dist/components/PlAnnotations/components/PlAnnotations.vue_vue_type_script_setup_true_lang.js 2.69 kB │ gzip: 1.12 kB │ map: 4.16 kB
204
- dist/components/PlAgCsvExporter/export-csv.js 2.69 kB │ gzip: 1.20 kB │ map: 8.79 kB
205
204
  dist/lib.js 2.73 kB │ gzip: 0.57 kB │ map: 3.98 kB
205
+ dist/components/PlAgCsvExporter/export-csv.js 2.83 kB │ gzip: 1.27 kB │ map: 9.11 kB
206
206
  dist/components/PlAgDataTable/compositions/useGrid.js 2.91 kB │ gzip: 1.29 kB │ map: 6.51 kB
207
207
  dist/components/PlAgColumnHeader/PlAgColumnHeader.vue_vue_type_script_setup_true_lang.js 2.93 kB │ gzip: 1.26 kB │ map: 7.97 kB
208
208
  dist/components/PlAgDataTable/sources/row-number.js 2.99 kB │ gzip: 1.31 kB │ map: 7.42 kB
@@ -227,12 +227,12 @@ dist/components/PlAdvancedFilter/FilterEditor.vue_vue_type_script_setup_true_lan
227
227
  dist/components/PlAgDataTable/PlAgDataTableV2.vue_vue_type_script_setup_true_lang.js 12.31 kB │ gzip: 3.90 kB │ map: 29.22 kB
228
228
 
229
229
  [PLUGIN_TIMINGS] Warning: Your build spent significant time in plugins. Here is a breakdown:
230
- - sourcemaps (37%)
231
- - vite:dts (20%)
232
- - vite:vue (13%)
233
- - vite:css-post (10%)
234
- - vite:css (8%)
230
+ - sourcemaps (39%)
231
+ - vite:dts (24%)
232
+ - vite:vue (9%)
233
+ - vite:css-post (8%)
234
+ - vite:css (7%)
235
235
  See https://rolldown.rs/options/checks#plugintimings for more details.
236
236
  
237
- ✓ built in 5.74s
237
+ ✓ built in 6.78s
238
238
  Build completed successfully
@@ -1,6 +1,6 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-sdk/ui-vue@1.78.6 formatter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
3
+ > @platforma-sdk/ui-vue@1.78.7 formatter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
4
4
  > ts-builder formatter --check
5
5
 
6
6
  Checking formatting...
@@ -8,5 +8,5 @@ Checking formatting...
8
8
  Checking formatting...
9
9
 
10
10
  All matched files use the correct format.
11
- Finished in 4149ms on 137 files using 8 threads.
11
+ Finished in 4983ms on 137 files using 8 threads.
12
12
  Format check completed successfully
@@ -1,10 +1,10 @@
1
1
   WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
2
 
3
- > @platforma-sdk/ui-vue@1.78.6 linter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
3
+ > @platforma-sdk/ui-vue@1.78.7 linter:check /home/runner/_work/platforma/platforma/sdk/ui-vue
4
4
  > ts-builder linter --check
5
5
 
6
6
  Linting project...
7
7
  ↳ oxlint --config /home/runner/_work/platforma/platforma/sdk/ui-vue/.oxlintrc.json --deny-warnings
8
8
  Found 0 warnings and 0 errors.
9
- Finished in 22ms on 120 files with 108 rules using 8 threads.
9
+ Finished in 49ms on 120 files with 108 rules using 8 threads.
10
10
  Linting completed successfully
@@ -1,6 +1,6 @@
1
-  WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
2
1
 
3
- > @platforma-sdk/ui-vue@1.78.6 types:check /home/runner/_work/platforma/platforma/sdk/ui-vue
2
+ > @platforma-sdk/ui-vue@1.78.7 types:check /home/runner/_work/platforma/platforma/sdk/ui-vue
3
+  WARN  Issue while reading "/home/runner/_work/platforma/platforma/.npmrc". Failed to replace env in config: ${NPMJS_TOKEN}
4
4
  > ts-builder type-check --target browser-lib
5
5
 
6
6
  ↳ vue-tsc.js --noEmit --project ./tsconfig.json --customConditions ,
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @platforma-sdk/ui-vue
2
2
 
3
+ ## 1.78.7
4
+
5
+ ### Patch Changes
6
+
7
+ - 60b13d1: Gate the xlsx export option in the UI on table size instead of failing after the dialog.
8
+
9
+ `exportCsv` now calls `getShape` before opening the save dialog and drops the Excel filter when the table exceeds the per-sheet row limit, so oversized tables simply never offer xlsx rather than erroring out post-selection. The `pf-driver` rejection is kept as a safety net. The shared `XLSX_MAX_ROWS_PER_SHEET` constant is now exported from `@milaboratories/pl-model-common` so the UI gate and the driver check can't drift.
10
+
11
+ - Updated dependencies [60b13d1]
12
+ - @milaboratories/pl-model-common@1.46.0
13
+ - @milaboratories/pf-spec-driver@1.4.5
14
+ - @platforma-sdk/model@1.78.7
15
+ - @milaboratories/uikit@2.14.24
16
+
3
17
  ## 1.78.6
4
18
 
5
19
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"export-csv.d.ts","sourceRoot":"","sources":["../../../src/components/PlAgCsvExporter/export-csv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,KAAK,EAEV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAI9C,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,YAAY,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAkCD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,SAAS,GAAG,qBAAqB,CAAC,CAoD5C;AAUD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,gBAAgB,EAAE,EACzB,UAAU,EAAE,gBAAgB,GAC3B,GAAG,GAAG,MAAM,EAAE,CAkBhB"}
1
+ {"version":3,"file":"export-csv.d.ts","sourceRoot":"","sources":["../../../src/components/PlAgCsvExporter/export-csv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,KAAK,EAEV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAC;AAI9C,2CAA2C;AAC3C,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,YAAY,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAkCD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,SAAS,GAAG,qBAAqB,CAAC,CA0D5C;AAUD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,gBAAgB,EAAE,EACzB,UAAU,EAAE,gBAAgB,GAC3B,GAAG,GAAG,MAAM,EAAE,CAkBhB"}
@@ -1,10 +1,10 @@
1
1
  import { getServices as e } from "../../internal/getServices.js";
2
2
  import "../PlAgDataTable/sources/row-number.js";
3
3
  import "../PlAgDataTable/index.js";
4
- import { getPTableColumnId as t } from "@platforma-sdk/model";
5
- import { isNil as n } from "es-toolkit";
4
+ import { XLSX_MAX_ROWS_PER_SHEET as t, getPTableColumnId as n } from "@platforma-sdk/model";
5
+ import { isNil as r } from "es-toolkit";
6
6
  //#region src/components/PlAgCsvExporter/export-csv.ts
7
- var r = [
7
+ var i = [
8
8
  {
9
9
  name: "CSV",
10
10
  extensions: ["csv"]
@@ -21,7 +21,7 @@ var r = [
21
21
  name: "Excel",
22
22
  extensions: ["xlsx"]
23
23
  }
24
- ], i = [
24
+ ], a = [
25
25
  {
26
26
  name: "CSV (gzip)",
27
27
  extensions: ["csv.gz"]
@@ -39,63 +39,63 @@ var r = [
39
39
  extensions: ["tsv"]
40
40
  }
41
41
  ];
42
- function a(e) {
42
+ function o(e) {
43
43
  let t = e.toLowerCase(), n = t.endsWith(".gz") ? t.slice(0, -3) : t;
44
44
  return n.slice(n.lastIndexOf(".") + 1);
45
45
  }
46
- function o(e, t) {
46
+ function s(e, t) {
47
47
  return t.some(({ extensions: t }) => t.some((t) => e.endsWith("." + t)));
48
48
  }
49
- async function s(t, s) {
50
- let { dialog: l, pframe: d, pframeSpec: f } = e();
51
- if (n(l)) throw Error("dialog service is not available in the current environment");
52
- if (n(d)) throw Error("pframe service is not available");
53
- if (n(f)) throw Error("pframeSpec service is not available");
54
- let p = u(t, await d.getSpec(s.tableHandle), f);
55
- if (n(p)) return;
56
- let m = s.defaultFileName ?? `table_${c(/* @__PURE__ */ new Date())}`;
57
- if (typeof d.exportPTable == "function") {
58
- let { canceled: e, path: t } = await l.showSaveDialog({
59
- defaultFileName: `${m}.csv`,
60
- filters: r
49
+ async function c(n, c) {
50
+ let { dialog: u, pframe: f, pframeSpec: p } = e();
51
+ if (r(u)) throw Error("dialog service is not available in the current environment");
52
+ if (r(f)) throw Error("pframe service is not available");
53
+ if (r(p)) throw Error("pframeSpec service is not available");
54
+ let m = d(n, await f.getSpec(c.tableHandle), p);
55
+ if (r(m)) return;
56
+ let h = c.defaultFileName ?? `table_${l(/* @__PURE__ */ new Date())}`;
57
+ if (typeof f.exportPTable == "function") {
58
+ let { rows: e } = await f.getShape(c.tableHandle), n = e > t ? i.filter(({ name: e }) => e !== "Excel") : i, { canceled: a, path: o } = await u.showSaveDialog({
59
+ defaultFileName: `${h}.csv`,
60
+ filters: n
61
61
  });
62
- if (e || n(t) || !o(t, r)) return;
63
- await d.exportPTable(s.tableHandle, {
64
- path: t,
65
- columnIndices: p
62
+ if (a || r(o) || !s(o, n)) return;
63
+ await f.exportPTable(c.tableHandle, {
64
+ path: o,
65
+ columnIndices: m
66
66
  });
67
67
  return;
68
68
  }
69
- let { canceled: h, path: g } = await l.showSaveDialog({
70
- defaultFileName: `${m}.csv.gz`,
71
- filters: i
69
+ let { canceled: g, path: _ } = await u.showSaveDialog({
70
+ defaultFileName: `${h}.csv.gz`,
71
+ filters: a
72
72
  });
73
- if (h || n(g) || !o(g, i)) return;
74
- let _ = a(g);
75
- if (!(_ !== "csv" && _ !== "tsv")) return d.writePTableToFs(s.tableHandle, {
76
- path: g,
77
- format: _,
78
- columnIndices: p,
79
- ...g.toLowerCase().endsWith(".gz") && { compression: { type: "gzip" } }
73
+ if (g || r(_) || !s(_, a)) return;
74
+ let v = o(_);
75
+ if (!(v !== "csv" && v !== "tsv")) return f.writePTableToFs(c.tableHandle, {
76
+ path: _,
77
+ format: v,
78
+ columnIndices: m,
79
+ ..._.toLowerCase().endsWith(".gz") && { compression: { type: "gzip" } }
80
80
  });
81
81
  }
82
- function c(e) {
82
+ function l(e) {
83
83
  let t = (e) => String(e).padStart(2, "0");
84
84
  return `${t(e.getDate())}-${t(e.getMonth() + 1)}-${e.getFullYear()}_${t(e.getHours())}-${t(e.getMinutes())}-${t(e.getSeconds())}`;
85
85
  }
86
- function l() {
86
+ function u() {
87
87
  try {
88
88
  let t = e();
89
- return !n(t?.dialog) && !n(t?.pframe);
89
+ return !r(t?.dialog) && !r(t?.pframe);
90
90
  } catch {
91
91
  return !1;
92
92
  }
93
93
  }
94
- function u(e, r, i) {
94
+ function d(e, t, i) {
95
95
  let a = e.getColumnDefs();
96
- return n(a) ? void 0 : [...new Set(a.flatMap((e) => "children" in e || e.hide === !0 || n(e.colId) || e.colId === "\"##RowNumberColumnId##\"" ? [] : [e.context]).map((e) => i.findTableColumn(r, t(e))))].filter((e) => e !== -1);
96
+ return r(a) ? void 0 : [...new Set(a.flatMap((e) => "children" in e || e.hide === !0 || r(e.colId) || e.colId === "\"##RowNumberColumnId##\"" ? [] : [e.context]).map((e) => i.findTableColumn(t, n(e))))].filter((e) => e !== -1);
97
97
  }
98
98
  //#endregion
99
- export { s as exportCsv, l as isCsvExportAvailable };
99
+ export { c as exportCsv, u as isCsvExportAvailable };
100
100
 
101
101
  //# sourceMappingURL=export-csv.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"export-csv.js","names":[],"sources":["../../../src/components/PlAgCsvExporter/export-csv.ts"],"sourcesContent":["import { type ColDef, type ColGroupDef, type GridApi } from \"ag-grid-enterprise\";\nimport type {\n FileFilter,\n PTableHandle,\n PTableColumnSpec,\n PFrameSpecDriver,\n WritePTableToFsResult,\n} from \"@platforma-sdk/model\";\nimport { getPTableColumnId } from \"@platforma-sdk/model\";\nimport { isNil } from \"es-toolkit\";\nimport { Nil } from \"@milaboratories/helpers\";\nimport { getServices } from \"../../internal/getServices\";\nimport { PlAgDataTableRowNumberColId } from \"../PlAgDataTable\";\n\n/** Options for the native table export. */\nexport interface ExportOptions {\n tableHandle: PTableHandle;\n defaultFileName?: string;\n}\n\n/** Save-dialog file-type filters for the native `exportPTable` path. */\nconst NATIVE_EXPORT_FILTERS: FileFilter[] = [\n { name: \"CSV\", extensions: [\"csv\"] },\n { name: \"TSV\", extensions: [\"tsv\"] },\n { name: \"Parquet\", extensions: [\"parquet\"] },\n { name: \"Excel\", extensions: [\"xlsx\"] },\n];\n\n/**\n * Save-dialog file-type filters for the `writePTableToFs` fallback. csv/tsv\n * only, offered both plain and gzip-compressed — a trailing `.gz` in the\n * chosen path selects gzip compression.\n */\nconst FALLBACK_EXPORT_FILTERS: FileFilter[] = [\n { name: \"CSV (gzip)\", extensions: [\"csv.gz\"] },\n { name: \"CSV\", extensions: [\"csv\"] },\n { name: \"TSV (gzip)\", extensions: [\"tsv.gz\"] },\n { name: \"TSV\", extensions: [\"tsv\"] },\n];\n\n/** Table format from a save path, ignoring a trailing `.gz`. e.g. `\"t.csv.gz\"` → `\"csv\"`. */\nfunction tableFormatFromPath(path: string): string {\n const lower = path.toLowerCase();\n const base = lower.endsWith(\".gz\") ? lower.slice(0, -3) : lower;\n return base.slice(base.lastIndexOf(\".\") + 1);\n}\n\n/** True when `path` ends with one of the filters' extensions (e.g. `\".csv\"`). */\nfunction matchesFilterExtension(path: string, filters: FileFilter[]): boolean {\n return filters.some(({ extensions }) => extensions.some((ext) => path.endsWith(\".\" + ext)));\n}\n\n/**\n * Table export via the platforma desktop runtime. Prompts for a save\n * destination via the `Dialog` service — offering the available output formats\n * as file-type filters so the user picks the format — then writes the PTable to\n * the chosen path.\n *\n * Prefers the native `PFrame.exportPTable` when the runtime advertises it: the\n * table handle is the *visible* one, so exporting the whole handle reproduces\n * exactly the visible columns/rows, and the format (`csv`/`tsv`/`parquet`/\n * `xlsx`) is taken from the chosen file extension. Falls back to streaming the\n * visible columns via `PFrame.writePTableToFs` (`csv`/`tsv`, optionally\n * gzip-compressed when the chosen path ends in `.gz`) on runtimes that do not\n * advertise `exportPTable`.\n */\nexport async function exportCsv(\n gridApi: GridApi,\n nativeOptions: ExportOptions,\n): Promise<undefined | WritePTableToFsResult> {\n const { dialog, pframe, pframeSpec } = getServices();\n if (isNil(dialog)) {\n throw new Error(\"dialog service is not available in the current environment\");\n }\n if (isNil(pframe)) {\n throw new Error(\"pframe service is not available\");\n }\n if (isNil(pframeSpec)) {\n throw new Error(\"pframeSpec service is not available\");\n }\n\n const specs = await pframe.getSpec(nativeOptions.tableHandle);\n const columnIndices = collectVisibleColumnIndices(gridApi, specs, pframeSpec);\n if (isNil(columnIndices)) {\n return undefined;\n }\n\n const baseFileName = nativeOptions.defaultFileName ?? `table_${formatTimestamp(new Date())}`;\n\n if (typeof pframe.exportPTable === \"function\") {\n const { canceled, path } = await dialog.showSaveDialog({\n defaultFileName: `${baseFileName}.csv`,\n filters: NATIVE_EXPORT_FILTERS,\n });\n if (canceled || isNil(path) || !matchesFilterExtension(path, NATIVE_EXPORT_FILTERS)) {\n return undefined;\n }\n\n await pframe.exportPTable(nativeOptions.tableHandle, { path, columnIndices });\n return undefined;\n }\n\n const { canceled, path } = await dialog.showSaveDialog({\n defaultFileName: `${baseFileName}.csv.gz`,\n filters: FALLBACK_EXPORT_FILTERS,\n });\n if (canceled || isNil(path) || !matchesFilterExtension(path, FALLBACK_EXPORT_FILTERS)) {\n return undefined;\n }\n\n const format = tableFormatFromPath(path);\n if (format !== \"csv\" && format !== \"tsv\") {\n return undefined;\n }\n\n return pframe.writePTableToFs(nativeOptions.tableHandle, {\n path,\n format,\n columnIndices,\n ...(path.toLowerCase().endsWith(\".gz\") && { compression: { type: \"gzip\" } }),\n });\n}\n\nfunction formatTimestamp(d: Date): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return (\n `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()}` +\n `_${pad(d.getHours())}-${pad(d.getMinutes())}-${pad(d.getSeconds())}`\n );\n}\n\n/**\n * Checks whether the native CSV export capability is available in the\n * current platforma runtime environment. Both `Dialog` and `PFrame`\n * services must be present — desktop-app wires them, web/preview do not.\n */\nexport function isCsvExportAvailable(): boolean {\n try {\n const services = getServices();\n return !isNil(services?.dialog) && !isNil(services?.pframe);\n } catch {\n return false;\n }\n}\n\n/**\n * Collect unified column indices for visible (non-hidden) columns from the\n * ag-grid column defs, remapped onto the provided PTable spec array so the\n * indices match the current table handle (ColDef.field indices may be stale\n * or diverge from the spec order).\n */\nexport function collectVisibleColumnIndices(\n gridApi: GridApi,\n specs: PTableColumnSpec[],\n pframeSpec: PFrameSpecDriver,\n): Nil | number[] {\n const columnDefs = gridApi.getColumnDefs();\n if (isNil(columnDefs)) {\n return;\n }\n\n const findIndex = (spec: PTableColumnSpec) =>\n pframeSpec.findTableColumn(specs, getPTableColumnId(spec));\n\n const specsForDef = (def: ColDef | ColGroupDef): PTableColumnSpec[] => {\n if (\"children\" in def) return [];\n if (def.hide === true) return [];\n if (isNil(def.colId)) return [];\n if (def.colId === PlAgDataTableRowNumberColId) return [];\n return [def.context as PTableColumnSpec];\n };\n\n return [...new Set(columnDefs.flatMap(specsForDef).map(findIndex))].filter((idx) => idx !== -1);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"export-csv.js","names":[],"sources":["../../../src/components/PlAgCsvExporter/export-csv.ts"],"sourcesContent":["import { type ColDef, type ColGroupDef, type GridApi } from \"ag-grid-enterprise\";\nimport type {\n FileFilter,\n PTableHandle,\n PTableColumnSpec,\n PFrameSpecDriver,\n WritePTableToFsResult,\n} from \"@platforma-sdk/model\";\nimport { getPTableColumnId, XLSX_MAX_ROWS_PER_SHEET } from \"@platforma-sdk/model\";\nimport { isNil } from \"es-toolkit\";\nimport { Nil } from \"@milaboratories/helpers\";\nimport { getServices } from \"../../internal/getServices\";\nimport { PlAgDataTableRowNumberColId } from \"../PlAgDataTable\";\n\n/** Options for the native table export. */\nexport interface ExportOptions {\n tableHandle: PTableHandle;\n defaultFileName?: string;\n}\n\n/** Save-dialog file-type filters for the native `exportPTable` path. */\nconst NATIVE_EXPORT_FILTERS: FileFilter[] = [\n { name: \"CSV\", extensions: [\"csv\"] },\n { name: \"TSV\", extensions: [\"tsv\"] },\n { name: \"Parquet\", extensions: [\"parquet\"] },\n { name: \"Excel\", extensions: [\"xlsx\"] },\n];\n\n/**\n * Save-dialog file-type filters for the `writePTableToFs` fallback. csv/tsv\n * only, offered both plain and gzip-compressed — a trailing `.gz` in the\n * chosen path selects gzip compression.\n */\nconst FALLBACK_EXPORT_FILTERS: FileFilter[] = [\n { name: \"CSV (gzip)\", extensions: [\"csv.gz\"] },\n { name: \"CSV\", extensions: [\"csv\"] },\n { name: \"TSV (gzip)\", extensions: [\"tsv.gz\"] },\n { name: \"TSV\", extensions: [\"tsv\"] },\n];\n\n/** Table format from a save path, ignoring a trailing `.gz`. e.g. `\"t.csv.gz\"` → `\"csv\"`. */\nfunction tableFormatFromPath(path: string): string {\n const lower = path.toLowerCase();\n const base = lower.endsWith(\".gz\") ? lower.slice(0, -3) : lower;\n return base.slice(base.lastIndexOf(\".\") + 1);\n}\n\n/** True when `path` ends with one of the filters' extensions (e.g. `\".csv\"`). */\nfunction matchesFilterExtension(path: string, filters: FileFilter[]): boolean {\n return filters.some(({ extensions }) => extensions.some((ext) => path.endsWith(\".\" + ext)));\n}\n\n/**\n * Table export via the platforma desktop runtime. Prompts for a save\n * destination via the `Dialog` service — offering the available output formats\n * as file-type filters so the user picks the format — then writes the PTable to\n * the chosen path.\n *\n * Prefers the native `PFrame.exportPTable` when the runtime advertises it: the\n * table handle is the *visible* one, so exporting the whole handle reproduces\n * exactly the visible columns/rows, and the format (`csv`/`tsv`/`parquet`/\n * `xlsx`) is taken from the chosen file extension. Falls back to streaming the\n * visible columns via `PFrame.writePTableToFs` (`csv`/`tsv`, optionally\n * gzip-compressed when the chosen path ends in `.gz`) on runtimes that do not\n * advertise `exportPTable`.\n */\nexport async function exportCsv(\n gridApi: GridApi,\n nativeOptions: ExportOptions,\n): Promise<undefined | WritePTableToFsResult> {\n const { dialog, pframe, pframeSpec } = getServices();\n if (isNil(dialog)) {\n throw new Error(\"dialog service is not available in the current environment\");\n }\n if (isNil(pframe)) {\n throw new Error(\"pframe service is not available\");\n }\n if (isNil(pframeSpec)) {\n throw new Error(\"pframeSpec service is not available\");\n }\n\n const specs = await pframe.getSpec(nativeOptions.tableHandle);\n const columnIndices = collectVisibleColumnIndices(gridApi, specs, pframeSpec);\n if (isNil(columnIndices)) {\n return undefined;\n }\n\n const baseFileName = nativeOptions.defaultFileName ?? `table_${formatTimestamp(new Date())}`;\n\n if (typeof pframe.exportPTable === \"function\") {\n const { rows } = await pframe.getShape(nativeOptions.tableHandle);\n const filters =\n rows > XLSX_MAX_ROWS_PER_SHEET\n ? NATIVE_EXPORT_FILTERS.filter(({ name }) => name !== \"Excel\")\n : NATIVE_EXPORT_FILTERS;\n\n const { canceled, path } = await dialog.showSaveDialog({\n defaultFileName: `${baseFileName}.csv`,\n filters,\n });\n if (canceled || isNil(path) || !matchesFilterExtension(path, filters)) {\n return undefined;\n }\n\n await pframe.exportPTable(nativeOptions.tableHandle, { path, columnIndices });\n return undefined;\n }\n\n const { canceled, path } = await dialog.showSaveDialog({\n defaultFileName: `${baseFileName}.csv.gz`,\n filters: FALLBACK_EXPORT_FILTERS,\n });\n if (canceled || isNil(path) || !matchesFilterExtension(path, FALLBACK_EXPORT_FILTERS)) {\n return undefined;\n }\n\n const format = tableFormatFromPath(path);\n if (format !== \"csv\" && format !== \"tsv\") {\n return undefined;\n }\n\n return pframe.writePTableToFs(nativeOptions.tableHandle, {\n path,\n format,\n columnIndices,\n ...(path.toLowerCase().endsWith(\".gz\") && { compression: { type: \"gzip\" } }),\n });\n}\n\nfunction formatTimestamp(d: Date): string {\n const pad = (n: number) => String(n).padStart(2, \"0\");\n return (\n `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()}` +\n `_${pad(d.getHours())}-${pad(d.getMinutes())}-${pad(d.getSeconds())}`\n );\n}\n\n/**\n * Checks whether the native CSV export capability is available in the\n * current platforma runtime environment. Both `Dialog` and `PFrame`\n * services must be present — desktop-app wires them, web/preview do not.\n */\nexport function isCsvExportAvailable(): boolean {\n try {\n const services = getServices();\n return !isNil(services?.dialog) && !isNil(services?.pframe);\n } catch {\n return false;\n }\n}\n\n/**\n * Collect unified column indices for visible (non-hidden) columns from the\n * ag-grid column defs, remapped onto the provided PTable spec array so the\n * indices match the current table handle (ColDef.field indices may be stale\n * or diverge from the spec order).\n */\nexport function collectVisibleColumnIndices(\n gridApi: GridApi,\n specs: PTableColumnSpec[],\n pframeSpec: PFrameSpecDriver,\n): Nil | number[] {\n const columnDefs = gridApi.getColumnDefs();\n if (isNil(columnDefs)) {\n return;\n }\n\n const findIndex = (spec: PTableColumnSpec) =>\n pframeSpec.findTableColumn(specs, getPTableColumnId(spec));\n\n const specsForDef = (def: ColDef | ColGroupDef): PTableColumnSpec[] => {\n if (\"children\" in def) return [];\n if (def.hide === true) return [];\n if (isNil(def.colId)) return [];\n if (def.colId === PlAgDataTableRowNumberColId) return [];\n return [def.context as PTableColumnSpec];\n };\n\n return [...new Set(columnDefs.flatMap(specsForDef).map(findIndex))].filter((idx) => idx !== -1);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platforma-sdk/ui-vue",
3
- "version": "1.78.6",
3
+ "version": "1.78.7",
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
- "@platforma-sdk/model": "1.78.6",
30
- "@milaboratories/pl-model-common": "1.45.0",
31
- "@milaboratories/uikit": "2.14.23",
32
- "@milaboratories/pf-spec-driver": "1.4.4"
29
+ "@milaboratories/pf-spec-driver": "1.4.5",
30
+ "@milaboratories/uikit": "2.14.24",
31
+ "@milaboratories/pl-model-common": "1.46.0",
32
+ "@platforma-sdk/model": "1.78.7"
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/ts-builder": "1.5.0",
49
48
  "@milaboratories/helpers": "1.14.2",
50
49
  "@milaboratories/build-configs": "2.0.0",
50
+ "@milaboratories/ts-builder": "1.5.0",
51
51
  "@milaboratories/ts-configs": "1.2.3"
52
52
  },
53
53
  "scripts": {
@@ -6,7 +6,7 @@ import type {
6
6
  PFrameSpecDriver,
7
7
  WritePTableToFsResult,
8
8
  } from "@platforma-sdk/model";
9
- import { getPTableColumnId } from "@platforma-sdk/model";
9
+ import { getPTableColumnId, XLSX_MAX_ROWS_PER_SHEET } from "@platforma-sdk/model";
10
10
  import { isNil } from "es-toolkit";
11
11
  import { Nil } from "@milaboratories/helpers";
12
12
  import { getServices } from "../../internal/getServices";
@@ -88,11 +88,17 @@ export async function exportCsv(
88
88
  const baseFileName = nativeOptions.defaultFileName ?? `table_${formatTimestamp(new Date())}`;
89
89
 
90
90
  if (typeof pframe.exportPTable === "function") {
91
+ const { rows } = await pframe.getShape(nativeOptions.tableHandle);
92
+ const filters =
93
+ rows > XLSX_MAX_ROWS_PER_SHEET
94
+ ? NATIVE_EXPORT_FILTERS.filter(({ name }) => name !== "Excel")
95
+ : NATIVE_EXPORT_FILTERS;
96
+
91
97
  const { canceled, path } = await dialog.showSaveDialog({
92
98
  defaultFileName: `${baseFileName}.csv`,
93
- filters: NATIVE_EXPORT_FILTERS,
99
+ filters,
94
100
  });
95
- if (canceled || isNil(path) || !matchesFilterExtension(path, NATIVE_EXPORT_FILTERS)) {
101
+ if (canceled || isNil(path) || !matchesFilterExtension(path, filters)) {
96
102
  return undefined;
97
103
  }
98
104