@databricks/appkit-ui 0.2.0 → 0.3.0
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/AGENTS.md +5 -2
- package/CLAUDE.md +5 -2
- package/dist/react/charts/create-chart.js +1 -2
- package/dist/react/charts/create-chart.js.map +1 -1
- package/dist/react/charts/types.d.ts +0 -5
- package/dist/react/charts/types.d.ts.map +1 -1
- package/dist/react/charts/types.js.map +1 -1
- package/dist/react/charts/wrapper.d.ts +0 -2
- package/dist/react/charts/wrapper.d.ts.map +1 -1
- package/dist/react/charts/wrapper.js +2 -4
- package/dist/react/charts/wrapper.js.map +1 -1
- package/dist/react/hooks/types.d.ts +0 -2
- package/dist/react/hooks/types.d.ts.map +1 -1
- package/dist/react/hooks/use-analytics-query.d.ts +4 -0
- package/dist/react/hooks/use-analytics-query.d.ts.map +1 -1
- package/dist/react/hooks/use-analytics-query.js +5 -2
- package/dist/react/hooks/use-analytics-query.js.map +1 -1
- package/dist/react/hooks/use-chart-data.d.ts +0 -2
- package/dist/react/hooks/use-chart-data.d.ts.map +1 -1
- package/dist/react/hooks/use-chart-data.js +2 -3
- package/dist/react/hooks/use-chart-data.js.map +1 -1
- package/dist/react/table/table-wrapper.js +2 -3
- package/dist/react/table/table-wrapper.js.map +1 -1
- package/dist/react/table/types.d.ts.map +1 -1
- package/dist/react/ui/accordion.d.ts +5 -5
- package/dist/react/ui/alert-dialog.d.ts +12 -12
- package/dist/react/ui/alert.d.ts +4 -4
- package/dist/react/ui/aspect-ratio.d.ts +2 -2
- package/dist/react/ui/avatar.d.ts +4 -4
- package/dist/react/ui/avatar.d.ts.map +1 -1
- package/dist/react/ui/badge.d.ts +4 -4
- package/dist/react/ui/breadcrumb.d.ts +8 -8
- package/dist/react/ui/button-group.d.ts +6 -6
- package/dist/react/ui/button.d.ts +4 -4
- package/dist/react/ui/calendar.d.ts +3 -3
- package/dist/react/ui/card.d.ts +8 -8
- package/dist/react/ui/carousel.d.ts +6 -6
- package/dist/react/ui/chart.d.ts +5 -5
- package/dist/react/ui/checkbox.d.ts +2 -2
- package/dist/react/ui/collapsible.d.ts +4 -4
- package/dist/react/ui/command.d.ts +10 -10
- package/dist/react/ui/context-menu.d.ts +16 -16
- package/dist/react/ui/dialog.d.ts +11 -11
- package/dist/react/ui/drawer.d.ts +11 -11
- package/dist/react/ui/dropdown-menu.d.ts +16 -16
- package/dist/react/ui/empty.d.ts +7 -7
- package/dist/react/ui/field.d.ts +11 -11
- package/dist/react/ui/form.d.ts +7 -7
- package/dist/react/ui/form.d.ts.map +1 -1
- package/dist/react/ui/hover-card.d.ts +4 -4
- package/dist/react/ui/input-group.d.ts +10 -10
- package/dist/react/ui/input-otp.d.ts +5 -5
- package/dist/react/ui/input.d.ts +2 -2
- package/dist/react/ui/item.d.ts +14 -14
- package/dist/react/ui/popover.d.ts +5 -5
- package/dist/react/ui/progress.d.ts +2 -2
- package/dist/react/ui/radio-group.d.ts +3 -3
- package/dist/react/ui/resizable.d.ts +4 -4
- package/dist/react/ui/scroll-area.d.ts +3 -3
- package/dist/react/ui/select.d.ts +11 -11
- package/dist/react/ui/separator.d.ts +2 -2
- package/dist/react/ui/sheet.d.ts +9 -9
- package/dist/react/ui/sidebar.d.ts +24 -24
- package/dist/react/ui/skeleton.d.ts +2 -2
- package/dist/react/ui/slider.d.ts +2 -2
- package/dist/react/ui/sonner.d.ts +2 -2
- package/dist/react/ui/spinner.d.ts +2 -2
- package/dist/react/ui/switch.d.ts +2 -2
- package/dist/react/ui/tabs.d.ts +5 -5
- package/dist/react/ui/textarea.d.ts +2 -2
- package/dist/react/ui/toggle-group.d.ts +3 -3
- package/dist/react/ui/toggle.d.ts +2 -2
- package/dist/react/ui/tooltip.d.ts +5 -5
- package/dist/react/ui/tooltip.d.ts.map +1 -1
- package/llms.txt +5 -2
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -431,9 +431,12 @@ WHERE workspace_id = :workspaceId
|
|
|
431
431
|
HTTP endpoints exposed (mounted under `/api/analytics`):
|
|
432
432
|
|
|
433
433
|
- `POST /api/analytics/query/:query_key`
|
|
434
|
-
- `POST /api/analytics/users/me/query/:query_key`
|
|
435
434
|
- `GET /api/analytics/arrow-result/:jobId`
|
|
436
|
-
|
|
435
|
+
|
|
436
|
+
**Query file naming convention determines execution context:**
|
|
437
|
+
|
|
438
|
+
- `config/queries/<query_key>.sql` - Executes as service principal (shared cache)
|
|
439
|
+
- `config/queries/<query_key>.obo.sql` - Executes as user (OBO = On-Behalf-Of, per-user cache)
|
|
437
440
|
|
|
438
441
|
Formats:
|
|
439
442
|
|
package/CLAUDE.md
CHANGED
|
@@ -431,9 +431,12 @@ WHERE workspace_id = :workspaceId
|
|
|
431
431
|
HTTP endpoints exposed (mounted under `/api/analytics`):
|
|
432
432
|
|
|
433
433
|
- `POST /api/analytics/query/:query_key`
|
|
434
|
-
- `POST /api/analytics/users/me/query/:query_key`
|
|
435
434
|
- `GET /api/analytics/arrow-result/:jobId`
|
|
436
|
-
|
|
435
|
+
|
|
436
|
+
**Query file naming convention determines execution context:**
|
|
437
|
+
|
|
438
|
+
- `config/queries/<query_key>.sql` - Executes as service principal (shared cache)
|
|
439
|
+
- `config/queries/<query_key>.obo.sql` - Executes as user (OBO = On-Behalf-Of, per-user cache)
|
|
437
440
|
|
|
438
441
|
Formats:
|
|
439
442
|
|
|
@@ -19,7 +19,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
19
19
|
*/
|
|
20
20
|
function createChart(chartType, displayName) {
|
|
21
21
|
const Component = (props) => {
|
|
22
|
-
const { queryKey, parameters, format, transformer,
|
|
22
|
+
const { queryKey, parameters, format, transformer, data, height = 300, className, ariaLabel, testId, ...chartProps } = props;
|
|
23
23
|
return /* @__PURE__ */ jsx(ChartWrapper, {
|
|
24
24
|
...data !== void 0 ? {
|
|
25
25
|
data,
|
|
@@ -32,7 +32,6 @@ function createChart(chartType, displayName) {
|
|
|
32
32
|
parameters,
|
|
33
33
|
format,
|
|
34
34
|
transformer,
|
|
35
|
-
asUser,
|
|
36
35
|
height,
|
|
37
36
|
className,
|
|
38
37
|
ariaLabel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-chart.js","names":[],"sources":["../../../src/react/charts/create-chart.tsx"],"sourcesContent":["import { BaseChart } from \"./base\";\nimport type { ChartType, UnifiedChartProps } from \"./types\";\nimport { ChartWrapper } from \"./wrapper\";\n\n/**\n * Factory function to create chart components.\n * Eliminates boilerplate by generating components with the same pattern.\n *\n * @param chartType - The ECharts chart type\n * @param displayName - Component display name for React DevTools\n * @returns A typed chart component\n *\n * @example\n * ```tsx\n * export const BarChart = createChart<BarChartProps>(\"bar\", \"BarChart\");\n * export const LineChart = createChart<LineChartProps>(\"line\", \"LineChart\");\n * ```\n */\nexport function createChart<TProps extends UnifiedChartProps>(\n chartType: ChartType,\n displayName: string,\n) {\n const Component = (props: TProps) => {\n const {\n // Query props\n queryKey,\n parameters,\n format,\n transformer,\n
|
|
1
|
+
{"version":3,"file":"create-chart.js","names":[],"sources":["../../../src/react/charts/create-chart.tsx"],"sourcesContent":["import { BaseChart } from \"./base\";\nimport type { ChartType, UnifiedChartProps } from \"./types\";\nimport { ChartWrapper } from \"./wrapper\";\n\n/**\n * Factory function to create chart components.\n * Eliminates boilerplate by generating components with the same pattern.\n *\n * @param chartType - The ECharts chart type\n * @param displayName - Component display name for React DevTools\n * @returns A typed chart component\n *\n * @example\n * ```tsx\n * export const BarChart = createChart<BarChartProps>(\"bar\", \"BarChart\");\n * export const LineChart = createChart<LineChartProps>(\"line\", \"LineChart\");\n * ```\n */\nexport function createChart<TProps extends UnifiedChartProps>(\n chartType: ChartType,\n displayName: string,\n) {\n const Component = (props: TProps) => {\n const {\n // Query props\n queryKey,\n parameters,\n format,\n transformer,\n // Data props\n data,\n // Common props\n height = 300,\n className,\n ariaLabel,\n testId,\n // All remaining props pass through to BaseChart\n ...chartProps\n } = props as TProps & {\n queryKey?: string;\n parameters?: Record<string, unknown>;\n format?: string;\n transformer?: unknown;\n data?: unknown;\n height?: number;\n className?: string;\n ariaLabel?: string;\n testId?: string;\n };\n\n const wrapperProps =\n data !== undefined\n ? { data, height, className, ariaLabel, testId }\n : {\n queryKey: queryKey as string,\n parameters,\n format,\n transformer,\n height,\n className,\n ariaLabel,\n testId: testId ?? `${chartType}-chart-${queryKey}`,\n };\n\n return (\n <ChartWrapper {...wrapperProps}>\n {(chartData) => (\n <BaseChart\n data={chartData}\n chartType={chartType}\n height={height}\n className={className}\n {...chartProps}\n />\n )}\n </ChartWrapper>\n );\n };\n\n Component.displayName = displayName;\n return Component;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAkBA,SAAgB,YACd,WACA,aACA;CACA,MAAM,aAAa,UAAkB;EACnC,MAAM,EAEJ,UACA,YACA,QACA,aAEA,MAEA,SAAS,KACT,WACA,WACA,QAEA,GAAG,eACD;AA0BJ,SACE,oBAAC;GAAa,GAdd,SAAS,SACL;IAAE;IAAM;IAAQ;IAAW;IAAW;IAAQ,GAC9C;IACY;IACV;IACA;IACA;IACA;IACA;IACA;IACA,QAAQ,UAAU,GAAG,UAAU,SAAS;IACzC;cAID,cACA,oBAAC;IACC,MAAM;IACK;IACH;IACG;IACX,GAAI;KACJ;IAES;;AAInB,WAAU,cAAc;AACxB,QAAO"}
|
|
@@ -57,11 +57,6 @@ interface QueryProps extends ChartBaseProps {
|
|
|
57
57
|
format?: DataFormat;
|
|
58
58
|
/** Transform raw data before rendering */
|
|
59
59
|
transformer?: <T>(data: T) => T;
|
|
60
|
-
/**
|
|
61
|
-
* Whether to execute the query as the current user
|
|
62
|
-
* @default false
|
|
63
|
-
*/
|
|
64
|
-
asUser?: boolean;
|
|
65
60
|
data?: never;
|
|
66
61
|
}
|
|
67
62
|
/** Props for direct data injection */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/react/charts/types.ts"],"sourcesContent":[],"mappings":";;;;KAOY,UAAA;AAAZ;AAGY,KAAA,WAAA,GAAW,UAAA,GAAA,YAAA;AAGvB;AAWY,KAXA,SAAA,GAWS,KAAA,GAAA,MAAA,GAAA,MAAA,GAAA,KAAA,GAAA,OAAA,GAAA,SAAA,GAAA,OAAA,GAAA,SAAA;;AAAG,KAAZ,SAAA,GAAY,KAAA,GAAQ,MAAR,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA;;AAAc,KAO1B,iBAAA,GAP0B,aAAA,GAAA,YAAA,GAAA,WAAA;AAOtC;AAGiB,UAAA,cAAA,CAAc;EAAA;OAWd,CAAA,EAAA,MAAA;;EAmBC,UAAA,CAAA,EAAA,OAAA;EAQD;;;;;;cAAmB,CAAA,EA3BnB,iBA2BmB;EAAc;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/react/charts/types.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../../src/react/charts/types.ts"],"sourcesContent":["import type { Table } from \"apache-arrow\";\n\n// ============================================================================\n// Data Format Types\n// ============================================================================\n\n/** Supported data formats for analytics queries */\nexport type DataFormat = \"json\" | \"arrow\" | \"auto\";\n\n/** Chart orientation */\nexport type Orientation = \"vertical\" | \"horizontal\";\n\n/** Supported chart types */\nexport type ChartType =\n | \"bar\"\n | \"line\"\n | \"area\"\n | \"pie\"\n | \"donut\"\n | \"scatter\"\n | \"radar\"\n | \"heatmap\";\n\n/** Data that can be passed to unified charts */\nexport type ChartData = Table | Record<string, unknown>[];\n\n// ============================================================================\n// Base Props (shared by all charts)\n// ============================================================================\n\n/** Color palette types for different visualization needs */\nexport type ChartColorPalette = \"categorical\" | \"sequential\" | \"diverging\";\n\n/** Common visual and behavior props for all charts */\nexport interface ChartBaseProps {\n /** Chart title */\n title?: string;\n /** Show legend */\n showLegend?: boolean;\n /**\n * Color palette to use. Auto-selected based on chart type if not specified.\n * - \"categorical\": Distinct colors for different categories (bar, pie, line)\n * - \"sequential\": Gradient for magnitude/intensity (heatmap)\n * - \"diverging\": Two-tone for positive/negative values\n */\n colorPalette?: ChartColorPalette;\n /** Custom colors for series (overrides colorPalette) */\n colors?: string[];\n /** Chart height in pixels @default 300 */\n height?: number;\n /** Additional CSS classes */\n className?: string;\n\n /** X-axis field key. Auto-detected from schema if not provided. */\n xKey?: string;\n /** Y-axis field key(s). Auto-detected from schema if not provided. */\n yKey?: string | string[];\n\n /** Accessibility label for screen readers */\n ariaLabel?: string;\n /** Test ID for automated testing */\n testId?: string;\n\n /** Additional ECharts options to merge */\n options?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Query-based Props (chart fetches data)\n// ============================================================================\n\n/** Props for query-based data fetching */\nexport interface QueryProps extends ChartBaseProps {\n /** Analytics query key registered with analytics plugin */\n queryKey: string;\n /** Query parameters passed to the analytics endpoint */\n parameters?: Record<string, unknown>;\n /**\n * Data format to use\n * - \"json\": Use JSON format (smaller payloads, simpler)\n * - \"arrow\": Use Arrow format (faster for large datasets)\n * - \"auto\": Automatically select based on expected data size\n * @default \"auto\"\n */\n format?: DataFormat;\n /** Transform raw data before rendering */\n transformer?: <T>(data: T) => T;\n
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../../src/react/charts/types.ts"],"sourcesContent":["import type { Table } from \"apache-arrow\";\n\n// ============================================================================\n// Data Format Types\n// ============================================================================\n\n/** Supported data formats for analytics queries */\nexport type DataFormat = \"json\" | \"arrow\" | \"auto\";\n\n/** Chart orientation */\nexport type Orientation = \"vertical\" | \"horizontal\";\n\n/** Supported chart types */\nexport type ChartType =\n | \"bar\"\n | \"line\"\n | \"area\"\n | \"pie\"\n | \"donut\"\n | \"scatter\"\n | \"radar\"\n | \"heatmap\";\n\n/** Data that can be passed to unified charts */\nexport type ChartData = Table | Record<string, unknown>[];\n\n// ============================================================================\n// Base Props (shared by all charts)\n// ============================================================================\n\n/** Color palette types for different visualization needs */\nexport type ChartColorPalette = \"categorical\" | \"sequential\" | \"diverging\";\n\n/** Common visual and behavior props for all charts */\nexport interface ChartBaseProps {\n /** Chart title */\n title?: string;\n /** Show legend */\n showLegend?: boolean;\n /**\n * Color palette to use. Auto-selected based on chart type if not specified.\n * - \"categorical\": Distinct colors for different categories (bar, pie, line)\n * - \"sequential\": Gradient for magnitude/intensity (heatmap)\n * - \"diverging\": Two-tone for positive/negative values\n */\n colorPalette?: ChartColorPalette;\n /** Custom colors for series (overrides colorPalette) */\n colors?: string[];\n /** Chart height in pixels @default 300 */\n height?: number;\n /** Additional CSS classes */\n className?: string;\n\n /** X-axis field key. Auto-detected from schema if not provided. */\n xKey?: string;\n /** Y-axis field key(s). Auto-detected from schema if not provided. */\n yKey?: string | string[];\n\n /** Accessibility label for screen readers */\n ariaLabel?: string;\n /** Test ID for automated testing */\n testId?: string;\n\n /** Additional ECharts options to merge */\n options?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Query-based Props (chart fetches data)\n// ============================================================================\n\n/** Props for query-based data fetching */\nexport interface QueryProps extends ChartBaseProps {\n /** Analytics query key registered with analytics plugin */\n queryKey: string;\n /** Query parameters passed to the analytics endpoint */\n parameters?: Record<string, unknown>;\n /**\n * Data format to use\n * - \"json\": Use JSON format (smaller payloads, simpler)\n * - \"arrow\": Use Arrow format (faster for large datasets)\n * - \"auto\": Automatically select based on expected data size\n * @default \"auto\"\n */\n format?: DataFormat;\n /** Transform raw data before rendering */\n transformer?: <T>(data: T) => T;\n // Discriminator: cannot use direct data with query\n data?: never;\n}\n\n// ============================================================================\n// Data-based Props (chart receives data externally)\n// ============================================================================\n\n/** Props for direct data injection */\nexport interface DataProps extends ChartBaseProps {\n /** Arrow Table or JSON array */\n data: ChartData;\n\n // Discriminator: cannot use query props with direct data\n queryKey?: never;\n parameters?: never;\n format?: never;\n transformer?: never;\n}\n\n// ============================================================================\n// Union Types for Each Chart\n// ============================================================================\n\n/** Base union type - either query-based or data-based */\nexport type UnifiedChartProps = QueryProps | DataProps;\n\n// ============================================================================\n// Chart-Specific Props\n// ============================================================================\n\n/** Props specific to bar charts */\nexport interface BarChartSpecificProps {\n /** Chart orientation @default \"vertical\" */\n orientation?: Orientation;\n /** Stack bars */\n stacked?: boolean;\n}\n\n/** Props specific to line charts */\nexport interface LineChartSpecificProps {\n /** Chart orientation @default \"vertical\" */\n orientation?: Orientation;\n /** Show data point symbols @default false */\n showSymbol?: boolean;\n /** Smooth line curves @default true */\n smooth?: boolean;\n}\n\n/** Props specific to area charts */\nexport interface AreaChartSpecificProps {\n /** Chart orientation @default \"vertical\" */\n orientation?: Orientation;\n /** Show data point symbols @default false */\n showSymbol?: boolean;\n /** Smooth line curves @default true */\n smooth?: boolean;\n /** Stack areas @default false */\n stacked?: boolean;\n}\n\n/** Props specific to scatter charts */\nexport interface ScatterChartSpecificProps {\n /** Symbol size @default 8 */\n symbolSize?: number;\n}\n\n/** Props specific to pie/donut charts */\nexport interface PieChartSpecificProps {\n /** Inner radius for donut charts (0-100%) @default 0 */\n innerRadius?: number;\n /** Show labels on slices @default true */\n showLabels?: boolean;\n /** Label position @default \"outside\" */\n labelPosition?: \"outside\" | \"inside\" | \"center\";\n}\n\n/** Props specific to radar charts */\nexport interface RadarChartSpecificProps {\n /** Show area fill @default true */\n showArea?: boolean;\n}\n\n/** Props specific to heatmap charts */\nexport interface HeatmapChartSpecificProps {\n /**\n * Field key for the Y-axis categories.\n * For heatmaps, data should have: xKey (column), yAxisKey (row), and yKey (value).\n */\n yAxisKey?: string;\n /** Min value for color scale (auto-detected if not provided) */\n min?: number;\n /** Max value for color scale (auto-detected if not provided) */\n max?: number;\n /** Show value labels on cells @default false */\n showLabels?: boolean;\n}\n\n// ============================================================================\n// Complete Chart Props (union + specific)\n// ============================================================================\n\nexport type BarChartProps = (QueryProps | DataProps) & BarChartSpecificProps;\nexport type LineChartProps = (QueryProps | DataProps) & LineChartSpecificProps;\nexport type AreaChartProps = (QueryProps | DataProps) & AreaChartSpecificProps;\nexport type ScatterChartProps = (QueryProps | DataProps) &\n ScatterChartSpecificProps;\nexport type PieChartProps = (QueryProps | DataProps) & PieChartSpecificProps;\nexport type DonutChartProps = (QueryProps | DataProps) & PieChartSpecificProps;\nexport type RadarChartProps = (QueryProps | DataProps) &\n RadarChartSpecificProps;\nexport type HeatmapChartProps = (QueryProps | DataProps) &\n HeatmapChartSpecificProps;\n\n// ============================================================================\n// Internal Types\n// ============================================================================\n\n/** Base normalized data shared by all chart types */\nexport interface NormalizedChartDataBase {\n xData: (string | number)[];\n xField: string;\n yFields: string[];\n chartType: \"timeseries\" | \"categorical\";\n}\n\n/** Normalized chart data for rendering (standard charts) */\nexport interface NormalizedChartData extends NormalizedChartDataBase {\n yDataMap: Record<string, (string | number)[]>;\n}\n\n/** Type guard to check if data is an Arrow Table */\nexport function isArrowTable(data: ChartData): data is Table {\n return (\n data !== null &&\n typeof data === \"object\" &&\n \"schema\" in data &&\n \"numRows\" in data &&\n typeof (data as Table).getChild === \"function\"\n );\n}\n\n/** Type guard to check if props are query-based */\nexport function isQueryProps(props: UnifiedChartProps): props is QueryProps {\n return (\n \"queryKey\" in props &&\n typeof props.queryKey === \"string\" &&\n props.queryKey.length > 0\n );\n}\n\n/** Type guard to check if props are data-based */\nexport function isDataProps(props: UnifiedChartProps): props is DataProps {\n return \"data\" in props && props.data != null;\n}\n"],"mappings":";;AA2NA,SAAgB,aAAa,MAAgC;AAC3D,QACE,SAAS,QACT,OAAO,SAAS,YAChB,YAAY,QACZ,aAAa,QACb,OAAQ,KAAe,aAAa;;;AAKxC,SAAgB,aAAa,OAA+C;AAC1E,QACE,cAAc,SACd,OAAO,MAAM,aAAa,YAC1B,MAAM,SAAS,SAAS;;;AAK5B,SAAgB,YAAY,OAA8C;AACxE,QAAO,UAAU,SAAS,MAAM,QAAQ"}
|
|
@@ -4,8 +4,6 @@ import * as react_jsx_runtime285 from "react/jsx-runtime";
|
|
|
4
4
|
|
|
5
5
|
//#region src/react/charts/wrapper.d.ts
|
|
6
6
|
interface ChartWrapperQueryProps {
|
|
7
|
-
/** Whether to execute the query as a user. Default is false. */
|
|
8
|
-
asUser?: boolean;
|
|
9
7
|
/** Analytics query key */
|
|
10
8
|
queryKey: string;
|
|
11
9
|
/** Query parameters */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.d.ts","names":[],"sources":["../../../src/react/charts/wrapper.tsx"],"sourcesContent":[],"mappings":";;;;;UAaU,sBAAA;;;EAAA;EAAsB,
|
|
1
|
+
{"version":3,"file":"wrapper.d.ts","names":[],"sources":["../../../src/react/charts/wrapper.tsx"],"sourcesContent":[],"mappings":";;;;;UAaU,sBAAA;;;EAAA;EAAsB,UAAA,CAAA,EAIjB,MAJiB,CAAA,MAAA,EAAA,OAAA,CAAA;;QAMrB,CAAA,EAAA,UAAA;;aAEqB,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EAAN,CAAM,EAAA,GAAA,CAAA;EAAC;EAKvB,IAAA,CAAA,EAAA,KAAA;AAEO;UAFP,qBAAA,CAUW;;MAUY,EAlBzB,SAkByB;EAAS;EAG9B,QAAA,CAAA,EAAA,KAAA;EAAiB,UAAA,CAAA,EAAA,KAAA;QAAG,CAAA,EAAA,KAAA;aAC7B,CAAA,EAAA,KAAA;;UAdO,WAAA,CAcuC;EA0GjC;EAAY,MAAA,CAAA,EAAA,MAAA;;WAAyB,CAAA,EAAA,MAAA;EAAA;;;;;mBA9GlC,cAAc;;KAGrB,iBAAA,GAAoB,eAC7B,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;iBA0GZ,YAAA,QAAoB,oBAAiB,oBAAA,CAAA,GAAA,CAAA"}
|
|
@@ -7,13 +7,12 @@ import { LoadingSkeleton } from "./loading.js";
|
|
|
7
7
|
import { jsx } from "react/jsx-runtime";
|
|
8
8
|
|
|
9
9
|
//#region src/react/charts/wrapper.tsx
|
|
10
|
-
function QueryModeContent({ queryKey, parameters, format, transformer,
|
|
10
|
+
function QueryModeContent({ queryKey, parameters, format, transformer, height, className, ariaLabel, testId, children }) {
|
|
11
11
|
const { data, loading, error, isEmpty } = useChartData({
|
|
12
12
|
queryKey,
|
|
13
13
|
parameters,
|
|
14
14
|
format,
|
|
15
|
-
transformer
|
|
16
|
-
asUser
|
|
15
|
+
transformer
|
|
17
16
|
});
|
|
18
17
|
if (loading) return /* @__PURE__ */ jsx(LoadingSkeleton, { height: height ?? 300 });
|
|
19
18
|
if (error) return /* @__PURE__ */ jsx(ErrorState, { error });
|
|
@@ -81,7 +80,6 @@ function ChartWrapper(props) {
|
|
|
81
80
|
parameters: props.parameters,
|
|
82
81
|
format: props.format,
|
|
83
82
|
transformer: props.transformer,
|
|
84
|
-
asUser: props.asUser,
|
|
85
83
|
height,
|
|
86
84
|
className,
|
|
87
85
|
ariaLabel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapper.js","names":[],"sources":["../../../src/react/charts/wrapper.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useChartData } from \"../hooks/use-chart-data\";\nimport { ChartErrorBoundary } from \"./chart-error-boundary\";\nimport { EmptyState } from \"./empty\";\nimport { ErrorState } from \"./error\";\nimport { LoadingSkeleton } from \"./loading\";\nimport type { ChartData, DataFormat } from \"./types\";\nimport { isArrowTable } from \"./types\";\n\n// ============================================================================\n// Props Types\n// ============================================================================\n\ninterface ChartWrapperQueryProps {\n /**
|
|
1
|
+
{"version":3,"file":"wrapper.js","names":[],"sources":["../../../src/react/charts/wrapper.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useChartData } from \"../hooks/use-chart-data\";\nimport { ChartErrorBoundary } from \"./chart-error-boundary\";\nimport { EmptyState } from \"./empty\";\nimport { ErrorState } from \"./error\";\nimport { LoadingSkeleton } from \"./loading\";\nimport type { ChartData, DataFormat } from \"./types\";\nimport { isArrowTable } from \"./types\";\n\n// ============================================================================\n// Props Types\n// ============================================================================\n\ninterface ChartWrapperQueryProps {\n /** Analytics query key */\n queryKey: string;\n /** Query parameters */\n parameters?: Record<string, unknown>;\n /** Data format preference */\n format?: DataFormat;\n /** Transform data after fetching */\n transformer?: <T>(data: T) => T;\n /** Direct data - not used in query mode */\n data?: never;\n}\n\ninterface ChartWrapperDataProps {\n /** Direct data (Arrow Table or JSON array) */\n data: ChartData;\n /** Not used in data mode */\n queryKey?: never;\n parameters?: never;\n format?: never;\n transformer?: never;\n}\n\ninterface CommonProps {\n /** Chart height in pixels */\n height?: number;\n /** Additional CSS classes */\n className?: string;\n /** Accessibility label */\n ariaLabel?: string;\n /** Test ID for automated testing */\n testId?: string;\n /** Render function receiving the chart data */\n children: (data: ChartData) => ReactNode;\n}\n\nexport type ChartWrapperProps = CommonProps &\n (ChartWrapperQueryProps | ChartWrapperDataProps);\n\n// ============================================================================\n// Query Mode Content\n// ============================================================================\n\nfunction QueryModeContent({\n queryKey,\n parameters,\n format,\n transformer,\n height,\n className,\n ariaLabel,\n testId,\n children,\n}: CommonProps & ChartWrapperQueryProps) {\n const { data, loading, error, isEmpty } = useChartData({\n queryKey,\n parameters,\n format,\n transformer,\n });\n\n if (loading) return <LoadingSkeleton height={height ?? 300} />;\n if (error) return <ErrorState error={error} />;\n if (isEmpty || !data) return <EmptyState />;\n\n return (\n <ChartErrorBoundary\n fallback={<ErrorState error=\"Failed to render chart\" />}\n >\n <div\n className={className}\n style={{ height }}\n aria-label={ariaLabel}\n data-testid={testId}\n role=\"img\"\n >\n {children(data)}\n </div>\n </ChartErrorBoundary>\n );\n}\n\n// ============================================================================\n// Data Mode Content\n// ============================================================================\n\nfunction DataModeContent({\n data,\n height,\n className,\n ariaLabel,\n testId,\n children,\n}: CommonProps & ChartWrapperDataProps) {\n const isEmpty = isArrowTable(data)\n ? data.numRows === 0\n : !Array.isArray(data) || data.length === 0;\n\n if (isEmpty) return <EmptyState />;\n\n return (\n <ChartErrorBoundary\n fallback={<ErrorState error=\"Failed to render chart\" />}\n >\n <div\n className={className}\n style={{ height }}\n aria-label={ariaLabel}\n data-testid={testId}\n role=\"img\"\n >\n {children(data)}\n </div>\n </ChartErrorBoundary>\n );\n}\n\n// ============================================================================\n// Main Wrapper Component\n// ============================================================================\n\n/**\n * Wrapper component for charts.\n * Handles data fetching (query mode) or direct data injection (data mode).\n *\n * @example Query mode - fetches data from analytics endpoint\n * ```tsx\n * <ChartWrapper\n * queryKey=\"spend_data\"\n * parameters={{ limit: 100 }}\n * format=\"auto\"\n * >\n * {(data) => <MyChart data={data} />}\n * </ChartWrapper>\n * ```\n *\n * @example Data mode - uses provided data directly\n * ```tsx\n * <ChartWrapper data={myArrowTable}>\n * {(data) => <MyChart data={data} />}\n * </ChartWrapper>\n * ```\n */\nexport function ChartWrapper(props: ChartWrapperProps) {\n const { height = 300, className, ariaLabel, testId, children } = props;\n\n // Data mode: use provided data directly\n if (\"data\" in props && props.data !== undefined) {\n return (\n <DataModeContent\n data={props.data}\n height={height}\n className={className}\n ariaLabel={ariaLabel}\n testId={testId}\n >\n {children}\n </DataModeContent>\n );\n }\n\n // Query mode: fetch data from analytics endpoint\n if (\"queryKey\" in props && props.queryKey !== undefined) {\n return (\n <QueryModeContent\n queryKey={props.queryKey}\n parameters={props.parameters}\n format={props.format}\n transformer={props.transformer}\n height={height}\n className={className}\n ariaLabel={ariaLabel}\n testId={testId}\n >\n {children}\n </QueryModeContent>\n );\n }\n\n // Should never reach here due to TypeScript, but safety fallback\n return <ErrorState error=\"Chart requires either 'queryKey' or 'data' prop\" />;\n}\n"],"mappings":";;;;;;;;;AAwDA,SAAS,iBAAiB,EACxB,UACA,YACA,QACA,aACA,QACA,WACA,WACA,QACA,YACuC;CACvC,MAAM,EAAE,MAAM,SAAS,OAAO,YAAY,aAAa;EACrD;EACA;EACA;EACA;EACD,CAAC;AAEF,KAAI,QAAS,QAAO,oBAAC,mBAAgB,QAAQ,UAAU,MAAO;AAC9D,KAAI,MAAO,QAAO,oBAAC,cAAkB,QAAS;AAC9C,KAAI,WAAW,CAAC,KAAM,QAAO,oBAAC,eAAa;AAE3C,QACE,oBAAC;EACC,UAAU,oBAAC,cAAW,OAAM,2BAA2B;YAEvD,oBAAC;GACY;GACX,OAAO,EAAE,QAAQ;GACjB,cAAY;GACZ,eAAa;GACb,MAAK;aAEJ,SAAS,KAAK;IACX;GACa;;AAQzB,SAAS,gBAAgB,EACvB,MACA,QACA,WACA,WACA,QACA,YACsC;AAKtC,KAJgB,aAAa,KAAK,GAC9B,KAAK,YAAY,IACjB,CAAC,MAAM,QAAQ,KAAK,IAAI,KAAK,WAAW,EAE/B,QAAO,oBAAC,eAAa;AAElC,QACE,oBAAC;EACC,UAAU,oBAAC,cAAW,OAAM,2BAA2B;YAEvD,oBAAC;GACY;GACX,OAAO,EAAE,QAAQ;GACjB,cAAY;GACZ,eAAa;GACb,MAAK;aAEJ,SAAS,KAAK;IACX;GACa;;;;;;;;;;;;;;;;;;;;;;;;AA8BzB,SAAgB,aAAa,OAA0B;CACrD,MAAM,EAAE,SAAS,KAAK,WAAW,WAAW,QAAQ,aAAa;AAGjE,KAAI,UAAU,SAAS,MAAM,SAAS,OACpC,QACE,oBAAC;EACC,MAAM,MAAM;EACJ;EACG;EACA;EACH;EAEP;GACe;AAKtB,KAAI,cAAc,SAAS,MAAM,aAAa,OAC5C,QACE,oBAAC;EACC,UAAU,MAAM;EAChB,YAAY,MAAM;EAClB,QAAQ,MAAM;EACd,aAAa,MAAM;EACX;EACG;EACA;EACH;EAEP;GACgB;AAKvB,QAAO,oBAAC,cAAW,OAAM,oDAAoD"}
|
|
@@ -28,8 +28,6 @@ interface UseAnalyticsQueryOptions<F extends AnalyticsFormat = "JSON"> {
|
|
|
28
28
|
maxParametersSize?: number;
|
|
29
29
|
/** Whether to automatically start the query when the hook is mounted. Default is true. */
|
|
30
30
|
autoStart?: boolean;
|
|
31
|
-
/** Whether to execute the query as a user. Default is false. */
|
|
32
|
-
asUser?: boolean;
|
|
33
31
|
}
|
|
34
32
|
/** Result state returned by useAnalyticsQuery */
|
|
35
33
|
interface UseAnalyticsQueryResult<T> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/react/hooks/types.ts"],"sourcesContent":[],"mappings":";;;;KAOY,eAAA;AAAZ;AAYA;;;;;;;AAeA;;AAAoD,UAfnC,eAemC,CAAA,aAdrC,MAcqC,CAAA,MAAA,EAAA,OAAA,CAAA,GAdX,MAcW,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,SAb1C,KAa0C,CAAA;;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/react/hooks/types.ts"],"sourcesContent":[],"mappings":";;;;KAOY,eAAA;AAAZ;AAYA;;;;;;;AAeA;;AAAoD,UAfnC,eAemC,CAAA,aAdrC,MAcqC,CAAA,MAAA,EAAA,OAAA,CAAA,GAdX,MAcW,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,SAb1C,KAa0C,CAAA;;;AAYpD;AA2BA;EASY,SAAA,SAAA,CAAA,EAxDW,IAwDM;;;AACK,UAjDjB,wBAiDiB,CAAA,UAjDkB,eAiDlB,GAAA,MAAA,CAAA,CAAA;;QAAgB,CAAA,EA/CvC,CA+CuC;;EAAG,iBAAA,CAAA,EAAA,MAAA;EAIzC;EAAQ,SAAA,CAAA,EAAA,OAAA;;;AAEE,UA3CL,uBA2CK,CAAA,CAAA,CAAA,CAAA;;EAAD,IAAA,EAzCb,CAyCa,GAAA,IAAA;EAMT;EAAW,OAAA,EAAA,OAAA;;OAAqC,EAAA,MAAA,GAAA,IAAA;;;;;;;;AAU5D;;;;;;;;;;;;AAKM,UArCW,aAAA,CAqCX;MACF,EAAA,MAAA,CAAA,EAAA;IAAM,IAAA,EAAA,MAAA;IAOE,UAAA,EA1CI,MA0Ce,CAAA,MAAA,EAAA,OAAA,CAAA;IAAA,MAAA,EAAA,OAAA,EAAA;;;;AAIS,KAxC5B,iBAwC4B,CAAA,CAAA,CAAA,GAAA,MAAA,QAAhB,MAvCV,CAuCU,IAAA,MAAA,SAvCU,CAuCV,GAAA,KAAA,GAvCsB,CAuCtB,GAvC0B,CAuC1B,CAvC4B,CAuC5B,CAAA;;AAAmC,KAnC/C,QAAA,GAAW,iBAmCoC,CAnClB,aAmCkB,CAAA,SAAA,KAAA,GAAA,MAAA,GAjCvD,iBAiCuD,CAjCrC,aAiCqC,CAAA;;AAK3D;;;AAAyD,KAhC7C,WAgC6C,CAAA,CAAA,EAAA,CAAA,CAAA,GAhCzB,CAgCyB,SAhCf,iBAgCe,CAhCG,aAgCH,CAAA,GA/BrD,aA+BqD,CA/BvC,CA+BuC,CAAA,SAAA;QAAlB,EAAA,KAAA,EAAA;IA9BjC,IACA,CA8BF,GA7BA,CA6BA;;;;;AAGM,KA1BE,YA0BF,CAAA,CAAA,CAAA,GA1BoB,CA0BpB,SA1B8B,iBA0B9B,CA1BgD,aA0BhD,CAAA,GAzBN,aAyBM,CAzBQ,CAyBR,CAAA,SAAA;EAEO,MAAA,EA3BsB,KA2BtB,CAAA,KAAc,EAAA,CAAA;IA1BzB,UAAU,0BACR,IACA,0BACF,0BACF;;;;;;KAOQ,oCAGA,mBACR,oBAAoB,gBAAgB,aAAa,MAAM,YAAY,GAAG;;;;KAK9D,iBAAiB,UAAU,kBAAkB,iBACrD,cAAc;;IACZ,IACA,0BACF;UAEa,cAAA;iBACA"}
|
|
@@ -10,6 +10,10 @@ import { AnalyticsFormat, InferParams, InferResultByFormat, QueryKey, UseAnalyti
|
|
|
10
10
|
* - `format: "JSON"` (default): Returns typed array from QueryRegistry
|
|
11
11
|
* - `format: "ARROW"`: Returns TypedArrowTable with row type preserved
|
|
12
12
|
*
|
|
13
|
+
* Note: User context execution is determined by query file naming:
|
|
14
|
+
* - `queryKey.obo.sql`: Executes as user (OBO = on-behalf-of / user delegation)
|
|
15
|
+
* - `queryKey.sql`: Executes as service principal
|
|
16
|
+
*
|
|
13
17
|
* @param queryKey - Analytics query identifier
|
|
14
18
|
* @param parameters - Query parameters (type-safe based on QueryRegistry)
|
|
15
19
|
* @param options - Analytics query settings including format
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-analytics-query.d.ts","names":[],"sources":["../../../src/react/hooks/use-analytics-query.ts"],"sourcesContent":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"use-analytics-query.d.ts","names":[],"sources":["../../../src/react/hooks/use-analytics-query.ts"],"sourcesContent":[],"mappings":";;;;;;AAqDA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,yCAEJ,WAAW,oBACX,oCAEA,gBACG,YAAY,qBAChB,yBAAyB,KACjC,wBAAwB,oBAAoB,GAAG,GAAG"}
|
|
@@ -20,6 +20,10 @@ function getArrowStreamUrl(id) {
|
|
|
20
20
|
* - `format: "JSON"` (default): Returns typed array from QueryRegistry
|
|
21
21
|
* - `format: "ARROW"`: Returns TypedArrowTable with row type preserved
|
|
22
22
|
*
|
|
23
|
+
* Note: User context execution is determined by query file naming:
|
|
24
|
+
* - `queryKey.obo.sql`: Executes as user (OBO = on-behalf-of / user delegation)
|
|
25
|
+
* - `queryKey.sql`: Executes as service principal
|
|
26
|
+
*
|
|
23
27
|
* @param queryKey - Analytics query identifier
|
|
24
28
|
* @param parameters - Query parameters (type-safe based on QueryRegistry)
|
|
25
29
|
* @param options - Analytics query settings including format
|
|
@@ -41,9 +45,8 @@ function useAnalyticsQuery(queryKey, parameters, options = {}) {
|
|
|
41
45
|
const format = options?.format ?? "JSON";
|
|
42
46
|
const maxParametersSize = options?.maxParametersSize ?? 100 * 1024;
|
|
43
47
|
const autoStart = options?.autoStart ?? true;
|
|
44
|
-
const asUser = options?.asUser ?? false;
|
|
45
48
|
const devMode = getDevMode();
|
|
46
|
-
const urlSuffix =
|
|
49
|
+
const urlSuffix = `/api/analytics/query/${encodeURIComponent(queryKey)}${devMode}`;
|
|
47
50
|
const [data, setData] = useState(null);
|
|
48
51
|
const [loading, setLoading] = useState(false);
|
|
49
52
|
const [error, setError] = useState(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-analytics-query.js","names":["error"],"sources":["../../../src/react/hooks/use-analytics-query.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"use-analytics-query.js","names":["error"],"sources":["../../../src/react/hooks/use-analytics-query.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { ArrowClient, connectSSE } from \"@/js\";\nimport type {\n AnalyticsFormat,\n InferParams,\n InferResultByFormat,\n QueryKey,\n UseAnalyticsQueryOptions,\n UseAnalyticsQueryResult,\n} from \"./types\";\nimport { useQueryHMR } from \"./use-query-hmr\";\n\nfunction getDevMode() {\n const url = new URL(window.location.href);\n const searchParams = url.searchParams;\n const dev = searchParams.get(\"dev\");\n\n return dev ? `?dev=${dev}` : \"\";\n}\n\nfunction getArrowStreamUrl(id: string) {\n return `/api/analytics/arrow-result/${id}`;\n}\n\n/**\n * Subscribe to an analytics query over SSE and returns its latest result.\n * Integration hook between client and analytics plugin.\n *\n * The return type is automatically inferred based on the format:\n * - `format: \"JSON\"` (default): Returns typed array from QueryRegistry\n * - `format: \"ARROW\"`: Returns TypedArrowTable with row type preserved\n *\n * Note: User context execution is determined by query file naming:\n * - `queryKey.obo.sql`: Executes as user (OBO = on-behalf-of / user delegation)\n * - `queryKey.sql`: Executes as service principal\n *\n * @param queryKey - Analytics query identifier\n * @param parameters - Query parameters (type-safe based on QueryRegistry)\n * @param options - Analytics query settings including format\n * @returns Query result state with format-appropriate data type\n *\n * @example JSON format (default)\n * ```typescript\n * const { data } = useAnalyticsQuery(\"spend_data\", params);\n * // data: Array<{ group_key: string; cost_usd: number; ... }> | null\n * ```\n *\n * @example Arrow format\n * ```typescript\n * const { data } = useAnalyticsQuery(\"spend_data\", params, { format: \"ARROW\" });\n * // data: TypedArrowTable<{ group_key: string; cost_usd: number; ... }> | null\n * ```\n */\nexport function useAnalyticsQuery<\n T = unknown,\n K extends QueryKey = QueryKey,\n F extends AnalyticsFormat = \"JSON\",\n>(\n queryKey: K,\n parameters?: InferParams<K> | null,\n options: UseAnalyticsQueryOptions<F> = {} as UseAnalyticsQueryOptions<F>,\n): UseAnalyticsQueryResult<InferResultByFormat<T, K, F>> {\n const format = options?.format ?? \"JSON\";\n const maxParametersSize = options?.maxParametersSize ?? 100 * 1024;\n const autoStart = options?.autoStart ?? true;\n\n const devMode = getDevMode();\n const urlSuffix = `/api/analytics/query/${encodeURIComponent(queryKey)}${devMode}`;\n\n type ResultType = InferResultByFormat<T, K, F>;\n const [data, setData] = useState<ResultType | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n if (!queryKey || queryKey.trim().length === 0) {\n throw new Error(\n \"useAnalyticsQuery: 'queryKey' must be a non-empty string.\",\n );\n }\n\n const payload = useMemo(() => {\n try {\n const serialized = JSON.stringify({ parameters, format });\n const sizeInBytes = new Blob([serialized]).size;\n if (sizeInBytes > maxParametersSize) {\n throw new Error(\n \"useAnalyticsQuery: Parameters size exceeds the maximum allowed size\",\n );\n }\n\n return serialized;\n } catch (error) {\n console.error(\"useAnalyticsQuery: Failed to serialize parameters\", error);\n return null;\n }\n }, [parameters, format, maxParametersSize]);\n\n const start = useCallback(() => {\n if (payload === null) {\n setError(\"Failed to serialize query parameters\");\n return;\n }\n\n // Abort previous request if exists\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n\n setLoading(true);\n setError(null);\n setData(null);\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n connectSSE({\n url: urlSuffix,\n payload: payload,\n signal: abortController.signal,\n onMessage: async (message) => {\n try {\n const parsed = JSON.parse(message.data);\n\n // success - JSON format\n if (parsed.type === \"result\") {\n setLoading(false);\n setData(parsed.data as ResultType);\n return;\n }\n\n // success - Arrow format\n if (parsed.type === \"arrow\") {\n try {\n const arrowData = await ArrowClient.fetchArrow(\n getArrowStreamUrl(parsed.statement_id),\n );\n const table = await ArrowClient.processArrowBuffer(arrowData);\n setLoading(false);\n // Table is cast to TypedArrowTable with row type from QueryRegistry\n setData(table as ResultType);\n return;\n } catch (error) {\n console.error(\n \"[useAnalyticsQuery] Failed to fetch Arrow data\",\n error,\n );\n setLoading(false);\n setError(\"Unable to load data, please try again\");\n return;\n }\n }\n\n // error\n if (parsed.type === \"error\" || parsed.error || parsed.code) {\n const errorMsg =\n parsed.error || parsed.message || \"Unable to execute query\";\n\n setLoading(false);\n setError(errorMsg);\n\n if (parsed.code) {\n console.error(\n `[useAnalyticsQuery] Code: ${parsed.code}, Message: ${errorMsg}`,\n );\n }\n return;\n }\n } catch (error) {\n console.warn(\"[useAnalyticsQuery] Malformed message received\", error);\n }\n },\n onError: (error) => {\n if (abortController.signal.aborted) return;\n setLoading(false);\n\n let userMessage = \"Unable to load data, please try again\";\n\n if (error instanceof Error) {\n if (error.name === \"AbortError\") {\n userMessage = \"Request timed out, please try again\";\n } else if (error.message.includes(\"Failed to fetch\")) {\n userMessage = \"Network error. Please check your connection.\";\n }\n\n console.error(\"[useAnalyticsQuery] Error\", {\n queryKey,\n error: error.message,\n stack: error.stack,\n });\n }\n setError(userMessage);\n },\n });\n }, [queryKey, payload, urlSuffix]);\n\n useEffect(() => {\n if (autoStart) {\n start();\n }\n\n return () => {\n abortControllerRef.current?.abort();\n };\n }, [start, autoStart]);\n\n // Enable HMR for query updates in dev mode\n useQueryHMR(queryKey, start);\n\n return { data, loading, error };\n}\n"],"mappings":";;;;;;;AAYA,SAAS,aAAa;CAGpB,MAAM,MAFM,IAAI,IAAI,OAAO,SAAS,KAAK,CAChB,aACA,IAAI,MAAM;AAEnC,QAAO,MAAM,QAAQ,QAAQ;;AAG/B,SAAS,kBAAkB,IAAY;AACrC,QAAO,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCxC,SAAgB,kBAKd,UACA,YACA,UAAuC,EAAE,EACc;CACvD,MAAM,SAAS,SAAS,UAAU;CAClC,MAAM,oBAAoB,SAAS,qBAAqB,MAAM;CAC9D,MAAM,YAAY,SAAS,aAAa;CAExC,MAAM,UAAU,YAAY;CAC5B,MAAM,YAAY,wBAAwB,mBAAmB,SAAS,GAAG;CAGzE,MAAM,CAAC,MAAM,WAAW,SAA4B,KAAK;CACzD,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAC7C,MAAM,CAAC,OAAO,YAAY,SAAwB,KAAK;CACvD,MAAM,qBAAqB,OAA+B,KAAK;AAE/D,KAAI,CAAC,YAAY,SAAS,MAAM,CAAC,WAAW,EAC1C,OAAM,IAAI,MACR,4DACD;CAGH,MAAM,UAAU,cAAc;AAC5B,MAAI;GACF,MAAM,aAAa,KAAK,UAAU;IAAE;IAAY;IAAQ,CAAC;AAEzD,OADoB,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,OACzB,kBAChB,OAAM,IAAI,MACR,sEACD;AAGH,UAAO;WACAA,SAAO;AACd,WAAQ,MAAM,qDAAqDA,QAAM;AACzE,UAAO;;IAER;EAAC;EAAY;EAAQ;EAAkB,CAAC;CAE3C,MAAM,QAAQ,kBAAkB;AAC9B,MAAI,YAAY,MAAM;AACpB,YAAS,uCAAuC;AAChD;;AAIF,MAAI,mBAAmB,QACrB,oBAAmB,QAAQ,OAAO;AAGpC,aAAW,KAAK;AAChB,WAAS,KAAK;AACd,UAAQ,KAAK;EAEb,MAAM,kBAAkB,IAAI,iBAAiB;AAC7C,qBAAmB,UAAU;AAE7B,aAAW;GACT,KAAK;GACI;GACT,QAAQ,gBAAgB;GACxB,WAAW,OAAO,YAAY;AAC5B,QAAI;KACF,MAAM,SAAS,KAAK,MAAM,QAAQ,KAAK;AAGvC,SAAI,OAAO,SAAS,UAAU;AAC5B,iBAAW,MAAM;AACjB,cAAQ,OAAO,KAAmB;AAClC;;AAIF,SAAI,OAAO,SAAS,QAClB,KAAI;MACF,MAAM,YAAY,MAAM,YAAY,WAClC,kBAAkB,OAAO,aAAa,CACvC;MACD,MAAM,QAAQ,MAAM,YAAY,mBAAmB,UAAU;AAC7D,iBAAW,MAAM;AAEjB,cAAQ,MAAoB;AAC5B;cACOA,SAAO;AACd,cAAQ,MACN,kDACAA,QACD;AACD,iBAAW,MAAM;AACjB,eAAS,wCAAwC;AACjD;;AAKJ,SAAI,OAAO,SAAS,WAAW,OAAO,SAAS,OAAO,MAAM;MAC1D,MAAM,WACJ,OAAO,SAAS,OAAO,WAAW;AAEpC,iBAAW,MAAM;AACjB,eAAS,SAAS;AAElB,UAAI,OAAO,KACT,SAAQ,MACN,6BAA6B,OAAO,KAAK,aAAa,WACvD;AAEH;;aAEKA,SAAO;AACd,aAAQ,KAAK,kDAAkDA,QAAM;;;GAGzE,UAAU,YAAU;AAClB,QAAI,gBAAgB,OAAO,QAAS;AACpC,eAAW,MAAM;IAEjB,IAAI,cAAc;AAElB,QAAIA,mBAAiB,OAAO;AAC1B,SAAIA,QAAM,SAAS,aACjB,eAAc;cACLA,QAAM,QAAQ,SAAS,kBAAkB,CAClD,eAAc;AAGhB,aAAQ,MAAM,6BAA6B;MACzC;MACA,OAAOA,QAAM;MACb,OAAOA,QAAM;MACd,CAAC;;AAEJ,aAAS,YAAY;;GAExB,CAAC;IACD;EAAC;EAAU;EAAS;EAAU,CAAC;AAElC,iBAAgB;AACd,MAAI,UACF,QAAO;AAGT,eAAa;AACX,sBAAmB,SAAS,OAAO;;IAEpC,CAAC,OAAO,UAAU,CAAC;AAGtB,aAAY,UAAU,MAAM;AAE5B,QAAO;EAAE;EAAM;EAAS;EAAO"}
|
|
@@ -16,8 +16,6 @@ interface UseChartDataOptions {
|
|
|
16
16
|
format?: DataFormat;
|
|
17
17
|
/** Transform data after fetching */
|
|
18
18
|
transformer?: <T>(data: T) => T;
|
|
19
|
-
/** Whether to execute the query as the current user. @default false */
|
|
20
|
-
asUser?: boolean;
|
|
21
19
|
}
|
|
22
20
|
interface UseChartDataResult {
|
|
23
21
|
/** The fetched data (Arrow Table or JSON array) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-chart-data.d.ts","names":[],"sources":["../../../src/react/hooks/use-chart-data.ts"],"sourcesContent":[],"mappings":";;;UAYiB,mBAAA;;EAAA,QAAA,EAAA,MAAA;EAAmB;YAIrB,CAAA,EAAA,MAAA,CAAA,MAAA,EAAA,OAAA,CAAA;;;;;
|
|
1
|
+
{"version":3,"file":"use-chart-data.d.ts","names":[],"sources":["../../../src/react/hooks/use-chart-data.ts"],"sourcesContent":[],"mappings":";;;UAYiB,mBAAA;;EAAA,QAAA,EAAA,MAAA;EAAmB;YAIrB,CAAA,EAAA,MAAA,CAAA,MAAA,EAAA,OAAA,CAAA;;;;;AAaf;AA0EA;;QAAsC,CAAA,EA/E3B,UA+E2B;;EAAwC,WAAA,CAAA,EAAA,CAAA,CAAA,CAAA,CAAA,IAAA,EA7EpD,CA6EoD,EAAA,GA7E9C,CA6E8C;;UA1E7D,kBAAA;;QAET;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwEQ,YAAA,UAAsB,sBAAsB"}
|
|
@@ -40,13 +40,12 @@ function resolveFormat(format, parameters) {
|
|
|
40
40
|
* ```
|
|
41
41
|
*/
|
|
42
42
|
function useChartData(options) {
|
|
43
|
-
const { queryKey, parameters, format = "auto", transformer
|
|
43
|
+
const { queryKey, parameters, format = "auto", transformer } = options;
|
|
44
44
|
const resolvedFormat = useMemo(() => resolveFormat(format, parameters), [format, parameters]);
|
|
45
45
|
const isArrowFormat = resolvedFormat === "ARROW";
|
|
46
46
|
const { data: rawData, loading, error } = useAnalyticsQuery(queryKey, parameters, {
|
|
47
47
|
autoStart: true,
|
|
48
|
-
format: resolvedFormat
|
|
49
|
-
asUser
|
|
48
|
+
format: resolvedFormat
|
|
50
49
|
});
|
|
51
50
|
const processedData = useMemo(() => {
|
|
52
51
|
if (!rawData) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-chart-data.js","names":[],"sources":["../../../src/react/hooks/use-chart-data.ts"],"sourcesContent":["import type { Table } from \"apache-arrow\";\nimport { useMemo } from \"react\";\nimport type { ChartData, DataFormat } from \"../charts/types\";\nimport { useAnalyticsQuery } from \"./use-analytics-query\";\n\n/** Threshold for auto-selecting Arrow format (row count hint) */\nconst ARROW_THRESHOLD = 500;\n\n// ============================================================================\n// Hook Options & Result Types\n// ============================================================================\n\nexport interface UseChartDataOptions {\n /** Analytics query key */\n queryKey: string;\n /** Query parameters */\n parameters?: Record<string, unknown>;\n /**\n * Data format preference\n * - \"json\": Force JSON format\n * - \"arrow\": Force Arrow format\n * - \"auto\": Auto-select based on heuristics\n * @default \"auto\"\n */\n format?: DataFormat;\n /** Transform data after fetching */\n transformer?: <T>(data: T) => T;\n
|
|
1
|
+
{"version":3,"file":"use-chart-data.js","names":[],"sources":["../../../src/react/hooks/use-chart-data.ts"],"sourcesContent":["import type { Table } from \"apache-arrow\";\nimport { useMemo } from \"react\";\nimport type { ChartData, DataFormat } from \"../charts/types\";\nimport { useAnalyticsQuery } from \"./use-analytics-query\";\n\n/** Threshold for auto-selecting Arrow format (row count hint) */\nconst ARROW_THRESHOLD = 500;\n\n// ============================================================================\n// Hook Options & Result Types\n// ============================================================================\n\nexport interface UseChartDataOptions {\n /** Analytics query key */\n queryKey: string;\n /** Query parameters */\n parameters?: Record<string, unknown>;\n /**\n * Data format preference\n * - \"json\": Force JSON format\n * - \"arrow\": Force Arrow format\n * - \"auto\": Auto-select based on heuristics\n * @default \"auto\"\n */\n format?: DataFormat;\n /** Transform data after fetching */\n transformer?: <T>(data: T) => T;\n}\n\nexport interface UseChartDataResult {\n /** The fetched data (Arrow Table or JSON array) */\n data: ChartData | null;\n /** Whether the data is in Arrow format */\n isArrow: boolean;\n /** Loading state */\n loading: boolean;\n /** Error message if any */\n error: string | null;\n /** Whether the data is empty */\n isEmpty: boolean;\n}\n\n// ============================================================================\n// Format Resolution\n// ============================================================================\n\n/**\n * Resolves the data format based on hints and preferences\n */\nfunction resolveFormat(\n format: DataFormat,\n parameters?: Record<string, unknown>,\n): \"JSON\" | \"ARROW\" {\n // Explicit format selection\n if (format === \"json\") return \"JSON\";\n if (format === \"arrow\") return \"ARROW\";\n\n // Auto-selection heuristics\n if (format === \"auto\") {\n // Check for explicit hint in parameters\n if (parameters?._preferArrow === true) return \"ARROW\";\n if (parameters?._preferJson === true) return \"JSON\";\n\n // Check limit parameter as data size hint\n const limit = parameters?.limit;\n if (typeof limit === \"number\" && limit > ARROW_THRESHOLD) {\n return \"ARROW\";\n }\n\n // Check for date range queries (often large)\n if (parameters?.startDate && parameters?.endDate) {\n return \"ARROW\";\n }\n\n return \"JSON\";\n }\n\n return \"JSON\";\n}\n\n// ============================================================================\n// Main Hook\n// ============================================================================\n\n/**\n * Hook for fetching chart data in either JSON or Arrow format.\n * Automatically selects the best format based on query hints.\n *\n * @example\n * ```tsx\n * // Auto-select format\n * const { data, isArrow, loading } = useChartData({\n * queryKey: \"spend_data\",\n * parameters: { limit: 1000 }\n * });\n *\n * // Force Arrow format\n * const { data } = useChartData({\n * queryKey: \"big_query\",\n * format: \"arrow\"\n * });\n * ```\n */\nexport function useChartData(options: UseChartDataOptions): UseChartDataResult {\n const { queryKey, parameters, format = \"auto\", transformer } = options;\n\n // Resolve the format to use\n const resolvedFormat = useMemo(\n () => resolveFormat(format, parameters),\n [format, parameters],\n );\n\n const isArrowFormat = resolvedFormat === \"ARROW\";\n\n // Fetch data using the analytics query hook\n const {\n data: rawData,\n loading,\n error,\n } = useAnalyticsQuery(queryKey, parameters, {\n autoStart: true,\n format: resolvedFormat,\n });\n\n // Process and transform data\n const processedData = useMemo(() => {\n if (!rawData) return null;\n\n // Apply transformer if provided\n if (transformer) {\n try {\n return transformer(rawData);\n } catch (err) {\n console.error(\"[useChartData] Transformer error:\", err);\n return rawData;\n }\n }\n\n return rawData;\n }, [rawData, transformer]);\n\n // Determine if data is empty\n const isEmpty = useMemo(() => {\n if (!processedData) return true;\n\n // Arrow Table - check using duck typing\n if (\n typeof processedData === \"object\" &&\n \"numRows\" in processedData &&\n typeof (processedData as Table).numRows === \"number\"\n ) {\n return (processedData as Table).numRows === 0;\n }\n\n // JSON Array\n if (Array.isArray(processedData)) {\n return processedData.length === 0;\n }\n\n return true;\n }, [processedData]);\n\n // Detect actual data type (may differ from requested if server doesn't support format)\n const isArrow = useMemo(() => {\n if (!processedData) return isArrowFormat;\n // Duck type check for Arrow Table\n return (\n typeof processedData === \"object\" &&\n processedData !== null &&\n \"schema\" in processedData &&\n \"numRows\" in processedData &&\n typeof (processedData as Table).getChild === \"function\"\n );\n }, [processedData, isArrowFormat]);\n\n return {\n data: processedData as ChartData | null,\n isArrow,\n loading,\n error,\n isEmpty,\n };\n}\n"],"mappings":";;;;;AAMA,MAAM,kBAAkB;;;;AA2CxB,SAAS,cACP,QACA,YACkB;AAElB,KAAI,WAAW,OAAQ,QAAO;AAC9B,KAAI,WAAW,QAAS,QAAO;AAG/B,KAAI,WAAW,QAAQ;AAErB,MAAI,YAAY,iBAAiB,KAAM,QAAO;AAC9C,MAAI,YAAY,gBAAgB,KAAM,QAAO;EAG7C,MAAM,QAAQ,YAAY;AAC1B,MAAI,OAAO,UAAU,YAAY,QAAQ,gBACvC,QAAO;AAIT,MAAI,YAAY,aAAa,YAAY,QACvC,QAAO;AAGT,SAAO;;AAGT,QAAO;;;;;;;;;;;;;;;;;;;;;AA0BT,SAAgB,aAAa,SAAkD;CAC7E,MAAM,EAAE,UAAU,YAAY,SAAS,QAAQ,gBAAgB;CAG/D,MAAM,iBAAiB,cACf,cAAc,QAAQ,WAAW,EACvC,CAAC,QAAQ,WAAW,CACrB;CAED,MAAM,gBAAgB,mBAAmB;CAGzC,MAAM,EACJ,MAAM,SACN,SACA,UACE,kBAAkB,UAAU,YAAY;EAC1C,WAAW;EACX,QAAQ;EACT,CAAC;CAGF,MAAM,gBAAgB,cAAc;AAClC,MAAI,CAAC,QAAS,QAAO;AAGrB,MAAI,YACF,KAAI;AACF,UAAO,YAAY,QAAQ;WACpB,KAAK;AACZ,WAAQ,MAAM,qCAAqC,IAAI;AACvD,UAAO;;AAIX,SAAO;IACN,CAAC,SAAS,YAAY,CAAC;CAG1B,MAAM,UAAU,cAAc;AAC5B,MAAI,CAAC,cAAe,QAAO;AAG3B,MACE,OAAO,kBAAkB,YACzB,aAAa,iBACb,OAAQ,cAAwB,YAAY,SAE5C,QAAQ,cAAwB,YAAY;AAI9C,MAAI,MAAM,QAAQ,cAAc,CAC9B,QAAO,cAAc,WAAW;AAGlC,SAAO;IACN,CAAC,cAAc,CAAC;AAenB,QAAO;EACL,MAAM;EACN,SAdc,cAAc;AAC5B,OAAI,CAAC,cAAe,QAAO;AAE3B,UACE,OAAO,kBAAkB,YACzB,kBAAkB,QAClB,YAAY,iBACZ,aAAa,iBACb,OAAQ,cAAwB,aAAa;KAE9C,CAAC,eAAe,cAAc,CAAC;EAKhC;EACA;EACA;EACD"}
|
|
@@ -29,7 +29,6 @@ const CHECKBOX_COLUMN_WIDTH = 40;
|
|
|
29
29
|
* @param props.queryKey - The query key to fetch the data
|
|
30
30
|
* @param props.parameters - The parameters to pass to the query
|
|
31
31
|
* @param props.transformer - Optional function to transform raw data before creating table
|
|
32
|
-
* @param props.asUser - Whether to execute the query as a user. Default is false.
|
|
33
32
|
* @param props.children - Render function that receives the TanStack Table instance
|
|
34
33
|
* @param props.className - Optional CSS class name for the wrapper
|
|
35
34
|
* @param props.ariaLabel - Optional accessibility label
|
|
@@ -38,12 +37,12 @@ const CHECKBOX_COLUMN_WIDTH = 40;
|
|
|
38
37
|
* @returns The rendered table with state management
|
|
39
38
|
*/
|
|
40
39
|
function TableWrapper(props) {
|
|
41
|
-
const { queryKey, parameters, transformer,
|
|
40
|
+
const { queryKey, parameters, transformer, children, className, ariaLabel, testId, enableRowSelection = false, onRowSelectionChange, pageSize = 10 } = props;
|
|
42
41
|
const [sorting, setSorting] = useState([]);
|
|
43
42
|
const [columnFilters, setColumnFilters] = useState([]);
|
|
44
43
|
const [columnVisibility, setColumnVisibility] = useState({});
|
|
45
44
|
const [rowSelection, setRowSelection] = useState({});
|
|
46
|
-
const { data, loading, error } = useAnalyticsQuery(queryKey, parameters
|
|
45
|
+
const { data, loading, error } = useAnalyticsQuery(queryKey, parameters);
|
|
47
46
|
useEffect(() => {
|
|
48
47
|
if (onRowSelectionChange && enableRowSelection) onRowSelectionChange(rowSelection);
|
|
49
48
|
}, [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"table-wrapper.js","names":["table"],"sources":["../../../src/react/table/table-wrapper.tsx"],"sourcesContent":["import {\n type Column,\n type ColumnFiltersState,\n getCoreRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type Row,\n type RowSelectionState,\n type SortingState,\n type Table,\n useReactTable,\n type VisibilityState,\n} from \"@tanstack/react-table\";\nimport { ArrowUpDown } from \"lucide-react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useAnalyticsQuery } from \"..\";\nimport {\n formatChartValue,\n formatFieldLabel,\n SAFE_KEY_REGEX,\n} from \"../lib/format\";\nimport { Button } from \"../ui/button\";\nimport { Checkbox } from \"../ui/checkbox\";\nimport { EmptyState } from \"./empty\";\nimport { ErrorState } from \"./error\";\nimport { LoadingSkeleton } from \"./loading\";\nimport type { TableWrapperProps } from \"./types\";\n\nconst CHECKBOX_COLUMN_WIDTH = 40;\n\n/**\n * Wrapper component for tables with automatic data fetching and state management\n * This component handles:\n * - Data fetching via useAnalyticsQuery\n * - Loading, error, and empty states with proper UI components\n * - Data transformation (optional)\n * - Dynamic column generation from data structure\n * - TanStack Table instance creation with all features (sorting, filtering, pagination, etc.)\n *\n * @template TRaw - The raw data type returned by the analytics query\n * @template TProcessed - The processed data type after transformation\n *\n * @param props - Props for the TableWrapper component\n * @param props.queryKey - The query key to fetch the data\n * @param props.parameters - The parameters to pass to the query\n * @param props.transformer - Optional function to transform raw data before creating table\n * @param props.
|
|
1
|
+
{"version":3,"file":"table-wrapper.js","names":["table"],"sources":["../../../src/react/table/table-wrapper.tsx"],"sourcesContent":["import {\n type Column,\n type ColumnFiltersState,\n getCoreRowModel,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type Row,\n type RowSelectionState,\n type SortingState,\n type Table,\n useReactTable,\n type VisibilityState,\n} from \"@tanstack/react-table\";\nimport { ArrowUpDown } from \"lucide-react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useAnalyticsQuery } from \"..\";\nimport {\n formatChartValue,\n formatFieldLabel,\n SAFE_KEY_REGEX,\n} from \"../lib/format\";\nimport { Button } from \"../ui/button\";\nimport { Checkbox } from \"../ui/checkbox\";\nimport { EmptyState } from \"./empty\";\nimport { ErrorState } from \"./error\";\nimport { LoadingSkeleton } from \"./loading\";\nimport type { TableWrapperProps } from \"./types\";\n\nconst CHECKBOX_COLUMN_WIDTH = 40;\n\n/**\n * Wrapper component for tables with automatic data fetching and state management\n * This component handles:\n * - Data fetching via useAnalyticsQuery\n * - Loading, error, and empty states with proper UI components\n * - Data transformation (optional)\n * - Dynamic column generation from data structure\n * - TanStack Table instance creation with all features (sorting, filtering, pagination, etc.)\n *\n * @template TRaw - The raw data type returned by the analytics query\n * @template TProcessed - The processed data type after transformation\n *\n * @param props - Props for the TableWrapper component\n * @param props.queryKey - The query key to fetch the data\n * @param props.parameters - The parameters to pass to the query\n * @param props.transformer - Optional function to transform raw data before creating table\n * @param props.children - Render function that receives the TanStack Table instance\n * @param props.className - Optional CSS class name for the wrapper\n * @param props.ariaLabel - Optional accessibility label\n * @param props.testId - Optional test ID for testing\n *\n * @returns The rendered table with state management\n */\nexport function TableWrapper<TRaw = any, TProcessed = any>(\n props: TableWrapperProps<TRaw, TProcessed>,\n) {\n const {\n queryKey,\n parameters,\n transformer,\n children,\n className,\n ariaLabel,\n testId,\n enableRowSelection = false,\n onRowSelectionChange,\n pageSize = 10,\n } = props;\n\n const [sorting, setSorting] = useState<SortingState>([]);\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);\n const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});\n const [rowSelection, setRowSelection] = useState<RowSelectionState>({});\n\n const { data, loading, error } = useAnalyticsQuery<TRaw[]>(\n queryKey,\n parameters,\n );\n\n useEffect(() => {\n if (onRowSelectionChange && enableRowSelection) {\n onRowSelectionChange(rowSelection);\n }\n }, [rowSelection, onRowSelectionChange, enableRowSelection]);\n\n const hasData = data && data.length > 0;\n\n const processedData = hasData\n ? transformer\n ? transformer(data)\n : (data as unknown as TProcessed[])\n : [];\n\n const tableColumns = useMemo(() => {\n if (!hasData) return [];\n\n if (!processedData[0] || typeof processedData[0] !== \"object\") {\n console.warn(\"Invalid data format for DataTable\");\n return [];\n }\n\n const dataColumns = Object.keys(processedData[0] as object)\n .filter((key) => SAFE_KEY_REGEX.test(key))\n .map((key) => {\n const formattedLabel = formatFieldLabel(key);\n return {\n accessorKey: key,\n header: ({ column }: { column: Column<TProcessed> }) => {\n return (\n <Button\n variant=\"ghost\"\n onClick={() =>\n column.toggleSorting(column.getIsSorted() === \"asc\")\n }\n className=\"h-8 px-2\"\n >\n {formattedLabel}\n <ArrowUpDown className=\"ml-2 h-4 w-4\" />\n </Button>\n );\n },\n cell: ({ row }: { row: Row<TProcessed> }) => {\n const value = row.getValue(key);\n if (typeof value === \"number\" || Number.isFinite(Number(value))) {\n return (\n <div className=\"text-right font-mono\">\n {formatChartValue(Number(value), key)}\n </div>\n );\n }\n return <div>{String(value)}</div>;\n },\n };\n });\n\n if (enableRowSelection) {\n return [\n {\n id: \"select\",\n maxSize: CHECKBOX_COLUMN_WIDTH,\n minSize: CHECKBOX_COLUMN_WIDTH,\n header: ({ table }: { table: Table<TProcessed> }) => (\n <div className=\"flex items-center justify-center\">\n <Checkbox\n checked={\n table.getIsAllPageRowsSelected() ||\n (table.getIsSomePageRowsSelected() && \"indeterminate\")\n }\n onCheckedChange={(value) =>\n table.toggleAllPageRowsSelected(!!value)\n }\n aria-label=\"Select all\"\n />\n </div>\n ),\n cell: ({ row }: { row: Row<TProcessed> }) => (\n <div className=\"flex items-center justify-center\">\n <Checkbox\n checked={row.getIsSelected()}\n onCheckedChange={(value) => row.toggleSelected(!!value)}\n aria-label=\"Select row\"\n />\n </div>\n ),\n enableSorting: false,\n enableHiding: false,\n },\n ...dataColumns,\n ];\n }\n\n return dataColumns;\n }, [hasData, processedData, enableRowSelection]);\n\n const table = useReactTable({\n data: processedData,\n columns: tableColumns,\n onSortingChange: setSorting,\n onColumnFiltersChange: setColumnFilters,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n onColumnVisibilityChange: setColumnVisibility,\n onRowSelectionChange: setRowSelection,\n state: {\n sorting,\n columnFilters,\n columnVisibility,\n rowSelection,\n },\n initialState: {\n pagination: {\n pageSize: pageSize,\n },\n },\n });\n\n if (loading) return <LoadingSkeleton />;\n if (error)\n return (\n <ErrorState error={typeof error === \"string\" ? error : \"Unknown error\"} />\n );\n\n if (!hasData) return <EmptyState />;\n\n return (\n <section className={className} aria-label={ariaLabel} data-testid={testId}>\n {children(table)}\n </section>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/react/table/types.ts"],"sourcesContent":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/react/table/types.ts"],"sourcesContent":[],"mappings":";;;;;UA+BiB,cAAA;;;;cAIH;;;;;;;;WAQH;;;;;;;;;;wCAU6B;;qBAEnB,eAAe,KAAA,CAAM;;;;;;;UAQzB,eAAA"}
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import * as React$1 from "react";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime5 from "react/jsx-runtime";
|
|
3
3
|
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
|
4
4
|
|
|
5
5
|
//#region src/react/ui/accordion.d.ts
|
|
6
6
|
declare function Accordion({
|
|
7
7
|
...props
|
|
8
|
-
}: React$1.ComponentProps<typeof AccordionPrimitive.Root>):
|
|
8
|
+
}: React$1.ComponentProps<typeof AccordionPrimitive.Root>): react_jsx_runtime5.JSX.Element;
|
|
9
9
|
declare function AccordionItem({
|
|
10
10
|
className,
|
|
11
11
|
...props
|
|
12
|
-
}: React$1.ComponentProps<typeof AccordionPrimitive.Item>):
|
|
12
|
+
}: React$1.ComponentProps<typeof AccordionPrimitive.Item>): react_jsx_runtime5.JSX.Element;
|
|
13
13
|
declare function AccordionTrigger({
|
|
14
14
|
className,
|
|
15
15
|
children,
|
|
16
16
|
...props
|
|
17
|
-
}: React$1.ComponentProps<typeof AccordionPrimitive.Trigger>):
|
|
17
|
+
}: React$1.ComponentProps<typeof AccordionPrimitive.Trigger>): react_jsx_runtime5.JSX.Element;
|
|
18
18
|
declare function AccordionContent({
|
|
19
19
|
className,
|
|
20
20
|
children,
|
|
21
21
|
...props
|
|
22
|
-
}: React$1.ComponentProps<typeof AccordionPrimitive.Content>):
|
|
22
|
+
}: React$1.ComponentProps<typeof AccordionPrimitive.Content>): react_jsx_runtime5.JSX.Element;
|
|
23
23
|
//#endregion
|
|
24
24
|
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
|
25
25
|
//# sourceMappingURL=accordion.d.ts.map
|
|
@@ -1,50 +1,50 @@
|
|
|
1
1
|
import * as React$1 from "react";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react_jsx_runtime12 from "react/jsx-runtime";
|
|
3
3
|
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
|
|
4
4
|
|
|
5
5
|
//#region src/react/ui/alert-dialog.d.ts
|
|
6
6
|
declare function AlertDialog({
|
|
7
7
|
...props
|
|
8
|
-
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Root>):
|
|
8
|
+
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Root>): react_jsx_runtime12.JSX.Element;
|
|
9
9
|
declare function AlertDialogTrigger({
|
|
10
10
|
...props
|
|
11
|
-
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Trigger>):
|
|
11
|
+
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Trigger>): react_jsx_runtime12.JSX.Element;
|
|
12
12
|
declare function AlertDialogPortal({
|
|
13
13
|
container,
|
|
14
14
|
...props
|
|
15
|
-
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Portal>):
|
|
15
|
+
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Portal>): react_jsx_runtime12.JSX.Element;
|
|
16
16
|
declare function AlertDialogOverlay({
|
|
17
17
|
className,
|
|
18
18
|
...props
|
|
19
|
-
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Overlay>):
|
|
19
|
+
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Overlay>): react_jsx_runtime12.JSX.Element;
|
|
20
20
|
declare function AlertDialogContent({
|
|
21
21
|
className,
|
|
22
22
|
...props
|
|
23
|
-
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Content>):
|
|
23
|
+
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Content>): react_jsx_runtime12.JSX.Element;
|
|
24
24
|
declare function AlertDialogHeader({
|
|
25
25
|
className,
|
|
26
26
|
...props
|
|
27
|
-
}: React$1.ComponentProps<"div">):
|
|
27
|
+
}: React$1.ComponentProps<"div">): react_jsx_runtime12.JSX.Element;
|
|
28
28
|
declare function AlertDialogFooter({
|
|
29
29
|
className,
|
|
30
30
|
...props
|
|
31
|
-
}: React$1.ComponentProps<"div">):
|
|
31
|
+
}: React$1.ComponentProps<"div">): react_jsx_runtime12.JSX.Element;
|
|
32
32
|
declare function AlertDialogTitle({
|
|
33
33
|
className,
|
|
34
34
|
...props
|
|
35
|
-
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Title>):
|
|
35
|
+
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Title>): react_jsx_runtime12.JSX.Element;
|
|
36
36
|
declare function AlertDialogDescription({
|
|
37
37
|
className,
|
|
38
38
|
...props
|
|
39
|
-
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Description>):
|
|
39
|
+
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Description>): react_jsx_runtime12.JSX.Element;
|
|
40
40
|
declare function AlertDialogAction({
|
|
41
41
|
className,
|
|
42
42
|
...props
|
|
43
|
-
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Action>):
|
|
43
|
+
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Action>): react_jsx_runtime12.JSX.Element;
|
|
44
44
|
declare function AlertDialogCancel({
|
|
45
45
|
className,
|
|
46
46
|
...props
|
|
47
|
-
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Cancel>):
|
|
47
|
+
}: React$1.ComponentProps<typeof AlertDialogPrimitive.Cancel>): react_jsx_runtime12.JSX.Element;
|
|
48
48
|
//#endregion
|
|
49
49
|
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger };
|
|
50
50
|
//# sourceMappingURL=alert-dialog.d.ts.map
|