pmx-canvas 0.1.26 → 0.1.27

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 (63) hide show
  1. package/.github/extensions/pmx-canvas/extension.mjs +191 -0
  2. package/CHANGELOG.md +74 -0
  3. package/Readme.md +74 -27
  4. package/dist/canvas/index.js +82 -82
  5. package/dist/json-render/index.css +1 -1
  6. package/dist/json-render/index.js +944 -164
  7. package/dist/types/json-render/catalog.d.ts +195 -20
  8. package/dist/types/json-render/charts/components.d.ts +7 -0
  9. package/dist/types/json-render/charts/definitions.d.ts +13 -1
  10. package/dist/types/json-render/charts/tufte-components.d.ts +65 -0
  11. package/dist/types/json-render/charts/tufte-definitions.d.ts +164 -0
  12. package/dist/types/json-render/directives.d.ts +23 -0
  13. package/dist/types/json-render/renderer/index.d.ts +1 -0
  14. package/dist/types/json-render/server.d.ts +32 -1
  15. package/dist/types/mcp/canvas-access.d.ts +62 -0
  16. package/dist/types/server/ax-state.d.ts +170 -0
  17. package/dist/types/server/canvas-db.d.ts +17 -1
  18. package/dist/types/server/canvas-operations.d.ts +45 -0
  19. package/dist/types/server/canvas-schema.d.ts +5 -1
  20. package/dist/types/server/canvas-state.d.ts +95 -4
  21. package/dist/types/server/index.d.ts +114 -2
  22. package/dist/types/server/mutation-history.d.ts +1 -1
  23. package/docs/cli.md +42 -0
  24. package/docs/http-api.md +64 -0
  25. package/docs/mcp.md +23 -5
  26. package/docs/node-types.md +1 -1
  27. package/docs/screenshots/codex-app.png +0 -0
  28. package/docs/screenshots/github-copilot-app.png +0 -0
  29. package/docs/sdk.md +19 -1
  30. package/package.json +10 -7
  31. package/skills/control-session-orchestrator/SKILL.md +359 -0
  32. package/skills/control-session-orchestrator/evals/evals.json +75 -0
  33. package/skills/data-analysis/SKILL.md +6 -0
  34. package/skills/pmx-canvas/SKILL.md +50 -4
  35. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +6 -0
  36. package/skills/tufte-viz/SKILL.md +157 -0
  37. package/skills/tufte-viz/references/analytical-design.md +217 -0
  38. package/skills/tufte-viz/references/tufte-principles.md +147 -0
  39. package/src/cli/agent.ts +280 -2
  40. package/src/cli/index.ts +2 -1
  41. package/src/client/nodes/ExtAppFrame.tsx +23 -1
  42. package/src/client/nodes/McpAppNode.tsx +6 -2
  43. package/src/json-render/catalog.ts +22 -1
  44. package/src/json-render/charts/components.tsx +97 -10
  45. package/src/json-render/charts/definitions.ts +19 -2
  46. package/src/json-render/charts/extra-components.tsx +5 -4
  47. package/src/json-render/charts/tufte-components.tsx +383 -0
  48. package/src/json-render/charts/tufte-definitions.ts +128 -0
  49. package/src/json-render/directives.ts +29 -0
  50. package/src/json-render/renderer/index.css +101 -0
  51. package/src/json-render/renderer/index.tsx +33 -0
  52. package/src/json-render/server.ts +257 -5
  53. package/src/mcp/canvas-access.ts +261 -0
  54. package/src/mcp/server.ts +496 -7
  55. package/src/server/ax-context.ts +8 -3
  56. package/src/server/ax-state.ts +447 -0
  57. package/src/server/canvas-db.ts +184 -1
  58. package/src/server/canvas-operations.ts +107 -0
  59. package/src/server/canvas-schema.ts +26 -3
  60. package/src/server/canvas-state.ts +349 -2
  61. package/src/server/index.ts +234 -2
  62. package/src/server/mutation-history.ts +6 -0
  63. package/src/server/server.ts +419 -2
@@ -7,6 +7,160 @@
7
7
  */
8
8
  import { z } from 'zod';
