Skip to content
Merged
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
140 changes: 115 additions & 25 deletions examples/grid-lite/components-react/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,136 @@ import {
type GridOptions,
Grid,
Caption,
Data,
DataTable,
ColumnDefaults,
Column,
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');
const grid = useRef<GridRefHandle<GridOptions> | null>(null);

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

// ==== 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]
});

// Data Table
// const dataTable = new DataTable({
// columns: {
// name: ['DATATABLE', 'Bob', 'Charlie', 'David', 'Eve'],
// age: [23, 34, 45, 56, 67],
// city: ['New York', 'Oslo', 'Paris', 'Tokyo', 'London'],
// salary: [50000, 60000, 70000, 80000, 90000]
// }
// });

// ==== 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 [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]
}
}
});
const onGridCallback = (grid: GridInstance<GridOptions>) => {
console.info('(callback) grid:', grid);
};

return (
<>
<Grid
options={options}
// options={options}
// gridRef={grid}
// callback={(grid) => console.info('(callback) grid:', grid)}
callback={onGridCallback}
>
<Caption>Grid Caption</Caption>
<Description>{description}</Description>
{ /* <DataTable>
<Column>
<Header>Grid Header</Header>
<Cell>Grid Cell</Cell>
</Column>
</DataTable> */}
<Data
// dataTable={dataTable}
columns={dataSource}
/>
<ColumnDefaults
dataType="string"
width="auto"
exportable
style={{ fontWeight: '400' }}
sortingEnabled
sortingOrderSequence={['asc', 'desc', null]}
filteringEnabled
filteringInline={true}
filteringCondition="contains"
filteringValue=""
headerClassName="hcg-default-header"
headerFormat="{id}"
cellClassName="hcg-default-cell"
cellFormat="{value}"
cellRowHeader={false}
/>
<Caption>Grid Caption v2.1</Caption>
<Column
headerFormat="#"
width={40}
cellValueGetter={function (this: { row: { index: number } }) {
return String(this.row.index + 1);
}}
/>
<Column
columnId="name"
className="hcg-name-column"
enabled
sortingEnabled
sortingOrder="asc"
sortingPriority={0}
// filteringEnabled
// filteringInline
// filteringCondition="contains"
headerClassName="hcg-name-header"
headerFormat="Name"
cellClassName="hcg-name-cell"
cellFormat="{value}"
/>
<Column
columnId="age"
dataType="number"
headerFormat="Age ({id})"
cellFormat="{value}"
/>
<Column
columnId="city"
width="20%"
headerFormatter={function () {
return `City: ${(this as { id?: string }).id ?? ''}`;
}}
/>
<Column
columnId="salary"
dataType="number"
headerFormat="Salary (USD)"
cellFormat="${value}"
/>
<Description>Grid Description</Description>
{/* <Pagination>Grid Pagination</Pagination> */}
</Grid>
<button onClick={onSetDescriptionClick}>Set new description</button>
<button onClick={onButtonClick}>Click me</button>
</>
);
}
Expand Down
8 changes: 8 additions & 0 deletions examples/grid-lite/components-react/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ export default defineConfig({
plugins: [react()],
resolve: {
alias: [
{
find: '@highcharts/grid-lite-react',
replacement: resolve(__dirname, '../../../packages/grid-lite-react/src/index.ts')
},
{
find: '@highcharts/grid-shared-react',
replacement: resolve(__dirname, '../../../packages/grid-shared-react/src/index.ts')
},
{
find: /^@highcharts\/grid-lite(\/.*)?$/,
replacement: resolve(__dirname, 'node_modules/@highcharts/grid-lite$1')
Expand Down
20 changes: 17 additions & 3 deletions packages/grid-lite-react/src/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,24 @@ import type { Options } from '@highcharts/grid-lite/es-modules/Grid/Core/Options

export default function GridLite(props: GridProps<Options>) {
const { gridRef, children, options, ...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 gridOptions = useMemo(
() => merge(getChildProps(children), options ?? {}) as Options,
[children, options]
() => merge(childOptions, options ?? {}) as Options,
[childOptions, options]
);

return <BaseGrid {...gridProps} options={gridOptions} Grid={Grid} ref={gridRef} />;
return (
<BaseGrid
key={columnKey}
{...gridProps}
options={gridOptions}
Grid={Grid}
ref={gridRef}
/>
);
}
19 changes: 17 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,21 @@ import GridLite from '@highcharts/grid-lite';

export { default as Grid } from './Grid';
export { default as GridLite } from './Grid';
export { Caption, Description } from '@highcharts/grid-shared-react';
export type { GridInstance, GridRefHandle, CaptionProps, DescriptionProps } from '@highcharts/grid-shared-react';
export { Caption, Data, ColumnDefaults, Column, Description } from '@highcharts/grid-shared-react';
export { DataTable, DataConnector } from '@highcharts/grid-lite';
export { merge } from '@highcharts/grid-lite/es-modules/Shared/Utilities.js';
export type {
GridInstance,
GridRefHandle,
CaptionProps,
DescriptionProps,
DataProps,
DataColumns,
DataColumnValue,
ColumnProps,
ColumnOptionsProps,
ColumnDataType,
ColumnSortingOrder,
CellValueGetterContext
} from '@highcharts/grid-shared-react';
export type GridOptions = GridLite.Options;
20 changes: 17 additions & 3 deletions packages/grid-pro-react/src/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,24 @@ import type { Options } from '@highcharts/grid-pro/es-modules/Grid/Core/Options'

export default function GridPro(props: GridProps<Options>) {
const { gridRef, children, options, ...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 gridOptions = useMemo(
() => merge(getChildProps(children), options ?? {}) as Options,
[children, options]
() => merge(childOptions, options ?? {}) as Options,
[childOptions, options]
);

return <BaseGrid {...gridProps} options={gridOptions} Grid={Grid} ref={gridRef} />;
return (
<BaseGrid
key={columnKey}
{...gridProps}
options={gridOptions}
Grid={Grid}
ref={gridRef}
/>
);
}
19 changes: 17 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,21 @@ import GridPro from '@highcharts/grid-pro';

export { default as Grid } from './Grid';
export { default as GridPro } from './Grid';
export { Caption, Description } from '@highcharts/grid-shared-react';
export type { GridInstance, GridRefHandle, CaptionProps, DescriptionProps } from '@highcharts/grid-shared-react';
export { Caption, Data, ColumnDefaults, Column, Description } from '@highcharts/grid-shared-react';
export { DataTable, DataConnector } from '@highcharts/grid-pro';
export { merge } from '@highcharts/grid-pro/es-modules/Shared/Utilities.js';
export type {
GridInstance,
GridRefHandle,
CaptionProps,
DescriptionProps,
DataProps,
DataColumns,
DataColumnValue,
ColumnProps,
ColumnOptionsProps,
ColumnDataType,
ColumnSortingOrder,
CellValueGetterContext
} from '@highcharts/grid-shared-react';
export type GridOptions = GridPro.Options;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Grid React integration.
* Copyright (c) 2025, Highsoft
*
* A valid license is required for using this software.
* See highcharts.com/license
*
*/

import type { ColumnProps } from './columnProps';

export function Column(_props: ColumnProps) {
return null;
}

Column._GridReact = {
type: 'Grid_Option',
gridOption: 'columns',
isArrayType: true
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Grid React integration.
* Copyright (c) 2025, Highsoft
*
* A valid license is required for using this software.
* See highcharts.com/license
*
*/

import type { ColumnOptionsProps } from './columnProps';

export function ColumnDefaults(_props: ColumnOptionsProps) {
return null;
}

ColumnDefaults._GridReact = {
type: 'Grid_Option',
gridOption: 'columnDefaults'
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Grid React integration.
* Copyright (c) 2025, Highsoft
*
* A valid license is required for using this software.
* See highcharts.com/license
*
*/

export type ColumnDataType = 'string' | 'number' | 'boolean' | 'datetime';

export type ColumnSortingOrder = 'asc' | 'desc' | null;

/**
* `this` context passed to `cellValueGetter` by Grid Core.
*/
export interface CellValueGetterContext {
row: {
index: number;
};
}

/**
* Shared column options (`columnDefaults` and per-column overrides).
*/
export interface ColumnOptionsProps {
dataType?: ColumnDataType;
width?: number | string;
sortingEnabled?: boolean;
sortingOrder?: ColumnSortingOrder;
sortingPriority?: number;
sortingOrderSequence?: ColumnSortingOrder[];
sortingCompare?: (a: unknown, b: unknown) => number;
filteringEnabled?: boolean;
filteringInline?: boolean;
filteringCondition?: string;
filteringValue?: string | number | boolean | null;
headerClassName?: string;
headerFormat?: string;
headerFormatter?: (this: unknown) => string;
headerStyle?: unknown;
cellRowHeader?: boolean;
cellClassName?: string;
cellFormat?: string;
cellFormatter?: (this: unknown) => string;
/**
* Custom cell value resolver. `this` is the Grid table cell (`row.index`
* is the row index in the presentation data).
*/
cellValueGetter?: (this: CellValueGetterContext) => unknown;
cellContextMenu?: {
enabled?: boolean;
items?: unknown[];
};
cellStyle?: unknown;
style?: unknown;
exportable?: boolean;
}

export interface ColumnProps extends ColumnOptionsProps {
/**
* HTML `id` attribute for styling hooks. Not passed to Grid options.
*/
id?: string;
/**
* References the column to configure (data field id). Maps header, cells,
* sorting, filtering, etc. to Grid Core column options.
*
* Becomes `options.columns[].id` in Grid Core (same identifier).
*/
columnId?: string;
className?: string;
enabled?: boolean;
}
Loading
Loading