@galyan/ui 0.0.1 → 0.0.2

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 (90) hide show
  1. package/package.json +53 -22
  2. package/.turbo/turbo-build.log +0 -20
  3. package/eslint.config.mjs +0 -4
  4. package/src/accordion/Accordion.tsx +0 -88
  5. package/src/accordion/accordion.css +0 -78
  6. package/src/accordion/index.ts +0 -2
  7. package/src/animatednumber/AnimatedNumber.tsx +0 -71
  8. package/src/animatednumber/index.ts +0 -2
  9. package/src/banner/Banner.tsx +0 -84
  10. package/src/banner/banner.css +0 -56
  11. package/src/banner/index.ts +0 -2
  12. package/src/breadcrumb/Breadcrumb.tsx +0 -94
  13. package/src/breadcrumb/breadcrumb.css +0 -58
  14. package/src/breadcrumb/index.ts +0 -2
  15. package/src/button/Button.tsx +0 -98
  16. package/src/button/button.css +0 -190
  17. package/src/button/index.ts +0 -2
  18. package/src/button.tsx +0 -20
  19. package/src/calendar/Calendar.tsx +0 -190
  20. package/src/calendar/calendar.css +0 -142
  21. package/src/calendar/index.ts +0 -2
  22. package/src/card/Card.tsx +0 -88
  23. package/src/card/card.css +0 -115
  24. package/src/card/index.ts +0 -2
  25. package/src/card.tsx +0 -27
  26. package/src/chart/Chart.tsx +0 -186
  27. package/src/chart/index.ts +0 -2
  28. package/src/checkbox/Checkbox.tsx +0 -101
  29. package/src/checkbox/checkbox.css +0 -76
  30. package/src/checkbox/index.ts +0 -2
  31. package/src/chips/Chips.tsx +0 -146
  32. package/src/chips/chips.css +0 -90
  33. package/src/chips/index.ts +0 -2
  34. package/src/code.tsx +0 -11
  35. package/src/datepicker/DatePicker.tsx +0 -104
  36. package/src/datepicker/datepicker.css +0 -22
  37. package/src/datepicker/index.ts +0 -2
  38. package/src/dragdrop/DragDrop.tsx +0 -168
  39. package/src/dragdrop/dragdrop.css +0 -122
  40. package/src/dragdrop/index.ts +0 -2
  41. package/src/dropdown/Dropdown.tsx +0 -176
  42. package/src/dropdown/dropdown.css +0 -118
  43. package/src/dropdown/index.ts +0 -2
  44. package/src/fileupload/FileUpload.tsx +0 -144
  45. package/src/fileupload/fileupload.css +0 -118
  46. package/src/fileupload/index.ts +0 -2
  47. package/src/index.ts +0 -28
  48. package/src/input/Input.tsx +0 -121
  49. package/src/input/index.ts +0 -2
  50. package/src/input/input.css +0 -120
  51. package/src/menu/Menu.tsx +0 -118
  52. package/src/menu/index.ts +0 -2
  53. package/src/menu/menu.css +0 -117
  54. package/src/modal/Modal.tsx +0 -103
  55. package/src/modal/index.ts +0 -2
  56. package/src/modal/modal.css +0 -79
  57. package/src/progressbar/ProgressBar.tsx +0 -68
  58. package/src/progressbar/index.ts +0 -2
  59. package/src/progressbar/progressbar.css +0 -73
  60. package/src/radiogroup/RadioGroup.tsx +0 -73
  61. package/src/radiogroup/index.ts +0 -2
  62. package/src/radiogroup/radiogroup.css +0 -80
  63. package/src/skeleton/Skeleton.tsx +0 -61
  64. package/src/skeleton/index.ts +0 -2
  65. package/src/skeleton/skeleton.css +0 -46
  66. package/src/spinner/Spinner.tsx +0 -29
  67. package/src/spinner/index.ts +0 -2
  68. package/src/spinner/spinner.css +0 -39
  69. package/src/stepper/Stepper.tsx +0 -127
  70. package/src/stepper/index.ts +0 -2
  71. package/src/stepper/stepper.css +0 -141
  72. package/src/tab/Tabs.tsx +0 -71
  73. package/src/tab/index.ts +0 -2
  74. package/src/tab/tab.css +0 -92
  75. package/src/table/Table.tsx +0 -205
  76. package/src/table/index.ts +0 -2
  77. package/src/table/table.css +0 -119
  78. package/src/textarea/Textarea.tsx +0 -102
  79. package/src/textarea/index.ts +0 -2
  80. package/src/textarea/textarea.css +0 -85
  81. package/src/toaster/Toaster.tsx +0 -108
  82. package/src/toaster/index.ts +0 -2
  83. package/src/toaster/toaster.css +0 -113
  84. package/src/toggle/Toggle.tsx +0 -88
  85. package/src/toggle/index.ts +0 -2
  86. package/src/toggle/toggle.css +0 -63
  87. package/src/typography/Typography.tsx +0 -58
  88. package/src/typography/index.ts +0 -2
  89. package/src/typography/typography.css +0 -102
  90. package/tsconfig.json +0 -13
