@aganzefelicite/responsekit-react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -0
- package/dist/ChartRenderer-UJNU2VNH.cjs +153 -0
- package/dist/ChartRenderer-UJNU2VNH.cjs.map +1 -0
- package/dist/ChartRenderer-URPZESVN.js +151 -0
- package/dist/ChartRenderer-URPZESVN.js.map +1 -0
- package/dist/chunk-3FSZRQQU.js +33 -0
- package/dist/chunk-3FSZRQQU.js.map +1 -0
- package/dist/chunk-D4WIPDH3.cjs +38 -0
- package/dist/chunk-D4WIPDH3.cjs.map +1 -0
- package/dist/index.cjs +5053 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +313 -0
- package/dist/index.d.ts +313 -0
- package/dist/index.js +4980 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +108 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# @aganzefelicite/responsekit-react
|
|
2
|
+
|
|
3
|
+
Render your AI backend's responses as interactive React UI. Point it at your backend and
|
|
4
|
+
it turns the standardized response contract (streamed as SSE or a single object) into
|
|
5
|
+
components — safely, and without ever crashing on unknown or invalid data.
|
|
6
|
+
|
|
7
|
+
- **Renders only** — never calls an AI model or generates responses.
|
|
8
|
+
- **Never crashes** — unknown block types / missing fields degrade to a safe fallback.
|
|
9
|
+
- **Safe by default** — AI text is GitHub-flavored Markdown with **no raw HTML**; data
|
|
10
|
+
values are escaped. No `dangerouslySetInnerHTML`.
|
|
11
|
+
- **Lean bundle** — tree-shakeable ESM, React as a peer dep; charts (Recharts) are
|
|
12
|
+
lazy-loaded into their own chunk.
|
|
13
|
+
|
|
14
|
+
> Full walkthrough: **[Adding ResponseKit to an existing project](../../docs/INTEGRATION.md)**.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
Not published to npm yet — install from a local build of this repo (`@responsekit/schema`
|
|
19
|
+
is bundled in, so it's a single tarball):
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# in the repo root
|
|
23
|
+
pnpm pack:local
|
|
24
|
+
# in your app
|
|
25
|
+
pnpm add /ABS/PATH/responsekit-react-0.0.0.tgz react react-dom
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import "@aganzefelicite/responsekit-react/styles.css"; // optional default styling
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
See [docs/INTEGRATION.md](../../docs/INTEGRATION.md) for `pnpm link` and publishing options.
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { AiRenderer, AiStream, useChat } from "@aganzefelicite/responsekit-react";
|
|
38
|
+
|
|
39
|
+
// 1) Render a response you already have
|
|
40
|
+
<AiRenderer response={response} onAction={(a) => {}} />;
|
|
41
|
+
|
|
42
|
+
// 2) Stream one message
|
|
43
|
+
<AiStream baseUrl="" conversationId={id} message="How many open cases?" onAction={(a) => {}} />;
|
|
44
|
+
|
|
45
|
+
// 3) A whole conversation
|
|
46
|
+
const { turns, send, isStreaming, newConversation } = useChat({ baseUrl: "" });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`baseUrl` is prepended to the API paths; `""` means same-origin (proxy `/api` to your
|
|
50
|
+
backend). The message endpoint is POST + `text/event-stream`; the SDK drives
|
|
51
|
+
`fetch` + `ReadableStream` internally (native `EventSource` can't POST).
|
|
52
|
+
|
|
53
|
+
## API
|
|
54
|
+
|
|
55
|
+
**Components** — `AiRenderer`, `AiStream`
|
|
56
|
+
**Hooks** — `useAiStream`, `useChat`
|
|
57
|
+
**Registry** — `registerBlock`, `unregisterBlock`, `resolveBlockComponent`
|
|
58
|
+
**Default blocks** — `TextBlock`, `KpiBlock`, `ChartBlock`, `TableBlock`, `InsightBlock`,
|
|
59
|
+
`RecommendationBlock`, `FilterBlock`, `FallbackBlock`, `defaultBlockComponents`
|
|
60
|
+
**Conversation REST** — `createConversation`, `listConversations`, `getConversation`,
|
|
61
|
+
`renameConversation`, `deleteConversation`, `getMessages`
|
|
62
|
+
**Transport** — `streamMessage`, `messageUrl`
|
|
63
|
+
**Misc** — `Markdown`, `ErrorBoundary`, action types, and everything re-exported from
|
|
64
|
+
[`@responsekit/schema`](../schema) (types, validators, the stream reducer).
|
|
65
|
+
|
|
66
|
+
## Overrides & custom blocks
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
// override built-ins for one render
|
|
70
|
+
<AiRenderer response={r} components={{ KPI: MyKpi, CHART: MyChart }} />;
|
|
71
|
+
|
|
72
|
+
// register a custom/unknown block type globally
|
|
73
|
+
import { registerBlock } from "@aganzefelicite/responsekit-react";
|
|
74
|
+
registerBlock({ type: "MAP", component: RwandaMap });
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Resolution order per block type: `components` prop → globally registered → built-in default
|
|
78
|
+
→ graceful fallback.
|
|
79
|
+
|
|
80
|
+
## Actions
|
|
81
|
+
|
|
82
|
+
Blocks emit intent through one `onAction(action)` callback (`DOWNLOAD`, `OPEN_LINK`,
|
|
83
|
+
`REFRESH`, `CUSTOM`, or host-defined). The SDK never runs business logic.
|
|
84
|
+
|
|
85
|
+
## License
|
|
86
|
+
|
|
87
|
+
MIT
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkD4WIPDH3_cjs = require('./chunk-D4WIPDH3.cjs');
|
|
4
|
+
var recharts = require('recharts');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
var PALETTE = [
|
|
8
|
+
"#2563eb",
|
|
9
|
+
"#16a34a",
|
|
10
|
+
"#d97706",
|
|
11
|
+
"#dc2626",
|
|
12
|
+
"#7c3aed",
|
|
13
|
+
"#0891b2",
|
|
14
|
+
"#db2777",
|
|
15
|
+
"#65a30d"
|
|
16
|
+
];
|
|
17
|
+
function inferShape(data) {
|
|
18
|
+
const first = data[0] ?? {};
|
|
19
|
+
const keys = Object.keys(first);
|
|
20
|
+
const isNumericCol = (k) => data.some((row) => typeof row[k] === "number");
|
|
21
|
+
const xKey = keys.find((k) => !isNumericCol(k)) ?? keys[0] ?? "x";
|
|
22
|
+
const seriesKeys = keys.filter((k) => k !== xKey && isNumericCol(k));
|
|
23
|
+
return {
|
|
24
|
+
xKey,
|
|
25
|
+
seriesKeys: seriesKeys.length ? seriesKeys : keys.filter((k) => k !== xKey)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
var HEIGHT = 300;
|
|
29
|
+
var color = (i) => PALETTE[i % PALETTE.length];
|
|
30
|
+
function ChartRenderer({ block }) {
|
|
31
|
+
const data = Array.isArray(block.data) ? block.data : [];
|
|
32
|
+
if (data.length === 0) return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rk-empty", children: "No chart data." });
|
|
33
|
+
const { xKey, seriesKeys } = inferShape(data);
|
|
34
|
+
const type = block.chartType;
|
|
35
|
+
switch (type) {
|
|
36
|
+
case "LINE":
|
|
37
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Frame, { children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data, children: [
|
|
38
|
+
grid(),
|
|
39
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: xKey, tick: AXIS_TICK }),
|
|
40
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { tick: AXIS_TICK }),
|
|
41
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, {}),
|
|
42
|
+
seriesKeys.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}) : null,
|
|
43
|
+
seriesKeys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Line, { type: "monotone", dataKey: k, stroke: color(i), strokeWidth: 2, dot: false }, k))
|
|
44
|
+
] }) });
|
|
45
|
+
case "AREA":
|
|
46
|
+
case "STACKED_AREA":
|
|
47
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Frame, { children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.AreaChart, { data, children: [
|
|
48
|
+
grid(),
|
|
49
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: xKey, tick: AXIS_TICK }),
|
|
50
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { tick: AXIS_TICK }),
|
|
51
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, {}),
|
|
52
|
+
seriesKeys.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}) : null,
|
|
53
|
+
seriesKeys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
54
|
+
recharts.Area,
|
|
55
|
+
{
|
|
56
|
+
type: "monotone",
|
|
57
|
+
dataKey: k,
|
|
58
|
+
stackId: type === "STACKED_AREA" ? "stack" : void 0,
|
|
59
|
+
stroke: color(i),
|
|
60
|
+
fill: color(i),
|
|
61
|
+
fillOpacity: 0.25
|
|
62
|
+
},
|
|
63
|
+
k
|
|
64
|
+
))
|
|
65
|
+
] }) });
|
|
66
|
+
case "BAR":
|
|
67
|
+
case "STACKED_BAR":
|
|
68
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Frame, { children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data, children: [
|
|
69
|
+
grid(),
|
|
70
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: xKey, tick: AXIS_TICK }),
|
|
71
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { tick: AXIS_TICK }),
|
|
72
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, {}),
|
|
73
|
+
seriesKeys.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}) : null,
|
|
74
|
+
seriesKeys.map((k, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
75
|
+
recharts.Bar,
|
|
76
|
+
{
|
|
77
|
+
dataKey: k,
|
|
78
|
+
stackId: type === "STACKED_BAR" ? "stack" : void 0,
|
|
79
|
+
fill: color(i)
|
|
80
|
+
},
|
|
81
|
+
k
|
|
82
|
+
))
|
|
83
|
+
] }) });
|
|
84
|
+
case "PIE":
|
|
85
|
+
case "DONUT": {
|
|
86
|
+
const valueKey = seriesKeys[0] ?? "value";
|
|
87
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Frame, { children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { children: [
|
|
88
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, {}),
|
|
89
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
|
|
90
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
91
|
+
recharts.Pie,
|
|
92
|
+
{
|
|
93
|
+
data,
|
|
94
|
+
dataKey: valueKey,
|
|
95
|
+
nameKey: xKey,
|
|
96
|
+
cx: "50%",
|
|
97
|
+
cy: "50%",
|
|
98
|
+
outerRadius: 110,
|
|
99
|
+
innerRadius: type === "DONUT" ? 60 : 0,
|
|
100
|
+
label: (entry) => chunkD4WIPDH3_cjs.formatValue(entry?.name),
|
|
101
|
+
children: data.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: color(i) }, i))
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
] }) });
|
|
105
|
+
}
|
|
106
|
+
case "SCATTER": {
|
|
107
|
+
const xNum = seriesKeys[0];
|
|
108
|
+
const yNum = seriesKeys[1] ?? seriesKeys[0];
|
|
109
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Frame, { children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ScatterChart, { children: [
|
|
110
|
+
grid(),
|
|
111
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: xNum ?? xKey, type: "number", tick: AXIS_TICK, name: xNum ?? xKey }),
|
|
112
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { dataKey: yNum, type: "number", tick: AXIS_TICK, name: yNum }),
|
|
113
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.ZAxis, { range: [60, 60] }),
|
|
114
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { cursor: { strokeDasharray: "3 3" } }),
|
|
115
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Scatter, { data, fill: color(0) })
|
|
116
|
+
] }) });
|
|
117
|
+
}
|
|
118
|
+
// HEATMAP (and anything Recharts can't express) → a readable data preview.
|
|
119
|
+
default:
|
|
120
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PreviewTable, { block, data });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
var AXIS_TICK = { fontSize: 12 };
|
|
124
|
+
var grid = () => /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", stroke: "#eee" });
|
|
125
|
+
function Frame({ children }) {
|
|
126
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rk-chart", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: HEIGHT, children }) });
|
|
127
|
+
}
|
|
128
|
+
function PreviewTable({
|
|
129
|
+
block,
|
|
130
|
+
data
|
|
131
|
+
}) {
|
|
132
|
+
const keys = Object.keys(data[0] ?? {});
|
|
133
|
+
const preview = data.slice(0, 8);
|
|
134
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rk-chart-fallback", "data-chart-type": block.chartType, children: [
|
|
135
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rk-chart-badge", children: [
|
|
136
|
+
block.chartType,
|
|
137
|
+
" \xB7 rendered as a table (no chart mapping)"
|
|
138
|
+
] }),
|
|
139
|
+
/* @__PURE__ */ jsxRuntime.jsxs("table", { className: "rk-table rk-chart-preview", children: [
|
|
140
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: keys.map((k) => /* @__PURE__ */ jsxRuntime.jsx("th", { scope: "col", children: k }, k)) }) }),
|
|
141
|
+
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: preview.map((row, i) => /* @__PURE__ */ jsxRuntime.jsx("tr", { children: keys.map((k) => /* @__PURE__ */ jsxRuntime.jsx("td", { children: chunkD4WIPDH3_cjs.formatValue(row[k]) }, k)) }, i)) })
|
|
142
|
+
] }),
|
|
143
|
+
data.length > preview.length ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "rk-chart-more", children: [
|
|
144
|
+
"+",
|
|
145
|
+
data.length - preview.length,
|
|
146
|
+
" more rows"
|
|
147
|
+
] }) : null
|
|
148
|
+
] });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
module.exports = ChartRenderer;
|
|
152
|
+
//# sourceMappingURL=ChartRenderer-UJNU2VNH.cjs.map
|
|
153
|
+
//# sourceMappingURL=ChartRenderer-UJNU2VNH.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/blocks/ChartRenderer.tsx"],"names":["jsx","jsxs","LineChart","XAxis","YAxis","Tooltip","Legend","Line","AreaChart","Area","BarChart","Bar","PieChart","Pie","formatValue","Cell","ScatterChart","ZAxis","Scatter","CartesianGrid","ResponsiveContainer"],"mappings":"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","file":"ChartRenderer-UJNU2VNH.cjs","sourcesContent":["import type { ReactElement } from \"react\";\nimport {\n ResponsiveContainer,\n LineChart,\n Line,\n BarChart,\n Bar,\n AreaChart,\n Area,\n PieChart,\n Pie,\n Cell,\n ScatterChart,\n Scatter,\n XAxis,\n YAxis,\n ZAxis,\n CartesianGrid,\n Tooltip,\n Legend,\n} from \"recharts\";\nimport type { ChartBlock as ChartBlockType } from \"@responsekit/schema\";\nimport { formatValue } from \"./util.js\";\n\n/**\n * Real chart adapter, loaded lazily (see `ChartBlock`) so Recharts lands in its own\n * chunk and never weighs down the main bundle. This is the single place the SDK is\n * coupled to a charting library — swap it for visx/nivo/etc. without touching anything\n * else.\n *\n * The backend sends generic rows (e.g. `{ status: \"ONGOING\", count: 10 }`), so we infer\n * the category/x key (first non-numeric column) and the numeric series from the data.\n */\n\nconst PALETTE = [\n \"#2563eb\",\n \"#16a34a\",\n \"#d97706\",\n \"#dc2626\",\n \"#7c3aed\",\n \"#0891b2\",\n \"#db2777\",\n \"#65a30d\",\n];\n\ninterface Inferred {\n xKey: string;\n seriesKeys: string[];\n}\n\nfunction inferShape(data: Record<string, unknown>[]): Inferred {\n const first = data[0] ?? {};\n const keys = Object.keys(first);\n const isNumericCol = (k: string) => data.some((row) => typeof row[k] === \"number\");\n const xKey = keys.find((k) => !isNumericCol(k)) ?? keys[0] ?? \"x\";\n const seriesKeys = keys.filter((k) => k !== xKey && isNumericCol(k));\n // Fallback: if nothing looked numeric, treat every non-x column as a series.\n return {\n xKey,\n seriesKeys: seriesKeys.length ? seriesKeys : keys.filter((k) => k !== xKey),\n };\n}\n\nconst HEIGHT = 300;\nconst color = (i: number) => PALETTE[i % PALETTE.length];\n\nexport default function ChartRenderer({ block }: { block: ChartBlockType }) {\n const data = Array.isArray(block.data) ? (block.data as Record<string, unknown>[]) : [];\n if (data.length === 0) return <p className=\"rk-empty\">No chart data.</p>;\n\n const { xKey, seriesKeys } = inferShape(data);\n const type = block.chartType;\n\n switch (type) {\n case \"LINE\":\n return (\n <Frame>\n <LineChart data={data}>\n {grid()}\n <XAxis dataKey={xKey} tick={AXIS_TICK} />\n <YAxis tick={AXIS_TICK} />\n <Tooltip />\n {seriesKeys.length > 1 ? <Legend /> : null}\n {seriesKeys.map((k, i) => (\n <Line key={k} type=\"monotone\" dataKey={k} stroke={color(i)} strokeWidth={2} dot={false} />\n ))}\n </LineChart>\n </Frame>\n );\n\n case \"AREA\":\n case \"STACKED_AREA\":\n return (\n <Frame>\n <AreaChart data={data}>\n {grid()}\n <XAxis dataKey={xKey} tick={AXIS_TICK} />\n <YAxis tick={AXIS_TICK} />\n <Tooltip />\n {seriesKeys.length > 1 ? <Legend /> : null}\n {seriesKeys.map((k, i) => (\n <Area\n key={k}\n type=\"monotone\"\n dataKey={k}\n stackId={type === \"STACKED_AREA\" ? \"stack\" : undefined}\n stroke={color(i)}\n fill={color(i)}\n fillOpacity={0.25}\n />\n ))}\n </AreaChart>\n </Frame>\n );\n\n case \"BAR\":\n case \"STACKED_BAR\":\n return (\n <Frame>\n <BarChart data={data}>\n {grid()}\n <XAxis dataKey={xKey} tick={AXIS_TICK} />\n <YAxis tick={AXIS_TICK} />\n <Tooltip />\n {seriesKeys.length > 1 ? <Legend /> : null}\n {seriesKeys.map((k, i) => (\n <Bar\n key={k}\n dataKey={k}\n stackId={type === \"STACKED_BAR\" ? \"stack\" : undefined}\n fill={color(i)}\n />\n ))}\n </BarChart>\n </Frame>\n );\n\n case \"PIE\":\n case \"DONUT\": {\n const valueKey = seriesKeys[0] ?? \"value\";\n return (\n <Frame>\n <PieChart>\n <Tooltip />\n <Legend />\n <Pie\n data={data}\n dataKey={valueKey}\n nameKey={xKey}\n cx=\"50%\"\n cy=\"50%\"\n outerRadius={110}\n innerRadius={type === \"DONUT\" ? 60 : 0}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n label={(entry: any) => formatValue(entry?.name)}\n >\n {data.map((_, i) => (\n <Cell key={i} fill={color(i)} />\n ))}\n </Pie>\n </PieChart>\n </Frame>\n );\n }\n\n case \"SCATTER\": {\n const xNum = seriesKeys[0];\n const yNum = seriesKeys[1] ?? seriesKeys[0];\n return (\n <Frame>\n <ScatterChart>\n {grid()}\n <XAxis dataKey={xNum ?? xKey} type=\"number\" tick={AXIS_TICK} name={xNum ?? xKey} />\n <YAxis dataKey={yNum} type=\"number\" tick={AXIS_TICK} name={yNum} />\n <ZAxis range={[60, 60]} />\n <Tooltip cursor={{ strokeDasharray: \"3 3\" }} />\n <Scatter data={data} fill={color(0)} />\n </ScatterChart>\n </Frame>\n );\n }\n\n // HEATMAP (and anything Recharts can't express) → a readable data preview.\n default:\n return <PreviewTable block={block} data={data} />;\n }\n}\n\nconst AXIS_TICK = { fontSize: 12 } as const;\nconst grid = () => <CartesianGrid strokeDasharray=\"3 3\" stroke=\"#eee\" />;\n\nfunction Frame({ children }: { children: ReactElement }) {\n return (\n <div className=\"rk-chart\">\n <ResponsiveContainer width=\"100%\" height={HEIGHT}>\n {children}\n </ResponsiveContainer>\n </div>\n );\n}\n\nfunction PreviewTable({\n block,\n data,\n}: {\n block: ChartBlockType;\n data: Record<string, unknown>[];\n}) {\n const keys = Object.keys(data[0] ?? {});\n const preview = data.slice(0, 8);\n return (\n <div className=\"rk-chart-fallback\" data-chart-type={block.chartType}>\n <div className=\"rk-chart-badge\">\n {block.chartType} · rendered as a table (no chart mapping)\n </div>\n <table className=\"rk-table rk-chart-preview\">\n <thead>\n <tr>\n {keys.map((k) => (\n <th key={k} scope=\"col\">\n {k}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {preview.map((row, i) => (\n <tr key={i}>\n {keys.map((k) => (\n <td key={k}>{formatValue(row[k])}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n {data.length > preview.length ? (\n <p className=\"rk-chart-more\">+{data.length - preview.length} more rows</p>\n ) : null}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { formatValue } from './chunk-3FSZRQQU.js';
|
|
2
|
+
import { ScatterChart, XAxis, YAxis, ZAxis, Tooltip, Scatter, PieChart, Legend, Pie, Cell, BarChart, Bar, AreaChart, Area, LineChart, Line, CartesianGrid, ResponsiveContainer } from 'recharts';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
var PALETTE = [
|
|
6
|
+
"#2563eb",
|
|
7
|
+
"#16a34a",
|
|
8
|
+
"#d97706",
|
|
9
|
+
"#dc2626",
|
|
10
|
+
"#7c3aed",
|
|
11
|
+
"#0891b2",
|
|
12
|
+
"#db2777",
|
|
13
|
+
"#65a30d"
|
|
14
|
+
];
|
|
15
|
+
function inferShape(data) {
|
|
16
|
+
const first = data[0] ?? {};
|
|
17
|
+
const keys = Object.keys(first);
|
|
18
|
+
const isNumericCol = (k) => data.some((row) => typeof row[k] === "number");
|
|
19
|
+
const xKey = keys.find((k) => !isNumericCol(k)) ?? keys[0] ?? "x";
|
|
20
|
+
const seriesKeys = keys.filter((k) => k !== xKey && isNumericCol(k));
|
|
21
|
+
return {
|
|
22
|
+
xKey,
|
|
23
|
+
seriesKeys: seriesKeys.length ? seriesKeys : keys.filter((k) => k !== xKey)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
var HEIGHT = 300;
|
|
27
|
+
var color = (i) => PALETTE[i % PALETTE.length];
|
|
28
|
+
function ChartRenderer({ block }) {
|
|
29
|
+
const data = Array.isArray(block.data) ? block.data : [];
|
|
30
|
+
if (data.length === 0) return /* @__PURE__ */ jsx("p", { className: "rk-empty", children: "No chart data." });
|
|
31
|
+
const { xKey, seriesKeys } = inferShape(data);
|
|
32
|
+
const type = block.chartType;
|
|
33
|
+
switch (type) {
|
|
34
|
+
case "LINE":
|
|
35
|
+
return /* @__PURE__ */ jsx(Frame, { children: /* @__PURE__ */ jsxs(LineChart, { data, children: [
|
|
36
|
+
grid(),
|
|
37
|
+
/* @__PURE__ */ jsx(XAxis, { dataKey: xKey, tick: AXIS_TICK }),
|
|
38
|
+
/* @__PURE__ */ jsx(YAxis, { tick: AXIS_TICK }),
|
|
39
|
+
/* @__PURE__ */ jsx(Tooltip, {}),
|
|
40
|
+
seriesKeys.length > 1 ? /* @__PURE__ */ jsx(Legend, {}) : null,
|
|
41
|
+
seriesKeys.map((k, i) => /* @__PURE__ */ jsx(Line, { type: "monotone", dataKey: k, stroke: color(i), strokeWidth: 2, dot: false }, k))
|
|
42
|
+
] }) });
|
|
43
|
+
case "AREA":
|
|
44
|
+
case "STACKED_AREA":
|
|
45
|
+
return /* @__PURE__ */ jsx(Frame, { children: /* @__PURE__ */ jsxs(AreaChart, { data, children: [
|
|
46
|
+
grid(),
|
|
47
|
+
/* @__PURE__ */ jsx(XAxis, { dataKey: xKey, tick: AXIS_TICK }),
|
|
48
|
+
/* @__PURE__ */ jsx(YAxis, { tick: AXIS_TICK }),
|
|
49
|
+
/* @__PURE__ */ jsx(Tooltip, {}),
|
|
50
|
+
seriesKeys.length > 1 ? /* @__PURE__ */ jsx(Legend, {}) : null,
|
|
51
|
+
seriesKeys.map((k, i) => /* @__PURE__ */ jsx(
|
|
52
|
+
Area,
|
|
53
|
+
{
|
|
54
|
+
type: "monotone",
|
|
55
|
+
dataKey: k,
|
|
56
|
+
stackId: type === "STACKED_AREA" ? "stack" : void 0,
|
|
57
|
+
stroke: color(i),
|
|
58
|
+
fill: color(i),
|
|
59
|
+
fillOpacity: 0.25
|
|
60
|
+
},
|
|
61
|
+
k
|
|
62
|
+
))
|
|
63
|
+
] }) });
|
|
64
|
+
case "BAR":
|
|
65
|
+
case "STACKED_BAR":
|
|
66
|
+
return /* @__PURE__ */ jsx(Frame, { children: /* @__PURE__ */ jsxs(BarChart, { data, children: [
|
|
67
|
+
grid(),
|
|
68
|
+
/* @__PURE__ */ jsx(XAxis, { dataKey: xKey, tick: AXIS_TICK }),
|
|
69
|
+
/* @__PURE__ */ jsx(YAxis, { tick: AXIS_TICK }),
|
|
70
|
+
/* @__PURE__ */ jsx(Tooltip, {}),
|
|
71
|
+
seriesKeys.length > 1 ? /* @__PURE__ */ jsx(Legend, {}) : null,
|
|
72
|
+
seriesKeys.map((k, i) => /* @__PURE__ */ jsx(
|
|
73
|
+
Bar,
|
|
74
|
+
{
|
|
75
|
+
dataKey: k,
|
|
76
|
+
stackId: type === "STACKED_BAR" ? "stack" : void 0,
|
|
77
|
+
fill: color(i)
|
|
78
|
+
},
|
|
79
|
+
k
|
|
80
|
+
))
|
|
81
|
+
] }) });
|
|
82
|
+
case "PIE":
|
|
83
|
+
case "DONUT": {
|
|
84
|
+
const valueKey = seriesKeys[0] ?? "value";
|
|
85
|
+
return /* @__PURE__ */ jsx(Frame, { children: /* @__PURE__ */ jsxs(PieChart, { children: [
|
|
86
|
+
/* @__PURE__ */ jsx(Tooltip, {}),
|
|
87
|
+
/* @__PURE__ */ jsx(Legend, {}),
|
|
88
|
+
/* @__PURE__ */ jsx(
|
|
89
|
+
Pie,
|
|
90
|
+
{
|
|
91
|
+
data,
|
|
92
|
+
dataKey: valueKey,
|
|
93
|
+
nameKey: xKey,
|
|
94
|
+
cx: "50%",
|
|
95
|
+
cy: "50%",
|
|
96
|
+
outerRadius: 110,
|
|
97
|
+
innerRadius: type === "DONUT" ? 60 : 0,
|
|
98
|
+
label: (entry) => formatValue(entry?.name),
|
|
99
|
+
children: data.map((_, i) => /* @__PURE__ */ jsx(Cell, { fill: color(i) }, i))
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
] }) });
|
|
103
|
+
}
|
|
104
|
+
case "SCATTER": {
|
|
105
|
+
const xNum = seriesKeys[0];
|
|
106
|
+
const yNum = seriesKeys[1] ?? seriesKeys[0];
|
|
107
|
+
return /* @__PURE__ */ jsx(Frame, { children: /* @__PURE__ */ jsxs(ScatterChart, { children: [
|
|
108
|
+
grid(),
|
|
109
|
+
/* @__PURE__ */ jsx(XAxis, { dataKey: xNum ?? xKey, type: "number", tick: AXIS_TICK, name: xNum ?? xKey }),
|
|
110
|
+
/* @__PURE__ */ jsx(YAxis, { dataKey: yNum, type: "number", tick: AXIS_TICK, name: yNum }),
|
|
111
|
+
/* @__PURE__ */ jsx(ZAxis, { range: [60, 60] }),
|
|
112
|
+
/* @__PURE__ */ jsx(Tooltip, { cursor: { strokeDasharray: "3 3" } }),
|
|
113
|
+
/* @__PURE__ */ jsx(Scatter, { data, fill: color(0) })
|
|
114
|
+
] }) });
|
|
115
|
+
}
|
|
116
|
+
// HEATMAP (and anything Recharts can't express) → a readable data preview.
|
|
117
|
+
default:
|
|
118
|
+
return /* @__PURE__ */ jsx(PreviewTable, { block, data });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
var AXIS_TICK = { fontSize: 12 };
|
|
122
|
+
var grid = () => /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", stroke: "#eee" });
|
|
123
|
+
function Frame({ children }) {
|
|
124
|
+
return /* @__PURE__ */ jsx("div", { className: "rk-chart", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: HEIGHT, children }) });
|
|
125
|
+
}
|
|
126
|
+
function PreviewTable({
|
|
127
|
+
block,
|
|
128
|
+
data
|
|
129
|
+
}) {
|
|
130
|
+
const keys = Object.keys(data[0] ?? {});
|
|
131
|
+
const preview = data.slice(0, 8);
|
|
132
|
+
return /* @__PURE__ */ jsxs("div", { className: "rk-chart-fallback", "data-chart-type": block.chartType, children: [
|
|
133
|
+
/* @__PURE__ */ jsxs("div", { className: "rk-chart-badge", children: [
|
|
134
|
+
block.chartType,
|
|
135
|
+
" \xB7 rendered as a table (no chart mapping)"
|
|
136
|
+
] }),
|
|
137
|
+
/* @__PURE__ */ jsxs("table", { className: "rk-table rk-chart-preview", children: [
|
|
138
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: keys.map((k) => /* @__PURE__ */ jsx("th", { scope: "col", children: k }, k)) }) }),
|
|
139
|
+
/* @__PURE__ */ jsx("tbody", { children: preview.map((row, i) => /* @__PURE__ */ jsx("tr", { children: keys.map((k) => /* @__PURE__ */ jsx("td", { children: formatValue(row[k]) }, k)) }, i)) })
|
|
140
|
+
] }),
|
|
141
|
+
data.length > preview.length ? /* @__PURE__ */ jsxs("p", { className: "rk-chart-more", children: [
|
|
142
|
+
"+",
|
|
143
|
+
data.length - preview.length,
|
|
144
|
+
" more rows"
|
|
145
|
+
] }) : null
|
|
146
|
+
] });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export { ChartRenderer as default };
|
|
150
|
+
//# sourceMappingURL=ChartRenderer-URPZESVN.js.map
|
|
151
|
+
//# sourceMappingURL=ChartRenderer-URPZESVN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/blocks/ChartRenderer.tsx"],"names":[],"mappings":"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","file":"ChartRenderer-URPZESVN.js","sourcesContent":["import type { ReactElement } from \"react\";\nimport {\n ResponsiveContainer,\n LineChart,\n Line,\n BarChart,\n Bar,\n AreaChart,\n Area,\n PieChart,\n Pie,\n Cell,\n ScatterChart,\n Scatter,\n XAxis,\n YAxis,\n ZAxis,\n CartesianGrid,\n Tooltip,\n Legend,\n} from \"recharts\";\nimport type { ChartBlock as ChartBlockType } from \"@responsekit/schema\";\nimport { formatValue } from \"./util.js\";\n\n/**\n * Real chart adapter, loaded lazily (see `ChartBlock`) so Recharts lands in its own\n * chunk and never weighs down the main bundle. This is the single place the SDK is\n * coupled to a charting library — swap it for visx/nivo/etc. without touching anything\n * else.\n *\n * The backend sends generic rows (e.g. `{ status: \"ONGOING\", count: 10 }`), so we infer\n * the category/x key (first non-numeric column) and the numeric series from the data.\n */\n\nconst PALETTE = [\n \"#2563eb\",\n \"#16a34a\",\n \"#d97706\",\n \"#dc2626\",\n \"#7c3aed\",\n \"#0891b2\",\n \"#db2777\",\n \"#65a30d\",\n];\n\ninterface Inferred {\n xKey: string;\n seriesKeys: string[];\n}\n\nfunction inferShape(data: Record<string, unknown>[]): Inferred {\n const first = data[0] ?? {};\n const keys = Object.keys(first);\n const isNumericCol = (k: string) => data.some((row) => typeof row[k] === \"number\");\n const xKey = keys.find((k) => !isNumericCol(k)) ?? keys[0] ?? \"x\";\n const seriesKeys = keys.filter((k) => k !== xKey && isNumericCol(k));\n // Fallback: if nothing looked numeric, treat every non-x column as a series.\n return {\n xKey,\n seriesKeys: seriesKeys.length ? seriesKeys : keys.filter((k) => k !== xKey),\n };\n}\n\nconst HEIGHT = 300;\nconst color = (i: number) => PALETTE[i % PALETTE.length];\n\nexport default function ChartRenderer({ block }: { block: ChartBlockType }) {\n const data = Array.isArray(block.data) ? (block.data as Record<string, unknown>[]) : [];\n if (data.length === 0) return <p className=\"rk-empty\">No chart data.</p>;\n\n const { xKey, seriesKeys } = inferShape(data);\n const type = block.chartType;\n\n switch (type) {\n case \"LINE\":\n return (\n <Frame>\n <LineChart data={data}>\n {grid()}\n <XAxis dataKey={xKey} tick={AXIS_TICK} />\n <YAxis tick={AXIS_TICK} />\n <Tooltip />\n {seriesKeys.length > 1 ? <Legend /> : null}\n {seriesKeys.map((k, i) => (\n <Line key={k} type=\"monotone\" dataKey={k} stroke={color(i)} strokeWidth={2} dot={false} />\n ))}\n </LineChart>\n </Frame>\n );\n\n case \"AREA\":\n case \"STACKED_AREA\":\n return (\n <Frame>\n <AreaChart data={data}>\n {grid()}\n <XAxis dataKey={xKey} tick={AXIS_TICK} />\n <YAxis tick={AXIS_TICK} />\n <Tooltip />\n {seriesKeys.length > 1 ? <Legend /> : null}\n {seriesKeys.map((k, i) => (\n <Area\n key={k}\n type=\"monotone\"\n dataKey={k}\n stackId={type === \"STACKED_AREA\" ? \"stack\" : undefined}\n stroke={color(i)}\n fill={color(i)}\n fillOpacity={0.25}\n />\n ))}\n </AreaChart>\n </Frame>\n );\n\n case \"BAR\":\n case \"STACKED_BAR\":\n return (\n <Frame>\n <BarChart data={data}>\n {grid()}\n <XAxis dataKey={xKey} tick={AXIS_TICK} />\n <YAxis tick={AXIS_TICK} />\n <Tooltip />\n {seriesKeys.length > 1 ? <Legend /> : null}\n {seriesKeys.map((k, i) => (\n <Bar\n key={k}\n dataKey={k}\n stackId={type === \"STACKED_BAR\" ? \"stack\" : undefined}\n fill={color(i)}\n />\n ))}\n </BarChart>\n </Frame>\n );\n\n case \"PIE\":\n case \"DONUT\": {\n const valueKey = seriesKeys[0] ?? \"value\";\n return (\n <Frame>\n <PieChart>\n <Tooltip />\n <Legend />\n <Pie\n data={data}\n dataKey={valueKey}\n nameKey={xKey}\n cx=\"50%\"\n cy=\"50%\"\n outerRadius={110}\n innerRadius={type === \"DONUT\" ? 60 : 0}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n label={(entry: any) => formatValue(entry?.name)}\n >\n {data.map((_, i) => (\n <Cell key={i} fill={color(i)} />\n ))}\n </Pie>\n </PieChart>\n </Frame>\n );\n }\n\n case \"SCATTER\": {\n const xNum = seriesKeys[0];\n const yNum = seriesKeys[1] ?? seriesKeys[0];\n return (\n <Frame>\n <ScatterChart>\n {grid()}\n <XAxis dataKey={xNum ?? xKey} type=\"number\" tick={AXIS_TICK} name={xNum ?? xKey} />\n <YAxis dataKey={yNum} type=\"number\" tick={AXIS_TICK} name={yNum} />\n <ZAxis range={[60, 60]} />\n <Tooltip cursor={{ strokeDasharray: \"3 3\" }} />\n <Scatter data={data} fill={color(0)} />\n </ScatterChart>\n </Frame>\n );\n }\n\n // HEATMAP (and anything Recharts can't express) → a readable data preview.\n default:\n return <PreviewTable block={block} data={data} />;\n }\n}\n\nconst AXIS_TICK = { fontSize: 12 } as const;\nconst grid = () => <CartesianGrid strokeDasharray=\"3 3\" stroke=\"#eee\" />;\n\nfunction Frame({ children }: { children: ReactElement }) {\n return (\n <div className=\"rk-chart\">\n <ResponsiveContainer width=\"100%\" height={HEIGHT}>\n {children}\n </ResponsiveContainer>\n </div>\n );\n}\n\nfunction PreviewTable({\n block,\n data,\n}: {\n block: ChartBlockType;\n data: Record<string, unknown>[];\n}) {\n const keys = Object.keys(data[0] ?? {});\n const preview = data.slice(0, 8);\n return (\n <div className=\"rk-chart-fallback\" data-chart-type={block.chartType}>\n <div className=\"rk-chart-badge\">\n {block.chartType} · rendered as a table (no chart mapping)\n </div>\n <table className=\"rk-table rk-chart-preview\">\n <thead>\n <tr>\n {keys.map((k) => (\n <th key={k} scope=\"col\">\n {k}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {preview.map((row, i) => (\n <tr key={i}>\n {keys.map((k) => (\n <td key={k}>{formatValue(row[k])}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n {data.length > preview.length ? (\n <p className=\"rk-chart-more\">+{data.length - preview.length} more rows</p>\n ) : null}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/blocks/util.ts
|
|
8
|
+
function formatValue(value) {
|
|
9
|
+
if (value === null || value === void 0) return "";
|
|
10
|
+
if (typeof value === "string") return value;
|
|
11
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
12
|
+
try {
|
|
13
|
+
return JSON.stringify(value);
|
|
14
|
+
} catch {
|
|
15
|
+
return String(value);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function isDev() {
|
|
19
|
+
const g = globalThis;
|
|
20
|
+
const env = g.process?.env?.NODE_ENV;
|
|
21
|
+
return env !== void 0 && env !== "production";
|
|
22
|
+
}
|
|
23
|
+
function rowsToCsv(columns, rows) {
|
|
24
|
+
const escape = (s) => `"${s.replace(/"/g, '""')}"`;
|
|
25
|
+
const header = columns.map((c) => escape(c.label)).join(",");
|
|
26
|
+
const body = rows.map((row) => columns.map((c) => escape(formatValue(row[c.key]))).join(",")).join("\n");
|
|
27
|
+
return `${header}
|
|
28
|
+
${body}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { __export, formatValue, isDev, rowsToCsv };
|
|
32
|
+
//# sourceMappingURL=chunk-3FSZRQQU.js.map
|
|
33
|
+
//# sourceMappingURL=chunk-3FSZRQQU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/blocks/util.ts"],"names":[],"mappings":";;;;;;;AAMO,SAAS,YAAY,KAAA,EAAwB;AAClD,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW,OAAO,EAAA;AAClD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,OAAO,UAAU,SAAA,EAAW,OAAO,OAAO,KAAK,CAAA;AAChF,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAAA,EAC7B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AACF;AAGO,SAAS,KAAA,GAAiB;AAG/B,EAAA,MAAM,CAAA,GAAI,UAAA;AACV,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,OAAA,EAAS,GAAA,EAAK,QAAA;AAC5B,EAAA,OAAO,GAAA,KAAQ,UAAa,GAAA,KAAQ,YAAA;AACtC;AAGO,SAAS,SAAA,CACd,SACA,IAAA,EACQ;AACR,EAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAc,CAAA,CAAA,EAAI,EAAE,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAA;AACvD,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,MAAA,CAAO,CAAA,CAAE,KAAK,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAC3D,EAAA,MAAM,IAAA,GAAO,KACV,GAAA,CAAI,CAAC,QAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,MAAA,CAAO,WAAA,CAAY,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,CAAC,CAAA,CAAE,KAAK,GAAG,CAAC,CAAA,CAC1E,IAAA,CAAK,IAAI,CAAA;AACZ,EAAA,OAAO,GAAG,MAAM;AAAA,EAAK,IAAI,CAAA,CAAA;AAC3B","file":"chunk-3FSZRQQU.js","sourcesContent":["/**\n * Value helpers for rendering untrusted data. Everything here returns a plain string\n * that React escapes on render — no HTML is ever produced.\n */\n\n/** Render an arbitrary cell/KPI value as display text. Never throws. */\nexport function formatValue(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/** True when running in a dev build (used to optionally surface raw JSON in fallbacks). */\nexport function isDev(): boolean {\n // Read NODE_ENV off globalThis so we don't depend on Node's `process` typings in a\n // browser-targeted package. Bundlers (Vite/webpack/esbuild) inline this at build time.\n const g = globalThis as { process?: { env?: Record<string, string | undefined> } };\n const env = g.process?.env?.NODE_ENV;\n return env !== undefined && env !== \"production\";\n}\n\n/** Convert table rows to CSV for a DOWNLOAD action. Pure data, no HTML. */\nexport function rowsToCsv(\n columns: { key: string; label: string }[],\n rows: Record<string, unknown>[],\n): string {\n const escape = (s: string) => `\"${s.replace(/\"/g, '\"\"')}\"`;\n const header = columns.map((c) => escape(c.label)).join(\",\");\n const body = rows\n .map((row) => columns.map((c) => escape(formatValue(row[c.key]))).join(\",\"))\n .join(\"\\n\");\n return `${header}\\n${body}`;\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __export = (target, all) => {
|
|
5
|
+
for (var name in all)
|
|
6
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// src/blocks/util.ts
|
|
10
|
+
function formatValue(value) {
|
|
11
|
+
if (value === null || value === void 0) return "";
|
|
12
|
+
if (typeof value === "string") return value;
|
|
13
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
14
|
+
try {
|
|
15
|
+
return JSON.stringify(value);
|
|
16
|
+
} catch {
|
|
17
|
+
return String(value);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function isDev() {
|
|
21
|
+
const g = globalThis;
|
|
22
|
+
const env = g.process?.env?.NODE_ENV;
|
|
23
|
+
return env !== void 0 && env !== "production";
|
|
24
|
+
}
|
|
25
|
+
function rowsToCsv(columns, rows) {
|
|
26
|
+
const escape = (s) => `"${s.replace(/"/g, '""')}"`;
|
|
27
|
+
const header = columns.map((c) => escape(c.label)).join(",");
|
|
28
|
+
const body = rows.map((row) => columns.map((c) => escape(formatValue(row[c.key]))).join(",")).join("\n");
|
|
29
|
+
return `${header}
|
|
30
|
+
${body}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
exports.__export = __export;
|
|
34
|
+
exports.formatValue = formatValue;
|
|
35
|
+
exports.isDev = isDev;
|
|
36
|
+
exports.rowsToCsv = rowsToCsv;
|
|
37
|
+
//# sourceMappingURL=chunk-D4WIPDH3.cjs.map
|
|
38
|
+
//# sourceMappingURL=chunk-D4WIPDH3.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/blocks/util.ts"],"names":[],"mappings":";;;;;;;;;AAMO,SAAS,YAAY,KAAA,EAAwB;AAClD,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW,OAAO,EAAA;AAClD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,OAAO,UAAU,SAAA,EAAW,OAAO,OAAO,KAAK,CAAA;AAChF,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAAA,EAC7B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AACF;AAGO,SAAS,KAAA,GAAiB;AAG/B,EAAA,MAAM,CAAA,GAAI,UAAA;AACV,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,OAAA,EAAS,GAAA,EAAK,QAAA;AAC5B,EAAA,OAAO,GAAA,KAAQ,UAAa,GAAA,KAAQ,YAAA;AACtC;AAGO,SAAS,SAAA,CACd,SACA,IAAA,EACQ;AACR,EAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAc,CAAA,CAAA,EAAI,EAAE,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAA;AACvD,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,MAAA,CAAO,CAAA,CAAE,KAAK,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAC3D,EAAA,MAAM,IAAA,GAAO,KACV,GAAA,CAAI,CAAC,QAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,MAAA,CAAO,WAAA,CAAY,IAAI,CAAA,CAAE,GAAG,CAAC,CAAC,CAAC,CAAA,CAAE,KAAK,GAAG,CAAC,CAAA,CAC1E,IAAA,CAAK,IAAI,CAAA;AACZ,EAAA,OAAO,GAAG,MAAM;AAAA,EAAK,IAAI,CAAA,CAAA;AAC3B","file":"chunk-D4WIPDH3.cjs","sourcesContent":["/**\n * Value helpers for rendering untrusted data. Everything here returns a plain string\n * that React escapes on render — no HTML is ever produced.\n */\n\n/** Render an arbitrary cell/KPI value as display text. Never throws. */\nexport function formatValue(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n/** True when running in a dev build (used to optionally surface raw JSON in fallbacks). */\nexport function isDev(): boolean {\n // Read NODE_ENV off globalThis so we don't depend on Node's `process` typings in a\n // browser-targeted package. Bundlers (Vite/webpack/esbuild) inline this at build time.\n const g = globalThis as { process?: { env?: Record<string, string | undefined> } };\n const env = g.process?.env?.NODE_ENV;\n return env !== undefined && env !== \"production\";\n}\n\n/** Convert table rows to CSV for a DOWNLOAD action. Pure data, no HTML. */\nexport function rowsToCsv(\n columns: { key: string; label: string }[],\n rows: Record<string, unknown>[],\n): string {\n const escape = (s: string) => `\"${s.replace(/\"/g, '\"\"')}\"`;\n const header = columns.map((c) => escape(c.label)).join(\",\");\n const body = rows\n .map((row) => columns.map((c) => escape(formatValue(row[c.key]))).join(\",\"))\n .join(\"\\n\");\n return `${header}\\n${body}`;\n}\n"]}
|