Skip to content

Commit

Permalink
feat(n-calendar): adds cell slot
Browse files Browse the repository at this point in the history
  • Loading branch information
jahnli committed Oct 11, 2024
1 parent acced75 commit eadb979
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- `n-progress`'s `color` prop supports gradient config.
- `n-select` adds `font-weight` theme variable
- `n-input` adds `font-weight` theme variable
- `n-calendar` adds `cell` slot

## 2.40.1

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- `n-progress``color` 属性支持渐变色配置
- `n-select` 新增 `font-weight` 主题变量
- `n-input` 新增 `font-weight` 主题变量
- `n-calendar` 新增 `cell` 插槽

## 2.40.1

Expand Down
109 changes: 109 additions & 0 deletions src/calendar/demos/enUS/cell.demo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<markdown>
# Custom Cell

You can use the `cell` slot to customize the data to be rendered.
</markdown>

<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import { useMessage, useThemeVars } from 'naive-ui'
import { addDays, format, isYesterday } from 'date-fns'
import { zhCN } from 'date-fns/locale'
import { Checkmark } from '@vicons/ionicons5'
export default defineComponent({
components: {
Checkmark
},
setup() {
const message = useMessage()
const themeVars = useThemeVars()
const primaryColor = computed(() => themeVars.value.primaryColor)
return {
zhCN,
format,
primaryColor,
value: ref(addDays(Date.now(), 1).valueOf()),
handleUpdateValue(
_: number,
{ year, month, date }: { year: number, month: number, date: number }
) {
message.success(`${year}-${month}-${date}`)
},
isDateDisabled(timestamp: number) {
if (isYesterday(timestamp)) {
return true
}
return false
}
}
}
})
</script>

<template>
<n-calendar
v-model:value="value"
:is-date-disabled="isDateDisabled"
@update:value="handleUpdateValue"
>
<template #cell="{ date, data }">
<div>
<div class="flex-center">
<span>
<n-avatar
:size="24"
round
:color="
data.isSelected
? primaryColor
: data.isDisabled
? '#ccc'
: '#959697'
"
>
{{ data.day }}
</n-avatar>
<n-icon
v-if="data.isSelected"
:color="primaryColor"
:size="24"
style="margin-left: 6px"
>
<Checkmark />
</n-icon>
</span>
<span>{{ format(data.timestamp, 'EEE', { locale: zhCN }) }}</span>
</div>
{{ date.year }} / {{ date.month }} / {{ date.date }}
<div v-if="data.day === 16 || data.day === 18">
<div class="flex-col-center">
<n-badge dot />
<span style="margin-left: 6px">一件高优先级的事</span>
</div>
<div class="flex-col-center">
<n-badge dot color="orange" />
<span style="margin-left: 6px">一件中优先级的事</span>
</div>
<div class="flex-col-center">
<n-badge dot color="#18a058" />
<span style="margin-left: 6px">一件低优先级的事</span>
</div>
</div>
</div>
</template>
</n-calendar>
</template>

<style>
.flex-center {
display: flex;
justify-content: space-between;
align-items: center;
}
.flex-col-center {
display: flex;
align-items: center;
}
</style>
2 changes: 2 additions & 0 deletions src/calendar/demos/enUS/index.demo-entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ How time flies.

```demo
basic.vue
cell.vue
```

## API
Expand All @@ -28,3 +29,4 @@ basic.vue
| --- | --- | --- | --- |
| default | `({ year: number, month: number, date: number })` | Content to be rendered in each date. | |
| header | `(props: { year: number, month: number })` | Header of the calendar. `month` starts from 1. | 2.29.1 |
| cell | `(props: { date: { year: number, month: number, date: number }, data: { timestamp: number, inCurrentMonth: boolean, isCurrentDate: boolean, isSelected: boolean, day: number, isDisabled: boolean } })` | Content to be rendered in each cell. | NEXT_VERSION |
109 changes: 109 additions & 0 deletions src/calendar/demos/zhCN/cell.demo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<markdown>
# 自定义单元格

你可以使用 `cell` 插槽来自定义需要渲染的数据。
</markdown>

