@lightdash/query-sdk 1.248.1 → 1.249.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.
@@ -7,7 +7,7 @@
7
7
  * 2. Poll GET /api/v2/projects/{projectUuid}/query/{queryUuid}
8
8
  * → returns results when status is 'ready'
9
9
  */
10
- import { VIZ_UNDERLYING_DATA_PATH } from './types';
10
+ import { VIZ_DRILL_DOWN_PATH, VIZ_UNDERLYING_DATA_PATH } from './types';
11
11
  // Mirrors the explorer's `useInfiniteQueryResults` polling rhythm so the
12
12
  // SDK behaves like a normal Lightdash chart: 500-row pages, exponential
13
13
  // backoff starting at 250ms, capped at 1000ms.
@@ -685,5 +685,8 @@ export function createApiTransport(config, adapter) {
685
685
  options,
686
686
  });
687
687
  },
688
+ async openVizDrillDown(intent) {
689
+ await fetchFn('POST', VIZ_DRILL_DOWN_PATH, intent);
690
+ },
688
691
  };
689
692
  }
package/dist/features.js CHANGED
@@ -95,6 +95,12 @@ export const SDK_FEATURES = [
95
95
  description: 'Open the raw result rows behind a clicked data point in a reusable visualization, with CSV/XLSX download.',
96
96
  wiring: 'In the viz, keep the untransformed source row on each interactive datum, show a data-point action menu only when useVizContext().underlyingData.enabled and the mark maps to exactly one source row, render underlyingData.get({ row, metric }) in a themed dialog, and wire its Download button to underlyingData.download.',
97
97
  },
98
+ {
99
+ key: 'viz-drill-down',
100
+ label: 'Drill into data points',
101
+ description: 'Drill into a clicked data point in a reusable visualization — pick a dimension in Lightdash and open the drilled view in explore.',
102
+ wiring: 'Show a "Drill into …" item in the data-point action menu only when useVizContext().drillDown.enabled and the mark maps to exactly one source row, and call drillDown.open({ row: datum.sourceRow, metric: "<field name>" }) on selection. The host opens its drill dialog — render no dialog in the viz and never render a disabled item.',
103
+ },
98
104
  ];
99
105
  export const SDK_FEATURE_KEYS = SDK_FEATURES.map((f) => f.key);
100
106
  export const SDK_MANIFEST_MESSAGE_TYPE = 'lightdash:sdk:manifest';
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "1.248.1";
1
+ export declare const SDK_VERSION = "1.249.0";
@@ -1,2 +1,2 @@
1
1
  // Generated by scripts/generateSdkVersion.mjs (prebuild) — do not edit.
2
- export const SDK_VERSION = '1.248.1';
2
+ export const SDK_VERSION = '1.249.0';
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export type { DeliveryQuery } from './delivery';
15
15
  export { exportToSheets } from './exportToSheets';
16
16
  export type { ExportToSheetsOptions, ExportToSheetsResult, } from './exportToSheets';
17
17
  export { VizContextProvider, useVizContext, getFormatted, getRaw, } from './vizContext';
18
- export type { VizContext, VizContextCell, VizContextOptionValue, VizContextPivotDetails, VizContextRow, VizUnderlyingData, DataAppVizContextMessage, VizContextRequestMessage, } from './vizContext';
18
+ export type { VizContext, VizContextCell, VizContextOptionValue, VizContextPivotDetails, VizContextRow, VizUnderlyingData, VizDrillDown, DataAppVizContextMessage, VizContextRequestMessage, } from './vizContext';
19
19
  export { useColorScheme } from './colorScheme';
20
20
  export type { HostColorScheme, HostColorSchemeMessage, HostColorSchemeRequestMessage, } from './colorScheme';
21
21
  export { isDeliveryRender, useDeliveryRender } from './deliveryRender';
package/dist/types.d.ts CHANGED
@@ -185,6 +185,29 @@ export type VizUnderlyingDataIntent = {
185
185
  metric: string;
186
186
  limit?: number | null;
187
187
  };
