mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[improvement] Functional components be just functions (#2735)
This commit is contained in:
parent
166397dad4
commit
5a9143c736
@ -4,75 +4,72 @@ import Loading from '../loading';
|
||||
|
||||
const [sfc, bem] = use('button');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function Button(h, props, slots, ctx) {
|
||||
const { type, disabled, loading, loadingText } = props;
|
||||
|
||||
props: {
|
||||
text: String,
|
||||
block: Boolean,
|
||||
plain: Boolean,
|
||||
round: Boolean,
|
||||
square: Boolean,
|
||||
loading: Boolean,
|
||||
disabled: Boolean,
|
||||
nativeType: String,
|
||||
loadingText: String,
|
||||
bottomAction: Boolean,
|
||||
tag: {
|
||||
type: String,
|
||||
default: 'button'
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'normal'
|
||||
const onClick = event => {
|
||||
if (!loading && !disabled) {
|
||||
emit(ctx, 'click', event);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<props.tag
|
||||
type={props.nativeType}
|
||||
disabled={disabled}
|
||||
class={bem([
|
||||
type,
|
||||
props.size,
|
||||
{
|
||||
loading,
|
||||
disabled,
|
||||
block: props.block,
|
||||
plain: props.plain,
|
||||
round: props.round,
|
||||
square: props.square,
|
||||
'bottom-action': props.bottomAction
|
||||
}
|
||||
])}
|
||||
onClick={onClick}
|
||||
{...inherit(ctx)}
|
||||
>
|
||||
{loading ? (
|
||||
[
|
||||
<Loading size="20px" color={type === 'default' ? undefined : ''} />,
|
||||
loadingText && <span class={bem('loading-text')}>{loadingText}</span>
|
||||
]
|
||||
) : (
|
||||
<span class={bem('text')}>
|
||||
{slots.default ? slots.default() : props.text}
|
||||
</span>
|
||||
)}
|
||||
</props.tag>
|
||||
);
|
||||
}
|
||||
|
||||
Button.props = {
|
||||
text: String,
|
||||
block: Boolean,
|
||||
plain: Boolean,
|
||||
round: Boolean,
|
||||
square: Boolean,
|
||||
loading: Boolean,
|
||||
disabled: Boolean,
|
||||
nativeType: String,
|
||||
loadingText: String,
|
||||
bottomAction: Boolean,
|
||||
tag: {
|
||||
type: String,
|
||||
default: 'button'
|
||||
},
|
||||
|
||||
render(h, context) {
|
||||
const { props } = context;
|
||||
const { type, disabled, loading, loadingText } = props;
|
||||
|
||||
const onClick = event => {
|
||||
if (!loading && !disabled) {
|
||||
emit(context, 'click', event);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<props.tag
|
||||
type={props.nativeType}
|
||||
disabled={disabled}
|
||||
class={bem([
|
||||
type,
|
||||
props.size,
|
||||
{
|
||||
loading,
|
||||
disabled,
|
||||
block: props.block,
|
||||
plain: props.plain,
|
||||
round: props.round,
|
||||
square: props.square,
|
||||
'bottom-action': props.bottomAction
|
||||
}
|
||||
])}
|
||||
onClick={onClick}
|
||||
{...inherit(context)}
|
||||
>
|
||||
{loading ? (
|
||||
[
|
||||
<Loading size="20px" color={type === 'default' ? undefined : ''} />,
|
||||
loadingText && (
|
||||
<span class={bem('loading-text')}>{loadingText}</span>
|
||||
)
|
||||
]
|
||||
) : (
|
||||
<span class={bem('text')}>{context.children || props.text}</span>
|
||||
)}
|
||||
</props.tag>
|
||||
);
|
||||
type: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'normal'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default sfc(Button);
|
||||
|
@ -2,21 +2,22 @@ import { use } from '../utils';
|
||||
|
||||
const [sfc, bem] = use('cell-group');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function CellGroup(h, props, slots, ctx) {
|
||||
return (
|
||||
<div
|
||||
class={[bem(), { 'van-hairline--top-bottom': props.border }]}
|
||||
{...ctx.data}
|
||||
>
|
||||
{slots.default && slots.default()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
props: {
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
|
||||
render(h, context) {
|
||||
return (
|
||||
<div class={[bem(), { 'van-hairline--top-bottom': context.props.border }]} {...context.data}>
|
||||
{context.children}
|
||||
</div>
|
||||
);
|
||||
CellGroup.props = {
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default sfc(CellGroup);
|
||||
|
@ -1,84 +1,80 @@
|
||||
import { use, isDef } from '../utils';
|
||||
import { cellProps } from './shared';
|
||||
import { emit, inherit, unifySlots } from '../utils/functional';
|
||||
import { emit, inherit } from '../utils/functional';
|
||||
import { routeProps, functionalRoute } from '../mixins/router';
|
||||
import Icon from '../icon';
|
||||
|
||||
const [sfc, bem] = use('cell');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function Cell(h, props, slots, ctx) {
|
||||
const { icon, size, title, label, value, isLink, arrowDirection } = props;
|
||||
|
||||
props: {
|
||||
...cellProps,
|
||||
...routeProps,
|
||||
size: String,
|
||||
clickable: Boolean,
|
||||
arrowDirection: String
|
||||
},
|
||||
const showTitle = slots.title || isDef(title);
|
||||
const showValue = slots.default || isDef(value);
|
||||
|
||||
render(h, context) {
|
||||
const slots = unifySlots(context);
|
||||
const { props } = context;
|
||||
const { icon, size, title, label, value, isLink, arrowDirection } = props;
|
||||
const Title = showTitle && (
|
||||
<div class={[bem('title'), props.titleClass]}>
|
||||
{slots.title ? slots.title() : <span>{title}</span>}
|
||||
{label && <div class={[bem('label'), props.labelClass]}>{label}</div>}
|
||||
</div>
|
||||
);
|
||||
|
||||
const showTitle = slots.title || isDef(title);
|
||||
const showValue = slots.default || isDef(value);
|
||||
const Value = showValue && (
|
||||
<div
|
||||
class={[
|
||||
bem('value', { alone: !slots.title && !title }),
|
||||
props.valueClass
|
||||
]}
|
||||
>
|
||||
{slots.default ? slots.default() : <span>{value}</span>}
|
||||
</div>
|
||||
);
|
||||
|
||||
const Title = showTitle && (
|
||||
<div class={[bem('title'), props.titleClass]}>
|
||||
{slots.title ? slots.title() : <span>{title}</span>}
|
||||
{label && <div class={[bem('label'), props.labelClass]}>{label}</div>}
|
||||
</div>
|
||||
const LeftIcon = slots.icon
|
||||
? slots.icon()
|
||||
: icon && <Icon class={bem('left-icon')} name={icon} />;
|
||||
|
||||
const RightIcon = slots['right-icon']
|
||||
? slots['right-icon']()
|
||||
: isLink && (
|
||||
<Icon
|
||||
class={bem('right-icon')}
|
||||
name={arrowDirection ? `arrow-${arrowDirection}` : 'arrow'}
|
||||
/>
|
||||
);
|
||||
|
||||
const Value = showValue && (
|
||||
<div
|
||||
class={[
|
||||
bem('value', { alone: !slots.title && !title }),
|
||||
props.valueClass
|
||||
]}
|
||||
>
|
||||
{slots.default ? slots.default() : <span>{value}</span>}
|
||||
</div>
|
||||
);
|
||||
const onClick = event => {
|
||||
emit(ctx, 'click', event);
|
||||
functionalRoute(ctx);
|
||||
};
|
||||
|
||||
const LeftIcon = slots.icon
|
||||
? slots.icon()
|
||||
: icon && <Icon class={bem('left-icon')} name={icon} />;
|
||||
return (
|
||||
<div
|
||||
class={bem({
|
||||
center: props.center,
|
||||
required: props.required,
|
||||
borderless: !props.border,
|
||||
clickable: isLink || props.clickable,
|
||||
[size]: size
|
||||
})}
|
||||
onClick={onClick}
|
||||
{...inherit(ctx)}
|
||||
>
|
||||
{LeftIcon}
|
||||
{Title}
|
||||
{Value}
|
||||
{RightIcon}
|
||||
{slots.extra && slots.extra()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const RightIcon = slots['right-icon']
|
||||
? slots['right-icon']()
|
||||
: isLink && (
|
||||
<Icon
|
||||
class={bem('right-icon')}
|
||||
name={arrowDirection ? `arrow-${arrowDirection}` : 'arrow'}
|
||||
/>
|
||||
);
|
||||
Cell.props = {
|
||||
...cellProps,
|
||||
...routeProps,
|
||||
size: String,
|
||||
clickable: Boolean,
|
||||
arrowDirection: String
|
||||
};
|
||||
|
||||
const onClick = event => {
|
||||
emit(context, 'click', event);
|
||||
functionalRoute(context);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
class={bem({
|
||||
center: props.center,
|
||||
required: props.required,
|
||||
borderless: !props.border,
|
||||
clickable: isLink || props.clickable,
|
||||
[size]: size
|
||||
})}
|
||||
onClick={onClick}
|
||||
{...inherit(context)}
|
||||
>
|
||||
{LeftIcon}
|
||||
{Title}
|
||||
{Value}
|
||||
{RightIcon}
|
||||
{slots.extra && slots.extra()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
export default sfc(Cell);
|
||||
|
@ -4,46 +4,46 @@ import Cell from '../cell';
|
||||
|
||||
const [sfc, bem, t] = use('contact-card');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function ContactCard(h, props, slots, ctx) {
|
||||
const { type, editable } = props;
|
||||
|
||||
props: {
|
||||
tel: String,
|
||||
name: String,
|
||||
addText: String,
|
||||
editable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'add'
|
||||
}
|
||||
return (
|
||||
<Cell
|
||||
center
|
||||
border={false}
|
||||
isLink={editable}
|
||||
class={bem([type])}
|
||||
valueClass={bem('value')}
|
||||
icon={type === 'edit' ? 'contact' : 'add-square'}
|
||||
onClick={event => {
|
||||
if (editable) {
|
||||
emit(ctx, 'click', event);
|
||||
}
|
||||
}}
|
||||
{...inherit(ctx)}
|
||||
>
|
||||
{type === 'add'
|
||||
? props.addText || t('addText')
|
||||
: [
|
||||
<div>{`${t('name')}:${props.name}`}</div>,
|
||||
<div>{`${t('tel')}:${props.tel}`}</div>
|
||||
]}
|
||||
</Cell>
|
||||
);
|
||||
}
|
||||
|
||||
ContactCard.props = {
|
||||
tel: String,
|
||||
name: String,
|
||||
addText: String,
|
||||
editable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
|
||||
render(h, context) {
|
||||
const { props } = context;
|
||||
const { type, editable } = props;
|
||||
|
||||
return (
|
||||
<Cell
|
||||
center
|
||||
border={false}
|
||||
isLink={editable}
|
||||
class={bem([type])}
|
||||
valueClass={bem('value')}
|
||||
icon={type === 'edit' ? 'contact' : 'add-square'}
|
||||
onClick={event => {
|
||||
if (editable) {
|
||||
emit(context, 'click', event);
|
||||
}
|
||||
}}
|
||||
{...inherit(context)}
|
||||
>
|
||||
{type === 'add'
|
||||
? props.addText || t('addText')
|
||||
: [<div>{`${t('name')}:${props.name}`}</div>, <div>{`${t('tel')}:${props.tel}`}</div>]}
|
||||
</Cell>
|
||||
);
|
||||
type: {
|
||||
type: String,
|
||||
default: 'add'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default sfc(ContactCard);
|
||||
|
@ -8,62 +8,58 @@ import RadioGroup from '../radio-group';
|
||||
|
||||
const [sfc, bem, t] = use('contact-list');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function ContactList(h, props, slots, ctx) {
|
||||
const List = props.list.map((item, index) => (
|
||||
<Cell
|
||||
key={item.id}
|
||||
isLink
|
||||
class={bem('item')}
|
||||
valueClass={bem('item-value')}
|
||||
scopedSlots={{
|
||||
default: () => (
|
||||
<Radio name={item.id}>
|
||||
<div class={bem('name')}>{`${item.name},${item.tel}`}</div>
|
||||
</Radio>
|
||||
),
|
||||
'right-icon': () => (
|
||||
<Icon
|
||||
name="edit"
|
||||
class={bem('edit')}
|
||||
onClick={event => {
|
||||
event.stopPropagation();
|
||||
emit(ctx, 'edit', item, index);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
onClick={() => {
|
||||
emit(ctx, 'input', item.id);
|
||||
emit(ctx, 'select', item, index);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
|
||||
props: {
|
||||
value: null,
|
||||
list: Array,
|
||||
addText: String
|
||||
},
|
||||
|
||||
render(h, context) {
|
||||
const { props, listeners } = context;
|
||||
|
||||
const List = props.list.map((item, index) => (
|
||||
<Cell
|
||||
key={item.id}
|
||||
isLink
|
||||
class={bem('item')}
|
||||
valueClass={bem('item-value')}
|
||||
scopedSlots={{
|
||||
default: () => (
|
||||
<Radio name={item.id}>
|
||||
<div class={bem('name')}>{`${item.name},${item.tel}`}</div>
|
||||
</Radio>
|
||||
),
|
||||
'right-icon': () => (
|
||||
<Icon
|
||||
name="edit"
|
||||
class={bem('edit')}
|
||||
onClick={event => {
|
||||
event.stopPropagation();
|
||||
emit(context, 'edit', item, index);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
onClick={() => {
|
||||
emit(context, 'input', item.id);
|
||||
emit(context, 'select', item, index);
|
||||
}}
|
||||
return (
|
||||
<div class={bem()} {...inherit(ctx)}>
|
||||
<RadioGroup value={props.value} class={bem('group')}>
|
||||
{List}
|
||||
</RadioGroup>
|
||||
<Button
|
||||
square
|
||||
size="large"
|
||||
type="danger"
|
||||
class={bem('add')}
|
||||
text={props.addText || t('addText')}
|
||||
onClick={ctx.listeners.add || noop}
|
||||
/>
|
||||
));
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div class={bem()} {...inherit(context)}>
|
||||
<RadioGroup value={props.value} class={bem('group')}>
|
||||
{List}
|
||||
</RadioGroup>
|
||||
<Button
|
||||
square
|
||||
size="large"
|
||||
type="danger"
|
||||
class={bem('add')}
|
||||
text={props.addText || t('addText')}
|
||||
onClick={listeners.add || noop}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
ContactList.props = {
|
||||
value: null,
|
||||
list: Array,
|
||||
addText: String
|
||||
};
|
||||
|
||||
export default sfc(ContactList);
|
||||
|
@ -1,43 +1,38 @@
|
||||
import { use } from '../utils';
|
||||
import Button from '../button';
|
||||
import { emit, inherit, unifySlots } from '../utils/functional';
|
||||
import { emit, inherit } from '../utils/functional';
|
||||
import { functionalRoute, routeProps } from '../mixins/router';
|
||||
|
||||
const [sfc, bem] = use('goods-action-big-btn');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function GoodsActionBigBtn(h, props, slots, ctx) {
|
||||
const onClick = event => {
|
||||
emit(ctx, 'click', event);
|
||||
functionalRoute(ctx);
|
||||
};
|
||||
|
||||
props: {
|
||||
...routeProps,
|
||||
text: String,
|
||||
primary: Boolean,
|
||||
loading: Boolean,
|
||||
disabled: Boolean
|
||||
},
|
||||
return (
|
||||
<Button
|
||||
square
|
||||
class={bem()}
|
||||
size="large"
|
||||
loading={props.loading}
|
||||
disabled={props.disabled}
|
||||
type={props.primary ? 'danger' : 'warning'}
|
||||
onClick={onClick}
|
||||
{...inherit(ctx)}
|
||||
>
|
||||
{slots.default ? slots.default() : props.text}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
render(h, context) {
|
||||
const { props } = context;
|
||||
const slots = unifySlots(context);
|
||||
GoodsActionBigBtn.props = {
|
||||
...routeProps,
|
||||
text: String,
|
||||
primary: Boolean,
|
||||
loading: Boolean,
|
||||
disabled: Boolean
|
||||
};
|
||||
|
||||
const onClick = event => {
|
||||
emit(context, 'click', event);
|
||||
functionalRoute(context);
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
square
|
||||
class={bem()}
|
||||
size="large"
|
||||
loading={props.loading}
|
||||
disabled={props.disabled}
|
||||
type={props.primary ? 'danger' : 'warning'}
|
||||
onClick={onClick}
|
||||
{...inherit(context)}
|
||||
>
|
||||
{slots.default ? slots.default() : props.text}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
});
|
||||
export default sfc(GoodsActionBigBtn);
|
||||
|
@ -1,43 +1,38 @@
|
||||
import { use } from '../utils';
|
||||
import Icon from '../icon';
|
||||
import { emit, inherit, unifySlots } from '../utils/functional';
|
||||
import { emit, inherit } from '../utils/functional';
|
||||
import { functionalRoute, routeProps } from '../mixins/router';
|
||||
|
||||
const [sfc, bem] = use('goods-action-mini-btn');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function GoodsActionMiniBtn(h, props, slots, ctx) {
|
||||
const onClick = event => {
|
||||
emit(ctx, 'click', event);
|
||||
functionalRoute(ctx);
|
||||
};
|
||||
|
||||
props: {
|
||||
...routeProps,
|
||||
text: String,
|
||||
icon: String,
|
||||
info: [String, Number],
|
||||
iconClass: String
|
||||
},
|
||||
return (
|
||||
<div
|
||||
class={[bem(), 'van-hairline']}
|
||||
onClick={onClick}
|
||||
{...inherit(ctx)}
|
||||
>
|
||||
<Icon
|
||||
class={[bem('icon'), props.iconClass]}
|
||||
info={props.info}
|
||||
name={props.icon}
|
||||
/>
|
||||
{slots.default ? slots.default() : props.text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render(h, context) {
|
||||
const { props } = context;
|
||||
const slots = unifySlots(context);
|
||||
GoodsActionMiniBtn.props = {
|
||||
...routeProps,
|
||||
text: String,
|
||||
icon: String,
|
||||
info: [String, Number],
|
||||
iconClass: String
|
||||
};
|
||||
|
||||
const onClick = event => {
|
||||
emit(context, 'click', event);
|
||||
functionalRoute(context);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
class={[bem(), 'van-hairline']}
|
||||
onClick={onClick}
|
||||
{...inherit(context)}
|
||||
>
|
||||
<Icon
|
||||
class={[bem('icon'), props.iconClass]}
|
||||
info={props.info}
|
||||
name={props.icon}
|
||||
/>
|
||||
{slots.default ? slots.default() : props.text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
export default sfc(GoodsActionMiniBtn);
|
||||
|
@ -2,14 +2,12 @@ import { use } from '../utils';
|
||||
|
||||
const [sfc, bem] = use('goods-action');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function GoodsAction(h, props, slots, ctx) {
|
||||
return (
|
||||
<div class={bem()} {...ctx.data}>
|
||||
{slots.default && slots.default()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render(h, context) {
|
||||
return (
|
||||
<div class={bem()} {...context.data}>
|
||||
{context.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
export default sfc(GoodsAction);
|
||||
|
@ -4,40 +4,37 @@ import isSrc from '../utils/validate/src';
|
||||
|
||||
const [sfc] = use('icon');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function Icon(h, props, slots, ctx) {
|
||||
const urlIcon = isSrc(props.name);
|
||||
|
||||
props: {
|
||||
name: String,
|
||||
size: String,
|
||||
color: String,
|
||||
info: [String, Number],
|
||||
classPrefix: {
|
||||
type: String,
|
||||
default: 'van-icon'
|
||||
}
|
||||
},
|
||||
return (
|
||||
<i
|
||||
class={[
|
||||
props.classPrefix,
|
||||
urlIcon ? 'van-icon--image' : `${props.classPrefix}-${props.name}`
|
||||
]}
|
||||
style={{
|
||||
color: props.color,
|
||||
fontSize: props.size
|
||||
}}
|
||||
{...ctx.data}
|
||||
>
|
||||
{ctx.default && ctx.default()}
|
||||
{urlIcon && <img src={props.name} />}
|
||||
<Info info={props.info} />
|
||||
</i>
|
||||
);
|
||||
}
|
||||
|
||||
render(h, context) {
|
||||
const { props } = context;
|
||||
const urlIcon = isSrc(props.name);
|
||||
|
||||
return (
|
||||
<i
|
||||
class={[
|
||||
props.classPrefix,
|
||||
urlIcon ? 'van-icon--image' : `${props.classPrefix}-${props.name}`
|
||||
]}
|
||||
style={{
|
||||
color: props.color,
|
||||
fontSize: props.size
|
||||
}}
|
||||
{...context.data}
|
||||
>
|
||||
{context.children}
|
||||
{urlIcon && <img src={props.name} />}
|
||||
<Info info={props.info} />
|
||||
</i>
|
||||
);
|
||||
Icon.props = {
|
||||
name: String,
|
||||
size: String,
|
||||
color: String,
|
||||
info: [String, Number],
|
||||
classPrefix: {
|
||||
type: String,
|
||||
default: 'van-icon'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default sfc(Icon);
|
||||
|
@ -2,20 +2,18 @@ import { use, isDef } from '../utils';
|
||||
|
||||
const [sfc, bem] = use('info');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function Info(h, props, slots, ctx) {
|
||||
return (
|
||||
isDef(props.info) && (
|
||||
<div class={bem()} {...ctx.data}>
|
||||
{props.info}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
props: {
|
||||
info: [String, Number]
|
||||
},
|
||||
Info.props = {
|
||||
info: [String, Number]
|
||||
};
|
||||
|
||||
render(h, { props, data }) {
|
||||
return (
|
||||
isDef(props.info) && (
|
||||
<div class={bem()} {...data}>
|
||||
{props.info}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
export default sfc(Info);
|
||||
|
@ -3,52 +3,50 @@ import { use } from '../utils';
|
||||
const [sfc, bem] = use('loading');
|
||||
const DEFAULT_COLOR = '#c9c9c9';
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function Loading(h, props, slots, ctx) {
|
||||
const { color, size, type } = props;
|
||||
|
||||
props: {
|
||||
size: String,
|
||||
type: {
|
||||
type: String,
|
||||
default: 'circular'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: DEFAULT_COLOR
|
||||
const colorType = color === 'white' || color === 'black' ? color : '';
|
||||
|
||||
const style = {
|
||||
color: color === 'black' ? DEFAULT_COLOR : color,
|
||||
width: size,
|
||||
height: size
|
||||
};
|
||||
|
||||
const Spin = [];
|
||||
if (type === 'spinner') {
|
||||
for (let i = 0; i < 12; i++) {
|
||||
Spin.push(<i />);
|
||||
}
|
||||
},
|
||||
|
||||
render(h, context) {
|
||||
const { color, size, type } = context.props;
|
||||
|
||||
const colorType = color === 'white' || color === 'black' ? color : '';
|
||||
|
||||
const style = {
|
||||
color: color === 'black' ? DEFAULT_COLOR : color,
|
||||
width: size,
|
||||
height: size
|
||||
};
|
||||
|
||||
const Spin = [];
|
||||
if (type === 'spinner') {
|
||||
for (let i = 0; i < 12; i++) {
|
||||
Spin.push(<i />);
|
||||
}
|
||||
}
|
||||
|
||||
const Circular = type === 'circular' && (
|
||||
<svg class={bem('circular')} viewBox="25 25 50 50">
|
||||
<circle cx="50" cy="50" r="20" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
return (
|
||||
<div class={bem([type, colorType])} style={style} {...context.data}>
|
||||
<span class={bem('spinner', type)}>
|
||||
{Spin}
|
||||
{Circular}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const Circular = type === 'circular' && (
|
||||
<svg class={bem('circular')} viewBox="25 25 50 50">
|
||||
<circle cx="50" cy="50" r="20" fill="none" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
return (
|
||||
<div class={bem([type, colorType])} style={style} {...ctx.data}>
|
||||
<span class={bem('spinner', type)}>
|
||||
{Spin}
|
||||
{Circular}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading.props = {
|
||||
size: String,
|
||||
type: {
|
||||
type: String,
|
||||
default: 'circular'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: DEFAULT_COLOR
|
||||
}
|
||||
};
|
||||
|
||||
export default sfc(Loading);
|
||||
|
@ -4,46 +4,56 @@ import Icon from '../icon';
|
||||
|
||||
const [sfc, bem] = use('nav-bar');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
|
||||
props: {
|
||||
title: String,
|
||||
fixed: Boolean,
|
||||
leftText: String,
|
||||
rightText: String,
|
||||
leftArrow: Boolean,
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
|
||||
render(h, context) {
|
||||
const { props, listeners } = context;
|
||||
const slots = context.slots();
|
||||
|
||||
return (
|
||||
<div
|
||||
class={[bem({ fixed: props.fixed }), { 'van-hairline--bottom': props.border }]}
|
||||
style={{ zIndex: props.zIndex }}
|
||||
{...inherit(context)}
|
||||
>
|
||||
<div class={bem('left')} onClick={listeners['click-left'] || noop}>
|
||||
{slots.left || [
|
||||
props.leftArrow && <Icon class={bem('arrow')} name="arrow-left" />,
|
||||
props.leftText && <span class={bem('text')}>{props.leftText}</span>
|
||||
function NavBar(h, props, slots, ctx) {
|
||||
return (
|
||||
<div
|
||||
class={[
|
||||
bem({ fixed: props.fixed }),
|
||||
{ 'van-hairline--bottom': props.border }
|
||||
]}
|
||||
style={{ zIndex: props.zIndex }}
|
||||
{...inherit(ctx)}
|
||||
>
|
||||
<div class={bem('left')} onClick={ctx.listeners['click-left'] || noop}>
|
||||
{slots.left
|
||||
? slots.left()
|
||||
: [
|
||||
props.leftArrow && (
|
||||
<Icon class={bem('arrow')} name="arrow-left" />
|
||||
),
|
||||
props.leftText && (
|
||||
<span class={bem('text')}>{props.leftText}</span>
|
||||
)
|
||||
]}
|
||||
</div>
|
||||
<div class={[bem('title'), 'van-ellipsis']}>{slots.title || props.title}</div>
|
||||
<div class={bem('right')} onClick={listeners['click-right'] || noop}>
|
||||
{slots.right || (props.rightText && <span class={bem('text')}>{props.rightText}</span>)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
<div class={[bem('title'), 'van-ellipsis']}>
|
||||
{slots.title ? slots.title() : props.title}
|
||||
</div>
|
||||
<div class={bem('right')} onClick={ctx.listeners['click-right'] || noop}>
|
||||
{slots.right
|
||||
? slots.right()
|
||||
: props.rightText && (
|
||||
<span class={bem('text')}>{props.rightText}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
NavBar.props = {
|
||||
title: String,
|
||||
fixed: Boolean,
|
||||
leftText: String,
|
||||
rightText: String,
|
||||
leftArrow: Boolean,
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default sfc(NavBar);
|
||||
|
@ -4,35 +4,34 @@ import CellGroup from '../cell-group';
|
||||
|
||||
const [sfc, bem] = use('panel');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function Panel(h, props, slots, ctx) {
|
||||
return (
|
||||
<CellGroup class={bem()} {...ctx.data}>
|
||||
{slots.header ? (
|
||||
slots.header()
|
||||
) : (
|
||||
<Cell
|
||||
icon={props.icon}
|
||||
label={props.desc}
|
||||
title={props.title}
|
||||
value={props.status}
|
||||
class={bem('header')}
|
||||
valueClass={bem('header-value')}
|
||||
/>
|
||||
)}
|
||||
<div class={bem('content')}>{slots.default && slots.default()}</div>
|
||||
{slots.footer && (
|
||||
<div class={[bem('footer'), 'van-hairline--top']}>{slots.footer()}</div>
|
||||
)}
|
||||
</CellGroup>
|
||||
);
|
||||
}
|
||||
|
||||
props: {
|
||||
icon: String,
|
||||
desc: String,
|
||||
title: String,
|
||||
status: String
|
||||
},
|
||||
Panel.props = {
|
||||
icon: String,
|
||||
desc: String,
|
||||
title: String,
|
||||
status: String
|
||||
};
|
||||
|
||||
render(h, context) {
|
||||
const { props } = context;
|
||||
const slots = context.slots();
|
||||
|
||||
return (
|
||||
<CellGroup class={bem()} {...context.data}>
|
||||
{slots.header || (
|
||||
<Cell
|
||||
icon={props.icon}
|
||||
label={props.desc}
|
||||
title={props.title}
|
||||
value={props.status}
|
||||
class={bem('header')}
|
||||
valueClass={bem('header-value')}
|
||||
/>
|
||||
)}
|
||||
<div class={bem('content')}>{slots.default}</div>
|
||||
{slots.footer && <div class={[bem('footer'), 'van-hairline--top']}>{slots.footer}</div>}
|
||||
</CellGroup>
|
||||
);
|
||||
}
|
||||
});
|
||||
export default sfc(Panel);
|
||||
|
@ -3,49 +3,48 @@ import { emit } from '../utils/functional';
|
||||
|
||||
const [sfc, bem] = use('password-input');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function PasswordInput(h, props, slots, ctx) {
|
||||
const info = props.errorInfo || props.info;
|
||||
|
||||
props: {
|
||||
info: String,
|
||||
errorInfo: String,
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
length: {
|
||||
type: Number,
|
||||
default: 6
|
||||
}
|
||||
},
|
||||
|
||||
render(h, context) {
|
||||
const { props } = context;
|
||||
const info = props.errorInfo || props.info;
|
||||
|
||||
const Points = [];
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
Points.push(
|
||||
<li class="van-hairline">
|
||||
<i style={{ visibility: props.value[i] ? 'visible' : 'hidden' }} />
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div class={bem()}>
|
||||
<ul
|
||||
class={[bem('security'), 'van-hairline--surround']}
|
||||
onTouchstart={event => {
|
||||
event.stopPropagation();
|
||||
emit(context, 'focus', event);
|
||||
}}
|
||||
{...context.data}
|
||||
>
|
||||
{Points}
|
||||
</ul>
|
||||
{info && <div class={bem(props.errorInfo ? 'error-info' : 'info')}>{info}</div>}
|
||||
</div>
|
||||
const Points = [];
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
Points.push(
|
||||
<li class="van-hairline">
|
||||
<i style={{ visibility: props.value[i] ? 'visible' : 'hidden' }} />
|
||||
</li>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div class={bem()}>
|
||||
<ul
|
||||
class={[bem('security'), 'van-hairline--surround']}
|
||||
onTouchstart={event => {
|
||||
event.stopPropagation();
|
||||
emit(ctx, 'focus', event);
|
||||
}}
|
||||
{...ctx.data}
|
||||
>
|
||||
{Points}
|
||||
</ul>
|
||||
{info && (
|
||||
<div class={bem(props.errorInfo ? 'error-info' : 'info')}>{info}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
PasswordInput.props = {
|
||||
info: String,
|
||||
errorInfo: String,
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
length: {
|
||||
type: Number,
|
||||
default: 6
|
||||
}
|
||||
};
|
||||
|
||||
export default sfc(PasswordInput);
|
||||
|
@ -4,63 +4,61 @@ import Button from '../button';
|
||||
|
||||
const [sfc, bem, t] = use('submit-bar');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function SubmitBar(h, props, slots, ctx) {
|
||||
const { tip, price } = props;
|
||||
const hasPrice = typeof price === 'number';
|
||||
|
||||
props: {
|
||||
tip: String,
|
||||
label: String,
|
||||
loading: Boolean,
|
||||
disabled: Boolean,
|
||||
buttonText: String,
|
||||
price: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
currency: {
|
||||
type: String,
|
||||
default: '¥'
|
||||
},
|
||||
buttonType: {
|
||||
type: String,
|
||||
default: 'danger'
|
||||
}
|
||||
},
|
||||
|
||||
render(h, context) {
|
||||
const { props, listeners } = context;
|
||||
const { tip, price } = props;
|
||||
const slots = context.slots();
|
||||
const hasPrice = typeof price === 'number';
|
||||
|
||||
return (
|
||||
<div class={bem()} {...inherit(context)}>
|
||||
{slots.top}
|
||||
{(slots.tip || tip) && (
|
||||
<div class={bem('tip')}>
|
||||
{tip}
|
||||
{slots.tip}
|
||||
</div>
|
||||
)}
|
||||
<div class={bem('bar')}>
|
||||
{slots.default}
|
||||
<div class={bem('text')}>
|
||||
{hasPrice && [
|
||||
<span>{props.label || t('label')}</span>,
|
||||
<span class={bem('price')}>{`${props.currency} ${(price / 100).toFixed(2)}`}</span>
|
||||
]}
|
||||
</div>
|
||||
<Button
|
||||
square
|
||||
size="large"
|
||||
type={props.buttonType}
|
||||
loading={props.loading}
|
||||
disabled={props.disabled}
|
||||
text={props.loading ? '' : props.buttonText}
|
||||
onClick={listeners.submit || noop}
|
||||
/>
|
||||
return (
|
||||
<div class={bem()} {...inherit(ctx)}>
|
||||
{slots.top && slots.top()}
|
||||
{(slots.tip || tip) && (
|
||||
<div class={bem('tip')}>
|
||||
{tip}
|
||||
{slots.tip && slots.tip()}
|
||||
</div>
|
||||
)}
|
||||
<div class={bem('bar')}>
|
||||
{slots.default && slots.default()}
|
||||
<div class={bem('text')}>
|
||||
{hasPrice && [
|
||||
<span>{props.label || t('label')}</span>,
|
||||
<span class={bem('price')}>{`${props.currency} ${(
|
||||
price / 100
|
||||
).toFixed(2)}`}</span>
|
||||
]}
|
||||
</div>
|
||||
<Button
|
||||
square
|
||||
size="large"
|
||||
type={props.buttonType}
|
||||
loading={props.loading}
|
||||
disabled={props.disabled}
|
||||
text={props.loading ? '' : props.buttonText}
|
||||
onClick={ctx.listeners.submit || noop}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
SubmitBar.props = {
|
||||
tip: String,
|
||||
label: String,
|
||||
loading: Boolean,
|
||||
disabled: Boolean,
|
||||
buttonText: String,
|
||||
price: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
currency: {
|
||||
type: String,
|
||||
default: '¥'
|
||||
},
|
||||
buttonType: {
|
||||
type: String,
|
||||
default: 'danger'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default sfc(SubmitBar);
|
||||
|
@ -2,31 +2,32 @@ import { use } from '../utils';
|
||||
import { inherit } from '../utils/functional';
|
||||
import Cell from '../cell';
|
||||
import Switch from '../switch';
|
||||
import SwitchMixin from '../mixins/switch';
|
||||
import { switchProps } from '../switch/shared';
|
||||
|
||||
const [sfc, bem] = use('switch-cell');
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function SwitchCell(h, props, slots, ctx) {
|
||||
return (
|
||||
<Cell
|
||||
center
|
||||
title={props.title}
|
||||
border={props.border}
|
||||
class={bem()}
|
||||
{...inherit(ctx)}
|
||||
>
|
||||
<Switch {...{ props, on: ctx.listeners }} />
|
||||
</Cell>
|
||||
);
|
||||
}
|
||||
|
||||
mixins: [SwitchMixin],
|
||||
|
||||
props: {
|
||||
title: String,
|
||||
border: Boolean,
|
||||
size: {
|
||||
type: String,
|
||||
default: '24px'
|
||||
}
|
||||
},
|
||||
|
||||
render(h, context) {
|
||||
const { props } = context;
|
||||
|
||||
return (
|
||||
<Cell center title={props.title} border={props.border} class={bem()} {...inherit(context)}>
|
||||
<Switch {...{ props, on: context.listeners }} />
|
||||
</Cell>
|
||||
);
|
||||
SwitchCell.props = {
|
||||
...switchProps,
|
||||
title: String,
|
||||
border: Boolean,
|
||||
size: {
|
||||
type: String,
|
||||
default: '24px'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default sfc(SwitchCell);
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { use } from '../utils';
|
||||
import Loading from '../loading';
|
||||
import SwitchMixin from '../mixins/switch';
|
||||
import { switchProps } from './shared';
|
||||
|
||||
const [sfc, bem] = use('switch');
|
||||
|
||||
export default sfc({
|
||||
mixins: [SwitchMixin],
|
||||
props: switchProps,
|
||||
|
||||
methods: {
|
||||
onClick() {
|
||||
|
23
packages/switch/shared.ts
Normal file
23
packages/switch/shared.ts
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Common Switch Props
|
||||
*/
|
||||
|
||||
export const switchProps = {
|
||||
value: null,
|
||||
loading: Boolean,
|
||||
disabled: Boolean,
|
||||
activeColor: String,
|
||||
inactiveColor: String,
|
||||
activeValue: {
|
||||
type: null,
|
||||
default: true
|
||||
},
|
||||
inactiveValue: {
|
||||
type: null,
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: '30px'
|
||||
}
|
||||
};
|
@ -9,44 +9,41 @@ const COLOR_MAP = {
|
||||
success: GREEN
|
||||
};
|
||||
|
||||
export default sfc({
|
||||
functional: true,
|
||||
function Tag(h, props, slots, ctx) {
|
||||
const { mark, plain, round, size } = ctx.props;
|
||||
|
||||
props: {
|
||||
size: String,
|
||||
type: String,
|
||||
mark: Boolean,
|
||||
color: String,
|
||||
plain: Boolean,
|
||||
round: Boolean,
|
||||
textColor: String
|
||||
},
|
||||
const color = props.color || COLOR_MAP[props.type] || GRAY_DARK;
|
||||
const key = plain ? 'color' : 'backgroundColor';
|
||||
const style = { [key]: color };
|
||||
|
||||
render(h, context) {
|
||||
const { props } = context;
|
||||
const { mark, plain, round, size } = context.props;
|
||||
|
||||
const color = props.color || COLOR_MAP[props.type] || GRAY_DARK;
|
||||
const key = plain ? 'color' : 'backgroundColor';
|
||||
const style = { [key]: color };
|
||||
|
||||
if (props.textColor) {
|
||||
style.color = props.textColor;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
style={style}
|
||||
class={[
|
||||
bem({ mark, plain, round, [size]: size }),
|
||||
{
|
||||
'van-hairline--surround': plain
|
||||
}
|
||||
]}
|
||||
{...context.data}
|
||||
>
|
||||
{context.children}
|
||||
</span>
|
||||
);
|
||||
if (props.textColor) {
|
||||
style.color = props.textColor;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<span
|
||||
style={style}
|
||||
class={[
|
||||
bem({ mark, plain, round, [size]: size }),
|
||||
{
|
||||
'van-hairline--surround': plain
|
||||
}
|
||||
]}
|
||||
{...ctx.data}
|
||||
>
|
||||
{slots.default && slots.default()}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
Tag.props = {
|
||||
size: String,
|
||||
type: String,
|
||||
mark: Boolean,
|
||||
color: String,
|
||||
plain: Boolean,
|
||||
round: Boolean,
|
||||
textColor: String
|
||||
};
|
||||
|
||||
export default sfc(Tag);
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { RenderContext, VNodeData } from 'vue/types';
|
||||
import { ScopedSlot } from 'vue/types/vnode';
|
||||
|
||||
type ObjectIndex = {
|
||||
[key: string]: any;
|
||||
@ -47,17 +46,3 @@ export function emit(context: Context, eventName: string, ...args: any[]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unify slots & scopedSlots
|
||||
export function unifySlots(context: Context) {
|
||||
const { scopedSlots } = context;
|
||||
const slots = context.slots();
|
||||
|
||||
Object.keys(slots).forEach(key => {
|
||||
if (!scopedSlots[key]) {
|
||||
scopedSlots[key] = () => slots[key];
|
||||
}
|
||||
});
|
||||
|
||||
return scopedSlots;
|
||||
}
|
||||
|
@ -4,13 +4,29 @@
|
||||
import '../../locale';
|
||||
import { camelize } from '..';
|
||||
import SlotsMixin from '../../mixins/slots';
|
||||
import Vue, { VueConstructor, ComponentOptions } from 'vue';
|
||||
import Vue, {
|
||||
VueConstructor,
|
||||
ComponentOptions,
|
||||
CreateElement,
|
||||
RenderContext
|
||||
} from 'vue/types';
|
||||
import { VNode, ScopedSlot } from 'vue/types/vnode';
|
||||
|
||||
type VantComponentOptions = ComponentOptions<Vue> & {
|
||||
functional?: boolean;
|
||||
install?: (Vue: VueConstructor) => void;
|
||||
};
|
||||
|
||||
type VantPureComponent = {
|
||||
(
|
||||
h: CreateElement,
|
||||
props: { [key: string]: any },
|
||||
slots: { [key: string]: ScopedSlot | undefined },
|
||||
context: RenderContext
|
||||
): VNode;
|
||||
props: any;
|
||||
};
|
||||
|
||||
const arrayProp = {
|
||||
type: Array,
|
||||
default: () => []
|
||||
@ -39,15 +55,46 @@ function install(this: ComponentOptions<Vue>, Vue: VueConstructor) {
|
||||
}
|
||||
}
|
||||
|
||||
export default (name: string) => (sfc: VantComponentOptions) => {
|
||||
sfc.name = name;
|
||||
sfc.install = install;
|
||||
sfc.mixins = sfc.mixins || [];
|
||||
sfc.mixins.push(SlotsMixin);
|
||||
// unify slots & scopedSlots
|
||||
export function unifySlots(context: RenderContext) {
|
||||
const { scopedSlots } = context;
|
||||
const slots = context.slots();
|
||||
|
||||
Object.keys(slots).forEach(key => {
|
||||
if (!scopedSlots[key]) {
|
||||
scopedSlots[key] = () => slots[key];
|
||||
}
|
||||
});
|
||||
|
||||
return scopedSlots;
|
||||
}
|
||||
|
||||
function transformPureComponent(pure: VantPureComponent): VantComponentOptions {
|
||||
return {
|
||||
functional: true,
|
||||
props: pure.props,
|
||||
render: (h, context) => pure(h, context.props, unifySlots(context), context)
|
||||
};
|
||||
}
|
||||
|
||||
export default (name: string) => (
|
||||
sfc: VantComponentOptions | VantPureComponent
|
||||
) => {
|
||||
if (typeof sfc === 'function') {
|
||||
sfc = transformPureComponent(sfc);
|
||||
}
|
||||
|
||||
if (!sfc.functional) {
|
||||
sfc.mixins = sfc.mixins || [];
|
||||
sfc.mixins.push(SlotsMixin);
|
||||
}
|
||||
|
||||
if (sfc.props) {
|
||||
defaultProps(sfc.props);
|
||||
}
|
||||
|
||||
sfc.name = name;
|
||||
sfc.install = install;
|
||||
|
||||
return sfc;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user