aplance-ui 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -0
  3. package/dist/api.d.ts +175 -0
  4. package/dist/api.js +1954 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/frameworks/astro/astro.config.snippet.md +23 -0
  7. package/dist/frameworks/astro/postcss.config.mjs.template +20 -0
  8. package/dist/frameworks/astro/vite-inline.snippet.md +22 -0
  9. package/dist/frameworks/electron-vite/vite.config.snippet.md +44 -0
  10. package/dist/frameworks/next/layout-import.snippet.md +19 -0
  11. package/dist/frameworks/next/next.config.snippet.md +15 -0
  12. package/dist/frameworks/next/postcss.config.js.template +16 -0
  13. package/dist/frameworks/tanstack-start/postcss.config.ts.template +17 -0
  14. package/dist/frameworks/tanstack-start/vite-inline.snippet.md +22 -0
  15. package/dist/frameworks/vite-react/postcss.config.ts.template +16 -0
  16. package/dist/frameworks/vite-react/vite-inline.snippet.md +20 -0
  17. package/dist/frameworks/vite-react/vite.config.ts.template +48 -0
  18. package/dist/index.js +2047 -0
  19. package/dist/index.js.map +1 -0
  20. package/package.json +63 -0
  21. package/registry/components/primitives/icon/icon.module.css +63 -0
  22. package/registry/components/primitives/icon/icon.tsx +53 -0
  23. package/registry/components/primitives/modal/modal-context.ts +19 -0
  24. package/registry/components/primitives/modal/modal.module.css +415 -0
  25. package/registry/components/primitives/modal/modal.tsx +550 -0
  26. package/registry/components/primitives/popover/popover-context.ts +28 -0
  27. package/registry/components/primitives/popover/popover.module.css +28 -0
  28. package/registry/components/primitives/popover/popover.tsx +465 -0
  29. package/registry/components/ui/accordion/accordion.module.css +208 -0
  30. package/registry/components/ui/accordion/accordion.tsx +327 -0
  31. package/registry/components/ui/avatar/avatar.module.css +32 -0
  32. package/registry/components/ui/avatar/avatar.tsx +37 -0
  33. package/registry/components/ui/badge/badge.module.css +103 -0
  34. package/registry/components/ui/badge/badge.tsx +29 -0
  35. package/registry/components/ui/button/button.module.css +216 -0
  36. package/registry/components/ui/button/button.tsx +133 -0
  37. package/registry/components/ui/chart/chart.module.css +168 -0
  38. package/registry/components/ui/chart/chart.tsx +1293 -0
  39. package/registry/components/ui/chart/types.ts +210 -0
  40. package/registry/components/ui/chart/utils.ts +59 -0
  41. package/registry/components/ui/copy-button/copy-button.module.css +21 -0
  42. package/registry/components/ui/copy-button/copy-button.tsx +123 -0
  43. package/registry/components/ui/countdown/countdown.module.css +5 -0
  44. package/registry/components/ui/countdown/countdown.tsx +152 -0
  45. package/registry/components/ui/data-table/checkbox-column.tsx +59 -0
  46. package/registry/components/ui/data-table/data-table.module.css +594 -0
  47. package/registry/components/ui/data-table/data-table.tsx +1109 -0
  48. package/registry/components/ui/data-table/filter-bar.tsx +33 -0
  49. package/registry/components/ui/data-table/pagination-bar.tsx +125 -0
  50. package/registry/components/ui/data-table/types.ts +594 -0
  51. package/registry/components/ui/data-table/useDataTable.tsx +573 -0
  52. package/registry/components/ui/data-table/utils.ts +445 -0
  53. package/registry/components/ui/empty-state/empty-state.module.css +26 -0
  54. package/registry/components/ui/empty-state/empty-state.tsx +32 -0
  55. package/registry/components/ui/input-fields/color-picker/color-palette.module.css +102 -0
  56. package/registry/components/ui/input-fields/color-picker/color-palette.tsx +92 -0
  57. package/registry/components/ui/input-fields/color-picker/color-picker.module.css +29 -0
  58. package/registry/components/ui/input-fields/color-picker/color-picker.tsx +168 -0
  59. package/registry/components/ui/input-fields/common/field-message/field-message.module.css +28 -0
  60. package/registry/components/ui/input-fields/common/field-message/field-message.tsx +39 -0
  61. package/registry/components/ui/input-fields/common/input-field-common.module.css +318 -0
  62. package/registry/components/ui/input-fields/common/input-field-native.module.css +267 -0
  63. package/registry/components/ui/input-fields/common/picker-popover-common.module.css +40 -0
  64. package/registry/components/ui/input-fields/common/select-button/select-button.module.css +9 -0
  65. package/registry/components/ui/input-fields/common/select-button/select-button.tsx +171 -0
  66. package/registry/components/ui/input-fields/common/types.ts +38 -0
  67. package/registry/components/ui/input-fields/custom-select/custom-select.module.css +56 -0
  68. package/registry/components/ui/input-fields/custom-select/custom-select.tsx +403 -0
  69. package/registry/components/ui/input-fields/date-picker/calendar.module.css +311 -0
  70. package/registry/components/ui/input-fields/date-picker/calendar.tsx +186 -0
  71. package/registry/components/ui/input-fields/date-picker/date-picker.module.css +57 -0
  72. package/registry/components/ui/input-fields/date-picker/date-picker.tsx +945 -0
  73. package/registry/components/ui/input-fields/date-picker/types.ts +102 -0
  74. package/registry/components/ui/input-fields/date-picker/utils.ts +236 -0
  75. package/registry/components/ui/input-fields/emoji-picker/emoji-palette.module.css +90 -0
  76. package/registry/components/ui/input-fields/emoji-picker/emoji-palette.tsx +168 -0
  77. package/registry/components/ui/input-fields/emoji-picker/emoji-picker.module.css +8 -0
  78. package/registry/components/ui/input-fields/emoji-picker/emoji-picker.tsx +102 -0
  79. package/registry/components/ui/input-fields/emoji-picker/utils.ts +505 -0
  80. package/registry/components/ui/input-fields/field-group/field-group.module.css +86 -0
  81. package/registry/components/ui/input-fields/field-group/field-group.tsx +86 -0
  82. package/registry/components/ui/input-fields/input/input.tsx +319 -0
  83. package/registry/components/ui/input-fields/media-input/kind-icons.tsx +62 -0
  84. package/registry/components/ui/input-fields/media-input/media-input.module.css +294 -0
  85. package/registry/components/ui/input-fields/media-input/media-input.tsx +327 -0
  86. package/registry/components/ui/input-fields/media-input/media-preview.tsx +101 -0
  87. package/registry/components/ui/input-fields/media-input/types.ts +129 -0
  88. package/registry/components/ui/input-fields/media-input/useMediaUpload.tsx +302 -0
  89. package/registry/components/ui/input-fields/media-input/utils.ts +325 -0
  90. package/registry/components/ui/input-fields/otp-input/otp-input.module.css +24 -0
  91. package/registry/components/ui/input-fields/otp-input/otp-input.tsx +291 -0
  92. package/registry/components/ui/input-fields/select/select.tsx +118 -0
  93. package/registry/components/ui/input-fields/switch/switch.module.css +70 -0
  94. package/registry/components/ui/input-fields/switch/switch.tsx +59 -0
  95. package/registry/components/ui/input-fields/textarea/textarea.tsx +133 -0
  96. package/registry/components/ui/input-fields/time-picker/time-picker.module.css +57 -0
  97. package/registry/components/ui/input-fields/time-picker/time-picker.tsx +437 -0
  98. package/registry/components/ui/loader/loader.module.css +156 -0
  99. package/registry/components/ui/loader/loader.tsx +102 -0
  100. package/registry/components/ui/stepper/stepper.module.css +294 -0
  101. package/registry/components/ui/stepper/stepper.tsx +197 -0
  102. package/registry/components/ui/tabs/tabs.module.css +150 -0
  103. package/registry/components/ui/tabs/tabs.tsx +134 -0
  104. package/registry/components/ui/toast/toast.module.css +159 -0
  105. package/registry/components/ui/toast/toast.tsx +104 -0
  106. package/registry/components/ui/tooltip/tooltip.module.css +82 -0
  107. package/registry/components/ui/tooltip/tooltip.tsx +72 -0
  108. package/registry/global.d.ts +4 -0
  109. package/registry/hooks/useFocusOutside.tsx +33 -0
  110. package/registry/hooks/useResizeObserver.tsx +32 -0
  111. package/registry/lib/dom.ts +25 -0
  112. package/registry/lib/string.ts +23 -0
  113. package/registry/registry.json +719 -0
  114. package/registry/styles/app.css +240 -0
  115. package/registry/styles/components.css +78 -0
  116. package/registry/styles/fonts/geist-regular.woff2 +0 -0
  117. package/registry/styles/globals.css +7 -0
  118. package/registry/styles/media.css +25 -0
  119. package/registry/styles/utilities.css +90 -0
  120. package/registry/themes/colors/blue.css +37 -0
  121. package/registry/themes/colors/green.css +37 -0
  122. package/registry/themes/colors/rose.css +37 -0
  123. package/registry/themes/colors/slate.css +37 -0
  124. package/registry/themes/colors/stone.css +37 -0
  125. package/registry/themes/colors/violet.css +37 -0
  126. package/registry/themes/colors/zinc.css +37 -0
  127. package/registry/themes/radius/pill.css +8 -0
  128. package/registry/themes/radius/rounded.css +8 -0
  129. package/registry/themes/radius/sharp.css +8 -0
  130. package/registry/themes/spacing/compact.css +17 -0
  131. package/registry/themes/spacing/spacious.css +17 -0
  132. package/registry/tsconfig.json +25 -0