188
+ /**
189
+ * Bridge-only virtual route for viz drill-down click intents. Duplicated from
190
+ * `@lightdash/common` (`APP_SDK_VIZ_DRILL_DOWN_PATH`) — this package must not
191
+ * depend on common. The host answers it directly (opens its drill dialog);
192
+ * nothing is forwarded to the API. On a direct-API transport it fails with a
193
+ * plain HTTP error.
194
+ */
195
+ export declare const VIZ_DRILL_DOWN_PATH = "/__sdk/viz/drill-down";
196
+ /**
197
+ * Drill click intent a viz sends to the host: the untransformed source row
198
+ * (as received from `useVizContext().rows`) and the declared field NAME bound
199
+ * to the clicked metric slot. The host resolves everything else and owns all
200
+ * subsequent UI.
201
+ */
202
+ export type VizDrillDownIntent = {
203
+ row: Record<string, {
204
+ value?: {
205
+ raw?: unknown;
206
+ formatted?: string;
207
+ };
208
+ } | undefined>;
209
+ metric: string;
210
+ };
188
211
  export type LightdashClientConfig = {
189
212
  /** Lightdash instance URL */
190
213
  baseUrl: string;
@@ -254,4 +277,11 @@ export type Transport = {
254
277
  getVizUnderlyingData?: (intent: VizUnderlyingDataIntent) => Promise<UnderlyingDataResult>;
255
278
  /** Schedule a CSV/XLSX export of the rows behind a viz data point. */
256
279
  downloadVizUnderlyingData?: (intent: Omit<VizUnderlyingDataIntent, 'limit'>, options?: DownloadResultsOptions) => Promise<DownloadResultsResult>;
280
+ /**
281
+ * Fire the drill-down intent for a viz data point via the host bridge.
282
+ * One-way: the host opens its drill dialog; the resolved promise is only
283
+ * an ack. Optional so custom transports predating the capability stay
284
+ * valid — `useVizContext().drillDown.enabled` is false when absent.
285
+ */
286
+ openVizDrillDown?: (intent: VizDrillDownIntent) => Promise<void>;
257
287
  };
package/dist/types.js CHANGED
@@ -10,3 +10,11 @@
10
10
  * on a direct-API transport it fails with a plain HTTP error.
11
11
  */
12
12
  export const VIZ_UNDERLYING_DATA_PATH = '/__sdk/viz/underlying-data';
13
+ /**
14
+ * Bridge-only virtual route for viz drill-down click intents. Duplicated from
15
+ * `@lightdash/common` (`APP_SDK_VIZ_DRILL_DOWN_PATH`) — this package must not
16
+ * depend on common. The host answers it directly (opens its drill dialog);
17
+ * nothing is forwarded to the API. On a direct-API transport it fails with a
18
+ * plain HTTP error.
19
+ */
20
+ export const VIZ_DRILL_DOWN_PATH = '/__sdk/viz/drill-down';
@@ -97,6 +97,10 @@ export type DataAppVizContextMessage = {
97
97
  underlyingData?: {
98
98
  enabled?: boolean;
99
99
  };
100
+ /** Absent when the installed host predates drill-down delivery. */
101
+ drillDown?: {
102
+ enabled?: boolean;
103
+ };
100
104
  };
101
105
  /** Posted by the iframe on mount so the host pushes the current context. */
102
106
  export type VizContextRequestMessage = {
@@ -145,6 +149,8 @@ export type VizContext = {
145
149
  ready: boolean;
146
150
  /** Fetch/export the raw rows behind a clicked data point via the host. */
147
151
  underlyingData: VizUnderlyingData;
152
+ /** Fire a drill-down on a clicked data point; the host opens its drill dialog. */
153
+ drillDown: VizDrillDown;
148
154
  };
149
155
  type VizContextValue = {
150
156
  fieldMapping: Record<string, string>;
@@ -153,6 +159,7 @@ type VizContextValue = {
153
159
  colorPalette: string[];
154
160
  pivotDetails: VizContextPivotDetails | null;
155
161
  underlyingDataEnabled: boolean;
162
+ drillDownEnabled: boolean;
156
163
  };
157
164
  type VizContextState = VizContextValue | null;
158
165
  /**
@@ -166,6 +173,22 @@ export declare function toVizContextState(message: DataAppVizContextMessage): Vi
166
173
  * standalone `useVizContext` usage). Exported for tests.
167
174
  */
168
175
  export declare function buildVizUnderlyingData(hostEnabled: boolean, transport: Transport | null): VizUnderlyingData;
176
+ /**
177
+ * Host-mediated drill-down for a clicked data point. `enabled` is false when
178
+ * the host predates the capability, the viewer lacks permission, results are
179
+ * pivoted, or no transport is mounted — render no menu item in that case
180
+ * (never a disabled one). `open` fires the intent; the HOST shows the drill
181
+ * dialog, nothing renders in the viz.
182
+ */
183
+ export type VizDrillDown = {
184
+ enabled: boolean;
185
+ open: (opts: {
186
+ row: VizContextRow;
187
+ metric: string;
188
+ }) => Promise<void>;
189
+ };
190
+ /** Builds the `drillDown` surface. Exported for tests. */
191
+ export declare function buildVizDrillDown(hostEnabled: boolean, transport: Transport | null): VizDrillDown;
169
192
  declare const NO_PROVIDER: unique symbol;
170
193
  /**
171
194
  * Owns the single listener + handshake for a data app viz. Mount it in the
@@ -55,6 +55,7 @@ export function toVizContextState(message) {
55
55
  pivotDetails: message.pivotDetails ?? null,
56
56
  // Strict boolean check — non-boolean payloads read as disabled.
57
57
  underlyingDataEnabled: message.underlyingData?.enabled === true,
58
+ drillDownEnabled: message.drillDown?.enabled === true,
58
59
  };
59
60
  }
60
61
  /**
@@ -89,6 +90,22 @@ export function buildVizUnderlyingData(hostEnabled, transport) {
89
90
  },
90
91
  };
91
92
  }
93
+ /** Builds the `drillDown` surface. Exported for tests. */
94
+ export function buildVizDrillDown(hostEnabled, transport) {
95
+ const supported = typeof transport?.openVizDrillDown === 'function';
96
+ return {
97
+ enabled: hostEnabled && supported,
98
+ open: async ({ row, metric }) => {
99
+ if (!hostEnabled) {
100
+ throw new Error('Drill-down is not enabled for this visualization.');
101
+ }
102
+ if (!transport?.openVizDrillDown) {
103
+ throw new Error('This SDK build predates drill-down. Rebuild the app on the current template.');
104
+ }
105
+ return transport.openVizDrillDown({ row, metric });
106
+ },
107
+ };
108
+ }
92
109
  // Distinguishes "no provider mounted" from "provider present, no context yet".
93
110
  const NO_PROVIDER = Symbol('viz-context/no-provider');
94
111
  const VizContextContext = createContext(NO_PROVIDER);
@@ -152,6 +169,8 @@ export function useVizContext() {
152
169
  const transport = useOptionalTransport();
153
170
  const hostEnabled = context?.underlyingDataEnabled === true;
154
171
  const underlyingData = useMemo(() => buildVizUnderlyingData(hostEnabled, transport), [hostEnabled, transport]);
172
+ const drillHostEnabled = context?.drillDownEnabled === true;
173
+ const drillDown = useMemo(() => buildVizDrillDown(drillHostEnabled, transport), [drillHostEnabled, transport]);
155
174
  return {
156
175
  fieldMapping: context?.fieldMapping ?? {},
157
176
  rows: context?.rows ?? [],
@@ -160,5 +179,6 @@ export function useVizContext() {
160
179
  pivotDetails: context?.pivotDetails ?? null,
161
180
  ready: context !== null,
162
181
  underlyingData,
182
+ drillDown,
163
183
  };
164
184
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/query-sdk",
3
- "version": "1.248.1",
3
+ "version": "1.249.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "SDK for building custom data apps against the Lightdash semantic layer",
@@ -34,7 +34,7 @@
34
34
  "jsdom": "26.1.0",
35
35
  "typescript": "7.0.2",
36
36
  "vitest": "4.1.6",
37
- "@lightdash/common": "1.248.1"
37
+ "@lightdash/common": "1.249.0"
38
38
  },
39
39
  "scripts": {
40
40
  "prebuild": "node ./scripts/generateSdkVersion.mjs",