From 85b3a1d9ac6b3ae34dacd06b8dfb8690c061bdce Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Tue, 7 Jul 2026 13:02:56 +0200 Subject: [PATCH 01/12] Added base for tailwind styling. --- .../grid-lite/components-react/package.json | 3 +- .../grid-lite/components-react/src/App.tsx | 208 +++++---- .../grid-lite/components-react/src/index.css | 23 +- .../grid-lite/components-react/vite.config.ts | 4 +- packages/grid-lite-react/src/Grid.tsx | 10 +- packages/grid-pro-react/src/Grid.tsx | 10 +- .../src/components/BaseGrid.tsx | 13 +- pnpm-lock.yaml | 428 +++++++++++++++--- 8 files changed, 519 insertions(+), 180 deletions(-) diff --git a/examples/grid-lite/components-react/package.json b/examples/grid-lite/components-react/package.json index cd5b45a..b98f691 100644 --- a/examples/grid-lite/components-react/package.json +++ b/examples/grid-lite/components-react/package.json @@ -16,11 +16,12 @@ "react-dom": ">=18" }, "devDependencies": { + "@tailwindcss/vite": "^4.3.2", "@types/react": ">=18", "@types/react-dom": ">=18", "@vitejs/plugin-react": "^4.2.0", + "tailwindcss": "^4.3.2", "typescript": "^5.0.0", "vite": "^5.0.0" } } - diff --git a/examples/grid-lite/components-react/src/App.tsx b/examples/grid-lite/components-react/src/App.tsx index cdb84e1..5f04361 100644 --- a/examples/grid-lite/components-react/src/App.tsx +++ b/examples/grid-lite/components-react/src/App.tsx @@ -71,102 +71,120 @@ function App() { // }; return ( - <> - - - - Grid Caption v2.1 -
- - - - - - Grid Description - - -
- - {/* */} +
+ + + + Grid Caption v2.1 +
+ + + + + + Grid Description + + +
+ + {/* */} +
- ); } diff --git a/examples/grid-lite/components-react/src/index.css b/examples/grid-lite/components-react/src/index.css index 9a63579..ba656e7 100644 --- a/examples/grid-lite/components-react/src/index.css +++ b/examples/grid-lite/components-react/src/index.css @@ -1,8 +1,4 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} +@import "tailwindcss"; body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', @@ -15,19 +11,4 @@ body { #root { width: 100%; min-height: 100vh; - padding: 20px; -} - -#controls { - margin-top: 20px; - display: flex; - gap: 10px; -} - -@media (prefers-color-scheme: dark) { - body { - background-color: #121212; - color: #ffffff; - } -} - +} \ No newline at end of file diff --git a/examples/grid-lite/components-react/vite.config.ts b/examples/grid-lite/components-react/vite.config.ts index 2e3f28b..0ec7891 100644 --- a/examples/grid-lite/components-react/vite.config.ts +++ b/examples/grid-lite/components-react/vite.config.ts @@ -1,12 +1,13 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; +import tailwindcss from '@tailwindcss/vite'; import { resolve, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); export default defineConfig({ - plugins: [react()], + plugins: [react(), tailwindcss()], resolve: { alias: [ { @@ -24,6 +25,7 @@ export default defineConfig({ ] }, server: { + host: true, port: 3000 } }); diff --git a/packages/grid-lite-react/src/Grid.tsx b/packages/grid-lite-react/src/Grid.tsx index aa47803..ee6ede3 100644 --- a/packages/grid-lite-react/src/Grid.tsx +++ b/packages/grid-lite-react/src/Grid.tsx @@ -19,7 +19,7 @@ import '@highcharts/grid-lite/css/grid-lite.css'; import type { Options } from '@highcharts/grid-lite/es-modules/Grid/Core/Options'; export default function GridLite(props: GridProps) { - const { gridRef, children, options, ...gridProps } = props; + const { gridRef, children, options, theme, ...gridProps } = props; const childOptions = useMemo(() => getChildProps(children), [children]); const columnKey = useMemo(() => { const columns = childOptions.columns as Array<{ id?: string }> | undefined; @@ -27,8 +27,12 @@ export default function GridLite(props: GridProps) { return columns?.map((column) => column.id).join('\0') ?? ''; }, [childOptions]); const gridOptions = useMemo( - () => merge(childOptions, options ?? {}) as Options, - [childOptions, options] + () => merge( + childOptions, + options ?? {}, + theme ? { rendering: { theme } } : {} + ) as Options, + [childOptions, options, theme] ); return ( diff --git a/packages/grid-pro-react/src/Grid.tsx b/packages/grid-pro-react/src/Grid.tsx index c236cfd..7f5d317 100644 --- a/packages/grid-pro-react/src/Grid.tsx +++ b/packages/grid-pro-react/src/Grid.tsx @@ -19,7 +19,7 @@ import '@highcharts/grid-pro/css/grid-pro.css'; import type { Options } from '@highcharts/grid-pro/es-modules/Grid/Core/Options'; export default function GridPro(props: GridProps) { - const { gridRef, children, options, ...gridProps } = props; + const { gridRef, children, options, theme, ...gridProps } = props; const childOptions = useMemo(() => getChildProps(children), [children]); const columnKey = useMemo(() => { const columns = childOptions.columns as Array<{ id?: string }> | undefined; @@ -27,8 +27,12 @@ export default function GridPro(props: GridProps) { return columns?.map((column) => column.id).join('\0') ?? ''; }, [childOptions]); const gridOptions = useMemo( - () => merge(childOptions, options ?? {}) as Options, - [childOptions, options] + () => merge( + childOptions, + options ?? {}, + theme ? { rendering: { theme } } : {} + ) as Options, + [childOptions, options, theme] ); return ( diff --git a/packages/grid-shared-react/src/components/BaseGrid.tsx b/packages/grid-shared-react/src/components/BaseGrid.tsx index 4d51c20..11be983 100644 --- a/packages/grid-shared-react/src/components/BaseGrid.tsx +++ b/packages/grid-shared-react/src/components/BaseGrid.tsx @@ -32,6 +32,14 @@ export interface GridProps { * Grid configuration options */ options?: TOptions; + /** + * Optional CSS class name applied to the root grid container. + */ + className?: string; + /** + * Optional theme name passed to Grid Core. + */ + theme?: string; /** * Declarative option components (e.g. Caption) passed as children. */ @@ -53,13 +61,14 @@ export interface BaseGridProps { options?: TOptions; Grid: GridType; callback?: (grid: GridInstance) => void; + className?: string; } export const BaseGrid = forwardRef(function BaseGrid( props: BaseGridProps, ref: ForwardedRef> ) { - const { options, Grid, callback } = props; + const { options, Grid, callback, className } = props; const containerRef = useRef(null); const currGridRef = useGrid({ @@ -79,5 +88,5 @@ export const BaseGrid = forwardRef(function BaseGrid( [] ); - return
; + return
; }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ff81d18..e4aa239 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: 9.39.1 '@stylistic/eslint-plugin': specifier: ^5.6.1 - version: 5.6.1(eslint@9.39.1) + version: 5.6.1(eslint@9.39.1(jiti@2.7.0)) '@testing-library/react': specifier: ^16.3.1 version: 16.3.1(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -22,13 +22,13 @@ importers: version: 20.19.26 '@vitest/browser': specifier: ^4.0.16 - version: 4.0.16(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16) + version: 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16) '@vitest/browser-playwright': specifier: ^4.0.16 - version: 4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16) + version: 4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16) eslint: specifier: ^9.39.1 - version: 9.39.1 + version: 9.39.1(jiti@2.7.0) globals: specifier: ^17.0.0 version: 17.0.0 @@ -43,10 +43,10 @@ importers: version: 5.9.3 typescript-eslint: specifier: ^8.48.0 - version: 8.49.0(eslint@9.39.1)(typescript@5.9.3) + version: 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) vitest: specifier: ^4.0.16 - version: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jsdom@27.4.0) + version: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jiti@2.7.0)(jsdom@27.4.0)(lightningcss@1.32.0) examples/grid-lite/components-react: dependencies: @@ -63,6 +63,9 @@ importers: specifier: '>=18' version: 19.2.1(react@19.2.1) devDependencies: + '@tailwindcss/vite': + specifier: ^4.3.2 + version: 4.3.2(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0)) '@types/react': specifier: '>=18' version: 19.2.7 @@ -71,13 +74,16 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^4.2.0 - version: 4.7.0(vite@5.4.21(@types/node@20.19.26)) + version: 4.7.0(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0)) + tailwindcss: + specifier: ^4.3.2 + version: 4.3.2 typescript: specifier: ^5.0.0 version: 5.9.3 vite: specifier: ^5.0.0 - version: 5.4.21(@types/node@20.19.26) + version: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) examples/grid-lite/minimal-nextjs: dependencies: @@ -133,13 +139,13 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^4.2.0 - version: 4.7.0(vite@5.4.21(@types/node@20.19.26)) + version: 4.7.0(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0)) typescript: specifier: ^5.0.0 version: 5.9.3 vite: specifier: ^5.0.0 - version: 5.4.21(@types/node@20.19.26) + version: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) examples/grid-pro/minimal-nextjs: dependencies: @@ -195,13 +201,13 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^4.2.0 - version: 4.7.0(vite@5.4.21(@types/node@20.19.26)) + version: 4.7.0(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0)) typescript: specifier: ^5.0.0 version: 5.9.3 vite: specifier: ^5.0.0 - version: 5.4.21(@types/node@20.19.26) + version: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) packages/grid-lite-react: dependencies: @@ -1055,6 +1061,96 @@ packages: '@swc/helpers@0.5.5': resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} + '@tailwindcss/node@4.3.2': + resolution: {integrity: sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==} + + '@tailwindcss/oxide-android-arm64@4.3.2': + resolution: {integrity: sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.2': + resolution: {integrity: sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.2': + resolution: {integrity: sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.2': + resolution: {integrity: sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + resolution: {integrity: sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + resolution: {integrity: sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + resolution: {integrity: sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + resolution: {integrity: sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.3.2': + resolution: {integrity: sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.3.2': + resolution: {integrity: sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + resolution: {integrity: sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + resolution: {integrity: sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.2': + resolution: {integrity: sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==} + engines: {node: '>= 20'} + + '@tailwindcss/vite@4.3.2': + resolution: {integrity: sha512-eHpMeX4JXfVNJDEcsouTeCBubJBTcTLigeaw/NTUW6PB5ATKKXdyonnXgTBX2VuRbjz1hjfz6C5XAhr52ImQXA==} + peerDependencies: + vite: ^5.2.0 || ^6 || ^7 || ^8 + '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} @@ -1360,12 +1456,20 @@ packages: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + dom-accessibility-api@0.5.16: resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} electron-to-chromium@1.5.267: resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} + enhanced-resolve@5.21.6: + resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} + engines: {node: '>=10.13.0'} + entities@6.0.1: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} @@ -1572,6 +1676,10 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1614,6 +1722,76 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -1897,6 +2075,13 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tailwindcss@4.3.2: + resolution: {integrity: sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -2444,9 +2629,9 @@ snapshots: '@esbuild/win32-x64@0.25.12': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.7.0))': dependencies: - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -2673,11 +2858,11 @@ snapshots: '@standard-schema/spec@1.0.0': {} - '@stylistic/eslint-plugin@5.6.1(eslint@9.39.1)': + '@stylistic/eslint-plugin@5.6.1(eslint@9.39.1(jiti@2.7.0))': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.7.0)) '@typescript-eslint/types': 8.49.0 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 @@ -2690,6 +2875,74 @@ snapshots: '@swc/counter': 0.1.3 tslib: 2.8.1 + '@tailwindcss/node@4.3.2': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.21.6 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.3.2 + + '@tailwindcss/oxide-android-arm64@4.3.2': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.2': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.2': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.2': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.2': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.2': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.2': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.2': + optional: true + + '@tailwindcss/oxide@4.3.2': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-arm64': 4.3.2 + '@tailwindcss/oxide-darwin-x64': 4.3.2 + '@tailwindcss/oxide-freebsd-x64': 4.3.2 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.2 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.2 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.2 + '@tailwindcss/oxide-linux-x64-musl': 4.3.2 + '@tailwindcss/oxide-wasm32-wasi': 4.3.2 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.2 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.2 + + '@tailwindcss/vite@4.3.2(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0))': + dependencies: + '@tailwindcss/node': 4.3.2 + '@tailwindcss/oxide': 4.3.2 + tailwindcss: 4.3.2 + vite: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) + '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.27.1 @@ -2759,15 +3012,15 @@ snapshots: '@types/resolve@1.20.2': {} - '@typescript-eslint/eslint-plugin@8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.49.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.49.0 - '@typescript-eslint/type-utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.49.0 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.1.0(typescript@5.9.3) @@ -2775,14 +3028,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/parser@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.49.0 '@typescript-eslint/types': 8.49.0 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.49.0 debug: 4.4.3 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2805,13 +3058,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.49.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.49.0 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -2834,13 +3087,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.49.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.7.0)) '@typescript-eslint/scope-manager': 8.49.0 '@typescript-eslint/types': 8.49.0 '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2850,7 +3103,7 @@ snapshots: '@typescript-eslint/types': 8.49.0 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@20.19.26))': + '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) @@ -2858,33 +3111,33 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.27 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 5.4.21(@types/node@20.19.26) + vite: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) transitivePeerDependencies: - supports-color - '@vitest/browser-playwright@4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16)': + '@vitest/browser-playwright@4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16)': dependencies: - '@vitest/browser': 4.0.16(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16) - '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)) + '@vitest/browser': 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16) + '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0)) playwright: 1.57.0 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jsdom@27.4.0) + vitest: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jiti@2.7.0)(jsdom@27.4.0)(lightningcss@1.32.0) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/browser@4.0.16(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16)': + '@vitest/browser@4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16)': dependencies: - '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)) + '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0)) '@vitest/utils': 4.0.16 magic-string: 0.30.21 pixelmatch: 7.1.0 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.0.3 - vitest: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jsdom@27.4.0) + vitest: 4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jiti@2.7.0)(jsdom@27.4.0)(lightningcss@1.32.0) ws: 8.18.3 transitivePeerDependencies: - bufferutil @@ -2901,13 +3154,13 @@ snapshots: chai: 6.2.1 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.16(vite@7.2.7(@types/node@20.19.26))': + '@vitest/mocker@4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))': dependencies: '@vitest/spy': 4.0.16 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.2.7(@types/node@20.19.26) + vite: 7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0) '@vitest/pretty-format@4.0.16': dependencies: @@ -3059,10 +3312,17 @@ snapshots: dequal@2.0.3: {} + detect-libc@2.1.2: {} + dom-accessibility-api@0.5.16: {} electron-to-chromium@1.5.267: {} + enhanced-resolve@5.21.6: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + entities@6.0.1: optional: true @@ -3136,9 +3396,9 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.1: + eslint@9.39.1(jiti@2.7.0): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.7.0)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 @@ -3172,6 +3432,8 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.7.0 transitivePeerDependencies: - supports-color @@ -3314,6 +3576,8 @@ snapshots: isexe@2.0.0: {} + jiti@2.7.0: {} + js-tokens@4.0.0: {} js-yaml@4.1.1: @@ -3368,6 +3632,55 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -3633,6 +3946,10 @@ snapshots: symbol-tree@3.2.4: optional: true + tailwindcss@4.3.2: {} + + tapable@2.3.3: {} + tinybench@2.9.0: {} tinyexec@1.0.2: {} @@ -3674,13 +3991,13 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.49.0(eslint@9.39.1)(typescript@5.9.3): + typescript-eslint@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/parser': 8.49.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.49.0(@typescript-eslint/parser@8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.49.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.49.0(eslint@9.39.1)(typescript@5.9.3) - eslint: 9.39.1 + '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.7.0))(typescript@5.9.3) + eslint: 9.39.1(jiti@2.7.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -3699,7 +4016,7 @@ snapshots: dependencies: punycode: 2.3.1 - vite@5.4.21(@types/node@20.19.26): + vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0): dependencies: esbuild: 0.21.5 postcss: 8.5.6 @@ -3707,8 +4024,9 @@ snapshots: optionalDependencies: '@types/node': 20.19.26 fsevents: 2.3.3 + lightningcss: 1.32.0 - vite@7.2.7(@types/node@20.19.26): + vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -3719,11 +4037,13 @@ snapshots: optionalDependencies: '@types/node': 20.19.26 fsevents: 2.3.3 + jiti: 2.7.0 + lightningcss: 1.32.0 - vitest@4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jsdom@27.4.0): + vitest@4.0.16(@types/node@20.19.26)(@vitest/browser-playwright@4.0.16)(jiti@2.7.0)(jsdom@27.4.0)(lightningcss@1.32.0): dependencies: '@vitest/expect': 4.0.16 - '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)) + '@vitest/mocker': 4.0.16(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0)) '@vitest/pretty-format': 4.0.16 '@vitest/runner': 4.0.16 '@vitest/snapshot': 4.0.16 @@ -3740,11 +4060,11 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.2.7(@types/node@20.19.26) + vite: 7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.19.26 - '@vitest/browser-playwright': 4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26))(vitest@4.0.16) + '@vitest/browser-playwright': 4.0.16(playwright@1.57.0)(vite@7.2.7(@types/node@20.19.26)(jiti@2.7.0)(lightningcss@1.32.0))(vitest@4.0.16) jsdom: 27.4.0 transitivePeerDependencies: - jiti From fe9d1360ab6f9e9a95ca615a29e7f983e7097c2a Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Wed, 8 Jul 2026 09:42:11 +0200 Subject: [PATCH 02/12] Init changes for tailwind. --- .../grid-lite/components-react/src/App.tsx | 16 +- .../grid-lite/components-react/src/index.css | 3 + packages/grid-lite-react/src/Grid.tsx | 12 +- .../grid-lite-react/src/styles/grid-core.css | 680 ++++++++++++++++++ .../src/styles/grid-theme-default.css | 63 ++ packages/grid-pro-react/src/Grid.tsx | 10 +- .../src/components/BaseGrid.tsx | 3 +- 7 files changed, 771 insertions(+), 16 deletions(-) create mode 100644 packages/grid-lite-react/src/styles/grid-core.css create mode 100644 packages/grid-lite-react/src/styles/grid-theme-default.css diff --git a/examples/grid-lite/components-react/src/App.tsx b/examples/grid-lite/components-react/src/App.tsx index 5f04361..eabd17b 100644 --- a/examples/grid-lite/components-react/src/App.tsx +++ b/examples/grid-lite/components-react/src/App.tsx @@ -75,7 +75,7 @@ function App() { @@ -90,10 +90,10 @@ function App() { style={{ fontWeight: '400' }} sortingEnabled sortingOrderSequence={['asc', 'desc', null]} - filteringEnabled - filteringInline={true} - filteringCondition="contains" - filteringValue="" + // filteringEnabled + // filteringInline={true} + // filteringCondition="contains" + // filteringValue="" // headerClassName="demo-header-cell" headerFormat="{id}" // cellClassName="demo-body-cell" @@ -101,8 +101,8 @@ function App() { cellRowHeader={false} /> Grid Caption v2.1 + className="p-4 bg-blue-500 text-white text-lg font-bold" + >Grid styled by Tailwind CSS
Grid Description ) { - const { gridRef, children, options, theme, ...gridProps } = props; + const { gridRef, children, options, theme, className, ...gridProps } = props; const childOptions = useMemo(() => getChildProps(children), [children]); const columnKey = useMemo(() => { const columns = childOptions.columns as Array<{ id?: string }> | undefined; return columns?.map((column) => column.id).join('\0') ?? ''; }, [childOptions]); + const containerTheme = useMemo( + () => [theme, className].filter(Boolean).join(' ') || void 0, + [theme, className] + ); const gridOptions = useMemo( () => merge( childOptions, options ?? {}, - theme ? { rendering: { theme } } : {} + containerTheme ? { rendering: { theme: containerTheme } } : {} ) as Options, - [childOptions, options, theme] + [childOptions, options, containerTheme] ); return ( diff --git a/packages/grid-lite-react/src/styles/grid-core.css b/packages/grid-lite-react/src/styles/grid-core.css new file mode 100644 index 0000000..ccd0493 --- /dev/null +++ b/packages/grid-lite-react/src/styles/grid-core.css @@ -0,0 +1,680 @@ +@import '@highcharts/grid-lite/css/modules/grid-base-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-popup-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-menu-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-link-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-input-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-button-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-icon-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-pagination-variables.css'; +@import '@highcharts/grid-lite/css/modules/grid-table-variables.css'; +/* Grid container */ +.hcg-container { + container-type: inline-size; + container-name: hcg; + position: relative; + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + box-sizing: border-box; + color-scheme: light dark; + max-height: inherit; +} + +.highcharts-light .hcg-container { + color-scheme: light; +} + +.highcharts-dark .hcg-container { + color-scheme: dark; +} + +.hcg-container * { + box-sizing: border-box; +} + +.hcg-container:has(.hcg-no-data) { + justify-content: center; + align-items: center; +} + +/* ---------------------------------------------------------- + INPUT ELEMENTS +------------------------------------------------------------ */ + +.hcg-container .hcg-input { + width: 100%; + + &:disabled { + opacity: 0.4; + cursor: not-allowed; + } + + &::placeholder { + color: #767676; + } + + &:focus-visible { + outline: none; + border-color: transparent; + } + + &[type="checkbox"] { + --ig-input-checkbox-size: 1.333em; + + appearance: none; + width: var(--ig-input-checkbox-size); + height: var(--ig-input-checkbox-size); + cursor: pointer; + position: relative; + + &:checked::before { + content: ""; + position: absolute; + inset: 0; + margin: 0.05em; + mask: center/contain no-repeat; + mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E"); + } + } + + &.hcg-icon-search { + padding-left: 25px; + appearance: none; + background-repeat: no-repeat; + background-position: left 10px center; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3e%3cpath d='M10.5 10.5L7.50005 7.5M8.5 5C8.5 6.933 6.933 8.5 5 8.5C3.067 8.5 1.5 6.933 1.5 5C1.5 3.067 3.067 1.5 5 1.5C6.933 1.5 8.5 3.067 8.5 5Z' stroke='%23767676' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e"); + } + + select& { + appearance: none; + background-image: url("data:image/svg+xml,%3csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M3.5 7.5L6 10L8.5 7.5M3.5 4.5L6 2L8.5 4.5' stroke='%23767676' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right 5px center; + white-space: nowrap; + text-overflow: ellipsis; + } +} + +/* ---------------------------------------------------------- + BUTTON ELEMENT +------------------------------------------------------------ */ + +.hcg-container :is(.hcg-button, .hcg-icon) { + position: relative; + display: inline-flex; + vertical-align: middle; + align-items: center; + justify-content: center; + flex-direction: row; + line-height: 1; + gap: 2px; + cursor: pointer; + transition: background-color 0.2s ease, box-shadow 0.2s ease, border 0.2s ease; + + svg { + width: 0.9em; + height: 0.9em; + display: block; + } + + span { + display: inline-block; + line-height: 1; + } + + span:empty { + display: none; + } + + &.reverse { + flex-direction: row-reverse; + } + + &:focus-visible { + outline: none; + border-color: transparent; + } + + &:disabled { + opacity: 0.4; + cursor: not-allowed; + } +} + +/* ---------------------------------------------------------- + TABLE ELEMENTS +------------------------------------------------------------ */ + +/* */ +.hcg-container .hcg-table { + width: 100%; + border-collapse: separate; + border-spacing: 0; + overflow: hidden; + table-layout: fixed; + flex: 1; + + &.hcg-scrollable-content { + display: flex; + flex-direction: column; + min-height: 0; + } + + /* */ + &.hcg-virtualization thead { + display: block; + } + + thead th { + position: relative; + } + + /* */ + &.hcg-scrollable-content > tbody { + height: 100%; + overflow: auto; + min-height: 0; + flex: 1; + } + + &.hcg-virtualization > tbody { + display: block; + position: relative; + } + + > tbody > tr { + overflow: hidden; + width: 100%; + } + + > tbody > tr > :where(.hcg-cell) { + position: relative; + line-height: 1em; + overflow: hidden; + } + + > tbody > tr.hcg-mocked-row > :where(.hcg-cell) { + white-space: nowrap; + text-overflow: ellipsis; + } + + .hcg-last-header-cell-in-row, + tbody tr > :where(.hcg-cell):last-child { + border-right: none; + } + + tbody tr:last-of-type > :where(.hcg-cell) { + border-bottom: none; + } + + &.hcg-scrollable-content > tbody > tr { + display: block; + } + + &.hcg-virtualization > tbody > tr { + position: absolute; + } + + > tbody.hcg-rows-content-nowrap > tr > :where(.hcg-cell) { + white-space: nowrap; + text-overflow: ellipsis; + } + + > tbody > tr > :where(.hcg-cell):focus { + outline: none; + } +} + +/* ---------------------------------------------------------- + HEADER ELEMENTS +------------------------------------------------------------ */ +.hcg-container thead th { + .hcg-header-cell-container { + display: flex; + align-items: center; + justify-content: space-between; + } + + .hcg-header-cell-content { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .hcg-header-cell-container.hcg-no-width .hcg-header-cell-content { + visibility: hidden; + transition: none; + } + + .hcg-header-cell-icons { + display: flex; + overflow: hidden; + align-items: center; + max-width: 0; + opacity: 0; + cursor: pointer; + transition: max-width 0.3s ease, opacity 0.3s ease; + } + + .hcg-header-cell-icons .hcg-icon.hcg-icon-selected::after { + content: ""; + position: absolute; + top: 2px; + right: 2px; + width: 0.3em; + height: 0.3em; + border-radius: 50%; + background: currentColor; + } + + :is(:hover, :focus-visible) .hcg-header-cell-icons, + .hcg-header-cell-icons:has(.hcg-button:focus-visible, .hcg-icon:focus-visible, .hcg-button.hcg-button-selected, .hcg-icon.hcg-icon-highlighted, .hcg-icon.hcg-icon-selected), + .hcg-header-cell-container.hcg-no-width .hcg-header-cell-icons { + max-width: 100px; + opacity: 1; + } + + .hcg-header-cell-container.hcg-no-width .hcg-header-cell-menu-icon { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + margin-left: 0; + } + + .hcg-header-cell-icons .hcg-header-cell-menu-icon .hcg-icon { + padding-inline: 3px; + } + + .hcg-header-cell-icons > :first-child { + margin-left: 5px; + } + + .hcg-column-resizer { + position: absolute; + display: flex; + align-items: center; + justify-content: center; + top: 0; + width: 9px; + right: -5px; + height: 100%; + user-select: none; + touch-action: none; + z-index: 10; + cursor: col-resize; + } + + .hcg-column-resizer.hovered::after { + content: ""; + height: 100%; + } +} + +/* ---------------------------------------------------------- + PAGINATION ELEMENTS +------------------------------------------------------------ */ + +.hcg-container .hcg-pagination { + display: flex; + align-items: center; + gap: 0.75rem; + flex-wrap: nowrap; + + > * { + flex: 1 1 0; + min-width: 0; + display: flex; + align-items: center; + } + + .hcg-pagination-info { + justify-content: flex-start; + } + + .hcg-pagination-controls { + justify-content: center; + gap: 2px; + + .hcg-pagination-pages { + display: flex; + flex-wrap: nowrap; + gap: 2px; + + .hcg-button { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 30px; + } + + span { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 20px; + } + } + } + + .hcg-pagination-page-size { + justify-content: flex-end; + text-align: right; + + select.hcg-input { + width: 60px; + margin-left: 8px; + } + } + + /* .hcg-pagination-nav-dropdown { + display: none; + min-width: 200px; + } */ + + &.hcg-pagination-left, + &.hcg-pagination-center, + &.hcg-pagination-right { + > * { + flex: 0 0 auto; + min-width: auto; + } + } + + &.hcg-pagination-left { justify-content: flex-start; } + &.hcg-pagination-center { justify-content: center; } + &.hcg-pagination-right { justify-content: flex-end; } + + &:not(:has(.hcg-pagination-info)) .hcg-pagination-controls { + justify-content: flex-start; + } + + &:not(:has(.hcg-pagination-page-size)) .hcg-pagination-controls { + justify-content: flex-end; + } +} + +@container hcg (max-width: 800px) { + .hcg-container .hcg-pagination { + flex-direction: column; + align-items: stretch; + --ig-pagination-stacked-align: center; + + &.hcg-pagination-left { --ig-pagination-stacked-align: flex-start; } + &.hcg-pagination-right { --ig-pagination-stacked-align: flex-end; } + + > * { + flex: 0 0 auto; + justify-content: var(--ig-pagination-stacked-align); + } + + .hcg-pagination-info, + .hcg-pagination-controls, + .hcg-pagination-page-size { + justify-content: var(--ig-pagination-stacked-align); + } + + .hcg-pagination-page-size { + text-align: center; + } + &.hcg-pagination-left .hcg-pagination-page-size { text-align: left; } + &.hcg-pagination-right .hcg-pagination-page-size { text-align: right; } + + &:not(:has(.hcg-pagination-page-size)) .hcg-pagination-controls, + &:not(:has(.hcg-pagination-info)) .hcg-pagination-controls { + justify-content: var(--ig-pagination-stacked-align); + } + } +} + +/* ---------------------------------------------------------- + CREDITS ELEMENT +------------------------------------------------------------ */ + +.hcg-credits, +.highcharts-light .hcg-credits { + display: block; + width: 114px; + height: 20px; + background-size: contain; + background-repeat: no-repeat; + background-image: + image-set( + /* stylelint-disable-next-line function-comma-newline-after */ + url("https://assets.highcharts.com/grid/logo_light.png") 1x, + url("https://assets.highcharts.com/grid/logo_lightx2.png") 2x + ); +} + +@media (prefers-color-scheme: dark) { + .hcg-credits { + background-image: + image-set( + /* stylelint-disable-next-line function-comma-newline-after */ + url("https://assets.highcharts.com/grid/logo_dark.png") 1x, + url("https://assets.highcharts.com/grid/logo_darkx2.png") 2x + ); + } +} + +.highcharts-dark .hcg-credits { + background-image: + image-set( + /* stylelint-disable-next-line function-comma-newline-after */ + url("https://assets.highcharts.com/grid/logo_dark.png") 1x, + url("https://assets.highcharts.com/grid/logo_darkx2.png") 2x + ); +} + +/* ---------------------------------------------------------- + POPUP ELEMENTS +------------------------------------------------------------ */ +.hcg-container .hcg-popup { + position: absolute; + z-index: 1000; + border-radius: 6px; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08), 0 7px 7px 0 rgba(0, 0, 0, 0.07), 0 17px 10px 0 rgba(0, 0, 0, 0.04), 0 30px 12px 0 rgba(0, 0, 0, 0.01); + min-width: 200px; + overflow: auto; + border-width: 1px; + border-style: solid; + + .hcg-popup-content { + padding: 5px; + } + + .hcg-menu-header { + font-size: 0.75rem; + padding: 3px; + margin-bottom: 5px; + } + + .hcg-menu-header-category { + opacity: 0.5; + user-select: none; + } +} + +/* ---------------------------------------------------------- + MENU ELEMENTS +------------------------------------------------------------ */ + +.hcg-container .hcg-menu-container { + margin: 0; + display: flex; + flex-direction: column; + list-style: none; + row-gap: 5px; + padding: 0; + + .hcg-menu-item { + display: flex; + align-items: center; + gap: 2px; + width: 100%; + min-width: 185px; + min-height: 2rem; + padding: 8px 8px 8px 12px; + font-size: 0.75rem; + font-weight: 600; + background-color: transparent; + border: 1px solid transparent; + border-radius: 5px; + } + + .hcg-menu-item:not(:disabled) { + cursor: pointer; + } + + .hcg-menu-item:focus-visible { + outline: none; + } + + .hcg-menu-item-icon { + --icon-size: 16px; + + flex: 0 0 var(--icon-size); + width: var(--icon-size); + height: var(--icon-size); + display: inline-flex; + align-items: center; + justify-content: center; + opacity: 0.6; + } + + .hcg-menu-item.active .hcg-menu-item-icon, + .hcg-menu-item.highlighted .hcg-menu-item-icon, + .hcg-menu-item:not(:disabled):hover .hcg-menu-item-icon { + opacity: 1; + } + + .hcg-menu-item-label { + flex: 1 1 auto; + min-width: 0; + text-align: left; + padding-left: 0.75rem; + } + + .hcg-menu-divider { + border-top-width: 1px; + border-top-style: solid; + height: 0; + } +} + +/* ---------------------------------------------------------- + FILTERING ELEMENTS +------------------------------------------------------------ */ + +.hcg-header-cell:has(.hcg-column-filter-wrapper) { + overflow: hidden; +} + +.hcg-column-filter-wrapper { + width: 100%; + display: flex; + flex-flow: column; + row-gap: 5px; + min-width: 50px; +} + +.hcg-clear-filter-button { + appearance: none; + background: none; + border: 0; + padding: 0; + margin: 0; + display: inline; + vertical-align: baseline; + font: inherit; + font-size: 0.625rem; + white-space: nowrap; + font-weight: normal; + align-self: end; +} + +.hcg-clear-filter-button:hover { + text-decoration: underline; + cursor: pointer; +} + +.hcg-clear-filter-button:disabled, +.hcg-clear-filter-button:disabled:hover { + opacity: 0.5; + text-decoration: none; + cursor: default; +} + +/* ---------------------------------------------------------- + OTHER ELEMENTS +------------------------------------------------------------ */ + +/* Sorting */ +.hcg-table thead th.hcg-column-sortable { + cursor: pointer; +} + +/* Accessibility */ +.hcg-visually-hidden { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + white-space: nowrap; + clip: rect(1px, 1px, 1px, 1px); + margin-top: -3px; + opacity: 0.01; +} + +/* Loader */ +.hcg-loading-wrapper { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + width: 100%; + height: 100%; + gap: 10px; + color: light-dark(#000000, #ffffff); +} + +.hcg-loading-wrapper .hcg-spinner { + border-top-width: 5px; + border-top-style: solid; + border-top-color: light-dark(#000000, #ffffff); + border-radius: 50%; + width: 30px; + height: 30px; + animation: spin 1s linear infinite; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +/* Start Grid CSS Helpers Classes */ + +.hcg-table thead tr th.hcg-right .hcg-header-cell-content, +.hcg-table tbody tr > :where(.hcg-cell).hcg-right { + text-align: right; +} + +.hcg-table thead tr th.hcg-center .hcg-header-cell-content, +.hcg-table tbody tr > :where(.hcg-cell).hcg-center { + text-align: center; +} + +.hcg-table thead tr th.hcg-left .hcg-header-cell-content, +.hcg-table tbody tr > :where(.hcg-cell).hcg-left { + text-align: left; +} + +/* End Grid CSS Helpers Classes */ diff --git a/packages/grid-lite-react/src/styles/grid-theme-default.css b/packages/grid-lite-react/src/styles/grid-theme-default.css new file mode 100644 index 0000000..7e85955 --- /dev/null +++ b/packages/grid-lite-react/src/styles/grid-theme-default.css @@ -0,0 +1,63 @@ +@import '@highcharts/grid-lite/css/modules/grid-theme-default.css'; + +.hcg-theme-default { + --hcg-description-color: var(--hcg-color); + --hcg-description-background: transparent; + --hcg-description-font-weight: normal; + --hcg-description-font-size: var(--hcg-font-size); + --hcg-description-font-family: inherit; + --hcg-description-line-height: normal; + --hcg-description-letter-spacing: normal; + --hcg-description-text-align: left; + --hcg-description-margin-top: 0; + --hcg-description-margin-right: 0; + --hcg-description-margin-bottom: 0; + --hcg-description-margin-left: 0; + --hcg-description-padding-top: var(--hcg-padding); + --hcg-description-padding-right: var(--hcg-padding); + --hcg-description-padding-bottom: 0; + --hcg-description-padding-left: var(--hcg-padding); +} + +.hcg-theme-default .hcg-caption { + color: var(--hcg-caption-color); + background: var(--hcg-caption-background); + font-weight: var(--hcg-caption-font-weight); + font-size: var(--hcg-caption-font-size); + font-family: var(--hcg-caption-font-family); + line-height: var(--hcg-caption-line-height); + letter-spacing: var(--hcg-caption-letter-spacing); + text-align: var(--hcg-caption-text-align); + margin-top: var(--hcg-caption-margin-top); + margin-right: var(--hcg-caption-margin-right); + margin-bottom: var(--hcg-caption-margin-bottom); + margin-left: var(--hcg-caption-margin-left); + padding-top: var(--hcg-caption-padding-top); + padding-right: var(--hcg-caption-padding-right); + padding-bottom: var(--hcg-caption-padding-bottom); + padding-left: var(--hcg-caption-padding-left); +} + +.hcg-theme-default.hcg-caption * { + font: inherit; + margin: var(--hcg-caption-child-margin); +} + +.hcg-theme-default .hcg-description { + color: var(--hcg-description-color); + background: var(--hcg-description-background); + font-weight: var(--hcg-description-font-weight); + font-size: var(--hcg-description-font-size); + font-family: var(--hcg-description-font-family); + line-height: var(--hcg-description-line-height); + letter-spacing: var(--hcg-description-letter-spacing); + text-align: var(--hcg-description-text-align); + margin-top: var(--hcg-description-margin-top); + margin-right: var(--hcg-description-margin-right); + margin-bottom: var(--hcg-description-margin-bottom); + margin-left: var(--hcg-description-margin-left); + padding-top: var(--hcg-description-padding-top); + padding-right: var(--hcg-description-padding-right); + padding-bottom: var(--hcg-description-padding-bottom); + padding-left: var(--hcg-description-padding-left); +} diff --git a/packages/grid-pro-react/src/Grid.tsx b/packages/grid-pro-react/src/Grid.tsx index 7f5d317..a70800b 100644 --- a/packages/grid-pro-react/src/Grid.tsx +++ b/packages/grid-pro-react/src/Grid.tsx @@ -19,20 +19,24 @@ import '@highcharts/grid-pro/css/grid-pro.css'; import type { Options } from '@highcharts/grid-pro/es-modules/Grid/Core/Options'; export default function GridPro(props: GridProps) { - const { gridRef, children, options, theme, ...gridProps } = props; + const { gridRef, children, options, theme, className, ...gridProps } = props; const childOptions = useMemo(() => getChildProps(children), [children]); const columnKey = useMemo(() => { const columns = childOptions.columns as Array<{ id?: string }> | undefined; return columns?.map((column) => column.id).join('\0') ?? ''; }, [childOptions]); + const containerTheme = useMemo( + () => [theme, className].filter(Boolean).join(' ') || void 0, + [theme, className] + ); const gridOptions = useMemo( () => merge( childOptions, options ?? {}, - theme ? { rendering: { theme } } : {} + containerTheme ? { rendering: { theme: containerTheme } } : {} ) as Options, - [childOptions, options, theme] + [childOptions, options, containerTheme] ); return ( diff --git a/packages/grid-shared-react/src/components/BaseGrid.tsx b/packages/grid-shared-react/src/components/BaseGrid.tsx index 11be983..917eb36 100644 --- a/packages/grid-shared-react/src/components/BaseGrid.tsx +++ b/packages/grid-shared-react/src/components/BaseGrid.tsx @@ -33,7 +33,8 @@ export interface GridProps { */ options?: TOptions; /** - * Optional CSS class name applied to the root grid container. + * Optional CSS class names applied on the Grid container (`hcg-container`), + * merged with `theme` into `rendering.theme`. */ className?: string; /** From 3a87695000e70853eeebccb77e623bd55277f2b5 Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Wed, 15 Jul 2026 15:30:38 +0200 Subject: [PATCH 03/12] Fixed broken linter and tests. --- .husky/pre-commit | 2 ++ packages/grid-lite-react/package.json | 2 +- packages/grid-lite-react/rollup.config.js | 2 +- packages/grid-pro-react/src/utils/mapEventsProps.ts | 2 +- packages/grid-pro-react/tests/mappers/gridOptions.test.tsx | 4 +++- pnpm-lock.yaml | 4 ++-- 6 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index e69de29..acd310a 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +pnpm lint +pnpm test diff --git a/packages/grid-lite-react/package.json b/packages/grid-lite-react/package.json index 36ee2cc..186cb2c 100644 --- a/packages/grid-lite-react/package.json +++ b/packages/grid-lite-react/package.json @@ -30,7 +30,7 @@ "url": "https://github.com/highcharts/grid-react/issues" }, "scripts": { - "build": "pnpm clean:dist && rollup -c", + "build": "pnpm clean:dist && rollup -c && cp -R src/styles dist/styles", "lint": "eslint src --ext .ts,.tsx", "clean:dist": "rimraf dist", "clean": "rimraf node_modules dist", diff --git a/packages/grid-lite-react/rollup.config.js b/packages/grid-lite-react/rollup.config.js index 24ea9c0..ad3b59f 100644 --- a/packages/grid-lite-react/rollup.config.js +++ b/packages/grid-lite-react/rollup.config.js @@ -6,7 +6,7 @@ const isExternal = (id) => [ 'react', 'react-dom', '@highcharts/grid-lite' -].some(pattern => id.startsWith(pattern)); +].some((pattern) => id.startsWith(pattern)) || id.endsWith('.css'); export default [{ input: 'src/index.ts', diff --git a/packages/grid-pro-react/src/utils/mapEventsProps.ts b/packages/grid-pro-react/src/utils/mapEventsProps.ts index 0dcab05..0da23d7 100644 --- a/packages/grid-pro-react/src/utils/mapEventsProps.ts +++ b/packages/grid-pro-react/src/utils/mapEventsProps.ts @@ -63,7 +63,7 @@ export function mapEventsProps( source?: Record ): void { const props = source ?? target; - const removeFlatProps = source === undefined; + const removeFlatProps = source === void 0; for (const [propName, path] of Object.entries(aliases)) { const handler = props[propName]; diff --git a/packages/grid-pro-react/tests/mappers/gridOptions.test.tsx b/packages/grid-pro-react/tests/mappers/gridOptions.test.tsx index b3dcde3..60a8f82 100644 --- a/packages/grid-pro-react/tests/mappers/gridOptions.test.tsx +++ b/packages/grid-pro-react/tests/mappers/gridOptions.test.tsx @@ -68,7 +68,7 @@ describe('buildGridOptions', () => { const options = buildGridOptions( 'GRID-KEY', getChildProps(), - undefined, + void 0, { gridKey: 'GRID-KEY' } as GridProProps ); @@ -88,6 +88,8 @@ describe('getGridEventPropDeps', () => { expect(GRID_EVENT_PROP_KEYS).toContain('onAfterLoad'); expect(getGridEventPropDeps(props)).toEqual([ 'KEY', + void 0, + void 0, ...GRID_EVENT_PROP_KEYS.map( (key: keyof GridProProps) => props[key] ) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1770d3..f3bbcb8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -173,13 +173,13 @@ importers: version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^4.2.0 - version: 4.7.0(vite@5.4.21(@types/node@20.19.26)) + version: 4.7.0(vite@5.4.21(@types/node@20.19.26)(lightningcss@1.32.0)) typescript: specifier: ^5.0.0 version: 5.9.3 vite: specifier: ^5.0.0 - version: 5.4.21(@types/node@20.19.26) + version: 5.4.21(@types/node@20.19.26)(lightningcss@1.32.0) examples/grid-pro/minimal-nextjs: dependencies: From dcffc46580209f17be254097e4020a44a2a8922c Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Thu, 16 Jul 2026 10:49:58 +0200 Subject: [PATCH 04/12] Fixed condlicts. --- examples/grid-lite/components-react/src/App.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/examples/grid-lite/components-react/src/App.tsx b/examples/grid-lite/components-react/src/App.tsx index c4feae6..3d21c75 100644 --- a/examples/grid-lite/components-react/src/App.tsx +++ b/examples/grid-lite/components-react/src/App.tsx @@ -74,11 +74,13 @@ function App() { // }; return ( - <> +
-
+
- Grid Description + Grid Description -
+
{/* */}
- +
); } From e4628a15b72494e51895623c50533f5b722be2ae Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Wed, 29 Jul 2026 09:51:41 +0200 Subject: [PATCH 05/12] Added tailwind classes to grid-lite demo. --- .../grid-lite/components-react/src/App.tsx | 257 ++++++++++-------- .../grid-lite/components-react/src/index.css | 91 ++++++- 2 files changed, 231 insertions(+), 117 deletions(-) diff --git a/examples/grid-lite/components-react/src/App.tsx b/examples/grid-lite/components-react/src/App.tsx index 3d21c75..7ec87da 100644 --- a/examples/grid-lite/components-react/src/App.tsx +++ b/examples/grid-lite/components-react/src/App.tsx @@ -34,11 +34,29 @@ function App() { // ==== DATA ==== // Data Columns - const [dataSource, setDataSource] = useState({ - name: ['COLUMNS', 'Bob', 'Charlie', 'David', 'Eve'], - age: [23, 34, 45, 56, 67], - city: ['New York', 'Oslo', 'Paris', 'Tokyo', 'London'], - salary: [50000, 60000, 70000, 80000, 90000] + const [dataSource] = useState({ + name: [ + 'Alice Nguyen', 'Bob Berg', 'Charlie Dupont', 'David Sato', 'Eve Shaw', + 'John Hale', 'Jane Ortiz', 'Jim Novak', 'Jill Meyer', 'Jack Quinn', + 'Nora Ellis', 'Omar Khan', 'Priya Shah', 'Quinn Blake', 'Ruth Adler', + 'Sam Okonkwo', 'Tina Rossi', 'Uma Patel', 'Victor Lang', 'Wendy Cho' + ], + age: [ + 23, 34, 45, 56, 67, 30, 25, 35, 40, 45, + 28, 31, 39, 42, 51, 27, 33, 36, 44, 48 + ], + city: [ + 'New York', 'Oslo', 'Paris', 'Tokyo', 'London', + 'New York', 'Oslo', 'Paris', 'Tokyo', 'London', + 'Berlin', 'Toronto', 'Mumbai', 'Sydney', 'Zurich', + 'Lagos', 'Rome', 'Lisbon', 'Seoul', 'Chicago' + ], + salary: [ + 50000, 60000, 70000, 80000, 90000, + 40000, 35000, 45000, 50000, 55000, + 62000, 71000, 48000, 53000, 88000, + 41000, 59000, 64000, 76000, 82000 + ] }); // Data Table @@ -52,15 +70,15 @@ function App() { // }); // ==== ACTIONS ==== - const onButtonClick = () => { - // console.info('(ref) grid:', grid.current?.grid); - setDataSource({ - name: ['John', 'Jane', 'Jim', 'Jill', 'Jack'], - age: [30, 25, 35, 40, 45], - city: ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Miami'], - salary: [40000, 35000, 45000, 50000, 55000] - }); - }; + // const onButtonClick = () => { + // // console.info('(ref) grid:', grid.current?.grid); + // setDataSource({ + // name: ['John', 'Jane', 'Jim', 'Jill', 'Jack'], + // age: [30, 25, 35, 40, 45], + // city: ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Miami'], + // salary: [40000, 35000, 45000, 50000, 55000] + // }); + // }; const onGridCallback = (grid: GridInstance) => { console.info('(callback) grid:', grid); @@ -74,104 +92,119 @@ function App() { // }; return ( -
- - - -
-
- - - - - - Grid Description - - -
- - {/* */} +
+
+ + + +
+
+ + + + + + + Filter, sort, and page through sample employee rows styled with + utility classes. + + + + {/*
+ + +
*/} ); diff --git a/examples/grid-lite/components-react/src/index.css b/examples/grid-lite/components-react/src/index.css index c050702..bcb41c2 100644 --- a/examples/grid-lite/components-react/src/index.css +++ b/examples/grid-lite/components-react/src/index.css @@ -1,8 +1,19 @@ @import "tailwindcss"; -/* Optional: load default Grid theme tokens + themed caption styles */ -/* @import "@highcharts/grid-lite-react/src/styles/grid-theme-default.css"; */ +/* Sample viewer theme toggle + system preference */ +@custom-variant dark { + &:where(.highcharts-dark, .highcharts-dark *) { + @slot; + } + @media (prefers-color-scheme: dark) { + &:where(:not(.highcharts-light):not(.highcharts-light *)) { + @slot; + } + } +} + +/* Load grid-theme-default.css only when using Core theme tokens (non-empty `theme`). */ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', @@ -11,7 +22,77 @@ body { -moz-osx-font-smoothing: grayscale; } -#root { +.hcg-container { width: 100%; - min-height: 100vh; -} \ No newline at end of file + height: 600px; +} + +/* + * Pagination buttons / select — Core internals, styled via cascade. + */ +.hcg-pagination-controls { + @apply border-l border-r border-slate-200 dark:border-slate-700; +} + +.hcg-pagination-controls .hcg-pagination-pages { + @apply gap-2; +} + +.hcg-pagination-controls .hcg-button { + @apply size-7 rounded border border-transparent text-sm leading-none + text-slate-700 dark:text-slate-200; +} + +.hcg-pagination-controls .hcg-button:hover:not(:disabled) { + @apply bg-slate-200 dark:bg-slate-700; +} + +.hcg-pagination-controls .hcg-button-selected, +.hcg-pagination-controls .hcg-button-selected:hover:not(:disabled) { + @apply bg-teal-700 text-white dark:bg-teal-600; +} + +.demo-pag-size select.hcg-input { + @apply rounded border border-slate-300 bg-white py-1 pl-2 pr-5 text-sm + text-slate-700 dark:border-slate-600 dark:bg-slate-900 dark:text-slate-200; +} + +/* + * Filter popup — Core internals, styled via cascade. + */ +.demo-grid .hcg-container .hcg-popup { + @apply rounded-lg border border-slate-200 bg-white text-sm text-slate-700 + shadow-lg dark:border-slate-700 dark:bg-slate-900 dark:text-slate-200 + dark:shadow-black/40; +} + +.demo-grid .hcg-container .hcg-menu-header { + @apply mb-2 px-1 text-xs font-semibold text-slate-500 dark:text-slate-400; +} + +.demo-grid .hcg-container .hcg-column-filter-wrapper { + @apply gap-2; +} + +.demo-grid .hcg-container .hcg-column-filter-wrapper .hcg-input { + @apply w-full rounded border border-slate-300 bg-white px-2 py-1.5 text-sm + text-slate-700 dark:border-slate-600 dark:bg-slate-900 dark:text-slate-200; +} + +.demo-grid .hcg-container .hcg-column-filter-wrapper select.hcg-input { + @apply pr-5; +} + +.demo-grid .hcg-container .hcg-clear-filter-button { + @apply text-xs font-medium text-slate-600 no-underline dark:text-slate-300; +} + +.demo-grid .hcg-container .hcg-clear-filter-button:hover:not(:disabled) { + @apply text-slate-900 underline dark:text-slate-50; +} + +@container hcg (max-width: 800px) { + .hcg-pagination-controls { + @apply justify-center border-r-0 border-l-0 mt-2 mb-2; + } +} From 60aeadae54af8e930aea9793dee2bfb47ff79146 Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Mon, 10 Aug 2026 10:50:45 +0200 Subject: [PATCH 06/12] Update grid-lite and grid-pro packages to 3.1.0. Pin examples and wrappers to the released CSS fixes, and use exact Vite aliases for workspace packages. Co-authored-by: Cursor --- .../grid-lite/components-react/package.json | 2 +- .../grid-lite/components-react/vite.config.ts | 6 +- .../grid-lite/minimal-nextjs/package.json | 3 +- examples/grid-lite/minimal-react/package.json | 3 +- .../grid-pro/components-react/package.json | 2 +- .../grid-pro/components-react/vite.config.ts | 5 +- examples/grid-pro/minimal-nextjs/package.json | 3 +- examples/grid-pro/minimal-react/package.json | 3 +- packages/grid-lite-react/package.json | 2 +- packages/grid-pro-react/package.json | 2 +- pnpm-lock.yaml | 315 +++++++++++------- 11 files changed, 200 insertions(+), 146 deletions(-) diff --git a/examples/grid-lite/components-react/package.json b/examples/grid-lite/components-react/package.json index b98f691..794c1e7 100644 --- a/examples/grid-lite/components-react/package.json +++ b/examples/grid-lite/components-react/package.json @@ -10,7 +10,7 @@ "clean": "rimraf dist node_modules" }, "dependencies": { - "@highcharts/grid-lite": ">=3.0.0", + "@highcharts/grid-lite": "3.1.0", "@highcharts/grid-lite-react": "workspace:*", "react": ">=18", "react-dom": ">=18" diff --git a/examples/grid-lite/components-react/vite.config.ts b/examples/grid-lite/components-react/vite.config.ts index 0ec7891..40dd699 100644 --- a/examples/grid-lite/components-react/vite.config.ts +++ b/examples/grid-lite/components-react/vite.config.ts @@ -11,11 +11,12 @@ export default defineConfig({ resolve: { alias: [ { - find: '@highcharts/grid-lite-react', + // Exact match — string aliases are prefix-based and break subpath ids. + find: /^@highcharts\/grid-lite-react$/, replacement: resolve(__dirname, '../../../packages/grid-lite-react/src/index.ts') }, { - find: '@highcharts/grid-shared-react', + find: /^@highcharts\/grid-shared-react$/, replacement: resolve(__dirname, '../../../packages/grid-shared-react/src/index.ts') }, { @@ -29,4 +30,3 @@ export default defineConfig({ port: 3000 } }); - diff --git a/examples/grid-lite/minimal-nextjs/package.json b/examples/grid-lite/minimal-nextjs/package.json index 0437b25..17c1988 100644 --- a/examples/grid-lite/minimal-nextjs/package.json +++ b/examples/grid-lite/minimal-nextjs/package.json @@ -10,7 +10,7 @@ "clean": "rimraf .next node_modules" }, "dependencies": { - "@highcharts/grid-lite": ">=3.0.0", + "@highcharts/grid-lite": "3.1.0", "@highcharts/grid-lite-react": "workspace:*", "next": "^14.0.0", "react": ">=18", @@ -23,4 +23,3 @@ "typescript": "^5.0.0" } } - diff --git a/examples/grid-lite/minimal-react/package.json b/examples/grid-lite/minimal-react/package.json index cd5b45a..2a56a5c 100644 --- a/examples/grid-lite/minimal-react/package.json +++ b/examples/grid-lite/minimal-react/package.json @@ -10,7 +10,7 @@ "clean": "rimraf dist node_modules" }, "dependencies": { - "@highcharts/grid-lite": ">=3.0.0", + "@highcharts/grid-lite": "3.1.0", "@highcharts/grid-lite-react": "workspace:*", "react": ">=18", "react-dom": ">=18" @@ -23,4 +23,3 @@ "vite": "^5.0.0" } } - diff --git a/examples/grid-pro/components-react/package.json b/examples/grid-pro/components-react/package.json index e70810f..4166d1a 100644 --- a/examples/grid-pro/components-react/package.json +++ b/examples/grid-pro/components-react/package.json @@ -10,7 +10,7 @@ "clean": "rimraf dist node_modules" }, "dependencies": { - "@highcharts/grid-pro": ">=3.0.0", + "@highcharts/grid-pro": "3.1.0", "@highcharts/grid-pro-react": "workspace:*", "react": ">=18", "react-dom": ">=18" diff --git a/examples/grid-pro/components-react/vite.config.ts b/examples/grid-pro/components-react/vite.config.ts index 524f9cd..a28be86 100644 --- a/examples/grid-pro/components-react/vite.config.ts +++ b/examples/grid-pro/components-react/vite.config.ts @@ -10,11 +10,12 @@ export default defineConfig({ resolve: { alias: [ { - find: '@highcharts/grid-pro-react', + // Exact match — string aliases are prefix-based and break subpath ids. + find: /^@highcharts\/grid-pro-react$/, replacement: resolve(__dirname, '../../../packages/grid-pro-react/src/index.ts') }, { - find: '@highcharts/grid-shared-react', + find: /^@highcharts\/grid-shared-react$/, replacement: resolve(__dirname, '../../../packages/grid-shared-react/src/index.ts') }, { diff --git a/examples/grid-pro/minimal-nextjs/package.json b/examples/grid-pro/minimal-nextjs/package.json index 9a126ce..da4ca30 100644 --- a/examples/grid-pro/minimal-nextjs/package.json +++ b/examples/grid-pro/minimal-nextjs/package.json @@ -10,7 +10,7 @@ "clean": "rimraf .next node_modules" }, "dependencies": { - "@highcharts/grid-pro": ">=3.0.0", + "@highcharts/grid-pro": "3.1.0", "@highcharts/grid-pro-react": "workspace:*", "next": "^14.0.0", "react": ">=18", @@ -23,4 +23,3 @@ "typescript": "^5.0.0" } } - diff --git a/examples/grid-pro/minimal-react/package.json b/examples/grid-pro/minimal-react/package.json index 915fd3f..edc3b3b 100644 --- a/examples/grid-pro/minimal-react/package.json +++ b/examples/grid-pro/minimal-react/package.json @@ -10,7 +10,7 @@ "clean": "rimraf dist node_modules" }, "dependencies": { - "@highcharts/grid-pro": ">=3.0.0", + "@highcharts/grid-pro": "3.1.0", "@highcharts/grid-pro-react": "workspace:*", "react": ">=18", "react-dom": ">=18" @@ -23,4 +23,3 @@ "vite": "^5.0.0" } } - diff --git a/packages/grid-lite-react/package.json b/packages/grid-lite-react/package.json index 186cb2c..a619e75 100644 --- a/packages/grid-lite-react/package.json +++ b/packages/grid-lite-react/package.json @@ -37,7 +37,7 @@ "prepublishOnly": "pnpm build" }, "dependencies": { - "@highcharts/grid-lite": ">=3.0.0" + "@highcharts/grid-lite": "3.1.0" }, "devDependencies": { "@highcharts/grid-shared-react": "workspace:*", diff --git a/packages/grid-pro-react/package.json b/packages/grid-pro-react/package.json index 7012236..ef043ee 100644 --- a/packages/grid-pro-react/package.json +++ b/packages/grid-pro-react/package.json @@ -38,7 +38,7 @@ "prepublishOnly": "pnpm build" }, "dependencies": { - "@highcharts/grid-pro": ">=3.0.0" + "@highcharts/grid-pro": "3.1.0" }, "devDependencies": { "@highcharts/grid-shared-react": "workspace:*", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3bbcb8..7b1f7b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,8 +54,8 @@ importers: examples/grid-lite/components-react: dependencies: '@highcharts/grid-lite': - specifier: '>=3.0.0' - version: 3.0.0 + specifier: 3.1.0 + version: 3.1.0 '@highcharts/grid-lite-react': specifier: workspace:* version: link:../../../packages/grid-lite-react @@ -91,8 +91,8 @@ importers: examples/grid-lite/minimal-nextjs: dependencies: '@highcharts/grid-lite': - specifier: '>=3.0.0' - version: 3.0.0 + specifier: 3.1.0 + version: 3.1.0 '@highcharts/grid-lite-react': specifier: workspace:* version: link:../../../packages/grid-lite-react @@ -122,8 +122,8 @@ importers: examples/grid-lite/minimal-react: dependencies: '@highcharts/grid-lite': - specifier: '>=3.0.0' - version: 3.0.0 + specifier: 3.1.0 + version: 3.1.0 '@highcharts/grid-lite-react': specifier: workspace:* version: link:../../../packages/grid-lite-react @@ -153,8 +153,8 @@ importers: examples/grid-pro/components-react: dependencies: '@highcharts/grid-pro': - specifier: '>=3.0.0' - version: 3.0.0 + specifier: 3.1.0 + version: 3.1.0 '@highcharts/grid-pro-react': specifier: workspace:* version: link:../../../packages/grid-pro-react @@ -184,8 +184,8 @@ importers: examples/grid-pro/minimal-nextjs: dependencies: '@highcharts/grid-pro': - specifier: '>=3.0.0' - version: 3.0.0 + specifier: 3.1.0 + version: 3.1.0 '@highcharts/grid-pro-react': specifier: workspace:* version: link:../../../packages/grid-pro-react @@ -215,8 +215,8 @@ importers: examples/grid-pro/minimal-react: dependencies: '@highcharts/grid-pro': - specifier: '>=3.0.0' - version: 3.0.0 + specifier: 3.1.0 + version: 3.1.0 '@highcharts/grid-pro-react': specifier: workspace:* version: link:../../../packages/grid-pro-react @@ -246,8 +246,8 @@ importers: packages/grid-lite-react: dependencies: '@highcharts/grid-lite': - specifier: '>=3.0.0' - version: 3.0.0 + specifier: 3.1.0 + version: 3.1.0 devDependencies: '@highcharts/grid-shared-react': specifier: workspace:* @@ -283,8 +283,8 @@ importers: packages/grid-pro-react: dependencies: '@highcharts/grid-pro': - specifier: '>=3.0.0' - version: 3.0.0 + specifier: 3.1.0 + version: 3.1.0 devDependencies: '@highcharts/grid-shared-react': specifier: workspace:* @@ -349,14 +349,14 @@ importers: packages: - '@acemir/cssom@0.9.30': - resolution: {integrity: sha512-9CnlMCI0LmCIq0olalQqdWrJHPzm0/tw3gzOA9zJSgvFX7Xau3D24mAGa4BtwxwY69nsuJW6kQqqCzf/mEcQgg==} + '@acemir/cssom@0.9.31': + resolution: {integrity: sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==} - '@asamuzakjp/css-color@4.1.1': - resolution: {integrity: sha512-B0Hv6G3gWGMn0xKJ0txEi/jM5iFpT3MfDxmhZFb4W047GvytCf1DHQ1D69W3zHI4yWe2aTZAA0JnbMZ7Xc8DuQ==} + '@asamuzakjp/css-color@4.1.2': + resolution: {integrity: sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==} - '@asamuzakjp/dom-selector@6.7.6': - resolution: {integrity: sha512-hBaJER6A9MpdG3WgdlOolHmbOYvSk46y7IQN/1+iqiCuUu6iWdQrs9DGKF8ocqsEqWujWf/V7b7vaDgiUmIvUg==} + '@asamuzakjp/dom-selector@6.8.1': + resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==} '@asamuzakjp/nwsapi@2.3.9': resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} @@ -365,6 +365,10 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.28.5': resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} engines: {node: '>=6.9.0'} @@ -407,6 +411,10 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} @@ -436,6 +444,10 @@ packages: resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -448,37 +460,41 @@ packages: resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - '@csstools/color-helpers@5.1.0': - resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} - engines: {node: '>=18'} + '@csstools/color-helpers@6.1.0': + resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} + engines: {node: '>=20.19.0'} - '@csstools/css-calc@2.1.4': - resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} - engines: {node: '>=18'} + '@csstools/css-calc@3.3.0': + resolution: {integrity: sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==} + engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-color-parser@3.1.0': - resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} - engines: {node: '>=18'} + '@csstools/css-color-parser@4.1.10': + resolution: {integrity: sha512-UZhQLIUyJaaMepqehrCODwCg2KW25vFvLWBmqYFaPclYvvxzj/sG8LBOhBFCp11i9uE7t1EyS+RAoV9tztPFyw==} + engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-parser-algorithms@3.0.5': - resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} - engines: {node: '>=18'} + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} peerDependencies: - '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-tokenizer': ^4.0.0 - '@csstools/css-syntax-patches-for-csstree@1.0.22': - resolution: {integrity: sha512-qBcx6zYlhleiFfdtzkRgwNC7VVoAwfK76Vmsw5t+PbvtdknO9StgRk7ROvq9so1iqbdW4uLIDAsXRsTfUrIoOw==} - engines: {node: '>=18'} + '@csstools/css-syntax-patches-for-csstree@1.1.7': + resolution: {integrity: sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true - '@csstools/css-tokenizer@3.0.4': - resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} - engines: {node: '>=18'} + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} @@ -812,20 +828,20 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@exodus/bytes@1.8.0': - resolution: {integrity: sha512-8JPn18Bcp8Uo1T82gR8lh2guEOa5KKU/IEKvvdp0sgmi7coPBWf1Doi1EXsGZb2ehc8ym/StJCjffYV+ne7sXQ==} + '@exodus/bytes@1.15.1': + resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@exodus/crypto': ^1.0.0-rc.4 + '@noble/hashes': ^1.8.0 || ^2.0.0 peerDependenciesMeta: - '@exodus/crypto': + '@noble/hashes': optional: true - '@highcharts/grid-lite@3.0.0': - resolution: {integrity: sha512-e42KWpkMCQUmjzZPmpRW9GyM60+MvsSVi/4PejchFJEDpwaPJ/06baAq5hZO9VF09+qG1RDpaCwRof2A9rfhfg==} + '@highcharts/grid-lite@3.1.0': + resolution: {integrity: sha512-WEYEjhlSK1kSuakRjqjiAclCydxxc1lrJsrkdt9xLojf3UKiSq3m35qTLLwrJDFlzr24I614qTS8q21eTnQj8Q==} - '@highcharts/grid-pro@3.0.0': - resolution: {integrity: sha512-zGE7EzfRxUx8w+oyKgUo6b8GrWme1i8AfKpuTjIrrxso2xLqYEpFozeJ9j5U1bwizKb39PMc7VyiK5407BZasQ==} + '@highcharts/grid-pro@3.1.0': + resolution: {integrity: sha512-QzAPfZUIjbrBBDPg17jmVauaLO5d4ogGW8LIfffKMX1Jtk1waKjBzHg0PdsvX/NZ/vNkt7L2RrMtl+kBaDopxg==} '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} @@ -1452,19 +1468,19 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - css-tree@3.1.0: - resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - cssstyle@5.3.6: - resolution: {integrity: sha512-legscpSpgSAeGEe0TNcai97DKt9Vd9AsAdOL7Uoetb52Ar/8eJm3LIa39qpv8wWzLFlNG4vVvppQM+teaMPj3A==} + cssstyle@5.3.7: + resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} engines: {node: '>=20'} csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - data-urls@6.0.0: - resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==} + data-urls@6.0.1: + resolution: {integrity: sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==} engines: {node: '>=20'} debug@4.4.3: @@ -1504,9 +1520,9 @@ packages: resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} engines: {node: '>=10.13.0'} - entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -1842,6 +1858,10 @@ packages: resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -1852,8 +1872,8 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - mdn-data@2.12.2: - resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} minimatch@10.1.1: resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} @@ -1929,8 +1949,8 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parse5@8.0.0: - resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} @@ -2136,19 +2156,19 @@ packages: resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} engines: {node: '>=14.0.0'} - tldts-core@7.0.19: - resolution: {integrity: sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==} + tldts-core@7.4.10: + resolution: {integrity: sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==} - tldts@7.0.19: - resolution: {integrity: sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==} + tldts@7.4.10: + resolution: {integrity: sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==} hasBin: true totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} - tough-cookie@6.0.0: - resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} + tough-cookie@6.0.2: + resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} engines: {node: '>=16'} tr46@6.0.0: @@ -2309,6 +2329,10 @@ packages: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + whatwg-url@15.1.0: resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} engines: {node: '>=20'} @@ -2339,6 +2363,18 @@ packages: utf-8-validate: optional: true + ws@8.21.3: + resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} @@ -2355,25 +2391,25 @@ packages: snapshots: - '@acemir/cssom@0.9.30': + '@acemir/cssom@0.9.31': optional: true - '@asamuzakjp/css-color@4.1.1': + '@asamuzakjp/css-color@4.1.2': dependencies: - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - lru-cache: 11.2.4 + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + lru-cache: 11.5.2 optional: true - '@asamuzakjp/dom-selector@6.7.6': + '@asamuzakjp/dom-selector@6.8.1': dependencies: '@asamuzakjp/nwsapi': 2.3.9 bidi-js: 1.0.3 - css-tree: 3.1.0 + css-tree: 3.2.1 is-potential-custom-element-name: 1.0.1 - lru-cache: 11.2.4 + lru-cache: 11.5.2 optional: true '@asamuzakjp/nwsapi@2.3.9': @@ -2385,6 +2421,12 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.28.5': {} '@babel/core@7.28.5': @@ -2447,6 +2489,8 @@ snapshots: '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.29.7': {} + '@babel/helper-validator-option@7.27.1': {} '@babel/helpers@7.28.4': @@ -2470,6 +2514,8 @@ snapshots: '@babel/runtime@7.28.4': {} + '@babel/runtime@7.29.7': {} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 @@ -2493,32 +2539,34 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@csstools/color-helpers@5.1.0': + '@csstools/color-helpers@6.1.0': optional: true - '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + '@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 optional: true - '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + '@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@csstools/color-helpers': 5.1.0 - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 + '@csstools/color-helpers': 6.1.0 + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 optional: true - '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': dependencies: - '@csstools/css-tokenizer': 3.0.4 + '@csstools/css-tokenizer': 4.0.0 optional: true - '@csstools/css-syntax-patches-for-csstree@1.0.22': + '@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 optional: true - '@csstools/css-tokenizer@3.0.4': + '@csstools/css-tokenizer@4.0.0': optional: true '@esbuild/aix-ppc64@0.21.5': @@ -2714,12 +2762,12 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 - '@exodus/bytes@1.8.0': + '@exodus/bytes@1.15.1': optional: true - '@highcharts/grid-lite@3.0.0': {} + '@highcharts/grid-lite@3.1.0': {} - '@highcharts/grid-pro@3.0.0': {} + '@highcharts/grid-pro@3.1.0': {} '@humanfs/core@0.19.1': {} @@ -2984,8 +3032,8 @@ snapshots: '@testing-library/dom@10.4.1': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/runtime': 7.28.4 + '@babel/code-frame': 7.29.7 + '@babel/runtime': 7.29.7 '@types/aria-query': 5.0.4 aria-query: 5.3.0 dom-accessibility-api: 0.5.16 @@ -3316,25 +3364,25 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-tree@3.1.0: + css-tree@3.2.1: dependencies: - mdn-data: 2.12.2 + mdn-data: 2.27.1 source-map-js: 1.2.1 optional: true - cssstyle@5.3.6: + cssstyle@5.3.7: dependencies: - '@asamuzakjp/css-color': 4.1.1 - '@csstools/css-syntax-patches-for-csstree': 1.0.22 - css-tree: 3.1.0 - lru-cache: 11.2.4 + '@asamuzakjp/css-color': 4.1.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.7(css-tree@3.2.1) + css-tree: 3.2.1 + lru-cache: 11.5.2 optional: true csstype@3.2.3: {} - data-urls@6.0.0: + data-urls@6.0.1: dependencies: - whatwg-mimetype: 4.0.0 + whatwg-mimetype: 5.0.0 whatwg-url: 15.1.0 optional: true @@ -3362,7 +3410,7 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.3 - entities@6.0.1: + entities@8.0.0: optional: true es-module-lexer@1.7.0: {} @@ -3562,9 +3610,9 @@ snapshots: html-encoding-sniffer@6.0.0: dependencies: - '@exodus/bytes': 1.8.0 + '@exodus/bytes': 1.15.1 transitivePeerDependencies: - - '@exodus/crypto' + - '@noble/hashes' optional: true http-proxy-agent@7.0.2: @@ -3627,28 +3675,28 @@ snapshots: jsdom@27.4.0: dependencies: - '@acemir/cssom': 0.9.30 - '@asamuzakjp/dom-selector': 6.7.6 - '@exodus/bytes': 1.8.0 - cssstyle: 5.3.6 - data-urls: 6.0.0 + '@acemir/cssom': 0.9.31 + '@asamuzakjp/dom-selector': 6.8.1 + '@exodus/bytes': 1.15.1 + cssstyle: 5.3.7 + data-urls: 6.0.1 decimal.js: 10.6.0 html-encoding-sniffer: 6.0.0 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 - parse5: 8.0.0 + parse5: 8.0.1 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 6.0.0 + tough-cookie: 6.0.2 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 4.0.0 whatwg-url: 15.1.0 - ws: 8.18.3 + ws: 8.21.3 xml-name-validator: 5.0.0 transitivePeerDependencies: - - '@exodus/crypto' + - '@noble/hashes' - bufferutil - supports-color - utf-8-validate @@ -3730,6 +3778,9 @@ snapshots: lru-cache@11.2.4: {} + lru-cache@11.5.2: + optional: true + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -3740,7 +3791,7 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - mdn-data@2.12.2: + mdn-data@2.27.1: optional: true minimatch@10.1.1: @@ -3817,9 +3868,9 @@ snapshots: dependencies: callsites: 3.1.0 - parse5@8.0.0: + parse5@8.0.1: dependencies: - entities: 6.0.1 + entities: 8.0.0 optional: true path-exists@4.0.0: {} @@ -4002,19 +4053,19 @@ snapshots: tinyrainbow@3.0.3: {} - tldts-core@7.0.19: + tldts-core@7.4.10: optional: true - tldts@7.0.19: + tldts@7.4.10: dependencies: - tldts-core: 7.0.19 + tldts-core: 7.4.10 optional: true totalist@3.0.1: {} - tough-cookie@6.0.0: + tough-cookie@6.0.2: dependencies: - tldts: 7.0.19 + tldts: 7.4.10 optional: true tr46@6.0.0: @@ -4131,6 +4182,9 @@ snapshots: whatwg-mimetype@4.0.0: optional: true + whatwg-mimetype@5.0.0: + optional: true + whatwg-url@15.1.0: dependencies: tr46: 6.0.0 @@ -4150,6 +4204,9 @@ snapshots: ws@8.18.3: {} + ws@8.21.3: + optional: true + xml-name-validator@5.0.0: optional: true From 35a7a1429d8040786e785fa19f40cf244b085426 Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Mon, 10 Aug 2026 10:58:40 +0200 Subject: [PATCH 07/12] Updated mappers and builders. --- .../src/utils/buildGridOptions.ts | 23 +++- .../src/utils/buildGridOptions.ts | 22 +++- .../src/utils/mappers/grid/gridOptions.ts | 1 + .../mappers/pagination/paginationOptions.ts | 60 +++++++++- .../src/utils/mergeClassNames.ts | 32 ++++++ .../src/utils/normalizeChildOptions.ts | 106 +++++++++++++++++- 6 files changed, 224 insertions(+), 20 deletions(-) create mode 100644 packages/grid-shared-react/src/utils/mergeClassNames.ts diff --git a/packages/grid-lite-react/src/utils/buildGridOptions.ts b/packages/grid-lite-react/src/utils/buildGridOptions.ts index 262df76..5bfd183 100644 --- a/packages/grid-lite-react/src/utils/buildGridOptions.ts +++ b/packages/grid-lite-react/src/utils/buildGridOptions.ts @@ -13,20 +13,33 @@ import type { Options } from '@highcharts/grid-lite/es-modules/Grid/Core/Options /** * Builds final Grid Lite options from raw declarative child options. + * + * `theme` → `rendering.theme` + * `tableClassName` → `rendering.table.className` (`.hcg-table`) + * + * `className` is React-only on the mount container + * (parent of `.hcg-container`). */ export function buildGridOptions( childOptions: Record, options?: Options, theme?: string, - className?: string + tableClassName?: string ): Options { - const containerTheme = [theme, className] - .filter(Boolean) - .join(' ') || void 0; + const rendering: Record = {}; + + if (theme !== void 0) { + rendering.theme = theme; + } + if (tableClassName !== void 0) { + rendering.table = { className: tableClassName }; + } return merge( normalizeChildOptions(childOptions), options ?? {}, - containerTheme ? { rendering: { theme: containerTheme } } : {} + // Skip empty `{ rendering: {} }` so merge does not inject a blank + // rendering block when theme / tableClassName were omitted. + Object.keys(rendering).length ? { rendering } : {} ) as Options; } diff --git a/packages/grid-pro-react/src/utils/buildGridOptions.ts b/packages/grid-pro-react/src/utils/buildGridOptions.ts index 9276355..107b096 100644 --- a/packages/grid-pro-react/src/utils/buildGridOptions.ts +++ b/packages/grid-pro-react/src/utils/buildGridOptions.ts @@ -19,6 +19,12 @@ import { /** * Builds final Grid Pro options from raw declarative child options. + * + * `theme` → `rendering.theme` + * `tableClassName` → `rendering.table.className` (`.hcg-table`) + * + * `className` is React-only on the mount container + * (parent of `.hcg-container`). */ export function buildGridOptions( gridKey: string, @@ -29,14 +35,22 @@ export function buildGridOptions( const declarativeOptions = mergePaginationEventProps( mergeColumnEventProps(normalizeChildOptions(childOptions)) ); - const containerTheme = [props.theme, props.className] - .filter(Boolean) - .join(' ') || void 0; + const rendering: Record = {}; + + if (props.theme !== void 0) { + rendering.theme = props.theme; + } + if (props.tableClassName !== void 0) { + rendering.table = { className: props.tableClassName }; + } + const result = merge( true, {}, merge(declarativeOptions, options ?? {}), - containerTheme ? { rendering: { theme: containerTheme } } : {}, + // Skip empty `{ rendering: {} }` so merge does not inject a blank + // rendering block when theme / tableClassName were omitted. + Object.keys(rendering).length ? { rendering } : {}, normalizeGridEventProps(props) ) as GridProOptions; diff --git a/packages/grid-pro-react/src/utils/mappers/grid/gridOptions.ts b/packages/grid-pro-react/src/utils/mappers/grid/gridOptions.ts index 39b406a..49e42ce 100644 --- a/packages/grid-pro-react/src/utils/mappers/grid/gridOptions.ts +++ b/packages/grid-pro-react/src/utils/mappers/grid/gridOptions.ts @@ -107,6 +107,7 @@ export function getGridEventPropDeps(props: GridProProps): unknown[] { props.gridKey, props.theme, props.className, + props.tableClassName, ...GRID_EVENT_PROP_KEYS.map((key) => props[key]) ]; } diff --git a/packages/grid-shared-react/src/utils/mappers/pagination/paginationOptions.ts b/packages/grid-shared-react/src/utils/mappers/pagination/paginationOptions.ts index 03c9f03..6730758 100644 --- a/packages/grid-shared-react/src/utils/mappers/pagination/paginationOptions.ts +++ b/packages/grid-shared-react/src/utils/mappers/pagination/paginationOptions.ts @@ -7,6 +7,29 @@ * */ +function withClassName( + value: unknown, + className: string | undefined +): unknown { + if (className === void 0) { + return value; + } + + // Disabled control is not rendered — keep boolean, drop className. + if (value === false) { + return false; + } + + if (value !== null && typeof value === 'object') { + return { ...value as Record, className }; + } + + return { + enabled: value === void 0 ? true : Boolean(value), + className + }; +} + export function normalizePaginationOptions( props: Record ): Record { @@ -22,6 +45,10 @@ export function normalizePaginationOptions( page, pageSize, align, + className, + infoClassName, + controlsClassName, + sizeClassName, ...rest } = props; @@ -38,22 +65,41 @@ export function normalizePaginationOptions( if (align !== void 0) { result.align = align; } + if (typeof className === 'string') { + result.className = className; + } const controls: Record = {}; - if (pageInfo !== void 0) { - controls.pageInfo = pageInfo; + if (typeof controlsClassName === 'string') { + controls.className = controlsClassName; + } + + const pageInfoValue = withClassName(pageInfo, asString(infoClassName)); + if (pageInfoValue !== void 0) { + controls.pageInfo = pageInfoValue; } + let pageSizeSelectorValue: unknown = pageSizeSelector; + if (pageSizeSelector === false) { - controls.pageSizeSelector = false; + pageSizeSelectorValue = false; } else if (pageSizeOptions !== void 0) { - controls.pageSizeSelector = { + pageSizeSelectorValue = { enabled: true, options: pageSizeOptions }; } else if (pageSizeSelector !== void 0) { - controls.pageSizeSelector = pageSizeSelector; + pageSizeSelectorValue = pageSizeSelector; + } + + pageSizeSelectorValue = withClassName( + pageSizeSelectorValue, + asString(sizeClassName) + ); + + if (pageSizeSelectorValue !== void 0) { + controls.pageSizeSelector = pageSizeSelectorValue; } if (pageButtons === false) { @@ -81,3 +127,7 @@ export function normalizePaginationOptions( return { ...result, ...rest }; } + +function asString(value: unknown): string | undefined { + return typeof value === 'string' ? value : void 0; +} diff --git a/packages/grid-shared-react/src/utils/mergeClassNames.ts b/packages/grid-shared-react/src/utils/mergeClassNames.ts new file mode 100644 index 0000000..d4f6737 --- /dev/null +++ b/packages/grid-shared-react/src/utils/mergeClassNames.ts @@ -0,0 +1,32 @@ +/** + * Grid React integration. + * Copyright (c) 2025, Highsoft + * + * A valid license is required for using this software. + * See highcharts.com/license + * + */ + +/** + * Joins CSS class tokens from defaults and overrides without duplicates. + * Used so ColumnDefaults `*ClassName` still applies when a Column sets its + * own `*ClassName`. + */ +export function mergeClassNames( + ...classNames: Array<(string | undefined | null)> +): string | undefined { + const tokens: string[] = []; + + for (const value of classNames) { + if (typeof value !== 'string' || !value.trim()) { + continue; + } + for (const token of value.trim().split(/\s+/)) { + if (token && !tokens.includes(token)) { + tokens.push(token); + } + } + } + + return tokens.length ? tokens.join(' ') : void 0; +} diff --git a/packages/grid-shared-react/src/utils/normalizeChildOptions.ts b/packages/grid-shared-react/src/utils/normalizeChildOptions.ts index ef45c01..5eb09b7 100644 --- a/packages/grid-shared-react/src/utils/normalizeChildOptions.ts +++ b/packages/grid-shared-react/src/utils/normalizeChildOptions.ts @@ -8,12 +8,20 @@ */ import { isObject } from './isObject'; +import { mergeClassNames } from './mergeClassNames'; import { normalizeColumnOptions } from './mappers/column'; import { normalizePaginationOptions } from './mappers/pagination'; /** * Maps raw declarative child options onto nested Grid option paths. * Used by lite and pro build pipelines after `getChildProps`. + * + * Also merges `columnDefaults` `className` / `header.className` / + * `cells.className` into each column so Column overrides do not wipe + * defaults (same semantics as Core `createOptionsProxy`). + * + * Lifts `rowClassName` / `evenRowClassName` from ColumnDefaults onto + * `rendering.rows` (not column options). */ export function normalizeChildOptions( raw: Record @@ -21,15 +29,49 @@ export function normalizeChildOptions( const result = { ...raw }; if (isObject(result.columnDefaults)) { - result.columnDefaults = normalizeColumnOptions({ - ...result.columnDefaults - }); + const defaults = { ...result.columnDefaults }; + const rowClassName = defaults.rowClassName; + const evenRowClassName = defaults.evenRowClassName; + delete defaults.rowClassName; + delete defaults.evenRowClassName; + + result.columnDefaults = normalizeColumnOptions(defaults); + + const rows: Record = {}; + if (typeof rowClassName === 'string') { + rows.className = rowClassName; + } + if (typeof evenRowClassName === 'string') { + rows.evenClassName = evenRowClassName; + } + + if (Object.keys(rows).length) { + const rendering = isObject(result.rendering) ? + { ...result.rendering } : + {}; + const existingRows = isObject(rendering.rows) ? + { ...rendering.rows as Record } : + {}; + rendering.rows = { ...existingRows, ...rows }; + result.rendering = rendering; + } } if (Array.isArray(result.columns)) { - result.columns = result.columns.map((column) => ( - isObject(column) ? normalizeColumnOptions({ ...column }) : column - )); + const defaults = isObject(result.columnDefaults) ? + result.columnDefaults as Record : + void 0; + + result.columns = result.columns.map((column) => { + if (!isObject(column)) { + return column; + } + + const normalized = normalizeColumnOptions({ ...column }); + return defaults ? + mergeColumnClassNames(normalized, defaults) : + normalized; + }); } if (isObject(result.pagination)) { @@ -46,3 +88,55 @@ export function normalizeChildOptions( return result; } + +function mergeColumnClassNames( + column: Record, + defaults: Record +): Record { + const result = { ...column }; + const className = mergeClassNames( + asString(defaults.className), + asString(column.className) + ); + + if (className !== void 0) { + result.className = className; + } + + result.header = mergeNestedClassName( + column.header, + defaults.header + ); + result.cells = mergeNestedClassName( + column.cells, + defaults.cells + ); + + return result; +} + +function mergeNestedClassName( + target: unknown, + defaults: unknown +): Record | unknown { + const targetObj = isObject(target) ? { ...target } : {}; + const defaultsObj = isObject(defaults) ? defaults : {}; + const className = mergeClassNames( + asString(defaultsObj.className), + asString(targetObj.className) + ); + + if (className === void 0 && !isObject(target)) { + return target; + } + + if (className !== void 0) { + targetObj.className = className; + } + + return targetObj; +} + +function asString(value: unknown): string | undefined { + return typeof value === 'string' ? value : void 0; +} From ae6dea058ddd041feced0fea93693800770cf0ff Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Mon, 10 Aug 2026 11:01:26 +0200 Subject: [PATCH 08/12] Updated CSS and package.json. --- examples/grid-lite/components-react/src/index.css | 1 - packages/grid-lite-react/package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/grid-lite/components-react/src/index.css b/examples/grid-lite/components-react/src/index.css index bcb41c2..93cfec9 100644 --- a/examples/grid-lite/components-react/src/index.css +++ b/examples/grid-lite/components-react/src/index.css @@ -13,7 +13,6 @@ } } -/* Load grid-theme-default.css only when using Core theme tokens (non-empty `theme`). */ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', diff --git a/packages/grid-lite-react/package.json b/packages/grid-lite-react/package.json index a619e75..a24a3d1 100644 --- a/packages/grid-lite-react/package.json +++ b/packages/grid-lite-react/package.json @@ -30,7 +30,7 @@ "url": "https://github.com/highcharts/grid-react/issues" }, "scripts": { - "build": "pnpm clean:dist && rollup -c && cp -R src/styles dist/styles", + "build": "pnpm clean:dist && rollup -c", "lint": "eslint src --ext .ts,.tsx", "clean:dist": "rimraf dist", "clean": "rimraf node_modules dist", From f5f5ce7bebcbc3e3714b495645df6be527f9db81 Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Mon, 10 Aug 2026 12:50:36 +0200 Subject: [PATCH 09/12] Fixed styles, mappers. --- .../grid-lite-react/src/styles/grid-core.css | 680 ------------------ .../src/styles/grid-theme-default.css | 63 -- .../src/utils/mappers/grid/gridOptions.ts | 2 +- .../tests/mappers/gridOptions.test.tsx | 73 ++ 4 files changed, 74 insertions(+), 744 deletions(-) delete mode 100644 packages/grid-lite-react/src/styles/grid-core.css delete mode 100644 packages/grid-lite-react/src/styles/grid-theme-default.css diff --git a/packages/grid-lite-react/src/styles/grid-core.css b/packages/grid-lite-react/src/styles/grid-core.css deleted file mode 100644 index ccd0493..0000000 --- a/packages/grid-lite-react/src/styles/grid-core.css +++ /dev/null @@ -1,680 +0,0 @@ -@import '@highcharts/grid-lite/css/modules/grid-base-variables.css'; -@import '@highcharts/grid-lite/css/modules/grid-popup-variables.css'; -@import '@highcharts/grid-lite/css/modules/grid-menu-variables.css'; -@import '@highcharts/grid-lite/css/modules/grid-link-variables.css'; -@import '@highcharts/grid-lite/css/modules/grid-input-variables.css'; -@import '@highcharts/grid-lite/css/modules/grid-button-variables.css'; -@import '@highcharts/grid-lite/css/modules/grid-icon-variables.css'; -@import '@highcharts/grid-lite/css/modules/grid-pagination-variables.css'; -@import '@highcharts/grid-lite/css/modules/grid-table-variables.css'; -/* Grid container */ -.hcg-container { - container-type: inline-size; - container-name: hcg; - position: relative; - display: flex; - flex-direction: column; - height: 100%; - overflow: hidden; - box-sizing: border-box; - color-scheme: light dark; - max-height: inherit; -} - -.highcharts-light .hcg-container { - color-scheme: light; -} - -.highcharts-dark .hcg-container { - color-scheme: dark; -} - -.hcg-container * { - box-sizing: border-box; -} - -.hcg-container:has(.hcg-no-data) { - justify-content: center; - align-items: center; -} - -/* ---------------------------------------------------------- - INPUT ELEMENTS ------------------------------------------------------------- */ - -.hcg-container .hcg-input { - width: 100%; - - &:disabled { - opacity: 0.4; - cursor: not-allowed; - } - - &::placeholder { - color: #767676; - } - - &:focus-visible { - outline: none; - border-color: transparent; - } - - &[type="checkbox"] { - --ig-input-checkbox-size: 1.333em; - - appearance: none; - width: var(--ig-input-checkbox-size); - height: var(--ig-input-checkbox-size); - cursor: pointer; - position: relative; - - &:checked::before { - content: ""; - position: absolute; - inset: 0; - margin: 0.05em; - mask: center/contain no-repeat; - mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E"); - } - } - - &.hcg-icon-search { - padding-left: 25px; - appearance: none; - background-repeat: no-repeat; - background-position: left 10px center; - background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3e%3cpath d='M10.5 10.5L7.50005 7.5M8.5 5C8.5 6.933 6.933 8.5 5 8.5C3.067 8.5 1.5 6.933 1.5 5C1.5 3.067 3.067 1.5 5 1.5C6.933 1.5 8.5 3.067 8.5 5Z' stroke='%23767676' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e"); - } - - select& { - appearance: none; - background-image: url("data:image/svg+xml,%3csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M3.5 7.5L6 10L8.5 7.5M3.5 4.5L6 2L8.5 4.5' stroke='%23767676' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e"); - background-repeat: no-repeat; - background-position: right 5px center; - white-space: nowrap; - text-overflow: ellipsis; - } -} - -/* ---------------------------------------------------------- - BUTTON ELEMENT ------------------------------------------------------------- */ - -.hcg-container :is(.hcg-button, .hcg-icon) { - position: relative; - display: inline-flex; - vertical-align: middle; - align-items: center; - justify-content: center; - flex-direction: row; - line-height: 1; - gap: 2px; - cursor: pointer; - transition: background-color 0.2s ease, box-shadow 0.2s ease, border 0.2s ease; - - svg { - width: 0.9em; - height: 0.9em; - display: block; - } - - span { - display: inline-block; - line-height: 1; - } - - span:empty { - display: none; - } - - &.reverse { - flex-direction: row-reverse; - } - - &:focus-visible { - outline: none; - border-color: transparent; - } - - &:disabled { - opacity: 0.4; - cursor: not-allowed; - } -} - -/* ---------------------------------------------------------- - TABLE ELEMENTS ------------------------------------------------------------- */ - -/*
Grid Caption v2.1Grid Caption v2.1 Grid Caption v2.1Team directory
*/ -.hcg-container .hcg-table { - width: 100%; - border-collapse: separate; - border-spacing: 0; - overflow: hidden; - table-layout: fixed; - flex: 1; - - &.hcg-scrollable-content { - display: flex; - flex-direction: column; - min-height: 0; - } - - /* */ - &.hcg-virtualization thead { - display: block; - } - - thead th { - position: relative; - } - - /* */ - &.hcg-scrollable-content > tbody { - height: 100%; - overflow: auto; - min-height: 0; - flex: 1; - } - - &.hcg-virtualization > tbody { - display: block; - position: relative; - } - - > tbody > tr { - overflow: hidden; - width: 100%; - } - - > tbody > tr > :where(.hcg-cell) { - position: relative; - line-height: 1em; - overflow: hidden; - } - - > tbody > tr.hcg-mocked-row > :where(.hcg-cell) { - white-space: nowrap; - text-overflow: ellipsis; - } - - .hcg-last-header-cell-in-row, - tbody tr > :where(.hcg-cell):last-child { - border-right: none; - } - - tbody tr:last-of-type > :where(.hcg-cell) { - border-bottom: none; - } - - &.hcg-scrollable-content > tbody > tr { - display: block; - } - - &.hcg-virtualization > tbody > tr { - position: absolute; - } - - > tbody.hcg-rows-content-nowrap > tr > :where(.hcg-cell) { - white-space: nowrap; - text-overflow: ellipsis; - } - - > tbody > tr > :where(.hcg-cell):focus { - outline: none; - } -} - -/* ---------------------------------------------------------- - HEADER ELEMENTS ------------------------------------------------------------- */ -.hcg-container thead th { - .hcg-header-cell-container { - display: flex; - align-items: center; - justify-content: space-between; - } - - .hcg-header-cell-content { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .hcg-header-cell-container.hcg-no-width .hcg-header-cell-content { - visibility: hidden; - transition: none; - } - - .hcg-header-cell-icons { - display: flex; - overflow: hidden; - align-items: center; - max-width: 0; - opacity: 0; - cursor: pointer; - transition: max-width 0.3s ease, opacity 0.3s ease; - } - - .hcg-header-cell-icons .hcg-icon.hcg-icon-selected::after { - content: ""; - position: absolute; - top: 2px; - right: 2px; - width: 0.3em; - height: 0.3em; - border-radius: 50%; - background: currentColor; - } - - :is(:hover, :focus-visible) .hcg-header-cell-icons, - .hcg-header-cell-icons:has(.hcg-button:focus-visible, .hcg-icon:focus-visible, .hcg-button.hcg-button-selected, .hcg-icon.hcg-icon-highlighted, .hcg-icon.hcg-icon-selected), - .hcg-header-cell-container.hcg-no-width .hcg-header-cell-icons { - max-width: 100px; - opacity: 1; - } - - .hcg-header-cell-container.hcg-no-width .hcg-header-cell-menu-icon { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - margin-left: 0; - } - - .hcg-header-cell-icons .hcg-header-cell-menu-icon .hcg-icon { - padding-inline: 3px; - } - - .hcg-header-cell-icons > :first-child { - margin-left: 5px; - } - - .hcg-column-resizer { - position: absolute; - display: flex; - align-items: center; - justify-content: center; - top: 0; - width: 9px; - right: -5px; - height: 100%; - user-select: none; - touch-action: none; - z-index: 10; - cursor: col-resize; - } - - .hcg-column-resizer.hovered::after { - content: ""; - height: 100%; - } -} - -/* ---------------------------------------------------------- - PAGINATION ELEMENTS ------------------------------------------------------------- */ - -.hcg-container .hcg-pagination { - display: flex; - align-items: center; - gap: 0.75rem; - flex-wrap: nowrap; - - > * { - flex: 1 1 0; - min-width: 0; - display: flex; - align-items: center; - } - - .hcg-pagination-info { - justify-content: flex-start; - } - - .hcg-pagination-controls { - justify-content: center; - gap: 2px; - - .hcg-pagination-pages { - display: flex; - flex-wrap: nowrap; - gap: 2px; - - .hcg-button { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 30px; - } - - span { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 20px; - } - } - } - - .hcg-pagination-page-size { - justify-content: flex-end; - text-align: right; - - select.hcg-input { - width: 60px; - margin-left: 8px; - } - } - - /* .hcg-pagination-nav-dropdown { - display: none; - min-width: 200px; - } */ - - &.hcg-pagination-left, - &.hcg-pagination-center, - &.hcg-pagination-right { - > * { - flex: 0 0 auto; - min-width: auto; - } - } - - &.hcg-pagination-left { justify-content: flex-start; } - &.hcg-pagination-center { justify-content: center; } - &.hcg-pagination-right { justify-content: flex-end; } - - &:not(:has(.hcg-pagination-info)) .hcg-pagination-controls { - justify-content: flex-start; - } - - &:not(:has(.hcg-pagination-page-size)) .hcg-pagination-controls { - justify-content: flex-end; - } -} - -@container hcg (max-width: 800px) { - .hcg-container .hcg-pagination { - flex-direction: column; - align-items: stretch; - --ig-pagination-stacked-align: center; - - &.hcg-pagination-left { --ig-pagination-stacked-align: flex-start; } - &.hcg-pagination-right { --ig-pagination-stacked-align: flex-end; } - - > * { - flex: 0 0 auto; - justify-content: var(--ig-pagination-stacked-align); - } - - .hcg-pagination-info, - .hcg-pagination-controls, - .hcg-pagination-page-size { - justify-content: var(--ig-pagination-stacked-align); - } - - .hcg-pagination-page-size { - text-align: center; - } - &.hcg-pagination-left .hcg-pagination-page-size { text-align: left; } - &.hcg-pagination-right .hcg-pagination-page-size { text-align: right; } - - &:not(:has(.hcg-pagination-page-size)) .hcg-pagination-controls, - &:not(:has(.hcg-pagination-info)) .hcg-pagination-controls { - justify-content: var(--ig-pagination-stacked-align); - } - } -} - -/* ---------------------------------------------------------- - CREDITS ELEMENT ------------------------------------------------------------- */ - -.hcg-credits, -.highcharts-light .hcg-credits { - display: block; - width: 114px; - height: 20px; - background-size: contain; - background-repeat: no-repeat; - background-image: - image-set( - /* stylelint-disable-next-line function-comma-newline-after */ - url("https://assets.highcharts.com/grid/logo_light.png") 1x, - url("https://assets.highcharts.com/grid/logo_lightx2.png") 2x - ); -} - -@media (prefers-color-scheme: dark) { - .hcg-credits { - background-image: - image-set( - /* stylelint-disable-next-line function-comma-newline-after */ - url("https://assets.highcharts.com/grid/logo_dark.png") 1x, - url("https://assets.highcharts.com/grid/logo_darkx2.png") 2x - ); - } -} - -.highcharts-dark .hcg-credits { - background-image: - image-set( - /* stylelint-disable-next-line function-comma-newline-after */ - url("https://assets.highcharts.com/grid/logo_dark.png") 1x, - url("https://assets.highcharts.com/grid/logo_darkx2.png") 2x - ); -} - -/* ---------------------------------------------------------- - POPUP ELEMENTS ------------------------------------------------------------- */ -.hcg-container .hcg-popup { - position: absolute; - z-index: 1000; - border-radius: 6px; - box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08), 0 7px 7px 0 rgba(0, 0, 0, 0.07), 0 17px 10px 0 rgba(0, 0, 0, 0.04), 0 30px 12px 0 rgba(0, 0, 0, 0.01); - min-width: 200px; - overflow: auto; - border-width: 1px; - border-style: solid; - - .hcg-popup-content { - padding: 5px; - } - - .hcg-menu-header { - font-size: 0.75rem; - padding: 3px; - margin-bottom: 5px; - } - - .hcg-menu-header-category { - opacity: 0.5; - user-select: none; - } -} - -/* ---------------------------------------------------------- - MENU ELEMENTS ------------------------------------------------------------- */ - -.hcg-container .hcg-menu-container { - margin: 0; - display: flex; - flex-direction: column; - list-style: none; - row-gap: 5px; - padding: 0; - - .hcg-menu-item { - display: flex; - align-items: center; - gap: 2px; - width: 100%; - min-width: 185px; - min-height: 2rem; - padding: 8px 8px 8px 12px; - font-size: 0.75rem; - font-weight: 600; - background-color: transparent; - border: 1px solid transparent; - border-radius: 5px; - } - - .hcg-menu-item:not(:disabled) { - cursor: pointer; - } - - .hcg-menu-item:focus-visible { - outline: none; - } - - .hcg-menu-item-icon { - --icon-size: 16px; - - flex: 0 0 var(--icon-size); - width: var(--icon-size); - height: var(--icon-size); - display: inline-flex; - align-items: center; - justify-content: center; - opacity: 0.6; - } - - .hcg-menu-item.active .hcg-menu-item-icon, - .hcg-menu-item.highlighted .hcg-menu-item-icon, - .hcg-menu-item:not(:disabled):hover .hcg-menu-item-icon { - opacity: 1; - } - - .hcg-menu-item-label { - flex: 1 1 auto; - min-width: 0; - text-align: left; - padding-left: 0.75rem; - } - - .hcg-menu-divider { - border-top-width: 1px; - border-top-style: solid; - height: 0; - } -} - -/* ---------------------------------------------------------- - FILTERING ELEMENTS ------------------------------------------------------------- */ - -.hcg-header-cell:has(.hcg-column-filter-wrapper) { - overflow: hidden; -} - -.hcg-column-filter-wrapper { - width: 100%; - display: flex; - flex-flow: column; - row-gap: 5px; - min-width: 50px; -} - -.hcg-clear-filter-button { - appearance: none; - background: none; - border: 0; - padding: 0; - margin: 0; - display: inline; - vertical-align: baseline; - font: inherit; - font-size: 0.625rem; - white-space: nowrap; - font-weight: normal; - align-self: end; -} - -.hcg-clear-filter-button:hover { - text-decoration: underline; - cursor: pointer; -} - -.hcg-clear-filter-button:disabled, -.hcg-clear-filter-button:disabled:hover { - opacity: 0.5; - text-decoration: none; - cursor: default; -} - -/* ---------------------------------------------------------- - OTHER ELEMENTS ------------------------------------------------------------- */ - -/* Sorting */ -.hcg-table thead th.hcg-column-sortable { - cursor: pointer; -} - -/* Accessibility */ -.hcg-visually-hidden { - position: absolute; - width: 1px; - height: 1px; - overflow: hidden; - white-space: nowrap; - clip: rect(1px, 1px, 1px, 1px); - margin-top: -3px; - opacity: 0.01; -} - -/* Loader */ -.hcg-loading-wrapper { - display: flex; - align-items: center; - justify-content: center; - position: absolute; - width: 100%; - height: 100%; - gap: 10px; - color: light-dark(#000000, #ffffff); -} - -.hcg-loading-wrapper .hcg-spinner { - border-top-width: 5px; - border-top-style: solid; - border-top-color: light-dark(#000000, #ffffff); - border-radius: 50%; - width: 30px; - height: 30px; - animation: spin 1s linear infinite; -} - -@keyframes spin { - from { - transform: rotate(0deg); - } - - to { - transform: rotate(360deg); - } -} - -/* Start Grid CSS Helpers Classes */ - -.hcg-table thead tr th.hcg-right .hcg-header-cell-content, -.hcg-table tbody tr > :where(.hcg-cell).hcg-right { - text-align: right; -} - -.hcg-table thead tr th.hcg-center .hcg-header-cell-content, -.hcg-table tbody tr > :where(.hcg-cell).hcg-center { - text-align: center; -} - -.hcg-table thead tr th.hcg-left .hcg-header-cell-content, -.hcg-table tbody tr > :where(.hcg-cell).hcg-left { - text-align: left; -} - -/* End Grid CSS Helpers Classes */ diff --git a/packages/grid-lite-react/src/styles/grid-theme-default.css b/packages/grid-lite-react/src/styles/grid-theme-default.css deleted file mode 100644 index 7e85955..0000000 --- a/packages/grid-lite-react/src/styles/grid-theme-default.css +++ /dev/null @@ -1,63 +0,0 @@ -@import '@highcharts/grid-lite/css/modules/grid-theme-default.css'; - -.hcg-theme-default { - --hcg-description-color: var(--hcg-color); - --hcg-description-background: transparent; - --hcg-description-font-weight: normal; - --hcg-description-font-size: var(--hcg-font-size); - --hcg-description-font-family: inherit; - --hcg-description-line-height: normal; - --hcg-description-letter-spacing: normal; - --hcg-description-text-align: left; - --hcg-description-margin-top: 0; - --hcg-description-margin-right: 0; - --hcg-description-margin-bottom: 0; - --hcg-description-margin-left: 0; - --hcg-description-padding-top: var(--hcg-padding); - --hcg-description-padding-right: var(--hcg-padding); - --hcg-description-padding-bottom: 0; - --hcg-description-padding-left: var(--hcg-padding); -} - -.hcg-theme-default .hcg-caption { - color: var(--hcg-caption-color); - background: var(--hcg-caption-background); - font-weight: var(--hcg-caption-font-weight); - font-size: var(--hcg-caption-font-size); - font-family: var(--hcg-caption-font-family); - line-height: var(--hcg-caption-line-height); - letter-spacing: var(--hcg-caption-letter-spacing); - text-align: var(--hcg-caption-text-align); - margin-top: var(--hcg-caption-margin-top); - margin-right: var(--hcg-caption-margin-right); - margin-bottom: var(--hcg-caption-margin-bottom); - margin-left: var(--hcg-caption-margin-left); - padding-top: var(--hcg-caption-padding-top); - padding-right: var(--hcg-caption-padding-right); - padding-bottom: var(--hcg-caption-padding-bottom); - padding-left: var(--hcg-caption-padding-left); -} - -.hcg-theme-default.hcg-caption * { - font: inherit; - margin: var(--hcg-caption-child-margin); -} - -.hcg-theme-default .hcg-description { - color: var(--hcg-description-color); - background: var(--hcg-description-background); - font-weight: var(--hcg-description-font-weight); - font-size: var(--hcg-description-font-size); - font-family: var(--hcg-description-font-family); - line-height: var(--hcg-description-line-height); - letter-spacing: var(--hcg-description-letter-spacing); - text-align: var(--hcg-description-text-align); - margin-top: var(--hcg-description-margin-top); - margin-right: var(--hcg-description-margin-right); - margin-bottom: var(--hcg-description-margin-bottom); - margin-left: var(--hcg-description-margin-left); - padding-top: var(--hcg-description-padding-top); - padding-right: var(--hcg-description-padding-right); - padding-bottom: var(--hcg-description-padding-bottom); - padding-left: var(--hcg-description-padding-left); -} diff --git a/packages/grid-pro-react/src/utils/mappers/grid/gridOptions.ts b/packages/grid-pro-react/src/utils/mappers/grid/gridOptions.ts index 49e42ce..4d62502 100644 --- a/packages/grid-pro-react/src/utils/mappers/grid/gridOptions.ts +++ b/packages/grid-pro-react/src/utils/mappers/grid/gridOptions.ts @@ -16,7 +16,7 @@ import type { import type { AfterTreeRowToggleEvent, BeforeTreeRowToggleEvent -} from '@highcharts/grid-pro/es-modules/Grid/Pro/TreeView/TreeProjectionController.js'; +} from '@highcharts/grid-pro/es-modules/Grid/Pro/TreeView/Projection/TreeProjectionController.js'; import { mapEventsProps } from '../../mapEventsProps'; /** diff --git a/packages/grid-pro-react/tests/mappers/gridOptions.test.tsx b/packages/grid-pro-react/tests/mappers/gridOptions.test.tsx index 60a8f82..dc07360 100644 --- a/packages/grid-pro-react/tests/mappers/gridOptions.test.tsx +++ b/packages/grid-pro-react/tests/mappers/gridOptions.test.tsx @@ -75,6 +75,78 @@ describe('buildGridOptions', () => { expect(options.gridKey).toBe('GRID-KEY'); expect(options.columns).toEqual([{ id: 'name' }]); }); + + it('omits rendering.theme when theme prop is undefined', () => { + const options = buildGridOptions( + 'GRID-KEY', + {}, + void 0, + { + gridKey: 'GRID-KEY', + className: 'rounded-md border' + } as GridProProps + ); + + expect(options.rendering?.theme).toBeUndefined(); + expect( + (options.rendering as { className?: string } | undefined)?.className + ).toBeUndefined(); + }); + + it('passes empty theme to disable Core default', () => { + const options = buildGridOptions( + 'GRID-KEY', + {}, + void 0, + { + gridKey: 'GRID-KEY', + theme: '', + className: 'rounded-md border' + } as GridProProps + ); + + expect(options.rendering?.theme).toBe(''); + expect( + (options.rendering as { className?: string } | undefined)?.className + ).toBeUndefined(); + }); + + it('passes custom theme without putting className into Core options', () => { + const options = buildGridOptions( + 'GRID-KEY', + {}, + void 0, + { + gridKey: 'GRID-KEY', + theme: 'myTheme', + className: 'rounded-md border' + } as GridProProps + ); + + expect(options.rendering?.theme).toBe('myTheme'); + expect( + (options.rendering as { className?: string } | undefined)?.className + ).toBeUndefined(); + }); + + it('maps tableClassName to rendering.table.className', () => { + const options = buildGridOptions( + 'GRID-KEY', + {}, + void 0, + { + gridKey: 'GRID-KEY', + theme: '', + className: 'p-8', + tableClassName: 'border border-slate-300' + } as GridProProps + ); + + expect(options.rendering?.theme).toBe(''); + expect(options.rendering?.table?.className).toBe( + 'border border-slate-300' + ); + }); }); describe('getGridEventPropDeps', () => { @@ -90,6 +162,7 @@ describe('getGridEventPropDeps', () => { 'KEY', void 0, void 0, + void 0, ...GRID_EVENT_PROP_KEYS.map( (key: keyof GridProProps) => props[key] ) From cf2fed614d8489598b3024fe4b24fe331969e2cd Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Tue, 11 Aug 2026 11:14:55 +0200 Subject: [PATCH 10/12] Fixed Grid component and the base. --- packages/grid-lite-react/src/Grid.tsx | 10 ++++++---- packages/grid-pro-react/src/Grid.tsx | 5 +++-- .../grid-shared-react/src/components/BaseGrid.tsx | 13 ++++++++++--- packages/grid-shared-react/src/index.ts | 2 ++ 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/grid-lite-react/src/Grid.tsx b/packages/grid-lite-react/src/Grid.tsx index e42fd46..d6aec44 100644 --- a/packages/grid-lite-react/src/Grid.tsx +++ b/packages/grid-lite-react/src/Grid.tsx @@ -12,7 +12,7 @@ import { useDeclarativeGridOptions } from '@highcharts/grid-shared-react'; import Grid from '@highcharts/grid-lite/es-modules/masters/grid-lite.src'; -import './styles/grid-core.css'; +import '@highcharts/grid-lite/css/grid-lite.css'; import type { Options } from '@highcharts/grid-lite/es-modules/Grid/Core/Options'; import type { GridProps } from '@highcharts/grid-shared-react'; import { buildGridOptions } from './utils/buildGridOptions'; @@ -24,7 +24,8 @@ export default function GridLite(props: GridProps) { options, callback, theme, - className + className, + tableClassName } = props; const { gridOptions, columnKey } = useDeclarativeGridOptions( children, @@ -33,9 +34,9 @@ export default function GridLite(props: GridProps) { childOptions, opts, theme, - className + tableClassName ), - [theme, className] + [theme, tableClassName] ); return ( @@ -45,6 +46,7 @@ export default function GridLite(props: GridProps) { Grid={Grid} callback={callback} ref={gridRef} + className={className} /> ); } diff --git a/packages/grid-pro-react/src/Grid.tsx b/packages/grid-pro-react/src/Grid.tsx index cbd0d46..7400e61 100644 --- a/packages/grid-pro-react/src/Grid.tsx +++ b/packages/grid-pro-react/src/Grid.tsx @@ -20,12 +20,12 @@ import { import { buildGridOptions } from './utils/buildGridOptions'; export default function GridPro(props: GridProProps) { - const { gridKey, gridRef, children, options, callback } = props; + const { gridRef, children, options, callback, className } = props; const { gridOptions, columnKey } = useDeclarativeGridOptions( children, options, (childOptions, opts) => buildGridOptions( - gridKey, + props.gridKey, childOptions, opts, props @@ -40,6 +40,7 @@ export default function GridPro(props: GridProProps) { Grid={Grid} callback={callback} ref={gridRef} + className={className} /> ); } diff --git a/packages/grid-shared-react/src/components/BaseGrid.tsx b/packages/grid-shared-react/src/components/BaseGrid.tsx index 917eb36..b9df08f 100644 --- a/packages/grid-shared-react/src/components/BaseGrid.tsx +++ b/packages/grid-shared-react/src/components/BaseGrid.tsx @@ -33,12 +33,19 @@ export interface GridProps { */ options?: TOptions; /** - * Optional CSS class names applied on the Grid container (`hcg-container`), - * merged with `theme` into `rendering.theme`. + * Optional CSS class names on the React mount container (parent of + * `.hcg-container`). Independent of `theme`. */ className?: string; /** - * Optional theme name passed to Grid Core. + * Optional CSS class names mapped to Core `rendering.table.className` on + * `.hcg-table`. Independent of `className` / `theme`. + */ + tableClassName?: string; + /** + * Optional theme name passed to Grid Core as `rendering.theme`. + * Omitted → Core default (`hcg-theme-default`). + * Defined (including `''`) → that value only. */ theme?: string; /** diff --git a/packages/grid-shared-react/src/index.ts b/packages/grid-shared-react/src/index.ts index e9f5bd8..23f0e41 100644 --- a/packages/grid-shared-react/src/index.ts +++ b/packages/grid-shared-react/src/index.ts @@ -23,6 +23,7 @@ export { } from './components/options'; export { getChildProps } from './utils/getChildProps'; export { isObject } from './utils/isObject'; +export { mergeClassNames } from './utils/mergeClassNames'; export { normalizeChildOptions } from './utils/normalizeChildOptions'; export { useDeclarativeGridOptions } from './hooks/useDeclarativeGridOptions'; export type { @@ -33,6 +34,7 @@ export type { DataColumnValue, ColumnProps, ColumnOptionsProps, + ColumnDefaultsProps, ColumnDataType, ColumnSortingOrder, CellValueGetterContext, From bcc20544857800974d572fbac007a400972d2684 Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Tue, 11 Aug 2026 13:33:47 +0200 Subject: [PATCH 11/12] Fixed pagination and ColumnDefaults. --- .../options/columns/ColumnDefaults.tsx | 19 +++++++++++++++++- .../src/components/options/index.ts | 1 + .../options/pagination/paginationProps.ts | 20 +++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/grid-shared-react/src/components/options/columns/ColumnDefaults.tsx b/packages/grid-shared-react/src/components/options/columns/ColumnDefaults.tsx index d8569ba..d5a1faf 100644 --- a/packages/grid-shared-react/src/components/options/columns/ColumnDefaults.tsx +++ b/packages/grid-shared-react/src/components/options/columns/ColumnDefaults.tsx @@ -9,7 +9,24 @@ import type { ColumnOptionsProps } from './columnProps'; -export function ColumnDefaults(_props: ColumnOptionsProps) { +/** + * ColumnDefaults props include shared column options plus grid-level row + * class hooks (lifted to `rendering.rows` during normalize). + */ +export interface ColumnDefaultsProps extends ColumnOptionsProps { + /** + * CSS class names on every body ``. + * Maps to Core `rendering.rows.className`. + */ + rowClassName?: string; + /** + * CSS class names on even body `` (Core `.hcg-row-even` parity). + * Maps to Core `rendering.rows.evenClassName`. + */ + evenRowClassName?: string; +} + +export function ColumnDefaults(_props: ColumnDefaultsProps) { return null; } diff --git a/packages/grid-shared-react/src/components/options/index.ts b/packages/grid-shared-react/src/components/options/index.ts index 36984b3..6966a89 100644 --- a/packages/grid-shared-react/src/components/options/index.ts +++ b/packages/grid-shared-react/src/components/options/index.ts @@ -12,6 +12,7 @@ export type { CaptionProps } from './caption'; export { Data } from './data/Data'; export type { DataProps, DataColumns, DataColumnValue } from './data/Data'; export { ColumnDefaults } from './columns/ColumnDefaults'; +export type { ColumnDefaultsProps } from './columns/ColumnDefaults'; export { Column } from './columns/Column'; export type { ColumnProps, diff --git a/packages/grid-shared-react/src/components/options/pagination/paginationProps.ts b/packages/grid-shared-react/src/components/options/pagination/paginationProps.ts index a5f9a93..3e31579 100644 --- a/packages/grid-shared-react/src/components/options/pagination/paginationProps.ts +++ b/packages/grid-shared-react/src/components/options/pagination/paginationProps.ts @@ -14,6 +14,26 @@ export interface PaginationProps { * Pass `false` to disable pagination while keeping other options. */ enabled?: boolean; + /** + * Additional CSS class name(s) for the pagination container + * (`.hcg-pagination`). + */ + className?: string; + /** + * Additional CSS class name(s) for the page info element + * (`.hcg-pagination-info`). + */ + infoClassName?: string; + /** + * Additional CSS class name(s) for the controls container + * (`.hcg-pagination-controls`). + */ + controlsClassName?: string; + /** + * Additional CSS class name(s) for the page size container + * (`.hcg-pagination-page-size`). + */ + sizeClassName?: string; /** * The current page number. */ From efcd81835991bdfa96a61b566965c791fee20c12 Mon Sep 17 00:00:00 2001 From: Sebastian Bochan Date: Tue, 11 Aug 2026 15:51:07 +0200 Subject: [PATCH 12/12] Added tests. --- .../tests/buildGridOptions.test.ts | 46 ++++++++++++++++ .../tests/options/ColumnDefaults.test.tsx | 52 +++++++++++++++++++ .../tests/options/Pagination.test.tsx | 34 ++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 packages/grid-lite-react/tests/buildGridOptions.test.ts diff --git a/packages/grid-lite-react/tests/buildGridOptions.test.ts b/packages/grid-lite-react/tests/buildGridOptions.test.ts new file mode 100644 index 0000000..6fe9dcd --- /dev/null +++ b/packages/grid-lite-react/tests/buildGridOptions.test.ts @@ -0,0 +1,46 @@ +import { describe, it, expect } from 'vitest'; +import { buildGridOptions } from '../src/utils/buildGridOptions'; + +describe('buildGridOptions theme', () => { + it('omits rendering.theme when theme prop is undefined', () => { + const options = buildGridOptions({}); + + expect(options.rendering?.theme).toBeUndefined(); + }); + + it('passes empty theme to disable Core default', () => { + const options = buildGridOptions({}, void 0, ''); + + expect(options.rendering?.theme).toBe(''); + }); + + it('passes custom theme as-is', () => { + const options = buildGridOptions({}, void 0, 'myTheme'); + + expect(options.rendering?.theme).toBe('myTheme'); + }); + + it('does not put className into Core options', () => { + // className is React-only on the mount container + const options = buildGridOptions({}, void 0, 'hcg-theme-default'); + + expect(options.rendering?.theme).toBe('hcg-theme-default'); + expect( + (options.rendering as { className?: string } | undefined)?.className + ).toBeUndefined(); + }); + + it('maps tableClassName to rendering.table.className', () => { + const options = buildGridOptions( + {}, + void 0, + '', + 'border border-slate-300 w-full' + ); + + expect(options.rendering?.theme).toBe(''); + expect(options.rendering?.table?.className).toBe( + 'border border-slate-300 w-full' + ); + }); +}); diff --git a/packages/grid-shared-react/tests/options/ColumnDefaults.test.tsx b/packages/grid-shared-react/tests/options/ColumnDefaults.test.tsx index 9cbfff9..ae83c94 100644 --- a/packages/grid-shared-react/tests/options/ColumnDefaults.test.tsx +++ b/packages/grid-shared-react/tests/options/ColumnDefaults.test.tsx @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest'; +import { Column } from '../../src/components/options/columns/Column'; import { ColumnDefaults } from '../../src/components/options/columns/ColumnDefaults'; import { getChildProps } from '../../src/utils/getChildProps'; import { normalizeChildOptions } from '../../src/utils/normalizeChildOptions'; @@ -47,4 +48,55 @@ describe('ColumnDefaults normalization', () => { } }); }); + + it('merges columnDefaults classNames into column overrides', () => { + const options = normalizeChildOptions( + getChildProps( + <> + + + + ) + ); + + expect(options.columns).toEqual([ + { + id: 'name', + className: 'hcg-name-column', + header: { + className: 'p-4 text-left border-b hcg-name-header' + }, + cells: { + className: 'p-4 text-left border-b hcg-name-cell' + } + } + ]); + }); + + it('lifts rowClassName and evenRowClassName to rendering.rows', () => { + const options = normalizeChildOptions( + getChildProps( + + ) + ); + + expect(options.columnDefaults).toEqual({}); + expect(options.rendering).toEqual({ + rows: { + className: 'hover:bg-slate-50', + evenClassName: 'bg-slate-50' + } + }); + }); }); diff --git a/packages/grid-shared-react/tests/options/Pagination.test.tsx b/packages/grid-shared-react/tests/options/Pagination.test.tsx index 400343c..fed4546 100644 --- a/packages/grid-shared-react/tests/options/Pagination.test.tsx +++ b/packages/grid-shared-react/tests/options/Pagination.test.tsx @@ -96,4 +96,38 @@ describe('Pagination normalization', () => { } }); }); + + it('maps className props onto pagination and controls', () => { + expect( + normalizeChildOptions( + getChildProps( + + ) + ) + ).toEqual({ + pagination: { + enabled: true, + className: 'mt-4', + position: 'top', + controls: { + className: 'gap-2', + pageInfo: { + enabled: true, + className: 'text-sm text-slate-500' + }, + pageSizeSelector: { + enabled: true, + options: [3, 5, 10], + className: 'text-sm' + } + } + } + }); + }); });