mgh-components 1.0.15 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +167 -53
  2. package/dist/components/CustomNoRowsOverlay/CustomNoRowsOverlay.types.d.ts +0 -0
  3. package/dist/components/Label/styles.d.ts +10 -6
  4. package/dist/components/MGHDataGrid/MGHDataGrid.d.ts +1 -1
  5. package/dist/components/MGHDataGrid/MGHDataGrid.types.d.ts +1 -1
  6. package/dist/components/MGHGrid/MGHGrid.d.ts +7 -0
  7. package/dist/components/MGHGrid/MGHGrid.styles.d.ts +10 -0
  8. package/dist/components/MGHGrid/MGHGrid.types.d.ts +708 -0
  9. package/dist/components/MGHGrid/components/ActionsCell.d.ts +22 -0
  10. package/dist/components/MGHGrid/components/ColumnMenu.d.ts +12 -0
  11. package/dist/components/MGHGrid/components/ColumnsPanel.d.ts +2 -0
  12. package/dist/components/MGHGrid/components/FilterPanel.d.ts +2 -0
  13. package/dist/components/MGHGrid/components/Footer.d.ts +3 -0
  14. package/dist/components/MGHGrid/components/Overlays.d.ts +5 -0
  15. package/dist/components/MGHGrid/components/Toolbar.d.ts +30 -0
  16. package/dist/components/MGHGrid/components/primitives.d.ts +81 -0
  17. package/dist/components/MGHGrid/context.d.ts +40 -0
  18. package/dist/components/MGHGrid/export.d.ts +18 -0
  19. package/dist/components/MGHGrid/grouping.d.ts +40 -0
  20. package/dist/components/MGHGrid/hooks.d.ts +23 -0
  21. package/dist/components/MGHGrid/icons.d.ts +32 -0
  22. package/dist/components/MGHGrid/index.d.ts +20 -0
  23. package/dist/components/MGHGrid/utils.d.ts +62 -0
  24. package/dist/index.cjs +1 -1
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.esm.js +1 -1
  28. package/dist/index.esm.js.map +1 -1
  29. package/package.json +1 -1
package/README.md CHANGED
@@ -2,101 +2,215 @@
2
2
 
3
3
  Metrolina Greenhouses (MGH) component library for React applications.
4
4
 
5
- This package provides reusable UI components built on MUI, including the MGH Data Grid and related helpers.
5
+ This package ships two data grids:
6
6
 
7
- ## Install
7
+ - **`MGHGrid`** – a self-contained data grid with **no MUI dependency** (and therefore no
8
+ `@mui/x-data-grid-premium` license). This is the grid to use going forward.
9
+ - **`MGHDataGrid`** – the legacy wrapper around MUI X Data Grid Premium. It is kept for backwards
10
+ compatibility and still requires the MUI peer dependencies.
8
11
 
9
- Using npm:
12
+ Plus a few helpers built on MUI (`Label`, `ConfirmDialog`, `ExportingDialog`, `Iconify`).
10
13
 
11
- ```bash
12
- npm install mgh-components
13
- ```
14
-
15
- Using pnpm:
14
+ ## Install
16
15
 
17
16
  ```bash
17
+ npm install mgh-components
18
+ # or
18
19
  pnpm add mgh-components
19
20
  ```
20
21
 
21
- Using yarn:
22
-
23
- ```bash
24
- yarn add mgh-components
25
- ```
26
-
27
22
  ## Peer Dependencies
28
23
 
29
- This package expects the following peer dependencies to be installed in your app:
24
+ `MGHGrid` only needs:
30
25
 
31
26
  - `react`
32
27
  - `react-dom`
33
- - `@mui/material`
34
- - `@mui/x-data-grid-premium`
35
- - `@mui/x-date-pickers-pro`
36
- - `@emotion/styled`
37
28
 
38
- ## Usage
29
+ (`dayjs` is a regular dependency and is used for date formatting.)
39
30
 
40
- Basic example with `MGHDataGrid`:
31
+ The legacy components (`MGHDataGrid`, `Label`, `ConfirmDialog`, …) additionally need
32
+ `@mui/material`, `@mui/x-data-grid-premium`, `@mui/x-date-pickers-pro`, `@emotion/styled` and `@iconify/react`.
41
33
 
42
- ```tsx
43
- import React from 'react';
44
- import { MGHDataGrid } from 'mgh-components';
34
+ ---
45
35
 
46
- const rows = [
47
- { id: 1, itemId: 'A-100', locationId: 'LOC-1', enterCount: 10 },
48
- { id: 2, itemId: 'B-200', locationId: 'LOC-2', enterCount: 20 },
49
- ];
36
+ ## MGHGrid (MUI-free)
37
+
38
+ ```tsx
39
+ import { MGHGrid, type MGHGridColDef } from 'mgh-components';
40
+
41
+ interface Item {
42
+ id: number;
43
+ itemId: string;
44
+ locationId: string;
45
+ enterCount: number;
46
+ updatedAt: Date;
47
+ }
50
48
 
