@seed-ship/mcp-ui-solid 4.3.5 → 4.3.7

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": "@seed-ship/mcp-ui-solid",
3
- "version": "4.3.5",
3
+ "version": "4.3.7",
4
4
  "description": "SolidJS components for rendering MCP-generated UI resources",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -345,7 +345,6 @@ function TableRenderer(props: {
345
345
  setSortDir('asc')
346
346
  }
347
347
  setClientPage(0)
348
- setProgressivePages(1)
349
348
  }
350
349
 
351
350
  const sortedRows = createMemo(() => {
@@ -389,7 +388,6 @@ function TableRenderer(props: {
389
388
  searchTimer = setTimeout(() => {
390
389
  setDebouncedQuery(value)
391
390
  setClientPage(0)
392
- setProgressivePages(1)
393
391
  }, 200)
394
392
  }
395
393
 
@@ -409,39 +407,47 @@ function TableRenderer(props: {
409
407
  )
410
408
  })
411
409
 
412
- // ─── Client-side pagination (v4.0.4, progressive v4.3.2, context-aware v4.3.4) ─────
410
+ // ─── Client-side pagination (v4.0.4, context-aware v4.3.4, selector v4.3.7) ─────
413
411
  const isExpanded = useExpanded()
414
- const fullPageSize = () => tableParams.pageSize ?? 25
415
- const chatPageSize = () => tableParams.chatPageSize ?? Math.min(10, fullPageSize())
416
- const clientPageSize = () => isExpanded() ? fullPageSize() : chatPageSize()
412
+ const defaultPageSize = () => tableParams.pageSize ?? 25
413
+ const chatDefault = () => tableParams.chatPageSize ?? Math.min(10, defaultPageSize())
414
+ const [userPageSize, setUserPageSize] = createSignal<number | null>(null) // null = use default
415
+ const clientPageSize = () => {
416
+ const ups = userPageSize()
417
+ if (ups !== null) return ups // user chose a size
418
+ return isExpanded() ? defaultPageSize() : chatDefault()
419
+ }
420
+ const showAll = () => userPageSize() === 0
417
421
  const hasServerPagination = () => !!tableParams.pagination
418
- const isProgressiveMode = () => !!tableParams.showAllLabel
419
422
  const needsClientPagination = () =>
420
- !hasServerPagination() && clientPageSize() > 0 && filteredRows().length > clientPageSize()
423
+ !hasServerPagination() && !showAll() && clientPageSize() > 0 && filteredRows().length > clientPageSize()
421
424
  const [clientPage, setClientPage] = createSignal(tableParams.initialPage ?? 0)
422
- // Progressive mode: track how many pages to show (append)
423
- const [progressivePages, setProgressivePages] = createSignal(1)
424
425
  const clientTotalPages = () => needsClientPagination() ? Math.ceil(filteredRows().length / clientPageSize()) : 1
425
426
  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
- }
427
+ if (showAll() || !needsClientPagination()) return filteredRows()
431
428
  const start = clientPage() * clientPageSize()
432
429
  return filteredRows().slice(start, start + clientPageSize())
433
430
  })
434
- const clientRangeStart = () => needsClientPagination()
435
- ? (isProgressiveMode() ? 1 : clientPage() * clientPageSize() + 1)
436
- : 1
431
+ const clientRangeStart = () => needsClientPagination() ? clientPage() * clientPageSize() + 1 : 1
437
432
  const clientRangeEnd = () => needsClientPagination()
438
- ? (isProgressiveMode()
439
- ? Math.min(progressivePages() * clientPageSize(), filteredRows().length)
440
- : Math.min((clientPage() + 1) * clientPageSize(), filteredRows().length))
433
+ ? Math.min((clientPage() + 1) * clientPageSize(), filteredRows().length)
441
434
  : filteredRows().length
442
- const progressiveHasMore = () => isProgressiveMode() && needsClientPagination() && progressivePages() < clientTotalPages()
443
- const progressiveRemaining = () => filteredRows().length - progressivePages() * clientPageSize()
444
- const showMoreLabel = () => tableParams.showAllLabel || 'Show more'
435
+
436
+ // Page size options for selector (fullscreen)
437
+ const pageSizeOptions = () => {
438
+ const total = filteredRows().length
439
+ const opts: Array<{ value: number; label: string }> = []
440
+ for (const n of [10, 30, 60, 100]) {
441
+ if (n < total) opts.push({ value: n, label: String(n) })
442
+ }
443
+ opts.push({ value: 0, label: 'All' })
444
+ return opts
445
+ }
446
+
447
+ const handlePageSizeChange = (val: number) => {
448
+ setUserPageSize(val === 0 ? 0 : val)
449
+ setClientPage(0)
450
+ }
445
451
 
