@happyvertical/smrt-reports 0.56.0 → 0.56.2

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.
@@ -0,0 +1,104 @@
1
+ <script lang="ts">
2
+ import { formatWidgetValue } from '@happyvertical/smrt-ui/charts/format';
3
+ import { DataTable, type DataTableColumn } from '@happyvertical/smrt-ui/data';
4
+ import { Button } from '@happyvertical/smrt-ui/ui';
5
+ import type { ReportDataTableColumn } from '../adapter.js';
6
+ import type {
7
+ MaterializedReportDrilldown,
8
+ MaterializedReportPage,
9
+ } from './materialized.js';
10
+
11
+ export interface Props {
12
+ /** Server-projected descriptor and bounded row page. No client tenant selector exists. */
13
+ page: MaterializedReportPage;
14
+ locale?: string;
15
+ onDrilldown?: MaterializedReportDrilldown;
16
+ /** The application route owns URL navigation for a changed server page. */
17
+ onPageChange?: (page: number) => void | Promise<void>;
18
+ caption?: string;
19
+ }
20
+
21
+ let {
22
+ page,
23
+ locale = 'en',
24
+ onDrilldown,
25
+ onPageChange,
26
+ caption = 'Materialized report',
27
+ }: Props = $props();
28
+
29
+ const validCurrency = (value: unknown): value is string =>
30
+ typeof value === 'string' && /^[A-Za-z]{3}$/.test(value);
31
+
32
+ function columns(): DataTableColumn<Record<string, unknown>>[] {
33
+ return page.descriptor.dataTable.columns.map(
34
+ (column: ReportDataTableColumn) => ({
35
+ id: column.id,
36
+ label: column.label,
37
+ accessor: column.accessor,
38
+ sortable: column.sortable,
39
+ filterable: column.filterable,
40
+ align: column.align,
41
+ role: column.role,
42
+ responsive: column.responsive,
43
+ }),
44
+ );
45
+ }
46
+
47
+ function formattedValue(
48
+ columnId: string,
49
+ value: unknown,
50
+ row: Record<string, unknown>,
51
+ ): string {
52
+ const column = page.descriptor.dataTable.columns.find(
53
+ (candidate) => candidate.id === columnId,
54
+ );
55
+ if (!column) return '–';
56
+ if (column.valueFormat === 'money') {
57
+ if (!Number.isSafeInteger(value) || !validCurrency(row.currency))
58
+ return '–';
59
+ return formatWidgetValue(value, {
60
+ format: 'money',
61
+ currency: row.currency,
62
+ locale,
63
+ });
64
+ }
65
+ return value == null ? '–' : String(value);
66
+ }
67
+
68
+ async function drilldown(id: unknown, columnId: string): Promise<void> {
69
+ if (typeof id !== 'string' || !id || !onDrilldown) return;
70
+ if (!page.drilldownColumnIds?.includes(columnId)) return;
71
+ await onDrilldown({ id, columnId });
72
+ }
73
+ </script>
74
+
75
+ {#snippet cell({ column, row, value }: {
76
+ column: DataTableColumn<Record<string, unknown>>;
77
+ row: Record<string, unknown>;
78
+ value: unknown;
79
+ })}
80
+ {#if onDrilldown && page.drilldownColumnIds?.includes(column.id)}
81
+ <Button
82
+ variant="ghost"
83
+ aria-label={`Inspect ${column.label}`}
84
+ onclick={() => drilldown(row[page.descriptor.identityField], column.id)}
85
+ >{formattedValue(column.id, value, row)}</Button>
86
+ {:else}
87
+ {formattedValue(column.id, value, row)}
88
+ {/if}
89
+ {/snippet}
90
+
91
+ <div data-smrt-component="MaterializedReportTable">
92
+ <DataTable
93
+ data={page.rows}
94
+ columns={columns()}
95
+ rowKey={page.descriptor.identityField}
96
+ manualPagination
97
+ totalRows={page.totalRows}
98
+ page={Math.floor(page.offset / page.limit) + 1}
99
+ pageSize={page.limit}
100
+ {caption}
101
+ {onPageChange}
102
+ {cell}
103
+ />
104
+ </div>
@@ -0,0 +1,14 @@
1
+ import type { MaterializedReportDrilldown, MaterializedReportPage } from './materialized.js';
2
+ export interface Props {
3
+ /** Server-projected descriptor and bounded row page. No client tenant selector exists. */
4
+ page: MaterializedReportPage;
5
+ locale?: string;
6
+ onDrilldown?: MaterializedReportDrilldown;
7
+ /** The application route owns URL navigation for a changed server page. */
8
+ onPageChange?: (page: number) => void | Promise<void>;
9
+ caption?: string;
10
+ }
11
+ declare const MaterializedReportTable: import("svelte").Component<Props, {}, "">;
12
+ type MaterializedReportTable = ReturnType<typeof MaterializedReportTable>;
13
+ export default MaterializedReportTable;
14
+ //# sourceMappingURL=MaterializedReportTable.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaterializedReportTable.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/MaterializedReportTable.svelte.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,2BAA2B,EAC3B,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAG3B,MAAM,WAAW,KAAK;IACpB,0FAA0F;IAC1F,IAAI,EAAE,sBAAsB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,2BAA2B,CAAC;IAC1C,2EAA2E;IAC3E,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAiFD,QAAA,MAAM,uBAAuB,2CAAwC,CAAC;AACtE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC1E,eAAe,uBAAuB,CAAC"}
@@ -1,5 +1,7 @@
1
1
  export { getRuntimeReportsBrowserClient, type RuntimeReportsBrowserClientOptions, } from './browser-client.js';
2
2
  export { createRuntimeReportsHttpClient, type RuntimeReportsHttpClientOptions, RuntimeReportsHttpError, } from './client.js';
3
+ export { default as MaterializedReportTable } from './MaterializedReportTable.svelte';
4
+ export type { MaterializedReportCell, MaterializedReportDrilldown, MaterializedReportPage, } from './materialized.js';
3
5
  export { default as ReportConfirmation } from './ReportConfirmation.svelte';
4
6
  export { default as ReportDetail } from './ReportDetail.svelte';
5
7
  export { default as ReportPicker } from './ReportPicker.svelte';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,KAAK,kCAAkC,GACxC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,8BAA8B,EAC9B,KAAK,+BAA+B,EACpC,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AACtF,OAAO,EAAE,OAAO,IAAI,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAC5F,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EAChC,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,KAAK,kCAAkC,GACxC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,8BAA8B,EAC9B,KAAK,+BAA+B,EACpC,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AACtF,YAAY,EACV,sBAAsB,EACtB,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AACtF,OAAO,EAAE,OAAO,IAAI,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAC5F,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EAChC,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
@@ -1,5 +1,6 @@
1
1
  export { getRuntimeReportsBrowserClient, } from './browser-client.js';
2
2
  export { createRuntimeReportsHttpClient, RuntimeReportsHttpError, } from './client.js';
3
+ export { default as MaterializedReportTable } from './MaterializedReportTable.svelte';
3
4
  export { default as ReportConfirmation } from './ReportConfirmation.svelte';
4
5
  export { default as ReportDetail } from './ReportDetail.svelte';
5
6
  export { default as ReportPicker } from './ReportPicker.svelte';
@@ -0,0 +1,19 @@
1
+ import type { ReportAdapterDescriptor } from '../adapter.js';
2
+ /** Server-projected page for a declared materialized report. */
3
+ export interface MaterializedReportPage {
4
+ descriptor: ReportAdapterDescriptor;
5
+ rows: Array<Record<string, unknown>>;
6
+ totalRows: number;
7
+ offset: number;
8
+ limit: number;
9
+ /** Closed visible columns that the host permits for source drilldown. */
10
+ drilldownColumnIds?: readonly string[];
11
+ }
12
+ /** A cell identity only; the authenticated host resolves tenant and report scope. */
13
+ export interface MaterializedReportCell {
14
+ id: string;
15
+ columnId: string;
16
+ }
17
+ /** Host callback for a validated, visible materialized-report cell. */
18
+ export type MaterializedReportDrilldown = (cell: MaterializedReportCell) => void | Promise<void>;
19
+ //# sourceMappingURL=materialized.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialized.d.ts","sourceRoot":"","sources":["../../src/svelte/materialized.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAE7D,gEAAgE;AAChE,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,uBAAuB,CAAC;IACpC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,qFAAqF;AACrF,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,uEAAuE;AACvE,MAAM,MAAM,2BAA2B,GAAG,CACxC,IAAI,EAAE,sBAAsB,KACzB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-reports",
3
- "version": "0.56.0",
3
+ "version": "0.56.2",
4
4
  "description": "Materialized aggregate report models for SMRT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -52,17 +52,17 @@
52
52
  }