@@ -1,141 +0,0 @@
1
- /* ── Stepper ──────────────────────────────────────────────────────────────── */
2
- .gy-stepper {
3
- display: flex;
4
- align-items: flex-start;
5
- width: 100%;
6
- }
7
-
8
- .gy-stepper--vertical {
9
- flex-direction: column;
10
- }
11
-
12
- .gy-stepper-step {
13
- display: flex;
14
- align-items: center;
15
- flex: 1;
16
- position: relative;
17
- }
18
-
19
- .gy-stepper--vertical .gy-stepper-step {
20
- flex-direction: column;
21
- align-items: flex-start;
22
- flex: none;
23
- width: 100%;
24
- }
25
-
26
- /* Connector line */
27
- .gy-stepper-connector {
28
- flex: 1;
29
- height: 2px;
30
- background: var(--gy-border);
31
- margin: 0 var(--gy-spacing-2);
32
- transition: background-color var(--gy-duration-slow);
33
- }
34
-
35
- .gy-stepper-connector--completed { background: var(--gy-primary); }
36
-
37
- .gy-stepper--vertical .gy-stepper-connector {
38
- width: 2px;
39
- height: 2.5rem;
40
- flex: none;
41
- margin: var(--gy-spacing-1) 0;
42
- margin-left: 19px;
43
- }
44
-
45
- /* Step indicator */
46
- .gy-stepper-indicator {
47
- display: flex;
48
- align-items: center;
49
- justify-content: center;
50
- width: 2.25rem;
51
- height: 2.25rem;
52
- border-radius: 50%;
53
- border: 2px solid var(--gy-border-strong);
54
- background: var(--gy-surface);
55
- font-size: var(--gy-font-size-sm);
56
- font-weight: var(--gy-font-weight-semibold);
57
- color: var(--gy-text-muted);
58
- flex-shrink: 0;
59
- transition:
60
- background-color var(--gy-duration-normal),
61
- border-color var(--gy-duration-normal),
62
- color var(--gy-duration-normal);
63
- cursor: default;
64
- position: relative;
65
- z-index: 1;
66
- }
67
-
68
- .gy-stepper-indicator--active {
69
- border-color: var(--gy-primary);
70
- color: var(--gy-primary);
71
- background: var(--gy-primary-subtle);
72
- box-shadow: 0 0 0 4px var(--gy-focus-ring);
73
- }
74
-
75
- .gy-stepper-indicator--completed {
76
- border-color: var(--gy-primary);
77
- background: var(--gy-primary);
78
- color: var(--gy-primary-fg);
79
- }
80
-
81
- .gy-stepper-indicator--error {
82
- border-color: var(--gy-danger);
83
- background: var(--gy-danger);
84
- color: white;
85
- }
86
-
87
- .gy-stepper-indicator--clickable {
88
- cursor: pointer;
89
- }
90
-
91
- .gy-stepper-indicator--clickable:hover {
92
- border-color: var(--gy-primary);
93
- color: var(--gy-primary);
94
- }
95
-
96
- /* Step content */
97
- .gy-stepper-item {
98
- display: flex;
99
- flex-direction: column;
100
- align-items: center;
101
- text-align: center;
102
- }
103
-
104
- .gy-stepper--vertical .gy-stepper-item {
105
- flex-direction: row;
106
- align-items: center;
107
- gap: var(--gy-spacing-3);
108
- text-align: left;
109
- }
110
-
111
- .gy-stepper-label {
112
- font-size: var(--gy-font-size-xs);
113
- font-weight: var(--gy-font-weight-semibold);
114
- color: var(--gy-text-muted);
115
- margin-top: var(--gy-spacing-2);
116
- white-space: nowrap;
117
- }
118
-
119
- .gy-stepper--vertical .gy-stepper-label { margin-top: 0; }
120
-
121
- .gy-stepper-label--active { color: var(--gy-primary); }
122
- .gy-stepper-label--completed { color: var(--gy-text); }
123
-
124
- .gy-stepper-description {
125
- font-size: var(--gy-font-size-xs);
126
- color: var(--gy-text-subtle);
127
- margin-top: 2px;
128
- }
129
-
130
- /* Panel */
131
- .gy-stepper-panel {
132
- margin-top: var(--gy-spacing-6);
133
- animation: gy-fade-in var(--gy-duration-normal) var(--gy-ease-out);
134
- }
135
-
136
- .gy-stepper-actions {
137
- display: flex;
138
- gap: var(--gy-spacing-3);
139
- margin-top: var(--gy-spacing-4);
140
- flex-wrap: wrap;
141
- }
package/src/tab/Tabs.tsx DELETED
@@ -1,71 +0,0 @@
1
- 'use client';
2
-
3
- import React, { useState } from 'react';
4
- import './tab.css';
5
-
6
- export interface TabItem {
7
- id: string;
8
- label: React.ReactNode;
9
- content: React.ReactNode;
10
- disabled?: boolean;
11
- badge?: string | number;
12
- icon?: React.ReactNode;
13
- }
14
-
15
- export interface TabsProps {
16
- items: TabItem[];
17
- defaultTab?: string;
18
- activeTab?: string;
19
- onChange?: (id: string) => void;
20
- orientation?: 'horizontal' | 'vertical';
21
- className?: string;
22
- }
23
-
24
- export function Tabs({ items, defaultTab, activeTab, onChange, orientation = 'horizontal', className = '' }: TabsProps) {
25
- const [internalActive, setInternalActive] = useState<string>(defaultTab ?? items[0]?.id ?? '');
26
- const current = activeTab ?? internalActive;
27
-
28
- const handleSelect = (id: string) => {
29
- setInternalActive(id);
30
- onChange?.(id);
31
- };
32
-
33
- const activeItem = items.find((i) => i.id === current);
34
-
35
- return (
36
- <div className={`gy-tabs ${orientation === 'vertical' ? 'gy-tabs--vertical' : ''} ${className}`}>
37
- <div className="gy-tabs-list" role="tablist" aria-orientation={orientation}>
38
- {items.map((item) => (
39
- <button
40
- key={item.id}
41
- role="tab"
42
- id={`gy-tab-${item.id}`}
43
- aria-controls={`gy-panel-${item.id}`}
44
- aria-selected={current === item.id}
45
- disabled={item.disabled}
46
- className={`gy-tabs-trigger ${current === item.id ? 'gy-tabs-trigger--active' : ''}`}
47
- onClick={() => !item.disabled && handleSelect(item.id)}
48
- >
49
- {item.icon && <span aria-hidden="true">{item.icon}</span>}
50
- {item.label}
51
- {item.badge !== undefined && (
52
- <span className="gy-tabs-trigger-badge">{item.badge}</span>
53
- )}
54
- </button>
55
- ))}
56
- </div>
57
-
58
- {activeItem && (
59
- <div
60
- key={current}
61
- id={`gy-panel-${current}`}
62
- role="tabpanel"
63
- aria-labelledby={`gy-tab-${current}`}
64
- className="gy-tabs-panel"
65
- >
66
- {activeItem.content}
67
- </div>
68
- )}
69
- </div>
70
- );
71
- }
package/src/tab/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export { Tabs } from './Tabs';
2
- export type { TabsProps, TabItem } from './Tabs';
package/src/tab/tab.css DELETED
@@ -1,92 +0,0 @@
1
- /* ── Tabs ─────────────────────────────────────────────────────────────────── */
2
- .gy-tabs {
3
- display: flex;
4
- flex-direction: column;
5
- }
6
-
7
- .gy-tabs--vertical {
8
- flex-direction: row;
9
- gap: var(--gy-spacing-4);
10
- }
11
-
12
- .gy-tabs-list {
13
- position: relative;
14
- display: flex;
15
- align-items: center;
16
- border-bottom: 2px solid var(--gy-border);
17
- overflow-x: auto;
18
- scrollbar-width: none;
19
- }
20
-
21
- .gy-tabs-list::-webkit-scrollbar { display: none; }
22
-
23
- .gy-tabs--vertical .gy-tabs-list {
24
- flex-direction: column;
25
- border-bottom: none;
26
- border-right: 2px solid var(--gy-border);
27
- min-width: 160px;
28
- align-items: stretch;
29
- }
30
-
31
- .gy-tabs-trigger {
32
- display: inline-flex;
33
- align-items: center;
34
- gap: var(--gy-spacing-2);
35
- padding: var(--gy-spacing-2-5) var(--gy-spacing-4);
36
- font-size: var(--gy-font-size-sm);
37
- font-weight: var(--gy-font-weight-medium);
38
- color: var(--gy-text-muted);
39
- white-space: nowrap;
40
- cursor: pointer;
41
- background: none;
42
- border: none;
43
- position: relative;
44
- transition: color var(--gy-duration-fast);
45
- border-bottom: 2px solid transparent;
46
- margin-bottom: -2px;
47
- }
48
-
49
- .gy-tabs--vertical .gy-tabs-trigger {
50
- border-bottom: none;
51
- border-right: 2px solid transparent;
52
- margin-bottom: 0;
53
- margin-right: -2px;
54
- border-radius: var(--gy-radius-md) 0 0 var(--gy-radius-md);
55
- }
56
-
57
- .gy-tabs-trigger:hover { color: var(--gy-text); }
58
- .gy-tabs-trigger:focus-visible { outline: none; color: var(--gy-primary); }
59
-
60
- .gy-tabs-trigger--active {
61
- color: var(--gy-primary) !important;
62
- border-color: var(--gy-primary);
63
- }
64
-
65
- .gy-tabs-trigger:disabled {
66
- opacity: 0.4;
67
- cursor: not-allowed;
68
- }
69
-
70
- .gy-tabs-trigger-badge {
71
- display: inline-flex;
72
- align-items: center;
73
- justify-content: center;
74
- min-width: 18px;
75
- height: 18px;
76
- padding: 0 5px;
77
- font-size: 0.65rem;
78
- font-weight: var(--gy-font-weight-semibold);
79
- background: var(--gy-primary-muted);
80
- color: var(--gy-primary-hover);
81
- border-radius: var(--gy-radius-full);
82
- }
83
-
84
- .gy-tabs-panel {
85
- padding: var(--gy-spacing-4) 0;
86
- animation: gy-fade-in var(--gy-duration-normal) var(--gy-ease-out);
87
- }
88
-
89
- .gy-tabs--vertical .gy-tabs-panel {
90
- flex: 1;
91
- padding: 0 var(--gy-spacing-4);
92
- }
@@ -1,205 +0,0 @@
1
- 'use client';
2
-
3
- import React, { useMemo, useState } from 'react';
4
- import { Checkbox } from '../checkbox/Checkbox';
5
- import './table.css';
6
-
7
- export type SortDirection = 'asc' | 'desc';
8
-
9
- export interface Column<T> {
10
- key: string;
11
- header: React.ReactNode;
12
- accessor: (row: T) => React.ReactNode;
13
- sortable?: boolean;
14
- width?: string;
15
- align?: 'left' | 'center' | 'right';
16
- }
17
-
18
- export interface TableProps<T> {
19
- columns: Column<T>[];
20
- data: T[];
21
- rowKey: (row: T) => string;
22
- selectable?: boolean;
23
- selectedRows?: string[];
24
- onSelectionChange?: (keys: string[]) => void;
25
- pageSize?: number;
26
- emptyMessage?: React.ReactNode;
27
- className?: string;
28
- stickyHeader?: boolean;
29
- }
30
-
31
- function SortIcon({ dir }: { dir?: SortDirection }) {
32
- return (
33
- <svg width="12" height="12" viewBox="0 0 12 12" fill="currentColor" className={`gy-table-sort-icon ${dir ? 'gy-table-sort-icon--active' : ''}`}>
34
- {dir === 'asc' ? (
35
- <path d="M6 2L10 8H2L6 2z" />
36
- ) : dir === 'desc' ? (
37
- <path d="M6 10L2 4H10L6 10z" />
38
- ) : (
39
- <>
40
- <path d="M6 1L9 5H3L6 1z" opacity=".5" />
41
- <path d="M6 11L3 7H9L6 11z" opacity=".5" />
42
- </>
43
- )}
44
- </svg>
45
- );
46
- }
47
-
48
- export function Table<T>({
49
- columns,
50
- data,
51
- rowKey,
52
- selectable = false,
53
- selectedRows = [],
54
- onSelectionChange,
55
- pageSize = 10,
56
- emptyMessage = 'No data available',
57
- className = '',
58
- stickyHeader = false,
59
- }: TableProps<T>) {
60
- const [sortKey, setSortKey] = useState<string | null>(null);
61
- const [sortDir, setSortDir] = useState<SortDirection>('asc');
62
- const [page, setPage] = useState(1);
63
-
64
- const sortedData = useMemo(() => {
65
- if (!sortKey) return data;
66
- const col = columns.find((c) => c.key === sortKey);
67
- if (!col) return data;
68
- return [...data].sort((a, b) => {
69
- const av = String(col.accessor(a) ?? '');
70
- const bv = String(col.accessor(b) ?? '');
71
- const cmp = av.localeCompare(bv, undefined, { numeric: true });
72
- return sortDir === 'asc' ? cmp : -cmp;
73
- });
74
- }, [data, sortKey, sortDir, columns]);
75
-
76
- const totalPages = Math.max(1, Math.ceil(sortedData.length / pageSize));
77
- const paged = sortedData.slice((page - 1) * pageSize, page * pageSize);
78
-
79
- const allSelected = paged.length > 0 && paged.every((r) => selectedRows.includes(rowKey(r)));
80
- const someSelected = paged.some((r) => selectedRows.includes(rowKey(r)));
81
-
82
- const toggleSort = (key: string) => {
83
- if (sortKey === key) {
84
- setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'));
85
- } else {
86
- setSortKey(key);
87
- setSortDir('asc');
88
- }
89
- setPage(1);
90
- };
91
-
92
- const toggleRow = (key: string) => {
93
- const next = selectedRows.includes(key)
94
- ? selectedRows.filter((k) => k !== key)
95
- : [...selectedRows, key];
96
- onSelectionChange?.(next);
97
- };
98
-
99
- const toggleAll = () => {
100
- const pageKeys = paged.map(rowKey);
101
- if (allSelected) {
102
- onSelectionChange?.(selectedRows.filter((k) => !pageKeys.includes(k)));
103
- } else {
104
- const combined = [...new Set([...selectedRows, ...pageKeys])];
105
- onSelectionChange?.(combined);
106
- }
107
- };
108
-
109
- const pageNums = Array.from({ length: totalPages }, (_, i) => i + 1);
110
- const visiblePages = pageNums.filter(
111
- (p) => p === 1 || p === totalPages || Math.abs(p - page) <= 1
112
- );
113
-
114
- return (
115
- <div className={`gy-table-wrapper ${className}`}>
116
- <table className="gy-table" aria-label="Data table">
117
- <thead className="gy-table-header">
118
- <tr>
119
- {selectable && (
120
- <th className="gy-table-th gy-table-th--checkbox">
121
- <Checkbox
122
- checked={allSelected}
123
- indeterminate={!allSelected && someSelected}
124
- onChange={toggleAll}
125
- size="sm"
126
- />
127
- </th>
128
- )}
129
- {columns.map((col) => (
130
- <th
131
- key={col.key}
132
- className={`gy-table-th ${col.sortable ? 'gy-table-th--sortable' : ''}`}
133
- style={{ width: col.width, textAlign: col.align }}
134
- onClick={col.sortable ? () => toggleSort(col.key) : undefined}
135
- aria-sort={sortKey === col.key ? (sortDir === 'asc' ? 'ascending' : 'descending') : undefined}
136
- >
137
- <span className="gy-table-th-inner">
138
- {col.header}
139
- {col.sortable && <SortIcon dir={sortKey === col.key ? sortDir : undefined} />}
140
- </span>
141
- </th>
142
- ))}
143
- </tr>
144
- </thead>
145
- <tbody>
146
- {paged.length === 0 ? (
147
- <tr>
148
- <td colSpan={columns.length + (selectable ? 1 : 0)} className="gy-table-empty">
149
- {emptyMessage}
150
- </td>
151
- </tr>
152
- ) : (
153
- paged.map((row) => {
154
- const key = rowKey(row);
155
- const isSelected = selectedRows.includes(key);
156
- return (
157
- <tr
158
- key={key}
159
- className={`gy-table-tr ${isSelected ? 'gy-table-tr--selected' : ''}`}
160
- aria-selected={selectable ? isSelected : undefined}
161
- >
162
- {selectable && (
163
- <td className="gy-table-td gy-table-td--checkbox">
164
- <Checkbox checked={isSelected} onChange={() => toggleRow(key)} size="sm" />
165
- </td>
166
- )}
167
- {columns.map((col) => (
168
- <td key={col.key} className="gy-table-td" style={{ textAlign: col.align }}>
169
- {col.accessor(row)}
170
- </td>
171
- ))}
172
- </tr>
173
- );
174
- })
175
- )}
176
- </tbody>
177
- </table>
178
-
179
- {totalPages > 1 && (
180
- <div className="gy-table-pagination">
181
- <span className="gy-table-pagination-info">
182
- Showing {(page - 1) * pageSize + 1}–{Math.min(page * pageSize, sortedData.length)} of {sortedData.length}
183
- </span>
184
- <div className="gy-table-pagination-controls">
185
- <button className="gy-table-pagination-btn" onClick={() => setPage((p) => p - 1)} disabled={page === 1} aria-label="Previous page">‹</button>
186
- {visiblePages.map((p, i, arr) => (
187
- <React.Fragment key={p}>
188
- {i > 0 && arr[i - 1] !== p - 1 && <span style={{ padding: '0 4px', color: 'var(--gy-text-subtle)' }}>…</span>}
189
- <button
190
- className={`gy-table-pagination-btn ${page === p ? 'gy-table-pagination-btn--active' : ''}`}
191
- onClick={() => setPage(p)}
192
- aria-label={`Page ${p}`}
193
- aria-current={page === p ? 'page' : undefined}
194
- >
195
- {p}
196
- </button>
197
- </React.Fragment>
198
- ))}
199
- <button className="gy-table-pagination-btn" onClick={() => setPage((p) => p + 1)} disabled={page === totalPages} aria-label="Next page">›</button>
200
- </div>
201
- </div>
202
- )}
203
- </div>
204
- );
205
- }
@@ -1,2 +0,0 @@
1
- export { Table } from './Table';
2
- export type { TableProps, Column, SortDirection } from './Table';
@@ -1,119 +0,0 @@
1
- /* ── Table ───────────────────────────────────────────────────────────────── */
2
- .gy-table-wrapper {
3
- width: 100%;
4
- overflow-x: auto;
5
- border-radius: var(--gy-radius-xl);
6
- border: 1px solid var(--gy-border);
7
- }
8
-
9
- .gy-table {
10
- width: 100%;
11
- border-collapse: collapse;
12
- font-size: var(--gy-font-size-sm);
13
- }
14
-
15
- .gy-table-header { background: var(--gy-background-subtle); }
16
-
17
- .gy-table-th {
18
- padding: var(--gy-spacing-3) var(--gy-spacing-4);
19
- text-align: left;
20
- font-weight: var(--gy-font-weight-semibold);
21
- color: var(--gy-text-muted);
22
- white-space: nowrap;
23
- letter-spacing: var(--gy-letter-spacing-wide);
24
- font-size: var(--gy-font-size-xs);
25
- text-transform: uppercase;
26
- border-bottom: 1px solid var(--gy-border);
27
- user-select: none;
28
- position: relative;
29
- }
30
-
31
- .gy-table-th--sortable { cursor: pointer; }
32
- .gy-table-th--sortable:hover { color: var(--gy-text); background: var(--gy-background-muted); }
33
-
34
- .gy-table-th-inner {
35
- display: inline-flex;
36
- align-items: center;
37
- gap: var(--gy-spacing-1-5);
38
- }
39
-
40
- .gy-table-sort-icon { color: var(--gy-text-subtle); }
41
- .gy-table-sort-icon--active { color: var(--gy-primary); }
42
-
43
- .gy-table-td {
44
- padding: var(--gy-spacing-3) var(--gy-spacing-4);
45
- color: var(--gy-text);
46
- border-bottom: 1px solid var(--gy-border);
47
- vertical-align: middle;
48
- }
49
-
50
- .gy-table-tr:last-child .gy-table-td { border-bottom: none; }
51
-
52
- .gy-table-tr { transition: background-color var(--gy-duration-fast); }
53
- .gy-table-tr:hover { background: var(--gy-background-subtle); }
54
- .gy-table-tr--selected { background: var(--gy-primary-subtle); }
55
-
56
- /* Selection checkbox column */
57
- .gy-table-th--checkbox,
58
- .gy-table-td--checkbox {
59
- width: 40px;
60
- padding-right: var(--gy-spacing-2);
61
- }
62
-
63
- /* Empty state */
64
- .gy-table-empty {
65
- text-align: center;
66
- padding: var(--gy-spacing-12) var(--gy-spacing-4);
67
- color: var(--gy-text-subtle);
68
- }
69
-
70
- /* Pagination */
71
- .gy-table-pagination {
72
- display: flex;
73
- align-items: center;
74
- justify-content: space-between;
75
- padding: var(--gy-spacing-3) var(--gy-spacing-4);
76
- border-top: 1px solid var(--gy-border);
77
- background: var(--gy-background-subtle);
78
- font-size: var(--gy-font-size-sm);
79
- }
80
-
81
- .gy-table-pagination-info { color: var(--gy-text-muted); }
82
-
83
- .gy-table-pagination-controls {
84
- display: flex;
85
- align-items: center;
86
- gap: var(--gy-spacing-1);
87
- }
88
-
89
- .gy-table-pagination-btn {
90
- display: flex;
91
- align-items: center;
92
- justify-content: center;
93
- width: 2rem;
94
- height: 2rem;
95
- border-radius: var(--gy-radius-md);
96
- font-size: var(--gy-font-size-sm);
97
- font-weight: var(--gy-font-weight-medium);
98
- color: var(--gy-text-muted);
99
- border: 1px solid transparent;
100
- cursor: pointer;
101
- background: none;
102
- transition: background var(--gy-duration-fast), color var(--gy-duration-fast);
103
- }
104
-
105
- .gy-table-pagination-btn:hover:not(:disabled) {
106
- background: var(--gy-background-muted);
107
- color: var(--gy-text);
108
- }
109
-
110
- .gy-table-pagination-btn--active {
111
- background: var(--gy-primary);
112
- color: var(--gy-primary-fg);
113
- border-color: var(--gy-primary);
114
- }
115
-
116
- .gy-table-pagination-btn:disabled {
117
- opacity: 0.4;
118
- cursor: not-allowed;
119
- }