446
452
  // ─── Virtualization ──────────────────────────────────────
447
453
  const [virtualizer, setVirtualizer] = createSignal<any>(null)
@@ -686,7 +692,7 @@ function TableRenderer(props: {
686
692
  value={searchQuery()}
687
693
  onInput={(e) => handleSearch(e.currentTarget.value)}
688
694
  placeholder={searchPlaceholder()}
689
- 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"
695
+ class="w-full max-w-xs min-w-[200px] 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"
690
696
  />
691
697
  <Show when={searchQuery()}>
692
698
  <button
@@ -711,8 +717,10 @@ function TableRenderer(props: {
711
717
  isVirtualizing()
712
718
  ? { 'max-height': '500px', 'overflow-y': 'auto' }
713
719
  : clientVisibleRows().length > 8
714
- ? { 'max-height': isExpanded() ? '70vh' : '400px', 'overflow-y': 'auto' }
715
- : {}
720
+ ? { 'max-height': isExpanded() ? 'calc(100vh - 180px)' : '400px', 'overflow-y': 'auto' }
721
+ : isExpanded()
722
+ ? { 'max-height': 'calc(100vh - 180px)', 'overflow-y': 'auto' }
723
+ : {}
716
724
  }
717
725
  role="region"
718
726
  aria-label={tableParams.title || 'Data table'}
@@ -722,13 +730,13 @@ function TableRenderer(props: {
722
730
  class="min-w-full divide-y divide-gray-200 dark:divide-gray-700 border-separate border-spacing-0"
723
731
  aria-labelledby={tableParams.title ? `${tableId}-title` : undefined}
724
732
  >
725
- <thead class="bg-gray-50 dark:bg-gray-900/50 sticky top-0 z-10">
733
+ <thead class="bg-gray-100 dark:bg-gray-900 sticky top-0 z-10">
726
734
  <tr>
727
735
  <For each={tableParams.columns}>
728
736
  {(column: any) => (
729
737
  <th
730
738
  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-50 dark:bg-gray-900/50 cursor-pointer select-none hover:bg-gray-100 dark:hover:bg-gray-800/50 transition-colors"
739
+ 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
740
  style={column.width ? { width: column.width } : {}}
733
741
  on:click={() => handleSort(column.key)}
734
742
  title={`Sort by ${column.label}`}
@@ -770,48 +778,44 @@ function TableRenderer(props: {
770
778
  </div>
771
779
  </Show>
772
780
 
773
- {/* Client-side paged pagination (v4.0.4) */}
774
- <Show when={needsClientPagination() && !isProgressiveMode()}>
781
+ {/* Client-side pagination (v4.3.7) */}
782
+ <Show when={needsClientPagination()}>
775
783
  <div class="mt-3 flex items-center justify-between text-xs text-gray-500 dark:text-gray-400">
776
784
  <span>
777
- Showing {clientRangeStart()}&ndash;{clientRangeEnd()} of {filteredRows().length.toLocaleString('fr-FR')}
785
+ {clientRangeStart()}&ndash;{clientRangeEnd()} / {filteredRows().length.toLocaleString('fr-FR')}
778
786
  </span>
779
- <div class="flex items-center gap-1">
787
+ <div class="flex items-center gap-2">
780
788
  <button
781
789
  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
790
  disabled={clientPage() === 0}
783
791
  onClick={() => setClientPage(p => p - 1)}
784
792
  >
785
- &#x25C0; Prev
793
+ &#x25C0;
786
794
  </button>
787
- <span class="px-2">Page {clientPage() + 1} / {clientTotalPages()}</span>
795
+ <span>{clientPage() + 1} / {clientTotalPages()}</span>
788
796
  <button
789
797
  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
798
  disabled={clientPage() >= clientTotalPages() - 1}
791
799
  onClick={() => setClientPage(p => p + 1)}
792
800
  >
793
- Next &#x25B6;
801
+ &#x25B6;
794
802
  </button>
803
+ {/* Page size selector — fullscreen only */}
804
+ <Show when={isExpanded() && filteredRows().length > 10}>
805
+ <select
806
+ 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"
807
+ value={clientPageSize()}
808
+ onChange={(e) => handlePageSizeChange(Number(e.currentTarget.value))}
809
+ >
810
+ <For each={pageSizeOptions()}>
811
+ {(opt) => <option value={opt.value}>{opt.label}</option>}
812
+ </For>
813
+ </select>
814
+ <span class="text-gray-400">/ page</span>
815
+ </Show>
795
816
  </div>
796
817
  </div>
797
818
  </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()}&ndash;{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
819
  </div>
816
820
  </div>
817
821
  </ExpandableWrapper>