Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export default defineConfig(
},
rules: {
'curly': ['error', 'all'],
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_'
}],
'@stylistic/semi': ['error', 'always'],
'@stylistic/quotes': ['error', 'single', { avoidEscape: true }],
'@stylistic/brace-style': ['error', '1tbs', { allowSingleLine: true }],
Expand Down
13 changes: 13 additions & 0 deletions examples/grid-lite/components-react/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Highcharts Grid Lite - React Example</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

26 changes: 26 additions & 0 deletions examples/grid-lite/components-react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "grid-lite-minimal-react",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"clean": "rimraf dist node_modules"
},
"dependencies": {
"@highcharts/grid-lite": ">=3.0.0",
"@highcharts/grid-lite-react": "workspace:*",
"react": ">=18",
"react-dom": ">=18"
},
"devDependencies": {
"@types/react": ">=18",
"@types/react-dom": ">=18",
"@vitejs/plugin-react": "^4.2.0",
"typescript": "^5.0.0",
"vite": "^5.0.0"
}
}

52 changes: 52 additions & 0 deletions examples/grid-lite/components-react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useState, useRef } from 'react';
import {
type GridInstance,
type GridRefHandle,
type GridOptions,
Grid,
Caption,
Description
} from '@highcharts/grid-lite-react';

function App() {
// const grid = useRef<GridRefHandle<GridOptions> | null>(null);
const [description, setDescription] = useState<string>('Grid Description');
const onSetDescriptionClick = () => {
setDescription('This is a new description');
// console.info('(ref) grid:', grid.current?.grid);
};

const [options] = useState<GridOptions>({
dataTable: {
columns: {
name: ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
age: [23, 34, 45, 56, 67],
city: ['New York', 'Oslo', 'Paris', 'Tokyo', 'London'],
salary: [50000, 60000, 70000, 80000, 90000]
}
}
});

return (
<>
<Grid
options={options}
// gridRef={grid}
// callback={(grid) => console.info('(callback) grid:', grid)}
>
<Caption>Grid Caption</Caption>
<Description>{description}</Description>
{ /* <DataTable>
<Column>
<Header>Grid Header</Header>
<Cell>Grid Cell</Cell>
</Column>
</DataTable> */}
{/* <Pagination>Grid Pagination</Pagination> */}
</Grid>
<button onClick={onSetDescriptionClick}>Set new description</button>
</>
);
}

export default App;
26 changes: 26 additions & 0 deletions examples/grid-lite/components-react/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

#root {
width: 100%;
min-height: 100vh;
padding: 20px;
}

@media (prefers-color-scheme: dark) {
body {
background-color: #121212;
color: #ffffff;
}
}
11 changes: 11 additions & 0 deletions examples/grid-lite/components-react/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);

28 changes: 28 additions & 0 deletions examples/grid-lite/components-react/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "ES2020",
"lib": [
"DOM",
"ES2016",
"ES2017.Object"
],
"jsx": "react-jsx",
"module": "ES6",
"moduleResolution": "node",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitThis": true,
"noFallthroughCasesInSwitch": true,
"skipDefaultLibCheck": true,
"skipLibCheck": true,
"ignoreDeprecations": "5.0",
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

12 changes: 12 additions & 0 deletions examples/grid-lite/components-react/tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"types": ["node"]
},
"include": ["vite.config.ts"]
}

22 changes: 22 additions & 0 deletions examples/grid-lite/components-react/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));

export default defineConfig({
plugins: [react()],
resolve: {
alias: [
{
find: /^@highcharts\/grid-lite(\/.*)?$/,
replacement: resolve(__dirname, 'node_modules/@highcharts/grid-lite$1')
}
]
},
server: {
port: 3000
}
});

15 changes: 12 additions & 3 deletions packages/grid-lite-react/src/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@
*
*/

import { useMemo } from 'react';
import {
BaseGrid,
GridProps
GridProps,
getChildProps
} from '@highcharts/grid-shared-react';
import { merge } from '@highcharts/grid-lite/es-modules/Shared/Utilities.js';
import Grid from '@highcharts/grid-lite/es-modules/masters/grid-lite.src';
import '@highcharts/grid-lite/css/grid-lite.css';
import type { Options } from '@highcharts/grid-lite/es-modules/Grid/Core/Options';

