Skip to content

Commit 413b7cb

Browse files
authored
Merge pull request #1027 from IgniteUI/didimmova/add-config-themes-sample
sample(grid-lite): add grid-lite sample with switchable themes
2 parents 4830e46 + f15d276 commit 413b7cb

16 files changed

Lines changed: 972 additions & 6 deletions

File tree

browser/package-lock.json

Lines changed: 419 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

browser/vite.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@ export default defineConfig(({ mode }) => ({
4949
server: {
5050
open: false
5151
},
52-
}));
52+
}));
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project
2+
module.exports = {
3+
parser: "@typescript-eslint/parser", // Specifies the ESLint parser
4+
parserOptions: {
5+
ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
6+
sourceType: "module", // Allows for the use of imports
7+
ecmaFeatures: {
8+
jsx: true // Allows for the parsing of JSX
9+
}
10+
},
11+
settings: {
12+
react: {
13+
version: "999.999.999" // Tells eslint-plugin-react to automatically detect the version of React to use
14+
}
15+
},
16+
extends: [
17+
"eslint:recommended",
18+
"plugin:react/recommended", // Uses the recommended rules from @eslint-plugin-react
19+
"plugin:@typescript-eslint/recommended" // Uses the recommended rules from @typescript-eslint/eslint-plugin
20+
],
21+
rules: {
22+
// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
23+
"default-case": "off",
24+
"jsx-a11y/alt-text": "off",
25+
"jsx-a11y/iframe-has-title": "off",
26+
"no-undef": "off",
27+
"no-unused-vars": "off",
28+
"no-extend-native": "off",
29+
"no-throw-literal": "off",
30+
"no-useless-concat": "off",
31+
"no-mixed-operators": "off",
32+
"no-prototype-builtins": "off",
33+
"no-mixed-spaces-and-tabs": 0,
34+
"prefer-const": "off",
35+
"prefer-rest-params": "off",
36+
"@typescript-eslint/no-unused-vars": "off",
37+
"@typescript-eslint/no-explicit-any": "off",
38+
"@typescript-eslint/no-inferrable-types": "off",
39+
"@typescript-eslint/no-useless-constructor": "off",
40+
"@typescript-eslint/no-use-before-define": "off",
41+
"@typescript-eslint/no-non-null-assertion": "off",
42+
"@typescript-eslint/interface-name-prefix": "off",
43+
"@typescript-eslint/prefer-namespace-keyword": "off",
44+
"@typescript-eslint/explicit-function-return-type": "off",
45+
"@typescript-eslint/explicit-module-boundary-types": "off"
46+
},
47+
"overrides": [
48+
{
49+
"files": ["*.ts", "*.tsx"],
50+
"rules": {
51+
"default-case": "off",
52+
"jsx-a11y/alt-text": "off",
53+
"jsx-a11y/iframe-has-title": "off",
54+
"no-var": "off",
55+
"no-undef": "off",
56+
"no-unused-vars": "off",
57+
"no-extend-native": "off",
58+
"no-throw-literal": "off",
59+
"no-useless-concat": "off",
60+
"no-mixed-operators": "off",
61+
"no-mixed-spaces-and-tabs": 0,
62+
"no-prototype-builtins": "off",
63+
"prefer-const": "off",
64+
"prefer-rest-params": "off",
65+
"@typescript-eslint/no-unused-vars": "off",
66+
"@typescript-eslint/no-explicit-any": "off",
67+
"@typescript-eslint/no-inferrable-types": "off",
68+
"@typescript-eslint/no-useless-constructor": "off",
69+
"@typescript-eslint/no-use-before-define": "off",
70+
"@typescript-eslint/no-non-null-assertion": "off",
71+
"@typescript-eslint/interface-name-prefix": "off",
72+
"@typescript-eslint/prefer-namespace-keyword": "off",
73+
"@typescript-eslint/explicit-function-return-type": "off",
74+
"@typescript-eslint/explicit-module-boundary-types": "off"
75+
}
76+
}
77+
]
78+
};
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<!-- NOTE: do not change this file because it's auto re-generated from template: -->
2+
<!-- https://github.com/IgniteUI/igniteui-react-examples/tree/vnext/templates/sample/ReadMe.md -->
3+
4+
This folder contains implementation of React application with example of Styling Config Themes feature using [Grid Lite](https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html) component.
5+
6+
7+
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
8+
<body>
9+
<a target="_blank" href="https://www.infragistics.com/products/ignite-ui-react/react/components/general-getting-started.html" rel="noopener noreferrer">
10+
<img height="40px" style="border-radius: 0rem" alt="View Docs" src="https://dl.infragistics.com/x/img/browsers/button-docs.png"/>
11+
</a>
12+
<a target="_blank" href="./src/index.tsx" rel="noopener noreferrer">
13+
<img height="40px" style="border-radius: 0rem; max-width: 100%;" alt="View Code" src="https://dl.infragistics.com/x/img/browsers/button-code.png"/>
14+
</a>
15+
<a target="_blank" href="https://www.infragistics.com/react-demos/samples/grids/grid-lite/styling-config-themes" rel="noopener noreferrer">
16+
<img height="40px" style="border-radius: 0rem; max-width: 100%;" alt="Run Sample" src="https://dl.infragistics.com/x/img/browsers/button-run.png"/>
17+
</a>
18+
<a target="_blank" href="https://codesandbox.io/s/github/IgniteUI/igniteui-react-examples/tree/master/samples/grids/grid-lite/styling-config-themes?fontsize=14&hidenavigation=1&theme=dark&view=preview&file=/src/index.tsx" rel="noopener noreferrer">
19+
<img height="40px" style="border-radius: 0rem; max-width: 100%;" alt="Run Sample" src="https://dl.infragistics.com/x/img/browsers/button-sandbox.png"/>
20+
</a>
21+
</body>
22+
</html>
23+
24+
## Branches
25+
26+
> **_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.
27+
28+
## Instructions
29+
30+
Follow these instructions to run this example:
31+
32+
33+
```
34+
git clone https://github.com/IgniteUI/igniteui-react-examples.git
35+
git checkout master
36+
cd ./igniteui-react-examples
37+
cd ./samples/grids/grid-lite/styling-config-themes
38+
```
39+
40+
open above folder in VS Code or type:
41+
```
42+
code .
43+
```
44+
45+
In terminal window, run:
46+
```
47+
npm install --legacy-peer-deps
48+
npm run-script start
49+
```
50+
51+
Then open http://localhost:4200/ in your browser
52+
53+
54+
## Learn More
55+
56+
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).
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Sample | Ignite UI | React | infragistics</title>
5+
<link rel="shortcut icon" href="https://dl.infragistics.com/x/img/browsers/react.png" >
6+
<link rel="stylesheet" href="https://dl.infragistics.com/x/css/samples/shared.v8.css" />
7+
</head>
8+
<body data-theme="bootstrap-light">
9+
<div id="root"></div>
10+
<script type="module" src="/src/index.tsx"></script>
11+
</body>
12+
</html>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"name": "example-ignite-ui-react",
3+
"description": "This project provides example of using Ignite UI for React components",
4+
"author": "Infragistics",
5+
"version": "1.4.0",
6+
"license": "",
7+
"homepage": ".",
8+
"private": true,
9+
"scripts": {
10+
"start": "vite --port 4200",
11+
"build": "tsc && node --max-old-space-size=4096 node_modules/vite/bin/vite build",
12+
"preview": "vite preview",
13+
"test": "vitest",
14+
"lint": "eslint ./src/**/*.{ts,tsx}"
15+
},
16+
"dependencies": {
17+
"igniteui-grid-lite": "~0.6.0",
18+
"igniteui-react": "^19.4.0",
19+
"igniteui-theming": "^25.0.1",
20+
"igniteui-webcomponents": "^6.3.0",
21+
"lit-html": "^3.2.0",
22+
"react": "^19.2.0",
23+
"react-dom": "^19.2.0",
24+
"tslib": "^2.4.0"
25+
},
26+
"devDependencies": {
27+
"@types/jest": "^29.2.0",
28+
"@types/node": "^24.7.1",
29+
"@types/react": "^18.3.28",
30+
"@types/react-dom": "^18.0.8",
31+
"@vitejs/plugin-react": "^5.0.4",
32+
"@vitest/browser": "^3.2.4",
33+
"eslint": "^8.33.0",
34+
"eslint-config-react": "^1.1.7",
35+
"eslint-plugin-react": "^7.20.0",
36+
"sass": "^1.83.0",
37+
"typescript": "^4.8.4",
38+
"vite": "^7.1.9",
39+
"vitest": "^3.2.4",
40+
"vitest-canvas-mock": "^0.3.3",
41+
"worker-loader": "^3.0.8"
42+
},
43+
"browserslist": [
44+
">0.2%",
45+
"not dead",
46+
"not ie <= 11",
47+
"not op_mini all"
48+
]
49+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"infiniteLoopProtection": false,
3+
"hardReloadOnChange": false,
4+
"view": "browser"
5+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
export type UserSimple = {
2+
id: string;
3+
username: string;
4+
email: string;
5+
subscribed: boolean;
6+
};
7+
8+
export type ProductInfo = {
9+
id: string;
10+
name: string;
11+
price: number;
12+
sold: number;
13+
rating: number;
14+
total: number;
15+
};
16+
17+
export type User = {
18+
id: string;
19+
firstName: string;
20+
lastName: string;
21+
age: number;
22+
email: string;
23+
avatar: string;
24+
active: boolean;
25+
priority: 'Low' | 'Standard' | 'High';
26+
satisfaction: number;
27+
registeredAt: Date;
28+
};
29+
30+
export class GridLiteDataService {
31+
private counter = 0;
32+
33+
private namesMen = ['John', 'Bob', 'Mark', 'Charlie', 'Martin', 'Bill', 'Frank', 'Larry', 'Henry', 'Steve', 'Mike', 'Andrew'];
34+
private namesWomen = ['Jane', 'Alice', 'Diana', 'Eve', 'Grace' , 'Katie', 'Irene', 'Liz', 'Fiona', 'Pam', 'Val', 'Mindy'];
35+
private lastNames = ['Smith', 'Johnson', 'Mendoza', 'Brown', 'Spencer', 'Stone', 'Stark', 'Rooney'];
36+
private productNames = ['Widget', 'Gadget', 'Gizmo', 'Device', 'Tool', 'Instrument', 'Machine', 'Equipment'];
37+
private productModels = ['Pro', 'Plus', 'Max', 'Ultra', 'Mini', 'Lite'];
38+
private priorities: ('Low' | 'Standard' | 'High')[] = ['Low', 'Standard', 'High'];
39+
40+
private randomInt(min: number, max: number): number {
41+
const array = new Uint32Array(1);
42+
window.crypto.getRandomValues(array);
43+
const random01 = array[0] / 2 ** 32;
44+
return Math.floor(random01 * (max - min + 1)) + min;
45+
}
46+
47+
private randomFloat(min: number, max: number, precision = 2): number {
48+
const array = new Uint32Array(1);
49+
window.crypto.getRandomValues(array);
50+
const random01 = array[0] / 2 ** 32;
51+
return parseFloat((random01 * (max - min) + min).toFixed(precision));
52+
}
53+
54+
private randomElement<T>(array: T[]): T {
55+
return array[this.randomInt(0, array.length - 1)];
56+
}
57+
58+
private randomBoolean(): boolean {
59+
const array = new Uint8Array(1);
60+
window.crypto.getRandomValues(array);
61+
return (array[0] & 1) === 0;
62+
}
63+
64+
private generateId(): string {
65+
return `1000-${this.counter++}-${this.randomInt(1000, 9999)}`;
66+
}
67+
68+
createProductInfo(): ProductInfo {
69+
const price = this.randomFloat(50, 500, 2);
70+
const sold = this.randomInt(10, 100);
71+
const total = parseFloat((price * sold).toFixed(2));
72+
const product = this.randomElement(this.productNames) + ' ' + this.randomElement(this.productModels);
73+
74+
return {
75+
price,
76+
sold,
77+
total,
78+
id: this.generateId(),
79+
name: product,
80+
rating: this.randomFloat(0, 5, 1)
81+
};
82+
}
83+
84+
createUserSimple(): UserSimple {
85+
const firstName = this.randomElement(this.namesMen.concat(this.namesWomen)).toLowerCase();
86+
const lastName = this.randomElement(this.lastNames).toLowerCase();
87+
const email = firstName + '.' + lastName + '@example.com';
88+
const username = firstName + '.' + lastName + this.randomInt(1, 99);
89+
return {
90+
id: this.generateId(),
91+
username: username,
92+
email: email,
93+
subscribed: this.randomBoolean()
94+
};
95+
}
96+
97+
createUser(): User {
98+
let imagePath: string = "";
99+
let firstName: string = "";
100+
const gender = this.randomInt(0, 1);
101+
if (gender === 0) {
102+
imagePath = "https://dl.infragistics.com/x/img/people/men/" + this.randomInt(10, 40) + ".png";
103+
firstName = this.randomElement(this.namesMen);
104+
} else {
105+
imagePath = "https://dl.infragistics.com/x/img/people/women/" + this.randomInt(10, 40) + ".png";
106+
firstName = this.randomElement(this.namesWomen);
107+
}
108+
const lastName = this.randomElement(this.lastNames);
109+
const email = firstName.toLowerCase() + '.' + lastName.toLowerCase() + '@example.com';
110+
111+
return {
112+
id: this.generateId(),
113+
firstName,
114+
lastName,
115+
age: this.randomInt(18, 90),
116+
email,
117+
avatar: imagePath,
118+
active: this.randomBoolean(),
119+
priority: this.randomElement(this.priorities),
120+
satisfaction: this.randomInt(0, 5),
121+
registeredAt: new Date(Date.now() - this.randomInt(0, 365 * 24 * 60 * 60 * 1000))
122+
};
123+
}
124+
125+
generateUsers(count: number): User[] {
126+
return Array.from({ length: count }, () => this.createUser());
127+
}
128+
129+
generateProducts(count: number): ProductInfo[] {
130+
return Array.from({ length: count }, () => this.createProductInfo());
131+
}
132+
133+
generateSimpleUsers(count: number): UserSimple[] {
134+
return Array.from({ length: count }, () => this.createUserSimple());
135+
}
136+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
@use 'sass:list';
2+
@use 'igniteui-theming' as *;
3+
@use 'igniteui-theming/sass/color/presets' as *;
4+
@use 'igniteui-theming/sass/typography/presets' as *;
5+
6+
.container {
7+
padding: rem(20px);
8+
}
9+
10+
.options {
11+
background: var(--ig-gray-100);
12+
gap: rem(10px);
13+
padding: rem(20px);
14+
margin-bottom: rem(20px);
15+
border-radius: rem(6px);
16+
}
17+
18+
.grid-lite-wrapper {
19+
height: 100vh;
20+
}
21+
22+
// Theme configurations
23+
$themes: (
24+
'bootstrap-light': ($light-bootstrap-palette, $bootstrap-typeface, $bootstrap-type-scale),
25+
'material-light': ($light-material-palette, $material-typeface, $material-type-scale),
26+
'fluent-light': ($light-fluent-palette, $fluent-typeface, $fluent-type-scale),
27+
'indigo-light': ($light-indigo-palette, $indigo-typeface, $indigo-type-scale),
28+
'bootstrap-dark': ($dark-bootstrap-palette, $bootstrap-typeface, $bootstrap-type-scale),
29+
'material-dark': ($dark-material-palette, $material-typeface, $material-type-scale),
30+
'fluent-dark': ($dark-fluent-palette, $fluent-typeface, $fluent-type-scale),
31+
'indigo-dark': ($dark-indigo-palette, $indigo-typeface, $indigo-type-scale)
32+
);
33+
34+
// Generate theme classes
35+
@each $name, $config in $themes {
36+
body[data-theme="#{$name}"] .grid-lite-wrapper {
37+
@include palette(list.nth($config, 1));
38+
@include typography(list.nth($config, 2), list.nth($config, 3));
39+
}
40+
}

0 commit comments

Comments
 (0)