npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tvapps-epg-web

v1.0.29

Published

EPG Component for React Js applications. ===

Downloads

16

Readme

EPG Component for React Js applications.

React Js TV Guide for web

Default UI screenshoot

  • [x] EPG component
    • Material design similar to the website
    • Supports model (channel, program)
    • Renderer support:
      • [x] Support React Js
      • [x] Support custom UI at component (date, time, channel, program)
      • [x] Support callback function when selecting (program, channel, favorite)
      • [x] Support change icons (next, prev, calendar, recorded, record, loading, catchup, purchase, favorite, favoriteActive, scheduled record, place holder channel)
      • [x] Support change text (today, no program info, loading),
      • [x] Support past and future date display
      • [x] Support slient load more programs by date
      • [x] Hooks for loading additional data when scrolling to the end of the loaded data
      • [x] Shows the current and next programme and it's start time

Data


Data is provided in formats defined.

    channel = {
        imageSrc: string,
        id: number,
        externalChannelId: string,
        name: string,
        url: string,
        description: string,
        category: string,
        extrafields: array,
        number: number,
        isNpvrActivated: bool,
        isCatchupActivated: bool,
        isFavouriteActivated: bool,
        isPurchaseActivated: bool,
        flags: number;
    };
//default value
    channel =  {
        imageSrc: null,
        id: -1,
        externalChannelId: '',
        name: '',
        url: '',
        description: '',
        category: '',
        extrafields: [],
        number: -1,
        isNpvrActivated: false,
        isCatchupActivated: false,
        isFavouriteActivated: false,
        isPurchaseActivated: false,
        flags: 0;
    }
};
//example value
    channel =  {
        imageSrc: 'https://votvapps-ng-test.tvaas.com/RTEFacade/images/attachments/TV2.png',
        id: 1895201,
        externalChannelId: 'LuxeTV',
        name: 'Luxe TV',
        url: '',
        description: '',
        category: '',
        extrafields: [
            {
                responseElementType: "Extrafield",
                name: "static-playback",
                value: "false"
            }
        ],
        number: 12,
        isNpvrActivated: false,
        isCatchupActivated: false,
        isFavouriteActivated: false,
        isPurchaseActivated: false,
        flags: 128,
    }
};
const channeList =  [
    {
        ...channel
    },
    {
        ...channel   
    },
    ...
];


//PROGRAM DATA FORMART
    program = {
        id:  number,
        name:  string,
        shortName:  string,
        serisName:  string,
        description:  string,
        prName:  string,
        startDate:  number,//(timestamp)
        endDate:  number,//(timestamp)
        startDateAdjusted:  number,// default equal to startDate (timestamp), adjusted to fix start of day (00:00:00)
        endDateAdjusted:  number,// default equal to endDate (timestamp), adjusted to fix end of day (23:59:59)
        referenceProgramId:  string,
        flags:  number,
        responseElementType:  string,
        price:  number,
        imageSrc: string,
        genres:  array,
        prLevel:  number,
    }
// default value
    program = {
        id:  -1,
        name:  '',
        shortName:  '',
        serisName:  '',
        description:  '',
        prName:  '',
        startDate:  0,//(timestamp)
        endDate:  0,//(timestamp)
        startDateAdjusted:  0,// default equal to startDate (timestamp), adjusted to fix start of day (00:00:00)
        endDateAdjusted:  0,// default equal to endDate (timestamp), adjusted to fix end of day (23:59:59)
        referenceProgramId:  '',
        flags:  0,
        responseElementType:  '',
        price:  0,
        imageSrc: '',
        genres:  [],
        prLevel:  -1,
    }  
//example data
 program = {
        id:  12966715,
        name:  'Los milagros de la rosa',
        shortName:  '',
        serisName:  '',
        description:  '',
        imageSrc: 'https://votvapps-ng-test.tvaas.com/RTEFacade/images/12055411.jpg',
        prName:  'APT',
        startDate:  1641769200000,//(timestamp)
        endDate:  1641776400000,//(timestamp)
        startDateAdjusted:  1641769200000,// default equal to startDate (timestamp), adjusted to fix start of day (00:00:00)
        endDateAdjusted:  1641776400000,// default equal to endDate (timestamp), adjusted to fix end of day (23:59:59)
        referenceProgramId:  '2466657917202201091800120',
        flags:  0,
        responseElementType:  'Program',
        price:  1,
        genres:  [],
        prLevel:  0,
    }



