@lightdash/cli 1.95.1 → 1.97.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.
@@ -22,6 +22,7 @@ Users describe features by what they see in the Lightdash editor. Translate:
22
22
  | drill down, click into a chart | `drill-down` | app code opt-in |
23
23
  | "share this view", URL that restores state | `url-state` | app code opt-in |
24
24
  | Google Sheets export | `gsheet-export` | app code opt-in |
25
+ | "delivery has all tabs", full data in scheduled deliveries | `delivery-render` | app code opt-in |
25
26
  | external API data | `external-fetch` | app code opt-in |
26
27
  | runs inside a dashboard tile | `viz-context` | required — see below |
27
28
  | light/dark mode, "matches my Lightdash theme" | `follow-host-theme` | CSS tokens — see below |
@@ -92,6 +93,11 @@ re-rendering on every host toggle.
92
93
  - `external-fetch`: `client.externalFetch(alias, opts)` calls an external
93
94
  connection linked to this app. The connection must already be linked by the
94
95
  host; you cannot add one from app code.
96
+ - `delivery-render`: `useDeliveryRender()` is `true` during scheduled-delivery
97
+ and delivery-preview capture renders. Gate tab/slide DATA mounting on it so
98
+ every tab's queries execute during capture while only the active tab stays
99
+ visible — never mount all tabs unconditionally (interactive loads must stay
100
+ lazy).
95
101
 
96
102
  ## After a template upgrade
97
103
 
@@ -75,6 +75,10 @@ per tab, tiles assigned by `tabUuid`, ordered by `order`. Skip tabs with
75
75
  `hidden: true`. Single implicit tab (empty `tabs`) → a single page, no tab
76
76
  chrome.
77
77
 
78
+ Gate each tab's data hooks on `useDeliveryRender()` (see "Tabs and
79
+ scheduled-delivery capture" in `skill.md`) so a scheduled delivery or its
80
+ preview captures every tab's data, not just the one open at capture time.
81
+
78
82
  ### Dashboard filters
79
83
 
80
84
  Each rule in `filters.dimensions` is a `DashboardFilterRule`: `target`
@@ -1,8 +1,8 @@
1
1
  # Client-side PDF downloads (html-to-image + jspdf)
2
2
 
3
- > Read this for PDF Report templates or whenever the user asks for a PDF download.
3
+ > Read this for PDF Report templates, for any report/printable/document-shaped app, or whenever the user asks for a PDF download.
4
4
 
5
- For PDF Report templates, or whenever the user asks for a PDF download, use the pre-installed `html-to-image` and `jspdf` packages. Do not load PDF libraries from a CDN or ask to install packages.
5
+ Every PDF or printable report app includes a visible Download PDF button — the app is incomplete without one, on first generation and after every edit. Use the pre-installed `html-to-image` and `jspdf` packages. Do not load PDF libraries from a CDN or ask to install packages.
6
6
 
7
7
  PDF downloads are image-based: they preserve the visible report exactly, but the exported text is not selectable/searchable. Keep `window.print()` only as a secondary Print action if useful; the Download PDF button should save a file directly.
8
8
 
@@ -458,7 +458,9 @@ When the user asks for "Open in Google Sheets" (or any Sheets destination), read
458
458
 
459
459
  ### Client-side PDF downloads
460
460
 
461
- For PDF Report templates, or whenever the user asks for a PDF download, read `/app/references/pdf-downloads.md` — it has the required `html-to-image` + `jspdf` pattern and page-capture rules.
461
+ A PDF or printable report app always includes a visible **Download PDF** button — the export action is part of the report shape, not an optional extra, and `window.print()` is only ever a secondary Print action. This applies whenever the app is report-shaped, whatever the request's wording: the PDF Report starter template, a "printable" / "document" / "report to share" ask, or an app that already renders `.pdf-page` sections. On edit turns, keep the existing Download PDF button working — an edit that removes it is a regression.
462
+
463
+ Before wiring the button, read `/app/references/pdf-downloads.md` — it has the required `html-to-image` + `jspdf` pattern and page-capture rules.
462
464
 
463
465
  ### Underlying data
464
466
 
@@ -745,6 +747,42 @@ Avoid — each of these inflates the screenshot:
745
747
  </div>
746
748
  ```
747
749
 
750
+ ### Tabs and scheduled-delivery capture
751
+
752
+ A tabbed layout normally mounts each tab's data-fetching hooks lazily — only the active tab queries. Scheduled deliveries (and their preview) capture the whole app in one headless pass with no user to click through tabs first, so a lazily-mounted tab ships with no data in the delivered screenshot.
753
+
754
+ Use `useDeliveryRender()` from `@lightdash/query-sdk` to mount every tab's data hooks during a capture render, while still showing only the active tab's UI:
755
+
756
+ ```tsx
757
+ import { useDeliveryRender } from '@lightdash/query-sdk';
758
+
759
+ function AppTabs() {
760
+ const [activeTab, setActiveTab] = useUrlState('tab', 'overview');
761
+ const deliveryRender = useDeliveryRender();
762
+
763
+ return (
764
+ <Tabs value={activeTab} onValueChange={setActiveTab}>
765
+ <TabsList>
766
+ <TabsTrigger value="overview">Overview</TabsTrigger>
767
+ <TabsTrigger value="details">Details</TabsTrigger>
768
+ </TabsList>
769
+ {/* Each panel's useLightdash() calls run whenever it mounts — hidden
770
+ panels stay mounted in a capture render via forceMount. */}
771
+ <TabsContent value="overview" forceMount={deliveryRender || undefined}>
772
+ <OverviewPanel />
773
+ </TabsContent>
774
+ <TabsContent value="details" forceMount={deliveryRender || undefined}>
775
+ <DetailsPanel />
776
+ </TabsContent>
777
+ </Tabs>
778
+ );
779
+ }
780
+ ```
781
+
782
+ **Never mount every tab unconditionally** — that runs every tab's queries on every interactive load, wasting warehouse spend for users who only ever open one tab. Gate the extra mounting strictly on `useDeliveryRender()`.
783
+
784
+ The same rule applies one level up: if the app opens on a landing, intro, or "press start" screen that mounts no data (slideshows, wizards, empty states), a capture render of the default view captures zero queries and the delivery fails. In a delivery render, mount the data-bearing components from the app's entry state — `useDeliveryRender()` must bypass any screen that gates data behind user interaction.
785
+
748
786
  ### Organization themes
749
787
 
750
788
  If `/app/src/design/` exists, an organization theme is active: its assets and any appended theme instructions override parts of `frontend-design`'s direction. Read `/app/references/themes.md` before writing any UI code. If the directory doesn't exist, no theme is active and this doesn't apply.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "1.95.1",
3
+ "version": "1.97.0",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,8 +41,8 @@
41
41
  "unique-names-generator": "4.7.1",
42
42
  "uuid": "11.1.1",
43
43
  "yaml": "2.8.3",
44
- "@lightdash/common": "1.95.1",
45
- "@lightdash/warehouses": "1.95.1"
44
+ "@lightdash/common": "1.97.0",
45
+ "@lightdash/warehouses": "1.97.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/inquirer": "8.2.4",