@malloy-publisher/sdk 0.0.219 → 0.0.221

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 (60) hide show
  1. package/dist/{ServerProvider-DaYKdCxq.es.js → ServerProvider-XsVzz-OD.es.js} +1426 -926
  2. package/dist/ServerProvider-j5Jof3CU.cjs.js +1 -0
  3. package/dist/client/api.d.ts +409 -13
  4. package/dist/client/index.cjs.js +1 -1
  5. package/dist/client/index.es.js +56 -54
  6. package/dist/components/Materializations/ManifestView.d.ts +1 -1
  7. package/dist/components/ServerProvider.d.ts +12 -0
  8. package/dist/components/highlighter.d.ts +6 -1
  9. package/dist/{core-BiGj7BML.es.js → core-D9Hl0IDY.es.js} +1 -1
  10. package/dist/{core-CnTkTGYk.cjs.js → core-Df0c84B0.cjs.js} +1 -1
  11. package/dist/github-dark-BKL9xNgN.cjs.js +1 -0
  12. package/dist/github-dark-DenFmJkN.es.js +4 -0
  13. package/dist/{index-BTfp6uRs.es.js → index-Br50Niyz.es.js} +13617 -13497
  14. package/dist/index-DmzHCafz.cjs.js +307 -0
  15. package/dist/index.cjs.js +1 -1
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.es.js +47 -38
  18. package/dist/theme/ThemeContext.d.ts +45 -0
  19. package/dist/theme/buildMalloyExplicitTheme.d.ts +34 -0
  20. package/dist/theme/buildTableCssVars.d.ts +25 -0
  21. package/dist/theme/buildVegaThemeOverride.d.ts +16 -0
  22. package/dist/theme/defaults.d.ts +7 -0
  23. package/dist/theme/index.d.ts +8 -0
  24. package/dist/theme/keys.d.ts +20 -0
  25. package/dist/theme/readChartAnnotations.d.ts +23 -0
  26. package/dist/theme/resolveTheme.d.ts +22 -0
  27. package/dist/theme/types.d.ts +61 -0
  28. package/package.json +7 -5
  29. package/src/components/AnalyzePackageButton.tsx +6 -3
  30. package/src/components/Environment/Packages.tsx +6 -3
  31. package/src/components/Home/AddEnvironmentDialog.tsx +1 -1
  32. package/src/components/Home/Home.tsx +6 -3
  33. package/src/components/Materializations/ManifestView.tsx +4 -4
  34. package/src/components/Materializations/MaterializationDetailDialog.tsx +2 -2
  35. package/src/components/Model/ModelCell.tsx +4 -2
  36. package/src/components/Notebook/NotebookCell.tsx +36 -18
  37. package/src/components/Package/Package.tsx +8 -3
  38. package/src/components/RenderedResult/RenderedResult.tsx +253 -31
  39. package/src/components/ServerProvider.tsx +142 -46
  40. package/src/components/Workbook/MutableCell.tsx +7 -5
  41. package/src/components/Workbook/Workbook.tsx +1 -1
  42. package/src/components/highlighter.ts +19 -5
  43. package/src/components/styles.ts +19 -18
  44. package/src/index.ts +1 -0
  45. package/src/theme/ThemeContext.tsx +83 -0
  46. package/src/theme/buildMalloyExplicitTheme.ts +58 -0
  47. package/src/theme/buildTableCssVars.spec.ts +64 -0
  48. package/src/theme/buildTableCssVars.ts +60 -0
  49. package/src/theme/buildVegaThemeOverride.spec.ts +53 -0
  50. package/src/theme/buildVegaThemeOverride.ts +44 -0
  51. package/src/theme/defaults.ts +75 -0
  52. package/src/theme/index.ts +8 -0
  53. package/src/theme/keys.ts +29 -0
  54. package/src/theme/readChartAnnotations.spec.ts +55 -0
  55. package/src/theme/readChartAnnotations.ts +66 -0
  56. package/src/theme/resolveTheme.spec.ts +144 -0
  57. package/src/theme/resolveTheme.ts +115 -0
  58. package/src/theme/types.ts +67 -0
  59. package/dist/ServerProvider-RXwIqb5f.cjs.js +0 -1
  60. package/dist/index-CQMDeQ_C.cjs.js +0 -235
