@seed-ship/mcp-ui-solid 4.3.6 → 4.3.8
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/components/UIResourceRenderer.cjs +264 -238
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts +6 -0
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +264 -238
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/package.json +1 -1
- package/src/components/UIResourceRenderer.tsx +76 -55
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -241,6 +241,25 @@ function ChartRenderer(props: {
|
|
|
241
241
|
/**
|
|
242
242
|
* Smart cell value renderer that handles markdown links and other formats
|
|
243
243
|
*/
|
|
244
|
+
/**
|
|
245
|
+
* Wrap matches of `query` in <mark> tags within an HTML string.
|
|
246
|
+
* Case-insensitive. Skips content inside HTML tag attributes to avoid corruption.
|
|
247
|
+
* v4.3.8
|
|
248
|
+
*/
|
|
249
|
+
export function highlightQuery(html: string, query: string): string {
|
|
250
|
+
const q = query.trim()
|
|
251
|
+
if (!q) return html
|
|
252
|
+
// Escape regex metacharacters
|
|
253
|
+
const escaped = q.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
254
|
+
const regex = new RegExp(`(${escaped})`, 'gi')
|
|
255
|
+
// Process text segments only (skip inside tags)
|
|
256
|
+
return html.replace(/(<[^>]+>)|([^<]+)/g, (_m, tag, text) => {
|
|
257
|
+
if (tag) return tag
|
|
258
|
+
if (!text) return ''
|
|
259
|
+
return text.replace(regex, '<mark class="bg-yellow-200 dark:bg-[#222F49] text-inherit rounded px-0.5">$1</mark>')
|
|
260
|
+
})
|
|
261
|
+
}
|
|
262
|
+
|
|
244
263
|
export function renderCellValue(value: any): string {
|
|
245
264
|
// Handle null/undefined
|
|
246
265
|
if (value === null || value === undefined) {
|
|
@@ -345,7 +364,6 @@ function TableRenderer(props: {
|
|
|
345
364
|
setSortDir('asc')
|
|
346
365
|
}
|
|
347
366
|
setClientPage(0)
|
|
348
|
-
setProgressivePages(1)
|
|
349
367
|
}
|
|
350
368
|
|
|
351
369
|
const sortedRows = createMemo(() => {
|
|
@@ -389,7 +407,6 @@ function TableRenderer(props: {
|
|
|
389
407
|
searchTimer = setTimeout(() => {
|
|
390
408
|
setDebouncedQuery(value)
|
|
391
409
|
setClientPage(0)
|
|
392
|
-
setProgressivePages(1)
|
|
393
410
|
}, 200)
|
|
394
411
|
}
|
|
395
412
|
|
|
@@ -409,39 +426,47 @@ function TableRenderer(props: {
|
|
|
409
426
|
)
|
|
410
427
|
})
|
|
411
428
|
|
|
412
|
-
// ─── Client-side pagination (v4.0.4,
|
|
429
|
+
// ─── Client-side pagination (v4.0.4, context-aware v4.3.4, selector v4.3.7) ─────
|
|
413
430
|
const isExpanded = useExpanded()
|
|
414
|
-
const
|
|
415
|
-
const
|
|
416
|
-
const
|
|
431
|
+
const defaultPageSize = () => tableParams.pageSize ?? 25
|
|
432
|
+
const chatDefault = () => tableParams.chatPageSize ?? Math.min(10, defaultPageSize())
|
|
433
|
+
const [userPageSize, setUserPageSize] = createSignal<number | null>(null) // null = use default
|
|
434
|
+
const clientPageSize = () => {
|
|
435
|
+
const ups = userPageSize()
|
|
436
|
+
if (ups !== null) return ups // user chose a size
|
|
437
|
+
return isExpanded() ? defaultPageSize() : chatDefault()
|
|
438
|
+
}
|
|
439
|
+
const showAll = () => userPageSize() === 0
|
|
417
440
|
const hasServerPagination = () => !!tableParams.pagination
|
|
418
|
-
const isProgressiveMode = () => !!tableParams.showAllLabel
|
|
419
441
|
const needsClientPagination = () =>
|
|
420
|
-
!hasServerPagination() && clientPageSize() > 0 && filteredRows().length > clientPageSize()
|
|
442
|
+
!hasServerPagination() && !showAll() && clientPageSize() > 0 && filteredRows().length > clientPageSize()
|
|
421
443
|
const [clientPage, setClientPage] = createSignal(tableParams.initialPage ?? 0)
|
|
422
|
-
// Progressive mode: track how many pages to show (append)
|
|
423
|
-
const [progressivePages, setProgressivePages] = createSignal(1)
|
|
424
444
|
const clientTotalPages = () => needsClientPagination() ? Math.ceil(filteredRows().length / clientPageSize()) : 1
|
|
425
445
|
const clientVisibleRows = createMemo(() => {
|
|
426
|
-
if (!needsClientPagination()) return filteredRows()
|
|
427
|
-
if (isProgressiveMode()) {
|
|
428
|
-
// Progressive: show first N * pageSize rows
|
|
429
|
-
return filteredRows().slice(0, progressivePages() * clientPageSize())
|
|
430
|
-
}
|
|
446
|
+
if (showAll() || !needsClientPagination()) return filteredRows()
|
|
431
447
|
const start = clientPage() * clientPageSize()
|
|
432
448
|
return filteredRows().slice(start, start + clientPageSize())
|
|
433
449
|
})
|
|
434
|
-
const clientRangeStart = () => needsClientPagination()
|
|
435
|
-
? (isProgressiveMode() ? 1 : clientPage() * clientPageSize() + 1)
|
|
436
|
-
: 1
|
|
450
|
+
const clientRangeStart = () => needsClientPagination() ? clientPage() * clientPageSize() + 1 : 1
|
|
437
451
|
const clientRangeEnd = () => needsClientPagination()
|
|
438
|
-
? (
|
|
439
|
-
? Math.min(progressivePages() * clientPageSize(), filteredRows().length)
|
|
440
|
-
: Math.min((clientPage() + 1) * clientPageSize(), filteredRows().length))
|
|
452
|
+
? Math.min((clientPage() + 1) * clientPageSize(), filteredRows().length)
|
|
441
453
|
: filteredRows().length
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
const
|
|
454
|
+
|
|
455
|
+
// Page size options for selector (fullscreen)
|
|
456
|
+
const pageSizeOptions = () => {
|
|
457
|
+
const total = filteredRows().length
|
|
458
|
+
const opts: Array<{ value: number; label: string }> = []
|
|
459
|
+
for (const n of [10, 30, 60, 100]) {
|
|
460
|
+
if (n < total) opts.push({ value: n, label: String(n) })
|
|
461
|
+
}
|
|
462
|
+
opts.push({ value: 0, label: 'All' })
|
|
463
|
+
return opts
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const handlePageSizeChange = (val: number) => {
|
|
467
|
+
setUserPageSize(val === 0 ? 0 : val)
|
|
468
|
+
setClientPage(0)
|
|
469
|
+
}
|
|
445
470
|
|
|
446
471
|
// ─── Virtualization ──────────────────────────────────────
|
|
447
472
|
const [virtualizer, setVirtualizer] = createSignal<any>(null)
|
|
@@ -586,7 +611,7 @@ function TableRenderer(props: {
|
|
|
586
611
|
<For each={tableParams.columns}>
|
|
587
612
|
{(column: any) => (
|
|
588
613
|
<td class="px-6 py-4 text-sm text-gray-700 dark:text-gray-200 whitespace-normal break-words leading-relaxed first:pl-6 last:pr-6">
|
|
589
|
-
<div innerHTML={renderCellValue(row[column.key])} />
|
|
614
|
+
<div innerHTML={highlightQuery(renderCellValue(row[column.key]), debouncedQuery())} />
|
|
590
615
|
</td>
|
|
591
616
|
)}
|
|
592
617
|
</For>
|
|
@@ -625,7 +650,7 @@ function TableRenderer(props: {
|
|
|
625
650
|
<For each={tableParams.columns}>
|
|
626
651
|
{(column: any) => (
|
|
627
652
|
<td class="px-6 py-4 text-sm text-gray-700 dark:text-gray-200 whitespace-normal break-words leading-relaxed first:pl-6 last:pr-6">
|
|
628
|
-
<div innerHTML={renderCellValue(row[column.key])} />
|
|
653
|
+
<div innerHTML={highlightQuery(renderCellValue(row[column.key]), debouncedQuery())} />
|
|
629
654
|
</td>
|
|
630
655
|
)}
|
|
631
656
|
</For>
|
|
@@ -639,7 +664,7 @@ function TableRenderer(props: {
|
|
|
639
664
|
|
|
640
665
|
return (
|
|
641
666
|
<ExpandableWrapper title={tableParams.title || 'Table'} copyData={getTableCSV()} copyLabel="Copy table (CSV)">
|
|
642
|
-
<div class=
|
|
667
|
+
<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 group ${isExpanded() ? '' : 'h-full'}`}>
|
|
643
668
|
<Show when={exportable} fallback={<CopyButton getText={getTableCSV} title="Copy table (CSV)" position="top-right" />}>
|
|
644
669
|
<div class="absolute right-10 top-2 z-10">
|
|
645
670
|
<button
|
|
@@ -710,8 +735,8 @@ function TableRenderer(props: {
|
|
|
710
735
|
style={
|
|
711
736
|
isVirtualizing()
|
|
712
737
|
? { 'max-height': '500px', 'overflow-y': 'auto' }
|
|
713
|
-
: clientVisibleRows().length > 8
|
|
714
|
-
? { 'max-height':
|
|
738
|
+
: !isExpanded() && clientVisibleRows().length > 8
|
|
739
|
+
? { 'max-height': '400px', 'overflow-y': 'auto' }
|
|
715
740
|
: {}
|
|
716
741
|
}
|
|
717
742
|
role="region"
|
|
@@ -722,13 +747,13 @@ function TableRenderer(props: {
|
|
|
722
747
|
class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border-separate border-spacing-0"
|
|
723
748
|
aria-labelledby={tableParams.title ? `${tableId}-title` : undefined}
|
|
724
749
|
>
|
|
725
|
-
<thead class="bg-gray-
|
|
750
|
+
<thead class="bg-gray-100 dark:bg-gray-900 sticky top-0 z-10">
|
|
726
751
|
<tr>
|
|
727
752
|
<For each={tableParams.columns}>
|
|
728
753
|
{(column: any) => (
|
|
729
754
|
<th
|
|
730
755
|
scope="col"
|
|
731
|
-
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider border-b border-gray-200 dark:border-gray-700 first:pl-6 last:pr-6 bg-gray-
|
|
756
|
+
class="px-6 py-3 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider border-b border-gray-200 dark:border-gray-700 first:pl-6 last:pr-6 bg-gray-100 dark:bg-gray-900 cursor-pointer select-none hover:bg-gray-200 dark:hover:bg-gray-800 transition-colors"
|
|
732
757
|
style={column.width ? { width: column.width } : {}}
|
|
733
758
|
on:click={() => handleSort(column.key)}
|
|
734
759
|
title={`Sort by ${column.label}`}
|
|
@@ -770,48 +795,44 @@ function TableRenderer(props: {
|
|
|
770
795
|
</div>
|
|
771
796
|
</Show>
|
|
772
797
|
|
|
773
|
-
{/* Client-side
|
|
774
|
-
<Show when={needsClientPagination()
|
|
798
|
+
{/* Client-side pagination (v4.3.7) */}
|
|
799
|
+
<Show when={needsClientPagination()}>
|
|
775
800
|
<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400">
|
|
776
801
|
<span>
|
|
777
|
-
|
|
802
|
+
{clientRangeStart()}–{clientRangeEnd()} / {filteredRows().length.toLocaleString('fr-FR')}
|
|
778
803
|
</span>
|
|
779
|
-
<div class="flex items-center gap-
|
|
804
|
+
<div class="flex items-center gap-2">
|
|
780
805
|
<button
|
|
781
806
|
class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
|
|
782
807
|
disabled={clientPage() === 0}
|
|
783
808
|
onClick={() => setClientPage(p => p - 1)}
|
|
784
809
|
>
|
|
785
|
-
◀
|
|
810
|
+
◀
|
|
786
811
|
</button>
|
|
787
|
-
<span
|
|
812
|
+
<span>{clientPage() + 1} / {clientTotalPages()}</span>
|
|
788
813
|
<button
|
|
789
814
|
class="px-2 py-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
|
|
790
815
|
disabled={clientPage() >= clientTotalPages() - 1}
|
|
791
816
|
onClick={() => setClientPage(p => p + 1)}
|
|
792
817
|
>
|
|
793
|
-
|
|
818
|
+
▶
|
|
794
819
|
</button>
|
|
820
|
+
{/* Page size selector — fullscreen only */}
|
|
821
|
+
<Show when={isExpanded() && filteredRows().length > 10}>
|
|
822
|
+
<select
|
|
823
|
+
class="ml-2 px-1 py-0.5 text-xs border border-gray-200 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300"
|
|
824
|
+
value={clientPageSize()}
|
|
825
|
+
onChange={(e) => handlePageSizeChange(Number(e.currentTarget.value))}
|
|
826
|
+
>
|
|
827
|
+
<For each={pageSizeOptions()}>
|
|
828
|
+
{(opt) => <option value={opt.value}>{opt.label}</option>}
|
|
829
|
+
</For>
|
|
830
|
+
</select>
|
|
831
|
+
<span class="text-gray-400">/ page</span>
|
|
832
|
+
</Show>
|
|
795
833
|
</div>
|
|
796
834
|
</div>
|
|
797
835
|
</Show>
|
|
798
|
-
|
|
799
|
-
{/* Client-side progressive pagination (v4.3.2) */}
|
|
800
|
-
<Show when={needsClientPagination() && isProgressiveMode()}>
|
|
801
|
-
<div class="mt-3 flex flex-col items-center gap-2 text-xs text-gray-500 dark:text-gray-400">
|
|
802
|
-
<span>
|
|
803
|
-
{clientRangeStart()}–{clientRangeEnd()} of {filteredRows().length.toLocaleString('fr-FR')}
|
|
804
|
-
</span>
|
|
805
|
-
<Show when={progressiveHasMore()}>
|
|
806
|
-
<button
|
|
807
|
-
class="px-4 py-1.5 rounded-md bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 text-gray-700 dark:text-gray-300 transition-colors"
|
|
808
|
-
onClick={() => setProgressivePages(p => p + 1)}
|
|
809
|
-
>
|
|
810
|
-
{showMoreLabel()} ({Math.min(progressiveRemaining(), clientPageSize())} suivant{Math.min(progressiveRemaining(), clientPageSize()) > 1 ? 'es' : 'e'})
|
|
811
|
-
</button>
|
|
812
|
-
</Show>
|
|
813
|
-
</div>
|
|
814
|
-
</Show>
|
|
815
836
|
</div>
|
|
816
837
|
</div>
|
|
817
838
|
</ExpandableWrapper>
|