photon-grid-core 0.0.2 → 0.0.3

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 (141) hide show
  1. package/icons/icon-sets/core-icons.js +1 -1
  2. package/icons/icon-sets/core-icons.js.map +1 -1
  3. package/index.d.ts +1 -0
  4. package/index.d.ts.map +1 -1
  5. package/package.json +1 -1
  6. package/renderer/body-renderer.d.ts.map +1 -1
  7. package/renderer/body-renderer.js +21 -4
  8. package/renderer/body-renderer.js.map +1 -1
  9. package/renderer/cell-renderer.js +1 -1
  10. package/renderer/cell-renderer.js.map +1 -1
  11. package/renderer/column-menu.js +24 -25
  12. package/renderer/column-menu.js.map +1 -1
  13. package/renderer/column-style-manager.d.ts.map +1 -1
  14. package/renderer/column-style-manager.js +11 -2
  15. package/renderer/column-style-manager.js.map +1 -1
  16. package/renderer/grid-renderer.js +1 -1
  17. package/renderer/grid-renderer.js.map +1 -1
  18. package/renderer/header-renderer.d.ts.map +1 -1
  19. package/renderer/header-renderer.js +17 -3
  20. package/renderer/header-renderer.js.map +1 -1
  21. package/renderer/row-drag-renderer.d.ts +18 -0
  22. package/renderer/row-drag-renderer.d.ts.map +1 -1
  23. package/renderer/row-drag-renderer.js +53 -0
  24. package/renderer/row-drag-renderer.js.map +1 -1
  25. package/styles/base/cells.css.d.ts +9 -0
  26. package/styles/base/cells.css.d.ts.map +1 -0
  27. package/styles/base/cells.css.js +233 -0
  28. package/styles/base/cells.css.js.map +1 -0
  29. package/styles/base/chart-panel.css.d.ts +9 -0
  30. package/styles/base/chart-panel.css.d.ts.map +1 -0
  31. package/styles/base/chart-panel.css.js +140 -0
  32. package/styles/base/chart-panel.css.js.map +1 -0
  33. package/styles/base/column-context-menu.css.d.ts +9 -0
  34. package/styles/base/column-context-menu.css.d.ts.map +1 -0
  35. package/styles/base/column-context-menu.css.js +153 -0
  36. package/styles/base/column-context-menu.css.js.map +1 -0
  37. package/styles/base/column-group-header.css.d.ts +9 -0
  38. package/styles/base/column-group-header.css.d.ts.map +1 -0
  39. package/styles/base/column-group-header.css.js +270 -0
  40. package/styles/base/column-group-header.css.js.map +1 -0
  41. package/styles/base/context-menu.css.d.ts +9 -0
  42. package/styles/base/context-menu.css.d.ts.map +1 -0
  43. package/styles/base/context-menu.css.js +103 -0
  44. package/styles/base/context-menu.css.js.map +1 -0
  45. package/styles/base/editors.css.d.ts +9 -0
  46. package/styles/base/editors.css.d.ts.map +1 -0
  47. package/styles/base/editors.css.js +291 -0
  48. package/styles/base/editors.css.js.map +1 -0
  49. package/styles/base/filter.css.d.ts +9 -0
  50. package/styles/base/filter.css.d.ts.map +1 -0
  51. package/styles/base/filter.css.js +312 -0
  52. package/styles/base/filter.css.js.map +1 -0
  53. package/styles/base/footer.css.d.ts +9 -0
  54. package/styles/base/footer.css.d.ts.map +1 -0
  55. package/styles/base/footer.css.js +78 -0
  56. package/styles/base/footer.css.js.map +1 -0
  57. package/styles/base/group-bar-search.css.d.ts +9 -0
  58. package/styles/base/group-bar-search.css.d.ts.map +1 -0
  59. package/styles/base/group-bar-search.css.js +86 -0
  60. package/styles/base/group-bar-search.css.js.map +1 -0
  61. package/styles/base/group-drop-zone.css.d.ts +9 -0
  62. package/styles/base/group-drop-zone.css.d.ts.map +1 -0
  63. package/styles/base/group-drop-zone.css.js +173 -0
  64. package/styles/base/group-drop-zone.css.js.map +1 -0
  65. package/styles/base/header.css.d.ts +9 -0
  66. package/styles/base/header.css.d.ts.map +1 -0
  67. package/styles/base/header.css.js +206 -0
  68. package/styles/base/header.css.js.map +1 -0
  69. package/styles/base/master-detail.css.d.ts +9 -0
  70. package/styles/base/master-detail.css.d.ts.map +1 -0
  71. package/styles/base/master-detail.css.js +202 -0
  72. package/styles/base/master-detail.css.js.map +1 -0
  73. package/styles/base/misc.css.d.ts +9 -0
  74. package/styles/base/misc.css.d.ts.map +1 -0
  75. package/styles/base/misc.css.js +65 -0
  76. package/styles/base/misc.css.js.map +1 -0
  77. package/styles/base/panels.css.d.ts +9 -0
  78. package/styles/base/panels.css.d.ts.map +1 -0
  79. package/styles/base/panels.css.js +162 -0
  80. package/styles/base/panels.css.js.map +1 -0
  81. package/styles/base/photon-ai.css.d.ts +9 -0
  82. package/styles/base/photon-ai.css.d.ts.map +1 -0
  83. package/styles/base/photon-ai.css.js +200 -0
  84. package/styles/base/photon-ai.css.js.map +1 -0
  85. package/styles/base/root.css.d.ts +9 -0
  86. package/styles/base/root.css.d.ts.map +1 -0
  87. package/styles/base/root.css.js +56 -0
  88. package/styles/base/root.css.js.map +1 -0
  89. package/styles/base/row-drag.css.d.ts +9 -0
  90. package/styles/base/row-drag.css.d.ts.map +1 -0
  91. package/styles/base/row-drag.css.js +93 -0
  92. package/styles/base/row-drag.css.js.map +1 -0
  93. package/styles/base/row-group.css.d.ts +9 -0
  94. package/styles/base/row-group.css.d.ts.map +1 -0
  95. package/styles/base/row-group.css.js +79 -0
  96. package/styles/base/row-group.css.js.map +1 -0
  97. package/styles/base/rows.css.d.ts +9 -0
  98. package/styles/base/rows.css.d.ts.map +1 -0
  99. package/styles/base/rows.css.js +83 -0
  100. package/styles/base/rows.css.js.map +1 -0
  101. package/styles/base/scrollbars.css.d.ts +9 -0
  102. package/styles/base/scrollbars.css.d.ts.map +1 -0
  103. package/styles/base/scrollbars.css.js +56 -0
  104. package/styles/base/scrollbars.css.js.map +1 -0
  105. package/styles/base/sparkline.css.d.ts +9 -0
  106. package/styles/base/sparkline.css.d.ts.map +1 -0
  107. package/styles/base/sparkline.css.js +109 -0
  108. package/styles/base/sparkline.css.js.map +1 -0
  109. package/styles/base/tooltip.css.d.ts +9 -0
  110. package/styles/base/tooltip.css.d.ts.map +1 -0
  111. package/styles/base/tooltip.css.js +39 -0
  112. package/styles/base/tooltip.css.js.map +1 -0
  113. package/styles/base/tree.css.d.ts +9 -0
  114. package/styles/base/tree.css.d.ts.map +1 -0
  115. package/styles/base/tree.css.js +78 -0
  116. package/styles/base/tree.css.js.map +1 -0
  117. package/styles/base-styles.d.ts.map +1 -1
  118. package/styles/base-styles.js +56 -3026
  119. package/styles/base-styles.js.map +1 -1
  120. package/styles/themes/theme-alpine.d.ts +1 -1
  121. package/styles/themes/theme-alpine.d.ts.map +1 -1
  122. package/styles/themes/theme-alpine.js +1 -1
  123. package/styles/themes/theme-balham.d.ts +1 -1
  124. package/styles/themes/theme-balham.d.ts.map +1 -1
  125. package/styles/themes/theme-balham.js +0 -1
  126. package/styles/themes/theme-balham.js.map +1 -1
  127. package/styles/themes/theme-dark.d.ts +1 -1
  128. package/styles/themes/theme-dark.d.ts.map +1 -1
  129. package/styles/themes/theme-dark.js +1 -1
  130. package/styles/themes/theme-material.d.ts +1 -1
  131. package/styles/themes/theme-material.d.ts.map +1 -1
  132. package/styles/themes/theme-material.js +0 -1
  133. package/styles/themes/theme-material.js.map +1 -1
  134. package/styles/themes/theme-quartz.d.ts +1 -1
  135. package/styles/themes/theme-quartz.d.ts.map +1 -1
  136. package/styles/themes/theme-quartz.js +1 -1
  137. package/LICENSE +0 -1
  138. package/chart/chart-analyzer.d.ts +0 -12
  139. package/chart/chart-analyzer.d.ts.map +0 -1
  140. package/chart/chart-analyzer.js +0 -77
  141. package/chart/chart-analyzer.js.map +0 -1
@@ -3,3033 +3,63 @@ import { themeAlpineCss } from './themes/theme-alpine';
3
3
  import { themeBalhamCss } from './themes/theme-balham';
4
4
  import { themeMaterialCss } from './themes/theme-material';
5
5
  import { themeDarkCss } from './themes/theme-dark';
6
+ // Base styles are authored as focused per-feature modules under ./base/ for
7
+ // maintainability, then concatenated here in a FIXED order. The order matters:
8
+ // CSS cascade resolves same-specificity conflicts by source order, so these
9
+ // must be joined exactly as listed (edit the individual ./base/*.css.ts files,
10
+ // not this list's ordering, unless you intend to change the cascade).
11
+ import { rootCss } from './base/root.css';
12
+ import { groupDropZoneCss } from './base/group-drop-zone.css';
13
+ import { groupBarSearchCss } from './base/group-bar-search.css';
14
+ import { panelsCss } from './base/panels.css';
15
+ import { headerCss } from './base/header.css';
16
+ import { columnGroupHeaderCss } from './base/column-group-header.css';
17
+ import { filterCss } from './base/filter.css';
18
+ import { rowsCss } from './base/rows.css';
19
+ import { cellsCss } from './base/cells.css';
20
+ import { contextMenuCss } from './base/context-menu.css';
21
+ import { rowGroupCss } from './base/row-group.css';
22
+ import { treeCss } from './base/tree.css';
23
+ import { scrollbarsCss } from './base/scrollbars.css';
24
+ import { editorsCss } from './base/editors.css';
25
+ import { footerCss } from './base/footer.css';
26
+ import { miscCss } from './base/misc.css';
27
+ import { rowDragCss } from './base/row-drag.css';
28
+ import { chartPanelCss } from './base/chart-panel.css';
29
+ import { sparklineCss } from './base/sparkline.css';
30
+ import { columnContextMenuCss } from './base/column-context-menu.css';
31
+ import { masterDetailCss } from './base/master-detail.css';
32
+ import { photonAiCss } from './base/photon-ai.css';
33
+ import { tooltipCss } from './base/tooltip.css';
6
34
  const STYLE_ID = 'photon-grid-base-styles';
