Skip to content

Commit

Permalink
chore: 自定义样式抽象成装饰器
Browse files Browse the repository at this point in the history
  • Loading branch information
qkiroc committed Oct 30, 2024
1 parent 1b17c39 commit 1b0a36d
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 73 deletions.
73 changes: 66 additions & 7 deletions packages/amis-core/src/components/CustomStyle.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import {useEffect, useRef} from 'react';
import type {RendererEnv} from '../env';
import {
removeCustomStyle,
type InsertCustomStyle,
insertCustomStyle,
insertEditCustomStyle
insertEditCustomStyle,
CustomStyleClassName,
setThemeClassName
} from '../utils/style-helper';
import React from 'react';
import {PlainObject} from '../types';
import cx from 'classnames';

interface CustomStyleProps {
config: {
wrapperCustomStyle?: any;
componentId?: string;
} & InsertCustomStyle;
[propName: string]: any;
}

export const styleIdCount = new Map();

export default function (props: CustomStyleProps) {
const {config, env, data} = props;
export default function CustomStyle(props: CustomStyleProps) {
const {config, env, data, children, classPrefix} = props;
const {themeCss, classNames, defaultData, wrapperCustomStyle} = config;
const id = config.id ? `${config.id}` : config.id;

Expand Down Expand Up @@ -47,7 +50,8 @@ export default function (props: CustomStyleProps) {
defaultData,
customStyleClassPrefix: env?.customStyleClassPrefix,
doc: env?.getModalContainer?.()?.ownerDocument,
data
data,
classPrefix
});
}

Expand Down Expand Up @@ -85,5 +89,60 @@ export default function (props: CustomStyleProps) {
};
}, [wrapperCustomStyle, id]);

return null;
return children;
}

/**
* 自定义样式装饰器
*/
export function CustomStyleWrapper(config: {
classNames: CustomStyleClassName[];
wrapperCustomStyle?: boolean;
themeCss?: string;
id?: string;
}) {
return function <T extends React.ComponentType>(Component: T): T {
const WrappedComponent = (props: any) => {
const id = config.id || props.id;
const themeCss = props[config.themeCss || 'themeCss'];

const [className, setClassName] = React.useState<PlainObject>({});

useEffect(() => {
const className: PlainObject = {};
config.classNames.forEach(item => {
if (item.name) {
className[item.name] = cx(
setThemeClassName({
props,
name: item.key,
id,
themeCss
}),
props[item.name]
);
}
});
setClassName(className);
}, [props]);

return (
<>
<CustomStyle
config={{
classNames: config.classNames,
id,
themeCss,
wrapperCustomStyle: config.wrapperCustomStyle
? props.wrapperCustomStyle
: null
}}
{...props}
/>
<Component {...props} {...className} />
</>
);
};
return WrappedComponent as unknown as T;
};
}
3 changes: 2 additions & 1 deletion packages/amis-core/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ import {
SchemaRenderer
} from './SchemaRenderer';
import type {IItem} from './store/list';
import CustomStyle from './components/CustomStyle';
import CustomStyle, {CustomStyleWrapper} from './components/CustomStyle';
import {StatusScoped} from './StatusScoped';

