pika-ux 1.0.0-beta.9 → 1.0.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/cli/template-files/pnpm-workspace.yaml +3 -3
- package/dist/cli/template-files/src/App.svelte +1 -1
- package/package.json +8 -1
- package/src/.DS_Store +0 -0
- package/src/App.svelte +2 -4
- package/src/icons/lucide/index.d.ts +28 -0
- package/src/pika/confirm-dialog/confirm-dialog.svelte +1 -1
- package/src/pika/pika-table/pika-table-pagination.svelte +32 -25
- package/src/pika/pika-table/pika-table-row-actions.svelte +1 -1
- package/src/pika/pika-table/pika-table.svelte +84 -58
- package/src/pika/pika-table/types.ts +13 -3
- package/src/pika/pika-toggle/index.ts +13 -0
- package/src/pika/pika-toggle/toggle.svelte +52 -0
- package/src/pika/pika-toggle-group/index.ts +10 -0
- package/src/pika/pika-toggle-group/toggle-group-item.svelte +88 -0
- package/src/pika/pika-toggle-group/toggle-group.svelte +72 -0
- package/src/pika/popup-help/popup-help.svelte +9 -3
- package/src/shadcn/chart/chart-container.svelte +69 -0
- package/src/shadcn/chart/chart-style.svelte +28 -0
- package/src/shadcn/chart/chart-tooltip.svelte +126 -0
- package/src/shadcn/chart/chart-utils.ts +37 -0
- package/src/shadcn/chart/index.ts +4 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-group.svelte +2 -3
- package/src/shadcn/dropdown-menu/dropdown-menu-item.svelte +1 -1
- package/src/shadcn/dropdown-menu/dropdown-menu-label.svelte +1 -7
- package/src/shadcn/dropdown-menu/dropdown-menu-radio-group.svelte +3 -13
- package/src/shadcn/dropdown-menu/dropdown-menu-radio-item.svelte +0 -1
- package/src/shadcn/dropdown-menu/dropdown-menu-separator.svelte +1 -7
- package/src/shadcn/dropdown-menu/dropdown-menu-shortcut.svelte +2 -13
- package/src/shadcn/dropdown-menu/dropdown-menu-sub-content.svelte +0 -1
- package/src/shadcn/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -2
- package/src/shadcn/dropdown-menu/dropdown-menu-trigger.svelte +2 -3
- package/src/shadcn/dropdown-menu/index.ts +44 -45
- package/src/shadcn/dropdown-menu copy/dropdown-menu-checkbox-item.svelte +41 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-content.svelte +27 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-group-heading.svelte +22 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-group.svelte +7 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-item.svelte +27 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-label.svelte +24 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-radio-group.svelte +16 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-radio-item.svelte +26 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-separator.svelte +13 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-shortcut.svelte +20 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-sub-content.svelte +16 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-sub-trigger.svelte +29 -0
- package/src/shadcn/dropdown-menu copy/dropdown-menu-trigger.svelte +7 -0
- package/src/shadcn/spinner/index.ts +1 -0
- package/src/shadcn/spinner/spinner.svelte +9 -0
- package/src/shadcn/toggle/toggle.svelte +36 -45
- package/src/shadcn/toggle-group/toggle-group-item.svelte +20 -23
- package/src/shadcn/toggle-group/toggle-group.svelte +9 -1
- /package/dist/cli/template-files/src/lib/{Counter.svelte → counter.svelte} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
catalog:
|
|
2
2
|
'@iconify-json/ci': ^1.2.2
|
|
3
|
-
'@iconify-json/lucide': ^1.2.
|
|
3
|
+
'@iconify-json/lucide': ^1.2.68
|
|
4
4
|
'@internationalized/date': ^3.8.1
|
|
5
|
-
'@lucide/svelte': ^0.
|
|
5
|
+
'@lucide/svelte': ^0.544.0
|
|
6
6
|
'@sveltejs/vite-plugin-svelte': ^6.2.0
|
|
7
7
|
'@tailwindcss/typography': ^0.5.16
|
|
8
8
|
'@tailwindcss/vite': ^4.1.13
|
|
@@ -17,5 +17,5 @@ catalog:
|
|
|
17
17
|
tailwindcss: ^4.1.11
|
|
18
18
|
tw-animate-css: ^1.4.0
|
|
19
19
|
typescript: ^5.9.2
|
|
20
|
-
unplugin-icons: ^22.
|
|
20
|
+
unplugin-icons: ^22.4.1
|
|
21
21
|
vite: ^7.1.7
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pika-ux",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./pika/*": "./src/pika/*",
|
|
@@ -29,14 +29,21 @@
|
|
|
29
29
|
"@tailwindcss/typography": "^0.5.16",
|
|
30
30
|
"@tailwindcss/vite": "^4.1.13",
|
|
31
31
|
"@tsconfig/svelte": "^5.0.5",
|
|
32
|
+
"@types/d3-array": "^3.2.2",
|
|
33
|
+
"@types/d3-scale": "^4.0.9",
|
|
34
|
+
"@types/d3-shape": "^3.1.7",
|
|
32
35
|
"@types/fs-extra": "^11.0.4",
|
|
33
36
|
"@types/indefinite": "^2.3.4",
|
|
34
37
|
"@types/inquirer": "^9.0.8",
|
|
35
38
|
"@types/node": "^22.15.17",
|
|
36
39
|
"@types/semver": "^7.7.0",
|
|
37
40
|
"bits-ui": "^1.8.0",
|
|
41
|
+
"d3-array": "^3.2.4",
|
|
42
|
+
"d3-scale": "^4.0.2",
|
|
43
|
+
"d3-shape": "^3.2.0",
|
|
38
44
|
"embla-carousel-svelte": "^8.6.0",
|
|
39
45
|
"eslint": "^9.26.0",
|
|
46
|
+
"layerchart": "^2.0.0-next.42",
|
|
40
47
|
"tailwind-merge": "^3.3.1",
|
|
41
48
|
"tailwind-variants": "^3.1.1",
|
|
42
49
|
"tailwindcss": "^4.1.11",
|
package/src/.DS_Store
CHANGED
|
Binary file
|
package/src/App.svelte
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import './app.css';
|
|
3
3
|
import Navigation from './lib/docsite/Navigation.svelte';
|
|
4
|
-
|
|
5
|
-
// Page components
|
|
6
|
-
import GettingStarted from './lib/docsite/pages/GettingStarted.svelte';
|
|
7
|
-
import Icons from './lib/docsite/pages/Icons.svelte';
|
|
8
4
|
import Colors from './lib/docsite/pages/Colors.svelte';
|
|
9
5
|
import Components from './lib/docsite/pages/Components.svelte';
|
|
10
6
|
import Button from './lib/docsite/pages/components/Button.svelte';
|
|
7
|
+
import GettingStarted from './lib/docsite/pages/GettingStarted.svelte';
|
|
8
|
+
import Icons from './lib/docsite/pages/Icons.svelte';
|
|
11
9
|
|
|
12
10
|
// Simple routing state
|
|
13
11
|
let currentPage = $state('getting-started');
|
|
@@ -1256,6 +1256,13 @@ declare module '$icons/lucide/bird' {
|
|
|
1256
1256
|
export default component;
|
|
1257
1257
|
}
|
|
1258
1258
|
|
|
1259
|
+
declare module '$icons/lucide/birdhouse' {
|
|
1260
|
+
import type { Component } from 'svelte';
|
|
1261
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
1262
|
+
const component: Component<SvelteHTMLElements['svg']>;
|
|
1263
|
+
export default component;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1259
1266
|
declare module '$icons/lucide/bitcoin' {
|
|
1260
1267
|
import type { Component } from 'svelte';
|
|
1261
1268
|
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
@@ -5029,6 +5036,13 @@ declare module '$icons/lucide/gamepad-2' {
|
|
|
5029
5036
|
export default component;
|
|
5030
5037
|
}
|
|
5031
5038
|
|
|
5039
|
+
declare module '$icons/lucide/gamepad-directional' {
|
|
5040
|
+
import type { Component } from 'svelte';
|
|
5041
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
5042
|
+
const component: Component<SvelteHTMLElements['svg']>;
|
|
5043
|
+
export default component;
|
|
5044
|
+
}
|
|
5045
|
+
|
|
5032
5046
|
declare module '$icons/lucide/gauge' {
|
|
5033
5047
|
import type { Component } from 'svelte';
|
|
5034
5048
|
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
@@ -7038,6 +7052,13 @@ declare module '$icons/lucide/monitor-check' {
|
|
|
7038
7052
|
export default component;
|
|
7039
7053
|
}
|
|
7040
7054
|
|
|
7055
|
+
declare module '$icons/lucide/monitor-cloud' {
|
|
7056
|
+
import type { Component } from 'svelte';
|
|
7057
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
7058
|
+
const component: Component<SvelteHTMLElements['svg']>;
|
|
7059
|
+
export default component;
|
|
7060
|
+
}
|
|
7061
|
+
|
|
7041
7062
|
declare module '$icons/lucide/monitor-cog' {
|
|
7042
7063
|
import type { Component } from 'svelte';
|
|
7043
7064
|
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
@@ -7129,6 +7150,13 @@ declare module '$icons/lucide/moon-star' {
|
|
|
7129
7150
|
export default component;
|
|
7130
7151
|
}
|
|
7131
7152
|
|
|
7153
|
+
declare module '$icons/lucide/motorbike' {
|
|
7154
|
+
import type { Component } from 'svelte';
|
|
7155
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
7156
|
+
const component: Component<SvelteHTMLElements['svg']>;
|
|
7157
|
+
export default component;
|
|
7158
|
+
}
|
|
7159
|
+
|
|
7132
7160
|
declare module '$icons/lucide/mountain' {
|
|
7133
7161
|
import type { Component } from 'svelte';
|
|
7134
7162
|
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
type TData = unknown;
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
|
+
<!-- @component
|
|
6
|
+
PikaTablePagination - Pagination controls for PikaTable
|
|
7
|
+
-->
|
|
5
8
|
<script lang="ts" generics="TData">
|
|
9
|
+
// @ts-ignore - Props interface is private but this is a Svelte framework limitation
|
|
6
10
|
import ChevronLeft from '$icons/lucide/chevron-left';
|
|
7
11
|
import ChevronRight from '$icons/lucide/chevron-right';
|
|
8
12
|
import ChevronsLeft from '$icons/lucide/chevrons-left';
|
|
@@ -15,9 +19,10 @@
|
|
|
15
19
|
interface Props {
|
|
16
20
|
table: Table<TData>;
|
|
17
21
|
serverSide: ServerSideConfig;
|
|
22
|
+
showRowsPerPage?: boolean;
|
|
18
23
|
}
|
|
19
24
|
|
|
20
|
-
let { table, serverSide }: Props = $props();
|
|
25
|
+
let { table, serverSide, showRowsPerPage = true }: Props = $props();
|
|
21
26
|
|
|
22
27
|
// For cursor-based pagination, we can't jump to arbitrary pages
|
|
23
28
|
const isCursorBased = $derived(serverSide?.paginationMode === 'cursor');
|
|
@@ -33,30 +38,32 @@
|
|
|
33
38
|
{table.getFilteredRowModel().rows.length} row(s) selected.
|
|
34
39
|
{/if}
|
|
35
40
|
</div>
|
|
36
|
-
<div class="flex items-center space-x-
|
|
37
|
-
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
{pageSize}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
41
|
+
<div class="flex items-center space-x-8">
|
|
42
|
+
{#if showRowsPerPage}
|
|
43
|
+
<div class="flex items-center space-x-2">
|
|
44
|
+
<p class="text-sm font-medium">Rows per page</p>
|
|
45
|
+
<Select.Root
|
|
46
|
+
allowDeselect={false}
|
|
47
|
+
type="single"
|
|
48
|
+
value={`${table.getState().pagination.pageSize}`}
|
|
49
|
+
onValueChange={(value) => {
|
|
50
|
+
table.setPageSize(Number(value));
|
|
51
|
+
}}
|
|
52
|
+
>
|
|
53
|
+
<Select.Trigger class="h-8 w-[70px]">
|
|
54
|
+
{String(table.getState().pagination.pageSize)}
|
|
55
|
+
</Select.Trigger>
|
|
56
|
+
<Select.Content side="top">
|
|
57
|
+
{#each [10, 20, 50, 100, 500, 1000] as pageSize (pageSize)}
|
|
58
|
+
<Select.Item value={`${pageSize}`}>
|
|
59
|
+
{pageSize}
|
|
60
|
+
</Select.Item>
|
|
61
|
+
{/each}
|
|
62
|
+
</Select.Content>
|
|
63
|
+
</Select.Root>
|
|
64
|
+
</div>
|
|
65
|
+
{/if}
|
|
66
|
+
<div class="flex w-[100px] items-center justify-center text-sm font-medium mr-2">
|
|
60
67
|
{#if table.getPageCount() > 0}
|
|
61
68
|
Page {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
|
|
62
69
|
{:else}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
{:else if 'menuItems' in item}
|
|
46
46
|
{@render subMenu(item)}
|
|
47
47
|
{:else}
|
|
48
|
-
<DropdownMenu.Item onclick={() => item.onclick?.(row
|
|
48
|
+
<DropdownMenu.Item onclick={() => item.onclick?.(row)}>
|
|
49
49
|
<div class="flex items-center gap-2">
|
|
50
50
|
{#if item.icon}
|
|
51
51
|
<item.icon />
|
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
type TValue = unknown;
|
|
4
4
|
</script>
|
|
5
5
|
|
|
6
|
+
<!-- @component
|
|
7
|
+
PikaTable - A reusable table component with server-side pagination, sorting, and filtering support
|
|
8
|
+
-->
|
|
6
9
|
<script lang="ts" generics="TData, TValue">
|
|
7
|
-
|
|
10
|
+
// @ts-ignore - Props interface is private but this is a Svelte framework limitation
|
|
8
11
|
import { createSvelteTable } from '../../shadcn/data-table/data-table.svelte';
|
|
9
12
|
import FlexRender from '../../shadcn/data-table/flex-render.svelte';
|
|
10
13
|
import * as Table from '../../shadcn/table';
|
|
@@ -20,10 +23,10 @@
|
|
|
20
23
|
type RowSelectionState,
|
|
21
24
|
type SortingState
|
|
22
25
|
} from '@tanstack/table-core';
|
|
23
|
-
import {
|
|
26
|
+
import { type Snippet } from 'svelte';
|
|
24
27
|
import TablePagination from './pika-table-pagination.svelte';
|
|
25
28
|
import TableToolbar from './pika-table-toolbar.svelte';
|
|
26
|
-
import type { FacetedFilters, GlobalFilterProps, ServerSideConfig, ServerSideTableState } from './types';
|
|
29
|
+
import type { FacetedFilters, GlobalFilterProps, ServerSideConfig, ServerSideTableState, TableSettingsFacade } from './types';
|
|
27
30
|
|
|
28
31
|
interface Props {
|
|
29
32
|
columns: ColumnDef<TData, TValue>[];
|
|
@@ -48,6 +51,15 @@
|
|
|
48
51
|
|
|
49
52
|
// Server-side configuration
|
|
50
53
|
serverSideConfig?: ServerSideConfig;
|
|
54
|
+
|
|
55
|
+
// Facade for table settings (required)
|
|
56
|
+
tableSettings: TableSettingsFacade;
|
|
57
|
+
|
|
58
|
+
// Show rows per page selector in pagination
|
|
59
|
+
showRowsPerPage?: boolean;
|
|
60
|
+
|
|
61
|
+
// Where to show pagination controls
|
|
62
|
+
paginationPlacement?: 'top' | 'bottom' | 'both';
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
let {
|
|
@@ -59,61 +71,64 @@
|
|
|
59
71
|
toolbarContent,
|
|
60
72
|
beneathToolbarContent,
|
|
61
73
|
tableKey,
|
|
62
|
-
serverSideConfig = $bindable<ServerSideConfig>()
|
|
74
|
+
serverSideConfig = $bindable<ServerSideConfig>(),
|
|
75
|
+
tableSettings,
|
|
76
|
+
showRowsPerPage = true,
|
|
77
|
+
paginationPlacement = 'bottom'
|
|
63
78
|
}: Props = $props();
|
|
64
79
|
|
|
65
|
-
const appState = getContext<AppState>('appState');
|
|
66
|
-
const appSettings = appState.settings;
|
|
67
|
-
|
|
68
80
|
let rowSelection = $state<RowSelectionState>({});
|
|
69
|
-
let columnVisibility = $derived(
|
|
70
|
-
//$state<VisibilityState>(appSettings.getTableColumnVisibilityObject(tableKey));
|
|
81
|
+
let columnVisibility = $derived(tableSettings.getTableColumnVisibilityObject(tableKey));
|
|
71
82
|
let columnFilters = $state<ColumnFiltersState>([]);
|
|
72
83
|
let sorting = $state<SortingState>([]);
|
|
73
84
|
let pageIndex = $state(0);
|
|
74
|
-
let pageSize = $derived(
|
|
85
|
+
let pageSize = $derived(tableSettings.getTableNumRows(tableKey, 10));
|
|
75
86
|
|
|
76
87
|
// === SERVER-SIDE LOGIC ===
|
|
77
88
|
|
|
78
89
|
let debouncedRequestData: ((tableState: ServerSideTableState) => Promise<void>) | undefined;
|
|
79
90
|
|
|
80
91
|
// Create debounced function when serverSide config changes
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
$effect(() => {
|
|
93
|
+
const serverState = serverSideConfig;
|
|
94
|
+
if (serverState) {
|
|
95
|
+
const debounceMs = serverState.debounceMs ?? 300;
|
|
96
|
+
debouncedRequestData = debounce(async (tableState: ServerSideTableState) => {
|
|
97
|
+
try {
|
|
98
|
+
await serverState.requestData(tableState);
|
|
88
99
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
// If using new API, update the tableState
|
|
101
|
+
if (serverSideConfig) {
|
|
102
|
+
serverSideConfig.tableState = { ...serverSideConfig.tableState, ...tableState };
|
|
103
|
+
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
serverState.onError?.(error instanceof Error ? error.message : 'Unknown error');
|
|
106
|
+
}
|
|
107
|
+
}, debounceMs);
|
|
108
|
+
} else {
|
|
109
|
+
debouncedRequestData = undefined;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
101
112
|
|
|
102
113
|
// Trigger server request when table state changes
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
114
|
+
function triggerServerRequest() {
|
|
115
|
+
const serverState = serverSideConfig;
|
|
116
|
+
if (!serverState || !debouncedRequestData) return;
|
|
106
117
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
118
|
+
const tableState: ServerSideTableState = {
|
|
119
|
+
pageIndex,
|
|
120
|
+
pageSize,
|
|
121
|
+
sorting,
|
|
122
|
+
columnFilters,
|
|
123
|
+
totalRecords: serverState.tableState?.totalRecords,
|
|
124
|
+
scrollId: serverState.tableState?.scrollId,
|
|
125
|
+
hasNextPage: serverState.tableState?.hasNextPage,
|
|
126
|
+
isLoading: true,
|
|
127
|
+
requestId: crypto.randomUUID()
|
|
128
|
+
};
|
|
114
129
|
|
|
115
|
-
|
|
116
|
-
|
|
130
|
+
debouncedRequestData(tableState);
|
|
131
|
+
}
|
|
117
132
|
|
|
118
133
|
// Utility function for debouncing
|
|
119
134
|
function debounce<T extends (...args: any[]) => any>(func: T, wait: number): T {
|
|
@@ -194,9 +209,9 @@
|
|
|
194
209
|
}
|
|
195
210
|
|
|
196
211
|
// Trigger server request for server-side tables
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
212
|
+
if (serverSideConfig) {
|
|
213
|
+
triggerServerRequest();
|
|
214
|
+
}
|
|
200
215
|
},
|
|
201
216
|
onColumnFiltersChange: (updater) => {
|
|
202
217
|
if (typeof updater === 'function') {
|
|
@@ -206,13 +221,13 @@
|
|
|
206
221
|
}
|
|
207
222
|
|
|
208
223
|
// Trigger server request for server-side tables
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
224
|
+
if (serverSideConfig) {
|
|
225
|
+
triggerServerRequest();
|
|
226
|
+
}
|
|
212
227
|
},
|
|
213
228
|
onColumnVisibilityChange: (updater) => {
|
|
214
229
|
if (typeof updater === 'function') {
|
|
215
|
-
|
|
230
|
+
tableSettings.setTableColumnVisibilityFromObject(tableKey, updater(columnVisibility));
|
|
216
231
|
} else {
|
|
217
232
|
throw new Error('onColumnVisibilityChange updater must be a function');
|
|
218
233
|
//columnVisibility = updater;
|
|
@@ -222,12 +237,12 @@
|
|
|
222
237
|
if (typeof updater === 'function') {
|
|
223
238
|
const val = updater({ pageIndex, pageSize });
|
|
224
239
|
pageIndex = val.pageIndex;
|
|
225
|
-
|
|
240
|
+
tableSettings.setTableNumRows(tableKey, val.pageSize);
|
|
226
241
|
|
|
227
242
|
// Trigger server request for server-side tables
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
243
|
+
if (serverSideConfig) {
|
|
244
|
+
triggerServerRequest();
|
|
245
|
+
}
|
|
231
246
|
} else {
|
|
232
247
|
throw new Error('onPaginationChange updater must be a function');
|
|
233
248
|
}
|
|
@@ -237,9 +252,9 @@
|
|
|
237
252
|
globalFilterProps.globalFilterValue = value;
|
|
238
253
|
|
|
239
254
|
// Trigger server request for server-side tables
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
255
|
+
if (serverSideConfig) {
|
|
256
|
+
triggerServerRequest();
|
|
257
|
+
}
|
|
243
258
|
}
|
|
244
259
|
},
|
|
245
260
|
|
|
@@ -257,8 +272,15 @@
|
|
|
257
272
|
});
|
|
258
273
|
</script>
|
|
259
274
|
|
|
260
|
-
<div class="
|
|
261
|
-
<
|
|
275
|
+
<div class="{classes ? classes : ''} ">
|
|
276
|
+
<div class="mb-4">
|
|
277
|
+
<TableToolbar {table} {globalFilterProps} {facetedFilters} {toolbarContent} {beneathToolbarContent} />
|
|
278
|
+
</div>
|
|
279
|
+
{#if paginationPlacement === 'top' || paginationPlacement === 'both'}
|
|
280
|
+
<div class="mt-2 pb-1">
|
|
281
|
+
<TablePagination {table} serverSide={serverSideConfig} {showRowsPerPage} />
|
|
282
|
+
</div>
|
|
283
|
+
{/if}
|
|
262
284
|
<div class="rounded-md border h-full flex flex-col overflow-y-auto">
|
|
263
285
|
<Table.Root class="h-full">
|
|
264
286
|
<Table.Header>
|
|
@@ -291,5 +313,9 @@
|
|
|
291
313
|
</Table.Body>
|
|
292
314
|
</Table.Root>
|
|
293
315
|
</div>
|
|
294
|
-
|
|
316
|
+
{#if paginationPlacement === 'bottom' || paginationPlacement === 'both'}
|
|
317
|
+
<div class="mt-2">
|
|
318
|
+
<TablePagination {table} serverSide={serverSideConfig} {showRowsPerPage} />
|
|
319
|
+
</div>
|
|
320
|
+
{/if}
|
|
295
321
|
</div>
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Column, ColumnFiltersState, Row, SortingState } from '@tanstack/table-core';
|
|
1
|
+
import type { Column, ColumnFiltersState, Row, SortingState, VisibilityState } from '@tanstack/table-core';
|
|
3
2
|
import type { Component } from 'svelte';
|
|
4
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Facade for table settings (column visibility, page size, etc.)
|
|
6
|
+
* This allows the pika-table component to be used without depending on AppState
|
|
7
|
+
*/
|
|
8
|
+
export interface TableSettingsFacade {
|
|
9
|
+
getTableColumnVisibilityObject(tableKey: string): VisibilityState;
|
|
10
|
+
getTableNumRows(tableKey: string, defaultValue: number): number;
|
|
11
|
+
setTableNumRows(tableKey: string, value: number): void;
|
|
12
|
+
setTableColumnVisibilityFromObject(tableKey: string, visibility: VisibilityState): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
5
15
|
export interface FacetedFilterData {
|
|
6
16
|
label: string;
|
|
7
17
|
value: string;
|
|
@@ -44,7 +54,7 @@ export interface GlobalFilterProps {
|
|
|
44
54
|
export interface RowActionMenuItemNode<TData> {
|
|
45
55
|
label: string;
|
|
46
56
|
icon?: Component;
|
|
47
|
-
onclick?: (row: Row<TData
|
|
57
|
+
onclick?: (row: Row<TData>) => void;
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
export interface RowActionMenuItemSubMenu<TData> {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import { type VariantProps, tv } from "tailwind-variants";
|
|
3
|
+
|
|
4
|
+
export const toggleVariants = tv({
|
|
5
|
+
base: "hover:bg-gray-200 hover:text-gray-900 data-[state=on]:bg-gray-200 data-[state=on]:text-gray-900 focus-visible:ring-ring inline-flex items-center justify-center gap-2 rounded-sm text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
6
|
+
variants: {
|
|
7
|
+
variant: {
|
|
8
|
+
default: "bg-white",
|
|
9
|
+
outline:
|
|
10
|
+
"border-input shadow-sm hover:bg-gray-200 hover:text-gray-900 border bg-white",
|
|
11
|
+
},
|
|
12
|
+
size: {
|
|
13
|
+
default: "h-9 min-w-9 px-3",
|
|
14
|
+
sm: "h-8 min-w-8 px-2",
|
|
15
|
+
lg: "h-10 min-w-10 px-3",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
defaultVariants: {
|
|
19
|
+
variant: "default",
|
|
20
|
+
size: "default",
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export type ToggleVariant = VariantProps<typeof toggleVariants>["variant"];
|
|
25
|
+
export type ToggleSize = VariantProps<typeof toggleVariants>["size"];
|
|
26
|
+
export type ToggleVariants = VariantProps<typeof toggleVariants>;
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<script lang="ts">
|
|
30
|
+
import { Toggle as TogglePrimitive } from "bits-ui";
|
|
31
|
+
import { cn } from '../../shadcn/utils.js';
|
|
32
|
+
|
|
33
|
+
let {
|
|
34
|
+
ref = $bindable(null),
|
|
35
|
+
pressed = $bindable(false),
|
|
36
|
+
class: className,
|
|
37
|
+
size = "default",
|
|
38
|
+
variant = "default",
|
|
39
|
+
...restProps
|
|
40
|
+
}: TogglePrimitive.RootProps & {
|
|
41
|
+
variant?: ToggleVariant;
|
|
42
|
+
size?: ToggleSize;
|
|
43
|
+
} = $props();
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<TogglePrimitive.Root
|
|
47
|
+
bind:ref
|
|
48
|
+
bind:pressed
|
|
49
|
+
data-slot="toggle"
|
|
50
|
+
class={cn(toggleVariants({ variant, size }), className)}
|
|
51
|
+
{...restProps}
|
|
52
|
+
/>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getToggleGroupCtx } from "./toggle-group.svelte";
|
|
3
|
+
import { cn } from '../../shadcn/utils.js';
|
|
4
|
+
import type { Snippet } from 'svelte';
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
value: string;
|
|
8
|
+
class?: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
value,
|
|
15
|
+
class: className,
|
|
16
|
+
disabled = false,
|
|
17
|
+
children
|
|
18
|
+
}: Props = $props();
|
|
19
|
+
|
|
20
|
+
const ctx = getToggleGroupCtx();
|
|
21
|
+
|
|
22
|
+
const isSelected = $derived(() => {
|
|
23
|
+
const currentValue = ctx.getValue();
|
|
24
|
+
if (ctx.type === 'single') {
|
|
25
|
+
return currentValue === value;
|
|
26
|
+
} else {
|
|
27
|
+
const arr = Array.isArray(currentValue) ? currentValue : [];
|
|
28
|
+
return arr.includes(value);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
function handleClick() {
|
|
33
|
+
if (!disabled) {
|
|
34
|
+
ctx.toggle(value);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Determine if buttonWidth is a Tailwind class or CSS value
|
|
39
|
+
const widthClass = ctx.buttonWidth?.match(/^(w-|min-w-|max-w-)/) ? ctx.buttonWidth : undefined;
|
|
40
|
+
const widthStyle = ctx.buttonWidth && !widthClass ? `width: ${ctx.buttonWidth};` : '';
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<button
|
|
44
|
+
type="button"
|
|
45
|
+
onclick={handleClick}
|
|
46
|
+
disabled={disabled}
|
|
47
|
+
class={cn(
|
|
48
|
+
// Base styles
|
|
49
|
+
'inline-flex items-center justify-center',
|
|
50
|
+
'text-sm font-medium',
|
|
51
|
+
'transition-colors',
|
|
52
|
+
'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',
|
|
53
|
+
'disabled:pointer-events-none disabled:opacity-50',
|
|
54
|
+
|
|
55
|
+
// Size
|
|
56
|
+
'h-9 px-3',
|
|
57
|
+
|
|
58
|
+
// White background by default
|
|
59
|
+
'bg-white',
|
|
60
|
+
|
|
61
|
+
// Border for outline variant
|
|
62
|
+
'border border-input',
|
|
63
|
+
|
|
64
|
+
// Selected state - gray background
|
|
65
|
+
isSelected() && 'bg-gray-100 text-gray-700',
|
|
66
|
+
|
|
67
|
+
// Hover state - use primary color from your theme
|
|
68
|
+
'hover:text-primary',
|
|
69
|
+
|
|
70
|
+
// No rounded corners, borders between buttons
|
|
71
|
+
'border-l-0 first:border-l',
|
|
72
|
+
|
|
73
|
+
// Focus
|
|
74
|
+
'focus:z-10 focus-visible:z-10',
|
|
75
|
+
|
|
76
|
+
// Width
|
|
77
|
+
widthClass,
|
|
78
|
+
|
|
79
|
+
// Flex
|
|
80
|
+
'min-w-0 flex-1 shrink-0',
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
className
|
|
84
|
+
)}
|
|
85
|
+
style={widthStyle}
|
|
86
|
+
>
|
|
87
|
+
{@render children?.()}
|
|
88
|
+
</button>
|