<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import { useMessage, useThemeVars } from 'naive-ui'
import { addDays, format, isYesterday } from 'date-fns'
import { zhCN } from 'date-fns/locale'
import { Checkmark } from '@vicons/ionicons5'
export default defineComponent({
components: {
Checkmark
},
setup() {
const message = useMessage()
const themeVars = useThemeVars()
const primaryColor = computed(() => themeVars.value.primaryColor)
return {
zhCN,
format,
primaryColor,
value: ref(addDays(Date.now(), 1).valueOf()),
handleUpdateValue(
_: number,
{ year, month, date }: { year: number, month: number, date: number }
) {
message.success(`${year}-${month}-${date}`)
},
isDateDisabled(timestamp: number) {
if (isYesterday(timestamp)) {
return true
}
return false
}
}
}
})
</script>

<template>
<n-calendar
v-model:value="value"
:is-date-disabled="isDateDisabled"
@update:value="handleUpdateValue"
>
<template #cell="{ date, data }">
<div>
<div class="flex-center">
<span>
<n-avatar
:size="24"
round
:color="
data.isSelected
? primaryColor
: data.isDisabled
? '#ccc'
: '#959697'
"
>
{{ data.day }}
</n-avatar>
<n-icon
v-if="data.isSelected"
:color="primaryColor"
:size="24"
style="margin-left: 6px"
>
<Checkmark />
</n-icon>
</span>
<span>{{ format(data.timestamp, 'EEE', { locale: zhCN }) }}</span>
</div>
{{ date.year }} / {{ date.month }} / {{ date.date }}
<div v-if="data.day === 16 || data.day === 18">
<div class="flex-col-center">
<n-badge dot />
<span style="margin-left: 6px">一件高优先级的事</span>
</div>
<div class="flex-col-center">
<n-badge dot color="orange" />
<span style="margin-left: 6px">一件中优先级的事</span>
</div>
<div class="flex-col-center">
<n-badge dot color="#18a058" />
<span style="margin-left: 6px">一件低优先级的事</span>
</div>
</div>
</div>
</template>
</n-calendar>
</template>

<style>
.flex-center {
display: flex;
justify-content: space-between;
align-items: center;
}
.flex-col-center {
display: flex;
align-items: center;
}
</style>
2 changes: 2 additions & 0 deletions src/calendar/demos/zhCN/index.demo-entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

```demo
basic.vue
cell.vue
```

## API
Expand All @@ -28,3 +29,4 @@ basic.vue
| --- | --- | --- | --- |
| default | `(props: { year: number, month: number, date: number })` | 每个日期中渲染的内容 | |
| header | `(props: { year: number, month: number })` | 日历的标题,`month` 从 1 开始 | 2.29.1 |
| cell | `(props: { date: { year: number, month: number, date: number }, data: { timestamp: number, inCurrentMonth: boolean, isCurrentDate: boolean, isSelected: boolean, day: number, isDisabled: boolean } })` | 每个单元格中渲染的内容 | NEXT_VERSION |
43 changes: 29 additions & 14 deletions src/calendar/src/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,17 @@ export default defineComponent({
const notInCurrentMonth = !inCurrentMonth
const disabled = isDateDisabled?.(ts) === true
const selected = normalizedValue === startOfDay(ts).valueOf()
const cellData = {
date: dateObject,
data: {
timestamp: ts,
inCurrentMonth,
isCurrentDate,
isSelected: selected,
day: date,
isDisabled: disabled
}
}
return (
<div
key={`${calendarMonth}-${index}`}
Expand Down Expand Up @@ -323,24 +334,28 @@ export default defineComponent({
})
}}
>
<div class={`${mergedClsPrefix}-calendar-date`}>
<div
class={`${mergedClsPrefix}-calendar-date__date`}
title={fullDate}
>
{date}
</div>
{index < 7 && (
{$slots.cell ? (
$slots.cell(cellData)
) : (
<div class={`${mergedClsPrefix}-calendar-date`}>
<div
class={`${mergedClsPrefix}-calendar-date__day`}
class={`${mergedClsPrefix}-calendar-date__date`}
title={fullDate}
>
{format(ts, 'EEE', {
locale
})}
{date}
</div>
)}
</div>
{index < 7 && (
<div
class={`${mergedClsPrefix}-calendar-date__day`}
title={fullDate}
>
{format(ts, 'EEE', {
locale
})}
</div>
)}
</div>
)}
{$slots.default?.({
year,
month: month + 1,
Expand Down

0 comments on commit eadb979

Please sign in to comment.