53
53
  },
54
54
  "dependencies": {
55
- "@happyvertical/smrt-core": "0.56.0",
56
- "@happyvertical/smrt-jobs": "0.56.0",
57
- "@happyvertical/smrt-types": "0.56.0",
58
- "@happyvertical/smrt-tenancy": "0.56.0",
59
- "@happyvertical/sql": "^0.103.6",
60
- "@happyvertical/smrt-config": "0.56.0",
61
- "@happyvertical/smrt-ui": "0.56.0"
55
+ "@happyvertical/smrt-core": "0.56.2",
56
+ "@happyvertical/smrt-jobs": "0.56.2",
57
+ "@happyvertical/smrt-types": "0.56.2",
58
+ "@happyvertical/smrt-tenancy": "0.56.2",
59
+ "@happyvertical/sql": "^0.103.7",
60
+ "@happyvertical/smrt-config": "0.56.2",
61
+ "@happyvertical/smrt-ui": "0.56.2"
62
62
  },
63
63
  "devDependencies": {
64
- "@happyvertical/smrt-scanner": "0.56.0",
65
- "@happyvertical/smrt-vitest": "0.56.0",
64
+ "@happyvertical/smrt-scanner": "0.56.2",
65
+ "@happyvertical/smrt-vitest": "0.56.2",
66
66
  "@types/node": "24.13.6",
67
67
  "typescript": "6.0.3",
68
68
  "vite": "8.1.4",