react-semaphor 0.1.532 → 0.1.533

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 (34) hide show
  1. package/dist/brand-studio/index.js +1 -1
  2. package/dist/chunks/{dashboard-BoSKlMPx.js → dashboard-DUCg1mNJ.js} +1 -1
  3. package/dist/chunks/{dashboard-briefing-launcher-BR5llbxb.js → dashboard-briefing-launcher-B0PuQUiR.js} +1401 -1383
  4. package/dist/chunks/{dashboard-controls-4Thl0eL1.js → dashboard-controls-Cl3fLg9W.js} +39 -39
  5. package/dist/chunks/{dashboard-json-Ez0I7b2H.js → dashboard-json-BSOgXGwr.js} +1 -1
  6. package/dist/chunks/{edit-dashboard-visual-DpGb6dpY.js → edit-dashboard-visual-CQDyMxM7.js} +516 -516
  7. package/dist/chunks/{editor-action-buttons--SQ3CcBI.js → editor-action-buttons-BKVrZnRQ.js} +2 -2
  8. package/dist/chunks/{matrix-formatter-DDjECnMd.js → matrix-formatter-DY1y9odV.js} +2 -1
  9. package/dist/chunks/{pivot-header-presentation-BTOXdU6S.js → pivot-header-presentation-Bb6b3Ch2.js} +232 -210
  10. package/dist/chunks/{report-preferences-dialog-Cv_2GMlz.js → report-preferences-dialog-WDM7qWxV.js} +16 -16
  11. package/dist/chunks/{semaphor-ready-indicator-lALyc-pQ.js → semaphor-ready-indicator-yZ0JtL4D.js} +33527 -33435
  12. package/dist/chunks/{slider-DlRYiI2m.js → slider-0mB67Lls.js} +3 -3
  13. package/dist/chunks/{switch-CCOKraBb.js → switch-D95vek6N.js} +1690 -1683
  14. package/dist/dashboard/index.js +1 -1
  15. package/dist/data-app-sdk/index.js +1 -1
  16. package/dist/format-utils/index.js +90 -89
  17. package/dist/index.js +120 -119
  18. package/dist/surfboard/index.js +1 -1
  19. package/dist/types/components/surfboard/filter/date-range-filter-v2.d.ts +2 -2
  20. package/dist/types/components/surfboard/filter/types.d.ts +9 -0
  21. package/dist/types/lib/api/exports-api.d.ts +30 -3
  22. package/dist/types/lib/csv-download.d.ts +4 -2
  23. package/dist/types/lib/export-messages.d.ts +47 -0
  24. package/dist/types/lib/exports/bounded-request.d.ts +12 -0
  25. package/dist/types/lib/exports/export-status.d.ts +2 -0
  26. package/dist/types/lib/hooks/use-date-filter.d.ts +3 -3
  27. package/dist/types/lib/hooks/use-export-polling.d.ts +9 -1
  28. package/dist/types/lib/matrix-table/submit-matrix-delivery.d.ts +14 -2
  29. package/dist/types/lib/matrix-table/use-matrix.d.ts +4 -0
  30. package/dist/types/lib/stores/export-store.d.ts +11 -0
  31. package/dist/types/lib/temporal-filter/temporal-filter-utils.d.ts +9 -0
  32. package/dist/types/shared/format-utils/formatters/matrix-formatter.d.ts +6 -0
  33. package/dist/types/shared/format-utils/matrix-export-presentation.d.ts +28 -4
  34. package/package.json +1 -1
@@ -83,7 +83,12 @@ export interface ExportJobStatus {
83
83
  createdAt: string;
84
84
  completedAt?: string;
85
85
  expiresAt: string;
86
+ /** Matrix exports: where the export is (the server computes it from committed work). */
87
+ phase?: MatrixExportPhase;
88
+ /** When the server stops the export (ISO); the browser gives up a grace period later. */
89
+ deadlineAt?: string;
86
90
  }
91
+ export type MatrixExportPhase = 'preparing' | 'acquiring' | 'finalizing' | 'completed';
87
92
  /** Export job from list endpoint */
