@invopop/popui 0.1.3 → 0.1.4-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.
Files changed (180) hide show
  1. package/dist/AlertDialog.svelte +10 -11
  2. package/dist/BaseButton.svelte +29 -104
  3. package/dist/BaseCard.svelte +35 -30
  4. package/dist/BaseCounter.svelte +11 -8
  5. package/dist/BaseDropdown.svelte +5 -5
  6. package/dist/BaseFlag.svelte +5 -3
  7. package/dist/BaseFlag.svelte.d.ts +1 -0
  8. package/dist/BaseTable.svelte +16 -16
  9. package/dist/BaseTable.svelte.d.ts +1 -1
  10. package/dist/BaseTableActions.svelte +4 -6
  11. package/dist/BaseTableCellContent.svelte +9 -21
  12. package/dist/BaseTableCheckbox.svelte +9 -11
  13. package/dist/BaseTableHeaderContent.svelte +4 -4
  14. package/dist/BaseTableHeaderOrderBy.svelte +23 -12
  15. package/dist/BaseTableRow.svelte +12 -10
  16. package/dist/Breadcrumb.svelte +40 -0
  17. package/dist/Breadcrumb.svelte.d.ts +4 -0
  18. package/dist/Breadcrumbs.svelte +5 -30
  19. package/dist/ButtonFile.svelte +40 -30
  20. package/dist/ButtonUuidCopy.svelte +6 -3
  21. package/dist/CardCheckbox.svelte +45 -32
  22. package/dist/CardCheckbox.svelte.d.ts +1 -1
  23. package/dist/CardRelation.svelte +12 -13
  24. package/dist/CompanySelector.svelte +35 -7
  25. package/dist/CounterWidget.svelte +52 -0
  26. package/dist/CounterWidget.svelte.d.ts +4 -0
  27. package/dist/DataListItem.svelte +14 -10
  28. package/dist/DatePicker.svelte +20 -17
  29. package/dist/DrawerContext.svelte +207 -15
  30. package/dist/DrawerContextItem.svelte +50 -50
  31. package/dist/DrawerContextSeparator.svelte +1 -1
  32. package/dist/DropdownSelect.svelte +81 -22
  33. package/dist/DropdownSelectGroup.svelte +15 -0
  34. package/dist/DropdownSelectGroup.svelte.d.ts +7 -0
  35. package/dist/EmptyState.svelte +42 -0
  36. package/dist/EmptyState.svelte.d.ts +4 -0
  37. package/dist/FeedEvents.svelte +9 -5
  38. package/dist/FeedIconEvent.svelte +2 -2
  39. package/dist/FeedIconStatus.svelte +4 -4
  40. package/dist/FeedItem.svelte +10 -11
  41. package/dist/FeedItemDetail.svelte +32 -6
  42. package/dist/FeedViewer.svelte +1 -1
  43. package/dist/GlobalSearch.svelte +13 -12
  44. package/dist/InputCheckbox.svelte +2 -5
  45. package/dist/InputError.svelte +4 -9
  46. package/dist/InputLabel.svelte +3 -1
  47. package/dist/InputRadio.svelte +29 -13
  48. package/dist/InputRadio.svelte.d.ts +1 -1
  49. package/dist/InputSearch.svelte +8 -8
  50. package/dist/InputSelect.svelte +32 -31
  51. package/dist/InputText.svelte +32 -24
  52. package/dist/InputTextarea.svelte +25 -19
  53. package/dist/InputToggle.svelte +24 -18
  54. package/dist/MenuItem.svelte +16 -11
  55. package/dist/MenuItemCollapsible.svelte +7 -7
  56. package/dist/Notification.svelte +60 -25
  57. package/dist/ProfileAvatar.svelte +43 -14
  58. package/dist/ProgressBar.svelte +42 -0
  59. package/dist/ProgressBar.svelte.d.ts +4 -0
  60. package/dist/ProgressBarCircle.svelte +46 -0
  61. package/dist/ProgressBarCircle.svelte.d.ts +4 -0
  62. package/dist/SeparatorHorizontal.svelte +2 -2
  63. package/dist/ShortcutWrapper.svelte +14 -5
  64. package/dist/StatusLabel.svelte +4 -5
  65. package/dist/StepIconList.svelte +11 -9
  66. package/dist/TagBeta.svelte +26 -14
  67. package/dist/TagProgress.svelte +28 -0
  68. package/dist/TagProgress.svelte.d.ts +4 -0
  69. package/dist/TagSearch.svelte +4 -4
  70. package/dist/TagStatus.svelte +32 -34
  71. package/dist/TitleMain.svelte +1 -1
  72. package/dist/TitleSection.svelte +1 -1
  73. package/dist/UuidCopy.svelte +4 -4
  74. package/dist/alert-dialog/alert-dialog-action.svelte +8 -4
  75. package/dist/alert-dialog/alert-dialog-cancel.svelte +7 -3
  76. package/dist/alert-dialog/alert-dialog-content.svelte +1 -1
  77. package/dist/alert-dialog/alert-dialog-description.svelte +1 -1
  78. package/dist/alert-dialog/alert-dialog-footer.svelte +1 -1
  79. package/dist/alert-dialog/alert-dialog-header.svelte +1 -1
  80. package/dist/alert-dialog/alert-dialog-overlay.svelte +1 -1
  81. package/dist/alert-dialog/alert-dialog-title.svelte +1 -1
  82. package/dist/alert-dialog/alert-dialog-trigger.svelte +4 -2
  83. package/dist/button/button.svelte +224 -24
  84. package/dist/button/button.svelte.d.ts +77 -26
  85. package/dist/clickOutside.d.ts +5 -2
  86. package/dist/clickOutside.js +9 -3
  87. package/dist/data-table/cells/boolean-cell.svelte +16 -0
  88. package/dist/data-table/cells/boolean-cell.svelte.d.ts +8 -0
  89. package/dist/data-table/cells/currency-cell.svelte +10 -0
  90. package/dist/data-table/cells/currency-cell.svelte.d.ts +8 -0
  91. package/dist/data-table/cells/date-cell.svelte +10 -0
  92. package/dist/data-table/cells/date-cell.svelte.d.ts +8 -0
  93. package/dist/data-table/cells/tag-cell.svelte +12 -0
  94. package/dist/data-table/cells/tag-cell.svelte.d.ts +8 -0
  95. package/dist/data-table/cells/text-cell.svelte +10 -0
  96. package/dist/data-table/cells/text-cell.svelte.d.ts +8 -0
  97. package/dist/data-table/column-definitions.d.ts +12 -0
  98. package/dist/data-table/column-definitions.js +40 -0
  99. package/dist/data-table/column-sizing-helpers.d.ts +6 -0
  100. package/dist/data-table/column-sizing-helpers.js +24 -0
  101. package/dist/data-table/create-columns.d.ts +3 -0
  102. package/dist/data-table/create-columns.js +50 -0
  103. package/dist/data-table/data-table-pagination.svelte +173 -0
  104. package/dist/data-table/data-table-pagination.svelte.d.ts +4 -0
  105. package/dist/data-table/data-table-svelte.svelte.d.ts +40 -0
  106. package/dist/data-table/data-table-svelte.svelte.js +111 -0
  107. package/dist/data-table/data-table-toolbar.svelte +16 -0
  108. package/dist/data-table/data-table-toolbar.svelte.d.ts +29 -0
  109. package/dist/data-table/data-table-types.d.ts +74 -0
  110. package/dist/data-table/data-table-types.js +1 -0
  111. package/dist/data-table/data-table-view-options.svelte +88 -0
  112. package/dist/data-table/data-table-view-options.svelte.d.ts +27 -0
  113. package/dist/data-table/data-table.svelte +324 -0
  114. package/dist/data-table/data-table.svelte.d.ts +25 -0
  115. package/dist/data-table/flex-render.svelte +40 -0
  116. package/dist/data-table/flex-render.svelte.d.ts +33 -0
  117. package/dist/data-table/index.d.ts +13 -0
  118. package/dist/data-table/index.js +13 -0
  119. package/dist/data-table/render-helpers.d.ts +90 -0
  120. package/dist/data-table/render-helpers.js +99 -0
  121. package/dist/data-table/table-setup.d.ts +36 -0
  122. package/dist/data-table/table-setup.js +130 -0
  123. package/dist/data-table/table-styles.d.ts +17 -0
  124. package/dist/data-table/table-styles.js +49 -0
  125. package/dist/helpers.d.ts +1 -0
  126. package/dist/helpers.js +3 -0
  127. package/dist/index.d.ts +16 -7
  128. package/dist/index.js +33 -14
  129. package/dist/range-calendar/range-calendar-cell.svelte +1 -1
  130. package/dist/range-calendar/range-calendar-day.svelte +11 -12
  131. package/dist/range-calendar/range-calendar-head-cell.svelte +1 -1
  132. package/dist/range-calendar/range-calendar-header.svelte +1 -1
  133. package/dist/range-calendar/range-calendar-month-select.svelte +1 -1
  134. package/dist/range-calendar/range-calendar-next-button.svelte +3 -3
  135. package/dist/range-calendar/range-calendar-prev-button.svelte +3 -3
  136. package/dist/range-calendar/range-calendar.svelte +1 -1
  137. package/dist/sonner/index.d.ts +1 -0
  138. package/dist/sonner/index.js +1 -0
  139. package/dist/sonner/sonner.svelte +44 -0
  140. package/dist/sonner/sonner.svelte.d.ts +4 -0
  141. package/dist/svg/CheckBadge.svelte +18 -0
  142. package/dist/svg/CheckBadge.svelte.d.ts +26 -0
  143. package/dist/svg/IconDelivery.svelte +86 -0
  144. package/dist/svg/IconDelivery.svelte.d.ts +20 -0
  145. package/dist/svg/IconEmpty.svelte +113 -121
  146. package/dist/svg/IconOrder.svelte +81 -0
  147. package/dist/svg/IconOrder.svelte.d.ts +20 -0
  148. package/dist/svg/IconPayment.svelte +86 -0
  149. package/dist/svg/IconPayment.svelte.d.ts +20 -0
  150. package/dist/table/table-body.svelte +5 -1
  151. package/dist/table/table-cell.svelte +4 -2
  152. package/dist/table/table-footer.svelte +1 -1
  153. package/dist/table/table-head.svelte +4 -2
  154. package/dist/table/table-header.svelte +1 -1
  155. package/dist/table/table-row.svelte +4 -2
  156. package/dist/table/table.svelte +2 -2
  157. package/dist/tabs/tabs-list.svelte +8 -2
  158. package/dist/tabs/tabs-list.svelte.d.ts +4 -1
  159. package/dist/tabs/tabs-trigger.svelte +5 -3
  160. package/dist/tabs/tabs-trigger.svelte.d.ts +4 -1
  161. package/dist/tailwind.theme.css +998 -0
  162. package/dist/tooltip/tooltip-content.svelte +2 -2
  163. package/dist/types.d.ts +76 -50
  164. package/package.json +20 -10
  165. package/dist/CounterWorkflow.svelte +0 -19
  166. package/dist/CounterWorkflow.svelte.d.ts +0 -4
  167. package/dist/DrawerContextWorkspace.svelte +0 -126
  168. package/dist/DrawerContextWorkspace.svelte.d.ts +0 -4
  169. package/dist/EmptyStateIcon.svelte +0 -52
  170. package/dist/EmptyStateIcon.svelte.d.ts +0 -4
  171. package/dist/EmptyStateIllustration.svelte +0 -66
  172. package/dist/EmptyStateIllustration.svelte.d.ts +0 -4
  173. package/dist/FormLayoutModal.svelte +0 -14
  174. package/dist/FormLayoutModal.svelte.d.ts +0 -4
  175. package/dist/ProfileSelector.svelte +0 -41
  176. package/dist/ProfileSelector.svelte.d.ts +0 -4
  177. package/dist/SectionLayout.svelte +0 -13
  178. package/dist/SectionLayout.svelte.d.ts +0 -4
  179. package/dist/tw.theme.d.ts +0 -171
  180. package/dist/tw.theme.js +0 -188