import styleManager from './StyleManager';
Expand Down Expand Up @@ -231,6 +231,7 @@ export {
filterTarget,
splitTarget,
CustomStyle,
CustomStyleWrapper,
enableDebug,
disableDebug,
envOverwrite,
Expand Down
45 changes: 35 additions & 10 deletions packages/amis-core/src/utils/style-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ export const inheritValueMap: PlainObject = {

interface extra {
important?: boolean;
parent?: string;
inner?: string;
pre?: string;
suf?: string;
parent?: string | ((ns: string) => string);
inner?: string | ((ns: string) => string);
pre?: string | ((ns: string) => string);
suf?: string | ((ns: string) => string);
}

/**
Expand Down Expand Up @@ -169,7 +169,8 @@ export function formatStyle(
classNames?: CustomStyleClassName[],
id?: string,
defaultData?: any,
data?: any
data?: any,
classPrefix?: string
) {
// 没有具体的样式,或者没有对应的classname
if (!themeCss || !classNames) {
Expand Down Expand Up @@ -272,9 +273,23 @@ export function formatStyle(
}
});
if (styles.length > 0) {
const cx = (weights?.pre || '') + className + (weights?.suf || '');
const inner = weights?.inner || '';
const parent = weights?.parent || '';
const pre =
typeof weights?.pre === 'function'
? weights.pre(classPrefix)
: weights?.pre || '';
const suf =
typeof weights?.suf === 'function'
? weights.suf(classPrefix)
: weights?.suf || '';
const cx = pre + className + suf;
const inner =
typeof weights?.inner === 'function'
? weights.inner(classPrefix)
: weights?.inner || '';
const parent =
weights?.parent === 'function'
? weights.parent(classPrefix)
: weights?.parent || '';

res.push({
className: parent + cx + status2string[status] + inner,
Expand All @@ -300,6 +315,7 @@ export function formatStyle(

export interface CustomStyleClassName {
key: string;
name?: string;
weights?: {
default?: extra;
hover?: extra;
Expand All @@ -316,6 +332,7 @@ export function insertCustomStyle(params: {
defaultData?: any;
customStyleClassPrefix?: string;
doc?: Document;
classPrefix?: string;
[propName: string]: any;
}) {
const {
Expand All @@ -325,13 +342,21 @@ export function insertCustomStyle(params: {
defaultData,
customStyleClassPrefix,
doc,
data
data,
classPrefix
} = params;
if (!themeCss) {
return;
}

let {value} = formatStyle(themeCss, classNames, id, defaultData, data);
let {value} = formatStyle(
themeCss,
classNames,
id,
defaultData,
data,
classPrefix
);
value = customStyleClassPrefix ? `${customStyleClassPrefix} ${value}` : value;
let classId = id?.replace?.('u:', '') || id + '';
if (typeof data?.index === 'number') {
Expand Down
93 changes: 38 additions & 55 deletions packages/amis/src/renderers/Form/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import {
autobind,
TestIdBuilder,
getVariable,
CustomStyle,
setThemeClassName
CustomStyleWrapper
} from 'amis-core';
import {TransferDropDown, Spinner, Select, SpinnerExtraProps} from 'amis-ui';
import {FormOptionsSchema, SchemaApi} from '../../Schema';
Expand Down Expand Up @@ -526,6 +525,7 @@ export default class SelectControl extends React.Component<SelectProps, any> {
showInvalidMatch,
options,
className,
controlClassName,
popoverClassName,
style,
loading,
Expand All @@ -550,7 +550,6 @@ export default class SelectControl extends React.Component<SelectProps, any> {
filterOption,
...rest
} = this.props;
const {classPrefix: ns, themeCss} = this.props;

if (noResultsText) {
noResultsText = render('noResultText', noResultsText);
Expand All @@ -571,23 +570,8 @@ export default class SelectControl extends React.Component<SelectProps, any> {
onAdd={this.handleOptionAdd}
onEdit={this.handleOptionEdit}
onDelete={this.handleOptionDelete}
className={cx(
setThemeClassName({
...this.props,
name: 'selectControlClassName',
id,
themeCss: themeCss
})
)}
popoverClassName={cx(
popoverClassName,
setThemeClassName({
...this.props,
name: 'selectPopoverClassName',
id,
themeCss: themeCss
})
)}
className={controlClassName}
popoverClassName={popoverClassName}
mobileUI={mobileUI}
popOverContainer={
mobileUI
Expand Down Expand Up @@ -620,41 +604,6 @@ export default class SelectControl extends React.Component<SelectProps, any> {
overlay={overlay}
/>
)}
<CustomStyle
{...this.props}
config={{
themeCss: themeCss,
classNames: [
{
key: 'selectControlClassName',
weights: {
focused: {
suf: '.is-opened:not(.is-mobile)'
},
disabled: {
suf: '.is-disabled'
}
}
},
{
key: 'selectPopoverClassName',
weights: {
default: {
suf: ` .${ns}Select-option`
},
hover: {
suf: ` .${ns}Select-option.is-highlight`
},
focused: {
inner: `.${ns}Select-option.is-active`
}
}
}
],
id: id
}}
env={env}
/>
</div>
);
}
Expand Down Expand Up @@ -789,14 +738,48 @@ class TransferDropdownRenderer extends BaseTransferRenderer<TransferDropDownProp
}
}

const customStyleOptions = {
classNames: [
{
key: 'selectControlClassName',
name: 'controlClassName',
weights: {
focused: {
suf: '.is-opened:not(.is-mobile)'
},
disabled: {
suf: '.is-disabled'
}
}
},
{
key: 'selectPopoverClassName',
name: 'popoverClassName',
weights: {
default: {
suf: (ns: string) => ` .${ns}Select-option`
},
hover: {
suf: (ns: string) => ` .${ns}Select-option.is-highlight`
},
focused: {
inner: (ns: string) => `.${ns}Select-option.is-active`
}
}
}
]
};

@OptionsControl({
type: 'select'
})
@CustomStyleWrapper(customStyleOptions)
export class SelectControlRenderer extends SelectControl {}

@OptionsControl({
type: 'multi-select'
})
@CustomStyleWrapper(customStyleOptions)
export class MultiSelectControlRenderer extends SelectControl {
static defaultProps = {
multiple: true
Expand Down

0 comments on commit 1b0a36d

Please sign in to comment.