88
93
  export interface ExportJobListItem {
89
94
  progress?: number | null;
@@ -102,6 +107,8 @@ export interface ExportJobListItem {
102
107
  expiresAt: string;
103
108
  dashboardId?: string;
104
109
  cardId?: string;
110
+ phase?: MatrixExportPhase;
111
+ deadlineAt?: string;
105
112
  }
106
113
  /** API error response */
107
114
  export interface ExportApiError {
@@ -113,25 +120,45 @@ export interface ExportApiError {
113
120
  * Create a new export job
114
121
  */
115
122
  export declare function createExport(apiServiceUrl: string, token: string, params: CardExportRequest): Promise<CreateExportResponse>;
123
+ /** The direct path's answer (MX-D11): the file, or the background export it started. */
124
+ export type MatrixDirectExportResult = {
125
+ kind: 'file';
126
+ file: Blob;
127
+ fileName: string;
128
+ } | {
129
+ kind: 'background';
130
+ exportId: string;
131
+ status: 'pending' | 'processing';
132
+ deadlineAt: string | null;
133
+ };
134
+ /**
135
+ * A Matrix CSV a user downloads: built in the request when it fits the direct
136
+ * limits, otherwise moved to a background export by the server. The file is
137
+ * read as bytes, so its BOM survives. Errors carry the server's catalog
138
+ * reason in `details.message`.
139
+ */
140
+ export declare function createMatrixDirectExport(apiServiceUrl: string, token: string, params: MatrixCsvExportRequest & {
141
+ format: 'csv';
142
+ }): Promise<MatrixDirectExportResult>;
116
143
  /**
117
144
  * Get list of user's exports
118
145
  */
119
146
  export declare function getExports(apiServiceUrl: string, token: string, options?: {
120
147
  status?: ExportStatus[];
121
148
  limit?: number;
122
- }): Promise<{
149
+ }, signal?: AbortSignal): Promise<{
123
150
  exports: ExportJobListItem[];
124
151
  }>;
125
152
  /**
126
153
  * Get status of a specific export job
127
154
  */
128
- export declare function getExportStatus(apiServiceUrl: string, token: string, exportId: string): Promise<ExportJobStatus>;
155
+ export declare function getExportStatus(apiServiceUrl: string, token: string, exportId: string, signal?: AbortSignal): Promise<ExportJobStatus>;
129
156
  /**
130
157
  * Get download URL for a completed export
131
158
  *
132
159
  * The backend returns a presigned S3 URL in JSON response.
133
160
  */
134
- export declare function getDownloadUrl(apiServiceUrl: string, token: string, exportId: string): Promise<string>;
161
+ export declare function getDownloadUrl(apiServiceUrl: string, token: string, exportId: string, signal?: AbortSignal): Promise<string>;
135
162
  /**
136
163
  * Cancel/delete an export job
137
164
  */
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * Save a CSV file in the browser. This is the only place react-semaphor
3
3
  * creates a CSV Blob; `content` comes from the CSV file contract
4
- * (`encodeCsvFile`), which owns the BOM, quoting and record separators.
4
+ * (`encodeCsvFile`), which owns the BOM, quoting and record separators, or is
5
+ * a file the server built (a direct Matrix CSV), saved byte for byte so its
6
+ * BOM survives.
5
7
  */
6
8
  export declare function downloadCsvFile({ content, fileName, }: {
7
- content: string;
9
+ content: string | Blob;
8
10
  fileName: string;
9
11
  }): void;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Every export message the export dialog, its toasts and the notification bell
3
+ * show (MX-D17; PLAN "Customer messages", M1 to M3, M7 and M8 to M18). Plain
4
+ * sentences that say where the export is and what to do: no internal terms,
5
+ * never the product name (white label), no em dashes. A failure reason comes
6
+ * from the server's own catalog.
7
+ */
8
+ export declare const EXPORT_UI_MESSAGES: {
9
+ /** M1: a direct Matrix CSV attempt is running (the export button, and the line under it). */
10
+ readonly preparingFile: "Preparing file...";
11
+ readonly preparingFileHint: "Large tables can take a few seconds.";
12
+ /** M2: the direct attempt returned the file. */
13
+ readonly fileDownloading: "Your file is downloading.";
14
+ /** M3: the direct attempt moved to a background export. */
15
+ readonly movedToBackground: "We're preparing your export in the background. We'll notify you when it's ready.";
16
+ /** M7: `reason` is the server's catalog reason. */
17
+ readonly directFailed: (reason: string) => string;
18
+ /** M8 */
19
+ readonly queued: "Queued...";
20
+ /** M9: a Matrix export before any rows. */
21
+ readonly preparing: "Preparing...";
22
+ /** M10: a Matrix export, with its committed row count. */
23
+ readonly fetchingRows: (rows: number) => string;
24
+ /** M11: a table export. */
25
+ readonly processing: "Processing...";
26
+ readonly percentComplete: (progress: number) => string;
27
+ readonly rowsProcessed: (rows: number) => string;
28
+ /** M12 */
29
+ readonly finalizing: "Finalizing...";
30
+ /** Every in-progress row; `elapsed` is a distance such as "5 minutes". */
31
+ readonly started: (elapsed: string) => string;
32
+ /** M13: still running 5 minutes after it started. */
33
+ readonly longRunning: "Large exports can take up to 30 minutes. You can keep working; we'll notify you.";
34
+ /** M14, M15, M16 */
35
+ readonly ready: "Ready";
36
+ readonly failed: "Failed";
37
+ readonly cancelled: "Cancelled";
38
+ readonly inProgress: "In progress";
39
+ /** M15 when an older server stored no reason: never only "Export failed". */
40
+ readonly failedFallback: "Something went wrong while preparing this export. Try again, and contact support if it keeps happening.";
41
+ /** M17: no final status by the server's deadline plus the grace period. */
42
+ readonly unconfirmed: "We couldn't confirm this export's status. Check the notification bell again when your connection returns.";
43
+ /** M18 */
44
+ readonly linkExpired: "This link expired. Refresh the tray to sign the file again.";
45
+ };
46
+ /** M13 appears this long after an export started. */
47
+ export declare const EXPORT_LONG_RUNNING_MS: number;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * One export status, list or download-link request never waits longer than
3
+ * this (hotspot H-06: every wait that decides something is bounded). A
4
+ * timed-out request counts as failed, and its fetch is aborted.
5
+ */
6
+ export declare const EXPORT_STATUS_TIMEOUT_MS = 15000;
7
+ /**
8
+ * Rejects when `work` outlasts `EXPORT_STATUS_TIMEOUT_MS`, and aborts its
9
+ * request. `work` must pass `signal` to its fetch, or the timeout releases the
10
+ * caller while the request stays open (a static test checks every caller).
11
+ */
12
+ export declare function boundedRequest<T>(work: (signal: AbortSignal) => Promise<T>): Promise<T>;
@@ -13,5 +13,7 @@ export declare function mapExportStatus(input: ExportJobStatus | ExportJobListIt
13
13
  lastUpdatedAt: Date;
14
14
  fileSize: number | undefined;
15
15
  error: string | undefined;
16
+ phase: import('../api/index.js').MatrixExportPhase | undefined;
17
+ deadlineAt: Date | undefined;
16
18
  downloadUrl: string | undefined;
17
19
  };
@@ -1,4 +1,4 @@
1
- import { TFilter, TFilterValue, RelativeDateFilter, DateComparisonOperation, FilterStorageOptions, TemporalPrecision } from '../../components/surfboard/filter/types.js';
1
+ import { TFilter, TFilterValue, RelativeDateFilter, DateComparisonOperation, FilterStorageOptions, RelativeDateChangeOptions, TemporalPrecision } from '../../components/surfboard/filter/types.js';
2
2
  import { DateRange } from 'react-day-picker';
3
3
  type UseDateFilterOptions = FilterStorageOptions;
4
4
  type DateFilterChangeOptions = {
@@ -15,7 +15,7 @@ export declare function useDateFilterHook(filterId: string): {
15
15
  handleClear: () => void;
16
16
  handleChange: (date: DateRange | undefined, operation?: DateComparisonOperation, options?: DateFilterChangeOptions) => void;
17
17
  handleNullOperation: (operation: "is null" | "is not null") => void;
18
- handleRelativeChange: (date: DateRange | undefined, relativeMeta: RelativeDateFilter, options?: DateFilterChangeOptions) => void;
18
+ handleRelativeChange: (date: DateRange | undefined, relativeMeta: RelativeDateFilter, options?: RelativeDateChangeOptions) => void;
19
19
  handleReset: () => void;
20
20
  };
21
21
  export declare function useDateFilter(filter: TFilter, options?: UseDateFilterOptions): {
@@ -30,7 +30,7 @@ export declare function useDateFilter(filter: TFilter, options?: UseDateFilterOp
30
30
  handleClear: () => void;
31
31
  handleChange: (date: DateRange | undefined, operation?: DateComparisonOperation, options?: DateFilterChangeOptions) => void;
32
32
  handleNullOperation: (operation: "is null" | "is not null") => void;
33
- handleRelativeChange: (date: DateRange | undefined, relativeMeta: RelativeDateFilter, options?: DateFilterChangeOptions) => void;
33
+ handleRelativeChange: (date: DateRange | undefined, relativeMeta: RelativeDateFilter, options?: RelativeDateChangeOptions) => void;
34
34
  handleReset: () => void;
35
35
  };
36
36
  export {};
@@ -1,3 +1,10 @@
1
+ import { EXPORT_STATUS_TIMEOUT_MS } from '../exports/bounded-request.js';
2
+ /**
3
+ * The browser follows the server (MX-D9): it gives up on an export this long
4
+ * after the server's `deadlineAt`, by which the server has settled the export.
5
+ */
6
+ export declare const EXPORT_POLL_GRACE_MS: number;
7
+ export { EXPORT_STATUS_TIMEOUT_MS };
1
8
  /**
2
9
  * Hook that manages smart polling for export status updates.
3
10
  *
@@ -20,5 +27,6 @@ export declare const POLLING_INTERVALS: {
20
27
  LONG: number;
21
28
  MEDIUM_THRESHOLD: number;
22
29
  LONG_THRESHOLD: number;
23
- MAX_POLLING_DURATION: number;
30
+ EXPORT_POLL_GRACE_MS: number;
31
+ FALLBACK_POLLING_DURATION: number;
24
32
  };
@@ -1,7 +1,12 @@
1
1
  import { buildMatrixDeliveryPayload } from './matrix-delivery.js';
2
2
  import { downloadMatrixPdf } from '../download-pdf.js';
3
3
  import { ActiveExport } from '../stores/export-store.js';
4
- /** Submission policy stays out of the dialog; presentation consumes the outcome. */
4
+ /**
5
+ * Submission policy stays out of the dialog; presentation consumes the
6
+ * outcome. A Matrix CSV goes to the direct path first (MX-D11): a file is
7
+ * saved here, so it still downloads if the dialog closed meanwhile (M6); a
8
+ * background export comes back to be tracked in the bell.
9
+ */
5
10
  export declare function submitMatrixDelivery(input: Omit<Parameters<typeof buildMatrixDeliveryPayload>[0], 'format'> & {
6
11
  format: string;
7
12
  apiServiceUrl: string;
@@ -11,9 +16,16 @@ export declare function submitMatrixDelivery(input: Omit<Parameters<typeof build
11
16
  }): Promise<{
12
17
  kind: "pdf";
13
18
  result: import('../download-pdf.js').PdfDownloadResponse;
19
+ fileName?: undefined;
14
20
  export?: undefined;
15
21
  } | {
16
- kind: "csv";
22
+ kind: "csv_file";
23
+ fileName: string;
24
+ result?: undefined;
25
+ export?: undefined;
26
+ } | {
27
+ kind: "csv_background";
17
28
  export: ActiveExport;
18
29
  result?: undefined;
30
+ fileName?: undefined;
19
31
  }>;
@@ -29,6 +29,10 @@ export declare function useMatrix(input: MatrixInput): {
29
29
  isNumeric: boolean;
30
30
  hasTextAffixes: boolean;
31
31
  }>;
32
+ absence: {
33
+ emptyText: string;
34
+ nullText: string;
35
+ };
32
36
  };
33
37
  readCell: (coordinate: import('./matrix-runtime-types.js').MatrixCellAddress) => import('./matrix-runtime-types.js').MatrixCellState;
34
38
  setViewport: (viewport: import('./matrix-runtime-types.js').MatrixViewport) => void;
@@ -17,6 +17,10 @@ export interface ActiveExport {
17
17
  fileSize?: number;
18
18
  error?: string;
19
19
  expiresAt: Date;
20
+ /** Matrix exports: the server's phase, for the bell's stage text (M9, M10, M12). */
21
+ phase?: 'preparing' | 'acquiring' | 'finalizing' | 'completed';
22
+ /** When the server stops the export; polling gives up a grace period later (MX-D9). */
23
+ deadlineAt?: Date;
20
24
  }
21
25
  type ExportStoreState = {
22
26
  /** Map of export ID to export data */
@@ -27,6 +31,13 @@ type ExportStoreActions = {
27
31
  addExport: (exportData: ActiveExport) => void;
28
32
  /** Update an existing export */
29
33
  updateExport: (id: string, updates: Partial<ActiveExport>) => void;
34
+ /**
35
+ * Applies a server answer (poll, refresh). An answer never moves an export
36
+ * that is final here back to in progress: a newer answer already settled it.
37
+ */
38
+ applyServerStatus: (id: string, updates: Partial<ActiveExport>) => void;
39
+ /** Adds a recovered export only if it is not tracked already (checked when adding). */
40
+ recoverExport: (exportData: ActiveExport) => void;
30
41
  /** Remove an export from the store */
31
42
  removeExport: (id: string) => void;
32
43
  /** Get all in-progress exports */
@@ -17,6 +17,15 @@ export declare function getFilterTemporalCapability(filter: {
17
17
  dataType?: unknown;
18
18
  };
19
19
  }): TemporalFilterCapability;
20
+ /**
21
+ * The range condition a relative date window ("Today", "Last 7 days") runs
22
+ * under. The window and the condition are independent, as the server treats
23
+ * them: "not between" excludes the window, anything else keeps it. A
24
+ * data-anchored window ("the latest day in the data") runs only as
25
+ * "between", the one form the server resolves. Every builder of a relative
26
+ * date filter value (defaults, the date filter hook, Global Date) uses this.
27
+ */
28
+ export declare function resolveRelativeWindowOperation(requested: string | undefined, relativeMeta: unknown): 'between' | 'not between';
20
29
  export declare function supportsMinutePrecisionForOperation(operation: DateComparisonOperation | undefined): boolean;
21
30
  export declare function isSubDayRelativeDateFilter(meta: RelativeDateFilter | undefined): meta is Extract<RelativeDateFilter, {
22
31
  mode: 'last';
@@ -30,6 +30,8 @@ export declare function matrixLevelLabels(input: {
30
30
  }>;
31
31
  /** Shared viewer/export adapter. Arithmetic, precision and temporal rules stay shared. */
32
32
  export declare function resolveMatrixValueFormat(override: SemaphorValueFormat | undefined, semantic: SemaphorValueFormat | undefined): import('../semantic-format.js').AdaptedCanonicalFormatSpec | undefined;
33
+ /** One card's prepared formats: every Matrix surface (screen, Layout CSV, Flat CSV, PDF) formats through it. */
34
+ export type MatrixFormatting = ReturnType<typeof prepareMatrixFormatting>;
33
35
  export declare function prepareMatrixFormatting(descriptors: MatrixWindow['descriptors'], presentation: MatrixPresentation, report: ReportRuntimeContext): {
34
36
  levels: Map<string, (value: SemaphorScalarValue) => string>;
35
37
  measures: Map<string, (value: SemaphorScalarValue) => string>;
@@ -37,4 +39,8 @@ export declare function prepareMatrixFormatting(descriptors: MatrixWindow['descr
37
39
  isNumeric: boolean;
38
40
  hasTextAffixes: boolean;
39
41
  }>;
42
+ absence: {
43
+ emptyText: string;
44
+ nullText: string;
45
+ };
40
46
  };
@@ -1,6 +1,18 @@
1
- import { MatrixExportLayout, MatrixExportRequest, MatrixExportRow } from '../analytics-protocol/index.js';
1
+ import { MatrixExportLayout, MatrixExportRequest, MatrixExportRow, MatrixPath } from '../analytics-protocol/index.js';
2
2
  import { ReportRuntimeContext } from '../report-runtime-context/index.js';
3
3
  import { FastPathTableStructure } from './table-structure.js';
4
+ import { MatrixFormatting } from './formatters/matrix-formatter.js';
5
+ export { prepareMatrixFormatting, type MatrixFormatting } from './formatters/matrix-formatter.js';
6
+ /**
7
+ * The identity of a Layout row, enough to decide which labels the next row
8
+ * repeats. A background export carries the last emitted row's identity between
9
+ * batches (MX-D14), so label suppression is file-wide.
10
+ */
11
+ export type MatrixExportRowIdentity = {
12
+ kind: 'layout';
13
+ rowPath: MatrixPath;
14
+ role: 'member' | 'subtotal' | 'grand_total';
15
+ };
4
16
  /** Same descriptor-based presentation for viewer, layout CSV and print. */
5
17
  export declare function prepareMatrixExportPresentation(layout: MatrixExportLayout, request: MatrixExportRequest, report: ReportRuntimeContext): {
6
18
  headers: string[];
@@ -16,11 +28,23 @@ export declare function prepareMatrixExportPresentation(layout: MatrixExportLayo
16
28
  */
17
29
  continuedColumns: (data: MatrixExportRow, previous?: MatrixExportRow) => number[];
18
30
  csvRow: (data: MatrixExportRow) => string[];
19
- csvRows: (data: readonly MatrixExportRow[]) => string[][];
31
+ /**
32
+ * `previousRow` is the row before `data[0]`, carried by the export's
33
+ * continuation, so a tabular layout prints each label once across the
34
+ * whole file. Retries are pure: suppression never relies on mutable
35
+ * formatter state or an earlier worker. Without it, the first row prints
36
+ * its labels.
37
+ */
38
+ csvRows: (data: readonly MatrixExportRow[], previousRow?: MatrixExportRowIdentity | null) => string[][];
20
39
  };
21
- /** Raw CSV intentionally preserves typed values instead of display formats. */
22
40
  export declare function matrixFlatCsvHeaders(layout: MatrixExportLayout): string[];
23
- export declare function matrixFlatCsvRow(data: MatrixExportRow): (string | number | null)[];
41
+ /**
42
+ * One Flat CSV record, formatted with the card's formats (MX-D10): level
43
+ * values as the screen and Layout CSV label members (`(Blank)` for a null
44
+ * member), measures through the same formatter and absence text as Layout
45
+ * CSV. Prepare `formatting` once per batch with `prepareMatrixFormatting`.
46
+ */
47
+ export declare function matrixFlatCsvRow(data: MatrixExportRow, layout: MatrixExportLayout, formatting: MatrixFormatting): string[];
24
48
  /** Bounded physical projection only; values and totals have already been acquired. */
25
49
  export declare function buildMatrixTableStructure(input: {
26
50
  layout: MatrixExportLayout;
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "email": "support@semaphor.cloud"
6
6
  },
7
7
  "license": "MIT",
8
- "version": "0.1.532",
8
+ "version": "0.1.533",
9
9
  "description": "Fully interactive and customizable dashboards for your apps.",
10
10
  "keywords": [
11
11
  "react",