@retrivora-ai/rag-engine 1.2.9 → 1.3.1
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/dist/index.js +44 -27
- package/dist/index.mjs +44 -27
- package/package.json +1 -1
- package/src/components/DynamicChart.tsx +36 -15
- package/src/components/MessageBubble.tsx +22 -27
package/dist/index.js
CHANGED
|
@@ -229,18 +229,35 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
|
|
|
229
229
|
const firstItem = data[0];
|
|
230
230
|
const allKeys = Object.keys(firstItem);
|
|
231
231
|
const resolvedXKey = config.xAxisKey && firstItem[config.xAxisKey] !== void 0 ? config.xAxisKey : allKeys.find((k) => k.toLowerCase() === "name" || k.toLowerCase() === "label" || k.toLowerCase() === "category") || allKeys.find((k) => typeof firstItem[k] === "string") || allKeys[0];
|
|
232
|
-
const resolvedDataKeys = config.dataKeys && config.dataKeys.every((k) =>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
232
|
+
const resolvedDataKeys = config.dataKeys && config.dataKeys.every((k) => {
|
|
233
|
+
const val = firstItem[k];
|
|
234
|
+
return val !== void 0 && typeof val !== "object";
|
|
235
|
+
}) ? config.dataKeys : allKeys.filter((k) => {
|
|
236
|
+
const val = firstItem[k];
|
|
237
|
+
return k !== resolvedXKey && (typeof val === "number" || k.toLowerCase() === "value" || k.toLowerCase() === "count");
|
|
238
|
+
}).slice(0, 5);
|
|
239
|
+
const finalXKey = String(resolvedXKey);
|
|
240
|
+
const finalDataKeys = resolvedDataKeys.map(String).filter((k) => k !== "undefined");
|
|
241
|
+
const sanitizedData = import_react4.default.useMemo(() => {
|
|
242
|
+
return data.map((item) => {
|
|
243
|
+
const newItem = {};
|
|
244
|
+
Object.keys(item).forEach((k) => {
|
|
245
|
+
const val = item[k];
|
|
246
|
+
if (typeof val !== "object" || val === null) {
|
|
247
|
+
newItem[k] = val;
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
return newItem;
|
|
251
|
+
});
|
|
252
|
+
}, [data]);
|
|
236
253
|
if (type === "pie") {
|
|
237
|
-
const pieDataKey =
|
|
254
|
+
const pieDataKey = finalDataKeys[0] || "value";
|
|
238
255
|
return /* @__PURE__ */ import_react4.default.createElement("div", { className: "w-full h-72 min-h-[280px] mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.ResponsiveContainer, { width: "99%", height: "100%" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.PieChart, null, /* @__PURE__ */ import_react4.default.createElement(
|
|
239
256
|
import_recharts.Pie,
|
|
240
257
|
{
|
|
241
|
-
data,
|
|
258
|
+
data: sanitizedData,
|
|
242
259
|
dataKey: pieDataKey,
|
|
243
|
-
nameKey:
|
|
260
|
+
nameKey: finalXKey,
|
|
244
261
|
cx: "50%",
|
|
245
262
|
cy: "50%",
|
|
246
263
|
outerRadius: 80,
|
|
@@ -254,13 +271,13 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
|
|
|
254
271
|
}
|
|
255
272
|
), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, null))));
|
|
256
273
|
}
|
|
257
|
-
return /* @__PURE__ */ import_react4.default.createElement("div", { className: "w-full h-72 min-h-[280px] mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.ResponsiveContainer, { width: "99%", height: "100%" }, type === "bar" ? /* @__PURE__ */ import_react4.default.createElement(import_recharts.BarChart, { data, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.XAxis, { dataKey:
|
|
274
|
+
return /* @__PURE__ */ import_react4.default.createElement("div", { className: "w-full h-72 min-h-[280px] mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.ResponsiveContainer, { width: "99%", height: "100%" }, type === "bar" ? /* @__PURE__ */ import_react4.default.createElement(import_recharts.BarChart, { data: sanitizedData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.XAxis, { dataKey: finalXKey, tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.YAxis, { tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react4.default.createElement(
|
|
258
275
|
import_recharts.Tooltip,
|
|
259
276
|
{
|
|
260
277
|
contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" },
|
|
261
278
|
cursor: { fill: "#f1f5f9" }
|
|
262
279
|
}
|
|
263
|
-
), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }),
|
|
280
|
+
), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }), finalDataKeys.map((key, index) => /* @__PURE__ */ import_react4.default.createElement(
|
|
264
281
|
import_recharts.Bar,
|
|
265
282
|
{
|
|
266
283
|
key,
|
|
@@ -269,12 +286,12 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
|
|
|
269
286
|
radius: [4, 4, 0, 0],
|
|
270
287
|
barSize: Math.max(20, 60 / data.length)
|
|
271
288
|
}
|
|
272
|
-
))) : /* @__PURE__ */ import_react4.default.createElement(import_recharts.LineChart, { data, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.XAxis, { dataKey:
|
|
289
|
+
))) : /* @__PURE__ */ import_react4.default.createElement(import_recharts.LineChart, { data: sanitizedData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.XAxis, { dataKey: finalXKey, tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.YAxis, { tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react4.default.createElement(
|
|
273
290
|
import_recharts.Tooltip,
|
|
274
291
|
{
|
|
275
292
|
contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" }
|
|
276
293
|
}
|
|
277
|
-
), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }),
|
|
294
|
+
), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }), finalDataKeys.map((key, index) => /* @__PURE__ */ import_react4.default.createElement(
|
|
278
295
|
import_recharts.Line,
|
|
279
296
|
{
|
|
280
297
|
key,
|
|
@@ -397,30 +414,30 @@ function MessageBubble({
|
|
|
397
414
|
return /* @__PURE__ */ import_react5.default.createElement("thead", __spreadValues({ className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, props));
|
|
398
415
|
},
|
|
399
416
|
th: (_c) => {
|
|
400
|
-
var props = __objRest(
|
|
401
|
-
return /* @__PURE__ */ import_react5.default.createElement("th", __spreadValues({ className: "p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl" }, props));
|
|
417
|
+
var _d = _c, { children } = _d, props = __objRest(_d, ["children"]);
|
|
418
|
+
return /* @__PURE__ */ import_react5.default.createElement("th", __spreadValues({ className: "p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl" }, props), typeof children === "object" && children !== null && !Array.isArray(children) && !children.$$typeof ? JSON.stringify(children) : children);
|
|
402
419
|
},
|
|
403
|
-
td: (
|
|
404
|
-
var props = __objRest(
|
|
405
|
-
return /* @__PURE__ */ import_react5.default.createElement("td", __spreadValues({ className: "p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70" }, props));
|
|
420
|
+
td: (_e) => {
|
|
421
|
+
var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
|
|
422
|
+
return /* @__PURE__ */ import_react5.default.createElement("td", __spreadValues({ className: "p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70" }, props), typeof children === "object" && children !== null && !Array.isArray(children) && !children.$$typeof ? JSON.stringify(children) : children);
|
|
406
423
|
},
|
|
407
|
-
code(
|
|
408
|
-
var
|
|
424
|
+
code(_g) {
|
|
425
|
+
var _h = _g, { inline, className, children } = _h, props = __objRest(_h, ["inline", "className", "children"]);
|
|
409
426
|
const match = /language-(\w+)/.exec(className || "");
|
|
410
427
|
const isChart = match && match[1] === "chart";
|
|
411
428
|
if (!inline && isChart) {
|
|
412
|
-
const rawContent = String(children).trim();
|
|
429
|
+
const rawContent = String(children || "").trim();
|
|
430
|
+
if (!rawContent || rawContent === "undefined") {
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
413
433
|
const sanitizeJson = (json) => {
|
|
414
434
|
return json.replace(/:\s*(\d+(\.\d+)?)\s*([\+\-\*\/])\s*(\d+(\.\d+)?)/g, (_, n1, __, op, n2) => {
|
|
435
|
+
var _a;
|
|
415
436
|
const v1 = parseFloat(n1);
|
|
416
437
|
const v2 = parseFloat(n2);
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (op === "*") res = v1 * v2;
|
|
421
|
-
if (op === "/") res = v1 / v2;
|
|
422
|
-
return `: ${res}`;
|
|
423
|
-
}).replace(/([{,])\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1 "$2":').replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, '"$1"').replace(/,\s*([\]}])/g, "$1").replace(/}\s*{/g, "},{").replace(/]\s*\[/g, "],[").replace(/\/\/.*$/gm, "").replace(/,\s*""\s*,/g, ",").replace(/\{\s*""\s*,/g, "{").replace(/,\s*""\s*\}/g, "}");
|
|
438
|
+
const ops = { "+": v1 + v2, "-": v1 - v2, "*": v1 * v2, "/": v1 / v2 };
|
|
439
|
+
return `: ${(_a = ops[op]) != null ? _a : v1}`;
|
|
440
|
+
}).replace(/([{,])\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1 "$2":').replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, '"$1"').replace(/,\s*([\]}])/g, "$1").replace(/}\s*{/g, "},{").replace(/]\s*\[/g, "],[").replace(/\/\/.*$/gm, "").replace(/([{,])\s*""\s*([,}])/g, "$1$2");
|
|
424
441
|
};
|
|
425
442
|
try {
|
|
426
443
|
const sanitized = sanitizeJson(rawContent);
|
|
@@ -438,7 +455,7 @@ function MessageBubble({
|
|
|
438
455
|
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "p-4 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-sm border border-red-100 dark:border-red-900/30" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "font-medium mb-1" }, "Failed to render chart"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "opacity-70 text-xs" }, "The generated configuration is invalid. Check console for details."));
|
|
439
456
|
}
|
|
440
457
|
}
|
|
441
|
-
return /* @__PURE__ */ import_react5.default.createElement("code", __spreadValues({ className }, props), children);
|
|
458
|
+
return /* @__PURE__ */ import_react5.default.createElement("code", __spreadValues({ className }, props), typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children));
|
|
442
459
|
}
|
|
443
460
|
}
|
|
444
461
|
},
|
package/dist/index.mjs
CHANGED
|
@@ -192,18 +192,35 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
|
|
|
192
192
|
const firstItem = data[0];
|
|
193
193
|
const allKeys = Object.keys(firstItem);
|
|
194
194
|
const resolvedXKey = config.xAxisKey && firstItem[config.xAxisKey] !== void 0 ? config.xAxisKey : allKeys.find((k) => k.toLowerCase() === "name" || k.toLowerCase() === "label" || k.toLowerCase() === "category") || allKeys.find((k) => typeof firstItem[k] === "string") || allKeys[0];
|
|
195
|
-
const resolvedDataKeys = config.dataKeys && config.dataKeys.every((k) =>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
195
|
+
const resolvedDataKeys = config.dataKeys && config.dataKeys.every((k) => {
|
|
196
|
+
const val = firstItem[k];
|
|
197
|
+
return val !== void 0 && typeof val !== "object";
|
|
198
|
+
}) ? config.dataKeys : allKeys.filter((k) => {
|
|
199
|
+
const val = firstItem[k];
|
|
200
|
+
return k !== resolvedXKey && (typeof val === "number" || k.toLowerCase() === "value" || k.toLowerCase() === "count");
|
|
201
|
+
}).slice(0, 5);
|
|
202
|
+
const finalXKey = String(resolvedXKey);
|
|
203
|
+
const finalDataKeys = resolvedDataKeys.map(String).filter((k) => k !== "undefined");
|
|
204
|
+
const sanitizedData = React4.useMemo(() => {
|
|
205
|
+
return data.map((item) => {
|
|
206
|
+
const newItem = {};
|
|
207
|
+
Object.keys(item).forEach((k) => {
|
|
208
|
+
const val = item[k];
|
|
209
|
+
if (typeof val !== "object" || val === null) {
|
|
210
|
+
newItem[k] = val;
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
return newItem;
|
|
214
|
+
});
|
|
215
|
+
}, [data]);
|
|
199
216
|
if (type === "pie") {
|
|
200
|
-
const pieDataKey =
|
|
217
|
+
const pieDataKey = finalDataKeys[0] || "value";
|
|
201
218
|
return /* @__PURE__ */ React4.createElement("div", { className: "w-full h-72 min-h-[280px] mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ React4.createElement(ResponsiveContainer, { width: "99%", height: "100%" }, /* @__PURE__ */ React4.createElement(PieChart, null, /* @__PURE__ */ React4.createElement(
|
|
202
219
|
Pie,
|
|
203
220
|
{
|
|
204
|
-
data,
|
|
221
|
+
data: sanitizedData,
|
|
205
222
|
dataKey: pieDataKey,
|
|
206
|
-
nameKey:
|
|
223
|
+
nameKey: finalXKey,
|
|
207
224
|
cx: "50%",
|
|
208
225
|
cy: "50%",
|
|
209
226
|
outerRadius: 80,
|
|
@@ -217,13 +234,13 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
|
|
|
217
234
|
}
|
|
218
235
|
), /* @__PURE__ */ React4.createElement(Legend, null))));
|
|
219
236
|
}
|
|
220
|
-
return /* @__PURE__ */ React4.createElement("div", { className: "w-full h-72 min-h-[280px] mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ React4.createElement(ResponsiveContainer, { width: "99%", height: "100%" }, type === "bar" ? /* @__PURE__ */ React4.createElement(BarChart, { data, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ React4.createElement(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React4.createElement(XAxis, { dataKey:
|
|
237
|
+
return /* @__PURE__ */ React4.createElement("div", { className: "w-full h-72 min-h-[280px] mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ React4.createElement(ResponsiveContainer, { width: "99%", height: "100%" }, type === "bar" ? /* @__PURE__ */ React4.createElement(BarChart, { data: sanitizedData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ React4.createElement(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React4.createElement(XAxis, { dataKey: finalXKey, tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }), /* @__PURE__ */ React4.createElement(YAxis, { tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ React4.createElement(
|
|
221
238
|
Tooltip,
|
|
222
239
|
{
|
|
223
240
|
contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" },
|
|
224
241
|
cursor: { fill: "#f1f5f9" }
|
|
225
242
|
}
|
|
226
|
-
), /* @__PURE__ */ React4.createElement(Legend, { wrapperStyle: { fontSize: 12 } }),
|
|
243
|
+
), /* @__PURE__ */ React4.createElement(Legend, { wrapperStyle: { fontSize: 12 } }), finalDataKeys.map((key, index) => /* @__PURE__ */ React4.createElement(
|
|
227
244
|
Bar,
|
|
228
245
|
{
|
|
229
246
|
key,
|
|
@@ -232,12 +249,12 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
|
|
|
232
249
|
radius: [4, 4, 0, 0],
|
|
233
250
|
barSize: Math.max(20, 60 / data.length)
|
|
234
251
|
}
|
|
235
|
-
))) : /* @__PURE__ */ React4.createElement(LineChart, { data, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ React4.createElement(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React4.createElement(XAxis, { dataKey:
|
|
252
|
+
))) : /* @__PURE__ */ React4.createElement(LineChart, { data: sanitizedData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ React4.createElement(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React4.createElement(XAxis, { dataKey: finalXKey, tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }), /* @__PURE__ */ React4.createElement(YAxis, { tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ React4.createElement(
|
|
236
253
|
Tooltip,
|
|
237
254
|
{
|
|
238
255
|
contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" }
|
|
239
256
|
}
|
|
240
|
-
), /* @__PURE__ */ React4.createElement(Legend, { wrapperStyle: { fontSize: 12 } }),
|
|
257
|
+
), /* @__PURE__ */ React4.createElement(Legend, { wrapperStyle: { fontSize: 12 } }), finalDataKeys.map((key, index) => /* @__PURE__ */ React4.createElement(
|
|
241
258
|
Line,
|
|
242
259
|
{
|
|
243
260
|
key,
|
|
@@ -360,30 +377,30 @@ function MessageBubble({
|
|
|
360
377
|
return /* @__PURE__ */ React5.createElement("thead", __spreadValues({ className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, props));
|
|
361
378
|
},
|
|
362
379
|
th: (_c) => {
|
|
363
|
-
var props = __objRest(
|
|
364
|
-
return /* @__PURE__ */ React5.createElement("th", __spreadValues({ className: "p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl" }, props));
|
|
380
|
+
var _d = _c, { children } = _d, props = __objRest(_d, ["children"]);
|
|
381
|
+
return /* @__PURE__ */ React5.createElement("th", __spreadValues({ className: "p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl" }, props), typeof children === "object" && children !== null && !Array.isArray(children) && !children.$$typeof ? JSON.stringify(children) : children);
|
|
365
382
|
},
|
|
366
|
-
td: (
|
|
367
|
-
var props = __objRest(
|
|
368
|
-
return /* @__PURE__ */ React5.createElement("td", __spreadValues({ className: "p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70" }, props));
|
|
383
|
+
td: (_e) => {
|
|
384
|
+
var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
|
|
385
|
+
return /* @__PURE__ */ React5.createElement("td", __spreadValues({ className: "p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70" }, props), typeof children === "object" && children !== null && !Array.isArray(children) && !children.$$typeof ? JSON.stringify(children) : children);
|
|
369
386
|
},
|
|
370
|
-
code(
|
|
371
|
-
var
|
|
387
|
+
code(_g) {
|
|
388
|
+
var _h = _g, { inline, className, children } = _h, props = __objRest(_h, ["inline", "className", "children"]);
|
|
372
389
|
const match = /language-(\w+)/.exec(className || "");
|
|
373
390
|
const isChart = match && match[1] === "chart";
|
|
374
391
|
if (!inline && isChart) {
|
|
375
|
-
const rawContent = String(children).trim();
|
|
392
|
+
const rawContent = String(children || "").trim();
|
|
393
|
+
if (!rawContent || rawContent === "undefined") {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
376
396
|
const sanitizeJson = (json) => {
|
|
377
397
|
return json.replace(/:\s*(\d+(\.\d+)?)\s*([\+\-\*\/])\s*(\d+(\.\d+)?)/g, (_, n1, __, op, n2) => {
|
|
398
|
+
var _a;
|
|
378
399
|
const v1 = parseFloat(n1);
|
|
379
400
|
const v2 = parseFloat(n2);
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
if (op === "*") res = v1 * v2;
|
|
384
|
-
if (op === "/") res = v1 / v2;
|
|
385
|
-
return `: ${res}`;
|
|
386
|
-
}).replace(/([{,])\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1 "$2":').replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, '"$1"').replace(/,\s*([\]}])/g, "$1").replace(/}\s*{/g, "},{").replace(/]\s*\[/g, "],[").replace(/\/\/.*$/gm, "").replace(/,\s*""\s*,/g, ",").replace(/\{\s*""\s*,/g, "{").replace(/,\s*""\s*\}/g, "}");
|
|
401
|
+
const ops = { "+": v1 + v2, "-": v1 - v2, "*": v1 * v2, "/": v1 / v2 };
|
|
402
|
+
return `: ${(_a = ops[op]) != null ? _a : v1}`;
|
|
403
|
+
}).replace(/([{,])\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1 "$2":').replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, '"$1"').replace(/,\s*([\]}])/g, "$1").replace(/}\s*{/g, "},{").replace(/]\s*\[/g, "],[").replace(/\/\/.*$/gm, "").replace(/([{,])\s*""\s*([,}])/g, "$1$2");
|
|
387
404
|
};
|
|
388
405
|
try {
|
|
389
406
|
const sanitized = sanitizeJson(rawContent);
|
|
@@ -401,7 +418,7 @@ function MessageBubble({
|
|
|
401
418
|
return /* @__PURE__ */ React5.createElement("div", { className: "p-4 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-sm border border-red-100 dark:border-red-900/30" }, /* @__PURE__ */ React5.createElement("p", { className: "font-medium mb-1" }, "Failed to render chart"), /* @__PURE__ */ React5.createElement("p", { className: "opacity-70 text-xs" }, "The generated configuration is invalid. Check console for details."));
|
|
402
419
|
}
|
|
403
420
|
}
|
|
404
|
-
return /* @__PURE__ */ React5.createElement("code", __spreadValues({ className }, props), children);
|
|
421
|
+
return /* @__PURE__ */ React5.createElement("code", __spreadValues({ className }, props), typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children));
|
|
405
422
|
}
|
|
406
423
|
}
|
|
407
424
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retrivora-ai/rag-engine",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Retrivora AI is a plug-and-play AI engine for RAG chat experiences — generic vector DB + LLM provider, embeddable or standalone.",
|
|
5
5
|
"author": "Abhinav Alkuchi",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,28 +42,49 @@ export function DynamicChart({ config, primaryColor = '#6366f1', accentColor = '
|
|
|
42
42
|
|| allKeys[0];
|
|
43
43
|
|
|
44
44
|
// Resolve dataKeys: use provided, fallback to 'value', 'count', 'amount', or all numeric keys
|
|
45
|
-
|
|
45
|
+
// CRITICAL: Filter out any keys that point to objects/arrays to prevent React render errors
|
|
46
|
+
const resolvedDataKeys = config.dataKeys && config.dataKeys.every(k => {
|
|
47
|
+
const val = firstItem[k];
|
|
48
|
+
return val !== undefined && typeof val !== 'object';
|
|
49
|
+
})
|
|
46
50
|
? config.dataKeys
|
|
47
|
-
: allKeys.filter(k =>
|
|
51
|
+
: allKeys.filter(k => {
|
|
52
|
+
const val = firstItem[k];
|
|
53
|
+
return k !== resolvedXKey && (typeof val === 'number' || k.toLowerCase() === 'value' || k.toLowerCase() === 'count');
|
|
54
|
+
})
|
|
48
55
|
.slice(0, 5); // Limit to 5 series for sanity
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
// Final sanity check: ensure all keys are strings
|
|
58
|
+
const finalXKey = String(resolvedXKey);
|
|
59
|
+
const finalDataKeys = resolvedDataKeys.map(String).filter(k => k !== 'undefined');
|
|
60
|
+
|
|
61
|
+
// CRITICAL: Sanitize the data array to remove any non-primitive values (objects/arrays)
|
|
62
|
+
// This prevents the "Objects are not valid as a React child" error in Tooltips/Legends
|
|
63
|
+
const sanitizedData = React.useMemo(() => {
|
|
64
|
+
return data.map(item => {
|
|
65
|
+
const newItem: Record<string, any> = {};
|
|
66
|
+
Object.keys(item).forEach(k => {
|
|
67
|
+
const val = item[k];
|
|
68
|
+
if (typeof val !== 'object' || val === null) {
|
|
69
|
+
newItem[k] = val;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
return newItem;
|
|
73
|
+
});
|
|
74
|
+
}, [data]);
|
|
54
75
|
|
|
55
76
|
// Handle Pie Chart separately as it has a different structure
|
|
56
77
|
if (type === 'pie') {
|
|
57
|
-
const pieDataKey =
|
|
78
|
+
const pieDataKey = finalDataKeys[0] || 'value';
|
|
58
79
|
|
|
59
80
|
return (
|
|
60
81
|
<div className="w-full h-72 min-h-[280px] mt-4 mb-2 select-none overflow-hidden">
|
|
61
82
|
<ResponsiveContainer width="99%" height="100%">
|
|
62
83
|
<PieChart>
|
|
63
84
|
<Pie
|
|
64
|
-
data={
|
|
85
|
+
data={sanitizedData}
|
|
65
86
|
dataKey={pieDataKey}
|
|
66
|
-
nameKey={
|
|
87
|
+
nameKey={finalXKey}
|
|
67
88
|
cx="50%"
|
|
68
89
|
cy="50%"
|
|
69
90
|
outerRadius={80}
|
|
@@ -88,16 +109,16 @@ export function DynamicChart({ config, primaryColor = '#6366f1', accentColor = '
|
|
|
88
109
|
<div className="w-full h-72 min-h-[280px] mt-4 mb-2 select-none overflow-hidden">
|
|
89
110
|
<ResponsiveContainer width="99%" height="100%">
|
|
90
111
|
{type === 'bar' ? (
|
|
91
|
-
<BarChart data={
|
|
112
|
+
<BarChart data={sanitizedData} margin={{ top: 10, right: 10, left: -20, bottom: 0 }}>
|
|
92
113
|
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="#e2e8f0" />
|
|
93
|
-
<XAxis dataKey={
|
|
114
|
+
<XAxis dataKey={finalXKey} tick={{ fontSize: 12, fill: '#64748b' }} tickLine={false} axisLine={{ stroke: '#cbd5e1' }} />
|
|
94
115
|
<YAxis tick={{ fontSize: 12, fill: '#64748b' }} tickLine={false} axisLine={false} />
|
|
95
116
|
<Tooltip
|
|
96
117
|
contentStyle={{ borderRadius: '8px', border: 'none', boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)' }}
|
|
97
118
|
cursor={{ fill: '#f1f5f9' }}
|
|
98
119
|
/>
|
|
99
120
|
<Legend wrapperStyle={{ fontSize: 12 }} />
|
|
100
|
-
{
|
|
121
|
+
{finalDataKeys.map((key, index) => (
|
|
101
122
|
<Bar
|
|
102
123
|
key={key}
|
|
103
124
|
dataKey={key}
|
|
@@ -108,15 +129,15 @@ export function DynamicChart({ config, primaryColor = '#6366f1', accentColor = '
|
|
|
108
129
|
))}
|
|
109
130
|
</BarChart>
|
|
110
131
|
) : (
|
|
111
|
-
<LineChart data={
|
|
132
|
+
<LineChart data={sanitizedData} margin={{ top: 10, right: 10, left: -20, bottom: 0 }}>
|
|
112
133
|
<CartesianGrid strokeDasharray="3 3" vertical={false} stroke="#e2e8f0" />
|
|
113
|
-
<XAxis dataKey={
|
|
134
|
+
<XAxis dataKey={finalXKey} tick={{ fontSize: 12, fill: '#64748b' }} tickLine={false} axisLine={{ stroke: '#cbd5e1' }} />
|
|
114
135
|
<YAxis tick={{ fontSize: 12, fill: '#64748b' }} tickLine={false} axisLine={false} />
|
|
115
136
|
<Tooltip
|
|
116
137
|
contentStyle={{ borderRadius: '8px', border: 'none', boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)' }}
|
|
117
138
|
/>
|
|
118
139
|
<Legend wrapperStyle={{ fontSize: 12 }} />
|
|
119
|
-
{
|
|
140
|
+
{finalDataKeys.map((key, index) => (
|
|
120
141
|
<Line
|
|
121
142
|
key={key}
|
|
122
143
|
type="monotone"
|
|
@@ -167,51 +167,46 @@ export function MessageBubble({
|
|
|
167
167
|
thead: ({...props}) => (
|
|
168
168
|
<thead className="bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" {...props} />
|
|
169
169
|
),
|
|
170
|
-
th: ({...props}) => (
|
|
171
|
-
<th className="p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl" {...props}
|
|
170
|
+
th: ({children, ...props}) => (
|
|
171
|
+
<th className="p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl" {...props}>
|
|
172
|
+
{typeof children === 'object' && children !== null && !Array.isArray(children) && !(children as any).$$typeof ? JSON.stringify(children) : children}
|
|
173
|
+
</th>
|
|
172
174
|
),
|
|
173
|
-
td: ({...props}) => (
|
|
174
|
-
<td className="p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70" {...props}
|
|
175
|
+
td: ({children, ...props}) => (
|
|
176
|
+
<td className="p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70" {...props}>
|
|
177
|
+
{typeof children === 'object' && children !== null && !Array.isArray(children) && !(children as any).$$typeof ? JSON.stringify(children) : children}
|
|
178
|
+
</td>
|
|
175
179
|
),
|
|
176
180
|
code({ inline, className, children, ...props }: React.HTMLAttributes<HTMLElement> & { inline?: boolean }) {
|
|
177
181
|
const match = /language-(\w+)/.exec(className || '');
|
|
178
182
|
const isChart = match && match[1] === 'chart';
|
|
179
183
|
|
|
180
184
|
if (!inline && isChart) {
|
|
181
|
-
const rawContent = String(children).trim();
|
|
185
|
+
const rawContent = String(children || '').trim();
|
|
182
186
|
|
|
183
|
-
|
|
187
|
+
if (!rawContent || rawContent === 'undefined') {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Optimized sanitization helper to handle LLM quirks
|
|
184
192
|
const sanitizeJson = (json: string) => {
|
|
185
193
|
return json
|
|
186
194
|
// 1. Resolve arithmetic: "value": 495 / 1000 => "value": 0.495
|
|
187
|
-
// Matches : number op number
|
|
188
195
|
.replace(/:\s*(\d+(\.\d+)?)\s*([\+\-\*\/])\s*(\d+(\.\d+)?)/g, (_, n1, __, op, n2) => {
|
|
189
|
-
const v1 = parseFloat(n1);
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
if (op === '+') res = v1 + v2;
|
|
193
|
-
if (op === '-') res = v1 - v2;
|
|
194
|
-
if (op === '*') res = v1 * v2;
|
|
195
|
-
if (op === '/') res = v1 / v2;
|
|
196
|
-
return `: ${res}`;
|
|
196
|
+
const v1 = parseFloat(n1); const v2 = parseFloat(n2);
|
|
197
|
+
const ops: Record<string, number> = { '+': v1 + v2, '-': v1 - v2, '*': v1 * v2, '/': v1 / v2 };
|
|
198
|
+
return `: ${ops[op] ?? v1}`;
|
|
197
199
|
})
|
|
198
|
-
// 2. Quote unquoted keys
|
|
199
|
-
// Matches a word followed by a colon, but not inside a string
|
|
200
|
+
// 2. Quote unquoted keys and fix single quotes
|
|
200
201
|
.replace(/([{,])\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1 "$2":')
|
|
201
|
-
// 3. Convert single quotes to double quotes (for delimiters)
|
|
202
|
-
// This is a heuristic that replaces ' with " when it looks like a JSON string
|
|
203
202
|
.replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, '"$1"')
|
|
204
|
-
//
|
|
203
|
+
// 3. Syntax cleanup: trailing/missing commas and comments
|
|
205
204
|
.replace(/,\s*([\]}])/g, '$1')
|
|
206
|
-
// 5. Fix missing commas between objects: {}{ } => {},{ }
|
|
207
205
|
.replace(/}\s*{/g, '},{')
|
|
208
206
|
.replace(/]\s*\[/g, '],[')
|
|
209
|
-
// 6. Remove JS-style comments: // something
|
|
210
207
|
.replace(/\/\/.*$/gm, '')
|
|
211
|
-
//
|
|
212
|
-
.replace(
|
|
213
|
-
.replace(/\{\s*""\s*,/g, '{')
|
|
214
|
-
.replace(/,\s*""\s*\}/g, '}');
|
|
208
|
+
// 4. Remove dangling empty strings
|
|
209
|
+
.replace(/([{,])\s*""\s*([,}])/g, '$1$2');
|
|
215
210
|
};
|
|
216
211
|
|
|
217
212
|
try {
|
|
@@ -238,7 +233,7 @@ export function MessageBubble({
|
|
|
238
233
|
}
|
|
239
234
|
return (
|
|
240
235
|
<code className={className} {...props}>
|
|
241
|
-
{children}
|
|
236
|
+
{typeof children === 'string' || typeof children === 'number' ? children : JSON.stringify(children)}
|
|
242
237
|
</code>
|
|
243
238
|
);
|
|
244
239
|
}
|