@wisdomai/react 0.0.8

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.
Files changed (87) hide show
  1. package/AGENTS.md +111 -0
  2. package/LICENSE +21 -0
  3. package/README.md +225 -0
  4. package/dist/WisdomAuthContext.d.ts +12 -0
  5. package/dist/WisdomProvider.d.ts +13 -0
  6. package/dist/client.d.ts +10 -0
  7. package/dist/dashboard/Dashboard.d.ts +12 -0
  8. package/dist/dashboard/DashboardContext.d.ts +53 -0
  9. package/dist/dashboard/DashboardFilters.d.ts +6 -0
  10. package/dist/dashboard/DashboardHeader.d.ts +4 -0
  11. package/dist/dashboard/DashboardProvider.d.ts +15 -0
  12. package/dist/dashboard/DashboardWidget.d.ts +6 -0
  13. package/dist/dashboard/DashboardWidgets.d.ts +3 -0
  14. package/dist/dashboard/SdkMarkdown.d.ts +12 -0
  15. package/dist/dashboard/SdkSummaryWidget.d.ts +5 -0
  16. package/dist/dashboard/SummaryContent.d.ts +6 -0
  17. package/dist/dashboard/WidgetActionsMenu.d.ts +6 -0
  18. package/dist/dashboard/WidgetCard.d.ts +13 -0
  19. package/dist/dashboard/WisdomChart.d.ts +6 -0
  20. package/dist/dashboard/WisdomMetric.d.ts +5 -0
  21. package/dist/dashboard/WisdomTable.d.ts +10 -0
  22. package/dist/dashboard/WisdomText.d.ts +5 -0
  23. package/dist/dashboard/WisdomVisualization.d.ts +7 -0
  24. package/dist/dashboard/exportWidgetAsImage.d.ts +6 -0
  25. package/dist/dashboard/filterForms/BoolFilterForm.d.ts +8 -0
  26. package/dist/dashboard/filterForms/CurrentDateInput.d.ts +11 -0
  27. package/dist/dashboard/filterForms/DateFilterForm.d.ts +21 -0
  28. package/dist/dashboard/filterForms/EnumFilterForm.d.ts +13 -0
  29. package/dist/dashboard/filterForms/FilterPill.d.ts +12 -0
  30. package/dist/dashboard/filterForms/LeftIntervalSelect.d.ts +7 -0
  31. package/dist/dashboard/filterForms/NextDateInput.d.ts +13 -0
  32. package/dist/dashboard/filterForms/NumberFilterForm.d.ts +9 -0
  33. package/dist/dashboard/filterForms/PreviousDateInput.d.ts +15 -0
  34. package/dist/dashboard/filterForms/QuarterInputField.d.ts +6 -0
  35. package/dist/dashboard/filterForms/RangeDateInput.d.ts +25 -0
  36. package/dist/dashboard/filterForms/RelativeDateInput.d.ts +20 -0
  37. package/dist/dashboard/filterForms/RightIntervalSelect.d.ts +7 -0
  38. package/dist/dashboard/filterForms/SingleDateInput.d.ts +20 -0
  39. package/dist/dashboard/filterForms/StringFilterForm.d.ts +18 -0
  40. package/dist/dashboard/filterForms/WeekInputField.d.ts +6 -0
  41. package/dist/dashboard/filterForms/YearInputField.d.ts +6 -0
  42. package/dist/dashboard/filterForms/buildFilter.d.ts +56 -0
  43. package/dist/dashboard/filterForms/columnInput.d.ts +2 -0
  44. package/dist/dashboard/filterForms/dateLabels.d.ts +7 -0
  45. package/dist/dashboard/filterForms/getGranularityOptions.d.ts +5 -0
  46. package/dist/dashboard/filterForms/granularityLabels.d.ts +2 -0
  47. package/dist/dashboard/filterForms/useStringFilterSuggestions.d.ts +14 -0
  48. package/dist/dashboard/useDashboardFilters.d.ts +23 -0
  49. package/dist/dashboard/useDashboardWidget.d.ts +25 -0
  50. package/dist/dashboard/useDashboardsList.d.ts +21 -0
  51. package/dist/dashboard/useSummaryWidget.d.ts +25 -0
  52. package/dist/dashboard/widgetFilterStateAccessors.d.ts +15 -0
  53. package/dist/dashboard/widgetStore.d.ts +115 -0
  54. package/dist/errors.d.ts +16 -0
  55. package/dist/generated/graphql/gql.d.ts +146 -0
  56. package/dist/generated/graphql/graphql.d.ts +16533 -0
  57. package/dist/generated/graphql/index.d.ts +1 -0
  58. package/dist/graphql/fragments/column.fragment.d.ts +1 -0
  59. package/dist/graphql/fragments/dashboard-filter-definition.fragment.d.ts +1 -0
  60. package/dist/graphql/fragments/dashboard-filter-operation.fragment.d.ts +1 -0
  61. package/dist/graphql/fragments/dashboard-filter-spec.fragment.d.ts +1 -0
  62. package/dist/graphql/fragments/dashboard-filter-widget-state.fragment.d.ts +1 -0
  63. package/dist/graphql/fragments/dashboard-pinned-filter.fragment.d.ts +1 -0
  64. package/dist/graphql/fragments/dashboard-widget-with-data.fragment.d.ts +7 -0
  65. package/dist/graphql/fragments/dashboard-widget.fragment.d.ts +1 -0
  66. package/dist/graphql/fragments/dashboard.fragment.d.ts +1 -0
  67. package/dist/graphql/fragments/expression.fragment.d.ts +1 -0
  68. package/dist/graphql/fragments/parsed-filter.fragment.d.ts +2 -0
  69. package/dist/graphql/fragments/visualization.fragment.d.ts +1 -0
  70. package/dist/graphql/fragments/viz-chart-config.fragment.d.ts +1 -0
  71. package/dist/graphql/fragments/widget-data.fragment.d.ts +1 -0
  72. package/dist/graphql/mutations/update-cached-summary.mutation.d.ts +5 -0
  73. package/dist/graphql/queries/dashboard-list.query.d.ts +4 -0
  74. package/dist/graphql/queries/dashboard.query.d.ts +4 -0
  75. package/dist/graphql/queries/domain-filter-columns.query.d.ts +3 -0
  76. package/dist/graphql/queries/possible-column-literals.query.d.ts +4 -0
  77. package/dist/graphql/queries/widget-data.query.d.ts +6 -0
  78. package/dist/graphql/subscriptions/dashboard-summary.subscription.d.ts +9 -0
  79. package/dist/graphql/subscriptions/update-filter-value.subscription.d.ts +9 -0
  80. package/dist/index.d.ts +40 -0
  81. package/dist/index.js +20234 -0
  82. package/dist/internal/initHighcharts.d.ts +2 -0
  83. package/dist/resources/dashboards.d.ts +51 -0
  84. package/dist/subscriptionTransport.d.ts +42 -0
  85. package/dist/theme.d.ts +15 -0
  86. package/dist/transport.d.ts +27 -0
  87. package/package.json +58 -0