7
- const baseCss = `
8
- /* ──────────────────── Root ──────────────────── */
9
- .pg-grid {
10
- display: flex;
11
- flex-direction: column;
12
- width: 100%;
13
- height: 100%;
14
- overflow: hidden;
15
- border: 1px solid var(--pg-colors-border, #e2e8f0);
16
- border-radius: var(--pg-borders-radius-md, 6px);
17
- background: var(--pg-colors-row-background, #fff);
18
- color: var(--pg-colors-text-primary, #0f172a);
19
- font-family: var(--pg-typography-font-family, system-ui, sans-serif);
20
- font-size: var(--pg-typography-font-size-md, 13px);
21
- box-sizing: border-box;
22
- position: relative;
23
- --pg-scroll-x: 0px;
24
- --pg-scroll-y: 0px;
25
- --pg-content-height: 0px;
26
- --pg-center-content-width: 0px;
27
- --pg-left-panel-width: auto;
28
- --pg-right-panel-width: auto;
29
- --pg-header-row-height: 44px;
30
- --pg-filter-row-height: 36px;
31
- }
32
- .pg-grid *, .pg-grid *::before, .pg-grid *::after { box-sizing: border-box; }
33
-
34
- /* ──────────────────── Outer flex-row / main flex-col wrappers ──────────────────── */
35
- .pg-grid-outer {
36
- display: flex;
37
- flex-direction: row;
38
- flex: 1 1 0;
39
- min-height: 0;
40
- overflow: hidden;
41
- }
42
- .pg-grid-main {
43
- display: flex;
44
- flex-direction: column;
45
- flex: 1 1 0;
46
- min-height: 0;
47
- min-width: 0;
48
- overflow: hidden;
49
- position: relative;
50
- }
51
-
52
- /* ──────────────────── Group drop zone ──────────────────── */
53
- .pg-group-drop-zone--top {
54
- display: flex;
55
- flex-direction: row;
56
- align-items: center;
57
- flex-shrink: 0;
58
- height: var(--pg-header-row-height, 44px);
59
- background: var(--pg-colors-header-background, #f8fafc);
60
- border-bottom: 1px solid var(--pg-colors-border, #e2e8f0);
61
- overflow: hidden;
62
- }
63
- .pg-group-drop-zone--left {
64
- display: flex;
65
- flex-direction: column;
66
- flex-shrink: 0;
67
- width: 160px;
68
- background: var(--pg-colors-header-background, #f8fafc);
69
- border-right: 1px solid var(--pg-colors-border, #e2e8f0);
70
- overflow: hidden;
71
- position: relative;
72
- }
73
- .pg-group-drop-zone--right {
74
- display: flex;
75
- flex-direction: column;
76
- flex-shrink: 0;
77
- width: 160px;
78
- background: var(--pg-colors-header-background, #f8fafc);
79
- border-left: 1px solid var(--pg-colors-border, #e2e8f0);
80
- overflow: hidden;
81
- position: relative;
82
- }
83
-
84
- /* Zone header row (grip + "Groups" label) */
85
- .pg-group-zone-header {
86
- display: flex;
87
- align-items: center;
88
- gap: 6px;
89
- padding: 4px 10px 4px 8px;
90
- flex-shrink: 0;
91
- border-bottom: 1px solid var(--pg-colors-border, #e2e8f0);
92
- user-select: none;
93
- }
94
- .pg-group-zone-grip {
95
- display: flex;
96
- align-items: center;
97
- cursor: grab;
98
- opacity: 0.45;
99
- padding: 2px 3px;
100
- border-radius: 3px;
101
- color: var(--pg-colors-text-secondary, #64748b);
102
- flex-shrink: 0;
103
- transition: opacity 100ms, background 100ms;
104
- }
105
- .pg-group-zone-grip:hover { opacity: 0.85; background: rgba(0,0,0,0.06); }
106
- .pg-group-zone-grip:active { cursor: grabbing; }
107
- .pg-group-zone-label {
108
- flex: 1;
109
- font-size: 11px;
110
- font-weight: 600;
111
- text-transform: uppercase;
112
- letter-spacing: 0.04em;
113
- color: var(--pg-colors-text-secondary, #64748b);
114
- user-select: none;
115
- }
116
-
117
- /* Chips area (the actual drop target) */
118
- .pg-group-zone-chips {
119
- display: flex;
120
- align-items: center;
121
- flex-wrap: wrap;
122
- gap: 6px;
123
- padding: 6px 10px;
124
- min-height: 38px;
125
- flex: 1;
126
- overflow: auto;
127
- }
128
- .pg-group-drop-zone--left .pg-group-zone-chips,
129
- .pg-group-drop-zone--right .pg-group-zone-chips {
130
- flex-direction: column;
131
- align-items: flex-start;
132
- overflow-y: auto;
133
- overflow-x: hidden;
134
- }
135
- .pg-group-zone-chips--over {
136
- background: var(--pg-colors-group-zone-over, #eff6ff);
137
- outline: 1px dashed var(--pg-colors-primary, #2563eb);
138
- outline-offset: -2px;
139
- }
140
-
141
- /* Resize handle */
142
- .pg-group-drop-zone--top .pg-group-zone-resize {
143
- height: 4px;
144
- flex-shrink: 0;
145
- cursor: ns-resize;
146
- background: transparent;
147
- transition: background 100ms;
148
- }
149
- .pg-group-drop-zone--top .pg-group-zone-resize:hover { background: var(--pg-colors-primary, #2563eb); opacity: 0.35; }
150
- .pg-group-drop-zone--left .pg-group-zone-resize {
151
- position: absolute;
152
- top: 0; right: 0; bottom: 0;
153
- width: 4px;
154
- cursor: ew-resize;
155
- background: transparent;
156
- transition: background 100ms;
157
- }
158
- .pg-group-drop-zone--right .pg-group-zone-resize {
159
- position: absolute;
160
- top: 0; left: 0; bottom: 0;
161
- width: 4px;
162
- cursor: ew-resize;
163
- background: transparent;
164
- transition: background 100ms;
165
- }
166
- .pg-group-drop-zone--left .pg-group-zone-resize:hover,
167
- .pg-group-drop-zone--right .pg-group-zone-resize:hover { background: var(--pg-colors-primary, #2563eb); opacity: 0.35; }
168
-
169
- /* Hint text */
170
- .pg-group-drop-zone__hint {
171
- font-size: var(--pg-typography-font-size-sm, 12px);
172
- color: var(--pg-colors-text-disabled, #94a3b8);
173
- pointer-events: none;
174
- user-select: none;
175
- }
176
-
177
- /* Chips */
178
- .pg-group-chip {
179
- display: inline-flex;
180
- align-items: center;
181
- gap: 5px;
182
- padding: 3px 6px 3px 10px;
183
- border-radius: var(--pg-borders-radius-pill, 9999px);
184
- background: var(--pg-colors-chip-background, #e0e7ff);
185
- color: var(--pg-colors-chip-text, #1e40af);
186
- font-size: var(--pg-typography-font-size-sm, 12px);
187
- font-weight: var(--pg-typography-font-weight-medium, 500);
188
- user-select: none;
189
- white-space: nowrap;
190
- transition: opacity 120ms;
191
- }
192
- .pg-group-chip--ghost {
193
- cursor: grabbing;
194
- }
195
- .pg-group-chip__label { line-height: 1.2; }
196
- .pg-group-chip__close {
197
- display: inline-flex;
198
- align-items: center;
199
- justify-content: center;
200
- width: 16px;
201
- height: 16px;
202
- border-radius: 50%;
203
- cursor: pointer;
204
- opacity: 0.55;
205
- transition: opacity 100ms, background 100ms;
206
- flex-shrink: 0;
207
- }
208
- .pg-group-chip__close:hover { opacity: 1; background: rgba(30,64,175,0.18); }
209
- .pg-group-chip__sep {
210
- display: inline-flex;
211
- align-items: center;
212
- color: var(--pg-colors-text-disabled, #94a3b8);
213
- flex-shrink: 0;
214
- }
215
-
216
- /* ──────────────────── Group bar quick-filter search ──────────────────── */
217
- .pg-group-search {
218
- display: flex;
219
- align-items: center;
220
- padding: 0 10px;
221
- flex-shrink: 0;
222
- height: 100%;
223
- }
224
- .pg-group-drop-zone--left .pg-group-search,
225
- .pg-group-drop-zone--right .pg-group-search { display: none; }
226
-
227
- /* Field wrapper: position:relative so icon + clear button can overlay the input */
228
- .pg-group-search__field {
229
- position: relative;
230
- display: flex;
231
- align-items: center;
232
- }
233
- .pg-group-search__icon {
234
- position: absolute;
235
- left: 9px;
236
- top: 50%;
237
- transform: translateY(-50%);
238
- display: flex;
239
- align-items: center;
240
- color: var(--pg-colors-text-disabled, #94a3b8);
241
- pointer-events: none;
242
- transition: color 150ms;
243
- z-index: 1;
244
- }
245
- .pg-group-search__field:focus-within .pg-group-search__icon {
246
- color: var(--pg-colors-primary, #2563eb);
247
- }
248
- .pg-group-search__input {
249
- width: 210px;
250
- height: 32px;
251
- padding: 0 28px 0 30px;
252
- font-size: var(--pg-typography-font-size-sm, 12px);
253
- font-family: inherit;
254
- color: var(--pg-colors-text-primary, #0f172a);
255
- background: var(--pg-colors-surface, #ffffff);
256
- border: 1px solid var(--pg-colors-border, #e2e8f0);
257
- border-radius: var(--pg-borders-radius-sm, 4px);
258
- outline: none;
259
- transition: border-color 150ms, box-shadow 150ms;
260
- appearance: none;
261
- }
262
- .pg-group-search__input::placeholder { color: var(--pg-colors-text-disabled, #94a3b8); }
263
- .pg-group-search__input:focus {
264
- border-color: var(--pg-colors-border-focus, #2563eb);
265
- box-shadow: 0 0 0 3px var(--pg-colors-selection-background, rgba(37, 99, 235, 0.12));
266
- }
267
- .pg-group-search__clear {
268
- position: absolute;
269
- right: 6px;
270
- top: 50%;
271
- transform: translateY(-50%);
272
- display: flex;
273
- align-items: center;
274
- justify-content: center;
275
- width: 18px;
276
- height: 18px;
277
- border-radius: 50%;
278
- cursor: pointer;
279
- color: var(--pg-colors-text-secondary, #64748b);
280
- opacity: 0;
281
- pointer-events: none;
282
- transition: opacity 150ms, background 100ms;
283
- }
284
- .pg-group-search__clear--visible {
285
- opacity: 0.55;
286
- pointer-events: auto;
287
- }
288
- .pg-group-search__clear--visible:hover {
289
- opacity: 1;
290
- background: var(--pg-colors-background-alt, #f1f5f9);
291
- }
292
-
293
- /* ──────────────────── Three-panel header ──────────────────── */
294
- .pg-grid__header {
295
- display: flex;
296
- flex-direction: row;
297
- flex-shrink: 0;
298
- border-bottom: 1px solid var(--pg-colors-header-border, #e2e8f0);
299
- background: var(--pg-colors-header-background, #f8fafc);
300
- overflow: hidden;
301
- z-index: 10;
302
- position: relative;
303
- }
304
- /* Mirrors the vertical-scrollbar flex item that lives in the body row so that
305
- the center header panel is exactly as wide as the center body panel.
306
- Without this spacer the header center is scrollbar_width wider and the right
307
- pinned-column header is shifted right relative to the body cells. */
308
- .pg-header-vscroll-spacer {
309
- flex-shrink: 0;
310
- width: var(--pg-scrollbar-v-width, 0px);
311
- background: var(--pg-colors-header-background, #f8fafc);
312
- }
313
-
314
- /* ──────────────────── Three-panel body ──────────────────── */
315
- .pg-grid__body {
316
- display: flex;
317
- flex-direction: row;
318
- flex: 1 1 0;
319
- min-height: 0;
320
- overflow: hidden;
321
- position: relative;
322
- }
323
-
324
- /* ──────────────────── Panel base ──────────────────── */
325
- .pg-panel {
326
- display: flex;
327
- flex-direction: column;
328
- overflow: hidden;
329
- flex-shrink: 0;
330
- position: relative;
331
- }
332
- .pg-panel--left {
333
- z-index: 2;
334
- // box-shadow: 2px 0 4px rgba(0,0,0,0.06);
335
- width: var(--pg-left-panel-width, auto);
336
- }
337
- .pg-panel--center {
338
- flex: 1 1 0;
339
- min-width: 0;
340
- overflow: hidden;
341
- }
342
- .pg-panel--right {
343
- z-index: 2;
344
- // box-shadow: -2px 0 4px rgba(0,0,0,0.06);
345
- width: var(--pg-right-panel-width, auto);
346
- }
347
-
348
- /* ──────────────────── Panel header ──────────────────── */
349
- .pg-panel__header {
350
- flex-shrink: 0;
351
- overflow: hidden;
352
- position: relative;
353
- z-index: 2;
354
- }
355
- /* Center panel header sits behind pinned-panel headers so that center
356
- content translated by the scroll transform cannot visually overlap the
357
- left / right pinned column headers when scrolled near their edges. */
358
- .pg-panel--center .pg-panel__header {
359
- z-index: 1;
360
- }
361
- .pg-panel__header-inner {
362
- display: flex;
363
- flex-direction: column;
364
- }
365
- .pg-panel--center .pg-panel__header-inner {
366
- transform: translateX(var(--pg-scroll-x, 0px));
367
- width: var(--pg-center-content-width, 100%);
368
- }
369
-
370
- /* ──────────────────── Panel body ──────────────────── */
371
- .pg-panel__body {
372
- flex: 1 1 0;
373
- min-height: 0;
374
- overflow: hidden;
375
- position: relative;
376
- }
377
-
378
- /* ──────────────────── Panel content (virtual scroll) ──────────────────── */
379
- .pg-panel__content {
380
- position: relative;
381
- height: var(--pg-content-height, 0px);
382
- will-change: transform;
383
- }
384
- .pg-panel--left .pg-panel__content,
385
- .pg-panel--right .pg-panel__content {
386
- transform: translateY(var(--pg-scroll-y, 0px));
387
- }
388
- .pg-panel--center .pg-panel__content {
389
- transform: translate(var(--pg-scroll-x, 0px), var(--pg-scroll-y, 0px));
390
- width: var(--pg-center-content-width, 100%);
391
- }
392
- /* Master/Detail only (see GridRenderer's pg-grid--has-master-detail class):
393
- a BODY panel (left/center/right — scoped via .pg-grid__body so the
394
- *header* panels, which share the same .pg-panel classes, are untouched
395
- and stay fully interactive for sort/resize/filter) is a full-height block
396
- regardless of whether it has a row at a given Y — including the Y range
397
- where the full-width detail/nested grid layer shows through underneath.
398
- Without this, empty panel space (there is no row there — a detail row
399
- renders nothing in these panels by design) still geometrically blocks
400
- clicks meant for whatever is showing through from that layer.
401
- pointer-events is inherited, so every actual row must explicitly opt
402
- back in — scoped to Master/Detail grids only, this has no effect on the
403
- vast majority of grids that never use it. */
404
- .pg-grid--has-master-detail .pg-grid__body > .pg-panel,
405
- .pg-grid--has-master-detail .pg-panel__body,
406
- .pg-grid--has-master-detail .pg-panel__content {
407
- pointer-events: none;
408
- }
409
- .pg-grid--has-master-detail .pg-row {
410
- pointer-events: auto;
411
- }
412
-
413
- /* ──────────────────── Header rows ──────────────────── */
414
- .pg-header-row, .pg-filter-row {
415
- display: flex;
416
- align-items: stretch;
417
- }
418
- .pg-header-row { height: var(--pg-header-row-height, 44px); }
419
- .pg-filter-row {
420
- height: var(--pg-filter-row-height, 36px);
421
- border-top: 1px solid var(--pg-colors-border, #e2e8f0);
422
- background: var(--pg-colors-filter-background, #fff);
423
- }
424
- .pg-th {
425
- display: flex;
426
- align-items: center;
427
- position: relative;
428
- flex-shrink: 0;
429
- padding: 0;
430
- color: var(--pg-colors-header-text, #374151);
431
- font-weight: var(--pg-typography-font-weight-semi-bold, 600);
432
- font-size: var(--pg-typography-font-size-sm, 12px);
433
- letter-spacing: var(--pg-typography-letter-spacing-wide, 0.025em);
434
- text-transform: uppercase;
435
- border-right: 1px solid var(--pg-colors-header-border, #e2e8f0);
436
- user-select: none;
437
- cursor: default;
438
- transition: background var(--pg-transitions-duration-fast, 100ms);
439
- overflow: hidden;
440
- min-width: var(--pg-sizing-column-min-width, 40px);
441
- }
442
- .pg-th:last-child { border-right: none; }
443
- .pg-th--sortable { cursor: pointer; }
444
- // .pg-th:hover, .pg-th.pg-th--sortable:hover { background: var(--pg-colors-header-hover, #f1f5f9); }
445
- // .pg-th.pg-th--sorted { background: var(--pg-colors-header-hover, #f1f5f9); }
446
- .pg-th.pg-th--sort-asc .pg-th__sort-icon,
447
- .pg-th.pg-th--sort-desc .pg-th__sort-icon { color: var(--pg-colors-primary, #2563eb); }
448
- .pg-th.pg-th--filter-active .pg-th__label { color: var(--pg-colors-primary, #2563eb); }
449
- .pg-th--checkbox {
450
- width: 44px;
451
- min-width: 44px;
452
- max-width: 44px;
453
- justify-content: center;
454
- flex-shrink: 0;
455
- }
456
- .pg-th--serial {
457
- width: 52px;
458
- min-width: 52px;
459
- max-width: 52px;
460
- justify-content: center;
461
- flex-shrink: 0;
462
- }
463
- .pg-th--auto-group {
464
- flex-shrink: 0;
465
- background: var(--pg-colors-header-background, #f8fafc);
466
- border-right: 1px solid var(--pg-colors-border, #e2e8f0);
467
- font-weight: var(--pg-typography-font-weight-semi-bold, 600);
468
- font-size: var(--pg-typography-font-size-xs, 11px);
469
- text-transform: uppercase;
470
- letter-spacing: 0.04em;
471
- color: var(--pg-colors-text-secondary, #64748b);
472
- }
473
- .pg-cell--auto-group-spacer {
474
- flex-shrink: 0;
475
- border-right: 1px solid var(--pg-colors-border, #e2e8f0);
476
- background: transparent;
477
- }
478
- .pg-th__content {
479
- display: flex;
480
- align-items: center;
481
- gap: 10px;
482
- flex: 1;
483
- min-width: 0;
484
- padding: 0 10px 0 12px;
485
- height: 100%;
486
- }
487
- .pg-th__label {
488
- flex: 0 1 auto;
489
- min-width: 0;
490
- overflow: hidden;
491
- text-overflow: ellipsis;
492
- white-space: nowrap;
493
- }
494
- .pg-th__sort-icon { flex-shrink: 0; opacity: 0; color: var(--pg-colors-text-secondary, #475569); }
495
- /* Aligned column headers */
496
- .pg-th--align-right .pg-th__label { text-align: right; }
497
- .pg-th--align-center .pg-th__label { text-align: center; }
498
- .pg-th--align-center .pg-th__content,
499
- .pg-th--no-group .pg-th__content {
500
- justify-content: center;
501
- }
502
- .pg-th--no-group .pg-th__label {
503
- text-align: center;
504
- }
505
- /* Reversed header layout for numeric/currency columns: icons LEFT, text RIGHT */
506
- .pg-th--reverse { flex-direction: row-reverse; }
507
- .pg-th--reverse .pg-th__content { flex-direction: row-reverse; padding: 0 12px 0 10px; }
508
- .pg-th--reverse .pg-th__label { flex: 1 1 auto; }
509
- .pg-th--reverse .pg-th__filter-btn { margin-right: 0; margin-left: 2px; }
510
- .pg-th--reverse .pg-th__menu-btn { margin-right: 0; margin-left: 4px; }
511
- .pg-th--sort-asc .pg-th__sort-icon,
512
- .pg-th--sort-desc .pg-th__sort-icon { opacity: 1; color: var(--pg-colors-primary, #2563eb); }
513
- /* ─── Column header filter button ─── */
514
- .pg-th__filter-btn {
515
- flex-shrink: 0;
516
- display: none;
517
- align-items: center;
518
- justify-content: center;
519
- cursor: pointer;
520
- padding: 4px;
521
- margin-right: 2px;
522
- border-radius: var(--pg-borders-radius-sm, 4px);
523
- color: var(--pg-colors-text-secondary, #475569);
524
- opacity: 0.7;
525
- transition: opacity var(--pg-transitions-duration-fast, 100ms),
526
- color var(--pg-transitions-duration-fast, 100ms),
527
- background var(--pg-transitions-duration-fast, 100ms);
528
- }
529
- .pg-th:hover .pg-th__filter-btn,
530
- .pg-th__filter-btn--active { display: flex; }
531
- .pg-th__filter-btn:hover { opacity: 1; background: var(--pg-colors-background-alt, #f1f5f9); }
532
- .pg-th__filter-btn--active {
533
- opacity: 1;
534
- color: var(--pg-colors-primary, #2563eb);
535
- }
536
- .pg-th__filter-icon { flex-shrink: 0; color: var(--pg-colors-primary, #2563eb); }
537
- .pg-th__menu-btn {
538
- flex-shrink: 0;
539
- display: none;
540
- cursor: pointer;
541
- padding: 6px;
542
- margin-right: 4px;
543
- border-radius: var(--pg-borders-radius-sm, 4px);
544
- color: var(--pg-colors-text-secondary, #475569);
545
- opacity: 0.6;
546
- transition: opacity var(--pg-transitions-duration-fast, 100ms);
547
- }
548
- .pg-th:hover .pg-th__menu-btn,
549
- .pg-th__menu-btn--active { display: flex; }
550
- .pg-th__menu-btn:hover { opacity: 1; background: var(--pg-colors-background-alt, #f1f5f9); }
551
- .pg-th__menu-btn--active { opacity: 1; background: var(--pg-colors-border, #e2e8f0); }
552
- .pg-th__resize-handle {
553
- position: absolute;
554
- right: -1px;
555
- top: 0;
556
- width: 6px;
557
- height: 50%;
558
- top: 25%;
559
- cursor: ew-resize;
560
- display: flex;
561
- align-items: center;
562
- justify-content: center;
563
- color: var(--pg-colors-resize-handle-color, #d9d9db);
564
- background: transparent;
565
- transition: background var(--pg-transitions-duration-fast, 100ms);
566
- z-index: 5;
567
- font-size: 10px;
568
- user-select: none;
569
- background: #d6d6d6;
570
- width: 2px;
571
- }
572
- .pg-th__resize-handle:hover,
573
- .pg-th.pg-resizing .pg-th__resize-handle,
574
- .pg-th--resizing .pg-th__resize-handle {
575
- // background: var(--pg-colors-resize-handle-active-color, #2563eb);
576
- }
577
-
578
- /* No vertical-borders mode: completely remove the 1px border slot from both headers and cells */
579
- .pg-grid--no-v-borders .pg-th { border-right: none; }
580
- .pg-grid--no-v-borders .pg-cell { border-right: none; }
581
- // .pg-grid--no-v-borders .pg-th__resize-handle {
582
- // background: var(--pg-colors-resize-handle-color, #e2e8f0);
583
- // }
584
- .pg-grid--no-v-borders .pg-th__resize-handle:hover,
585
- .pg-grid--no-v-borders .pg-th.pg-resizing .pg-th__resize-handle,
586
- .pg-grid--no-v-borders .pg-th--resizing .pg-th__resize-handle {
587
- // background: var(--pg-colors-resize-handle-active-color, #2563eb);
588
- }
589
- .pg-th__drag-handle {
590
- position: absolute;
591
- left: 2px;
592
- top: 50%;
593
- transform: translateY(-50%);
594
- display: none;
595
- align-items: center;
596
- justify-content: center;
597
- width: 16px;
598
- height: 24px;
599
- cursor: grab;
600
- color: var(--pg-colors-text-secondary, #475569);
601
- z-index: 2;
602
- border-radius: 3px;
603
- }
604
- .pg-th:hover .pg-th__drag-handle { display: flex; opacity: 0.5; }
605
- .pg-th__drag-handle:hover { opacity: 1 !important; background: var(--pg-colors-background-alt, #f1f5f9); }
606
- .pg-th--dragging { opacity: 0.72; cursor: grabbing !important; }
607
- .pg-th__serial-label { font-size: 11px; opacity: 0.45; }
608
- .pg-header-checkbox { cursor: pointer; width: 16px; height: 16px; }
609
-
610
- /* ──────────────────── Column group header rows ──────────────────── */
611
- .pg-header-group-row {
612
- position: relative;
613
- flex-shrink: 0;
614
- height: var(--pg-header-row-height, 44px);
615
- background: var(--pg-colors-header-background, #f8fafc);
616
- border-bottom: 1px solid var(--pg-colors-border, #e2e8f0);
617
- }
618
- .pg-th--group {
619
- position: absolute;
620
- top: 0;
621
- height: 100%;
622
- display: flex;
623
- align-items: center;
624
- overflow: hidden;
625
- border-right: 1px solid var(--pg-colors-border, #e2e8f0);
626
- background: var(--pg-colors-header-background, #f8fafc);
627
- cursor: pointer;
628
- outline: none;
629
- transition: background var(--pg-transitions-duration-fast, 100ms);
630
- font-weight: var(--pg-typography-header-font-weight, 600);
631
- font-size: var(--pg-typography-font-size-sm, 13px);
632
- color: var(--pg-colors-text-primary, #1e293b);
633
- user-select: none;
634
- }
635
- .pg-th--group:hover,
636
- .pg-th--group:focus-visible { background: var(--pg-colors-header-hover, #f1f5f9); }
637
- .pg-th--group--collapsed {
638
- background: var(--pg-colors-background-alt, #f1f5f9);
639
- justify-content: center;
640
- }
641
- // .pg-th--group--collapsed .pg-th__label { display: none; }
642
- .pg-th__collapse-btn {
643
- flex-shrink: 0;
644
- display: flex;
645
- align-items: center;
646
- justify-content: center;
647
- width: 20px;
648
- height: 20px;
649
- margin-right: 4px;
650
- border-radius: var(--pg-sizing-border-radius, 4px);
651
- color: var(--pg-colors-text-secondary, #475569);
652
- transition: background var(--pg-transitions-duration-fast, 100ms),
653
- color var(--pg-transitions-duration-fast, 100ms);
654
- }
655
- .pg-th--group:hover .pg-th__collapse-btn,
656
- .pg-th--group:focus-visible .pg-th__collapse-btn {
657
- background: var(--pg-colors-background-alt, #f1f5f9);
658
- color: var(--pg-colors-primary, #2563eb);
659
- }
660
- .pg-th__resize-handle--group {
661
- position: absolute;
662
- right: 0;
663
- top: 0;
664
- width: 6px;
665
- height: 100%;
666
- cursor: col-resize;
667
- display: flex;
668
- align-items: center;
669
- justify-content: center;
670
- opacity: 0;
671
- color: var(--pg-colors-resize-handle-color, #e2e8f0);
672
- z-index: 6;
673
- transition: opacity var(--pg-transitions-duration-fast, 100ms);
674
- }
675
- .pg-th--group:hover .pg-th__resize-handle--group { opacity: 1; }
676
-
677
- /* ── Flat columns alongside grouped headers ── */
678
- /* A flat (ungrouped) leaf column in a grid that has grouped columns must span
679
- the full header height (group rows + leaf row) so it does not appear as a
680
- short stub next to taller group header cells.
681
- Strategy: keep the cell in normal flex flow (preserves horizontal layout),
682
- give it the combined height, and translateY it upward so its visual top
683
- aligns with the top of the header area. The panel header overflow:hidden
684
- clips exactly at the combined height, so nothing leaks outside the header.
685
- --pg-group-rows-count is set in JS by HeaderRenderer. */
686
- .pg-th--no-group {
687
- align-self: flex-start;
688
- position: relative;
689
- z-index: 2;
690
- height: calc((var(--pg-group-rows-count, 0) + 1) * var(--pg-header-row-height, 44px));
691
- transform: translate(var(--pg-drag-x, 0px), calc(var(--pg-group-rows-count, 0) * -1 * var(--pg-header-row-height, 44px)));
692
- }
693
-
694
- .pg-group-drop-indicator {
695
- position: absolute;
696
- top: 0;
697
- width: 2px;
698
- height: var(--pg-header-row-height, 44px);
699
- background: var(--pg-colors-primary, #2563eb);
700
- z-index: 20;
701
- pointer-events: none;
702
- border-radius: 1px;
703
- }
704
- .pg-th-group-filler { position: absolute; top: 0; height: 100%; }
705
- .pg-th--standalone-filler {
706
- position: absolute;
707
- top: 0;
708
- height: 100%;
709
- background: var(--pg-colors-header-background, #f8fafc);
710
- border-right: 1px solid var(--pg-colors-border, #e2e8f0);
711
- pointer-events: none;
712
- cursor: default;
713
- }
714
- /* Filler cell in a group row for columns with no ancestor group at this depth.
715
- Blends with the header background — makes flat/shallow columns appear to span
716
- the full header height. No interactive elements, no bottom border. */
717
- .pg-th--depth-filler {
718
- position: absolute;
719
- top: 0;
720
- height: 100%;
721
- background: var(--pg-colors-header-background, #f8fafc);
722
- border-right: 1px solid var(--pg-colors-border, #e2e8f0);
723
- pointer-events: none;
724
- cursor: default;
725
- z-index: 0;
726
- }
727
-
728
- @keyframes pg-drag-indicator-in { from { opacity: 0; } to { opacity: 1; } }
729
-
730
- /* Smooth column-shift animation — enabled ONLY while actively dragging a column */
731
- .pg-grid--col-dragging .pg-th[data-col-id],
732
- .pg-grid--col-dragging .pg-cell[data-col-id] {
733
- transform: translateX(var(--pg-drag-x, 0px));
734
- transition: transform 180ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
735
- will-change: transform;
736
- }
737
- .pg-grid--col-dragging .pg-th--no-group[data-col-id] {
738
- transform: translate(var(--pg-drag-x, 0px), calc(var(--pg-group-rows-count, 0) * -1 * var(--pg-header-row-height, 44px)));
739
- }
740
-
741
- /* During header auto-scroll the transforms update every RAF tick — disable the
742
- transition so cells snap instantly rather than endlessly chasing a moving target */
743
- .pg-grid--col-autoscrolling .pg-th[data-col-id],
744
- .pg-grid--col-autoscrolling .pg-cell[data-col-id] {
745
- transition: none;
746
- }
747
- /* Live-preview path (store mutations during drag): suppress all transitions */
748
- .pg-grid--drag-preview-sync .pg-th[data-col-id],
749
- .pg-grid--drag-preview-sync .pg-cell[data-col-id] {
750
- transition: none !important;
751
- }
752
-
753
- /* ── Group-header CSS-transform drag ─────────────────────────────────────────
754
- * Cells shift via --pg-drag-x. The --pg-drag-transition variable is 0ms for
755
- * the actively-dragged group (injected by display-group-drag-handler.ts) and
756
- * falls back to the default 180ms for displaced neighbours — giving AG Grid-
757
- * style smooth animation for everything except the grabbed group itself.
758
- * body cells use the same variable so leaf columns and data rows stay in sync.
759
- */
760
- .pg-grid--group-dragging .pg-th--group {
761
- transform: translateX(var(--pg-drag-x, 0px));
762
- transition: transform var(--pg-drag-transition, 180ms cubic-bezier(0.25, 0.46, 0.45, 0.94));
763
- will-change: transform;
764
- }
765
- .pg-grid--group-dragging .pg-th[data-col-id] {
766
- transform: translateX(var(--pg-drag-x, 0px));
767
- transition: transform var(--pg-drag-transition, 180ms cubic-bezier(0.25, 0.46, 0.45, 0.94));
768
- }
769
- .pg-grid--group-dragging .pg-cell[data-col-id] {
770
- transform: translateX(var(--pg-drag-x, 0px));
771
- transition: transform var(--pg-drag-transition, 180ms cubic-bezier(0.25, 0.46, 0.45, 0.94));
772
- }
773
- .pg-grid--group-dragging .pg-th--depth-filler {
774
- transform: translateX(var(--pg-drag-x, 0px));
775
- }
776
- .pg-grid--group-dragging .pg-th--no-group[data-col-id] {
777
- transform: translate(var(--pg-drag-x, 0px), calc(var(--pg-group-rows-count, 0) * -1 * var(--pg-header-row-height, 44px)));
778
- transition: transform var(--pg-drag-transition, 180ms cubic-bezier(0.25, 0.46, 0.45, 0.94));
779
- }
780
-
781
- /* Column drag ghost (floating preview chip that follows the cursor) */
782
- .pg-col-drag-ghost {
783
- position: fixed;
784
- pointer-events: none;
785
- z-index: 9999;
786
- display: flex;
787
- align-items: center;
788
- gap: var(--pg-drag-ghost-gap, 8px);
789
- padding: 5px 12px 5px 10px;
790
- background: var(--pg-colors-drag-ghost-background, #fff);
791
- border: 1.5px solid var(--pg-colors-primary, #2563eb);
792
- border-radius: var(--pg-borders-radius-md, 6px);
793
- box-shadow: 0 6px 24px rgba(0,0,0,0.13), 0 2px 8px rgba(37, 99, 235, 0.12);
794
- font-family: var(--pg-typography-font-family, system-ui, sans-serif);
795
- font-size: var(--pg-typography-font-size-sm, 12px);
796
- font-weight: var(--pg-typography-font-weight-semi-bold, 600);
797
- color: var(--pg-colors-header-text, #374151);
798
- white-space: nowrap;
799
- user-select: none;
800
- transform: translateY(-50%);
801
- transition:
802
- border-color var(--pg-transitions-duration-fast, 100ms),
803
- box-shadow var(--pg-transitions-duration-fast, 100ms);
804
- }
805
- .pg-col-drag-ghost__icon {
806
- display: inline-flex;
807
- align-items: center;
808
- flex-shrink: 0;
809
- color: var(--pg-colors-primary, #2563eb);
810
- opacity: 0.7;
811
- }
812
- .pg-col-drag-ghost__label {
813
- flex: 1;
814
- min-width: 0;
815
- }
816
-
817
- /* Default icon visibility */
818
- .pg-col-drag-ghost__icon--move { display: inline-flex; }
819
- .pg-col-drag-ghost__icon--ban { display: none; }
820
- .pg-col-drag-ghost__icon--arrow-left { display: none; }
821
- .pg-col-drag-ghost__icon--arrow-right { display: none; }
822
-
823
- /* Hide-column state: amber ghost + eyeOff icon */
824
- .pg-col-drag-ghost__icon--hide { display: none; }
825
- .pg-col-drag-ghost--hide .pg-col-drag-ghost__icon--move { display: none; }
826
- .pg-col-drag-ghost--hide .pg-col-drag-ghost__icon--hide { display: inline-flex; color: var(--pg-colors-warning, #f59e0b); }
827
- .pg-col-drag-ghost--hide {
828
- border-color: var(--pg-colors-warning, #f59e0b);
829
- box-shadow: 0 6px 24px rgba(245,158,11,0.13), 0 2px 8px rgba(245,158,11,0.12);
830
- color: var(--pg-colors-warning, #f59e0b);
831
- }
832
-
833
- /* No-drop state: red ghost + ban icon */
834
- .pg-col-drag-ghost--no-drop {
835
- border-color: var(--pg-colors-danger, #ef4444);
836
- box-shadow: 0 6px 24px rgba(239,68,68,0.13), 0 2px 8px rgba(239,68,68,0.12);
837
- color: var(--pg-colors-danger, #ef4444);
838
- }
839
- .pg-col-drag-ghost--no-drop .pg-col-drag-ghost__icon { color: var(--pg-colors-danger, #ef4444); }
840
- .pg-col-drag-ghost--no-drop .pg-col-drag-ghost__icon--move { display: none; }
841
- .pg-col-drag-ghost--no-drop .pg-col-drag-ghost__icon--ban { display: inline-flex; }
842
-
843
- /* Outside-grid drop state: red ghost signals "drop = hide all columns in group" */
844
- .pg-col-drag-ghost--outside {
845
- border-color: var(--pg-colors-danger, #ef4444);
846
- box-shadow: 0 6px 24px rgba(239,68,68,0.18), 0 2px 8px rgba(239,68,68,0.14);
847
- color: var(--pg-colors-danger, #ef4444);
848
- opacity: 0.85;
849
- }
850
- .pg-col-drag-ghost--outside .pg-col-drag-ghost__label::after {
851
- content: ' (hide)';
852
- font-size: 10px;
853
- opacity: 0.7;
854
- }
855
-
856
- /* Auto-scroll state: directional arrow replaces move icon */
857
- @keyframes pg-scroll-arrow-left { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(-4px); } }
858
- @keyframes pg-scroll-arrow-right { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(4px); } }
859
-
860
- .pg-col-drag-ghost--scroll-left .pg-col-drag-ghost__icon--move,
861
- .pg-col-drag-ghost--scroll-right .pg-col-drag-ghost__icon--move { display: none; }
862
- .pg-col-drag-ghost--scroll-left .pg-col-drag-ghost__icon--arrow-left {
863
- display: inline-flex;
864
- animation: pg-scroll-arrow-left 700ms ease-in-out infinite;
865
- }
866
- .pg-col-drag-ghost--scroll-right .pg-col-drag-ghost__icon--arrow-right {
867
- display: inline-flex;
868
- animation: pg-scroll-arrow-right 700ms ease-in-out infinite;
869
- }
870
-
871
- /* ──────────────────── Filter Row ──────────────────── */
872
- .pg-drag-preview {
873
- position: fixed;
874
- pointer-events: none;
875
- z-index: 99999;
876
- display: flex;
877
- align-items: center;
878
- gap: var(--pg-drag-preview-gap, 8px);
879
- padding: var(--pg-drag-preview-padding, 6px 12px);
880
- border-radius: var(--pg-borders-radius-md, 6px);
881
- box-shadow: var(--pg-shadows-drag-preview, 0 4px 16px rgba(0,0,0,0.18));
882
- font-size: var(--pg-typography-font-size-md, 13px);
883
- font-weight: var(--pg-typography-font-weight-medium, 500);
884
- white-space: nowrap;
885
- will-change: transform;
886
- background: var(--pg-colors-drag-preview-background, var(--pg-drag-preview-bg, #fff));
887
- border: 1px solid var(--pg-colors-drag-preview-border, var(--pg-drag-preview-border, #e0e0e0));
888
- color: var(--pg-colors-text-primary, var(--pg-text-primary, #222));
889
- top: 0;
890
- left: 0;
891
- transform: translate(-9999px, -9999px);
892
- }
893
- .pg-drag-preview__avatar {
894
- width: var(--pg-drag-preview-avatar-size, 24px);
895
- height: var(--pg-drag-preview-avatar-size, 24px);
896
- background: var(--pg-colors-primary, var(--pg-primary, #2563eb));
897
- overflow: hidden;
898
- flex-shrink: 0;
899
- }
900
- .pg-drag-preview__avatar--circle { border-radius: 50%; }
901
- .pg-drag-preview__avatar--square { border-radius: var(--pg-borders-radius-sm, 4px); }
902
- .pg-drag-preview__avatar-img {
903
- width: 100%;
904
- height: 100%;
905
- object-fit: cover;
906
- }
907
- .pg-drag-preview__label {
908
- flex: 1;
909
- min-width: 0;
910
- }
911
- .pg-drag-preview__badge {
912
- background: var(--pg-colors-primary, var(--pg-primary, #2563eb));
913
- color: var(--pg-colors-primary-contrast, #fff);
914
- border-radius: var(--pg-borders-radius-pill, 999px);
915
- padding: 1px 7px;
916
- font-size: var(--pg-typography-font-size-xs, 11px);
917
- font-weight: var(--pg-typography-font-weight-semi-bold, 600);
918
- min-width: 20px;
919
- text-align: center;
920
- }
921
-
922
- .pg-filter-cell {
923
- display: flex;
924
- align-items: center;
925
- flex-shrink: 0;
926
- padding: 0 6px;
927
- border-right: 1px solid var(--pg-colors-border, #e2e8f0);
928
- }
929
- .pg-filter-cell:last-child { border-right: none; }
930
- .pg-filter-cell--checkbox {
931
- width: 44px;
932
- min-width: 44px;
933
- max-width: 44px;
934
- flex-shrink: 0;
935
- }
936
- .pg-filter-cell--serial {
937
- width: 52px;
938
- min-width: 52px;
939
- max-width: 52px;
940
- flex-shrink: 0;
941
- }
942
- .pg-filter-input {
943
- width: 100%;
944
- height: 24px;
945
- padding: 0 8px;
946
- border: 1px solid var(--pg-colors-border, #e2e8f0);
947
- border-radius: var(--pg-borders-radius-sm, 4px);
948
- font-size: var(--pg-typography-font-size-sm, 12px);
949
- font-family: inherit;
950
- background: var(--pg-colors-surface, #fff);
951
- color: inherit;
952
- outline: none;
953
- transition: border-color var(--pg-transitions-duration-fast, 100ms);
954
- }
955
- .pg-filter-input:focus { border-color: var(--pg-colors-border-focus, #2563eb); }
956
-
957
- /* ──────────────────── Filter Panel ──────────────────── */
958
- .pg-filter-panel {
959
- position: absolute;
960
- z-index: var(--pg-z-index-filter-panel, 200);
961
- min-width: 270px;
962
- max-width: 320px;
963
- width: max-content;
964
- background: var(--pg-colors-surface, #fff);
965
- border: 1px solid var(--pg-colors-border, #e2e8f0);
966
- border-radius: var(--pg-borders-radius-md, 6px);
967
- box-shadow: var(--pg-shadows-lg, 0 8px 24px rgba(0,0,0,.12));
968
- overflow: hidden;
969
- font-size: var(--pg-typography-font-size-sm, 13px);
970
- color: var(--pg-colors-text, #1e293b);
971
- user-select: none;
972
- }
973
-
974
- /* ── Condition filter ── */
975
- .pg-filter-cond-wrap { padding: 10px; display: flex; flex-direction: column; gap: 6px; }
976
-
977
- .pg-filter-cond__row { display: flex; flex-direction: column; gap: 4px; }
978
- .pg-filter-cond__row--hidden { display: none; }
979
-
980
- .pg-filter-cond__select {
981
- width: 100%;
982
- height: 30px;
983
- padding: 0 8px;
984
- border: 1px solid var(--pg-colors-border, #e2e8f0);
985
- border-radius: var(--pg-borders-radius-sm, 4px);
986
- background: var(--pg-colors-surface, #fff);
987
- color: var(--pg-colors-text, #1e293b);
988
- font-size: inherit;
989
- font-family: inherit;
990
- cursor: pointer;
991
- outline: none;
992
- transition: border-color var(--pg-transitions-duration-fast, 100ms);
993
- }
994
- .pg-filter-cond__select:focus { border-color: var(--pg-colors-border-focus, #2563eb); }
995
-
996
- .pg-filter-cond__inputs { display: flex; align-items: center; gap: 4px; }
997
- .pg-filter-cond__inputs--hidden { display: none; }
998
- /* Stack inputs vertically in range (Between) mode so the panel never overflows horizontally */
999
- .pg-filter-cond__inputs--range { flex-direction: column; align-items: stretch; gap: 4px; }
1000
- .pg-filter-cond__inputs--range .pg-filter-cond__range-sep {
1001
- text-align: center;
1002
- padding: 2px 0;
1003
- color: var(--pg-colors-text-secondary, #64748b);
1004
- font-size: var(--pg-typography-font-size-xs, 11px);
1005
- font-weight: 500;
1006
- }
1007
-
1008
- .pg-filter-cond__input {
1009
- flex: 1;
1010
- height: 30px;
1011
- padding: 0 8px;
1012
- border: 1px solid var(--pg-colors-border, #e2e8f0);
1013
- border-radius: var(--pg-borders-radius-sm, 4px);
1014
- background: var(--pg-colors-surface, #fff);
1015
- color: var(--pg-colors-text, #1e293b);
1016
- font-size: inherit;
1017
- font-family: inherit;
1018
- outline: none;
1019
- padding: 6px;
1020
- transition: border-color var(--pg-transitions-duration-fast, 100ms);
1021
- }
1022
- .pg-filter-cond__input:focus { border-color: var(--pg-colors-border-focus, #2563eb); }
1023
- .pg-filter-cond__input--hidden { display: none; }
1024
-
1025
- .pg-filter-cond__range-sep {
1026
- flex-shrink: 0;
1027
- font-size: var(--pg-typography-font-size-xs, 11px);
1028
- color: var(--pg-colors-text-secondary, #475569);
1029
- padding: 0 2px;
1030
- }
1031
- .pg-filter-cond__range-sep--hidden { display: none; }
1032
-
1033
- /* ── Logic toggle row (AND / OR / None) ── */
1034
- .pg-filter-logic {
1035
- display: flex;
1036
- gap: 4px;
1037
- padding: 4px 0 2px;
1038
- }
1039
- .pg-filter-logic--hidden { display: none; }
1040
-
1041
- .pg-filter-logic__btn {
1042
- flex: 1;
1043
- height: 26px;
1044
- padding: 0 6px;
1045
- border: 1px solid var(--pg-colors-border, #e2e8f0);
1046
- border-radius: var(--pg-borders-radius-sm, 4px);
1047
- background: var(--pg-colors-surface, #fff);
1048
- color: var(--pg-colors-text-secondary, #475569);
1049
- font-size: var(--pg-typography-font-size-xs, 11px);
1050
- font-family: inherit;
1051
- font-weight: 500;
1052
- cursor: pointer;
1053
- text-align: center;
1054
- transition: background var(--pg-transitions-duration-fast, 100ms),
1055
- color var(--pg-transitions-duration-fast, 100ms),
1056
- border-color var(--pg-transitions-duration-fast, 100ms);
1057
- }
1058
- .pg-filter-logic__btn:hover { background: var(--pg-colors-background-alt, #f1f5f9); }
1059
- .pg-filter-logic__btn--active {
1060
- background: var(--pg-colors-primary, #2563eb);
1061
- color: #fff;
1062
- border-color: var(--pg-colors-primary, #2563eb);
1063
- }
1064
-
1065
- /* ── Set filter (dropdown / array) ── */
1066
- .pg-filter-set { display: flex; flex-direction: column; }
1067
-
1068
- .pg-filter-set__search {
1069
- padding: 8px 10px 4px;
1070
- }
1071
- .pg-filter-set__search-input {
1072
- width: 100%;
1073
- height: 30px;
1074
- padding: 0 10px;
1075
- border: 1px solid var(--pg-colors-border, #e2e8f0);
1076
- border-radius: var(--pg-borders-radius-sm, 4px);
1077
- background: var(--pg-colors-surface, #fff);
1078
- color: var(--pg-colors-text, #1e293b);
1079
- font-size: inherit;
1080
- font-family: inherit;
1081
- box-sizing: border-box;
1082
- outline: none;
1083
- transition: border-color var(--pg-transitions-duration-fast, 100ms);
1084
- }
1085
- .pg-filter-set__search-input:focus { border-color: var(--pg-colors-border-focus, #2563eb); }
1086
-
1087
- .pg-filter-set__divider {
1088
- height: 1px;
1089
- background: var(--pg-colors-border, #e2e8f0);
1090
- margin: 2px 0;
1091
- }
1092
-
1093
- /* Select All item */
1094
- .pg-filter-set__item {
1095
- display: flex;
1096
- align-items: center;
1097
- gap: 8px;
1098
- height: 28px;
1099
- padding: 0 10px;
1100
- cursor: pointer;
1101
- transition: background var(--pg-transitions-duration-fast, 100ms);
1102
- box-sizing: border-box;
1103
- position: absolute;
1104
- left: 0;
1105
- right: 0;
1106
- }
1107
- .pg-filter-set__item:hover { background: var(--pg-colors-background-alt, #f1f5f9); }
1108
- .pg-filter-set__item--select-all {
1109
- position: static;
1110
- font-weight: 500;
1111
- color: var(--pg-colors-text, #1e293b);
1112
- }
1113
- .pg-filter-set__item-label {
1114
- overflow: hidden;
1115
- text-overflow: ellipsis;
1116
- white-space: nowrap;
1117
- }
1118
- .pg-filter-set__item-label--blank { color: var(--pg-colors-text-disabled, #94a3b8); font-style: italic; }
1119
-
1120
- .pg-filter-set__checkbox {
1121
- flex-shrink: 0;
1122
- width: 14px;
1123
- height: 14px;
1124
- cursor: pointer;
1125
- accent-color: var(--pg-colors-primary, #2563eb);
1126
- }
1127
-
1128
- /* Virtual scroll containers */
1129
- .pg-filter-set__list {
1130
- overflow-y: auto;
1131
- overflow-x: hidden;
1132
- position: relative;
1133
- scrollbar-width: thin;
1134
- scrollbar-color: var(--pg-colors-border, #e2e8f0) transparent;
1135
- }
1136
- .pg-filter-set__list::-webkit-scrollbar { width: 6px; }
1137
- .pg-filter-set__list::-webkit-scrollbar-track { background: transparent; }
1138
- .pg-filter-set__list::-webkit-scrollbar-thumb {
1139
- background: var(--pg-colors-border, #e2e8f0);
1140
- border-radius: 3px;
1141
- }
1142
- .pg-filter-set__list-inner { position: relative; width: 100%; }
1143
-
1144
- /* ── Panel footer ── */
1145
- .pg-filter-panel__footer {
1146
- display: flex;
1147
- align-items: center;
1148
- justify-content: flex-end;
1149
- padding: 8px 10px;
1150
- // border-top: 1px solid var(--pg-colors-border, #e2e8f0);
1151
- // background: var(--pg-colors-background, #f8fafc);
1152
- }
1153
-
1154
- .pg-filter-panel__clear-btn {
1155
- height: 28px;
1156
- padding: 0 14px;
1157
- border: 1px solid var(--pg-colors-border, #e2e8f0);
1158
- border-radius: var(--pg-borders-radius-sm, 4px);
1159
- background: var(--pg-colors-surface, #fff);
1160
- color: var(--pg-colors-text-secondary, #475569);
1161
- font-size: var(--pg-typography-font-size-sm, 12px);
1162
- font-family: inherit;
1163
- cursor: pointer;
1164
- transition: background var(--pg-transitions-duration-fast, 100ms),
1165
- border-color var(--pg-transitions-duration-fast, 100ms),
1166
- color var(--pg-transitions-duration-fast, 100ms);
1167
- }
1168
- .pg-filter-panel__clear-btn:hover {
1169
- background: var(--pg-colors-background-alt, #f1f5f9);
1170
- border-color: var(--pg-colors-text-secondary, #475569);
1171
- color: var(--pg-colors-text, #1e293b);
1172
- }
1173
-
1174
- /* ──────────────────── Rows ──────────────────── */
1175
- .pg-row {
1176
- display: flex;
1177
- align-items: stretch;
1178
- position: absolute;
1179
- left: 0;
1180
- width: 100%;
1181
- border-bottom: 1px solid var(--pg-colors-border, #e2e8f0);
1182
- background: var(--pg-colors-row-background, #fff);
1183
- transition: background var(--pg-transitions-duration-fast, 100ms);
1184
- }
1185
- .pg-row--hover { background: var(--pg-colors-row-hover, #f0f7ff) !important; }
1186
- .pg-row--alt { background: var(--pg-colors-row-background-alt, #f8fafc); }
1187
- .pg-row--selected {
1188
- background: var(--pg-colors-row-selected, #eff6ff) !important;
1189
- outline: none;
1190
- }
1191
- .pg-row--selected .pg-cell { color: inherit; }
1192
- .pg-row--group {
1193
- background: var(--pg-colors-group-row-background, #f8fafc);
1194
- font-weight: var(--pg-typography-font-weight-semi-bold, 600);
1195
- // border-left: var(--pg-group-row-border-width, 3px) solid var(--pg-colors-primary, #2563eb);
1196
- cursor: pointer;
1197
- }
1198
- .pg-row--group:hover,
1199
- .pg-row--group.pg-row--hover {
1200
- background: var(--pg-colors-group-row-hover, #eff2ff) !important;
1201
- }
1202
- .pg-row--group:hover .pg-row-group__toggle,
1203
- .pg-row--group.pg-row--hover .pg-row-group__toggle {
1204
- background: var(--pg-colors-group-toggle-hover, rgba(37, 99, 235, 0.1));
1205
- color: var(--pg-colors-primary, #2563eb);
1206
- }
1207
-
1208
- /* ──────────────────── Group footer row ──────────────────── */
1209
- /*
1210
- * Appears below the last leaf child of each expanded group.
1211
- * Shows the same aggregate values as the group header row (AG Grid groupIncludeFooter).
1212
- * Cells are fully selectable and copyable; editing is blocked because values are computed.
1213
- */
1214
- .pg-row--group-footer {
1215
- background: var(--pg-colors-group-footer-background, #eef2fa);
1216
- font-style: italic;
1217
- font-weight: var(--pg-typography-font-weight-semi-bold, 600);
1218
- border-bottom: 2px solid var(--pg-colors-primary-light, #bfdbfe);
1219
- cursor: default;
1220
- }
1221
- .pg-row--group-footer:hover,
1222
- .pg-row--group-footer.pg-row--hover {
1223
- background: var(--pg-colors-group-footer-hover, #e0e9f8) !important;
1224
- }
1225
- /* Level-based indentation mirrors the group header rules */
1226
- .pg-row--group-footer[data-level="0"] .pg-row-group__cell { padding-left: var(--pg-group-indent-0, 8px); }
1227
- .pg-row--group-footer[data-level="1"] .pg-row-group__cell { padding-left: var(--pg-group-indent-1, 28px); }
1228
- .pg-row--group-footer[data-level="2"] .pg-row-group__cell { padding-left: var(--pg-group-indent-2, 48px); }
1229
- .pg-row--group-footer[data-level="3"] .pg-row-group__cell { padding-left: var(--pg-group-indent-3, 68px); }
1230
- .pg-row--group-footer[data-level="4"] .pg-row-group__cell { padding-left: var(--pg-group-indent-4, 88px); }
1231
- .pg-row--group-footer[data-level="5"] .pg-row-group__cell { padding-left: var(--pg-group-indent-5, 108px); }
1232
- .pg-row--group-footer .pg-row-group__label {
1233
- color: var(--pg-colors-text-secondary, #475569);
1234
- }
1235
- /* Dark-mode overrides */
1236
- .pg-grid[data-theme="dark"] .pg-row--group-footer {
1237
- background: var(--pg-colors-group-footer-background, rgba(37, 99, 235, 0.06));
1238
- border-bottom-color: rgba(96, 165, 250, 0.28);
1239
- }
1240
- .pg-grid[data-theme="dark"] .pg-row--group-footer:hover,
1241
- .pg-grid[data-theme="dark"] .pg-row--group-footer.pg-row--hover {
1242
- background: var(--pg-colors-group-footer-hover, rgba(37, 99, 235, 0.11)) !important;
1243
- }
1244
- .pg-grid[data-theme="dark"] .pg-row--group-footer .pg-row-group__label {
1245
- color: var(--pg-colors-text-secondary, #94a3b8);
1246
- }
1247
-
1248
- /* ──────────────────── Cells ──────────────────── */
1249
- .pg-cell {
1250
- display: flex;
1251
- align-items: center;
1252
- flex-shrink: 0;
1253
- min-width: var(--pg-sizing-column-min-width, 40px);
1254
- border-right: 1px solid transparent;
1255
- padding: 0;
1256
- overflow: hidden;
1257
- position: relative;
1258
- }
1259
- .pg-cell--v-border { border-right-color: var(--pg-colors-border, #e2e8f0); }
1260
- .pg-cell:last-child { border-right: none; }
1261
- .pg-cell--align-right { justify-content: flex-end; }
1262
- .pg-cell--align-center { justify-content: center; }
1263
- .pg-cell--align-right .pg-cell__inner { text-align: right; }
1264
- .pg-cell--align-center .pg-cell__inner { text-align: center; }
1265
-
1266
- /* ─── Cell selection (CSS-based, replaces canvas) ─── */
1267
- /* Suppress the browser's native focus ring — the grid uses its own blue
1268
- box-shadow indicator on .pg-cell--active-cell instead. */
1269
- .pg-cell { user-select: none; outline: none; }
1270
-
1271
- /*
1272
- * Range selection — edge borders drawn via ::after so CSS border corners
1273
- * always connect cleanly (no box-shadow joining artefacts).
1274
- * The JS engine adds sel-top/right/bottom/left only on cells that sit on
1275
- * the outer edge of the range; interior cells carry no edge classes.
1276
- */
1277
- .pg-cell--in-selection {
1278
- background-color: var(--pg-colors-selection-background, aliceblue) !important;
1279
- position: relative;
1280
- z-index: 1;
1281
- }
1282
- .pg-cell--in-selection::after {
1283
- content: '';
1284
- position: absolute;
1285
- inset: 0;
1286
- border: 0 solid var(--pg-colors-primary, #2563eb);
1287
- pointer-events: none;
1288
- }
1289
- .pg-cell--sel-top::after { border-top-width: 1px; }
1290
- .pg-cell--sel-bottom::after { border-bottom-width: 1px; }
1291
- .pg-cell--sel-left::after { border-left-width: 1px; }
1292
- .pg-cell--sel-right::after { border-right-width: 1px; }
1293
-
1294
- /* Active (focused) cell — solid 2px inset border, no background */
1295
- .pg-cell--active-cell {
1296
- background-color: transparent !important;
1297
- box-shadow: inset 0 0 0 2px var(--pg-colors-primary, #2563eb) !important;
1298
- position: relative;
1299
- z-index: 2;
1300
- outline: none;
1301
- }
1302
- /* Suppress the ::after edge overlay only when the active cell is NOT inside a selection */
1303
- .pg-cell--active-cell:not(.pg-cell--in-selection)::after { content: none; }
1304
-
1305
- /* Active cell inside a range — selection wins entirely: no 2px border, full selection look */
1306
- .pg-cell--in-selection.pg-cell--active-cell {
1307
- background-color: var(--pg-colors-selection-background, aliceblue) !important;
1308
- box-shadow: none !important;
1309
- }
1310
-
1311
- /* Dark-mode overrides */
1312
- .pg-grid[data-theme="dark"] .pg-cell--in-selection {
1313
- background-color: rgba(37,99,235,0.18) !important;
1314
- }
1315
- .pg-grid[data-theme="dark"] .pg-cell--sel-top { --_t: 2px; }
1316
- .pg-grid[data-theme="dark"] .pg-cell--sel-bottom { --_b: -2px; }
1317
- .pg-grid[data-theme="dark"] .pg-cell--sel-left { --_l: 2px; }
1318
- .pg-grid[data-theme="dark"] .pg-cell--sel-right { --_r: -2px; }
1319
- .pg-grid[data-theme="dark"] .pg-cell--active-cell {
1320
- background-color: rgba(37,99,235,0.25) !important;
1321
- box-shadow: inset 0 0 0 2px #60a5fa !important;
1322
- }
1323
- .pg-grid[data-theme="dark"] .pg-cell--in-selection.pg-cell--active-cell {
1324
- background-color: rgba(37,99,235,0.18) !important;
1325
- box-shadow:
1326
- inset 0 var(--_t) 0 0 #60a5fa,
1327
- inset 0 var(--_b) 0 0 #60a5fa,
1328
- inset var(--_l) 0 0 0 #60a5fa,
1329
- inset var(--_r) 0 0 0 #60a5fa !important;
1330
- }
1331
-
1332
- /* ─── Group aggregate cells ─── */
1333
- /*
1334
- * Aggregate values are displayed inside .pg-cell--agg cells that sit directly
1335
- * under their column headers, aligned with normal data-row cells via the same
1336
- * [data-col-id] width rules managed by ColumnStyleManager.
1337
- */
1338
- .pg-cell--agg {
1339
- color: var(--pg-colors-agg-text, var(--pg-colors-text-secondary, #475569));
1340
- font-style: italic;
1341
- font-weight: var(--pg-typography-font-weight-semi-bold, 600);
1342
- }
1343
- .pg-grid[data-theme="dark"] .pg-cell--agg {
1344
- color: var(--pg-colors-agg-text, var(--pg-colors-text-secondary, #94a3b8));
1345
- }
1346
-
1347
- /* ─── Copy / Cut flash feedback ─── */
1348
- /*
1349
- * background-color: !important on pg-cell--in-selection blocks keyframe bg changes.
1350
- * Use a ::after overlay instead — it's a separate layer, no !important conflict.
1351
- */
1352
- @keyframes pg-copy-flash-overlay {
1353
- 0% { opacity: 0; }
1354
- 15% { opacity: 1; }
1355
- 100% { opacity: 0; }
1356
- }
1357
- @keyframes pg-cut-flash-overlay {
1358
- 0% { opacity: 0; }
1359
- 15% { opacity: 1; }
1360
- 100% { opacity: 0; }
1361
- }
1362
- /*
1363
- * Flash overlay uses ::before so it never conflicts with the ::after
1364
- * pseudo-element that draws the selection edge borders.
1365
- */
1366
- .pg-cell--copy-flash::before,
1367
- .pg-cell--cut-flash::before {
1368
- content: '';
1369
- position: absolute;
1370
- inset: 0;
1371
- pointer-events: none;
1372
- z-index: 5;
1373
- }
1374
- .pg-cell--copy-flash::before {
1375
- background: rgba(59, 130, 246, 0.45);
1376
- animation: pg-copy-flash-overlay 0.75s ease-out forwards;
1377
- }
1378
- .pg-cell--cut-flash::before {
1379
- background: rgba(239, 68, 68, 0.45);
1380
- animation: pg-cut-flash-overlay 0.75s ease-out forwards;
1381
- }
1382
- /* Dark mode uses stronger overlay */
1383
- .pg-grid[data-theme="dark"] .pg-cell--copy-flash::before {
1384
- background: rgba(99, 165, 253, 0.5);
1385
- }
1386
- .pg-grid[data-theme="dark"] .pg-cell--cut-flash::before {
1387
- background: rgba(252, 100, 100, 0.5);
1388
- }
1389
-
1390
- /* ─── Fill success flash ─── */
1391
- /*
1392
- * Applied to the newly filled cells after a fill-handle drag completes.
1393
- * Uses ::before (same as copy/cut flash) so it never conflicts with the
1394
- * selection edge border drawn on ::after.
1395
- */
1396
- @keyframes pg-fill-flash-overlay {
1397
- 0% { opacity: 0; }
1398
- 20% { opacity: 1; }
1399
- 100% { opacity: 0; }
1400
- }
1401
- .pg-cell--fill-flash::before {
1402
- content: '';
1403
- position: absolute;
1404
- inset: 0;
1405
- pointer-events: none;
1406
- z-index: 5;
1407
- background: rgba(34, 197, 94, 0.45);
1408
- animation: pg-fill-flash-overlay 0.75s ease-out forwards;
1409
- }
1410
- .pg-grid[data-theme="dark"] .pg-cell--fill-flash::before {
1411
- background: rgba(74, 222, 128, 0.5);
1412
- }
1413
-
1414
- /* ─── Fill handle ─── */
1415
- /*
1416
- * The fill handle is a small drag target at the bottom-right corner of the
1417
- * primary selection range. It lives inside the corner cell as an absolutely-
1418
- * positioned child so it scrolls with the grid naturally.
1419
- *
1420
- * pg-cell--has-fill-handle lets the handle extend 4 px past the cell edge
1421
- * (standard AG Grid behaviour) by lifting overflow:hidden on that one cell.
1422
- *
1423
- * Dragging from the handle copies the source range into the dragged area in
1424
- * one direction at a time; a dashed overlay (pg-cell--fill-preview) previews
1425
- * the fill area before the mouse button is released.
1426
- */
1427
- .pg-cell--has-fill-handle {
1428
- overflow: visible !important;
1429
- }
1430
- .pg-fill-handle {
1431
- position: absolute;
1432
- right: 0px;
1433
- bottom: 0px;
1434
- width: 6px;
1435
- height: 6px;
1436
- box-sizing: border-box;
1437
- background-color: var(--pg-colors-primary, #2563eb);
1438
- cursor: crosshair;
1439
- z-index: 10;
1440
- pointer-events: auto;
1441
- user-select: none;
1442
- }
1443
-
1444
- /* ─── Fill preview — dashed border on cells being hovered during fill drag ─── */
1445
- .pg-cell--fill-preview {
1446
- background-color: var(--pg-colors-selection-background, aliceblue) !important;
1447
- position: relative;
1448
- z-index: 1;
1449
- }
1450
- /*
1451
- * The fill-preview ::after uses a dashed border (vs the solid selection border)
1452
- * to clearly distinguish "about to be filled" from "already selected."
1453
- * These classes are orthogonal to sel-top/bottom/left/right — fill-preview
1454
- * cells are never pg-cell--in-selection, so there is no ::after conflict.
1455
- */
1456
- .pg-cell--fill-preview::after {
1457
- content: '';
1458
- position: absolute;
1459
- inset: 0;
1460
- border: 0 dashed var(--pg-colors-primary, #2563eb);
1461
- pointer-events: none;
1462
- }
1463
- .pg-cell--fp-top::after { border-top-width: 1px; }
1464
- .pg-cell--fp-bottom::after { border-bottom-width: 1px; }
1465
- .pg-cell--fp-left::after { border-left-width: 1px; }
1466
- .pg-cell--fp-right::after { border-right-width: 1px; }
1467
-
1468
- .pg-grid[data-theme="dark"] .pg-cell--fill-preview {
1469
- background-color: rgba(37, 99, 235, 0.12) !important;
1470
- }
1471
-
1472
- /* ─── Context menu ─── */
1473
- .pg-context-menu {
1474
- position: fixed;
1475
- z-index: 999999;
1476
- display: none;
1477
- min-width: 192px;
1478
- padding: 4px 0;
1479
- background: var(--pg-colors-surface, #fff);
1480
- border: 1px solid var(--pg-colors-border, #e2e8f0);
1481
- border-radius: var(--pg-borders-radius-md, 6px);
1482
- box-shadow: var(--pg-shadows-dropdown, 0 8px 24px rgba(0,0,0,0.12), 0 2px 6px rgba(0,0,0,0.07));
1483
- font-family: var(--pg-typography-font-family, system-ui, sans-serif);
1484
- font-size: var(--pg-typography-font-size-md, 13px);
1485
- }
1486
- .pg-context-menu--visible { display: block; }
1487
- .pg-context-menu__item {
1488
- display: flex;
1489
- align-items: center;
1490
- width: 100%;
1491
- padding: 7px 14px;
1492
- border: none;
1493
- background: transparent;
1494
- cursor: pointer;
1495
- text-align: left;
1496
- color: var(--pg-colors-text-primary, #0f172a);
1497
- gap: 0;
1498
- transition: background 80ms;
1499
- }
1500
- .pg-context-menu__item:hover { background: var(--pg-colors-background-alt, #f1f5f9); }
1501
- .pg-context-menu__item:active { background: var(--pg-colors-border, #e2e8f0); }
1502
- .pg-context-menu__label { flex: 1; }
1503
- .pg-context-menu__kbd {
1504
- font-size: var(--pg-typography-font-size-sm, 11px);
1505
- color: var(--pg-colors-text-disabled, #94a3b8);
1506
- letter-spacing: 0.01em;
1507
- }
1508
- .pg-context-menu__sep {
1509
- height: 1px;
1510
- margin: 4px 0;
1511
- background: var(--pg-colors-border, #e2e8f0);
1512
- }
1513
-
1514
- .pg-cell__inner {
1515
- display: flex;
1516
- align-items: center;
1517
- width: 100%;
1518
- height: 100%;
1519
- padding: 0 12px;
1520
- overflow: hidden;
1521
- }
1522
- .pg-cell__value {
1523
- flex: 1;
1524
- min-width: 0;
1525
- overflow: hidden;
1526
- text-overflow: ellipsis;
1527
- white-space: nowrap;
1528
- line-height: var(--pg-typography-line-height-base, 1.5);
1529
- }
1530
- .pg-cell--checkbox {
1531
- width: 44px;
1532
- min-width: 44px;
1533
- max-width: 44px;
1534
- justify-content: center;
1535
- flex-shrink: 0;
1536
- border-right: 1px solid var(--pg-colors-border, #e2e8f0);
1537
- }
1538
- .pg-cell--serial {
1539
- width: 52px;
1540
- min-width: 52px;
1541
- max-width: 52px;
1542
- justify-content: center;
1543
- flex-shrink: 0;
1544
- border-right: 1px solid var(--pg-colors-border, #e2e8f0);
1545
- color: var(--pg-colors-text-secondary, #475569);
1546
- font-size: var(--pg-typography-font-size-sm, 12px);
1547
- }
1548
- .pg-cell__serial { font-variant-numeric: tabular-nums; }
1549
- .pg-cell--bool-true { color: var(--pg-colors-success, #16a34a); }
1550
- .pg-cell--bool-false { color: var(--pg-colors-text-disabled, #94a3b8); }
1551
- .pg-cell__image { border-radius: var(--pg-borders-radius-sm, 4px); object-fit: cover; }
1552
- .pg-badge {
1553
- display: inline-flex;
1554
- align-items: center;
1555
- padding: 2px 8px;
1556
- border-radius: var(--pg-borders-radius-pill, 9999px);
1557
- font-size: var(--pg-typography-font-size-xs, 11px);
1558
- font-weight: var(--pg-typography-font-weight-medium, 500);
1559
- white-space: nowrap;
1560
- }
1561
- .pg-cell--range-selected { background: var(--pg-colors-selection-background, rgba(37,99,235,0.08)); }
1562
- .pg-cell--editing { padding: 0;border-radius: 4px }
1563
- .pg-cell--editing .pg-cell__inner { padding: 0; overflow: visible; }
1564
- .pg-selection-canvas { position: absolute; top: 0; left: 0; pointer-events: none; z-index: 10; }
1565
-
1566
- /* ──────────────────── Checkbox ──────────────────── */
1567
- .pg-checkbox {
1568
- width: var(--pg-sizing-checkbox-size, 16px);
1569
- height: var(--pg-sizing-checkbox-size, 16px);
1570
- accent-color: var(--pg-colors-primary, #2563eb);
1571
- cursor: pointer;
1572
- flex-shrink: 0;
1573
- }
1574
-
1575
- /* ──────────────────── Row Group ──────────────────── */
1576
-
1577
- /* Inner layout cell — carries level-based left padding */
1578
- .pg-row-group__cell {
1579
- display: flex;
1580
- align-items: center;
1581
- gap: var(--pg-group-row-gap, 6px);
1582
- flex: 1;
1583
- min-width: 0;
1584
- overflow: hidden;
1585
- padding-right: var(--pg-group-row-padding-right, 16px);
1586
- }
1587
-
1588
- /* Level-based indentation (data-level set by the renderer, no inline style) */
1589
- .pg-row--group[data-level="0"] .pg-row-group__cell { padding-left: var(--pg-group-indent-0, 8px); }
1590
- .pg-row--group[data-level="1"] .pg-row-group__cell { padding-left: var(--pg-group-indent-1, 28px); }
1591
- .pg-row--group[data-level="2"] .pg-row-group__cell { padding-left: var(--pg-group-indent-2, 48px); }
1592
- .pg-row--group[data-level="3"] .pg-row-group__cell { padding-left: var(--pg-group-indent-3, 68px); }
1593
- .pg-row--group[data-level="4"] .pg-row-group__cell { padding-left: var(--pg-group-indent-4, 88px); }
1594
- .pg-row--group[data-level="5"] .pg-row-group__cell { padding-left: var(--pg-group-indent-5, 108px); }
1595
-
1596
- /* Toggle button — a themed wrapper, not the raw icon element */
1597
- .pg-row-group__toggle {
1598
- display: inline-flex;
1599
- align-items: center;
1600
- justify-content: center;
1601
- flex-shrink: 0;
1602
- width: var(--pg-group-toggle-size, 24px);
1603
- height: var(--pg-group-toggle-size, 24px);
1604
- border-radius: var(--pg-borders-radius-sm, 4px);
1605
- color: var(--pg-colors-text-secondary, #64748b);
1606
- background: transparent;
1607
- transition:
1608
- background var(--pg-transitions-duration-fast, 100ms),
1609
- color var(--pg-transitions-duration-fast, 100ms);
1610
- }
1611
-
1612
- .pg-row-group__label {
1613
- flex: 1;
1614
- min-width: 0;
1615
- overflow: hidden;
1616
- text-overflow: ellipsis;
1617
- white-space: nowrap;
1618
- color: var(--pg-colors-group-row-text, inherit);
1619
- }
1620
-
1621
- .pg-row-group__count {
1622
- display: inline-flex;
1623
- align-items: center;
1624
- justify-content: center;
1625
- min-width: var(--pg-group-count-min-width, 24px);
1626
- padding: var(--pg-group-count-padding, 1px 8px);
1627
- border-radius: var(--pg-borders-radius-pill, 9999px);
1628
- background: var(--pg-colors-badge-background, #dbeafe);
1629
- color: var(--pg-colors-badge-text, #1e40af);
1630
- font-size: var(--pg-typography-font-size-xs, 11px);
1631
- font-weight: var(--pg-typography-font-weight-semi-bold, 600);
1632
- flex-shrink: 0;
1633
- letter-spacing: 0.02em;
1634
- }
1635
-
1636
- /* ──────────────────── Tree Data ────────────────────
1637
- The toggle column's cell gets a marker class ('.pg-cell--tree-toggle-col',
1638
- applied by applyTreeToggle regardless of whether the row has children —
1639
- leaves still need to sit indented under their parent), then indentation is
1640
- purely data-level-driven CSS, the same mechanism '.pg-row--group' already
1641
- uses (see above) — no inline styles, no per-instance stylesheet. */
1642
- .pg-cell--tree-toggle-col {
1643
- display: flex;
1644
- align-items: center;
1645
- gap: var(--pg-group-row-gap, 6px);
1646
- min-width: 0;
1647
- }
1648
-
1649
- .pg-row--tree[data-level="0"] .pg-cell--tree-toggle-col { padding-left: var(--pg-tree-indent-0, 8px); }
1650
- .pg-row--tree[data-level="1"] .pg-cell--tree-toggle-col { padding-left: var(--pg-tree-indent-1, 28px); }
1651
- .pg-row--tree[data-level="2"] .pg-cell--tree-toggle-col { padding-left: var(--pg-tree-indent-2, 48px); }
1652
- .pg-row--tree[data-level="3"] .pg-cell--tree-toggle-col { padding-left: var(--pg-tree-indent-3, 68px); }
1653
- .pg-row--tree[data-level="4"] .pg-cell--tree-toggle-col { padding-left: var(--pg-tree-indent-4, 88px); }
1654
- .pg-row--tree[data-level="5"] .pg-cell--tree-toggle-col { padding-left: var(--pg-tree-indent-5, 108px); }
1655
- .pg-row--tree[data-level="6"] .pg-cell--tree-toggle-col { padding-left: var(--pg-tree-indent-6, 128px); }
1656
- .pg-row--tree[data-level="7"] .pg-cell--tree-toggle-col { padding-left: var(--pg-tree-indent-7, 148px); }
1657
-
1658
- .pg-tree-toggle {
1659
- display: inline-flex;
1660
- align-items: center;
1661
- justify-content: center;
1662
- flex-shrink: 0;
1663
- width: var(--pg-group-toggle-size, 24px);
1664
- height: var(--pg-group-toggle-size, 24px);
1665
- border-radius: var(--pg-borders-radius-sm, 4px);
1666
- color: var(--pg-colors-text-secondary, #64748b);
1667
- cursor: pointer;
1668
- transition:
1669
- background var(--pg-transitions-duration-fast, 100ms),
1670
- color var(--pg-transitions-duration-fast, 100ms);
1671
- }
1672
- .pg-tree-toggle:hover {
1673
- background: var(--pg-colors-row-hover, #f0f7ff);
1674
- color: var(--pg-colors-text-primary, #1e293b);
1675
- }
1676
-
1677
- /* Reserves the toggle's own footprint on leaf rows (no chevron) so a leaf's
1678
- content lines up under its parent's content, not under the parent's toggle. */
1679
- .pg-tree-toggle-spacer {
1680
- display: inline-block;
1681
- flex-shrink: 0;
1682
- width: var(--pg-group-toggle-size, 24px);
1683
- height: var(--pg-group-toggle-size, 24px);
1684
- }
1685
-
1686
- /* A getDataPath filler node — a synthetic path-prefix row with no real backing record. */
1687
- .pg-row--tree-filler .pg-cell__value {
1688
- font-style: italic;
1689
- color: var(--pg-colors-text-secondary, #64748b);
1690
- }
1691
-
1692
- /* Drag-to-reparent drop feedback (3-way before/inside/after — see RowDragRenderer.setTreeMode) */
1693
- .pg-row--drop-target.pg-row--drop-inside {
1694
- background: var(--pg-colors-selection-background, rgba(37, 99, 235, 0.1));
1695
- outline: 2px dashed var(--pg-colors-primary, #2563eb);
1696
- outline-offset: -2px;
1697
- }
1698
- .pg-row--drop-target.pg-row--drop-before {
1699
- box-shadow: inset 0 2px 0 0 var(--pg-colors-primary, #2563eb);
1700
- }
1701
- .pg-row--drop-target.pg-row--drop-after {
1702
- box-shadow: inset 0 -2px 0 0 var(--pg-colors-primary, #2563eb);
1703
- }
1704
-
1705
- /* ──────────────────── Scrollbars ──────────────────── */
1706
-
1707
- /* Native vertical scrollbar — flex item that lives beside the center panel.
1708
- It is NOT absolutely positioned so it never overlaps cell content; the center
1709
- panel shrinks to make room for it, keeping every cell border fully visible. */
1710
- .pg-scrollbar-v-native {
1711
- flex-shrink: 0;
1712
- overflow-y: scroll;
1713
- overflow-x: hidden;
1714
- background: var(--pg-colors-scrollbar-bg, #fff);
1715
- }
1716
- .pg-scrollbar-v-spacer {
1717
- width: 1px;
1718
- pointer-events: none;
1719
- }
1720
- /* Horizontal row: sits below the body */
1721
- .pg-scrollbar-h-row {
1722
- display: flex;
1723
- flex-direction: row;
1724
- flex-shrink: 0;
1725
- border-top: 1px solid var(--pg-colors-border, #e2e8f0);
1726
- }
1727
- .pg-scrollbar-h-spacer { flex-shrink: 0; background: var(--pg-colors-scrollbar-bg, #fff); }
1728
- .pg-scrollbar-h-spacer--left { width: var(--pg-left-panel-width, 0px); overflow: scroll; }
1729
- .pg-scrollbar-h-spacer--right { width: var(--pg-right-panel-width, 0px); overflow: scroll; }
1730
- /* Aligns the h-scroll track with the narrowed center panel (which is now
1731
- offset by the vertical scrollbar width captured in --pg-scrollbar-v-width). */
1732
- .pg-scrollbar-h-spacer--vscroll {
1733
- flex-shrink: 0;
1734
- width: 0px;
1735
- background: var(--pg-colors-scrollbar-bg, #fff);
1736
- }
1737
- /* Native horizontal scrollbar container */
1738
- .pg-scrollbar-h-native {
1739
- flex: 1 1 0;
1740
- min-width: 0;
1741
- overflow-x: scroll;
1742
- overflow-y: hidden;
1743
- background: var(--pg-colors-scrollbar-bg, #fff);
1744
- }
1745
- .pg-scrollbar-h-content {
1746
- height: 1px;
1747
- pointer-events: none;
1748
- }
1749
- /* Hidden state — applied to wraps */
1750
- .pg-scrollbar--hidden { display: none; }
1751
-
1752
- /* ──────────────────── Editors ──────────────────── */
1753
- .pg-editor {
1754
- width: 100%;
1755
- height: 100%;
1756
- padding: 0 12px;
1757
- border: none;
1758
- outline: none;
1759
- font-size: inherit;
1760
- font-family: inherit;
1761
- background: var(--pg-colors-cell-edit-background, #fff);
1762
- color: inherit;
1763
- box-sizing: border-box;
1764
- }
1765
- .pg-editor:focus { outline: none; box-shadow: inset 0 0 0 2px var(--pg-colors-primary, #2563eb); }
1766
- .pg-editor--select { cursor: pointer; padding-right: 8px; }
1767
- .pg-editor--checkbox { width: auto; height: auto; margin: auto; cursor: pointer; }
1768
-
1769
- /* ── Multi-select (array) editor ── */
1770
- .pg-editor--multiselect {
1771
- position: relative;
1772
- display: flex;
1773
- align-items: center;
1774
- height: 100%;
1775
- padding: 0;
1776
- cursor: pointer;
1777
- background: var(--pg-colors-cell-edit-background, #fff);
1778
- }
1779
- .pg-editor__ms-trigger {
1780
- display: flex;
1781
- align-items: center;
1782
- justify-content: space-between;
1783
- width: 100%;
1784
- height: 100%;
1785
- padding: 0 8px 0 12px;
1786
- user-select: none;
1787
- gap: 6px;
1788
- }
1789
- .pg-editor__ms-text {
1790
- flex: 1;
1791
- min-width: 0;
1792
- overflow: hidden;
1793
- text-overflow: ellipsis;
1794
- white-space: nowrap;
1795
- font-size: inherit;
1796
- color: inherit;
1797
- }
1798
- .pg-editor__ms-arrow {
1799
- flex-shrink: 0;
1800
- width: 16px;
1801
- height: 16px;
1802
- display: flex;
1803
- align-items: center;
1804
- justify-content: center;
1805
- color: var(--pg-colors-text-secondary, #64748b);
1806
- }
1807
- .pg-editor__ms-arrow::after {
1808
- content: '';
1809
- display: block;
1810
- width: 0;
1811
- height: 0;
1812
- border-left: 4px solid transparent;
1813
- border-right: 4px solid transparent;
1814
- border-top: 5px solid currentColor;
1815
- }
1816
- .pg-editor__ms-panel {
1817
- display: none;
1818
- position: absolute;
1819
- top: calc(100% + 2px);
1820
- left: 0;
1821
- min-width: 100%;
1822
- max-height: 220px;
1823
- overflow-y: auto;
1824
- background: var(--pg-colors-surface, #fff);
1825
- border: 1px solid var(--pg-colors-border, #e2e8f0);
1826
- border-radius: 6px;
1827
- box-shadow: 0 8px 24px rgba(0,0,0,0.12), 0 2px 6px rgba(0,0,0,0.06);
1828
- z-index: 9999;
1829
- padding: 4px;
1830
- }
1831
- .pg-editor__ms-panel--open { display: block; }
1832
- .pg-editor__ms-option {
1833
- display: flex;
1834
- align-items: center;
1835
- gap: 8px;
1836
- padding: 6px 10px;
1837
- border-radius: 4px;
1838
- cursor: pointer;
1839
- transition: background 80ms;
1840
- font-size: inherit;
1841
- font-family: inherit;
1842
- color: var(--pg-colors-text-primary, #0f172a);
1843
- }
1844
- .pg-editor__ms-option:hover { background: var(--pg-colors-background-alt, #f1f5f9); }
1845
- .pg-editor__ms-check {
1846
- flex-shrink: 0;
1847
- width: 14px;
1848
- height: 14px;
1849
- cursor: pointer;
1850
- accent-color: var(--pg-colors-primary, #2563eb);
1851
- }
1852
- .pg-editor__ms-label {
1853
- flex: 1;
1854
- min-width: 0;
1855
- overflow: hidden;
1856
- text-overflow: ellipsis;
1857
- white-space: nowrap;
1858
- }
1859
-
1860
- /* ── Custom dropdown editor ── */
1861
- .pg-dropdown-editor__trigger {
1862
- display: flex;
1863
- align-items: center;
1864
- width: 100%;
1865
- height: 100%;
1866
- padding: 0 6px 0 12px;
1867
- gap: 6px;
1868
- cursor: default;
1869
- }
1870
- .pg-dropdown-editor__trigger-label {
1871
- flex: 1;
1872
- min-width: 0;
1873
- overflow: hidden;
1874
- text-overflow: ellipsis;
1875
- white-space: nowrap;
1876
- font-size: inherit;
1877
- color: inherit;
1878
- }
1879
- .pg-dropdown-editor__arrow {
1880
- flex-shrink: 0;
1881
- width: 16px;
1882
- height: 16px;
1883
- display: flex;
1884
- align-items: center;
1885
- justify-content: center;
1886
- color: var(--pg-colors-text-secondary, #64748b);
1887
- }
1888
- .pg-dropdown-editor__arrow::after {
1889
- content: '';
1890
- display: block;
1891
- width: 0;
1892
- height: 0;
1893
- border-left: 4px solid transparent;
1894
- border-right: 4px solid transparent;
1895
- border-top: 5px solid currentColor;
1896
- }
1897
- /* Panel — position:fixed, appended to document.body */
1898
- .pg-dropdown-editor__panel {
1899
- position: fixed;
1900
- z-index: 99999;
1901
- background: var(--pg-colors-surface, #fff);
1902
- border: 1px solid var(--pg-colors-border, #e2e8f0);
1903
- border-radius: 8px;
1904
- box-shadow: 0 8px 32px rgba(0,0,0,0.13), 0 2px 8px rgba(0,0,0,0.07);
1905
- overflow: hidden;
1906
- opacity: 0;
1907
- transform: scaleY(0.94) translateY(-4px);
1908
- transform-origin: top center;
1909
- transition: opacity 130ms ease, transform 130ms ease;
1910
- }
1911
- .pg-dropdown-editor__panel--visible {
1912
- opacity: 1;
1913
- transform: scaleY(1) translateY(0);
1914
- }
1915
- .pg-dropdown-editor__panel--above {
1916
- transform-origin: bottom center;
1917
- transform: scaleY(0.94) translateY(4px);
1918
- }
1919
- .pg-dropdown-editor__panel--above.pg-dropdown-editor__panel--visible {
1920
- transform: scaleY(1) translateY(0);
1921
- }
1922
- /* Scrollable list */
1923
- .pg-dropdown-editor__scroll {
1924
- overflow-y: auto;
1925
- overflow-x: hidden;
1926
- outline: none;
1927
- }
1928
- .pg-dropdown-editor__scroll::-webkit-scrollbar { width: 5px; }
1929
- .pg-dropdown-editor__scroll::-webkit-scrollbar-track { background: transparent; }
1930
- .pg-dropdown-editor__scroll::-webkit-scrollbar-thumb {
1931
- background: var(--pg-colors-border, #e2e8f0);
1932
- border-radius: 3px;
1933
- }
1934
- /* Virtual scroll layout */
1935
- .pg-dropdown-editor__spacer { position: relative; }
1936
- .pg-dropdown-editor__items { position: absolute; left: 0; right: 0; top: 0; }
1937
- /* Option rows — height must equal CustomDropdownEditor.ITEM_HEIGHT (34px) */
1938
- .pg-dropdown-editor__option {
1939
- display: flex;
1940
- align-items: center;
1941
- gap: 8px;
1942
- padding: 0 10px;
1943
- height: 34px;
1944
- cursor: pointer;
1945
- transition: background 60ms;
1946
- color: var(--pg-colors-text-primary, #0f172a);
1947
- font-family: var(--pg-typography-font-family, system-ui, sans-serif);
1948
- font-size: 13px;
1949
- }
1950
- .pg-dropdown-editor__option:hover,
1951
- .pg-dropdown-editor__option--highlighted {
1952
- background: var(--pg-colors-background-alt, #f1f5f9);
1953
- }
1954
- .pg-dropdown-editor__option--selected {
1955
- background: var(--pg-colors-primary-subtle, #eff6ff);
1956
- color: var(--pg-colors-primary, #2563eb);
1957
- font-weight: 500;
1958
- }
1959
- .pg-dropdown-editor__option--selected.pg-dropdown-editor__option--highlighted {
1960
- background: var(--pg-colors-primary-subtle-hover, #dbeafe);
1961
- }
1962
- /* Icon / image before label */
1963
- .pg-dropdown-editor__opt-icon {
1964
- flex-shrink: 0;
1965
- width: 20px;
1966
- height: 20px;
1967
- display: inline-flex;
1968
- align-items: center;
1969
- justify-content: center;
1970
- overflow: hidden;
1971
- border-radius: 3px;
1972
- }
1973
- .pg-dropdown-editor__opt-icon img {
1974
- width: 20px;
1975
- height: 20px;
1976
- object-fit: cover;
1977
- border-radius: 2px;
1978
- display: block;
1979
- }
1980
- .pg-dropdown-editor__opt-label {
1981
- flex: 1;
1982
- min-width: 0;
1983
- overflow: hidden;
1984
- text-overflow: ellipsis;
1985
- white-space: nowrap;
1986
- }
1987
- /* Checkmark for the currently selected option */
1988
- .pg-dropdown-editor__opt-check {
1989
- flex-shrink: 0;
1990
- width: 16px;
1991
- height: 16px;
1992
- display: flex;
1993
- align-items: center;
1994
- justify-content: center;
1995
- color: var(--pg-colors-primary, #2563eb);
1996
- }
1997
- .pg-dropdown-editor__opt-check::after {
1998
- content: '';
1999
- display: block;
2000
- width: 5px;
2001
- height: 9px;
2002
- border-right: 2px solid currentColor;
2003
- border-bottom: 2px solid currentColor;
2004
- transform: rotate(45deg) translate(-1px, -1px);
2005
- }
2006
- /* Empty state */
2007
- .pg-dropdown-editor__empty {
2008
- display: flex;
2009
- align-items: center;
2010
- justify-content: center;
2011
- height: 48px;
2012
- color: var(--pg-colors-text-secondary, #64748b);
2013
- font-size: 13px;
2014
- font-family: var(--pg-typography-font-family, system-ui, sans-serif);
2015
- }
2016
-
2017
- /* ── Array cell tag display ── */
2018
- .pg-cell__value--tags {
2019
- display: flex;
2020
- align-items: center;
2021
- gap: 4px;
2022
- flex-wrap: nowrap;
2023
- overflow: hidden;
2024
- flex: 1;
2025
- min-width: 0;
2026
- }
2027
- .pg-badge--overflow {
2028
- background: var(--pg-colors-background-alt, #f1f5f9);
2029
- color: var(--pg-colors-text-secondary, #64748b);
2030
- font-size: 10px;
2031
- flex-shrink: 0;
2032
- }
2033
-
2034
- /* ──────────────────── Footer ──────────────────── */
2035
- .pg-grid__footer {
2036
- flex-shrink: 0;
2037
- border-top: 1px solid var(--pg-colors-footer-border, #e2e8f0);
2038
- background: var(--pg-colors-footer-background, #f8fafc);
2039
- }
2040
- .pg-footer {
2041
- display: flex;
2042
- align-items: center;
2043
- justify-content: space-between;
2044
- padding: 0 16px;
2045
- height: 44px;
2046
- gap: 16px;
2047
- }
2048
- .pg-pagination {
2049
- display: flex;
2050
- align-items: center;
2051
- gap: 4px;
2052
- }
2053
- .pg-pagination__info {
2054
- font-size: var(--pg-typography-font-size-sm, 12px);
2055
- color: var(--pg-colors-text-secondary, #475569);
2056
- min-width: 100px;
2057
- text-align: center;
2058
- }
2059
- .pg-pagination__btn {
2060
- display: inline-flex;
2061
- align-items: center;
2062
- justify-content: center;
2063
- width: 30px;
2064
- height: 30px;
2065
- border: 1px solid var(--pg-colors-border, #e2e8f0);
2066
- border-radius: var(--pg-borders-radius-sm, 4px);
2067
- background: var(--pg-colors-surface, #fff);
2068
- color: var(--pg-colors-text-primary, #0f172a);
2069
- cursor: pointer;
2070
- transition: all var(--pg-transitions-duration-fast, 100ms);
2071
- }
2072
- .pg-pagination__btn:hover:not(:disabled) { background: var(--pg-colors-background-alt, #f1f5f9); border-color: var(--pg-colors-border-strong, #cbd5e1); }
2073
- .pg-pagination__btn:disabled { opacity: 0.38; cursor: not-allowed; }
2074
- .pg-pagination__page-input {
2075
- width: 54px;
2076
- height: 30px;
2077
- padding: 0 8px;
2078
- border: 1px solid var(--pg-colors-border, #e2e8f0);
2079
- border-radius: var(--pg-borders-radius-sm, 4px);
2080
- font-size: var(--pg-typography-font-size-sm, 12px);
2081
- font-family: inherit;
2082
- background: var(--pg-colors-surface, #fff);
2083
- color: inherit;
2084
- text-align: center;
2085
- outline: none;
2086
- }
2087
- .pg-pagination__page-input:focus { border-color: var(--pg-colors-border-focus, #2563eb); }
2088
- .pg-pagination__size { display: flex; align-items: center; gap: 8px; }
2089
- .pg-pagination__size-label { font-size: var(--pg-typography-font-size-sm, 12px); color: var(--pg-colors-text-secondary, #475569); white-space: nowrap; }
2090
- .pg-pagination__size-select {
2091
- height: 30px;
2092
- padding: 0 6px;
2093
- border: 1px solid var(--pg-colors-border, #e2e8f0);
2094
- border-radius: var(--pg-borders-radius-sm, 4px);
2095
- font-size: var(--pg-typography-font-size-sm, 12px);
2096
- font-family: inherit;
2097
- background: var(--pg-colors-surface, #fff);
2098
- color: inherit;
2099
- cursor: pointer;
2100
- outline: none;
2101
- }
2102
-
2103
- /* ──────────────────── Overlay ──────────────────── */
2104
- .pg-overlay {
2105
- position: absolute;
2106
- inset: 0;
2107
- display: flex;
2108
- flex-direction: column;
2109
- align-items: center;
2110
- justify-content: center;
2111
- gap: 12px;
2112
- background: var(--pg-colors-surface, #fff);
2113
- z-index: 20;
2114
- }
2115
- .pg-overlay--loading { background: rgba(255,255,255,0.85); }
2116
- .pg-overlay__text { color: var(--pg-colors-text-secondary, #475569); font-size: var(--pg-typography-font-size-md, 13px); }
2117
- .pg-overlay__icon { color: var(--pg-colors-text-disabled, #94a3b8); }
2118
-
2119
- /* ──────────────────── Drag ──────────────────── */
2120
- .pg-dragging { opacity: 0.5; }
2121
- .pg-drop-before { box-shadow: 0 -2px 0 0 var(--pg-colors-primary, #2563eb); }
2122
- .pg-drop-after { box-shadow: 0 2px 0 0 var(--pg-colors-primary, #2563eb); }
2123
- .pg-drop-over { background: var(--pg-colors-drag-over-highlight, rgba(37,99,235,0.06)) !important; }
2124
-
2125
- /* ──────────────────── Fullscreen ──────────────────── */
2126
- .pg-grid--fullscreen { position: fixed; inset: 0; z-index: 9999; border-radius: 0; }
2127
-
2128
- /* ──────────────────── Chart ──────────────────── */
2129
- .pg-chart { display: flex; flex-direction: column; gap: 8px; }
2130
- .pg-chart__title { font-size: var(--pg-typography-font-size-lg, 14px); font-weight: var(--pg-typography-font-weight-semi-bold, 600); color: var(--pg-colors-text-primary); padding: 4px 0; }
2131
- .pg-chart__canvas { display: block; max-width: 100%; }
2132
-
2133
- /* ──────────────────── Icon ──────────────────── */
2134
- .pg-icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
2135
- .pg-icon svg { display: block; }
2136
-
2137
- /* ──────────────────── Auto Row Height ──────────────────── */
2138
- .pg-grid--auto-row-height .pg-row {
2139
- height: auto;
2140
- }
2141
- .pg-grid--auto-row-height .pg-cell {
2142
- overflow: visible;
2143
- }
2144
- .pg-grid--auto-row-height .pg-cell__inner {
2145
- height: auto;
2146
- overflow: visible;
2147
- align-items: flex-start;
2148
- padding-top: 10px;
2149
- padding-bottom: 10px;
2150
- }
2151
- .pg-grid--auto-row-height .pg-cell__value {
2152
- white-space: normal;
2153
- overflow: visible;
2154
- text-overflow: initial;
2155
- overflow-wrap: break-word;
2156
- word-break: break-word;
2157
- }
2158
-
2159
- /* ──────────────────── Row Drag ──────────────────── */
2160
- .pg-grid__body { position: relative; }
2161
-
2162
- .pg-row-drag-handle {
2163
- display: inline-flex;
2164
- align-items: center;
2165
- justify-content: center;
2166
- width: 16px;
2167
- height: 100%;
2168
- flex-shrink: 0;
2169
- cursor: grab;
2170
- opacity: 0.35;
2171
- color: var(--pg-colors-text-secondary, #475569);
2172
- margin-right: 4px;
2173
- }
2174
- .pg-row-drag-handle:hover { opacity: 0.7; }
2175
- .pg-row-drag-handle:active { cursor: grabbing; }
2176
-
2177
- .pg-row-drag-ghost {
2178
- position: fixed;
2179
- pointer-events: none;
2180
- z-index: 9999;
2181
- display: inline-flex;
2182
- align-items: center;
2183
- gap: 6px;
2184
- padding: 5px 10px;
2185
- border-radius: var(--pg-borders-radius-md, 6px);
2186
- border: 1.5px solid var(--pg-colors-primary, #2563eb);
2187
- background: var(--pg-colors-surface, #fff);
2188
- color: var(--pg-colors-primary, #2563eb);
2189
- font-size: var(--pg-typography-font-size-sm, 12px);
2190
- font-weight: 500;
2191
- box-shadow: 0 6px 24px rgba(37,99,235,0.13), 0 2px 8px rgba(37,99,235,0.12);
2192
- transform: translate(12px, -50%);
2193
- white-space: nowrap;
2194
- max-width: 240px;
2195
- overflow: hidden;
2196
- text-overflow: ellipsis;
2197
- }
2198
- .pg-row-drag-ghost__icon { display: inline-flex; align-items: center; opacity: 0.8; }
2199
- .pg-row-drag-ghost__icon--block { display: none; }
2200
- .pg-row-drag-ghost__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
2201
-
2202
- .pg-row-drag-ghost--outside {
2203
- border-color: var(--pg-colors-danger, #ef4444);
2204
- box-shadow: 0 6px 24px rgba(239,68,68,0.13), 0 2px 8px rgba(239,68,68,0.12);
2205
- color: var(--pg-colors-danger, #ef4444);
2206
- }
2207
- .pg-row-drag-ghost--outside .pg-row-drag-ghost__icon--drag { display: none; }
2208
- .pg-row-drag-ghost--outside .pg-row-drag-ghost__icon--block { display: inline-flex; }
2209
-
2210
- .pg-row-drop-indicator {
2211
- position: absolute;
2212
- left: 0;
2213
- right: 0;
2214
- height: 2px;
2215
- background: var(--pg-colors-primary, #2563eb);
2216
- pointer-events: none;
2217
- z-index: 100;
2218
- border-radius: 1px;
2219
- }
2220
- .pg-row-drop-indicator::before {
2221
- content: '';
2222
- position: absolute;
2223
- left: -3px;
2224
- top: -3px;
2225
- width: 8px;
2226
- height: 8px;
2227
- border-radius: 50%;
2228
- background: var(--pg-colors-primary, #2563eb);
2229
- }
2230
-
2231
- /* The dragged row: semi-transparent, moves to virtual landing position */
2232
- .pg-row--row-dragging { opacity: 0.4; }
2233
-
2234
- /* During row drag: kill hover/click on all rows; animate top changes.
2235
- Uses top (not transform) so rows stay within panel overflow:hidden bounds. */
2236
- .pg-grid--row-dragging .pg-row {
2237
- pointer-events: none;
2238
- will-change: top;
2239
- transition: background var(--pg-transitions-duration-fast, 100ms),
2240
- top 130ms cubic-bezier(0.2, 0, 0, 1);
2241
- }
2242
-
2243
- /* ──────────────────── Chart Panel ──────────────────── */
2244
- .pg-chart-panel-backdrop {
2245
- position: absolute; inset: 0; z-index: 9990;
2246
- background: transparent;
2247
- overflow: hidden;
2248
- pointer-events: none;
2249
- }
2250
- .pg-chart-panel-backdrop--open {
2251
- pointer-events: auto;
2252
- }
2253
- .pg-chart-panel-backdrop--fullscreen {
2254
- position: fixed !important;
2255
- background: rgba(0,0,0,0.40) !important;
2256
- }
2257
- .pg-chart-panel {
2258
- position: absolute;
2259
- background: var(--pg-colors-surface,#fff);
2260
- border-radius: 4px;
2261
- box-shadow: 0 8px 40px rgba(0,0,0,0.18),0 2px 12px rgba(0,0,0,0.10);
2262
- display: flex; flex-direction: column;
2263
- width: min(720px, 88%); height: min(520px, 85%);
2264
- overflow: hidden;
2265
- pointer-events: auto;
2266
- }
2267
- .pg-chart-panel--fullscreen {
2268
- width: calc(100%) !important; height: calc(100%) !important;
2269
- }
2270
- .pg-chart-panel__header {
2271
- display: flex; align-items: center; justify-content: space-between;
2272
- padding: 14px 16px;
2273
- border-bottom: 1px solid var(--pg-colors-border,#e2e8f0);
2274
- flex-shrink: 0;
2275
- cursor: grab; user-select: none;
2276
- }
2277
- .pg-chart-panel__header--dragging { cursor: grabbing; }
2278
- .pg-chart-panel--dragging .pg-chart-panel__body { pointer-events: none; }
2279
- .pg-chart-panel__title {
2280
- font-size: 15px; font-weight: 600;
2281
- color: var(--pg-colors-text-primary,#0f172a);
2282
- font-family: var(--pg-typography-font-family,system-ui,sans-serif);
2283
- }
2284
- .pg-chart-panel__actions { display: flex; align-items: center; gap: 4px; }
2285
- .pg-chart-panel__action-btn {
2286
- display: inline-flex; align-items: center; justify-content: center;
2287
- width: 28px; height: 28px; border-radius: 4px;
2288
- border: none; background: transparent;
2289
- color: var(--pg-colors-text-secondary,#64748b); cursor: pointer;
2290
- transition: background 80ms, color 80ms;
2291
- }
2292
- .pg-chart-panel__action-btn:hover {
2293
- background: var(--pg-colors-background-alt,#f1f5f9);
2294
- color: var(--pg-colors-text-primary,#0f172a);
2295
- }
2296
- .pg-chart-panel__body {
2297
- flex: 1; min-height: 0; position: relative; padding: 8px; overflow: hidden;
2298
- }
2299
- .pg-chart-panel__canvas { display: block; }
2300
- .pg-chart-panel__dots-btn {
2301
- position: absolute; top: 12px; right: 12px; z-index: 10;
2302
- display: inline-flex; align-items: center; justify-content: center;
2303
- width: 26px; height: 26px; border-radius: 4px;
2304
- border: none; background: transparent;
2305
- color: var(--pg-colors-text-secondary,#64748b); cursor: pointer;
2306
- transition: background 80ms;
2307
- }
2308
- .pg-chart-panel__dots-btn:hover, .pg-chart-panel__dots-btn--active {
2309
- background: var(--pg-colors-background-alt,#f1f5f9);
2310
- color: var(--pg-colors-text-primary,#0f172a);
2311
- }
2312
- .pg-chart-panel__dots-menu {
2313
- display: none; position: absolute; top: 40px; right: 8px; z-index: 20;
2314
- background: var(--pg-colors-surface,#fff);
2315
- border: 1px solid var(--pg-colors-border,#e2e8f0);
2316
- border-radius: 6px;
2317
- box-shadow: 0 8px 24px rgba(0,0,0,0.12);
2318
- min-width: 160px; padding: 4px;
2319
- }
2320
- .pg-chart-panel__dots-menu--open { display: block; }
2321
- .pg-chart-panel__dots-item {
2322
- display: flex; align-items: center; gap: 8px;
2323
- width: 100%; padding: 7px 10px;
2324
- border: none; border-radius: 4px; background: transparent;
2325
- cursor: pointer; text-align: left;
2326
- font-size: 13px; color: var(--pg-colors-text-primary,#0f172a);
2327
- font-family: var(--pg-typography-font-family,system-ui,sans-serif);
2328
- transition: background 80ms;
2329
- }
2330
- .pg-chart-panel__dots-item:hover { background: var(--pg-colors-background-alt,#f1f5f9); }
2331
- .pg-chart-panel__empty {
2332
- display: flex; flex-direction: column; align-items: center; justify-content: center;
2333
- height: 100%; gap: 10px; padding: 24px;
2334
- color: var(--pg-colors-text-secondary,#64748b);
2335
- font-family: var(--pg-typography-font-family,system-ui,sans-serif);
2336
- }
2337
- .pg-chart-panel__empty-icon { opacity: 0.35; color: var(--pg-colors-text-secondary,#64748b); }
2338
- .pg-chart-panel__empty-text {
2339
- font-size: 15px; font-weight: 600;
2340
- color: var(--pg-colors-text-primary,#0f172a);
2341
- }
2342
- .pg-chart-panel__empty-sub {
2343
- font-size: 12px; text-align: center; max-width: 280px;
2344
- color: var(--pg-colors-text-secondary,#64748b);
2345
- }
2346
- .pg-chart-panel__legend {
2347
- display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
2348
- gap: 2px 4px; padding: 5px 12px 8px;
2349
- flex-shrink: 0;
2350
- border-top: 1px solid var(--pg-colors-border,#e2e8f0);
2351
- }
2352
- .pg-chart-panel__legend:empty { border-top: none; padding: 0; }
2353
- .pg-chart-panel__legend-item {
2354
- display: inline-flex; align-items: center; gap: 6px;
2355
- padding: 4px 8px; border-radius: 5px;
2356
- border: none; background: transparent; cursor: pointer;
2357
- font-size: 12px; color: var(--pg-colors-text-secondary,#64748b);
2358
- font-family: var(--pg-typography-font-family,system-ui,sans-serif);
2359
- user-select: none;
2360
- transition: background 80ms, opacity 220ms;
2361
- }
2362
- .pg-chart-panel__legend-item:hover {
2363
- background: var(--pg-colors-background-alt,#f1f5f9);
2364
- color: var(--pg-colors-text-primary,#0f172a);
2365
- }
2366
- .pg-chart-panel__legend-item--hidden { opacity: 0.35; }
2367
- .pg-chart-panel__legend-swatch {
2368
- width: 12px; height: 12px; border-radius: 3px; flex-shrink: 0;
2369
- }
2370
- .pg-chart-panel__legend-label {
2371
- max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
2372
- }
2373
-
2374
- /* ──────────────────── Context menu submenu ──────────────────── */
2375
- .pg-context-menu__item { display: flex; align-items: center; gap: 8px; }
2376
- .pg-context-menu__item--has-sub { position: relative; padding-right: 28px; }
2377
- .pg-context-menu__item--has-sub > .pg-context-menu__sub { display: none; }
2378
- .pg-context-menu__item--has-sub:hover > .pg-context-menu__sub { display: block; }
2379
- .pg-context-menu__sub {
2380
- position: absolute; left: 100%; top: -4px; z-index: 10001;
2381
- background: var(--pg-colors-surface,#fff);
2382
- border: 1px solid var(--pg-colors-border,#e2e8f0);
2383
- border-radius: var(--pg-borders-radius-md,6px);
2384
- box-shadow: var(--pg-shadows-dropdown,0 8px 24px rgba(0,0,0,0.12));
2385
- min-width: 175px; padding: 4px;
2386
- white-space: nowrap;
2387
- }
2388
- .pg-context-menu__item--has-sub::after {
2389
- content: '›'; position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
2390
- font-size: 16px; color: var(--pg-colors-text-secondary,#64748b); line-height: 1;
2391
- }
2392
- .pg-context-menu__icon {
2393
- display: inline-flex; align-items: center; width: 16px; flex-shrink: 0;
2394
- color: var(--pg-colors-text-secondary,#64748b);
2395
- }
2396
-
2397
- /* ──────────────────── Sparkline cell ──────────────────── */
2398
-
2399
- /* Cell value wrapper — fills the inner cell area as a flex row */
2400
- .pg-cell__value--sparkline {
2401
- display: flex;
2402
- align-items: stretch;
2403
- width: 100%;
2404
- height: 100%;
2405
- padding: 0;
2406
- }
2407
-
2408
- /* Wrapper div that stretches canvas to fill the cell */
2409
- .pg-sparkline-wrapper {
2410
- display: flex;
2411
- align-items: center;
2412
- width: 100%;
2413
- height: 100%;
2414
- min-width: 0;
2415
- }
2416
-
2417
- /* Canvas element — fills wrapper, no border or background */
2418
- .pg-sparkline {
2419
- display: block;
2420
- width: 100%;
2421
- height: 100%;
2422
- min-width: 0;
2423
- cursor: crosshair;
2424
- }
2425
-
2426
- /* ──────────────────── Sparkline tooltip ──────────────────── */
2427
-
2428
- /* Singleton floating tooltip attached to document.body */
2429
- .pg-sparkline-tooltip {
2430
- position: fixed;
2431
- z-index: 99999;
2432
- pointer-events: none;
2433
- background: var(--pg-colors-surface, #fff);
2434
- border: 1px solid var(--pg-colors-border, #e2e8f0);
2435
- border-radius: var(--pg-borders-radius-md, 6px);
2436
- box-shadow: var(--pg-shadows-tooltip, 0 4px 14px rgba(0,0,0,0.12));
2437
- padding: 6px 10px;
2438
- font-size: var(--pg-typography-font-size-sm, 12px);
2439
- font-family: var(--pg-typography-font-family, system-ui, sans-serif);
2440
- color: var(--pg-colors-text-primary, #0f172a);
2441
- white-space: nowrap;
2442
- line-height: 1.5;
2443
- min-width: 60px;
2444
- }
2445
- .pg-sparkline-tooltip--hidden {
2446
- display: none;
2447
- }
2448
-
2449
- /* x-axis label row (shown when data is an object array with xKey) */
2450
- .pg-sparkline-tooltip__label {
2451
- color: var(--pg-colors-text-secondary, #64748b);
2452
- font-size: var(--pg-typography-font-size-xs, 11px);
2453
- margin-bottom: 2px;
2454
- }
2455
-
2456
- /* Numeric value row */
2457
- .pg-sparkline-tooltip__value {
2458
- font-weight: 600;
2459
- color: var(--pg-colors-text-primary, #0f172a);
2460
- }
2461
-
2462
- /* OHLC four-row layout */
2463
- .pg-sparkline-tooltip__ohlc-row {
2464
- display: flex;
2465
- justify-content: space-between;
2466
- gap: 12px;
2467
- }
2468
- .pg-sparkline-tooltip__ohlc-key {
2469
- color: var(--pg-colors-text-secondary, #64748b);
2470
- font-size: var(--pg-typography-font-size-xs, 11px);
2471
- min-width: 12px;
2472
- }
2473
-
2474
- /* ──────────────────── Column Context Menu ──────────────────── */
2475
-
2476
- /* Menu container — fixed-position dropdown attached to document.body.
2477
- Height is capped so the menu never grows into the viewport's top/bottom
2478
- 200px; content beyond that scrolls internally via overflow-y instead of
2479
- being clipped. Fly-out submenus (.pg-col-ctx-menu__submenu) are portaled to
2480
- document.body while open rather than nested here, so this container's
2481
- scroll clipping never cuts them off on the X axis. */
2482
- .pg-col-ctx-menu {
2483
- position: fixed;
2484
- z-index: 9999;
2485
- min-width: 220px;
2486
- max-width: 300px;
2487
- max-height: calc(100% - 200px);
2488
- overflow-y: auto;
2489
- overflow-x: hidden;
2490
- padding: 4px;
2491
- background: var(--pg-colors-surface, #ffffff);
2492
- border: 1px solid var(--pg-colors-border, #e2e8f0);
2493
- border-radius: var(--pg-borders-radius-md, 6px);
2494
- box-shadow: var(--pg-shadows-dropdown, 0 8px 24px rgba(15, 23, 42, 0.12));
2495
- font-family: var(--pg-typography-font-family, system-ui, sans-serif);
2496
- font-size: var(--pg-typography-font-size-sm, 13px);
2497
- color: var(--pg-colors-text-primary, #0f172a);
2498
- user-select: none;
2499
- outline: none;
2500
- }
2501
-
2502
- /* Horizontal divider between section groups */
2503
- .pg-col-ctx-menu__separator {
2504
- height: 1px;
2505
- background: var(--pg-colors-border, #e2e8f0);
2506
- margin: 4px 0;
2507
- }
2508
-
2509
- /* ── Menu items ─────────────────────────────────────────────── */
2510
-
2511
- /* Base item — covers both leaf items and parent (submenu-trigger) items */
2512
- .pg-col-ctx-menu__item {
2513
- position: relative;
2514
- display: flex;
2515
- align-items: center;
2516
- gap: 8px;
2517
- padding: 7px 10px;
2518
- border-radius: var(--pg-borders-radius-sm, 4px);
2519
- cursor: pointer;
2520
- transition: background var(--pg-transitions-fast, 80ms ease);
2521
- outline: none;
2522
- white-space: nowrap;
2523
- }
2524
-
2525
- .pg-col-ctx-menu__item:hover,
2526
- .pg-col-ctx-menu__item:focus-visible {
2527
- background: var(--pg-colors-background-alt, #f1f5f9);
2528
- }
2529
-
2530
- /* Highlighted / "currently applied" item (e.g. active sort direction) */
2531
- .pg-col-ctx-menu__item--active {
2532
- color: var(--pg-colors-primary, #2563eb);
2533
- font-weight: 600;
2534
- }
2535
-
2536
- /* Disabled item — rendered but not interactive */
2537
- .pg-col-ctx-menu__item--disabled {
2538
- opacity: 0.38;
2539
- cursor: not-allowed;
2540
- pointer-events: none;
2541
- }
2542
-
2543
- /* ── Item anatomy ────────────────────────────────────────────── */
2544
-
2545
- /* Leading icon */
2546
- .pg-col-ctx-menu__item-icon {
2547
- display: flex;
2548
- align-items: center;
2549
- justify-content: center;
2550
- flex-shrink: 0;
2551
- width: 16px;
2552
- height: 16px;
2553
- opacity: 0.6;
2554
- }
2555
-
2556
- .pg-col-ctx-menu__item--active .pg-col-ctx-menu__item-icon {
2557
- opacity: 1;
2558
- }
2559
-
2560
- /* Text label — fills remaining space */
2561
- .pg-col-ctx-menu__item-label {
2562
- flex: 1;
2563
- overflow: hidden;
2564
- text-overflow: ellipsis;
2565
- }
2566
-
2567
- /* Trailing chevron indicating a fly-out submenu */
2568
- .pg-col-ctx-menu__item-chevron {
2569
- display: flex;
2570
- align-items: center;
2571
- justify-content: center;
2572
- flex-shrink: 0;
2573
- width: 14px;
2574
- height: 14px;
2575
- opacity: 0.4;
2576
- margin-left: 4px;
2577
- transition: opacity var(--pg-transitions-fast, 80ms ease);
2578
- }
2579
-
2580
- .pg-col-ctx-menu__item--has-submenu:hover .pg-col-ctx-menu__item-chevron {
2581
- opacity: 0.75;
2582
- }
2583
-
2584
- /* ── Fly-out submenu ─────────────────────────────────────────── */
2585
-
2586
- /* Hidden by default; shown when JS adds --open. Positioned fixed rather than
2587
- absolute-within-parent because it is portaled to document.body while open
2588
- (see ColumnMenu.openSubmenu) — left/top are set inline in viewport
2589
- coordinates by adjustSubmenuPosition. */
2590
- .pg-col-ctx-menu__submenu {
2591
- display: none;
2592
- position: fixed;
2593
- min-width: 180px;
2594
- padding: 4px;
2595
- background: var(--pg-colors-surface, #ffffff);
2596
- border: 1px solid var(--pg-colors-border, #e2e8f0);
2597
- border-radius: var(--pg-borders-radius-md, 6px);
2598
- box-shadow: var(--pg-shadows-dropdown, 0 8px 24px rgba(15, 23, 42, 0.12));
2599
- z-index: 10000;
2600
- }
2601
-
2602
- /* JS-controlled open state */
2603
- .pg-col-ctx-menu__submenu--open {
2604
- display: block;
2605
- }
2606
-
2607
- /* Invisible hover bridge — prevents flicker when mouse crosses from
2608
- parent item edge into the submenu. Extends 6px to the left of the submenu. */
2609
- .pg-col-ctx-menu__submenu--open::before {
2610
- content: '';
2611
- position: absolute;
2612
- right: 100%;
2613
- top: 0;
2614
- width: 8px;
2615
- height: 100%;
2616
- }
2617
-
2618
- /* ──────────────────── Master/Detail ────────────────────
2619
- The detail layer is a sibling of the left/center/right body panels, not a
2620
- child of any of them — that is what lets a detail row span the full grid
2621
- width regardless of pinned columns. Its content wrapper receives only the
2622
- vertical scroll transform (never the horizontal one center columns use),
2623
- so it structurally cannot shift when the user scrolls horizontally. */
2624
- .pg-detail-layer {
2625
- position: absolute;
2626
- top: 0;
2627
- left: 0;
2628
- bottom: 0;
2629
- /* Stops short of the vertical scrollbar's *current* column width (0 when
2630
- it's hidden) instead of a blanket inset:0 — otherwise an expanded
2631
- detail row's opaque background paints over the native scrollbar
2632
- whenever one is showing. See ScrollController.syncScrollbars. */
2633
- right: var(--pg-scrollbar-v-live-width, 0px);
2634
- overflow: hidden;
2635
- pointer-events: none;
2636
- /* Tied with .pg-panel--left/--right's z-index (2, base-styles.ts ~line
2637
- 335) rather than below it — this layer is a later DOM sibling of the
2638
- panels (mounted after them in GridRenderer.buildLayout), so an equal
2639
- z-index still paints on top per normal stacking-order tie-breaking.
2640
- This is what lets an expanded detail row's opaque background cover the
2641
- pinned panels' own edge box-shadow instead of that shadow bleeding
2642
- across the full-width detail content underneath (the panels are
2643
- full-viewport-height flex items, so their shadow would otherwise span
2644
- every detail row too, not just their own pinned cells). Sticky Master/
2645
- Detail rows are unaffected by this ordering — they live in the
2646
- independent, always-on-top .pg-sticky-layer below, not here. */
2647
- z-index: 2;
2648
- }
2649
- .pg-detail-layer__content {
2650
- position: relative;
2651
- width: 100%;
2652
- height: 100%;
2653
- transform: translateY(var(--pg-scroll-y, 0px));
2654
- }
2655
- /* Sticky Master/Detail row layer — a TOP-LEVEL sibling of the left/center/
2656
- right panels and of .pg-detail-layer (not nested inside any of them).
2657
- .pg-panel--left/--right set their own explicit z-index for pinned-column
2658
- elevation, which makes each one its own stacking context — anything
2659
- nested inside is trapped there and can never out-rank a sibling like
2660
- .pg-detail-layer merely by having a higher z-index of its own. Living at
2661
- this same top level lets one z-index correctly out-rank everything, in
2662
- every pinned/non-pinned column, with no stacking-context surprises.
2663
- The container itself is pointer-events:none (so empty space with no
2664
- sticky row never blocks clicks through to what's underneath); the actual
2665
- row element re-enables pointer-events at the default (auto). */
2666
- .pg-sticky-layer {
2667
- position: absolute;
2668
- top: 0;
2669
- left: 0;
2670
- right: var(--pg-scrollbar-v-live-width, 0px);
2671
- bottom: 0;
2672
- pointer-events: none;
2673
- z-index: 3;
2674
- }
2675
- /* Mirrors .pg-panel--left's own pinned-edge shadow. That shadow lives on the
2676
- panel container itself, which a stuck row's own background paints over
2677
- for its own height once moved into this overlay — without repeating it
2678
- here, the pinned-edge shadow has a visible gap wherever a sticky row
2679
- currently sits.
2680
- z-index: 2 (matching .pg-panel--left/--right's own z-index, base-styles.ts
2681
- ~line 334) is required, not optional — this shadow bleeds *rightward*,
2682
- into the center region's own horizontal space, and .pg-sticky-layer__center
2683
- is appended after it in the DOM (see GridRenderer.buildStickyLayer); on
2684
- equal stacking contexts a later sibling paints over an earlier one, so
2685
- without an explicit z-index center's own background silently covers the
2686
- bled-through part of this shadow, while the right shadow (appended last)
2687
- was never affected — z-index makes both sides correct regardless of
2688
- append order instead of depending on it. */
2689
- .pg-sticky-layer__left {
2690
- position: absolute;
2691
- top: 0;
2692
- left: 0;
2693
- height: 100%;
2694
- width: var(--pg-left-panel-width, 0px);
2695
- overflow: hidden;
2696
- box-shadow: 2px 0 4px rgba(0,0,0,0.06);
2697
- z-index: 2;
2698
- }
2699
- .pg-sticky-layer__center {
2700
- position: absolute;
2701
- top: 0;
2702
- left: var(--pg-left-panel-width, 0px);
2703
- right: var(--pg-right-panel-width, 0px);
2704
- height: 100%;
2705
- overflow: hidden;
2706
- z-index: 1;
2707
- }
2708
- /* Mirrors .pg-panel--center .pg-panel__content's horizontal-scroll transform
2709
- so a stuck row's center cells track the user's horizontal scroll exactly
2710
- like the real (non-sticky) center panel does. */
2711
- .pg-sticky-layer__center-inner {
2712
- position: relative;
2713
- height: 100%;
2714
- width: var(--pg-center-content-width, 100%);
2715
- transform: translateX(var(--pg-scroll-x, 0px));
2716
- }
2717
- /* Mirrors .pg-panel--right's own pinned-edge shadow — see .pg-sticky-layer__left above. */
2718
- .pg-sticky-layer__right {
2719
- position: absolute;
2720
- top: 0;
2721
- right: 0;
2722
- height: 100%;
2723
- width: var(--pg-right-panel-width, 0px);
2724
- overflow: hidden;
2725
- box-shadow: -2px 0 4px rgba(0,0,0,0.06);
2726
- }
2727
- .pg-row--sticky {
2728
- /* The sticky layer container above is pointer-events:none (so empty space
2729
- with no sticky row never blocks clicks through to whatever's underneath)
2730
- — pointer-events inherits, so without this the row itself, and every
2731
- interactive thing inside it (cells, the tree/group toggle, checkboxes),
2732
- would silently inherit "none" and stop responding to clicks entirely. */
2733
- pointer-events: auto;
2734
- }
2735
- .pg-row--detail-container {
2736
- position: absolute;
2737
- left: 0;
2738
- width: 100%;
2739
- box-sizing: border-box;
2740
- overflow: hidden;
2741
- pointer-events: auto;
2742
- padding: 20px;
2743
- background: var(--pg-colors-surface, #fff);
2744
- border-bottom: 1px solid var(--pg-colors-border, #e2e8f0);
2745
- opacity: 1;
2746
- /* Deliberately not tied to the theme's --pg-transitions-duration-* tokens —
2747
- those are tuned for snappy hover/focus feedback elsewhere; expand/collapse
2748
- reads better slightly slower and more deliberate. */
2749
- transition:
2750
- height 340ms cubic-bezier(0.4, 0, 0.2, 1),
2751
- opacity 260ms ease;
2752
- }
2753
- /* Expand: fades in on first mount; height grows for free once RowPositionSheet
2754
- updates from the initial min/cached height to the auto-measured one. */
2755
- .pg-row--detail-container.pg-row--detail-entering {
2756
- opacity: 0;
2757
- }
2758
- /* Collapse: DetailRowRenderer.beginCollapse freezes top/height as inline
2759
- styles first (the RowPositionSheet rule for this row is about to disappear
2760
- for good), then this class plus height: 0 (set in JS) drives the shrink. */
2761
- .pg-row--detail-container.pg-row--detail-collapsing {
2762
- opacity: 0;
2763
- border-bottom-color: transparent;
2764
- }
2765
- .pg-detail-nested-grid-host {
2766
- width: 100%;
2767
- height: 100%;
2768
- }
2769
- .pg-detail-loading {
2770
- display: flex;
2771
- align-items: center;
2772
- justify-content: center;
2773
- width: 100%;
2774
- height: 100%;
2775
- color: var(--pg-colors-text-secondary, #64748b);
2776
- }
2777
- .pg-detail-toggle {
2778
- display: inline-flex;
2779
- align-items: center;
2780
- justify-content: center;
2781
- flex-shrink: 0;
2782
- width: var(--pg-group-toggle-size, 24px);
2783
- height: var(--pg-group-toggle-size, 24px);
2784
- margin-left: 8px;
2785
- margin-right: 4px;
2786
- border-radius: var(--pg-borders-radius-sm, 4px);
2787
- color: var(--pg-colors-text-secondary, #64748b);
2788
- cursor: pointer;
2789
- transition:
2790
- background var(--pg-transitions-duration-fast, 100ms),
2791
- color var(--pg-transitions-duration-fast, 100ms);
2792
- }
2793
- .pg-detail-toggle:hover {
2794
- background: var(--pg-colors-row-hover, #f0f7ff);
2795
- color: var(--pg-colors-text-primary, #1e293b);
2796
- }
2797
- .pg-detail-resize-handle {
2798
- position: absolute;
2799
- left: 0;
2800
- right: 0;
2801
- bottom: 0;
2802
- height: 6px;
2803
- cursor: row-resize;
2804
- background: transparent;
2805
- transition: background var(--pg-transitions-duration-fast, 100ms);
2806
- }
2807
- .pg-detail-resize-handle:hover {
2808
- background: var(--pg-colors-resize-handle-color, #e2e8f0);
2809
- }
2810
-
2811
- /* ──────────────────── Photon AI ────────────────────
2812
- Floating command bar, anchored to the grid body's bottom-right corner.
2813
- Mounted as a sibling of the pinned-column panels (see PhotonAIPanel.mount /
2814
- GridRenderer.buildLayout) so it floats independently of virtualization and
2815
- scroll; the grid body's own overflow: hidden is what keeps it inside the
2816
- grid container per spec, without this component needing to enforce that
2817
- itself. */
2818
- .pg-ai-launcher {
2819
- position: absolute;
2820
- bottom: 16px;
2821
- right: 16px;
2822
- z-index: 201;
2823
- display: flex;
2824
- align-items: center;
2825
- justify-content: center;
2826
- width: 44px;
2827
- height: 44px;
2828
- border: none;
2829
- border-radius: var(--pg-borders-radius-pill, 9999px);
2830
- background: var(--pg-colors-primary, #2563eb);
2831
- color: var(--pg-colors-primary-text, #ffffff);
2832
- box-shadow: var(--pg-shadows-lg, 0 8px 24px rgba(15, 23, 42, 0.16));
2833
- cursor: pointer;
2834
- transition:
2835
- transform var(--pg-transitions-duration-base, 150ms) var(--pg-transitions-easing-base, ease),
2836
- opacity var(--pg-transitions-duration-base, 150ms) var(--pg-transitions-easing-base, ease),
2837
- background var(--pg-transitions-duration-fast, 100ms);
2838
- }
2839
- .pg-ai-launcher:hover {
2840
- background: var(--pg-colors-primary-hover, #1d4ed8);
2841
- transform: scale(1.06);
2842
- }
2843
- .pg-ai-launcher:active {
2844
- background: var(--pg-colors-primary-active, #1e40af);
2845
- transform: scale(0.97);
2846
- }
2847
- .pg-ai-launcher--hidden {
2848
- opacity: 0;
2849
- transform: scale(0.7);
2850
- pointer-events: none;
2851
- }
2852
-
2853
- .pg-ai-panel {
2854
- position: absolute;
2855
- top: 12px;
2856
- right: 12px;
2857
- bottom: 12px;
2858
- z-index: 201;
2859
- width: min(360px, calc(100% - 24px));
2860
- display: none;
2861
- flex-direction: column;
2862
- background: var(--pg-colors-surface, #ffffff);
2863
- border: var(--pg-borders-width-thin, 1px) solid var(--pg-colors-border, #e2e8f0);
2864
- border-radius: var(--pg-borders-radius-lg, 10px);
2865
- box-shadow: var(--pg-shadows-dropdown, 0 16px 48px rgba(15, 23, 42, 0.24));
2866
- font-family: var(--pg-typography-font-family, system-ui, sans-serif);
2867
- color: var(--pg-colors-text-primary, #0f172a);
2868
- }
2869
- .pg-ai-panel--open {
2870
- display: flex;
2871
- }
2872
-
2873
- .pg-ai-panel__header {
2874
- flex-shrink: 0;
2875
- display: flex;
2876
- align-items: center;
2877
- justify-content: space-between;
2878
- padding: 10px 12px;
2879
- border-bottom: var(--pg-borders-width-thin, 1px) solid var(--pg-colors-border, #e2e8f0);
2880
- }
2881
- .pg-ai-panel__title {
2882
- display: flex;
2883
- align-items: center;
2884
- gap: 6px;
2885
- font-size: var(--pg-typography-font-size-sm, 13px);
2886
- font-weight: var(--pg-typography-font-weight-semi-bold, 600);
2887
- color: var(--pg-colors-primary, #2563eb);
2888
- }
2889
- .pg-ai-panel__close {
2890
- display: flex;
2891
- align-items: center;
2892
- justify-content: center;
2893
- width: 20px;
2894
- height: 20px;
2895
- border: none;
2896
- border-radius: var(--pg-borders-radius-sm, 4px);
2897
- background: transparent;
2898
- color: var(--pg-colors-text-secondary, #64748b);
2899
- cursor: pointer;
2900
- transition: background var(--pg-transitions-duration-fast, 100ms);
2901
- }
2902
- .pg-ai-panel__close:hover {
2903
- background: var(--pg-colors-background-alt, #f1f5f9);
2904
- }
2905
-
2906
- .pg-ai-panel__log {
2907
- flex: 1 1 0;
2908
- min-height: 0;
2909
- overflow-y: auto;
2910
- display: flex;
2911
- flex-direction: column;
2912
- gap: 10px;
2913
- padding: 14px;
2914
- }
2915
-
2916
- .pg-ai-panel__message {
2917
- max-width: 85%;
2918
- padding: 8px 12px;
2919
- border-radius: var(--pg-borders-radius-lg, 10px);
2920
- font-size: var(--pg-typography-font-size-sm, 13px);
2921
- line-height: 1.45;
2922
- white-space: pre-wrap;
2923
- word-break: break-word;
2924
- }
2925
- .pg-ai-panel__message--user {
2926
- align-self: flex-end;
2927
- background: var(--pg-colors-primary, #2563eb);
2928
- color: var(--pg-colors-primary-text, #ffffff);
2929
- border-bottom-right-radius: var(--pg-borders-radius-sm, 4px);
2930
- }
2931
- .pg-ai-panel__message--assistant {
2932
- align-self: flex-start;
2933
- background: var(--pg-colors-background-alt, #f1f5f9);
2934
- color: var(--pg-colors-text-primary, #0f172a);
2935
- border-bottom-left-radius: var(--pg-borders-radius-sm, 4px);
2936
- }
2937
- .pg-ai-panel__message--assistant.pg-ai-panel__message--error {
2938
- background: var(--pg-colors-error-subtle, #fef2f2);
2939
- color: var(--pg-colors-error, #dc2626);
2940
- }
2941
-
2942
- .pg-ai-panel__input-wrap {
2943
- position: relative;
2944
- flex-shrink: 0;
2945
- display: flex;
2946
- padding: 10px 12px 12px;
2947
- border-top: var(--pg-borders-width-thin, 1px) solid var(--pg-colors-border, #e2e8f0);
2948
- }
2949
- .pg-ai-panel__input {
2950
- flex: 1 1 0;
2951
- width: 100%;
2952
- min-height: 36px;
2953
- max-height: 120px;
2954
- padding: 8px 40px 8px 12px;
2955
- border: var(--pg-borders-width-thin, 1px) solid var(--pg-colors-border, #e2e8f0);
2956
- border-radius: var(--pg-borders-radius-md, 6px);
2957
- background: var(--pg-colors-surface, #ffffff);
2958
- color: var(--pg-colors-text-primary, #0f172a);
2959
- font-family: var(--pg-typography-font-family, system-ui, sans-serif);
2960
- font-size: var(--pg-typography-font-size-sm, 13px);
2961
- line-height: 1.4;
2962
- resize: none;
2963
- outline: none;
2964
- transition: border-color var(--pg-transitions-duration-fast, 100ms);
2965
- }
2966
- .pg-ai-panel__input::placeholder {
2967
- color: var(--pg-colors-text-disabled, #94a3b8);
2968
- }
2969
- .pg-ai-panel__input:focus {
2970
- border-color: var(--pg-colors-border-focus, #2563eb);
2971
- }
2972
- .pg-ai-panel__send {
2973
- position: absolute;
2974
- right: 20px;
2975
- bottom: 17px;
2976
- display: flex;
2977
- align-items: center;
2978
- justify-content: center;
2979
- width: 26px;
2980
- height: 26px;
2981
- flex-shrink: 0;
2982
- border: none;
2983
- border-radius: var(--pg-borders-radius-pill, 9999px);
2984
- background: var(--pg-colors-primary, #2563eb);
2985
- color: var(--pg-colors-primary-text, #ffffff);
2986
- cursor: pointer;
2987
- transition:
2988
- background var(--pg-transitions-duration-fast, 100ms),
2989
- transform var(--pg-transitions-duration-fast, 100ms),
2990
- opacity var(--pg-transitions-duration-fast, 100ms);
2991
- }
2992
- .pg-ai-panel__send:hover:not(:disabled) {
2993
- background: var(--pg-colors-primary-hover, #1d4ed8);
2994
- transform: scale(1.08);
2995
- }
2996
- .pg-ai-panel__send:disabled {
2997
- background: var(--pg-colors-text-disabled, #94a3b8);
2998
- opacity: 0.5;
2999
- cursor: default;
3000
- }
3001
-
3002
- /* ──────────────────── Custom cell tooltip ────────────────────
3003
- * Only mounted/shown for columns with renderer.tooltip — plain columns keep
3004
- * using the free native title attribute. Positioned via a transform set
3005
- * in JS relative to .pg-grid__body so it never affects grid layout. */
3006
- .pg-tooltip {
3007
- position: absolute;
3008
- top: 0;
3009
- left: 0;
3010
- z-index: var(--pg-z-index-tooltip, 150);
3011
- max-width: 320px;
3012
- padding: var(--pg-spacing-xs, 6px) var(--pg-spacing-sm, 10px);
3013
- border-radius: var(--pg-borders-radius-sm, 4px);
3014
- background: var(--pg-colors-tooltip-bg, #1f2937);
3015
- color: var(--pg-colors-tooltip-text, #ffffff);
3016
- font-family: var(--pg-typography-font-family, sans-serif);
3017
- font-size: var(--pg-typography-font-size-xs, 12px);
3018
- line-height: 1.4;
3019
- box-shadow: var(--pg-shadows-dropdown, 0 4px 12px rgba(0, 0, 0, 0.15));
3020
- pointer-events: none;
3021
- opacity: 0;
3022
- visibility: hidden;
3023
- transition:
3024
- opacity var(--pg-transitions-duration-fast, 100ms),
3025
- visibility var(--pg-transitions-duration-fast, 100ms);
3026
- }
3027
- .pg-tooltip--visible {
3028
- opacity: 1;
3029
- visibility: visible;
3030
- }
3031
-
3032
- `;
35
+ // Joined with '' (not '\n') so the output is byte-identical to the original
36
+ // single template: each module already carries its own leading/trailing
37
+ // whitespace from the split.
38
+ const baseCss = [
39
+ rootCss,
40
+ groupDropZoneCss,
41
+ groupBarSearchCss,
42
+ panelsCss,
43
+ headerCss,
44
+ columnGroupHeaderCss,
45
+ filterCss,
46
+ rowsCss,
47
+ cellsCss,
48
+ contextMenuCss,
49
+ rowGroupCss,
50
+ treeCss,
51
+ scrollbarsCss,
52
+ editorsCss,
53
+ footerCss,
54
+ miscCss,
55
+ rowDragCss,
56
+ chartPanelCss,
57
+ sparklineCss,
58
+ columnContextMenuCss,
59
+ masterDetailCss,
60
+ photonAiCss,
61
+ tooltipCss,
62
+ ].join('');
3033
63
  const css = [baseCss, themeQuartzCss, themeAlpineCss, themeBalhamCss, themeMaterialCss, themeDarkCss].join('\n');
3034
64
  export function injectBaseStyles() {
3035
65
  if (document.getElementById(STYLE_ID))