flexdesk 0.14.0 → 0.14.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.
- package/README.md +19 -0
- package/dist/charts.js +2 -2
- package/dist/{chunk-M2L4XW2U.js → chunk-FBGP5KN5.js} +33 -21
- package/dist/chunk-FBGP5KN5.js.map +7 -0
- package/dist/{chunk-IYMNDPWH.js → chunk-RQM5Z2MU.js} +2 -2
- package/dist/flow.js +1 -1
- package/dist/tiles.js +11 -3
- package/dist/tiles.js.map +2 -2
- package/dist/widgets.js +1 -1
- package/package.json +1 -1
- package/src/tiles/chart_tiles.js +14 -1
- package/src/ui/components/data_table.js +32 -14
- package/dist/chunk-M2L4XW2U.js.map +0 -7
- /package/dist/{chunk-IYMNDPWH.js.map → chunk-RQM5Z2MU.js.map} +0 -0
package/dist/widgets.js
CHANGED
package/package.json
CHANGED
package/src/tiles/chart_tiles.js
CHANGED
|
@@ -528,9 +528,22 @@ export class ChartTile extends TileBase {
|
|
|
528
528
|
try {
|
|
529
529
|
const P = await ensurePlotly();
|
|
530
530
|
const uri = await P.toImage(this._plotEl, { format: 'png', scale: 2 });
|
|
531
|
+
const filename = `${slug(this.config.title || this.constructor.TITLE)}.png`;
|
|
532
|
+
// The native Save dialog when the host has one (a desktop window).
|
|
533
|
+
// `saveFile` answers null when there is no dialog behind it, which
|
|
534
|
+
// means "download it yourself", not a failed save.
|
|
535
|
+
const dialogs = this.host?.dialogs;
|
|
536
|
+
const result = dialogs
|
|
537
|
+
? await dialogs.saveFile({ data: uri.split(',')[1], filename, kind: 'png' })
|
|
538
|
+
: null;
|
|
539
|
+
if (result) {
|
|
540
|
+
if (result.ok) this._notify('Download', `Chart saved to ${result.path}`, 'success');
|
|
541
|
+
else if (!result.cancelled) this._notify('Download failed', result.error || 'The image could not be saved', 'error');
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
531
544
|
const a = document.createElement('a');
|
|
532
545
|
a.href = uri;
|
|
533
|
-
a.download =
|
|
546
|
+
a.download = filename;
|
|
534
547
|
a.click();
|
|
535
548
|
} catch (err) {
|
|
536
549
|
this._notify('Download failed', `The image could not be made: ${err?.message || err}`, 'error');
|
|
@@ -327,7 +327,8 @@ const AUTOSIZE_MAX_PX = 520;
|
|
|
327
327
|
* @property {Function} [onRowClick] - Row click handler: (rowIdx, row, ev) => void. Receives the original (unfiltered) row index.
|
|
328
328
|
* @property {Function} [onRowContextMenu] - Row right-click handler: (rowIdx, row, ev) => void. Fires before the default context menu; call ev.preventDefault() to suppress the default.
|
|
329
329
|
* @property {Function} [onCellContextMenu] - Cell right-click handler: (colIdx, rowIdx, value, td, ev) => void. Fires before onRowContextMenu; same suppression semantics.
|
|
330
|
-
* @property {boolean} [showExportButton=false] - Adds a "CSV" download button to the pagination strip that invokes `downloadCSV()`.
|
|
330
|
+
* @property {boolean} [showExportButton=false] - Adds a "CSV" download button to the pagination strip that invokes `downloadCSV()`. The strip is drawn for it even when the table fits on one page (0.14.1).
|
|
331
|
+
* @property {string|function(DataTable): string} [exportFilename='data.csv'] - The file the export button saves (0.14.1); in a desktop host, the name the Save dialog suggests.
|
|
331
332
|
* @property {Object} [host] - A Host (see ui/js/host/host.js). Its `dialogs` capability backs `downloadCSV()`'s native save dialog; without it CSV export falls back to a Blob download.
|
|
332
333
|
* @property {Object} [stateStore] - `{ ready(), get(key), set(key, state) }` — REQUIRED when `persistKey` is set. Built by `createTableStateStore()`.
|
|
333
334
|
* @property {'container'|'content'} [columnFit='container'] - How the automatic fit pass sizes a column the user has NOT dragged. 'container' squeezes every column into the wrap: a 360px cap, a more generous one for the first column, and water-fill-shrink toward the 40px floor when they do not fit. 'content' sizes each column to its own content through the same `_autoWidth` a grip double-click uses (520px cap) and lets the body scroll sideways rather than squeezing. A pinned column is honoured verbatim under both.
|
|
@@ -466,6 +467,7 @@ export class DataTable {
|
|
|
466
467
|
onRowContextMenu: null,
|
|
467
468
|
onCellContextMenu: null,
|
|
468
469
|
showExportButton: false,
|
|
470
|
+
exportFilename: null,
|
|
469
471
|
// The host port. TOP LEVEL, deliberately — NOT inside `services`,
|
|
470
472
|
// which most call sites never pass. Supplies the native save
|
|
471
473
|
// dialog for downloadCSV(); absent => Blob fallback.
|
|
@@ -2623,7 +2625,7 @@ export class DataTable {
|
|
|
2623
2625
|
// Don't render the strip when there's only one page — the row
|
|
2624
2626
|
// count is uninformative (the table itself shows every row) and
|
|
2625
2627
|
// the nav buttons would all be disabled.
|
|
2626
|
-
if (totalPages <= 1 && !isFiltered) return
|
|
2628
|
+
if (totalPages <= 1 && !isFiltered) return this._createExportOnlyStrip();
|
|
2627
2629
|
const currentPage = Math.floor(offset / pageSize) + 1;
|
|
2628
2630
|
const hasPrev = offset > 0;
|
|
2629
2631
|
const hasNext = offset + pageSize < effectiveTotal;
|
|
@@ -2719,16 +2721,35 @@ export class DataTable {
|
|
|
2719
2721
|
// CSV export button (opt-in). Re-uses the existing downloadCSV
|
|
2720
2722
|
// method which already handles the host save dialog + browser
|
|
2721
2723
|
// fallback.
|
|
2722
|
-
if (this.config.showExportButton)
|
|
2723
|
-
const exportBtn = this._createPaginationBtn(
|
|
2724
|
-
'download', 'Download visible rows as CSV', false,
|
|
2725
|
-
() => this.downloadCSV('data.csv'));
|
|
2726
|
-
el.appendChild(exportBtn);
|
|
2727
|
-
}
|
|
2724
|
+
if (this.config.showExportButton) el.appendChild(this._createExportBtn());
|
|
2728
2725
|
|
|
2729
2726
|
return el;
|
|
2730
2727
|
}
|
|
2731
2728
|
|
|
2729
|
+
/** The export button: downloadCSV() under the configured file name. */
|
|
2730
|
+
_createExportBtn() {
|
|
2731
|
+
const name = this.config.exportFilename;
|
|
2732
|
+
const filename = (typeof name === 'function' ? name(this) : name) || 'data.csv';
|
|
2733
|
+
return this._createPaginationBtn('download', 'Download visible rows as CSV', false,
|
|
2734
|
+
() => this.downloadCSV(filename));
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
/**
|
|
2738
|
+
* The strip on a table with one page: nothing, as always, unless the export
|
|
2739
|
+
* button needs somewhere to be. Then the button alone, with no page
|
|
2740
|
+
* buttons (0.14.1).
|
|
2741
|
+
*/
|
|
2742
|
+
_createExportOnlyStrip() {
|
|
2743
|
+
if (!this.config.showExportButton) return null;
|
|
2744
|
+
const el = document.createElement('div');
|
|
2745
|
+
el.className = 'twm-pagination-controls twm-pagination-controls--export-only';
|
|
2746
|
+
el.style.cssText = 'display:flex; align-items:center; gap:6px; padding:2px 8px; border-bottom:1px solid #2a2a2a; font-size:11px;';
|
|
2747
|
+
const spacer = document.createElement('div');
|
|
2748
|
+
spacer.style.flex = '1';
|
|
2749
|
+
el.append(spacer, this._createExportBtn());
|
|
2750
|
+
return el;
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2732
2753
|
_createPaginationBtn(icon, tooltip, disabled, onClick, textLabel = null) {
|
|
2733
2754
|
const btn = document.createElement('button');
|
|
2734
2755
|
btn.type = 'button';
|
|
@@ -4738,8 +4759,8 @@ export class DataTable {
|
|
|
4738
4759
|
const pn = this._pageNav({ offset, held: drawn, total, hasMore: hasMoreKnown, pageSize });
|
|
4739
4760
|
const { hasPrev, hasNext, page } = pn;
|
|
4740
4761
|
const totalPages = pn.pages;
|
|
4741
|
-
if (known && totalPages <= 1 && !isFiltered && !hasPrev) return
|
|
4742
|
-
if (!known && !hasPrev && !hasNext) return
|
|
4762
|
+
if (known && totalPages <= 1 && !isFiltered && !hasPrev) return this._createExportOnlyStrip();
|
|
4763
|
+
if (!known && !hasPrev && !hasNext) return this._createExportOnlyStrip();
|
|
4743
4764
|
const maxJump = Number.isFinite(c.maxJumpOffset) ? c.maxJumpOffset : null;
|
|
4744
4765
|
|
|
4745
4766
|
const go = (newOffset) => {
|
|
@@ -4817,10 +4838,7 @@ export class DataTable {
|
|
|
4817
4838
|
jumpBtn.dataset.pager = 'go';
|
|
4818
4839
|
|
|
4819
4840
|
el.append(info, spacer, firstBtn, prevBtn, pageInfo, nextBtn, lastBtn, jumpInput, jumpBtn);
|
|
4820
|
-
if (c.showExportButton)
|
|
4821
|
-
el.appendChild(this._createPaginationBtn('download', 'Download visible rows as CSV', false,
|
|
4822
|
-
() => this.downloadCSV('data.csv')));
|
|
4823
|
-
}
|
|
4841
|
+
if (c.showExportButton) el.appendChild(this._createExportBtn());
|
|
4824
4842
|
return el;
|
|
4825
4843
|
}
|
|
4826
4844
|
|