Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/sondh0127/vue-epg-planby


https://github.com/sondh0127/vue-epg-planby

Last synced: 1 day ago
JSON representation

Awesome Lists containing this project

README

        

## Vue EPG Planby
[![License](https://img.shields.io/github/license/logustra/vue-epg-planby)](https://github.com/sondh0127/vue-epg-planby/blob/master/license.md)
[![Code Style](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
[![Commitizen](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli)

> Electronic Program Guide (EPG) is a digital TV program that is used to display information about a channel's programs.

> Vue EPG Planby is a Vue components for EPG based Timeline, (ported from [planby](https://github.com/karolkozer/planby) - React based)



Planby preview

## Features
- Reactivity props
- Customizable template

## Installation
```sh
# install packages
$ pnpm install @sondh0127/vue-epg-planby
```

## Usage
Vue 3 (Vue 2.7)
### Basic Usage
```ts
import { addDays, addHours, endOfDay, format, startOfDay, subDays } from 'date-fns'
import type { Channel, Program, Theme } from '@sondh0127/vue-epg-planby'
import { Epg, Layout, TIME_FORMAT, formatTime, useEpg } from '@sondh0127/vue-epg-planby'
import '@sondh0127/vue-epg-planby/style.css'

import { fetchChannels, fetchEpg } from './helpers'

const darkTheme: Theme = {
primary: {
600: '#1a202c',
900: '#171923',
},
grey: { 300: '#d1d1d1' },
white: '#fff',
green: {
300: '#2C7A7B',
},
loader: {
bg: '#171923db',
},
scrollbar: {
border: '#ffffff',
thumb: {
bg: '#e1e1e1',
},
},

gradient: {
blue: {
300: '#002eb3',
600: '#002360',
900: '#051937',
},
},

text: {
grey: {
300: '#a0aec0',
500: '#718096',
},
},

timeline: {
divider: {
bg: '#718096',
},
},
}

const themeLight: Theme = {
primary: {
600: '#f7fafc',
900: '#cbd5e0',
},
grey: { 300: '#2d3748' },
white: '#1a202c',
green: {
300: '#2C7A7B',
},
loader: {
bg: '#cbd5e0db',
},
scrollbar: {
border: '#ffffff',
thumb: {
bg: '#718096',
},
},

gradient: {
blue: {
300: '#a0aec0',
600: '#e2e8f0',
900: '#a0aec0',
},
},

text: {
grey: {
300: '#2d3748',
500: '#1a202c',
},
},

timeline: {
divider: {
bg: '#1a202c',
},
},
}

const themeValue = useStorage('__VUE_EPG_THEME__', 'light')
const options = [
{
label: 'Dark theme',
value: 'dark',
},
{
label: 'Light theme',
value: 'light',
},
]

const theme = computed(() => {
return themeValue.value === 'dark' ? darkTheme : themeLight
})

const channels = ref([])
const epg = ref([])
const isLoading = ref(false)

const date = ref(new Date())
const timeRange = ref([addHours(startOfDay(new Date()), 0), endOfDay(new Date())])

const startDate = computed(() => {
const day = date.value
const startTime = timeRange.value[0]
day.setHours(startTime.getHours())
day.setMinutes(startTime.getMinutes())
day.setSeconds(startTime.getSeconds())
return formatTime(day)
})

const endDate = computed(() => {
const day = date.value
const endTime = timeRange.value[1]
day.setHours(endTime.getHours())
day.setMinutes(endTime.getMinutes())
day.setSeconds(endTime.getSeconds())
return formatTime(day)
})

const itemHeight = ref(80)
const dayWidth = ref(7200)
const sidebarWidth = ref(100)
const isSidebar = ref(true)
const isTimeline = ref(true)
const isBaseTimeFormat = ref(false)

const _24hFormat = computed({
get() {
return !isBaseTimeFormat.value
},
set(value) {
isBaseTimeFormat.value = !value
},
})

const { getEpgProps, getLayoutProps, onScrollToNow } = useEpg({
channels,
epg,
dayWidth,
sidebarWidth,
itemHeight,
isSidebar,
isTimeline,
isLine: true,
startDate,
endDate,
isBaseTimeFormat,
theme,
})

async function fetchDate() {
isLoading.value = true
epg.value = await fetchEpg(
format(subDays(date.value, 1), TIME_FORMAT.DATE),
format(addDays(date.value, 0), TIME_FORMAT.DATE),
)

channels.value = await fetchChannels()
isLoading.value = false
}

onMounted(async () => {
await fetchDate()
})

watch(date, async () => {
await fetchDate()
})

function disabledSeconds() {
return Array.from({ length: 60 }, (_, i) => i)
}

function onProgramClick(p: Program) {
console.log('onProgramClick', p)
}

function onChannelClick(c: Channel) {
console.log('onChannelClick', c)
}

```

```html







Reload




Now







































Preview


{{ data.title }}


{{ format12HoursTime(data.since) }} -{{ " " }}
{{ format12HoursTime(data.till) }}






{{ formatTimelineTime(index + offsetStartHoursRange) }}








```

[Demo →](https://stackblitz.com/edit/vue-epg-planby-demo?file=src%2FApp.vue)

## Checklist
When you use this template, try follow the checklist to update your info properly

- [x] full Interactive Demo
- [x] Light | Dark Theme
- [ ] Zooming use dayWidth
- [x] stackblitz demo
- [ ] Testing
- [ ] Loader
- [x] renderProps => scoped slot
- [ ] Vue 2.7 Test
- [x] Ref => MaybeRef => new convention of passing reactive getters as arguments. [https://github.com/vueuse/vueuse/releases/tag/v9.0.0-beta.0](https://github.com/vueuse/vueuse/releases/tag/v9.0.0-beta.0)
- [ ] Tanstack/Virtual

## Cheer me on
If you like my works, you can cheer me on here 😆

## License
MIT License © 2022 Son Hong Do

## Credits

Karol Kozer - [@kozerkarol_twitter](https://twitter.com/kozerkarol)

Planby: React based [https://github.com/karolkozer/planby](https://github.com/karolkozer/planby)