@canvas-components/utils 0.2.4 → 0.2.6

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/index.cjs CHANGED
@@ -33,7 +33,10 @@ var __export = (target, all) => {
33
33
  };
34
34
 
35
35
  // src/export/xlsx-runtime.ts
36
- function createXlsxWriter(xlsx, header, sheetName, maxRows = 1048576) {
36
+ function createXlsxWriter(xlsx, header, sheetName, maxRows = 1048576, merges = []) {
37
+ const headerRows = Array.isArray(header[0]) ? header : [header];
38
+ if (headerRows.length >= maxRows)
39
+ throw new Error("XLSX \u8868\u5934\u884C\u6570\u8D85\u8FC7\u5DE5\u4F5C\u8868\u5BB9\u91CF");
37
40
  const workbook = xlsx.utils.book_new();
38
41
  let worksheet;
39
42
  let rowCount = 0;
@@ -41,7 +44,7 @@ function createXlsxWriter(xlsx, header, sheetName, maxRows = 1048576) {
41
44
  const baseName = sheetName.replace(/[\\/?*[\]:]/g, "_").replace(/^'+|'+$/g, "") || "Sheet1";
42
45
  const addSheet = () => {
43
46
  const suffix = sheetIndex === 0 ? "" : `_${sheetIndex + 1}`;
44
- worksheet = xlsx.utils.aoa_to_sheet([header], {
47
+ worksheet = xlsx.utils.aoa_to_sheet(headerRows, {
45
48
  dense: true
46
49
  });
47
50
  xlsx.utils.book_append_sheet(
@@ -49,7 +52,8 @@ function createXlsxWriter(xlsx, header, sheetName, maxRows = 1048576) {
49
52
  worksheet,
50
53
  baseName.slice(0, 31 - suffix.length) + suffix
51
54
  );
52
- rowCount = 1;
55
+ if (merges.length && sheetIndex === 0) worksheet["!merges"] = merges;
56
+ rowCount = headerRows.length;
53
57
  sheetIndex += 1;
54
58
  };
55
59
  addSheet();
@@ -125,7 +129,7 @@ let writer;
125
129
  self.onmessage = function(event) {
126
130
  try {
127
131
  const message = event.data;
128
- if (message.type === 'init') writer = createWriter(XLSX, message.header, message.sheetName);
132
+ if (message.type === 'init') writer = createWriter(XLSX, message.header, message.sheetName, undefined, message.merges);
129
133
  else if (message.type === 'append') writer.append(message.rows);
130
134
  else if (message.type === 'finish') {
131
135
  const buffer = writer.finish();
@@ -228,8 +232,22 @@ async function buildXlsxPart(params, rangeStart, rangeEnd) {
228
232
  throw new Error(
229
233
  "\u5355\u4EFD XLSX \u6570\u636E\u8D85\u8FC7\u5B89\u5168\u9650\u5236\uFF0C\u8BF7\u4F7F\u7528 exportTableToXlsx \u81EA\u52A8\u5206\u6587\u4EF6\u5BFC\u51FA"
230
234
  );
231
- const header = columns.map((column) => column.title);
232
- let textSize = header.reduce((size, title) => size + title.length, 0);
235
+ const header = params.headerRows?.length ? params.headerRows : [columns.map((column) => column.title)];
236
+ const headerRowCount = header.length;
237
+ const merges = (params.merges ?? []).flatMap((merge) => {
238
+ if (merge.e.r < headerRowCount) return [merge];
239
+ const start = Math.max(merge.s.r, headerRowCount + rangeStart);
240
+ const end = Math.min(merge.e.r, headerRowCount + rangeEnd - 1);
241
+ return end < start || end === start && merge.s.c === merge.e.c ? [] : [
242
+ {
243
+ s: { r: start - rangeStart, c: merge.s.c },
244
+ e: { r: end - rangeStart, c: merge.e.c }
245
+ }
246
+ ];
247
+ });
248
+ if (header.some((row) => row.length > columns.length))
249
+ throw new Error("XLSX \u8868\u5934\u5355\u5143\u683C\u6570\u4E0D\u80FD\u8D85\u8FC7\u5BFC\u51FA\u5217\u6570");
250
+ let textSize = header.flat().reduce((size, title) => size + title.length, 0);
233
251
  const normalizeExportCell = (value) => {
234
252
  const cell = normalizeCell(value);
235
253
  if (typeof cell === "string") {
@@ -243,7 +261,7 @@ async function buildXlsxPart(params, rangeStart, rangeEnd) {
243
261
  }
244
262
  return cell;
245
263
  };
246
- header.forEach((title) => {
264
+ header.flat().forEach((title) => {
247
265
  if (title.length > 32767) throw new Error("XLSX \u8868\u5934\u8D85\u8FC7 32767 \u5B57\u7B26");
248
266
  });
249
267
  if (textSize > XLSX_MAX_TEXT_CHARS_PER_FILE)
@@ -295,7 +313,7 @@ async function buildXlsxPart(params, rangeStart, rangeEnd) {
295
313
  () => fail(new Error("XLSX Worker \u542F\u52A8\u8D85\u65F6")),
296
314
  1e4
297
315
  );
298
- await request({ type: "init", header, sheetName });
316
+ await request({ type: "init", header, sheetName, merges });
299
317
  } catch {
300
318
  worker?.terminate();
301
319
  worker = void 0;
@@ -305,7 +323,7 @@ async function buildXlsxPart(params, rangeStart, rangeEnd) {
305
323
  }
306
324
  }
307
325
  checkAbort();
308
- const writer = worker ? void 0 : createXlsxWriter(XLSX__namespace, header, sheetName);
326
+ const writer = worker ? void 0 : createXlsxWriter(XLSX__namespace, header, sheetName, void 0, merges);
309
327
  const totalRows = rangeEnd - rangeStart;
310
328
  const report = (phase, completedRows) => params.onProgress?.({
311
329
  phase,
@@ -436,7 +454,7 @@ function getXlsxRowsPerFile(params) {
436
454
  throw new Error("XLSX \u5206\u6587\u4EF6\u4E0A\u9650\u5FC5\u987B\u4E3A\u6B63\u6574\u6570");
437
455
  const byCells = Math.floor(
438
456
  Math.min(cellLimit, XLSX_MAX_CELLS_PER_FILE) / Math.max(1, params.columns.length)
439
- ) - 1;
457
+ ) - (params.headerRows?.length || 1);
440
458
  if (byCells < 1) throw new Error("XLSX \u5355\u5143\u683C\u9884\u7B97\u4E0D\u8DB3\u4EE5\u5BB9\u7EB3\u8868\u5934\u548C\u4E00\u884C\u6570\u636E");
441
459
  return Math.min(rowLimit, XLSX_MAX_ROWS_PER_FILE, byCells);
442
460
  }
@@ -458,7 +476,8 @@ function buildCsvContent(params) {
458
476
  columns.map((column) => column.title),
459
477
  ...rows.map(
460
478
  (row, rowIndex) => columns.map((column) => column.value(row, rowIndex))
461
- )
479
+ ),
480
+ ...params.footerRows ?? []
462
481
  ]);
463
482
  }
464
483
  function serializeCsvRows(rows, lineBreak = "\n") {
@@ -470,7 +489,13 @@ function buildTxtContent(params) {
470
489
  const body = rows.map(
471
490
  (row, rowIndex) => columns.map((column) => normalizeTextCell(column.value(row, rowIndex))).join(" ")
472
491
  );
473
- return [header, ...body].join("\n");
492
+ return [
493
+ header,
494
+ ...body,
495
+ ...(params.footerRows ?? []).map(
496
+ (row) => row.map(normalizeTextCell).join(" ")
497
+ )
498
+ ].join("\n");
474
499
  }
475
500
  async function downloadJsonFile(params) {
476
501
  const { data, fileName, space = 2 } = params;
@@ -482,8 +507,8 @@ async function downloadJsonFile(params) {
482
507
  });
483
508
  }
484
509
  async function exportTableToCsv(params) {
485
- const { fileName, rows, columns } = params;
486
- const content = await buildCsvContentAsync({ rows, columns });
510
+ const { fileName, rows, columns, footerRows } = params;
511
+ const content = await buildCsvContentAsync({ rows, columns, footerRows });
487
512
  downloadTextFile({
488
513
  fileName: ensureExtension(fileName, "csv"),
489
514
  content,
@@ -491,8 +516,8 @@ async function exportTableToCsv(params) {
491
516
  });
492
517
  }
493
518
  async function exportTableToTxt(params) {
494
- const { fileName, rows, columns } = params;
495
- const content = await buildTxtContentAsync({ rows, columns });
519
+ const { fileName, rows, columns, footerRows } = params;
520
+ const content = await buildTxtContentAsync({ rows, columns, footerRows });
496
521
  downloadTextFile({
497
522
  fileName: ensureExtension(fileName, "txt"),
498
523
  content,
@@ -536,6 +561,9 @@ async function buildCsvContentAsync(params) {
536
561
  }
537
562
  await yieldToMainThread();
538
563
  }
564
+ for (const footer of params.footerRows ?? []) {
565
+ parts.push("\n", footer.map(escapeCsvCell).join(","));
566
+ }
539
567
  return parts.join("");
540
568
  }
541
569
  async function buildTxtContentAsync(params) {
@@ -551,6 +579,9 @@ async function buildTxtContentAsync(params) {
551
579
  }
552
580
  await yieldToMainThread();
553
581
  }
582
+ for (const footer of params.footerRows ?? []) {
583
+ parts.push("\n", footer.map(normalizeTextCell).join(" "));
584
+ }
554
585
  return parts.join("");
555
586
  }
556
587
  function escapeCsvCell(value) {
@@ -779,16 +810,29 @@ function isPointInRect(x, y, rect) {
779
810
  function resolveCanvasScrollbarAxis(options, axis) {
780
811
  const override = options?.[axis];
781
812
  const merged = { ...options, ...override };
782
- const thickness = Number.isFinite(merged.thickness) ? Math.max(merged.thickness, 6) : 10;
813
+ const axisSize = axis === "vertical" ? merged.width : merged.height;
814
+ const requestedThickness = axisSize ?? merged.thickness;
815
+ const thickness = Number.isFinite(requestedThickness) ? Math.max(requestedThickness, 6) : 10;
783
816
  return {
817
+ mode: merged.mode === "button" ? "button" : "scrollbar",
784
818
  visible: options?.visible !== false && override !== false && merged.visible !== false,
785
819
  thickness,
820
+ maxScrollSpeed: Number.isFinite(merged.maxScrollSpeed) && merged.maxScrollSpeed > 0 ? merged.maxScrollSpeed : 1800,
786
821
  thumbColor: merged.thumbColor ?? "rgba(100, 116, 139, 0.8)",
787
822
  trackColor: merged.trackColor,
788
823
  buttonColor: merged.buttonColor ?? "rgba(71, 85, 105, 0.88)",
824
+ buttonBackgroundColor: merged.buttonBackgroundColor,
825
+ buttonHoverBackgroundColor: merged.buttonHoverBackgroundColor ?? "rgba(71, 85, 105, 0.09)",
826
+ buttonPressedBackgroundColor: merged.buttonPressedBackgroundColor ?? "rgba(37, 99, 235, 0.18)",
789
827
  thumbRadius: Number.isFinite(merged.thumbRadius) ? Math.max(merged.thumbRadius, 0) : void 0
790
828
  };
791
829
  }
830
+ function resolveCanvasScrollbarHoldSpeed(elapsedMs, maxScrollSpeed) {
831
+ const maximum = Math.max(maxScrollSpeed, 1);
832
+ const initial = Math.min(240, maximum);
833
+ const progress = Math.min(Math.max(elapsedMs, 0) / 2500, 1);
834
+ return initial + (maximum - initial) * progress * progress;
835
+ }
792
836
 
793
837
  // src/number/precise.ts
794
838
  function addPreciseNumbers(left, right) {
@@ -1202,6 +1246,7 @@ exports.normalizeDecimalPlaces = normalizeDecimalPlaces;
1202
1246
  exports.parseChineseNumber = parseChineseNumber;
1203
1247
  exports.parseNumberValue = parseNumberValue;
1204
1248
  exports.resolveCanvasScrollbarAxis = resolveCanvasScrollbarAxis;
1249
+ exports.resolveCanvasScrollbarHoldSpeed = resolveCanvasScrollbarHoldSpeed;
1205
1250
  exports.resolveDateValue = resolveDateValue;
1206
1251
  exports.roundPreciseNumber = roundPreciseNumber;
1207
1252
  exports.serializeCsvRows = serializeCsvRows;