pika-ux 1.0.0-beta.0
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/LICENSE +9 -0
- package/dist/icon-generator/generate-icon-ts-indices.js +78 -0
- package/dist/shadcn-postinstall/index.js +114 -0
- package/package.json +102 -0
- package/readme.md +50 -0
- package/scripts/setup.js +100 -0
- package/src/App.svelte +51 -0
- package/src/app.css +349 -0
- package/src/icons/ci/index.d.ts +5009 -0
- package/src/icons/lucide/index.d.ts +11274 -0
- package/src/index.ts +23 -0
- package/src/lib/docsite/Navigation.svelte +77 -0
- package/src/lib/docsite/pages/Colors.svelte +35 -0
- package/src/lib/docsite/pages/Components.svelte +50 -0
- package/src/lib/docsite/pages/GettingStarted.svelte +21 -0
- package/src/lib/docsite/pages/Icons.svelte +22 -0
- package/src/lib/docsite/pages/components/Button.svelte +40 -0
- package/src/main.ts +9 -0
- package/src/pika/chip/chip.svelte +95 -0
- package/src/pika/chip/index.ts +1 -0
- package/src/pika/combobox/combobox-types.ts +5 -0
- package/src/pika/combobox/combobox.svelte +221 -0
- package/src/pika/combobox/index.ts +2 -0
- package/src/pika/confirm-dialog/confirm-dialog.svelte +48 -0
- package/src/pika/confirm-dialog/index.ts +1 -0
- package/src/pika/copy-button/copy-button.svelte +134 -0
- package/src/pika/copy-button/index.ts +1 -0
- package/src/pika/create-copy-link-button/create-copy-link-button.svelte +133 -0
- package/src/pika/create-copy-link-button/index.ts +1 -0
- package/src/pika/date-picker/date-picker.svelte +33 -0
- package/src/pika/date-picker/index.ts +1 -0
- package/src/pika/date-range-picker/date-range-picker.svelte +48 -0
- package/src/pika/date-range-picker/index.ts +1 -0
- package/src/pika/date-time-picker/date-time-picker.svelte +336 -0
- package/src/pika/date-time-picker/index.ts +1 -0
- package/src/pika/expandable-container/expandable-container.svelte +155 -0
- package/src/pika/expandable-container/index.ts +1 -0
- package/src/pika/index.ts +29 -0
- package/src/pika/list/index.ts +2 -0
- package/src/pika/list/list-types.ts +5 -0
- package/src/pika/list/list.svelte +349 -0
- package/src/pika/markdown-editor/github.scss +87 -0
- package/src/pika/markdown-editor/index.ts +1 -0
- package/src/pika/markdown-editor/markdown-editor.svelte +44 -0
- package/src/pika/permanent-toast/index.ts +1 -0
- package/src/pika/permanent-toast/permanent-toast.svelte +47 -0
- package/src/pika/pika-alert/index.ts +1 -0
- package/src/pika/pika-alert/pika-alert.svelte +53 -0
- package/src/pika/pika-badge/index.ts +1 -0
- package/src/pika/pika-badge/pika-badge.svelte +61 -0
- package/src/pika/pika-table/index.ts +7 -0
- package/src/pika/pika-table/pika-table-cell.svelte +9 -0
- package/src/pika/pika-table/pika-table-checkbox.svelte +8 -0
- package/src/pika/pika-table/pika-table-column-header.svelte +88 -0
- package/src/pika/pika-table/pika-table-faceted-filter.svelte +109 -0
- package/src/pika/pika-table/pika-table-pagination.svelte +95 -0
- package/src/pika/pika-table/pika-table-row-actions.svelte +58 -0
- package/src/pika/pika-table/pika-table-toolbar.svelte +88 -0
- package/src/pika/pika-table/pika-table-view-options.svelte +35 -0
- package/src/pika/pika-table/pika-table.svelte +295 -0
- package/src/pika/pika-table/types.ts +106 -0
- package/src/pika/pika-tabs/index.ts +18 -0
- package/src/pika/pika-tabs/tabs-content.svelte +16 -0
- package/src/pika/pika-tabs/tabs-list.svelte +12 -0
- package/src/pika/pika-tabs/tabs-trigger.svelte +23 -0
- package/src/pika/popup-help/index.ts +1 -0
- package/src/pika/popup-help/popup-help.svelte +33 -0
- package/src/pika/simple-dropdown/index.ts +2 -0
- package/src/pika/simple-dropdown/simple-dropdown-types.ts +5 -0
- package/src/pika/simple-dropdown/simple-dropdown.svelte +288 -0
- package/src/pika/slideout/constants.ts +5 -0
- package/src/pika/slideout/context.svelte.ts +110 -0
- package/src/pika/slideout/index.ts +19 -0
- package/src/pika/slideout/slideout-content.svelte +36 -0
- package/src/pika/slideout/slideout-panel.svelte +126 -0
- package/src/pika/slideout/slideout-provider.svelte +49 -0
- package/src/pika/slideout/slideout-rail.svelte.die +69 -0
- package/src/pika/slideout/slideout.svelte +33 -0
- package/src/pika/slideout/slideout.svelte.old +113 -0
- package/src/pika/text-wave-shimmer/index.ts +1 -0
- package/src/pika/text-wave-shimmer/text-wave-shimmer.svelte +43 -0
- package/src/pika/tooltip-plus/index.ts +1 -0
- package/src/pika/tooltip-plus/tooltip-plus.svelte +42 -0
- package/src/shadcn/.DS_Store +0 -0
- package/src/shadcn/alert/alert-description.svelte +11 -0
- package/src/shadcn/alert/alert-title.svelte +24 -0
- package/src/shadcn/alert/alert.svelte +39 -0
- package/src/shadcn/alert/index.ts +14 -0
- package/src/shadcn/avatar/avatar-fallback.svelte +13 -0
- package/src/shadcn/avatar/avatar-image.svelte +13 -0
- package/src/shadcn/avatar/avatar.svelte +19 -0
- package/src/shadcn/avatar/index.ts +13 -0
- package/src/shadcn/badge/badge.svelte +48 -0
- package/src/shadcn/badge/index.ts +2 -0
- package/src/shadcn/breadcrumb/breadcrumb-ellipsis.svelte +12 -0
- package/src/shadcn/breadcrumb/breadcrumb-item.svelte +20 -0
- package/src/shadcn/breadcrumb/breadcrumb-link.svelte +31 -0
- package/src/shadcn/breadcrumb/breadcrumb-list.svelte +20 -0
- package/src/shadcn/breadcrumb/breadcrumb-page.svelte +23 -0
- package/src/shadcn/breadcrumb/breadcrumb-separator.svelte +15 -0
- package/src/shadcn/breadcrumb/breadcrumb.svelte +15 -0
- package/src/shadcn/breadcrumb/index.ts +25 -0
- package/src/shadcn/button/button.svelte +81 -0
- package/src/shadcn/button/index.ts +17 -0
- package/src/shadcn/calendar/calendar-caption.svelte +76 -0
- package/src/shadcn/calendar/calendar-cell.svelte +19 -0
- package/src/shadcn/calendar/calendar-day.svelte +31 -0
- package/src/shadcn/calendar/calendar-grid-body.svelte +12 -0
- package/src/shadcn/calendar/calendar-grid-head.svelte +12 -0
- package/src/shadcn/calendar/calendar-grid-row.svelte +12 -0
- package/src/shadcn/calendar/calendar-grid.svelte +16 -0
- package/src/shadcn/calendar/calendar-head-cell.svelte +16 -0
- package/src/shadcn/calendar/calendar-header.svelte +16 -0
- package/src/shadcn/calendar/calendar-heading.svelte +12 -0
- package/src/shadcn/calendar/calendar-month-select.svelte +25 -0
- package/src/shadcn/calendar/calendar-month.svelte +15 -0
- package/src/shadcn/calendar/calendar-months.svelte +20 -0
- package/src/shadcn/calendar/calendar-nav.svelte +19 -0
- package/src/shadcn/calendar/calendar-next-button.svelte +19 -0
- package/src/shadcn/calendar/calendar-prev-button.svelte +19 -0
- package/src/shadcn/calendar/calendar-year-select.svelte +25 -0
- package/src/shadcn/calendar/calendar.svelte +61 -0
- package/src/shadcn/calendar/index.ts +30 -0
- package/src/shadcn/card/card-content.svelte +16 -0
- package/src/shadcn/card/card-description.svelte +16 -0
- package/src/shadcn/card/card-footer.svelte +16 -0
- package/src/shadcn/card/card-header.svelte +16 -0
- package/src/shadcn/card/card-title.svelte +25 -0
- package/src/shadcn/card/card.svelte +20 -0
- package/src/shadcn/card/index.ts +22 -0
- package/src/shadcn/carousel/carousel-content.svelte +39 -0
- package/src/shadcn/carousel/carousel-item.svelte +26 -0
- package/src/shadcn/carousel/carousel-next.svelte +30 -0
- package/src/shadcn/carousel/carousel-previous.svelte +30 -0
- package/src/shadcn/carousel/carousel.svelte +88 -0
- package/src/shadcn/carousel/context.ts +51 -0
- package/src/shadcn/carousel/index.ts +19 -0
- package/src/shadcn/checkbox/checkbox.svelte +36 -0
- package/src/shadcn/checkbox/index.ts +6 -0
- package/src/shadcn/collapsible/collapsible-content.svelte +7 -0
- package/src/shadcn/collapsible/collapsible-trigger.svelte +7 -0
- package/src/shadcn/collapsible/collapsible.svelte +11 -0
- package/src/shadcn/collapsible/index.ts +13 -0
- package/src/shadcn/command/command-dialog.svelte +40 -0
- package/src/shadcn/command/command-empty.svelte +13 -0
- package/src/shadcn/command/command-group.svelte +30 -0
- package/src/shadcn/command/command-input.svelte +21 -0
- package/src/shadcn/command/command-item.svelte +16 -0
- package/src/shadcn/command/command-link-item.svelte +16 -0
- package/src/shadcn/command/command-list.svelte +13 -0
- package/src/shadcn/command/command-separator.svelte +13 -0
- package/src/shadcn/command/command-shortcut.svelte +20 -0
- package/src/shadcn/command/command.svelte +19 -0
- package/src/shadcn/command/index.ts +40 -0
- package/src/shadcn/data-table/data-table.svelte.ts +141 -0
- package/src/shadcn/data-table/flex-render.svelte +36 -0
- package/src/shadcn/data-table/index.ts +3 -0
- package/src/shadcn/data-table/render-helpers.ts +111 -0
- package/src/shadcn/dialog/dialog-close.svelte +7 -0
- package/src/shadcn/dialog/dialog-content.svelte +43 -0
- package/src/shadcn/dialog/dialog-description.svelte +13 -0
- package/src/shadcn/dialog/dialog-footer.svelte +20 -0
- package/src/shadcn/dialog/dialog-header.svelte +20 -0
- package/src/shadcn/dialog/dialog-overlay.svelte +16 -0
- package/src/shadcn/dialog/dialog-title.svelte +13 -0
- package/src/shadcn/dialog/dialog-trigger.svelte +7 -0
- package/src/shadcn/dialog/index.ts +37 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-checkbox-item.svelte +41 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-content.svelte +27 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-label.svelte +24 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-radio-item.svelte +26 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-separator.svelte +13 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-sub-content.svelte +16 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/src/shadcn/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/src/shadcn/dropdown-menu/index.ts +49 -0
- package/src/shadcn/index.ts +40 -0
- package/src/shadcn/input/index.ts +7 -0
- package/src/shadcn/input/input.svelte +51 -0
- package/src/shadcn/is-mobile.svelte.ts +9 -0
- package/src/shadcn/label/index.ts +7 -0
- package/src/shadcn/label/label.svelte +16 -0
- package/src/shadcn/popover/index.ts +17 -0
- package/src/shadcn/popover/popover-content.svelte +29 -0
- package/src/shadcn/popover/popover-trigger.svelte +8 -0
- package/src/shadcn/radio-group/index.ts +10 -0
- package/src/shadcn/radio-group/radio-group-item.svelte +25 -0
- package/src/shadcn/radio-group/radio-group.svelte +19 -0
- package/src/shadcn/range-calendar/index.ts +30 -0
- package/src/shadcn/range-calendar/range-calendar-cell.svelte +19 -0
- package/src/shadcn/range-calendar/range-calendar-day.svelte +35 -0
- package/src/shadcn/range-calendar/range-calendar-grid-body.svelte +12 -0
- package/src/shadcn/range-calendar/range-calendar-grid-head.svelte +12 -0
- package/src/shadcn/range-calendar/range-calendar-grid-row.svelte +12 -0
- package/src/shadcn/range-calendar/range-calendar-grid.svelte +16 -0
- package/src/shadcn/range-calendar/range-calendar-head-cell.svelte +16 -0
- package/src/shadcn/range-calendar/range-calendar-header.svelte +16 -0
- package/src/shadcn/range-calendar/range-calendar-heading.svelte +16 -0
- package/src/shadcn/range-calendar/range-calendar-months.svelte +20 -0
- package/src/shadcn/range-calendar/range-calendar-next-button.svelte +18 -0
- package/src/shadcn/range-calendar/range-calendar-prev-button.svelte +18 -0
- package/src/shadcn/range-calendar/range-calendar.svelte +57 -0
- package/src/shadcn/resizable/index.ts +13 -0
- package/src/shadcn/resizable/resizable-handle.svelte +30 -0
- package/src/shadcn/resizable/resizable-pane-group.svelte +22 -0
- package/src/shadcn/scroll-area/index.ts +10 -0
- package/src/shadcn/scroll-area/scroll-area-scrollbar.svelte +28 -0
- package/src/shadcn/scroll-area/scroll-area.svelte +35 -0
- package/src/shadcn/select/index.ts +37 -0
- package/src/shadcn/select/select-content.svelte +38 -0
- package/src/shadcn/select/select-group-heading.svelte +21 -0
- package/src/shadcn/select/select-group.svelte +7 -0
- package/src/shadcn/select/select-item.svelte +31 -0
- package/src/shadcn/select/select-label.svelte +20 -0
- package/src/shadcn/select/select-scroll-down-button.svelte +11 -0
- package/src/shadcn/select/select-scroll-up-button.svelte +11 -0
- package/src/shadcn/select/select-separator.svelte +14 -0
- package/src/shadcn/select/select-trigger.svelte +30 -0
- package/src/shadcn/separator/index.ts +7 -0
- package/src/shadcn/separator/separator.svelte +16 -0
- package/src/shadcn/sheet/index.ts +36 -0
- package/src/shadcn/sheet/sheet-close.svelte +7 -0
- package/src/shadcn/sheet/sheet-content.svelte +66 -0
- package/src/shadcn/sheet/sheet-description.svelte +13 -0
- package/src/shadcn/sheet/sheet-footer.svelte +15 -0
- package/src/shadcn/sheet/sheet-header.svelte +15 -0
- package/src/shadcn/sheet/sheet-overlay.svelte +16 -0
- package/src/shadcn/sheet/sheet-title.svelte +13 -0
- package/src/shadcn/sheet/sheet-trigger.svelte +7 -0
- package/src/shadcn/sidebar/constants.ts +6 -0
- package/src/shadcn/sidebar/context.svelte.ts +80 -0
- package/src/shadcn/sidebar/index.ts +75 -0
- package/src/shadcn/sidebar/sidebar-content.svelte +24 -0
- package/src/shadcn/sidebar/sidebar-footer.svelte +21 -0
- package/src/shadcn/sidebar/sidebar-group-action.svelte +36 -0
- package/src/shadcn/sidebar/sidebar-group-content.svelte +21 -0
- package/src/shadcn/sidebar/sidebar-group-label.svelte +34 -0
- package/src/shadcn/sidebar/sidebar-group.svelte +21 -0
- package/src/shadcn/sidebar/sidebar-header.svelte +21 -0
- package/src/shadcn/sidebar/sidebar-input.svelte +21 -0
- package/src/shadcn/sidebar/sidebar-inset.svelte +24 -0
- package/src/shadcn/sidebar/sidebar-menu-action.svelte +43 -0
- package/src/shadcn/sidebar/sidebar-menu-badge.svelte +29 -0
- package/src/shadcn/sidebar/sidebar-menu-button.svelte +101 -0
- package/src/shadcn/sidebar/sidebar-menu-item.svelte +21 -0
- package/src/shadcn/sidebar/sidebar-menu-skeleton.svelte +36 -0
- package/src/shadcn/sidebar/sidebar-menu-sub-button.svelte +43 -0
- package/src/shadcn/sidebar/sidebar-menu-sub-item.svelte +21 -0
- package/src/shadcn/sidebar/sidebar-menu-sub.svelte +25 -0
- package/src/shadcn/sidebar/sidebar-menu.svelte +21 -0
- package/src/shadcn/sidebar/sidebar-provider.svelte +46 -0
- package/src/shadcn/sidebar/sidebar-rail.svelte +36 -0
- package/src/shadcn/sidebar/sidebar-separator.svelte +15 -0
- package/src/shadcn/sidebar/sidebar-trigger.svelte +35 -0
- package/src/shadcn/sidebar/sidebar.svelte +94 -0
- package/src/shadcn/skeleton/index.ts +7 -0
- package/src/shadcn/skeleton/skeleton.svelte +17 -0
- package/src/shadcn/slider/index.ts +7 -0
- package/src/shadcn/slider/slider.svelte +44 -0
- package/src/shadcn/sonner/index.ts +1 -0
- package/src/shadcn/sonner/sonner.svelte +13 -0
- package/src/shadcn/switch/index.ts +7 -0
- package/src/shadcn/switch/switch.svelte +27 -0
- package/src/shadcn/table/index.ts +28 -0
- package/src/shadcn/table/table-body.svelte +15 -0
- package/src/shadcn/table/table-caption.svelte +20 -0
- package/src/shadcn/table/table-cell.svelte +20 -0
- package/src/shadcn/table/table-footer.svelte +20 -0
- package/src/shadcn/table/table-head.svelte +23 -0
- package/src/shadcn/table/table-header.svelte +15 -0
- package/src/shadcn/table/table-row.svelte +23 -0
- package/src/shadcn/table/table.svelte +17 -0
- package/src/shadcn/tabs/index.ts +18 -0
- package/src/shadcn/tabs/tabs-content.svelte +21 -0
- package/src/shadcn/tabs/tabs-list.svelte +19 -0
- package/src/shadcn/tabs/tabs-trigger.svelte +21 -0
- package/src/shadcn/textarea/index.ts +7 -0
- package/src/shadcn/textarea/textarea.svelte +22 -0
- package/src/shadcn/toggle/index.ts +13 -0
- package/src/shadcn/toggle/toggle.svelte +51 -0
- package/src/shadcn/toggle-group/index.ts +10 -0
- package/src/shadcn/toggle-group/toggle-group-item.svelte +30 -0
- package/src/shadcn/toggle-group/toggle-group.svelte +41 -0
- package/src/shadcn/tooltip/index.ts +21 -0
- package/src/shadcn/tooltip/tooltip-content.svelte +47 -0
- package/src/shadcn/tooltip/tooltip-trigger.svelte +7 -0
- package/src/shadcn/utils.ts +14 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
type TData = unknown;
|
|
3
|
+
type TValue = unknown;
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<script lang="ts" generics="TData, TValue">
|
|
7
|
+
import type { AppState } from '$client/app/app.state.svelte';
|
|
8
|
+
import { createSvelteTable } from '../../shadcn/data-table/data-table.svelte';
|
|
9
|
+
import FlexRender from '../../shadcn/data-table/flex-render.svelte';
|
|
10
|
+
import * as Table from '../../shadcn/table';
|
|
11
|
+
import {
|
|
12
|
+
getCoreRowModel,
|
|
13
|
+
getFacetedRowModel,
|
|
14
|
+
getFacetedUniqueValues,
|
|
15
|
+
getFilteredRowModel,
|
|
16
|
+
getPaginationRowModel,
|
|
17
|
+
getSortedRowModel,
|
|
18
|
+
type ColumnDef,
|
|
19
|
+
type ColumnFiltersState,
|
|
20
|
+
type RowSelectionState,
|
|
21
|
+
type SortingState
|
|
22
|
+
} from '@tanstack/table-core';
|
|
23
|
+
import { getContext, type Snippet } from 'svelte';
|
|
24
|
+
import TablePagination from './pika-table-pagination.svelte';
|
|
25
|
+
import TableToolbar from './pika-table-toolbar.svelte';
|
|
26
|
+
import type { FacetedFilters, GlobalFilterProps, ServerSideConfig, ServerSideTableState } from './types';
|
|
27
|
+
|
|
28
|
+
interface Props {
|
|
29
|
+
columns: ColumnDef<TData, TValue>[];
|
|
30
|
+
data: TData[];
|
|
31
|
+
classes?: string;
|
|
32
|
+
|
|
33
|
+
// If you pass in toolbar content then global filter and faceted filters will be ignored
|
|
34
|
+
globalFilterProps?: GlobalFilterProps;
|
|
35
|
+
facetedFilters?: FacetedFilters;
|
|
36
|
+
|
|
37
|
+
// Appears above the table
|
|
38
|
+
toolbarContent?: Snippet;
|
|
39
|
+
|
|
40
|
+
// Appears beneath the toolbar and above the table
|
|
41
|
+
beneathToolbarContent?: Snippet;
|
|
42
|
+
|
|
43
|
+
// This should be a human readable name for the table that is used to save/load column visibility
|
|
44
|
+
// and to show in the settings UI. Here's an example: "AWS SSO Profiles"
|
|
45
|
+
tableKey: string;
|
|
46
|
+
alwaysPinLeftColumns?: string[];
|
|
47
|
+
alwaysPinRightColumns?: string[];
|
|
48
|
+
|
|
49
|
+
// Server-side configuration
|
|
50
|
+
serverSideConfig?: ServerSideConfig;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let {
|
|
54
|
+
columns,
|
|
55
|
+
data,
|
|
56
|
+
classes,
|
|
57
|
+
globalFilterProps = $bindable<GlobalFilterProps>(),
|
|
58
|
+
facetedFilters,
|
|
59
|
+
toolbarContent,
|
|
60
|
+
beneathToolbarContent,
|
|
61
|
+
tableKey,
|
|
62
|
+
serverSideConfig = $bindable<ServerSideConfig>()
|
|
63
|
+
}: Props = $props();
|
|
64
|
+
|
|
65
|
+
const appState = getContext<AppState>('appState');
|
|
66
|
+
const appSettings = appState.settings;
|
|
67
|
+
|
|
68
|
+
let rowSelection = $state<RowSelectionState>({});
|
|
69
|
+
let columnVisibility = $derived(appSettings.getTableColumnVisibilityObject(tableKey));
|
|
70
|
+
//$state<VisibilityState>(appSettings.getTableColumnVisibilityObject(tableKey));
|
|
71
|
+
let columnFilters = $state<ColumnFiltersState>([]);
|
|
72
|
+
let sorting = $state<SortingState>([]);
|
|
73
|
+
let pageIndex = $state(0);
|
|
74
|
+
let pageSize = $derived(appSettings.getTableNumRows(tableKey, 10));
|
|
75
|
+
|
|
76
|
+
// === SERVER-SIDE LOGIC ===
|
|
77
|
+
|
|
78
|
+
let debouncedRequestData: ((tableState: ServerSideTableState) => Promise<void>) | undefined;
|
|
79
|
+
|
|
80
|
+
// Create debounced function when serverSide config changes
|
|
81
|
+
// $effect(() => {
|
|
82
|
+
// const serverState = serverSideConfig;
|
|
83
|
+
// if (serverState) {
|
|
84
|
+
// const debounceMs = serverState.debounceMs ?? 300;
|
|
85
|
+
// debouncedRequestData = debounce(async (tableState: ServerSideTableState) => {
|
|
86
|
+
// try {
|
|
87
|
+
// await serverState.requestData(tableState);
|
|
88
|
+
|
|
89
|
+
// // If using new API, update the tableState
|
|
90
|
+
// if (serverSideConfig) {
|
|
91
|
+
// serverSideConfig.tableState = { ...serverSideConfig.tableState, ...tableState };
|
|
92
|
+
// }
|
|
93
|
+
// } catch (error) {
|
|
94
|
+
// serverState.onError?.(error instanceof Error ? error.message : 'Unknown error');
|
|
95
|
+
// }
|
|
96
|
+
// }, debounceMs);
|
|
97
|
+
// } else {
|
|
98
|
+
// debouncedRequestData = undefined;
|
|
99
|
+
// }
|
|
100
|
+
// });
|
|
101
|
+
|
|
102
|
+
// Trigger server request when table state changes
|
|
103
|
+
// function triggerServerRequest() {
|
|
104
|
+
// const serverState = serverSideConfig;
|
|
105
|
+
// if (!serverState || !debouncedRequestData) return;
|
|
106
|
+
|
|
107
|
+
// const tableState: ServerSideTableState = {
|
|
108
|
+
// pageIndex,
|
|
109
|
+
// pageSize,
|
|
110
|
+
// sorting,
|
|
111
|
+
// columnFilters,
|
|
112
|
+
// requestId: crypto.randomUUID(),
|
|
113
|
+
// };
|
|
114
|
+
|
|
115
|
+
// debouncedRequestData(tableState);
|
|
116
|
+
// }
|
|
117
|
+
|
|
118
|
+
// Utility function for debouncing
|
|
119
|
+
function debounce<T extends (...args: any[]) => any>(func: T, wait: number): T {
|
|
120
|
+
let timeout: ReturnType<typeof setTimeout>;
|
|
121
|
+
return ((...args: any[]) => {
|
|
122
|
+
clearTimeout(timeout);
|
|
123
|
+
timeout = setTimeout(() => func(...args), wait);
|
|
124
|
+
}) as T;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const table = createSvelteTable({
|
|
128
|
+
columns,
|
|
129
|
+
enableRowSelection: true,
|
|
130
|
+
...(globalFilterProps?.showGlobalFilter ? { globalFilterFn: 'includesString' } : {}),
|
|
131
|
+
get data() {
|
|
132
|
+
return data;
|
|
133
|
+
},
|
|
134
|
+
state: {
|
|
135
|
+
get sorting() {
|
|
136
|
+
return sorting;
|
|
137
|
+
},
|
|
138
|
+
get columnVisibility() {
|
|
139
|
+
return columnVisibility;
|
|
140
|
+
},
|
|
141
|
+
get rowSelection() {
|
|
142
|
+
return rowSelection;
|
|
143
|
+
},
|
|
144
|
+
get columnFilters() {
|
|
145
|
+
return columnFilters;
|
|
146
|
+
},
|
|
147
|
+
get pagination() {
|
|
148
|
+
return { pageIndex, pageSize };
|
|
149
|
+
},
|
|
150
|
+
get globalFilter() {
|
|
151
|
+
return globalFilterProps?.showGlobalFilter ? globalFilterProps.globalFilterValue : '';
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
// === MANUAL MODES FOR SERVER-SIDE ===
|
|
156
|
+
get manualSorting() {
|
|
157
|
+
return !!serverSideConfig;
|
|
158
|
+
},
|
|
159
|
+
get manualFiltering() {
|
|
160
|
+
return !!serverSideConfig;
|
|
161
|
+
},
|
|
162
|
+
get manualPagination() {
|
|
163
|
+
return !!serverSideConfig;
|
|
164
|
+
},
|
|
165
|
+
get pageCount() {
|
|
166
|
+
const serverState = serverSideConfig;
|
|
167
|
+
if (!serverState) return undefined;
|
|
168
|
+
|
|
169
|
+
const tableState = serverSideConfig?.tableState;
|
|
170
|
+
|
|
171
|
+
// Calculate pageCount if totalRecords is available, regardless of pagination mode
|
|
172
|
+
if (tableState?.totalRecords !== undefined && pageSize > 0) {
|
|
173
|
+
return Math.ceil(tableState.totalRecords / pageSize);
|
|
174
|
+
}
|
|
175
|
+
// For cursor-based pagination without totalRecords, we don't know the total
|
|
176
|
+
if (serverState.paginationMode === 'cursor') {
|
|
177
|
+
return -1; // Unknown page count for cursor pagination without totalRecords
|
|
178
|
+
}
|
|
179
|
+
return undefined; // Unknown page count
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
onRowSelectionChange: (updater) => {
|
|
183
|
+
if (typeof updater === 'function') {
|
|
184
|
+
rowSelection = updater(rowSelection);
|
|
185
|
+
} else {
|
|
186
|
+
rowSelection = updater;
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
onSortingChange: (updater) => {
|
|
190
|
+
if (typeof updater === 'function') {
|
|
191
|
+
sorting = updater(sorting);
|
|
192
|
+
} else {
|
|
193
|
+
sorting = updater;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Trigger server request for server-side tables
|
|
197
|
+
// if (serverSideConfig) {
|
|
198
|
+
// triggerServerRequest();
|
|
199
|
+
// }
|
|
200
|
+
},
|
|
201
|
+
onColumnFiltersChange: (updater) => {
|
|
202
|
+
if (typeof updater === 'function') {
|
|
203
|
+
columnFilters = updater(columnFilters);
|
|
204
|
+
} else {
|
|
205
|
+
columnFilters = updater;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Trigger server request for server-side tables
|
|
209
|
+
// if (serverSideConfig) {
|
|
210
|
+
// triggerServerRequest();
|
|
211
|
+
// }
|
|
212
|
+
},
|
|
213
|
+
onColumnVisibilityChange: (updater) => {
|
|
214
|
+
if (typeof updater === 'function') {
|
|
215
|
+
appSettings.setTableColumnVisibilityFromObject(tableKey, updater(columnVisibility));
|
|
216
|
+
} else {
|
|
217
|
+
throw new Error('onColumnVisibilityChange updater must be a function');
|
|
218
|
+
//columnVisibility = updater;
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
onPaginationChange: (updater) => {
|
|
222
|
+
if (typeof updater === 'function') {
|
|
223
|
+
const val = updater({ pageIndex, pageSize });
|
|
224
|
+
pageIndex = val.pageIndex;
|
|
225
|
+
appSettings.setTableNumRows(tableKey, val.pageSize);
|
|
226
|
+
|
|
227
|
+
// Trigger server request for server-side tables
|
|
228
|
+
// if (serverSideConfig) {
|
|
229
|
+
// triggerServerRequest();
|
|
230
|
+
// }
|
|
231
|
+
} else {
|
|
232
|
+
throw new Error('onPaginationChange updater must be a function');
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
onGlobalFilterChange: (value) => {
|
|
236
|
+
if (globalFilterProps?.showGlobalFilter) {
|
|
237
|
+
globalFilterProps.globalFilterValue = value;
|
|
238
|
+
|
|
239
|
+
// Trigger server request for server-side tables
|
|
240
|
+
// if (serverSideConfig) {
|
|
241
|
+
// triggerServerRequest();
|
|
242
|
+
// }
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
// === ROW MODELS ===
|
|
247
|
+
getCoreRowModel: getCoreRowModel(),
|
|
248
|
+
...(serverSideConfig
|
|
249
|
+
? {}
|
|
250
|
+
: {
|
|
251
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
252
|
+
getPaginationRowModel: getPaginationRowModel(),
|
|
253
|
+
getSortedRowModel: getSortedRowModel()
|
|
254
|
+
}),
|
|
255
|
+
getFacetedRowModel: getFacetedRowModel(),
|
|
256
|
+
getFacetedUniqueValues: getFacetedUniqueValues()
|
|
257
|
+
});
|
|
258
|
+
</script>
|
|
259
|
+
|
|
260
|
+
<div class="space-y-4 {classes ? classes : ''} ">
|
|
261
|
+
<TableToolbar {table} {globalFilterProps} {facetedFilters} {toolbarContent} {beneathToolbarContent} />
|
|
262
|
+
<div class="rounded-md border h-full flex flex-col overflow-y-auto">
|
|
263
|
+
<Table.Root class="h-full">
|
|
264
|
+
<Table.Header>
|
|
265
|
+
{#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
|
|
266
|
+
<Table.Row class="sticky top-0 bg-gray-50 shadow-[inset_0_-1px_0_#ededed]">
|
|
267
|
+
{#each headerGroup.headers as header (header.id)}
|
|
268
|
+
<Table.Head colspan={header.colSpan}>
|
|
269
|
+
{#if !header.isPlaceholder}
|
|
270
|
+
<FlexRender content={header.column.columnDef.header} context={header.getContext()} />
|
|
271
|
+
{/if}
|
|
272
|
+
</Table.Head>
|
|
273
|
+
{/each}
|
|
274
|
+
</Table.Row>
|
|
275
|
+
{/each}
|
|
276
|
+
</Table.Header>
|
|
277
|
+
<Table.Body class="">
|
|
278
|
+
{#each table.getRowModel().rows as row (row.id)}
|
|
279
|
+
<Table.Row data-state={row.getIsSelected() && 'selected'}>
|
|
280
|
+
{#each row.getVisibleCells() as cell (cell.id)}
|
|
281
|
+
<Table.Cell>
|
|
282
|
+
<FlexRender content={cell.column.columnDef.cell} context={cell.getContext()} />
|
|
283
|
+
</Table.Cell>
|
|
284
|
+
{/each}
|
|
285
|
+
</Table.Row>
|
|
286
|
+
{:else}
|
|
287
|
+
<Table.Row>
|
|
288
|
+
<Table.Cell colspan={columns.length} class="h-24 text-center">No results.</Table.Cell>
|
|
289
|
+
</Table.Row>
|
|
290
|
+
{/each}
|
|
291
|
+
</Table.Body>
|
|
292
|
+
</Table.Root>
|
|
293
|
+
</div>
|
|
294
|
+
<TablePagination {table} serverSide={serverSideConfig} />
|
|
295
|
+
</div>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { AppState } from '$client/app/app.state.svelte';
|
|
2
|
+
import type { Column, ColumnFiltersState, Row, SortingState } from '@tanstack/table-core';
|
|
3
|
+
import type { Component } from 'svelte';
|
|
4
|
+
|
|
5
|
+
export interface FacetedFilterData {
|
|
6
|
+
label: string;
|
|
7
|
+
value: string;
|
|
8
|
+
icon?: Component;
|
|
9
|
+
iconClasses?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface FacetedFilterProps {
|
|
13
|
+
columnId: string;
|
|
14
|
+
title: string;
|
|
15
|
+
options: FacetedFilterData[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface FacetedFilterPropsWithColumn<TData> extends FacetedFilterProps {
|
|
19
|
+
column: Column<TData, unknown>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Each of these is a column that has a filter that will be displayed in the toolbar as a dropdown
|
|
24
|
+
* that allows the user to filter by the column and the options provided.
|
|
25
|
+
*/
|
|
26
|
+
export type FacetedFilters = FacetedFilterProps[];
|
|
27
|
+
|
|
28
|
+
export type FacetedFiltersWithColumn<TData> = FacetedFilterPropsWithColumn<TData>[];
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* You control which columns are filtered by the global input filter by setting enableGlobalFilter to true on the column def
|
|
32
|
+
* and false on the others.
|
|
33
|
+
*
|
|
34
|
+
* TODO: add a way to let them pass in the globalFilterFn and override the default if needed
|
|
35
|
+
*
|
|
36
|
+
* The globalFilterValue should just be `$state<string>('')`
|
|
37
|
+
*/
|
|
38
|
+
export interface GlobalFilterProps {
|
|
39
|
+
showGlobalFilter: boolean;
|
|
40
|
+
globalFilterValue?: string;
|
|
41
|
+
globalFilterPlaceholder?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface RowActionMenuItemNode<TData> {
|
|
45
|
+
label: string;
|
|
46
|
+
icon?: Component;
|
|
47
|
+
onclick?: (row: Row<TData>, appState: AppState) => void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface RowActionMenuItemSubMenu<TData> {
|
|
51
|
+
label: string;
|
|
52
|
+
icon?: Component;
|
|
53
|
+
menuItems: RowActionMenuItem<TData>[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface RowActionsProps<TData> {
|
|
57
|
+
menuWidth?: string; // must be a valid css unit like 160px, will pair concat with w- to form the width using tailwind
|
|
58
|
+
menuItems: RowActionMenuItem<TData>[];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type RowActionMenuItem<TData> = 'Separator' | RowActionMenuItemNode<TData> | RowActionMenuItemSubMenu<TData>;
|
|
62
|
+
|
|
63
|
+
// === SERVER-SIDE TYPES ===
|
|
64
|
+
|
|
65
|
+
export interface ServerSideTableState {
|
|
66
|
+
// === PAGINATION ===
|
|
67
|
+
pageIndex: number;
|
|
68
|
+
pageSize: number;
|
|
69
|
+
totalRecords?: number; // Total number of records available
|
|
70
|
+
scrollId?: string; // For cursor-based pagination
|
|
71
|
+
hasNextPage?: boolean; // Indicates if there are more pages available
|
|
72
|
+
|
|
73
|
+
// === SORTING ===
|
|
74
|
+
sorting: SortingState;
|
|
75
|
+
|
|
76
|
+
// === FILTERING ===
|
|
77
|
+
columnFilters: ColumnFiltersState;
|
|
78
|
+
|
|
79
|
+
// === LOADING STATE ===
|
|
80
|
+
isLoading?: boolean;
|
|
81
|
+
error?: string;
|
|
82
|
+
|
|
83
|
+
// === METADATA ===
|
|
84
|
+
requestId: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Unified server-side configuration that combines both configuration and state.
|
|
89
|
+
* This is the recommended interface for new implementations.
|
|
90
|
+
*/
|
|
91
|
+
export interface ServerSideConfig {
|
|
92
|
+
// === REQUEST INITIATOR ===
|
|
93
|
+
requestData: (tableState: ServerSideTableState) => Promise<void>;
|
|
94
|
+
|
|
95
|
+
// === PAGINATION STYLE ===
|
|
96
|
+
paginationMode: 'offset' | 'cursor';
|
|
97
|
+
|
|
98
|
+
// === DEBOUNCING ===
|
|
99
|
+
debounceMs?: number; // Default 300ms
|
|
100
|
+
|
|
101
|
+
// === ERROR HANDLING ===
|
|
102
|
+
onError?: (error: string) => void;
|
|
103
|
+
|
|
104
|
+
// === DYNAMIC TABLE STATE ===
|
|
105
|
+
tableState: ServerSideTableState;
|
|
106
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Tabs as TabsPrimitive } from 'bits-ui';
|
|
2
|
+
import Content from './tabs-content.svelte';
|
|
3
|
+
import List from './tabs-list.svelte';
|
|
4
|
+
import Trigger from './tabs-trigger.svelte';
|
|
5
|
+
|
|
6
|
+
const Root = TabsPrimitive.Root;
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
Content,
|
|
10
|
+
List,
|
|
11
|
+
Root,
|
|
12
|
+
//
|
|
13
|
+
Root as Tabs,
|
|
14
|
+
Content as TabsContent,
|
|
15
|
+
List as TabsList,
|
|
16
|
+
Trigger as TabsTrigger,
|
|
17
|
+
Trigger
|
|
18
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../shadcn/utils.js';
|
|
3
|
+
import { Tabs as TabsPrimitive } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
let { ref = $bindable(null), class: className, value, ...restProps }: TabsPrimitive.ContentProps = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<TabsPrimitive.Content
|
|
9
|
+
bind:ref
|
|
10
|
+
class={cn(
|
|
11
|
+
'ring-offset-background focus-visible:ring-ring mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
|
|
12
|
+
className
|
|
13
|
+
)}
|
|
14
|
+
{value}
|
|
15
|
+
{...restProps}
|
|
16
|
+
/>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../shadcn/utils.js';
|
|
3
|
+
import { Tabs as TabsPrimitive } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
let { ref = $bindable(null), class: className, ...restProps }: TabsPrimitive.ListProps = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<TabsPrimitive.List
|
|
9
|
+
bind:ref
|
|
10
|
+
class={cn('bg-muted text-muted-foreground inline-flex h-9 items-center justify-center rounded-lg p-1', className)}
|
|
11
|
+
{...restProps}
|
|
12
|
+
/>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { cn } from '../../shadcn/utils.js';
|
|
3
|
+
import { Tabs as TabsPrimitive } from 'bits-ui';
|
|
4
|
+
|
|
5
|
+
let { ref = $bindable(null), class: className, value, ...restProps }: TabsPrimitive.TriggerProps = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<!--
|
|
9
|
+
Modified from standard shadcn tabs trigger component:
|
|
10
|
+
Added 'data-[state=inactive]:hover:text-primary' to provide visual feedback
|
|
11
|
+
when hovering over unselected tabs. This changes the text color to the theme's
|
|
12
|
+
primary color on hover for better UX, indicating that the tabs are clickable.
|
|
13
|
+
-->
|
|
14
|
+
|
|
15
|
+
<TabsPrimitive.Trigger
|
|
16
|
+
bind:ref
|
|
17
|
+
class={cn(
|
|
18
|
+
'ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=inactive]:hover:text-primary inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow',
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{value}
|
|
22
|
+
{...restProps}
|
|
23
|
+
/>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PopupHelp } from './popup-help.svelte';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import HelpCircleOutline from '$icons/ci/help-circle-outline';
|
|
3
|
+
import * as Popover from '../../shadcn/popover';
|
|
4
|
+
import { cn } from '../../shadcn/utils';
|
|
5
|
+
import type { Snippet } from 'svelte';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
popoverClasses?: string;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { popoverClasses, children }: Props = $props();
|
|
13
|
+
|
|
14
|
+
let open = $state(false);
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<Popover.Root bind:open>
|
|
18
|
+
<Popover.Trigger
|
|
19
|
+
class="inline-flex items-center justify-center"
|
|
20
|
+
onmouseenter={() => {
|
|
21
|
+
open = true;
|
|
22
|
+
}}
|
|
23
|
+
onmouseleave={() => {
|
|
24
|
+
open = false;
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
<HelpCircleOutline class="w-4 h-4 text-gray-400 hover:text-blue-500 transition-colors" />
|
|
28
|
+
</Popover.Trigger>
|
|
29
|
+
|
|
30
|
+
<Popover.Content class={cn('w-120', popoverClasses)}>
|
|
31
|
+
{@render children?.()}
|
|
32
|
+
</Popover.Content>
|
|
33
|
+
</Popover.Root>
|