feat(core): journal sidebar dater-picker navigation (#5558)

This commit is contained in:
Cats Juice 2024-01-18 12:34:23 +00:00
parent 496dc588be
commit 70ea1e5ef8
No known key found for this signature in database
GPG Key ID: 1C1E76924FAFDDE4
8 changed files with 88 additions and 28 deletions

View File

@ -5,7 +5,7 @@ import {
} from '@blocksuite/icons';
import clsx from 'clsx';
import dayjs from 'dayjs';
import { type HTMLAttributes, useCallback, useState } from 'react';
import { type HTMLAttributes, useCallback, useEffect, useState } from 'react';
import DatePicker, { type ReactDatePickerProps } from 'react-datepicker';
import * as styles from './index.css';
@ -24,9 +24,10 @@ const months = [
'December',
];
export interface AFFiNEDatePickerProps
extends Omit<ReactDatePickerProps, 'onChange'> {
extends Omit<ReactDatePickerProps, 'onChange' | 'onSelect'> {
value?: string;
onChange: (value: string) => void;
onChange?: (value: string) => void;
onSelect?: (value: string) => void;
}
interface HeaderLayoutProps extends HTMLAttributes<HTMLDivElement> {
@ -74,6 +75,10 @@ const HeaderLayout = ({
export const AFFiNEDatePicker = ({
value,
onChange,
onSelect,
calendarClassName,
...props
}: AFFiNEDatePickerProps) => {
const [openMonthPicker, setOpenMonthPicker] = useState(false);
@ -86,10 +91,16 @@ export const AFFiNEDatePicker = ({
const handleCloseMonthPicker = useCallback(() => {
setOpenMonthPicker(false);
}, []);
const handleSelectDate = (date: Date | null) => {
const handleDateChange = (date: Date | null) => {
if (date) {
setSelectedDate(date);
onChange(dayjs(date).format('YYYY-MM-DD'));
onChange?.(dayjs(date).format('YYYY-MM-DD'));
setOpenMonthPicker(false);
}
};
const handleDateSelect = (date: Date | null) => {
if (date) {
onSelect?.(dayjs(date).format('YYYY-MM-DD'));
setOpenMonthPicker(false);
}
};
@ -207,17 +218,23 @@ export const AFFiNEDatePicker = ({
/>
);
};
useEffect(() => {
setSelectedDate(value ? dayjs(value).toDate() : null);
}, [value]);
return (
<DatePicker
onClickOutside={handleCloseMonthPicker}
className={styles.inputStyle}
calendarClassName={styles.calendarStyle}
calendarClassName={clsx(styles.calendarStyle, calendarClassName)}
weekDayClassName={() => styles.weekStyle}
dayClassName={() => styles.dayStyle}
popperClassName={styles.popperStyle}
monthClassName={() => styles.mouthsStyle}
selected={selectedDate}
onChange={handleSelectDate}
onChange={handleDateChange}
onSelect={handleDateSelect}
showPopperArrow={false}
dateFormat="MMM dd"
showMonthYearPicker={openMonthPicker}

View File

@ -151,28 +151,22 @@ export const dayStyle = style([
fontWeight: '400',
borderRadius: '8px',
selectors: {
'&:hover': {
'&[aria-selected="false"]:hover': {
background: 'var(--affine-hover-color)',
borderRadius: '8px',
transition: 'background-color 0.3s ease-in-out',
},
'&[aria-selected="true"]': {
color: 'var(--affine-black)',
background: 'var(--affine-hover-color)',
},
'&[aria-selected="true"]:hover': {
background: 'var(--affine-hover-color)',
color: 'var(--affine-pure-white)',
background: 'var(--affine-primary-color)',
fontWeight: '500',
},
'&[tabindex="0"][aria-selected="false"]': {
background: 'var(--affine-background-overlay-panel-color)',
},
'&.react-datepicker__day--today[aria-selected="false"]': {
background: 'var(--affine-primary-color)',
color: 'var(--affine-palette-line-white)',
},
'&.react-datepicker__day--today[aria-selected="false"]:hover': {
color: 'var(--affine-black)',
background: 'var(--affine-hover-color)',
fontWeight: '600',
color: 'var(--affine-primary-color)',
},
'&.react-datepicker__day--outside-month[aria-selected="false"]': {
color: 'var(--affine-text-disable-color)',

View File

@ -194,7 +194,7 @@ const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) {
!isInTrash ? (
<div className={styles.sidebarContainerInner}>
<RightSidebarHeader workspace={blockSuiteWorkspace} page={page} />
<EditorSidebar />
<EditorSidebar workspace={blockSuiteWorkspace} page={page} />
</div>
) : null
}

View File

@ -1,11 +1,16 @@
import { useAtomValue } from 'jotai';
import type { EditorExtensionProps } from '.';
import { editorSidebarActiveExtensionAtom } from './atoms';
import * as styles from './editor-sidebar.css';
export const EditorSidebar = () => {
export const EditorSidebar = (props: EditorExtensionProps) => {
const activeExtension = useAtomValue(editorSidebarActiveExtensionAtom);
const Component = activeExtension?.Component;
return <div className={styles.root}>{Component ? <Component /> : null}</div>;
return (
<div className={styles.root}>
{Component ? <Component {...props} /> : null}
</div>
);
};

View File

@ -0,0 +1,5 @@
import { style } from '@vanilla-extract/css';
export const calendar = style({
padding: '16px',
});

View File

@ -1,9 +1,40 @@
import { AFFiNEDatePicker } from '@affine/component';
import {
useJournalHelper,
useJournalInfoHelper,
} from '@affine/core/hooks/use-journal';
import { TodayIcon } from '@blocksuite/icons';
import dayjs from 'dayjs';
import { useCallback, useEffect, useState } from 'react';
import type { EditorExtension } from '..';
import type { EditorExtension, EditorExtensionProps } from '..';
import * as styles from './journal.css';
const EditorJournalPanel = () => {
return <div>journal extension</div>;
const EditorJournalPanel = ({ workspace, page }: EditorExtensionProps) => {
const { journalDate } = useJournalInfoHelper(page?.meta);
const { openJournal } = useJournalHelper(workspace);
const [date, setDate] = useState(dayjs().format('YYYY-MM-DD'));
useEffect(() => {
journalDate && setDate(journalDate.format('YYYY-MM-DD'));
}, [journalDate]);
const onDateSelect = useCallback(
(date: string) => {
if (journalDate && dayjs(date).isSame(dayjs(journalDate))) return;
openJournal(date);
},
[journalDate, openJournal]
);
return (
<AFFiNEDatePicker
inline
value={date}
onSelect={onDateSelect}
calendarClassName={styles.calendar}
/>
);
};
export const journalExtension: EditorExtension = {

View File

@ -1,7 +1,15 @@
import type { BlockSuiteWorkspace } from '@affine/core/shared';
import type { Page } from '@blocksuite/store';
export type EditorExtensionName = 'outline' | 'frame' | 'copilot' | 'journal';
export interface EditorExtensionProps {
workspace: BlockSuiteWorkspace;
page: Page;
}
export interface EditorExtension {
name: EditorExtensionName;
icon: React.ReactNode;
Component: React.ComponentType;
Component: React.ComponentType<EditorExtensionProps>;
}

View File

@ -460,8 +460,8 @@ test('disable quick search when the link-popup is visitable', async ({
await getBlockSuiteEditorTitle(page).click();
await getBlockSuiteEditorTitle(page).fill(specialTitle);
await page.keyboard.press('Enter', { delay: 10 });
await page.keyboard.insertText('123456');
await page.getByText('123456').dblclick();
await page.keyboard.insertText('1234567890');
await page.getByText('1234567890').dblclick();
await withCtrlOrMeta(page, () => page.keyboard.press('k', { delay: 50 }));
const linkPopup = page.locator('.affine-link-popover');