package/dist/index.cjs.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-CQMDeQ_C.cjs.js"),o=require("./ServerProvider-RXwIqb5f.cjs.js");exports.AnalyzePackageButton=e.AnalyzePackageButton;exports.BrowserWorkbookStorage=e.BrowserWorkbookStorage;exports.ConnectionExplorer=e.ConnectionExplorer;exports.DimensionFilter=e.DimensionFilter;exports.EmbeddedQueryResult=e.EmbeddedQueryResult;exports.Environment=e.Environment;exports.Home=e.Home;exports.Loading=e.Loading;exports.Materializations=e.Materializations;exports.Model=e.Model;exports.ModelExplorer=e.ModelExplorer;exports.ModelExplorerDialog=e.ModelExplorerDialog;exports.Models=e.Models;exports.Notebook=e.Notebook;exports.Package=e.Package;exports.Packages=e.Packages;exports.PageViewer=e.PageViewer;exports.QueryResult=e.QueryResult;exports.RenderedResult=e.RenderedResult;exports.ResultContainer=e.ResultContainer;exports.SourceExplorerComponent=e.SourceExplorerComponent;exports.SourcesExplorer=e.SourcesExplorer;exports.Workbook=e.Workbook;exports.WorkbookList=e.WorkbookList;exports.WorkbookManager=e.WorkbookManager;exports.WorkbookStorageProvider=e.WorkbookStorageProvider;exports.createEmbeddedQueryResult=e.createEmbeddedQueryResult;exports.encodeResourceUri=e.encodeResourceUri;exports.extractDimensionSpecs=e.extractDimensionSpecs;exports.extractSourceFromQuery=e.extractSourceFromQuery;exports.generateFilterClause=e.generateFilterClause;exports.getDimensionKey=e.getDimensionKey;exports.getJoinedSources=e.getJoinedSources;exports.injectWhereClause=e.injectWhereClause;exports.makeDimensionKey=e.makeDimensionKey;exports.parseAllSourceInfos=e.parseAllSourceInfos;exports.parseDimensionFilterAnnotation=e.parseDimensionFilterAnnotation;exports.parseNotebookFilterAnnotation=e.parseNotebookFilterAnnotation;exports.parseResourceUri=e.parseResourceUri;exports.useDimensionFilters=e.useDimensionFilters;exports.useDimensionFiltersFromSpec=e.useDimensionFiltersFromSpec;exports.useDimensionFiltersQuery=e.useDimensionFiltersQuery;exports.useDimensionalFilterRangeData=e.useDimensionalFilterRangeData;exports.useGivensForm=e.useGivensForm;exports.useModelData=e.useModelData;exports.useModelGivens=e.useModelGivens;exports.useRawQueryData=e.useRawQueryData;exports.useRouterClickHandler=e.useRouterClickHandler;exports.ServerProvider=o.ServerProvider;exports.useServer=o.useServer;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index-DmzHCafz.cjs.js"),r=require("./ServerProvider-j5Jof3CU.cjs.js");exports.AnalyzePackageButton=e.AnalyzePackageButton;exports.BrowserWorkbookStorage=e.BrowserWorkbookStorage;exports.ConnectionExplorer=e.ConnectionExplorer;exports.DimensionFilter=e.DimensionFilter;exports.EmbeddedQueryResult=e.EmbeddedQueryResult;exports.Environment=e.Environment;exports.Home=e.Home;exports.Loading=e.Loading;exports.Materializations=e.Materializations;exports.Model=e.Model;exports.ModelExplorer=e.ModelExplorer;exports.ModelExplorerDialog=e.ModelExplorerDialog;exports.Models=e.Models;exports.Notebook=e.Notebook;exports.Package=e.Package;exports.Packages=e.Packages;exports.PageViewer=e.PageViewer;exports.QueryResult=e.QueryResult;exports.RenderedResult=e.RenderedResult;exports.ResultContainer=e.ResultContainer;exports.SourceExplorerComponent=e.SourceExplorerComponent;exports.SourcesExplorer=e.SourcesExplorer;exports.Workbook=e.Workbook;exports.WorkbookList=e.WorkbookList;exports.WorkbookManager=e.WorkbookManager;exports.WorkbookStorageProvider=e.WorkbookStorageProvider;exports.buildMalloyExplicitTheme=e.buildMalloyExplicitTheme;exports.buildTableCssVars=e.buildTableCssVars;exports.buildVegaThemeOverride=e.buildVegaThemeOverride;exports.createEmbeddedQueryResult=e.createEmbeddedQueryResult;exports.encodeResourceUri=e.encodeResourceUri;exports.extractDimensionSpecs=e.extractDimensionSpecs;exports.extractSourceFromQuery=e.extractSourceFromQuery;exports.generateFilterClause=e.generateFilterClause;exports.getDimensionKey=e.getDimensionKey;exports.getJoinedSources=e.getJoinedSources;exports.injectWhereClause=e.injectWhereClause;exports.makeDimensionKey=e.makeDimensionKey;exports.parseAllSourceInfos=e.parseAllSourceInfos;exports.parseDimensionFilterAnnotation=e.parseDimensionFilterAnnotation;exports.parseNotebookFilterAnnotation=e.parseNotebookFilterAnnotation;exports.parseResourceUri=e.parseResourceUri;exports.readChartAnnotations=e.readChartAnnotations;exports.useDimensionFilters=e.useDimensionFilters;exports.useDimensionFiltersFromSpec=e.useDimensionFiltersFromSpec;exports.useDimensionFiltersQuery=e.useDimensionFiltersQuery;exports.useDimensionalFilterRangeData=e.useDimensionalFilterRangeData;exports.useGivensForm=e.useGivensForm;exports.useModelData=e.useModelData;exports.useModelGivens=e.useModelGivens;exports.useRawQueryData=e.useRawQueryData;exports.useRouterClickHandler=e.useRouterClickHandler;exports.DEFAULT_THEME=r.DEFAULT_THEME;exports.ServerProvider=r.ServerProvider;exports.ThemeProvider=r.ThemeProvider;exports.resolveMode=r.resolveMode;exports.resolveTheme=r.resolveTheme;exports.usePublisherTheme=r.usePublisherTheme;exports.useServer=r.useServer;
package/dist/index.d.ts CHANGED
@@ -3,4 +3,5 @@ export { default as ConnectionExplorer } from './components/Environment/Connecti
3
3
  export { useServer } from './components/ServerProvider';
