@seed-ship/mcp-ui-solid 3.0.4 → 4.0.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/CHANGELOG.md +115 -0
- package/README.md +253 -280
- package/dist/components/ChartJSRenderer.cjs +37 -15
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +37 -15
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/DataPreviewSection.cjs +172 -0
- package/dist/components/DataPreviewSection.cjs.map +1 -0
- package/dist/components/DataPreviewSection.d.ts +19 -0
- package/dist/components/DataPreviewSection.d.ts.map +1 -0
- package/dist/components/DataPreviewSection.js +172 -0
- package/dist/components/DataPreviewSection.js.map +1 -0
- package/dist/components/FormFieldRenderer.cjs +4 -1
- package/dist/components/FormFieldRenderer.cjs.map +1 -1
- package/dist/components/FormFieldRenderer.js +4 -1
- package/dist/components/FormFieldRenderer.js.map +1 -1
- package/dist/components/MapRenderer.cjs +168 -26
- package/dist/components/MapRenderer.cjs.map +1 -1
- package/dist/components/MapRenderer.d.ts +2 -2
- package/dist/components/MapRenderer.d.ts.map +1 -1
- package/dist/components/MapRenderer.js +169 -27
- package/dist/components/MapRenderer.js.map +1 -1
- package/dist/components/ScratchpadPanel.cjs +74 -0
- package/dist/components/ScratchpadPanel.cjs.map +1 -1
- package/dist/components/ScratchpadPanel.d.ts.map +1 -1
- package/dist/components/ScratchpadPanel.js +75 -1
- package/dist/components/ScratchpadPanel.js.map +1 -1
- package/dist/components/VerifiedText.cjs +166 -0
- package/dist/components/VerifiedText.cjs.map +1 -0
- package/dist/components/VerifiedText.d.ts +22 -0
- package/dist/components/VerifiedText.d.ts.map +1 -0
- package/dist/components/VerifiedText.js +166 -0
- package/dist/components/VerifiedText.js.map +1 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components.cjs +4 -0
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.cts +4 -0
- package/dist/components.d.ts +4 -0
- package/dist/components.js +4 -0
- package/dist/components.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useDataValidator.cjs +31 -0
- package/dist/hooks/useDataValidator.cjs.map +1 -0
- package/dist/hooks/useDataValidator.d.ts +42 -0
- package/dist/hooks/useDataValidator.d.ts.map +1 -0
- package/dist/hooks/useDataValidator.js +31 -0
- package/dist/hooks/useDataValidator.js.map +1 -0
- package/dist/hooks.cjs +2 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +2 -0
- package/dist/hooks.d.ts +2 -0
- package/dist/hooks.js +2 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +8 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -5
- package/dist/index.d.ts +9 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/node_modules/.pnpm/@mapbox_point-geometry@1.1.0/node_modules/@mapbox/point-geometry/index.cjs +290 -0
- package/dist/node_modules/.pnpm/@mapbox_point-geometry@1.1.0/node_modules/@mapbox/point-geometry/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@mapbox_point-geometry@1.1.0/node_modules/@mapbox/point-geometry/index.js +291 -0
- package/dist/node_modules/.pnpm/@mapbox_point-geometry@1.1.0/node_modules/@mapbox/point-geometry/index.js.map +1 -0
- package/dist/node_modules/.pnpm/@mapbox_vector-tile@2.0.4/node_modules/@mapbox/vector-tile/index.cjs +243 -0
- package/dist/node_modules/.pnpm/@mapbox_vector-tile@2.0.4/node_modules/@mapbox/vector-tile/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/@mapbox_vector-tile@2.0.4/node_modules/@mapbox/vector-tile/index.js +243 -0
- package/dist/node_modules/.pnpm/@mapbox_vector-tile@2.0.4/node_modules/@mapbox/vector-tile/index.js.map +1 -0
- package/dist/node_modules/.pnpm/color2k@2.0.3/node_modules/color2k/dist/index.exports.import.es.cjs +137 -0
- package/dist/node_modules/.pnpm/color2k@2.0.3/node_modules/color2k/dist/index.exports.import.es.cjs.map +1 -0
- package/dist/node_modules/.pnpm/color2k@2.0.3/node_modules/color2k/dist/index.exports.import.es.js +137 -0
- package/dist/node_modules/.pnpm/color2k@2.0.3/node_modules/color2k/dist/index.exports.import.es.js.map +1 -0
- package/dist/node_modules/.pnpm/pbf@4.0.1/node_modules/pbf/index.cjs +686 -0
- package/dist/node_modules/.pnpm/pbf@4.0.1/node_modules/pbf/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/pbf@4.0.1/node_modules/pbf/index.js +687 -0
- package/dist/node_modules/.pnpm/pbf@4.0.1/node_modules/pbf/index.js.map +1 -0
- package/dist/node_modules/.pnpm/pmtiles@3.2.1/node_modules/pmtiles/dist/index.cjs +1366 -0
- package/dist/node_modules/.pnpm/pmtiles@3.2.1/node_modules/pmtiles/dist/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/pmtiles@3.2.1/node_modules/pmtiles/dist/index.js +1366 -0
- package/dist/node_modules/.pnpm/pmtiles@3.2.1/node_modules/pmtiles/dist/index.js.map +1 -0
- package/dist/node_modules/.pnpm/potpack@1.0.2/node_modules/potpack/index.cjs +54 -0
- package/dist/node_modules/.pnpm/potpack@1.0.2/node_modules/potpack/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/potpack@1.0.2/node_modules/potpack/index.js +55 -0
- package/dist/node_modules/.pnpm/potpack@1.0.2/node_modules/potpack/index.js.map +1 -0
- package/dist/node_modules/.pnpm/protomaps-leaflet@4.1.1/node_modules/protomaps-leaflet/dist/esm/index.cjs +1256 -0
- package/dist/node_modules/.pnpm/protomaps-leaflet@4.1.1/node_modules/protomaps-leaflet/dist/esm/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/protomaps-leaflet@4.1.1/node_modules/protomaps-leaflet/dist/esm/index.js +1256 -0
- package/dist/node_modules/.pnpm/protomaps-leaflet@4.1.1/node_modules/protomaps-leaflet/dist/esm/index.js.map +1 -0
- package/dist/node_modules/.pnpm/quickselect@2.0.0/node_modules/quickselect/index.cjs +47 -0
- package/dist/node_modules/.pnpm/quickselect@2.0.0/node_modules/quickselect/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/quickselect@2.0.0/node_modules/quickselect/index.js +48 -0
- package/dist/node_modules/.pnpm/quickselect@2.0.0/node_modules/quickselect/index.js.map +1 -0
- package/dist/node_modules/.pnpm/rbush@3.0.1/node_modules/rbush/index.cjs +378 -0
- package/dist/node_modules/.pnpm/rbush@3.0.1/node_modules/rbush/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/rbush@3.0.1/node_modules/rbush/index.js +379 -0
- package/dist/node_modules/.pnpm/rbush@3.0.1/node_modules/rbush/index.js.map +1 -0
- package/dist/services/data-validator.cjs +85 -0
- package/dist/services/data-validator.cjs.map +1 -0
- package/dist/services/data-validator.d.ts +28 -0
- package/dist/services/data-validator.d.ts.map +1 -0
- package/dist/services/data-validator.js +85 -0
- package/dist/services/data-validator.js.map +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/types/chat-bus.d.ts +88 -1
- package/dist/types/chat-bus.d.ts.map +1 -1
- package/dist/types/index.d.ts +135 -6
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types.d.cts +135 -6
- package/dist/types.d.ts +135 -6
- package/package.json +5 -1
- package/src/components/ChartJSRenderer.tsx +35 -13
- package/src/components/DataPreviewSection.tsx +206 -0
- package/src/components/FormFieldRenderer.tsx +7 -1
- package/src/components/MapRenderer.test.tsx +94 -5
- package/src/components/MapRenderer.tsx +246 -45
- package/src/components/ScratchpadPanel.tsx +10 -2
- package/src/components/VerifiedText.tsx +187 -0
- package/src/components/index.ts +7 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useDataValidator.ts +68 -0
- package/src/index.ts +26 -1
- package/src/services/data-validator.test.ts +151 -0
- package/src/services/data-validator.ts +149 -0
- package/src/services/index.ts +2 -0
- package/src/types/chat-bus.ts +98 -1
- package/src/types/index.ts +145 -6
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -64,7 +64,7 @@ const ChartJSRenderer = (props) => {
|
|
|
64
64
|
a.click();
|
|
65
65
|
};
|
|
66
66
|
solidJs.createEffect(async () => {
|
|
67
|
-
var _a, _b, _c, _d;
|
|
67
|
+
var _a, _b, _c, _d, _e;
|
|
68
68
|
if (!canvasRef) return;
|
|
69
69
|
const chartParams = params();
|
|
70
70
|
setIsLoading(true);
|
|
@@ -75,29 +75,51 @@ const ChartJSRenderer = (props) => {
|
|
|
75
75
|
chartInstance.destroy();
|
|
76
76
|
chartInstance = null;
|
|
77
77
|
}
|
|
78
|
+
const baseOptions = {
|
|
79
|
+
responsive: true,
|
|
80
|
+
maintainAspectRatio: false,
|
|
81
|
+
...chartParams.options,
|
|
82
|
+
plugins: {
|
|
83
|
+
...(_a = chartParams.options) == null ? void 0 : _a.plugins,
|
|
84
|
+
legend: {
|
|
85
|
+
display: true,
|
|
86
|
+
position: "bottom",
|
|
87
|
+
...(_c = (_b = chartParams.options) == null ? void 0 : _b.plugins) == null ? void 0 : _c.legend
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
if (chartParams.timeAxis) {
|
|
92
|
+
const ta = chartParams.timeAxis;
|
|
93
|
+
baseOptions.scales = {
|
|
94
|
+
...baseOptions.scales,
|
|
95
|
+
x: {
|
|
96
|
+
...(_d = baseOptions.scales) == null ? void 0 : _d.x,
|
|
97
|
+
type: "time",
|
|
98
|
+
time: {
|
|
99
|
+
parser: ta.parser,
|
|
100
|
+
unit: ta.unit,
|
|
101
|
+
tooltipFormat: ta.tooltipFormat
|
|
102
|
+
},
|
|
103
|
+
...ta.min ? {
|
|
104
|
+
min: ta.min
|
|
105
|
+
} : {},
|
|
106
|
+
...ta.max ? {
|
|
107
|
+
max: ta.max
|
|
108
|
+
} : {}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
78
112
|
chartInstance = new Chart(canvasRef, {
|
|
79
113
|
type: chartParams.type,
|
|
80
114
|
data: chartParams.data,
|
|
81
|
-
options:
|
|
82
|
-
responsive: true,
|
|
83
|
-
maintainAspectRatio: false,
|
|
84
|
-
...chartParams.options,
|
|
85
|
-
plugins: {
|
|
86
|
-
...(_a = chartParams.options) == null ? void 0 : _a.plugins,
|
|
87
|
-
legend: {
|
|
88
|
-
display: true,
|
|
89
|
-
position: "bottom",
|
|
90
|
-
...(_c = (_b = chartParams.options) == null ? void 0 : _b.plugins) == null ? void 0 : _c.legend
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
115
|
+
options: baseOptions
|
|
94
116
|
});
|
|
95
117
|
setIsLoading(false);
|
|
96
118
|
} catch (err) {
|
|
97
119
|
const error2 = err instanceof Error ? err : new Error("Chart rendering failed");
|
|
98
120
|
setError(error2.message);
|
|
99
121
|
setIsLoading(false);
|
|
100
|
-
(
|
|
122
|
+
(_e = props.onError) == null ? void 0 : _e.call(props, error2);
|
|
101
123
|
}
|
|
102
124
|
});
|
|
103
125
|
solidJs.onCleanup(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartJSRenderer.cjs","sources":["../../src/components/ChartJSRenderer.tsx"],"sourcesContent":["/**\n * ChartJSRenderer - Native Chart.js rendering\n * Sprint 4: State & Charts\n *\n * Requires chart.js peer dependency:\n * ```\n * pnpm add chart.js\n * ```\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show } from 'solid-js'\nimport type { UIComponent, ChartComponentParams } from '../types'\nimport { ExpandableWrapper } from './ExpandableWrapper'\n\n// Lazy load Chart.js to avoid bundling if not used\nlet ChartJS: any = null\nlet chartJSLoadPromise: Promise<any> | null = null\n\nconst loadChartJS = async () => {\n if (ChartJS) return ChartJS\n\n if (!chartJSLoadPromise) {\n chartJSLoadPromise = import('chart.js/auto')\n .then((module) => {\n ChartJS = module.default || module.Chart\n return ChartJS\n })\n .catch((err) => {\n chartJSLoadPromise = null\n throw err\n })\n }\n\n return chartJSLoadPromise\n}\n\n/**\n * Check if Chart.js is available\n */\nexport async function isChartJSAvailable(): Promise<boolean> {\n try {\n await loadChartJS()\n return true\n } catch {\n return false\n }\n}\n\nexport interface ChartJSRendererProps {\n /**\n * UIComponent with chart params\n */\n component: UIComponent\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n}\n\n/**\n * Native Chart.js renderer component\n *\n * @example\n * ```tsx\n * const chartComponent: UIComponent = {\n * id: 'revenue-chart',\n * type: 'chart',\n * position: { colStart: 1, colSpan: 6 },\n * params: {\n * type: 'bar',\n * title: 'Monthly Revenue',\n * data: {\n * labels: ['Jan', 'Feb', 'Mar'],\n * datasets: [{ label: 'Revenue', data: [100, 200, 150] }]\n * },\n * renderer: 'native',\n * },\n * }\n * <ChartJSRenderer component={chartComponent} />\n * ```\n */\nexport const ChartJSRenderer: Component<ChartJSRendererProps> = (props) => {\n const [isLoading, setIsLoading] = createSignal(true)\n const [error, setError] = createSignal<string>()\n let canvasRef: HTMLCanvasElement | undefined\n let chartInstance: any\n\n const params = () => props.component.params as ChartComponentParams\n\n // Chart PNG export\n const handleExportPNG = () => {\n if (!canvasRef) return\n const url = canvasRef.toDataURL('image/png')\n const a = document.createElement('a')\n a.href = url\n a.download = `${(params().title || 'chart').replace(/\\s+/g, '-').toLowerCase()}.png`\n a.click()\n }\n\n // Create/update chart when params change\n createEffect(async () => {\n if (!canvasRef) return\n\n // Access params to track dependencies\n const chartParams = params()\n\n setIsLoading(true)\n setError(undefined)\n\n try {\n const Chart = await loadChartJS()\n\n // Destroy previous instance\n if (chartInstance) {\n chartInstance.destroy()\n chartInstance = null\n }\n\n // Create new chart\n chartInstance = new Chart(canvasRef, {\n type: chartParams.type,\n data: chartParams.data,\n options: {\n responsive: true,\n maintainAspectRatio: false,\n ...chartParams.options,\n plugins: {\n ...chartParams.options?.plugins,\n legend: {\n display: true,\n position: 'bottom',\n ...chartParams.options?.plugins?.legend,\n },\n },\n },\n })\n\n setIsLoading(false)\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Chart rendering failed')\n setError(error.message)\n setIsLoading(false)\n props.onError?.(error)\n }\n })\n\n // Cleanup on unmount\n onCleanup(() => {\n if (chartInstance) {\n chartInstance.destroy()\n chartInstance = null\n }\n })\n\n return (\n <ExpandableWrapper title={params().title || 'Chart'}>\n <div class=\"relative w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden p-4 group\">\n <Show when={params().title || params().exportable}>\n <div class=\"flex items-center justify-between mb-3\">\n <Show when={params().title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">\n {params().title}\n </h3>\n </Show>\n <Show when={params().exportable}>\n <button\n onClick={handleExportPNG}\n class=\"opacity-0 group-hover:opacity-60 hover:!opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm\"\n title=\"Download PNG\"\n aria-label=\"Download chart as PNG\"\n >\n <svg class=\"w-3 h-3 text-gray-500 dark:text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n </button>\n </Show>\n </div>\n </Show>\n\n <Show when={isLoading()}>\n <div class=\"absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-800/80\">\n <div class=\"flex flex-col items-center gap-2\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\" />\n <span class=\"text-sm text-gray-500 dark:text-gray-400\">Loading chart...</span>\n </div>\n </div>\n </Show>\n\n <Show when={error()}>\n <div class=\"absolute inset-0 flex items-center justify-center p-4 bg-white dark:bg-gray-800\">\n <div class=\"text-center\">\n <div class=\"inline-flex items-center justify-center w-12 h-12 rounded-full bg-red-100 dark:bg-red-900/20 mb-3\">\n <svg\n class=\"w-6 h-6 text-red-600 dark:text-red-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <p class=\"text-red-600 dark:text-red-400 text-sm font-medium\">Chart Error</p>\n <p class=\"text-gray-600 dark:text-gray-400 text-xs mt-1 max-w-xs\">{error()}</p>\n </div>\n </div>\n </Show>\n\n <div\n class=\"w-full\"\n style={{ height: params().height || '250px', display: error() ? 'none' : 'block' }}\n >\n <canvas ref={canvasRef} />\n </div>\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["ChartJS","chartJSLoadPromise","loadChartJS","then","module","default","Chart","catch","err","isChartJSAvailable","ChartJSRenderer","props","isLoading","setIsLoading","createSignal","error","setError","canvasRef","chartInstance","params","component","handleExportPNG","url","toDataURL","a","document","createElement","href","download","title","replace","toLowerCase","click","createEffect","chartParams","undefined","destroy","type","data","options","responsive","maintainAspectRatio","plugins","legend","display","position","Error","message","onError","onCleanup","_$createComponent","ExpandableWrapper","children","_el$","_$getNextElement","_tmpl$6","_el$15","firstChild","_el$16","_co$3","_$getNextMarker","nextSibling","_el$17","_el$18","_co$4","_el$19","_el$20","_co$5","_el$13","_el$14","_$insert","Show","when","exportable","_el$2","_tmpl$3","_el$5","_el$6","_co$","_el$7","_el$8","_co$2","_el$3","_tmpl$","_el$4","_tmpl$2","$$click","_$runHydrationEvents","_tmpl$4","_el$0","_tmpl$5","_el$1","_el$10","_el$11","_el$12","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","e","_$setStyleProperty","t","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChartJSRenderer.cjs","sources":["../../src/components/ChartJSRenderer.tsx"],"sourcesContent":["/**\n * ChartJSRenderer - Native Chart.js rendering\n * Sprint 4: State & Charts\n *\n * Requires chart.js peer dependency:\n * ```\n * pnpm add chart.js\n * ```\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show } from 'solid-js'\nimport type { UIComponent, ChartComponentParams } from '../types'\nimport { ExpandableWrapper } from './ExpandableWrapper'\n\n// Lazy load Chart.js to avoid bundling if not used\nlet ChartJS: any = null\nlet chartJSLoadPromise: Promise<any> | null = null\n\nconst loadChartJS = async () => {\n if (ChartJS) return ChartJS\n\n if (!chartJSLoadPromise) {\n chartJSLoadPromise = import('chart.js/auto')\n .then((module) => {\n ChartJS = module.default || module.Chart\n return ChartJS\n })\n .catch((err) => {\n chartJSLoadPromise = null\n throw err\n })\n }\n\n return chartJSLoadPromise\n}\n\n/**\n * Check if Chart.js is available\n */\nexport async function isChartJSAvailable(): Promise<boolean> {\n try {\n await loadChartJS()\n return true\n } catch {\n return false\n }\n}\n\nexport interface ChartJSRendererProps {\n /**\n * UIComponent with chart params\n */\n component: UIComponent\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n}\n\n/**\n * Native Chart.js renderer component\n *\n * @example\n * ```tsx\n * const chartComponent: UIComponent = {\n * id: 'revenue-chart',\n * type: 'chart',\n * position: { colStart: 1, colSpan: 6 },\n * params: {\n * type: 'bar',\n * title: 'Monthly Revenue',\n * data: {\n * labels: ['Jan', 'Feb', 'Mar'],\n * datasets: [{ label: 'Revenue', data: [100, 200, 150] }]\n * },\n * renderer: 'native',\n * },\n * }\n * <ChartJSRenderer component={chartComponent} />\n * ```\n */\nexport const ChartJSRenderer: Component<ChartJSRendererProps> = (props) => {\n const [isLoading, setIsLoading] = createSignal(true)\n const [error, setError] = createSignal<string>()\n let canvasRef: HTMLCanvasElement | undefined\n let chartInstance: any\n\n const params = () => props.component.params as ChartComponentParams\n\n // Chart PNG export\n const handleExportPNG = () => {\n if (!canvasRef) return\n const url = canvasRef.toDataURL('image/png')\n const a = document.createElement('a')\n a.href = url\n a.download = `${(params().title || 'chart').replace(/\\s+/g, '-').toLowerCase()}.png`\n a.click()\n }\n\n // Create/update chart when params change\n createEffect(async () => {\n if (!canvasRef) return\n\n // Access params to track dependencies\n const chartParams = params()\n\n setIsLoading(true)\n setError(undefined)\n\n try {\n const Chart = await loadChartJS()\n\n // Destroy previous instance\n if (chartInstance) {\n chartInstance.destroy()\n chartInstance = null\n }\n\n // Build options, merging time-axis config if present (v3.1.0)\n const baseOptions: any = {\n responsive: true,\n maintainAspectRatio: false,\n ...chartParams.options,\n plugins: {\n ...chartParams.options?.plugins,\n legend: {\n display: true,\n position: 'bottom',\n ...chartParams.options?.plugins?.legend,\n },\n },\n }\n\n // Time-series axis (v3.1.0)\n if (chartParams.timeAxis) {\n const ta = chartParams.timeAxis\n baseOptions.scales = {\n ...baseOptions.scales,\n x: {\n ...baseOptions.scales?.x,\n type: 'time',\n time: {\n parser: ta.parser,\n unit: ta.unit,\n tooltipFormat: ta.tooltipFormat,\n },\n ...(ta.min ? { min: ta.min } : {}),\n ...(ta.max ? { max: ta.max } : {}),\n },\n }\n }\n\n // Create new chart\n chartInstance = new Chart(canvasRef, {\n type: chartParams.type,\n data: chartParams.data,\n options: baseOptions,\n })\n\n setIsLoading(false)\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Chart rendering failed')\n setError(error.message)\n setIsLoading(false)\n props.onError?.(error)\n }\n })\n\n // Cleanup on unmount\n onCleanup(() => {\n if (chartInstance) {\n chartInstance.destroy()\n chartInstance = null\n }\n })\n\n return (\n <ExpandableWrapper title={params().title || 'Chart'}>\n <div class=\"relative w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden p-4 group\">\n <Show when={params().title || params().exportable}>\n <div class=\"flex items-center justify-between mb-3\">\n <Show when={params().title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">\n {params().title}\n </h3>\n </Show>\n <Show when={params().exportable}>\n <button\n onClick={handleExportPNG}\n class=\"opacity-0 group-hover:opacity-60 hover:!opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm\"\n title=\"Download PNG\"\n aria-label=\"Download chart as PNG\"\n >\n <svg class=\"w-3 h-3 text-gray-500 dark:text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n </button>\n </Show>\n </div>\n </Show>\n\n <Show when={isLoading()}>\n <div class=\"absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-800/80\">\n <div class=\"flex flex-col items-center gap-2\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\" />\n <span class=\"text-sm text-gray-500 dark:text-gray-400\">Loading chart...</span>\n </div>\n </div>\n </Show>\n\n <Show when={error()}>\n <div class=\"absolute inset-0 flex items-center justify-center p-4 bg-white dark:bg-gray-800\">\n <div class=\"text-center\">\n <div class=\"inline-flex items-center justify-center w-12 h-12 rounded-full bg-red-100 dark:bg-red-900/20 mb-3\">\n <svg\n class=\"w-6 h-6 text-red-600 dark:text-red-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <p class=\"text-red-600 dark:text-red-400 text-sm font-medium\">Chart Error</p>\n <p class=\"text-gray-600 dark:text-gray-400 text-xs mt-1 max-w-xs\">{error()}</p>\n </div>\n </div>\n </Show>\n\n <div\n class=\"w-full\"\n style={{ height: params().height || '250px', display: error() ? 'none' : 'block' }}\n >\n <canvas ref={canvasRef} />\n </div>\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["ChartJS","chartJSLoadPromise","loadChartJS","then","module","default","Chart","catch","err","isChartJSAvailable","ChartJSRenderer","props","isLoading","setIsLoading","createSignal","error","setError","canvasRef","chartInstance","params","component","handleExportPNG","url","toDataURL","a","document","createElement","href","download","title","replace","toLowerCase","click","createEffect","chartParams","undefined","destroy","baseOptions","responsive","maintainAspectRatio","options","plugins","legend","display","position","timeAxis","ta","scales","x","type","time","parser","unit","tooltipFormat","min","max","data","Error","message","onError","onCleanup","_$createComponent","ExpandableWrapper","children","_el$","_$getNextElement","_tmpl$6","_el$15","firstChild","_el$16","_co$3","_$getNextMarker","nextSibling","_el$17","_el$18","_co$4","_el$19","_el$20","_co$5","_el$13","_el$14","_$insert","Show","when","exportable","_el$2","_tmpl$3","_el$5","_el$6","_co$","_el$7","_el$8","_co$2","_el$3","_tmpl$","_el$4","_tmpl$2","$$click","_$runHydrationEvents","_tmpl$4","_el$0","_tmpl$5","_el$1","_el$10","_el$11","_el$12","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","e","_$setStyleProperty","t","_$delegateEvents"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartJSRenderer.d.ts","sourceRoot":"","sources":["../../src/components/ChartJSRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAA+C,MAAM,UAAU,CAAA;AACjF,OAAO,KAAK,EAAE,WAAW,EAAwB,MAAM,UAAU,CAAA;AAyBjE;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO3D;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,SAAS,EAAE,WAAW,CAAA;IAEtB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,CAAC,oBAAoB,
|
|
1
|
+
{"version":3,"file":"ChartJSRenderer.d.ts","sourceRoot":"","sources":["../../src/components/ChartJSRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAA+C,MAAM,UAAU,CAAA;AACjF,OAAO,KAAK,EAAE,WAAW,EAAwB,MAAM,UAAU,CAAA;AAyBjE;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO3D;AAED,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,SAAS,EAAE,WAAW,CAAA;IAEtB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,CAAC,oBAAoB,CAkK3D,CAAA"}
|
|
@@ -40,7 +40,7 @@ const ChartJSRenderer = (props) => {
|
|
|
40
40
|
a.click();
|
|
41
41
|
};
|
|
42
42
|
createEffect(async () => {
|
|
43
|
-
var _a, _b, _c, _d;
|
|
43
|
+
var _a, _b, _c, _d, _e;
|
|
44
44
|
if (!canvasRef) return;
|
|
45
45
|
const chartParams = params();
|
|
46
46
|
setIsLoading(true);
|
|
@@ -51,29 +51,51 @@ const ChartJSRenderer = (props) => {
|
|
|
51
51
|
chartInstance.destroy();
|
|
52
52
|
chartInstance = null;
|
|
53
53
|
}
|
|
54
|
+
const baseOptions = {
|
|
55
|
+
responsive: true,
|
|
56
|
+
maintainAspectRatio: false,
|
|
57
|
+
...chartParams.options,
|
|
58
|
+
plugins: {
|
|
59
|
+
...(_a = chartParams.options) == null ? void 0 : _a.plugins,
|
|
60
|
+
legend: {
|
|
61
|
+
display: true,
|
|
62
|
+
position: "bottom",
|
|
63
|
+
...(_c = (_b = chartParams.options) == null ? void 0 : _b.plugins) == null ? void 0 : _c.legend
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
if (chartParams.timeAxis) {
|
|
68
|
+
const ta = chartParams.timeAxis;
|
|
69
|
+
baseOptions.scales = {
|
|
70
|
+
...baseOptions.scales,
|
|
71
|
+
x: {
|
|
72
|
+
...(_d = baseOptions.scales) == null ? void 0 : _d.x,
|
|
73
|
+
type: "time",
|
|
74
|
+
time: {
|
|
75
|
+
parser: ta.parser,
|
|
76
|
+
unit: ta.unit,
|
|
77
|
+
tooltipFormat: ta.tooltipFormat
|
|
78
|
+
},
|
|
79
|
+
...ta.min ? {
|
|
80
|
+
min: ta.min
|
|
81
|
+
} : {},
|
|
82
|
+
...ta.max ? {
|
|
83
|
+
max: ta.max
|
|
84
|
+
} : {}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
}
|
|
54
88
|
chartInstance = new Chart(canvasRef, {
|
|
55
89
|
type: chartParams.type,
|
|
56
90
|
data: chartParams.data,
|
|
57
|
-
options:
|
|
58
|
-
responsive: true,
|
|
59
|
-
maintainAspectRatio: false,
|
|
60
|
-
...chartParams.options,
|
|
61
|
-
plugins: {
|
|
62
|
-
...(_a = chartParams.options) == null ? void 0 : _a.plugins,
|
|
63
|
-
legend: {
|
|
64
|
-
display: true,
|
|
65
|
-
position: "bottom",
|
|
66
|
-
...(_c = (_b = chartParams.options) == null ? void 0 : _b.plugins) == null ? void 0 : _c.legend
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
91
|
+
options: baseOptions
|
|
70
92
|
});
|
|
71
93
|
setIsLoading(false);
|
|
72
94
|
} catch (err) {
|
|
73
95
|
const error2 = err instanceof Error ? err : new Error("Chart rendering failed");
|
|
74
96
|
setError(error2.message);
|
|
75
97
|
setIsLoading(false);
|
|
76
|
-
(
|
|
98
|
+
(_e = props.onError) == null ? void 0 : _e.call(props, error2);
|
|
77
99
|
}
|
|
78
100
|
});
|
|
79
101
|
onCleanup(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChartJSRenderer.js","sources":["../../src/components/ChartJSRenderer.tsx"],"sourcesContent":["/**\n * ChartJSRenderer - Native Chart.js rendering\n * Sprint 4: State & Charts\n *\n * Requires chart.js peer dependency:\n * ```\n * pnpm add chart.js\n * ```\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show } from 'solid-js'\nimport type { UIComponent, ChartComponentParams } from '../types'\nimport { ExpandableWrapper } from './ExpandableWrapper'\n\n// Lazy load Chart.js to avoid bundling if not used\nlet ChartJS: any = null\nlet chartJSLoadPromise: Promise<any> | null = null\n\nconst loadChartJS = async () => {\n if (ChartJS) return ChartJS\n\n if (!chartJSLoadPromise) {\n chartJSLoadPromise = import('chart.js/auto')\n .then((module) => {\n ChartJS = module.default || module.Chart\n return ChartJS\n })\n .catch((err) => {\n chartJSLoadPromise = null\n throw err\n })\n }\n\n return chartJSLoadPromise\n}\n\n/**\n * Check if Chart.js is available\n */\nexport async function isChartJSAvailable(): Promise<boolean> {\n try {\n await loadChartJS()\n return true\n } catch {\n return false\n }\n}\n\nexport interface ChartJSRendererProps {\n /**\n * UIComponent with chart params\n */\n component: UIComponent\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n}\n\n/**\n * Native Chart.js renderer component\n *\n * @example\n * ```tsx\n * const chartComponent: UIComponent = {\n * id: 'revenue-chart',\n * type: 'chart',\n * position: { colStart: 1, colSpan: 6 },\n * params: {\n * type: 'bar',\n * title: 'Monthly Revenue',\n * data: {\n * labels: ['Jan', 'Feb', 'Mar'],\n * datasets: [{ label: 'Revenue', data: [100, 200, 150] }]\n * },\n * renderer: 'native',\n * },\n * }\n * <ChartJSRenderer component={chartComponent} />\n * ```\n */\nexport const ChartJSRenderer: Component<ChartJSRendererProps> = (props) => {\n const [isLoading, setIsLoading] = createSignal(true)\n const [error, setError] = createSignal<string>()\n let canvasRef: HTMLCanvasElement | undefined\n let chartInstance: any\n\n const params = () => props.component.params as ChartComponentParams\n\n // Chart PNG export\n const handleExportPNG = () => {\n if (!canvasRef) return\n const url = canvasRef.toDataURL('image/png')\n const a = document.createElement('a')\n a.href = url\n a.download = `${(params().title || 'chart').replace(/\\s+/g, '-').toLowerCase()}.png`\n a.click()\n }\n\n // Create/update chart when params change\n createEffect(async () => {\n if (!canvasRef) return\n\n // Access params to track dependencies\n const chartParams = params()\n\n setIsLoading(true)\n setError(undefined)\n\n try {\n const Chart = await loadChartJS()\n\n // Destroy previous instance\n if (chartInstance) {\n chartInstance.destroy()\n chartInstance = null\n }\n\n // Create new chart\n chartInstance = new Chart(canvasRef, {\n type: chartParams.type,\n data: chartParams.data,\n options: {\n responsive: true,\n maintainAspectRatio: false,\n ...chartParams.options,\n plugins: {\n ...chartParams.options?.plugins,\n legend: {\n display: true,\n position: 'bottom',\n ...chartParams.options?.plugins?.legend,\n },\n },\n },\n })\n\n setIsLoading(false)\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Chart rendering failed')\n setError(error.message)\n setIsLoading(false)\n props.onError?.(error)\n }\n })\n\n // Cleanup on unmount\n onCleanup(() => {\n if (chartInstance) {\n chartInstance.destroy()\n chartInstance = null\n }\n })\n\n return (\n <ExpandableWrapper title={params().title || 'Chart'}>\n <div class=\"relative w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden p-4 group\">\n <Show when={params().title || params().exportable}>\n <div class=\"flex items-center justify-between mb-3\">\n <Show when={params().title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">\n {params().title}\n </h3>\n </Show>\n <Show when={params().exportable}>\n <button\n onClick={handleExportPNG}\n class=\"opacity-0 group-hover:opacity-60 hover:!opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm\"\n title=\"Download PNG\"\n aria-label=\"Download chart as PNG\"\n >\n <svg class=\"w-3 h-3 text-gray-500 dark:text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n </button>\n </Show>\n </div>\n </Show>\n\n <Show when={isLoading()}>\n <div class=\"absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-800/80\">\n <div class=\"flex flex-col items-center gap-2\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\" />\n <span class=\"text-sm text-gray-500 dark:text-gray-400\">Loading chart...</span>\n </div>\n </div>\n </Show>\n\n <Show when={error()}>\n <div class=\"absolute inset-0 flex items-center justify-center p-4 bg-white dark:bg-gray-800\">\n <div class=\"text-center\">\n <div class=\"inline-flex items-center justify-center w-12 h-12 rounded-full bg-red-100 dark:bg-red-900/20 mb-3\">\n <svg\n class=\"w-6 h-6 text-red-600 dark:text-red-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <p class=\"text-red-600 dark:text-red-400 text-sm font-medium\">Chart Error</p>\n <p class=\"text-gray-600 dark:text-gray-400 text-xs mt-1 max-w-xs\">{error()}</p>\n </div>\n </div>\n </Show>\n\n <div\n class=\"w-full\"\n style={{ height: params().height || '250px', display: error() ? 'none' : 'block' }}\n >\n <canvas ref={canvasRef} />\n </div>\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["ChartJS","chartJSLoadPromise","loadChartJS","then","module","default","Chart","catch","err","isChartJSAvailable","ChartJSRenderer","props","isLoading","setIsLoading","createSignal","error","setError","canvasRef","chartInstance","params","component","handleExportPNG","url","toDataURL","a","document","createElement","href","download","title","replace","toLowerCase","click","createEffect","chartParams","undefined","destroy","type","data","options","responsive","maintainAspectRatio","plugins","legend","display","position","Error","message","onError","onCleanup","_$createComponent","ExpandableWrapper","children","_el$","_$getNextElement","_tmpl$6","_el$15","firstChild","_el$16","_co$3","_$getNextMarker","nextSibling","_el$17","_el$18","_co$4","_el$19","_el$20","_co$5","_el$13","_el$14","_$insert","Show","when","exportable","_el$2","_tmpl$3","_el$5","_el$6","_co$","_el$7","_el$8","_co$2","_el$3","_tmpl$","_el$4","_tmpl$2","$$click","_$runHydrationEvents","_tmpl$4","_el$0","_tmpl$5","_el$1","_el$10","_el$11","_el$12","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","e","_$setStyleProperty","t","_$delegateEvents"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChartJSRenderer.js","sources":["../../src/components/ChartJSRenderer.tsx"],"sourcesContent":["/**\n * ChartJSRenderer - Native Chart.js rendering\n * Sprint 4: State & Charts\n *\n * Requires chart.js peer dependency:\n * ```\n * pnpm add chart.js\n * ```\n */\n\nimport { Component, createEffect, onCleanup, createSignal, Show } from 'solid-js'\nimport type { UIComponent, ChartComponentParams } from '../types'\nimport { ExpandableWrapper } from './ExpandableWrapper'\n\n// Lazy load Chart.js to avoid bundling if not used\nlet ChartJS: any = null\nlet chartJSLoadPromise: Promise<any> | null = null\n\nconst loadChartJS = async () => {\n if (ChartJS) return ChartJS\n\n if (!chartJSLoadPromise) {\n chartJSLoadPromise = import('chart.js/auto')\n .then((module) => {\n ChartJS = module.default || module.Chart\n return ChartJS\n })\n .catch((err) => {\n chartJSLoadPromise = null\n throw err\n })\n }\n\n return chartJSLoadPromise\n}\n\n/**\n * Check if Chart.js is available\n */\nexport async function isChartJSAvailable(): Promise<boolean> {\n try {\n await loadChartJS()\n return true\n } catch {\n return false\n }\n}\n\nexport interface ChartJSRendererProps {\n /**\n * UIComponent with chart params\n */\n component: UIComponent\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n}\n\n/**\n * Native Chart.js renderer component\n *\n * @example\n * ```tsx\n * const chartComponent: UIComponent = {\n * id: 'revenue-chart',\n * type: 'chart',\n * position: { colStart: 1, colSpan: 6 },\n * params: {\n * type: 'bar',\n * title: 'Monthly Revenue',\n * data: {\n * labels: ['Jan', 'Feb', 'Mar'],\n * datasets: [{ label: 'Revenue', data: [100, 200, 150] }]\n * },\n * renderer: 'native',\n * },\n * }\n * <ChartJSRenderer component={chartComponent} />\n * ```\n */\nexport const ChartJSRenderer: Component<ChartJSRendererProps> = (props) => {\n const [isLoading, setIsLoading] = createSignal(true)\n const [error, setError] = createSignal<string>()\n let canvasRef: HTMLCanvasElement | undefined\n let chartInstance: any\n\n const params = () => props.component.params as ChartComponentParams\n\n // Chart PNG export\n const handleExportPNG = () => {\n if (!canvasRef) return\n const url = canvasRef.toDataURL('image/png')\n const a = document.createElement('a')\n a.href = url\n a.download = `${(params().title || 'chart').replace(/\\s+/g, '-').toLowerCase()}.png`\n a.click()\n }\n\n // Create/update chart when params change\n createEffect(async () => {\n if (!canvasRef) return\n\n // Access params to track dependencies\n const chartParams = params()\n\n setIsLoading(true)\n setError(undefined)\n\n try {\n const Chart = await loadChartJS()\n\n // Destroy previous instance\n if (chartInstance) {\n chartInstance.destroy()\n chartInstance = null\n }\n\n // Build options, merging time-axis config if present (v3.1.0)\n const baseOptions: any = {\n responsive: true,\n maintainAspectRatio: false,\n ...chartParams.options,\n plugins: {\n ...chartParams.options?.plugins,\n legend: {\n display: true,\n position: 'bottom',\n ...chartParams.options?.plugins?.legend,\n },\n },\n }\n\n // Time-series axis (v3.1.0)\n if (chartParams.timeAxis) {\n const ta = chartParams.timeAxis\n baseOptions.scales = {\n ...baseOptions.scales,\n x: {\n ...baseOptions.scales?.x,\n type: 'time',\n time: {\n parser: ta.parser,\n unit: ta.unit,\n tooltipFormat: ta.tooltipFormat,\n },\n ...(ta.min ? { min: ta.min } : {}),\n ...(ta.max ? { max: ta.max } : {}),\n },\n }\n }\n\n // Create new chart\n chartInstance = new Chart(canvasRef, {\n type: chartParams.type,\n data: chartParams.data,\n options: baseOptions,\n })\n\n setIsLoading(false)\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Chart rendering failed')\n setError(error.message)\n setIsLoading(false)\n props.onError?.(error)\n }\n })\n\n // Cleanup on unmount\n onCleanup(() => {\n if (chartInstance) {\n chartInstance.destroy()\n chartInstance = null\n }\n })\n\n return (\n <ExpandableWrapper title={params().title || 'Chart'}>\n <div class=\"relative w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden p-4 group\">\n <Show when={params().title || params().exportable}>\n <div class=\"flex items-center justify-between mb-3\">\n <Show when={params().title}>\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">\n {params().title}\n </h3>\n </Show>\n <Show when={params().exportable}>\n <button\n onClick={handleExportPNG}\n class=\"opacity-0 group-hover:opacity-60 hover:!opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm\"\n title=\"Download PNG\"\n aria-label=\"Download chart as PNG\"\n >\n <svg class=\"w-3 h-3 text-gray-500 dark:text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\" />\n </svg>\n </button>\n </Show>\n </div>\n </Show>\n\n <Show when={isLoading()}>\n <div class=\"absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-800/80\">\n <div class=\"flex flex-col items-center gap-2\">\n <div class=\"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600\" />\n <span class=\"text-sm text-gray-500 dark:text-gray-400\">Loading chart...</span>\n </div>\n </div>\n </Show>\n\n <Show when={error()}>\n <div class=\"absolute inset-0 flex items-center justify-center p-4 bg-white dark:bg-gray-800\">\n <div class=\"text-center\">\n <div class=\"inline-flex items-center justify-center w-12 h-12 rounded-full bg-red-100 dark:bg-red-900/20 mb-3\">\n <svg\n class=\"w-6 h-6 text-red-600 dark:text-red-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n </div>\n <p class=\"text-red-600 dark:text-red-400 text-sm font-medium\">Chart Error</p>\n <p class=\"text-gray-600 dark:text-gray-400 text-xs mt-1 max-w-xs\">{error()}</p>\n </div>\n </div>\n </Show>\n\n <div\n class=\"w-full\"\n style={{ height: params().height || '250px', display: error() ? 'none' : 'block' }}\n >\n <canvas ref={canvasRef} />\n </div>\n </div>\n </ExpandableWrapper>\n )\n}\n"],"names":["ChartJS","chartJSLoadPromise","loadChartJS","then","module","default","Chart","catch","err","isChartJSAvailable","ChartJSRenderer","props","isLoading","setIsLoading","createSignal","error","setError","canvasRef","chartInstance","params","component","handleExportPNG","url","toDataURL","a","document","createElement","href","download","title","replace","toLowerCase","click","createEffect","chartParams","undefined","destroy","baseOptions","responsive","maintainAspectRatio","options","plugins","legend","display","position","timeAxis","ta","scales","x","type","time","parser","unit","tooltipFormat","min","max","data","Error","message","onError","onCleanup","_$createComponent","ExpandableWrapper","children","_el$","_$getNextElement","_tmpl$6","_el$15","firstChild","_el$16","_co$3","_$getNextMarker","nextSibling","_el$17","_el$18","_co$4","_el$19","_el$20","_co$5","_el$13","_el$14","_$insert","Show","when","exportable","_el$2","_tmpl$3","_el$5","_el$6","_co$","_el$7","_el$8","_co$2","_el$3","_tmpl$","_el$4","_tmpl$2","$$click","_$runHydrationEvents","_tmpl$4","_el$0","_tmpl$5","_el$1","_el$10","_el$11","_el$12","_ref$","_$use","_$effect","_p$","_v$","height","_v$2","e","_$setStyleProperty","t","_$delegateEvents"],"mappings":"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"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const web = require("solid-js/web");
|
|
4
|
+
const solidJs = require("solid-js");
|
|
5
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<span class=font-medium>`), _tmpl$2 = /* @__PURE__ */ web.template(`<span class="px-1.5 py-0.5 rounded bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300">`), _tmpl$3 = /* @__PURE__ */ web.template(`<div class="flex items-center gap-1"><button class="px-2 py-1 text-xs rounded border border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"title="Export CSV">CSV</button><button class="px-2 py-1 text-xs rounded border border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"title="Export JSON">JSON`), _tmpl$4 = /* @__PURE__ */ web.template(`<div class="flex items-center gap-1"><button class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 transition-colors">«</button><span><!$><!/> / <!$><!/></span><button class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 transition-colors">»`), _tmpl$5 = /* @__PURE__ */ web.template(`<div class=data-preview-section><div class="flex items-center justify-between mb-2"><div class="flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400"><!$><!/><!$><!/></div><!$><!/></div><div class="overflow-x-auto rounded border border-gray-200 dark:border-gray-700"><table class="w-full text-sm"><thead><tr class="bg-gray-50 dark:bg-gray-800"></tr></thead><tbody></tbody></table></div><div class="flex items-center justify-between mt-2 text-xs text-gray-500 dark:text-gray-400"><span></span><!$><!/>`), _tmpl$6 = /* @__PURE__ */ web.template(`<th class="px-3 py-2 font-medium text-xs text-gray-600 dark:text-gray-400 uppercase tracking-wider border-b border-gray-200 dark:border-gray-700">`), _tmpl$7 = /* @__PURE__ */ web.template(`<tr class="border-b border-gray-100 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors">`), _tmpl$8 = /* @__PURE__ */ web.template(`<td class="px-3 py-2 text-gray-800 dark:text-gray-200">`);
|
|
6
|
+
function formatNumber(value, format) {
|
|
7
|
+
if (typeof value !== "number" || !isFinite(value)) return String(value ?? "");
|
|
8
|
+
if (format === "percent") return `${(value * 100).toFixed(1)}%`;
|
|
9
|
+
if (format === "currency") return `${value.toLocaleString("fr-FR")} EUR`;
|
|
10
|
+
if (Number.isInteger(value)) return value.toLocaleString("fr-FR");
|
|
11
|
+
return value.toLocaleString("fr-FR", {
|
|
12
|
+
maximumFractionDigits: 2
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function formatCell(value, col) {
|
|
16
|
+
if (value == null) return "—";
|
|
17
|
+
if (col.type === "number") return formatNumber(value, col.format);
|
|
18
|
+
if (col.type === "date" && typeof value === "string") {
|
|
19
|
+
try {
|
|
20
|
+
return new Date(value).toLocaleDateString("fr-FR");
|
|
21
|
+
} catch {
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return String(value);
|
|
26
|
+
}
|
|
27
|
+
function toCSV(columns, rows) {
|
|
28
|
+
const header = columns.map((c) => `"${c.label.replace(/"/g, '""')}"`).join(";");
|
|
29
|
+
const body = rows.map((row) => columns.map((c) => {
|
|
30
|
+
const val = row[c.key];
|
|
31
|
+
if (val == null) return "";
|
|
32
|
+
if (typeof val === "string") return `"${val.replace(/"/g, '""')}"`;
|
|
33
|
+
return String(val);
|
|
34
|
+
}).join(";")).join("\n");
|
|
35
|
+
return `${header}
|
|
36
|
+
${body}`;
|
|
37
|
+
}
|
|
38
|
+
function downloadFile(content, filename, mimeType) {
|
|
39
|
+
const blob = new Blob([content], {
|
|
40
|
+
type: mimeType
|
|
41
|
+
});
|
|
42
|
+
const url = URL.createObjectURL(blob);
|
|
43
|
+
const a = document.createElement("a");
|
|
44
|
+
a.href = url;
|
|
45
|
+
a.download = filename;
|
|
46
|
+
a.click();
|
|
47
|
+
URL.revokeObjectURL(url);
|
|
48
|
+
}
|
|
49
|
+
function DataPreviewSection(props) {
|
|
50
|
+
const content = () => props.content;
|
|
51
|
+
const pageSize = () => content().pageSize || 25;
|
|
52
|
+
const [page, setPage] = solidJs.createSignal(0);
|
|
53
|
+
const totalRows = () => content().rows.length;
|
|
54
|
+
const totalPages = () => Math.max(1, Math.ceil(totalRows() / pageSize()));
|
|
55
|
+
const pagedRows = solidJs.createMemo(() => {
|
|
56
|
+
const start = page() * pageSize();
|
|
57
|
+
return content().rows.slice(start, start + pageSize());
|
|
58
|
+
});
|
|
59
|
+
const handleExportCSV = () => {
|
|
60
|
+
const csv = toCSV(content().columns, content().rows);
|
|
61
|
+
downloadFile(csv, "data-export.csv", "text/csv;charset=utf-8");
|
|
62
|
+
};
|
|
63
|
+
const handleExportJSON = () => {
|
|
64
|
+
const json = JSON.stringify(content().rows, null, 2);
|
|
65
|
+
downloadFile(json, "data-export.json", "application/json");
|
|
66
|
+
};
|
|
67
|
+
const columnAlign = (col) => {
|
|
68
|
+
if (col.align) return col.align;
|
|
69
|
+
if (col.type === "number") return "right";
|
|
70
|
+
return "left";
|
|
71
|
+
};
|
|
72
|
+
return (() => {
|
|
73
|
+
var _el$ = web.getNextElement(_tmpl$5), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$6 = _el$3.firstChild, [_el$7, _co$] = web.getNextMarker(_el$6.nextSibling), _el$8 = _el$7.nextSibling, [_el$9, _co$2] = web.getNextMarker(_el$8.nextSibling), _el$11 = _el$3.nextSibling, [_el$12, _co$3] = web.getNextMarker(_el$11.nextSibling), _el$13 = _el$2.nextSibling, _el$14 = _el$13.firstChild, _el$15 = _el$14.firstChild, _el$16 = _el$15.firstChild, _el$17 = _el$15.nextSibling, _el$18 = _el$13.nextSibling, _el$19 = _el$18.firstChild, _el$29 = _el$19.nextSibling, [_el$30, _co$6] = web.getNextMarker(_el$29.nextSibling);
|
|
74
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
75
|
+
get when() {
|
|
76
|
+
return content().source;
|
|
77
|
+
},
|
|
78
|
+
get children() {
|
|
79
|
+
var _el$4 = web.getNextElement(_tmpl$);
|
|
80
|
+
web.insert(_el$4, () => content().source);
|
|
81
|
+
return _el$4;
|
|
82
|
+
}
|
|
83
|
+
}), _el$7, _co$);
|
|
84
|
+
web.insert(_el$3, web.createComponent(solidJs.Show, {
|
|
85
|
+
get when() {
|
|
86
|
+
return content().freshness;
|
|
87
|
+
},
|
|
88
|
+
get children() {
|
|
89
|
+
var _el$5 = web.getNextElement(_tmpl$2);
|
|
90
|
+
web.insert(_el$5, () => content().freshness);
|
|
91
|
+
return _el$5;
|
|
92
|
+
}
|
|
93
|
+
}), _el$9, _co$2);
|
|
94
|
+
web.insert(_el$2, web.createComponent(solidJs.Show, {
|
|
95
|
+
get when() {
|
|
96
|
+
return content().exportable !== false;
|
|
97
|
+
},
|
|
98
|
+
get children() {
|
|
99
|
+
var _el$0 = web.getNextElement(_tmpl$3), _el$1 = _el$0.firstChild, _el$10 = _el$1.nextSibling;
|
|
100
|
+
_el$1.$$click = handleExportCSV;
|
|
101
|
+
_el$10.$$click = handleExportJSON;
|
|
102
|
+
web.runHydrationEvents();
|
|
103
|
+
return _el$0;
|
|
104
|
+
}
|
|
105
|
+
}), _el$12, _co$3);
|
|
106
|
+
web.insert(_el$16, web.createComponent(solidJs.For, {
|
|
107
|
+
get each() {
|
|
108
|
+
return content().columns;
|
|
109
|
+
},
|
|
110
|
+
children: (col) => (() => {
|
|
111
|
+
var _el$31 = web.getNextElement(_tmpl$6);
|
|
112
|
+
web.insert(_el$31, () => col.label);
|
|
113
|
+
web.effect((_$p) => web.setStyleProperty(_el$31, "text-align", columnAlign(col)));
|
|
114
|
+
return _el$31;
|
|
115
|
+
})()
|
|
116
|
+
}));
|
|
117
|
+
web.insert(_el$17, web.createComponent(solidJs.For, {
|
|
118
|
+
get each() {
|
|
119
|
+
return pagedRows();
|
|
120
|
+
},
|
|
121
|
+
children: (row, i) => (() => {
|
|
122
|
+
var _el$32 = web.getNextElement(_tmpl$7);
|
|
123
|
+
web.insert(_el$32, web.createComponent(solidJs.For, {
|
|
124
|
+
get each() {
|
|
125
|
+
return content().columns;
|
|
126
|
+
},
|
|
127
|
+
children: (col) => (() => {
|
|
128
|
+
var _el$33 = web.getNextElement(_tmpl$8);
|
|
129
|
+
web.insert(_el$33, () => formatCell(row[col.key], col));
|
|
130
|
+
web.effect((_$p) => web.setStyleProperty(_el$33, "text-align", columnAlign(col)));
|
|
131
|
+
return _el$33;
|
|
132
|
+
})()
|
|
133
|
+
}));
|
|
134
|
+
web.effect((_$p) => web.classList(_el$32, {
|
|
135
|
+
"bg-gray-25 dark:bg-gray-850": i() % 2 === 1
|
|
136
|
+
}, _$p));
|
|
137
|
+
return _el$32;
|
|
138
|
+
})()
|
|
139
|
+
}));
|
|
140
|
+
web.insert(_el$19, (() => {
|
|
141
|
+
var _c$ = web.memo(() => !!content().totalRows);
|
|
142
|
+
return () => _c$() ? `${totalRows()} / ${content().totalRows.toLocaleString("fr-FR")} rows` : `${totalRows()} row${totalRows() !== 1 ? "s" : ""}`;
|
|
143
|
+
})());
|
|
144
|
+
web.insert(_el$18, web.createComponent(solidJs.Show, {
|
|
145
|
+
get when() {
|
|
146
|
+
return totalPages() > 1;
|
|
147
|
+
},
|
|
148
|
+
get children() {
|
|
149
|
+
var _el$20 = web.getNextElement(_tmpl$4), _el$21 = _el$20.firstChild, _el$22 = _el$21.nextSibling, _el$24 = _el$22.firstChild, [_el$25, _co$4] = web.getNextMarker(_el$24.nextSibling), _el$23 = _el$25.nextSibling, _el$26 = _el$23.nextSibling, [_el$27, _co$5] = web.getNextMarker(_el$26.nextSibling), _el$28 = _el$22.nextSibling;
|
|
150
|
+
_el$21.$$click = () => setPage((p) => p - 1);
|
|
151
|
+
web.insert(_el$22, () => page() + 1, _el$25, _co$4);
|
|
152
|
+
web.insert(_el$22, totalPages, _el$27, _co$5);
|
|
153
|
+
_el$28.$$click = () => setPage((p) => p + 1);
|
|
154
|
+
web.effect((_p$) => {
|
|
155
|
+
var _v$ = page() === 0, _v$2 = page() >= totalPages() - 1;
|
|
156
|
+
_v$ !== _p$.e && web.setProperty(_el$21, "disabled", _p$.e = _v$);
|
|
157
|
+
_v$2 !== _p$.t && web.setProperty(_el$28, "disabled", _p$.t = _v$2);
|
|
158
|
+
return _p$;
|
|
159
|
+
}, {
|
|
160
|
+
e: void 0,
|
|
161
|
+
t: void 0
|
|
162
|
+
});
|
|
163
|
+
web.runHydrationEvents();
|
|
164
|
+
return _el$20;
|
|
165
|
+
}
|
|
166
|
+
}), _el$30, _co$6);
|
|
167
|
+
return _el$;
|
|
168
|
+
})();
|
|
169
|
+
}
|
|
170
|
+
web.delegateEvents(["click"]);
|
|
171
|
+
exports.DataPreviewSection = DataPreviewSection;
|
|
172
|
+
//# sourceMappingURL=DataPreviewSection.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataPreviewSection.cjs","sources":["../../src/components/DataPreviewSection.tsx"],"sourcesContent":["/**\n * DataPreviewSection — paginated data table with export\n * v3.1.0: Replaces LLM-generated markdown tables with exact source data\n *\n * @experimental\n *\n * Features:\n * - Column types (number right-aligned, string left-aligned)\n * - Pagination (configurable page size)\n * - CSV / JSON export buttons\n * - Source attribution + freshness label\n * - Number formatting (FR locale)\n */\n\nimport { createSignal, createMemo, For, Show } from 'solid-js'\nimport type { DataPreviewContent, DataPreviewColumn } from '../types/chat-bus'\n\nexport interface DataPreviewSectionProps {\n content: DataPreviewContent\n}\n\n/** Format a number for display (French locale) */\nfunction formatNumber(value: unknown, format?: string): string {\n if (typeof value !== 'number' || !isFinite(value)) return String(value ?? '')\n // Simple formatting: use locale\n if (format === 'percent') return `${(value * 100).toFixed(1)}%`\n if (format === 'currency') return `${value.toLocaleString('fr-FR')} EUR`\n if (Number.isInteger(value)) return value.toLocaleString('fr-FR')\n return value.toLocaleString('fr-FR', { maximumFractionDigits: 2 })\n}\n\n/** Format a cell value based on column type */\nfunction formatCell(value: unknown, col: DataPreviewColumn): string {\n if (value == null) return '—'\n if (col.type === 'number') return formatNumber(value, col.format)\n if (col.type === 'date' && typeof value === 'string') {\n try {\n return new Date(value).toLocaleDateString('fr-FR')\n } catch {\n return value\n }\n }\n return String(value)\n}\n\n/** Generate CSV from columns + rows */\nfunction toCSV(columns: DataPreviewColumn[], rows: Record<string, unknown>[]): string {\n const header = columns.map(c => `\"${c.label.replace(/\"/g, '\"\"')}\"`).join(';')\n const body = rows.map(row =>\n columns.map(c => {\n const val = row[c.key]\n if (val == null) return ''\n if (typeof val === 'string') return `\"${val.replace(/\"/g, '\"\"')}\"`\n return String(val)\n }).join(';')\n ).join('\\n')\n return `${header}\\n${body}`\n}\n\n/** Trigger browser download */\nfunction downloadFile(content: string, filename: string, mimeType: string) {\n const blob = new Blob([content], { type: mimeType })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = filename\n a.click()\n URL.revokeObjectURL(url)\n}\n\nexport function DataPreviewSection(props: DataPreviewSectionProps) {\n const content = () => props.content\n const pageSize = () => content().pageSize || 25\n const [page, setPage] = createSignal(0)\n\n const totalRows = () => content().rows.length\n const totalPages = () => Math.max(1, Math.ceil(totalRows() / pageSize()))\n\n const pagedRows = createMemo(() => {\n const start = page() * pageSize()\n return content().rows.slice(start, start + pageSize())\n })\n\n const handleExportCSV = () => {\n const csv = toCSV(content().columns, content().rows)\n downloadFile(csv, 'data-export.csv', 'text/csv;charset=utf-8')\n }\n\n const handleExportJSON = () => {\n const json = JSON.stringify(content().rows, null, 2)\n downloadFile(json, 'data-export.json', 'application/json')\n }\n\n const columnAlign = (col: DataPreviewColumn) => {\n if (col.align) return col.align\n if (col.type === 'number') return 'right'\n return 'left'\n }\n\n return (\n <div class=\"data-preview-section\">\n {/* Header with source + export */}\n <div class=\"flex items-center justify-between mb-2\">\n <div class=\"flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400\">\n <Show when={content().source}>\n <span class=\"font-medium\">{content().source}</span>\n </Show>\n <Show when={content().freshness}>\n <span class=\"px-1.5 py-0.5 rounded bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300\">\n {content().freshness}\n </span>\n </Show>\n </div>\n\n <Show when={content().exportable !== false}>\n <div class=\"flex items-center gap-1\">\n <button\n class=\"px-2 py-1 text-xs rounded border border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\n onClick={handleExportCSV}\n title=\"Export CSV\"\n >\n CSV\n </button>\n <button\n class=\"px-2 py-1 text-xs rounded border border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors\"\n onClick={handleExportJSON}\n title=\"Export JSON\"\n >\n JSON\n </button>\n </div>\n </Show>\n </div>\n\n {/* Table */}\n <div class=\"overflow-x-auto rounded border border-gray-200 dark:border-gray-700\">\n <table class=\"w-full text-sm\">\n <thead>\n <tr class=\"bg-gray-50 dark:bg-gray-800\">\n <For each={content().columns}>\n {(col) => (\n <th\n class=\"px-3 py-2 font-medium text-xs text-gray-600 dark:text-gray-400 uppercase tracking-wider border-b border-gray-200 dark:border-gray-700\"\n style={{ \"text-align\": columnAlign(col) }}\n >\n {col.label}\n </th>\n )}\n </For>\n </tr>\n </thead>\n <tbody>\n <For each={pagedRows()}>\n {(row, i) => (\n <tr\n class=\"border-b border-gray-100 dark:border-gray-800 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors\"\n classList={{ 'bg-gray-25 dark:bg-gray-850': i() % 2 === 1 }}\n >\n <For each={content().columns}>\n {(col) => (\n <td\n class=\"px-3 py-2 text-gray-800 dark:text-gray-200\"\n style={{ \"text-align\": columnAlign(col) }}\n >\n {formatCell(row[col.key], col)}\n </td>\n )}\n </For>\n </tr>\n )}\n </For>\n </tbody>\n </table>\n </div>\n\n {/* Footer: pagination + row count */}\n <div class=\"flex items-center justify-between mt-2 text-xs text-gray-500 dark:text-gray-400\">\n <span>\n {content().totalRows\n ? `${totalRows()} / ${content().totalRows!.toLocaleString('fr-FR')} rows`\n : `${totalRows()} row${totalRows() !== 1 ? 's' : ''}`}\n </span>\n\n <Show when={totalPages() > 1}>\n <div class=\"flex items-center gap-1\">\n <button\n class=\"px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 transition-colors\"\n disabled={page() === 0}\n onClick={() => setPage(p => p - 1)}\n >\n «\n </button>\n <span>{page() + 1} / {totalPages()}</span>\n <button\n class=\"px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 transition-colors\"\n disabled={page() >= totalPages() - 1}\n onClick={() => setPage(p => p + 1)}\n >\n »\n </button>\n </div>\n </Show>\n </div>\n </div>\n )\n}\n"],"names":["formatNumber","value","format","isFinite","String","toFixed","toLocaleString","Number","isInteger","maximumFractionDigits","formatCell","col","type","Date","toLocaleDateString","toCSV","columns","rows","header","map","c","label","replace","join","body","row","val","key","downloadFile","content","filename","mimeType","blob","Blob","url","URL","createObjectURL","a","document","createElement","href","download","click","revokeObjectURL","DataPreviewSection","props","pageSize","page","setPage","createSignal","totalRows","length","totalPages","Math","max","ceil","pagedRows","createMemo","start","slice","handleExportCSV","csv","handleExportJSON","json","JSON","stringify","columnAlign","align","_el$","_$getNextElement","_tmpl$5","_el$2","firstChild","_el$3","_el$6","_el$7","_co$","_$getNextMarker","nextSibling","_el$8","_el$9","_co$2","_el$11","_el$12","_co$3","_el$13","_el$14","_el$15","_el$16","_el$17","_el$18","_el$19","_el$29","_el$30","_co$6","_$insert","_$createComponent","Show","when","source","children","_el$4","_tmpl$","freshness","_el$5","_tmpl$2","exportable","_el$0","_tmpl$3","_el$1","_el$10","$$click","_$runHydrationEvents","For","each","_el$31","_tmpl$6","_$effect","_$p","_$setStyleProperty","i","_el$32","_tmpl$7","_el$33","_tmpl$8","_$classList","_c$","_$memo","_el$20","_tmpl$4","_el$21","_el$22","_el$24","_el$25","_co$4","_el$23","_el$26","_el$27","_co$5","_el$28","p","_p$","_v$","_v$2","e","_$setProperty","t","undefined","_$delegateEvents"],"mappings":";;;;;AAsBA,SAASA,aAAaC,OAAgBC,QAAyB;AAC7D,MAAI,OAAOD,UAAU,YAAY,CAACE,SAASF,KAAK,EAAG,QAAOG,OAAOH,SAAS,EAAE;AAE5E,MAAIC,WAAW,UAAW,QAAO,IAAID,QAAQ,KAAKI,QAAQ,CAAC,CAAC;AAC5D,MAAIH,WAAW,WAAY,QAAO,GAAGD,MAAMK,eAAe,OAAO,CAAC;AAClE,MAAIC,OAAOC,UAAUP,KAAK,EAAG,QAAOA,MAAMK,eAAe,OAAO;AAChE,SAAOL,MAAMK,eAAe,SAAS;AAAA,IAAEG,uBAAuB;AAAA,EAAA,CAAG;AACnE;AAGA,SAASC,WAAWT,OAAgBU,KAAgC;AAClE,MAAIV,SAAS,KAAM,QAAO;AAC1B,MAAIU,IAAIC,SAAS,iBAAiBZ,aAAaC,OAAOU,IAAIT,MAAM;AAChE,MAAIS,IAAIC,SAAS,UAAU,OAAOX,UAAU,UAAU;AACpD,QAAI;AACF,aAAO,IAAIY,KAAKZ,KAAK,EAAEa,mBAAmB,OAAO;AAAA,IACnD,QAAQ;AACN,aAAOb;AAAAA,IACT;AAAA,EACF;AACA,SAAOG,OAAOH,KAAK;AACrB;AAGA,SAASc,MAAMC,SAA8BC,MAAyC;AACpF,QAAMC,SAASF,QAAQG,IAAIC,CAAAA,MAAK,IAAIA,EAAEC,MAAMC,QAAQ,MAAM,IAAI,CAAC,GAAG,EAAEC,KAAK,GAAG;AAC5E,QAAMC,OAAOP,KAAKE,IAAIM,CAAAA,QACpBT,QAAQG,IAAIC,CAAAA,MAAK;AACf,UAAMM,MAAMD,IAAIL,EAAEO,GAAG;AACrB,QAAID,OAAO,KAAM,QAAO;AACxB,QAAI,OAAOA,QAAQ,SAAU,QAAO,IAAIA,IAAIJ,QAAQ,MAAM,IAAI,CAAC;AAC/D,WAAOlB,OAAOsB,GAAG;AAAA,EACnB,CAAC,EAAEH,KAAK,GAAG,CACb,EAAEA,KAAK,IAAI;AACX,SAAO,GAAGL,MAAM;AAAA,EAAKM,IAAI;AAC3B;AAGA,SAASI,aAAaC,SAAiBC,UAAkBC,UAAkB;AACzE,QAAMC,OAAO,IAAIC,KAAK,CAACJ,OAAO,GAAG;AAAA,IAAEjB,MAAMmB;AAAAA,EAAAA,CAAU;AACnD,QAAMG,MAAMC,IAAIC,gBAAgBJ,IAAI;AACpC,QAAMK,IAAIC,SAASC,cAAc,GAAG;AACpCF,IAAEG,OAAON;AACTG,IAAEI,WAAWX;AACbO,IAAEK,MAAAA;AACFP,MAAIQ,gBAAgBT,GAAG;AACzB;AAEO,SAASU,mBAAmBC,OAAgC;AACjE,QAAMhB,UAAUA,MAAMgB,MAAMhB;AAC5B,QAAMiB,WAAWA,MAAMjB,QAAAA,EAAUiB,YAAY;AAC7C,QAAM,CAACC,MAAMC,OAAO,IAAIC,QAAAA,aAAa,CAAC;AAEtC,QAAMC,YAAYA,MAAMrB,QAAAA,EAAUZ,KAAKkC;AACvC,QAAMC,aAAaA,MAAMC,KAAKC,IAAI,GAAGD,KAAKE,KAAKL,UAAAA,IAAcJ,SAAAA,CAAU,CAAC;AAExE,QAAMU,YAAYC,QAAAA,WAAW,MAAM;AACjC,UAAMC,QAAQX,KAAAA,IAASD,SAAAA;AACvB,WAAOjB,UAAUZ,KAAK0C,MAAMD,OAAOA,QAAQZ,UAAU;AAAA,EACvD,CAAC;AAED,QAAMc,kBAAkBA,MAAM;AAC5B,UAAMC,MAAM9C,MAAMc,QAAAA,EAAUb,SAASa,QAAAA,EAAUZ,IAAI;AACnDW,iBAAaiC,KAAK,mBAAmB,wBAAwB;AAAA,EAC/D;AAEA,QAAMC,mBAAmBA,MAAM;AAC7B,UAAMC,OAAOC,KAAKC,UAAUpC,UAAUZ,MAAM,MAAM,CAAC;AACnDW,iBAAamC,MAAM,oBAAoB,kBAAkB;AAAA,EAC3D;AAEA,QAAMG,cAAcA,CAACvD,QAA2B;AAC9C,QAAIA,IAAIwD,MAAO,QAAOxD,IAAIwD;AAC1B,QAAIxD,IAAIC,SAAS,SAAU,QAAO;AAClC,WAAO;AAAA,EACT;AAEA,UAAA,MAAA;AAAA,QAAAwD,OAAAC,IAAAA,eAAAC,OAAA,GAAAC,QAAAH,KAAAI,YAAAC,QAAAF,MAAAC,YAAAE,QAAAD,MAAAD,YAAA,CAAAG,OAAAC,IAAA,IAAAC,IAAAA,cAAAH,MAAAI,WAAA,GAAAC,QAAAJ,MAAAG,aAAA,CAAAE,OAAAC,KAAA,IAAAJ,IAAAA,cAAAE,MAAAD,WAAA,GAAAI,SAAAT,MAAAK,aAAA,CAAAK,QAAAC,KAAA,IAAAP,IAAAA,cAAAK,OAAAJ,WAAA,GAAAO,SAAAd,MAAAO,aAAAQ,SAAAD,OAAAb,YAAAe,SAAAD,OAAAd,YAAAgB,SAAAD,OAAAf,YAAAiB,SAAAF,OAAAT,aAAAY,SAAAL,OAAAP,aAAAa,SAAAD,OAAAlB,YAAAoB,SAAAD,OAAAb,aAAA,CAAAe,QAAAC,KAAA,IAAAjB,IAAAA,cAAAe,OAAAd,WAAA;AAAAiB,eAAAtB,OAAAuB,IAAAA,gBAKSC,cAAI;AAAA,MAAA,IAACC,OAAI;AAAA,eAAErE,UAAUsE;AAAAA,MAAM;AAAA,MAAA,IAAAC,WAAA;AAAA,YAAAC,QAAAhC,IAAAA,eAAAiC,MAAA;AAAAP,YAAAA,OAAAM,OAAA,MACCxE,QAAAA,EAAUsE,MAAM;AAAA,eAAAE;AAAAA,MAAA;AAAA,IAAA,CAAA,GAAA1B,OAAAC,IAAA;AAAAmB,eAAAtB,OAAAuB,IAAAA,gBAE5CC,cAAI;AAAA,MAAA,IAACC,OAAI;AAAA,eAAErE,UAAU0E;AAAAA,MAAS;AAAA,MAAA,IAAAH,WAAA;AAAA,YAAAI,QAAAnC,IAAAA,eAAAoC,OAAA;AAAAV,YAAAA,OAAAS,OAAA,MAE1B3E,QAAAA,EAAU0E,SAAS;AAAA,eAAAC;AAAAA,MAAA;AAAA,IAAA,CAAA,GAAAxB,OAAAC,KAAA;AAAAc,eAAAxB,OAAAyB,IAAAA,gBAKzBC,cAAI;AAAA,MAAA,IAACC,OAAI;AAAA,eAAErE,QAAAA,EAAU6E,eAAe;AAAA,MAAK;AAAA,MAAA,IAAAN,WAAA;AAAA,YAAAO,QAAAtC,mBAAAuC,OAAA,GAAAC,QAAAF,MAAAnC,YAAAsC,SAAAD,MAAA/B;AAAA+B,cAAAE,UAI3BnD;AAAekD,eAAAC,UAOfjD;AAAgBkD,+BAAAA;AAAA,eAAAL;AAAAA,MAAA;AAAA,IAAA,CAAA,GAAAxB,QAAAC,KAAA;AAAAW,eAAAP,QAAAQ,IAAAA,gBAcxBiB,aAAG;AAAA,MAAA,IAACC,OAAI;AAAA,eAAErF,UAAUb;AAAAA,MAAO;AAAA,MAAAoF,UACxBzF,UAAG,MAAA;AAAA,YAAAwG,SAAA9C,IAAAA,eAAA+C,OAAA;AAAArB,YAAAA,OAAAoB,QAAA,MAKAxG,IAAIU,KAAK;AAAAgG,mBAAAC,SAAAC,qBAAAJ,QAAA,cAFajD,YAAYvD,GAAG,CAAC,CAAA;AAAA,eAAAwG;AAAAA,MAAA,GAAA;AAAA,IAAA,CAI1C,CAAA;AAAApB,eAAAN,QAAAO,IAAAA,gBAKJiB,aAAG;AAAA,MAAA,IAACC,OAAI;AAAA,eAAE1D,UAAAA;AAAAA,MAAW;AAAA,MAAA4C,UACnBA,CAAC3E,KAAK+F,OAAC,MAAA;AAAA,YAAAC,SAAApD,IAAAA,eAAAqD,OAAA;AAAA3B,mBAAA0B,QAAAzB,IAAAA,gBAKHiB,aAAG;AAAA,UAAA,IAACC,OAAI;AAAA,mBAAErF,UAAUb;AAAAA,UAAO;AAAA,UAAAoF,UACxBzF,UAAG,MAAA;AAAA,gBAAAgH,SAAAtD,IAAAA,eAAAuD,OAAA;AAAA7B,uBAAA4B,QAAA,MAKAjH,WAAWe,IAAId,IAAIgB,GAAG,GAAGhB,GAAG,CAAC;AAAA0G,uBAAAC,SAAAC,qBAAAI,QAAA,cAFPzD,YAAYvD,GAAG,CAAC,CAAA;AAAA,mBAAAgH;AAAAA,UAAA,GAAA;AAAA,QAAA,CAI1C,CAAA;AAAAN,YAAAA,OAAAC,CAAAA,QAAAO,IAAAA,UAAAJ,QAVQ;AAAA,UAAE,+BAA+BD,EAAAA,IAAM,MAAM;AAAA,QAAA,GAAGF,GAAA,CAAA;AAAA,eAAAG;AAAAA,MAAA,GAAA;AAAA,IAAA,CAa9D,CAAA;AAAA1B,QAAAA,OAAAJ,SAAA,MAAA;AAAA,UAAAmC,MAAAC,IAAAA,KAAA,MAAA,CAAA,CASJlG,QAAAA,EAAUqB,SAAS;AAAA,aAAA,MAAnB4E,QACG,GAAG5E,WAAW,MAAMrB,QAAAA,EAAUqB,UAAW5C,eAAe,OAAO,CAAC,UAChE,GAAG4C,WAAW,OAAOA,UAAAA,MAAgB,IAAI,MAAM,EAAE;AAAA,IAAE,IAAA;AAAA6C,eAAAL,QAAAM,IAAAA,gBAGxDC,cAAI;AAAA,MAAA,IAACC,OAAI;AAAA,eAAE9C,eAAe;AAAA,MAAC;AAAA,MAAA,IAAAgD,WAAA;AAAA,YAAA4B,SAAA3D,IAAAA,eAAA4D,OAAA,GAAAC,SAAAF,OAAAxD,YAAA2D,SAAAD,OAAApD,aAAAsD,SAAAD,OAAA3D,YAAA,CAAA6D,QAAAC,KAAA,IAAAzD,IAAAA,cAAAuD,OAAAtD,WAAA,GAAAyD,SAAAF,OAAAvD,aAAA0D,SAAAD,OAAAzD,aAAA,CAAA2D,QAAAC,KAAA,IAAA7D,IAAAA,cAAA2D,OAAA1D,WAAA,GAAA6D,SAAAR,OAAArD;AAAAoD,eAAAnB,UAKb,MAAM/D,QAAQ4F,CAAAA,MAAKA,IAAI,CAAC;AAAC7C,YAAAA,OAAAoC,QAAA,MAI7BpF,KAAAA,IAAS,GAACsF,QAAAC,KAAA;AAAAvC,YAAAA,OAAAoC,QAAK/E,YAAUqF,QAAAC,KAAA;AAAAC,eAAA5B,UAIrB,MAAM/D,QAAQ4F,CAAAA,MAAKA,IAAI,CAAC;AAACvB,YAAAA,OAAAwB,CAAAA,QAAA;AAAA,cAAAC,MATxB/F,WAAW,GAACgG,OAQZhG,KAAAA,KAAUK,eAAe;AAAC0F,kBAAAD,IAAAG,KAAAC,IAAAA,YAAAf,QAAA,YAAAW,IAAAG,IAAAF,GAAA;AAAAC,mBAAAF,IAAAK,KAAAD,IAAAA,YAAAN,QAAA,YAAAE,IAAAK,IAAAH,IAAA;AAAA,iBAAAF;AAAAA,QAAA,GAAA;AAAA,UAAAG,GAAAG;AAAAA,UAAAD,GAAAC;AAAAA,QAAAA,CAAA;AAAAnC,+BAAAA;AAAA,eAAAgB;AAAAA,MAAA;AAAA,IAAA,CAAA,GAAAnC,QAAAC,KAAA;AAAA,WAAA1B;AAAAA,EAAA,GAAA;AAUlD;AAACgF,IAAAA,eAAA,CAAA,OAAA,CAAA;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataPreviewSection — paginated data table with export
|
|
3
|
+
* v3.1.0: Replaces LLM-generated markdown tables with exact source data
|
|
4
|
+
*
|
|
5
|
+
* @experimental
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Column types (number right-aligned, string left-aligned)
|
|
9
|
+
* - Pagination (configurable page size)
|
|
10
|
+
* - CSV / JSON export buttons
|
|
11
|
+
* - Source attribution + freshness label
|
|
12
|
+
* - Number formatting (FR locale)
|
|
13
|
+
*/
|
|
14
|
+
import type { DataPreviewContent } from '../types/chat-bus';
|
|
15
|
+
export interface DataPreviewSectionProps {
|
|
16
|
+
content: DataPreviewContent;
|
|
17
|
+
}
|
|
18
|
+
export declare function DataPreviewSection(props: DataPreviewSectionProps): import("solid-js").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=DataPreviewSection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataPreviewSection.d.ts","sourceRoot":"","sources":["../../src/components/DataPreviewSection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAqB,MAAM,mBAAmB,CAAA;AAE9E,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,kBAAkB,CAAA;CAC5B;AAmDD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,kCAuIhE"}
|