const programList  = [
    {
        channelExternalId:'France24Fr2',
        programs: [program,...]
    },
    {
        channelExternalId:'ArteLoop',
        programs: [program,...]
    },
    {
        channelExternalId:'Arte',
        programs: [program,...]
    },
    ....
];

Data example

Config Defaults


You can specify config defaults that will be applied to every request.

Available tokens and their meanings are as follows:

| Prop types | meaning | examples of output | |:---------------------------|:--------------------------------------------------|:----------------------------------------------------------| | catchupEnabled | config catchup | catchupEnabled={false} | | npvrEnabled | config npvr | npvrEnabled={false} | | favouriteEnabled | config favourite | favouriteEnabled={false} |
| numberOfFutureDays | the future number is display | 1 | | numberOfPastDays | number of day too was display | 1 | | currentDate | current date value is selected | 'Date Fri Jan 21 2022 10:30:00 GMT+0700 (Indochina Time)' | | todayText | text showing current date | 'Today' | | noProgramInfoText | display text no program info | 'No Program Info' | | loadingText | text showing loading | 'Loading' | | programDetail | object program detail is currently selected | {} | | isLoadingShown | status loading | false | | isLoadingMore | status loading more | false | | channelList | channel list data | [] | | programList | program list data | [] | | tvGuideContainer | Take the element tv guide to check the height | | | onDateChanged | callback to change date | (f) => f | | onTimeChanged | callback to change time | (f) => f | | onProgramSelected | callback to select program item | (f) => f | | onChannelClicked | callback on click channel | (f) => f | | onFavoriteClicked | callback on favorite | (f) => f | | tvGuideWrapperStyles | put css to change the style of tv guide wrapper | { marginTop: 364, background: '#000' } | | datePickerStyles | put css to change the style of date | { fontSize: 16 } | | timeLineCellStyles | put css to change the style of time | { fontSize: 24, color: '#fff' } | | channelStyles | put css to change the style of channel | { number: { color: '#03143f' } } | | programStyles | put css to change the style of program item | {current: { fontSize: 24 }, future: { color: '#fff' }} | | programHoverBorderStyles | put css to change the style when hover at program | { '--hover-border': '1px solid #EE3325' } | | timeBarStyles | put css to change the style of time bar | timeBar: { background: '#EE3325' } | | loadingIcon | allow to change the loading icon | '' | | nextIcon | allow to change the next icon | '' | | prevIcon | allow to change the prev icon | '' | | calendarIcon | allow to change the calendar icon | '' | | purchaseIcon | allow to change the purchase icon | '' | | recordIcon | allow to change the record icon | '' | | recordedIcon | allow to change the recorded icon | '' | | favoriteActiveIcon | allow to change the favorite active icon | '' | | favoriteIcon | allow to change the favorite icon | '' | | catchupIcon | allow to change the catchup icon | '' | | scheduledRecordIcon | allow to change the scheduled record icon | '' | | placeHolderChannelIcon | allow to change the place holder channel icon | '' |

Support library function


You can call functions from the library to get the required data.

Available tokens and their meanings are as follows:

| Function Suport | meaning | examples of output | |:---------------------------|:-----------------------------------------------------------------------|:----------------------------------------------------------| | TvGuide | component TvGuide | | | getDate | function get date to handle date change when next or prev or calendar | getDate(date) | | getTime | function get time to handle time change when next or prev | getDate(time) | | formatCurrentDate | format the current time with component | formatCurrentDate(currentDate) | | bitToBitCompare | function compare flag | bitToBitCompare(flas, 16) | | getImage | function get image from api | attachments.map((img) => getImage(img)) | | Channel | channel model | new Channel(); | | ProgramItem | program item model | new ProgramItem(); | | ProgramLine | program model | new ProgramLine(); |

Import To Your Web:


Import TV Guide Web component with default properties below:

  • [x] All properties are the same TV Guide above

import React from 'react';
import { throttle } from 'lodash';
import { isMobile, isTablet } from 'react-device-detect';
import { TvGuide, getDate, getTime, formatCurrentDate, bitToBitCompare, getImage, Channel, ProgramItem, ProgramLine, FilterComponent } from './tvapps-epg-web/src';
import ICON_ARROW_LEFT from './images/arrow-left.png';
import ICON_ARROW_RIGHT from './images/arrow-right.png';
import ICON_CALENDAR from './images/calendar-icon.png';
import ICON_RECORD from './images/icon-record.png';
import ICON_CATCHUP from './images/icon-catchup.png';
import ICON_FAVORITE_ACTIVE from './images/favorite-active.png';
import ICON_FAVORITE from './images/favorite.png';
import ICON_PURCHASE from './images/purchase-icon.png';
import ICON_RECORDED from './images/icon-recorded.png';
import ICON_SCHEDULED_RECORD from './images/icon-scheduled-record.png';
import ICON_LOADING from './images/loading.svg';
import ICON_START_OVER from './images/icon-startOver.png';
import ICON_CATCHUP_IN_PROGRAM from './images/icon-catchup-in-program.png';
import PLACE_HOLDER_CHANNEL from './images/placeHolder/channel.png';
const axios = require('axios');