package/AGENTS.md ADDED
@@ -0,0 +1,111 @@
1
+ # @wisdomai/react — agent setup guide
2
+
3
+ Instructions for an AI coding agent integrating `@wisdomai/react` into a React
4
+ app. This SDK renders dashboards authored on the Wisdom platform, with live data
5
+ and interactive filtering. This file is a condensed, actionable companion to
6
+ `README.md` — consult the README for full detail.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @wisdomai/react
12
+ ```
13
+
14
+ The host app must provide these peer dependencies: `react` (>=18), `react-dom`
15
+ (>=18), `@mui/material` (^7), `@mui/x-date-pickers` (^7), `@emotion/react` (^11),
16
+ `@emotion/styled` (^11), `highcharts` (^12), `highcharts-react-official` (^3),
17
+ `graphql` (^16), `luxon` (^3).
18
+
19
+ `@wisdomai/react` is **ESM-only**. Pure-CommonJS callers must use dynamic
20
+ `import()`.
21
+
22
+ ## Setup
23
+
24
+ ### 1. Serve a token endpoint from the app's backend
25
+
26
+ Add `POST /auth-token` on the **same origin** as the app, returning
27
+ `{ jwt: string, baseUrl: string }`. The backend exchanges a long-lived,
28
+ server-side access token for a short-lived browser JWT.
29
+
30
+ Hard requirements — do not skip:
31
+
32
+ - **Protect the route with the app's own authentication.** Only signed-in users
33
+ may call it; an open `/auth-token` lets anyone mint a Wisdom JWT for the org.
34
+ - **`baseUrl` must include the scheme** (e.g. `https://<tenant>.wisdom.ai`). A
35
+ bare host throws `SubscriptionTransport: unrecognized baseUrl protocol`.
36
+ - Keep the access token (`WISDOM_ACCESS_TOKEN`) server-side only — never send it
37
+ to the browser.
38
+
39
+ Zero-dependency backend (any framework) via the GraphQL `exchangeAccessToken`
40
+ query:
41
+
42
+ ```ts
43
+ // Pseudocode — wrap in the app's existing auth/session check first.
44
+ app.post('/auth-token', requireAuth, async () => {
45
+ const res = await fetch(`${process.env.WISDOM_BASE_URL}/graphql`, {
46
+ method: 'POST',
47
+ headers: { 'Content-Type': 'application/json' },
48
+ body: JSON.stringify({
49
+ query: 'query Exchange($t: String!) { exchangeAccessToken(accessToken: $t) }',
50
+ variables: { t: process.env.WISDOM_ACCESS_TOKEN },
51
+ }),
52
+ });
53
+ const { data } = await res.json();
54
+ return { jwt: data.exchangeAccessToken, baseUrl: process.env.WISDOM_BASE_URL };
55
+ });
56
+ ```
57
+
58
+ `exchangeAccessToken` issues an **org-level** JWT. When each end user should see
59
+ only their own data, mint a **per-user** JWT with `impersonateUser` instead and
60
+ return it as `jwt`. The node SDK's `getAuthToken()` wraps `exchangeAccessToken`
61
+ if a Node helper is preferred.
62
+
63
+ ### 2. Wrap the app
64
+
65
+ ```tsx
66
+ import { WisdomProvider } from '@wisdomai/react';
67
+
68
+ function App() {
69
+ return (
70
+ <WisdomProvider>
71
+ <YourDashboards />
72
+ </WisdomProvider>
73
+ );
74
+ }
75
+ ```
76
+
77
+ `<WisdomProvider>` calls `POST /auth-token`, exposes the client via context, and
78
+ silently refreshes the JWT before it expires. Pass a `getAuthToken` callback to
79
+ bypass the endpoint when the app already holds a Wisdom JWT. Pass a `theme` prop
80
+ to style SDK-rendered components.
81
+
82
+ ### 3. Render dashboards
83
+
84
+ ```tsx
85
+ import { Dashboard, DashboardWidget, useWisdomClient } from '@wisdomai/react';
86
+
87
+ // A whole dashboard:
88
+ <Dashboard dashboardId="dashboard-id-123" />
89
+
90
+ // Or a single widget:
91
+ <DashboardWidget dashboardId="dashboard-id-123" widgetId="widget-id-456" />
92
+
93
+ // Or the typed client directly (null until auth succeeds):
94
+ const client = useWisdomClient();
95
+ const dashboard = await client?.dashboards.get('dashboard-id-123');
96
+ ```
97
+
98
+ ## What renders
99
+
100
+ - **Visualizations**: all chart types, data tables (server-side paging),
101
+ single- and multi-value metric cards, and text.
102
+ - **Filters**: interactive string, numeric (integer/float), enum, and date —
103
+ via row-click, the filter drawer, or programmatically with `setFilterValue`.
104
+
105
+ ## Common errors
106
+
107
+ - `SubscriptionTransport: unrecognized baseUrl protocol` → `baseUrl` is missing
108
+ the `https://` scheme.
109
+ - `WisdomAuthError` → JWT rejected/expired; the provider's `refresh()` re-fetches.
110
+ - `WisdomDashboardNotFoundError` → the dashboard id doesn't exist or the user
111
+ lacks access.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Wisdom AI, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # @wisdomai/react
2
+
3
+ React SDK for Wisdom AI. Ships a React context provider, auth hook, and a typed GraphQL client:
4
+
5
+ - `<WisdomProvider>` — fetches a short-lived JWT + the tenant `baseUrl` from your backend's `/auth-token` endpoint and exposes them via context. Accepts an optional `theme` prop (see [Theming](#theming)) and an optional `getAuthToken` callback to bypass the default endpoint (see [Custom auth token source](#custom-auth-token-source)).
6
+ - `useWisdomAuth()` — hook returning `{ jwt, baseUrl, client, isLoading, error, refresh }`.
7
+ - `useWisdomClient()` — hook returning a ready-to-use `WisdomClient` (null until auth succeeds).
8
+ - `useWisdomTheme()` — hook returning the active `WisdomTheme` (the prop passed to `<WisdomProvider>`, or the default).
9
+ - `WisdomClient` — typed GraphQL client. Currently exposes `client.dashboards.get(id)`.
10
+
11
+ ## Capabilities
12
+
13
+ The SDK renders dashboards authored on the Wisdom platform directly in your React app — live data, your theme, and interactive filtering. Render a full dashboard with `<Dashboard>`, or drop in individual widgets with `<DashboardWidget>`.
14
+
15
+ - **Visualizations** — all chart types, data tables (with server-side paging), single- and multi-value metric cards, and text.
16
+ - **Filters** — interactive string, numeric (integer and float), enum, and date filters, driven by row-click, the filter drawer, or programmatically via `setFilterValue` (see [Dashboard filters](#dashboard-filters)).
17
+
18
+ The layout, data, and filter specs come from the dashboard you built in Wisdom; the SDK renders them client-side and keeps them in sync with the platform.
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install @wisdomai/react
24
+ ```
25
+
26
+ Provide these peer dependencies from your app: `react` (>=18), `react-dom` (>=18), `@mui/material` (^7), `@mui/x-date-pickers` (^7), `@emotion/react` (^11), `@emotion/styled` (^11), `highcharts` (^12), `highcharts-react-official` (^3), `graphql` (^16), `luxon` (^3).
27
+
28
+ > Using an AI coding agent? The package ships an [`AGENTS.md`](./AGENTS.md) with condensed, copy-ready setup steps — point your agent at it to scaffold the integration.
29
+
30
+ ## Quick start: authentication
31
+
32
+ The SDK never sees your long-lived Wisdom access token. Your backend mints a short-lived JWT from that access token and serves it; `<WisdomProvider>` fetches the JWT in the browser and refreshes it before it expires.
33
+
34
+ ### 1. Serve a token endpoint from your backend
35
+
36
+ Expose `POST /auth-token` on the **same origin** as your app, returning `{ jwt, baseUrl }`. Keep `WISDOM_ACCESS_TOKEN` server-side only.
37
+
38
+ > **Protect this route with your app's own authentication.** It exchanges your server-side access token for browser credentials, so only signed-in users of your app should be able to call it — an open `/auth-token` lets anyone mint a Wisdom JWT for your org. The examples below omit that guard for brevity; add your existing session/authz check before the exchange (and mint a per-user token with [`impersonateUser`](https://docs.wisdom.ai/integrations/graphql-api/mutations/auth/impersonate-user) when each user should see only their own data).
39
+
40
+ ```ts
41
+ import { WisdomAI } from '@wisdomai/node';
42
+ import Fastify from 'fastify';
43
+
44
+ const wisdom = new WisdomAI({
45
+ accessToken: process.env.WISDOM_ACCESS_TOKEN!,
46
+ baseUrl: process.env.WISDOM_BASE_URL!,
47
+ });
48
+
49
+ const app = Fastify();
50
+
51
+ // Returns { jwt, baseUrl } — a short-lived token plus your tenant API URL.
52
+ app.post('/auth-token', () => wisdom.getAuthToken());
53
+
54
+ await app.listen({ port: 3000 });
55
+ ```
56
+
57
+ **Not on Node?** `getAuthToken()` is just a thin wrapper over the GraphQL [`exchangeAccessToken`](https://docs.wisdom.ai/integrations/graphql-api/queries/auth/exchange-access-token) query, so any backend can do the same exchange — `POST {baseUrl}/graphql` with your access key, then pair the returned JWT with your tenant `baseUrl`:
58
+
59
+ ```ts
60
+ // exchangeAccessToken(accessToken: String!): String! — returns a bare ~60-min JWT.
61
+ app.post('/auth-token', async () => {
62
+ const res = await fetch(`${process.env.WISDOM_BASE_URL}/graphql`, {
63
+ method: 'POST',
64
+ headers: { 'Content-Type': 'application/json' },
65
+ body: JSON.stringify({
66
+ query: 'query Exchange($t: String!) { exchangeAccessToken(accessToken: $t) }',
67
+ variables: { t: process.env.WISDOM_ACCESS_TOKEN },
68
+ }),
69
+ });
70
+ const { data } = await res.json();
71
+ return { jwt: data.exchangeAccessToken, baseUrl: process.env.WISDOM_BASE_URL };
72
+ });
73
+ ```
74
+
75
+ `exchangeAccessToken` issues an **org-level** JWT (the same identity for every caller). For multi-user production embeds where each end user should see only their own data, mint a **per-user** JWT with [`impersonateUser`](https://docs.wisdom.ai/integrations/graphql-api/mutations/auth/impersonate-user) instead and return that as `jwt` — the provider contract (`{ jwt, baseUrl }`) is the same.
76
+
77
+ ### 2. Wrap your app and read a dashboard
78
+
79
+ `<WisdomProvider>` calls `POST /auth-token`, exposes a ready-to-use client via `useWisdomClient()` (null until auth succeeds), and silently re-fetches the JWT shortly before it expires and when the tab regains focus.
80
+
81
+ ```tsx
82
+ import { WisdomProvider, useWisdomClient } from '@wisdomai/react';
83
+ import { useEffect, useState } from 'react';
84
+
85
+ function App() {
86
+ return (
87
+ <WisdomProvider>
88
+ <DashboardName id="dashboard-id-123" />
89
+ </WisdomProvider>
90
+ );
91
+ }
92
+
93
+ function DashboardName({ id }: { id: string }) {
94
+ const client = useWisdomClient();
95
+ const [name, setName] = useState<string | null>(null);
96
+
97
+ useEffect(() => {
98
+ if (!client) return;
99
+ client.dashboards.get(id).then((dashboard) => setName(dashboard.name));
100
+ }, [client, id]);
101
+
102
+ if (!client) return <p>Authenticating…</p>;
103
+ return <p>{name ?? 'Loading…'}</p>;
104
+ }
105
+ ```
106
+
107
+ If your app already holds a Wisdom JWT (e.g. the SDK is mounted inside an authenticated app), skip the endpoint entirely with the [`getAuthToken` callback](#custom-auth-token-source). For the exact endpoint contract and error handling, see [Requirements on the partner backend](#requirements-on-the-partner-backend).
108
+
109
+ ## Usage
110
+
111
+ ```tsx
112
+ import { WisdomProvider, useWisdomClient, WisdomDashboardNotFoundError } from '@wisdomai/react';
113
+ import { useEffect, useState } from 'react';
114
+
115
+ function App() {
116
+ return (
117
+ <WisdomProvider>
118
+ <DashboardView />
119
+ </WisdomProvider>
120
+ );
121
+ }
122
+
123
+ function DashboardView() {
124
+ const client = useWisdomClient();
125
+ const [name, setName] = useState<string | null>(null);
126
+ const [notFound, setNotFound] = useState(false);
127
+
128
+ useEffect(() => {
129
+ if (!client) return;
130
+ client.dashboards
131
+ .get('dashboard-id-123')
132
+ .then((dashboard) => setName(dashboard.name))
133
+ .catch((err) => {
134
+ if (err instanceof WisdomDashboardNotFoundError) setNotFound(true);
135
+ else throw err;
136
+ });
137
+ }, [client]);
138
+
139
+ if (!client) return <p>Authenticating…</p>;
140
+ if (notFound) return <p>Dashboard not found</p>;
141
+ return <p>{name ?? 'Loading…'}</p>;
142
+ }
143
+ ```
144
+
145
+ ### Requirements on the partner backend
146
+
147
+ `WisdomProvider` sends `POST /auth-token` to the same origin and expects a JSON response of shape `{ jwt: string, baseUrl: string }`. This matches the `sdk-playground` Fastify server exactly. If your backend hosts the token endpoint at a different path, you'll need a dev proxy or a reverse proxy in front of your app.
148
+
149
+ > **`baseUrl` must include the scheme.** Use the full origin, e.g. `https://canary.gowisdom.ai` — not a bare host (`canary.gowisdom.ai`). The SDK derives its WebSocket endpoint from `baseUrl`, and a value without an `http(s)://` prefix throws `SubscriptionTransport: unrecognized baseUrl protocol`.
150
+
151
+ ### Custom auth token source
152
+
153
+ If your app already has access to a JWT (e.g., the SDK is mounted inside an app that holds the user's session), pass a `getAuthToken` callback to bypass the default `POST /auth-token` fetch. The callback must resolve to `{ jwt, baseUrl }` (typed as `WisdomAuthTokenResult`), where `baseUrl` is the Wisdom tenant API URL (the same value the partner backend would otherwise return from `/auth-token`) — not the host app's origin, unless the host app reverse-proxies `/graphql` and the WS endpoints to Wisdom.
154
+
155
+ ```tsx
156
+ import { WisdomProvider, type WisdomAuthTokenResult } from '@wisdomai/react';
157
+ import { useCallback } from 'react';
158
+ import { getAuthToken } from '@/services/auth';
159
+
160
+ const WISDOM_BASE_URL = 'https://your-tenant.wisdom.ai';
161
+
162
+ function App() {
163
+ const resolveAuth = useCallback(async (): Promise<WisdomAuthTokenResult> => {
164
+ const jwt = await getAuthToken();
165
+ return { jwt, baseUrl: WISDOM_BASE_URL };
166
+ }, []);
167
+
168
+ return (
169
+ <WisdomProvider getAuthToken={resolveAuth}>
170
+ <DashboardView />
171
+ </WisdomProvider>
172
+ );
173
+ }
174
+ ```
175
+
176
+ When `getAuthToken` is set, the SDK does not call `POST /auth-token` — your callback is the sole token source. Throw from the callback to surface an auth error via `useWisdomAuth().error`. Wrap the callback in `useCallback` (or define it at module scope) so its identity is stable across renders; the provider re-fetches whenever the callback reference changes.
177
+
178
+ ## Theming
179
+
180
+ Pass a `theme` prop to `<WisdomProvider>` to control the colors, fonts, and chart palette used by SDK-rendered components (`Dashboard`, `DashboardWidgets`, `DashboardFilters`, `WisdomChart`). The theme is exposed to your own components via `useWisdomTheme()` so partner UI can stay visually consistent.
181
+
182
+ ```tsx
183
+ import { WisdomProvider, type WisdomTheme } from '@wisdomai/react';
184
+
185
+ const theme: WisdomTheme = {
186
+ primaryTextColor: '#ffffff',
187
+ secondaryTextColor: '#a0a0a0',
188
+ background: '#1a1a1a',
189
+ border: '#2a2a2a',
190
+ fontFamily: 'Inter, sans-serif',
191
+ chartColors: ['#4f46e5', '#10b981', '#f59e0b'],
192
+ };
193
+
194
+ <WisdomProvider theme={theme}>
195
+ <DashboardView />
196
+ </WisdomProvider>;
197
+ ```
198
+
199
+ `fontFamily` and `chartColors` are optional; everything else is required. If `theme` is omitted, a light default is used. The SDK does not ship light/dark presets — partner apps own their full color system.
200
+
201
+ You can pass `theme` as an inline object literal without causing chart re-renders on every parent render; the provider stabilizes its identity by content.
202
+
203
+ ## Dashboard filters
204
+
205
+ Interactive filtering (row-click, drawer, or programmatic) goes through `setFilterValue(filterId, filter)` from the dashboard context. Two parts of the contract are easy to get wrong:
206
+
207
+ ### `filterId` is the lookup key
208
+
209
+ `setFilterValue` matches the `filterId` against `dashboard.filterSpecs[*].filterId` exactly. A `filterId` that doesn't match any spec throws `Filter not found on dashboard: <filterId>`. The same `filterId` keys highlight/active-filter lookups, so it must be the spec's `filterId` verbatim — not the `parameterName`, `displayName`, or column name.
210
+
211
+ ### The `columnRef` vs `column` shape asymmetry
212
+
213
+ A `FilterSpec` exposes its column under **`spec.columnRefs[0]`** (a `ColumnRef`). But the serialized filter `lhs` reads the column from **`lhs.expression.flattened[0].column`** (a `DataframeColumn`) when building the GraphQL input. These are different shapes at different layers — the SDK maps between them in `buildLhsFromSpec`. If you hand-assemble an `lhs`, you must populate `expression.flattened[0].column`; leaving it empty throws a `malformed lhs` error naming the `filterId` (it does not silently render a blank chart).
214
+
215
+ ### Filtering a column the widgets don't query
216
+
217
+ A filter only changes a widget if that widget's underlying query references the filtered column (`WidgetFilterStatus.WIDGET_FILTER_STATUS_ADDED`). If you set a filter whose column no visible widget queries — common for chat-authored widgets whose SQL never selected the entity column — `setFilterValue` resolves successfully but nothing visibly changes. The SDK emits a `console.warn` in this case so the no-op is observable during development.
218
+
219
+ ## Errors
220
+
221
+ All errors thrown by the client extend `WisdomError`:
222
+
223
+ - `WisdomAuthError` — JWT rejected or expired (HTTP 401/403, or GraphQL `UNAUTHENTICATED` / `INVALID_TOKEN`). Consumers should call `refresh()` to re-fetch a token.
224
+ - `WisdomDashboardNotFoundError` — `dashboards.get(id)` could not return a dashboard because the ID does not exist or the caller lacks access (server emits `NOT_FOUND` or `FORBIDDEN`).
225
+ - `WisdomError` — everything else (network failure, 5xx, malformed response, uncategorized backend errors). Carries an optional `cause` and, for GraphQL-level failures, an `errors` array.
@@ -0,0 +1,12 @@
1
+ import type { WisdomClient } from './client';
2
+ export interface WisdomAuthContextValue {
3
+ jwt: string | null;
4
+ baseUrl: string | null;
5
+ client: WisdomClient | null;
6
+ isLoading: boolean;
7
+ error: Error | null;
8
+ refresh: () => Promise<void>;
9
+ }
10
+ export declare const WisdomAuthContext: import("react").Context<WisdomAuthContextValue | null>;
11
+ export declare function useWisdomAuth(): WisdomAuthContextValue;
12
+ export declare function useWisdomClient(): WisdomClient | null;
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ import { WisdomTheme } from './theme';
3
+ export interface WisdomAuthTokenResult {
4
+ jwt: string;
5
+ baseUrl: string;
6
+ }
7
+ interface WisdomProviderProps {
8
+ children: ReactNode;
9
+ theme?: Partial<WisdomTheme>;
10
+ getAuthToken?: () => Promise<WisdomAuthTokenResult>;
11
+ }
12
+ export declare function WisdomProvider({ children, theme, getAuthToken }: WisdomProviderProps): import("@emotion/react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,10 @@
1
+ import { DashboardsAPI } from './resources/dashboards';
2
+ import { SubscriptionTransport, type SubscriptionTransportOptions } from './subscriptionTransport';
3
+ import { type TransportOptions } from './transport';
4
+ export type WisdomClientOptions = TransportOptions & Partial<Pick<SubscriptionTransportOptions, 'webSocketImpl'>>;
5
+ export declare class WisdomClient {
6
+ readonly dashboards: DashboardsAPI;
7
+ readonly subscriptions: SubscriptionTransport;
8
+ constructor(options: WisdomClientOptions);
9
+ dispose(): void;
10
+ }
@@ -0,0 +1,12 @@
1
+ import { DashboardScope } from '../generated/graphql/graphql';
2
+ import type { Dashboard as DashboardData } from '../resources/dashboards';
3
+ type DashboardProps = {
4
+ dashboardId: string;
5
+ dashboard?: never;
6
+ scope?: DashboardScope;
7
+ } | {
8
+ dashboardId?: never;
9
+ dashboard: DashboardData;
10
+ };
11
+ export declare function Dashboard(props: DashboardProps): import("@emotion/react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,53 @@
1
+ import type { ParsedVisualizationFilter } from '@wisdomai/visualization/sdk-filters';
2
+ import type { Dashboard, DomainFilterColumn } from '../resources/dashboards';
3
+ import type { WidgetStore } from './widgetStore';
4
+ export interface DashboardActions {
5
+ refetch: () => Promise<void>;
6
+ /**
7
+ * Apply a filter value (or pass `null` to clear). Resolves when the
8
+ * server has finished re-executing all affected widgets.
9
+ *
10
+ * Throws if the dashboard has `useFiltersV2: false` (v1 is not supported
11
+ * by the SDK).
12
+ */
13
+ setFilterValue: (filterId: string, filter: ParsedVisualizationFilter | null) => Promise<void>;
14
+ }
15
+ export interface LastRefreshedFields {
16
+ /**
17
+ * Earliest `min(visualization.collectedAt ?? dataRefreshedAt)` across the
18
+ * dashboard's visualization widgets, or `null` while widgets are still
19
+ * loading or no visualization widget exposes a usable timestamp. Reflects
20
+ * data staleness, not the last refresh action.
21
+ */
22
+ lastRefreshedAt: Date | null;
23
+ /** True once every visualization widget has settled to `success` or `error`. */
24
+ allWidgetsReady: boolean;
25
+ }
26
+ export type DashboardContextValue = ({
27
+ status: 'loading';
28
+ dashboard: Dashboard | null;
29
+ error: null;
30
+ activeFilterId: null;
31
+ widgetStore: WidgetStore;
32
+ } & LastRefreshedFields & DashboardActions) | ({
33
+ status: 'error';
34
+ dashboard: null;
35
+ error: Error;
36
+ activeFilterId: null;
37
+ widgetStore: WidgetStore;
38
+ } & LastRefreshedFields & DashboardActions) | ({
39
+ status: 'success';
40
+ dashboard: Dashboard;
41
+ error: null;
42
+ /** Filter currently being mutated, or null when idle. */
43
+ activeFilterId: string | null;
44
+ widgetStore: WidgetStore;
45
+ /**
46
+ * Domain columns (with allowed-value metadata) for the dashboard's
47
+ * filter specs, fetched eagerly by domainId. Empty until that fetch
48
+ * resolves; used to classify fresh enum filters as closed vs. dynamic.
49
+ */
50
+ filterColumns: DomainFilterColumn[];
51
+ } & LastRefreshedFields & DashboardActions);
52
+ export declare const DashboardContext: import("react").Context<DashboardContextValue | null>;
53
+ export declare function useDashboard(): DashboardContextValue;
@@ -0,0 +1,6 @@
1
+ type FiltersDirection = 'row' | 'column';
2
+ interface DashboardFiltersProps {
3
+ direction?: FiltersDirection;
4
+ }
5
+ export declare function DashboardFilters({ direction }?: DashboardFiltersProps): import("@emotion/react/jsx-runtime").JSX.Element | null;
6
+ export {};
@@ -0,0 +1,4 @@
1
+ export interface DashboardHeaderProps {
2
+ className?: string;
3
+ }
4
+ export declare function DashboardHeader({ className }: DashboardHeaderProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { ReactNode } from 'react';
2
+ import { DashboardScope } from '../generated/graphql/graphql';
3
+ import type { Dashboard } from '../resources/dashboards';
4
+ type DashboardProviderProps = {
5
+ dashboardId: string;
6
+ dashboard?: never;
7
+ scope?: DashboardScope;
8
+ children: ReactNode;
9
+ } | {
10
+ dashboardId?: never;
11
+ dashboard: Dashboard;
12
+ children: ReactNode;
13
+ };
14
+ export declare function DashboardProvider(props: DashboardProviderProps): import("@emotion/react/jsx-runtime").JSX.Element;
15
+ export {};
@@ -0,0 +1,6 @@
1
+ export interface DashboardWidgetProps {
2
+ widgetId: string;
3
+ /** Optional — when omitted, reads the id from `<DashboardProvider>`. */
4
+ dashboardId?: string;
5
+ }
6
+ export declare function DashboardWidget({ widgetId, dashboardId: dashboardIdProp }: DashboardWidgetProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import 'react-grid-layout/css/styles.css';
2
+ import 'react-resizable/css/styles.css';
3
+ export declare function DashboardWidgets(): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { type Components } from 'react-markdown';
2
+ export interface SdkMarkdownProps {
3
+ text: string;
4
+ components?: Components;
5
+ }
6
+ /**
7
+ * Lean markdown renderer bundled into the SDK. Generic on purpose — no math,
8
+ * no app-internal link routing, no LLM-output preprocessing (those live in the
9
+ * frontend's LlmMarkdown). `remark-gfm` covers tables/strikethrough/autolinks,
10
+ * which dashboard summaries do use.
11
+ */
12
+ export declare function SdkMarkdown({ text, components }: SdkMarkdownProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ export interface SdkSummaryWidgetProps {
2
+ /** Stable root widget id — never a filter-versioned clone id. */
3
+ widgetId: string;
4
+ }
5
+ export declare function SdkSummaryWidget({ widgetId }: SdkSummaryWidgetProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ export interface SummaryContentProps {
2
+ summary: string;
3
+ /** True while a fresh summary is streaming — keeps the view pinned to the newest text. */
4
+ enableAutoScroll: boolean;
5
+ }
6
+ export declare function SummaryContent({ summary, enableAutoScroll }: SummaryContentProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { RefObject } from 'react';
2
+ export interface WidgetActionsMenuProps {
3
+ captureRef: RefObject<HTMLElement | null>;
4
+ title: string;
5
+ }
6
+ export declare function WidgetActionsMenu({ captureRef, title }: WidgetActionsMenuProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface WidgetCardProps {
3
+ title: string;
4
+ children: ReactNode;
5
+ headerActions?: ReactNode;
6
+ titleLoading?: boolean;
7
+ }
8
+ export declare function WidgetCard({ title, children, headerActions, titleLoading }: WidgetCardProps): import("@emotion/react/jsx-runtime").JSX.Element;
9
+ export declare function WidgetPlaceholderBody(): import("@emotion/react/jsx-runtime").JSX.Element;
10
+ export declare function WidgetErrorBody({ message }: {
11
+ message: string;
12
+ }): import("@emotion/react/jsx-runtime").JSX.Element;
13
+ export declare function WidgetLoadingBody(): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ import { type Visualization } from '@wisdomai/visualization';
2
+ export interface WisdomChartProps {
3
+ visualization: Visualization;
4
+ }
5
+ /** @deprecated Use `<WisdomVisualization>` — it routes to the right renderer based on `visualization.type`. */
6
+ export declare function WisdomChart({ visualization }: WisdomChartProps): import("@emotion/react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,5 @@
1
+ import { type Visualization } from '@wisdomai/visualization';
2
+ export interface WisdomMetricProps {
3
+ visualization: Visualization;
4
+ }
5
+ export declare function WisdomMetric({ visualization }: WisdomMetricProps): import("@emotion/react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,10 @@
1
+ import { type Visualization } from '@wisdomai/visualization';
2
+ export interface WisdomTableProps {
3
+ visualization: Visualization;
4
+ /**
5
+ * Server-side paging; omitted when the table isn't backed by a widget fetch.
6
+ * Resolves to the number of rows loaded after the fetch.
7
+ */
8
+ fetchMore?: (nextLimit: number) => Promise<number>;
9
+ }
10
+ export declare function WisdomTable({ visualization, fetchMore }: WisdomTableProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { type Visualization } from '@wisdomai/visualization';
2
+ export interface WisdomTextProps {
3
+ visualization: Visualization;
4
+ }
5
+ export declare function WisdomText({ visualization }: WisdomTextProps): import("@emotion/react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,7 @@
1
+ import { type Visualization } from '@wisdomai/visualization';
2
+ export interface WisdomVisualizationProps {
3
+ visualization: Visualization;
4
+ /** Server-side paging for table widgets; omitted for charts/metrics/text. */
5
+ fetchMore?: (nextLimit: number) => Promise<number>;
6
+ }
7
+ export declare function WisdomVisualization({ visualization, fetchMore }: WisdomVisualizationProps): import("@emotion/react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ export type ImageFormat = 'png' | 'jpg';
2
+ export interface ExportImageOptions {
3
+ backgroundColor?: string;
4
+ pixelRatio?: number;
5
+ }
6
+ export declare function exportWidgetAsImage(element: HTMLElement | null, baseName: string, format: ImageFormat, options?: ExportImageOptions): Promise<void>;
@@ -0,0 +1,8 @@
1
+ import { BoolFilter } from '@wisdomai/visualization/sdk-filters';
2
+ interface BoolFilterFormProps {
3
+ filter: BoolFilter;
4
+ close: () => void;
5
+ onSubmit: () => void;
6
+ }
7
+ export declare function BoolFilterForm({ filter, close, onSubmit }: BoolFilterFormProps): import("@emotion/react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,11 @@
1
+ import { DataframeFunctionType, DateFilter } from '@wisdomai/visualization/sdk-filters';
2
+ import { DateFilterType } from './DateFilterForm';
3
+ type Props = {
4
+ currentDateType: DataframeFunctionType;
5
+ filterType: DateFilterType | undefined;
6
+ setFilterType: (filterType: DateFilterType) => void;
7
+ setCurrentDateType: (currentDateType: DataframeFunctionType) => void;
8
+ };
9
+ export declare const getDefaultCurrentDateType: (filter: DateFilter) => DataframeFunctionType;
10
+ export declare const CurrentDateInput: ({ currentDateType, filterType, setFilterType, setCurrentDateType }: Props) => import("@emotion/react/jsx-runtime").JSX.Element;
11
+ export {};