From 628dbca22d8bad0fbf78203c0facebc1ce949b70 Mon Sep 17 00:00:00 2001 From: Mandeep Virdi Date: Tue, 8 Oct 2024 16:54:40 +0530 Subject: [PATCH 1/6] First version of pega slider --- .../Pega_Extensions_PegaSlider/Docs.mdx | 95 +++++++ .../DotsNavigation.tsx | 26 ++ .../OneColumnPage.svg | 36 +++ .../PConnProps.d.ts | 45 +++ .../Pega_Extensions_PegaSlider/SlideItem.tsx | 37 +++ .../Pega_Extensions_PegaSlider/Slider.tsx | 104 +++++++ .../SliderControls.tsx | 20 ++ .../Pega_Extensions_PegaSlider/config.json | 138 +++++++++ .../demo.stories.tsx | 70 +++++ .../Pega_Extensions_PegaSlider/index.tsx | 47 ++++ .../Pega_Extensions_PegaSlider/mock.ts | 65 +++++ .../Pega_Extensions_PegaSlider/styles.ts | 264 ++++++++++++++++++ 12 files changed, 947 insertions(+) create mode 100644 src/components/Pega_Extensions_PegaSlider/Docs.mdx create mode 100644 src/components/Pega_Extensions_PegaSlider/DotsNavigation.tsx create mode 100644 src/components/Pega_Extensions_PegaSlider/OneColumnPage.svg create mode 100644 src/components/Pega_Extensions_PegaSlider/PConnProps.d.ts create mode 100644 src/components/Pega_Extensions_PegaSlider/SlideItem.tsx create mode 100644 src/components/Pega_Extensions_PegaSlider/Slider.tsx create mode 100644 src/components/Pega_Extensions_PegaSlider/SliderControls.tsx create mode 100644 src/components/Pega_Extensions_PegaSlider/config.json create mode 100644 src/components/Pega_Extensions_PegaSlider/demo.stories.tsx create mode 100644 src/components/Pega_Extensions_PegaSlider/index.tsx create mode 100644 src/components/Pega_Extensions_PegaSlider/mock.ts create mode 100644 src/components/Pega_Extensions_PegaSlider/styles.ts diff --git a/src/components/Pega_Extensions_PegaSlider/Docs.mdx b/src/components/Pega_Extensions_PegaSlider/Docs.mdx new file mode 100644 index 0000000..1f5b37a --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/Docs.mdx @@ -0,0 +1,95 @@ +Image Carousel Component for Pega Constellation + + +## Overview + +The Image Carousel Component is a dynamic and flexible carousel designed for Pega Constellation applications. It fetches images from a (Example:- D_YourDataPage) data 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. + +## Key Features + +1. Height Customization + The height of the carousel is fully customizable to fit the design requirements of your Pega application. The height can be set using fixed units (e.g. rem ). + +2. Text Positioning Options + Choose from various text alignment options for your carousel: + Top Left: Position the carousel in the top left corner. + Top Center: Center the carousel at the top. + Top Right: Align the carousel in the top right corner. + Center Left: Place the carousel on the left side, vertically centered. + Center: Center the carousel both vertically and horizontally. + Center Right: Position the carousel on the right side, vertically centered. + Bottom Left: Align the carousel in the bottom left corner. + Bottom Center: Center the carousel at the bottom. + Bottom Right: Position the carousel in the bottom right corner. + +3. Object Fit Options + Control how images are displayed within the carousel with the following settings: + Fill: Stretches the image to fill the entire carousel area. + Contain: Scales the image to fit within the carousel while maintaining its aspect ratio. + Cover: Scales the image to cover the entire carousel, cropping as needed to maintain the aspect ratio. + None: Displays the image in its original size, without scaling. + Scale Down: Scales the image down to fit within the carousel only if it exceeds its original dimensions. + +4. Autoplay + Enable or disable autoplay functionality: + Yes: Automatically cycles through items at a set interval. + No: Requires manual navigation to view items. + +5. Autoplay Duration (ms) + Set the duration (in milliseconds) for how long each item is displayed before transitioning to the next one during autoplay. + +6. Control Type + Select the type of navigation controls for the carousel: + None: No navigation controls displayed. + Button: Includes next/previous buttons for manual navigation. + Dots: Displays dot indicators representing each item in the carousel. + Both: Combines buttons and dot indicators for versatile navigation. + +7. Animation Type + Select the type of animation for transitions between carousel items: + Fade In: Gradually appears with a fade effect. + Fade Out: Gradually disappears with a fade effect. + Slide In: Slides in from a specific direction. + Slide Out: Slides out to a specific direction. + Zoom In: Gradually enlarges the item as it appears. + Zoom Out: Gradually reduces the item as it disappears. + Bounce: Bounces in or out for a playful effect. + Shake: Shakes the item for a dynamic transition. + +## 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: Banner) 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_BannersList) that retrieves records filtered by visibility, using a report definition (RD_VisibleBanners). This ensures that only banners 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_BannerList.pxResults) + Image Source:- Specify the image property. + Title:- Specify the Title property. + Description:- Specify the Description property. + + + +## Limitations + +The limitations of the components are: + +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. + + +## 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 banners or promotions fetched from a backend system. diff --git a/src/components/Pega_Extensions_PegaSlider/DotsNavigation.tsx b/src/components/Pega_Extensions_PegaSlider/DotsNavigation.tsx new file mode 100644 index 0000000..16bb37d --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/DotsNavigation.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Dot, DotsContainer } from './styles'; + +type DotsNavigationProps = { + imageSliderData: { id: string | number | null | undefined }[]; // Add the id type + currentSlide: number; + showSlide: (index: number) => void; +}; + +const DotsNavigation: React.FC = ({ + imageSliderData, // Receive image slider data to get ids + currentSlide, + showSlide, +}) => ( + + {imageSliderData.map((slide, index) => ( + showSlide(index)} + active={currentSlide === index} + /> + ))} + +); + +export default DotsNavigation; diff --git a/src/components/Pega_Extensions_PegaSlider/OneColumnPage.svg b/src/components/Pega_Extensions_PegaSlider/OneColumnPage.svg new file mode 100644 index 0000000..5f2dec9 --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/OneColumnPage.svg @@ -0,0 +1,36 @@ + + + 1 col + + + + + + + + + + + + + + + + + + + + + + + + + A + + + + + + + + \ No newline at end of file diff --git a/src/components/Pega_Extensions_PegaSlider/PConnProps.d.ts b/src/components/Pega_Extensions_PegaSlider/PConnProps.d.ts new file mode 100644 index 0000000..aa913e3 --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/PConnProps.d.ts @@ -0,0 +1,45 @@ +import { PConnect } from '@pega/pcore-pconnect-typedefs'; + +// PConnProps.d.ts +// This gives us a place to have each component (which is most DX Components) that is +// expected to have a getPConnect extend its props (from BaseProps) +// such that every component will be expected to have a getPConnect() function +// that returns a PConnect object. (new/better way of doing .propTypes). +// This PConnProps can be extended to include other props that we know are in every component +export interface PConnProps { + // getPConnect should exist for every C11n component. (add @ts-ignore in special cases where it isn't) + getPConnect: () => typeof PConnect; + + // Allow any/all other key/value pairs in the BaseProps for now + // TODO: refine which other props are always expected for various component + // types and consider further interface "subclassing". For example, we may + // want to create a "BasePropsForm" that gives guidance on required, readonly, etc. + // and any other props that every Form component expects. + // For example, see the PConnFieldProps below. + // NOTE: if you uncomment the line below, the PConnProps type will allow + // otherwise undefined types to appear. This can be helpful for debugging + // or when adding new components whose types aren't yet known. + // [key: string]: any; +} + +// PConnFieldProps extends PConnProps to bring in the common properties that are +// associated with most field components (ex: Dropdown, TextInput, etc.) in the +// components/field directory +export interface PConnFieldProps extends PConnProps { + label: string; + required: boolean; + disabled: boolean; + value: any; + validatemessage: string; + status?: string; + onChange?: any; + onBlur?: any; + readOnly: boolean; + testId: string; + helperText: string; + displayMode?: string; + hideLabel: boolean; + placeholder?: string; + fieldMetadata?: any; + additionalProps?: any; +} diff --git a/src/components/Pega_Extensions_PegaSlider/SlideItem.tsx b/src/components/Pega_Extensions_PegaSlider/SlideItem.tsx new file mode 100644 index 0000000..5583d26 --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/SlideItem.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { Slide, SlideImage, SliderTextContainer } from './styles'; + +type SlideItemProps = { + slide: { + title: React.ReactNode; // Updated to ReactNode for flexibility + description: React.ReactNode; // Updated to ReactNode for flexibility + imageURL: string | undefined; + }; + animationClass: string; + isActive: boolean; + objectFit?: string; + textPosition?: string; +}; + +const SlideItem: React.FC = ({ + slide, + animationClass, + isActive, + objectFit, + textPosition = 'Center', +}) => { + return ( + + +

{slide.title}

+

{slide.description}

