@harbortouch/skytab-analytics-report-utils 0.41.10 → 0.41.12
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/dist/{chunk-ENBT7KRJ.js → chunk-UUKHJDV3.js} +6 -1
- package/dist/exporters/excel/index.d.cts +2 -2
- package/dist/exporters/excel/index.d.ts +2 -2
- package/dist/exporters/exportBuilder.cjs +15 -5
- package/dist/exporters/exportBuilder.d.cts +2 -2
- package/dist/exporters/exportBuilder.d.ts +2 -2
- package/dist/exporters/exportBuilder.js +9 -2
- package/dist/exporters/pdf/index.cjs +74 -38
- package/dist/exporters/pdf/index.d.cts +2 -1
- package/dist/exporters/pdf/index.d.ts +2 -1
- package/dist/exporters/pdf/index.js +74 -38
- package/dist/index.cjs +8 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{report-LuHGzrLx.d.cts → report-Dj8UU5d_.d.cts} +2 -2
- package/dist/{report-LuHGzrLx.d.ts → report-Dj8UU5d_.d.ts} +2 -2
- package/dist/{types-JAEAu4KX.d.ts → types-D3IyO__4.d.cts} +1 -0
- package/dist/{types-JAEAu4KX.d.cts → types-D3IyO__4.d.ts} +1 -0
- package/package.json +1 -1
|
@@ -2838,6 +2838,7 @@ var dailySalesTrendsOrderTypeConfig = {
|
|
|
2838
2838
|
};
|
|
2839
2839
|
|
|
2840
2840
|
// src/report.ts
|
|
2841
|
+
import { isValid, parseISO } from "date-fns";
|
|
2841
2842
|
var Report = {
|
|
2842
2843
|
TICKET_LIVE: "ticket-live",
|
|
2843
2844
|
TICKET_ANALYTICS: "ticket-analytics",
|
|
@@ -2911,7 +2912,11 @@ var getReportExportFileName = ({
|
|
|
2911
2912
|
endDate,
|
|
2912
2913
|
format
|
|
2913
2914
|
}) => {
|
|
2914
|
-
const formatDate2 = (
|
|
2915
|
+
const formatDate2 = (value) => {
|
|
2916
|
+
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}/.test(value) && isValid(parseISO(value))) {
|
|
2917
|
+
return value.slice(0, 10);
|
|
2918
|
+
}
|
|
2919
|
+
const date = typeof value === "string" ? new Date(value) : value;
|
|
2915
2920
|
return [
|
|
2916
2921
|
date.getFullYear(),
|
|
2917
2922
|
String(date.getMonth() + 1).padStart(2, "0"),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ExportSection } from '../../types-
|
|
2
|
-
export { E as XlsxFilter, b as XlsxTable, c as XlsxTableColumn } from '../../types-
|
|
1
|
+
import { a as ExportSection } from '../../types-D3IyO__4.cjs';
|
|
2
|
+
export { E as XlsxFilter, b as XlsxTable, c as XlsxTableColumn } from '../../types-D3IyO__4.cjs';
|
|
3
3
|
|
|
4
4
|
declare class ExcelExporter {
|
|
5
5
|
generate(content: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as ExportSection } from '../../types-
|
|
2
|
-
export { E as XlsxFilter, b as XlsxTable, c as XlsxTableColumn } from '../../types-
|
|
1
|
+
import { a as ExportSection } from '../../types-D3IyO__4.js';
|
|
2
|
+
export { E as XlsxFilter, b as XlsxTable, c as XlsxTableColumn } from '../../types-D3IyO__4.js';
|
|
3
3
|
|
|
4
4
|
declare class ExcelExporter {
|
|
5
5
|
generate(content: {
|
|
@@ -1861,6 +1861,9 @@ var formatFieldValue = (value, type, localeOptions, fullRecord, fieldConfig = DE
|
|
|
1861
1861
|
}
|
|
1862
1862
|
};
|
|
1863
1863
|
|
|
1864
|
+
// src/report.ts
|
|
1865
|
+
var import_date_fns = require("date-fns");
|
|
1866
|
+
|
|
1864
1867
|
// src/reports/salesByItemDetail.ts
|
|
1865
1868
|
var FIELDS = {
|
|
1866
1869
|
businessDate: { type: "date", columnKey: "date", filteringAvailable: false },
|
|
@@ -4021,7 +4024,7 @@ function resolveRawFiltersToExportFilters(rawFilters, locale, reportType) {
|
|
|
4021
4024
|
}
|
|
4022
4025
|
|
|
4023
4026
|
// src/exporters/exportBuilder.ts
|
|
4024
|
-
var
|
|
4027
|
+
var import_date_fns2 = require("date-fns");
|
|
4025
4028
|
var ExportBuilder = class {
|
|
4026
4029
|
constructor(reportType, locations, locale) {
|
|
4027
4030
|
this.reportType = reportType;
|
|
@@ -4143,7 +4146,10 @@ var ExportBuilder = class {
|
|
|
4143
4146
|
renderTableContent(config, reportData, parameters) {
|
|
4144
4147
|
const data = this.getDataForConfig(reportData, config);
|
|
4145
4148
|
const { columns, headers, columnTypes } = this.resolveColumnsAndHeaders(parameters, config);
|
|
4146
|
-
const tableColumns = columns.map((col, i) =>
|
|
4149
|
+
const tableColumns = columns.map((col, i) => {
|
|
4150
|
+
const size = config.fields[col]?.size;
|
|
4151
|
+
return { header: headers[i], key: col, ...size !== void 0 ? { size } : {} };
|
|
4152
|
+
});
|
|
4147
4153
|
const rows = data.filter((row) => typeof row === "object" && row !== null).map((row) => this.formatRow(row, columns, columnTypes, row));
|
|
4148
4154
|
if (config.hasFooter) {
|
|
4149
4155
|
const totalsRow = this.buildTotalsRow(data, config);
|
|
@@ -4163,11 +4169,14 @@ var ExportBuilder = class {
|
|
|
4163
4169
|
return config.dataAccessKey ? data[config.dataAccessKey] ?? [] : [];
|
|
4164
4170
|
}
|
|
4165
4171
|
formatMaybeDate(value) {
|
|
4166
|
-
|
|
4167
|
-
|
|
4172
|
+
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}/.test(value) && (0, import_date_fns2.isValid)((0, import_date_fns2.parseISO)(value))) {
|
|
4173
|
+
return value.slice(0, 10);
|
|
4174
|
+
}
|
|
4175
|
+
const date = typeof value === "string" ? (0, import_date_fns2.parseISO)(value) : value;
|
|
4176
|
+
if (!(0, import_date_fns2.isValid)(date)) {
|
|
4168
4177
|
return "";
|
|
4169
4178
|
}
|
|
4170
|
-
return (0,
|
|
4179
|
+
return (0, import_date_fns2.format)(date, "yyyy-MM-dd");
|
|
4171
4180
|
}
|
|
4172
4181
|
buildReportMetadataFilters(parameters, name, meta) {
|
|
4173
4182
|
const locationNames = this.locations.map((l) => l.name).join(", ");
|
|
@@ -4208,6 +4217,7 @@ var ExportBuilder = class {
|
|
|
4208
4217
|
day: "numeric",
|
|
4209
4218
|
hour: "numeric",
|
|
4210
4219
|
minute: "2-digit",
|
|
4220
|
+
timeZone: this.locations[0]?.timezone ?? "UTC",
|
|
4211
4221
|
timeZoneName: "short"
|
|
4212
4222
|
}).format(meta.generatedAt);
|
|
4213
4223
|
filters.push({ label: this.translate("scheduled-reports.generated-at"), value: formatted });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as ReportType, A as AnalyticsField } from '../report-
|
|
2
|
-
import { E as ExportFilter, R as ReportMetadata, a as ExportSection } from '../types-
|
|
1
|
+
import { R as ReportType, A as AnalyticsField } from '../report-Dj8UU5d_.cjs';
|
|
2
|
+
import { E as ExportFilter, R as ReportMetadata, a as ExportSection } from '../types-D3IyO__4.cjs';
|
|
3
3
|
|
|
4
4
|
declare function resolveRawFiltersToExportFilters(rawFilters: Record<string, (string | number)[] | undefined>, locale: string, reportType?: ReportType): ExportFilter[];
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { R as ReportType, A as AnalyticsField } from '../report-
|
|
2
|
-
import { E as ExportFilter, R as ReportMetadata, a as ExportSection } from '../types-
|
|
1
|
+
import { R as ReportType, A as AnalyticsField } from '../report-Dj8UU5d_.js';
|
|
2
|
+
import { E as ExportFilter, R as ReportMetadata, a as ExportSection } from '../types-D3IyO__4.js';
|
|
3
3
|
|
|
4
4
|
declare function resolveRawFiltersToExportFilters(rawFilters: Record<string, (string | number)[] | undefined>, locale: string, reportType?: ReportType): ExportFilter[];
|
|
5
5
|
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
getReportFormattingLocaleOptions,
|
|
9
9
|
getReportName,
|
|
10
10
|
resolveTranslate
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-UUKHJDV3.js";
|
|
12
12
|
|
|
13
13
|
// src/utils/filter-resolver.ts
|
|
14
14
|
var ANALYTICS_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -197,7 +197,10 @@ var ExportBuilder = class {
|
|
|
197
197
|
renderTableContent(config, reportData, parameters) {
|
|
198
198
|
const data = this.getDataForConfig(reportData, config);
|
|
199
199
|
const { columns, headers, columnTypes } = this.resolveColumnsAndHeaders(parameters, config);
|
|
200
|
-
const tableColumns = columns.map((col, i) =>
|
|
200
|
+
const tableColumns = columns.map((col, i) => {
|
|
201
|
+
const size = config.fields[col]?.size;
|
|
202
|
+
return { header: headers[i], key: col, ...size !== void 0 ? { size } : {} };
|
|
203
|
+
});
|
|
201
204
|
const rows = data.filter((row) => typeof row === "object" && row !== null).map((row) => this.formatRow(row, columns, columnTypes, row));
|
|
202
205
|
if (config.hasFooter) {
|
|
203
206
|
const totalsRow = this.buildTotalsRow(data, config);
|
|
@@ -217,6 +220,9 @@ var ExportBuilder = class {
|
|
|
217
220
|
return config.dataAccessKey ? data[config.dataAccessKey] ?? [] : [];
|
|
218
221
|
}
|
|
219
222
|
formatMaybeDate(value) {
|
|
223
|
+
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}/.test(value) && isValid(parseISO(value))) {
|
|
224
|
+
return value.slice(0, 10);
|
|
225
|
+
}
|
|
220
226
|
const date = typeof value === "string" ? parseISO(value) : value;
|
|
221
227
|
if (!isValid(date)) {
|
|
222
228
|
return "";
|
|
@@ -262,6 +268,7 @@ var ExportBuilder = class {
|
|
|
262
268
|
day: "numeric",
|
|
263
269
|
hour: "numeric",
|
|
264
270
|
minute: "2-digit",
|
|
271
|
+
timeZone: this.locations[0]?.timezone ?? "UTC",
|
|
265
272
|
timeZoneName: "short"
|
|
266
273
|
}).format(meta.generatedAt);
|
|
267
274
|
filters.push({ label: this.translate("scheduled-reports.generated-at"), value: formatted });
|
|
@@ -207,7 +207,14 @@ var PdfExporter = class {
|
|
|
207
207
|
const dataFontSize = columnCount > 13 ? 5 : columnCount > 10 ? 6 : columnCount > 7 ? 7 : 8;
|
|
208
208
|
const headerWidthSlack = 2;
|
|
209
209
|
const headerMinWidths = /* @__PURE__ */ new Map();
|
|
210
|
+
const cssPixelsToPoints = 0.75;
|
|
211
|
+
const boundedColumns = /* @__PURE__ */ new Set();
|
|
210
212
|
columns.forEach((col) => {
|
|
213
|
+
if (col.size !== void 0 && Number.isFinite(col.size) && col.size > 0) {
|
|
214
|
+
col.width = col.size * cssPixelsToPoints;
|
|
215
|
+
boundedColumns.add(col);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
211
218
|
doc.font(FONT_BOLD).fontSize(headerFontSize);
|
|
212
219
|
const headerTextWidth = doc.widthOfString(col.header);
|
|
213
220
|
const headerMinWidth = Math.max(...col.header.split(" ").map((w) => doc.widthOfString(w)));
|
|
@@ -226,49 +233,50 @@ var PdfExporter = class {
|
|
|
226
233
|
headerMinWidths.set(col, headerMinWidth + TABLE_CELL_PADDING * 2 + headerWidthSlack);
|
|
227
234
|
});
|
|
228
235
|
const usableWidth = doc.page.width - doc.page.margins.left - doc.page.margins.right;
|
|
236
|
+
const minimumColumnWidth = Math.min(MIN_COLUMN_WIDTH, usableWidth / columnCount);
|
|
229
237
|
const totalColumnWidth = columns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0);
|
|
230
238
|
if (totalColumnWidth > usableWidth) {
|
|
231
239
|
const scale = usableWidth / totalColumnWidth;
|
|
232
240
|
columns.forEach((c) => {
|
|
233
|
-
const
|
|
234
|
-
|
|
241
|
+
const width = c.width ?? MIN_COLUMN_WIDTH;
|
|
242
|
+
const headerMin = headerMinWidths.get(c) ?? minimumColumnWidth;
|
|
243
|
+
const minimumWidth = Math.min(width, Math.max(headerMin, minimumColumnWidth));
|
|
244
|
+
c.width = Math.max(Math.floor(width * scale), minimumWidth);
|
|
235
245
|
});
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
246
|
+
const excess = columns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0) - usableWidth;
|
|
247
|
+
if (excess > 0) {
|
|
248
|
+
const reducibleWidth = columns.reduce(
|
|
249
|
+
(sum, c) => sum + Math.max((c.width ?? MIN_COLUMN_WIDTH) - minimumColumnWidth, 0),
|
|
250
|
+
0
|
|
251
|
+
);
|
|
252
|
+
if (reducibleWidth > 0) {
|
|
253
|
+
columns.forEach((c) => {
|
|
254
|
+
const width = c.width ?? MIN_COLUMN_WIDTH;
|
|
255
|
+
const available = Math.max(width - minimumColumnWidth, 0);
|
|
256
|
+
c.width = width - excess * (available / reducibleWidth);
|
|
257
|
+
});
|
|
244
258
|
}
|
|
245
259
|
}
|
|
246
260
|
} else if (totalColumnWidth < usableWidth) {
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
261
|
+
const expandableColumns = columns.filter((c) => !boundedColumns.has(c));
|
|
262
|
+
const expandableWidth = expandableColumns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0);
|
|
263
|
+
if (expandableWidth > 0) {
|
|
264
|
+
const scale = (expandableWidth + usableWidth - totalColumnWidth) / expandableWidth;
|
|
265
|
+
expandableColumns.forEach((c) => {
|
|
266
|
+
c.width = Math.floor((c.width ?? MIN_COLUMN_WIDTH) * scale);
|
|
267
|
+
});
|
|
268
|
+
const expanded = columns.reduce((sum, c) => sum + (c.width ?? 0), 0);
|
|
269
|
+
const lastExpandableColumn = expandableColumns[expandableColumns.length - 1];
|
|
270
|
+
lastExpandableColumn.width = (lastExpandableColumn.width ?? 0) + (usableWidth - expanded);
|
|
271
|
+
}
|
|
253
272
|
}
|
|
254
273
|
const tableWidth = columns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0);
|
|
255
274
|
const pageBottom = doc.page.height - doc.page.margins.bottom;
|
|
256
|
-
const calculateRowHeight = (
|
|
257
|
-
|
|
258
|
-
doc.
|
|
259
|
-
let maxLines = 1;
|
|
260
|
-
columns.forEach((col) => {
|
|
261
|
-
const cellValue = isHeader ? col.header : row?.[col.key] !== void 0 ? String(row[col.key]) : "";
|
|
262
|
-
const textWidth = doc.widthOfString(cellValue);
|
|
263
|
-
const availableWidth = (col.width ?? MIN_COLUMN_WIDTH) - TABLE_CELL_PADDING * 2;
|
|
264
|
-
const lines = Math.ceil(textWidth / availableWidth);
|
|
265
|
-
if (lines > maxLines) {
|
|
266
|
-
maxLines = lines;
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
return Math.max(maxLines * (fontSize + 2) + TABLE_CELL_PADDING * 2, DEFAULT_ROW_HEIGHT);
|
|
275
|
+
const calculateRowHeight = (isHeader = false) => {
|
|
276
|
+
doc.font(isHeader ? FONT_BOLD : FONT_REGULAR).fontSize(isHeader ? headerFontSize : dataFontSize);
|
|
277
|
+
return Math.max(doc.currentLineHeight(true) + TABLE_CELL_PADDING * 2, DEFAULT_ROW_HEIGHT);
|
|
270
278
|
};
|
|
271
|
-
const headerHeight = calculateRowHeight(
|
|
279
|
+
const headerHeight = calculateRowHeight(true);
|
|
272
280
|
const drawTableHeader = (y) => this.drawHeader(doc, columns, y, tableWidth, headerHeight, TABLE_CELL_PADDING, headerFontSize, MIN_COLUMN_WIDTH);
|
|
273
281
|
let tableStartY = startY;
|
|
274
282
|
if (tableStartY + headerHeight > pageBottom) {
|
|
@@ -278,7 +286,7 @@ var PdfExporter = class {
|
|
|
278
286
|
let currentY = drawTableHeader(tableStartY);
|
|
279
287
|
doc.font(FONT_REGULAR).fontSize(dataFontSize);
|
|
280
288
|
rows.forEach((row, rowIndex) => {
|
|
281
|
-
const currentRowHeight = calculateRowHeight(
|
|
289
|
+
const currentRowHeight = calculateRowHeight();
|
|
282
290
|
if (currentY + currentRowHeight > pageBottom) {
|
|
283
291
|
doc.addPage();
|
|
284
292
|
currentY = drawTableHeader(doc.page.margins.top);
|
|
@@ -301,6 +309,28 @@ var PdfExporter = class {
|
|
|
301
309
|
doc.strokeColor(HEADER_RULE_COLOR).lineWidth(HEADER_RULE_WIDTH).moveTo(left, closingRuleY).lineTo(left + tableWidth, closingRuleY).stroke();
|
|
302
310
|
return closingRuleY;
|
|
303
311
|
}
|
|
312
|
+
truncateTextToWidth(doc, text, availableWidth) {
|
|
313
|
+
if (doc.widthOfString(text) <= availableWidth) {
|
|
314
|
+
return text;
|
|
315
|
+
}
|
|
316
|
+
const ellipsis = "\u2026";
|
|
317
|
+
if (doc.widthOfString(ellipsis) > availableWidth) {
|
|
318
|
+
return "";
|
|
319
|
+
}
|
|
320
|
+
const characters = Array.from(text);
|
|
321
|
+
let low = 0;
|
|
322
|
+
let high = characters.length;
|
|
323
|
+
while (low < high) {
|
|
324
|
+
const middle = Math.ceil((low + high) / 2);
|
|
325
|
+
const candidate = `${characters.slice(0, middle).join("").trimEnd()}${ellipsis}`;
|
|
326
|
+
if (doc.widthOfString(candidate) <= availableWidth) {
|
|
327
|
+
low = middle;
|
|
328
|
+
} else {
|
|
329
|
+
high = middle - 1;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return `${characters.slice(0, low).join("").trimEnd()}${ellipsis}`;
|
|
333
|
+
}
|
|
304
334
|
drawHeader(doc, columns, startY, tableWidth, headerHeight, cellPadding, headerFontSize, minColumnWidth) {
|
|
305
335
|
const left = doc.page.margins.left;
|
|
306
336
|
doc.rect(left, startY, tableWidth, headerHeight).fill(HEADER_BACKGROUND_COLOR);
|
|
@@ -310,12 +340,15 @@ var PdfExporter = class {
|
|
|
310
340
|
const headerLineHeight = doc.currentLineHeight(true);
|
|
311
341
|
const headerTextY = startY + Math.max((headerHeight - headerLineHeight) / 2, 0);
|
|
312
342
|
columns.forEach((col) => {
|
|
313
|
-
|
|
314
|
-
|
|
343
|
+
const innerWidth = (col.width ?? minColumnWidth) - cellPadding * 2;
|
|
344
|
+
const bounded = col.size !== void 0 && Number.isFinite(col.size) && col.size > 0;
|
|
345
|
+
const headerText = bounded ? this.truncateTextToWidth(doc, col.header, innerWidth) : col.header;
|
|
346
|
+
doc.text(headerText, xPosition + cellPadding, headerTextY, {
|
|
347
|
+
width: innerWidth,
|
|
315
348
|
height: headerLineHeight,
|
|
316
349
|
align: "left",
|
|
317
350
|
lineBreak: false,
|
|
318
|
-
ellipsis:
|
|
351
|
+
ellipsis: !bounded
|
|
319
352
|
});
|
|
320
353
|
xPosition += col.width ?? minColumnWidth;
|
|
321
354
|
});
|
|
@@ -336,12 +369,15 @@ var PdfExporter = class {
|
|
|
336
369
|
const rawValue = row[col.key];
|
|
337
370
|
const cellValue = typeof rawValue === "string" || typeof rawValue === "number" || typeof rawValue === "boolean" ? String(rawValue) : "";
|
|
338
371
|
const isNumeric = typeof rawValue === "number" || typeof rawValue === "string" && rawValue !== "" && !isNaN(Number(rawValue));
|
|
339
|
-
|
|
340
|
-
|
|
372
|
+
const innerWidth = (col.width ?? minColumnWidth) - cellPadding * 2;
|
|
373
|
+
const bounded = col.size !== void 0 && Number.isFinite(col.size) && col.size > 0;
|
|
374
|
+
const rowText = bounded ? this.truncateTextToWidth(doc, cellValue, innerWidth) : cellValue;
|
|
375
|
+
doc.text(rowText, xPosition + cellPadding, dataTextY, {
|
|
376
|
+
width: innerWidth,
|
|
341
377
|
height: dataLineHeight,
|
|
342
378
|
align: isNumeric ? "right" : "left",
|
|
343
379
|
lineBreak: false,
|
|
344
|
-
ellipsis:
|
|
380
|
+
ellipsis: !bounded
|
|
345
381
|
});
|
|
346
382
|
xPosition += col.width ?? minColumnWidth;
|
|
347
383
|
if (i < columns.length - 1) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ExportSection, E as ExportFilter, b as ExportTable, c as ExportTableColumn } from '../../types-
|
|
1
|
+
import { a as ExportSection, E as ExportFilter, b as ExportTable, c as ExportTableColumn } from '../../types-D3IyO__4.cjs';
|
|
2
2
|
|
|
3
3
|
type MetaDataValue = ExportFilter[] | string;
|
|
4
4
|
declare class PdfExporter {
|
|
@@ -10,6 +10,7 @@ declare class PdfExporter {
|
|
|
10
10
|
drawSectionTitle(doc: PDFKit.PDFDocument, title: string, startY: number): number;
|
|
11
11
|
drawMetaData(doc: PDFKit.PDFDocument, metaData: Record<string, MetaDataValue>, startY: number): number;
|
|
12
12
|
drawTable(doc: PDFKit.PDFDocument, table: ExportTable, startY: number): number;
|
|
13
|
+
private truncateTextToWidth;
|
|
13
14
|
drawHeader(doc: PDFKit.PDFDocument, columns: ExportTableColumn[], startY: number, tableWidth: number, headerHeight: number, cellPadding: number, headerFontSize: number, minColumnWidth: number): number;
|
|
14
15
|
drawRow(doc: PDFKit.PDFDocument, row: Record<string, unknown>, columns: ExportTableColumn[], currentY: number, rowHeight: number, cellPadding: number, dataFontSize: number, minColumnWidth: number, rowIndex?: number): number;
|
|
15
16
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ExportSection, E as ExportFilter, b as ExportTable, c as ExportTableColumn } from '../../types-
|
|
1
|
+
import { a as ExportSection, E as ExportFilter, b as ExportTable, c as ExportTableColumn } from '../../types-D3IyO__4.js';
|
|
2
2
|
|
|
3
3
|
type MetaDataValue = ExportFilter[] | string;
|
|
4
4
|
declare class PdfExporter {
|
|
@@ -10,6 +10,7 @@ declare class PdfExporter {
|
|
|
10
10
|
drawSectionTitle(doc: PDFKit.PDFDocument, title: string, startY: number): number;
|
|
11
11
|
drawMetaData(doc: PDFKit.PDFDocument, metaData: Record<string, MetaDataValue>, startY: number): number;
|
|
12
12
|
drawTable(doc: PDFKit.PDFDocument, table: ExportTable, startY: number): number;
|
|
13
|
+
private truncateTextToWidth;
|
|
13
14
|
drawHeader(doc: PDFKit.PDFDocument, columns: ExportTableColumn[], startY: number, tableWidth: number, headerHeight: number, cellPadding: number, headerFontSize: number, minColumnWidth: number): number;
|
|
14
15
|
drawRow(doc: PDFKit.PDFDocument, row: Record<string, unknown>, columns: ExportTableColumn[], currentY: number, rowHeight: number, cellPadding: number, dataFontSize: number, minColumnWidth: number, rowIndex?: number): number;
|
|
15
16
|
}
|
|
@@ -167,7 +167,14 @@ var PdfExporter = class {
|
|
|
167
167
|
const dataFontSize = columnCount > 13 ? 5 : columnCount > 10 ? 6 : columnCount > 7 ? 7 : 8;
|
|
168
168
|
const headerWidthSlack = 2;
|
|
169
169
|
const headerMinWidths = /* @__PURE__ */ new Map();
|
|
170
|
+
const cssPixelsToPoints = 0.75;
|
|
171
|
+
const boundedColumns = /* @__PURE__ */ new Set();
|
|
170
172
|
columns.forEach((col) => {
|
|
173
|
+
if (col.size !== void 0 && Number.isFinite(col.size) && col.size > 0) {
|
|
174
|
+
col.width = col.size * cssPixelsToPoints;
|
|
175
|
+
boundedColumns.add(col);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
171
178
|
doc.font(FONT_BOLD).fontSize(headerFontSize);
|
|
172
179
|
const headerTextWidth = doc.widthOfString(col.header);
|
|
173
180
|
const headerMinWidth = Math.max(...col.header.split(" ").map((w) => doc.widthOfString(w)));
|
|
@@ -186,49 +193,50 @@ var PdfExporter = class {
|
|
|
186
193
|
headerMinWidths.set(col, headerMinWidth + TABLE_CELL_PADDING * 2 + headerWidthSlack);
|
|
187
194
|
});
|
|
188
195
|
const usableWidth = doc.page.width - doc.page.margins.left - doc.page.margins.right;
|
|
196
|
+
const minimumColumnWidth = Math.min(MIN_COLUMN_WIDTH, usableWidth / columnCount);
|
|
189
197
|
const totalColumnWidth = columns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0);
|
|
190
198
|
if (totalColumnWidth > usableWidth) {
|
|
191
199
|
const scale = usableWidth / totalColumnWidth;
|
|
192
200
|
columns.forEach((c) => {
|
|
193
|
-
const
|
|
194
|
-
|
|
201
|
+
const width = c.width ?? MIN_COLUMN_WIDTH;
|
|
202
|
+
const headerMin = headerMinWidths.get(c) ?? minimumColumnWidth;
|
|
203
|
+
const minimumWidth = Math.min(width, Math.max(headerMin, minimumColumnWidth));
|
|
204
|
+
c.width = Math.max(Math.floor(width * scale), minimumWidth);
|
|
195
205
|
});
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
206
|
+
const excess = columns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0) - usableWidth;
|
|
207
|
+
if (excess > 0) {
|
|
208
|
+
const reducibleWidth = columns.reduce(
|
|
209
|
+
(sum, c) => sum + Math.max((c.width ?? MIN_COLUMN_WIDTH) - minimumColumnWidth, 0),
|
|
210
|
+
0
|
|
211
|
+
);
|
|
212
|
+
if (reducibleWidth > 0) {
|
|
213
|
+
columns.forEach((c) => {
|
|
214
|
+
const width = c.width ?? MIN_COLUMN_WIDTH;
|
|
215
|
+
const available = Math.max(width - minimumColumnWidth, 0);
|
|
216
|
+
c.width = width - excess * (available / reducibleWidth);
|
|
217
|
+
});
|
|
204
218
|
}
|
|
205
219
|
}
|
|
206
220
|
} else if (totalColumnWidth < usableWidth) {
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
221
|
+
const expandableColumns = columns.filter((c) => !boundedColumns.has(c));
|
|
222
|
+
const expandableWidth = expandableColumns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0);
|
|
223
|
+
if (expandableWidth > 0) {
|
|
224
|
+
const scale = (expandableWidth + usableWidth - totalColumnWidth) / expandableWidth;
|
|
225
|
+
expandableColumns.forEach((c) => {
|
|
226
|
+
c.width = Math.floor((c.width ?? MIN_COLUMN_WIDTH) * scale);
|
|
227
|
+
});
|
|
228
|
+
const expanded = columns.reduce((sum, c) => sum + (c.width ?? 0), 0);
|
|
229
|
+
const lastExpandableColumn = expandableColumns[expandableColumns.length - 1];
|
|
230
|
+
lastExpandableColumn.width = (lastExpandableColumn.width ?? 0) + (usableWidth - expanded);
|
|
231
|
+
}
|
|
213
232
|
}
|
|
214
233
|
const tableWidth = columns.reduce((sum, c) => sum + (c.width ?? MIN_COLUMN_WIDTH), 0);
|
|
215
234
|
const pageBottom = doc.page.height - doc.page.margins.bottom;
|
|
216
|
-
const calculateRowHeight = (
|
|
217
|
-
|
|
218
|
-
doc.
|
|
219
|
-
let maxLines = 1;
|
|
220
|
-
columns.forEach((col) => {
|
|
221
|
-
const cellValue = isHeader ? col.header : row?.[col.key] !== void 0 ? String(row[col.key]) : "";
|
|
222
|
-
const textWidth = doc.widthOfString(cellValue);
|
|
223
|
-
const availableWidth = (col.width ?? MIN_COLUMN_WIDTH) - TABLE_CELL_PADDING * 2;
|
|
224
|
-
const lines = Math.ceil(textWidth / availableWidth);
|
|
225
|
-
if (lines > maxLines) {
|
|
226
|
-
maxLines = lines;
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
return Math.max(maxLines * (fontSize + 2) + TABLE_CELL_PADDING * 2, DEFAULT_ROW_HEIGHT);
|
|
235
|
+
const calculateRowHeight = (isHeader = false) => {
|
|
236
|
+
doc.font(isHeader ? FONT_BOLD : FONT_REGULAR).fontSize(isHeader ? headerFontSize : dataFontSize);
|
|
237
|
+
return Math.max(doc.currentLineHeight(true) + TABLE_CELL_PADDING * 2, DEFAULT_ROW_HEIGHT);
|
|
230
238
|
};
|
|
231
|
-
const headerHeight = calculateRowHeight(
|
|
239
|
+
const headerHeight = calculateRowHeight(true);
|
|
232
240
|
const drawTableHeader = (y) => this.drawHeader(doc, columns, y, tableWidth, headerHeight, TABLE_CELL_PADDING, headerFontSize, MIN_COLUMN_WIDTH);
|
|
233
241
|
let tableStartY = startY;
|
|
234
242
|
if (tableStartY + headerHeight > pageBottom) {
|
|
@@ -238,7 +246,7 @@ var PdfExporter = class {
|
|
|
238
246
|
let currentY = drawTableHeader(tableStartY);
|
|
239
247
|
doc.font(FONT_REGULAR).fontSize(dataFontSize);
|
|
240
248
|
rows.forEach((row, rowIndex) => {
|
|
241
|
-
const currentRowHeight = calculateRowHeight(
|
|
249
|
+
const currentRowHeight = calculateRowHeight();
|
|
242
250
|
if (currentY + currentRowHeight > pageBottom) {
|
|
243
251
|
doc.addPage();
|
|
244
252
|
currentY = drawTableHeader(doc.page.margins.top);
|
|
@@ -261,6 +269,28 @@ var PdfExporter = class {
|
|
|
261
269
|
doc.strokeColor(HEADER_RULE_COLOR).lineWidth(HEADER_RULE_WIDTH).moveTo(left, closingRuleY).lineTo(left + tableWidth, closingRuleY).stroke();
|
|
262
270
|
return closingRuleY;
|
|
263
271
|
}
|
|
272
|
+
truncateTextToWidth(doc, text, availableWidth) {
|
|
273
|
+
if (doc.widthOfString(text) <= availableWidth) {
|
|
274
|
+
return text;
|
|
275
|
+
}
|
|
276
|
+
const ellipsis = "\u2026";
|
|
277
|
+
if (doc.widthOfString(ellipsis) > availableWidth) {
|
|
278
|
+
return "";
|
|
279
|
+
}
|
|
280
|
+
const characters = Array.from(text);
|
|
281
|
+
let low = 0;
|
|
282
|
+
let high = characters.length;
|
|
283
|
+
while (low < high) {
|
|
284
|
+
const middle = Math.ceil((low + high) / 2);
|
|
285
|
+
const candidate = `${characters.slice(0, middle).join("").trimEnd()}${ellipsis}`;
|
|
286
|
+
if (doc.widthOfString(candidate) <= availableWidth) {
|
|
287
|
+
low = middle;
|
|
288
|
+
} else {
|
|
289
|
+
high = middle - 1;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return `${characters.slice(0, low).join("").trimEnd()}${ellipsis}`;
|
|
293
|
+
}
|
|
264
294
|
drawHeader(doc, columns, startY, tableWidth, headerHeight, cellPadding, headerFontSize, minColumnWidth) {
|
|
265
295
|
const left = doc.page.margins.left;
|
|
266
296
|
doc.rect(left, startY, tableWidth, headerHeight).fill(HEADER_BACKGROUND_COLOR);
|
|
@@ -270,12 +300,15 @@ var PdfExporter = class {
|
|
|
270
300
|
const headerLineHeight = doc.currentLineHeight(true);
|
|
271
301
|
const headerTextY = startY + Math.max((headerHeight - headerLineHeight) / 2, 0);
|
|
272
302
|
columns.forEach((col) => {
|
|
273
|
-
|
|
274
|
-
|
|
303
|
+
const innerWidth = (col.width ?? minColumnWidth) - cellPadding * 2;
|
|
304
|
+
const bounded = col.size !== void 0 && Number.isFinite(col.size) && col.size > 0;
|
|
305
|
+
const headerText = bounded ? this.truncateTextToWidth(doc, col.header, innerWidth) : col.header;
|
|
306
|
+
doc.text(headerText, xPosition + cellPadding, headerTextY, {
|
|
307
|
+
width: innerWidth,
|
|
275
308
|
height: headerLineHeight,
|
|
276
309
|
align: "left",
|
|
277
310
|
lineBreak: false,
|
|
278
|
-
ellipsis:
|
|
311
|
+
ellipsis: !bounded
|
|
279
312
|
});
|
|
280
313
|
xPosition += col.width ?? minColumnWidth;
|
|
281
314
|
});
|
|
@@ -296,12 +329,15 @@ var PdfExporter = class {
|
|
|
296
329
|
const rawValue = row[col.key];
|
|
297
330
|
const cellValue = typeof rawValue === "string" || typeof rawValue === "number" || typeof rawValue === "boolean" ? String(rawValue) : "";
|
|
298
331
|
const isNumeric = typeof rawValue === "number" || typeof rawValue === "string" && rawValue !== "" && !isNaN(Number(rawValue));
|
|
299
|
-
|
|
300
|
-
|
|
332
|
+
const innerWidth = (col.width ?? minColumnWidth) - cellPadding * 2;
|
|
333
|
+
const bounded = col.size !== void 0 && Number.isFinite(col.size) && col.size > 0;
|
|
334
|
+
const rowText = bounded ? this.truncateTextToWidth(doc, cellValue, innerWidth) : cellValue;
|
|
335
|
+
doc.text(rowText, xPosition + cellPadding, dataTextY, {
|
|
336
|
+
width: innerWidth,
|
|
301
337
|
height: dataLineHeight,
|
|
302
338
|
align: isNumeric ? "right" : "left",
|
|
303
339
|
lineBreak: false,
|
|
304
|
-
ellipsis:
|
|
340
|
+
ellipsis: !bounded
|
|
305
341
|
});
|
|
306
342
|
xPosition += col.width ?? minColumnWidth;
|
|
307
343
|
if (i < columns.length - 1) {
|
package/dist/index.cjs
CHANGED
|
@@ -73,6 +73,9 @@ __export(index_exports, {
|
|
|
73
73
|
});
|
|
74
74
|
module.exports = __toCommonJS(index_exports);
|
|
75
75
|
|
|
76
|
+
// src/report.ts
|
|
77
|
+
var import_date_fns = require("date-fns");
|
|
78
|
+
|
|
76
79
|
// src/reports/salesByItemDetail.ts
|
|
77
80
|
var FIELDS = {
|
|
78
81
|
businessDate: { type: "date", columnKey: "date", filteringAvailable: false },
|
|
@@ -2985,7 +2988,11 @@ var getReportExportFileName = ({
|
|
|
2985
2988
|
endDate,
|
|
2986
2989
|
format
|
|
2987
2990
|
}) => {
|
|
2988
|
-
const formatDate2 = (
|
|
2991
|
+
const formatDate2 = (value) => {
|
|
2992
|
+
if (typeof value === "string" && /^\d{4}-\d{2}-\d{2}/.test(value) && (0, import_date_fns.isValid)((0, import_date_fns.parseISO)(value))) {
|
|
2993
|
+
return value.slice(0, 10);
|
|
2994
|
+
}
|
|
2995
|
+
const date = typeof value === "string" ? new Date(value) : value;
|
|
2989
2996
|
return [
|
|
2990
2997
|
date.getFullYear(),
|
|
2991
2998
|
String(date.getMonth() + 1).padStart(2, "0"),
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as MessageKey, F as FieldType, C as ColumnAlignment, a as ColumnPresentationConfig, b as ColumnGroupConfig, R as ReportType, c as ReportConfig, d as ReportColumnKey } from './report-
|
|
2
|
-
export { A as AnalyticsField, e as COLUMN_REGISTRY, f as ColumnMessageKey, g as ColumnMetadata, h as FooterCalculation, i as FooterCalculationType, j as Report, k as getColumnExportHeaderLabel, l as getColumnMetadata, m as getFixedColumns, n as getReportConfig, o as getReportExportFileName } from './report-
|
|
1
|
+
import { M as MessageKey, F as FieldType, C as ColumnAlignment, a as ColumnPresentationConfig, b as ColumnGroupConfig, R as ReportType, c as ReportConfig, d as ReportColumnKey } from './report-Dj8UU5d_.cjs';
|
|
2
|
+
export { A as AnalyticsField, e as COLUMN_REGISTRY, f as ColumnMessageKey, g as ColumnMetadata, h as FooterCalculation, i as FooterCalculationType, j as Report, k as getColumnExportHeaderLabel, l as getColumnMetadata, m as getFixedColumns, n as getReportConfig, o as getReportExportFileName } from './report-Dj8UU5d_.cjs';
|
|
3
3
|
import { LocaleCode } from '@harbortouch/locale-registry';
|
|
4
4
|
export { R as RenderedReport, a as ReportDocument, b as ReportFormat, c as ReportSection, d as ResolvedColumn, S as SummaryRow } from './ir-CUi0Z9hv.cjs';
|
|
5
5
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as MessageKey, F as FieldType, C as ColumnAlignment, a as ColumnPresentationConfig, b as ColumnGroupConfig, R as ReportType, c as ReportConfig, d as ReportColumnKey } from './report-
|
|
2
|
-
export { A as AnalyticsField, e as COLUMN_REGISTRY, f as ColumnMessageKey, g as ColumnMetadata, h as FooterCalculation, i as FooterCalculationType, j as Report, k as getColumnExportHeaderLabel, l as getColumnMetadata, m as getFixedColumns, n as getReportConfig, o as getReportExportFileName } from './report-
|
|
1
|
+
import { M as MessageKey, F as FieldType, C as ColumnAlignment, a as ColumnPresentationConfig, b as ColumnGroupConfig, R as ReportType, c as ReportConfig, d as ReportColumnKey } from './report-Dj8UU5d_.js';
|
|
2
|
+
export { A as AnalyticsField, e as COLUMN_REGISTRY, f as ColumnMessageKey, g as ColumnMetadata, h as FooterCalculation, i as FooterCalculationType, j as Report, k as getColumnExportHeaderLabel, l as getColumnMetadata, m as getFixedColumns, n as getReportConfig, o as getReportExportFileName } from './report-Dj8UU5d_.js';
|
|
3
3
|
import { LocaleCode } from '@harbortouch/locale-registry';
|
|
4
4
|
export { R as RenderedReport, a as ReportDocument, b as ReportFormat, c as ReportSection, d as ResolvedColumn, S as SummaryRow } from './ir-CUi0Z9hv.js';
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -1477,8 +1477,8 @@ declare const getFixedColumns: <TField extends string = string>(config: ReportCo
|
|
|
1477
1477
|
}) => TField[];
|
|
1478
1478
|
declare const getReportExportFileName: ({ reportType, startDate, endDate, format, }: {
|
|
1479
1479
|
reportType: ReportType;
|
|
1480
|
-
startDate: Date;
|
|
1481
|
-
endDate: Date;
|
|
1480
|
+
startDate: string | Date;
|
|
1481
|
+
endDate: string | Date;
|
|
1482
1482
|
format: "csv" | "xlsx" | "pdf";
|
|
1483
1483
|
}) => string;
|
|
1484
1484
|
|
|
@@ -1477,8 +1477,8 @@ declare const getFixedColumns: <TField extends string = string>(config: ReportCo
|
|
|
1477
1477
|
}) => TField[];
|
|
1478
1478
|
declare const getReportExportFileName: ({ reportType, startDate, endDate, format, }: {
|
|
1479
1479
|
reportType: ReportType;
|
|
1480
|
-
startDate: Date;
|
|
1481
|
-
endDate: Date;
|
|
1480
|
+
startDate: string | Date;
|
|
1481
|
+
endDate: string | Date;
|
|
1482
1482
|
format: "csv" | "xlsx" | "pdf";
|
|
1483
1483
|
}) => string;
|
|
1484
1484
|
|