Skip to content

Commit

Permalink
✨ feat: Add FormModal
Browse files Browse the repository at this point in the history
  • Loading branch information
canisminor1990 committed Dec 27, 2024
1 parent 3ae3d16 commit 8fad511
Show file tree
Hide file tree
Showing 18 changed files with 708 additions and 208 deletions.
16 changes: 11 additions & 5 deletions src/Collapse/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { useStyles } from './style';

export type Variant = 'default' | 'block' | 'ghost' | 'pure';

export interface CollapseProps extends AntdCollapseProps {
export interface CollapseProps extends Omit<AntdCollapseProps, 'collapsible'> {
collapsible?: boolean;
gap?: number;
padding?:
| number
Expand All @@ -21,13 +22,13 @@ export interface CollapseProps extends AntdCollapseProps {
}

const Collapse = memo<CollapseProps>(
({ style, variant = 'default', gap = 0, className, padding, ...rest }) => {
({ style, variant = 'default', gap = 0, className, padding, collapsible = true, ...rest }) => {
const bodyPadding = typeof padding === 'object' ? padding.body : padding;
const headerPadding = typeof padding === 'object' ? padding.header : padding;

const { cx, styles } = useStyles({
bodyPadding: bodyPadding === undefined ? '12px 16px' : bodyPadding,
headerPadding: headerPadding === undefined ? '12px 16px' : headerPadding,
bodyPadding,
headerPadding,
isSplit: !!gap,
});

Expand All @@ -41,7 +42,12 @@ const Collapse = memo<CollapseProps>(
return (
<AntdCollapse
bordered={!gap && (variant === 'default' || variant === 'ghost')}
className={cx(styles.group, variantStyle, className)}
className={cx(
styles.group,
!collapsible && styles.hideCollapsibleIcon,
variantStyle,
className,
)}
expandIcon={({ isActive }) => (
<Icon
className={styles.icon}
Expand Down
11 changes: 8 additions & 3 deletions src/Collapse/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ export const useStyles = createStyles(
{ css, cx, token, isDarkMode, prefixCls },
{
isSplit,
bodyPadding,
headerPadding,
}: { bodyPadding: number | string; headerPadding: number | string; isSplit: boolean },
bodyPadding = '12px 16px',
headerPadding = '12px 16px',
}: { bodyPadding?: number | string; headerPadding?: number | string; isSplit?: boolean },
) => {
const pureStyle = css`
background: transparent;
Expand Down Expand Up @@ -171,6 +171,11 @@ export const useStyles = createStyles(
}
`,
),
hideCollapsibleIcon: css`
.${prefixCls}-collapse-expand-icon {
display: none !important;
}
`,

icon: css`
transition: all 100ms ${token.motionEaseOut};
Expand Down
166 changes: 51 additions & 115 deletions src/Form/components/FormGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,111 +1,34 @@
import { Collapse, type CollapseProps } from 'antd';
import { createStyles, useResponsive } from 'antd-style';
import { ChevronDown } from 'lucide-react';
import { isUndefined } from 'lodash-es';
import { type ReactNode, memo } from 'react';
import { Flexbox } from 'react-layout-kit';

import Collapse, { type CollapseProps } from '@/Collapse';
import Icon, { type IconProps } from '@/Icon';

export type FormVariant = 'default' | 'block' | 'ghost' | 'pure';
export type ItemsType = 'group' | 'flat';

export const useStyles = createStyles(({ css, cx, token, isDarkMode, responsive, prefixCls }) => {
const pureStyle = css`
background: transparent;
border: none;
border-radius: 0;
.${prefixCls}-collapse-header {
padding-block: 0 20px !important;
padding-inline: 2px !important;
background: transparent !important;
border-radius: 0 !important;
}
.${prefixCls}-collapse-content {
background: transparent;
border-color: ${token.colorFillSecondary};
}
.${prefixCls}-collapse-content-box {
padding-inline: 2px !important;
background: transparent;
border-radius: 0;
}
`;

const blockStyle = css`
background: ${token.colorFillQuaternary};
border: none;
border-radius: ${token.borderRadiusLG}px;
.${prefixCls}-collapse-content {
border: none !important;
}
`;
const ghostStyle = css`
background: transparent;
border: 1px solid ${token.colorBorderSecondary};
.${prefixCls}-collapse-header {
background: transparent !important;
}
.${prefixCls}-collapse-content-box {
background: transparent;
}
`;

const defaultStyle = css`
background: ${token.colorFillQuaternary};
border: 1px solid ${token.colorBorderSecondary};
border-radius: ${token.borderRadiusLG}px;
`;

export const useStyles = createStyles(({ css, token, responsive }) => {
return {
blockStyle,
defaultStyle,
blockStyle: css`
background: ${token.colorFillQuaternary};
border: none;
border-radius: ${token.borderRadiusLG}px;
`,
defaultStyle: css`
background: ${token.colorFillQuaternary};
border: 1px solid ${token.colorBorderSecondary};
border-radius: ${token.borderRadiusLG}px;
`,
flatGroup: css`
overflow: hidden;
padding-inline: 16px;
`,
ghostStyle,
group: cx(
isDarkMode &&
css`
.${prefixCls}-collapse-content {
background: transparent;
border-color: ${token.colorBorderSecondary};
}
.${prefixCls}-collapse-header {
background: ${token.colorFillTertiary};
}
`,
css`
overflow: hidden;
flex: none;
.${prefixCls}-collapse-item {
border: none;
}
.${prefixCls}-collapse-header {
align-items: center !important;
border-radius: 0 !important;
}
.${prefixCls}-collapse-content-box {
padding-block: 0 !important;
}
.${prefixCls}-form-item-label {
display: flex;
flex-direction: column;
justify-content: center;
}
`,
),

ghostStyle: css`
background: transparent;
border: 1px solid ${token.colorBorderSecondary};
`,
icon: css`
transition: all 100ms ${token.motionEaseOut};
`,
Expand All @@ -121,7 +44,12 @@ export const useStyles = createStyles(({ css, cx, token, isDarkMode, responsive,
padding: 16px;
background: ${token.colorBgLayout};
`,
pureStyle,
pureStyle: css`
padding: 0;
background: transparent;
border: none;
border-radius: 0;
`,
pureTitle: css`
font-size: 18px;
font-weight: 700;
Expand All @@ -145,8 +73,9 @@ export const useStyles = createStyles(({ css, cx, token, isDarkMode, responsive,
};
});

export interface FormGroupProps extends CollapseProps {
export interface FormGroupProps extends Omit<CollapseProps, 'collapsible'> {
children: ReactNode;
collapsible?: boolean;
defaultActive?: boolean;
extra?: ReactNode;
icon?: IconProps['icon'];
Expand All @@ -165,10 +94,16 @@ const FormGroup = memo<FormGroupProps>(
itemsType,
variant = 'default',
defaultActive = true,
collapsible,
...rest
}) => {
const { mobile } = useResponsive();
const { cx, styles } = useStyles(variant);
const { cx, styles, prefixCls } = useStyles(variant);

const groupClassName = `${prefixCls}-form-group`;
const groupTitleClassName = `${prefixCls}-form-group-title`;
const groupHeaderClassName = `${prefixCls}-form-group-header`;
const groupContentClassName = `${prefixCls}-form-group-content`;

const variantStyle = cx(
variant === 'default' && styles.defaultStyle,
Expand All @@ -177,9 +112,11 @@ const FormGroup = memo<FormGroupProps>(
variant === 'pure' && styles.pureStyle,
);

const defaultCollapsible = isUndefined(collapsible) ? variant !== 'pure' : collapsible;

const titleContent = (
<Flexbox
className={cx(styles.title, variant === 'pure' && styles.pureTitle)}
className={cx(groupTitleClassName, styles.title, variant === 'pure' && styles.pureTitle)}
gap={8}
horizontal
>
Expand All @@ -190,40 +127,38 @@ const FormGroup = memo<FormGroupProps>(

if (itemsType === 'flat') {
return mobile ? (
<Flexbox className={cx(styles.mobileFlatGroup, styles.mobileGroupBody, className)}>
<Flexbox
className={cx(groupClassName, styles.mobileFlatGroup, styles.mobileGroupBody, className)}
>
{children}
</Flexbox>
) : (
<Flexbox className={cx(styles.flatGroup, variantStyle, className)}>{children}</Flexbox>
<Flexbox className={cx(groupClassName, styles.flatGroup, variantStyle, className)}>
{children}
</Flexbox>
);
}

if (mobile)
return (
<Flexbox className={className}>
<Flexbox className={styles.mobileGroupHeader} horizontal justify={'space-between'}>
<Flexbox className={cx(groupClassName, className)}>
<Flexbox
className={cx(groupHeaderClassName, styles.mobileGroupHeader)}
horizontal
justify={'space-between'}
>
{titleContent}
{extra}
</Flexbox>
<div className={styles.mobileGroupBody}>{children}</div>
<div className={cx(groupContentClassName, styles.mobileGroupBody)}>{children}</div>
</Flexbox>
);

return (
<Collapse
className={cx(styles.group, variantStyle, className)}
collapsible={variant === 'pure' ? 'icon' : undefined}
className={cx(groupClassName, className)}
collapsible={defaultCollapsible}
defaultActiveKey={defaultActive ? [1] : undefined}
expandIcon={({ isActive }) =>
variant === 'pure' ? null : (
<Icon
className={styles.icon}
icon={ChevronDown}
size={{ fontSize: 16 }}
style={isActive ? {} : { rotate: '-90deg' }}
/>
)
}
items={[
{
children,
Expand All @@ -233,6 +168,7 @@ const FormGroup = memo<FormGroupProps>(
},
]}
key={1}
variant={variant}
{...rest}
/>
);
Expand Down
4 changes: 4 additions & 0 deletions src/Form/components/FormItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export const useStyles = createStyles(
padding-block: 16px;
padding-inline: 0;
.${prefixCls}-form-item-label {
text-align: start;
}
.${prefixCls}-row {
gap: 12px;
justify-content: space-between;
Expand Down
30 changes: 23 additions & 7 deletions src/Form/demos/Flat.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Form, type FormProps } from '@lobehub/ui';
import { StoryBook, useControls, useCreateStore } from '@lobehub/ui/storybook';
import { Select, Switch } from 'antd';

const setting = {
Expand Down Expand Up @@ -40,13 +41,28 @@ const items: FormProps['items'] = [
];

export default () => {
const store = useCreateStore();

const { variant }: any = useControls(
{
variant: {
options: ['default', 'block', 'ghost', 'pure'],
value: 'default',
},
},
{ store },
);

return (
<Form
initialValues={setting}
itemMinWidth={'max(30%,240px)'}
items={items}
itemsType={'flat'}
onFinish={console.table}
/>
<StoryBook levaStore={store}>
<Form
initialValues={setting}
itemMinWidth={'max(30%,240px)'}
items={items}
itemsType={'flat'}
onFinish={console.table}
variant={variant}
/>
</StoryBook>
);
};
2 changes: 1 addition & 1 deletion src/Form/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ description: High performance Form component with data scope management. Includi

## Flat Type

<code src="./demos/Flat.tsx" center></code>
<code src="./demos/Flat.tsx" nopadding></code>

## APIs

Expand Down
Loading

0 comments on commit 8fad511

Please sign in to comment.