@invopop/popui 0.1.1 → 0.1.3-6.beta.1
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/AlertDialog.svelte +10 -11
- package/dist/BaseButton.svelte +25 -104
- package/dist/BaseCard.svelte +35 -30
- package/dist/BaseCounter.svelte +11 -8
- package/dist/BaseDropdown.svelte +5 -5
- package/dist/BaseFlag.svelte +5 -3
- package/dist/BaseFlag.svelte.d.ts +1 -0
- package/dist/BaseTable.svelte +16 -16
- package/dist/BaseTable.svelte.d.ts +1 -1
- package/dist/BaseTableActions.svelte +4 -6
- package/dist/BaseTableCellContent.svelte +9 -21
- package/dist/BaseTableCheckbox.svelte +9 -11
- package/dist/BaseTableHeaderContent.svelte +4 -4
- package/dist/BaseTableHeaderOrderBy.svelte +23 -12
- package/dist/BaseTableRow.svelte +12 -10
- package/dist/Breadcrumb.svelte +40 -0
- package/dist/Breadcrumb.svelte.d.ts +4 -0
- package/dist/Breadcrumbs.svelte +5 -30
- package/dist/ButtonFile.svelte +40 -30
- package/dist/ButtonUuidCopy.svelte +6 -3
- package/dist/CardCheckbox.svelte +45 -32
- package/dist/CardCheckbox.svelte.d.ts +1 -1
- package/dist/CardRelation.svelte +12 -13
- package/dist/CompanySelector.svelte +35 -7
- package/dist/CounterWidget.svelte +52 -0
- package/dist/CounterWidget.svelte.d.ts +4 -0
- package/dist/DataListItem.svelte +14 -10
- package/dist/DatePicker.svelte +20 -17
- package/dist/DrawerContext.svelte +207 -15
- package/dist/DrawerContextItem.svelte +50 -50
- package/dist/DrawerContextSeparator.svelte +1 -1
- package/dist/DropdownSelect.svelte +46 -18
- package/dist/EmptyState.svelte +42 -0
- package/dist/EmptyState.svelte.d.ts +4 -0
- package/dist/FeedEvents.svelte +9 -5
- package/dist/FeedIconEvent.svelte +2 -2
- package/dist/FeedIconStatus.svelte +4 -4
- package/dist/FeedItem.svelte +10 -11
- package/dist/FeedItemDetail.svelte +32 -6
- package/dist/FeedViewer.svelte +1 -1
- package/dist/GlobalSearch.svelte +13 -12
- package/dist/InputCheckbox.svelte +2 -5
- package/dist/InputError.svelte +4 -9
- package/dist/InputLabel.svelte +3 -1
- package/dist/InputRadio.svelte +29 -13
- package/dist/InputRadio.svelte.d.ts +1 -1
- package/dist/InputSearch.svelte +8 -8
- package/dist/InputSelect.svelte +32 -31
- package/dist/InputText.svelte +32 -24
- package/dist/InputTextarea.svelte +25 -19
- package/dist/InputToggle.svelte +24 -18
- package/dist/MenuItem.svelte +16 -11
- package/dist/MenuItemCollapsible.svelte +7 -7
- package/dist/Notification.svelte +60 -25
- package/dist/ProfileAvatar.svelte +43 -14
- package/dist/ProgressBar.svelte +42 -0
- package/dist/ProgressBar.svelte.d.ts +4 -0
- package/dist/ProgressBarCircle.svelte +46 -0
- package/dist/ProgressBarCircle.svelte.d.ts +4 -0
- package/dist/SeparatorHorizontal.svelte +2 -2
- package/dist/ShortcutWrapper.svelte +14 -5
- package/dist/StatusLabel.svelte +4 -5
- package/dist/StepIconList.svelte +11 -9
- package/dist/TagBeta.svelte +26 -14
- package/dist/TagProgress.svelte +28 -0
- package/dist/TagProgress.svelte.d.ts +4 -0
- package/dist/TagSearch.svelte +4 -4
- package/dist/TagStatus.svelte +32 -34
- package/dist/TitleMain.svelte +1 -1
- package/dist/TitleSection.svelte +1 -1
- package/dist/UuidCopy.svelte +4 -4
- package/dist/alert-dialog/alert-dialog-action.svelte +8 -4
- package/dist/alert-dialog/alert-dialog-cancel.svelte +7 -3
- package/dist/alert-dialog/alert-dialog-content.svelte +1 -1
- package/dist/alert-dialog/alert-dialog-description.svelte +1 -1
- package/dist/alert-dialog/alert-dialog-footer.svelte +1 -1
- package/dist/alert-dialog/alert-dialog-header.svelte +1 -1
- package/dist/alert-dialog/alert-dialog-overlay.svelte +1 -1
- package/dist/alert-dialog/alert-dialog-title.svelte +1 -1
- package/dist/alert-dialog/alert-dialog-trigger.svelte +4 -2
- package/dist/button/button.svelte +200 -24
- package/dist/button/button.svelte.d.ts +51 -26
- package/dist/clickOutside.d.ts +5 -2
- package/dist/clickOutside.js +9 -3
- package/dist/data-table/cells/boolean-cell.svelte +16 -0
- package/dist/data-table/cells/boolean-cell.svelte.d.ts +8 -0
- package/dist/data-table/cells/currency-cell.svelte +10 -0
- package/dist/data-table/cells/currency-cell.svelte.d.ts +8 -0
- package/dist/data-table/cells/date-cell.svelte +10 -0
- package/dist/data-table/cells/date-cell.svelte.d.ts +8 -0
- package/dist/data-table/cells/tag-cell.svelte +12 -0
- package/dist/data-table/cells/tag-cell.svelte.d.ts +8 -0
- package/dist/data-table/cells/text-cell.svelte +10 -0
- package/dist/data-table/cells/text-cell.svelte.d.ts +8 -0
- package/dist/data-table/column-definitions.d.ts +12 -0
- package/dist/data-table/column-definitions.js +40 -0
- package/dist/data-table/column-sizing-helpers.d.ts +6 -0
- package/dist/data-table/column-sizing-helpers.js +24 -0
- package/dist/data-table/create-columns.d.ts +3 -0
- package/dist/data-table/create-columns.js +50 -0
- package/dist/data-table/data-table-pagination.svelte +144 -0
- package/dist/data-table/data-table-pagination.svelte.d.ts +4 -0
- package/dist/data-table/data-table-svelte.svelte.d.ts +40 -0
- package/dist/data-table/data-table-svelte.svelte.js +111 -0
- package/dist/data-table/data-table-toolbar.svelte +16 -0
- package/dist/data-table/data-table-toolbar.svelte.d.ts +29 -0
- package/dist/data-table/data-table-types.d.ts +66 -0
- package/dist/data-table/data-table-types.js +1 -0
- package/dist/data-table/data-table-view-options.svelte +88 -0
- package/dist/data-table/data-table-view-options.svelte.d.ts +27 -0
- package/dist/data-table/data-table.svelte +303 -0
- package/dist/data-table/data-table.svelte.d.ts +25 -0
- package/dist/data-table/flex-render.svelte +40 -0
- package/dist/data-table/flex-render.svelte.d.ts +33 -0
- package/dist/data-table/index.d.ts +13 -0
- package/dist/data-table/index.js +13 -0
- package/dist/data-table/render-helpers.d.ts +90 -0
- package/dist/data-table/render-helpers.js +99 -0
- package/dist/data-table/table-setup.d.ts +36 -0
- package/dist/data-table/table-setup.js +130 -0
- package/dist/data-table/table-styles.d.ts +17 -0
- package/dist/data-table/table-styles.js +48 -0
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +3 -0
- package/dist/index.d.ts +15 -7
- package/dist/index.js +31 -14
- package/dist/range-calendar/range-calendar-cell.svelte +1 -1
- package/dist/range-calendar/range-calendar-day.svelte +11 -12
- package/dist/range-calendar/range-calendar-head-cell.svelte +1 -1
- package/dist/range-calendar/range-calendar-header.svelte +1 -1
- package/dist/range-calendar/range-calendar-month-select.svelte +1 -1
- package/dist/range-calendar/range-calendar-next-button.svelte +3 -3
- package/dist/range-calendar/range-calendar-prev-button.svelte +3 -3
- package/dist/range-calendar/range-calendar.svelte +1 -1
- package/dist/sonner/index.d.ts +1 -0
- package/dist/sonner/index.js +1 -0
- package/dist/sonner/sonner.svelte +44 -0
- package/dist/sonner/sonner.svelte.d.ts +4 -0
- package/dist/svg/CheckBadge.svelte +18 -0
- package/dist/svg/CheckBadge.svelte.d.ts +26 -0
- package/dist/svg/IconDelivery.svelte +86 -0
- package/dist/svg/IconDelivery.svelte.d.ts +20 -0
- package/dist/svg/IconEmpty.svelte +113 -121
- package/dist/svg/IconOrder.svelte +81 -0
- package/dist/svg/IconOrder.svelte.d.ts +20 -0
- package/dist/svg/IconPayment.svelte +86 -0
- package/dist/svg/IconPayment.svelte.d.ts +20 -0
- package/dist/table/table-body.svelte +5 -1
- package/dist/table/table-cell.svelte +4 -2
- package/dist/table/table-footer.svelte +1 -1
- package/dist/table/table-head.svelte +4 -2
- package/dist/table/table-header.svelte +1 -1
- package/dist/table/table-row.svelte +4 -2
- package/dist/table/table.svelte +2 -2
- package/dist/tabs/tabs-list.svelte +8 -2
- package/dist/tabs/tabs-list.svelte.d.ts +4 -1
- package/dist/tabs/tabs-trigger.svelte +5 -3
- package/dist/tabs/tabs-trigger.svelte.d.ts +4 -1
- package/dist/tailwind.theme.css +998 -0
- package/dist/tooltip/tooltip-content.svelte +2 -2
- package/dist/types.d.ts +71 -50
- package/package.json +21 -11
- package/dist/CounterWorkflow.svelte +0 -19
- package/dist/CounterWorkflow.svelte.d.ts +0 -4
- package/dist/DrawerContextWorkspace.svelte +0 -126
- package/dist/DrawerContextWorkspace.svelte.d.ts +0 -4
- package/dist/EmptyStateIcon.svelte +0 -52
- package/dist/EmptyStateIcon.svelte.d.ts +0 -4
- package/dist/EmptyStateIllustration.svelte +0 -66
- package/dist/EmptyStateIllustration.svelte.d.ts +0 -4
- package/dist/FormLayoutModal.svelte +0 -14
- package/dist/FormLayoutModal.svelte.d.ts +0 -4
- package/dist/ProfileSelector.svelte +0 -41
- package/dist/ProfileSelector.svelte.d.ts +0 -4
- package/dist/SectionLayout.svelte +0 -13
- package/dist/SectionLayout.svelte.d.ts +0 -4
- package/dist/tw.theme.d.ts +0 -142
- package/dist/tw.theme.js +0 -158
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Component, Snippet } from 'svelte';
|
|
2
|
+
import type { StatusType, AnyProp, TableAction, EmptyStateProps } from '../types.js';
|
|
3
|
+
import type { IconSource } from '@steeze-ui/svelte-icon';
|
|
4
|
+
import type { Table } from '@tanstack/table-core';
|
|
5
|
+
export type CellType = 'text' | 'boolean' | 'tag' | 'date' | 'currency' | 'custom';
|
|
6
|
+
export interface TextCellConfig {
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface BooleanCellConfig {
|
|
10
|
+
icon?: IconSource;
|
|
11
|
+
iconClass?: string;
|
|
12
|
+
showWhenTrue?: boolean;
|
|
13
|
+
showWhenFalse?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface TagCellConfig {
|
|
16
|
+
options: Array<{
|
|
17
|
+
value: string;
|
|
18
|
+
label: string;
|
|
19
|
+
color: StatusType;
|
|
20
|
+
}>;
|
|
21
|
+
showDot?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface DateCellConfig {
|
|
24
|
+
className?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface CurrencyCellConfig {
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
export type CellConfig = TextCellConfig | BooleanCellConfig | TagCellConfig | DateCellConfig | CurrencyCellConfig;
|
|
30
|
+
export interface DataTableColumn<TData> {
|
|
31
|
+
id: string;
|
|
32
|
+
accessorKey?: keyof TData;
|
|
33
|
+
header?: string;
|
|
34
|
+
cellType?: CellType;
|
|
35
|
+
cellConfig?: CellConfig;
|
|
36
|
+
cell?: (value: any, row: TData) => Snippet | Component | string;
|
|
37
|
+
enableSorting?: boolean;
|
|
38
|
+
enableHiding?: boolean;
|
|
39
|
+
enableResizing?: boolean;
|
|
40
|
+
size?: number;
|
|
41
|
+
minSize?: number;
|
|
42
|
+
maxSize?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface DataTableProps<TData> {
|
|
45
|
+
data: TData[];
|
|
46
|
+
columns: DataTableColumn<TData>[];
|
|
47
|
+
disableSelection?: boolean;
|
|
48
|
+
disablePagination?: boolean;
|
|
49
|
+
rowActions?: TableAction[];
|
|
50
|
+
onRowAction?: (action: AnyProp, row: TData) => void;
|
|
51
|
+
initialPageSize?: number;
|
|
52
|
+
pageSizeOptions?: number[];
|
|
53
|
+
emptyState?: Omit<EmptyStateProps, 'children' | 'check'>;
|
|
54
|
+
onRowClick?: (row: TData) => void;
|
|
55
|
+
onSelectionChange?: (selectedRows: TData[]) => void;
|
|
56
|
+
filters?: Snippet;
|
|
57
|
+
}
|
|
58
|
+
export interface DataTablePaginationProps<T> {
|
|
59
|
+
table: Table<T>;
|
|
60
|
+
id?: string;
|
|
61
|
+
class?: string;
|
|
62
|
+
showRowsPerPage?: boolean;
|
|
63
|
+
rowsPerPageOptions?: number[];
|
|
64
|
+
itemsLabel?: string;
|
|
65
|
+
children?: Snippet;
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script lang="ts" generics="TData">
|
|
2
|
+
import { Sliders, Drag } from '@invopop/ui-icons'
|
|
3
|
+
import type { Table } from '@tanstack/table-core'
|
|
4
|
+
import type { DrawerOption } from '../types.js'
|
|
5
|
+
import BaseDropdown from '../BaseDropdown.svelte'
|
|
6
|
+
import DrawerContext from '../DrawerContext.svelte'
|
|
7
|
+
import InputToggle from '../InputToggle.svelte'
|
|
8
|
+
import BaseButton from '../BaseButton.svelte'
|
|
9
|
+
import { capitalize } from '../helpers.js'
|
|
10
|
+
|
|
11
|
+
let { table }: { table: Table<TData> } = $props()
|
|
12
|
+
|
|
13
|
+
let itemsWithActions = $state<DrawerOption[]>([])
|
|
14
|
+
|
|
15
|
+
// Initialize and update items when table state changes
|
|
16
|
+
$effect(() => {
|
|
17
|
+
const columnOrder = table.getState().columnOrder
|
|
18
|
+
const allColumns = table.getAllColumns()
|
|
19
|
+
|
|
20
|
+
let orderedColumns
|
|
21
|
+
// If there's a custom order, use it; otherwise use default order
|
|
22
|
+
if (columnOrder.length > 0) {
|
|
23
|
+
orderedColumns = columnOrder
|
|
24
|
+
.map((id) => allColumns.find((col) => col.id === id))
|
|
25
|
+
.filter((col) => col && col.id !== 'select' && col.id !== 'actions')
|
|
26
|
+
} else {
|
|
27
|
+
orderedColumns = allColumns.filter((col) => col.id !== 'select' && col.id !== 'actions')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const newItems = orderedColumns.map((col) => ({
|
|
31
|
+
label: (col?.columnDef.header as string) || capitalize(col?.id || ''),
|
|
32
|
+
value: col?.id,
|
|
33
|
+
icon: Drag,
|
|
34
|
+
action: toggleAction
|
|
35
|
+
})) as DrawerOption[]
|
|
36
|
+
|
|
37
|
+
// Only update if the order has actually changed (avoid overwriting during drag)
|
|
38
|
+
const currentOrder = itemsWithActions.map((i) => i.value).join(',')
|
|
39
|
+
const newOrder = newItems.map((i) => i.value).join(',')
|
|
40
|
+
|
|
41
|
+
if (currentOrder !== newOrder) {
|
|
42
|
+
itemsWithActions = newItems
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
function handleReorder(reorderedItems: any[]) {
|
|
47
|
+
// Update local items to match the drag order immediately
|
|
48
|
+
itemsWithActions = reorderedItems
|
|
49
|
+
|
|
50
|
+
const newOrder = reorderedItems.map((item) => item.value)
|
|
51
|
+
// Get all column IDs from the table
|
|
52
|
+
const allColumnIds = table.getAllColumns().map((col) => col.id)
|
|
53
|
+
|
|
54
|
+
// Filter to keep select and actions in their fixed positions
|
|
55
|
+
const selectColumn = 'select'
|
|
56
|
+
const actionsColumn = 'actions'
|
|
57
|
+
|
|
58
|
+
// Build final order: select first (if exists), reordered columns in middle, actions last (if exists)
|
|
59
|
+
const finalOrder = [
|
|
60
|
+
...(allColumnIds.includes(selectColumn) ? [selectColumn] : []),
|
|
61
|
+
...newOrder.filter((id) => id !== selectColumn && id !== actionsColumn),
|
|
62
|
+
...(allColumnIds.includes(actionsColumn) ? [actionsColumn] : [])
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
table.setColumnOrder(finalOrder)
|
|
66
|
+
}
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
{#snippet toggleAction(item: DrawerOption)}
|
|
70
|
+
{@const column = table.getColumn(String(item.value))}
|
|
71
|
+
{#if column?.getCanHide()}
|
|
72
|
+
<InputToggle
|
|
73
|
+
checked={column?.getIsVisible() ?? false}
|
|
74
|
+
onchange={(v) => column?.toggleVisibility(!!v)}
|
|
75
|
+
/>
|
|
76
|
+
{/if}
|
|
77
|
+
{/snippet}
|
|
78
|
+
|
|
79
|
+
<BaseDropdown class="ms-auto hidden lg:flex">
|
|
80
|
+
{#snippet trigger()}
|
|
81
|
+
<BaseButton icon={Sliders} variant="outline" size="md" />
|
|
82
|
+
{/snippet}
|
|
83
|
+
<DrawerContext items={itemsWithActions} draggable={true} onreorder={handleReorder}>
|
|
84
|
+
<div class="p-3 py-1.5 text-sm font-medium text-foreground-default-secondary">
|
|
85
|
+
Table options
|
|
86
|
+
</div>
|
|
87
|
+
</DrawerContext>
|
|
88
|
+
</BaseDropdown>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Table } from '@tanstack/table-core';
|
|
2
|
+
declare function $$render<TData>(): {
|
|
3
|
+
props: {
|
|
4
|
+
table: Table<TData>;
|
|
5
|
+
};
|
|
6
|
+
exports: {};
|
|
7
|
+
bindings: "";
|
|
8
|
+
slots: {};
|
|
9
|
+
events: {};
|
|
10
|
+
};
|
|
11
|
+
declare class __sveltets_Render<TData> {
|
|
12
|
+
props(): ReturnType<typeof $$render<TData>>['props'];
|
|
13
|
+
events(): ReturnType<typeof $$render<TData>>['events'];
|
|
14
|
+
slots(): ReturnType<typeof $$render<TData>>['slots'];
|
|
15
|
+
bindings(): "";
|
|
16
|
+
exports(): {};
|
|
17
|
+
}
|
|
18
|
+
interface $$IsomorphicComponent {
|
|
19
|
+
new <TData>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TData>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TData>['props']>, ReturnType<__sveltets_Render<TData>['events']>, ReturnType<__sveltets_Render<TData>['slots']>> & {
|
|
20
|
+
$$bindings?: ReturnType<__sveltets_Render<TData>['bindings']>;
|
|
21
|
+
} & ReturnType<__sveltets_Render<TData>['exports']>;
|
|
22
|
+
<TData>(internal: unknown, props: ReturnType<__sveltets_Render<TData>['props']> & {}): ReturnType<__sveltets_Render<TData>['exports']>;
|
|
23
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
24
|
+
}
|
|
25
|
+
declare const DataTableViewOptions: $$IsomorphicComponent;
|
|
26
|
+
type DataTableViewOptions<TData> = InstanceType<typeof DataTableViewOptions<TData>>;
|
|
27
|
+
export default DataTableViewOptions;
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
<script lang="ts" generics="TData">
|
|
2
|
+
import {
|
|
3
|
+
type ColumnSizingState,
|
|
4
|
+
type ColumnSizingInfoState,
|
|
5
|
+
type ColumnOrderState,
|
|
6
|
+
type PaginationState,
|
|
7
|
+
type Row,
|
|
8
|
+
type RowSelectionState,
|
|
9
|
+
type SortingState,
|
|
10
|
+
type VisibilityState,
|
|
11
|
+
type Column
|
|
12
|
+
} from '@tanstack/table-core'
|
|
13
|
+
import DataTableToolbar from './data-table-toolbar.svelte'
|
|
14
|
+
import DataTablePagination from './data-table-pagination.svelte'
|
|
15
|
+
import FlexRender from './flex-render.svelte'
|
|
16
|
+
import * as Table from '../table/index.js'
|
|
17
|
+
import BaseTableActions from '../BaseTableActions.svelte'
|
|
18
|
+
import BaseDropdown from '../BaseDropdown.svelte'
|
|
19
|
+
import BaseTableHeaderOrderBy from '../BaseTableHeaderOrderBy.svelte'
|
|
20
|
+
import EmptyState from '../EmptyState.svelte'
|
|
21
|
+
import { Icon } from '@steeze-ui/svelte-icon'
|
|
22
|
+
import { ArrowUp, ArrowDown, Search } from '@invopop/ui-icons'
|
|
23
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
24
|
+
import { cn } from '../utils.js'
|
|
25
|
+
import type { DataTableProps } from './data-table-types.js'
|
|
26
|
+
import { calculateColumnSizing } from './column-sizing-helpers.js'
|
|
27
|
+
import { getHeaderStyle, getHeaderClasses, getCellStyle, getCellClasses } from './table-styles.js'
|
|
28
|
+
import { buildColumns, setupTable } from './table-setup.js'
|
|
29
|
+
|
|
30
|
+
let {
|
|
31
|
+
data,
|
|
32
|
+
columns: columnConfig,
|
|
33
|
+
disableSelection = false,
|
|
34
|
+
disablePagination = false,
|
|
35
|
+
rowActions = [],
|
|
36
|
+
onRowAction,
|
|
37
|
+
initialPageSize = 10,
|
|
38
|
+
emptyState = {
|
|
39
|
+
iconSource: Search,
|
|
40
|
+
title: 'No results',
|
|
41
|
+
description: 'Try adjusting your filters or search query'
|
|
42
|
+
},
|
|
43
|
+
onRowClick,
|
|
44
|
+
onSelectionChange,
|
|
45
|
+
filters
|
|
46
|
+
}: DataTableProps<TData> = $props()
|
|
47
|
+
|
|
48
|
+
const enableSelection = !disableSelection
|
|
49
|
+
const enablePagination = !disablePagination
|
|
50
|
+
|
|
51
|
+
let rowSelection = $state<RowSelectionState>({})
|
|
52
|
+
let columnVisibility = $state<VisibilityState>({})
|
|
53
|
+
let sorting = $state<SortingState>([])
|
|
54
|
+
let pagination = $state<PaginationState>({ pageIndex: 0, pageSize: initialPageSize })
|
|
55
|
+
let columnSizing = $state<ColumnSizingState>({})
|
|
56
|
+
let columnSizingInfo = $state<ColumnSizingInfoState>({
|
|
57
|
+
columnSizingStart: [],
|
|
58
|
+
deltaOffset: null,
|
|
59
|
+
deltaPercentage: null,
|
|
60
|
+
isResizingColumn: false,
|
|
61
|
+
startOffset: null,
|
|
62
|
+
startSize: null
|
|
63
|
+
})
|
|
64
|
+
let columnOrder = $state<ColumnOrderState>([])
|
|
65
|
+
let containerRef = $state<HTMLDivElement | null>(null)
|
|
66
|
+
|
|
67
|
+
// Build TanStack columns from config
|
|
68
|
+
const columns = $derived.by(() =>
|
|
69
|
+
buildColumns<TData>(columnConfig, enableSelection, RowActions, rowActions.length > 0)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
// Calculate initial column sizes based on available width
|
|
73
|
+
$effect(() => {
|
|
74
|
+
if (containerRef && Object.keys(columnSizing).length === 0) {
|
|
75
|
+
const containerWidth = containerRef.offsetWidth
|
|
76
|
+
const newSizing = calculateColumnSizing(columns, containerWidth)
|
|
77
|
+
if (newSizing) {
|
|
78
|
+
columnSizing = newSizing
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
// Track selection changes
|
|
84
|
+
$effect(() => {
|
|
85
|
+
if (onSelectionChange) {
|
|
86
|
+
const selectedRows = Object.keys(rowSelection)
|
|
87
|
+
.filter((key) => rowSelection[key])
|
|
88
|
+
.map((key) => data[parseInt(key)])
|
|
89
|
+
onSelectionChange(selectedRows)
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const table = setupTable({
|
|
94
|
+
get data() {
|
|
95
|
+
return data
|
|
96
|
+
},
|
|
97
|
+
get columns() {
|
|
98
|
+
return columns
|
|
99
|
+
},
|
|
100
|
+
enableSelection,
|
|
101
|
+
enablePagination,
|
|
102
|
+
getRowSelection: () => rowSelection,
|
|
103
|
+
getColumnVisibility: () => columnVisibility,
|
|
104
|
+
getSorting: () => sorting,
|
|
105
|
+
getPagination: () => pagination,
|
|
106
|
+
getColumnSizing: () => columnSizing,
|
|
107
|
+
getColumnSizingInfo: () => columnSizingInfo,
|
|
108
|
+
getColumnOrder: () => columnOrder,
|
|
109
|
+
setRowSelection: (value) => (rowSelection = value),
|
|
110
|
+
setColumnVisibility: (value) => (columnVisibility = value),
|
|
111
|
+
setSorting: (value) => (sorting = value),
|
|
112
|
+
setPagination: (value) => (pagination = value),
|
|
113
|
+
setColumnSizing: (value) => (columnSizing = value),
|
|
114
|
+
setColumnSizingInfo: (value) => (columnSizingInfo = value),
|
|
115
|
+
setColumnOrder: (value) => (columnOrder = value)
|
|
116
|
+
})
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
{#snippet StickyCellWrapper({
|
|
120
|
+
children,
|
|
121
|
+
align = 'left'
|
|
122
|
+
}: {
|
|
123
|
+
children: any
|
|
124
|
+
align?: 'left' | 'right'
|
|
125
|
+
})}
|
|
126
|
+
<div
|
|
127
|
+
class={cn(
|
|
128
|
+
'h-10 flex items-center px-3 relative group-hover/row:bg-background-default-secondary group-data-[state=selected]/row:bg-background-selected',
|
|
129
|
+
align === 'right' ? 'justify-end' : ''
|
|
130
|
+
)}
|
|
131
|
+
>
|
|
132
|
+
<div class="relative z-10">
|
|
133
|
+
{@render children()}
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
{/snippet}
|
|
137
|
+
|
|
138
|
+
{#snippet RowActions({ row }: { row: Row<TData> })}
|
|
139
|
+
<BaseTableActions
|
|
140
|
+
actions={rowActions}
|
|
141
|
+
onclick={(action) => {
|
|
142
|
+
if (onRowAction) {
|
|
143
|
+
onRowAction(action, row.original)
|
|
144
|
+
}
|
|
145
|
+
}}
|
|
146
|
+
/>
|
|
147
|
+
{/snippet}
|
|
148
|
+
|
|
149
|
+
{#snippet ColumnHeader({
|
|
150
|
+
column,
|
|
151
|
+
title,
|
|
152
|
+
class: className,
|
|
153
|
+
...restProps
|
|
154
|
+
}: { column: Column<TData>; title?: string } & HTMLAttributes<HTMLDivElement>)}
|
|
155
|
+
{#if !column?.getCanSort()}
|
|
156
|
+
<div class={className} {...restProps}>
|
|
157
|
+
{title || ''}
|
|
158
|
+
</div>
|
|
159
|
+
{:else}
|
|
160
|
+
<div class={cn('flex items-center w-full', className)} {...restProps}>
|
|
161
|
+
<BaseDropdown fullWidth>
|
|
162
|
+
{#snippet trigger()}
|
|
163
|
+
<button
|
|
164
|
+
class="data-[state=open]:bg-accent w-full flex items-center gap-1 py-2.5 text-left"
|
|
165
|
+
>
|
|
166
|
+
<span>
|
|
167
|
+
{title || ''}
|
|
168
|
+
</span>
|
|
169
|
+
{#if column.getIsSorted() === 'desc'}
|
|
170
|
+
<Icon src={ArrowDown} class="size-4" />
|
|
171
|
+
{:else if column.getIsSorted() === 'asc'}
|
|
172
|
+
<Icon src={ArrowUp} class="size-4" />
|
|
173
|
+
{/if}
|
|
174
|
+
</button>
|
|
175
|
+
{/snippet}
|
|
176
|
+
<BaseTableHeaderOrderBy
|
|
177
|
+
sortDirection={column.getIsSorted() === 'asc' ? 'asc' : 'desc'}
|
|
178
|
+
isActive={column.getIsSorted() !== false}
|
|
179
|
+
onOrderBy={(direction) => column.toggleSorting(direction === 'desc')}
|
|
180
|
+
onHide={() => column.toggleVisibility(false)}
|
|
181
|
+
/>
|
|
182
|
+
</BaseDropdown>
|
|
183
|
+
</div>
|
|
184
|
+
{/if}
|
|
185
|
+
{/snippet}
|
|
186
|
+
|
|
187
|
+
<div class="flex flex-col gap-4">
|
|
188
|
+
<DataTableToolbar {table} {filters} />
|
|
189
|
+
<div class="flex flex-col gap-[5px]">
|
|
190
|
+
<div bind:this={containerRef} class="relative bg-background">
|
|
191
|
+
<div class="overflow-x-auto relative z-10">
|
|
192
|
+
<Table.Root>
|
|
193
|
+
<Table.Header>
|
|
194
|
+
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
|
|
195
|
+
<Table.Row class="hover:!bg-transparent border-b border-border">
|
|
196
|
+
{#each headerGroup.headers as header, index (header.id)}
|
|
197
|
+
{@const isLastScrollable = index === headerGroup.headers.length - 2}
|
|
198
|
+
<Table.Head
|
|
199
|
+
colspan={header.colSpan}
|
|
200
|
+
style={getHeaderStyle(header, isLastScrollable)}
|
|
201
|
+
class={getHeaderClasses(header, isLastScrollable)}
|
|
202
|
+
>
|
|
203
|
+
{#if !header.isPlaceholder}
|
|
204
|
+
{#if typeof header.column.columnDef.header === 'string'}
|
|
205
|
+
{@render ColumnHeader({
|
|
206
|
+
column: header.column as Column<TData>,
|
|
207
|
+
title: header.column.columnDef.header as string
|
|
208
|
+
})}
|
|
209
|
+
{:else}
|
|
210
|
+
<FlexRender
|
|
211
|
+
content={header.column.columnDef.header}
|
|
212
|
+
context={header.getContext()}
|
|
213
|
+
/>
|
|
214
|
+
{/if}
|
|
215
|
+
{/if}
|
|
216
|
+
{#if header.column.getCanResize()}
|
|
217
|
+
<div
|
|
218
|
+
role="button"
|
|
219
|
+
tabindex="0"
|
|
220
|
+
aria-label="Resize column"
|
|
221
|
+
class="absolute right-0 top-0 h-full w-3 cursor-col-resize select-none touch-none group -mr-1.5"
|
|
222
|
+
onmousedown={header.getResizeHandler()}
|
|
223
|
+
ontouchstart={header.getResizeHandler()}
|
|
224
|
+
>
|
|
225
|
+
<div
|
|
226
|
+
class={cn(
|
|
227
|
+
'absolute right-1.5 top-0 h-full w-0.5 bg-border-default-secondary transition-opacity',
|
|
228
|
+
header.column.getIsResizing()
|
|
229
|
+
? 'opacity-0'
|
|
230
|
+
: 'opacity-0 group-hover:opacity-100'
|
|
231
|
+
)}
|
|
232
|
+
></div>
|
|
233
|
+
</div>
|
|
234
|
+
{/if}
|
|
235
|
+
</Table.Head>
|
|
236
|
+
{/each}
|
|
237
|
+
</Table.Row>
|
|
238
|
+
{/each}
|
|
239
|
+
</Table.Header>
|
|
240
|
+
<Table.Body>
|
|
241
|
+
{#each table.getRowModel().rows as row (row.id)}
|
|
242
|
+
<Table.Row
|
|
243
|
+
data-state={row.getIsSelected() ? 'selected' : undefined}
|
|
244
|
+
class="border-b border-border"
|
|
245
|
+
onclick={() => onRowClick?.(row.original as TData)}
|
|
246
|
+
>
|
|
247
|
+
{#each row.getVisibleCells() as cell, index (cell.id)}
|
|
248
|
+
{@const isLastScrollable = index === row.getVisibleCells().length - 2}
|
|
249
|
+
<Table.Cell
|
|
250
|
+
style={getCellStyle(cell, isLastScrollable)}
|
|
251
|
+
class={getCellClasses(cell, isLastScrollable)}
|
|
252
|
+
>
|
|
253
|
+
{#if cell.column.id === 'actions'}
|
|
254
|
+
{@render StickyCellWrapper({
|
|
255
|
+
align: 'right',
|
|
256
|
+
children: CellContent
|
|
257
|
+
})}
|
|
258
|
+
{#snippet CellContent()}
|
|
259
|
+
<FlexRender
|
|
260
|
+
content={cell.column.columnDef.cell}
|
|
261
|
+
context={cell.getContext()}
|
|
262
|
+
/>
|
|
263
|
+
{/snippet}
|
|
264
|
+
{:else if cell.column.id === 'select'}
|
|
265
|
+
{@render StickyCellWrapper({
|
|
266
|
+
align: 'left',
|
|
267
|
+
children: CellContent
|
|
268
|
+
})}
|
|
269
|
+
{#snippet CellContent()}
|
|
270
|
+
<FlexRender
|
|
271
|
+
content={cell.column.columnDef.cell}
|
|
272
|
+
context={cell.getContext()}
|
|
273
|
+
/>
|
|
274
|
+
{/snippet}
|
|
275
|
+
{:else}
|
|
276
|
+
<FlexRender
|
|
277
|
+
content={cell.column.columnDef.cell}
|
|
278
|
+
context={cell.getContext()}
|
|
279
|
+
/>
|
|
280
|
+
{/if}
|
|
281
|
+
</Table.Cell>
|
|
282
|
+
{/each}
|
|
283
|
+
</Table.Row>
|
|
284
|
+
{:else}
|
|
285
|
+
<Table.Row>
|
|
286
|
+
<Table.Cell colspan={columns.length} class="h-48">
|
|
287
|
+
<EmptyState
|
|
288
|
+
iconSource={emptyState.iconSource}
|
|
289
|
+
title={emptyState.title}
|
|
290
|
+
description={emptyState.description}
|
|
291
|
+
/>
|
|
292
|
+
</Table.Cell>
|
|
293
|
+
</Table.Row>
|
|
294
|
+
{/each}
|
|
295
|
+
</Table.Body>
|
|
296
|
+
</Table.Root>
|
|
297
|
+
</div>
|
|
298
|
+
</div>
|
|
299
|
+
{#if enablePagination}
|
|
300
|
+
<DataTablePagination {table} />
|
|
301
|
+
{/if}
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { DataTableProps } from './data-table-types.js';
|
|
2
|
+
declare function $$render<TData>(): {
|
|
3
|
+
props: DataTableProps<TData>;
|
|
4
|
+
exports: {};
|
|
5
|
+
bindings: "";
|
|
6
|
+
slots: {};
|
|
7
|
+
events: {};
|
|
8
|
+
};
|
|
9
|
+
declare class __sveltets_Render<TData> {
|
|
10
|
+
props(): ReturnType<typeof $$render<TData>>['props'];
|
|
11
|
+
events(): ReturnType<typeof $$render<TData>>['events'];
|
|
12
|
+
slots(): ReturnType<typeof $$render<TData>>['slots'];
|
|
13
|
+
bindings(): "";
|
|
14
|
+
exports(): {};
|
|
15
|
+
}
|
|
16
|
+
interface $$IsomorphicComponent {
|
|
17
|
+
new <TData>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TData>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TData>['props']>, ReturnType<__sveltets_Render<TData>['events']>, ReturnType<__sveltets_Render<TData>['slots']>> & {
|
|
18
|
+
$$bindings?: ReturnType<__sveltets_Render<TData>['bindings']>;
|
|
19
|
+
} & ReturnType<__sveltets_Render<TData>['exports']>;
|
|
20
|
+
<TData>(internal: unknown, props: ReturnType<__sveltets_Render<TData>['props']> & {}): ReturnType<__sveltets_Render<TData>['exports']>;
|
|
21
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
22
|
+
}
|
|
23
|
+
declare const DataTable: $$IsomorphicComponent;
|
|
24
|
+
type DataTable<TData> = InstanceType<typeof DataTable<TData>>;
|
|
25
|
+
export default DataTable;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script
|
|
2
|
+
lang="ts"
|
|
3
|
+
generics="TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>"
|
|
4
|
+
>
|
|
5
|
+
import type { CellContext, ColumnDefTemplate, HeaderContext } from '@tanstack/table-core'
|
|
6
|
+
import { RenderComponentConfig, RenderSnippetConfig } from './render-helpers.js'
|
|
7
|
+
import type { Attachment } from 'svelte/attachments'
|
|
8
|
+
type Props = {
|
|
9
|
+
/** The cell or header field of the current cell's column definition. */
|
|
10
|
+
content?: TContext extends HeaderContext<TData, TValue>
|
|
11
|
+
? ColumnDefTemplate<HeaderContext<TData, TValue>>
|
|
12
|
+
: TContext extends CellContext<TData, TValue>
|
|
13
|
+
? ColumnDefTemplate<CellContext<TData, TValue>>
|
|
14
|
+
: never
|
|
15
|
+
/** The result of the `getContext()` function of the header or cell */
|
|
16
|
+
context: TContext
|
|
17
|
+
|
|
18
|
+
/** Used to pass attachments that can't be gotten through context */
|
|
19
|
+
attach?: Attachment
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let { content, context, attach }: Props = $props()
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
{#if typeof content === 'string'}
|
|
26
|
+
{content}
|
|
27
|
+
{:else if content instanceof Function}
|
|
28
|
+
<!-- It's unlikely that a CellContext will be passed to a Header -->
|
|
29
|
+
<!-- eslint-disable-next-line @typescript-eslint/no-explicit-any -->
|
|
30
|
+
{@const result = content(context as any)}
|
|
31
|
+
{#if result instanceof RenderComponentConfig}
|
|
32
|
+
{@const { component: Component, props } = result}
|
|
33
|
+
<Component {...props} {attach} />
|
|
34
|
+
{:else if result instanceof RenderSnippetConfig}
|
|
35
|
+
{@const { snippet, params } = result}
|
|
36
|
+
{@render snippet({ ...params, attach })}
|
|
37
|
+
{:else}
|
|
38
|
+
{result}
|
|
39
|
+
{/if}
|
|
40
|
+
{/if}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { CellContext, ColumnDefTemplate, HeaderContext } from '@tanstack/table-core';
|
|
2
|
+
import type { Attachment } from 'svelte/attachments';
|
|
3
|
+
declare function $$render<TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>>(): {
|
|
4
|
+
props: {
|
|
5
|
+
/** The cell or header field of the current cell's column definition. */
|
|
6
|
+
content?: TContext extends HeaderContext<TData, TValue> ? ColumnDefTemplate<HeaderContext<TData, TValue>> : TContext extends CellContext<TData, TValue> ? ColumnDefTemplate<CellContext<TData, TValue>> : never;
|
|
7
|
+
/** The result of the `getContext()` function of the header or cell */
|
|
8
|
+
context: TContext;
|
|
9
|
+
/** Used to pass attachments that can't be gotten through context */
|
|
10
|
+
attach?: Attachment;
|
|
11
|
+
};
|
|
12
|
+
exports: {};
|
|
13
|
+
bindings: "";
|
|
14
|
+
slots: {};
|
|
15
|
+
events: {};
|
|
16
|
+
};
|
|
17
|
+
declare class __sveltets_Render<TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>> {
|
|
18
|
+
props(): ReturnType<typeof $$render<TData, TValue, TContext>>['props'];
|
|
19
|
+
events(): ReturnType<typeof $$render<TData, TValue, TContext>>['events'];
|
|
20
|
+
slots(): ReturnType<typeof $$render<TData, TValue, TContext>>['slots'];
|
|
21
|
+
bindings(): "";
|
|
22
|
+
exports(): {};
|
|
23
|
+
}
|
|
24
|
+
interface $$IsomorphicComponent {
|
|
25
|
+
new <TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<TData, TValue, TContext>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<TData, TValue, TContext>['props']>, ReturnType<__sveltets_Render<TData, TValue, TContext>['events']>, ReturnType<__sveltets_Render<TData, TValue, TContext>['slots']>> & {
|
|
26
|
+
$$bindings?: ReturnType<__sveltets_Render<TData, TValue, TContext>['bindings']>;
|
|
27
|
+
} & ReturnType<__sveltets_Render<TData, TValue, TContext>['exports']>;
|
|
28
|
+
<TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>>(internal: unknown, props: ReturnType<__sveltets_Render<TData, TValue, TContext>['props']> & {}): ReturnType<__sveltets_Render<TData, TValue, TContext>['exports']>;
|
|
29
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any, any, any>['bindings']>;
|
|
30
|
+
}
|
|
31
|
+
declare const FlexRender: $$IsomorphicComponent;
|
|
32
|
+
type FlexRender<TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>> = InstanceType<typeof FlexRender<TData, TValue, TContext>>;
|
|
33
|
+
export default FlexRender;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { default as DataTable } from "./data-table.svelte";
|
|
2
|
+
export { default as DataTableToolbar } from "./data-table-toolbar.svelte";
|
|
3
|
+
export { default as DataTableViewOptions } from "./data-table-view-options.svelte";
|
|
4
|
+
export { default as FlexRender } from "./flex-render.svelte";
|
|
5
|
+
export { createSvelteTable } from "./data-table-svelte.svelte.js";
|
|
6
|
+
export { renderComponent, renderSnippet } from "./render-helpers.js";
|
|
7
|
+
export { createColumns } from "./create-columns.js";
|
|
8
|
+
export { default as TextCell } from "./cells/text-cell.svelte";
|
|
9
|
+
export { default as BooleanCell } from "./cells/boolean-cell.svelte";
|
|
10
|
+
export { default as TagCell } from "./cells/tag-cell.svelte";
|
|
11
|
+
export { default as DateCell } from "./cells/date-cell.svelte";
|
|
12
|
+
export { default as CurrencyCell } from "./cells/currency-cell.svelte";
|
|
13
|
+
export type { DataTableColumn, DataTableProps, CellType, TextCellConfig, BooleanCellConfig, TagCellConfig, DateCellConfig, CurrencyCellConfig, CellConfig } from "./data-table-types.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { default as DataTable } from "./data-table.svelte";
|
|
2
|
+
export { default as DataTableToolbar } from "./data-table-toolbar.svelte";
|
|
3
|
+
export { default as DataTableViewOptions } from "./data-table-view-options.svelte";
|
|
4
|
+
export { default as FlexRender } from "./flex-render.svelte";
|
|
5
|
+
export { createSvelteTable } from "./data-table-svelte.svelte.js";
|
|
6
|
+
export { renderComponent, renderSnippet } from "./render-helpers.js";
|
|
7
|
+
export { createColumns } from "./create-columns.js";
|
|
8
|
+
// Re-export cell components
|
|
9
|
+
export { default as TextCell } from "./cells/text-cell.svelte";
|
|
10
|
+
export { default as BooleanCell } from "./cells/boolean-cell.svelte";
|
|
11
|
+
export { default as TagCell } from "./cells/tag-cell.svelte";
|
|
12
|
+
export { default as DateCell } from "./cells/date-cell.svelte";
|
|
13
|
+
export { default as CurrencyCell } from "./cells/currency-cell.svelte";
|