export class WebEpgDemo extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentDate: new Date(), // Current date (today)
      programDetail: {}, // obj program detail
      isLoadingShown: true, // status loading when load first page TvGuide
      isLoadingMore: false, // status loading more when scroll to the bottom
      channelList: [], // array channel list
      programList: [], // array program list
      numberChannel: [], // number channel or number line show at the epg
      allChannelList: [], // all channel
      categories: [
        'ALL',
        'Favourite',
        'Nacionales',
        'Novelas',
        'Estilo de Vida',
        'Noticias e Internacionales ',
        'Series y Peliculas',
        'Infantiles',
        'Culturales y Educativos',
        'Deportes',
        'Musica y Realities',
        'Religiosos',
        'Regionales Peru',
        'Adultos',
      ], // categories in the filter
      selectedChannelCategoryText: 'All', // selected channel category text
      width: window.innerWidth, // width screen
    };
    this.currentProgram = true; // flag check set current program the first
  }

  componentDidMount() {
    const { currentDate } = this.state;
    this.setState({ currentDate: formatCurrentDate(currentDate) }); // format current date when load the first and only
    window.scrollTo(0, 0); // set scroll to top when load page
    window.addEventListener('scroll', this.handleScroll); // create event scroll and function handleScroll
    window.addEventListener('resize', this.updateDimensions); // reate event scroll and function updateDimensions
  }

  UNSAFE_componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScroll); // remove event scroll and function handleScroll
    window.removeEventListener('resize', this.updateDimensions); // remove event scroll and function updateDimensions
  }

  updateDimensions = () => {
    this.setState({ width: window.innerWidth });
  };

  handleScroll = () => { // function handle scroll when scroll to the bottom
    if (window.innerHeight + window.pageYOffset >= document.body.offsetHeight - window.innerHeight / 2) { / check height screen and scroll
      this.loadMoreData(); // call load more data
    }
  };

  loadMoreData = throttle(() => { // function load more date
    const { numberChannel, currentDate, allChannelList, isLoadingMore } = this.state;
    let curentList = [...numberChannel];
    if (!isLoadingMore && curentList && curentList.length && allChannelList && allChannelList.length) {
      if (curentList.length < allChannelList.length) {
        let nextList =
          allChannelList && allChannelList.length && allChannelList.slice(curentList.length, curentList.length + 10);
        this.getData(currentDate, nextList, true);
        this.setState((prevState) => {
          return {
            ...prevState,
            numberChannel: [...prevState.numberChannel, ...nextList],
          };
        });
      }
    }
  }, 500);

  getData = (currentDate, channelList, isLoadMore = false) => { // get data and set state loading more
    this.setState({ isLoadingMore: isLoadMore });
    this.getPrograms(currentDate, channelList, isLoadMore);
  };

  getChannel = (cb) => { // get channel list
    const urlApi = 'https://urlApi'; // url api
    const urlGetChannelList = `${urlApi}`;
    const params = {
      ...
    };
    const optionChannel = {
      url: urlGetChannelList,
      method: 'GET',
      params,
      withCredentials: true,
    };
    axios(optionChannel)
      .then((channels) => {
        if (
          channels.status == 200 &&
          channels &&
          channels.data &&
          channels.data.response &&
          channels.data.response.length &&
          channels.data.response
        ) {
          const channelList = [];
          channels.data.response.map((item) => {
            const channelModel = new Channel();
            const images = [];
            const attachments = item.images ? item.images : item.attachments ? item.attachments : [];
            images.push(...attachments.map((img) => getImage(img))); // map and create imageSrc
            if (images && images.length) {
              const findImage = images.find((item) => item.name == 'HorizontalImage');
              if (findImage) {
                item.imageSrc = `${rightv}${findImage.url}`;
              }
            }
            item.isNpvrActivated = bitToBitCompare(item.flags, 16); // check show icon npvr
            item.isCatchupActivated = bitToBitCompare(item.flags, 128); // check show icon catchup
            item.isFavouriteActivated = false; // check show icon favorite
            item.isPurchaseActivated = true; // check show icon purchase
            channelModel.unSerialize(item); // channel model
            channelList.push(channelModel);
          });
          cb(channelList); // callback channel list
        }
      })
      .catch((error) => {
        console.log('clientEvents err', error);
        cb([]); // callback []
      });
  };

  getPrograms = (currentDate, channelList, isLoadMore) => { // get programList
    const self = this;
    const urlApi = 'https://urlApi'; // url api
    const startTime = new Date(currentDate);
    startTime.setHours(0, 0, 0, 0);
    const endTime = new Date(currentDate);
    endTime.setDate(endTime.getDate() + 1);
    endTime.setHours(1, 0, 0, 0);
    if (channelList && channelList.length) {
      const promises = channelList.map((item) => {
        return new Promise((resolve) => {
          const urlGetProgramLists = `${urlApi}/GetProgramLists`;
          const params = {
            channel_external_ids: item.externalChannelId,
            start_date: startTime.getTime(),
            end_date: endTime.getTime(),
            language_code: 'en',
            gaps: true,
            client: 'json',
          };
          const optionProgram = {
            url: urlGetProgramLists,
            method: 'GET',
            params,
            withCredentials: true,
          };
          axios(optionProgram)
            .then((programs) => {
              if (
                programs.status == 200 &&
                programs &&
                programs.data &&
                programs.data.response &&
                programs.data.response.length &&
                programs.data.response[0]
              ) {
                resolve(
                  programs &&
                    programs.data &&
                    programs.data.response &&
                    programs.data.response.length &&
                    programs.data.response[0]
                );
              }
            })
            .catch((error) => {
              console.log('123123 program err', error);
            });
        });
      });
      Promise.all(promises).then((results) => {
        const programList = [];
        const currentProgram = [];
        results.map((program) => {
          const programs = [];
          if (program && program.programs && program.programs.length) {
            program.programs.map((tvProgram) => {
              const images = [];
              const attachments = tvProgram.images
                ? tvProgram.images
                : tvProgram.attachments
                ? tvProgram.attachments
                : [];
              images.push(...attachments.map((img) => getImage(img)));
              if (images && images.length) {
                const findImage = images.find((item) => item.name == 'HorizontalImage');
                if (findImage) {
                  tvProgram.imageSrc = `${urlApi}${findImage.url}`;
                }
              }
              const programItemModel = new ProgramItem();
              programItemModel.unSerialize(tvProgram);
              programs.push(programItemModel);
              if (this.currentProgram) {
                const current = new Date().getTime();
                const proStartTime = tvProgram && tvProgram.startDate ? tvProgram.startDate : null;
                const prpEndTime = tvProgram && tvProgram.endDate ? tvProgram.endDate : null;
                if (proStartTime && prpEndTime && proStartTime <= current && prpEndTime >= current) {
                  currentProgram.push(tvProgram);
                }
              }
            });
          }
          const programModel = new ProgramLine(program.channelExternalId, programs);
          programList.push({ ...programModel });
        });
        if (this.currentProgram && currentProgram && currentProgram.length) {
          self.setState({ programDetail: currentProgram[0] });
          this.currentProgram = false;
        }
        if (isLoadMore) {
          const newProgramList = new Set([...this.state.programList, ...programList]);
          const newChannelList = new Set([...this.state.channelList, ...channelList]);
          const setProgramList = Array.from(newProgramList);
          const setChannelList = Array.from(newChannelList);
          self.setState((prevState) => {
            return {
              ...prevState,
              programList: setProgramList,
              channelList: setChannelList,
              isLoadingMore: false,
            };
          });
        } else {
          self.setState((prevState) => {
            return {
              ...prevState,
              isLoadingShown: false,
              programList,
              channelList,
              isLoadingMore: false,
            };
          });
        }
      });
    }
  };

  handleDateChanged = (value) => { // change date
    // Next or Prev
    this.onDateChanged(getDate(value)); // return date
  };

  handleTimeChanged = (value) => { // change time
    // Next or Prev
    getTime(value, (res) => { // return status isChangeDate or isChangeTime
      if (res && res.isChangeDate) {
        this.onDateChanged(res.date);
      } else if (res && res.isChangeTime) {
        this.onTimeChanged(res.date);
      }
    });
  };

  onDateChanged = (date) => { // update date and get data
    // Update currentDat
    this.setState({
      currentDate: date,
    });
    const { numberChannel } = this.state;
    this.getData(date, numberChannel);
  };

  onTimeChanged = (date) => { // update time
    // Update currentDate
    this.setState({
      currentDate: date,
    });
  };

  handleProgramSelected = (detail) => { // change detail
    this.setState({ programDetail: detail });
  };

  getTvGuideContainer = (element) => { // check height tv guide and set number channel the first load page
    if (element) {
      const heightEpg = element.clientHeight - 364; // 300 height detail
      const heightEpgHeader = 40 + 20; // height 40, margin 20
      const heightEpgLine = 79; // height 79, margin 12
      const numberLine = Math.abs(Math.ceil((heightEpg - heightEpgHeader) / heightEpgLine)); // not margin
      this.getChannel((channels) => {
        const channelList = channels.slice(0, numberLine);
        this.setState({ numberChannel: channelList, allChannelList: channels });
        const { currentDate } = this.state;
        this.getData(currentDate, channelList);
      });
    }
  };

  handleChannelClicked = (data) => {
    console.log('handleChannelClicked', data);
  };

  handleFavoriteClicked = (data) => {
    console.log('handleFavoriteClicked', data);
  };

  handleChannelCateogryChanged = (data) => {
    console.log('handleChannelCateogryChanged', data);
    this.setState({ selectedChannelCategoryText: data });
  };

  render() {
    const { currentDate, programDetail, isLoadingShown, programList, channelList, isLoadingMore, categories, selectedChannelCategoryText, width } =
      this.state;
    {/* format date show preview */}
    let progress_bar = null;
    const progStartDate = programDetail && programDetail.startDate ? programDetail.startDate : null;
    const progEndDate = programDetail && programDetail.endDate ? programDetail.endDate : null;
    const now = new Date().getTime();
    if (progStartDate && progEndDate) {
      if (progStartDate <= now && progEndDate >= now) {
        const percent = Math.floor(((now - progStartDate) * 100) / (progEndDate - progStartDate));
        // Progress for curent program
        progress_bar = (
          <div className='tv-guide-preview-progress'>
            <span>{`${new Date(progStartDate).getHours()}:${('0' + new Date(progStartDate).getMinutes()).slice(
              -2
            )}`}</span>
            <div className='tv-guide-preview-progress-bar'>
              <div className='tv-guide-preview-progress-current' style={{ width: `${percent}%` }} />
            </div>
            <span>{`${new Date(progEndDate).getHours()}:${('0' + new Date(progEndDate).getMinutes()).slice(-2)}`}</span>
          </div>
        );
      }
    }
    { /* End format date show preview */}
    return (
      <>
        { /* check show preview */}
        {(!isMobile && isTablet) ||
          (width > 768 && (
            <div id='tv-guide-preview-wrapper'>
              <div id='tv-guide-preview'>
                <div className='tv-guide-preview-left'>
                  <img src={programDetail && programDetail.imageSrc} className='tv-guide-preview-left-img' />
                </div>
                <div className='tv-guide-preview-right'>
                  <div className='tv-guide-preview-title'>{programDetail && programDetail.name}</div>
                  {progress_bar}
                  <div className='tv-guide-preview-des'>{programDetail && programDetail.description}</div>
                </div>
              </div>
              <div className='tv-guide-filter'>
                <FilterComponent
                  value={selectedChannelCategoryText}
                  items={categories}
                  onChannelCateogryChanged={(data) => this.handleChannelCateogryChanged(data)}
                  mobileFilterLabelText='Filter'
                  desktopFilterLabelText='Channel'
                  favoriteText='Favorite'
                  prevIcon={ICON_ARROW_LEFT}
                  favouriteEnabled
                />
              </div>
            </div>
            { /* end show preview */}
          ))}
        <TvGuide
          catchupEnabled
          npvrEnabled
          favouriteEnabled
          startoverEnabled
          numberOfFutureDays={1}
          numberOfPastDays={3}
          currentDate={currentDate}
          numberOfTimelineCellDisplayed={5}
          todayText='Today'
          noProgramInfoText='No Program Info'
          loadingText='Loading'
          // mobileTitle='Program guide'
          isLoadingShown={isLoadingShown}
          isLoadingMore={isLoadingMore}
          channelList={channelList}
          programList={programList}
          tvGuideContainer={this.getTvGuideContainer}
          onDateChanged={(value) => this.handleDateChanged(value)}
          onTimeChanged={(value) => this.handleTimeChanged(value)}
          onProgramSelected={(detail) => this.handleProgramSelected(detail)}
          onChannelClicked={(data) => this.handleChannelClicked(data)}
          onFavoriteClicked={(data) => this.handleFavoriteClicked(data)}
          onChannelCateogryChanged={(data) => this.handleChannelCateogryChanged(data)}
          tvGuideWrapperStyles={{ marginTop: 364, background: '#000' }}
          // datePickerStyles={{ fontSize: 16 }}
          // timeLineCellStyles={{ fontSize: 24, color: '#fff' }}
          // channelStyles={{ number: { color: '#03143f' } }}
          // programStyles={{
          //   selected: { background: '#EE3325', color: '#fff', boxShadow: '2px 2px 26px 19px rgba(255, 255, 255, 0.5)' },
          //   current: { fontSize: 24 },
          //   pass: { color: '#fff', fontSize: 24 },
          //   future: { color: '#fff' },
          //   noProgram: { color: 'rgba(255, 255, 255, 0.3)' },
          // }}
          // programHoverBorderStyles={{
          //   '--hover-border': '1px solid #EE3325',
          // }}
          // timeBarStyles={{
          //   timeBar: { background: '#EE3325' },
          //   timeBarHead: { background: '#EE3325' },
          //   timeBarIcon: { background: '#fff' },
          // }}
          tvGuideHeaderStyles={{ left: 10, margin: 0, padding: 0 }}
          tvGuideBodyStyles={{ width: 'calc(100% - 20px', left: 10 }}
          loadingIcon={ICON_LOADING}
          nextIcon={ICON_ARROW_RIGHT}
          prevIcon={ICON_ARROW_LEFT}
          calendarIcon={ICON_CALENDAR}
          purchaseIcon={ICON_PURCHASE}
          recordIcon={ICON_RECORD}
          recordedIcon={ICON_RECORDED}
          favoriteActiveIcon={ICON_FAVORITE_ACTIVE}
          favoriteIcon={ICON_FAVORITE}
          catchupIcon={ICON_CATCHUP}
          catchupInProgramIcon={ICON_CATCHUP_IN_PROGRAM}
          scheduledRecordIcon={ICON_SCHEDULED_RECORD}
          placeHolderChannelIcon={PLACE_HOLDER_CHANNEL}
          startOverIcon={ICON_START_OVER}
          categories={categories}
          selectedChannelCategoryText={selectedChannelCategoryText}
          mobileFilterLabelText='Filter'
          desktopFilterLabelText='Channel'
          favoriteText='Favorite'
        />
      </>
    );
  }
}