export default function GridLite({ options, gridRef, callback }: GridProps<Options>) {
return <BaseGrid options={options} Grid={Grid} ref={gridRef} callback={callback} />;
export default function GridLite(props: GridProps<Options>) {
const { gridRef, children, options, ...gridProps } = props;
const gridOptions = useMemo(
() => merge(getChildProps(children), options ?? {}) as Options,
[children, options]
);

return <BaseGrid {...gridProps} options={gridOptions} Grid={Grid} ref={gridRef} />;
}
4 changes: 2 additions & 2 deletions packages/grid-lite-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ import GridLite from '@highcharts/grid-lite';

export { default as Grid } from './Grid';
export { default as GridLite } from './Grid';
export type { GridInstance } from '@highcharts/grid-shared-react';
export type { GridRefHandle } from '@highcharts/grid-shared-react';
export { Caption, Description } from '@highcharts/grid-shared-react';
export type { GridInstance, GridRefHandle, CaptionProps, DescriptionProps } from '@highcharts/grid-shared-react';
export type GridOptions = GridLite.Options;
15 changes: 12 additions & 3 deletions packages/grid-pro-react/src/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@
*
*/

import { useMemo } from 'react';
import {
BaseGrid,
GridProps
GridProps,
getChildProps
} from '@highcharts/grid-shared-react';
import { merge } from '@highcharts/grid-pro/es-modules/Shared/Utilities.js';
import Grid from '@highcharts/grid-pro/es-modules/masters/grid-pro.src';
import '@highcharts/grid-pro/css/grid-pro.css';
import type { Options } from '@highcharts/grid-pro/es-modules/Grid/Core/Options';

export default function GridPro({ options, gridRef, callback }: GridProps<Options>) {
return <BaseGrid options={options} Grid={Grid} ref={gridRef} callback={callback} />;
export default function GridPro(props: GridProps<Options>) {
const { gridRef, children, options, ...gridProps } = props;
const gridOptions = useMemo(
() => merge(getChildProps(children), options ?? {}) as Options,
[children, options]
);

return <BaseGrid {...gridProps} options={gridOptions} Grid={Grid} ref={gridRef} />;
}
4 changes: 2 additions & 2 deletions packages/grid-pro-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ import GridPro from '@highcharts/grid-pro';

export { default as Grid } from './Grid';
export { default as GridPro } from './Grid';
export type { GridInstance } from '@highcharts/grid-shared-react';
export type { GridRefHandle } from '@highcharts/grid-shared-react';
export { Caption, Description } from '@highcharts/grid-shared-react';
export type { GridInstance, GridRefHandle, CaptionProps, DescriptionProps } from '@highcharts/grid-shared-react';
export type GridOptions = GridPro.Options;
15 changes: 9 additions & 6 deletions packages/grid-shared-react/src/components/BaseGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*
*/

import { useRef, useImperativeHandle, forwardRef, ForwardedRef } from 'react';
import { useRef, useImperativeHandle, forwardRef, ForwardedRef, ReactNode } from 'react';
import {
useGrid,
GridType,
Expand All @@ -31,7 +31,11 @@ export interface GridProps<TOptions> {
/**
* Grid configuration options
*/
options: TOptions;
options?: TOptions;
/**
* Declarative option components (e.g. Caption) passed as children.
*/
children?: ReactNode;
/**
* Optional ref to access the grid instance
*/
Expand All @@ -45,11 +49,10 @@ export interface GridProps<TOptions> {
/**
* Props for BaseGrid component
*/
export interface BaseGridProps<TOptions> extends GridProps<TOptions> {
/**
* Grid instance (from @highcharts/grid-lite or @highcharts/grid-pro)
*/
export interface BaseGridProps<TOptions> {
options?: TOptions;
Grid: GridType<TOptions>;
callback?: (grid: GridInstance<TOptions>) => void;
}

export const BaseGrid = forwardRef(function BaseGrid<TOptions>(
Expand Down
32 changes: 32 additions & 0 deletions packages/grid-shared-react/src/components/BaseGridOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Grid React integration.
* Copyright (c) 2025, Highsoft
*
* A valid license is required for using this software.
* See highcharts.com/license
*
*/

/**
* Metadata attached to declarative option components rendered as BaseGrid children.
*/
export interface BaseGridOptions {
type: 'Grid_Option';
/**
* Dot-notation path of the Grid option (e.g. `caption`).
*/
gridOption: string;
/**
* Sub-option that receives string children (e.g. `text`).
*/
childOption?: string;
defaultOptions?: Record<string, unknown>;
isArrayType?: boolean;
}

/**
* A React component that maps JSX props to a Grid options path via `_GridReact`.
*/
export interface BaseGridOptionsComponent {
_GridReact: BaseGridOptions;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Grid React integration.
* Copyright (c) 2025, Highsoft
*
* A valid license is required for using this software.
* See highcharts.com/license
*
*/

import { ReactNode } from 'react';

export interface CaptionProps {
/**
* The custom CSS class name for the table caption.
*/
className?: string;
/**
* The HTML tag to use for the caption.
*/
htmlTag?: string;
children?: ReactNode;
}

export function Caption(_props: CaptionProps) {
return null;
}

Caption._GridReact = {
type: 'Grid_Option',
gridOption: 'caption',
childOption: 'text',
isArrayType: false
};
11 changes: 11 additions & 0 deletions packages/grid-shared-react/src/components/options/caption/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Grid React integration.
* Copyright (c) 2025, Highsoft
*
* A valid license is required for using this software.
* See highcharts.com/license
*
*/

export { Caption } from './Caption';
export type { CaptionProps } from './Caption';
Loading
Loading