@@ -0,0 +1,594 @@
1
+ /* ─────────────────────────────────────────────
2
+ Root
3
+ Fills its flex parent. Stacks filter bar (fixed) + content wrap (grows).
4
+ ───────────────────────────────────────────── */
5
+ .root {
6
+ width: 100%;
7
+ flex: 1;
8
+ min-height: 0;
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: var(--spacing-6);
12
+ }
13
+
14
+ /* ─────────────────────────────────────────────
15
+ Filter bar
16
+ CSS grid - always one row, never wraps.
17
+ gridTemplateColumns is set inline from FilterBar.
18
+ ───────────────────────────────────────────── */
19
+ .filter_bar {
20
+ display: grid;
21
+ align-items: center;
22
+ place-items: center;
23
+ gap: var(--spacing-6);
24
+ width: 100%;
25
+ flex-shrink: 0;
26
+
27
+ > * {
28
+ min-width: 0;
29
+ }
30
+ }
31
+
32
+ /* ─────────────────────────────────────────────
33
+ Content wrap
34
+ Grows to fill all space below the filter bar.
35
+ Flex column: table shell (grows) + pagination (pinned to bottom via margin-top:auto).
36
+ ───────────────────────────────────────────── */
37
+ .content_wrap {
38
+ flex: 1;
39
+ min-height: 0;
40
+ display: flex;
41
+ flex-direction: column;
42
+ }
43
+
44
+ /* ─────────────────────────────────────────────
45
+ Table shell
46
+ Grows to fill space above pagination. Header pill + scrollable body.
47
+ ───────────────────────────────────────────── */
48
+ .table_shell {
49
+ flex: 1;
50
+ min-height: 0;
51
+ display: flex;
52
+ flex-direction: column;
53
+ gap: var(--spacing-6);
54
+ padding-bottom: var(--spacing-6);
55
+ }
56
+
57
+ /* no bottom padding when pagination is not shown */
58
+ .table_shell_no_pagination {
59
+ padding-bottom: 0;
60
+ }
61
+
62
+ /* ─────────────────────────────────────────────
63
+ Detached header pill
64
+ Rounded standalone bar. scrollLeft synced to body via JS so pinned
65
+ columns stay perfectly aligned with their body counterparts.
66
+ ───────────────────────────────────────────── */
67
+ .table_header_container {
68
+ position: relative;
69
+ flex-shrink: 0;
70
+ width: 100%;
71
+ }
72
+
73
+ .table_header_wrap {
74
+ width: 100%;
75
+ overflow-x: auto;
76
+ overflow-y: hidden;
77
+ border-radius: var(--radius-md);
78
+ background: var(--color-muted);
79
+ border: var(--border-1) solid var(--color-border);
80
+ scrollbar-width: none;
81
+ }
82
+
83
+ .table_header_wrap::-webkit-scrollbar {
84
+ display: none;
85
+ }
86
+
87
+ .header_padding_mask {
88
+ position: absolute;
89
+ top: 0;
90
+ right: 0;
91
+ bottom: 0;
92
+ width: var(--header-padding-right, 0px);
93
+ background: var(--color-muted);
94
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
95
+ border-top: var(--border-1) solid var(--color-border);
96
+ border-right: var(--border-1) solid var(--color-border);
97
+ border-bottom: var(--border-1) solid var(--color-border);
98
+ pointer-events: none;
99
+ z-index: 10;
100
+ visibility: hidden;
101
+ }
102
+
103
+ .table_header_container[data-has-scroll="true"] .header_padding_mask {
104
+ visibility: visible;
105
+ }
106
+
107
+ /* ─────────────────────────────────────────────
108
+ Scrollable body
109
+ flex:1 + min-height:0 = fills all space, then scrolls.
110
+ ───────────────────────────────────────────── */
111
+ .table_body_wrap {
112
+ flex: 1;
113
+ min-height: 0;
114
+ overflow-x: auto;
115
+ overflow-y: auto;
116
+ border: var(--border-1) solid var(--color-border);
117
+ border-radius: var(--radius-md);
118
+ background: var(--color-background);
119
+ position: relative;
120
+ /* Add this smooth transition */
121
+ transition: opacity 0.2s ease;
122
+ }
123
+
124
+ /* ─────────────────────────────────────────────
125
+ Shared <table> - header wrap + body wrap.
126
+ table-layout:fixed + identical widths = perfect column alignment.
127
+ ───────────────────────────────────────────── */
128
+ .table {
129
+ border-collapse: separate;
130
+ border-spacing: 0;
131
+ table-layout: fixed;
132
+
133
+ thead th {
134
+ position: relative;
135
+ height: var(--spacing-11);
136
+ padding: 0 var(--spacing-6);
137
+ font-size: var(--font-size-xs);
138
+ font-weight: var(--font-weight-semibold);
139
+ color: var(--color-foreground);
140
+ white-space: nowrap;
141
+ /* explicit background so sticky pinned cells mask scrolled content */
142
+ background: var(--color-muted);
143
+ /* visible: header checkbox focus ring not clipped */
144
+ overflow: visible;
145
+ }
146
+
147
+ tbody tr {
148
+ transition: background var(--transition-fast);
149
+
150
+ &:hover td {
151
+ background: var(--color-secondary);
152
+ }
153
+
154
+ &.row_selected td {
155
+ background: var(--color-muted);
156
+ }
157
+
158
+ &.row_group td {
159
+ background: var(--color-secondary);
160
+ font-weight: var(--font-weight-medium);
161
+ }
162
+
163
+ &.row_editing {
164
+ /* hover should not flicker the background of a row the user is editing */
165
+ &:hover td {
166
+ background: var(--color-background);
167
+ }
168
+
169
+ td {
170
+ background: var(--color-background);
171
+
172
+ .td_inner {
173
+ /* let inline-edit focus rings + dropdown shadows escape the cell */
174
+ overflow: visible;
175
+ text-overflow: clip;
176
+ }
177
+ }
178
+ }
179
+
180
+ &.row_dragging td {
181
+ opacity: 0.5;
182
+ background: var(--color-muted);
183
+ }
184
+
185
+ &.row_drop_target td {
186
+ box-shadow: inset 0 2px 0 0 var(--color-primary);
187
+ }
188
+
189
+ td {
190
+ padding: var(--spacing-5) var(--spacing-6);
191
+ font-size: var(--font-size-sm);
192
+ font-weight: var(--font-weight-normal);
193
+ color: var(--color-foreground);
194
+ vertical-align: middle;
195
+ border-bottom: var(--border-1) solid var(--color-border);
196
+ /* explicit background so sticky pinned cells mask scrolled content */
197
+ background: var(--color-background);
198
+ /* visible: focus rings + dropdowns escape the cell */
199
+ overflow: visible;
200
+ }
201
+ }
202
+ }
203
+
204
+ /* ─────────────────────────────────────────────
205
+ Vertical column borders (showVerticalBorders prop)
206
+ Drawn on the LEFT of every cell except the first, so we never get a
207
+ double border at the table's outer edge.
208
+ ───────────────────────────────────────────── */
209
+ .table_vertical_borders {
210
+ /* Only add vertical border if the previous cell is not the last left-pinned cell. Prevents double border with pinned columns. */
211
+ thead th:not(.col_pinned_last.col_pinned_left) + th,
212
+ tbody td:not(.col_pinned_last.col_pinned_left) + td {
213
+ border-left: var(--border-1) solid var(--color-border);
214
+ }
215
+ }
216
+
217
+ /* ─────────────────────────────────────────────
218
+ Header inner - flex container that hugs its content.
219
+ No `flex: 1` on the label; icons sit immediately next to the text and
220
+ `justify-content` (set by `.align_*`) determines start/end alignment.
221
+ ───────────────────────────────────────────── */
222
+ .th_inner {
223
+ width: 100%;
224
+ display: flex;
225
+ align-items: center;
226
+ min-height: var(--spacing-11);
227
+ gap: var(--spacing-2);
228
+ margin: 0;
229
+ padding: 0;
230
+ overflow: hidden;
231
+ }
232
+
233
+ .th_label {
234
+ flex: 0 1 auto;
235
+ min-width: 0;
236
+ max-width: 100%;
237
+ overflow: hidden;
238
+ text-overflow: ellipsis;
239
+ white-space: nowrap;
240
+ }
241
+
242
+ .th_actions {
243
+ display: inline-flex;
244
+ align-items: center;
245
+ gap: var(--spacing-1);
246
+ flex-shrink: 0;
247
+ }
248
+
249
+ .drag_handle {
250
+ width: 1rem;
251
+ height: 1rem;
252
+ display: inline-flex;
253
+ align-items: center;
254
+ justify-content: center;
255
+ color: var(--color-muted-foreground);
256
+ cursor: grab;
257
+ flex-shrink: 0;
258
+
259
+ &:active {
260
+ cursor: grabbing;
261
+ }
262
+ }
263
+
264
+ /* ─────────────────────────────────────────────
265
+ Compact icon-only button used for sort / group / pin in the header.
266
+ ───────────────────────────────────────────── */
267
+ .icon_btn {
268
+ /* !important needed: --button-icon is also set by :is(.ghost, .tone_ghost) in
269
+ button.module.css at equal specificity - CSS module load order is not guaranteed,
270
+ so !important on the var is the only reliable way to win without hardcoding svg color. */
271
+ --button-icon: var(--color-muted-foreground) !important;
272
+
273
+ &:hover:not(.disabled) {
274
+ --button-icon: var(--color-foreground) !important;
275
+ background-color: var(--color-border) !important;
276
+ }
277
+ }
278
+
279
+ /* ─────────────────────────────────────────────
280
+ Body cell inner - default truncates with ellipsis.
281
+ Override per-column with `meta.truncate = false` for cells hosting
282
+ inputs/buttons so focus rings and dropdowns aren't clipped.
283
+ ───────────────────────────────────────────── */
284
+ .td_inner {
285
+ overflow: hidden;
286
+ text-overflow: ellipsis;
287
+ white-space: nowrap;
288
+ /* outset breathing room mirrors the header's */
289
+ margin: calc(var(--spacing-2) * -1);
290
+ padding: var(--spacing-2);
291
+ }
292
+
293
+ .td_inner_no_truncate {
294
+ overflow: visible;
295
+ text-overflow: clip;
296
+ white-space: normal;
297
+ }
298
+
299
+ .selection_checkbox {
300
+ width: fit-content;
301
+ min-width: fit-content;
302
+ display: inline-flex;
303
+ align-items: center;
304
+ justify-content: center;
305
+ padding: 0;
306
+ margin: 0;
307
+
308
+ > * {
309
+ width: fit-content;
310
+ min-width: fit-content;
311
+ }
312
+
313
+ > * > * {
314
+ width: fit-content;
315
+ min-width: fit-content;
316
+ }
317
+ }
318
+
319
+ .col_select {
320
+ padding-left: var(--spacing-5) !important;
321
+ padding-right: var(--spacing-5) !important;
322
+
323
+ .th_inner,
324
+ .td_inner {
325
+ margin: 0;
326
+ padding: 0;
327
+ display: flex;
328
+ align-items: center;
329
+ justify-content: center;
330
+ gap: 0;
331
+ overflow: visible;
332
+ }
333
+ }
334
+
335
+ .group_anchor_cell {
336
+ text-align: left !important;
337
+
338
+ .td_inner {
339
+ display: flex;
340
+ align-items: center;
341
+ justify-content: flex-start;
342
+ }
343
+ }
344
+
345
+ /* ─────────────────────────────────────────────
346
+ Cell alignment via `column.meta.align`
347
+ - text-align handles inline text (truncate=true case)
348
+ - flex justify-content handles non-truncated content (action buttons, inputs)
349
+ - header is always a flex container so we always set justify-content there
350
+ ───────────────────────────────────────────── */
351
+ .align_left {
352
+ text-align: left;
353
+
354
+ .th_inner {
355
+ justify-content: flex-start;
356
+ }
357
+
358
+ .td_inner_no_truncate {
359
+ display: flex;
360
+ align-items: center;
361
+ justify-content: flex-start;
362
+ }
363
+ }
364
+
365
+ .align_center {
366
+ text-align: center;
367
+
368
+ .th_inner {
369
+ justify-content: center;
370
+ }
371
+
372
+ .td_inner_no_truncate {
373
+ display: flex;
374
+ align-items: center;
375
+ justify-content: center;
376
+ }
377
+ }
378
+
379
+ .align_right {
380
+ text-align: right;
381
+
382
+ .th_inner {
383
+ justify-content: flex-end;
384
+ }
385
+
386
+ .td_inner_no_truncate {
387
+ display: flex;
388
+ align-items: center;
389
+ justify-content: flex-end;
390
+ }
391
+ }
392
+
393
+ /* ─────────────────────────────────────────────
394
+ Column pinning - sticky offsets are written inline by JS
395
+ The hairline divider lives only on the LAST column of each pinning group
396
+ (`col_pinned_last`) so adjacent pinned columns don't get double dividers.
397
+ ───────────────────────────────────────────── */
398
+ .table th.col_pinned_left,
399
+ .table th.col_pinned_right,
400
+ .table td.col_pinned_left,
401
+ .table td.col_pinned_right {
402
+ position: sticky;
403
+ z-index: 1;
404
+
405
+ /* To ensure pinned columns are visible above other content */
406
+ background-color: var(--color-muted);
407
+ }
408
+
409
+ .table thead th.col_pinned_left,
410
+ .table thead th.col_pinned_right {
411
+ z-index: 2;
412
+ }
413
+
414
+ /* Pinned left columns: add a right border only to the last pinned cell to act as a divider. */
415
+ .col_pinned_last.col_pinned_left {
416
+ border-right: var(--border-1) solid var(--color-border);
417
+ }
418
+
419
+ /* Pinned right columns: add a left border only to the last pinned cell to act as a divider. */
420
+ .col_pinned_last.col_pinned_right {
421
+ border-left: var(--border-1) solid var(--color-border);
422
+ }
423
+
424
+ /* Keep interactive cell popovers above sticky neighbors when they are rendered
425
+ in-place (non-portal mode). */
426
+ .table tbody td:focus-within {
427
+ position: relative;
428
+ z-index: 3;
429
+ }
430
+
431
+ /* ─────────────────────────────────────────────
432
+ Drag-and-drop column reordering
433
+ ───────────────────────────────────────────── */
434
+ .col_dragging {
435
+ opacity: 0.5;
436
+ }
437
+
438
+ .col_drop_target {
439
+ /* a slim vertical bar on the leading edge of the drop target */
440
+ outline: 2px solid var(--color-primary);
441
+ outline-offset: -2px;
442
+ }
443
+
444
+ /* ─────────────────────────────────────────────
445
+ Column resize handle - narrow vertical strip on the cell's right edge
446
+ ───────────────────────────────────────────── */
447
+ .resize_handle {
448
+ position: absolute;
449
+ top: 0;
450
+ right: 0;
451
+ bottom: 0;
452
+ width: 5px;
453
+ cursor: col-resize;
454
+ user-select: none;
455
+ touch-action: none;
456
+ background: transparent;
457
+ transition: background var(--transition-fast);
458
+
459
+ &:hover,
460
+ &.resize_handle_active {
461
+ background: var(--color-primary);
462
+ }
463
+ }
464
+
465
+ /* ─────────────────────────────────────────────
466
+ Group rows + toggle
467
+ ───────────────────────────────────────────── */
468
+ .group_toggle {
469
+ display: inline-flex;
470
+ align-items: center;
471
+ gap: var(--spacing-3);
472
+ padding: 0;
473
+ border: none;
474
+ background: transparent;
475
+ color: var(--color-foreground);
476
+ font: inherit;
477
+ cursor: pointer;
478
+ }
479
+
480
+ .group_chevron_icon {
481
+ color: var(--color-muted-foreground);
482
+ }
483
+
484
+ .group_chevron {
485
+ transition: transform var(--transition-fast);
486
+ flex-shrink: 0;
487
+ }
488
+
489
+ .group_chevron_open {
490
+ transform: rotate(90deg);
491
+ }
492
+
493
+ .group_value {
494
+ font-weight: var(--font-weight-semibold);
495
+ }
496
+
497
+ .group_count {
498
+ color: var(--color-muted-foreground);
499
+ font-size: var(--font-size-xs);
500
+ }
501
+
502
+ .cell_aggregated {
503
+ font-weight: var(--font-weight-semibold);
504
+ }
505
+
506
+ /* ─────────────────────────────────────────────
507
+ Loading / empty states
508
+ ───────────────────────────────────────────── */
509
+ .state_overlay {
510
+ width: 100%;
511
+ padding: var(--spacing-14) var(--spacing-8);
512
+ display: flex;
513
+ align-items: center;
514
+ justify-content: center;
515
+ }
516
+
517
+ .empty_msg {
518
+ font-size: var(--font-size-sm);
519
+ color: var(--color-muted-foreground);
520
+ }
521
+
522
+ /* ─────────────────────────────────────────────
523
+ Pagination bar
524
+ margin-top:auto pushes it to the absolute bottom of content_wrap
525
+ no matter how few rows are visible.
526
+ flex-shrink:0 stops it compressing when space is tight.
527
+ ───────────────────────────────────────────── */
528
+ .pagination_bar {
529
+ flex-shrink: 0;
530
+ margin-top: auto;
531
+ width: 100%;
532
+ display: flex;
533
+ align-items: center;
534
+ justify-content: space-between;
535
+ gap: var(--spacing-8);
536
+ min-width: 0;
537
+ }
538
+
539
+ .pagination_left {
540
+ display: flex;
541
+ align-items: center;
542
+ gap: var(--spacing-8);
543
+ min-width: 0;
544
+ flex-shrink: 1;
545
+ }
546
+
547
+ .pagination_count {
548
+ font-size: var(--font-size-sm);
549
+ color: var(--color-muted-foreground);
550
+ white-space: nowrap;
551
+
552
+ span {
553
+ font-weight: var(--font-weight-medium);
554
+ color: var(--color-foreground);
555
+ }
556
+ }
557
+
558
+ .pagination_controls {
559
+ display: flex;
560
+ align-items: center;
561
+ gap: var(--spacing-8);
562
+ flex-shrink: 0;
563
+ }
564
+
565
+ .page_size_wrap {
566
+ display: flex;
567
+ align-items: center;
568
+ gap: var(--spacing-5);
569
+ }
570
+
571
+ .page_size_label {
572
+ font-size: var(--font-size-sm);
573
+ color: var(--color-muted-foreground);
574
+ white-space: nowrap;
575
+ }
576
+
577
+ .page_indicator {
578
+ font-size: var(--font-size-sm);
579
+ color: var(--color-muted-foreground);
580
+ white-space: nowrap;
581
+ min-width: 6rem;
582
+ text-align: center;
583
+
584
+ span {
585
+ font-weight: var(--font-weight-medium);
586
+ color: var(--color-foreground);
587
+ }
588
+ }
589
+
590
+ .page_nav {
591
+ display: flex;
592
+ align-items: center;
593
+ gap: var(--spacing-2);
594
+ }