@malloydata/render 0.0.351 → 0.0.353

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.
@@ -144,6 +144,9 @@ export function viteMalloyStoriesPlugin(): PluginOption {
144
144
  import {MalloyRenderer} from '../api/malloy-renderer';
145
145
  import {DummyPluginFactory} from '@/plugins/dummy-plugin';
146
146
  import {DummyDOMPluginFactory} from '@/plugins/dummy-dom-plugin';
147
+ import {addons} from '@storybook/preview-api';
148
+
149
+ const RENDERER_LOGS_EVENT = 'malloy/renderer-logs/logs';
147
150
 
148
151
  const meta = {
149
152
  title: "Malloy Next/${modelStoriesMeta.componentName}",
@@ -190,6 +193,12 @@ export function viteMalloyStoriesPlugin(): PluginOption {
190
193
  console.groupEnd();
191
194
  viz.render(targetElement);
192
195
 
196
+ viz.onReady(() => {
197
+ const logs = viz.getLogs();
198
+ const channel = addons.getChannel();
199
+ channel.emit(RENDERER_LOGS_EVENT, logs);
200
+ });
201
+
193
202
  return parent;
194
203
  },
195
204
  loaders: [createLoader(script)],
@@ -1,15 +1,25 @@
1
- import {addons} from '@storybook/manager-api';
1
+ import React from 'react';
2
+ import {addons, types} from '@storybook/manager-api';
2
3
  import theme from './theme';
4
+ import {RendererLogsPanel, ADDON_ID, PANEL_ID} from './renderer-logs-panel';
5
+
6
+ addons.register(ADDON_ID, () => {
7
+ addons.add(PANEL_ID, {
8
+ type: types.PANEL,
9
+ title: 'Renderer Logs',
10
+ render: ({active}) => React.createElement(RendererLogsPanel, {active}),
11
+ });
12
+ });
3
13
 
4
14
  addons.setConfig({
5
15
  theme,
6
16
  isFullscreen: false,
7
17
  showNav: true,
8
- showPanel: false,
18
+ showPanel: true,
9
19
  panelPosition: 'bottom',
10
20
  enableShortcuts: true,
11
21
  showToolbar: false,
12
- selectedPanel: undefined,
22
+ selectedPanel: PANEL_ID,
13
23
  initialActive: 'sidebar',
14
24
  sidebar: {},
15
25
  toolbar: {},
@@ -0,0 +1,67 @@
1
+ import React, {useState} from 'react';
2
+ import {useChannel} from '@storybook/manager-api';
3
+ import {AddonPanel} from '@storybook/components';
4
+
5
+ export const ADDON_ID = 'malloy/renderer-logs';
6
+ export const PANEL_ID = `${ADDON_ID}/panel`;
7
+ export const EVENT_ID = `${ADDON_ID}/logs`;
8
+
9
+ interface LogMessage {
10
+ severity: string;
11
+ message: string;
12
+ }
13
+
14
+ const h = React.createElement;
15
+
16
+ function LogsContent() {
17
+ const [logs, setLogs] = useState<LogMessage[]>([]);
18
+
19
+ useChannel({
20
+ [EVENT_ID]: (newLogs: LogMessage[]) => {
21
+ setLogs(newLogs);
22
+ },
23
+ });
24
+
25
+ if (logs.length === 0) {
26
+ return h(
27
+ 'div',
28
+ {
29
+ style: {
30
+ padding: '12px',
31
+ color: '#888',
32
+ fontFamily: 'monospace',
33
+ fontSize: '12px',
34
+ },
35
+ },
36
+ 'No renderer logs.'
37
+ );
38
+ }
39
+
40
+ return h(
41
+ 'div',
42
+ {style: {padding: '8px', fontFamily: 'monospace', fontSize: '12px'}},
43
+ logs.map((log, i) =>
44
+ h(
45
+ 'div',
46
+ {
47
+ key: i,
48
+ style: {
49
+ padding: '4px 8px',
50
+ color: log.severity === 'error' ? '#c62828' : '#f57f17',
51
+ borderBottom: '1px solid #eee',
52
+ },
53
+ },
54
+ h(
55
+ 'span',
56
+ {style: {marginRight: '6px'}},
57
+ log.severity === 'error' ? '\u274c' : '\u26a0\ufe0f'
58
+ ),
59
+ log.message
60
+ )
61
+ )
62
+ );
63
+ }
64
+
65
+ export function RendererLogsPanel(props: {active?: boolean}) {
66
+ return h(AddonPanel, {active: props.active ?? false}, h(LogsContent));
67
+ }
@@ -9,6 +9,9 @@ export declare class MalloyViz {
9
9
  private result;
10
10
  private metadata;
11
11
  private pluginRegistry;
12
+ private logCollector;
13
+ private readyCallbacks;
14
+ private isReady;
12
15
  constructor(options: MalloyRendererOptions, pluginRegistry?: RenderPluginFactory[]);
13
16
  static addStylesheet(styles: string): void;
14
17
  getHTML(): Promise<string>;
@@ -19,4 +22,24 @@ export declare class MalloyViz {
19
22
  updateOptions(newOptions: Partial<MalloyRendererOptions>): void;
20
23
  getMetadata(): RenderFieldMetadata | null;
21
24
  getActivePlugin(fieldKey: string): RenderPluginInstance | null;
25
+ /**
26
+ * Register a callback to be called when the render is complete.
27
+ * If the render is already complete, the callback is called immediately.
28
+ * Unread tag warnings are collected once the render is ready,
29
+ * so `getLogs()` should be called from the onReady callback
30
+ * to include unread tag warnings.
31
+ */
32
+ onReady(callback: () => void): void;
33
+ /**
34
+ * Get log messages from the most recent render pass.
35
+ * Includes warnings for unread (unknown) tags and semantic errors.
36
+ * For complete results including unread tag warnings,
37
+ * call this from an `onReady` callback.
38
+ */
39
+ getLogs(): Malloy.LogMessage[];
40
+ private handleReady;
41
+ /**
42
+ * Walk all field tags and collect warnings for unread properties.
43
+ */
44
+ private collectUnreadTagWarnings;
22
45
  }
@@ -16,6 +16,14 @@ interface BaseRenderPluginInstance<TMetadata = unknown> {
16
16
  processData?(field: NestField, cell: NestCell): void;
17
17
  beforeRender?(metadata: RenderMetadata, options: GetResultMetadataOptions): void;
18
18
  getStyleOverrides?(): Record<string, string>;
19
+ /**
20
+ * Declare tag paths this plugin reads during render or interaction.
21
+ * Each entry is a path of tag property names, e.g. ['viz', 'title'].
22
+ * The framework marks these as read at registration time so they
23
+ * don't produce false-positive "unknown tag" warnings when the
24
+ * component hasn't rendered yet (e.g. virtualized off-screen).
25
+ */
26
+ getDeclaredTagPaths?(): string[][];
19
27
  }
20
28
  export interface SolidJSRenderPluginInstance<TMetadata = unknown> extends BaseRenderPluginInstance<TMetadata> {
21
29
  readonly renderMode: 'solidjs';
@@ -0,0 +1,20 @@
1
+ import { Tag } from '@malloydata/malloy-tag';
2
+ import type * as Malloy from '@malloydata/malloy-interfaces';
3
+ /**
4
+ * Collects LogMessages during rendering.
5
+ * Semantic validation logs are added during setResult().
6
+ * Unread tag warnings are added when onReady fires after render completes.
7
+ */
8
+ export declare class RenderLogCollector {
9
+ private logs;
10
+ reset(): void;
11
+ warn(message: string, tag?: Tag): void;
12
+ error(message: string, tag?: Tag): void;
13
+ private add;
14
+ /**
15
+ * Walk a tag tree and generate warnings for any unread properties.
16
+ * Call this after rendering is complete.
17
+ */
18
+ collectUnreadTags(tag: Tag, fieldName: string): void;
19
+ getLogs(): Malloy.LogMessage[];
20
+ }
@@ -16,6 +16,7 @@ export type MalloyRenderProps = {
16
16
  dashboardConfig?: Partial<DashboardConfig>;
17
17
  renderFieldMetadata: RenderFieldMetadata;
18
18
  useVegaInterpreter?: boolean;
19
+ onReady?: () => void;
19
20
  };
20
21
  export declare const useConfig: () => {
21
22
  tableConfig: Accessor<TableConfig>;
@@ -30,6 +31,7 @@ export declare function MalloyRenderInner(props: {
30
31
  result: Malloy.Result;
31
32
  element: HTMLElement;
32
33
  scrollEl?: HTMLElement;
34
+ onReady?: () => void;
33
35
  vegaConfigOverride?: VegaConfigHandler;
34
36
  renderFieldMetadata: RenderFieldMetadata;
35
37
  useVegaInterpreter?: boolean;