@seed-ship/mcp-ui-solid 4.0.4 → 4.0.6
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 +235 -175
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +236 -176
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/package.json +1 -1
- package/src/components/UIResourceRenderer.tsx +69 -13
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -330,30 +330,74 @@ function TableRenderer(props: {
|
|
|
330
330
|
const tableParams = props.component.params as any
|
|
331
331
|
let scrollContainerRef: HTMLDivElement | undefined
|
|
332
332
|
|
|
333
|
-
// Client-side
|
|
333
|
+
// ─── Client-side sorting (v4.0.5) ────────────────────────
|
|
334
|
+
const allRows = () => tableParams.rows || []
|
|
335
|
+
const columns = () => tableParams.columns || []
|
|
336
|
+
const [sortKey, setSortKey] = createSignal<string | null>(null)
|
|
337
|
+
const [sortDir, setSortDir] = createSignal<'asc' | 'desc' | null>(null)
|
|
338
|
+
|
|
339
|
+
const handleSort = (key: string) => {
|
|
340
|
+
if (sortKey() === key) {
|
|
341
|
+
if (sortDir() === 'asc') setSortDir('desc')
|
|
342
|
+
else { setSortKey(null); setSortDir(null) }
|
|
343
|
+
} else {
|
|
344
|
+
setSortKey(key)
|
|
345
|
+
setSortDir('asc')
|
|
346
|
+
}
|
|
347
|
+
setClientPage(0)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const sortedRows = createMemo(() => {
|
|
351
|
+
const r = allRows()
|
|
352
|
+
const key = sortKey()
|
|
353
|
+
const dir = sortDir()
|
|
354
|
+
if (!key || !dir) return r
|
|
355
|
+
const col = columns().find((c: any) => c.key === key)
|
|
356
|
+
const isNum = col?.type === 'number' || (r.length > 0 && typeof r[0]?.[key] === 'number')
|
|
357
|
+
return [...r].sort((a: any, b: any) => {
|
|
358
|
+
const va = a[key], vb = b[key]
|
|
359
|
+
if (va == null && vb == null) return 0
|
|
360
|
+
if (va == null) return 1
|
|
361
|
+
if (vb == null) return -1
|
|
362
|
+
let cmp: number
|
|
363
|
+
if (isNum) {
|
|
364
|
+
cmp = (Number(va) || 0) - (Number(vb) || 0)
|
|
365
|
+
} else {
|
|
366
|
+
cmp = String(va).localeCompare(String(vb), 'fr', { sensitivity: 'base' })
|
|
367
|
+
}
|
|
368
|
+
return dir === 'desc' ? -cmp : cmp
|
|
369
|
+
})
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
const sortIndicator = (key: string) => {
|
|
373
|
+
if (sortKey() !== key) return '\u2195'
|
|
374
|
+
return sortDir() === 'asc' ? '\u2191' : '\u2193'
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// ─── Client-side pagination (v4.0.4) ─────────────────────
|
|
334
378
|
const clientPageSize = () => tableParams.pageSize ?? 25
|
|
335
379
|
const hasServerPagination = () => !!tableParams.pagination
|
|
336
|
-
const allRows = () => tableParams.rows || []
|
|
337
380
|
const needsClientPagination = () =>
|
|
338
|
-
!hasServerPagination() && clientPageSize() > 0 &&
|
|
381
|
+
!hasServerPagination() && clientPageSize() > 0 && sortedRows().length > clientPageSize()
|
|
339
382
|
const [clientPage, setClientPage] = createSignal(tableParams.initialPage ?? 0)
|
|
340
|
-
const clientTotalPages = () => needsClientPagination() ? Math.ceil(
|
|
383
|
+
const clientTotalPages = () => needsClientPagination() ? Math.ceil(sortedRows().length / clientPageSize()) : 1
|
|
341
384
|
const clientVisibleRows = createMemo(() => {
|
|
342
|
-
if (!needsClientPagination()) return
|
|
385
|
+
if (!needsClientPagination()) return sortedRows()
|
|
343
386
|
const start = clientPage() * clientPageSize()
|
|
344
|
-
return
|
|
387
|
+
return sortedRows().slice(start, start + clientPageSize())
|
|
345
388
|
})
|
|
346
389
|
const clientRangeStart = () => needsClientPagination() ? clientPage() * clientPageSize() + 1 : 1
|
|
347
390
|
const clientRangeEnd = () => needsClientPagination()
|
|
348
|
-
? Math.min((clientPage() + 1) * clientPageSize(),
|
|
349
|
-
:
|
|
391
|
+
? Math.min((clientPage() + 1) * clientPageSize(), sortedRows().length)
|
|
392
|
+
: sortedRows().length
|
|
350
393
|
|
|
351
|
-
// Virtualization
|
|
394
|
+
// ─── Virtualization ──────────────────────────────────────
|
|
352
395
|
const [virtualizer, setVirtualizer] = createSignal<any>(null)
|
|
353
396
|
const [isVirtualizing, setIsVirtualizing] = createSignal(false)
|
|
354
397
|
|
|
355
|
-
//
|
|
398
|
+
// Disable virtualization when client pagination is active (they conflict)
|
|
356
399
|
const shouldVirtualize = createMemo(() => {
|
|
400
|
+
if (needsClientPagination()) return false // pagination handles slicing
|
|
357
401
|
const opts = tableParams.virtualize
|
|
358
402
|
if (opts === false) return false
|
|
359
403
|
if (opts === true) return true
|
|
@@ -362,7 +406,6 @@ function TableRenderer(props: {
|
|
|
362
406
|
const threshold = opts.threshold ?? 100
|
|
363
407
|
return (tableParams.rows?.length ?? 0) > threshold
|
|
364
408
|
}
|
|
365
|
-
// Auto-enable if > 100 rows by default
|
|
366
409
|
return (tableParams.rows?.length ?? 0) > 100
|
|
367
410
|
})
|
|
368
411
|
|
|
@@ -600,10 +643,23 @@ function TableRenderer(props: {
|
|
|
600
643
|
{(column: any) => (
|
|
601
644
|
<th
|
|
602
645
|
scope="col"
|
|
603
|
-
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"
|
|
646
|
+
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"
|
|
604
647
|
style={column.width ? { width: column.width } : {}}
|
|
648
|
+
on:click={() => handleSort(column.key)}
|
|
649
|
+
title={`Sort by ${column.label}`}
|
|
605
650
|
>
|
|
606
|
-
|
|
651
|
+
<span class="inline-flex items-center gap-1">
|
|
652
|
+
{column.label}
|
|
653
|
+
<span
|
|
654
|
+
class="text-[10px] leading-none"
|
|
655
|
+
classList={{
|
|
656
|
+
'opacity-30': sortKey() !== column.key,
|
|
657
|
+
'opacity-100 text-blue-600 dark:text-blue-400': sortKey() === column.key,
|
|
658
|
+
}}
|
|
659
|
+
>
|
|
660
|
+
{sortIndicator(column.key)}
|
|
661
|
+
</span>
|
|
662
|
+
</span>
|
|
607
663
|
</th>
|
|
608
664
|
)}
|
|
609
665
|
</For>
|