WebEpgDemo.propTypes = {
};

WebEpgDemo.defaultProps = {};

export default WebEpgDemo;

Custom UI Component For Web:

-- By default, if these props are not present, the website will take the default color

You can re-adjust the color through the following props:

<TvGuide
  ...
  tvGuideWrapperStyles={{ marginTop: 364, background: '#000' }}
  datePickerStyles={{ fontSize: 16 }}
  timeLineCellStyles={{ fontSize: 24, color: '#fff' }}
  channelStyles={{ number: { color: '#03143f' } }}
  programStyles={{
    selected: { background: '#EE3325', color: '#fff', boxShadow: '2px 2px 26px 19px rgba(255, 255, 255, 0.5)' },
    current: { fontSize: 24 },
    pass: { color: '#fff', fontSize: 24 },
    future: { color: '#fff' },
    noProgram: { color: 'rgba(255, 255, 255, 0.3)' },
  }}
  programHoverBorderStyles={{
    '--hover-border': '1px solid #EE3325',
  }}
  timeBarStyles={{
    timeBar: { background: '#EE3325' },
    timeBarHead: { background: '#EE3325' },
    timeBarIcon: { background: '#fff' },
  }}
/>

Change Icon In Component For Web:

-- By default, if these props are not present, the website will get the default icon

You can change the default icons back through the following props:

<TvGuide
  ...
  loadingIcon={'path/image/...'}
  nextIcon={'path/image/...'}
  prevIcon={'path/image/...'}
  calendarIcon={'path/image/...'}
  purchaseIcon={'path/image/...'}
  recordIcon={'path/image/...'}
  recordedIcon={'path/image/...'}
  favoriteActiveIcon={'path/image/...'}
  favoriteIcon={'path/image/...'}
  catchupIcon={'path/image/...'}
  scheduledRecordIcon={'path/image/...'}
  placeHolderChannelIcon={'path/image/...'}
/>