@lightdash/cli 2.290.0 → 2.291.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/dist/.tsbuildinfo.build +1 -1
- package/dist/vendor/authoring/chart-type/lightdash-library-theme.md +7 -3
- package/dist/vendor/authoring/developing-chart-types-locally/SKILL.md +2 -0
- package/dist/vendor/template/.claude/skills/reusable-visualization/SKILL.md +68 -21
- package/dist/vendor/template/.claude/skills/sdk-features/SKILL.md +25 -9
- package/package.json +3 -3
|
@@ -96,9 +96,13 @@ turn missing values into zeros, or sample away facts without disclosure.
|
|
|
96
96
|
Honor saved options and pivoted results. Empty, invalid, and zero-only states
|
|
97
97
|
explain the relevant condition in `var(--ll-text-muted)`.
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
Never hand-build a data-point action menu when
|
|
100
|
+
`useVizContext().pointMenu.enabled` — call `pointMenu.open({ x, y, row, metric })`
|
|
101
|
+
and let Lightdash render it; an in-viz menu is only the fallback for hosts that
|
|
102
|
+
predate the capability. Preserve native **View underlying data** and **Drill
|
|
103
|
+
into** on eligible marks (via `pointMenu`, or the `underlyingData`/`drillDown`
|
|
104
|
+
fallback), retaining original result-row references through transforms. Marks
|
|
105
|
+
are inspectable by pointer and keyboard. Decorative overlays use
|
|
102
106
|
`pointer-events: none`. Scope SVG gradient/mask/pattern IDs uniquely.
|
|
103
107
|
Reduced motion disables reveal effects; animation is never the mechanism
|
|
104
108
|
that makes data visible.
|
|
@@ -11,6 +11,8 @@ You are editing a Lightdash **custom chart type** (a reusable visualization, the
|
|
|
11
11
|
|
|
12
12
|
Read `.claude/skills/reusable-visualization` before editing. It defines everything the component may do: `useVizContext()` is the only channel to the host (data, options, resolved colours), the component runs no query, owns no explore, and never fetches anything itself. App-level SDK APIs (query builder, `useLightdash`, filters, `externalFetch`) do not apply here and must not be introduced.
|
|
13
13
|
|
|
14
|
+
Never hand-build a data-point action menu when `useVizContext().pointMenu.enabled` — call `pointMenu.open({ x, y, row, metric })` and let Lightdash render it; an in-viz menu is only the fallback for hosts that predate the capability.
|
|
15
|
+
|
|
14
16
|
## The declaration lives in lightdash-app.yml — keep it in lockstep
|
|
15
17
|
|
|
16
18
|
In the in-product builder the declaration is emitted by the generation run; **locally it is the `vizSchema` block in this folder's `lightdash-app.yml`**, and upload round-trips it to the server (without it the chart type never appears in the explorer's chart type picker).
|
|
@@ -35,6 +35,7 @@ const {
|
|
|
35
35
|
colorPalette,
|
|
36
36
|
pivotDetails,
|
|
37
37
|
ready,
|
|
38
|
+
pointMenu,
|
|
38
39
|
underlyingData,
|
|
39
40
|
drillDown,
|
|
40
41
|
} = context;
|
|
@@ -57,9 +58,13 @@ const {
|
|
|
57
58
|
- `pivotDetails` — the complete backend-pivot layout, or `null` for ordinary rows. See
|
|
58
59
|
"Backend-pivoted results" below.
|
|
59
60
|
- `ready` — false until the first context arrives.
|
|
60
|
-
- `
|
|
61
|
-
See "Data-point actions" below.
|
|
62
|
-
- `
|
|
61
|
+
- `pointMenu` — host-rendered data-point action menu for a clicked mark; this is
|
|
62
|
+
the current data-point action contract. See "Data-point actions" below.
|
|
63
|
+
- `underlyingData` — host-mediated access to the raw rows behind a clicked data point;
|
|
64
|
+
the fallback per-action dialog for hosts that predate `pointMenu`. See
|
|
65
|
+
"Data-point actions" below.
|
|
66
|
+
- `drillDown` — host-mediated drill on a clicked data point; the fallback
|
|
67
|
+
per-action dialog for hosts that predate `pointMenu`. See "Data-point
|
|
63
68
|
actions" below.
|
|
64
69
|
|
|
65
70
|
Read all of them. Pass the complete `context` to the colour helpers; they preserve model
|
|
@@ -169,18 +174,46 @@ declared series fields builds its label from each matching `pivotValues` entry i
|
|
|
169
174
|
field order. Backend-pivoted rows do not have safe one-source-row provenance, so the host
|
|
170
175
|
sets `underlyingData.enabled` to false for them.
|
|
171
176
|
|
|
172
|
-
## Data-point actions: underlying data and drill-down
|
|
177
|
+
## Data-point actions: pointMenu, underlying data, and drill-down
|
|
173
178
|
|
|
174
|
-
Every chart whose marks satisfy the provenance rule below MUST wire the
|
|
175
|
-
action
|
|
176
|
-
"keep it minimal" prompt does not waive it.
|
|
177
|
-
|
|
179
|
+
Every chart whose marks satisfy the provenance rule below MUST wire the standard
|
|
180
|
+
data-point action. This is part of the component contract, not an optional nicety —
|
|
181
|
+
a "keep it minimal" prompt does not waive it. `pointMenu.enabled` (or, on the
|
|
182
|
+
fallback path, `underlyingData.enabled` and `drillDown.enabled`) decides at RUNTIME
|
|
183
|
+
whether anything shows; you always write the wiring, and it costs nothing visually
|
|
184
|
+
when disabled.
|
|
178
185
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
186
|
+
### `pointMenu`: the current contract
|
|
187
|
+
|
|
188
|
+
The current contract is a single call on click: `pointMenu.open({ x, y, row, metric,
|
|
189
|
+
fieldId? })`, with `x`/`y` taken from the click event's `clientX`/`clientY`. Lightdash
|
|
190
|
+
renders the entire menu — copy value, view underlying data, drill, dashboard
|
|
191
|
+
cross-filtering — over the viz and owns all subsequent UI; the component renders no
|
|
192
|
+
menu of its own. `pointMenu.open` resolves `{ shown: boolean }`; `shown: false` means
|
|
193
|
+
the host had no applicable action for that point, and the component still renders
|
|
194
|
+
nothing extra.
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
onClick={(event, datum) => {
|
|
198
|
+
if (pointMenu.enabled) {
|
|
199
|
+
pointMenu
|
|
200
|
+
.open({
|
|
201
|
+
x: event.clientX,
|
|
202
|
+
y: event.clientY,
|
|
203
|
+
row: datum.sourceRow,
|
|
204
|
+
metric: 'value',
|
|
205
|
+
})
|
|
206
|
+
.catch(() => {});
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
// Fallback for hosts that predate the point menu:
|
|
210
|
+
openLocalActionMenu(event, datum);
|
|
211
|
+
}}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Only when `pointMenu.enabled` is false (a host that predates the capability) does the
|
|
215
|
+
component fall back to building its own in-viz action menu from `underlyingData.open`
|
|
216
|
+
and `drillDown.open`, as described in the rest of this section.
|
|
184
217
|
|
|
185
218
|
Provenance is the contract: **every interactive datum keeps a reference to its
|
|
186
219
|
untransformed source row.** When mapping `rows` into chart data, carry the row:
|
|
@@ -189,13 +222,25 @@ untransformed source row.** When mapping `rows` into chart data, carry the row:
|
|
|
189
222
|
const data = rows.map((row) => ({
|
|
190
223
|
label: getFormatted(row, catField),
|
|
191
224
|
value: Number(getRaw(row, valField) ?? 0),
|
|
192
|
-
sourceRow: row, // ← required for
|
|
225
|
+
sourceRow: row, // ← required for the data-point action
|
|
193
226
|
}));
|
|
194
227
|
```
|
|
195
228
|
|
|
196
229
|
Only attach the action where one mark maps to exactly ONE source row and ONE metric-slot
|
|
197
230
|
field. A mark that aggregates several rows (a binned bucket, a "top N + other" slice)
|
|
198
|
-
gets no
|
|
231
|
+
gets no data-point action.
|
|
232
|
+
|
|
233
|
+
### Fallback: the in-viz action menu
|
|
234
|
+
|
|
235
|
+
Everything through "Open the menu at the data point" below applies only when
|
|
236
|
+
`pointMenu.enabled` is false. It calls the two per-action APIs directly and builds
|
|
237
|
+
its own accessible in-viz menu instead of delegating to a Lightdash-rendered one.
|
|
238
|
+
|
|
239
|
+
When `underlyingData.enabled` is true, viewers get the fallback action on chart
|
|
240
|
+
marks: click a data point → small action menu → "View underlying data" → the
|
|
241
|
+
standard Lightdash dialog listing the raw rows behind that point, with its Download
|
|
242
|
+
button. When it is false (host too old, viewer lacks permission, embed), render no menu
|
|
243
|
+
item — never a disabled one.
|
|
199
244
|
|
|
200
245
|
On click, send the intent and render nothing else. Lightdash opens the dialog outside
|
|
201
246
|
the viz and owns its table, loading, error, sorting, and download controls:
|
|
@@ -280,7 +325,7 @@ const registerMark = (key, node) => {
|
|
|
280
325
|
if (node) markElements.current.set(key, node);
|
|
281
326
|
else markElements.current.delete(key);
|
|
282
327
|
};
|
|
283
|
-
const
|
|
328
|
+
const openFallbackMenu = (datum, anchor) => {
|
|
284
329
|
if (!underlyingData.enabled && !drillDown.enabled) return;
|
|
285
330
|
const rect = anchor.activator.getBoundingClientRect();
|
|
286
331
|
setTooltipVisible(false);
|
|
@@ -318,8 +363,9 @@ const openPointMenu = (datum, anchor) => {
|
|
|
318
363
|
|
|
319
364
|
### Interaction hygiene
|
|
320
365
|
|
|
321
|
-
|
|
322
|
-
|
|
366
|
+
These rules apply on both paths — the host-rendered `pointMenu` and the fallback
|
|
367
|
+
in-viz menu. One floating surface at a time, and no leftover emphasis — native
|
|
368
|
+
Lightdash charts show a menu OR a tooltip, never both, and clicking leaves no mark
|
|
323
369
|
highlighted:
|
|
324
370
|
|
|
325
371
|
- **Opening the action menu closes the tooltip.** Drive tooltip visibility
|
|
@@ -545,9 +591,10 @@ matters. Keep that help reusable across queries: describe the chart contract rat
|
|
|
545
591
|
specific dataset.
|
|
546
592
|
|
|
547
593
|
Finally, if any mark maps to exactly one source row, the data-point action
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
594
|
+
is wired: each interactive datum carries `sourceRow`, and the click handler calls
|
|
595
|
+
`pointMenu.open({ x, y, row, metric })` when `pointMenu.enabled`, falling back to
|
|
596
|
+
an in-viz menu — gated on `underlyingData.enabled` and `drillDown.enabled` — only
|
|
597
|
+
when it is not. Omitting the action on a chart whose marks satisfy
|
|
551
598
|
provenance is a defect, not a simplification. Then click a mark mentally:
|
|
552
599
|
the tooltip closes, nothing stays highlighted, and only the menu remains —
|
|
553
600
|
one floating surface at a time.
|
|
@@ -28,6 +28,7 @@ Users describe features by what they see in the Lightdash editor. Translate:
|
|
|
28
28
|
| external API data | `external-fetch` | app code opt-in |
|
|
29
29
|
| runs inside a dashboard tile | `viz-context` | required — see below |
|
|
30
30
|
| reusable chart/table with pivoted results | `viz-pivoted-results` | required — see below |
|
|
31
|
+
| "Data point actions" — native context menu on a data-point click (copy, view underlying data, drill, cross-filter; viz only) | `point-action-menu` | app code opt-in |
|
|
31
32
|
| "view underlying data", raw rows behind a point (viz only) | `viz-underlying-data` | app code opt-in |
|
|
32
33
|
| Lightdash-owned "View underlying data" dialog (viz only) | `viz-host-underlying-data` | app code opt-in |
|
|
33
34
|
| light/dark mode, "matches my Lightdash theme" | `follow-host-theme` | CSS tokens — see below |
|
|
@@ -106,10 +107,23 @@ order, `sortBy` describes result ordering, `totalColumnCount` exposes truncation
|
|
|
106
107
|
|
|
107
108
|
- `drill-down`: `drillDown(...)` derives a more detailed query from a clicked
|
|
108
109
|
result row — wire it to click handlers on charts/rows.
|
|
109
|
-
- `
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
- `point-action-menu` (vizs only): the primary data-point-action contract. On a
|
|
111
|
+
data-point click, when `useVizContext().pointMenu.enabled`, call
|
|
112
|
+
`pointMenu.open({ x: event.clientX, y: event.clientY, row: datum.sourceRow, metric: '<field name>' })`
|
|
113
|
+
and render no menu of your own — Lightdash renders the entire native menu
|
|
114
|
+
(copy value, view underlying data, drill, dashboard cross-filtering) and
|
|
115
|
+
owns all subsequent UI. `viz-drill-down` and
|
|
116
|
+
`viz-underlying-data`/`viz-host-underlying-data` below are the
|
|
117
|
+
`pointMenu.enabled === false` fallback for older hosts, not a separate
|
|
118
|
+
feature to wire in addition.
|
|
119
|
+
- `viz-drill-down`: in a reusable visualization, when
|
|
120
|
+
`useVizContext().pointMenu.enabled`, call `pointMenu.open({ x, y, row, metric })`
|
|
121
|
+
and render no menu of your own — Lightdash's menu offers "Drill into …".
|
|
122
|
+
Only when `pointMenu.enabled` is false, fall back to a local data-point
|
|
123
|
+
action menu gated on `drillDown.enabled` and call
|
|
124
|
+
`drillDown.open({ row, metric })` on selection. Either way Lightdash opens
|
|
125
|
+
its drill dialog. Distinct from `drill-down`, which is the full-app query
|
|
126
|
+
helper.
|
|
113
127
|
- `url-state`: `useUrlState(...)` syncs a piece of app state into the page URL
|
|
114
128
|
so views can be shared and restored.
|
|
115
129
|
- `gsheet-export`: `exportToSheets(...)` sends tabular results to a new
|
|
@@ -137,11 +151,13 @@ order, `sortBy` describes result ordering, `totalColumnCount` exposes truncation
|
|
|
137
151
|
visible — never mount all tabs unconditionally (interactive loads must stay
|
|
138
152
|
lazy).
|
|
139
153
|
- `viz-underlying-data` and `viz-host-underlying-data` (vizs only): keep the
|
|
140
|
-
untransformed `sourceRow` on each interactive datum
|
|
141
|
-
`useVizContext().
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
`
|
|
154
|
+
untransformed `sourceRow` on each interactive datum. When
|
|
155
|
+
`useVizContext().pointMenu.enabled`, call `pointMenu.open({ x, y, row, metric })`
|
|
156
|
+
and render no menu of your own. Only when `pointMenu.enabled` is false, fall
|
|
157
|
+
back to a local data-point action menu gated on `underlyingData.enabled` and
|
|
158
|
+
call `underlyingData.open({ row, metric })` on selection. Either way,
|
|
159
|
+
Lightdash renders the dialog and owns its table, loading, error, and
|
|
160
|
+
download controls. Full contract in the `reusable-visualization` skill.
|
|
145
161
|
|
|
146
162
|
## After a template upgrade
|
|
147
163
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightdash/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.291.0",
|
|
4
4
|
"description": "Lightdash CLI tool",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"@actions/core": "1.11.1",
|
|
23
23
|
"@aws-sdk/credential-providers": "3.995.0",
|
|
24
24
|
"@casl/ability": "6.8.0",
|
|
25
|
-
"@lightdash/common": "2.
|
|
26
|
-
"@lightdash/warehouses": "2.
|
|
25
|
+
"@lightdash/common": "2.291.0",
|
|
26
|
+
"@lightdash/warehouses": "2.291.0",
|
|
27
27
|
"@sidvind/better-ajv-errors": "7.0.0",
|
|
28
28
|
"@types/columnify": "1.5.1",
|
|
29
29
|
"ajv": "8.18.0",
|