diff --git a/browser/package-lock.json b/browser/package-lock.json
index 48ded16e3..a49e6e8b2 100644
--- a/browser/package-lock.json
+++ b/browser/package-lock.json
@@ -15,6 +15,8 @@
"classnames": "2.3.1",
"dompurify": "^3.3.0",
"file-saver": "1.3.8",
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-grid-lite": "^1.0.0-alpha.9",
"igniteui-react": "^19.4.0-rc.0",
"igniteui-react-charts": "19.3.0-beta.0",
"igniteui-react-core": "19.3.0-beta.0",
@@ -7958,6 +7960,36 @@
"igniteui-trial-watermark": "^1.0.3"
}
},
+ "node_modules/igniteui-grid-lite": {
+ "version": "1.0.0-alpha.9",
+ "resolved": "https://registry.npmjs.org/igniteui-grid-lite/-/igniteui-grid-lite-1.0.0-alpha.9.tgz",
+ "integrity": "sha512-LxyUDHf/lTTbAAupup8HovSKsy1qgTUp4btrWVRQDFq2HI2s75UroplNGSX1yLfy3VCMEf8xY0sciM2tyFgzQQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@lit-labs/virtualizer": "~2.1.0",
+ "@lit/context": "~1.1.5",
+ "igniteui-webcomponents": "~6.1.0",
+ "lit": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/igniteui-grid-lite/node_modules/igniteui-webcomponents": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/igniteui-webcomponents/-/igniteui-webcomponents-6.1.2.tgz",
+ "integrity": "sha512-q3a3Q28xzRwDBmfDprY0PsN9cs5xgqOJigXWWmbWAfcMgPg5dIrPyMDV6Aj6GD7u1RgPeoZmTP/pz9gTWNhHJA==",
+ "license": "SEE LICENSE IN LICENSE",
+ "dependencies": {
+ "@floating-ui/dom": "^1.7.0",
+ "@lit-labs/virtualizer": "^2.1.0",
+ "@lit/context": "^1.1.0",
+ "lit": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=20"
+ }
+ },
"node_modules/igniteui-react": {
"version": "19.4.0-rc.0",
"resolved": "https://registry.npmjs.org/igniteui-react/-/igniteui-react-19.4.0-rc.0.tgz",
diff --git a/browser/package.json b/browser/package.json
index 92533c38b..cfb696e13 100644
--- a/browser/package.json
+++ b/browser/package.json
@@ -23,6 +23,8 @@
"classnames": "2.3.1",
"dompurify": "^3.3.0",
"file-saver": "1.3.8",
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-grid-lite": "^1.0.0-alpha.9",
"igniteui-react": "^19.4.0-rc.0",
"igniteui-react-charts": "19.3.0-beta.0",
"igniteui-react-core": "19.3.0-beta.0",
diff --git a/browser/public/meta.json b/browser/public/meta.json
index c071e16e1..042142baa 100644
--- a/browser/public/meta.json
+++ b/browser/public/meta.json
@@ -1 +1 @@
-{"version":"23.2.915","date":"2025-11-14 14:29:21","note":"this file is auto-generated"}
+{"version":"23.2.915","date":"2025-11-24 10:34:52","note":"this file is auto-generated"}
\ No newline at end of file
diff --git a/browser/src/navigation/SamplesBrowser.json b/browser/src/navigation/SamplesBrowser.json
index 55577491b..042142baa 100644
--- a/browser/src/navigation/SamplesBrowser.json
+++ b/browser/src/navigation/SamplesBrowser.json
@@ -1 +1 @@
-{"version":"23.2.915","date":"2025-11-14 15:39:37","note":"this file is auto-generated"}
+{"version":"23.2.915","date":"2025-11-24 10:34:52","note":"this file is auto-generated"}
\ No newline at end of file
diff --git a/browser/src/typedecls.d.ts b/browser/src/typedecls.d.ts
new file mode 100644
index 000000000..0423e4419
--- /dev/null
+++ b/browser/src/typedecls.d.ts
@@ -0,0 +1,12 @@
+/* tslint:disable */
+declare module JSX {
+ interface IntrinsicElements {
+ "igc-grid-lite": any;
+ "igc-avatar": any;
+ "igc-rating": any;
+ "igc-checkbox": any;
+ "igc-select": any;
+ "igc-select-item": any;
+ }
+ }
+ /* tslint:enable */
\ No newline at end of file
diff --git a/samples/charts/data-chart/user-annotation-layer/ReadMe.md b/samples/charts/data-chart/user-annotation-layer/ReadMe.md
index 311717f82..6560b02b4 100644
--- a/samples/charts/data-chart/user-annotation-layer/ReadMe.md
+++ b/samples/charts/data-chart/user-annotation-layer/ReadMe.md
@@ -1,7 +1,7 @@
-This folder contains implementation of React application with example of Actions Built In Data Chart feature using [Toolbar](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+This folder contains implementation of React application with example of User Annotation Layer feature using [Data Chart](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
@@ -12,10 +12,10 @@ This folder contains implementation of React application with example of Actions
-
+
-
+
@@ -34,7 +34,7 @@ Follow these instructions to run this example:
git clone https://github.com/IgniteUI/igniteui-react-examples.git
git checkout master
cd ./igniteui-react-examples
-cd ./samples/charts/toolbar/actions-built-in-data-chart
+cd ./samples/charts/data-chart/user-annotation-layer
```
open above folder in VS Code or type:
diff --git a/samples/grids/grid-lite/column-config-basic/.eslintrc.js b/samples/grids/grid-lite/column-config-basic/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-basic/ReadMe.md b/samples/grids/grid-lite/column-config-basic/ReadMe.md
new file mode 100644
index 000000000..d8e264b92
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Column Config Basic feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/column-config-basic
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/column-config-basic/index.html b/samples/grids/grid-lite/column-config-basic/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-basic/package.json b/samples/grids/grid-lite/column-config-basic/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/column-config-basic/sandbox.config.json b/samples/grids/grid-lite/column-config-basic/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-basic/src/GridLiteDataService.ts b/samples/grids/grid-lite/column-config-basic/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-basic/src/index.css b/samples/grids/grid-lite/column-config-basic/src/index.css
new file mode 100644
index 000000000..4a470efda
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/src/index.css
@@ -0,0 +1,9 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+ --ig-size: 2;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-basic/src/index.tsx b/samples/grids/grid-lite/column-config-basic/src/index.tsx
new file mode 100644
index 000000000..2aadabba0
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/src/index.tsx
@@ -0,0 +1,99 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, ProductInfo } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import {
+ defineComponents,
+ IgcRatingComponent
+} from 'igniteui-webcomponents';
+
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+defineComponents(IgcRatingComponent);
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private formatter: Intl.NumberFormat;
+ private gridRef: React.RefObject;
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.formatter = new Intl.NumberFormat('en-EN', {
+ style: 'currency',
+ currency: 'EUR'
+ });
+ this.gridRef = React.createRef();
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: ProductInfo[] = this.dataService.generateProducts(50);
+
+ const columns = [
+ {
+ key: 'name',
+ headerText: 'Product Name'
+ },
+ {
+ key: 'price',
+ headerText: 'Price',
+ type: 'number',
+ cellTemplate: (params: any) => {
+ const span = document.createElement('span');
+ span.textContent = this.formatter.format(params.value);
+ return span;
+ }
+ },
+ {
+ key: 'sold',
+ type: 'number',
+ headerText: 'Units sold'
+ },
+ {
+ key: 'total',
+ headerText: 'Total sold',
+ cellTemplate: (params: any) => {
+ const span = document.createElement('span');
+ span.textContent = this.formatter.format(params.value);
+ return span;
+ }
+ },
+ {
+ key: 'rating',
+ type: 'number',
+ headerText: 'Customer rating',
+ cellTemplate: (params: any) => {
+ const rating = document.createElement('igc-rating');
+ rating.setAttribute('readonly', '');
+ rating.setAttribute('step', '0.01');
+ rating.setAttribute('value', params.value.toString());
+ return rating;
+ }
+ }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+ }
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/column-config-basic/tsconfig.json b/samples/grids/grid-lite/column-config-basic/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/column-config-basic/vite.config.js b/samples/grids/grid-lite/column-config-basic/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-basic/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-dynamic/.eslintrc.js b/samples/grids/grid-lite/column-config-dynamic/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-dynamic/ReadMe.md b/samples/grids/grid-lite/column-config-dynamic/ReadMe.md
new file mode 100644
index 000000000..9a174f74b
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Column Config Dynamic feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/column-config-dynamic
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/column-config-dynamic/index.html b/samples/grids/grid-lite/column-config-dynamic/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-dynamic/package.json b/samples/grids/grid-lite/column-config-dynamic/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/column-config-dynamic/sandbox.config.json b/samples/grids/grid-lite/column-config-dynamic/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-dynamic/src/GridLiteDataService.ts b/samples/grids/grid-lite/column-config-dynamic/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-dynamic/src/index.css b/samples/grids/grid-lite/column-config-dynamic/src/index.css
new file mode 100644
index 000000000..41b27aca7
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/src/index.css
@@ -0,0 +1,38 @@
+#panel {
+ margin: 1rem 0;
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.config-key {
+ flex: 2 1 25% !important;
+ font-weight: bold;
+}
+
+.config {
+ display: flex;
+ flex-flow: row nowrap;
+ justify-content: space-evenly;
+ align-items: center;
+ gap: 0.75rem;
+}
+
+.config * {
+ flex: 1;
+}
+
+igc-dropdown-item {
+ padding: 0.5rem 1rem;
+}
+
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+ --ig-size: 2;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-dynamic/src/index.tsx b/samples/grids/grid-lite/column-config-dynamic/src/index.tsx
new file mode 100644
index 000000000..a146f4cc9
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/src/index.tsx
@@ -0,0 +1,142 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, ProductInfo } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import {
+ defineComponents,
+ IgcRatingComponent
+} from 'igniteui-webcomponents';
+
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+defineComponents(IgcRatingComponent);
+
+const formatter = new Intl.NumberFormat('en-EN', {
+ style: 'currency',
+ currency: 'EUR',
+});
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+ protected hasFormatters = true;
+ protected format = (params: any) => {
+ const span = document.createElement('span');
+ span.textContent = formatter.format(params.value);
+ return span;
+ };
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ this.toggleFormatters = this.toggleFormatters.bind(this);
+ this.toggleColumnProperty = this.toggleColumnProperty.bind(this);
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: ProductInfo[] = this.dataService.generateProducts(50);
+
+ const columns = [
+ {
+ key: 'id',
+ hidden: true,
+ headerText: 'ID'
+ },
+ {
+ key: 'name',
+ headerText: 'Product Name'
+ },
+ {
+ key: 'price',
+ headerText: 'Price',
+ type: 'number',
+ cellTemplate: this.format
+ },
+ {
+ key: 'sold',
+ type: 'number',
+ headerText: 'Units sold'
+ },
+ {
+ key: 'total',
+ headerText: 'Total sold',
+ cellTemplate: this.format
+ },
+ {
+ key: 'rating',
+ type: 'number',
+ headerText: 'Customer rating',
+ cellTemplate: (params: any) => {
+ const rating = document.createElement('igc-rating');
+ rating.setAttribute('readonly', '');
+ rating.setAttribute('step', '0.01');
+ rating.setAttribute('value', params.value.toString());
+ return rating;
+ }
+ }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+ }
+ }
+
+ toggleFormatters(checked: boolean) {
+ if (this.gridRef.current) {
+ this.gridRef.current.updateColumns(
+ ['price', 'total'].map((key) => ({
+ key,
+ cellTemplate: checked ? this.format : undefined,
+ }))
+ );
+ }
+ }
+
+ toggleColumnProperty(columnKey: string, property: string, value: boolean) {
+ if (this.gridRef.current) {
+ this.gridRef.current.updateColumns({ key: columnKey, [property]: value });
+ }
+ }
+
+ public render(): JSX.Element {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/column-config-dynamic/tsconfig.json b/samples/grids/grid-lite/column-config-dynamic/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/column-config-dynamic/vite.config.js b/samples/grids/grid-lite/column-config-dynamic/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-dynamic/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-headers/.eslintrc.js b/samples/grids/grid-lite/column-config-headers/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-headers/ReadMe copy.md b/samples/grids/grid-lite/column-config-headers/ReadMe copy.md
new file mode 100644
index 000000000..c3201cc22
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/ReadMe copy.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Toolbar Sample3 feature using [Grid](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid/toolbar-sample-3
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/column-config-headers/ReadMe.md b/samples/grids/grid-lite/column-config-headers/ReadMe.md
new file mode 100644
index 000000000..28e6b48b3
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Column Config Headers feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/column-config-headers
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/column-config-headers/index.html b/samples/grids/grid-lite/column-config-headers/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-headers/package.json b/samples/grids/grid-lite/column-config-headers/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/column-config-headers/sandbox.config.json b/samples/grids/grid-lite/column-config-headers/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-headers/src/GridLiteDataService.ts b/samples/grids/grid-lite/column-config-headers/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-headers/src/index.css b/samples/grids/grid-lite/column-config-headers/src/index.css
new file mode 100644
index 000000000..2079f4e88
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/src/index.css
@@ -0,0 +1,9 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+ --ig-size: 2;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/column-config-headers/src/index.tsx b/samples/grids/grid-lite/column-config-headers/src/index.tsx
new file mode 100644
index 000000000..76cd0ff18
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/src/index.tsx
@@ -0,0 +1,71 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, User } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: User[] = this.dataService.generateUsers(50);
+
+ const columns = [
+ {
+ key: 'id',
+ headerText: '🆔 ID',
+ width: '150px'
+ },
+ {
+ key: 'firstName',
+ headerText: '👤 First Name'
+ },
+ {
+ key: 'lastName',
+ headerText: '👤 Last Name'
+ },
+ {
+ key: 'age',
+ headerText: '🎂 Age',
+ type: 'number',
+ width: '100px'
+ },
+ {
+ key: 'email',
+ headerText: '📧 Email'
+ }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+ }
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/column-config-headers/tsconfig.json b/samples/grids/grid-lite/column-config-headers/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/column-config-headers/vite.config.js b/samples/grids/grid-lite/column-config-headers/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/column-config-headers/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/data-binding/.eslintrc.js b/samples/grids/grid-lite/data-binding/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/data-binding/ReadMe.md b/samples/grids/grid-lite/data-binding/ReadMe.md
new file mode 100644
index 000000000..ac7302ece
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Data Binding feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/data-binding
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/data-binding/index.html b/samples/grids/grid-lite/data-binding/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/data-binding/package.json b/samples/grids/grid-lite/data-binding/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/data-binding/sandbox.config.json b/samples/grids/grid-lite/data-binding/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/data-binding/src/GridLiteDataService.ts b/samples/grids/grid-lite/data-binding/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/data-binding/src/index.css b/samples/grids/grid-lite/data-binding/src/index.css
new file mode 100644
index 000000000..329ffb098
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/src/index.css
@@ -0,0 +1,34 @@
+.controls-wrapper {
+ margin-bottom: 1rem;
+ display: flex;
+ gap: 0.5rem;
+ align-items: center;
+}
+
+.sample-button {
+ padding: 0.5rem 1rem;
+ cursor: pointer;
+ background-color: #007bff;
+ color: white;
+ border: none;
+ border-radius: 4px;
+}
+
+.sample-button:hover {
+ background-color: #0056b3;
+}
+
+.record-count {
+ font-weight: bold;
+ margin-left: 1rem;
+}
+
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+ --ig-size: 2;
+}
diff --git a/samples/grids/grid-lite/data-binding/src/index.tsx b/samples/grids/grid-lite/data-binding/src/index.tsx
new file mode 100644
index 000000000..9f2e6e052
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/src/index.tsx
@@ -0,0 +1,73 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import {
+ defineComponents,
+ IgcButtonComponent
+} from 'igniteui-webcomponents';
+
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+defineComponents(IgcButtonComponent);
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+ private showingProducts = true;
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ this.switchData = this.switchData.bind(this);
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ this.gridRef.current.data = this.dataService.generateProducts(50);
+
+ window.addEventListener('error', (e) => {
+ if (e.message === 'ResizeObserver loop completed with undelivered notifications.') {
+ e.stopImmediatePropagation();
+ }
+ });
+ }
+ }
+
+ private switchData() {
+ if (this.gridRef.current) {
+ this.gridRef.current.columns = [];
+
+ if (this.showingProducts) {
+ this.gridRef.current.data = this.dataService.generateUsers(50);
+ this.showingProducts = false;
+ } else {
+ this.gridRef.current.data = this.dataService.generateProducts(50);
+ this.showingProducts = true;
+ }
+ }
+ }
+
+ public render(): JSX.Element {
+ return (
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/data-binding/tsconfig.json b/samples/grids/grid-lite/data-binding/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/data-binding/vite.config.js b/samples/grids/grid-lite/data-binding/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/data-binding/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-events/.eslintrc.js b/samples/grids/grid-lite/filtering-config-events/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-events/ReadMe.md b/samples/grids/grid-lite/filtering-config-events/ReadMe.md
new file mode 100644
index 000000000..851b905f4
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Filtering Config Events feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/filtering-config-events
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/filtering-config-events/index.html b/samples/grids/grid-lite/filtering-config-events/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-events/package.json b/samples/grids/grid-lite/filtering-config-events/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/filtering-config-events/sandbox.config.json b/samples/grids/grid-lite/filtering-config-events/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-events/src/GridLiteDataService.ts b/samples/grids/grid-lite/filtering-config-events/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-events/src/index.css b/samples/grids/grid-lite/filtering-config-events/src/index.css
new file mode 100644
index 000000000..6cf15a462
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/src/index.css
@@ -0,0 +1,27 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: calc(100% - 10rem);
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+}
+
+.log {
+ margin-top: 0.5rem;
+ border: 1px solid #ccc;
+ padding: 1rem;
+ min-height: 1rem;
+ font-size: 0.75rem;
+ max-height: 5rem;
+ overflow-y: auto;
+}
+
+.log p {
+ margin: 0.25rem 0;
+}
+
+.log code {
+ font-family: monospace;
+ font-size: 0.75rem;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-events/src/index.tsx b/samples/grids/grid-lite/filtering-config-events/src/index.tsx
new file mode 100644
index 000000000..017e0332e
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/src/index.tsx
@@ -0,0 +1,86 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, User } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+ private logRef: React.RefObject;
+ private log: string[] = [];
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ this.logRef = React.createRef();
+ this.state = { logContent: '' };
+ }
+
+ get time() {
+ return `[${new Date().toLocaleTimeString()}]`;
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: User[] = this.dataService.generateUsers(50);
+
+ const columns = [
+ { key: 'firstName', headerText: 'First name', filter: true },
+ { key: 'lastName', headerText: 'Last name', filter: true },
+ { key: 'age', headerText: 'Age', filter: true, type: 'number' },
+ { key: 'email', headerText: 'Email', filter: true }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+
+ // Listen to filter events
+ this.gridRef.current.addEventListener('filtering', (e: any) => {
+ const { expressions, type } = e.detail;
+ this.updateLog(`${this.time} :: Event \`${e.type}\` :: Filter operation of type '${type}' for column '${expressions[0].key}'`);
+ });
+ this.gridRef.current.addEventListener('filtered', (e: any) => {
+ this.updateLog(`${this.time} :: Event \`${e.type}\` for column '${e.detail.key}'`);
+ });
+ }
+ }
+
+ private updateLog(message: string) {
+ if (this.log.length > 10) {
+ this.log.shift();
+ }
+ this.log.push(message);
+ this.renderLog();
+ }
+
+ private renderLog() {
+ const logContent = this.log
+ .map(entry => `${entry}
`)
+ .join('');
+ this.setState({ logContent });
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/filtering-config-events/tsconfig.json b/samples/grids/grid-lite/filtering-config-events/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/filtering-config-events/vite.config.js b/samples/grids/grid-lite/filtering-config-events/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-events/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-remote/.eslintrc.js b/samples/grids/grid-lite/filtering-config-remote/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-remote/ReadMe.md b/samples/grids/grid-lite/filtering-config-remote/ReadMe.md
new file mode 100644
index 000000000..609cf70fa
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Filtering Config Remote feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/filtering-config-remote
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/filtering-config-remote/index.html b/samples/grids/grid-lite/filtering-config-remote/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-remote/package.json b/samples/grids/grid-lite/filtering-config-remote/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/filtering-config-remote/sandbox.config.json b/samples/grids/grid-lite/filtering-config-remote/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-remote/src/GridLiteDataService.ts b/samples/grids/grid-lite/filtering-config-remote/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-remote/src/index.css b/samples/grids/grid-lite/filtering-config-remote/src/index.css
new file mode 100644
index 000000000..a04c50eec
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/src/index.css
@@ -0,0 +1,30 @@
+p {
+ border: 1px solid var(--border);
+ padding: 1rem;
+ min-height: 1rem;
+ font-size: 0.75rem;
+}
+
+code {
+ background-color: rgba(0, 0, 0, 0.05);
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 4px;
+ padding: 0.125rem 0.375rem;
+ font-family: 'Courier New', Courier, monospace;
+ font-size: 0.875em;
+ color: #222222;
+ display: inline-block;
+ width: 100%;
+ min-height: 2em;
+ box-sizing: border-box;
+}
+
+.grid-lite-wrapper {
+ width: 100%;
+ height: calc(100% - 1rem);
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+ --ig-size: 2;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config-remote/src/index.tsx b/samples/grids/grid-lite/filtering-config-remote/src/index.tsx
new file mode 100644
index 000000000..590f05b85
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/src/index.tsx
@@ -0,0 +1,100 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, User } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+
+function groupBy(arr: T[], key: keyof T) {
+ const out: Record = {};
+ for (const each of arr) {
+ const slot = each[key] as string;
+ if (!out[slot]) {
+ out[slot] = [];
+ }
+ out[slot].push(each);
+ }
+ return out;
+}
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+ private allData: User[] = [];
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ this.allData = this.dataService.generateUsers(100);
+ this.state = { queryString: '' };
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const columns = [
+ { key: 'firstName', headerText: 'First name', filter: true },
+ { key: 'lastName', headerText: 'Last name', filter: true },
+ { key: 'age', headerText: 'Age', filter: true, type: 'number' },
+ { key: 'email', headerText: 'Email' }
+ ];
+
+ const config = {
+ filter: async ({ data, grid }: any) => {
+ this.buildUri(grid.filterExpressions);
+ await new Promise((resolve) => setTimeout(resolve, 250));
+ return data;
+ },
+ };
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = this.allData;
+ this.gridRef.current.dataPipelineConfiguration = config;
+ }
+ }
+
+ protected mapExpressions(arr: any[]) {
+ return arr
+ .map(({ searchTerm, criteria, condition }: any, idx: number) => {
+ const c = condition;
+ return idx < 1
+ ? `${c.name}("${searchTerm}")`
+ : `${criteria?.toUpperCase()} ${c.name}("${searchTerm}")`;
+ })
+ .join(' ');
+ }
+
+ protected buildUri(state: any[]) {
+ const out: string[] = [];
+ const qs = groupBy(state, 'key');
+ for (const [key, exprs] of Object.entries(qs)) {
+ out.push(`${key}(${this.mapExpressions(exprs)})`);
+ }
+ this.setState({ queryString: `GET: /data?filter=${out.join('&')}` });
+ }
+
+ public render(): JSX.Element {
+ return (
+
+
+
+ {this.state.queryString}
+
+
+
+
+
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/filtering-config-remote/tsconfig.json b/samples/grids/grid-lite/filtering-config-remote/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/filtering-config-remote/vite.config.js b/samples/grids/grid-lite/filtering-config-remote/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config-remote/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config/.eslintrc.js b/samples/grids/grid-lite/filtering-config/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config/ReadMe.md b/samples/grids/grid-lite/filtering-config/ReadMe.md
new file mode 100644
index 000000000..7606d807a
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Filtering Config feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/filtering-config
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/filtering-config/index.html b/samples/grids/grid-lite/filtering-config/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config/package.json b/samples/grids/grid-lite/filtering-config/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/filtering-config/sandbox.config.json b/samples/grids/grid-lite/filtering-config/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config/src/GridLiteDataService.ts b/samples/grids/grid-lite/filtering-config/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config/src/index.css b/samples/grids/grid-lite/filtering-config/src/index.css
new file mode 100644
index 000000000..2079f4e88
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/src/index.css
@@ -0,0 +1,9 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+ --ig-size: 2;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/filtering-config/src/index.tsx b/samples/grids/grid-lite/filtering-config/src/index.tsx
new file mode 100644
index 000000000..d4ad26d14
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/src/index.tsx
@@ -0,0 +1,83 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, User } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import {
+ defineComponents,
+ IgcCheckboxComponent
+} from 'igniteui-webcomponents';
+
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+defineComponents(IgcCheckboxComponent);
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: User[] = this.dataService.generateUsers(50);
+
+ const columns = [
+ {
+ key: 'firstName',
+ headerText: 'First name',
+ filter: true
+ },
+ {
+ key: 'lastName',
+ headerText: 'Last name',
+ filter: true
+ },
+ {
+ key: 'age',
+ headerText: 'Age',
+ filter: true,
+ type: 'number'
+ },
+ {
+ key: 'active',
+ headerText: 'Active',
+ type: 'boolean',
+ filter: true,
+ cellTemplate: (params: any) => {
+ const checkbox = document.createElement('igc-checkbox');
+ if (params.value) {
+ checkbox.setAttribute('checked', '');
+ }
+ return checkbox;
+ }
+ }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+ }
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/filtering-config/tsconfig.json b/samples/grids/grid-lite/filtering-config/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/filtering-config/vite.config.js b/samples/grids/grid-lite/filtering-config/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/filtering-config/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/overview/.eslintrc.js b/samples/grids/grid-lite/overview/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/overview/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/overview/ReadMe.md b/samples/grids/grid-lite/overview/ReadMe.md
new file mode 100644
index 000000000..9d3f5fcf4
--- /dev/null
+++ b/samples/grids/grid-lite/overview/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Overview feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/overview
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/overview/index.html b/samples/grids/grid-lite/overview/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/overview/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/overview/package.json b/samples/grids/grid-lite/overview/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/overview/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/overview/sandbox.config.json b/samples/grids/grid-lite/overview/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/overview/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/overview/src/GridLiteDataService.ts b/samples/grids/grid-lite/overview/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/overview/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/overview/src/index.css b/samples/grids/grid-lite/overview/src/index.css
new file mode 100644
index 000000000..651829746
--- /dev/null
+++ b/samples/grids/grid-lite/overview/src/index.css
@@ -0,0 +1,9 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+igc-grid-lite {
+ min-height: 75vh;
+ --ig-size: 1;
+}
diff --git a/samples/grids/grid-lite/overview/src/index.tsx b/samples/grids/grid-lite/overview/src/index.tsx
new file mode 100644
index 000000000..5e3a342f4
--- /dev/null
+++ b/samples/grids/grid-lite/overview/src/index.tsx
@@ -0,0 +1,151 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, User } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import {
+ defineComponents,
+ IgcRatingComponent,
+ IgcCheckboxComponent,
+ IgcSelectComponent,
+ IgcAvatarComponent
+} from 'igniteui-webcomponents';
+
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+defineComponents(
+ IgcAvatarComponent,
+ IgcRatingComponent,
+ IgcCheckboxComponent,
+ IgcSelectComponent
+);
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private choices = ['Low', 'Standard', 'High'];
+ private gridRef: React.RefObject;
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: User[] = this.dataService.generateUsers(1000);
+
+ const columns = [
+ {
+ key: 'avatar',
+ headerText: 'Avatar',
+ cellTemplate: (params: any) => {
+ const cell = document.createElement('igc-avatar');
+ cell.setAttribute('shape', 'circle');
+ cell.setAttribute('alt', 'User avatar');
+ cell.setAttribute('src', params.value);
+ return cell;
+ }
+ },
+ {
+ key: 'firstName',
+ headerText: 'First name',
+ sort: true,
+ filter: true,
+ resizable: true
+ },
+ {
+ key: 'lastName',
+ headerText: 'Last name',
+ sort: true,
+ filter: true,
+ resizable: true
+ },
+ {
+ key: 'email',
+ headerText: 'Email Address'
+ },
+ {
+ key: 'priority',
+ headerText: 'Priority',
+ width: '12rem',
+ sort: {
+ comparer: (a: string, b: string) => this.choices.indexOf(a) - this.choices.indexOf(b),
+ caseSensitive: true
+ },
+ cellTemplate: (params: any) => {
+ const select = document.createElement('igc-select');
+ select.setAttribute('outlined', '');
+ select.setAttribute('flip', '');
+ select.setAttribute('value', params.value);
+
+ this.choices.forEach(choice => {
+ const item = document.createElement('igc-select-item');
+ item.setAttribute('value', choice);
+ item.textContent = choice;
+ select.appendChild(item);
+ });
+
+ return select;
+ }
+ },
+ {
+ key: 'satisfaction',
+ headerText: 'Satisfaction rating',
+ type: 'number',
+ sort: true,
+ filter: true,
+ cellTemplate: (params: any) => {
+ const rating = document.createElement('igc-rating');
+ rating.setAttribute('readonly', '');
+ rating.setAttribute('value', params.value.toString());
+ return rating;
+ }
+ },
+ {
+ key: 'registeredAt',
+ headerText: 'Registered @',
+ sort: true,
+ cellTemplate: (params: any) => {
+ const span = document.createElement('span');
+ span.textContent = params.value.toLocaleString();
+ return span;
+ }
+ },
+ {
+ key: 'active',
+ type: 'boolean',
+ headerText: 'Active',
+ cellTemplate: (params: any) => {
+ const checkbox = document.createElement('igc-checkbox');
+ if (params.value) {
+ checkbox.setAttribute('checked', '');
+ }
+ return checkbox;
+ }
+ }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+ }
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/overview/tsconfig.json b/samples/grids/grid-lite/overview/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/overview/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/overview/vite.config.js b/samples/grids/grid-lite/overview/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/overview/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-events/.eslintrc.js b/samples/grids/grid-lite/sort-config-events/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-events/ReadMe copy.md b/samples/grids/grid-lite/sort-config-events/ReadMe copy.md
new file mode 100644
index 000000000..c3201cc22
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/ReadMe copy.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Toolbar Sample3 feature using [Grid](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid/toolbar-sample-3
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/sort-config-events/ReadMe.md b/samples/grids/grid-lite/sort-config-events/ReadMe.md
new file mode 100644
index 000000000..3c055bc87
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Sort Config Events feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/sort-config-events
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/sort-config-events/index.html b/samples/grids/grid-lite/sort-config-events/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-events/package.json b/samples/grids/grid-lite/sort-config-events/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/sort-config-events/sandbox.config.json b/samples/grids/grid-lite/sort-config-events/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-events/src/GridLiteDataService.ts b/samples/grids/grid-lite/sort-config-events/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-events/src/index.css b/samples/grids/grid-lite/sort-config-events/src/index.css
new file mode 100644
index 000000000..6cf15a462
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/src/index.css
@@ -0,0 +1,27 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: calc(100% - 10rem);
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+}
+
+.log {
+ margin-top: 0.5rem;
+ border: 1px solid #ccc;
+ padding: 1rem;
+ min-height: 1rem;
+ font-size: 0.75rem;
+ max-height: 5rem;
+ overflow-y: auto;
+}
+
+.log p {
+ margin: 0.25rem 0;
+}
+
+.log code {
+ font-family: monospace;
+ font-size: 0.75rem;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-events/src/index.tsx b/samples/grids/grid-lite/sort-config-events/src/index.tsx
new file mode 100644
index 000000000..108d11390
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/src/index.tsx
@@ -0,0 +1,140 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, ProductInfo } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import {
+ defineComponents,
+ IgcRatingComponent
+} from 'igniteui-webcomponents';
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+defineComponents(IgcRatingComponent);
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+ private log: string[] = [];
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ this.state = { logContent: '' };
+ this.handleSorting = this.handleSorting.bind(this);
+ this.handleSorted = this.handleSorted.bind(this);
+ }
+
+ get timeStamp(): string {
+ return `[${new Date().toLocaleTimeString()}]`;
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: ProductInfo[] = this.dataService.generateProducts(100);
+
+ const columns = [
+ {
+ key: 'name',
+ headerText: 'Name',
+ sort: true
+ },
+ {
+ key: 'price',
+ type: 'number',
+ headerText: 'Price',
+ sort: true
+ },
+ {
+ key: 'rating',
+ type: 'number',
+ headerText: 'Rating',
+ sort: true,
+ cellTemplate: (params: any) => {
+ const rating = document.createElement('igc-rating');
+ rating.setAttribute('readonly', '');
+ rating.setAttribute('step', '0.01');
+ rating.setAttribute('value', params.value.toString());
+ return rating;
+ }
+ },
+ {
+ key: 'sold',
+ type: 'number',
+ headerText: 'Sold',
+ sort: true
+ },
+ {
+ key: 'total',
+ type: 'number',
+ headerText: 'Total',
+ sort: true
+ }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+
+ // Listen to sorting events
+ this.gridRef.current.addEventListener('sorting', this.handleSorting);
+ this.gridRef.current.addEventListener('sorted', this.handleSorted);
+ }
+ }
+
+ private updateLog(message: string) {
+ if (this.log.length > 10) {
+ this.log.shift();
+ }
+ this.log.push(message);
+ this.renderLog();
+ }
+
+ private renderLog() {
+ const logContent = this.log
+ .map(entry => `${entry}
`)
+ .join('');
+ this.setState({ logContent });
+ }
+
+ private handleSorting(event: any) {
+ const { detail, type } = event;
+ const allowedColumns = ['price', 'total', 'sold'];
+
+ if (!allowedColumns.includes(detail.key)) {
+ event.preventDefault();
+ this.updateLog(
+ `${this.timeStamp} :: Event '${type}' :: Sort operation was prevented for column '${detail.key}'`
+ );
+ } else {
+ this.updateLog(
+ `${this.timeStamp} :: Event '${type}' :: Column '${detail.key}' is being sorted with expression: ${JSON.stringify(detail)}`
+ );
+ }
+ }
+
+ private handleSorted(event: any) {
+ const { detail, type } = event;
+ this.updateLog(
+ `${this.timeStamp} :: Event '${type}' :: Column '${detail.key}' was sorted with expression: ${JSON.stringify(detail)}`
+ );
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/sort-config-events/tsconfig.json b/samples/grids/grid-lite/sort-config-events/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/sort-config-events/vite.config.js b/samples/grids/grid-lite/sort-config-events/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-events/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-grid/.eslintrc.js b/samples/grids/grid-lite/sort-config-grid/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-grid/ReadMe copy.md b/samples/grids/grid-lite/sort-config-grid/ReadMe copy.md
new file mode 100644
index 000000000..c3201cc22
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/ReadMe copy.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Toolbar Sample3 feature using [Grid](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid/toolbar-sample-3
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/sort-config-grid/ReadMe.md b/samples/grids/grid-lite/sort-config-grid/ReadMe.md
new file mode 100644
index 000000000..2ce7eb028
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Sort Config Grid feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/sort-config-grid
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/sort-config-grid/index.html b/samples/grids/grid-lite/sort-config-grid/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-grid/package.json b/samples/grids/grid-lite/sort-config-grid/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/sort-config-grid/sandbox.config.json b/samples/grids/grid-lite/sort-config-grid/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-grid/src/GridLiteDataService.ts b/samples/grids/grid-lite/sort-config-grid/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-grid/src/index.css b/samples/grids/grid-lite/sort-config-grid/src/index.css
new file mode 100644
index 000000000..0ab8179b9
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/src/index.css
@@ -0,0 +1,14 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+.config-panel {
+ margin: 1rem 0;
+ display: flex;
+ gap: 2rem;
+}
+
+igc-grid-lite {
+ height: 510px;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-grid/src/index.tsx b/samples/grids/grid-lite/sort-config-grid/src/index.tsx
new file mode 100644
index 000000000..2f86ec854
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/src/index.tsx
@@ -0,0 +1,113 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, ProductInfo } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import {
+ defineComponents,
+ IgcRatingComponent,
+ IgcSwitchComponent
+} from 'igniteui-webcomponents';
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+defineComponents(IgcRatingComponent, IgcSwitchComponent);
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+ private sortConfiguration: any = {
+ multiple: true,
+ triState: true
+ };
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ this.updateConfig = this.updateConfig.bind(this);
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: ProductInfo[] = this.dataService.generateProducts(100);
+
+ const columns = [
+ {
+ key: 'name',
+ headerText: 'Name',
+ sort: true
+ },
+ {
+ key: 'price',
+ type: 'number',
+ headerText: 'Price',
+ sort: true
+ },
+ {
+ key: 'rating',
+ type: 'number',
+ headerText: 'Rating',
+ sort: true,
+ cellTemplate: (params: any) => {
+ const rating = document.createElement('igc-rating');
+ rating.setAttribute('readonly', '');
+ rating.setAttribute('step', '0.01');
+ rating.setAttribute('value', params.value.toString());
+ return rating;
+ }
+ },
+ {
+ key: 'sold',
+ type: 'number',
+ headerText: 'Sold',
+ sort: true
+ },
+ {
+ key: 'total',
+ type: 'number',
+ headerText: 'Total',
+ sort: true
+ }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+ this.gridRef.current.sortConfiguration = this.sortConfiguration;
+ }
+ }
+
+ private updateConfig(prop: string, checked: boolean) {
+ this.sortConfiguration = { ...this.sortConfiguration, [prop]: checked };
+ if (this.gridRef.current) {
+ this.gridRef.current.sortConfiguration = this.sortConfiguration;
+ }
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/sort-config-grid/tsconfig.json b/samples/grids/grid-lite/sort-config-grid/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/sort-config-grid/vite.config.js b/samples/grids/grid-lite/sort-config-grid/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-grid/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-pipeline/.eslintrc.js b/samples/grids/grid-lite/sort-config-pipeline/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-pipeline/ReadMe.md b/samples/grids/grid-lite/sort-config-pipeline/ReadMe.md
new file mode 100644
index 000000000..299a9fe00
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Sort Config Pipeline feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/sort-config-pipeline
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/sort-config-pipeline/index.html b/samples/grids/grid-lite/sort-config-pipeline/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-pipeline/package.json b/samples/grids/grid-lite/sort-config-pipeline/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/sort-config-pipeline/sandbox.config.json b/samples/grids/grid-lite/sort-config-pipeline/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-pipeline/src/GridLiteDataService.ts b/samples/grids/grid-lite/sort-config-pipeline/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-pipeline/src/index.css b/samples/grids/grid-lite/sort-config-pipeline/src/index.css
new file mode 100644
index 000000000..3c9d8e570
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/src/index.css
@@ -0,0 +1,37 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+.grid-section {
+ position: relative;
+}
+
+igc-circular-progress {
+ visibility: hidden;
+ --diameter: 4rem;
+ background-color: rgba(255, 255, 255, 0.5);
+ position: absolute;
+ z-index: 2;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.in-operation {
+ visibility: visible;
+ pointer-events: all;
+ user-select: contain;
+}
+
+p {
+ border: 1px solid #ccc;
+ padding: 1rem;
+ min-height: 1rem;
+ font-size: 0.75rem;
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-pipeline/src/index.tsx b/samples/grids/grid-lite/sort-config-pipeline/src/index.tsx
new file mode 100644
index 000000000..09beead12
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/src/index.tsx
@@ -0,0 +1,135 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, ProductInfo } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import {
+ defineComponents,
+ IgcRatingComponent,
+ IgcCircularProgressComponent
+} from 'igniteui-webcomponents';
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+defineComponents(IgcRatingComponent, IgcCircularProgressComponent);
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+ private progressRef: React.RefObject;
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ this.progressRef = React.createRef();
+ this.state = { queryString: '' };
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: ProductInfo[] = this.dataService.generateProducts(100);
+
+ const columns = [
+ {
+ key: 'name',
+ headerText: 'Name',
+ sort: true
+ },
+ {
+ key: 'price',
+ type: 'number',
+ headerText: 'Price',
+ sort: true
+ },
+ {
+ key: 'rating',
+ type: 'number',
+ headerText: 'Rating',
+ sort: true,
+ cellTemplate: (params: any) => {
+ const rating = document.createElement('igc-rating');
+ rating.setAttribute('readonly', '');
+ rating.setAttribute('step', '0.01');
+ rating.setAttribute('value', params.value.toString());
+ return rating;
+ }
+ },
+ {
+ key: 'sold',
+ type: 'number',
+ headerText: 'Sold',
+ sort: true
+ },
+ {
+ key: 'total',
+ type: 'number',
+ headerText: 'Total',
+ sort: true
+ }
+ ];
+
+ const dataPipelineConfiguration = {
+ sort: async ({ data, grid }: any) => {
+ if (this.progressRef.current) {
+ this.progressRef.current.classList.add('in-operation');
+ }
+ const queryString = grid.sortExpressions.length
+ ? this.buildUri(grid.sortExpressions)
+ : '';
+ this.setState({ queryString });
+
+ await new Promise(resolve => setTimeout(resolve, 250));
+ if (this.progressRef.current) {
+ this.progressRef.current.classList.remove('in-operation');
+ }
+ return data;
+ }
+ };
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+ this.gridRef.current.dataPipelineConfiguration = dataPipelineConfiguration;
+ }
+ }
+
+ private buildUri(state: any[]): string {
+ const uri: string[] = [];
+ for (const expr of state) {
+ if (expr.direction === 'none') {
+ continue;
+ }
+ uri.push(
+ expr.direction === 'ascending'
+ ? `asc(${expr.key})`
+ : `desc(${expr.key})`
+ );
+ }
+ return `GET: /data?sort_by=${uri.join(',')}`;
+ }
+
+ public render(): JSX.Element {
+ return (
+
+
+
+
+
+
+ {this.state.queryString}
+
+
+
+
+
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/sort-config-pipeline/tsconfig.json b/samples/grids/grid-lite/sort-config-pipeline/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/sort-config-pipeline/vite.config.js b/samples/grids/grid-lite/sort-config-pipeline/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-pipeline/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-sample/.eslintrc.js b/samples/grids/grid-lite/sort-config-sample/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-sample/ReadMe.md b/samples/grids/grid-lite/sort-config-sample/ReadMe.md
new file mode 100644
index 000000000..9378f9196
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Sort Config Sample feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/sort-config-sample
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/sort-config-sample/index.html b/samples/grids/grid-lite/sort-config-sample/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-sample/package.json b/samples/grids/grid-lite/sort-config-sample/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/sort-config-sample/sandbox.config.json b/samples/grids/grid-lite/sort-config-sample/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-sample/src/GridLiteDataService.ts b/samples/grids/grid-lite/sort-config-sample/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-sample/src/index.css b/samples/grids/grid-lite/sort-config-sample/src/index.css
new file mode 100644
index 000000000..2079f4e88
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/src/index.css
@@ -0,0 +1,9 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+igc-grid-lite {
+ min-height: 65vh;
+ --ig-size: 2;
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/sort-config-sample/src/index.tsx b/samples/grids/grid-lite/sort-config-sample/src/index.tsx
new file mode 100644
index 000000000..c2953a766
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/src/index.tsx
@@ -0,0 +1,70 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, User } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: User[] = this.dataService.generateUsers(50);
+
+ const columns = [
+ {
+ key: 'firstName',
+ headerText: 'First name',
+ sort: true
+ },
+ {
+ key: 'lastName',
+ headerText: 'Last name',
+ sort: true
+ },
+ {
+ key: 'age',
+ headerText: 'Age',
+ sort: true,
+ type: 'number'
+ },
+ {
+ key: 'email',
+ headerText: 'Email',
+ sort: true
+ }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+ }
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/sort-config-sample/tsconfig.json b/samples/grids/grid-lite/sort-config-sample/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/sort-config-sample/vite.config.js b/samples/grids/grid-lite/sort-config-sample/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/sort-config-sample/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file
diff --git a/samples/grids/grid-lite/styling-custom-theme/.eslintrc.js b/samples/grids/grid-lite/styling-custom-theme/.eslintrc.js
new file mode 100644
index 000000000..7168b7144
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/.eslintrc.js
@@ -0,0 +1,78 @@
+// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
+module.exports = {
+ parser: "@typescript-eslint/parser", // Specifies the ESLint parser
+ parserOptions: {
+ ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ ecmaFeatures: {
+ jsx: true // Allows for the parsing of JSX
+ }
+ },
+ settings: {
+ react: {
+ version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
+ }
+ },
+ extends: [
+ "eslint:recommended",
+ "plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
+ "plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
+ ],
+ rules: {
+ // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-prototype-builtins": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ },
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {
+ "default-case": "off",
+ "jsx-a11y/alt-text": "off",
+ "jsx-a11y/iframe-has-title": "off",
+ "no-var": "off",
+ "no-undef": "off",
+ "no-unused-vars": "off",
+ "no-extend-native": "off",
+ "no-throw-literal": "off",
+ "no-useless-concat": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-spaces-and-tabs": 0,
+ "no-prototype-builtins": "off",
+ "prefer-const": "off",
+ "prefer-rest-params": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "@typescript-eslint/no-inferrable-types": "off",
+ "@typescript-eslint/no-useless-constructor": "off",
+ "@typescript-eslint/no-use-before-define": "off",
+ "@typescript-eslint/no-non-null-assertion": "off",
+ "@typescript-eslint/interface-name-prefix": "off",
+ "@typescript-eslint/prefer-namespace-keyword": "off",
+ "@typescript-eslint/explicit-function-return-type": "off",
+ "@typescript-eslint/explicit-module-boundary-types": "off"
+ }
+ }
+ ]
+ };
\ No newline at end of file
diff --git a/samples/grids/grid-lite/styling-custom-theme/ReadMe.md b/samples/grids/grid-lite/styling-custom-theme/ReadMe.md
new file mode 100644
index 000000000..625be1b94
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/ReadMe.md
@@ -0,0 +1,56 @@
+
+
+
+This folder contains implementation of React application with example of Styling Custom Theme feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Branches
+
+> **_NOTE:_** You should use [master](https://github.com/IgniteUI/igniteui-react-examples/tree/master) branch of this repository if you want to run samples on your computer. Use the [vnext](https://github.com/IgniteUI/igniteui-react-examples/tree/vnext) branch only when you want to contribute new samples to this repository.
+
+## Instructions
+
+Follow these instructions to run this example:
+
+
+```
+git clone https://github.com/IgniteUI/igniteui-react-examples.git
+git checkout master
+cd ./igniteui-react-examples
+cd ./samples/grids/grid-lite/styling-custom-theme
+```
+
+open above folder in VS Code or type:
+```
+code .
+```
+
+In terminal window, run:
+```
+npm install --legacy-peer-deps
+npm run-script start
+```
+
+Then open http://localhost:4200/ in your browser
+
+
+## Learn More
+
+To learn more about **Ignite UI for React** components, check out the [React documentation](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html).
diff --git a/samples/grids/grid-lite/styling-custom-theme/index.html b/samples/grids/grid-lite/styling-custom-theme/index.html
new file mode 100644
index 000000000..fd8d08d53
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/index.html
@@ -0,0 +1,12 @@
+
+
+
+ Sample | Ignite UI | React | infragistics
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/grids/grid-lite/styling-custom-theme/package.json b/samples/grids/grid-lite/styling-custom-theme/package.json
new file mode 100644
index 000000000..1fb4f5e31
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "example-ignite-ui-react",
+ "description": "This project provides example of using Ignite UI for React components",
+ "author": "Infragistics",
+ "version": "1.4.0",
+ "license": "",
+ "homepage": ".",
+ "private": true,
+ "scripts": {
+ "start": "vite --port 4200",
+ "build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
+ "preview": "vite preview",
+ "test": "vitest",
+ "lint": "eslint ./src/**/*.{ts,tsx}"
+ },
+ "dependencies": {
+ "igniteui-dockmanager": "^1.17.0",
+ "igniteui-react": "^19.3.0",
+ "igniteui-react-core": "19.3.0-beta.0",
+ "igniteui-react-grids": "^19.3.0",
+ "igniteui-webcomponents": "^6.3.0",
+ "lit-html": "^3.2.0",
+ "react": "^19.2.0",
+ "react-dom": "^19.2.0",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.2.0",
+ "@types/node": "^24.7.1",
+ "@types/react": "^18.0.24",
+ "@types/react-dom": "^18.0.8",
+ "@vitejs/plugin-react": "^5.0.4",
+ "@vitest/browser": "^3.2.4",
+ "eslint": "^8.33.0",
+ "eslint-config-react": "^1.1.7",
+ "eslint-plugin-react": "^7.20.0",
+ "typescript": "^4.8.4",
+ "vite": "^7.1.9",
+ "vitest": "^3.2.4",
+ "vitest-canvas-mock": "^0.3.3",
+ "worker-loader": "^3.0.8"
+ },
+ "browserslist": [
+ ">0.2%",
+ "not dead",
+ "not ie <= 11",
+ "not op_mini all"
+ ]
+}
diff --git a/samples/grids/grid-lite/styling-custom-theme/sandbox.config.json b/samples/grids/grid-lite/styling-custom-theme/sandbox.config.json
new file mode 100644
index 000000000..07f53508e
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/sandbox.config.json
@@ -0,0 +1,5 @@
+{
+ "infiniteLoopProtection": false,
+ "hardReloadOnChange": false,
+ "view": "browser"
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/styling-custom-theme/src/GridLiteDataService.ts b/samples/grids/grid-lite/styling-custom-theme/src/GridLiteDataService.ts
new file mode 100644
index 000000000..aa34be2d5
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/src/GridLiteDataService.ts
@@ -0,0 +1,122 @@
+export type UserSimple = {
+ id: string;
+ username: string;
+ email: string;
+ subscribed: boolean;
+};
+
+export type ProductInfo = {
+ id: string;
+ name: string;
+ price: number;
+ sold: number;
+ rating: number;
+ total: number;
+};
+
+export type User = {
+ id: string;
+ firstName: string;
+ lastName: string;
+ age: number;
+ email: string;
+ avatar: string;
+ active: boolean;
+ priority: 'Low' | 'Standard' | 'High';
+ satisfaction: number;
+ registeredAt: Date;
+};
+
+export class GridLiteDataService {
+ private counter = 0;
+
+ private firstNames = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana', 'Eve', 'Frank', 'Grace', 'Henry',
+ 'Ivy', 'Jack', 'Kate', 'Liam', 'Mia', 'Noah', 'Olivia', 'Peter', 'Quinn', 'Rachel'];
+ private lastNames = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Garcia', 'Miller', 'Davis',
+ 'Rodriguez', 'Martinez', 'Wilson', 'Anderson', 'Taylor', 'Thomas', 'Moore', 'Jackson', 'White', 'Harris'];
+ private productNames = ['Widget', 'Gadget', 'Doohickey', 'Thingamajig', 'Gizmo', 'Contraption',
+ 'Device', 'Tool', 'Apparatus', 'Instrument', 'Machine', 'Equipment'];
+ private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
+
+ private randomInt(min: number, max: number): number {
+ return Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ private randomFloat(min: number, max: number, precision = 2): number {
+ const array = new Uint32Array(1);
+ window.crypto.getRandomValues(array);
+ const random01 = array[0] / 2 ** 32;
+ return parseFloat((random01 * (max - min) + min).toFixed(precision));
+ }
+
+ private randomElement(array: T[]): T {
+ return array[this.randomInt(0, array.length - 1)];
+ }
+
+ private randomBoolean(): boolean {
+ const array = new Uint8Array(1);
+ window.crypto.getRandomValues(array);
+ return (array[0] & 1) === 0;
+ }
+
+ private generateId(): string {
+ return `${Date.now()}-${this.counter++}-${this.randomInt(1000, 9999)}`;
+ }
+
+ createProductInfo(): ProductInfo {
+ const price = this.randomFloat(50, 500, 2);
+ const sold = this.randomInt(10, 100);
+ const total = parseFloat((price * sold).toFixed(2));
+
+ return {
+ price,
+ sold,
+ total,
+ id: this.generateId(),
+ name: `${this.randomElement(this.productNames)} ${this.randomElement(['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'])}`,
+ rating: this.randomFloat(0, 5, 1)
+ };
+ }
+
+ createUserSimple(): UserSimple {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ return {
+ id: this.generateId(),
+ username: `${firstName.toLowerCase()}.${lastName.toLowerCase()}${this.randomInt(1, 99)}`,
+ email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`,
+ subscribed: this.randomBoolean()
+ };
+ }
+
+ createUser(): User {
+ const firstName = this.randomElement(this.firstNames);
+ const lastName = this.randomElement(this.lastNames);
+ const email = `${firstName.toLowerCase()}.${lastName.toLowerCase()}@example.com`;
+
+ return {
+ id: this.generateId(),
+ firstName,
+ lastName,
+ age: this.randomInt(18, 90),
+ email,
+ avatar: `https://i.pravatar.cc/150?img=${this.randomInt(1, 70)}`,
+ active: this.randomBoolean(),
+ priority: this.randomElement(this.priorities),
+ satisfaction: this.randomInt(0, 5),
+ registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
+ };
+ }
+
+ generateUsers(count: number): User[] {
+ return Array.from({ length: count }, () => this.createUser());
+ }
+
+ generateProducts(count: number): ProductInfo[] {
+ return Array.from({ length: count }, () => this.createProductInfo());
+ }
+
+ generateSimpleUsers(count: number): UserSimple[] {
+ return Array.from({ length: count }, () => this.createUserSimple());
+ }
+}
\ No newline at end of file
diff --git a/samples/grids/grid-lite/styling-custom-theme/src/index.css b/samples/grids/grid-lite/styling-custom-theme/src/index.css
new file mode 100644
index 000000000..5532f1303
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/src/index.css
@@ -0,0 +1,405 @@
+.grid-lite-wrapper {
+ width: 100%;
+ height: 100%;
+}
+
+.custom-styled {
+ --content-background: hsla(var(--ig-gray-50), var(--ig-gray-a));
+ --content-text-color: var(--ig-gray-50-contrast);
+ --header-background: hsla(var(--ig-surface-500), var(--ig-surface-a));
+ --header-text-color: var(--ig-surface-500-contrast);
+ --header-border-width: 0.0625rem;
+ --header-border-style: solid;
+ --header-border-color: hsla(var(--ig-gray-400), 0.38);
+ --filtering-header-background: hsla(var(--ig-gray-50) 205deg, 92%, 13%, var(--ig-gray-a));
+ --filtering-row-background: hsla(var(--ig-gray-50), var(--ig-gray-a));
+ --filtering-row-text-color: var(--ig-gray-50-contrast);
+ --sorted-header-icon-color: hsla(var(--ig-primary-500), var(--ig-primary-a));
+ --icon-color: "currentColor";
+ --row-hover-background: hsla(var(--ig-gray-200), var(--ig-gray-a));
+ --row-hover-text-color: var(--ig-gray-200-contrast);
+ --row-even-background: hsla(var(--ig-gray-50), var(--ig-gray-a));
+ --row-even-text-color: var(--ig-gray-50-contrast);
+ --row-odd-background: hsla(var(--ig-gray-50), var(--ig-gray-a));
+ --row-odd-text-color: var(--ig-gray-50-contrast);
+ --row-border-color: hsla(var(--ig-gray-300), 0.38);
+ --row-border-style: solid;
+ --row-border-width: 0.0625rem;
+ --cell-active-border-color: hsla(var(--ig-primary-500), var(--ig-primary-a));
+ --grid-resize-line-color: hsla(var(--ig-primary-500), var(--ig-primary-a));
+ --ig-font-family: "Merriweather Sans", sans-serif;
+ --ig-h1-font-family: var(--ig-font-family);
+ --ig-h1-font-size: 2.5rem;
+ --ig-h1-font-weight: 500;
+ --ig-h1-font-style: normal;
+ --ig-h1-line-height: 3rem;
+ --ig-h1-letter-spacing: -0.09375rem;
+ --ig-h1-text-transform: none;
+ --ig-h1-margin-top: 0;
+ --ig-h1-margin-bottom: 0.5rem;
+ --ig-h2-font-family: var(--ig-font-family);
+ --ig-h2-font-size: 2rem;
+ --ig-h2-font-weight: 500;
+ --ig-h2-font-style: normal;
+ --ig-h2-line-height: 2.4rem;
+ --ig-h2-letter-spacing: -0.03125rem;
+ --ig-h2-text-transform: none;
+ --ig-h2-margin-top: 0;
+ --ig-h2-margin-bottom: 0.5rem;
+ --ig-h3-font-family: var(--ig-font-family);
+ --ig-h3-font-size: 1.75rem;
+ --ig-h3-font-weight: 500;
+ --ig-h3-font-style: normal;
+ --ig-h3-line-height: 2.1rem;
+ --ig-h3-letter-spacing: 0;
+ --ig-h3-text-transform: none;
+ --ig-h3-margin-top: 0;
+ --ig-h3-margin-bottom: 0.5rem;
+ --ig-h4-font-family: var(--ig-font-family);
+ --ig-h4-font-size: 1.5rem;
+ --ig-h4-font-weight: 500;
+ --ig-h4-font-style: normal;
+ --ig-h4-line-height: 1.8rem;
+ --ig-h4-letter-spacing: 0.015625rem;
+ --ig-h4-text-transform: none;
+ --ig-h4-margin-top: 0;
+ --ig-h4-margin-bottom: 0.5rem;
+ --ig-h5-font-family: var(--ig-font-family);
+ --ig-h5-font-size: 1.25rem;
+ --ig-h5-font-weight: 500;
+ --ig-h5-font-style: normal;
+ --ig-h5-line-height: 1.5rem;
+ --ig-h5-letter-spacing: 0;
+ --ig-h5-text-transform: none;
+ --ig-h5-margin-top: 0;
+ --ig-h5-margin-bottom: 0.5rem;
+ --ig-h6-font-family: var(--ig-font-family);
+ --ig-h6-font-size: 1rem;
+ --ig-h6-font-weight: 500;
+ --ig-h6-font-style: normal;
+ --ig-h6-line-height: 1.2rem;
+ --ig-h6-letter-spacing: 0.009375rem;
+ --ig-h6-text-transform: none;
+ --ig-h6-margin-top: 0;
+ --ig-h6-margin-bottom: 0.5rem;
+ --ig-subtitle-1-font-family: var(--ig-font-family);
+ --ig-subtitle-1-font-size: 0.875rem;
+ --ig-subtitle-1-font-weight: 400;
+ --ig-subtitle-1-font-style: normal;
+ --ig-subtitle-1-line-height: 1.5rem;
+ --ig-subtitle-1-letter-spacing: 0.009375rem;
+ --ig-subtitle-1-text-transform: none;
+ --ig-subtitle-1-margin-top: 0;
+ --ig-subtitle-1-margin-bottom: 0;
+ --ig-subtitle-2-font-family: var(--ig-font-family);
+ --ig-subtitle-2-font-size: 0.9rem;
+ --ig-subtitle-2-font-weight: 400;
+ --ig-subtitle-2-font-style: normal;
+ --ig-subtitle-2-line-height: 1.35rem;
+ --ig-subtitle-2-letter-spacing: 0.00625rem;
+ --ig-subtitle-2-text-transform: none;
+ --ig-subtitle-2-margin-top: 0;
+ --ig-subtitle-2-margin-bottom: 0;
+ --ig-body-1-font-family: var(--ig-font-family);
+ --ig-body-1-font-size: 1rem;
+ --ig-body-1-font-weight: 400;
+ --ig-body-1-font-style: normal;
+ --ig-body-1-line-height: 1.5rem;
+ --ig-body-1-letter-spacing: 0.03125rem;
+ --ig-body-1-text-transform: none;
+ --ig-body-1-margin-top: 0;
+ --ig-body-1-margin-bottom: 0;
+ --ig-body-2-font-family: var(--ig-font-family);
+ --ig-body-2-font-size: 0.9rem;
+ --ig-body-2-font-weight: 400;
+ --ig-body-2-font-style: normal;
+ --ig-body-2-line-height: 1.5rem;
+ --ig-body-2-letter-spacing: 0.015625rem;
+ --ig-body-2-text-transform: none;
+ --ig-body-2-margin-top: 0;
+ --ig-body-2-margin-bottom: 0;
+ --ig-button-font-family: var(--ig-font-family);
+ --ig-button-font-size: 1rem;
+ --ig-button-font-weight: 500;
+ --ig-button-font-style: normal;
+ --ig-button-line-height: 1.5rem;
+ --ig-button-letter-spacing: 0.046875rem;
+ --ig-button-text-transform: none;
+ --ig-button-margin-top: 0;
+ --ig-button-margin-bottom: 0;
+ --ig-caption-font-family: var(--ig-font-family);
+ --ig-caption-font-size: 0.75rem;
+ --ig-caption-font-weight: 400;
+ --ig-caption-font-style: normal;
+ --ig-caption-line-height: 1rem;
+ --ig-caption-letter-spacing: 0.025rem;
+ --ig-caption-text-transform: none;
+ --ig-caption-margin-top: 0;
+ --ig-caption-margin-bottom: 0;
+ --ig-overline-font-family: var(--ig-font-family);
+ --ig-overline-font-size: 0.625rem;
+ --ig-overline-font-weight: 400;
+ --ig-overline-font-style: normal;
+ --ig-overline-line-height: 1rem;
+ --ig-overline-letter-spacing: 0.09375rem;
+ --ig-overline-text-transform: uppercase;
+ --ig-overline-margin-top: 0;
+ --ig-overline-margin-bottom: 0;
+ --ig-calendar-labels-font-family: var(--ig-font-family);
+ --ig-calendar-labels-font-size: 0.8125rem;
+ --ig-calendar-labels-font-weight: 400;
+ --ig-calendar-labels-font-style: normal;
+ --ig-calendar-labels-line-height: normal;
+ --ig-calendar-labels-letter-spacing: normal;
+ --ig-calendar-labels-text-transform: none;
+ --ig-calendar-labels-margin-top: 0;
+ --ig-calendar-labels-margin-bottom: 0;
+ --ig-primary-50-contrast: black;
+ --ig-primary-50: var(--ig-primary-h), calc(var(--ig-primary-s) * 1.23), calc(var(--ig-primary-l) * 1.78);
+ --ig-primary-100-contrast: black;
+ --ig-primary-100: var(--ig-primary-h), calc(var(--ig-primary-s) * 0.8), calc(var(--ig-primary-l) * 1.66);
+ --ig-primary-200-contrast: black;
+ --ig-primary-200: var(--ig-primary-h), calc(var(--ig-primary-s) * 0.64), calc(var(--ig-primary-l) * 1.43);
+ --ig-primary-300-contrast: black;
+ --ig-primary-300: var(--ig-primary-h), calc(var(--ig-primary-s) * 0.73), calc(var(--ig-primary-l) * 1.19);
+ --ig-primary-400-contrast: black;
+ --ig-primary-400: var(--ig-primary-h), calc(var(--ig-primary-s) * 0.875), calc(var(--ig-primary-l) * 1.08);
+ --ig-primary-h: 56deg;
+ --ig-primary-s: 75%;
+ --ig-primary-l: 50%;
+ --ig-primary-a: 1;
+ --ig-primary-500-contrast: black;
+ --ig-primary-500: var(--ig-primary-h), calc(var(--ig-primary-s) * 1), calc(var(--ig-primary-l) * 1);
+ --ig-primary-600-contrast: black;
+ --ig-primary-600: var(--ig-primary-h), calc(var(--ig-primary-s) * 1.26), calc(var(--ig-primary-l) * 0.89);
+ --ig-primary-700-contrast: black;
+ --ig-primary-700: var(--ig-primary-h), calc(var(--ig-primary-s) * 1.52), calc(var(--ig-primary-l) * 0.81);
+ --ig-primary-800-contrast: black;
+ --ig-primary-800: var(--ig-primary-h), calc(var(--ig-primary-s) * 1.5), calc(var(--ig-primary-l) * 0.73);
+ --ig-primary-900-contrast: black;
+ --ig-primary-900: var(--ig-primary-h), calc(var(--ig-primary-s) * 1.34), calc(var(--ig-primary-l) * 0.64);
+ --ig-primary-A100-contrast: black;
+ --ig-primary-A100: var(--ig-primary-h), calc(var(--ig-primary-s) * 1.23), calc(var(--ig-primary-l) * 1.34);
+ --ig-primary-A200-contrast: black;
+ --ig-primary-A200: var(--ig-primary-h), calc(var(--ig-primary-s) * 1.22), calc(var(--ig-primary-l) * 1.16);
+ --ig-primary-A400-contrast: black;
+ --ig-primary-A400: var(--ig-primary-h), calc(var(--ig-primary-s) * 1.23), calc(var(--ig-primary-l) * 0.91);
+ --ig-primary-A700-contrast: black;
+ --ig-primary-A700: var(--ig-primary-h), calc(var(--ig-primary-s) * 1.23), calc(var(--ig-primary-l) * 0.65);
+ --ig-secondary-50-contrast: black;
+ --ig-secondary-50: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1.23), calc(var(--ig-secondary-l) * 1.78);
+ --ig-secondary-100-contrast: black;
+ --ig-secondary-100: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 0.8), calc(var(--ig-secondary-l) * 1.66);
+ --ig-secondary-200-contrast: black;
+ --ig-secondary-200: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 0.64), calc(var(--ig-secondary-l) * 1.43);
+ --ig-secondary-300-contrast: black;
+ --ig-secondary-300: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 0.73), calc(var(--ig-secondary-l) * 1.19);
+ --ig-secondary-400-contrast: black;
+ --ig-secondary-400: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 0.875), calc(var(--ig-secondary-l) * 1.08);
+ --ig-secondary-h: 15deg;
+ --ig-secondary-s: 55%;
+ --ig-secondary-l: 64%;
+ --ig-secondary-a: 1;
+ --ig-secondary-500-contrast: black;
+ --ig-secondary-500: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1), calc(var(--ig-secondary-l) * 1);
+ --ig-secondary-600-contrast: black;
+ --ig-secondary-600: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1.26), calc(var(--ig-secondary-l) * 0.89);
+ --ig-secondary-700-contrast: black;
+ --ig-secondary-700: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1.52), calc(var(--ig-secondary-l) * 0.81);
+ --ig-secondary-800-contrast: black;
+ --ig-secondary-800: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1.5), calc(var(--ig-secondary-l) * 0.73);
+ --ig-secondary-900-contrast: white;
+ --ig-secondary-900: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1.34), calc(var(--ig-secondary-l) * 0.64);
+ --ig-secondary-A100-contrast: black;
+ --ig-secondary-A100: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1.23), calc(var(--ig-secondary-l) * 1.34);
+ --ig-secondary-A200-contrast: black;
+ --ig-secondary-A200: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1.22), calc(var(--ig-secondary-l) * 1.16);
+ --ig-secondary-A400-contrast: black;
+ --ig-secondary-A400: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1.23), calc(var(--ig-secondary-l) * 0.91);
+ --ig-secondary-A700-contrast: white;
+ --ig-secondary-A700: var(--ig-secondary-h), calc(var(--ig-secondary-s) * 1.23), calc(var(--ig-secondary-l) * 0.65);
+ --ig-gray-50-contrast: white;
+ --ig-gray-50: var(--ig-gray-h), var(--ig-gray-s), 13%;
+ --ig-gray-100-contrast: white;
+ --ig-gray-100: var(--ig-gray-h), var(--ig-gray-s), 26%;
+ --ig-gray-200-contrast: white;
+ --ig-gray-200: var(--ig-gray-h), var(--ig-gray-s), 38%;
+ --ig-gray-300-contrast: black;
+ --ig-gray-300: var(--ig-gray-h), var(--ig-gray-s), 54%;
+ --ig-gray-400-contrast: black;
+ --ig-gray-400: var(--ig-gray-h), var(--ig-gray-s), 62%;
+ --ig-gray-h: 205deg;
+ --ig-gray-s: 92%;
+ --ig-gray-l: 74%;
+ --ig-gray-a: 1;
+ --ig-gray-500-contrast: black;
+ --ig-gray-500: var(--ig-gray-h), var(--ig-gray-s), 74%;
+ --ig-gray-600-contrast: black;
+ --ig-gray-600: var(--ig-gray-h), var(--ig-gray-s), 88%;
+ --ig-gray-700-contrast: black;
+ --ig-gray-700: var(--ig-gray-h), var(--ig-gray-s), 93%;
+ --ig-gray-800-contrast: black;
+ --ig-gray-800: var(--ig-gray-h), var(--ig-gray-s), 96%;
+ --ig-gray-900-contrast: black;
+ --ig-gray-900: var(--ig-gray-h), var(--ig-gray-s), 98%;
+ --ig-surface-50-contrast: white;
+ --ig-surface-50: var(--ig-surface-h), calc(var(--ig-surface-s) * 1.23), calc(var(--ig-surface-l) * 1.78);
+ --ig-surface-100-contrast: white;
+ --ig-surface-100: var(--ig-surface-h), calc(var(--ig-surface-s) * 0.8), calc(var(--ig-surface-l) * 1.66);
+ --ig-surface-200-contrast: white;
+ --ig-surface-200: var(--ig-surface-h), calc(var(--ig-surface-s) * 0.64), calc(var(--ig-surface-l) * 1.43);
+ --ig-surface-300-contrast: white;
+ --ig-surface-300: var(--ig-surface-h), calc(var(--ig-surface-s) * 0.73), calc(var(--ig-surface-l) * 1.19);
+ --ig-surface-400-contrast: white;
+ --ig-surface-400: var(--ig-surface-h), calc(var(--ig-surface-s) * 0.875), calc(var(--ig-surface-l) * 1.08);
+ --ig-surface-h: 216deg;
+ --ig-surface-s: 92%;
+ --ig-surface-l: 14%;
+ --ig-surface-a: 1;
+ --ig-surface-500-contrast: white;
+ --ig-surface-500: var(--ig-surface-h), calc(var(--ig-surface-s) * 1), calc(var(--ig-surface-l) * 1);
+ --ig-surface-600-contrast: white;
+ --ig-surface-600: var(--ig-surface-h), calc(var(--ig-surface-s) * 1.26), calc(var(--ig-surface-l) * 0.89);
+ --ig-surface-700-contrast: white;
+ --ig-surface-700: var(--ig-surface-h), calc(var(--ig-surface-s) * 1.52), calc(var(--ig-surface-l) * 0.81);
+ --ig-surface-800-contrast: white;
+ --ig-surface-800: var(--ig-surface-h), calc(var(--ig-surface-s) * 1.5), calc(var(--ig-surface-l) * 0.73);
+ --ig-surface-900-contrast: white;
+ --ig-surface-900: var(--ig-surface-h), calc(var(--ig-surface-s) * 1.34), calc(var(--ig-surface-l) * 0.64);
+ --ig-surface-A100-contrast: white;
+ --ig-surface-A100: var(--ig-surface-h), calc(var(--ig-surface-s) * 1.23), calc(var(--ig-surface-l) * 1.34);
+ --ig-surface-A200-contrast: white;
+ --ig-surface-A200: var(--ig-surface-h), calc(var(--ig-surface-s) * 1.22), calc(var(--ig-surface-l) * 1.16);
+ --ig-surface-A400-contrast: white;
+ --ig-surface-A400: var(--ig-surface-h), calc(var(--ig-surface-s) * 1.23), calc(var(--ig-surface-l) * 0.91);
+ --ig-surface-A700-contrast: white;
+ --ig-surface-A700: var(--ig-surface-h), calc(var(--ig-surface-s) * 1.23), calc(var(--ig-surface-l) * 0.65);
+ --ig-info-50-contrast: black;
+ --ig-info-50: var(--ig-info-h), calc(var(--ig-info-s) * 1.23), calc(var(--ig-info-l) * 1.78);
+ --ig-info-100-contrast: black;
+ --ig-info-100: var(--ig-info-h), calc(var(--ig-info-s) * 0.8), calc(var(--ig-info-l) * 1.66);
+ --ig-info-200-contrast: black;
+ --ig-info-200: var(--ig-info-h), calc(var(--ig-info-s) * 0.64), calc(var(--ig-info-l) * 1.43);
+ --ig-info-300-contrast: black;
+ --ig-info-300: var(--ig-info-h), calc(var(--ig-info-s) * 0.73), calc(var(--ig-info-l) * 1.19);
+ --ig-info-400-contrast: black;
+ --ig-info-400: var(--ig-info-h), calc(var(--ig-info-s) * 0.875), calc(var(--ig-info-l) * 1.08);
+ --ig-info-h: 209deg;
+ --ig-info-s: 84%;
+ --ig-info-l: 45%;
+ --ig-info-a: 1;
+ --ig-info-500-contrast: black;
+ --ig-info-500: var(--ig-info-h), calc(var(--ig-info-s) * 1), calc(var(--ig-info-l) * 1);
+ --ig-info-600-contrast: white;
+ --ig-info-600: var(--ig-info-h), calc(var(--ig-info-s) * 1.26), calc(var(--ig-info-l) * 0.89);
+ --ig-info-700-contrast: white;
+ --ig-info-700: var(--ig-info-h), calc(var(--ig-info-s) * 1.52), calc(var(--ig-info-l) * 0.81);
+ --ig-info-800-contrast: white;
+ --ig-info-800: var(--ig-info-h), calc(var(--ig-info-s) * 1.5), calc(var(--ig-info-l) * 0.73);
+ --ig-info-900-contrast: white;
+ --ig-info-900: var(--ig-info-h), calc(var(--ig-info-s) * 1.34), calc(var(--ig-info-l) * 0.64);
+ --ig-info-A100-contrast: black;
+ --ig-info-A100: var(--ig-info-h), calc(var(--ig-info-s) * 1.23), calc(var(--ig-info-l) * 1.34);
+ --ig-info-A200-contrast: black;
+ --ig-info-A200: var(--ig-info-h), calc(var(--ig-info-s) * 1.22), calc(var(--ig-info-l) * 1.16);
+ --ig-info-A400-contrast: white;
+ --ig-info-A400: var(--ig-info-h), calc(var(--ig-info-s) * 1.23), calc(var(--ig-info-l) * 0.91);
+ --ig-info-A700-contrast: white;
+ --ig-info-A700: var(--ig-info-h), calc(var(--ig-info-s) * 1.23), calc(var(--ig-info-l) * 0.65);
+ --ig-success-50-contrast: black;
+ --ig-success-50: var(--ig-success-h), calc(var(--ig-success-s) * 1.23), calc(var(--ig-success-l) * 1.78);
+ --ig-success-100-contrast: black;
+ --ig-success-100: var(--ig-success-h), calc(var(--ig-success-s) * 0.8), calc(var(--ig-success-l) * 1.66);
+ --ig-success-200-contrast: black;
+ --ig-success-200: var(--ig-success-h), calc(var(--ig-success-s) * 0.64), calc(var(--ig-success-l) * 1.43);
+ --ig-success-300-contrast: black;
+ --ig-success-300: var(--ig-success-h), calc(var(--ig-success-s) * 0.73), calc(var(--ig-success-l) * 1.19);
+ --ig-success-400-contrast: black;
+ --ig-success-400: var(--ig-success-h), calc(var(--ig-success-s) * 0.875), calc(var(--ig-success-l) * 1.08);
+ --ig-success-h: 131deg;
+ --ig-success-s: 43%;
+ --ig-success-l: 51%;
+ --ig-success-a: 1;
+ --ig-success-500-contrast: black;
+ --ig-success-500: var(--ig-success-h), calc(var(--ig-success-s) * 1), calc(var(--ig-success-l) * 1);
+ --ig-success-600-contrast: black;
+ --ig-success-600: var(--ig-success-h), calc(var(--ig-success-s) * 1.26), calc(var(--ig-success-l) * 0.89);
+ --ig-success-700-contrast: black;
+ --ig-success-700: var(--ig-success-h), calc(var(--ig-success-s) * 1.52), calc(var(--ig-success-l) * 0.81);
+ --ig-success-800-contrast: black;
+ --ig-success-800: var(--ig-success-h), calc(var(--ig-success-s) * 1.5), calc(var(--ig-success-l) * 0.73);
+ --ig-success-900-contrast: white;
+ --ig-success-900: var(--ig-success-h), calc(var(--ig-success-s) * 1.34), calc(var(--ig-success-l) * 0.64);
+ --ig-success-A100-contrast: black;
+ --ig-success-A100: var(--ig-success-h), calc(var(--ig-success-s) * 1.23), calc(var(--ig-success-l) * 1.34);
+ --ig-success-A200-contrast: black;
+ --ig-success-A200: var(--ig-success-h), calc(var(--ig-success-s) * 1.22), calc(var(--ig-success-l) * 1.16);
+ --ig-success-A400-contrast: black;
+ --ig-success-A400: var(--ig-success-h), calc(var(--ig-success-s) * 1.23), calc(var(--ig-success-l) * 0.91);
+ --ig-success-A700-contrast: white;
+ --ig-success-A700: var(--ig-success-h), calc(var(--ig-success-s) * 1.23), calc(var(--ig-success-l) * 0.65);
+ --ig-warn-50-contrast: black;
+ --ig-warn-50: var(--ig-warn-h), calc(var(--ig-warn-s) * 1.23), calc(var(--ig-warn-l) * 1.78);
+ --ig-warn-100-contrast: black;
+ --ig-warn-100: var(--ig-warn-h), calc(var(--ig-warn-s) * 0.8), calc(var(--ig-warn-l) * 1.66);
+ --ig-warn-200-contrast: black;
+ --ig-warn-200: var(--ig-warn-h), calc(var(--ig-warn-s) * 0.64), calc(var(--ig-warn-l) * 1.43);
+ --ig-warn-300-contrast: black;
+ --ig-warn-300: var(--ig-warn-h), calc(var(--ig-warn-s) * 0.73), calc(var(--ig-warn-l) * 1.19);
+ --ig-warn-400-contrast: black;
+ --ig-warn-400: var(--ig-warn-h), calc(var(--ig-warn-s) * 0.875), calc(var(--ig-warn-l) * 1.08);
+ --ig-warn-h: 37deg;
+ --ig-warn-s: 96%;
+ --ig-warn-l: 54%;
+ --ig-warn-a: 1;
+ --ig-warn-500-contrast: black;
+ --ig-warn-500: var(--ig-warn-h), calc(var(--ig-warn-s) * 1), calc(var(--ig-warn-l) * 1);
+ --ig-warn-600-contrast: black;
+ --ig-warn-600: var(--ig-warn-h), calc(var(--ig-warn-s) * 1.26), calc(var(--ig-warn-l) * 0.89);
+ --ig-warn-700-contrast: black;
+ --ig-warn-700: var(--ig-warn-h), calc(var(--ig-warn-s) * 1.52), calc(var(--ig-warn-l) * 0.81);
+ --ig-warn-800-contrast: black;
+ --ig-warn-800: var(--ig-warn-h), calc(var(--ig-warn-s) * 1.5), calc(var(--ig-warn-l) * 0.73);
+ --ig-warn-900-contrast: black;
+ --ig-warn-900: var(--ig-warn-h), calc(var(--ig-warn-s) * 1.34), calc(var(--ig-warn-l) * 0.64);
+ --ig-warn-A100-contrast: black;
+ --ig-warn-A100: var(--ig-warn-h), calc(var(--ig-warn-s) * 1.23), calc(var(--ig-warn-l) * 1.34);
+ --ig-warn-A200-contrast: black;
+ --ig-warn-A200: var(--ig-warn-h), calc(var(--ig-warn-s) * 1.22), calc(var(--ig-warn-l) * 1.16);
+ --ig-warn-A400-contrast: black;
+ --ig-warn-A400: var(--ig-warn-h), calc(var(--ig-warn-s) * 1.23), calc(var(--ig-warn-l) * 0.91);
+ --ig-warn-A700-contrast: black;
+ --ig-warn-A700: var(--ig-warn-h), calc(var(--ig-warn-s) * 1.23), calc(var(--ig-warn-l) * 0.65);
+ --ig-error-50-contrast: black;
+ --ig-error-50: var(--ig-error-h), calc(var(--ig-error-s) * 1.23), calc(var(--ig-error-l) * 1.78);
+ --ig-error-100-contrast: black;
+ --ig-error-100: var(--ig-error-h), calc(var(--ig-error-s) * 0.8), calc(var(--ig-error-l) * 1.66);
+ --ig-error-200-contrast: black;
+ --ig-error-200: var(--ig-error-h), calc(var(--ig-error-s) * 0.64), calc(var(--ig-error-l) * 1.43);
+ --ig-error-300-contrast: black;
+ --ig-error-300: var(--ig-error-h), calc(var(--ig-error-s) * 0.73), calc(var(--ig-error-l) * 1.19);
+ --ig-error-400-contrast: black;
+ --ig-error-400: var(--ig-error-h), calc(var(--ig-error-s) * 0.875), calc(var(--ig-error-l) * 1.08);
+ --ig-error-h: 346deg;
+ --ig-error-s: 100%;
+ --ig-error-l: 54%;
+ --ig-error-a: 1;
+ --ig-error-500-contrast: black;
+ --ig-error-500: var(--ig-error-h), calc(var(--ig-error-s) * 1), calc(var(--ig-error-l) * 1);
+ --ig-error-600-contrast: black;
+ --ig-error-600: var(--ig-error-h), calc(var(--ig-error-s) * 1.26), calc(var(--ig-error-l) * 0.89);
+ --ig-error-700-contrast: white;
+ --ig-error-700: var(--ig-error-h), calc(var(--ig-error-s) * 1.52), calc(var(--ig-error-l) * 0.81);
+ --ig-error-800-contrast: white;
+ --ig-error-800: var(--ig-error-h), calc(var(--ig-error-s) * 1.5), calc(var(--ig-error-l) * 0.73);
+ --ig-error-900-contrast: white;
+ --ig-error-900: var(--ig-error-h), calc(var(--ig-error-s) * 1.34), calc(var(--ig-error-l) * 0.64);
+ --ig-error-A100-contrast: black;
+ --ig-error-A100: var(--ig-error-h), calc(var(--ig-error-s) * 1.23), calc(var(--ig-error-l) * 1.34);
+ --ig-error-A200-contrast: black;
+ --ig-error-A200: var(--ig-error-h), calc(var(--ig-error-s) * 1.22), calc(var(--ig-error-l) * 1.16);
+ --ig-error-A400-contrast: black;
+ --ig-error-A400: var(--ig-error-h), calc(var(--ig-error-s) * 1.23), calc(var(--ig-error-l) * 0.91);
+ --ig-error-A700-contrast: white;
+ --ig-error-A700: var(--ig-error-h), calc(var(--ig-error-s) * 1.23), calc(var(--ig-error-l) * 0.65);
+}
diff --git a/samples/grids/grid-lite/styling-custom-theme/src/index.tsx b/samples/grids/grid-lite/styling-custom-theme/src/index.tsx
new file mode 100644
index 000000000..f5aa47649
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/src/index.tsx
@@ -0,0 +1,94 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import { GridLiteDataService, ProductInfo } from './GridLiteDataService';
+
+// Import the web component
+import { IgcGridLite } from 'igniteui-grid-lite';
+import {
+ defineComponents,
+ IgcRatingComponent
+} from 'igniteui-webcomponents';
+
+import "igniteui-webcomponents/themes/light/bootstrap.css";
+import "./index.css";
+
+// Register components
+IgcGridLite.register();
+defineComponents(IgcRatingComponent);
+
+export default class Sample extends React.Component {
+ private dataService: GridLiteDataService;
+ private gridRef: React.RefObject;
+
+ constructor(props: any) {
+ super(props);
+ this.dataService = new GridLiteDataService();
+ this.gridRef = React.createRef();
+ }
+
+ componentDidMount() {
+ if (this.gridRef.current) {
+ const data: ProductInfo[] = this.dataService.generateProducts(50);
+
+ const columns = [
+ {
+ key: 'name',
+ headerText: 'Product',
+ sort: true,
+ filter: true
+ },
+ {
+ key: 'price',
+ headerText: 'Price',
+ sort: true,
+ filter: true,
+ type: 'number'
+ },
+ {
+ key: 'sold',
+ headerText: 'Sold',
+ sort: true,
+ filter: true,
+ type: 'number'
+ },
+ {
+ key: 'total',
+ headerText: 'Total',
+ sort: true,
+ filter: true,
+ type: 'number'
+ },
+ {
+ key: 'rating',
+ headerText: 'Rating',
+ type: 'number',
+ sort: true,
+ filter: true,
+ cellTemplate: (params: any) => {
+ const rating = document.createElement('igc-rating');
+ rating.setAttribute('readonly', '');
+ rating.setAttribute('value', params.value.toString());
+ return rating;
+ }
+ }
+ ];
+
+ this.gridRef.current.columns = columns;
+ this.gridRef.current.data = data;
+ }
+ }
+
+ public render(): JSX.Element {
+ return (
+
+ );
+ }
+}
+
+// rendering above component in the React DOM
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render();
diff --git a/samples/grids/grid-lite/styling-custom-theme/tsconfig.json b/samples/grids/grid-lite/styling-custom-theme/tsconfig.json
new file mode 100644
index 000000000..8c0d146f9
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/tsconfig.json
@@ -0,0 +1,44 @@
+{
+ "compilerOptions": {
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "baseUrl": ".",
+ "outDir": "build/dist",
+ "module": "esnext",
+ "target": "es5",
+ "lib": [
+ "es6",
+ "dom"
+ ],
+ "sourceMap": true,
+ "allowJs": true,
+ "jsx": "react-jsx",
+ "moduleResolution": "node",
+ "rootDir": "src",
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noImplicitAny": true,
+ "noUnusedLocals": false,
+ "importHelpers": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "isolatedModules": true,
+ "noEmit": true
+ },
+ "exclude": [
+ "node_modules",
+ "build",
+ "scripts",
+ "acceptance-tests",
+ "webpack",
+ "jest",
+ "src/setupTests.ts",
+ "**/odatajs-4.0.0.js",
+ "config-overrides.js"
+ ],
+ "include": [
+ "src"
+ ]
+}
diff --git a/samples/grids/grid-lite/styling-custom-theme/vite.config.js b/samples/grids/grid-lite/styling-custom-theme/vite.config.js
new file mode 100644
index 000000000..1744dbc71
--- /dev/null
+++ b/samples/grids/grid-lite/styling-custom-theme/vite.config.js
@@ -0,0 +1,12 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()],
+ build: {
+ outDir: 'build'
+ },
+ server: {
+ open: false
+ },
+});
\ No newline at end of file