@invopop/popui 0.1.4-beta.1 → 0.1.4-beta.2
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/data-table/column-definitions.js +10 -8
- package/dist/data-table/data-table-toolbar.svelte +1 -1
- package/dist/data-table/data-table-types.d.ts +1 -0
- package/dist/data-table/data-table.svelte +114 -115
- package/dist/data-table/table-styles.js +2 -2
- package/dist/table/table-header.svelte +1 -1
- package/package.json +1 -1
|
@@ -10,19 +10,21 @@ export function createSelectionColumn() {
|
|
|
10
10
|
checked: table.getIsAllPageRowsSelected(),
|
|
11
11
|
onchange: (value) => table.toggleAllPageRowsSelected(value),
|
|
12
12
|
indeterminate: table.getIsSomePageRowsSelected() && !table.getIsAllPageRowsSelected(),
|
|
13
|
-
'aria-label': 'Select all'
|
|
13
|
+
'aria-label': 'Select all',
|
|
14
|
+
onclick: (e) => e.stopPropagation()
|
|
14
15
|
}),
|
|
15
16
|
cell: ({ row }) => renderComponent(InputCheckbox, {
|
|
16
17
|
checked: row.getIsSelected(),
|
|
17
18
|
onchange: (value) => row.toggleSelected(value),
|
|
18
|
-
'aria-label': 'Select row'
|
|
19
|
+
'aria-label': 'Select row',
|
|
20
|
+
onclick: (e) => e.stopPropagation()
|
|
19
21
|
}),
|
|
20
22
|
enableSorting: false,
|
|
21
23
|
enableHiding: false,
|
|
22
24
|
enableResizing: false,
|
|
23
|
-
size:
|
|
24
|
-
minSize:
|
|
25
|
-
maxSize:
|
|
25
|
+
size: 52,
|
|
26
|
+
minSize: 52,
|
|
27
|
+
maxSize: 52
|
|
26
28
|
};
|
|
27
29
|
}
|
|
28
30
|
/**
|
|
@@ -33,8 +35,8 @@ export function createActionsColumn(rowActionsSnippet) {
|
|
|
33
35
|
id: 'actions',
|
|
34
36
|
cell: ({ row }) => renderSnippet(rowActionsSnippet, { row }),
|
|
35
37
|
enableResizing: false,
|
|
36
|
-
size:
|
|
37
|
-
minSize:
|
|
38
|
-
maxSize:
|
|
38
|
+
size: 56,
|
|
39
|
+
minSize: 56,
|
|
40
|
+
maxSize: 56
|
|
39
41
|
};
|
|
40
42
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
let { table, filters }: { table: Table<TData>; filters?: Snippet } = $props()
|
|
7
7
|
</script>
|
|
8
8
|
|
|
9
|
-
<div class="flex items-center justify-between">
|
|
9
|
+
<div class="flex items-center justify-between px-6 py-4">
|
|
10
10
|
{#if filters}
|
|
11
11
|
<div class="flex-1">
|
|
12
12
|
{@render filters()}
|
|
@@ -47,6 +47,7 @@ export interface DataTableProps<TData> {
|
|
|
47
47
|
disableSelection?: boolean;
|
|
48
48
|
disablePagination?: boolean;
|
|
49
49
|
rowActions?: TableAction[];
|
|
50
|
+
getRowActions?: (row: TData) => TableAction[];
|
|
50
51
|
onRowAction?: (action: AnyProp, row: TData) => void;
|
|
51
52
|
initialPageSize?: number;
|
|
52
53
|
pageSizeOptions?: number[];
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
disableSelection = false,
|
|
34
34
|
disablePagination = false,
|
|
35
35
|
rowActions = [],
|
|
36
|
+
getRowActions,
|
|
36
37
|
onRowAction,
|
|
37
38
|
initialPageSize = 10,
|
|
38
39
|
emptyState = {
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
|
|
71
72
|
// Build TanStack columns from config
|
|
72
73
|
const columns = $derived.by(() =>
|
|
73
|
-
buildColumns<TData>(columnConfig, enableSelection, RowActions, rowActions.length > 0)
|
|
74
|
+
buildColumns<TData>(columnConfig, enableSelection, RowActions, getRowActions !== undefined || rowActions.length > 0)
|
|
74
75
|
)
|
|
75
76
|
|
|
76
77
|
// Calculate initial column sizes based on available width
|
|
@@ -129,8 +130,8 @@
|
|
|
129
130
|
})}
|
|
130
131
|
<div
|
|
131
132
|
class={cn(
|
|
132
|
-
'h-10 flex items-center
|
|
133
|
-
align === 'right' ? 'justify-end' : ''
|
|
133
|
+
'h-10 flex items-center relative group-hover/row:bg-background-default-secondary group-data-[state=selected]/row:bg-background-selected',
|
|
134
|
+
align === 'right' ? 'justify-end pl-3 pr-6' : 'pl-6 pr-3'
|
|
134
135
|
)}
|
|
135
136
|
>
|
|
136
137
|
<div class="relative z-10">
|
|
@@ -141,7 +142,7 @@
|
|
|
141
142
|
|
|
142
143
|
{#snippet RowActions({ row }: { row: Row<TData> })}
|
|
143
144
|
<BaseTableActions
|
|
144
|
-
actions={rowActions}
|
|
145
|
+
actions={getRowActions ? getRowActions(row.original) : rowActions}
|
|
145
146
|
onclick={(action) => {
|
|
146
147
|
if (onRowAction) {
|
|
147
148
|
onRowAction(action, row.original)
|
|
@@ -188,128 +189,126 @@
|
|
|
188
189
|
{/if}
|
|
189
190
|
{/snippet}
|
|
190
191
|
|
|
191
|
-
<div class="flex flex-col
|
|
192
|
+
<div class="flex flex-col h-screen">
|
|
192
193
|
<DataTableToolbar {table} {filters} />
|
|
193
|
-
<div class="flex flex-col
|
|
194
|
-
<div bind:this={containerRef} class="relative bg-background">
|
|
195
|
-
<
|
|
196
|
-
<Table.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
{
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
{#if
|
|
208
|
-
{
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
/>
|
|
218
|
-
{/if}
|
|
194
|
+
<div class="flex-1 overflow-hidden flex flex-col">
|
|
195
|
+
<div bind:this={containerRef} class="relative bg-background flex-1 overflow-auto">
|
|
196
|
+
<Table.Root>
|
|
197
|
+
<Table.Header>
|
|
198
|
+
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
|
|
199
|
+
<Table.Row class="hover:!bg-transparent border-b border-border">
|
|
200
|
+
{#each headerGroup.headers as header, index (header.id)}
|
|
201
|
+
{@const isLastScrollable = index === headerGroup.headers.length - 2}
|
|
202
|
+
<Table.Head
|
|
203
|
+
colspan={header.colSpan}
|
|
204
|
+
style={getHeaderStyle(header, isLastScrollable)}
|
|
205
|
+
class={getHeaderClasses(header, isLastScrollable)}
|
|
206
|
+
>
|
|
207
|
+
{#if !header.isPlaceholder}
|
|
208
|
+
{#if typeof header.column.columnDef.header === 'string'}
|
|
209
|
+
{@render ColumnHeader({
|
|
210
|
+
column: header.column as Column<TData>,
|
|
211
|
+
title: header.column.columnDef.header as string
|
|
212
|
+
})}
|
|
213
|
+
{:else}
|
|
214
|
+
<FlexRender
|
|
215
|
+
content={header.column.columnDef.header}
|
|
216
|
+
context={header.getContext()}
|
|
217
|
+
/>
|
|
219
218
|
{/if}
|
|
220
|
-
|
|
221
|
-
|
|
219
|
+
{/if}
|
|
220
|
+
{#if header.column.getCanResize()}
|
|
221
|
+
<!-- Always visible vertical border -->
|
|
222
|
+
<div
|
|
223
|
+
class={cn(
|
|
224
|
+
'absolute right-0 top-1/2 -translate-y-1/2 h-3 w-px bg-background-default-tertiary',
|
|
225
|
+
header.column.getIsResizing() && 'opacity-0'
|
|
226
|
+
)}
|
|
227
|
+
></div>
|
|
228
|
+
<!-- Resize handler (larger interactive area, enhanced on hover) -->
|
|
229
|
+
<div
|
|
230
|
+
role="button"
|
|
231
|
+
tabindex="0"
|
|
232
|
+
aria-label="Resize column"
|
|
233
|
+
class="absolute right-0 top-0 h-full w-3 cursor-col-resize select-none touch-none group -mr-1.5"
|
|
234
|
+
onmousedown={header.getResizeHandler()}
|
|
235
|
+
ontouchstart={header.getResizeHandler()}
|
|
236
|
+
>
|
|
222
237
|
<div
|
|
223
238
|
class={cn(
|
|
224
|
-
'absolute right-
|
|
225
|
-
header.column.getIsResizing() && 'opacity-
|
|
239
|
+
'absolute right-1.5 top-0 h-full w-0.5 bg-border-default-secondary transition-opacity opacity-0',
|
|
240
|
+
!header.column.getIsResizing() && 'group-hover:opacity-100'
|
|
226
241
|
)}
|
|
227
242
|
></div>
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
{@const visibleCells = row.getVisibleCells()}
|
|
260
|
-
{@const firstDataColumnIndex = visibleCells.findIndex(
|
|
261
|
-
(c) => c.column.id !== 'select' && c.column.id !== 'actions'
|
|
262
|
-
)}
|
|
263
|
-
{@const isFirstDataColumn = index === firstDataColumnIndex}
|
|
264
|
-
<Table.Cell
|
|
265
|
-
style={getCellStyle(cell, isLastScrollable)}
|
|
266
|
-
class={getCellClasses(cell, isLastScrollable, isFirstDataColumn)}
|
|
267
|
-
>
|
|
268
|
-
{#if cell.column.id === 'actions'}
|
|
269
|
-
{@render StickyCellWrapper({
|
|
270
|
-
align: 'right',
|
|
271
|
-
children: CellContent
|
|
272
|
-
})}
|
|
273
|
-
{#snippet CellContent()}
|
|
274
|
-
<FlexRender
|
|
275
|
-
content={cell.column.columnDef.cell}
|
|
276
|
-
context={cell.getContext()}
|
|
277
|
-
/>
|
|
278
|
-
{/snippet}
|
|
279
|
-
{:else if cell.column.id === 'select'}
|
|
280
|
-
{@render StickyCellWrapper({
|
|
281
|
-
align: 'left',
|
|
282
|
-
children: CellContent
|
|
283
|
-
})}
|
|
284
|
-
{#snippet CellContent()}
|
|
285
|
-
<FlexRender
|
|
286
|
-
content={cell.column.columnDef.cell}
|
|
287
|
-
context={cell.getContext()}
|
|
288
|
-
/>
|
|
289
|
-
{/snippet}
|
|
290
|
-
{:else}
|
|
243
|
+
</div>
|
|
244
|
+
{/if}
|
|
245
|
+
</Table.Head>
|
|
246
|
+
{/each}
|
|
247
|
+
</Table.Row>
|
|
248
|
+
{/each}
|
|
249
|
+
</Table.Header>
|
|
250
|
+
<Table.Body>
|
|
251
|
+
{#each table.getRowModel().rows as row (row.id)}
|
|
252
|
+
<Table.Row
|
|
253
|
+
data-state={row.getIsSelected() ? 'selected' : undefined}
|
|
254
|
+
class="border-b border-border"
|
|
255
|
+
onclick={() => onRowClick?.(row.original as TData)}
|
|
256
|
+
>
|
|
257
|
+
{#each row.getVisibleCells() as cell, index (cell.id)}
|
|
258
|
+
{@const isLastScrollable = index === row.getVisibleCells().length - 2}
|
|
259
|
+
{@const visibleCells = row.getVisibleCells()}
|
|
260
|
+
{@const firstDataColumnIndex = visibleCells.findIndex(
|
|
261
|
+
(c) => c.column.id !== 'select' && c.column.id !== 'actions'
|
|
262
|
+
)}
|
|
263
|
+
{@const isFirstDataColumn = index === firstDataColumnIndex}
|
|
264
|
+
<Table.Cell
|
|
265
|
+
style={getCellStyle(cell, isLastScrollable)}
|
|
266
|
+
class={getCellClasses(cell, isLastScrollable, isFirstDataColumn)}
|
|
267
|
+
>
|
|
268
|
+
{#if cell.column.id === 'actions'}
|
|
269
|
+
{@render StickyCellWrapper({
|
|
270
|
+
align: 'right',
|
|
271
|
+
children: CellContent
|
|
272
|
+
})}
|
|
273
|
+
{#snippet CellContent()}
|
|
291
274
|
<FlexRender
|
|
292
275
|
content={cell.column.columnDef.cell}
|
|
293
276
|
context={cell.getContext()}
|
|
294
277
|
/>
|
|
295
|
-
{/
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
278
|
+
{/snippet}
|
|
279
|
+
{:else if cell.column.id === 'select'}
|
|
280
|
+
{@render StickyCellWrapper({
|
|
281
|
+
align: 'left',
|
|
282
|
+
children: CellContent
|
|
283
|
+
})}
|
|
284
|
+
{#snippet CellContent()}
|
|
285
|
+
<FlexRender
|
|
286
|
+
content={cell.column.columnDef.cell}
|
|
287
|
+
context={cell.getContext()}
|
|
288
|
+
/>
|
|
289
|
+
{/snippet}
|
|
290
|
+
{:else}
|
|
291
|
+
<FlexRender
|
|
292
|
+
content={cell.column.columnDef.cell}
|
|
293
|
+
context={cell.getContext()}
|
|
294
|
+
/>
|
|
295
|
+
{/if}
|
|
307
296
|
</Table.Cell>
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
297
|
+
{/each}
|
|
298
|
+
</Table.Row>
|
|
299
|
+
{:else}
|
|
300
|
+
<Table.Row>
|
|
301
|
+
<Table.Cell colspan={columns.length} class="h-48">
|
|
302
|
+
<EmptyState
|
|
303
|
+
iconSource={emptyState.iconSource}
|
|
304
|
+
title={emptyState.title}
|
|
305
|
+
description={emptyState.description}
|
|
306
|
+
/>
|
|
307
|
+
</Table.Cell>
|
|
308
|
+
</Table.Row>
|
|
309
|
+
{/each}
|
|
310
|
+
</Table.Body>
|
|
311
|
+
</Table.Root>
|
|
313
312
|
</div>
|
|
314
313
|
{#if enablePagination}
|
|
315
314
|
<DataTablePagination
|
|
@@ -17,8 +17,8 @@ export function getHeaderStyle(header, isLastScrollable) {
|
|
|
17
17
|
*/
|
|
18
18
|
export function getHeaderClasses(header, isLastScrollable) {
|
|
19
19
|
return clsx('relative whitespace-nowrap overflow-hidden', {
|
|
20
|
-
'sticky right-0 text-right bg-background': header.id === 'actions',
|
|
21
|
-
'sticky left-0 bg-background z-10': header.id === 'select',
|
|
20
|
+
'sticky right-0 text-right bg-background pl-3 pr-6': header.id === 'actions',
|
|
21
|
+
'sticky left-0 bg-background z-10 pl-6 pr-3': header.id === 'select',
|
|
22
22
|
'w-full': isLastScrollable,
|
|
23
23
|
'hover:!bg-transparent': !header.column.getCanSort()
|
|
24
24
|
});
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<thead
|
|
16
16
|
bind:this={ref}
|
|
17
17
|
data-slot="table-header"
|
|
18
|
-
class={cn('[&_tr]:border-b [&_tr]:border-border bg-background', className)}
|
|
18
|
+
class={cn('sticky top-0 z-20 [&_tr]:border-b [&_tr]:border-border bg-background', className)}
|
|
19
19
|
onclick={bubble('click')}
|
|
20
20
|
onkeydown={bubble('keydown')}
|
|
21
21
|
>
|