@seed-ship/mcp-ui-solid 4.3.2 → 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 +15 -0
- package/dist/components/UIResourceRenderer.cjs +274 -208
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +274 -208
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/package.json +1 -1
- package/src/components/UIResourceRenderer.tsx +72 -11
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -375,35 +375,69 @@ function TableRenderer(props: {
|
|
|
375
375
|
return sortDir() === 'asc' ? '\u2191' : '\u2193'
|
|
376
376
|
}
|
|
377
377
|
|
|
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
|
+
|
|
378
412
|
// ─── Client-side pagination (v4.0.4, progressive mode v4.3.2) ─────
|
|
379
413
|
const clientPageSize = () => tableParams.pageSize ?? 25
|
|
380
414
|
const hasServerPagination = () => !!tableParams.pagination
|
|
381
415
|
const isProgressiveMode = () => !!tableParams.showAllLabel
|
|
382
416
|
const needsClientPagination = () =>
|
|
383
|
-
!hasServerPagination() && clientPageSize() > 0 &&
|
|
417
|
+
!hasServerPagination() && clientPageSize() > 0 && filteredRows().length > clientPageSize()
|
|
384
418
|
const [clientPage, setClientPage] = createSignal(tableParams.initialPage ?? 0)
|
|
385
419
|
// Progressive mode: track how many pages to show (append)
|
|
386
420
|
const [progressivePages, setProgressivePages] = createSignal(1)
|
|
387
|
-
const clientTotalPages = () => needsClientPagination() ? Math.ceil(
|
|
421
|
+
const clientTotalPages = () => needsClientPagination() ? Math.ceil(filteredRows().length / clientPageSize()) : 1
|
|
388
422
|
const clientVisibleRows = createMemo(() => {
|
|
389
|
-
if (!needsClientPagination()) return
|
|
423
|
+
if (!needsClientPagination()) return filteredRows()
|
|
390
424
|
if (isProgressiveMode()) {
|
|
391
425
|
// Progressive: show first N * pageSize rows
|
|
392
|
-
return
|
|
426
|
+
return filteredRows().slice(0, progressivePages() * clientPageSize())
|
|
393
427
|
}
|
|
394
428
|
const start = clientPage() * clientPageSize()
|
|
395
|
-
return
|
|
429
|
+
return filteredRows().slice(start, start + clientPageSize())
|
|
396
430
|
})
|
|
397
431
|
const clientRangeStart = () => needsClientPagination()
|
|
398
432
|
? (isProgressiveMode() ? 1 : clientPage() * clientPageSize() + 1)
|
|
399
433
|
: 1
|
|
400
434
|
const clientRangeEnd = () => needsClientPagination()
|
|
401
435
|
? (isProgressiveMode()
|
|
402
|
-
? Math.min(progressivePages() * clientPageSize(),
|
|
403
|
-
: Math.min((clientPage() + 1) * clientPageSize(),
|
|
404
|
-
:
|
|
436
|
+
? Math.min(progressivePages() * clientPageSize(), filteredRows().length)
|
|
437
|
+
: Math.min((clientPage() + 1) * clientPageSize(), filteredRows().length))
|
|
438
|
+
: filteredRows().length
|
|
405
439
|
const progressiveHasMore = () => isProgressiveMode() && needsClientPagination() && progressivePages() < clientTotalPages()
|
|
406
|
-
const progressiveRemaining = () =>
|
|
440
|
+
const progressiveRemaining = () => filteredRows().length - progressivePages() * clientPageSize()
|
|
407
441
|
const showMoreLabel = () => tableParams.showAllLabel || 'Show more'
|
|
408
442
|
|
|
409
443
|
// ─── Virtualization ──────────────────────────────────────
|
|
@@ -640,6 +674,33 @@ function TableRenderer(props: {
|
|
|
640
674
|
</h3>
|
|
641
675
|
</Show>
|
|
642
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
|
+
|
|
643
704
|
<div
|
|
644
705
|
ref={scrollContainerRef}
|
|
645
706
|
class="overflow-x-auto"
|
|
@@ -704,7 +765,7 @@ function TableRenderer(props: {
|
|
|
704
765
|
<Show when={needsClientPagination() && !isProgressiveMode()}>
|
|
705
766
|
<div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400">
|
|
706
767
|
<span>
|
|
707
|
-
Showing {clientRangeStart()}–{clientRangeEnd()} of {
|
|
768
|
+
Showing {clientRangeStart()}–{clientRangeEnd()} of {filteredRows().length.toLocaleString('fr-FR')}
|
|
708
769
|
</span>
|
|
709
770
|
<div class="flex items-center gap-1">
|
|
710
771
|
<button
|
|
@@ -730,7 +791,7 @@ function TableRenderer(props: {
|
|
|
730
791
|
<Show when={needsClientPagination() && isProgressiveMode()}>
|
|
731
792
|
<div class="mt-3 flex flex-col items-center gap-2 text-xs text-gray-500 dark:text-gray-400">
|
|
732
793
|
<span>
|
|
733
|
-
{clientRangeStart()}–{clientRangeEnd()} of {
|
|
794
|
+
{clientRangeStart()}–{clientRangeEnd()} of {filteredRows().length.toLocaleString('fr-FR')}
|
|
734
795
|
</span>
|
|
735
796
|
<Show when={progressiveHasMore()}>
|
|
736
797
|
<button
|