+
+ +
+ ); +}; + +export default SlideItem; diff --git a/src/components/Pega_Extensions_PegaSlider/Slider.tsx b/src/components/Pega_Extensions_PegaSlider/Slider.tsx new file mode 100644 index 0000000..a622a51 --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/Slider.tsx @@ -0,0 +1,104 @@ + +import React, { useState, useEffect, useCallback } from 'react'; +import { SliderContainer, SliderWrapper } from './styles'; +import SlideItem from './SlideItem'; +import SliderControls from './SliderControls'; +import DotsNavigation from './DotsNavigation'; + +type PegaSliderProps = { + imageData: { source: any }; + height?: string; + animationType?: string; + controlType?: any; + autoplay?: string; // New prop for autoplay + autoplayDuration?: number; + objectFit?: string; + textPosition?: string; +}; + +const PegaSlider: React.FC = ({ + imageData, + height, + controlType, + autoplay, + autoplayDuration = 3000, + objectFit, + textPosition = 'TopLeft', + animationType = 'fade-in', +}) => { + const imageSliderData = imageData?.source || []; + +// eslint-disable-next-line no-console +console.log(imageSliderData, 'imageSliderData DX page') + + + const [currentSlide, setCurrentSlide] = useState(0); + const [animationClass, setAnimationClass] = useState(animationType); + + const totalSlides = imageSliderData.length; + + const showSlide = useCallback( + (index: number) => { + setAnimationClass(animationType); // Start fade-out animation + setTimeout(() => { + setCurrentSlide((index + totalSlides) % totalSlides); // Change the slide after animation + setAnimationClass(animationType); // Reset to fade-in animation + }, 500); // Match this duration with your CSS animation duration + }, + [animationType, totalSlides] + ); + + const prevSlide = () => showSlide(currentSlide - 1); + const nextSlide = useCallback(() => { + showSlide(currentSlide + 1); + }, [currentSlide, showSlide]); + + // Autoplay functionality + useEffect(() => { + if (autoplay === 'true' && totalSlides > 1) { + const autoplayTimer = setInterval(() => { + nextSlide(); + }, autoplayDuration); + + return () => clearInterval(autoplayTimer); + } + }, [autoplay, totalSlides, nextSlide, autoplayDuration]); + + return ( + + + {imageSliderData.map( + (slide: { + id: string | null | undefined; + title: React.ReactNode; + description: React.ReactNode; + imageURL: string | undefined; + }) => ( + + ) + )} + + + {(controlType === 'Buttons' || controlType === 'Both') && ( + + )} + + {(controlType === 'Dots' || controlType === 'Both') && ( + + )} + + ); +}; + +export default PegaSlider; diff --git a/src/components/Pega_Extensions_PegaSlider/SliderControls.tsx b/src/components/Pega_Extensions_PegaSlider/SliderControls.tsx new file mode 100644 index 0000000..c1a7db2 --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/SliderControls.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { ButtonPrev, ButtonNext } from './styles'; + +type SliderControlsProps = { + prevSlide: () => void; + nextSlide: () => void; +}; + +const SliderControls: React.FC = ({ prevSlide, nextSlide }) => ( + <> + + ❮ + + + ❯ + + +); + +export default SliderControls; diff --git a/src/components/Pega_Extensions_PegaSlider/config.json b/src/components/Pega_Extensions_PegaSlider/config.json new file mode 100644 index 0000000..77fc97e --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/config.json @@ -0,0 +1,138 @@ +{ + "name": "Pega_Extensions_PegaSlider", + "label": "Pega Slider", + "description": "Pega Slider", + "organization": "Pega", + "version": "1.0.0", + "library": "Extensions", + "allowedApplications": [], + "componentKey": "Pega_Extensions_PegaSlider", + "type": "Widget", + "subtype": ["PAGE", "CASE"], + "icon": "OneColumnPage.svg", + "properties": [ + { + "name": "datasource", + "label": "Data source for Banner", + "defaultValue": "@DATASOURCE D_pyAnnouncements.pxResults", + "format": "DATASOURCE", + "properties": [ + { + "name": "imageURL", + "label": "Image URL", + "required": true, + "defaultValue": "@P .pyImageURL" + }, + { + "name": "description", + "label": "Image Description", + "required": false, + "defaultValue": "@P .pyDescription" + }, + { + "name": "title", + "label": "Image Title", + "required": false, + "defaultValue": "@P .pyTitle" + } + ] + }, + { + "name": "height", + "label": "Minimum height of the Banner", + "format": "TEXT" + }, + { + "format": "SELECT", + "label": "Text Position", + "name": "textPosition", + "defaultValue": "TopLeft", + "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", + "source": [ + { "key": "fill", "value": "Fill" }, + { "key": "contain", "value": "Contain" }, + { "key": "cover", "value": "Cover" }, + { "key": "none", "value": "None" }, + { "key": "scale-down", "value": "Scale Down" } + ] + }, + { + "format": "SELECT", + "label": "Autoplay", + "name": "autoplay", + "defaultValue": "false", + "source": [ + { "key": "true", "value": "Yes" }, + { "key": "false", "value": "No" } + ] + }, + { + "name": "autoplayDuration", + "label": "Autoplay Duration (ms)", + "format": "TEXT", + "defaultValue": "3000" + }, + { + "format": "SELECT", + "label": "Control Type", + "name": "controlType", + "defaultValue": "Dots", + "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", + "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": "Pega Slider" + } +} diff --git a/src/components/Pega_Extensions_PegaSlider/demo.stories.tsx b/src/components/Pega_Extensions_PegaSlider/demo.stories.tsx new file mode 100644 index 0000000..4e10fb2 --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/demo.stories.tsx @@ -0,0 +1,70 @@ +/* eslint-disable react/jsx-no-useless-fragment */ +// @ts-nocheck +import type { Meta, StoryObj } from '@storybook/react'; + +import PegaExtensionsPegaSlider from './index'; +import { configProps, operatorDetails } from './mock'; + +const meta: Meta = { + title: 'PegaExtensionsPegaSlider', + component: PegaExtensionsPegaSlider, + excludeStories: /.*Data$/, +}; + +export default meta; + +type Story = StoryObj; + +if (!window.PCore) { + window.PCore = {}; +} + +window.PCore.getLocaleUtils = () => { + return { + getLocaleValue: value => { + return value; + } + }; +}; + +window.PCore.getUserApi = () => { + return { + getOperatorDetails: () => { + return Promise.resolve(operatorDetails); + } + }; +}; + +export const BasePegaExtensionsPegaSlider: Story = args => { + const props = { + datasource: configProps.datasource, + height: configProps.height, + textPosition: configProps.textPosition, + objectFit: configProps.objectFit, + autoplay: configProps.autoplay, + autoplayDuration: configProps.autoplayDuration, + controlType: configProps.controlType, + animationType: configProps.animationType, + visibility: configProps.visibility, + label: configProps.label, // Include label if needed + }; + + return ( + <> + + + ); +}; + +// Default args for the Storybook story +BasePegaExtensionsPegaSlider.args = { + height: '40rem', + textPosition: 'Center', + objectFit: 'cover', + autoplay: true, + autoplayDuration: '3000', + controlType: 'Dots', + animationType: 'fade-in', + visibility: true, + label: 'Pega Slider', +}; diff --git a/src/components/Pega_Extensions_PegaSlider/index.tsx b/src/components/Pega_Extensions_PegaSlider/index.tsx new file mode 100644 index 0000000..6a3b256 --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/index.tsx @@ -0,0 +1,47 @@ +import { withConfiguration } from '@pega/cosmos-react-core'; + +import type { PConnFieldProps } from './PConnProps'; + +import StyledPegaExtensionsPegaSliderWrapper from './styles'; +import PegaSlider from './Slider'; + +// interface for props +interface PegaExtensionsPegaSliderProps extends PConnFieldProps { + // eslint-disable-next-line react/no-unused-prop-types + imageData: any; // Ensure imageData is defined here + datasource: { source: [] }; + height?: string; + controlType?: any; + autoplay?: any; + autoplayDuration?: any; + objectFit?: any; + textPosition?: any; + animationType?: any; +} + +function PegaExtensionsPegaSlider(props: PegaExtensionsPegaSliderProps) { + // eslint-disable-next-line no-console + console.log(props, 'index page props Pega Slider '); + // eslint-disable-next-line no-console + console.log(props.datasource, 'i am pega datasource Pega Slider data'); + + const { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + getPConnect, + height = '30rem', + datasource, + controlType, + autoplay, + autoplayDuration, + objectFit, + textPosition, + animationType + } = props; + + return ( + + + + ); +} +export default withConfiguration(PegaExtensionsPegaSlider); diff --git a/src/components/Pega_Extensions_PegaSlider/mock.ts b/src/components/Pega_Extensions_PegaSlider/mock.ts new file mode 100644 index 0000000..60fe6d7 --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/mock.ts @@ -0,0 +1,65 @@ +// @ts-nocheck +export const configProps = { + label: 'Pega Slider', + 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: {} + }, + height: '40rem', + textPosition: 'TopLeft', + objectFit: 'cover', + autoplay: false, + autoplayDuration: '3000', + controlType: 'Dots', + animationType: 'fade-in', + visibility: true +}; + +export const operatorDetails = { + data: { + pzLoadTime: 'January 18, 2023 10:33:19 AM EST', + pzPageNameHash: '_pa1519192551088960pz', + pyOperatorInfo: { + pyUserName: 'french DigV2', + pyPosition: '', + pyImageInsKey: '', + pySkills: [ + { + pySkillName: '', + pzIndexOwnerKey: 'DATA-ADMIN-OPERATOR-ID FRENCHTEST.DIGV2', + pySkillRating: 0 + } + ], + pyReportToUserName: '', + pyReportTo: '', + pyOrganization: 'DXIL', + pyTitle: '', + pyLabel: 'frenchTest.DigV2', + pyEmailAddress: 'User@DigV2', + pyTelephone: '' + } + }, + status: 200, + statusText: '', + headers: { + 'content-length': '435', + 'content-type': 'application/json;charset=UTF-8' + }, + request: {} +}; diff --git a/src/components/Pega_Extensions_PegaSlider/styles.ts b/src/components/Pega_Extensions_PegaSlider/styles.ts new file mode 100644 index 0000000..fffa26f --- /dev/null +++ b/src/components/Pega_Extensions_PegaSlider/styles.ts @@ -0,0 +1,264 @@ +// individual style, comment out above, and uncomment here and add styles +import styled, { css } from 'styled-components'; +import { keyframes } from 'styled-components'; + +export default styled.div(() => { + return css` + margin: 0px 0; + + `; +}); + +export const SliderContainer = styled.div` + position: relative; + overflow: hidden; +`; + +export const SliderWrapper = styled.div<{ totalSlides: number; currentSlide: number }>` + display: flex; + transition: transform 0.5s ease-in-out; + transform: translateX(-${props => props.currentSlide * 100}%); // Changed to 100% per slide + width: 100%; + height: 100%; +`; + +export const SlideImage = styled.img<{ objectFit?: string }>` + width: 100%; + height: 100%; + object-fit: ${(props) => props.objectFit || 'cover'}; + object-position: center; +`; + +export const ButtonPrev = styled.button` + position: absolute; + top: 50%; + left: 10px; + transform: translateY(-50%); + background: none; + border: none; + cursor: pointer; + font-size: 2rem; + color: #fff; + z-index: 10; +`; + +export const ButtonNext = styled.button` + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); + background: none; + border: none; + cursor: pointer; + font-size: 2rem; + color: #fff; + z-index: 10; +`; + +export const DotsContainer = styled.div` + display: flex; + justify-content: center; + z-index: 9999; + position: relative; + top: -20px; +`; + +export const Dot = styled.a<{ active: boolean }>` + background-color: ${(props) => (props.active ? '#285aa8' : '#b1b1b1')}; // Active dot color + border: none; + border-radius: 50%; + height: 12px; // Size of the dot + width: 12px; // Size of the dot + margin: 0 5px; // Spacing between dots + cursor: pointer; + transition: background-color 0.3s; + + &:hover { + background-color: #6293df; // Hover color + } +`; + +export const SliderTextContainer = styled.div<{ position: string }>` + position: absolute; + width: 50%; + ${({ position }) => { + switch (position) { + case 'TopLeft': + return css`top: 20px; left: 50px; text-align: left;`; + case 'TopCenter': + return css`top: 20px; left: 50%; transform: translateX(-50%); text-align: center;`; + case 'TopRight': + return css`top: 20px; right: 50px; text-align: right;`; + case 'CenterLeft': + return css`top: 50%; left: 50px; transform: translateY(-50%); text-align: left;`; + case 'Center': + return css`top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center;`; + case 'CenterRight': + return css`top: 50%; right: 50px; transform: translateY(-50%); text-align: right;`; + case 'BottomLeft': + return css`bottom: 20px; left: 50px; text-align: left;`; + case 'BottomCenter': + return css`bottom: 20px; left: 50%; transform: translateX(-50%); text-align: center;`; + case 'BottomRight': + return css`bottom: 20px; right: 50px; text-align: right;`; + default: + return css`top: 20px; left: 50px; text-align: left;`; + } + }} +`; + +// Fade In and Out +export const fadeIn = keyframes` + from { + opacity: 0; + } + to { + opacity: 1; + } +`; + +export const fadeOut = keyframes` + 0% { + opacity: 1; + } + 50% { + opacity: 0.9; + } + 70% { + opacity: 0.8; + } + 90% { + opacity: 0.9; + } + 100% { + opacity: 1; + } +`; + +// Slide In and Out +export const slideIn = keyframes` + 0% { + transform: translateX(0); + opacity: 0.3; + } + 50% { + transform: translateX(-100%); + opacity: 0.5; + } + 100% { + transform: translateX(0); + opacity: 1; + } +`; + +export const slideOut = keyframes` + 0% { + transform: translateY(0); + opacity: 0.3; + } + 50% { + transform: translateY(-100%); + opacity: 0.5; + } + 100% { + transform: translateY(0); + opacity: 1; + } +`; + +// Zoom In and Out +export const zoomIn = keyframes` + 0% { + transform: scale(0); + } + 50% { + transform: scale(0.5); + } + 100% { + transform: scale(1); + } +`; + +export const zoomOut = keyframes` + 0% { + transform: scale(1); + } + 50% { + transform: scale(0.5); + } + 100% { + transform: scale(1); + } +`; + +// Shake Animation +export const shake = keyframes` + 0% { + transform: translateX(0); + } + 25% { + transform: translateX(-20px); + } + 50% { + transform: translateX(20px); + } + 75% { + transform: translateX(-20px); + } + 100% { + transform: translateX(0); + } +`; + +// Bounce Animation +export const bounce = keyframes` + 0%, 20%, 50%, 80%, 100% { + transform: translateY(0); + } + 40% { + transform: translateY(-30px); + } + 60% { + transform: translateY(-15px); + } +`; + +// Rotate Clockwise and Counter Clockwise (optional) +export const rotateClockwise = keyframes` + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +`; + +export const rotateCounterClockwise = keyframes` + from { transform: rotate(360deg); } + to { transform: rotate(0deg); } +`; + +export const Slide = styled.div<{ animationClass: string }>` + min-width: 100%; + opacity: 1; + height: 100%; + position: relative; + animation: ${({ animationClass }) => { + switch (animationClass) { + case 'fade-in': + return css`${fadeIn} 0.5s forwards`; + case 'fade-out': + return css`${fadeOut} 0.5s forwards`; + case 'slide-in': + return css`${slideIn} 0.5s forwards`; + case 'slide-out': + return css`${slideOut} 0.5s forwards`; + case 'zoom-in': + return css`${zoomIn} 0.5s forwards`; + case 'zoom-out': + return css`${zoomOut} 0.5s forwards`; + case 'shake': + return css`${shake} 0.5s forwards`; + case 'bounce': + return css`${bounce} 0.5s forwards`; + default: + return css`${fadeIn} 0.5s forwards`; + } + }}; +`; From f4d349cc3ae416fd32eda515b7078233cfeee226 Mon Sep 17 00:00:00 2001 From: Mandeep Virdi Date: Tue, 8 Oct 2024 17:57:48 +0530 Subject: [PATCH 2/6] updated Doc file --- .../Pega_Extensions_PegaSlider/Docs.mdx | 79 ++++++++++++------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/src/components/Pega_Extensions_PegaSlider/Docs.mdx b/src/components/Pega_Extensions_PegaSlider/Docs.mdx index 1f5b37a..ffae389 100644 --- a/src/components/Pega_Extensions_PegaSlider/Docs.mdx +++ b/src/components/Pega_Extensions_PegaSlider/Docs.mdx @@ -1,34 +1,34 @@ -Image Carousel Component for Pega Constellation +Image Slider Component for Pega Constellation ## Overview -The Image Carousel Component is a dynamic and flexible carousel designed for Pega Constellation applications. It fetches images from a (Example:- D_YourDataPage) data 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. +The Image slider Component is a dynamic and flexible slider designed for Pega Constellation applications. It fetches images from a (Example:- D_YourDataPage) data 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. ## Key Features 1. Height Customization - The height of the carousel is fully customizable to fit the design requirements of your Pega application. The height can be set using fixed units (e.g. rem ). + The height of the slider is fully customizable to fit the design requirements of your Pega application. The height can be set using fixed units (e.g. rem ). 2. Text Positioning Options - Choose from various text alignment options for your carousel: - Top Left: Position the carousel in the top left corner. - Top Center: Center the carousel at the top. - Top Right: Align the carousel in the top right corner. - Center Left: Place the carousel on the left side, vertically centered. - Center: Center the carousel both vertically and horizontally. - Center Right: Position the carousel on the right side, vertically centered. - Bottom Left: Align the carousel in the bottom left corner. - Bottom Center: Center the carousel at the bottom. - Bottom Right: Position the carousel in the bottom right corner. + Choose from various text alignment options for your slider: + Top Left: Position the slider in the top left corner. + Top Center: Center the slider at the top. + Top Right: Align the slider in the top right corner. + Center Left: Place the slider on the left side, vertically centered. + Center: Center the slider both vertically and horizontally. + Center Right: Position the slider on the right side, vertically centered. + Bottom Left: Align the slider in the bottom left corner. + Bottom Center: Center the slider at the bottom. + Bottom Right: Position the slider in the bottom right corner. 3. Object Fit Options - Control how images are displayed within the carousel with the following settings: - Fill: Stretches the image to fill the entire carousel area. - Contain: Scales the image to fit within the carousel while maintaining its aspect ratio. - Cover: Scales the image to cover the entire carousel, cropping as needed to maintain the aspect ratio. + Control how images are displayed within the slider with the following settings: + Fill: Stretches the image to fill the entire slider area. + Contain: Scales the image to fit within the slider while maintaining its aspect ratio. + Cover: Scales the image to cover the entire slider, cropping as needed to maintain the aspect ratio. None: Displays the image in its original size, without scaling. - Scale Down: Scales the image down to fit within the carousel only if it exceeds its original dimensions. + Scale Down: Scales the image down to fit within the slider only if it exceeds its original dimensions. 4. Autoplay Enable or disable autoplay functionality: @@ -39,14 +39,14 @@ The Image Carousel Component is a dynamic and flexible carousel designed for Peg Set the duration (in milliseconds) for how long each item is displayed before transitioning to the next one during autoplay. 6. Control Type - Select the type of navigation controls for the carousel: + Select the type of navigation controls for the slider: None: No navigation controls displayed. Button: Includes next/previous buttons for manual navigation. - Dots: Displays dot indicators representing each item in the carousel. + Dots: Displays dot indicators representing each item in the slider. Both: Combines buttons and dot indicators for versatile navigation. 7. Animation Type - Select the type of animation for transitions between carousel items: + Select the type of animation for transitions between slider items: Fade In: Gradually appears with a fade effect. Fade Out: Gradually disappears with a fade effect. Slide In: Slides in from a specific direction. @@ -56,22 +56,41 @@ The Image Carousel Component is a dynamic and flexible carousel designed for Peg Bounce: Bounces in or out for a playful effect. Shake: Shakes the item for a dynamic transition. +8. Future Enhancement + + Keyboard navigation + Implement keyboard navigation and screen reader compatibility to ensure the slider is usable by individuals with disabilities. + + Video Support + Extend the slider 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 slider items, allowing users to quickly jump to a specific slide. + + Interactive Elements + Incorporate interactive features like hotspots or clickable areas within slider images to enhance engagement. + + ## 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: Banner) with the following columns: +1. Create a Data Type for the slider + To manage and display the images in the slider component, create a Data Type in Pega (Example: Banner) 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. + Image URL: URL of the image to be displayed in the slider. + Visible: Boolean field to indicate if the image should be shown in the slider. 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_BannersList) that retrieves records filtered by visibility, using a report definition (RD_VisibleBanners). This ensures that only banners with Visible = true are displayed, and it can be seamlessly integrated into components like the Image Carousel for a dynamic user experience. +Users will create a custom list Data Page (D_BannersList) that retrieves records filtered by visibility, using a report definition (RD_VisibleBanners). This ensures that only banners with Visible = true are displayed, and it can be seamlessly integrated into components like the Image slider for a dynamic user experience. 2. Component Configuration - Add the carousel component to your Landing Page and Summary panel using the following configuration: + Add the slider component to your Landing Page and Summary panel using the following configuration: Data Page:- Specify the Data Page (Example:- D_BannerList.pxResults) Image Source:- Specify the image property. Title:- Specify the Title property. @@ -90,6 +109,6 @@ Font Color: There is no capability to modify the font color for the title and de ## 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 banners or promotions fetched from a backend system. +Product Gallery: Display a slider of product images that update based on user selections or current promotions. +User Profile slider: Show a collection of user-uploaded photos or media. +Dynamic Advertisements: Rotating slider for dynamic ad banners or promotions fetched from a backend system. From 8a5b7f0365e4ca7e07a64e7780584f9d79d6c1ce Mon Sep 17 00:00:00 2001 From: Mandeep Virdi Date: Wed, 9 Oct 2024 15:28:22 +0530 Subject: [PATCH 3/6] first version of image slider with documentation update and name updated --- .../Pega_Extensions_ImageSlider/Docs.mdx | 179 ++++++++++++++++++ .../DotsNavigation.tsx | 0 .../OneColumnPage.svg | 0 .../PConnProps.d.ts | 0 .../SlideItem.tsx | 0 .../Slider.tsx | 0 .../SliderControls.tsx | 0 .../config.json | 0 .../demo.stories.tsx | 0 .../index.tsx | 0 .../mock.ts | 0 .../styles.ts | 0 .../Pega_Extensions_PegaSlider/Docs.mdx | 114 ----------- 13 files changed, 179 insertions(+), 114 deletions(-) create mode 100644 src/components/Pega_Extensions_ImageSlider/Docs.mdx rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/DotsNavigation.tsx (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/OneColumnPage.svg (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/PConnProps.d.ts (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/SlideItem.tsx (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/Slider.tsx (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/SliderControls.tsx (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/config.json (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/demo.stories.tsx (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/index.tsx (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/mock.ts (100%) rename src/components/{Pega_Extensions_PegaSlider => Pega_Extensions_ImageSlider}/styles.ts (100%) delete mode 100644 src/components/Pega_Extensions_PegaSlider/Docs.mdx diff --git a/src/components/Pega_Extensions_ImageSlider/Docs.mdx b/src/components/Pega_Extensions_ImageSlider/Docs.mdx new file mode 100644 index 0000000..579c42c --- /dev/null +++ b/src/components/Pega_Extensions_ImageSlider/Docs.mdx @@ -0,0 +1,179 @@ +# Image Slider Component for Pega Constellation + + +## Overview + +The Image slider Component is a dynamic and flexible slider designed for Pega Constellation applications. It fetches images from a **(Example:- D_YourDataPage)** data 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. + +## Key Features + +**1. Height Customization** + + The height of the slider is fully customizable to fit the design requirements of your Pega application. + The height can be set using fixed units (e.g. rem ). + +**2. Text Positioning Options:** + Choose from various text alignment options for your slider: + + - **Top Left:** Position the slider in the top left corner. + + - **Top Center:** Center the slider at the top. + + - **Top Right:** Align the slider in the top right corner. + + - **Center Left:** Place the slider on the left side, vertically centered. + + - **Center:** Center the slider both vertically and horizontally. + + - **Center Right:** Position the slider on the right side, vertically centered. + + - **Bottom Left:** Align the slider in the bottom left corner. + + - **Bottom Center:** Center the slider at the bottom. + + - **Bottom Right:** Position the slider in the bottom right corner. + + +**3. Object Fit Options** + + Control how images are displayed within the slider with the following settings: + + - **Fill:** Stretches the image to fill the entire slider area. + + - **Contain:** Scales the image to fit within the slider while maintaining its aspect ratio. + + - **Cover:** Scales the image to cover the entire slider, cropping as needed to maintain the aspect ratio. + + - **None:** Displays the image in its original size, without scaling. + + - **Scale Down:** Scales the image down to fit within the slider only if it exceeds its original dimensions. + + + +**4. Autoplay** + + Enable or disable autoplay functionality: + + - **Yes:** Automatically cycles through items at a set interval. + + - **No:** Requires manual navigation to view items. + + + +**5. Autoplay Duration (ms)** + + Set the duration (in milliseconds) for how long each item is displayed before transitioning to the next one during autoplay. + + + +**6. Control Type** + + Select the type of navigation controls for the slider: + + - **None:** No navigation controls displayed. + + - **Button:** Includes next/previous buttons for manual navigation. + + - **Dots:** Displays dot indicators representing each item in the slider. + + - **Both:** Combines buttons and dot indicators for versatile navigation. + + + +**7. Animation Type** + + Select the type of animation for transitions between slider items: + + - **Fade In:** Gradually appears with a fade effect. + + - **Fade Out:** Gradually disappears with a fade effect. + + - **Slide In:** Slides in from a specific direction. + + - **Slide Out:** Slides out to a specific direction. + + - **Zoom In:** Gradually enlarges the item as it appears. + + - **Zoom Out:** Gradually reduces the item as it disappears. + + - **Bounce:** Bounces in or out for a playful effect. + + - **Shake:** Shakes the item for a dynamic transition. + + + +**8. Future Enhancement** + + - **Keyboard navigation:** + Implement keyboard navigation and screen reader compatibility to ensure the slider is usable by individuals with disabilities. + + - **Video Support:** + Extend the slider 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 slider items, allowing users to quickly jump to a specific slide. + + - **Interactive Elements:** + Incorporate interactive features like hotspots or clickable areas within slider images to enhance engagement. + + +## Deployment and Integration Instructions:- + +**1. Create a Data Type for the slider** + + To manage and display the images in the slider component, create a Data Type in Pega **(Example: Banner)** 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 slider. + + - **Visible:** Boolean field to indicate if the image should be shown in the slider. + + +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_BannersList)** that retrieves records filtered by visibility, using a report definition **(RD_VisibleBanners)**. This ensures that only banners with **Visible = true** are displayed, and it can be seamlessly integrated into components like the Image slider for a dynamic user experience. + + +**2. Component Configuration** + + Add the slider component to your **Landing Page** and **Summary panel** using the following configuration: + + - **Data Page:** Specify the Data Page **(Example:- D_BannerList.pxResults)** + + - **Image Source:** Specify the image property. + + - **Title:** Specify the Title property. + + - **Description:** Specify the Description property. + + + + +## Limitations + +The limitations of the components are: + + - **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. + + + +## Example Use Cases + +- **Product Gallery:** Display a slider of product images that update based on user selections or current promotions. + +- **User Profile slider:** Show a collection of user-uploaded photos or media. + +- **Dynamic Advertisements:** Rotating slider for dynamic ad banners or promotions fetched from a backend system. diff --git a/src/components/Pega_Extensions_PegaSlider/DotsNavigation.tsx b/src/components/Pega_Extensions_ImageSlider/DotsNavigation.tsx similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/DotsNavigation.tsx rename to src/components/Pega_Extensions_ImageSlider/DotsNavigation.tsx diff --git a/src/components/Pega_Extensions_PegaSlider/OneColumnPage.svg b/src/components/Pega_Extensions_ImageSlider/OneColumnPage.svg similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/OneColumnPage.svg rename to src/components/Pega_Extensions_ImageSlider/OneColumnPage.svg diff --git a/src/components/Pega_Extensions_PegaSlider/PConnProps.d.ts b/src/components/Pega_Extensions_ImageSlider/PConnProps.d.ts similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/PConnProps.d.ts rename to src/components/Pega_Extensions_ImageSlider/PConnProps.d.ts diff --git a/src/components/Pega_Extensions_PegaSlider/SlideItem.tsx b/src/components/Pega_Extensions_ImageSlider/SlideItem.tsx similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/SlideItem.tsx rename to src/components/Pega_Extensions_ImageSlider/SlideItem.tsx diff --git a/src/components/Pega_Extensions_PegaSlider/Slider.tsx b/src/components/Pega_Extensions_ImageSlider/Slider.tsx similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/Slider.tsx rename to src/components/Pega_Extensions_ImageSlider/Slider.tsx diff --git a/src/components/Pega_Extensions_PegaSlider/SliderControls.tsx b/src/components/Pega_Extensions_ImageSlider/SliderControls.tsx similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/SliderControls.tsx rename to src/components/Pega_Extensions_ImageSlider/SliderControls.tsx diff --git a/src/components/Pega_Extensions_PegaSlider/config.json b/src/components/Pega_Extensions_ImageSlider/config.json similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/config.json rename to src/components/Pega_Extensions_ImageSlider/config.json diff --git a/src/components/Pega_Extensions_PegaSlider/demo.stories.tsx b/src/components/Pega_Extensions_ImageSlider/demo.stories.tsx similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/demo.stories.tsx rename to src/components/Pega_Extensions_ImageSlider/demo.stories.tsx diff --git a/src/components/Pega_Extensions_PegaSlider/index.tsx b/src/components/Pega_Extensions_ImageSlider/index.tsx similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/index.tsx rename to src/components/Pega_Extensions_ImageSlider/index.tsx diff --git a/src/components/Pega_Extensions_PegaSlider/mock.ts b/src/components/Pega_Extensions_ImageSlider/mock.ts similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/mock.ts rename to src/components/Pega_Extensions_ImageSlider/mock.ts diff --git a/src/components/Pega_Extensions_PegaSlider/styles.ts b/src/components/Pega_Extensions_ImageSlider/styles.ts similarity index 100% rename from src/components/Pega_Extensions_PegaSlider/styles.ts rename to src/components/Pega_Extensions_ImageSlider/styles.ts diff --git a/src/components/Pega_Extensions_PegaSlider/Docs.mdx b/src/components/Pega_Extensions_PegaSlider/Docs.mdx deleted file mode 100644 index ffae389..0000000 --- a/src/components/Pega_Extensions_PegaSlider/Docs.mdx +++ /dev/null @@ -1,114 +0,0 @@ -Image Slider Component for Pega Constellation - - -## Overview - -The Image slider Component is a dynamic and flexible slider designed for Pega Constellation applications. It fetches images from a (Example:- D_YourDataPage) data 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. - -## Key Features - -1. Height Customization - The height of the slider is fully customizable to fit the design requirements of your Pega application. The height can be set using fixed units (e.g. rem ). - -2. Text Positioning Options - Choose from various text alignment options for your slider: - Top Left: Position the slider in the top left corner. - Top Center: Center the slider at the top. - Top Right: Align the slider in the top right corner. - Center Left: Place the slider on the left side, vertically centered. - Center: Center the slider both vertically and horizontally. - Center Right: Position the slider on the right side, vertically centered. - Bottom Left: Align the slider in the bottom left corner. - Bottom Center: Center the slider at the bottom. - Bottom Right: Position the slider in the bottom right corner. - -3. Object Fit Options - Control how images are displayed within the slider with the following settings: - Fill: Stretches the image to fill the entire slider area. - Contain: Scales the image to fit within the slider while maintaining its aspect ratio. - Cover: Scales the image to cover the entire slider, cropping as needed to maintain the aspect ratio. - None: Displays the image in its original size, without scaling. - Scale Down: Scales the image down to fit within the slider only if it exceeds its original dimensions. - -4. Autoplay - Enable or disable autoplay functionality: - Yes: Automatically cycles through items at a set interval. - No: Requires manual navigation to view items. - -5. Autoplay Duration (ms) - Set the duration (in milliseconds) for how long each item is displayed before transitioning to the next one during autoplay. - -6. Control Type - Select the type of navigation controls for the slider: - None: No navigation controls displayed. - Button: Includes next/previous buttons for manual navigation. - Dots: Displays dot indicators representing each item in the slider. - Both: Combines buttons and dot indicators for versatile navigation. - -7. Animation Type - Select the type of animation for transitions between slider items: - Fade In: Gradually appears with a fade effect. - Fade Out: Gradually disappears with a fade effect. - Slide In: Slides in from a specific direction. - Slide Out: Slides out to a specific direction. - Zoom In: Gradually enlarges the item as it appears. - Zoom Out: Gradually reduces the item as it disappears. - Bounce: Bounces in or out for a playful effect. - Shake: Shakes the item for a dynamic transition. - -8. Future Enhancement - - Keyboard navigation - Implement keyboard navigation and screen reader compatibility to ensure the slider is usable by individuals with disabilities. - - Video Support - Extend the slider 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 slider items, allowing users to quickly jump to a specific slide. - - Interactive Elements - Incorporate interactive features like hotspots or clickable areas within slider images to enhance engagement. - - -## Deployment and Integration Instructions:- - -1. Create a Data Type for the slider - To manage and display the images in the slider component, create a Data Type in Pega (Example: Banner) 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 slider. - Visible: Boolean field to indicate if the image should be shown in the slider. - -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_BannersList) that retrieves records filtered by visibility, using a report definition (RD_VisibleBanners). This ensures that only banners with Visible = true are displayed, and it can be seamlessly integrated into components like the Image slider for a dynamic user experience. - -2. Component Configuration - Add the slider component to your Landing Page and Summary panel using the following configuration: - Data Page:- Specify the Data Page (Example:- D_BannerList.pxResults) - Image Source:- Specify the image property. - Title:- Specify the Title property. - Description:- Specify the Description property. - - - -## Limitations - -The limitations of the components are: - -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. - - -## Example Use Cases - -Product Gallery: Display a slider of product images that update based on user selections or current promotions. -User Profile slider: Show a collection of user-uploaded photos or media. -Dynamic Advertisements: Rotating slider for dynamic ad banners or promotions fetched from a backend system. From 7bf244a4fa391f0d4881ea00f3192aa49b7aedad Mon Sep 17 00:00:00 2001 From: Mandeep Virdi Date: Wed, 9 Oct 2024 15:40:34 +0530 Subject: [PATCH 4/6] label configuration updated --- .../Pega_Extensions_ImageSlider/config.json | 14 +++++++------- .../Pega_Extensions_ImageSlider/demo.stories.tsx | 2 +- src/components/Pega_Extensions_ImageSlider/mock.ts | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/Pega_Extensions_ImageSlider/config.json b/src/components/Pega_Extensions_ImageSlider/config.json index 77fc97e..15a4d96 100644 --- a/src/components/Pega_Extensions_ImageSlider/config.json +++ b/src/components/Pega_Extensions_ImageSlider/config.json @@ -23,17 +23,17 @@ "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": "title", - "label": "Image Title", - "required": false, - "defaultValue": "@P .pyTitle" } ] }, @@ -133,6 +133,6 @@ "controlType": "dots", "Autoplay": "yes", "autoplayDuration": "3000", - "label": "Pega Slider" + "label": "Image Slider" } } diff --git a/src/components/Pega_Extensions_ImageSlider/demo.stories.tsx b/src/components/Pega_Extensions_ImageSlider/demo.stories.tsx index 4e10fb2..c71b62d 100644 --- a/src/components/Pega_Extensions_ImageSlider/demo.stories.tsx +++ b/src/components/Pega_Extensions_ImageSlider/demo.stories.tsx @@ -66,5 +66,5 @@ BasePegaExtensionsPegaSlider.args = { controlType: 'Dots', animationType: 'fade-in', visibility: true, - label: 'Pega Slider', + label: 'Image Slider', }; diff --git a/src/components/Pega_Extensions_ImageSlider/mock.ts b/src/components/Pega_Extensions_ImageSlider/mock.ts index 60fe6d7..b1f2931 100644 --- a/src/components/Pega_Extensions_ImageSlider/mock.ts +++ b/src/components/Pega_Extensions_ImageSlider/mock.ts @@ -1,6 +1,6 @@ // @ts-nocheck export const configProps = { - label: 'Pega Slider', + label: 'Image Slider', datasource: { source: [ { From d890df746952dca806db880ecd4e2b1f46930bbf Mon Sep 17 00:00:00 2001 From: Mandeep Virdi Date: Thu, 17 Oct 2024 10:55:12 +0530 Subject: [PATCH 5/6] Rename as per instructions --- .../Docs.mdx | 68 +++++++++---------- .../DotsNavigation.tsx | 6 +- .../OneColumnPage.svg | 0 .../PConnProps.d.ts | 0 .../SlideItem.tsx | 0 .../Slider.tsx | 2 +- .../SliderControls.tsx | 0 .../config.json | 8 +-- .../demo.stories.tsx | 2 +- .../index.tsx | 6 +- .../mock.ts | 2 +- .../styles.ts | 0 12 files changed, 47 insertions(+), 47 deletions(-) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/Docs.mdx (52%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/DotsNavigation.tsx (74%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/OneColumnPage.svg (100%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/PConnProps.d.ts (100%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/SlideItem.tsx (100%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/Slider.tsx (98%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/SliderControls.tsx (100%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/config.json (96%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/demo.stories.tsx (98%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/index.tsx (88%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/mock.ts (98%) rename src/components/{Pega_Extensions_ImageSlider => Pega_Extensions_ImageCarousel}/styles.ts (100%) diff --git a/src/components/Pega_Extensions_ImageSlider/Docs.mdx b/src/components/Pega_Extensions_ImageCarousel/Docs.mdx similarity index 52% rename from src/components/Pega_Extensions_ImageSlider/Docs.mdx rename to src/components/Pega_Extensions_ImageCarousel/Docs.mdx index 579c42c..2396a30 100644 --- a/src/components/Pega_Extensions_ImageSlider/Docs.mdx +++ b/src/components/Pega_Extensions_ImageCarousel/Docs.mdx @@ -1,52 +1,52 @@ -# Image Slider Component for Pega Constellation +# Image Carousel Component for Pega Constellation ## Overview -The Image slider Component is a dynamic and flexible slider designed for Pega Constellation applications. It fetches images from a **(Example:- D_YourDataPage)** data 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. +The Image Carousel Component is a dynamic and flexible Carousel designed for Pega Constellation applications. It fetches images from a **(Example:- D_YourDataPage)** data 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. ## Key Features **1. Height Customization** - The height of the slider is fully customizable to fit the design requirements of your Pega application. + The height of the Carousel is fully customizable to fit the design requirements of your Pega application. The height can be set using fixed units (e.g. rem ). **2. Text Positioning Options:** - Choose from various text alignment options for your slider: + Choose from various text alignment options for your Carousel: - - **Top Left:** Position the slider in the top left corner. + - **Top Left:** Position the Carousel in the top left corner. - - **Top Center:** Center the slider at the top. + - **Top Center:** Center the Carousel at the top. - - **Top Right:** Align the slider in the top right corner. + - **Top Right:** Align the Carousel in the top right corner. - - **Center Left:** Place the slider on the left side, vertically centered. + - **Center Left:** Place the Carousel on the left side, vertically centered. - - **Center:** Center the slider both vertically and horizontally. + - **Center:** Center the Carousel both vertically and horizontally. - - **Center Right:** Position the slider on the right side, vertically centered. + - **Center Right:** Position the Carousel on the right side, vertically centered. - - **Bottom Left:** Align the slider in the bottom left corner. + - **Bottom Left:** Align the Carousel in the bottom left corner. - - **Bottom Center:** Center the slider at the bottom. + - **Bottom Center:** Center the Carousel at the bottom. - - **Bottom Right:** Position the slider in the bottom right corner. + - **Bottom Right:** Position the Carousel in the bottom right corner. **3. Object Fit Options** - Control how images are displayed within the slider with the following settings: + Control how images are displayed within the Carousel with the following settings: - - **Fill:** Stretches the image to fill the entire slider area. + - **Fill:** Stretches the image to fill the entire Carousel area. - - **Contain:** Scales the image to fit within the slider while maintaining its aspect ratio. + - **Contain:** Scales the image to fit within the Carousel while maintaining its aspect ratio. - - **Cover:** Scales the image to cover the entire slider, cropping as needed to maintain the aspect ratio. + - **Cover:** Scales the image to cover the entire Carousel, cropping as needed to maintain the aspect ratio. - **None:** Displays the image in its original size, without scaling. - - **Scale Down:** Scales the image down to fit within the slider only if it exceeds its original dimensions. + - **Scale Down:** Scales the image down to fit within the Carousel only if it exceeds its original dimensions. @@ -68,13 +68,13 @@ The Image slider Component is a dynamic and flexible slider designed for Pega Co **6. Control Type** - Select the type of navigation controls for the slider: + Select the type of navigation controls for the Carousel: - **None:** No navigation controls displayed. - **Button:** Includes next/previous buttons for manual navigation. - - **Dots:** Displays dot indicators representing each item in the slider. + - **Dots:** Displays dot indicators representing each item in the Carousel. - **Both:** Combines buttons and dot indicators for versatile navigation. @@ -82,7 +82,7 @@ The Image slider Component is a dynamic and flexible slider designed for Pega Co **7. Animation Type** - Select the type of animation for transitions between slider items: + Select the type of animation for transitions between Carousel items: - **Fade In:** Gradually appears with a fade effect. @@ -105,26 +105,26 @@ The Image slider Component is a dynamic and flexible slider designed for Pega Co **8. Future Enhancement** - **Keyboard navigation:** - Implement keyboard navigation and screen reader compatibility to ensure the slider is usable by individuals with disabilities. + Implement keyboard navigation and screen reader compatibility to ensure the Carousel is usable by individuals with disabilities. - **Video Support:** - Extend the slider to support video content alongside images, offering a richer multimedia experience. + 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 slider items, allowing users to quickly jump to a specific slide. + 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 slider images to enhance engagement. + Incorporate interactive features like hotspots or clickable areas within Carousel images to enhance engagement. ## Deployment and Integration Instructions:- -**1. Create a Data Type for the slider** +**1. Create a Data Type for the Carousel** - To manage and display the images in the slider component, create a Data Type in Pega **(Example: Banner)** with the following columns: + To manage and display the images in the Carousel component, create a Data Type in Pega **(Example: Banner)** with the following columns: - **Id:** Unique identifier for the image. @@ -132,20 +132,20 @@ The Image slider Component is a dynamic and flexible slider designed for Pega Co - **Description:** Optional description or metadata for the image. - - **Image URL:** URL of the image to be displayed in the slider. + - **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 slider. + - **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_BannersList)** that retrieves records filtered by visibility, using a report definition **(RD_VisibleBanners)**. This ensures that only banners with **Visible = true** are displayed, and it can be seamlessly integrated into components like the Image slider for a dynamic user experience. +Users will create a custom list Data Page **(D_BannersList)** that retrieves records filtered by visibility, using a report definition **(RD_VisibleBanners)**. This ensures that only banners 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 slider component to your **Landing Page** and **Summary panel** using the following configuration: + Add the Carousel component to your **Landing Page** and **Summary panel** using the following configuration: - **Data Page:** Specify the Data Page **(Example:- D_BannerList.pxResults)** @@ -172,8 +172,8 @@ The limitations of the components are: ## Example Use Cases -- **Product Gallery:** Display a slider of product images that update based on user selections or current promotions. +- **Product Gallery:** Display a Carousel of product images that update based on user selections or current promotions. -- **User Profile slider:** Show a collection of user-uploaded photos or media. +- **User Profile Carousel:** Show a collection of user-uploaded photos or media. -- **Dynamic Advertisements:** Rotating slider for dynamic ad banners or promotions fetched from a backend system. +- **Dynamic Advertisements:** Rotating Carousel for dynamic ad banners or promotions fetched from a backend system. diff --git a/src/components/Pega_Extensions_ImageSlider/DotsNavigation.tsx b/src/components/Pega_Extensions_ImageCarousel/DotsNavigation.tsx similarity index 74% rename from src/components/Pega_Extensions_ImageSlider/DotsNavigation.tsx rename to src/components/Pega_Extensions_ImageCarousel/DotsNavigation.tsx index 16bb37d..aea589f 100644 --- a/src/components/Pega_Extensions_ImageSlider/DotsNavigation.tsx +++ b/src/components/Pega_Extensions_ImageCarousel/DotsNavigation.tsx @@ -2,20 +2,20 @@ import React from 'react'; import { Dot, DotsContainer } from './styles'; type DotsNavigationProps = { - imageSliderData: { id: string | number | null | undefined }[]; // Add the id type + imageSliderData: { id: string | number | null | undefined }[]; currentSlide: number; showSlide: (index: number) => void; }; const DotsNavigation: React.FC = ({ - imageSliderData, // Receive image slider data to get ids + imageSliderData, currentSlide, showSlide, }) => ( {imageSliderData.map((slide, index) => ( showSlide(index)} active={currentSlide === index} /> diff --git a/src/components/Pega_Extensions_ImageSlider/OneColumnPage.svg b/src/components/Pega_Extensions_ImageCarousel/OneColumnPage.svg similarity index 100% rename from src/components/Pega_Extensions_ImageSlider/OneColumnPage.svg rename to src/components/Pega_Extensions_ImageCarousel/OneColumnPage.svg diff --git a/src/components/Pega_Extensions_ImageSlider/PConnProps.d.ts b/src/components/Pega_Extensions_ImageCarousel/PConnProps.d.ts similarity index 100% rename from src/components/Pega_Extensions_ImageSlider/PConnProps.d.ts rename to src/components/Pega_Extensions_ImageCarousel/PConnProps.d.ts diff --git a/src/components/Pega_Extensions_ImageSlider/SlideItem.tsx b/src/components/Pega_Extensions_ImageCarousel/SlideItem.tsx similarity index 100% rename from src/components/Pega_Extensions_ImageSlider/SlideItem.tsx rename to src/components/Pega_Extensions_ImageCarousel/SlideItem.tsx diff --git a/src/components/Pega_Extensions_ImageSlider/Slider.tsx b/src/components/Pega_Extensions_ImageCarousel/Slider.tsx similarity index 98% rename from src/components/Pega_Extensions_ImageSlider/Slider.tsx rename to src/components/Pega_Extensions_ImageCarousel/Slider.tsx index a622a51..afb5dd2 100644 --- a/src/components/Pega_Extensions_ImageSlider/Slider.tsx +++ b/src/components/Pega_Extensions_ImageCarousel/Slider.tsx @@ -29,7 +29,7 @@ const PegaSlider: React.FC = ({ const imageSliderData = imageData?.source || []; // eslint-disable-next-line no-console -console.log(imageSliderData, 'imageSliderData DX page') +console.log(imageSliderData, 'Image Carousel Data DX page') const [currentSlide, setCurrentSlide] = useState(0); diff --git a/src/components/Pega_Extensions_ImageSlider/SliderControls.tsx b/src/components/Pega_Extensions_ImageCarousel/SliderControls.tsx similarity index 100% rename from src/components/Pega_Extensions_ImageSlider/SliderControls.tsx rename to src/components/Pega_Extensions_ImageCarousel/SliderControls.tsx diff --git a/src/components/Pega_Extensions_ImageSlider/config.json b/src/components/Pega_Extensions_ImageCarousel/config.json similarity index 96% rename from src/components/Pega_Extensions_ImageSlider/config.json rename to src/components/Pega_Extensions_ImageCarousel/config.json index 15a4d96..1a0fc8c 100644 --- a/src/components/Pega_Extensions_ImageSlider/config.json +++ b/src/components/Pega_Extensions_ImageCarousel/config.json @@ -1,7 +1,7 @@ { - "name": "Pega_Extensions_PegaSlider", - "label": "Pega Slider", - "description": "Pega Slider", + "name": "Pega_Extensions_Image_Carousel", + "label": "Image carousel", + "description": "Image carousel", "organization": "Pega", "version": "1.0.0", "library": "Extensions", @@ -133,6 +133,6 @@ "controlType": "dots", "Autoplay": "yes", "autoplayDuration": "3000", - "label": "Image Slider" + "label": "Image Carousel" } } diff --git a/src/components/Pega_Extensions_ImageSlider/demo.stories.tsx b/src/components/Pega_Extensions_ImageCarousel/demo.stories.tsx similarity index 98% rename from src/components/Pega_Extensions_ImageSlider/demo.stories.tsx rename to src/components/Pega_Extensions_ImageCarousel/demo.stories.tsx index c71b62d..69ba6ee 100644 --- a/src/components/Pega_Extensions_ImageSlider/demo.stories.tsx +++ b/src/components/Pega_Extensions_ImageCarousel/demo.stories.tsx @@ -66,5 +66,5 @@ BasePegaExtensionsPegaSlider.args = { controlType: 'Dots', animationType: 'fade-in', visibility: true, - label: 'Image Slider', + label: 'Image Carousel', }; diff --git a/src/components/Pega_Extensions_ImageSlider/index.tsx b/src/components/Pega_Extensions_ImageCarousel/index.tsx similarity index 88% rename from src/components/Pega_Extensions_ImageSlider/index.tsx rename to src/components/Pega_Extensions_ImageCarousel/index.tsx index 6a3b256..0f34089 100644 --- a/src/components/Pega_Extensions_ImageSlider/index.tsx +++ b/src/components/Pega_Extensions_ImageCarousel/index.tsx @@ -8,7 +8,7 @@ import PegaSlider from './Slider'; // interface for props interface PegaExtensionsPegaSliderProps extends PConnFieldProps { // eslint-disable-next-line react/no-unused-prop-types - imageData: any; // Ensure imageData is defined here + imageData: any; datasource: { source: [] }; height?: string; controlType?: any; @@ -21,9 +21,9 @@ interface PegaExtensionsPegaSliderProps extends PConnFieldProps { function PegaExtensionsPegaSlider(props: PegaExtensionsPegaSliderProps) { // eslint-disable-next-line no-console - console.log(props, 'index page props Pega Slider '); + console.log(props, 'index page props Image Carousel '); // eslint-disable-next-line no-console - console.log(props.datasource, 'i am pega datasource Pega Slider data'); + console.log(props.datasource, 'i am pega datasource Image Carousel data'); const { // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/src/components/Pega_Extensions_ImageSlider/mock.ts b/src/components/Pega_Extensions_ImageCarousel/mock.ts similarity index 98% rename from src/components/Pega_Extensions_ImageSlider/mock.ts rename to src/components/Pega_Extensions_ImageCarousel/mock.ts index b1f2931..050b504 100644 --- a/src/components/Pega_Extensions_ImageSlider/mock.ts +++ b/src/components/Pega_Extensions_ImageCarousel/mock.ts @@ -1,6 +1,6 @@ // @ts-nocheck export const configProps = { - label: 'Image Slider', + label: 'Image Carousel', datasource: { source: [ { diff --git a/src/components/Pega_Extensions_ImageSlider/styles.ts b/src/components/Pega_Extensions_ImageCarousel/styles.ts similarity index 100% rename from src/components/Pega_Extensions_ImageSlider/styles.ts rename to src/components/Pega_Extensions_ImageCarousel/styles.ts From 220fb156a64a32745ed539e2e02e34573656d247 Mon Sep 17 00:00:00 2001 From: Richard Marsot Date: Wed, 23 Oct 2024 19:22:03 -0400 Subject: [PATCH 6/6] clean up stories and code --- .../{SliderControls.tsx => Controls.tsx} | 0 .../Pega_Extensions_ImageCarousel/Docs.mdx | 168 ++++------------- .../OneColumnPage.svg | 36 ---- .../PConnProps.d.ts | 45 ----- .../SlideItem.tsx | 13 +- .../Pega_Extensions_ImageCarousel/Slider.tsx | 104 ---------- .../Pega_Extensions_ImageCarousel/config.json | 44 ++--- .../demo.stories.tsx | 121 ++++++------ .../demo.test.tsx | 10 + .../Pega_Extensions_ImageCarousel/index.tsx | 178 ++++++++++++++---- .../Pega_Extensions_ImageCarousel/mock.ts | 65 ------- .../Pega_Extensions_ImageCarousel/styles.ts | 108 ++++++++--- 12 files changed, 354 insertions(+), 538 deletions(-) rename src/components/Pega_Extensions_ImageCarousel/{SliderControls.tsx => Controls.tsx} (100%) delete mode 100644 src/components/Pega_Extensions_ImageCarousel/OneColumnPage.svg delete mode 100644 src/components/Pega_Extensions_ImageCarousel/PConnProps.d.ts delete mode 100644 src/components/Pega_Extensions_ImageCarousel/Slider.tsx create mode 100644 src/components/Pega_Extensions_ImageCarousel/demo.test.tsx delete mode 100644 src/components/Pega_Extensions_ImageCarousel/mock.ts diff --git a/src/components/Pega_Extensions_ImageCarousel/SliderControls.tsx b/src/components/Pega_Extensions_ImageCarousel/Controls.tsx similarity index 100% rename from src/components/Pega_Extensions_ImageCarousel/SliderControls.tsx rename to src/components/Pega_Extensions_ImageCarousel/Controls.tsx diff --git a/src/components/Pega_Extensions_ImageCarousel/Docs.mdx b/src/components/Pega_Extensions_ImageCarousel/Docs.mdx index 2396a30..b7e5e8f 100644 --- a/src/components/Pega_Extensions_ImageCarousel/Docs.mdx +++ b/src/components/Pega_Extensions_ImageCarousel/Docs.mdx @@ -1,130 +1,23 @@ -# Image Carousel Component for Pega Constellation +import { Meta, Primary, Controls, Story } from '@storybook/blocks'; +import * as DemoStories from './demo.stories'; + -## Overview +# Overview -The Image Carousel Component is a dynamic and flexible Carousel designed for Pega Constellation applications. It fetches images from a **(Example:- D_YourDataPage)** data 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. +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. -## Key Features + -**1. Height Customization** +## Props - The height of the Carousel is fully customizable to fit the design requirements of your Pega application. - The height can be set using fixed units (e.g. rem ). + -**2. Text Positioning Options:** - Choose from various text alignment options for your Carousel: +# Deployment and Integration Instructions:- - - **Top Left:** Position the Carousel in the top left corner. +**1. Create a Data Type for the Carousel** - - **Top Center:** Center the Carousel at the top. - - - **Top Right:** Align the Carousel in the top right corner. - - - **Center Left:** Place the Carousel on the left side, vertically centered. - - - **Center:** Center the Carousel both vertically and horizontally. - - - **Center Right:** Position the Carousel on the right side, vertically centered. - - - **Bottom Left:** Align the Carousel in the bottom left corner. - - - **Bottom Center:** Center the Carousel at the bottom. - - - **Bottom Right:** Position the Carousel in the bottom right corner. - - -**3. Object Fit Options** - - Control how images are displayed within the Carousel with the following settings: - - - **Fill:** Stretches the image to fill the entire Carousel area. - - - **Contain:** Scales the image to fit within the Carousel while maintaining its aspect ratio. - - - **Cover:** Scales the image to cover the entire Carousel, cropping as needed to maintain the aspect ratio. - - - **None:** Displays the image in its original size, without scaling. - - - **Scale Down:** Scales the image down to fit within the Carousel only if it exceeds its original dimensions. - - - -**4. Autoplay** - - Enable or disable autoplay functionality: - - - **Yes:** Automatically cycles through items at a set interval. - - - **No:** Requires manual navigation to view items. - - - -**5. Autoplay Duration (ms)** - - Set the duration (in milliseconds) for how long each item is displayed before transitioning to the next one during autoplay. - - - -**6. Control Type** - - Select the type of navigation controls for the Carousel: - - - **None:** No navigation controls displayed. - - - **Button:** Includes next/previous buttons for manual navigation. - - - **Dots:** Displays dot indicators representing each item in the Carousel. - - - **Both:** Combines buttons and dot indicators for versatile navigation. - - - -**7. Animation Type** - - Select the type of animation for transitions between Carousel items: - - - **Fade In:** Gradually appears with a fade effect. - - - **Fade Out:** Gradually disappears with a fade effect. - - - **Slide In:** Slides in from a specific direction. - - - **Slide Out:** Slides out to a specific direction. - - - **Zoom In:** Gradually enlarges the item as it appears. - - - **Zoom Out:** Gradually reduces the item as it disappears. - - - **Bounce:** Bounces in or out for a playful effect. - - - **Shake:** Shakes the item for a dynamic transition. - - - -**8. Future Enhancement** - - - **Keyboard navigation:** - Implement keyboard navigation and screen reader compatibility to ensure the Carousel is usable by individuals with disabilities. - - - **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. - - -## 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: Banner)** with the following columns: + 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. @@ -136,18 +29,15 @@ The Image Carousel Component is a dynamic and flexible Carousel designed for Peg - **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. -Users will create a custom list Data Page **(D_BannersList)** that retrieves records filtered by visibility, using a report definition **(RD_VisibleBanners)**. This ensures that only banners 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** +**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_BannerList.pxResults)** + - **Data Page:** Specify the Data Page **(Example:- D_CarouselList.pxResults)** - **Image Source:** Specify the image property. @@ -155,25 +45,41 @@ Users will create a custom list Data Page **(D_BannersList)** that retrieves rec - **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. -## Limitations +- **Font Size:** There is no option to change the font size for the title and description. -The limitations of the components are: +- **Font Type:** The components do not support changing the font family for the title and description. - - **Font Size:** There is no option to change the font size for the title and description. +- **Font Color:** There is no capability to modify the font color for the title and description. - - **Font Type:** The components do not support changing the font family for the title and description. +Ideas for enhancements are: - - **Font Color:** There is no capability to modify the font color for the title and description. +- **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. -## Example Use Cases +- **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 banners or promotions fetched from a backend system. +- **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) diff --git a/src/components/Pega_Extensions_ImageCarousel/OneColumnPage.svg b/src/components/Pega_Extensions_ImageCarousel/OneColumnPage.svg deleted file mode 100644 index 5f2dec9..0000000 --- a/src/components/Pega_Extensions_ImageCarousel/OneColumnPage.svg +++ /dev/null @@ -1,36 +0,0 @@ - - - 1 col - - - - - - - - - - - - - - - - - - - - - - - - - A - - - - - - - - \ No newline at end of file diff --git a/src/components/Pega_Extensions_ImageCarousel/PConnProps.d.ts b/src/components/Pega_Extensions_ImageCarousel/PConnProps.d.ts deleted file mode 100644 index aa913e3..0000000 --- a/src/components/Pega_Extensions_ImageCarousel/PConnProps.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { PConnect } from '@pega/pcore-pconnect-typedefs'; - -// PConnProps.d.ts -// This gives us a place to have each component (which is most DX Components) that is -// expected to have a getPConnect extend its props (from BaseProps) -// such that every component will be expected to have a getPConnect() function -// that returns a PConnect object. (new/better way of doing .propTypes). -// This PConnProps can be extended to include other props that we know are in every component -export interface PConnProps { - // getPConnect should exist for every C11n component. (add @ts-ignore in special cases where it isn't) - getPConnect: () => typeof PConnect; - - // Allow any/all other key/value pairs in the BaseProps for now - // TODO: refine which other props are always expected for various component - // types and consider further interface "subclassing". For example, we may - // want to create a "BasePropsForm" that gives guidance on required, readonly, etc. - // and any other props that every Form component expects. - // For example, see the PConnFieldProps below. - // NOTE: if you uncomment the line below, the PConnProps type will allow - // otherwise undefined types to appear. This can be helpful for debugging - // or when adding new components whose types aren't yet known. - // [key: string]: any; -} - -// PConnFieldProps extends PConnProps to bring in the common properties that are -// associated with most field components (ex: Dropdown, TextInput, etc.) in the -// components/field directory -export interface PConnFieldProps extends PConnProps { - label: string; - required: boolean; - disabled: boolean; - value: any; - validatemessage: string; - status?: string; - onChange?: any; - onBlur?: any; - readOnly: boolean; - testId: string; - helperText: string; - displayMode?: string; - hideLabel: boolean; - placeholder?: string; - fieldMetadata?: any; - additionalProps?: any; -} diff --git a/src/components/Pega_Extensions_ImageCarousel/SlideItem.tsx b/src/components/Pega_Extensions_ImageCarousel/SlideItem.tsx index 5583d26..6cb9b21 100644 --- a/src/components/Pega_Extensions_ImageCarousel/SlideItem.tsx +++ b/src/components/Pega_Extensions_ImageCarousel/SlideItem.tsx @@ -3,8 +3,8 @@ import { Slide, SlideImage, SliderTextContainer } from './styles'; type SlideItemProps = { slide: { - title: React.ReactNode; // Updated to ReactNode for flexibility - description: React.ReactNode; // Updated to ReactNode for flexibility + title: string; + description: string; imageURL: string | undefined; }; animationClass: string; @@ -18,15 +18,12 @@ const SlideItem: React.FC = ({ animationClass, isActive, objectFit, - textPosition = 'Center', + textPosition = 'Center' }) => { return ( - + -

{slide.title}

+

{slide.title}

{slide.description}

diff --git a/src/components/Pega_Extensions_ImageCarousel/Slider.tsx b/src/components/Pega_Extensions_ImageCarousel/Slider.tsx deleted file mode 100644 index afb5dd2..0000000 --- a/src/components/Pega_Extensions_ImageCarousel/Slider.tsx +++ /dev/null @@ -1,104 +0,0 @@ - -import React, { useState, useEffect, useCallback } from 'react'; -import { SliderContainer, SliderWrapper } from './styles'; -import SlideItem from './SlideItem'; -import SliderControls from './SliderControls'; -import DotsNavigation from './DotsNavigation'; - -type PegaSliderProps = { - imageData: { source: any }; - height?: string; - animationType?: string; - controlType?: any; - autoplay?: string; // New prop for autoplay - autoplayDuration?: number; - objectFit?: string; - textPosition?: string; -}; - -const PegaSlider: React.FC = ({ - imageData, - height, - controlType, - autoplay, - autoplayDuration = 3000, - objectFit, - textPosition = 'TopLeft', - animationType = 'fade-in', -}) => { - const imageSliderData = imageData?.source || []; - -// eslint-disable-next-line no-console -console.log(imageSliderData, 'Image Carousel Data DX page') - - - const [currentSlide, setCurrentSlide] = useState(0); - const [animationClass, setAnimationClass] = useState(animationType); - - const totalSlides = imageSliderData.length; - - const showSlide = useCallback( - (index: number) => { - setAnimationClass(animationType); // Start fade-out animation - setTimeout(() => { - setCurrentSlide((index + totalSlides) % totalSlides); // Change the slide after animation - setAnimationClass(animationType); // Reset to fade-in animation - }, 500); // Match this duration with your CSS animation duration - }, - [animationType, totalSlides] - ); - - const prevSlide = () => showSlide(currentSlide - 1); - const nextSlide = useCallback(() => { - showSlide(currentSlide + 1); - }, [currentSlide, showSlide]); - - // Autoplay functionality - useEffect(() => { - if (autoplay === 'true' && totalSlides > 1) { - const autoplayTimer = setInterval(() => { - nextSlide(); - }, autoplayDuration); - - return () => clearInterval(autoplayTimer); - } - }, [autoplay, totalSlides, nextSlide, autoplayDuration]); - - return ( - - - {imageSliderData.map( - (slide: { - id: string | null | undefined; - title: React.ReactNode; - description: React.ReactNode; - imageURL: string | undefined; - }) => ( - - ) - )} - - - {(controlType === 'Buttons' || controlType === 'Both') && ( - - )} - - {(controlType === 'Dots' || controlType === 'Both') && ( - - )} - - ); -}; - -export default PegaSlider; diff --git a/src/components/Pega_Extensions_ImageCarousel/config.json b/src/components/Pega_Extensions_ImageCarousel/config.json index 1a0fc8c..a9970c2 100644 --- a/src/components/Pega_Extensions_ImageCarousel/config.json +++ b/src/components/Pega_Extensions_ImageCarousel/config.json @@ -6,47 +6,48 @@ "version": "1.0.0", "library": "Extensions", "allowedApplications": [], - "componentKey": "Pega_Extensions_PegaSlider", "type": "Widget", "subtype": ["PAGE", "CASE"], - "icon": "OneColumnPage.svg", "properties": [ { "name": "datasource", - "label": "Data source for Banner", + "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": "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 Banner", - "format": "TEXT" + "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" }, @@ -64,6 +65,7 @@ "label": "Object Fit", "name": "objectFit", "defaultValue": "cover", + "required": true, "source": [ { "key": "fill", "value": "Fill" }, { "key": "contain", "value": "Contain" }, @@ -73,26 +75,23 @@ ] }, { - "format": "SELECT", + "format": "BOOLEAN", "label": "Autoplay", "name": "autoplay", - "defaultValue": "false", - "source": [ - { "key": "true", "value": "Yes" }, - { "key": "false", "value": "No" } - ] + "defaultValue": false }, { "name": "autoplayDuration", "label": "Autoplay Duration (ms)", - "format": "TEXT", - "defaultValue": "3000" + "format": "INTEGER", + "defaultValue": 3000 }, { "format": "SELECT", "label": "Control Type", "name": "controlType", "defaultValue": "Dots", + "required": true, "source": [ { "key": "None", "value": "None" }, { "key": "Dots", "value": "Dots" }, @@ -105,6 +104,7 @@ "label": "Animation Type", "name": "animationType", "defaultValue": "fade-in", + "required": true, "source": [ { "key": "fade-in", "value": "Fade In" }, { "key": "fade-out", "value": "Fade Out" }, diff --git a/src/components/Pega_Extensions_ImageCarousel/demo.stories.tsx b/src/components/Pega_Extensions_ImageCarousel/demo.stories.tsx index 69ba6ee..4ce7670 100644 --- a/src/components/Pega_Extensions_ImageCarousel/demo.stories.tsx +++ b/src/components/Pega_Extensions_ImageCarousel/demo.stories.tsx @@ -1,70 +1,69 @@ -/* eslint-disable react/jsx-no-useless-fragment */ -// @ts-nocheck -import type { Meta, StoryObj } from '@storybook/react'; +import type { StoryObj } from '@storybook/react'; +import { PegaExtensionsImageCarousel } from './index'; -import PegaExtensionsPegaSlider from './index'; -import { configProps, operatorDetails } from './mock'; - -const meta: Meta = { - title: 'PegaExtensionsPegaSlider', - component: PegaExtensionsPegaSlider, - excludeStories: /.*Data$/, -}; - -export default meta; - -type Story = StoryObj; - -if (!window.PCore) { - window.PCore = {}; -} - -window.PCore.getLocaleUtils = () => { - return { - getLocaleValue: value => { - return value; +export default { + title: 'Widgets/Image Carousel', + argTypes: { + datasource: { + table: { + disable: true + } + }, + getPConnect: { + table: { + disable: true + } } - }; + }, + component: PegaExtensionsImageCarousel }; -window.PCore.getUserApi = () => { - return { - getOperatorDetails: () => { - return Promise.resolve(operatorDetails); - } +const setPCore = () => { + (window as any).PCore = { + /* Nothing */ }; }; -export const BasePegaExtensionsPegaSlider: Story = args => { - const props = { - datasource: configProps.datasource, - height: configProps.height, - textPosition: configProps.textPosition, - objectFit: configProps.objectFit, - autoplay: configProps.autoplay, - autoplayDuration: configProps.autoplayDuration, - controlType: configProps.controlType, - animationType: configProps.animationType, - visibility: configProps.visibility, - label: configProps.label, // Include label if needed - }; - - return ( - <> - - - ); -}; +type Story = StoryObj; -// Default args for the Storybook story -BasePegaExtensionsPegaSlider.args = { - height: '40rem', - textPosition: 'Center', - objectFit: 'cover', - autoplay: true, - autoplayDuration: '3000', - controlType: 'Dots', - animationType: 'fade-in', - visibility: true, - label: 'Image Carousel', +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 ; + }, + args: { + height: '40rem', + textPosition: 'Center', + objectFit: 'cover', + autoplay: true, + autoplayDuration: 3000, + controlType: 'Dots', + animationType: 'fade-in' + } }; diff --git a/src/components/Pega_Extensions_ImageCarousel/demo.test.tsx b/src/components/Pega_Extensions_ImageCarousel/demo.test.tsx new file mode 100644 index 0000000..4691b30 --- /dev/null +++ b/src/components/Pega_Extensions_ImageCarousel/demo.test.tsx @@ -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(); + expect(await screen.findByText('Title for Image 1')).toBeVisible(); +}); diff --git a/src/components/Pega_Extensions_ImageCarousel/index.tsx b/src/components/Pega_Extensions_ImageCarousel/index.tsx index 0f34089..f33ecf4 100644 --- a/src/components/Pega_Extensions_ImageCarousel/index.tsx +++ b/src/components/Pega_Extensions_ImageCarousel/index.tsx @@ -1,47 +1,153 @@ import { withConfiguration } from '@pega/cosmos-react-core'; - -import type { PConnFieldProps } from './PConnProps'; - -import StyledPegaExtensionsPegaSliderWrapper from './styles'; -import PegaSlider from './Slider'; +import { useState, useEffect, useCallback } from 'react'; +import { SliderContainer, SliderWrapper } from './styles'; +import SlideItem from './SlideItem'; +import SliderControls from './Controls'; +import DotsNavigation from './DotsNavigation'; // interface for props -interface PegaExtensionsPegaSliderProps extends PConnFieldProps { - // eslint-disable-next-line react/no-unused-prop-types - imageData: any; - datasource: { source: [] }; - height?: string; - controlType?: any; - autoplay?: any; - autoplayDuration?: any; - objectFit?: any; - textPosition?: any; - animationType?: any; -} +export interface ImageCarouselProps { + /** Name of the data page that will be called to get the Images */ + datasource: { source: any }; + /** Minimum height of the Carousel + * @default 30rem + */ + height: string; + /** Type of animation for transitions between Carousel items + * @default fade-in + */ + animationType: + | 'fade-in' + | 'fade-out' + | 'slide-in' + | 'slide-out' + | 'zoom-in' + | 'zoom-out' + | 'bounce' + | 'shake'; + /** Type of navigation controls for the Carousel + - None: No navigation controls displayed. + - Button: Includes next/previous buttons for manual navigation. + - Dots: Displays dot indicators representing each item in the Carousel. + - Both: Combines buttons and dot indicators for versatile navigation. -function PegaExtensionsPegaSlider(props: PegaExtensionsPegaSliderProps) { - // eslint-disable-next-line no-console - console.log(props, 'index page props Image Carousel '); - // eslint-disable-next-line no-console - console.log(props.datasource, 'i am pega datasource Image Carousel data'); + * @default Dots + */ + controlType: 'None' | 'Dots' | 'Buttons' | 'Both'; + /** Enable or disable autoplay functionality: + - true: Automatically cycles through items at a set interval. + - false: Requires manual navigation to view items. + * @default true + */ + autoplay?: boolean; + /** Set the duration (in milliseconds) for how long each item is displayed before transitioning to the next one during autoplay. + * @default 3000 + */ + autoplayDuration?: number; + /** Object Fit Options + - Fill: Stretches the image to fill the entire Carousel area. + - Contain: Scales the image to fit within the Carousel while maintaining its aspect ratio. + - Cover: Scales the image to cover the entire Carousel, cropping as needed to maintain the aspect ratio. + - None: Displays the image in its original size, without scaling. + - Scale Down: Scales the image down to fit within the Carousel only if it exceeds its original dimensions. + * @default cover + */ + objectFit: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down'; + /** Text Positioning Options + * @default TopLeft + */ + textPosition: + | 'TopLeft' + | 'TopCenter' + | 'TopRight' + | 'CenterLeft' + | 'Center' + | 'CenterRight' + | 'BottomLeft' + | 'BottomCenter' + | 'BottomRight'; +} +export const PegaExtensionsImageCarousel = (props: ImageCarouselProps) => { const { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - getPConnect, - height = '30rem', datasource, - controlType, - autoplay, - autoplayDuration, - objectFit, - textPosition, - animationType + height = '30rem', + controlType = 'Dots', + autoplay = true, + autoplayDuration = 3000, + objectFit = 'cover', + textPosition = 'TopLeft', + animationType = 'fade-in' } = props; + const imageSliderData = datasource?.source || []; + + const [currentSlide, setCurrentSlide] = useState(0); + const [animationClass, setAnimationClass] = useState(animationType); + + const totalSlides = imageSliderData.length; + + const showSlide = useCallback( + (index: number) => { + setAnimationClass(animationType); // Start fade-out animation + setTimeout(() => { + setCurrentSlide((index + totalSlides) % totalSlides); // Change the slide after animation + setAnimationClass(animationType); // Reset to fade-in animation + }, 500); // Match this duration with your CSS animation duration + }, + [animationType, totalSlides] + ); + + const prevSlide = () => showSlide(currentSlide - 1); + const nextSlide = useCallback(() => { + showSlide(currentSlide + 1); + }, [currentSlide, showSlide]); + + // Autoplay functionality + useEffect(() => { + if (autoplay && totalSlides > 1) { + const autoplayTimer = setInterval(() => { + nextSlide(); + }, autoplayDuration); + + return () => clearInterval(autoplayTimer); + } + }, [autoplay, totalSlides, nextSlide, autoplayDuration]); return ( - - - + + + {imageSliderData.map( + (slide: { + id: string | null | undefined; + title: string; + description: string; + imageURL: string | undefined; + }) => ( + + ) + )} + + + {(controlType === 'Buttons' || controlType === 'Both') && ( + + )} + + {(controlType === 'Dots' || controlType === 'Both') && ( + + )} + ); -} -export default withConfiguration(PegaExtensionsPegaSlider); +}; + +export default withConfiguration(PegaExtensionsImageCarousel); diff --git a/src/components/Pega_Extensions_ImageCarousel/mock.ts b/src/components/Pega_Extensions_ImageCarousel/mock.ts deleted file mode 100644 index 050b504..0000000 --- a/src/components/Pega_Extensions_ImageCarousel/mock.ts +++ /dev/null @@ -1,65 +0,0 @@ -// @ts-nocheck -export const configProps = { - label: 'Image Carousel', - 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: {} - }, - height: '40rem', - textPosition: 'TopLeft', - objectFit: 'cover', - autoplay: false, - autoplayDuration: '3000', - controlType: 'Dots', - animationType: 'fade-in', - visibility: true -}; - -export const operatorDetails = { - data: { - pzLoadTime: 'January 18, 2023 10:33:19 AM EST', - pzPageNameHash: '_pa1519192551088960pz', - pyOperatorInfo: { - pyUserName: 'french DigV2', - pyPosition: '', - pyImageInsKey: '', - pySkills: [ - { - pySkillName: '', - pzIndexOwnerKey: 'DATA-ADMIN-OPERATOR-ID FRENCHTEST.DIGV2', - pySkillRating: 0 - } - ], - pyReportToUserName: '', - pyReportTo: '', - pyOrganization: 'DXIL', - pyTitle: '', - pyLabel: 'frenchTest.DigV2', - pyEmailAddress: 'User@DigV2', - pyTelephone: '' - } - }, - status: 200, - statusText: '', - headers: { - 'content-length': '435', - 'content-type': 'application/json;charset=UTF-8' - }, - request: {} -}; diff --git a/src/components/Pega_Extensions_ImageCarousel/styles.ts b/src/components/Pega_Extensions_ImageCarousel/styles.ts index fffa26f..6a40780 100644 --- a/src/components/Pega_Extensions_ImageCarousel/styles.ts +++ b/src/components/Pega_Extensions_ImageCarousel/styles.ts @@ -2,13 +2,6 @@ import styled, { css } from 'styled-components'; import { keyframes } from 'styled-components'; -export default styled.div(() => { - return css` - margin: 0px 0; - - `; -}); - export const SliderContainer = styled.div` position: relative; overflow: hidden; @@ -25,7 +18,7 @@ export const SliderWrapper = styled.div<{ totalSlides: number; currentSlide: num export const SlideImage = styled.img<{ objectFit?: string }>` width: 100%; height: 100%; - object-fit: ${(props) => props.objectFit || 'cover'}; + object-fit: ${props => props.objectFit || 'cover'}; object-position: center; `; @@ -64,7 +57,7 @@ export const DotsContainer = styled.div` `; export const Dot = styled.a<{ active: boolean }>` - background-color: ${(props) => (props.active ? '#285aa8' : '#b1b1b1')}; // Active dot color + background-color: ${props => (props.active ? '#285aa8' : '#b1b1b1')}; // Active dot color border: none; border-radius: 50%; height: 12px; // Size of the dot @@ -83,26 +76,66 @@ export const SliderTextContainer = styled.div<{ position: string }>` width: 50%; ${({ position }) => { switch (position) { - case 'TopLeft': - return css`top: 20px; left: 50px; text-align: left;`; case 'TopCenter': - return css`top: 20px; left: 50%; transform: translateX(-50%); text-align: center;`; + return css` + top: 20px; + left: 50%; + transform: translateX(-50%); + text-align: center; + `; case 'TopRight': - return css`top: 20px; right: 50px; text-align: right;`; + return css` + top: 20px; + right: 50px; + text-align: right; + `; case 'CenterLeft': - return css`top: 50%; left: 50px; transform: translateY(-50%); text-align: left;`; + return css` + top: 50%; + left: 50px; + transform: translateY(-50%); + text-align: left; + `; case 'Center': - return css`top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center;`; + return css` + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + text-align: center; + `; case 'CenterRight': - return css`top: 50%; right: 50px; transform: translateY(-50%); text-align: right;`; + return css` + top: 50%; + right: 50px; + transform: translateY(-50%); + text-align: right; + `; case 'BottomLeft': - return css`bottom: 20px; left: 50px; text-align: left;`; + return css` + bottom: 20px; + left: 50px; + text-align: left; + `; case 'BottomCenter': - return css`bottom: 20px; left: 50%; transform: translateX(-50%); text-align: center;`; + return css` + bottom: 20px; + left: 50%; + transform: translateX(-50%); + text-align: center; + `; case 'BottomRight': - return css`bottom: 20px; right: 50px; text-align: right;`; + return css` + bottom: 20px; + right: 50px; + text-align: right; + `; + case 'TopLeft': default: - return css`top: 20px; left: 50px; text-align: left;`; + return css` + top: 20px; + left: 50px; + text-align: left; + `; } }} `; @@ -241,24 +274,39 @@ export const Slide = styled.div<{ animationClass: string }>` position: relative; animation: ${({ animationClass }) => { switch (animationClass) { - case 'fade-in': - return css`${fadeIn} 0.5s forwards`; case 'fade-out': - return css`${fadeOut} 0.5s forwards`; + return css` + ${fadeOut} 0.5s forwards + `; case 'slide-in': - return css`${slideIn} 0.5s forwards`; + return css` + ${slideIn} 0.5s forwards + `; case 'slide-out': - return css`${slideOut} 0.5s forwards`; + return css` + ${slideOut} 0.5s forwards + `; case 'zoom-in': - return css`${zoomIn} 0.5s forwards`; + return css` + ${zoomIn} 0.5s forwards + `; case 'zoom-out': - return css`${zoomOut} 0.5s forwards`; + return css` + ${zoomOut} 0.5s forwards + `; case 'shake': - return css`${shake} 0.5s forwards`; + return css` + ${shake} 0.5s forwards + `; case 'bounce': - return css`${bounce} 0.5s forwards`; + return css` + ${bounce} 0.5s forwards + `; + case 'fade-in': default: - return css`${fadeIn} 0.5s forwards`; + return css` + ${fadeIn} 0.5s forwards + `; } }}; `;