@@ -0,0 +1,111 @@
1
+ import { createTable, } from "@tanstack/table-core";
2
+ /**
3
+ * Creates a reactive TanStack table object for Svelte.
4
+ * @param options Table options to create the table with.
5
+ * @returns A reactive table object.
6
+ * @example
7
+ * ```svelte
8
+ * <script>
9
+ * const table = createSvelteTable({ ... })
10
+ * </script>
11
+ *
12
+ * <table>
13
+ * <thead>
14
+ * {#each table.getHeaderGroups() as headerGroup}
15
+ * <tr>
16
+ * {#each headerGroup.headers as header}
17
+ * <th colspan={header.colSpan}>
18
+ * <FlexRender content={header.column.columnDef.header} context={header.getContext()} />
19
+ * </th>
20
+ * {/each}
21
+ * </tr>
22
+ * {/each}
23
+ * </thead>
24
+ * <!-- ... -->
25
+ * </table>
26
+ * ```
27
+ */
28
+ export function createSvelteTable(options) {
29
+ const resolvedOptions = mergeObjects({
30
+ state: {},
31
+ onStateChange() { },
32
+ renderFallbackValue: null,
33
+ mergeOptions: (defaultOptions, options) => {
34
+ return mergeObjects(defaultOptions, options);
35
+ },
36
+ }, options);
37
+ const table = createTable(resolvedOptions);
38
+ let state = $state(table.initialState);
39
+ function updateOptions() {
40
+ table.setOptions((prev) => {
41
+ return mergeObjects(prev, options, {
42
+ state: mergeObjects(state, options.state || {}),
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ onStateChange: (updater) => {
45
+ if (updater instanceof Function)
46
+ state = updater(state);
47
+ else
48
+ state = mergeObjects(state, updater);
49
+ options.onStateChange?.(updater);
50
+ },
51
+ });
52
+ });
53
+ }
54
+ updateOptions();
55
+ $effect.pre(() => {
56
+ updateOptions();
57
+ });
58
+ return table;
59
+ }
60
+ /**
61
+ * Lazily merges several objects (or thunks) while preserving
62
+ * getter semantics from every source.
63
+ *
64
+ * Proxy-based to avoid known WebKit recursion issue.
65
+ */
66
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
67
+ export function mergeObjects(...sources) {
68
+ const resolve = (src) => typeof src === "function" ? (src() ?? undefined) : src;
69
+ const findSourceWithKey = (key) => {
70
+ for (let i = sources.length - 1; i >= 0; i--) {
71
+ const obj = resolve(sources[i]);
72
+ if (obj && key in obj)
73
+ return obj;
74
+ }
75
+ return undefined;
76
+ };
77
+ return new Proxy(Object.create(null), {
78
+ get(_, key) {
79
+ const src = findSourceWithKey(key);
80
+ return src?.[key];
81
+ },
82
+ has(_, key) {
83
+ return !!findSourceWithKey(key);
84
+ },
85
+ ownKeys() {
86
+ // eslint-disable-next-line svelte/prefer-svelte-reactivity
87
+ const all = new Set();
88
+ for (const s of sources) {
89
+ const obj = resolve(s);
90
+ if (obj) {
91
+ for (const k of Reflect.ownKeys(obj)) {
92
+ all.add(k);
93
+ }
94
+ }
95
+ }
96
+ return [...all];
97
+ },
98
+ getOwnPropertyDescriptor(_, key) {
99
+ const src = findSourceWithKey(key);
100
+ if (!src)
101
+ return undefined;
102
+ return {
103
+ configurable: true,
104
+ enumerable: true,
105
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
106
+ value: src[key],
107
+ writable: true,
108
+ };
109
+ },
110
+ });
111
+ }
@@ -0,0 +1,16 @@
1
+ <script lang="ts" generics="TData">
2
+ import type { Table } from '@tanstack/table-core'
3
+ import type { Snippet } from 'svelte'
4
+ import { DataTableViewOptions } from './index.js'
5
+
6
+ let { table, filters }: { table: Table<TData>; filters?: Snippet } = $props()
7
+ </script>
8
+
9
+ <div class="flex items-center justify-between">
10
+ {#if filters}
11
+ <div class="flex-1">
12
+ {@render filters()}
13
+ </div>
14
+ {/if}
15
+ <DataTableViewOptions {table} />
16
+ </div>
@@ -0,0 +1,29 @@
1
+ import type { Table } from '@tanstack/table-core';
2
+ import type { Snippet } from 'svelte';
3
+ declare function $$render<TData>(): {
4
+ props: {
5
+ table: Table<TData>;
6
+ filters?: Snippet;
7
+ };
8
+ exports: {};
9
+ bindings: "";
10
+ slots: {};
11
+ events: {};
12
+ };
13
+ declare class __sveltets_Render<TData> {
14
+ props(): ReturnType<typeof $$render<TData>>['props'];
15
+ events(): ReturnType<typeof $$render<TData>>['events'];
16
+ slots(): ReturnType<typeof $$render<TData>>['slots'];
17
+ bindings(): "";
18
+ exports(): {};
19
+ }
20
+ interface $$IsomorphicComponent {
21
+ 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']>> & {
22
+ $$bindings?: ReturnType<__sveltets_Render<TData>['bindings']>;
23
+ } & ReturnType<__sveltets_Render<TData>['exports']>;
24
+ <TData>(internal: unknown, props: ReturnType<__sveltets_Render<TData>['props']> & {}): ReturnType<__sveltets_Render<TData>['exports']>;
25
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
26
+ }
27
+ declare const DataTableToolbar: $$IsomorphicComponent;
28
+ type DataTableToolbar<TData> = InstanceType<typeof DataTableToolbar<TData>>;
29
+ export default DataTableToolbar;
@@ -0,0 +1,74 @@
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
+ paginationSelectedSlot?: Snippet;
58
+ paginationUnselectedSlot?: Snippet;
59
+ onPageChange?: (pageIndex: number) => void;
60
+ onPageSizeChange?: (pageSize: number) => void;
61
+ }
62
+ export interface DataTablePaginationProps<T> {
63
+ table: Table<T>;
64
+ id?: string;
65
+ class?: string;
66
+ showRowsPerPage?: boolean;
67
+ rowsPerPageOptions?: number[];
68
+ itemsLabel?: string;
69
+ children?: Snippet;
70
+ selectedSlot?: Snippet;
71
+ unselectedSlot?: Snippet;
72
+ onPageChange?: (pageIndex: number) => void;
73
+ onPageSizeChange?: (pageSize: number) => void;
74
+ }
@@ -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,324 @@
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
+ paginationSelectedSlot,
47
+ paginationUnselectedSlot,
48
+ onPageChange,
49
+ onPageSizeChange
50
+ }: DataTableProps<TData> = $props()
51
+
52
+ const enableSelection = !disableSelection
53
+ const enablePagination = !disablePagination
54
+
55
+ let rowSelection = $state<RowSelectionState>({})
56
+ let columnVisibility = $state<VisibilityState>({})
57
+ let sorting = $state<SortingState>([])
58
+ let pagination = $state<PaginationState>({ pageIndex: 0, pageSize: initialPageSize })
59
+ let columnSizing = $state<ColumnSizingState>({})
60
+ let columnSizingInfo = $state<ColumnSizingInfoState>({
61
+ columnSizingStart: [],
62
+ deltaOffset: null,
63
+ deltaPercentage: null,
64
+ isResizingColumn: false,
65
+ startOffset: null,
66
+ startSize: null
67
+ })
68
+ let columnOrder = $state<ColumnOrderState>([])
69
+ let containerRef = $state<HTMLDivElement | null>(null)
70
+
71
+ // Build TanStack columns from config
72
+ const columns = $derived.by(() =>
73
+ buildColumns<TData>(columnConfig, enableSelection, RowActions, rowActions.length > 0)
74
+ )
75
+
76
+ // Calculate initial column sizes based on available width
77
+ $effect(() => {
78
+ if (containerRef && Object.keys(columnSizing).length === 0) {
79
+ const containerWidth = containerRef.offsetWidth
80
+ const newSizing = calculateColumnSizing(columns, containerWidth)
81
+ if (newSizing) {
82
+ columnSizing = newSizing
83
+ }
84
+ }
85
+ })
86
+
87
+ // Track selection changes
88
+ $effect(() => {
89
+ if (onSelectionChange) {
90
+ const selectedRows = Object.keys(rowSelection)
91
+ .filter((key) => rowSelection[key])
92
+ .map((key) => data[parseInt(key)])
93
+ onSelectionChange(selectedRows)
94
+ }
95
+ })
96
+
97
+ const table = setupTable({
98
+ get data() {
99
+ return data
100
+ },
101
+ get columns() {
102
+ return columns
103
+ },
104
+ enableSelection,
105
+ enablePagination,
106
+ getRowSelection: () => rowSelection,
107
+ getColumnVisibility: () => columnVisibility,
108
+ getSorting: () => sorting,
109
+ getPagination: () => pagination,
110
+ getColumnSizing: () => columnSizing,
111
+ getColumnSizingInfo: () => columnSizingInfo,
112
+ getColumnOrder: () => columnOrder,
113
+ setRowSelection: (value) => (rowSelection = value),
114
+ setColumnVisibility: (value) => (columnVisibility = value),
115
+ setSorting: (value) => (sorting = value),
116
+ setPagination: (value) => (pagination = value),
117
+ setColumnSizing: (value) => (columnSizing = value),
118
+ setColumnSizingInfo: (value) => (columnSizingInfo = value),
119
+ setColumnOrder: (value) => (columnOrder = value)
120
+ })
121
+ </script>
122
+
123
+ {#snippet StickyCellWrapper({
124
+ children,
125
+ align = 'left'
126
+ }: {
127
+ children: any
128
+ align?: 'left' | 'right'
129
+ })}
130
+ <div
131
+ class={cn(
132
+ 'h-10 flex items-center px-3 relative group-hover/row:bg-background-default-secondary group-data-[state=selected]/row:bg-background-selected',
133
+ align === 'right' ? 'justify-end' : ''
134
+ )}
135
+ >
136
+ <div class="relative z-10">
137
+ {@render children()}
138
+ </div>
139
+ </div>
140
+ {/snippet}
141
+
142
+ {#snippet RowActions({ row }: { row: Row<TData> })}
143
+ <BaseTableActions
144
+ actions={rowActions}
145
+ onclick={(action) => {
146
+ if (onRowAction) {
147
+ onRowAction(action, row.original)
148
+ }
149
+ }}
150
+ />
151
+ {/snippet}
152
+
153
+ {#snippet ColumnHeader({
154
+ column,
155
+ title,
156
+ class: className,
157
+ ...restProps
158
+ }: { column: Column<TData>; title?: string } & HTMLAttributes<HTMLDivElement>)}
159
+ {#if !column?.getCanSort()}
160
+ <div class={className} {...restProps}>
161
+ {title || ''}
162
+ </div>
163
+ {:else}
164
+ <div class={cn('flex items-center w-full', className)} {...restProps}>
165
+ <BaseDropdown fullWidth>
166
+ {#snippet trigger()}
167
+ <button
168
+ class="data-[state=open]:bg-accent w-full flex items-center gap-1 py-2.5 text-left"
169
+ >
170
+ <span>
171
+ {title || ''}
172
+ </span>
173
+ {#if column.getIsSorted() === 'desc'}
174
+ <Icon src={ArrowDown} class="size-4" />
175
+ {:else if column.getIsSorted() === 'asc'}
176
+ <Icon src={ArrowUp} class="size-4" />
177
+ {/if}
178
+ </button>
179
+ {/snippet}
180
+ <BaseTableHeaderOrderBy
181
+ sortDirection={column.getIsSorted() === 'asc' ? 'asc' : 'desc'}
182
+ isActive={column.getIsSorted() !== false}
183
+ onOrderBy={(direction) => column.toggleSorting(direction === 'desc')}
184
+ onHide={() => column.toggleVisibility(false)}
185
+ />
186
+ </BaseDropdown>
187
+ </div>
188
+ {/if}
189
+ {/snippet}
190
+
191
+ <div class="flex flex-col gap-4">
192
+ <DataTableToolbar {table} {filters} />
193
+ <div class="flex flex-col gap-[5px]">
194
+ <div bind:this={containerRef} class="relative bg-background">
195
+ <div class="overflow-x-auto relative z-10">
196
+ <Table.Root>
197
+ <Table.Header>
198
+ {#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
199
+ <Table.Row class="hover:!bg-transparent border-b border-border">
200
+ {#each headerGroup.headers as header, index (header.id)}
201
+ {@const isLastScrollable = index === headerGroup.headers.length - 2}
202
+ <Table.Head
203
+ colspan={header.colSpan}
204
+ style={getHeaderStyle(header, isLastScrollable)}
205
+ class={getHeaderClasses(header, isLastScrollable)}
206
+ >
207
+ {#if !header.isPlaceholder}
208
+ {#if typeof header.column.columnDef.header === 'string'}
209
+ {@render ColumnHeader({
210
+ column: header.column as Column<TData>,
211
+ title: header.column.columnDef.header as string
212
+ })}
213
+ {:else}
214
+ <FlexRender
215
+ content={header.column.columnDef.header}
216
+ context={header.getContext()}
217
+ />
218
+ {/if}
219
+ {/if}
220
+ {#if header.column.getCanResize()}
221
+ <!-- Always visible vertical border -->
222
+ <div
223
+ class={cn(
224
+ 'absolute right-0 top-1/2 -translate-y-1/2 h-3 w-px bg-background-default-tertiary',
225
+ header.column.getIsResizing() && 'opacity-0'
226
+ )}
227
+ ></div>
228
+ <!-- Resize handler (larger interactive area, enhanced on hover) -->
229
+ <div
230
+ role="button"
231
+ tabindex="0"
232
+ aria-label="Resize column"
233
+ class="absolute right-0 top-0 h-full w-3 cursor-col-resize select-none touch-none group -mr-1.5"
234
+ onmousedown={header.getResizeHandler()}
235
+ ontouchstart={header.getResizeHandler()}
236
+ >
237
+ <div
238
+ class={cn(
239
+ 'absolute right-1.5 top-0 h-full w-0.5 bg-border-default-secondary transition-opacity opacity-0',
240
+ !header.column.getIsResizing() && 'group-hover:opacity-100'
241
+ )}
242
+ ></div>
243
+ </div>
244
+ {/if}
245
+ </Table.Head>
246
+ {/each}
247
+ </Table.Row>
248
+ {/each}
249
+ </Table.Header>
250
+ <Table.Body>
251
+ {#each table.getRowModel().rows as row (row.id)}
252
+ <Table.Row
253
+ data-state={row.getIsSelected() ? 'selected' : undefined}
254
+ class="border-b border-border"
255
+ onclick={() => onRowClick?.(row.original as TData)}
256
+ >
257
+ {#each row.getVisibleCells() as cell, index (cell.id)}
258
+ {@const isLastScrollable = index === row.getVisibleCells().length - 2}
259
+ {@const visibleCells = row.getVisibleCells()}
260
+ {@const firstDataColumnIndex = visibleCells.findIndex(
261
+ (c) => c.column.id !== 'select' && c.column.id !== 'actions'
262
+ )}
263
+ {@const isFirstDataColumn = index === firstDataColumnIndex}
264
+ <Table.Cell
265
+ style={getCellStyle(cell, isLastScrollable)}
266
+ class={getCellClasses(cell, isLastScrollable, isFirstDataColumn)}
267
+ >
268
+ {#if cell.column.id === 'actions'}
269
+ {@render StickyCellWrapper({
270
+ align: 'right',
271
+ children: CellContent
272
+ })}
273
+ {#snippet CellContent()}
274
+ <FlexRender
275
+ content={cell.column.columnDef.cell}
276
+ context={cell.getContext()}
277
+ />
278
+ {/snippet}
279
+ {:else if cell.column.id === 'select'}
280
+ {@render StickyCellWrapper({
281
+ align: 'left',
282
+ children: CellContent
283
+ })}
284
+ {#snippet CellContent()}
285
+ <FlexRender
286
+ content={cell.column.columnDef.cell}
287
+ context={cell.getContext()}
288
+ />
289
+ {/snippet}
290
+ {:else}
291
+ <FlexRender
292
+ content={cell.column.columnDef.cell}
293
+ context={cell.getContext()}
294
+ />
295
+ {/if}
296
+ </Table.Cell>
297
+ {/each}
298
+ </Table.Row>
299
+ {:else}
300
+ <Table.Row>
301
+ <Table.Cell colspan={columns.length} class="h-48">
302
+ <EmptyState
303
+ iconSource={emptyState.iconSource}
304
+ title={emptyState.title}
305
+ description={emptyState.description}
306
+ />
307
+ </Table.Cell>
308
+ </Table.Row>
309
+ {/each}
310
+ </Table.Body>
311
+ </Table.Root>
312
+ </div>
313
+ </div>
314
+ {#if enablePagination}
315
+ <DataTablePagination
316
+ {table}
317
+ selectedSlot={paginationSelectedSlot}
318
+ unselectedSlot={paginationUnselectedSlot}
319
+ {onPageChange}
320
+ {onPageSizeChange}
321
+ />
322
+ {/if}
323
+ </div>
324
+ </div>