diff --git a/applications/GettingStartedWith/Pagination/index.css b/applications/GettingStartedWith/Pagination/index.css
new file mode 100644
index 0000000000..65633211db
--- /dev/null
+++ b/applications/GettingStartedWith/Pagination/index.css
@@ -0,0 +1,5 @@
+#cards {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+}
\ No newline at end of file
diff --git a/applications/GettingStartedWith/Pagination/index.html b/applications/GettingStartedWith/Pagination/index.html
new file mode 100644
index 0000000000..9fed08e96d
--- /dev/null
+++ b/applications/GettingStartedWith/Pagination/index.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/applications/GettingStartedWith/Pagination/index.js b/applications/GettingStartedWith/Pagination/index.js
new file mode 100644
index 0000000000..4c323fc2d7
--- /dev/null
+++ b/applications/GettingStartedWith/Pagination/index.js
@@ -0,0 +1,118 @@
+const total = 100;
+const hexCodes = [];
+const apiEndpoint = 'https://www.thecolorapi.com/id?hex=';
+const cache = new Map();
+
+function fetchData(colorId) {
+ return new Promise((resolve, reject) => {
+ if (cache.has(colorId)) {
+ resolve(cache.get(colorId));
+ } else {
+ $.getJSON(apiEndpoint + colorId, (data) => {
+ const colorData = {
+ image: data.image.bare,
+ name: data.name.value,
+ };
+ cache.set(colorId, colorData);
+ resolve(colorData);
+ }).fail(() => {
+ reject(new Error(`Error loading color for hex: ${colorId}`));
+ });
+ }
+ });
+}
+
+const getRandomPastelColor = () => {
+ const hue = Math.floor(Math.random() * 360);
+ const saturation = Math.random() * 0.4 + 0.2;
+ const brightness = Math.random() * 0.3 + 0.7;
+ return hsvToHex(hue, saturation, brightness);
+};
+
+const hsvToHex = (h, s, v) => {
+ let r = 0;
+ let g = 0;
+ let b = 0;
+ const i = Math.floor(h / 60);
+ const f = h / 60 - i;
+ const p = v * (1 - s);
+ const q = v * (1 - f * s);
+ const t = v * (1 - (1 - f) * s);
+ switch (i % 6) {
+ case 0: r = v; g = t; b = p; break;
+ case 1: r = q; g = v; b = p; break;
+ case 2: r = p; g = v; b = t; break;
+ case 3: r = p; g = q; b = v; break;
+ case 4: r = t; g = p; b = v; break;
+ case 5: r = v; g = p; b = q; break;
+ }
+ const toHex = (x) => {
+ const hex = Math.round(x * 255).toString(16);
+ return hex.length === 1 ? `0${hex}` : hex;
+ };
+ return toHex(r) + toHex(g) + toHex(b);
+};
+
+const renderCards = async (pageSize, pageIndex) => {
+ $('#cards').empty();
+ const startIndex = (pageIndex - 1) * pageSize;
+ const endIndex = pageIndex * pageSize;
+
+ const hexSubset = hexCodes.slice(startIndex, endIndex);
+ const promises = hexSubset.map((hex) => fetchData(hex));
+ try {
+ const pageColors = await Promise.all(promises);
+ pageColors.forEach((color) => {
+ const image = $('').attr({
+ src: color.image,
+ alt: color.name,
+ });
+ $('#cards').append(image);
+ });
+ } catch (error) {
+ console.error('Error rendering cards:', error);
+ }
+};
+
+$(() => {
+ for (let i = 0; i < total; i += 1) {
+ hexCodes.push(getRandomPastelColor());
+ }
+
+ const loadPanel = $('#load-panel')
+ .dxLoadPanel({
+ position: {
+ my: 'top',
+ at: 'top',
+ of: '#cards',
+ },
+ visible: false,
+ showIndicator: true,
+ showPane: true,
+ hideOnOutsideClick: false,
+ })
+ .dxLoadPanel('instance');
+
+ const pagination = $('#pagination')
+ .dxPagination({
+ showInfo: true,
+ showNavigationButtons: true,
+ itemCount: total,
+ pageIndex: 1,
+ pageSize: 5,
+ onOptionChanged: (e) => {
+ if (e.name === 'pageSize' || e.name === 'pageIndex') {
+ const pageIndex = pagination.option('pageIndex');
+ const pageSize = pagination.option('pageSize');
+ loadPanel.show();
+ renderCards(pageSize, pageIndex).finally(() => loadPanel.hide());
+ }
+ },
+ })
+ .dxPagination('instance');
+
+ const pageSize = pagination.option('pageSize');
+ const pageIndex = pagination.option('pageIndex');
+ loadPanel.show();
+ renderCards(pageSize, pageIndex).finally(() => loadPanel.hide());
+});
diff --git a/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/00 Getting Started with Pagination.md b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/00 Getting Started with Pagination.md
new file mode 100644
index 0000000000..cc7fea697b
--- /dev/null
+++ b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/00 Getting Started with Pagination.md
@@ -0,0 +1,13 @@
+#include tutorials-intro-installationnote
+
+Pagination is a UI component that allows users to navigate through pages and change page size at runtime.
+
+This tutorial explains how to add Pagination to a page and configure the component's core settings. It also covers implementing remote pagination. Colored cards are loaded each time a user switches pages or changes page size. The final result is displayed below:
+
+
+
+Each section in this tutorial describes a single configuration step. You can also find the full source code in the following GitHub repository:
+
+#include btn-open-github with {
+ href: "https://github.com/DevExpress-Examples/devextreme-getting-started-with-pagination"
+}
diff --git a/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/05 Create Pagination.md b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/05 Create Pagination.md
new file mode 100644
index 0000000000..04f1d2aff2
--- /dev/null
+++ b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/05 Create Pagination.md
@@ -0,0 +1,95 @@
+---
+##### jQuery
+[Add DevExtreme to your jQuery application](/concepts/58%20jQuery%20Components/05%20Add%20DevExtreme%20to%20a%20jQuery%20Application/00%20Add%20DevExtreme%20to%20a%20jQuery%20Application.md '/Documentation/Guide/jQuery_Components/Add_DevExtreme_to_a_jQuery_Application/') and use the following code to create a Pagination component:
+
+
+ $(function() {
+ $("#pagination").dxPagination({ });
+ });
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+##### Angular
+
+[Add DevExtreme to your Angular application](/concepts/40%20Angular%20Components/10%20Getting%20Started/03%20Add%20DevExtreme%20to%20an%20Angular%20CLI%20Application '/Documentation/Guide/Angular_Components/Getting_Started/Add_DevExtreme_to_an_Angular_CLI_Application/') and use the following code to create a Pagination component:
+
+
+
+
+
+ import { Component } from '@angular/core';
+
+ @Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+ })
+ export class AppComponent {
+
+ }
+
+
+ import { BrowserModule } from '@angular/platform-browser';
+ import { NgModule } from '@angular/core';
+ import { AppComponent } from './app.component';
+
+ import { DxPaginationModule } from 'devextreme-angular';
+
+ @NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule,
+ DxPaginationModule
+ ],
+ providers: [ ],
+ bootstrap: [AppComponent]
+ })
+ export class AppModule { }
+
+##### Vue
+
+[Add DevExtreme to your Vue application](/concepts/55%20Vue%20Components/05%20Add%20DevExtreme%20to%20a%20Vue%20Application/00%20Add%20DevExtreme%20to%20a%20Vue%20Application.md '/Documentation/Guide/Vue_Components/Add_DevExtreme_to_a_Vue_Application/') and use the following code to create a Pagination component:
+
+
+
+
+
+
+
+
+##### React
+
+[Add DevExtreme to your React application](/concepts/50%20React%20Components/05%20Add%20DevExtreme%20to%20a%20React%20Application/00%20Add%20DevExtreme%20to%20a%20React%20Application.md '/Documentation/Guide/React_Components/Add_DevExtreme_to_a_React_Application/') and use the following code to create a Pagination component:
+
+
+ import React from 'react';
+ import 'devextreme/dist/css/dx.light.css';
+ import { Pagination } from 'devextreme-react/pagination';
+
+ function App(): JSX.Element {
+ return (
+
+ );
+ }
+
+ export default App;
+
+---
\ No newline at end of file
diff --git a/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/10 Configure Pagination.md b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/10 Configure Pagination.md
new file mode 100644
index 0000000000..e14f961ee9
--- /dev/null
+++ b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/10 Configure Pagination.md
@@ -0,0 +1,100 @@
+This tutorial step guides you through the basic Pagination setup.
+
+Specify the following settings:
+
+* [itemCount](/Documentation/ApiReference/UI_Components/dxPagination/Configuration/#itemCount) sets the total number of items. Pagination does not function properly without this setting.
+* [pageIndex](/Documentation/ApiReference/UI_Components/dxPagination/Configuration/#pageIndex) sets the initial page to display. This tutorial sets **pageIndex** to 3 (the default value is 1).
+* [allowedPageSizes](/Documentation/ApiReference/UI_Components/dxPagination/Configuration/#allowedPageSizes) specifies page sizes available to users. Modify this list as needed. Include `'all'` to allow users to display all items on one page. This tutorial uses the default value: `[5, 10]`.
+* [pageSize](/Documentation/ApiReference/UI_Components/dxPagination/Configuration/#pageSize) specifies the initial page size.
+
+The following code snippet demonstrates how to apply the aforementioned settings:
+
+---
+##### jQuery
+
+
+ const total = 100;
+ $(() => {
+ const pagination = $('#pagination')
+ .dxPagination({
+ showInfo: true,
+ showNavigationButtons: true,
+ itemCount: total,
+ pageIndex: 3,
+ pageSize: 5,
+ })
+ .dxPagination('instance');
+ });
+
+##### Angular
+
+
+
+
+
+
+ import { Component } from '@angular/core';
+
+ @Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+ })
+ export class AppComponent {
+ total = 100;
+ pageIndex = 3;
+ pageSize = 5;
+ }
+
+##### Vue
+
+
+
+
+
+
+
+
+##### React
+
+
+ import React, { useState } from 'react';
+ // ...
+ const total = 100;
+
+ function App(): JSX.Element {
+ const [pageSize, setPageSize] = useState(5);
+ const [pageIndex, setPageIndex] = useState(3);
+ return (
+
+ );
+ }
+
+ export default App;
+
+---
\ No newline at end of file
diff --git a/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/15 Implement Remote Pagination/00 Implement Remote Pagination.md b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/15 Implement Remote Pagination/00 Implement Remote Pagination.md
new file mode 100644
index 0000000000..ffca7ffb24
--- /dev/null
+++ b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/15 Implement Remote Pagination/00 Implement Remote Pagination.md
@@ -0,0 +1,243 @@
+This section explains how to implement remote pagination. Client code generates a color list and requests a remote service for cards representing color entries on the screen. The pagination component helps users browse the resulting color cards.
+
+Implementation can be broken down into three steps:
+
+1. Generate 100 hex codes.
+2. Fetch color cards from [The Color API](https://www.thecolorapi.com/) service when necessary:
+ - On page load
+ - On page size changes
+ - On page index changes
+3. Display color cards obtained from the service.
+
+Implement the first step. Generate 100 random pastel hex codes and add them to an array:
+
+---
+##### jQuery
+
+
+ const hexCodes = [];
+
+ const getRandomPastelColor = () => {
+ const hue = Math.floor(Math.random() * 360);
+ const saturation = Math.random() * 0.4 + 0.2;
+ const brightness = Math.random() * 0.3 + 0.7;
+ return hsvToHex(hue, saturation, brightness);
+ };
+
+ const hsvToHex = (h, s, v) => {
+ let r = 0;
+ let g = 0;
+ let b = 0;
+ const i = Math.floor(h / 60);
+ const f = h / 60 - i;
+ const p = v * (1 - s);
+ const q = v * (1 - f * s);
+ const t = v * (1 - (1 - f) * s);
+ switch (i % 6) {
+ case 0: r = v; g = t; b = p; break;
+ case 1: r = q; g = v; b = p; break;
+ case 2: r = p; g = v; b = t; break;
+ case 3: r = p; g = q; b = v; break;
+ case 4: r = t; g = p; b = v; break;
+ case 5: r = v; g = p; b = q; break;
+ }
+ const toHex = (x) => {
+ const hex = Math.round(x * 255).toString(16);
+ return hex.length === 1 ? `0${hex}` : hex;
+ };
+ return toHex(r) + toHex(g) + toHex(b);
+ };
+ $(() => {
+ for (let i = 0; i < total; i += 1) {
+ hexCodes.push(getRandomPastelColor());
+ }
+
+ const pagination = $('#pagination')
+ .dxPagination({
+ // ...
+ })
+ .dxPagination('instance');
+ });
+
+##### Angular
+
+
+ import { Component } from '@angular/core';
+ import { ColorService } from './app.service';
+
+ @Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css'],
+ providers: [ColorService],
+ })
+ export class AppComponent {
+ // ...
+ hexCodes: string[] = [];
+
+ constructor(private readonly colorService: ColorService) {}
+
+ ngOnInit(): void {
+ this.generateHexCodes();
+ }
+
+ generateHexCodes(): void {
+ for (let i = 0; i < this.total; i++) {
+ this.hexCodes.push(this.colorService.getRandomPastelColor());
+ }
+ }
+ }
+
+
+ import { Injectable } from '@angular/core';
+
+ @Injectable({
+ providedIn: 'root',
+ })
+ export class ColorService {
+ private hsvToHex(h: number, s: number, v: number): string {
+ let r = 0;
+ let g = 0;
+ let b = 0;
+ const i = Math.floor(h / 60);
+ const f = h / 60 - i;
+ const p = v * (1 - s);
+ const q = v * (1 - f * s);
+ const t = v * (1 - (1 - f) * s);
+
+ switch (i % 6) {
+ case 0: [r, g, b] = [v, t, p]; break;
+ case 1: [r, g, b] = [q, v, p]; break;
+ case 2: [r, g, b] = [p, v, t]; break;
+ case 3: [r, g, b] = [p, q, v]; break;
+ case 4: [r, g, b] = [t, p, v]; break;
+ case 5: [r, g, b] = [v, p, q]; break;
+ }
+
+ const toHex = (x: number): string => Math.round(x * 255).toString(16).padStart(2, '0');
+ return `${toHex(r)}${toHex(g)}${toHex(b)}`;
+ }
+
+ getRandomPastelColor(): string {
+ const hue = Math.floor(Math.random() * 360);
+ const saturation = Math.random() * 0.4 + 0.2;
+ const brightness = Math.random() * 0.3 + 0.7;
+ return this.hsvToHex(hue, saturation, brightness);
+ }
+ }
+
+##### Vue
+
+
+
+
+
+
+
+
+
+ export const getRandomPastelColor = (): string => {
+ const hue = Math.floor(Math.random() * 360);
+ const saturation = Math.random() * 0.4 + 0.2;
+ const brightness = Math.random() * 0.3 + 0.7;
+ return hsvToHex(hue, saturation, brightness);
+ };
+
+ const hsvToHex = (h: number, s: number, v: number): string => {
+ let r: number, g: number, b: number;
+ const i = Math.floor(h / 60) % 6;
+ const f = h / 60 - i;
+ const p = v * (1 - s);
+ const q = v * (1 - f * s);
+ const t = v * (1 - (1 - f) * s);
+
+ switch (i) {
+ case 0: [r, g, b] = [v, t, p]; break;
+ case 1: [r, g, b] = [q, v, p]; break;
+ case 2: [r, g, b] = [p, v, t]; break;
+ case 3: [r, g, b] = [p, q, v]; break;
+ case 4: [r, g, b] = [t, p, v]; break;
+ case 5: [r, g, b] = [v, p, q]; break;
+ default: throw new Error("Unexpected case in HSV to RGB conversion");
+ }
+
+ const toHex = (x: number): string => Math.round(x * 255).toString(16).padStart(2, '0');
+ return `${toHex(r)}${toHex(g)}${toHex(b)}`;
+ };
+
+##### React
+
+
+ import React, { useState, useEffect } from 'react';
+ import { getRandomPastelColor } from './colorService';
+ // ...
+
+ function App(): JSX.Element {
+ // ...
+ const hexCodes = useRef([]);
+
+ useEffect(() => {
+ for (let i = 0; i < total; i++) {
+ hexCodes.current.push(getRandomPastelColor());
+ }
+ }, []);
+
+ return (
+
+ );
+ }
+
+ export default App;
+
+
+ export const getRandomPastelColor = (): string => {
+ const hue = Math.floor(Math.random() * 360);
+ const saturation = Math.random() * 0.4 + 0.2;
+ const brightness = Math.random() * 0.3 + 0.7;
+ return hsvToHex(hue, saturation, brightness);
+ };
+
+ const hsvToHex = (h: number, s: number, v: number): string => {
+ let r: number, g: number, b: number;
+ const i = Math.floor(h / 60) % 6;
+ const f = h / 60 - i;
+ const p = v * (1 - s);
+ const q = v * (1 - f * s);
+ const t = v * (1 - (1 - f) * s);
+
+ switch (i) {
+ case 0: [r, g, b] = [v, t, p]; break;
+ case 1: [r, g, b] = [q, v, p]; break;
+ case 2: [r, g, b] = [p, v, t]; break;
+ case 3: [r, g, b] = [p, q, v]; break;
+ case 4: [r, g, b] = [t, p, v]; break;
+ case 5: [r, g, b] = [v, p, q]; break;
+ default: throw new Error("Unexpected case in HSV to RGB conversion");
+ }
+
+ function toHex(x: number): string {
+ if (isNaN(x) || x < 0 || x > 1) {
+ return '00';
+ }
+ return Math.round(x * 255).toString(16).padStart(2, '0');
+ }
+ return `${toHex(r)}${toHex(g)}${toHex(b)}`;
+ };
+
+---
\ No newline at end of file
diff --git a/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/15 Implement Remote Pagination/05 Fetch Data.md b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/15 Implement Remote Pagination/05 Fetch Data.md
new file mode 100644
index 0000000000..102e8d68a3
--- /dev/null
+++ b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/15 Implement Remote Pagination/05 Fetch Data.md
@@ -0,0 +1,103 @@
+The following code snippet demonstrates how to fetch data from the Color API:
+
+---
+##### jQuery
+
+
+ // ...
+ const apiEndpoint = 'https://www.thecolorapi.com/id?hex=';
+ const cache = new Map();
+
+ function fetchData(colorId) {
+ return new Promise((resolve, reject) => {
+ if (cache.has(colorId)) {
+ resolve(cache.get(colorId));
+ } else {
+ $.getJSON(apiEndpoint + colorId, (data) => {
+ const colorData = {
+ image: data.image.bare,
+ name: data.name.value,
+ };
+ cache.set(colorId, colorData);
+ resolve(colorData);
+ }).fail(() => {
+ reject(new Error(`Error loading color for hex: ${colorId}`));
+ });
+ }
+ });
+ }
+
+ $(() => {
+ // ...
+ const pagination = $('#pagination')
+ .dxPagination({
+ // ...
+ })
+ .dxPagination('instance');
+ });
+
+##### Angular
+
+
+ import { Injectable } from '@angular/core';
+
+ @Injectable({
+ providedIn: 'root',
+ })
+ export class ColorService {
+ // ...
+ fetchColorData(hex: string): Observable {
+ return this.http.get(`${this.apiEndpoint}${hex}`)
+ .pipe(
+ catchError((error: any) => throwError(() => new Error(`Error fetching color: ${error.message || error}`))),
+ )
+ .pipe(map((data: any) => ({
+ name: data.name.value,
+ image: data.image.bare,
+ })));
+ }
+ }
+
+##### Vue
+
+
+ import axios from 'axios';
+
+ const apiEndpoint = 'https://www.thecolorapi.com/id?hex=';
+
+ export const fetchColorData = async (
+ hex: string,
+ ): Promise<{ name: string; image: string } | null> => {
+ try {
+ const response = await axios.get(`${apiEndpoint}${hex}`);
+ return {
+ name: response.data.name.value,
+ image: response.data.image.bare,
+ };
+ } catch (error) {
+ console.error(`Error fetching color for hex ${hex}:`, error);
+ return null;
+ }
+ };
+
+##### React
+
+
+ import axios from 'axios';
+
+ const apiEndpoint = 'https://www.thecolorapi.com/id?hex=';
+
+ export async function fetchColorData(hex: string): Promise<{ name: string; image: string } | null> {
+ try {
+ const response = await axios.get(`${apiEndpoint}${hex}`);
+ return {
+ name: response.data.name.value,
+ image: response.data.image.bare,
+ };
+ } catch (error) {
+ console.error(`Error fetching color for hex ${hex}:`, error);
+ return null;
+ }
+ }
+
+---
\ No newline at end of file
diff --git a/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/15 Implement Remote Pagination/10 Render Items.md b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/15 Implement Remote Pagination/10 Render Items.md
new file mode 100644
index 0000000000..5144b41e22
--- /dev/null
+++ b/concepts/05 UI Components/Pagination/05 Getting Started with Pagination/15 Implement Remote Pagination/10 Render Items.md
@@ -0,0 +1,260 @@
+The render function determines the subset of cards to be displayed and populates the array with images and alt strings.
+
+---
+##### jQuery
+
+
+
+
+
+
+
+
+
+
+
+
+
+ const renderCards = async (pageSize, pageIndex) => {
+ $('#cards').empty();
+ const startIndex = (pageIndex - 1) * pageSize;
+ const endIndex = pageIndex * pageSize;
+
+ const hexSubset = hexCodes.slice(startIndex, endIndex);
+ const promises = hexSubset.map((hex) => fetchData(hex));
+ try {
+ const pageColors = await Promise.all(promises);
+ pageColors.forEach((color) => {
+ const image = $('').attr({
+ src: color.image,
+ alt: color.name,
+ });
+ $('#cards').append(image);
+ });
+ } catch (error) {
+ console.error('Error rendering cards:', error);
+ }
+ };
+
+ $(() => {
+ const pagination = $('#pagination')
+ .dxPagination({
+ // ...
+ })
+ .dxPagination('instance');
+
+ const pageSize = pagination.option('pageSize');
+ const pageIndex = pagination.option('pageIndex');
+ renderCards(pageSize, pageIndex);
+ });
+
+
+ #cards {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ }
+
+##### Angular
+
+
+
+
+
+
+
+
+
+
+ import { Component } from '@angular/core';
+ import { firstValueFrom } from 'rxjs';
+ import { ColorService, Color } from './app.service';
+
+ @Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css'],
+ providers: [ColorService],
+ })
+ export class AppComponent {
+ // ...
+ colors: Map = new Map();
+ visibleCards: Color[] = [];
+
+ constructor(private readonly colorService: ColorService) {}
+
+ ngOnInit(): void {
+ // ...
+ void this.fetchColorsForPage();
+ }
+
+ async fetchColorsForPage(): Promise {
+ const startIndex = (this.pageIndex - 1) * this.pageSize;
+ const endIndex = this.pageIndex * this.pageSize;
+ const hexSubset = this.hexCodes.slice(startIndex, endIndex);
+
+ const promises: Promise[] = hexSubset.map((hex) => {
+ if (this.colors.has(hex)) {
+ return Promise.resolve(this.colors.get(hex)!);
+ } else {
+ return firstValueFrom(this.colorService.fetchColorData(hex)).then((data) => {
+ const colorData: Color = data;
+ this.colors.set(hex, colorData);
+ return colorData;
+ });
+ }
+ });
+
+ try {
+ const fetchedColors = await Promise.all(promises);
+ this.visibleCards = fetchedColors;
+ } catch (error) {
+ console.error('Error fetching colors:', error);
+ }
+ }
+ }
+
+
+ // ...
+ export interface Color {
+ image: string;
+ name: string;
+ }
+
+
+ #cards {
+ display: flex;
+ justify-content: center;
+ flex-wrap: wrap;
+ }
+
+##### Vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+##### React
+
+
+ import React, { useState, useRef, useEffect } from 'react';
+ // ...
+ interface Color {
+ image: string;
+ name: string;
+ }
+
+ function App(): JSX.Element {
+ // ...
+ const [visibleCards, setVisibleCards] = useState([]);
+ const colorsCache = useRef