@placeholderco/placeholder-ui 1.0.12 → 2.0.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 +1 -1
- package/README.md +134 -130
- package/dist/app.css +178 -0
- package/dist/bootstrap.min.css +3600 -0
- package/dist/cards/GitCard.svelte +115 -0
- package/dist/cards/GitCard.svelte.d.ts +22 -0
- package/dist/display/Avatar.svelte +29 -17
- package/dist/display/Avatar.svelte.d.ts +12 -2
- package/dist/display/LinkCollection.svelte +40 -18
- package/dist/display/LinkCollection.svelte.d.ts +9 -2
- package/dist/display/Paper.svelte +31 -19
- package/dist/display/Paper.svelte.d.ts +12 -3
- package/dist/display/alert/Alert.svelte +129 -0
- package/dist/display/alert/Alert.svelte.d.ts +15 -0
- package/dist/display/alert/AlertVariant.d.ts +1 -0
- package/dist/display/alert/AlertVariant.js +1 -0
- package/dist/display/filetree/FileTree.svelte +259 -0
- package/dist/display/filetree/FileTree.svelte.d.ts +76 -0
- package/dist/display/filetree/FileTreeItem.svelte +396 -0
- package/dist/display/filetree/FileTreeItem.svelte.d.ts +40 -0
- package/dist/display/filetree/FileTreeNode.d.ts +46 -0
- package/dist/display/filetree/FileTreeNode.js +115 -0
- package/dist/display/filetree/index.d.ts +5 -0
- package/dist/display/filetree/index.js +3 -0
- package/dist/editors/CodeMirror.svelte +306 -0
- package/dist/editors/CodeMirror.svelte.d.ts +31 -0
- package/dist/editors/tiptap/LinkActionMenu.svelte +307 -0
- package/dist/editors/tiptap/LinkActionMenu.svelte.d.ts +8 -0
- package/dist/editors/tiptap/TipTap.svelte +856 -0
- package/dist/editors/tiptap/TipTap.svelte.d.ts +54 -0
- package/dist/editors/tiptap/TipTapBubble.svelte +790 -0
- package/dist/editors/tiptap/TipTapBubble.svelte.d.ts +44 -0
- package/dist/editors/tiptap/collaboration.d.ts +55 -0
- package/dist/editors/tiptap/collaboration.js +1 -0
- package/dist/editors/tiptap/extensions/Alert.d.ts +18 -0
- package/dist/editors/tiptap/extensions/Alert.js +72 -0
- package/dist/editors/tiptap/extensions/CodeBlockEditor.d.ts +21 -0
- package/dist/editors/tiptap/extensions/CodeBlockEditor.js +326 -0
- package/dist/editors/tiptap/extensions/Div.d.ts +19 -0
- package/dist/editors/tiptap/extensions/Div.js +89 -0
- package/dist/editors/tiptap/extensions/Span.d.ts +5 -0
- package/dist/editors/tiptap/extensions/Span.js +56 -0
- package/dist/editors/tiptap/extensions/codeBlockEditor.css +236 -0
- package/dist/editors/tiptap/extensions/codeBlockLanguages.d.ts +17 -0
- package/dist/editors/tiptap/extensions/codeBlockLanguages.js +124 -0
- package/dist/editors/tiptap/extensions/index.d.ts +7 -0
- package/dist/editors/tiptap/extensions/index.js +5 -0
- package/dist/editors/tiptap/toolbar/AlertButton.svelte +261 -0
- package/dist/editors/tiptap/toolbar/AlertButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/AlignRightButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/AlignRightButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/BoldButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/BoldButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/BulletListButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/BulletListButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/CodeButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/CodeButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/ColorButton.svelte +299 -0
- package/dist/editors/tiptap/toolbar/ColorButton.svelte.d.ts +20 -0
- package/dist/editors/tiptap/toolbar/DocumentButton.svelte +58 -0
- package/dist/editors/tiptap/toolbar/DocumentButton.svelte.d.ts +9 -0
- package/dist/editors/tiptap/toolbar/HeadingButton.svelte +30 -0
- package/dist/editors/tiptap/toolbar/HeadingButton.svelte.d.ts +8 -0
- package/dist/editors/tiptap/toolbar/HtmlButton.svelte +68 -0
- package/dist/editors/tiptap/toolbar/HtmlButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/ImageButton.svelte +54 -0
- package/dist/editors/tiptap/toolbar/ImageButton.svelte.d.ts +8 -0
- package/dist/editors/tiptap/toolbar/ItalicButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/ItalicButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/LinkButton.svelte +257 -0
- package/dist/editors/tiptap/toolbar/LinkButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/OrderedListButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/OrderedListButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/RedoButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/RedoButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/SubscriptButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/SubscriptButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/TableButton.svelte +258 -0
- package/dist/editors/tiptap/toolbar/TableButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/ToolbarButton.svelte +84 -0
- package/dist/editors/tiptap/toolbar/ToolbarButton.svelte.d.ts +10 -0
- package/dist/editors/tiptap/toolbar/UnderlineButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/UnderlineButton.svelte.d.ts +7 -0
- package/dist/editors/tiptap/toolbar/UndoButton.svelte +18 -0
- package/dist/editors/tiptap/toolbar/UndoButton.svelte.d.ts +7 -0
- package/dist/form/Autocomplete.svelte +86 -135
- package/dist/form/Autocomplete.svelte.d.ts +6 -8
- package/dist/form/AutocompleteMulti.svelte +385 -227
- package/dist/form/AutocompleteMulti.svelte.d.ts +59 -10
- package/dist/form/Checkbox.svelte +59 -54
- package/dist/form/Checkbox.svelte.d.ts +14 -5
- package/dist/form/Chips.svelte +29 -13
- package/dist/form/Chips.svelte.d.ts +16 -2
- package/dist/form/ComboBox.svelte +30 -20
- package/dist/form/ComboBox.svelte.d.ts +1 -1
- package/dist/form/ComboBoxItemBuilder.svelte +161 -188
- package/dist/form/ComboBoxItemBuilder.svelte.d.ts +19 -2
- package/dist/form/ComboBoxMulti.svelte +38 -24
- package/dist/form/ComboBoxMulti.svelte.d.ts +1 -1
- package/dist/form/CronBuilder.svelte +84 -67
- package/dist/form/CronBuilder.svelte.d.ts +16 -3
- package/dist/form/DatePicker.svelte +148 -195
- package/dist/form/DateRangePicker.svelte +101 -98
- package/dist/form/DateTimePicker.svelte +167 -208
- package/dist/form/DateTimePicker.svelte.d.ts +10 -2
- package/dist/form/FormGroup.svelte +33 -10
- package/dist/form/FormGroup.svelte.d.ts +12 -2
- package/dist/form/Number.svelte +70 -47
- package/dist/form/Number.svelte.d.ts +36 -6
- package/dist/form/Radio.svelte +18 -18
- package/dist/form/RadioGroup.svelte +23 -12
- package/dist/form/RadioGroup.svelte.d.ts +13 -2
- package/dist/form/SegmentedControl.svelte +76 -56
- package/dist/form/SegmentedControl.svelte.d.ts +9 -4
- package/dist/form/Select.svelte +150 -233
- package/dist/form/Select.svelte.d.ts +29 -5
- package/dist/form/SelectMulti.svelte +163 -277
- package/dist/form/SelectMulti.svelte.d.ts +36 -7
- package/dist/form/Slider.svelte +183 -269
- package/dist/form/Slider.svelte.d.ts +32 -17
- package/dist/form/StringArrayBuilder.svelte +249 -0
- package/dist/form/StringArrayBuilder.svelte.d.ts +15 -0
- package/dist/form/Switch.svelte +164 -106
- package/dist/form/Switch.svelte.d.ts +22 -3
- package/dist/form/TextArea.svelte +49 -29
- package/dist/form/TextArea.svelte.d.ts +23 -3
- package/dist/form/Textbox.svelte +69 -68
- package/dist/form/Textbox.svelte.d.ts +32 -4
- package/dist/form/TimePicker.svelte +42 -47
- package/dist/form/TimePicker.svelte.d.ts +12 -2
- package/dist/form/comboBoxCore.svelte.d.ts +99 -0
- package/dist/form/comboBoxCore.svelte.js +243 -0
- package/dist/icon/Icon.svelte +8 -3
- package/dist/icon/Icon.svelte.d.ts +8 -3
- package/dist/icon/file-type-bmp.svg +1 -0
- package/dist/icon/file-type-csv.svg +1 -0
- package/dist/icon/file-type-doc.svg +1 -0
- package/dist/icon/file-type-docx.svg +1 -0
- package/dist/icon/file-type-jpg.svg +1 -0
- package/dist/icon/file-type-pdf.svg +1 -0
- package/dist/icon/file-type-png.svg +1 -0
- package/dist/icon/file-type-ppt.svg +1 -0
- package/dist/icon/file-type-svg.svg +1 -0
- package/dist/icon/file-type-txt.svg +1 -0
- package/dist/icon/file-type-xls.svg +1 -0
- package/dist/icon/file-type-zip.svg +1 -0
- package/dist/icon/index.d.ts +166 -151
- package/dist/icon/index.js +166 -152
- package/dist/icon/logo-placeholder.svg +6 -0
- package/dist/icon/source-code.svg +1 -0
- package/dist/icon/sun-moon.svg +1 -0
- package/dist/icon/table.svg +6 -0
- package/dist/index.d.ts +87 -26
- package/dist/index.js +25 -28
- package/dist/layout/AppShell.svelte +12 -162
- package/dist/layout/AppShell.svelte.d.ts +6 -27
- package/dist/layout/CustomNavbar.svelte +9 -7
- package/dist/layout/CustomNavbar.svelte.d.ts +4 -2
- package/dist/layout/Navbar.svelte +161 -129
- package/dist/layout/Navbar.svelte.d.ts +29 -15
- package/dist/layout/NavbarItemDisplay.svelte +2 -2
- package/dist/layout/NavbarItemView.svelte +182 -0
- package/dist/layout/NavbarItemView.svelte.d.ts +10 -0
- package/dist/layout/Sidenav.svelte +280 -341
- package/dist/layout/Sidenav.svelte.d.ts +36 -4
- package/dist/models/ComboBoxItem.d.ts +2 -0
- package/dist/models/Employee.d.ts +53 -0
- package/dist/models/Employee.js +23 -0
- package/dist/models/Hyperlink.d.ts +3 -1
- package/dist/models/LinkCollectionItem.d.ts +3 -1
- package/dist/models/NavbarItem.d.ts +6 -2
- package/dist/theme.svelte.d.ts +0 -1
- package/dist/theme.svelte.js +46 -58
- package/dist/ui/Accordion.svelte +81 -242
- package/dist/ui/Accordion.svelte.d.ts +37 -14
- package/dist/ui/AccordionItem.svelte +303 -0
- package/dist/ui/AccordionItem.svelte.d.ts +21 -0
- package/dist/ui/ActionIcon.svelte +25 -21
- package/dist/ui/ActionIcon.svelte.d.ts +15 -2
- package/dist/ui/Badge.svelte +163 -171
- package/dist/ui/Badge.svelte.d.ts +13 -5
- package/dist/ui/Button.svelte +178 -205
- package/dist/ui/Button.svelte.d.ts +19 -2
- package/dist/ui/ButtonVariant.d.ts +15 -1
- package/dist/ui/ContextMenu.svelte +146 -0
- package/dist/ui/ContextMenu.svelte.d.ts +37 -0
- package/dist/ui/ContextMenuList.svelte +188 -0
- package/dist/ui/ContextMenuList.svelte.d.ts +12 -0
- package/dist/ui/Dialog.svelte +183 -111
- package/dist/ui/Dialog.svelte.d.ts +21 -4
- package/dist/ui/Drawer.svelte +237 -184
- package/dist/ui/Drawer.svelte.d.ts +20 -2
- package/dist/ui/Dropdown.svelte +24 -14
- package/dist/ui/Dropdown.svelte.d.ts +11 -2
- package/dist/ui/Dropzone.svelte +159 -57
- package/dist/ui/Dropzone.svelte.d.ts +29 -2
- package/dist/ui/Link.svelte +12 -4
- package/dist/ui/Link.svelte.d.ts +8 -2
- package/dist/ui/Loader.svelte +23 -18
- package/dist/ui/Loader.svelte.d.ts +5 -2
- package/dist/ui/Logo.svelte +37 -0
- package/dist/ui/Logo.svelte.d.ts +16 -0
- package/dist/ui/MultiSortable.svelte +287 -0
- package/dist/ui/MultiSortable.svelte.d.ts +50 -0
- package/dist/ui/Pagination.svelte +15 -9
- package/dist/ui/Pagination.svelte.d.ts +6 -2
- package/dist/ui/Popover.svelte +43 -65
- package/dist/ui/Popover.svelte.d.ts +14 -5
- package/dist/ui/ProgressBar.svelte +28 -30
- package/dist/ui/ProgressBarVariant.d.ts +7 -1
- package/dist/ui/SegmentedControl.svelte +0 -0
- package/dist/ui/SegmentedControl.svelte.d.ts +26 -0
- package/dist/ui/Sortable.svelte +163 -0
- package/dist/ui/Sortable.svelte.d.ts +47 -0
- package/dist/ui/Table.svelte +383 -80
- package/dist/ui/Table.svelte.d.ts +43 -2
- package/dist/ui/Tabs.svelte +22 -18
- package/dist/ui/Tabs.svelte.d.ts +6 -2
- package/dist/ui/ThemeSwitcher.svelte +26 -7
- package/dist/ui/ThemeSwitcher.svelte.d.ts +4 -2
- package/dist/ui/Tooltip.svelte +312 -180
- package/dist/ui/Tooltip.svelte.d.ts +4 -3
- package/dist/uiTheme.svelte.d.ts +86 -0
- package/dist/uiTheme.svelte.js +214 -0
- package/dist/util/DateFunctions.js +1 -1
- package/dist/util/DragDrop.d.ts +50 -0
- package/dist/util/DragDrop.js +154 -0
- package/dist/util/NavigateTo.js +2 -2
- package/dist/util/dayjs.d.ts +4 -0
- package/dist/util/dayjs.js +15 -0
- package/package.json +66 -26
- package/dist/display/Alert.svelte +0 -179
- package/dist/display/Alert.svelte.d.ts +0 -13
- package/dist/form/FileInput.svelte +0 -235
- package/dist/form/FileInput.svelte.d.ts +0 -23
- package/dist/form/PasswordInput.svelte +0 -253
- package/dist/form/PasswordInput.svelte.d.ts +0 -34
- package/dist/form/Rating.svelte +0 -235
- package/dist/form/Rating.svelte.d.ts +0 -21
- package/dist/styles/components.css +0 -199
- package/dist/styles/dark.css +0 -146
- package/dist/styles/index.css +0 -116
- package/dist/styles/reset.css +0 -110
- package/dist/styles/semantic.css +0 -86
- package/dist/styles/tokens.css +0 -203
- package/dist/styles/utilities.css +0 -523
- package/dist/ui/Breadcrumbs.svelte +0 -131
- package/dist/ui/Breadcrumbs.svelte.d.ts +0 -16
- package/dist/ui/LoadingOverlay.svelte +0 -53
- package/dist/ui/LoadingOverlay.svelte.d.ts +0 -11
- package/dist/ui/Progress.svelte +0 -191
- package/dist/ui/Progress.svelte.d.ts +0 -15
- package/dist/ui/RingProgress.svelte +0 -141
- package/dist/ui/RingProgress.svelte.d.ts +0 -18
- package/dist/ui/Skeleton.svelte +0 -85
- package/dist/ui/Skeleton.svelte.d.ts +0 -12
- package/dist/ui/Stepper.svelte +0 -355
- package/dist/ui/Stepper.svelte.d.ts +0 -24
- package/dist/ui/Timeline.svelte +0 -225
- package/dist/ui/Timeline.svelte.d.ts +0 -23
- /package/dist/{actions → util}/ClickOutside.d.ts +0 -0
- /package/dist/{actions → util}/ClickOutside.js +0 -0
- /package/dist/{transitions → util}/Transitions.d.ts +0 -0
- /package/dist/{transitions → util}/Transitions.js +0 -0
package/dist/ui/Table.svelte
CHANGED
|
@@ -3,7 +3,15 @@
|
|
|
3
3
|
import Textbox from '../form/Textbox.svelte';
|
|
4
4
|
import Checkbox from '../form/Checkbox.svelte';
|
|
5
5
|
import Icon from '../icon/Icon.svelte';
|
|
6
|
-
import
|
|
6
|
+
import Pagination from './Pagination.svelte';
|
|
7
|
+
import {
|
|
8
|
+
iconArrowsSort,
|
|
9
|
+
iconChevronDown,
|
|
10
|
+
iconChevronRight,
|
|
11
|
+
iconChevronUp,
|
|
12
|
+
iconSearch
|
|
13
|
+
} from '../icon/index.js';
|
|
14
|
+
import { navigateTo } from '../util/NavigateTo.js';
|
|
7
15
|
|
|
8
16
|
export interface Column<T = any> {
|
|
9
17
|
key: string;
|
|
@@ -11,10 +19,14 @@
|
|
|
11
19
|
sortable?: boolean;
|
|
12
20
|
width?: string;
|
|
13
21
|
align?: 'left' | 'center' | 'right';
|
|
22
|
+
/** Snippet rendered as the cell content. Takes precedence over `render`. */
|
|
23
|
+
cell?: Snippet<[{ value: any; row: T; index: number }]>;
|
|
24
|
+
/** @deprecated Returns raw HTML injected via {@html} — unsafe for untrusted
|
|
25
|
+
* data and cannot render components. Use `cell` instead. */
|
|
14
26
|
render?: (value: any, row: T) => any;
|
|
15
27
|
}
|
|
16
28
|
|
|
17
|
-
interface
|
|
29
|
+
export interface TableProps<T = any> {
|
|
18
30
|
/** Column definitions for the table */
|
|
19
31
|
columns: Column<T>[];
|
|
20
32
|
/** Data rows to display */
|
|
@@ -41,6 +53,10 @@
|
|
|
41
53
|
buttons?: Snippet<[T, number]>;
|
|
42
54
|
/** Callback when a row is clicked */
|
|
43
55
|
onrowclick?: (row: T, index: number) => void;
|
|
56
|
+
/** Returns a URL for a row. When provided, rows act as links: a plain click
|
|
57
|
+
* navigates client-side, while middle-click or ctrl/cmd/shift-click opens the
|
|
58
|
+
* URL in a new tab. Return a falsy value to make a row non-navigable. */
|
|
59
|
+
rowHref?: (row: T, index: number) => string | undefined | null;
|
|
44
60
|
/** Enable checkbox selection */
|
|
45
61
|
selectable?: boolean;
|
|
46
62
|
/** Field name used to uniquely identify rows (required when selectable is true) */
|
|
@@ -49,6 +65,35 @@
|
|
|
49
65
|
selectedRows?: T[];
|
|
50
66
|
/** Callback when selection changes */
|
|
51
67
|
onselect?: (selectedRows: T[]) => void;
|
|
68
|
+
/** Detail content rendered in a full-width row beneath an expanded row.
|
|
69
|
+
* Providing this enables row expansion: expandable rows toggle on row click
|
|
70
|
+
* or via their chevron button. Requires rowKey. */
|
|
71
|
+
expandedContent?: Snippet<[T, number]>;
|
|
72
|
+
/** Limits which rows can expand (e.g. only group rows). Default: all rows. */
|
|
73
|
+
canExpand?: (row: T, index: number) => boolean;
|
|
74
|
+
/** Keys (via rowKey) of currently expanded rows (bindable) */
|
|
75
|
+
expandedKeys?: any[];
|
|
76
|
+
/** Callback when a row is expanded or collapsed — trigger on-demand fetches here */
|
|
77
|
+
onexpand?: (row: T, index: number, expanded: boolean) => void;
|
|
78
|
+
/** Rows per page. Setting this enables built-in client-side pagination,
|
|
79
|
+
* applied after search filtering and sorting. */
|
|
80
|
+
pageSize?: number;
|
|
81
|
+
/** Current page number, 1-based (bindable) */
|
|
82
|
+
page?: number;
|
|
83
|
+
/** Callback when the current page changes */
|
|
84
|
+
onpagechange?: (page: number) => void;
|
|
85
|
+
/** Key of the column currently sorted by, or null for unsorted (bindable).
|
|
86
|
+
* Set it to render the sort indicator for a server-supplied sort order. */
|
|
87
|
+
sortKey?: string | null;
|
|
88
|
+
/** Current sort direction (bindable) */
|
|
89
|
+
sortDirection?: 'asc' | 'desc';
|
|
90
|
+
/** Callback when the user clicks a sortable header, after `sortKey` and
|
|
91
|
+
* `sortDirection` have been updated. Use it to request sorted data from a
|
|
92
|
+
* server. Paginated tables also reset to page 1 before this fires. */
|
|
93
|
+
onsort?: (key: string, direction: 'asc' | 'desc') => void;
|
|
94
|
+
/** Skip the built-in client-side sort and render `rows` in the order given.
|
|
95
|
+
* Use with `onsort` when the server returns pre-sorted rows. */
|
|
96
|
+
manualSort?: boolean;
|
|
52
97
|
}
|
|
53
98
|
|
|
54
99
|
let {
|
|
@@ -65,24 +110,85 @@
|
|
|
65
110
|
children,
|
|
66
111
|
buttons,
|
|
67
112
|
onrowclick,
|
|
113
|
+
rowHref = undefined,
|
|
68
114
|
selectable = false,
|
|
69
115
|
rowKey = undefined,
|
|
70
116
|
selectedRows = $bindable([]),
|
|
71
|
-
onselect = undefined
|
|
72
|
-
|
|
117
|
+
onselect = undefined,
|
|
118
|
+
expandedContent = undefined,
|
|
119
|
+
canExpand = undefined,
|
|
120
|
+
expandedKeys = $bindable([]),
|
|
121
|
+
onexpand = undefined,
|
|
122
|
+
pageSize = undefined,
|
|
123
|
+
page = $bindable(1),
|
|
124
|
+
onpagechange = undefined,
|
|
125
|
+
sortKey = $bindable(null),
|
|
126
|
+
sortDirection = $bindable('asc'),
|
|
127
|
+
onsort = undefined,
|
|
128
|
+
manualSort = false
|
|
129
|
+
}: TableProps = $props();
|
|
73
130
|
|
|
74
131
|
let searchQuery = $state('');
|
|
75
|
-
let sortColumn = $state<string | null>(null);
|
|
76
|
-
let sortDirection = $state<'asc' | 'desc'>('asc');
|
|
77
132
|
|
|
78
133
|
let _selectionWarned = false;
|
|
79
|
-
$effect(() => {
|
|
134
|
+
$effect(() => {
|
|
135
|
+
if (selectable && !rowKey && !_selectionWarned) {
|
|
136
|
+
_selectionWarned = true;
|
|
137
|
+
console.warn('Table: rowKey is required when selectable is true');
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
let _expandWarned = false;
|
|
142
|
+
$effect(() => {
|
|
143
|
+
if (expandedContent && !rowKey && !_expandWarned) {
|
|
144
|
+
_expandWarned = true;
|
|
145
|
+
console.warn('Table: rowKey is required when expandedContent is provided');
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const expandable = $derived(!!expandedContent && !!rowKey);
|
|
150
|
+
|
|
151
|
+
// Prune expandedKeys when rows changes to remove entries no longer present
|
|
152
|
+
$effect(() => {
|
|
153
|
+
if (!expandable || expandedKeys.length === 0) return;
|
|
154
|
+
const validKeys = new Set(rows.map((r) => getValue(r, rowKey!)));
|
|
155
|
+
const pruned = expandedKeys.filter((k) => validKeys.has(k));
|
|
156
|
+
if (pruned.length !== expandedKeys.length) {
|
|
157
|
+
expandedKeys = pruned;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Set of expanded row keys for O(1) lookup
|
|
162
|
+
const expandedKeySet = $derived(new Set(expandedKeys));
|
|
163
|
+
|
|
164
|
+
function isRowExpanded(row: any): boolean {
|
|
165
|
+
if (!expandable) return false;
|
|
166
|
+
return expandedKeySet.has(getValue(row, rowKey!));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function rowCanExpand(row: any, index: number): boolean {
|
|
170
|
+
if (!expandable) return false;
|
|
171
|
+
return canExpand ? canExpand(row, index) : true;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function toggleExpand(row: any, index: number) {
|
|
175
|
+
if (!rowCanExpand(row, index)) return;
|
|
176
|
+
|
|
177
|
+
const key = getValue(row, rowKey!);
|
|
178
|
+
const expanded = !expandedKeySet.has(key);
|
|
179
|
+
if (expanded) {
|
|
180
|
+
expandedKeys = [...expandedKeys, key];
|
|
181
|
+
} else {
|
|
182
|
+
expandedKeys = expandedKeys.filter((k) => k !== key);
|
|
183
|
+
}
|
|
184
|
+
onexpand?.(row, index, expanded);
|
|
185
|
+
}
|
|
80
186
|
|
|
81
|
-
// Prune selectedRows when rows
|
|
187
|
+
// Prune selectedRows when rows changes to remove entries no longer present
|
|
82
188
|
$effect(() => {
|
|
83
189
|
if (!selectable || !rowKey || selectedRows.length === 0) return;
|
|
84
|
-
const validKeys = new Set(rows.map(r => getValue(r, rowKey)));
|
|
85
|
-
const pruned = selectedRows.filter(r => validKeys.has(getValue(r, rowKey)));
|
|
190
|
+
const validKeys = new Set(rows.map((r) => getValue(r, rowKey)));
|
|
191
|
+
const pruned = selectedRows.filter((r) => validKeys.has(getValue(r, rowKey)));
|
|
86
192
|
if (pruned.length !== selectedRows.length) {
|
|
87
193
|
selectedRows = pruned;
|
|
88
194
|
onselect?.(selectedRows);
|
|
@@ -92,64 +198,101 @@
|
|
|
92
198
|
// Set of selected row keys for O(1) lookup
|
|
93
199
|
const selectedKeys = $derived.by(() => {
|
|
94
200
|
if (!selectable || !rowKey) return new Set<any>();
|
|
95
|
-
return new Set(selectedRows.map(r => getValue(r, rowKey)));
|
|
201
|
+
return new Set(selectedRows.map((r) => getValue(r, rowKey)));
|
|
96
202
|
});
|
|
97
203
|
|
|
204
|
+
// Check if a row is selected
|
|
98
205
|
function isRowSelected(row: any): boolean {
|
|
99
206
|
if (!selectable || !rowKey) return false;
|
|
100
207
|
return selectedKeys.has(getValue(row, rowKey));
|
|
101
208
|
}
|
|
102
209
|
|
|
210
|
+
// Toggle individual row selection
|
|
103
211
|
function toggleRow(row: any) {
|
|
104
212
|
if (!selectable || !rowKey) return;
|
|
105
213
|
|
|
106
214
|
const key = getValue(row, rowKey);
|
|
107
215
|
if (selectedKeys.has(key)) {
|
|
108
|
-
|
|
216
|
+
// Deselect: remove from selectedRows
|
|
217
|
+
selectedRows = selectedRows.filter((r) => getValue(r, rowKey) !== key);
|
|
109
218
|
} else {
|
|
219
|
+
// Select: add to selectedRows
|
|
110
220
|
selectedRows = [...selectedRows, row];
|
|
111
221
|
}
|
|
112
222
|
onselect?.(selectedRows);
|
|
113
223
|
}
|
|
114
224
|
|
|
225
|
+
// Handle a row click. Middle-click and ctrl/cmd/shift-click are treated as
|
|
226
|
+
// open-in-new-tab intent when a rowHref is provided.
|
|
227
|
+
function handleRowClick(row: any, index: number, event: MouseEvent) {
|
|
228
|
+
const href = rowHref?.(row, index);
|
|
229
|
+
const newTabIntent = event.button === 1 || event.ctrlKey || event.metaKey || event.shiftKey;
|
|
230
|
+
|
|
231
|
+
// Expansion/selection toggling only applies to a plain primary click without
|
|
232
|
+
// nav intent. Expansion wins on rows that can expand; selection stays
|
|
233
|
+
// available via the checkbox and still handles non-expandable rows.
|
|
234
|
+
if (expandable && !href && event.button !== 1 && rowCanExpand(row, index)) {
|
|
235
|
+
toggleExpand(row, index);
|
|
236
|
+
} else if (selectable && !href && event.button !== 1) {
|
|
237
|
+
toggleRow(row);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
onrowclick?.(row, index);
|
|
241
|
+
|
|
242
|
+
if (href) {
|
|
243
|
+
event.preventDefault();
|
|
244
|
+
if (newTabIntent) window.open(href, '_blank', 'noopener');
|
|
245
|
+
else navigateTo(href);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Toggle all visible rows (the current page when paginated, else all filtered rows)
|
|
115
250
|
function toggleAll() {
|
|
116
251
|
if (!selectable || !rowKey) return;
|
|
117
252
|
|
|
118
|
-
|
|
253
|
+
// Check if all visible rows are selected
|
|
254
|
+
const allSelected =
|
|
255
|
+
pagedRows.length > 0 && pagedRows.every((row) => selectedKeys.has(getValue(row, rowKey!)));
|
|
119
256
|
|
|
120
257
|
if (allSelected) {
|
|
121
|
-
// Deselect all
|
|
122
|
-
const
|
|
123
|
-
selectedRows = selectedRows.filter(r => !
|
|
258
|
+
// Deselect all visible rows
|
|
259
|
+
const visibleKeys = new Set(pagedRows.map((r) => getValue(r, rowKey!)));
|
|
260
|
+
selectedRows = selectedRows.filter((r) => !visibleKeys.has(getValue(r, rowKey!)));
|
|
124
261
|
} else {
|
|
125
|
-
// Select all
|
|
126
|
-
const existingKeys = new Set(selectedRows.map(r => getValue(r, rowKey!)));
|
|
127
|
-
const newSelections =
|
|
262
|
+
// Select all visible rows (merge with existing selections elsewhere)
|
|
263
|
+
const existingKeys = new Set(selectedRows.map((r) => getValue(r, rowKey!)));
|
|
264
|
+
const newSelections = pagedRows.filter((r) => !existingKeys.has(getValue(r, rowKey!)));
|
|
128
265
|
selectedRows = [...selectedRows, ...newSelections];
|
|
129
266
|
}
|
|
130
267
|
onselect?.(selectedRows);
|
|
131
268
|
}
|
|
132
269
|
|
|
270
|
+
// Derived states for select-all checkbox
|
|
133
271
|
const isAllSelected = $derived.by(() => {
|
|
134
|
-
if (!selectable || !rowKey ||
|
|
135
|
-
return
|
|
272
|
+
if (!selectable || !rowKey || pagedRows.length === 0) return false;
|
|
273
|
+
return pagedRows.every((row) => selectedKeys.has(getValue(row, rowKey)));
|
|
136
274
|
});
|
|
137
275
|
|
|
138
276
|
const isSomeSelected = $derived.by(() => {
|
|
139
|
-
if (!selectable || !rowKey ||
|
|
140
|
-
const selectedCount =
|
|
141
|
-
return selectedCount > 0 && selectedCount <
|
|
277
|
+
if (!selectable || !rowKey || pagedRows.length === 0) return false;
|
|
278
|
+
const selectedCount = pagedRows.filter((row) => selectedKeys.has(getValue(row, rowKey))).length;
|
|
279
|
+
return selectedCount > 0 && selectedCount < pagedRows.length;
|
|
142
280
|
});
|
|
143
281
|
|
|
144
282
|
function handleSort(column: Column) {
|
|
145
283
|
if (!column.sortable) return;
|
|
146
284
|
|
|
147
|
-
if (
|
|
285
|
+
if (sortKey === column.key) {
|
|
148
286
|
sortDirection = sortDirection === 'asc' ? 'desc' : 'asc';
|
|
149
287
|
} else {
|
|
150
|
-
|
|
288
|
+
sortKey = column.key;
|
|
151
289
|
sortDirection = 'asc';
|
|
152
290
|
}
|
|
291
|
+
|
|
292
|
+
// A new sort order invalidates the current page position
|
|
293
|
+
if (paginated && page !== 1) page = 1;
|
|
294
|
+
|
|
295
|
+
onsort?.(column.key, sortDirection);
|
|
153
296
|
}
|
|
154
297
|
|
|
155
298
|
function getValue(row: any, key: string): any {
|
|
@@ -166,8 +309,8 @@
|
|
|
166
309
|
|
|
167
310
|
// Apply search filter
|
|
168
311
|
if (searchable && searchQuery) {
|
|
169
|
-
filtered = filtered.filter(row => {
|
|
170
|
-
return columns.some(column => {
|
|
312
|
+
filtered = filtered.filter((row) => {
|
|
313
|
+
return columns.some((column) => {
|
|
171
314
|
const value = getValue(row, column.key);
|
|
172
315
|
if (value === null || value === undefined) return false;
|
|
173
316
|
return String(value).toLowerCase().includes(searchQuery.toLowerCase());
|
|
@@ -175,11 +318,11 @@
|
|
|
175
318
|
});
|
|
176
319
|
}
|
|
177
320
|
|
|
178
|
-
// Apply sorting
|
|
179
|
-
if (
|
|
321
|
+
// Apply sorting — skipped when the caller sorts the rows itself (e.g. server-side)
|
|
322
|
+
if (sortKey && !manualSort) {
|
|
180
323
|
filtered.sort((a, b) => {
|
|
181
|
-
const aValue = getValue(a,
|
|
182
|
-
const bValue = getValue(b,
|
|
324
|
+
const aValue = getValue(a, sortKey!);
|
|
325
|
+
const bValue = getValue(b, sortKey!);
|
|
183
326
|
|
|
184
327
|
if (aValue === null || aValue === undefined) return 1;
|
|
185
328
|
if (bValue === null || bValue === undefined) return -1;
|
|
@@ -198,15 +341,51 @@
|
|
|
198
341
|
return filtered;
|
|
199
342
|
});
|
|
200
343
|
|
|
344
|
+
// Pagination — applied after search filtering and sorting
|
|
345
|
+
const paginated = $derived(!!pageSize && pageSize > 0);
|
|
346
|
+
const totalPages = $derived(
|
|
347
|
+
paginated ? Math.max(1, Math.ceil(filteredRows.length / pageSize!)) : 1
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
// Clamp page when filtering or a rows update shrinks the page count
|
|
351
|
+
$effect(() => {
|
|
352
|
+
if (page > totalPages) page = totalPages;
|
|
353
|
+
else if (page < 1) page = 1;
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// A new search invalidates the current page position — jump back to the first page
|
|
357
|
+
let _lastQuery = '';
|
|
358
|
+
$effect(() => {
|
|
359
|
+
if (searchQuery !== _lastQuery) {
|
|
360
|
+
_lastQuery = searchQuery;
|
|
361
|
+
if (page !== 1) page = 1;
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
const pagedRows = $derived.by(() => {
|
|
366
|
+
if (!paginated) return filteredRows;
|
|
367
|
+
const start = (page - 1) * pageSize!;
|
|
368
|
+
return filteredRows.slice(start, start + pageSize!);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
const pageStart = $derived(paginated ? (page - 1) * pageSize! + 1 : 1);
|
|
372
|
+
const pageEnd = $derived(
|
|
373
|
+
paginated ? Math.min(page * pageSize!, filteredRows.length) : filteredRows.length
|
|
374
|
+
);
|
|
375
|
+
|
|
201
376
|
const getSortIcon = (column: Column) => {
|
|
202
377
|
if (!column.sortable) return '';
|
|
203
|
-
if (
|
|
378
|
+
if (sortKey !== column.key) return iconArrowsSort;
|
|
204
379
|
return sortDirection === 'asc' ? iconChevronUp : iconChevronDown;
|
|
205
380
|
};
|
|
206
381
|
|
|
207
382
|
const tableClasses = $derived(
|
|
208
383
|
`pui-table ${tableClass} ${striped ? 'striped' : ''} ${hover ? 'hover' : ''}`
|
|
209
384
|
);
|
|
385
|
+
|
|
386
|
+
const totalColumns = $derived(
|
|
387
|
+
columns.length + (expandable ? 1 : 0) + (selectable && rowKey ? 1 : 0) + (buttons ? 1 : 0)
|
|
388
|
+
);
|
|
210
389
|
</script>
|
|
211
390
|
|
|
212
391
|
<div class="table-container">
|
|
@@ -225,12 +404,17 @@
|
|
|
225
404
|
<table class={tableClasses}>
|
|
226
405
|
<thead>
|
|
227
406
|
<tr>
|
|
407
|
+
{#if expandable}
|
|
408
|
+
<th class="table-header expand-cell" style="width: 40px"></th>
|
|
409
|
+
{/if}
|
|
228
410
|
{#if selectable && rowKey}
|
|
229
411
|
<th class="table-header checkbox-cell" style="width: 40px">
|
|
230
412
|
<Checkbox
|
|
231
413
|
controlled
|
|
232
414
|
checked={isAllSelected}
|
|
415
|
+
indeterminate={isSomeSelected}
|
|
233
416
|
onchange={() => toggleAll()}
|
|
417
|
+
ariaLabel="Select all rows"
|
|
234
418
|
/>
|
|
235
419
|
</th>
|
|
236
420
|
{/if}
|
|
@@ -244,10 +428,7 @@
|
|
|
244
428
|
<span>{column.label}</span>
|
|
245
429
|
{#if column.sortable}
|
|
246
430
|
<div class="sort-icon">
|
|
247
|
-
<Icon
|
|
248
|
-
svg={getSortIcon(column)}
|
|
249
|
-
size="14px"
|
|
250
|
-
/>
|
|
431
|
+
<Icon svg={getSortIcon(column)} size="14px" />
|
|
251
432
|
</div>
|
|
252
433
|
{/if}
|
|
253
434
|
</div>
|
|
@@ -261,38 +442,70 @@
|
|
|
261
442
|
<tbody>
|
|
262
443
|
{#if loading}
|
|
263
444
|
<tr>
|
|
264
|
-
<td colspan={
|
|
445
|
+
<td colspan={totalColumns} class="loading-cell">
|
|
265
446
|
<div class="loading-content">Loading...</div>
|
|
266
447
|
</td>
|
|
267
448
|
</tr>
|
|
268
449
|
{:else if filteredRows.length === 0}
|
|
269
450
|
<tr>
|
|
270
|
-
<td colspan={
|
|
451
|
+
<td colspan={totalColumns} class="empty-cell">
|
|
271
452
|
<div class="empty-content">{emptyMessage}</div>
|
|
272
453
|
</td>
|
|
273
454
|
</tr>
|
|
274
455
|
{:else}
|
|
275
|
-
{#each
|
|
456
|
+
{#each pagedRows as row, index}
|
|
457
|
+
{@const expanded = isRowExpanded(row)}
|
|
276
458
|
<tr
|
|
277
|
-
class=
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
459
|
+
class={(onrowclick ||
|
|
460
|
+
selectable ||
|
|
461
|
+
rowHref ||
|
|
462
|
+
(expandable && rowCanExpand(row, index))
|
|
463
|
+
? 'clickable-row'
|
|
464
|
+
: '') +
|
|
465
|
+
(selectable && isRowSelected(row) ? ' selected' : '') +
|
|
466
|
+
(expanded ? ' expanded' : '')}
|
|
467
|
+
class:row-even={index % 2 === 1}
|
|
468
|
+
onclick={(e) => handleRowClick(row, index, e)}
|
|
469
|
+
onmousedown={(e) => {
|
|
470
|
+
// Suppress the default middle-button action (autoscroll) so auxclick fires.
|
|
471
|
+
if (e.button === 1 && rowHref?.(row, index)) e.preventDefault();
|
|
472
|
+
}}
|
|
473
|
+
onauxclick={(e) => {
|
|
474
|
+
if (e.button === 1) handleRowClick(row, index, e);
|
|
281
475
|
}}
|
|
282
476
|
>
|
|
477
|
+
{#if expandable}
|
|
478
|
+
<td class="table-cell expand-cell" onclick={(e) => e.stopPropagation()}>
|
|
479
|
+
{#if rowCanExpand(row, index)}
|
|
480
|
+
<button
|
|
481
|
+
type="button"
|
|
482
|
+
class="expand-toggle"
|
|
483
|
+
class:expanded
|
|
484
|
+
aria-expanded={expanded}
|
|
485
|
+
aria-label={expanded ? 'Collapse row' : 'Expand row'}
|
|
486
|
+
onclick={() => toggleExpand(row, index)}
|
|
487
|
+
>
|
|
488
|
+
<Icon svg={iconChevronRight} size="16px" />
|
|
489
|
+
</button>
|
|
490
|
+
{/if}
|
|
491
|
+
</td>
|
|
492
|
+
{/if}
|
|
283
493
|
{#if selectable && rowKey}
|
|
284
494
|
<td class="table-cell checkbox-cell" onclick={(e) => e.stopPropagation()}>
|
|
285
495
|
<Checkbox
|
|
286
496
|
controlled
|
|
287
497
|
checked={isRowSelected(row)}
|
|
288
498
|
onchange={() => toggleRow(row)}
|
|
499
|
+
ariaLabel="Select row"
|
|
289
500
|
/>
|
|
290
501
|
</td>
|
|
291
502
|
{/if}
|
|
292
503
|
{#each columns as column}
|
|
293
504
|
{@const value = getValue(row, column.key)}
|
|
294
505
|
<td class="table-cell {column.align || 'left'}">
|
|
295
|
-
{#if column.
|
|
506
|
+
{#if column.cell}
|
|
507
|
+
{@render column.cell({ value, row, index })}
|
|
508
|
+
{:else if column.render}
|
|
296
509
|
{@html column.render(value, row)}
|
|
297
510
|
{:else if typeof value === 'function'}
|
|
298
511
|
{@render value()}
|
|
@@ -307,12 +520,28 @@
|
|
|
307
520
|
</td>
|
|
308
521
|
{/if}
|
|
309
522
|
</tr>
|
|
523
|
+
{#if expanded && expandedContent}
|
|
524
|
+
<tr class="detail-row" class:row-even={index % 2 === 1}>
|
|
525
|
+
<td class="detail-cell" colspan={totalColumns}>
|
|
526
|
+
{@render expandedContent(row, index)}
|
|
527
|
+
</td>
|
|
528
|
+
</tr>
|
|
529
|
+
{/if}
|
|
310
530
|
{/each}
|
|
311
531
|
{/if}
|
|
312
532
|
</tbody>
|
|
313
533
|
</table>
|
|
314
534
|
</div>
|
|
315
535
|
|
|
536
|
+
{#if paginated && !loading && totalPages > 1}
|
|
537
|
+
<div class="table-pagination">
|
|
538
|
+
<span class="pagination-info">
|
|
539
|
+
Showing {pageStart}–{pageEnd} of {filteredRows.length}
|
|
540
|
+
</span>
|
|
541
|
+
<Pagination bind:selectedPage={page} {totalPages} onPageChange={(p) => onpagechange?.(p)} />
|
|
542
|
+
</div>
|
|
543
|
+
{/if}
|
|
544
|
+
|
|
316
545
|
{@render children?.()}
|
|
317
546
|
</div>
|
|
318
547
|
|
|
@@ -322,45 +551,45 @@
|
|
|
322
551
|
}
|
|
323
552
|
|
|
324
553
|
.table-search {
|
|
325
|
-
margin-bottom:
|
|
554
|
+
margin-bottom: 1rem;
|
|
326
555
|
max-width: 400px;
|
|
327
556
|
}
|
|
328
557
|
|
|
329
558
|
.table-wrapper {
|
|
330
559
|
width: 100%;
|
|
331
560
|
overflow-x: auto;
|
|
332
|
-
border: 1px solid var(--
|
|
333
|
-
background-color: var(--
|
|
561
|
+
border: 1px solid var(--border-color);
|
|
562
|
+
background-color: var(--input-bg-color);
|
|
334
563
|
}
|
|
335
564
|
|
|
336
565
|
.table-wrapper.rounded {
|
|
337
|
-
border-radius:
|
|
566
|
+
border-radius: 0.5rem;
|
|
338
567
|
}
|
|
339
568
|
|
|
340
569
|
.pui-table {
|
|
341
570
|
width: 100%;
|
|
342
571
|
border-collapse: collapse;
|
|
343
|
-
font-size:
|
|
572
|
+
font-size: 0.875rem;
|
|
344
573
|
}
|
|
345
574
|
|
|
346
575
|
.table-header {
|
|
347
|
-
padding:
|
|
576
|
+
padding: 0.5rem;
|
|
348
577
|
text-align: left;
|
|
349
|
-
font-weight:
|
|
350
|
-
color: var(--
|
|
351
|
-
background-color: var(--
|
|
352
|
-
border-bottom: 2px solid var(--
|
|
578
|
+
font-weight: 600;
|
|
579
|
+
color: var(--text-color);
|
|
580
|
+
background-color: var(--bg-color);
|
|
581
|
+
border-bottom: 2px solid var(--border-color);
|
|
353
582
|
user-select: none;
|
|
354
583
|
white-space: nowrap;
|
|
355
584
|
}
|
|
356
585
|
|
|
357
586
|
.table-header.sortable {
|
|
358
587
|
cursor: pointer;
|
|
359
|
-
transition: background-color
|
|
588
|
+
transition: background-color 0.2s;
|
|
360
589
|
}
|
|
361
590
|
|
|
362
591
|
.table-header.sortable:hover {
|
|
363
|
-
background-color: var(--
|
|
592
|
+
background-color: var(--hover-bg);
|
|
364
593
|
}
|
|
365
594
|
|
|
366
595
|
.table-header.center {
|
|
@@ -374,7 +603,7 @@
|
|
|
374
603
|
.header-content {
|
|
375
604
|
display: flex;
|
|
376
605
|
align-items: center;
|
|
377
|
-
gap:
|
|
606
|
+
gap: 0.5rem;
|
|
378
607
|
justify-content: space-between;
|
|
379
608
|
}
|
|
380
609
|
|
|
@@ -382,7 +611,7 @@
|
|
|
382
611
|
display: inline-flex;
|
|
383
612
|
align-items: center;
|
|
384
613
|
opacity: 0.5;
|
|
385
|
-
transition: opacity
|
|
614
|
+
transition: opacity 0.2s;
|
|
386
615
|
}
|
|
387
616
|
|
|
388
617
|
.table-header.sortable:hover .sort-icon {
|
|
@@ -390,10 +619,10 @@
|
|
|
390
619
|
}
|
|
391
620
|
|
|
392
621
|
.table-cell {
|
|
393
|
-
padding:
|
|
622
|
+
padding: 0.5rem;
|
|
394
623
|
text-align: left;
|
|
395
|
-
color: var(--
|
|
396
|
-
border-bottom: 1px solid var(--
|
|
624
|
+
color: var(--text-color);
|
|
625
|
+
border-bottom: 1px solid var(--border-color);
|
|
397
626
|
}
|
|
398
627
|
|
|
399
628
|
.table-cell.center {
|
|
@@ -407,7 +636,7 @@
|
|
|
407
636
|
.checkbox-cell {
|
|
408
637
|
width: 40px;
|
|
409
638
|
text-align: center;
|
|
410
|
-
padding:
|
|
639
|
+
padding: 0.25rem;
|
|
411
640
|
}
|
|
412
641
|
|
|
413
642
|
.checkbox-cell :global(.checkbox-container) {
|
|
@@ -419,23 +648,73 @@
|
|
|
419
648
|
margin: 2px;
|
|
420
649
|
}
|
|
421
650
|
|
|
422
|
-
.
|
|
423
|
-
|
|
651
|
+
.expand-cell {
|
|
652
|
+
width: 40px;
|
|
653
|
+
text-align: center;
|
|
654
|
+
padding: 0.25rem;
|
|
424
655
|
}
|
|
425
656
|
|
|
426
|
-
.
|
|
427
|
-
|
|
428
|
-
|
|
657
|
+
.expand-toggle {
|
|
658
|
+
display: inline-flex;
|
|
659
|
+
align-items: center;
|
|
660
|
+
justify-content: center;
|
|
661
|
+
width: 24px;
|
|
662
|
+
height: 24px;
|
|
663
|
+
padding: 0;
|
|
664
|
+
border: none;
|
|
665
|
+
background: transparent;
|
|
666
|
+
color: var(--text-color);
|
|
667
|
+
cursor: pointer;
|
|
668
|
+
border-radius: 0.25rem;
|
|
669
|
+
transition:
|
|
670
|
+
transform 0.15s ease,
|
|
671
|
+
background-color 0.2s;
|
|
429
672
|
}
|
|
430
673
|
|
|
431
|
-
.
|
|
432
|
-
|
|
433
|
-
|
|
674
|
+
.expand-toggle:hover {
|
|
675
|
+
background-color: var(--hover-bg);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
.expand-toggle.expanded {
|
|
679
|
+
transform: rotate(90deg);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/* An expanded row and its detail row read as one unit: the parent's border
|
|
683
|
+
* moves to the bottom of the detail row. */
|
|
684
|
+
tbody tr.expanded td {
|
|
685
|
+
border-bottom: none;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
.detail-cell {
|
|
689
|
+
padding: 0.5rem;
|
|
690
|
+
color: var(--text-color);
|
|
691
|
+
border-bottom: 1px solid var(--border-color);
|
|
434
692
|
}
|
|
435
693
|
|
|
694
|
+
.pui-table.striped tbody tr.row-even {
|
|
695
|
+
background-color: var(--stripe-bg);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
.pui-table.hover tbody tr:not(.detail-row):hover {
|
|
699
|
+
background-color: var(--hover-bg);
|
|
700
|
+
transition: background-color 0.2s;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
.pui-table tbody tr.selected,
|
|
704
|
+
.pui-table.striped tbody tr.selected.row-even {
|
|
705
|
+
background-color: rgba(var(--ui-tertiary-rgbc), 0.15);
|
|
706
|
+
}
|
|
436
707
|
.pui-table tbody tr.selected:hover,
|
|
437
708
|
.pui-table.hover tbody tr.selected:hover {
|
|
438
|
-
background-color: var(--
|
|
709
|
+
background-color: rgba(var(--ui-tertiary-rgbc), 0.22);
|
|
710
|
+
}
|
|
711
|
+
:global(.dark) .pui-table tbody tr.selected,
|
|
712
|
+
:global(.dark) .pui-table.striped tbody tr.selected.row-even {
|
|
713
|
+
background-color: rgba(var(--ui-tertiary-rgbc), 0.12);
|
|
714
|
+
}
|
|
715
|
+
:global(.dark) .pui-table tbody tr.selected:hover,
|
|
716
|
+
:global(.dark) .pui-table.hover tbody tr.selected:hover {
|
|
717
|
+
background-color: rgba(var(--ui-tertiary-rgbc), 0.16);
|
|
439
718
|
}
|
|
440
719
|
|
|
441
720
|
.clickable-row {
|
|
@@ -443,8 +722,8 @@
|
|
|
443
722
|
}
|
|
444
723
|
|
|
445
724
|
.clickable-row:hover {
|
|
446
|
-
background-color: var(--
|
|
447
|
-
transition: background-color
|
|
725
|
+
background-color: var(--hover-bg);
|
|
726
|
+
transition: background-color 0.2s;
|
|
448
727
|
}
|
|
449
728
|
|
|
450
729
|
tbody tr:last-child td {
|
|
@@ -453,9 +732,9 @@
|
|
|
453
732
|
|
|
454
733
|
.empty-cell,
|
|
455
734
|
.loading-cell {
|
|
456
|
-
padding:
|
|
735
|
+
padding: 2rem;
|
|
457
736
|
text-align: center;
|
|
458
|
-
color: var(--
|
|
737
|
+
color: var(--text-muted);
|
|
459
738
|
border-bottom: none;
|
|
460
739
|
}
|
|
461
740
|
|
|
@@ -464,21 +743,45 @@
|
|
|
464
743
|
font-style: italic;
|
|
465
744
|
}
|
|
466
745
|
|
|
467
|
-
|
|
746
|
+
.table-pagination {
|
|
747
|
+
display: flex;
|
|
748
|
+
align-items: center;
|
|
749
|
+
justify-content: space-between;
|
|
750
|
+
gap: 1rem;
|
|
751
|
+
flex-wrap: wrap;
|
|
752
|
+
margin-top: 1rem;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
.pagination-info {
|
|
756
|
+
color: var(--text-muted);
|
|
757
|
+
font-size: 0.875rem;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
:global(:root) {
|
|
761
|
+
--stripe-bg: rgba(0, 0, 0, 0.02);
|
|
762
|
+
--hover-bg: rgba(0, 0, 0, 0.04);
|
|
763
|
+
--text-muted: #6b7280;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
:global(.dark) {
|
|
767
|
+
--stripe-bg: rgba(255, 255, 255, 0.02);
|
|
768
|
+
--hover-bg: rgba(255, 255, 255, 0.04);
|
|
769
|
+
--text-muted: #9ca3af;
|
|
770
|
+
}
|
|
771
|
+
|
|
468
772
|
:global(.pui-table .sort-icon svg) {
|
|
469
773
|
width: 14px;
|
|
470
774
|
height: 14px;
|
|
471
775
|
}
|
|
472
776
|
|
|
473
|
-
/* Responsive adjustments */
|
|
474
777
|
@media (max-width: 640px) {
|
|
475
778
|
.table-header,
|
|
476
779
|
.table-cell {
|
|
477
|
-
padding:
|
|
780
|
+
padding: 0.5rem 0.75rem;
|
|
478
781
|
}
|
|
479
782
|
|
|
480
783
|
.pui-table {
|
|
481
|
-
font-size:
|
|
784
|
+
font-size: 0.75rem;
|
|
482
785
|
}
|
|
483
786
|
}
|
|
484
787
|
</style>
|