fix(core): adjust new doc list filter style (#12629)
close AF-2678, AF-2677, AF-2674, AF-2655 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added customizable spacing for dividers. - Introduced a flexible filter value menu for easier filter editing. - Added options to control visibility of creation actions in empty document views. - **Improvements** - Enhanced menu components for filter values with a more declarative and simplified interface. - Improved vertical alignment in some UI containers. - Updated divider spacing for more consistent UI appearance. - **Bug Fixes** - Menu popups for filters now appear in correct positions. - **Removals** - Removed support for the "zotero" integration type from integration settings and filters. - **Style** - Updated CSS for better menu positioning and alignment. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
24b205ae83
commit
ea92e2291d
@ -1,3 +1,4 @@
|
||||
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
||||
import clsx from 'clsx';
|
||||
import type { HTMLAttributes, PropsWithChildren } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
@ -8,6 +9,7 @@ export type DividerProps = PropsWithChildren &
|
||||
Omit<HTMLAttributes<HTMLDivElement>, 'type'> & {
|
||||
orientation?: DividerOrientation;
|
||||
size?: 'thinner' | 'default';
|
||||
space?: number;
|
||||
dividerColor?: string;
|
||||
};
|
||||
|
||||
@ -16,6 +18,7 @@ export const Divider = forwardRef<HTMLDivElement, DividerProps>(
|
||||
{
|
||||
orientation = 'horizontal',
|
||||
size = 'default',
|
||||
space: propSpace,
|
||||
dividerColor,
|
||||
style,
|
||||
className,
|
||||
@ -23,6 +26,8 @@ export const Divider = forwardRef<HTMLDivElement, DividerProps>(
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const space = propSpace ?? (orientation === 'horizontal' ? 8 : 2);
|
||||
|
||||
return (
|
||||
<div
|
||||
data-divider
|
||||
@ -38,6 +43,7 @@ export const Divider = forwardRef<HTMLDivElement, DividerProps>(
|
||||
style={{
|
||||
borderColor: dividerColor ? dividerColor : undefined,
|
||||
...style,
|
||||
...assignInlineVars({ [styles.dividerSpace]: `${space}px` }),
|
||||
}}
|
||||
{...otherProps}
|
||||
/>
|
||||
|
@ -1,9 +1,15 @@
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { style } from '@vanilla-extract/css';
|
||||
import { createVar, style } from '@vanilla-extract/css';
|
||||
|
||||
export const dividerSpace = createVar('dividerSpace');
|
||||
|
||||
export const divider = style({
|
||||
vars: {
|
||||
[dividerSpace]: '8px',
|
||||
},
|
||||
borderBottom: `1px solid ${cssVar('borderColor')}`,
|
||||
height: 0,
|
||||
margin: '8px 0',
|
||||
margin: `${dividerSpace} 0`,
|
||||
width: '100%',
|
||||
});
|
||||
|
||||
@ -11,7 +17,7 @@ export const verticalDivider = style({
|
||||
borderLeft: `1px solid ${cssVar('borderColor')}`,
|
||||
width: 0,
|
||||
height: '100%',
|
||||
margin: '0 2px',
|
||||
margin: `0 ${dividerSpace}`,
|
||||
});
|
||||
|
||||
export const thinner = style({
|
||||
|
@ -19,11 +19,13 @@ export interface EmptyDocsProps extends UniversalEmptyProps {
|
||||
* Used for "New doc", if provided, new doc will be created with this tag.
|
||||
*/
|
||||
tagId?: string;
|
||||
allowCreate?: boolean;
|
||||
}
|
||||
|
||||
export const EmptyDocs = ({
|
||||
type = 'all',
|
||||
tagId,
|
||||
allowCreate = true,
|
||||
...props
|
||||
}: EmptyDocsProps) => {
|
||||
const t = useI18n();
|
||||
@ -56,7 +58,7 @@ export const EmptyDocs = ({
|
||||
: t['com.affine.empty.docs.all-description']()
|
||||
}
|
||||
action={
|
||||
showActionButton ? (
|
||||
allowCreate && showActionButton ? (
|
||||
<ActionButton onClick={onCreate} prefix={<AllDocsIcon />}>
|
||||
{t['com.affine.empty.docs.action.new-doc']()}
|
||||
</ActionButton>
|
||||
|
@ -81,12 +81,13 @@ const ExplorerDisplayMenu = ({
|
||||
</span>
|
||||
</div>
|
||||
</MenuSub>
|
||||
<Divider size="thinner" />
|
||||
<Divider space={4} size="thinner" />
|
||||
<DisplayProperties
|
||||
displayPreference={displayPreference}
|
||||
onDisplayPreferenceChange={onDisplayPreferenceChange}
|
||||
/>
|
||||
<Divider size="thinner" />
|
||||
|
||||
<Divider space={4} size="thinner" />
|
||||
<QuickActionsConfig
|
||||
displayPreference={displayPreference}
|
||||
onDisplayPreferenceChange={onDisplayPreferenceChange}
|
||||
|
@ -102,26 +102,30 @@ export const DisplayProperties = ({
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Divider size="thinner" />
|
||||
<section className={styles.sectionLabel}>
|
||||
{t['com.affine.all-docs.display.list-view']()}
|
||||
</section>
|
||||
<div className={styles.properties}>
|
||||
<Button
|
||||
className={styles.property}
|
||||
data-show={showIcon}
|
||||
onClick={toggleIcon}
|
||||
>
|
||||
{t['com.affine.all-docs.display.list-view.icon']()}
|
||||
</Button>
|
||||
<Button
|
||||
className={styles.property}
|
||||
data-show={showBody}
|
||||
onClick={toggleBody}
|
||||
>
|
||||
{t['com.affine.all-docs.display.list-view.body']()}
|
||||
</Button>
|
||||
</div>
|
||||
{displayPreference.view === 'list' ? (
|
||||
<>
|
||||
<Divider space={4} size="thinner" />
|
||||
<section className={styles.sectionLabel}>
|
||||
{t['com.affine.all-docs.display.list-view']()}
|
||||
</section>
|
||||
<div className={styles.properties}>
|
||||
<Button
|
||||
className={styles.property}
|
||||
data-show={showIcon}
|
||||
onClick={toggleIcon}
|
||||
>
|
||||
{t['com.affine.all-docs.display.list-view.icon']()}
|
||||
</Button>
|
||||
<Button
|
||||
className={styles.property}
|
||||
data-show={showBody}
|
||||
onClick={toggleBody}
|
||||
>
|
||||
{t['com.affine.all-docs.display.list-view.body']()}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -11,6 +11,7 @@ import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { memo, useCallback, useContext, useEffect, useMemo } from 'react';
|
||||
|
||||
import { EmptyDocs } from '../../affine/empty';
|
||||
import { ListFloatingToolbar } from '../../page-list/components/list-floating-toolbar';
|
||||
import { SystemPropertyTypes } from '../../system-property-types';
|
||||
import { WorkspacePropertyTypes } from '../../workspace-property-types';
|
||||
@ -228,6 +229,12 @@ export const DocsExplorer = ({
|
||||
[]
|
||||
);
|
||||
|
||||
const isEmpty = masonryItems.length === 0;
|
||||
|
||||
if (isEmpty) {
|
||||
return <EmptyDocs allowCreate={false} style={{ height: '100%' }} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Masonry
|
||||
|
@ -0,0 +1,33 @@
|
||||
import { Menu, type MenuProps, type MenuRef } from '@affine/component';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
export const FilterValueMenu = ({
|
||||
isDraft,
|
||||
rootOptions,
|
||||
contentOptions,
|
||||
onDraftCompleted,
|
||||
...otherProps
|
||||
}: { isDraft?: boolean; onDraftCompleted?: () => void } & MenuProps) => {
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
...rootOptions,
|
||||
}}
|
||||
contentOptions={{
|
||||
alignOffset: -4,
|
||||
...contentOptions,
|
||||
}}
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
import { Menu, MenuItem, type MenuRef } from '@affine/component';
|
||||
import { MenuItem } from '@affine/component';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
|
||||
export const FavoriteFilterValue = ({
|
||||
filter,
|
||||
@ -13,20 +14,10 @@ export const FavoriteFilterValue = ({
|
||||
onDraftCompleted?: () => void;
|
||||
onChange?: (filter: FilterParams) => void;
|
||||
}) => {
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
}}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
onDraftCompleted={onDraftCompleted}
|
||||
items={
|
||||
<>
|
||||
<MenuItem
|
||||
@ -55,6 +46,6 @@ export const FavoriteFilterValue = ({
|
||||
}
|
||||
>
|
||||
<span>{filter.value === 'true' ? 'True' : 'False'}</span>
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
@ -1,14 +1,17 @@
|
||||
import { Menu, MenuItem, type MenuRef } from '@affine/component';
|
||||
import { MenuItem } from '@affine/component';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules';
|
||||
import type { DocRecord } from '@affine/core/modules/doc';
|
||||
import { IntegrationTypeIcon } from '@affine/core/modules/integration';
|
||||
import { INTEGRATION_TYPE_NAME_MAP } from '@affine/core/modules/integration/constant';
|
||||
import type { IntegrationType } from '@affine/core/modules/integration/type';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { IntegrationsIcon, ReadwiseIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData } from '@toeverything/infra';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
|
||||
export const IntegrationTypeFilterValue = ({
|
||||
filter,
|
||||
@ -22,41 +25,37 @@ export const IntegrationTypeFilterValue = ({
|
||||
onChange?: (filter: FilterParams) => void;
|
||||
}) => {
|
||||
const t = useI18n();
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
}}
|
||||
items={
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
onChange?.({
|
||||
...filter,
|
||||
value: 'readwise',
|
||||
});
|
||||
}}
|
||||
prefixIcon={<ReadwiseIcon />}
|
||||
selected={filter.value === 'readwise'}
|
||||
>
|
||||
{t['com.affine.integration.readwise.name']()}
|
||||
</MenuItem>
|
||||
}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
onDraftCompleted={onDraftCompleted}
|
||||
items={Object.entries(INTEGRATION_TYPE_NAME_MAP).map(entries => {
|
||||
const type = entries[0] as IntegrationType;
|
||||
const i18nKey = entries[1];
|
||||
return (
|
||||
<MenuItem
|
||||
key={type}
|
||||
onClick={() => {
|
||||
onChange?.({
|
||||
...filter,
|
||||
value: type,
|
||||
});
|
||||
}}
|
||||
prefixIcon={<IntegrationTypeIcon type={type} />}
|
||||
selected={filter.value === type}
|
||||
>
|
||||
{t.t(i18nKey)}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
>
|
||||
<span>
|
||||
{filter.value === 'readwise'
|
||||
? t['com.affine.integration.readwise.name']()
|
||||
{INTEGRATION_TYPE_NAME_MAP[filter.value as IntegrationType]
|
||||
? t.t(INTEGRATION_TYPE_NAME_MAP[filter.value as IntegrationType])
|
||||
: filter.value}
|
||||
</span>
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Menu, MenuItem, type MenuRef } from '@affine/component';
|
||||
import { MenuItem } from '@affine/component';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
|
||||
export const SharedFilterValue = ({
|
||||
filter,
|
||||
@ -13,20 +14,10 @@ export const SharedFilterValue = ({
|
||||
onDraftCompleted?: () => void;
|
||||
onChange?: (filter: FilterParams) => void;
|
||||
}) => {
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
}}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
onDraftCompleted={onDraftCompleted}
|
||||
items={
|
||||
<>
|
||||
<MenuItem
|
||||
@ -55,6 +46,6 @@ export const SharedFilterValue = ({
|
||||
}
|
||||
>
|
||||
<span>{filter.value === 'true' ? 'True' : 'False'}</span>
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
@ -1,18 +1,13 @@
|
||||
import {
|
||||
Checkbox,
|
||||
Menu,
|
||||
MenuItem,
|
||||
type MenuRef,
|
||||
PropertyValue,
|
||||
} from '@affine/component';
|
||||
import { Checkbox, MenuItem, PropertyValue } from '@affine/component';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { CheckBoxCheckLinearIcon } from '@blocksuite/icons/rc';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { DocListPropertyProps, GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
import type { PropertyValueProps } from '../properties/types';
|
||||
import * as styles from './checkbox.css';
|
||||
|
||||
@ -55,20 +50,10 @@ export const CheckboxFilterValue = ({
|
||||
onDraftCompleted?: () => void;
|
||||
onChange?: (filter: FilterParams) => void;
|
||||
}) => {
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
}}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
onDraftCompleted={onDraftCompleted}
|
||||
items={
|
||||
<>
|
||||
<MenuItem
|
||||
@ -97,7 +82,7 @@ export const CheckboxFilterValue = ({
|
||||
}
|
||||
>
|
||||
<span>{filter.value === 'true' ? 'True' : 'False'}</span>
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -9,3 +9,7 @@ export const userLabelContainer = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
export const filterValueMenu = style({
|
||||
top: 'calc(var(--radix-popper-anchor-height) - 18px) !important',
|
||||
});
|
||||
|
@ -160,6 +160,7 @@ export const CreatedByUpdatedByFilterValue = ({
|
||||
onChange={handleChange}
|
||||
ref={menuRef}
|
||||
onEditorClose={onDraftCompleted}
|
||||
menuClassName={styles.filterValueMenu}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { DocListPropertyProps, GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
import { FilterOptionsGroup } from '../filter/options';
|
||||
import type { PropertyValueProps } from '../properties/types';
|
||||
import * as styles from './date.css';
|
||||
@ -123,11 +124,14 @@ const DateSelectorMenu = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
<FilterValueMenu
|
||||
rootOptions={{
|
||||
open,
|
||||
onOpenChange: handleOpenChange,
|
||||
}}
|
||||
contentOptions={{
|
||||
style: { padding: '12px 16px' },
|
||||
}}
|
||||
items={<DatePicker value={value || undefined} onChange={handleChange} />}
|
||||
>
|
||||
{value ? (
|
||||
@ -137,7 +141,7 @@ const DateSelectorMenu = ({
|
||||
{t['com.affine.filter.empty']()}
|
||||
</span>
|
||||
)}
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
type MenuRef,
|
||||
notify,
|
||||
PropertyValue,
|
||||
type RadioItem,
|
||||
@ -12,11 +10,12 @@ import { useI18n } from '@affine/i18n';
|
||||
import type { DocMode } from '@blocksuite/affine/model';
|
||||
import { EdgelessIcon, PageIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { DocListPropertyProps, GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
import type { PropertyValueProps } from '../properties/types';
|
||||
import { PropertyRadioGroup } from '../properties/widgets/radio-group';
|
||||
import * as styles from './doc-primary-mode.css';
|
||||
@ -89,20 +88,11 @@ export const DocPrimaryModeFilterValue = ({
|
||||
onChange?: (filter: FilterParams) => void;
|
||||
}) => {
|
||||
const t = useI18n();
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
}}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
onDraftCompleted={onDraftCompleted}
|
||||
items={
|
||||
<>
|
||||
<MenuItem
|
||||
@ -131,7 +121,7 @@ export const DocPrimaryModeFilterValue = ({
|
||||
}
|
||||
>
|
||||
<span>{filter.value === 'edgeless' ? t['Edgeless']() : t['Page']()}</span>
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,20 +1,15 @@
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
type MenuRef,
|
||||
PropertyValue,
|
||||
type RadioItem,
|
||||
} from '@affine/component';
|
||||
import { MenuItem, PropertyValue, type RadioItem } from '@affine/component';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules';
|
||||
import { type DocRecord, DocService } from '@affine/core/modules/doc';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { EdgelessIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
import type { PropertyValueProps } from '../properties/types';
|
||||
import { PropertyRadioGroup } from '../properties/widgets/radio-group';
|
||||
import * as styles from './edgeless-theme.css';
|
||||
@ -97,20 +92,11 @@ export const EdgelessThemeFilterValue = ({
|
||||
onChange?: (filter: FilterParams) => void;
|
||||
}) => {
|
||||
const t = useI18n();
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
}}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
onDraftCompleted={onDraftCompleted}
|
||||
items={
|
||||
<>
|
||||
<MenuItem
|
||||
@ -156,7 +142,7 @@ export const EdgelessThemeFilterValue = ({
|
||||
? t['com.affine.themeSettings.light']()
|
||||
: t['com.affine.themeSettings.dark']()}
|
||||
</span>
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,6 @@ import {
|
||||
DatePicker,
|
||||
Menu,
|
||||
MenuItem,
|
||||
type MenuRef,
|
||||
PropertyValue,
|
||||
} from '@affine/component';
|
||||
import { MobileJournalConflictList } from '@affine/core/mobile/pages/workspace/detail/menu/journal-conflicts';
|
||||
@ -25,6 +24,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { DocListPropertyProps, GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
import type { PropertyValueProps } from '../properties/types';
|
||||
import * as styles from './journal.css';
|
||||
|
||||
@ -192,20 +192,10 @@ export const JournalFilterValue = ({
|
||||
onDraftCompleted?: () => void;
|
||||
onChange?: (filter: FilterParams) => void;
|
||||
}) => {
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
}}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
onDraftCompleted={onDraftCompleted}
|
||||
items={
|
||||
<>
|
||||
<MenuItem
|
||||
@ -234,7 +224,7 @@ export const JournalFilterValue = ({
|
||||
}
|
||||
>
|
||||
<span>{filter.value === 'true' ? 'True' : 'False'}</span>
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Input, Menu, type MenuRef, PropertyValue } from '@affine/component';
|
||||
import { Input, PropertyValue } from '@affine/component';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { NumberIcon } from '@blocksuite/icons/rc';
|
||||
@ -8,13 +8,13 @@ import {
|
||||
type ChangeEventHandler,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
import type { PropertyValueProps } from '../properties/types';
|
||||
import * as styles from './number.css';
|
||||
|
||||
@ -77,15 +77,8 @@ export const NumberFilterValue = ({
|
||||
}) => {
|
||||
const [tempValue, setTempValue] = useState(filter.value || '');
|
||||
const [valueMenuOpen, setValueMenuOpen] = useState(false);
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
const t = useI18n();
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
useEffect(() => {
|
||||
// update temp value with new filter value
|
||||
setTempValue(filter.value || '');
|
||||
@ -126,8 +119,7 @@ export const NumberFilterValue = ({
|
||||
}, [isDraft, filter.method, onDraftCompleted]);
|
||||
|
||||
return filter.method !== 'is-not-empty' && filter.method !== 'is-empty' ? (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
<FilterValueMenu
|
||||
rootOptions={{
|
||||
open: valueMenuOpen,
|
||||
onOpenChange: setValueMenuOpen,
|
||||
@ -135,7 +127,6 @@ export const NumberFilterValue = ({
|
||||
}}
|
||||
contentOptions={{
|
||||
onPointerDownOutside: submitTempValue,
|
||||
sideOffset: -28,
|
||||
}}
|
||||
items={
|
||||
<Input
|
||||
@ -163,7 +154,7 @@ export const NumberFilterValue = ({
|
||||
{t['com.affine.filter.empty']()}
|
||||
</span>
|
||||
)}
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
) : null;
|
||||
};
|
||||
|
||||
|
@ -1,21 +1,16 @@
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
type MenuRef,
|
||||
PropertyValue,
|
||||
type RadioItem,
|
||||
} from '@affine/component';
|
||||
import { MenuItem, PropertyValue, type RadioItem } from '@affine/component';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules';
|
||||
import { type DocRecord, DocService } from '@affine/core/modules/doc';
|
||||
import { EditorSettingService } from '@affine/core/modules/editor-setting';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { LongerIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
import type { PropertyValueProps } from '../properties/types';
|
||||
import { PropertyRadioGroup } from '../properties/widgets/radio-group';
|
||||
import { container } from './page-width.css';
|
||||
@ -99,20 +94,11 @@ export const PageWidthFilterValue = ({
|
||||
onChange?: (filter: FilterParams) => void;
|
||||
}) => {
|
||||
const t = useI18n();
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
}}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
onDraftCompleted={onDraftCompleted}
|
||||
items={
|
||||
<>
|
||||
<MenuItem
|
||||
@ -153,7 +139,7 @@ export const PageWidthFilterValue = ({
|
||||
'com.affine.settings.editorSettings.page.default-page-width.standard'
|
||||
]()}
|
||||
</span>
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -24,3 +24,6 @@ export const groupHeaderLabel = style({
|
||||
alignItems: 'center',
|
||||
gap: 4,
|
||||
});
|
||||
export const filterValueMenu = style({
|
||||
top: 'calc(var(--radix-popper-anchor-height) - 18px) !important',
|
||||
});
|
||||
|
@ -118,6 +118,7 @@ export const TagsFilterValue = ({
|
||||
selectedTags={selectedTags}
|
||||
onSelectTag={handleSelectTag}
|
||||
onDeselectTag={handleDeselectTag}
|
||||
menuClassName={styles.filterValueMenu}
|
||||
tagMode="inline-tag"
|
||||
ref={menuRef}
|
||||
onEditorClose={onDraftCompleted}
|
||||
|
@ -1,20 +1,15 @@
|
||||
import {
|
||||
Checkbox,
|
||||
Menu,
|
||||
MenuItem,
|
||||
type MenuRef,
|
||||
PropertyValue,
|
||||
} from '@affine/component';
|
||||
import { Checkbox, MenuItem, PropertyValue } from '@affine/component';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules';
|
||||
import { type DocRecord, DocService } from '@affine/core/modules/doc';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { TemplateIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import { type ChangeEvent, useCallback, useEffect, useRef } from 'react';
|
||||
import { type ChangeEvent, useCallback } from 'react';
|
||||
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
import type { PropertyValueProps } from '../properties/types';
|
||||
import * as styles from './template.css';
|
||||
|
||||
@ -95,20 +90,10 @@ export const TemplateFilterValue = ({
|
||||
onDraftCompleted?: () => void;
|
||||
onChange?: (filter: FilterParams) => void;
|
||||
}) => {
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
rootOptions={{
|
||||
onClose: onDraftCompleted,
|
||||
}}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
onDraftCompleted={onDraftCompleted}
|
||||
items={
|
||||
<>
|
||||
<MenuItem
|
||||
@ -137,6 +122,6 @@ export const TemplateFilterValue = ({
|
||||
}
|
||||
>
|
||||
<span>{filter.value === 'true' ? 'True' : 'False'}</span>
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Input, Menu, type MenuRef, PropertyValue } from '@affine/component';
|
||||
import { Input, PropertyValue } from '@affine/component';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { TextIcon, TextTypeIcon } from '@blocksuite/icons/rc';
|
||||
@ -15,6 +15,7 @@ import {
|
||||
import { PlainTextDocGroupHeader } from '../explorer/docs-view/group-header';
|
||||
import { StackProperty } from '../explorer/docs-view/stack-property';
|
||||
import type { GroupHeaderProps } from '../explorer/types';
|
||||
import { FilterValueMenu } from '../filter/filter-value-menu';
|
||||
import { ConfigModal } from '../mobile';
|
||||
import type { PropertyValueProps } from '../properties/types';
|
||||
import * as styles from './text.css';
|
||||
@ -188,15 +189,8 @@ export const TextFilterValue = ({
|
||||
}) => {
|
||||
const [tempValue, setTempValue] = useState(filter.value || '');
|
||||
const [valueMenuOpen, setValueMenuOpen] = useState(false);
|
||||
const menuRef = useRef<MenuRef>(null);
|
||||
const t = useI18n();
|
||||
|
||||
useEffect(() => {
|
||||
if (isDraft) {
|
||||
menuRef.current?.changeOpen(true);
|
||||
}
|
||||
}, [isDraft]);
|
||||
|
||||
useEffect(() => {
|
||||
// update temp value with new filter value
|
||||
setTempValue(filter.value || '');
|
||||
@ -237,8 +231,8 @@ export const TextFilterValue = ({
|
||||
}, [isDraft, filter.method, onDraftCompleted]);
|
||||
|
||||
return filter.method !== 'is-not-empty' && filter.method !== 'is-empty' ? (
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
<FilterValueMenu
|
||||
isDraft={isDraft}
|
||||
rootOptions={{
|
||||
open: valueMenuOpen,
|
||||
onOpenChange: setValueMenuOpen,
|
||||
@ -246,7 +240,6 @@ export const TextFilterValue = ({
|
||||
}}
|
||||
contentOptions={{
|
||||
onPointerDownOutside: submitTempValue,
|
||||
sideOffset: -28,
|
||||
}}
|
||||
items={
|
||||
<Input
|
||||
@ -272,7 +265,7 @@ export const TextFilterValue = ({
|
||||
{t['com.affine.filter.empty']()}
|
||||
</span>
|
||||
)}
|
||||
</Menu>
|
||||
</FilterValueMenu>
|
||||
) : null;
|
||||
};
|
||||
|
||||
|
@ -45,4 +45,5 @@ export const container = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
gap: 4,
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
@ -9,7 +9,7 @@ import { nanoid } from 'nanoid';
|
||||
|
||||
import type { WorkspacePropertyType } from '../../workspace-property';
|
||||
|
||||
const integrationType = f.enum('readwise', 'zotero');
|
||||
const integrationType = f.enum('readwise');
|
||||
|
||||
export const AFFiNE_WORKSPACE_DB_SCHEMA = {
|
||||
folders: {
|
||||
|
@ -13,7 +13,7 @@ import type { IntegrationProperty, IntegrationType } from './type';
|
||||
// name
|
||||
export const INTEGRATION_TYPE_NAME_MAP: Record<IntegrationType, I18nString> = {
|
||||
readwise: 'com.affine.integration.name.readwise',
|
||||
zotero: 'Zotero',
|
||||
// zotero: 'Zotero',
|
||||
};
|
||||
|
||||
// schema
|
||||
@ -50,7 +50,7 @@ export const INTEGRATION_PROPERTY_SCHEMA: {
|
||||
icon: HistoryIcon,
|
||||
},
|
||||
},
|
||||
zotero: {},
|
||||
// zotero: {},
|
||||
};
|
||||
|
||||
// icon
|
||||
@ -59,5 +59,5 @@ export const INTEGRATION_ICON_MAP: Record<
|
||||
React.ComponentType<SVGProps<SVGSVGElement>>
|
||||
> = {
|
||||
readwise: ReadwiseLogoDuotoneIcon,
|
||||
zotero: () => null,
|
||||
// zotero: () => null,
|
||||
};
|
||||
|
@ -9,7 +9,6 @@ export type IntegrationType = NonNullable<DocIntegrationRef['type']>;
|
||||
|
||||
export type IntegrationDocPropertiesMap = {
|
||||
readwise: ReadwiseDocProperties;
|
||||
zotero: never;
|
||||
};
|
||||
|
||||
export type IntegrationProperty<T extends IntegrationType> = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user