4
4
  export * from './hooks';
5
5
  export { useRawQueryData } from './hooks/useRawQueryData';
6
+ export * from './theme';
6
7
  export * from './utils/formatting';
package/dist/index.es.js CHANGED
@@ -1,54 +1,63 @@
1
- import { A as a, O as o, C as r, D as n, F as i, E as t, H as l, L as u, M as m, o as d, q as c, r as k, y as p, N as g, x as D, P as S, B as F, Q as R, R as x, I as y, t as b, S as E, W as M, J as v, T as C, K as P, G as Q, a2 as W, g as A, i as f, j as w, Z as B, k as G, l as H, _ as K, p as L, m as N, n as U, a1 as j, U as z, V as I, X as J, Y as V, a0 as h, v as q, $ as O, u as T, e as X } from "./index-BTfp6uRs.es.js";
2
- import { S as Z, u as _ } from "./ServerProvider-DaYKdCxq.es.js";
1
+ import { A as s, O as o, C as r, D as i, F as n, E as t, H as l, L as u, M as d, o as m, q as c, r as k, y as p, N as g, x as D, P as b, B as E, Q as F, R as S, I as v, t as y, S as M, W as R, J as x, T as C, K as P, a1 as T, a2 as h, a3 as A, G as Q, a6 as W, g as B, i as H, j as L, Z as U, k as V, l as f, _ as w, p as z, m as G, n as K, a5 as N, a4 as j, U as I, V as J, X as O, Y as _, a0 as q, v as X, $ as Y, u as Z, e as $ } from "./index-Br50Niyz.es.js";
2
+ import { az as ae, S as se, aB as oe, aA as re, ay as ie, al as ne, u as te } from "./ServerProvider-XsVzz-OD.es.js";
3
3
  export {
4
- a as AnalyzePackageButton,
4
+ s as AnalyzePackageButton,
5
5
  o as BrowserWorkbookStorage,
6
6
  r as ConnectionExplorer,
7
- n as DimensionFilter,
8
- i as EmbeddedQueryResult,
7
+ ae as DEFAULT_THEME,
8
+ i as DimensionFilter,
9
+ n as EmbeddedQueryResult,
9
10
  t as Environment,
10
11
  l as Home,
11
12
  u as Loading,
12
- m as Materializations,
13
- d as Model,
13
+ d as Materializations,
14
+ m as Model,
14
15
  c as ModelExplorer,
15
16
  k as ModelExplorerDialog,
16
17
  p as Models,
17
18
  g as Notebook,
18
19
  D as Package,
19
- S as Packages,
20
- F as PageViewer,
21
- R as QueryResult,
22
- x as RenderedResult,
23
- y as ResultContainer,
24
- Z as ServerProvider,
25
- b as SourceExplorerComponent,
26
- E as SourcesExplorer,
27
- M as Workbook,
28
- v as WorkbookList,
20
+ b as Packages,
21
+ E as PageViewer,
22
+ F as QueryResult,
23
+ S as RenderedResult,
24
+ v as ResultContainer,
25
+ se as ServerProvider,
26
+ y as SourceExplorerComponent,
27
+ M as SourcesExplorer,
28
+ oe as ThemeProvider,
29
+ R as Workbook,
30
+ x as WorkbookList,
29
31
  C as WorkbookManager,
30
32
  P as WorkbookStorageProvider,
33
+ T as buildMalloyExplicitTheme,
34
+ h as buildTableCssVars,
35
+ A as buildVegaThemeOverride,
31
36
  Q as createEmbeddedQueryResult,
32
37
  W as encodeResourceUri,
33
- A as extractDimensionSpecs,
34
- f as extractSourceFromQuery,
35
- w as generateFilterClause,
36
- B as getDimensionKey,
37
- G as getJoinedSources,
38
- H as injectWhereClause,
39
- K as makeDimensionKey,
40
- L as parseAllSourceInfos,
41
- N as parseDimensionFilterAnnotation,
42
- U as parseNotebookFilterAnnotation,
43
- j as parseResourceUri,
44
- z as useDimensionFilters,
45
- I as useDimensionFiltersFromSpec,
46
- J as useDimensionFiltersQuery,
47
- V as useDimensionalFilterRangeData,
48
- h as useGivensForm,
49
- q as useModelData,
50
- O as useModelGivens,
51
- T as useRawQueryData,
52
- X as useRouterClickHandler,
53
- _ as useServer
38
+ B as extractDimensionSpecs,
39
+ H as extractSourceFromQuery,
40
+ L as generateFilterClause,
41
+ U as getDimensionKey,
42
+ V as getJoinedSources,
43
+ f as injectWhereClause,
44
+ w as makeDimensionKey,
45
+ z as parseAllSourceInfos,
46
+ G as parseDimensionFilterAnnotation,
47
+ K as parseNotebookFilterAnnotation,
48
+ N as parseResourceUri,
49
+ j as readChartAnnotations,
50
+ re as resolveMode,
51
+ ie as resolveTheme,
52
+ I as useDimensionFilters,
53
+ J as useDimensionFiltersFromSpec,
54
+ O as useDimensionFiltersQuery,
55
+ _ as useDimensionalFilterRangeData,
56
+ q as useGivensForm,
57
+ X as useModelData,
58
+ Y as useModelGivens,
59
+ ne as usePublisherTheme,
60
+ Z as useRawQueryData,
61
+ $ as useRouterClickHandler,
62
+ te as useServer
54
63
  };
