@startsimpli/ui 0.4.168 → 0.4.169

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 (28) hide show
  1. package/package.json +8 -7
  2. package/src/components/charts/PeriodBars.tsx +36 -0
  3. package/src/components/charts/index.ts +2 -0
  4. package/src/components/index.ts +3 -0
  5. package/src/components/reports/ExportButtons.tsx +28 -0
  6. package/src/components/reports/PeriodReport.tsx +124 -0
  7. package/src/components/reports/__tests__/PeriodReport.test.tsx +75 -0
  8. package/src/components/reports/index.ts +4 -0
  9. package/src/components/timer/ColorPicker.tsx +43 -0
  10. package/src/components/timer/EntryFormDialog.tsx +104 -0
  11. package/src/components/timer/EntryList.tsx +42 -0
  12. package/src/components/timer/IdlePromptDialog.tsx +65 -0
  13. package/src/components/timer/ProjectSelect.tsx +52 -0
  14. package/src/components/timer/ProjectSwatch.tsx +15 -0
  15. package/src/components/timer/ProjectsDialog.tsx +221 -0
  16. package/src/components/timer/TimerBar.tsx +74 -0
  17. package/src/components/timer/__tests__/interval-logic.test.ts +121 -0
  18. package/src/components/timer/__tests__/projects-dialog.test.tsx +113 -0
  19. package/src/components/timer/__tests__/timer-components.test.tsx +147 -0
  20. package/src/components/timer/__tests__/useIdleReturn.test.tsx +59 -0
  21. package/src/components/timer/__tests__/useRunningTimer.test.tsx +167 -0
  22. package/src/components/timer/index.ts +20 -0
  23. package/src/components/timer/interval-logic.ts +140 -0
  24. package/src/components/timer/useIdleReturn.ts +49 -0
  25. package/src/components/timer/useRunningTimer.ts +209 -0
  26. package/src/utils/__tests__/xlsx.test.ts +36 -0
  27. package/src/utils/index.ts +1 -0
  28. package/src/utils/xlsx.ts +35 -0
@@ -8,6 +8,7 @@ export {
8
8
  downloadBlob,
9
9
  type CsvColumn,
10
10
  } from './csv'
11
+ export { xlsxFromRows, downloadXlsx, XLSX_MIME, type XlsxCell } from './xlsx'
11
12
 
12
13
  /**
13
14
  * Generate a random ID with optional prefix
@@ -0,0 +1,35 @@
1
+ import * as XLSX from 'xlsx'
2
+ import { downloadBlob } from './csv'
3
+
4
+ /**
5
+ * A spreadsheet from rows, written so a spreadsheet can use it.
6
+ *
7
+ * Numbers stay numbers (a total column can be summed), strings stay strings -
8
+ * a `=...` string is stored as text, never as a formula, so no guard prefix is
9
+ * needed here (the CSV writer needs one; this format has a cell type for text).
10
+ * Returns the bytes so a test, a server or a download can all consume it;
11
+ * `downloadXlsx` is the thin browser wrapper. Pairs with `csvFromRows`: give
12
+ * both the same matrix and the two files hold the same values.
13
+ *
14
+ * Uses `xlsx` (SheetJS), already a dependency of this package for the table
15
+ * export. Only the write path is used; the parse path with the published
16
+ * advisories is not reachable from here.
17
+ */
18
+ export type XlsxCell = string | number | boolean | null
19
+
20
+ export function xlsxFromRows(rows: XlsxCell[][], opts: { sheetName?: string } = {}): Uint8Array {
21
+ const ws = XLSX.utils.aoa_to_sheet(rows)
22
+ const widths = rows[0]?.map((_, i) => ({
23
+ wch: Math.min(50, Math.max(...rows.map((r) => String(r[i] ?? '').length)) + 2),
24
+ }))
25
+ if (widths) ws['!cols'] = widths
26
+ const wb = XLSX.utils.book_new()
27
+ XLSX.utils.book_append_sheet(wb, ws, (opts.sheetName ?? 'Sheet1').slice(0, 31))
28
+ return new Uint8Array(XLSX.write(wb, { bookType: 'xlsx', type: 'array' }))
29
+ }
30
+
31
+ export const XLSX_MIME = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
32
+
33
+ export function downloadXlsx(filename: string, rows: XlsxCell[][], opts: { sheetName?: string } = {}): void {
34
+ downloadBlob(filename, new Blob([xlsxFromRows(rows, opts) as BlobPart], { type: XLSX_MIME }))
35
+ }