9
9
  export declare const allComponentDefinitions: {
10
+ Sparkline: {
11
+ readonly props: z.ZodObject<{
12
+ title: z.ZodNullable<z.ZodString>;
13
+ data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
14
+ valueKey: z.ZodString;
15
+ color: z.ZodNullable<z.ZodString>;
16
+ fill: z.ZodNullable<z.ZodBoolean>;
17
+ showEndDot: z.ZodNullable<z.ZodBoolean>;
18
+ showMinMax: z.ZodNullable<z.ZodBoolean>;
19
+ showValue: z.ZodNullable<z.ZodBoolean>;
20
+ height: z.ZodNullable<z.ZodNumber>;
21
+ }, z.core.$strip>;
22
+ readonly description: "Word-sized sparkline: a single trend line with no axes, grid, or labels. Optional end dot, min/max markers, light area fill, and an inline last value. The canonical Tufte primitive for showing a trajectory in minimal space.";
23
+ readonly example: {
24
+ readonly title: "Latency p95";
25
+ readonly data: readonly [{
26
+ readonly t: 0;
27
+ readonly ms: 120;
28
+ }, {
29
+ readonly t: 1;
30
+ readonly ms: 138;
31
+ }, {
32
+ readonly t: 2;
33
+ readonly ms: 117;
34
+ }, {
35
+ readonly t: 3;
36
+ readonly ms: 152;
37
+ }, {
38
+ readonly t: 4;
39
+ readonly ms: 109;
40
+ }];
41
+ readonly valueKey: "ms";
42
+ readonly color: null;
43
+ readonly fill: true;
44
+ readonly showEndDot: true;
45
+ readonly showMinMax: false;
46
+ readonly showValue: true;
47
+ readonly height: null;
48
+ };
49
+ };
50
+ DotPlot: {
51
+ readonly props: z.ZodObject<{
52
+ title: z.ZodNullable<z.ZodString>;
53
+ data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
54
+ labelKey: z.ZodString;
55
+ valueKey: z.ZodString;
56
+ color: z.ZodNullable<z.ZodString>;
57
+ sort: z.ZodNullable<z.ZodEnum<{
58
+ none: "none";
59
+ asc: "asc";
60
+ desc: "desc";
61
+ }>>;
62
+ height: z.ZodNullable<z.ZodNumber>;
63
+ }, z.core.$strip>;
64
+ readonly description: "Cleveland dot plot: categorical labels down the Y axis, one dot per category positioned by value on X. Higher data-ink ratio than a bar chart for ranked comparison. Sorts descending by default.";
65
+ readonly example: {
66
+ readonly title: "Build time by package";
67
+ readonly data: readonly [{
68
+ readonly pkg: "core";
69
+ readonly seconds: 42;
70
+ }, {
71
+ readonly pkg: "client";
72
+ readonly seconds: 31;
73
+ }, {
74
+ readonly pkg: "mcp";
75
+ readonly seconds: 18;
76
+ }, {
77
+ readonly pkg: "cli";
78
+ readonly seconds: 9;
79
+ }];
80
+ readonly labelKey: "pkg";
81
+ readonly valueKey: "seconds";
82
+ readonly color: null;
83
+ readonly sort: "desc";
84
+ readonly height: null;
85
+ };
86
+ };
87
+ BulletChart: {
88
+ readonly props: z.ZodObject<{
89
+ title: z.ZodNullable<z.ZodString>;
90
+ data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
91
+ labelKey: z.ZodNullable<z.ZodString>;
92
+ valueKey: z.ZodString;
93
+ targetKey: z.ZodNullable<z.ZodString>;
94
+ rangesKey: z.ZodNullable<z.ZodString>;
95
+ color: z.ZodNullable<z.ZodString>;
96
+ height: z.ZodNullable<z.ZodNumber>;
97
+ }, z.core.$strip>;
98
+ readonly description: "Stephen Few's bullet graph: a measure bar against grayscale qualitative bands with a target tick and per-row scale ticks. Compact KPI-vs-target display. Provide per-row `ranges` (ascending band thresholds) and `target`.";
99
+ readonly example: {
100
+ readonly title: "Quarterly KPIs vs target";
101
+ readonly data: readonly [{
102
+ readonly label: "Revenue";
103
+ readonly value: 84;
104
+ readonly target: 90;
105
+ readonly ranges: readonly [50, 75, 100];
106
+ }, {
107
+ readonly label: "NPS";
108
+ readonly value: 67;
109
+ readonly target: 60;
110
+ readonly ranges: readonly [40, 60, 80];
111
+ }, {
112
+ readonly label: "Uptime";
113
+ readonly value: 99;
114
+ readonly target: 99.9;
115
+ readonly ranges: readonly [95, 99, 100];
116
+ }];
117
+ readonly labelKey: "label";
118
+ readonly valueKey: "value";
119
+ readonly targetKey: "target";
120
+ readonly rangesKey: "ranges";
121
+ readonly color: null;
122
+ readonly height: null;
123
+ };
124
+ };
125
+ Slopegraph: {
126
+ readonly props: z.ZodObject<{
127
+ title: z.ZodNullable<z.ZodString>;
128
+ data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
129
+ labelKey: z.ZodString;
130
+ beforeKey: z.ZodString;
131
+ afterKey: z.ZodString;
132
+ beforeLabel: z.ZodNullable<z.ZodString>;
133
+ afterLabel: z.ZodNullable<z.ZodString>;
134
+ color: z.ZodNullable<z.ZodString>;
135
+ colorByDirection: z.ZodNullable<z.ZodBoolean>;
136
+ height: z.ZodNullable<z.ZodNumber>;
137
+ }, z.core.$strip>;
138
+ readonly description: "Tufte slopegraph: two value columns (before/after) with a connecting line per category. Lines use one neutral ink by default; set colorByDirection to accent rising lines and mute falling ones. Ideal for paired change across many items.";
139
+ readonly example: {
140
+ readonly title: "Coverage before/after refactor";
141
+ readonly data: readonly [{
142
+ readonly module: "auth";
143
+ readonly before: 62;
144
+ readonly after: 81;
145
+ }, {
146
+ readonly module: "canvas";
147
+ readonly before: 74;
148
+ readonly after: 78;
149
+ }, {
150
+ readonly module: "mcp";
151
+ readonly before: 55;
152
+ readonly after: 49;
153
+ }];
154
+ readonly labelKey: "module";
155
+ readonly beforeKey: "before";
156
+ readonly afterKey: "after";
157
+ readonly beforeLabel: "Before";
158
+ readonly afterLabel: "After";
159
+ readonly color: null;
160
+ readonly colorByDirection: null;
161
+ readonly height: null;
162
+ };
163
+ };
10
164
  AreaChart: {
11
165
  readonly props: z.ZodObject<{
12
166
  title: z.ZodNullable<z.ZodString>;
@@ -232,8 +386,18 @@ export declare const allComponentDefinitions: {
232
386
  }>>;
233
387
  color: z.ZodNullable<z.ZodString>;
234
388
  height: z.ZodNullable<z.ZodNumber>;
389
+ colorBy: z.ZodNullable<z.ZodEnum<{
390
+ value: "value";
391
+ series: "series";
392
+ category: "category";
393
+ none: "none";
394
+ }>>;
395
+ highlight: z.ZodNullable<z.ZodUnion<readonly [z.ZodNumber, z.ZodEnum<{
396
+ max: "max";
397
+ min: "min";
398
+ }>]>>;
235
399
  }, z.core.$strip>;
236
- readonly description: "Bar chart for comparing categories. Provide data as an array of objects with xKey and yKey fields.";
400
+ readonly description: "Bar chart for comparing categories. Provide data as an array of objects with xKey and yKey fields. Color encodes data, not decoration: by default one accent with the tallest bar highlighted (colorBy='series'). Set colorBy='category' only when the category itself is the message, 'value' to shade by magnitude, or 'none' for a flat fill.";
237
401
  readonly example: {
238
402
  readonly title: "Sales by region";
239
403
  readonly data: readonly [{
@@ -251,6 +415,8 @@ export declare const allComponentDefinitions: {
251
415
  readonly aggregate: null;
252
416
  readonly color: null;
253
417
  readonly height: null;
418
+ readonly colorBy: "series";
419
+ readonly highlight: "max";
254
420
  };
255
421
  };
256
422
  PieChart: {
@@ -288,13 +454,13 @@ export declare const allComponentDefinitions: {
288
454
  text: z.ZodString;
289
455
  variant: z.ZodNullable<z.ZodEnum<{
290
456
  error: "error";
457
+ info: "info";
458
+ warning: "warning";
291
459
  default: "default";
292
460
  success: "success";
293
461
  secondary: "secondary";
294
462
  destructive: "destructive";
295
463
  outline: "outline";
296
- info: "info";
297
- warning: "warning";
298
464
  danger: "danger";
299
465
  }>>;
300
466
  }, z.core.$strip>;
@@ -304,6 +470,27 @@ export declare const allComponentDefinitions: {
304
470
  variant: string;
305
471
  };
306
472
  };
473
+ Button: {
474
+ props: z.ZodObject<{
475
+ label: z.ZodString;
476
+ disabled: z.ZodNullable<z.ZodBoolean>;
477
+ variant: z.ZodNullable<z.ZodEnum<{
478
+ success: "success";
479
+ secondary: "secondary";
480
+ destructive: "destructive";
481
+ outline: "outline";
482
+ danger: "danger";
483
+ primary: "primary";
484
+ ghost: "ghost";
485
+ }>>;
486
+ }, z.core.$strip>;
487
+ description: string;
488
+ example: {
489
+ label: string;
490
+ variant: string;
491
+ };
492
+ events: string[];
493
+ };
307
494
  Card: {
308
495
  props: z.ZodObject<{
309
496
  title: z.ZodNullable<z.ZodString>;
@@ -315,6 +502,7 @@ export declare const allComponentDefinitions: {
315
502
  full: "full";
316
503
  }>>;
317
504
  centered: z.ZodNullable<z.ZodBoolean>;
505
+ className: z.ZodNullable<z.ZodString>;
318
506
  }, z.core.$strip>;
319
507
  slots: string[];
320
508
  description: string;
@@ -334,6 +522,7 @@ export declare const allComponentDefinitions: {
334
522
  md: "md";
335
523
  lg: "lg";
336
524
  none: "none";
525
+ xl: "xl";
337
526
  }>>;
338
527
  align: z.ZodNullable<z.ZodEnum<{
339
528
  start: "start";
@@ -348,6 +537,7 @@ export declare const allComponentDefinitions: {
348
537
  between: "between";
349
538
  around: "around";
350
539
  }>>;
540
+ className: z.ZodNullable<z.ZodString>;
351
541
  }, z.core.$strip>;
352
542
  slots: string[];
353
543
  description: string;
@@ -363,7 +553,9 @@ export declare const allComponentDefinitions: {
363
553
  sm: "sm";
364
554
  md: "md";
365
555
  lg: "lg";
556
+ xl: "xl";
366
557
  }>>;
558
+ className: z.ZodNullable<z.ZodString>;
367
559
  }, z.core.$strip>;
368
560
  slots: string[];
369
561
  description: string;
@@ -717,23 +909,6 @@ export declare const allComponentDefinitions: {
717
909
  events: string[];
718
910
  description: string;
719
911
  };
720
- Button: {
721
- props: z.ZodObject<{
722
- label: z.ZodString;
723
- variant: z.ZodNullable<z.ZodEnum<{
724
- secondary: "secondary";
725
- primary: "primary";
726
- danger: "danger";
727
- }>>;
728
- disabled: z.ZodNullable<z.ZodBoolean>;
729
- }, z.core.$strip>;
730
- events: string[];
731
- description: string;
732
- example: {
733
- label: string;
734
- variant: string;
735
- };
736
- };
737
912
  Link: {
738
913
  props: z.ZodObject<{
739
914
  label: z.ZodString;
@@ -11,6 +11,8 @@ import type { BaseComponentProps } from '@json-render/react';
11
11
  export declare const CHART_COLORS: string[];
12
12
  export type AggregateMode = 'sum' | 'count' | 'avg';
13
13
  export declare function processChartData(data: Record<string, unknown>[], xKey: string, yKey: string, aggregate: AggregateMode | null | undefined): Record<string, unknown>[];
14
+ export type BarColorBy = 'series' | 'category' | 'value' | 'none';
15
+ export type BarHighlight = number | 'max' | 'min' | null;
14
16
  export interface CartesianChartProps {
15
17
  title?: string | null;
16
18
  data: Record<string, unknown>[];
@@ -19,6 +21,10 @@ export interface CartesianChartProps {
19
21
  aggregate?: AggregateMode | null;
20
22
  color?: string | null;
21
23
  height?: number | null;
24
+ /** Bar-only: how bar fills are colored. Defaults to 'series'. Ignored by line charts. */
25
+ colorBy?: BarColorBy | null;
26
+ /** Bar-only: which bar gets the accent under colorBy='series'. Defaults to 'max'. */
27
+ highlight?: BarHighlight;
22
28
  }
23
29
  interface PieChartProps {
24
30
  title?: string | null;
@@ -59,6 +65,7 @@ export declare const legendMargin: {
59
65
  export declare function useChartFrameHeight(explicitHeight: number | null | undefined, fallbackHeight?: number): {
60
66
  frameRef: import("react").RefObject<HTMLDivElement | null>;
61
67
  height: number;
68
+ width: number;
62
69
  };
63
70
  /** Shared wrapper for cartesian charts (Line + Bar). */
64
71
  export declare function CartesianChart({ props, children, className, }: {
@@ -53,8 +53,18 @@ export declare const chartComponentDefinitions: {
53
53
  }>>;
54
54
  color: z.ZodNullable<z.ZodString>;
55
55
  height: z.ZodNullable<z.ZodNumber>;
56
+ colorBy: z.ZodNullable<z.ZodEnum<{
57
+ value: "value";
58
+ series: "series";
59
+ category: "category";
60
+ none: "none";
61
+ }>>;
62
+ highlight: z.ZodNullable<z.ZodUnion<readonly [z.ZodNumber, z.ZodEnum<{
63
+ max: "max";
64
+ min: "min";
65
+ }>]>>;
56
66
  }, z.core.$strip>;
57
- readonly description: "Bar chart for comparing categories. Provide data as an array of objects with xKey and yKey fields.";
67
+ readonly description: "Bar chart for comparing categories. Provide data as an array of objects with xKey and yKey fields. Color encodes data, not decoration: by default one accent with the tallest bar highlighted (colorBy='series'). Set colorBy='category' only when the category itself is the message, 'value' to shade by magnitude, or 'none' for a flat fill.";
58
68
  readonly example: {
59
69
  readonly title: "Sales by region";
60
70
  readonly data: readonly [{
@@ -72,6 +82,8 @@ export declare const chartComponentDefinitions: {
72
82
  readonly aggregate: null;
73
83
  readonly color: null;
74
84
  readonly height: null;
85
+ readonly colorBy: "series";
86
+ readonly highlight: "max";
75
87
  };
76
88
  };
77
89
  readonly PieChart: {
@@ -0,0 +1,65 @@
1
+ /** @jsxImportSource react */
2
+ /**
3
+ * Tufte primitive chart components for json-render.
4
+ *
5
+ * Word-sized / high-data-ink-ratio primitives that Recharts handles poorly:
6
+ * Sparkline, DotPlot (Cleveland), BulletChart (Few), and Slopegraph (Tufte).
7
+ * Hand-rolled SVG keeps the data-ink ratio high and avoids Recharts chartjunk.
8
+ *
9
+ * Lives alongside ./components.tsx and ./extra-components.tsx so the original
10
+ * chart sets stay unchanged; ./catalog.ts is the only merge surface.
11
+ */
12
+ import type { BaseComponentProps } from '@json-render/react';
13
+ interface SparklineProps {
14
+ title?: string | null;
15
+ data: Record<string, unknown>[];
16
+ valueKey: string;
17
+ color?: string | null;
18
+ fill?: boolean | null;
19
+ showEndDot?: boolean | null;
20
+ showMinMax?: boolean | null;
21
+ showValue?: boolean | null;
22
+ height?: number | null;
23
+ }
24
+ declare function ChartSparkline({ props }: BaseComponentProps<SparklineProps>): import("react/jsx-runtime").JSX.Element;
25
+ interface DotPlotProps {
26
+ title?: string | null;
27
+ data: Record<string, unknown>[];
28
+ labelKey: string;
29
+ valueKey: string;
30
+ color?: string | null;
31
+ sort?: 'asc' | 'desc' | 'none' | null;
32
+ height?: number | null;
33
+ }
34
+ declare function ChartDotPlot({ props }: BaseComponentProps<DotPlotProps>): import("react/jsx-runtime").JSX.Element;
35
+ interface BulletChartProps {
36
+ title?: string | null;
37
+ data: Record<string, unknown>[];
38
+ labelKey?: string | null;
39
+ valueKey: string;
40
+ targetKey?: string | null;
41
+ rangesKey?: string | null;
42
+ color?: string | null;
43
+ height?: number | null;
44
+ }
45
+ declare function ChartBulletChart({ props }: BaseComponentProps<BulletChartProps>): import("react/jsx-runtime").JSX.Element;
46
+ interface SlopegraphProps {
47
+ title?: string | null;
48
+ data: Record<string, unknown>[];
49
+ labelKey: string;
50
+ beforeKey: string;
51
+ afterKey: string;
52
+ beforeLabel?: string | null;
53
+ afterLabel?: string | null;
54
+ color?: string | null;
55
+ colorByDirection?: boolean | null;
56
+ height?: number | null;
57
+ }
58
+ declare function ChartSlopegraph({ props }: BaseComponentProps<SlopegraphProps>): import("react/jsx-runtime").JSX.Element;
59
+ export declare const tufteChartComponents: {
60
+ Sparkline: typeof ChartSparkline;
61
+ DotPlot: typeof ChartDotPlot;
62
+ BulletChart: typeof ChartBulletChart;
63
+ Slopegraph: typeof ChartSlopegraph;
64
+ };
65
+ export {};
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Definitions for the Tufte primitive chart components in ./tufte-components.tsx.
3
+ *
4
+ * Kept separate from ./definitions.ts and ./extra-definitions.ts so the
5
+ * original chart catalogs stay untouched and the merge in ./catalog.ts is the
6
+ * only contact surface.
7
+ */
8
+ import { z } from 'zod';
9
+ export declare const tufteChartComponentDefinitions: {
10
+ readonly Sparkline: {
11
+ readonly props: z.ZodObject<{
12
+ title: z.ZodNullable<z.ZodString>;
13
+ data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
14
+ valueKey: z.ZodString;
15
+ color: z.ZodNullable<z.ZodString>;
16
+ fill: z.ZodNullable<z.ZodBoolean>;
17
+ showEndDot: z.ZodNullable<z.ZodBoolean>;
18
+ showMinMax: z.ZodNullable<z.ZodBoolean>;
19
+ showValue: z.ZodNullable<z.ZodBoolean>;
20
+ height: z.ZodNullable<z.ZodNumber>;
21
+ }, z.core.$strip>;
22
+ readonly description: "Word-sized sparkline: a single trend line with no axes, grid, or labels. Optional end dot, min/max markers, light area fill, and an inline last value. The canonical Tufte primitive for showing a trajectory in minimal space.";
23
+ readonly example: {
24
+ readonly title: "Latency p95";
25
+ readonly data: readonly [{
26
+ readonly t: 0;
27
+ readonly ms: 120;
28
+ }, {
29
+ readonly t: 1;
30
+ readonly ms: 138;
31
+ }, {
32
+ readonly t: 2;
33
+ readonly ms: 117;
34
+ }, {
35
+ readonly t: 3;
36
+ readonly ms: 152;
37
+ }, {
38
+ readonly t: 4;
39
+ readonly ms: 109;
40
+ }];
41
+ readonly valueKey: "ms";
42
+ readonly color: null;
43
+ readonly fill: true;
44
+ readonly showEndDot: true;
45
+ readonly showMinMax: false;
46
+ readonly showValue: true;
47
+ readonly height: null;
48
+ };
49
+ };
50
+ readonly DotPlot: {
51
+ readonly props: z.ZodObject<{
52
+ title: z.ZodNullable<z.ZodString>;
53
+ data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
54
+ labelKey: z.ZodString;
55
+ valueKey: z.ZodString;
56
+ color: z.ZodNullable<z.ZodString>;
57
+ sort: z.ZodNullable<z.ZodEnum<{
58
+ none: "none";
59
+ asc: "asc";
60
+ desc: "desc";
61
+ }>>;
62
+ height: z.ZodNullable<z.ZodNumber>;
63
+ }, z.core.$strip>;
64
+ readonly description: "Cleveland dot plot: categorical labels down the Y axis, one dot per category positioned by value on X. Higher data-ink ratio than a bar chart for ranked comparison. Sorts descending by default.";
65
+ readonly example: {
66
+ readonly title: "Build time by package";
67
+ readonly data: readonly [{
68
+ readonly pkg: "core";
69
+ readonly seconds: 42;
70
+ }, {
71
+ readonly pkg: "client";
72
+ readonly seconds: 31;
73
+ }, {
74
+ readonly pkg: "mcp";
75
+ readonly seconds: 18;
76
+ }, {
77
+ readonly pkg: "cli";
78
+ readonly seconds: 9;
79
+ }];
80
+ readonly labelKey: "pkg";
81
+ readonly valueKey: "seconds";
82
+ readonly color: null;
83
+ readonly sort: "desc";
84
+ readonly height: null;
85
+ };
86
+ };
87
+ readonly BulletChart: {
88
+ readonly props: z.ZodObject<{
89
+ title: z.ZodNullable<z.ZodString>;
90
+ data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
91
+ labelKey: z.ZodNullable<z.ZodString>;
92
+ valueKey: z.ZodString;
93
+ targetKey: z.ZodNullable<z.ZodString>;
94
+ rangesKey: z.ZodNullable<z.ZodString>;
95
+ color: z.ZodNullable<z.ZodString>;
96
+ height: z.ZodNullable<z.ZodNumber>;
97
+ }, z.core.$strip>;
98
+ readonly description: "Stephen Few's bullet graph: a measure bar against grayscale qualitative bands with a target tick and per-row scale ticks. Compact KPI-vs-target display. Provide per-row `ranges` (ascending band thresholds) and `target`.";
99
+ readonly example: {
100
+ readonly title: "Quarterly KPIs vs target";
101
+ readonly data: readonly [{
102
+ readonly label: "Revenue";
103
+ readonly value: 84;
104
+ readonly target: 90;
105
+ readonly ranges: readonly [50, 75, 100];
106
+ }, {
107
+ readonly label: "NPS";
108
+ readonly value: 67;
109
+ readonly target: 60;
110
+ readonly ranges: readonly [40, 60, 80];
111
+ }, {
112
+ readonly label: "Uptime";
113
+ readonly value: 99;
114
+ readonly target: 99.9;
115
+ readonly ranges: readonly [95, 99, 100];
116
+ }];
117
+ readonly labelKey: "label";
118
+ readonly valueKey: "value";
119
+ readonly targetKey: "target";
120
+ readonly rangesKey: "ranges";
121
+ readonly color: null;
122
+ readonly height: null;
123
+ };
124
+ };
125
+ readonly Slopegraph: {
126
+ readonly props: z.ZodObject<{
127
+ title: z.ZodNullable<z.ZodString>;
128
+ data: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
129
+ labelKey: z.ZodString;
130
+ beforeKey: z.ZodString;
131
+ afterKey: z.ZodString;
132
+ beforeLabel: z.ZodNullable<z.ZodString>;
133
+ afterLabel: z.ZodNullable<z.ZodString>;
134
+ color: z.ZodNullable<z.ZodString>;
135
+ colorByDirection: z.ZodNullable<z.ZodBoolean>;
136
+ height: z.ZodNullable<z.ZodNumber>;
137
+ }, z.core.$strip>;
138
+ readonly description: "Tufte slopegraph: two value columns (before/after) with a connecting line per category. Lines use one neutral ink by default; set colorByDirection to accent rising lines and mute falling ones. Ideal for paired change across many items.";
139
+ readonly example: {
140
+ readonly title: "Coverage before/after refactor";
141
+ readonly data: readonly [{
142
+ readonly module: "auth";
143
+ readonly before: 62;
144
+ readonly after: 81;
145
+ }, {
146
+ readonly module: "canvas";
147
+ readonly before: 74;
148
+ readonly after: 78;
149
+ }, {
150
+ readonly module: "mcp";
151
+ readonly before: 55;
152
+ readonly after: 49;
153
+ }];
154
+ readonly labelKey: "module";
155
+ readonly beforeKey: "before";
156
+ readonly afterKey: "after";
157
+ readonly beforeLabel: "Before";
158
+ readonly afterLabel: "After";
159
+ readonly color: null;
160
+ readonly colorByDirection: null;
161
+ readonly height: null;
162
+ };
163
+ };
164
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Custom json-render directives available in PMX Canvas specs.
3
+ *
4
+ * Directives let agent specs declare formatting/derivation ($format, $math,
5
+ * $concat, $count, $truncate, $pluralize, $join) instead of pre-formatting
6
+ * strings. Registered into the iframe renderer via <JSONUIProvider directives>.
7
+ */
8
+ import type { DirectiveDefinition } from '@json-render/core';
9
+ /**
10
+ * Directives enabled in the PMX Canvas viewer. `standardDirectives` covers the
11
+ * seven stateless directives. The $t i18n directive is intentionally omitted —
12
+ * it is a factory requiring locale config and PMX Canvas has no locale source.
13
+ */
14
+ export declare const pmxCanvasDirectives: DirectiveDefinition[];
15
+ /**
16
+ * True when a prop value is a render-time dynamic expression — a directive
17
+ * (`$format`/`$math`/…) or an existing binding (`$state`/`$item`/`$bindItem`/
18
+ * `$cond`/`$template`/`$computed`). These objects are resolved inside the
19
+ * renderer, so the server-side validators must leave them untouched instead of
20
+ * string-coercing them to `"[object Object]"` or rejecting them as the wrong
21
+ * primitive type.
22
+ */
23
+ export declare function isDynamicPropValue(value: unknown): boolean;
@@ -13,5 +13,6 @@ declare global {
13
13
  };
14
14
  __PMX_CANVAS_JSON_RENDER_THEME__?: string;
15
15
  __PMX_CANVAS_JSON_RENDER_DISPLAY__?: string;
16
+ __PMX_CANVAS_JSON_RENDER_DEVTOOLS__?: boolean;
16
17
  }
17
18
  }
@@ -28,8 +28,23 @@ export interface GraphNodeInput {
28
28
  lineKey?: string;
29
29
  aggregate?: 'sum' | 'count' | 'avg';
30
30
  color?: string;
31
+ colorBy?: 'series' | 'category' | 'value' | 'none';
32
+ highlight?: number | 'max' | 'min' | null;
31
33
  barColor?: string;
32
34
  lineColor?: string;
35
+ labelKey?: string;
36
+ beforeKey?: string;
37
+ afterKey?: string;
38
+ beforeLabel?: string;
39
+ afterLabel?: string;
40
+ targetKey?: string;
41
+ rangesKey?: string;
42
+ sort?: 'asc' | 'desc' | 'none';
43
+ fill?: boolean;
44
+ showEndDot?: boolean;
45
+ showMinMax?: boolean;
46
+ showValue?: boolean;
47
+ colorByDirection?: boolean;
33
48
  height?: number;
34
49
  showLegend?: boolean;
35
50
  showLabels?: boolean;
@@ -47,16 +62,32 @@ export declare const GRAPH_NODE_SIZE: {
47
62
  width: number;
48
63
  height: number;
49
64
  };
50
- export type GraphChartType = 'LineChart' | 'BarChart' | 'PieChart' | 'AreaChart' | 'ScatterChart' | 'RadarChart' | 'StackedBarChart' | 'ComposedChart';
65
+ export type GraphChartType = 'LineChart' | 'BarChart' | 'PieChart' | 'AreaChart' | 'ScatterChart' | 'RadarChart' | 'StackedBarChart' | 'ComposedChart' | 'Sparkline' | 'DotPlot' | 'BulletChart' | 'Slopegraph';
51
66
  export declare function inferJsonRenderNodeTitle(spec: JsonRenderSpec, fallback?: string): string;
52
67
  export declare function normalizeAndValidateJsonRenderSpec(spec: unknown): JsonRenderSpec;
53
68
  export declare function normalizeGraphType(value: string): GraphChartType;
54
69
  export declare function buildGraphSpec(input: GraphNodeInput): JsonRenderSpec;
55
70
  export declare function buildGraphConfig(input: GraphNodeInput): Record<string, unknown>;
71
+ /** The minimal spec a streaming json-render node starts from before any patches. */
72
+ export declare function emptyStreamingSpec(): JsonRenderSpec;
73
+ /**
74
+ * Apply a batch of SpecStream patches to the current spec, accumulating the
75
+ * result. The canvas is the source of truth — patches are applied server-side
76
+ * and the browser only renders the current accumulated spec, so there is no
77
+ * client-side reconciliation. Tolerant by design: malformed or inapplicable
78
+ * patches are skipped and counted, never thrown, so a partial stream keeps
79
+ * building toward the final spec.
80
+ */
81
+ export declare function applyJsonRenderStreamPatches(currentSpec: JsonRenderSpec, items: unknown[]): {
82
+ spec: JsonRenderSpec;
83
+ applied: number;
84
+ skipped: number;
85
+ };
56
86
  export declare function createJsonRenderNodeData(nodeId: string, title: string, spec: JsonRenderSpec, extra?: Record<string, unknown>): Record<string, unknown>;
57
87
  export declare function buildJsonRenderViewerHtml(options: {
58
88
  title: string;
59
89
  spec: JsonRenderSpec;
60
90
  theme?: 'dark' | 'light' | 'high-contrast';
61
91
  display?: 'expanded';
92
+ devtools?: boolean;
62
93
  }): Promise<string>;