ant-design/components/calendar/demo/lunar.tsx
二货爱吃白萝卜 45eeee60bb
Some checks are pending
Publish Any Commit / build (push) Waiting to run
🔀 Sync mirror to Gitee / mirror (push) Waiting to run
✅ test / lint (push) Waiting to run
✅ test / test-react-legacy (16, 1/2) (push) Waiting to run
✅ test / test-react-legacy (16, 2/2) (push) Waiting to run
✅ test / test-react-legacy (17, 1/2) (push) Waiting to run
✅ test / test-react-legacy (17, 2/2) (push) Waiting to run
✅ test / test-node (push) Waiting to run
✅ test / test-react-latest (dom, 1/2) (push) Waiting to run
✅ test / test-react-latest (dom, 2/2) (push) Waiting to run
✅ test / test-react-latest-dist (dist, 1/2) (push) Blocked by required conditions
✅ test / test-react-latest-dist (dist, 2/2) (push) Blocked by required conditions
✅ test / test-react-latest-dist (dist-min, 1/2) (push) Blocked by required conditions
✅ test / test-react-latest-dist (dist-min, 2/2) (push) Blocked by required conditions
✅ test / test-coverage (push) Blocked by required conditions
✅ test / build (push) Waiting to run
✅ test / test lib/es module (es, 1/2) (push) Waiting to run
✅ test / test lib/es module (es, 2/2) (push) Waiting to run
✅ test / test lib/es module (lib, 1/2) (push) Waiting to run
✅ test / test lib/es module (lib, 2/2) (push) Waiting to run
👁️ Visual Regression Persist Start / test image (push) Waiting to run
feat: Add unstable api for React 19 compitable (#51979)
* chore: add unstable entrance

* chore: rest of it

* chore: use React 19

* chore: fix lint

* chore: fix lint

* chore: fix lint

* chore: fix lint

* chore: fix lint

* chore: fix lint

* chore: fix lint

* chore: test ignore 19 preload

* chore: bump rc-util

* fix: warning of pure render

* fix: warning of 19

* chore: adjust ts

* test: fix test logic

* test: fix test case

* test: fix test case

* test: fix test case

* test: fix test case

* test: fix test case

* test: fix test case

* test: fix test case

* test: fix test case

* chore: restore file

* test: fix test case

* test: fix test case

* test: fix test case

* test: fix test case

* test: fix test case

* test: update test

* test: fix test case

* test: update snapshot

* test: fix coverage

* test: fix coverage

* test: add ignore image
2024-12-18 14:09:49 +08:00

257 lines
7.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react';
import { Calendar, Col, Radio, Row, Select } from 'antd';
import type { CalendarProps } from 'antd';
import { createStyles } from 'antd-style';
import classNames from 'classnames';
import dayjs from 'dayjs';
import type { Dayjs } from 'dayjs';
import { HolidayUtil, Lunar } from 'lunar-typescript';
const useStyle = createStyles(({ token, css, cx }) => {
const lunar = css`
color: ${token.colorTextTertiary};
font-size: ${token.fontSizeSM}px;
`;
const weekend = css`
color: ${token.colorError};
&.gray {
opacity: 0.4;
}
`;
return {
wrapper: css`
width: 450px;
border: 1px solid ${token.colorBorderSecondary};
border-radius: ${token.borderRadiusOuter};
padding: 5px;
`,
dateCell: css`
position: relative;
&:before {
content: '';
position: absolute;
inset-inline-start: 0;
inset-inline-end: 0;
top: 0;
bottom: 0;
margin: auto;
max-width: 40px;
max-height: 40px;
background: transparent;
transition: background-color 300ms;
border-radius: ${token.borderRadiusOuter}px;
border: 1px solid transparent;
box-sizing: border-box;
}
&:hover:before {
background: rgba(0, 0, 0, 0.04);
}
`,
today: css`
&:before {
border: 1px solid ${token.colorPrimary};
}
`,
text: css`
position: relative;
z-index: 1;
`,
lunar,
current: css`
color: ${token.colorTextLightSolid};
&:before {
background: ${token.colorPrimary};
}
&:hover:before {
background: ${token.colorPrimary};
opacity: 0.8;
}
.${cx(lunar)} {
color: ${token.colorTextLightSolid};
opacity: 0.9;
}
.${cx(weekend)} {
color: ${token.colorTextLightSolid};
}
`,
monthCell: css`
width: 120px;
color: ${token.colorTextBase};
border-radius: ${token.borderRadiusOuter}px;
padding: 5px 0;
&:hover {
background: rgba(0, 0, 0, 0.04);
}
`,
monthCellCurrent: css`
color: ${token.colorTextLightSolid};
background: ${token.colorPrimary};
&:hover {
background: ${token.colorPrimary};
opacity: 0.8;
}
`,
weekend,
};
});
const App: React.FC = () => {
const { styles } = useStyle({ test: true });
const [selectDate, setSelectDate] = React.useState<Dayjs>(dayjs());
const [panelDateDate, setPanelDate] = React.useState<Dayjs>(dayjs());
const onPanelChange = (value: Dayjs, mode: CalendarProps<Dayjs>['mode']) => {
console.log(value.format('YYYY-MM-DD'), mode);
setPanelDate(value);
};
const onDateChange: CalendarProps<Dayjs>['onSelect'] = (value, selectInfo) => {
if (selectInfo.source === 'date') {
setSelectDate(value);
}
};
const cellRender: CalendarProps<Dayjs>['fullCellRender'] = (date, info) => {
const d = Lunar.fromDate(date.toDate());
const lunar = d.getDayInChinese();
const solarTerm = d.getJieQi();
const isWeekend = date.day() === 6 || date.day() === 0;
const h = HolidayUtil.getHoliday(date.get('year'), date.get('month') + 1, date.get('date'));
const displayHoliday = h?.getTarget() === h?.getDay() ? h?.getName() : undefined;
if (info.type === 'date') {
return React.cloneElement(info.originNode, {
...(info.originNode as React.ReactElement<any>).props,
className: classNames(styles.dateCell, {
[styles.current]: selectDate.isSame(date, 'date'),
[styles.today]: date.isSame(dayjs(), 'date'),
}),
children: (
<div className={styles.text}>
<span
className={classNames({
[styles.weekend]: isWeekend,
gray: !panelDateDate.isSame(date, 'month'),
})}
>
{date.get('date')}
</span>
{info.type === 'date' && (
<div className={styles.lunar}>{displayHoliday || solarTerm || lunar}</div>
)}
</div>
),
});
}
if (info.type === 'month') {
// Due to the fact that a solar month is part of the lunar month X and part of the lunar month X+1,
// when rendering a month, always take X as the lunar month of the month
const d2 = Lunar.fromDate(new Date(date.get('year'), date.get('month')));
const month = d2.getMonthInChinese();
return (
<div
className={classNames(styles.monthCell, {
[styles.monthCellCurrent]: selectDate.isSame(date, 'month'),
})}
>
{date.get('month') + 1}{month}
</div>
);
}
};
const getYearLabel = (year: number) => {
const d = Lunar.fromDate(new Date(year + 1, 0));
return `${d.getYearInChinese()}年(${d.getYearInGanZhi()}${d.getYearShengXiao()}年)`;
};
const getMonthLabel = (month: number, value: Dayjs) => {
const d = Lunar.fromDate(new Date(value.year(), month));
const lunar = d.getMonthInChinese();
return `${month + 1}月(${lunar}月)`;
};
return (
<div className={styles.wrapper}>
<Calendar
fullCellRender={cellRender}
fullscreen={false}
onPanelChange={onPanelChange}
onSelect={onDateChange}
headerRender={({ value, type, onChange, onTypeChange }) => {
const start = 0;
const end = 12;
const monthOptions = [];
let current = value.clone();
const localeData = value.localeData();
const months = [];
for (let i = 0; i < 12; i++) {
current = current.month(i);
months.push(localeData.monthsShort(current));
}
for (let i = start; i < end; i++) {
monthOptions.push({
label: getMonthLabel(i, value),
value: i,
});
}
const year = value.year();
const month = value.month();
const options = [];
for (let i = year - 10; i < year + 10; i += 1) {
options.push({
label: getYearLabel(i),
value: i,
});
}
return (
<Row justify="end" gutter={8} style={{ padding: 8 }}>
<Col>
<Select
size="small"
popupMatchSelectWidth={false}
className="my-year-select"
value={year}
options={options}
onChange={(newYear) => {
const now = value.clone().year(newYear);
onChange(now);
}}
/>
</Col>
<Col>
<Select
size="small"
popupMatchSelectWidth={false}
value={month}
options={monthOptions}
onChange={(newMonth) => {
const now = value.clone().month(newMonth);
onChange(now);
}}
/>
</Col>
<Col>
<Radio.Group
size="small"
onChange={(e) => onTypeChange(e.target.value)}
value={type}
>
<Radio.Button value="month"></Radio.Button>
<Radio.Button value="year"></Radio.Button>
</Radio.Group>
</Col>
</Row>
);
}}
/>
</div>
);
};
export default App;