51
- const columns = [
49
+ const columns: MGHGridColDef<Item>[] = [
52
50
  { field: 'itemId', headerName: 'Item', flex: 1 },
53
51
  { field: 'locationId', headerName: 'Location', flex: 1 },
54
- { field: 'enterCount', headerName: 'Count', type: 'number', flex: 1 },
52
+ { field: 'enterCount', headerName: 'Count', type: 'number', width: 110 },
53
+ { field: 'updatedAt', headerName: 'Updated', type: 'dateTime', width: 170 },
55
54
  ];
56
55
 
57
- export default function ExampleGrid() {
56
+ export default function ExampleGrid({ rows, loading }: { rows: Item[]; loading: boolean }) {
58
57
  return (
59
- <MGHDataGrid
58
+ <MGHGrid<Item>
60
59
  header="Finished Goods - On Hand"
61
60
  rows={rows}
62
61
  columns={columns}
62
+ loading={loading}
63
+ boxStyle={{ height: '70vh' }}
64
+ checkboxSelection
65
+ columnOrderStorageKey="fg_onhand_column_order"
66
+ columnVisibilityStorageKey="fg_onhand_column_visibility"
63
67
  noRowsText="No finished goods availability submissions found within your filters."
64
- boxSx={{ height: '70vh' }}
65
68
  initialState={{
66
- pinnedColumns: { left: ['itemId'], right: ['enterCount'] },
69
+ pinnedColumns: { left: ['itemId'] },
70
+ sorting: { sortModel: [{ field: 'enterCount', sort: 'desc' }] },
67
71
  }}
68
72
  />
69
73
  );
70
74
  }
71
75
  ```
72
76
 
73
- ### Theme-aware no-rows overlay
77
+ Styles are injected automatically the first time a grid mounts – there is no CSS file to import.
78
+
79
+ ### Features
80
+
81
+ | Area | Details |
82
+ | --- | --- |
83
+ | Columns | `width`, `minWidth`, `maxWidth`, `flex`, `align`, `headerAlign`, `valueGetter`, `valueFormatter`, `renderCell`, `renderHeader`, `cellClassName`, `headerClassName`, `description` |
84
+ | Column types | `string`, `number`, `date`, `dateTime`, `boolean`, `singleSelect` (`valueOptions`), `actions` (`getActions` + `MGHGridActionsCellItem`) |
85
+ | Sorting | Click header (multi-sort with **Shift**), `sortModel` / `onSortModelChange`, `sortComparator`, `sortingOrder` |
86
+ | Filtering | Filter panel (per-type operators, AND/OR), quick filter (debounced search), `filterModel` / `onFilterModelChange`, custom `filterOperators`, `getApplyQuickFilterFn` |
87
+ | Pagination | `pagination`, `pageSize`, `pageSizeOptions`, `paginationModel` / `onPaginationModelChange` |
88
+ | Selection | `checkboxSelection`, `checkboxSelectionVisibleOnly`, `disableRowSelectionOnClick`, `disableMultipleRowSelection`, `isRowSelectable`, `rowSelectionModel` (`{ type: 'include', ids: Set }`, arrays also accepted), `keepNonExistentRowsSelected` |
89
+ | Column management | Columns panel, column menu, drag-and-drop reorder, resize (double-click the handle to autosize), pin left/right, hide/show. Persist with `columnVisibilityStorageKey`, `columnOrderStorageKey`, `columnWidthStorageKey`, `pinnedColumnsStorageKey` |
90
+ | Rows | `getRowId`, `getRowClassName`, `getRowHeight` (number or `'auto'`), `rowHeight`, `density` (`compact` default), `pinnedRows` (top/bottom), `onRowClick`, `onRowDoubleClick`, `onCellClick` |
91
+ | Detail panels | `getDetailPanelContent`, `getDetailPanelHeight` (number or `'auto'`), `detailPanelExpandedRowIds` |
92
+ | Row grouping | `rowGroupingModel` / `onRowGroupingModelChange`, `defaultGroupingExpansionDepth`, `groupingColDef`, "Group by" in the column menu |
93
+ | Aggregation | `aggregationModel` (`sum`, `avg`, `min`, `max`, `size` or custom `aggregationFunctions`), footer row and/or group rows (`aggregationPosition`) |
94
+ | Editing | `editable` columns, double-click / Enter to edit, `processRowUpdate`, `onProcessRowUpdateError`, `valueParser`, `valueSetter`, `renderEditCell`, `isCellEditable` |
95
+ | Export | CSV, real `.xlsx` (no library), print. Export menu in the toolbar, or `apiRef.current.exportDataAsCsv()` / `exportDataAsExcel()` / `exportDataAsPrint()` |
96
+ | Performance | Row virtualization when row heights are known (`disableVirtualization` to opt out), `autoHeight` |
97
+ | Keyboard | Arrow keys, Home/End, PageUp/PageDown, Enter/F2 to edit, Space to select, Ctrl/Cmd+A |
98
+ | Theming | `themeMode="light" | "dark"`, `themeVars` (any `--mgh-grid-*` CSS variable), `className`/`style` props |
99
+ | Slots | `slots.toolbar`, `slots.footer`, `slots.noRowsOverlay`, `slots.loadingOverlay` + `slotProps` |
100
+
101
+ ### Toolbar
102
+
103
+ The default toolbar mirrors the legacy one: Columns, Filters, Export (CSV / Excel / Print), an optional
104
+ density selector, an optional centre slot (`renderDateRange`), extra buttons and the expanding quick filter.
105
+
106
+ ```tsx
107
+ <MGHGrid
108
+ rows={rows}
109
+ columns={columns}
110
+ toolbarProps={{
111
+ showDensitySelector: true,
112
+ renderDateRange: <MyDateRangePicker />,
113
+ renderOtherButtons: <button>Refresh</button>,
114
+ customMenuItem: [
115
+ <MGHGridExportMenuItem key="pdf" onClick={() => downloadPdf()}>
116
+ Download as PDF
117
+ </MGHGridExportMenuItem>,
118
+ ],
119
+ csvOptions: { fileName: 'on-hand', utf8WithBom: true },
120
+ }}
121
+ />
122
+ ```
74
123
 
75
- If you use `useSettingsContext` in your app, pass it into the no-rows overlay so the component can read your theme mode.
124
+ Custom toolbars can use the building blocks (`MGHGridColumnsButton`, `MGHGridFiltersButton`,
125
+ `MGHGridExportMenu`, `MGHGridDensitySelector`, `MGHGridQuickFilter`) and `useMGHGridApiContext()`:
76
126
 
77
127
  ```tsx
78
- import { MGHDataGrid } from 'mgh-components';
79
- import { useSettingsContext } from 'src/contexts/SettingsContext';
128
+ import { MGHGrid, MGHGridQuickFilter, MGHGridExportMenu, useMGHGridApiContext } from 'mgh-components';
80
129
 
81
- export default function ExampleGridWithTheme() {
130
+ function MyToolbar() {
131
+ const api = useMGHGridApiContext();
82
132
  return (
83
- <MGHDataGrid
84
- header="Finished Goods - On Hand"
85
- rows={[]}
86
- columns={[]}
87
- slotProps={{
88
- noRowsOverlay: {
89
- text: 'No finished goods availability submissions found within your filters.',
90
- useSettingsContext,
91
- },
92
- }}
93
- />
133
+ <div className="mgh-grid-toolbar">
134
+ <button onClick={() => api.setRowSelectionModel([])}>Clear selection</button>
135
+ <MGHGridExportMenu />
136
+ <MGHGridQuickFilter />
137
+ </div>
94
138
  );
95
139
  }
140
+
141
+ <MGHGrid rows={rows} columns={columns} slots={{ toolbar: MyToolbar }} />;
142
+ ```
143
+
144
+ > The default toolbar component is exported as `MGHGridDefaultToolbar` because the legacy
145
+ > `MGHGridToolbar` export name belongs to the MUI-based grid.
146
+
147
+ ### Imperative API
148
+
149
+ ```tsx
150
+ import { MGHGrid, useMGHGridApiRef } from 'mgh-components';
151
+
152
+ const apiRef = useMGHGridApiRef<Item>();
153
+
154
+ <MGHGrid apiRef={apiRef} rows={rows} columns={columns} />;
155
+
156
+ apiRef.current?.getSelectedRows(); // Map<id, row>
157
+ apiRef.current?.getSortedRows(); // filtered + sorted rows
158
+ apiRef.current?.exportDataAsExcel({ fileName: 'report' });
159
+ apiRef.current?.setQuickFilterValues(['LOC-1']);
160
+ apiRef.current?.setRowGroupingModel(['category']);
161
+ apiRef.current?.state; // current models (sort, filter, pagination, …)
162
+ ```
163
+
164
+ ### Migrating from `MGHDataGrid`
165
+
166
+ 1. Change the import: `MGHDataGrid` → `MGHGrid`, `GridColDef` → `MGHGridColDef`.
167
+ 2. Column definitions keep the MUI v8 signatures (`valueGetter(value, row, column, api)`,
168
+ `valueFormatter(value, row, column, api)`, `renderCell(params)`), so most columns work unchanged.
169
+ 3. `sx`, `cardSx` and `boxSx` are accepted but treated as plain inline styles (`cardStyle`, `boxStyle`,
170
+ `style` are the preferred names). Nested MUI selectors such as `'& .MuiDataGrid-row'` are ignored.
171
+ 4. `rowSelectionModel` uses the same shape as MUI v8 (`{ type: 'include', ids: Set }`).
172
+ 5. `slots.toolbar` components must be rewritten without MUI internals; use the exported building blocks.
173
+ 6. Custom export menu items receive a `hideMenu` prop (like MUI) – use `MGHGridExportMenuItem`.
174
+ 7. The no-rows overlay no longer needs `useSettingsContext`; pass `themeMode="dark"` to the grid instead.
175
+
176
+ ### Theming
177
+
178
+ ```tsx
179
+ <MGHGrid
180
+ themeMode="dark"
181
+ themeVars={{ '--mgh-grid-primary': '#00a76f', '--mgh-grid-radius': '8px' }}
182
+
183
+ />
184
+ ```
185
+
186
+ Or globally in your CSS:
187
+
188
+ ```css
189
+ .mgh-grid-card {
190
+ --mgh-grid-primary: #00a76f;
191
+ --mgh-grid-font-family: 'Public Sans', sans-serif;
192
+ }
193
+ ```
194
+
195
+ ---
196
+
197
+ ## Legacy: MGHDataGrid (MUI X Premium)
198
+
199
+ ```tsx
200
+ import { MGHDataGrid } from 'mgh-components';
201
+
202
+ <MGHDataGrid
203
+ header="Finished Goods - On Hand"
204
+ rows={rows}
205
+ columns={columns}
206
+ boxSx={{ height: '70vh' }}
207
+ initialState={{ pinnedColumns: { left: ['itemId'], right: ['enterCount'] } }}
208
+ />;
96
209
  ```
97
210
 
98
211
  ## Components
99
212
 
100
- - `MGHDataGrid`
101
- - `MGHGridToolbar`
102
- - `CustomNoRowsOverlay`
213
+ - `MGHGrid` (+ `MGHGridDefaultToolbar`, `MGHGridQuickFilter`, `MGHGridExportMenu`, `MGHGridExportMenuItem`,
214
+ `MGHGridActionsCellItem`, `MGHGridNoRowsOverlay`, `MGHGridIcons`, `useMGHGridApiRef`, `useMGHGridApiContext`)
215
+ - `MGHDataGrid`, `MGHGridToolbar`, `DataGridQuickFilter`, `CustomNoRowsOverlay`, `CustomGridToolbarExport` (legacy, MUI)
216
+ - `Label`, `ConfirmDialog`, `ExportingDialog`, `Iconify`
@@ -1,7 +1,11 @@
1
+ import type { ComponentProps, ComponentType } from 'react';
2
+ import Box from '@mui/material/Box';
1
3
  import { LabelColor, LabelVariant } from './types';
2
- export declare const StyledLabel: import("@emotion/styled").StyledComponent<import("@mui/system").BoxOwnProps<import("@mui/material/styles").Theme> & Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof import("@mui/system").BoxOwnProps<import("@mui/material/styles").Theme>> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme> & {
3
- ownerState: {
4
- color: LabelColor;
5
- variant: LabelVariant;
6
- };
7
- }, {}, {}>;
4
+ interface StyledLabelOwnerState {
5
+ color: LabelColor;
6
+ variant: LabelVariant;
7
+ }
8
+ export declare const StyledLabel: ComponentType<ComponentProps<typeof Box> & {
9
+ ownerState: StyledLabelOwnerState;
10
+ }>;
11
+ export {};
@@ -1,7 +1,7 @@
1
1
  import React, { JSX } from 'react';
2
2
  import dayjs from 'dayjs';
3
3
  import { DateRange } from '@mui/x-date-pickers-pro';
4
- import { GridInitialStatePremium } from '@mui/x-data-grid-premium/models/gridStatePremium';
4
+ import { GridInitialState as GridInitialStatePremium } from '@mui/x-data-grid-premium';
5
5
  import { Theme, SxProps } from '@mui/material';
6
6
  import { GridColDef, GridRowParams, GridToolbarProps, GridEventListener, GridSlotsComponent, GridCallbackDetails, GridRowHeightParams, GridCsvExportOptions, GridRowSelectionModel, ToolbarPropsOverrides, GridRowClassNameParams, GridExcelExportOptions, GridPrintExportOptions, GridSlotsComponentsProps, GridExportDisplayOptions, GridRowHeightReturnValue, GridColumnVisibilityModel, GridPinnedRowsProp } from '@mui/x-data-grid-premium';
7
7
  interface CustomToolbarProps {
@@ -1,7 +1,7 @@
1
1
  import React, { JSX } from 'react';
2
2
  import { SxProps, Theme } from '@mui/material';
3
3
  import { DataGridPremiumProps, GridColDef, GridSlotsComponentsProps, GridToolbarProps, ToolbarPropsOverrides, GridColumnVisibilityModel } from '@mui/x-data-grid-premium';
4
- import { GridInitialStatePremium } from '@mui/x-data-grid-premium/models/gridStatePremium';
4
+ import { GridInitialState as GridInitialStatePremium } from '@mui/x-data-grid-premium';
5
5
  export interface MGHDataGridProps extends DataGridPremiumProps {
6
6
  rows: any[];
7
7
  columns: GridColDef[];
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { MGHGridProps, MGHGridValidRowModel } from './MGHGrid.types';
3
+ declare function MGHGrid<R extends MGHGridValidRowModel = any>(props: MGHGridProps<R>): React.JSX.Element;
4
+ declare namespace MGHGrid {
5
+ var displayName: string;
6
+ }
7
+ export default MGHGrid;
@@ -0,0 +1,10 @@
1
+ export declare const MGH_GRID_STYLE_ID = "mgh-grid-styles";
2
+ /**
3
+ * Stylesheet for MGHGrid. It is injected once into <head> the first time a grid mounts,
4
+ * so consumers do not need a CSS loader. All colours are CSS variables so the look can be
5
+ * customised globally (by redefining `--mgh-grid-*` on `.mgh-grid-card`) or per instance
6
+ * through the `themeVars` prop.
7
+ */
8
+ export declare const MGH_GRID_CSS = "\n.mgh-grid-card {\n --mgh-grid-font-family: inherit;\n --mgh-grid-font-size: 14px;\n --mgh-grid-radius: 16px;\n --mgh-grid-inner-radius: 4px;\n --mgh-grid-paper: #ffffff;\n --mgh-grid-bg: #ffffff;\n --mgh-grid-fg: rgba(0, 0, 0, 0.87);\n --mgh-grid-fg-secondary: rgba(0, 0, 0, 0.6);\n --mgh-grid-fg-disabled: rgba(0, 0, 0, 0.38);\n --mgh-grid-border: rgba(224, 224, 224, 1);\n --mgh-grid-header-bg: #ffffff;\n --mgh-grid-header-fg: rgba(0, 0, 0, 0.87);\n --mgh-grid-hover: rgba(0, 0, 0, 0.04);\n --mgh-grid-hover-strong: rgba(0, 0, 0, 0.08);\n --mgh-grid-selected: rgba(25, 118, 210, 0.08);\n --mgh-grid-selected-hover: rgba(25, 118, 210, 0.12);\n --mgh-grid-primary: #1976d2;\n --mgh-grid-primary-contrast: #ffffff;\n --mgh-grid-focus: #1976d2;\n --mgh-grid-shadow: 0 0 2px rgba(145, 158, 171, 0.2), 0 12px 24px -4px rgba(145, 158, 171, 0.12);\n --mgh-grid-popover-shadow: 0 5px 5px -3px rgba(0,0,0,.2), 0 8px 10px 1px rgba(0,0,0,.14), 0 3px 14px 2px rgba(0,0,0,.12);\n --mgh-grid-overlay: rgba(255, 255, 255, 0.6);\n --mgh-grid-input-bg: transparent;\n --mgh-grid-input-border: rgba(0, 0, 0, 0.23);\n --mgh-grid-pinned-shadow: rgba(0, 0, 0, 0.12);\n --mgh-grid-group-bg: rgba(0, 0, 0, 0.02);\n --mgh-grid-footer-bg: rgba(0, 0, 0, 0.02);\n --mgh-grid-badge: #1976d2;\n --mgh-grid-scrollbar: rgba(0, 0, 0, 0.3);\n\n position: relative;\n display: flex;\n flex-direction: column;\n min-width: 0;\n background: var(--mgh-grid-paper);\n color: var(--mgh-grid-fg);\n border-radius: var(--mgh-grid-radius);\n box-shadow: var(--mgh-grid-shadow);\n font-family: var(--mgh-grid-font-family);\n font-size: var(--mgh-grid-font-size);\n line-height: 1.5;\n overflow: hidden;\n box-sizing: border-box;\n}\n.mgh-grid-card[data-mgh-theme=\"dark\"] {\n --mgh-grid-paper: #212b36;\n --mgh-grid-bg: #212b36;\n --mgh-grid-fg: #ffffff;\n --mgh-grid-fg-secondary: rgba(255, 255, 255, 0.7);\n --mgh-grid-fg-disabled: rgba(255, 255, 255, 0.5);\n --mgh-grid-border: rgba(81, 81, 81, 1);\n --mgh-grid-header-bg: #212b36;\n --mgh-grid-header-fg: #ffffff;\n --mgh-grid-hover: rgba(255, 255, 255, 0.08);\n --mgh-grid-hover-strong: rgba(255, 255, 255, 0.16);\n --mgh-grid-selected: rgba(144, 202, 249, 0.16);\n --mgh-grid-selected-hover: rgba(144, 202, 249, 0.24);\n --mgh-grid-primary: #90caf9;\n --mgh-grid-primary-contrast: rgba(0, 0, 0, 0.87);\n --mgh-grid-focus: #90caf9;\n --mgh-grid-shadow: 0 0 2px rgba(0, 0, 0, 0.2), 0 12px 24px -4px rgba(0, 0, 0, 0.12);\n --mgh-grid-overlay: rgba(33, 43, 54, 0.6);\n --mgh-grid-input-border: rgba(255, 255, 255, 0.23);\n --mgh-grid-pinned-shadow: rgba(0, 0, 0, 0.5);\n --mgh-grid-group-bg: rgba(255, 255, 255, 0.03);\n --mgh-grid-footer-bg: rgba(255, 255, 255, 0.03);\n --mgh-grid-badge: #90caf9;\n --mgh-grid-scrollbar: rgba(255, 255, 255, 0.3);\n}\n.mgh-grid-card *, .mgh-grid-card *::before, .mgh-grid-card *::after,\n.mgh-grid-popover *, .mgh-grid-popover *::before, .mgh-grid-popover *::after { box-sizing: border-box; }\n.mgh-grid-card--plain { box-shadow: none; border-radius: 0; background: transparent; }\n\n/* ---- card header ---- */\n.mgh-grid-card-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 0 8px 0 0; flex-wrap: wrap; }\n.mgh-grid-card-title { padding: 24px 24px 0; margin: 0 0 16px; font-size: 1.125rem; font-weight: 700; line-height: 1.5556; }\n.mgh-grid-card-header-center { flex: 1 1 auto; display: flex; align-items: center; }\n.mgh-grid-card-header-end { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; justify-content: flex-end; }\n@media (max-width: 599.95px) { .mgh-grid-card-header-end { gap: 8px; } }\n\n/* ---- box + root ---- */\n.mgh-grid-box { display: flex; flex-direction: column; flex-grow: 1; min-height: 0; min-width: 0; }\n.mgh-grid {\n position: relative;\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-height: 0;\n min-width: 0;\n border: 1px solid var(--mgh-grid-border);\n border-radius: var(--mgh-grid-inner-radius);\n background: var(--mgh-grid-bg);\n color: var(--mgh-grid-fg);\n outline: none;\n}\n.mgh-grid--auto-height { flex: 0 0 auto; }\n\n/* ---- toolbar ---- */\n.mgh-grid-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 45px; padding: 4px 8px; border-bottom: 1px solid var(--mgh-grid-border); flex-wrap: wrap; }\n.mgh-grid-toolbar-group { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }\n.mgh-grid-toolbar-center { display: flex; align-items: center; flex: 1 1 auto; justify-content: center; }\n\n/* ---- buttons ---- */\n.mgh-grid-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; border: 0; margin: 0; background: transparent; color: var(--mgh-grid-fg-secondary); font: inherit; font-size: 0.8125rem; font-weight: 500; line-height: 1.75; letter-spacing: .02em; padding: 4px 8px; border-radius: 4px; cursor: pointer; user-select: none; transition: background-color .15s, color .15s; text-transform: none; white-space: nowrap; }\n.mgh-grid-btn:hover { background: var(--mgh-grid-hover); color: var(--mgh-grid-fg); }\n.mgh-grid-btn:focus-visible { outline: 2px solid var(--mgh-grid-focus); outline-offset: 1px; }\n.mgh-grid-btn:disabled { color: var(--mgh-grid-fg-disabled); cursor: default; background: transparent; }\n.mgh-grid-btn--icon { padding: 6px; border-radius: 50%; width: 32px; height: 32px; }\n.mgh-grid-btn--icon.mgh-grid-btn--small { width: 26px; height: 26px; padding: 3px; }\n.mgh-grid-btn--icon.mgh-grid-btn--small .mgh-grid-icon { width: 18px; height: 18px; }\n.mgh-grid-btn--primary { color: var(--mgh-grid-primary); }\n.mgh-grid-btn--primary:hover { background: var(--mgh-grid-selected); color: var(--mgh-grid-primary); }\n.mgh-grid-btn--contained { background: var(--mgh-grid-primary); color: var(--mgh-grid-primary-contrast); }\n.mgh-grid-btn--contained:hover { background: var(--mgh-grid-primary); color: var(--mgh-grid-primary-contrast); filter: brightness(0.92); }\n.mgh-grid-btn--active { color: var(--mgh-grid-primary); }\n\n/* ---- badge ---- */\n.mgh-grid-badge { position: relative; display: inline-flex; }\n.mgh-grid-badge-dot { position: absolute; top: 0; right: 0; min-width: 8px; height: 8px; border-radius: 4px; background: var(--mgh-grid-badge); transform: translate(50%, -50%); }\n.mgh-grid-badge-count { position: absolute; top: 0; right: 0; min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px; background: var(--mgh-grid-badge); color: var(--mgh-grid-primary-contrast); font-size: 10px; font-weight: 600; line-height: 16px; text-align: center; transform: translate(50%, -50%); }\n\n/* ---- inputs ---- */\n.mgh-grid-input, .mgh-grid-select { font: inherit; font-size: 0.875rem; color: var(--mgh-grid-fg); background: var(--mgh-grid-input-bg); border: 1px solid var(--mgh-grid-input-border); border-radius: 6px; padding: 6px 10px; height: 36px; min-width: 0; outline: none; transition: border-color .15s, box-shadow .15s; }\n.mgh-grid-input:hover, .mgh-grid-select:hover { border-color: var(--mgh-grid-fg); }\n.mgh-grid-input:focus, .mgh-grid-select:focus { border-color: var(--mgh-grid-focus); box-shadow: 0 0 0 1px var(--mgh-grid-focus); }\n.mgh-grid-input::placeholder { color: var(--mgh-grid-fg-disabled); }\n.mgh-grid-input--small, .mgh-grid-select--small { height: 32px; padding: 4px 8px; font-size: 0.8125rem; }\n.mgh-grid-select { appearance: none; -webkit-appearance: none; padding-right: 28px; background-image: url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23888'><path d='M7 10l5 5 5-5z'/></svg>\"); background-repeat: no-repeat; background-position: right 6px center; background-size: 18px; cursor: pointer; }\n.mgh-grid-select option { color: initial; background: initial; }\n.mgh-grid-card[data-mgh-theme=\"dark\"] .mgh-grid-select option, .mgh-grid-popover[data-mgh-theme=\"dark\"] .mgh-grid-select option { color: #fff; background: #212b36; }\n.mgh-grid-select[multiple] { height: auto; min-height: 36px; background-image: none; padding-right: 10px; }\n.mgh-grid-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }\n.mgh-grid-field-label { font-size: 0.75rem; color: var(--mgh-grid-fg-secondary); }\n.mgh-grid-input-adorned { position: relative; display: flex; align-items: center; }\n.mgh-grid-input-adorned .mgh-grid-input { width: 100%; padding-left: 34px; }\n.mgh-grid-input-adorned--clearable .mgh-grid-input { padding-right: 34px; }\n.mgh-grid-input-adornment { position: absolute; left: 10px; display: inline-flex; color: var(--mgh-grid-fg-secondary); pointer-events: none; }\n.mgh-grid-input-adornment--end { left: auto; right: 4px; pointer-events: auto; }\n\n/* ---- checkbox ---- */\n.mgh-grid-checkbox { appearance: none; -webkit-appearance: none; width: 18px; height: 18px; margin: 0; border: 2px solid var(--mgh-grid-fg-secondary); border-radius: 3px; background: transparent; cursor: pointer; display: inline-grid; place-content: center; position: relative; flex: 0 0 auto; transition: background-color .12s, border-color .12s; }\n.mgh-grid-checkbox:hover { border-color: var(--mgh-grid-fg); }\n.mgh-grid-checkbox:focus-visible { outline: 2px solid var(--mgh-grid-focus); outline-offset: 2px; }\n.mgh-grid-checkbox:checked, .mgh-grid-checkbox:indeterminate { background: var(--mgh-grid-primary); border-color: var(--mgh-grid-primary); }\n.mgh-grid-checkbox:checked::after { content: \"\"; width: 5px; height: 10px; border: solid var(--mgh-grid-primary-contrast); border-width: 0 2px 2px 0; transform: translateY(-1px) rotate(45deg); }\n.mgh-grid-checkbox:indeterminate::after { content: \"\"; width: 10px; height: 2px; background: var(--mgh-grid-primary-contrast); }\n.mgh-grid-checkbox:disabled { opacity: 0.4; cursor: default; }\n.mgh-grid-checkbox-label { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; font-size: 0.875rem; padding: 6px 4px; border-radius: 4px; }\n.mgh-grid-checkbox-label:hover { background: var(--mgh-grid-hover); }\n\n/* ---- quick filter ---- */\n.mgh-grid-quick-filter { display: grid; align-items: center; }\n.mgh-grid-quick-filter-trigger { grid-area: 1 / 1; z-index: 1; transition: opacity .2s; }\n.mgh-grid-quick-filter--expanded .mgh-grid-quick-filter-trigger { opacity: 0; pointer-events: none; }\n.mgh-grid-quick-filter-control { grid-area: 1 / 1; width: 32px; opacity: 0; overflow: hidden; transition: width .2s, opacity .2s; }\n.mgh-grid-quick-filter--expanded .mgh-grid-quick-filter-control { width: 260px; opacity: 1; }\n@media (max-width: 599.95px) { .mgh-grid-quick-filter--expanded .mgh-grid-quick-filter-control { width: 180px; } }\n\n/* ---- main / scroller ---- */\n.mgh-grid-main { position: relative; display: flex; flex: 1 1 auto; min-height: 0; min-width: 0; overflow: hidden; }\n.mgh-grid--auto-height .mgh-grid-main { flex: 0 0 auto; }\n.mgh-grid-scroller { position: relative; flex: 1 1 auto; min-height: 0; min-width: 0; overflow: auto; outline: none; scrollbar-width: thin; }\n.mgh-grid--auto-height .mgh-grid-scroller { overflow-y: hidden; }\n.mgh-grid-scroller::-webkit-scrollbar { width: 10px; height: 10px; }\n.mgh-grid-scroller::-webkit-scrollbar-thumb { background: var(--mgh-grid-scrollbar); border-radius: 5px; border: 2px solid transparent; background-clip: content-box; }\n\n/* ---- column headers ---- */\n.mgh-grid-columns { position: sticky; top: 0; z-index: 3; background: var(--mgh-grid-header-bg); border-bottom: 1px solid var(--mgh-grid-border); min-width: 100%; width: max-content; }\n.mgh-grid-header-row { display: flex; min-width: 100%; }\n.mgh-grid-header-cell { position: relative; display: flex; align-items: center; flex: 0 0 auto; height: var(--mgh-grid-header-height); padding: 0 10px; font-weight: 600; font-size: 0.875rem; color: var(--mgh-grid-header-fg); background: var(--mgh-grid-header-bg); white-space: nowrap; overflow: hidden; user-select: none; outline: none; }\n.mgh-grid-header-cell--sortable { cursor: pointer; }\n.mgh-grid-header-cell:focus-visible { outline: 2px solid var(--mgh-grid-focus); outline-offset: -2px; }\n.mgh-grid-header-cell--align-center { justify-content: center; }\n.mgh-grid-header-cell--align-right { justify-content: flex-end; }\n.mgh-grid-header-cell--align-right .mgh-grid-header-title-container { flex-direction: row-reverse; }\n.mgh-grid-header-title-container { display: flex; align-items: center; gap: 2px; min-width: 0; flex: 1 1 auto; overflow: hidden; }\n.mgh-grid-header-cell--align-center .mgh-grid-header-title-container { flex: 0 1 auto; }\n.mgh-grid-header-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.mgh-grid-sort-icon { display: inline-flex; align-items: center; color: var(--mgh-grid-fg-secondary); opacity: 0; transition: opacity .15s; flex: 0 0 auto; }\n.mgh-grid-header-cell:hover .mgh-grid-sort-icon, .mgh-grid-sort-icon--active { opacity: 1; }\n.mgh-grid-sort-index { font-size: 10px; margin-left: -2px; color: var(--mgh-grid-fg-secondary); }\n.mgh-grid-header-menu-btn { position: absolute; right: 2px; opacity: 0; transition: opacity .15s; background: var(--mgh-grid-header-bg); }\n.mgh-grid-header-cell--align-right .mgh-grid-header-menu-btn { right: auto; left: 2px; }\n.mgh-grid-header-cell:hover .mgh-grid-header-menu-btn, .mgh-grid-header-menu-btn--open, .mgh-grid-header-cell:focus-within .mgh-grid-header-menu-btn { opacity: 1; }\n.mgh-grid-header-cell--menu-open { background: var(--mgh-grid-hover); }\n.mgh-grid-resize-handle { position: absolute; top: 0; right: -4px; width: 9px; height: 100%; cursor: col-resize; z-index: 2; display: flex; justify-content: center; touch-action: none; }\n.mgh-grid-resize-handle::after { content: \"\"; width: 1px; height: 60%; margin-top: 20%; background: var(--mgh-grid-border); transition: background .15s, width .15s; }\n.mgh-grid-resize-handle:hover::after, .mgh-grid-resize-handle--active::after { background: var(--mgh-grid-primary); width: 2px; }\n.mgh-grid-header-cell--last .mgh-grid-resize-handle { right: 0; }\n.mgh-grid-header-cell--dragging { opacity: 0.5; }\n.mgh-grid-header-cell--drop-left::before, .mgh-grid-header-cell--drop-right::before { content: \"\"; position: absolute; top: 4px; bottom: 4px; width: 2px; background: var(--mgh-grid-primary); z-index: 3; }\n.mgh-grid-header-cell--drop-left::before { left: 0; }\n.mgh-grid-header-cell--drop-right::before { right: 0; }\n.mgh-grid-header-filler { flex: 1 1 auto; background: var(--mgh-grid-header-bg); }\n\n/* ---- pinned cells ---- */\n.mgh-grid-cell--pinned-left, .mgh-grid-header-cell--pinned-left { position: sticky; z-index: 2; background-color: var(--mgh-grid-bg); }\n.mgh-grid-cell--pinned-right, .mgh-grid-header-cell--pinned-right { position: sticky; z-index: 2; background-color: var(--mgh-grid-bg); }\n.mgh-grid-header-cell--pinned-left, .mgh-grid-header-cell--pinned-right { z-index: 4; background-color: var(--mgh-grid-header-bg); }\n.mgh-grid-cell--pinned-left-last, .mgh-grid-header-cell--pinned-left-last { box-shadow: 2px 0 4px -2px var(--mgh-grid-pinned-shadow); }\n.mgh-grid-cell--pinned-right-first, .mgh-grid-header-cell--pinned-right-first { box-shadow: -2px 0 4px -2px var(--mgh-grid-pinned-shadow); }\n.mgh-grid--no-pinned-shadow .mgh-grid-cell--pinned-left-last, .mgh-grid--no-pinned-shadow .mgh-grid-header-cell--pinned-left-last { box-shadow: none; }\n\n/* ---- body & rows ---- */\n.mgh-grid-body { position: relative; min-width: 100%; width: max-content; }\n.mgh-grid-body--flow { display: flex; flex-direction: column; }\n.mgh-grid-row-block { min-width: 100%; }\n.mgh-grid-body--virtual .mgh-grid-row-block { position: absolute; left: 0; }\n.mgh-grid-row { display: flex; min-width: 100%; border-bottom: 1px solid var(--mgh-grid-border); background: var(--mgh-grid-bg); position: relative; }\n.mgh-grid-row--auto-height { align-items: stretch; }\n.mgh-grid-row:hover { background: var(--mgh-grid-hover); }\n.mgh-grid-row--selected { background: var(--mgh-grid-selected); }\n.mgh-grid-row--selected:hover { background: var(--mgh-grid-selected-hover); }\n.mgh-grid-row--clickable { cursor: pointer; }\n.mgh-grid-row--group { background: var(--mgh-grid-group-bg); }\n.mgh-grid-row--pinned { background: var(--mgh-grid-bg); }\n.mgh-grid-row--footer { background: var(--mgh-grid-footer-bg); font-weight: 600; }\n.mgh-grid-row:hover .mgh-grid-cell--pinned-left, .mgh-grid-row:hover .mgh-grid-cell--pinned-right { background-image: linear-gradient(var(--mgh-grid-hover), var(--mgh-grid-hover)); }\n.mgh-grid-row--selected .mgh-grid-cell--pinned-left, .mgh-grid-row--selected .mgh-grid-cell--pinned-right { background-image: linear-gradient(var(--mgh-grid-selected), var(--mgh-grid-selected)); }\n.mgh-grid-row--selected:hover .mgh-grid-cell--pinned-left, .mgh-grid-row--selected:hover .mgh-grid-cell--pinned-right { background-image: linear-gradient(var(--mgh-grid-selected-hover), var(--mgh-grid-selected-hover)); }\n.mgh-grid-row--group .mgh-grid-cell--pinned-left, .mgh-grid-row--group .mgh-grid-cell--pinned-right { background-image: linear-gradient(var(--mgh-grid-group-bg), var(--mgh-grid-group-bg)); }\n.mgh-grid-row--footer .mgh-grid-cell--pinned-left, .mgh-grid-row--footer .mgh-grid-cell--pinned-right { background-image: linear-gradient(var(--mgh-grid-footer-bg), var(--mgh-grid-footer-bg)); }\n.mgh-grid-row-filler { flex: 1 1 auto; }\n\n.mgh-grid-cell { display: flex; align-items: center; flex: 0 0 auto; padding: 0 10px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 0.875rem; outline: none; min-height: 100%; }\n.mgh-grid-cell > .mgh-grid-cell-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }\n.mgh-grid-row--auto-height .mgh-grid-cell { white-space: normal; align-items: flex-start; padding-top: 8px; padding-bottom: 8px; }\n.mgh-grid-row--auto-height .mgh-grid-cell > .mgh-grid-cell-text { white-space: normal; word-break: break-word; }\n.mgh-grid-cell--align-center { justify-content: center; }\n.mgh-grid-cell--align-right { justify-content: flex-end; }\n.mgh-grid-cell--focused { outline: 1px solid var(--mgh-grid-focus); outline-offset: -1px; }\n.mgh-grid-cell--editable { cursor: text; }\n.mgh-grid-cell--editing { padding: 0 4px; outline: 2px solid var(--mgh-grid-focus); outline-offset: -2px; background: var(--mgh-grid-bg); }\n.mgh-grid-cell--editing .mgh-grid-input, .mgh-grid-cell--editing .mgh-grid-select { width: 100%; height: calc(100% - 6px); border: 0; box-shadow: none; padding: 0 6px; background: transparent; }\n.mgh-grid-cell--checkbox, .mgh-grid-header-cell--checkbox, .mgh-grid-cell--detail-toggle, .mgh-grid-header-cell--detail-toggle { justify-content: center; padding: 0; }\n.mgh-grid-cell--boolean .mgh-grid-icon { color: var(--mgh-grid-fg-secondary); }\n.mgh-grid-cell--actions { gap: 2px; justify-content: center; }\n.mgh-grid-cell--aggregation { flex-direction: column; align-items: stretch; justify-content: center; line-height: 1.2; }\n.mgh-grid-cell--aggregation.mgh-grid-cell--align-right { align-items: flex-end; }\n.mgh-grid-cell--aggregation.mgh-grid-cell--align-center { align-items: center; }\n.mgh-grid-aggregation-label { font-size: 0.65rem; font-weight: 500; text-transform: uppercase; color: var(--mgh-grid-fg-secondary); letter-spacing: .04em; }\n.mgh-grid-group-cell { display: flex; align-items: center; gap: 4px; min-width: 0; }\n.mgh-grid-group-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }\n.mgh-grid-group-count { color: var(--mgh-grid-fg-secondary); margin-left: 2px; }\n.mgh-grid-group-toggle { flex: 0 0 auto; }\n.mgh-grid-group-toggle .mgh-grid-icon { transition: transform .15s; }\n.mgh-grid-group-toggle--expanded .mgh-grid-icon { transform: rotate(90deg); }\n.mgh-grid-detail-toggle .mgh-grid-icon { transition: transform .15s; }\n.mgh-grid-detail-toggle--expanded .mgh-grid-icon { transform: rotate(180deg); }\n\n/* ---- pinned rows ---- */\n.mgh-grid-pinned-rows { position: sticky; z-index: 2; min-width: 100%; width: max-content; background: var(--mgh-grid-bg); }\n.mgh-grid-pinned-rows--top { box-shadow: 0 2px 4px -2px var(--mgh-grid-pinned-shadow); }\n.mgh-grid-pinned-rows--bottom { bottom: 0; box-shadow: 0 -2px 4px -2px var(--mgh-grid-pinned-shadow); }\n.mgh-grid-pinned-rows--bottom .mgh-grid-row { border-bottom: 0; border-top: 1px solid var(--mgh-grid-border); }\n\n/* ---- detail panel ---- */\n.mgh-grid-detail-panel { position: sticky; left: 0; overflow: auto; border-bottom: 1px solid var(--mgh-grid-border); background: var(--mgh-grid-bg); z-index: 1; }\n\n/* ---- overlays ---- */\n.mgh-grid-overlay { position: absolute; left: 0; right: 0; bottom: 0; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 8px; z-index: 5; color: var(--mgh-grid-fg-secondary); font-size: 0.875rem; pointer-events: none; }\n.mgh-grid-overlay--loading { background: var(--mgh-grid-overlay); pointer-events: auto; }\n.mgh-grid-no-rows { display: flex; align-items: center; justify-content: center; gap: 8px; height: 100%; text-align: center; padding: 16px; }\n.mgh-grid-no-rows img, .mgh-grid-no-rows .mgh-grid-icon { width: 50px; height: 50px; color: var(--mgh-grid-fg-disabled); }\n.mgh-grid-spinner { width: 36px; height: 36px; border-radius: 50%; border: 3px solid var(--mgh-grid-selected); border-top-color: var(--mgh-grid-primary); animation: mgh-grid-spin .8s linear infinite; }\n@keyframes mgh-grid-spin { to { transform: rotate(360deg); } }\n\n/* ---- footer ---- */\n.mgh-grid-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 52px; padding: 0 8px 0 16px; border-top: 1px solid var(--mgh-grid-border); font-size: 0.875rem; color: var(--mgh-grid-fg-secondary); flex-wrap: wrap; }\n.mgh-grid-footer-left { display: flex; align-items: center; gap: 16px; }\n.mgh-grid-pagination { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-wrap: wrap; }\n.mgh-grid-pagination-select { height: 32px; padding: 2px 24px 2px 8px; font-size: 0.875rem; border-color: transparent; }\n.mgh-grid-pagination-select:hover { border-color: transparent; background-color: var(--mgh-grid-hover); }\n.mgh-grid-pagination-actions { display: inline-flex; align-items: center; }\n\n/* ---- popover / menu / panels ---- */\n.mgh-grid-popover {\n --mgh-grid-font-family: inherit; --mgh-grid-font-size: 14px; --mgh-grid-paper: #ffffff; --mgh-grid-bg: #fff; --mgh-grid-fg: rgba(0,0,0,.87); --mgh-grid-fg-secondary: rgba(0,0,0,.6); --mgh-grid-fg-disabled: rgba(0,0,0,.38); --mgh-grid-border: rgba(224,224,224,1); --mgh-grid-hover: rgba(0,0,0,.04); --mgh-grid-selected: rgba(25,118,210,.08); --mgh-grid-primary: #1976d2; --mgh-grid-primary-contrast: #fff; --mgh-grid-focus: #1976d2; --mgh-grid-input-bg: transparent; --mgh-grid-input-border: rgba(0,0,0,.23); --mgh-grid-popover-shadow: 0 5px 5px -3px rgba(0,0,0,.2), 0 8px 10px 1px rgba(0,0,0,.14), 0 3px 14px 2px rgba(0,0,0,.12);\n position: fixed; z-index: 1300; background: var(--mgh-grid-paper); color: var(--mgh-grid-fg); border-radius: 8px; box-shadow: var(--mgh-grid-popover-shadow); font-family: var(--mgh-grid-font-family); font-size: var(--mgh-grid-font-size); line-height: 1.5; outline: none; max-height: calc(100vh - 16px); overflow: auto; animation: mgh-grid-pop .12s ease-out;\n}\n.mgh-grid-popover[data-mgh-theme=\"dark\"] { --mgh-grid-paper: #212b36; --mgh-grid-bg: #212b36; --mgh-grid-fg: #fff; --mgh-grid-fg-secondary: rgba(255,255,255,.7); --mgh-grid-fg-disabled: rgba(255,255,255,.5); --mgh-grid-border: rgba(81,81,81,1); --mgh-grid-hover: rgba(255,255,255,.08); --mgh-grid-selected: rgba(144,202,249,.16); --mgh-grid-primary: #90caf9; --mgh-grid-primary-contrast: rgba(0,0,0,.87); --mgh-grid-focus: #90caf9; --mgh-grid-input-border: rgba(255,255,255,.23); }\n@keyframes mgh-grid-pop { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } }\n.mgh-grid-menu { list-style: none; margin: 0; padding: 6px 0; min-width: 180px; }\n.mgh-grid-menu-item { display: flex; align-items: center; gap: 12px; padding: 6px 16px; min-height: 36px; font-size: 0.875rem; cursor: pointer; white-space: nowrap; color: var(--mgh-grid-fg); background: transparent; border: 0; width: 100%; text-align: left; font-family: inherit; outline: none; }\n.mgh-grid-menu-item:hover, .mgh-grid-menu-item:focus-visible { background: var(--mgh-grid-hover); }\n.mgh-grid-menu-item--disabled { color: var(--mgh-grid-fg-disabled); cursor: default; pointer-events: none; }\n.mgh-grid-menu-item--selected { background: var(--mgh-grid-selected); }\n.mgh-grid-menu-item .mgh-grid-icon { color: var(--mgh-grid-fg-secondary); flex: 0 0 auto; }\n.mgh-grid-menu-divider { height: 1px; margin: 6px 0; background: var(--mgh-grid-border); border: 0; }\n.mgh-grid-menu-header { padding: 6px 16px 2px; font-size: 0.75rem; color: var(--mgh-grid-fg-secondary); text-transform: uppercase; letter-spacing: .04em; }\n.mgh-grid-menu-section { padding: 4px 16px 8px; display: flex; flex-direction: column; gap: 4px; }\n.mgh-grid-panel { display: flex; flex-direction: column; min-width: 300px; max-width: min(640px, calc(100vw - 16px)); }\n.mgh-grid-panel-header { padding: 12px 12px 4px; }\n.mgh-grid-panel-content { padding: 4px 12px; overflow: auto; max-height: 360px; }\n.mgh-grid-panel-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 12px; }\n.mgh-grid-columns-list { display: flex; flex-direction: column; }\n.mgh-grid-filter-row { display: grid; grid-template-columns: 32px minmax(120px, 1fr) minmax(120px, 1fr) minmax(140px, 1.3fr); gap: 8px; align-items: end; margin-bottom: 8px; }\n.mgh-grid-filter-row--first { grid-template-columns: 32px minmax(120px, 1fr) minmax(120px, 1fr) minmax(140px, 1.3fr); }\n.mgh-grid-filter-row--with-logic { grid-template-columns: 32px 80px minmax(120px, 1fr) minmax(120px, 1fr) minmax(140px, 1.3fr); }\n.mgh-grid-filter-row .mgh-grid-btn--icon { margin-bottom: 4px; }\n.mgh-grid-filter-empty { padding: 8px 4px; color: var(--mgh-grid-fg-secondary); font-size: 0.875rem; }\n@media (max-width: 599.95px) { .mgh-grid-filter-row, .mgh-grid-filter-row--with-logic { grid-template-columns: 1fr; } }\n\n/* ---- misc ---- */\n.mgh-grid-tooltip-anchor { display: inline-flex; }\n.mgh-grid-visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); border: 0; }\n@media print { .mgh-grid-toolbar, .mgh-grid-footer { display: none !important; } }\n";
9
+ /** Injects the MGHGrid stylesheet once per document. Safe on the server (no-op). */
10
+ export declare const useMGHGridStyles: () => void;