@seed-ship/mcp-ui-solid 4.3.1 → 4.3.3
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 +28 -0
- package/dist/components/UIResourceRenderer.cjs +295 -193
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +295 -193
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/package.json +1 -1
- package/src/components/UIResourceRenderer.tsx +104 -11
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -345,6 +345,7 @@ function TableRenderer(props: {
|
|
|
345
345
|
setSortDir('asc')
|
|
346
346
|
}
|
|
347
347
|
setClientPage(0)
|
|
348
|
+
setProgressivePages(1)
|
|
348
349
|
}
|
|
349
350
|
|
|
350
351
|
const sortedRows = createMemo(() => {
|
|
@@ -374,22 +375,70 @@ function TableRenderer(props: {
|
|
|
374
375
|
return sortDir() === 'asc' ? '\u2191' : '\u2193'
|
|
375
376
|
}
|
|
376
377
|
|
|
377
|
-
// ─── Client-side
|
|
378
|
+
// ─── Client-side search filter (v4.3.3) ─────────────────────
|
|
379
|
+
const [searchQuery, setSearchQuery] = createSignal('')
|
|
380
|
+
const [debouncedQuery, setDebouncedQuery] = createSignal('')
|
|
381
|
+
let searchTimer: ReturnType<typeof setTimeout> | null = null
|
|
382
|
+
|
|
383
|
+
const isSearchable = () => tableParams.searchable === true || (tableParams.searchable !== false && allRows().length > 10)
|
|
384
|
+
const searchPlaceholder = () => tableParams.searchPlaceholder || 'Rechercher dans le tableau...'
|
|
385
|
+
|
|
386
|
+
const handleSearch = (value: string) => {
|
|
387
|
+
setSearchQuery(value)
|
|
388
|
+
if (searchTimer) clearTimeout(searchTimer)
|
|
389
|
+
searchTimer = setTimeout(() => {
|
|
390
|
+
setDebouncedQuery(value)
|
|
391
|
+
setClientPage(0)
|
|
392
|
+
setProgressivePages(1)
|
|
393
|
+
}, 200)
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/** Normalize string for accent-insensitive matching */
|
|
397
|
+
const normalize = (s: string) => s.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase()
|
|
398
|
+
|
|
399
|
+
const filteredRows = createMemo(() => {
|
|
400
|
+
const q = normalize(debouncedQuery())
|
|
401
|
+
if (!q) return sortedRows()
|
|
402
|
+
const cols = columns()
|
|
403
|
+
return sortedRows().filter((row: any) =>
|
|
404
|
+
cols.some((col: any) => {
|
|
405
|
+
const val = row[col.key]
|
|
406
|
+
if (val == null) return false
|
|
407
|
+
return normalize(String(val)).includes(q)
|
|
408
|
+
})
|
|
409
|
+
)
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
// ─── Client-side pagination (v4.0.4, progressive mode v4.3.2) ─────
|
|
378
413
|
const clientPageSize = () => tableParams.pageSize ?? 25
|
|
379
414
|
const hasServerPagination = () => !!tableParams.pagination
|
|
415
|
+
const isProgressiveMode = () => !!tableParams.showAllLabel
|
|
380
416
|
const needsClientPagination = () =>
|
|
381
|
-
!hasServerPagination() && clientPageSize() > 0 &&
|
|
417
|
+
!hasServerPagination() && clientPageSize() > 0 && filteredRows().length > clientPageSize()
|
|
382
418
|
const [clientPage, setClientPage] = createSignal(tableParams.initialPage ?? 0)
|
|
383
|
-
|
|
419
|
+
// Progressive mode: track how many pages to show (append)
|
|
420
|
+
const [progressivePages, setProgressivePages] = createSignal(1)
|
|
421
|
+
const clientTotalPages = () => needsClientPagination() ? Math.ceil(filteredRows().length / clientPageSize()) : 1
|
|
384
422
|
const clientVisibleRows = createMemo(() => {
|
|
385
|
-
if (!needsClientPagination()) return
|
|
423
|
+
if (!needsClientPagination()) return filteredRows()
|
|
424
|
+
if (isProgressiveMode()) {
|
|
425
|
+
// Progressive: show first N * pageSize rows
|
|
426
|
+
return filteredRows().slice(0, progressivePages() * clientPageSize())
|
|
427
|
+
}
|
|
386
428
|
const start = clientPage() * clientPageSize()
|
|
387
|
-
return
|
|
429
|
+
return filteredRows().slice(start, start + clientPageSize())
|
|
388
430
|
})
|
|
389
|
-
const clientRangeStart = () => needsClientPagination()
|
|
431
|
+
const clientRangeStart = () => needsClientPagination()
|
|
432
|
+
? (isProgressiveMode() ? 1 : clientPage() * clientPageSize() + 1)
|
|
433
|
+
: 1
|
|
390
434
|
const clientRangeEnd = () => needsClientPagination()
|
|
391
|
-
?
|
|
392
|
-
|
|
435
|
+
? (isProgressiveMode()
|
|
436
|
+
? Math.min(progressivePages() * clientPageSize(), filteredRows().length)
|
|
437
|
+
: Math.min((clientPage() + 1) * clientPageSize(), filteredRows().length))
|
|
438
|
+
: filteredRows().length
|
|
439
|
+
const progressiveHasMore = () => isProgressiveMode() && needsClientPagination() && progressivePages() < clientTotalPages()
|
|
440
|
+
const progressiveRemaining = () => filteredRows().length - progressivePages() * clientPageSize()
|
|
441
|
+
const showMoreLabel = () => tableParams.showAllLabel || 'Show more'
|
|
393
442
|
|
|
394
443
|
// ─── Virtualization ──────────────────────────────────────
|
|
395
444
|
const [virtualizer, setVirtualizer] = createSignal<any>(null)
|
|
@@ -625,6 +674,33 @@ function TableRenderer(props: {
|
|
|
625
674
|
</h3>
|
|
626
675
|
</Show>
|
|
627
676
|
|
|
677
|
+
{/* Search input (v4.3.3) */}
|
|
678
|
+
<Show when={isSearchable()}>
|
|
679
|
+
<div class="relative mb-3">
|
|
680
|
+
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 pointer-events-none text-sm">{'\uD83D\uDD0D'}</span>
|
|
681
|
+
<input
|
|
682
|
+
type="text"
|
|
683
|
+
value={searchQuery()}
|
|
684
|
+
onInput={(e) => handleSearch(e.currentTarget.value)}
|
|
685
|
+
placeholder={searchPlaceholder()}
|
|
686
|
+
class="w-full pl-8 pr-8 py-1.5 text-sm border border-gray-200 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-400 focus:border-blue-400 focus:ring-1 focus:ring-blue-400 outline-none"
|
|
687
|
+
/>
|
|
688
|
+
<Show when={searchQuery()}>
|
|
689
|
+
<button
|
|
690
|
+
type="button"
|
|
691
|
+
onClick={() => { handleSearch(''); setSearchQuery(''); setDebouncedQuery('') }}
|
|
692
|
+
class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 text-sm"
|
|
693
|
+
aria-label="Clear search"
|
|
694
|
+
>×</button>
|
|
695
|
+
</Show>
|
|
696
|
+
</div>
|
|
697
|
+
<Show when={debouncedQuery() && filteredRows().length !== sortedRows().length}>
|
|
698
|
+
<p class="text-xs text-gray-500 dark:text-gray-400 mb-2">
|
|
699
|
+
{filteredRows().length} result{filteredRows().length !== 1 ? 's' : ''} on {sortedRows().length}
|
|
700
|
+
</p>
|
|
701
|
+
</Show>
|
|
702
|
+
</Show>
|
|
703
|
+
|
|
628
704
|
<div
|
|
629
705
|
ref={scrollContainerRef}
|
|
630
706
|
class="overflow-x-auto"
|
|
@@ -685,11 +761,11 @@ function TableRenderer(props: {
|
|
|
685
761
|
</div>
|
|
686
762
|
</Show>
|
|
687
763
|
|
|
688
|
-
{/* Client-side
|
|
689
|
-
<Show when={needsClientPagination()}>
|
|
764
|
+
{/* Client-side paged pagination (v4.0.4) */}
|
|
765
|
+
<Show when={needsClientPagination() && !isProgressiveMode()}>
|
|
690
766
|
<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400">
|
|
691
767
|
<span>
|
|
692
|
-
Showing {clientRangeStart()}–{clientRangeEnd()} of {
|
|
768
|
+
Showing {clientRangeStart()}–{clientRangeEnd()} of {filteredRows().length.toLocaleString('fr-FR')}
|
|
693
769
|
</span>
|
|
694
770
|
<div class="flex items-center gap-1">
|
|
695
771
|
<button
|
|
@@ -710,6 +786,23 @@ function TableRenderer(props: {
|
|
|
710
786
|
</div>
|
|
711
787
|
</div>
|
|
712
788
|
</Show>
|
|
789
|
+
|
|
790
|
+
{/* Client-side progressive pagination (v4.3.2) */}
|
|
791
|
+
<Show when={needsClientPagination() && isProgressiveMode()}>
|
|
792
|
+
<div class="mt-3 flex flex-col items-center gap-2 text-xs text-gray-500 dark:text-gray-400">
|
|
793
|
+
<span>
|
|
794
|
+
{clientRangeStart()}–{clientRangeEnd()} of {filteredRows().length.toLocaleString('fr-FR')}
|
|
795
|
+
</span>
|
|
796
|
+
<Show when={progressiveHasMore()}>
|
|
797
|
+
<button
|
|
798
|
+
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"
|
|
799
|
+
onClick={() => setProgressivePages(p => p + 1)}
|
|
800
|
+
>
|
|
801
|
+
{showMoreLabel()} ({Math.min(progressiveRemaining(), clientPageSize())} suivant{Math.min(progressiveRemaining(), clientPageSize()) > 1 ? 'es' : 'e'})
|
|
802
|
+
</button>
|
|
803
|
+
</Show>
|
|
804
|
+
</div>
|
|
805
|
+
</Show>
|
|
713
806
|
</div>
|
|
714
807
|
</div>
|
|
715
808
|
</ExpandableWrapper>
|