-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #84 from pegasystems/image_carousel
Image carousel
- Loading branch information
Showing
9 changed files
with
847 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from 'react'; | ||
import { ButtonPrev, ButtonNext } from './styles'; | ||
|
||
type SliderControlsProps = { | ||
prevSlide: () => void; | ||
nextSlide: () => void; | ||
}; | ||
|
||
const SliderControls: React.FC<SliderControlsProps> = ({ prevSlide, nextSlide }) => ( | ||
<> | ||
<ButtonPrev onClick={prevSlide} aria-label="Previous Slide"> | ||
❮ | ||
</ButtonPrev> | ||
<ButtonNext onClick={nextSlide} aria-label="Next Slide"> | ||
❯ | ||
</ButtonNext> | ||
</> | ||
); | ||
|
||
export default SliderControls; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { Meta, Primary, Controls, Story } from '@storybook/blocks'; | ||
import * as DemoStories from './demo.stories'; | ||
|
||
<Meta of={DemoStories} /> | ||
|
||
# Overview | ||
|
||
The Image Carousel Component is a dynamic and flexible Carousel designed for Pega Constellation applications. It fetches images from a Data Page as a source, allowing developers to display a collection of images in a rotating slideshow format. This component supports configurable height, transition effects, and dynamic image handling. Its responsive design ensures that it adjusts automatically to different screen sizes, making it an ideal solution for creating engaging, dynamic visual content in your Pega applications. | ||
|
||
<Primary /> | ||
|
||
## Props | ||
|
||
<Controls /> | ||
|
||
# Deployment and Integration Instructions:- | ||
|
||
**1. Create a Data Type for the Carousel** | ||
|
||
To manage and display the images in the Carousel component, create a Data Type in Pega **(Example: Carousel)** with the following columns: | ||
|
||
- **Id:** Unique identifier for the image. | ||
|
||
- **Title:** Optional title or caption of the image. | ||
|
||
- **Description:** Optional description or metadata for the image. | ||
|
||
- **Image URL:** URL of the image to be displayed in the Carousel. | ||
|
||
- **Visible:** Boolean field to indicate if the image should be shown in the Carousel. | ||
|
||
Each entry in the Data Type corresponds to an image, allowing for easy updates and management of the content. | ||
|
||
Users will create a custom list Data Page **(D_CarouselsList)** that retrieves records filtered by visibility, using a report definition **(RD_VisibleCarousels)**. This ensures that only Carousels with **Visible = true** are displayed, and it can be seamlessly integrated into components like the Image Carousel for a dynamic user experience. | ||
|
||
**2. Component Configuration** | ||
|
||
Add the Carousel component to your **Landing Page** and **Summary panel** using the following configuration: | ||
|
||
- **Data Page:** Specify the Data Page **(Example:- D_CarouselList.pxResults)** | ||
|
||
- **Image Source:** Specify the image property. | ||
|
||
- **Title:** Specify the Title property. | ||
|
||
- **Description:** Specify the Description property. | ||
|
||
# Limitations and Enhancements | ||
|
||
The limitations of the component are: | ||
|
||
- **Keyboard navigation:** | ||
No support for keyboard navigation and screen reader compatibility to ensure the Carousel is usable by individuals with disabilities. | ||
|
||
- **Font Size:** There is no option to change the font size for the title and description. | ||
|
||
- **Font Type:** The components do not support changing the font family for the title and description. | ||
|
||
- **Font Color:** There is no capability to modify the font color for the title and description. | ||
|
||
Ideas for enhancements are: | ||
|
||
- **Video Support:** | ||
Extend the Carousel to support video content alongside images, offering a richer multimedia experience. | ||
|
||
- **Customizable Transitions:** | ||
Developers can create and apply their transition effects beyond the built-in options. | ||
|
||
- **Thumbnail Navigation:** | ||
Provide a thumbnail view of all Carousel items, allowing users to quickly jump to a specific slide. | ||
|
||
- **Interactive Elements:** | ||
Incorporate interactive features like hotspots or clickable areas within Carousel images to enhance engagement. | ||
|
||
# Example Use Cases | ||
|
||
- **Product Gallery:** Display a Carousel of product images that update based on user selections or current promotions. | ||
|
||
- **User Profile Carousel:** Show a collection of user-uploaded photos or media. | ||
|
||
- **Dynamic Advertisements:** Rotating Carousel for dynamic ad Carousels or promotions fetched from a backend system. | ||
|
||
# Contributors | ||
|
||
This component was contributed by Khozema Nagdi working with [Bits In Glass | www.bitsinglass.com](https://www.bitsinglass.com) |
26 changes: 26 additions & 0 deletions
26
src/components/Pega_Extensions_ImageCarousel/DotsNavigation.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import React from 'react'; | ||
import { Dot, DotsContainer } from './styles'; | ||
|
||
type DotsNavigationProps = { | ||
imageSliderData: { id: string | number | null | undefined }[]; | ||
currentSlide: number; | ||
showSlide: (index: number) => void; | ||
}; | ||
|
||
const DotsNavigation: React.FC<DotsNavigationProps> = ({ | ||
imageSliderData, | ||
currentSlide, | ||
showSlide, | ||
}) => ( | ||
<DotsContainer> | ||
{imageSliderData.map((slide, index) => ( | ||
<Dot | ||
key={slide.id ? slide.id : `dot-${index}`} | ||
onClick={() => showSlide(index)} | ||
active={currentSlide === index} | ||
/> | ||
))} | ||
</DotsContainer> | ||
); | ||
|
||
export default DotsNavigation; |
34 changes: 34 additions & 0 deletions
34
src/components/Pega_Extensions_ImageCarousel/SlideItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React from 'react'; | ||
import { Slide, SlideImage, SliderTextContainer } from './styles'; | ||
|
||
type SlideItemProps = { | ||
slide: { | ||
title: string; | ||
description: string; | ||
imageURL: string | undefined; | ||
}; | ||
animationClass: string; | ||
isActive: boolean; | ||
objectFit?: string; | ||
textPosition?: string; | ||
}; | ||
|
||
const SlideItem: React.FC<SlideItemProps> = ({ | ||
slide, | ||
animationClass, | ||
isActive, | ||
objectFit, | ||
textPosition = 'Center' | ||
}) => { | ||
return ( | ||
<Slide animationClass={animationClass} style={{ display: isActive ? 'block' : '' }}> | ||
<SliderTextContainer position={textPosition}> | ||
<h2 title='This is image slide title'>{slide.title}</h2> | ||
<p>{slide.description}</p> | ||
</SliderTextContainer> | ||
<SlideImage src={slide.imageURL} alt={`Slide ${slide.title}`} objectFit={objectFit} /> | ||
</Slide> | ||
); | ||
}; | ||
|
||
export default SlideItem; |
138 changes: 138 additions & 0 deletions
138
src/components/Pega_Extensions_ImageCarousel/config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
{ | ||
"name": "Pega_Extensions_Image_Carousel", | ||
"label": "Image carousel", | ||
"description": "Image carousel", | ||
"organization": "Pega", | ||
"version": "1.0.0", | ||
"library": "Extensions", | ||
"allowedApplications": [], | ||
"type": "Widget", | ||
"subtype": ["PAGE", "CASE"], | ||
"properties": [ | ||
{ | ||
"name": "datasource", | ||
"label": "Data source for Carousel", | ||
"defaultValue": "@DATASOURCE D_pyAnnouncements.pxResults", | ||
"format": "DATASOURCE", | ||
"required": true, | ||
"properties": [ | ||
{ | ||
"name": "imageURL", | ||
"label": "Image URL", | ||
"required": true, | ||
"defaultValue": "@P .pyImageURL" | ||
}, | ||
{ | ||
"name": "title", | ||
"label": "Image Title", | ||
"required": false, | ||
"defaultValue": "@P .pyTitle" | ||
}, | ||
{ | ||
"name": "description", | ||
"label": "Image Description", | ||
"required": false, | ||
"defaultValue": "@P .pyDescription" | ||
} | ||
] | ||
}, | ||
{ | ||
"name": "height", | ||
"label": "Minimum height of the Carousel", | ||
"format": "TEXT", | ||
"required": true | ||
}, | ||
{ | ||
"format": "SELECT", | ||
"label": "Text Position", | ||
"name": "textPosition", | ||
"defaultValue": "TopLeft", | ||
"required": true, | ||
"source": [ | ||
{ "key": "TopLeft", "value": "Top Left" }, | ||
{ "key": "TopCenter", "value": "Top Center" }, | ||
{ "key": "TopRight", "value": "Top Right" }, | ||
{ "key": "CenterLeft", "value": "Center Left" }, | ||
{ "key": "Center", "value": "Center" }, | ||
{ "key": "CenterRight", "value": "Center Right" }, | ||
{ "key": "BottomLeft", "value": "Bottom Left" }, | ||
{ "key": "BottomCenter", "value": "Bottom Center" }, | ||
{ "key": "BottomRight", "value": "Bottom Right" } | ||
] | ||
}, | ||
{ | ||
"format": "SELECT", | ||
"label": "Object Fit", | ||
"name": "objectFit", | ||
"defaultValue": "cover", | ||
"required": true, | ||
"source": [ | ||
{ "key": "fill", "value": "Fill" }, | ||
{ "key": "contain", "value": "Contain" }, | ||
{ "key": "cover", "value": "Cover" }, | ||
{ "key": "none", "value": "None" }, | ||
{ "key": "scale-down", "value": "Scale Down" } | ||
] | ||
}, | ||
{ | ||
"format": "BOOLEAN", | ||
"label": "Autoplay", | ||
"name": "autoplay", | ||
"defaultValue": false | ||
}, | ||
{ | ||
"name": "autoplayDuration", | ||
"label": "Autoplay Duration (ms)", | ||
"format": "INTEGER", | ||
"defaultValue": 3000 | ||
}, | ||
{ | ||
"format": "SELECT", | ||
"label": "Control Type", | ||
"name": "controlType", | ||
"defaultValue": "Dots", | ||
"required": true, | ||
"source": [ | ||
{ "key": "None", "value": "None" }, | ||
{ "key": "Dots", "value": "Dots" }, | ||
{ "key": "Buttons", "value": "Buttons" }, | ||
{ "key": "Both", "value": "Both" } | ||
] | ||
}, | ||
{ | ||
"format": "SELECT", | ||
"label": "Animation Type", | ||
"name": "animationType", | ||
"defaultValue": "fade-in", | ||
"required": true, | ||
"source": [ | ||
{ "key": "fade-in", "value": "Fade In" }, | ||
{ "key": "fade-out", "value": "Fade Out" }, | ||
{ "key": "slide-in", "value": "Slide In" }, | ||
{ "key": "slide-out", "value": "Slide Out" }, | ||
{ "key": "zoom-in", "value": "Zoom In" }, | ||
{ "key": "zoom-out", "value": "Zoom Out" }, | ||
{ "key": "bounce", "value": "Bounce" }, | ||
{ "key": "shake", "value": "Shake" } | ||
] | ||
}, | ||
{ | ||
"label": "Conditions", | ||
"format": "GROUP", | ||
"properties": [ | ||
{ | ||
"name": "visibility", | ||
"label": "Visibility", | ||
"format": "VISIBILITY" | ||
} | ||
] | ||
} | ||
], | ||
"defaultConfig": { | ||
"height": "40rem", | ||
"controlType": "dots", | ||
"Autoplay": "yes", | ||
"autoplayDuration": "3000", | ||
"label": "Image Carousel" | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
src/components/Pega_Extensions_ImageCarousel/demo.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import type { StoryObj } from '@storybook/react'; | ||
import { PegaExtensionsImageCarousel } from './index'; | ||
|
||
export default { | ||
title: 'Widgets/Image Carousel', | ||
argTypes: { | ||
datasource: { | ||
table: { | ||
disable: true | ||
} | ||
}, | ||
getPConnect: { | ||
table: { | ||
disable: true | ||
} | ||
} | ||
}, | ||
component: PegaExtensionsImageCarousel | ||
}; | ||
|
||
const setPCore = () => { | ||
(window as any).PCore = { | ||
/* Nothing */ | ||
}; | ||
}; | ||
|
||
type Story = StoryObj<typeof PegaExtensionsImageCarousel>; | ||
|
||
export const Default: Story = { | ||
render: args => { | ||
setPCore(); | ||
const props = { | ||
...args, | ||
datasource: { | ||
source: [ | ||
{ | ||
imageURL: | ||
'https://images.pexels.com/photos/1166644/pexels-photo-1166644.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1', | ||
description: 'Description for Image 1', | ||
title: 'Title for Image 1' | ||
}, | ||
{ | ||
imageURL: | ||
'https://images.pexels.com/photos/1166644/pexels-photo-1166644.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1', | ||
description: 'Description for Image 2', | ||
title: 'Title for Image 2' | ||
}, | ||
{ | ||
imageURL: | ||
'https://images.pexels.com/photos/1166644/pexels-photo-1166644.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1', | ||
description: 'Description for Image 3', | ||
title: 'Title for Image 3' | ||
} | ||
], | ||
fields: {} | ||
} | ||
}; | ||
return <PegaExtensionsImageCarousel {...props} />; | ||
}, | ||
args: { | ||
height: '40rem', | ||
textPosition: 'Center', | ||
objectFit: 'cover', | ||
autoplay: true, | ||
autoplayDuration: 3000, | ||
controlType: 'Dots', | ||
animationType: 'fade-in' | ||
} | ||
}; |
10 changes: 10 additions & 0 deletions
10
src/components/Pega_Extensions_ImageCarousel/demo.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { render, screen } from '@testing-library/react'; | ||
import { composeStories } from '@storybook/react'; | ||
import * as DemoStories from './demo.stories'; | ||
|
||
const { Default } = composeStories(DemoStories); | ||
|
||
test('renders the Image Carousel with default args', async () => { | ||
render(<Default />); | ||
expect(await screen.findByText('Title for Image 1')).toBeVisible(); | ||
}); |
Oops, something went wrong.