@webmcp-auto-ui/ui 2.5.19 → 2.5.21
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webmcp-auto-ui/ui",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.21",
|
|
4
4
|
"description": "Svelte 5 UI components — primitives, widgets, window manager",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"@types/d3": "^7.4.3",
|
|
51
51
|
"bits-ui": "^2.17.2",
|
|
52
52
|
"clsx": "^2.1.1",
|
|
53
|
+
"html-to-image": "^1.11.13",
|
|
53
54
|
"tailwind-merge": "^3.5.0",
|
|
54
55
|
"tailwind-variants": "^3.2.2"
|
|
55
56
|
}
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
compressHistory?: boolean;
|
|
12
12
|
compressPreview?: number;
|
|
13
13
|
contextRAGEnabled?: boolean;
|
|
14
|
+
ragResidueSize?: number;
|
|
14
15
|
cacheEnabled?: boolean;
|
|
15
16
|
temperature?: number;
|
|
16
17
|
topK?: number;
|
|
@@ -29,6 +30,7 @@
|
|
|
29
30
|
compressHistory = $bindable(false),
|
|
30
31
|
compressPreview = $bindable(500),
|
|
31
32
|
contextRAGEnabled = $bindable(false),
|
|
33
|
+
ragResidueSize = $bindable(200),
|
|
32
34
|
cacheEnabled = $bindable(true),
|
|
33
35
|
temperature = $bindable(0.7),
|
|
34
36
|
topK = $bindable(10),
|
|
@@ -210,7 +212,7 @@
|
|
|
210
212
|
<div>
|
|
211
213
|
<label class="flex items-center gap-2 cursor-pointer select-none mb-1">
|
|
212
214
|
<input type="checkbox" bind:checked={compressHistory} class="accent-accent w-3.5 h-3.5" />
|
|
213
|
-
<span class="text-[9px] font-mono text-text2 uppercase tracking-wider">
|
|
215
|
+
<span class="text-[9px] font-mono text-text2 uppercase tracking-wider">Tronquer l'historique</span>
|
|
214
216
|
</label>
|
|
215
217
|
{#if compressHistory}
|
|
216
218
|
<div class="flex justify-between items-baseline mb-1">
|
|
@@ -230,9 +232,18 @@
|
|
|
230
232
|
<span class="text-[8px] font-mono text-text2/40 ml-auto">experimental</span>
|
|
231
233
|
</label>
|
|
232
234
|
{#if contextRAGEnabled}
|
|
233
|
-
<div class="text-[9px] font-mono text-text2/60 pl-5">
|
|
235
|
+
<div class="text-[9px] font-mono text-text2/60 pl-5 mb-2">
|
|
234
236
|
Semantic context compaction via vector embeddings
|
|
235
237
|
</div>
|
|
238
|
+
<div class="pl-5">
|
|
239
|
+
<div class="flex justify-between items-baseline mb-1">
|
|
240
|
+
<span class="text-[9px] font-mono text-text2 uppercase tracking-wider">Résidu inline (chars)</span>
|
|
241
|
+
<span class="font-mono text-xs text-text1">{ragResidueSize}</span>
|
|
242
|
+
</div>
|
|
243
|
+
<input type="range" bind:value={ragResidueSize}
|
|
244
|
+
min={0} max={2000} step={50}
|
|
245
|
+
class="w-full accent-accent" />
|
|
246
|
+
</div>
|
|
236
247
|
{/if}
|
|
237
248
|
</section>
|
|
238
249
|
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
* Determines the best export format based on widget type and triggers a file download.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { toPng } from 'html-to-image';
|
|
7
|
+
|
|
8
|
+
const TARGET_PNG_WIDTH = 2048;
|
|
9
|
+
|
|
6
10
|
// ── helpers ──────────────────────────────────────────────────────────────────
|
|
7
11
|
|
|
8
12
|
function timestamp(): string {
|
|
@@ -81,54 +85,37 @@ function exportCsv(type: string, data: Record<string, unknown>): void {
|
|
|
81
85
|
downloadFile(lines.join('\r\n'), filename(type, 'csv'), 'text/csv;charset=utf-8');
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
// ── PNG via
|
|
85
|
-
|
|
86
|
-
function svgToPng(svgEl: SVGElement, name: string): void {
|
|
87
|
-
// Inline computed styles on the SVG to improve fidelity when rendered off-DOM
|
|
88
|
-
const svgData = new XMLSerializer().serializeToString(svgEl);
|
|
89
|
-
const canvas = document.createElement('canvas');
|
|
90
|
-
const ctx = canvas.getContext('2d')!;
|
|
91
|
-
const img = new Image();
|
|
92
|
-
const blob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
|
|
93
|
-
const url = URL.createObjectURL(blob);
|
|
94
|
-
img.onload = () => {
|
|
95
|
-
canvas.width = img.naturalWidth || svgEl.clientWidth || 800;
|
|
96
|
-
canvas.height = img.naturalHeight || svgEl.clientHeight || 600;
|
|
97
|
-
ctx.drawImage(img, 0, 0);
|
|
98
|
-
const pngUrl = canvas.toDataURL('image/png');
|
|
99
|
-
downloadFile(pngUrl, name);
|
|
100
|
-
URL.revokeObjectURL(url);
|
|
101
|
-
};
|
|
102
|
-
img.onerror = () => {
|
|
103
|
-
// Fallback: try canvas.toDataURL directly if available
|
|
104
|
-
URL.revokeObjectURL(url);
|
|
105
|
-
};
|
|
106
|
-
img.src = url;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function canvasToPng(canvasEl: HTMLCanvasElement, name: string): void {
|
|
110
|
-
const url = canvasEl.toDataURL('image/png');
|
|
111
|
-
downloadFile(url, name);
|
|
112
|
-
}
|
|
88
|
+
// ── PNG via html-to-image ─────────────────────────────────────────────────────
|
|
113
89
|
|
|
114
|
-
function exportPng(type: string, containerEl: HTMLElement): void {
|
|
90
|
+
async function exportPng(type: string, containerEl: HTMLElement): Promise<void> {
|
|
115
91
|
const name = filename(type, 'png');
|
|
116
|
-
|
|
117
|
-
//
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
92
|
+
// Use scroll dimensions to capture the FULL content, not just the visible viewport.
|
|
93
|
+
// Widgets like data-table can overflow horizontally; clientWidth would crop them.
|
|
94
|
+
const scrollW = Math.max(containerEl.scrollWidth, containerEl.clientWidth, 1);
|
|
95
|
+
const scrollH = Math.max(containerEl.scrollHeight, containerEl.clientHeight, 1);
|
|
96
|
+
const pixelRatio = TARGET_PNG_WIDTH / scrollW;
|
|
97
|
+
|
|
98
|
+
const bg = (typeof document !== 'undefined'
|
|
99
|
+
? getComputedStyle(document.documentElement).getPropertyValue('--color-surface').trim()
|
|
100
|
+
: '') || '#ffffff';
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const dataUrl = await toPng(containerEl, {
|
|
104
|
+
pixelRatio,
|
|
105
|
+
width: scrollW,
|
|
106
|
+
height: scrollH,
|
|
107
|
+
cacheBust: true,
|
|
108
|
+
backgroundColor: bg,
|
|
109
|
+
style: {
|
|
110
|
+
// Force children visibility inside the cloned node so overflow content renders
|
|
111
|
+
overflow: 'visible',
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
downloadFile(dataUrl, name);
|
|
115
|
+
} catch (err) {
|
|
116
|
+
console.error('[exportWidget] PNG export failed for type', type, err);
|
|
117
|
+
alert(`Export PNG impossible : ${err instanceof Error ? err.message : String(err)}`);
|
|
122
118
|
}
|
|
123
|
-
|
|
124
|
-
// Fall back to SVG
|
|
125
|
-
const svgEl = containerEl.querySelector('svg');
|
|
126
|
-
if (svgEl) {
|
|
127
|
-
svgToPng(svgEl as SVGElement, name);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
console.warn('[exportWidget] No <canvas> or <svg> found in container for type:', type);
|
|
132
119
|
}
|
|
133
120
|
|
|
134
121
|
// ── Markdown ──────────────────────────────────────────────────────────────────
|
|
@@ -209,53 +196,39 @@ const HTML_FMT: ExportFormat = { id: 'html', label: 'HTML', icon: '🌐' };
|
|
|
209
196
|
* Return the list of export formats available for a given widget type.
|
|
210
197
|
*/
|
|
211
198
|
export function getExportFormats(type: string, containerEl?: HTMLElement): ExportFormat[] {
|
|
199
|
+
const base: ExportFormat[] = [PNG_FMT, JSON_FMT];
|
|
212
200
|
switch (type) {
|
|
213
201
|
case 'data-table':
|
|
214
202
|
case 'grid-data':
|
|
215
203
|
case 'kv':
|
|
216
204
|
case 'list':
|
|
217
|
-
return [CSV_FMT,
|
|
218
|
-
|
|
219
|
-
case 'chart':
|
|
220
|
-
case 'chart-rich':
|
|
221
|
-
case 'sankey':
|
|
222
|
-
case 'd3':
|
|
223
|
-
case 'hemicycle':
|
|
224
|
-
case 'map':
|
|
225
|
-
return [PNG_FMT, JSON_FMT];
|
|
226
|
-
|
|
205
|
+
return [CSV_FMT, ...base];
|
|
227
206
|
case 'text':
|
|
228
207
|
case 'code':
|
|
229
208
|
case 'log':
|
|
230
|
-
return [MD_FMT,
|
|
231
|
-
|
|
209
|
+
return [MD_FMT, ...base];
|
|
232
210
|
case 'js-sandbox':
|
|
233
|
-
return [HTML_FMT,
|
|
234
|
-
|
|
235
|
-
case 'gallery':
|
|
236
|
-
case 'carousel':
|
|
237
|
-
return [JSON_FMT];
|
|
238
|
-
|
|
211
|
+
return [HTML_FMT, ...base];
|
|
239
212
|
default:
|
|
240
|
-
return
|
|
213
|
+
return base;
|
|
241
214
|
}
|
|
242
215
|
}
|
|
243
216
|
|
|
244
217
|
/**
|
|
245
218
|
* Export a widget in a specific format chosen by the user.
|
|
246
219
|
*/
|
|
247
|
-
export function exportWidgetAs(
|
|
220
|
+
export async function exportWidgetAs(
|
|
248
221
|
format: string,
|
|
249
222
|
type: string,
|
|
250
223
|
data: Record<string, unknown>,
|
|
251
224
|
containerEl?: HTMLElement
|
|
252
|
-
): void {
|
|
225
|
+
): Promise<void> {
|
|
253
226
|
switch (format) {
|
|
254
227
|
case 'csv':
|
|
255
228
|
exportCsv(type, data);
|
|
256
229
|
break;
|
|
257
230
|
case 'png':
|
|
258
|
-
if (containerEl) exportPng(type, containerEl);
|
|
231
|
+
if (containerEl) await exportPng(type, containerEl);
|
|
259
232
|
else console.warn('[exportWidgetAs] containerEl required for PNG export');
|
|
260
233
|
break;
|
|
261
234
|
case 'md':
|
|
@@ -281,11 +254,11 @@ export function exportWidgetAs(
|
|
|
281
254
|
* @param data The widget's data object
|
|
282
255
|
* @param containerEl Optional DOM container — required for PNG exports
|
|
283
256
|
*/
|
|
284
|
-
export function exportWidget(
|
|
257
|
+
export async function exportWidget(
|
|
285
258
|
type: string,
|
|
286
259
|
data: Record<string, unknown>,
|
|
287
260
|
containerEl?: HTMLElement
|
|
288
|
-
): void {
|
|
261
|
+
): Promise<void> {
|
|
289
262
|
switch (type) {
|
|
290
263
|
// ── CSV ──
|
|
291
264
|
case 'data-table':
|
|
@@ -303,7 +276,7 @@ export function exportWidget(
|
|
|
303
276
|
case 'hemicycle':
|
|
304
277
|
case 'map':
|
|
305
278
|
if (containerEl) {
|
|
306
|
-
exportPng(type, containerEl);
|
|
279
|
+
await exportPng(type, containerEl);
|
|
307
280
|
} else {
|
|
308
281
|
console.warn('[exportWidget] containerEl required for PNG export of type:', type);
|
|
309
282
|
}
|