@@ -0,0 +1,45 @@
1
+ import { ReactNode } from 'react';
2
+ import { ResolvedTheme, Theme, ThemeMode } from './types';
3
+ interface ThemeContextValue {
4
+ /** Theme resolved from {@link layers} + {@link mode}. Used by the app shell. */
5
+ theme: ResolvedTheme;
6
+ /**
7
+ * Raw base layers in cascade order. Today this holds only the
8
+ * instance-level theme from `/status`; the built-in defaults live inside
9
+ * {@link resolveTheme}, not in this array. Exposed so per-chart renderers
10
+ * can append a per-chart override and re-run {@link resolveTheme} without
11
+ * losing that instance baseline. The merge accepts any number of
12
+ * lower-precedence layers, so a per-environment layer can be fed in here
13
+ * later (once the server wires it through) without changing the merge.
14
+ */
15
+ layers: Array<Theme | undefined>;
16
+ /**
17
+ * The effective mode applied to charts and chrome (always "light" or "dark").
18
+ * "auto" is resolved before reaching here.
19
+ */
20
+ mode: ThemeMode;
21
+ /**
22
+ * The viewer's stored preference: "light" | "dark" | "auto", or undefined
23
+ * when no choice has been persisted. Use this (not {@link mode}) when
24
+ * rendering a multi-state toggle that needs to expose "auto" as a position.
25
+ */
26
+ userChoice: ThemeMode | "auto" | undefined;
27
+ setMode: (mode: ThemeMode | "auto") => void;
28
+ allowUserToggle: boolean;
29
+ }
30
+ interface ThemeProviderProps {
31
+ layers: Array<Theme | undefined>;
32
+ mode: ThemeMode;
33
+ userChoice: ThemeMode | "auto" | undefined;
34
+ setMode: (mode: ThemeMode | "auto") => void;
35
+ allowUserToggle?: boolean;
36
+ children: ReactNode;
37
+ }
38
+ export declare function ThemeProvider({ layers, mode, userChoice, setMode, allowUserToggle, children, }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
39
+ /**
40
+ * Resolved publisher theme. Returns a sensible default outside a provider
41
+ * so SDK consumers (third-party embedders, isolated stories) still get
42
+ * styled output without having to mount the provider.
43
+ */
44
+ export declare function usePublisherTheme(): ThemeContextValue;
45
+ export {};
@@ -0,0 +1,34 @@
1
+ import { MalloyExplicitTheme } from '@malloydata/render';
2
+ import { ResolvedTheme } from './types';
3
+ /**
4
+ * Map our {@link ResolvedTheme} onto the explicit `theme` option that
5
+ * `@malloydata/render` accepts. Values flow into the renderer's inline
6
+ * `--malloy-render--*` style ahead of any `# theme.*` annotations the
7
+ * Malloy result carries, so operator choices made in the Theme Editor
8
+ * reach table chrome and dashboard tiles directly instead of going
9
+ * through the outer-wrapper var cascade.
10
+ *
11
+ * Two non-operator-customizable fields:
12
+ *
13
+ * - `background` paints the renderer's HTML chrome (the area between
14
+ * dashboard tiles). Sourced from `theme.dashboardRoot` — mode-keyed,
15
+ * stays decoupled from `palette.background` so a bold accent on the
16
+ * chart canvas doesn't bleed across the panel.
17
+ * - `tableBackground` paints the table interior. Sourced from
18
+ * `theme.tableBackground` — currently tracks `palette.background`
19
+ * so charts and tables share a single viz surface colour.
20
+ *
21
+ * Operator-customizable mappings:
22
+ *
23
+ * - `tablePinnedBackground` = `theme.tableHeaderBackground` (a NEW
24
+ * schema field). Despite the renderer's name, this paints the
25
+ * table header row (`.malloy-table .pinned-header.th` in
26
+ * scroll-pinned tables; for non-pinned tables our CSS override
27
+ * forces the same value onto `.th.column-cell`). Distinct from
28
+ * `tile` (below).
29
+ * - `tile` does NOT flow to `tablePinnedBackground` anymore — the
30
+ * dashboard tile container picks it up via our outer-wrapper
31
+ * `--malloy-render--tile-background` var and the CSS override on
32
+ * `.dashboard-item`. See `buildTableCssVars`.
33
+ */
34
+ export declare function buildMalloyExplicitTheme(theme: ResolvedTheme): MalloyExplicitTheme;
@@ -0,0 +1,25 @@
1
+ import { ResolvedTheme } from './types';
2
+ /**
3
+ * Build the CSS variable map applied to the wrapper element around
4
+ * `<malloy-render>`. The values here power two things only:
5
+ *
6
+ * 1. The dashboard tile chrome rules in
7
+ * {@link PUBLISHER_RENDERER_OVERRIDES_CSS} (`.dashboard-item`,
8
+ * `.dashboard-item-title`, `.dashboard-item-value`, ...). The
9
+ * renderer doesn't expose those surfaces through its `theme` prop,
10
+ * so we paint them ourselves via the var cascade.
11
+ *
12
+ * 2. Renderer-internal rules that read the same `--malloy-render--*`
13
+ * names. The renderer's own `theme` prop write (see
14
+ * `buildMalloyExplicitTheme`) usually sets these inline on a deeper
15
+ * element first, but we set them on the outer wrapper so the var
16
+ * has a value even when the prop is partial.
17
+ *
18
+ * Single namespace by design: the `--malloy-theme--*` shadow set we
19
+ * used to emit was a workaround for the renderer's
20
+ * `var(--malloy-theme--<key>)` fallback lookup, which only fires when
21
+ * no explicit `theme` prop is given. With the prop wired we no longer
22
+ * compete with that lookup, so the shadow namespace just bloated
23
+ * every wrapper element's inline style.
24
+ */
25
+ export declare function buildTableCssVars(theme: ResolvedTheme): Record<string, string>;
@@ -0,0 +1,16 @@
1
+ import { ResolvedTheme } from './types';
2
+ /**
3
+ * Produce a `vegaConfigOverride` callback for `new MalloyRenderer({...})`.
4
+ * The renderer invokes the callback once per chart type and merges the
5
+ * returned object into the Vega spec's config. We set the category
6
+ * colour scale, the global font, the page background, and foreground /
7
+ * faint colours so chart text and axis chrome inherit the active mode.
8
+ *
9
+ * Foreground and axis-faint values come from {@link ResolvedTheme}
10
+ * (computed once in `resolveTheme`), so this builder no longer branches
11
+ * on mode itself.
12
+ *
13
+ * The same config is returned for every chart type today. The
14
+ * parameter is reserved for future per-chart-type tweaks.
15
+ */
16
+ export declare function buildVegaThemeOverride(theme: ResolvedTheme): (_chartType: string) => Record<string, unknown>;
@@ -0,0 +1,7 @@
1
+ import { Theme } from './types';
2
+ /**
3
+ * Built-in theme used when nothing has been configured. Series palette
4
+ * and font are shared across modes; only colours that should genuinely
5
+ * change in dark mode (backgrounds, foregrounds) are per-mode.
6
+ */
7
+ export declare const DEFAULT_THEME: Required<Theme>;
@@ -0,0 +1,8 @@
1
+ export { buildMalloyExplicitTheme } from './buildMalloyExplicitTheme';
2
+ export { buildTableCssVars } from './buildTableCssVars';
3
+ export { buildVegaThemeOverride } from './buildVegaThemeOverride';
4
+ export { DEFAULT_THEME } from './defaults';
5
+ export { readChartAnnotations } from './readChartAnnotations';
6
+ export { resolveMode, resolveTheme } from './resolveTheme';
7
+ export { ThemeProvider, usePublisherTheme } from './ThemeContext';
8
+ export type { ResolvedTheme, Theme, ThemeMode } from './types';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The set of palette colour keys that have separate light and dark
3
+ * variants. This is the SDK-side canonical list, consumed by the
4
+ * annotation reader (readChartAnnotations) and the theme resolver
5
+ * (resolveTheme). The server keeps its own copy in
6
+ * packages/server/src/config.ts: the two packages are intentionally
7
+ * decoupled (neither imports the other; their only shared contract is
8
+ * api-doc.yaml, from which the server generates its Theme type), so the
9
+ * list is hand-duplicated. A server-side parity test
10
+ * (theme_key_parity.spec.ts) fails if this list, the server copy, or the
11
+ * api-doc Theme.palette schema drift apart. Adding a new per-mode colour
12
+ * means updating all three.
13
+ *
14
+ * Non-per-mode fields (series palette, font.family, font.size,
15
+ * defaultMode, allowUserToggle) are intentionally absent. Operators
16
+ * picked colours that change between modes; brand identity (series,
17
+ * fonts) stays consistent across modes.
18
+ */
19
+ export declare const PER_MODE_COLOR_KEYS: readonly ["background", "tableHeader", "tableHeaderBackground", "tableBody", "tile", "tileTitle", "mapColor"];
20
+ export type PerModeColorKey = (typeof PER_MODE_COLOR_KEYS)[number];
@@ -0,0 +1,23 @@
1
+ import { Tag } from '@malloydata/malloy-tag';
2
+ import { Theme } from './types';
3
+ /**
4
+ * Read a `theme.*` annotation block out of a parsed Malloy {@link Tag}
5
+ * and turn it into a partial {@link Theme} suitable for the cascade.
6
+ * Returns `undefined` if the tag has no `theme` namespace.
7
+ *
8
+ * Recognised annotation forms (all optional, all sit under `theme`):
9
+ *
10
+ * # theme.palette.series = ["#ff0080", "#ff6b00"]
11
+ * # theme.palette.background.light = "#fff"
12
+ * # theme.palette.background.dark = "#000"
13
+ * # theme.palette.tableHeader.light = "#666"
14
+ * # theme.palette.tableHeader.dark = "#aaa"
15
+ * # theme.font.family = "Roboto, sans-serif"
16
+ * # theme.font.size = 13
17
+ *
18
+ * Series and font are shared across modes; only the seven
19
+ * {@link PER_MODE_COLOR_KEYS} accept light/dark variants. Annotations
20
+ * with the wrong type are silently ignored. The goal is "worst-case a
21
+ * typo means no styling", not "a typo crashes the renderer."
22
+ */
23
+ export declare function readChartAnnotations(tag: Tag | undefined): Theme | undefined;
@@ -0,0 +1,22 @@
1
+ import { ResolvedTheme, Theme, ThemeMode } from './types';
2
+ /**
3
+ * Collapse the layered theme cascade into a {@link ResolvedTheme} that
4
+ * downstream code can consume without null-checks or mode branches.
5
+ * Layer order is low → high precedence; later layers overwrite earlier
6
+ * ones for the keys they set. Per-mode colour objects merge per-mode
7
+ * (a layer that sets only `palette.tile.dark` doesn't clobber the
8
+ * instance-level `palette.tile.light`).
9
+ *
10
+ * The derived fields on ResolvedTheme (border, pinnedBorder,
11
+ * valueColor, foreground, axisFaint) are computed once here from the
12
+ * active mode so the three builders that consume the theme stop
13
+ * recomputing them with duplicated hex literals.
14
+ */
15
+ export declare function resolveTheme(layers: Array<Theme | undefined>, mode: ThemeMode): ResolvedTheme;
16
+ /**
17
+ * Pick the active mode for a viewer given the operator's `defaultMode`,
18
+ * any persisted viewer choice, and a snapshot of the OS dark-mode
19
+ * preference. "auto" is resolved here; callers see only "light" or
20
+ * "dark".
21
+ */
22
+ export declare function resolveMode(defaultMode: Theme["defaultMode"] | undefined, userChoice: ThemeMode | "auto" | undefined, prefersDark: boolean): ThemeMode;
@@ -0,0 +1,61 @@
1
+ import { Theme } from '../client';
2
+ export type { Theme };
3
+ export type ThemeMode = "light" | "dark";
4
+ /**
5
+ * A Theme with every field downstream consumers need actually filled in.
6
+ * Produced by `resolveTheme(layers, mode)`, which flattens the cascade
7
+ * and the per-mode colour split into a single mode-agnostic shape — so
8
+ * `buildTableCssVars`, `buildVegaThemeOverride`, and
9
+ * `buildMalloyExplicitTheme` never have to branch on mode themselves.
10
+ *
11
+ * The seven `palette.*` colour keys are stored per-mode on the raw Theme
12
+ * (one of light/dark per field) and collapse to the active mode here.
13
+ * The five "derived" fields (border, pinnedBorder, valueColor,
14
+ * foreground, axisFaint) are computed once from the resolved mode so
15
+ * the same hex literal isn't repeated across three builders.
16
+ */
17
+ export interface ResolvedTheme {
18
+ mode: ThemeMode;
19
+ series: string[];
20
+ font: {
21
+ family: string;
22
+ size: number;
23
+ };
24
+ background: string;
25
+ tableHeader: string;
26
+ tableHeaderBackground: string;
27
+ tableBody: string;
28
+ tile: string;
29
+ tileTitle: string;
30
+ /**
31
+ * Saturated end of the gradient used by sequential color scales
32
+ * (choropleth maps, heatmaps). The renderer pairs it with a
33
+ * near-neutral low-end so the operator only picks the brand end.
34
+ */
35
+ mapColor: string;
36
+ border: string;
37
+ pinnedBorder: string;
38
+ valueColor: string;
39
+ foreground: string;
40
+ axisFaint: string;
41
+ /**
42
+ * Background for the renderer's HTML chrome (the area between
43
+ * dashboard tiles). Mode-keyed and intentionally NOT
44
+ * operator-customizable — when an operator picks a bold accent
45
+ * for `palette.background` (the chart canvas), the surrounding
46
+ * panel should stay neutral so the accent reads cleanly. In dark
47
+ * mode it paints slate so the panel doesn't sit as a stark white
48
+ * box on the dark page chrome.
49
+ */
50
+ dashboardRoot: string;
51
+ /**
52
+ * Background for the renderer's table interior. Follows the
53
+ * operator's `palette.background` (the chart canvas colour) so
54
+ * tables and charts share a single "viz surface" colour. In dark
55
+ * mode this also keeps the (light-slate) header/body text from
56
+ * painting unreadable light-on-white against the renderer's
57
+ * hardcoded default. Distinct from `dashboardRoot`, which is the
58
+ * panel BETWEEN tiles and stays mode-keyed / neutral.
59
+ */
60
+ tableBackground: string;
61
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@malloy-publisher/sdk",
3
3
  "description": "Malloy Publisher SDK",
4
- "version": "0.0.219",
4
+ "version": "0.0.221",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs.js",
7
7
  "module": "dist/index.es.js",
@@ -71,9 +71,10 @@
71
71
  "react-router-dom": ">=7.6.2",
72
72
  "@tanstack/react-query": ">=5.59.16",
73
73
  "@malloydata/malloy-explorer": "0.0.338-dev260215172810",
74
- "@malloydata/malloy-interfaces": "^0.0.415",
75
- "@malloydata/malloy-query-builder": "^0.0.415",
76
- "@malloydata/render": "^0.0.415",
74
+ "@malloydata/malloy-interfaces": "^0.0.421",
75
+ "@malloydata/malloy-query-builder": "^0.0.421",
76
+ "@malloydata/malloy-tag": "^0.0.421",
77
+ "@malloydata/render": "^0.0.421",
77
78
  "@mui/icons-material": ">=7.1.1",
78
79
  "@mui/x-date-pickers": ">=7.1.1",
79
80
  "@mui/material": ">=7.1.1",
@@ -91,7 +92,8 @@
91
92
  },
92
93
  "devDependencies": {
93
94
  "@malloydata/malloy-explorer": "0.0.338-dev260215172810",
94
- "@malloydata/malloy-query-builder": "^0.0.415",
95
+ "@malloydata/malloy-query-builder": "^0.0.421",
96
+ "@malloydata/malloy-tag": "^0.0.421",
95
97
  "@openapitools/openapi-generator-cli": "^2.20.2",
96
98
  "@types/bun": "^1.2.21",
97
99
  "@types/k6": "^1.0.2",
@@ -230,13 +230,16 @@ export function AnalyzePackageButton({
230
230
  </FormControl>
231
231
  ) : availableWorkspaces.length === 1 ? (
232
232
  <Box
233
- sx={{
233
+ sx={(theme) => ({
234
234
  p: 2,
235
235
  border: 1,
236
236
  borderColor: "divider",
237
237
  borderRadius: 1,
238
- backgroundColor: "grey.50",
239
- }}
238
+ backgroundColor:
239
+ theme.palette.mode === "dark"
240
+ ? "rgba(255, 255, 255, 0.04)"
241
+ : "grey.50",
242
+ })}
240
243
  >
241
244
  <Typography
242
245
  variant="body2"
@@ -117,17 +117,20 @@ function PackageCard({
117
117
  <CardContent sx={{ p: 2.5, "&:last-child": { pb: 2.5 } }}>
118
118
  <Box sx={{ display: "flex", alignItems: "flex-start", gap: 1.5 }}>
119
119
  <Box
120
- sx={{
120
+ sx={(theme) => ({
121
121
  width: 36,
122
122
  height: 36,
123
123
  borderRadius: 1.5,
124
- bgcolor: "grey.100",
124
+ bgcolor:
125
+ theme.palette.mode === "dark"
126
+ ? "rgba(255, 255, 255, 0.08)"
127
+ : "grey.100",
125
128
  display: "flex",
126
129
  alignItems: "center",
127
130
  justifyContent: "center",
128
131
  flexShrink: 0,
129
132
  color: "text.primary",
130
- }}
133
+ })}
131
134
  >
132
135
  <Inventory2OutlinedIcon sx={{ fontSize: 20 }} />
133
136
  </Box>
@@ -70,7 +70,7 @@ export default function AddEnvironmentDialog() {
70
70
  variant="contained"
71
71
  onClick={handleClickOpen}
72
72
  startIcon={<AddCircleRounded />}
73
- sx={{ mt: 2, color: "white" }}
73
+ sx={{ mt: 2 }}
74
74
  >
75
75
  Create New Environment
76
76
  </Button>
@@ -269,17 +269,20 @@ function EnvironmentCard({
269
269
  }}
270
270
  >
271
271
  <Box
272
- sx={{
272
+ sx={(theme) => ({
273
273
  width: 36,
274
274
  height: 36,
275
275
  borderRadius: 1.5,
276
- bgcolor: "grey.100",
276
+ bgcolor:
277
+ theme.palette.mode === "dark"
278
+ ? "rgba(255, 255, 255, 0.08)"
279
+ : "grey.100",
277
280
  display: "flex",
278
281
  alignItems: "center",
279
282
  justifyContent: "center",
280
283
  flexShrink: 0,
281
284
  color: "text.primary",
282
- }}
285
+ })}
283
286
  >
284
287
  <FolderOutlinedIcon sx={{ fontSize: 20 }} />
285
288
  </Box>
@@ -13,7 +13,7 @@ import { MONO_FONT_FAMILY } from "../styles";
13
13
  import { formatTimestamp } from "./utils";
14
14
 
15
15
  type ManifestViewProps = {
16
- entries: { [buildId: string]: ManifestEntry } | undefined;
16
+ entries: { [sourceEntityId: string]: ManifestEntry } | undefined;
17
17
  builtAt?: string;
18
18
  };
19
19
 
@@ -60,10 +60,10 @@ export default function ManifestView({ entries, builtAt }: ManifestViewProps) {
60
60
  </TableRow>
61
61
  </TableHead>
62
62
  <TableBody>
63
- {rows.map(([buildId, entry]) => (
64
- <TableRow key={buildId}>
63
+ {rows.map(([sourceEntityId, entry]) => (
64
+ <TableRow key={sourceEntityId}>
65
65
  <TableCell sx={{ fontFamily: MONO_FONT_FAMILY }}>
66
- {entry.sourceName ?? buildId}
66
+ {entry.sourceName ?? sourceEntityId}
67
67
  </TableCell>
68
68
  <TableCell sx={{ fontFamily: MONO_FONT_FAMILY }}>
69
69
  {entry.physicalTableName ?? "-"}
@@ -168,7 +168,7 @@ export default function MaterializationDetailDialog({
168
168
  <TableCell>Connection</TableCell>
169
169
  <TableCell>Dialect</TableCell>
170
170
  <TableCell align="right">Columns</TableCell>
171
- <TableCell>Build ID</TableCell>
171
+ <TableCell>Source Entity ID</TableCell>
172
172
  </TableRow>
173
173
  </TableHead>
174
174
  <TableBody>
@@ -198,7 +198,7 @@ export default function MaterializationDetailDialog({
198
198
  maxWidth: 220,
199
199
  }}
200
200
  >
201
- {source.buildId}
201
+ {source.sourceEntityId}
202
202
  </TableCell>
203
203
  </TableRow>
204
204
  ))}
@@ -3,6 +3,7 @@ import SearchIcon from "@mui/icons-material/Search";
3
3
  import { Box, Button, IconButton, Typography } from "@mui/material";
4
4
  import React, { useEffect } from "react";
5
5
  import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
6
+ import { usePublisherTheme } from "../../theme/ThemeContext";
6
7
  import { parseResourceUri } from "../../utils/formatting";
7
8
  import { highlight } from "../highlighter";
8
9
  import ResultContainer from "../RenderedResult/ResultContainer";
@@ -57,16 +58,17 @@ export function ModelCell({
57
58
  enabled: runOnDemand ? hasRun : true, // Execute on demand or always
58
59
  });
59
60
 
61
+ const { mode } = usePublisherTheme();
60
62
  useEffect(() => {
61
63
  if (annotations && annotations.length > 0) {
62
64
  const code = annotations
63
65
  .map((annotation) => `// ${annotation}`)
64
66
  .join("\n");
65
- highlight(code, "typescript").then((highlightedCode) => {
67
+ highlight(code, "typescript", mode).then((highlightedCode) => {
66
68
  setHighlightedAnnotations(highlightedCode);
67
69
  });
68
70
  }
69
- }, [annotations]);
71
+ }, [annotations, mode]);
70
72
 
71
73
  return (
72
74
  <CleanNotebookCell>