Feat v4 theme editor (#6348)

* feat: add theme editor container

* feat: add theme editor layout

* add left panel

* add vue-colorful & fix bug

* 修复hue组件抖动问题

* fix bug && add demo

* fix bug

* fix demo preview

* fix theme editor components demo
This commit is contained in:
果冻橙 2023-03-12 15:15:52 +08:00 committed by GitHub
parent 23a213acda
commit f429148734
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
308 changed files with 13767 additions and 8 deletions

View File

@ -81,7 +81,7 @@ export default defineComponent({
return (
<div
class={`${prefixCls.value}-expand-icon`}
class={[`${prefixCls.value}-expand-icon`, hashId.value]}
onClick={() =>
['header', 'icon'].includes(props.collapsible) && onClickItem(panelProps.panelKey)
}

View File

@ -25,6 +25,9 @@ export const tagProps = () => ({
onClose: {
type: Function as PropType<(e: MouseEvent) => void>,
},
onClick: {
type: Function as PropType<(e: MouseEvent) => void>,
},
'onUpdate:visible': Function as PropType<(vis: boolean) => void>,
icon: PropTypes.any,
});
@ -86,7 +89,7 @@ const Tag = defineComponent({
);
const tagClassName = computed(() =>
classNames(prefixCls.value, hashId.value, {
classNames(prefixCls.value, hashId.value, attrs.class, {
[`${prefixCls.value}-${props.color}`]: isInternalColor.value,
[`${prefixCls.value}-has-color`]: props.color && !isInternalColor.value,
[`${prefixCls.value}-hidden`]: !visible.value,

View File

@ -246,6 +246,7 @@
"stylelint-order": "^5.0.0",
"terser-webpack-plugin": "^5.1.1",
"through2": "^3.0.0",
"tinycolor2": "^1.6.0",
"ts-jest": "^28.0.5",
"ts-loader": "^9.1.0",
"ts-node": "^10.8.2",
@ -254,6 +255,7 @@
"umi-request": "^1.3.5",
"unified": "9.2.2",
"url-loader": "^3.0.0",
"vanilla-jsoneditor": "^0.15.1",
"vite": "^3.0.0",
"vue": "^3.2.0",
"vue-antd-md-loader": "^1.2.1-beta.1",

View File

@ -0,0 +1,344 @@
import type { InputProps } from 'ant-design-vue';
import { Input, InputNumber, Select, theme } from 'ant-design-vue';
import classNames from 'ant-design-vue/es/_util/classNames';
import type { PropType } from 'vue';
import { defineComponent, watchEffect, watch, computed, toRefs, ref } from 'vue';
import { HexColorPicker, RgbaColorPicker } from '../vue-colorful';
import tinycolor from 'tinycolor2';
import makeStyle from './utils/makeStyle';
const { useToken } = theme;
const useStyle = makeStyle('ColorPanel', token => ({
'.color-panel': {
padding: 12,
backgroundColor: '#fff',
borderRadius: 12,
border: '1px solid rgba(0, 0, 0, 0.06)',
boxShadow: token.boxShadow,
width: 224,
boxSizing: 'border-box',
'.color-panel-mode': {
display: 'flex',
alignItems: 'center',
marginBottom: 6,
},
'.color-panel-preview': {
width: 24,
height: 24,
borderRadius: 4,
boxShadow: '0 2px 3px -1px rgba(0,0,0,0.20), inset 0 0 0 1px rgba(0,0,0,0.09)',
flex: 'none',
overflow: 'hidden',
background:
'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAFpJREFUWAntljEKADAIA23p6v//qQ+wfUEcCu1yriEgp0FHRJSJcnehmmWm1Dv/lO4HIg1AAAKjTqm03ea88zMCCEDgO4HV5bS757f+7wRoAAIQ4B9gByAAgQ3pfiDmXmAeEwAAAABJRU5ErkJggg==) 0% 0% / 32px',
},
'.color-panel-preset-colors': {
paddingTop: 12,
display: 'flex',
flexWrap: 'wrap',
width: 200,
},
'.color-panel-preset-color-btn': {
borderRadius: 4,
width: 20,
height: 20,
border: 'none',
outline: 'none',
margin: 4,
cursor: 'pointer',
boxShadow: '0 2px 3px -1px rgba(0,0,0,0.20), inset 0 0 0 1px rgba(0,0,0,0.09)',
},
'.color-panel-mode-title': {
color: token.colorTextPlaceholder,
marginTop: 2,
fontSize: 12,
textAlign: 'center',
},
'.color-panel-rgba-input': {
display: 'flex',
alignItems: 'center',
'&-part': {
flex: 1,
width: 0,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
'&-title': {
color: token.colorTextPlaceholder,
marginTop: 2,
fontSize: 12,
},
'&:not(:last-child)': {
marginRight: 4,
},
[`${token.rootCls}-input-number`]: {
width: '100%',
input: {
fontSize: 12,
padding: '0 4px',
},
},
},
},
},
}));
export type HexColorInputProps = {
value: string;
onChange?: (value: string) => void;
alpha?: boolean;
};
const getHexValue = (value: string, alpha: boolean = false) => {
return alpha ? tinycolor(value).toHex8() : tinycolor(value).toHex();
};
const HexColorInput = defineComponent({
name: 'HexColorInput',
props: {
value: { type: String },
alpha: { type: Boolean },
onChange: { type: Function as PropType<(value: string) => void> },
},
setup(props) {
const { value, alpha } = toRefs(props);
const hexValue = ref<string>(value.value);
const focusRef = ref<boolean>(false);
const handleChange: InputProps['onChange'] = e => {
hexValue.value = e.target.value;
props.onChange(getHexValue(e.target.value, alpha.value));
};
const handleBlur: InputProps['onBlur'] = (e: any) => {
focusRef.value = false;
hexValue.value = getHexValue(e.target.value, alpha.value);
};
const handleFocus = () => {
focusRef.value = true;
};
watchEffect(() => {
if (!focusRef.value) {
hexValue.value = getHexValue(value.value, alpha.value);
}
});
return () => {
return (
<div>
<Input
size="small"
value={hexValue.value}
onFocus={handleFocus}
onChange={handleChange}
onBlur={handleBlur}
v-slots={{
prefix: () => '#',
}}
/>
<div class="color-panel-mode-title">HEX{alpha.value ? '8' : ''}</div>
</div>
);
};
},
});
type RgbaColor = tinycolor.ColorFormats.RGBA;
export type RgbColorInputProps = {
value?: RgbaColor;
onChange?: (value: RgbaColor) => void;
alpha?: boolean;
};
const RgbColorInput = defineComponent({
name: 'RgbColorInput',
props: {
value: { type: Object as PropType<RgbaColor>, default: () => ({ r: 0, g: 0, b: 0, a: 1 }) },
onChange: { type: Function as PropType<(value: RgbaColor) => void> },
alpha: { type: Boolean },
},
setup(props) {
const { value, alpha } = toRefs(props);
watch(value, val => {
props.onChange(val);
});
return () => {
return (
<div class="color-panel-rgba-input">
{/* <ConfigProvider theme={{ components: { InputNumber: { handleWidth: 12 } } }}> */}
<div class="color-panel-rgba-input-part">
<InputNumber min={0} max={255} size="small" v-model={[value.value.r, 'value']} />
<div class="color-panel-mode-title">R</div>
</div>
<div class="color-panel-rgba-input-part">
<InputNumber min={0} max={255} size="small" v-model={[value.value.g, 'value']} />
<div class="color-panel-mode-title">G</div>
</div>
<div class="color-panel-rgba-input-part">
<InputNumber min={0} max={255} size="small" v-model={[value.value.b, 'value']} />
<div class="color-panel-mode-title">B</div>
</div>
{alpha && (
<div class="color-panel-rgba-input-part">
<InputNumber
min={0}
max={1}
step={0.01}
size="small"
v-model={[value.value.a, 'value']}
/>
<div class="color-panel-mode-title">A</div>
</div>
)}
{/* </ConfigProvider> */}
</div>
);
};
},
});
export type ColorPanelProps = {
color: string;
onChange: (color: string) => void;
alpha?: boolean;
};
const colorModes = ['HEX', 'HEX8', 'RGB', 'RGBA'] as const;
type ColorMode = (typeof colorModes)[number];
const getColorStr = (color: any, mode: ColorMode) => {
switch (mode) {
case 'HEX':
return tinycolor(color).toHexString();
case 'HEX8':
return tinycolor(color).toHex8String();
case 'RGBA':
case 'RGB':
default:
return tinycolor(color).toRgbString();
}
};
const ColorPanel = defineComponent({
name: 'ColorPanel',
props: {
color: { type: String },
onChange: { type: Function as PropType<(color: string) => void> },
alpha: { type: Boolean },
},
inheritAttrs: false,
setup(props, { attrs }) {
const { color, alpha } = toRefs(props);
const { token } = useToken();
const [wrapSSR, hashId] = useStyle();
const colorMode = ref<ColorMode>('HEX');
const presetColors = computed(() => {
return [
token.value.blue,
token.value.purple,
token.value.cyan,
token.value.green,
token.value.magenta,
token.value.pink,
token.value.red,
token.value.orange,
token.value.yellow,
token.value.volcano,
token.value.geekblue,
token.value.gold,
token.value.lime,
'#000',
];
});
const handleColorModeChange = (value: ColorMode) => {
colorMode.value = value;
props.onChange(getColorStr(color.value, value));
};
return () => {
return wrapSSR(
<div {...attrs} class={classNames(hashId.value, 'color-panel')}>
{(colorMode.value === 'HEX' || colorMode.value === 'RGB') && (
<HexColorPicker
style={{ height: '160px' }}
color={tinycolor(color.value).toHex()}
onChange={value => {
props.onChange(getColorStr(value, colorMode.value));
}}
/>
)}
{(colorMode.value === 'RGBA' || colorMode.value === 'HEX8') && (
<RgbaColorPicker
style={{ height: '160px' }}
color={tinycolor(color).toRgb()}
onChange={value => {
props.onChange(getColorStr(value, colorMode.value));
}}
/>
)}
<div style={{ marginTop: '12px' }}>
<div class="color-panel-mode">
<div class="color-panel-preview">
<div style={{ backgroundColor: color.value, width: '100%', height: '100%' }} />
</div>
<Select
value={colorMode.value}
onChange={handleColorModeChange}
options={colorModes
.filter(item => alpha.value || item === 'HEX' || item === 'RGB')
.map(item => ({ value: item, key: item }))}
size="small"
bordered={false}
dropdownMatchSelectWidth={false}
/>
</div>
{colorMode.value === 'HEX' && (
<HexColorInput
value={tinycolor(color.value).toHex()}
onChange={v => props.onChange(tinycolor(v).toHexString())}
/>
)}
{colorMode.value === 'HEX8' && (
<HexColorInput
alpha
value={tinycolor(color.value).toHex8()}
onChange={v => props.onChange(tinycolor(v).toHex8String())}
/>
)}
{(colorMode.value === 'RGBA' || colorMode.value === 'RGB') && (
<RgbColorInput
alpha={colorMode.value === 'RGBA'}
value={tinycolor(color.value).toRgb()}
onChange={v => props.onChange(tinycolor(v).toRgbString())}
/>
)}
</div>
<div class="color-panel-preset-colors">
{presetColors.value.map(presetColor => (
<button
key={presetColor}
class="color-panel-preset-color-btn"
style={{ backgroundColor: presetColor }}
onClick={() => props.onChange(presetColor)}
/>
))}
</div>
</div>,
);
};
},
});
export default ColorPanel;

View File

@ -0,0 +1,80 @@
import { defineComponent, toRefs } from 'vue';
import type { CSSProperties } from 'vue';
import classNames from 'ant-design-vue/es/_util/classNames';
import makeStyle from './utils/makeStyle';
import getColorBgImg from './utils/getColorBgImg';
export type ColorPreviewProps = {
color: string;
dark?: boolean;
};
const useStyle = makeStyle('ColorPreview', () => ({
'.previewer-color-preview': {
width: '20px',
height: '20px',
position: 'relative',
borderRadius: '50%',
padding: 0,
display: 'inline-block',
'&::before': {
content: '""',
width: '100%',
height: '100%',
borderRadius: '50%',
top: 0,
insetInlineStart: 0,
position: 'absolute',
zIndex: 2,
backgroundColor: 'var(--antd-token-previewer-color-preview)',
boxShadow: '0 2px 3px -1px rgba(0,0,0,0.20), inset 0 0 0 1px rgba(0,0,0,0.09)',
},
},
}));
const ColorPreview = defineComponent({
name: 'ColorPreview',
inheritAttrs: false,
props: {
color: { type: String },
dark: { type: Boolean },
},
setup(props, { attrs }) {
const { color, dark } = toRefs(props);
const [warpSSR, hashId] = useStyle();
return () => {
return warpSSR(
<div
{...attrs}
class={classNames('previewer-color-preview', attrs.class, hashId.value)}
style={[
{
// @ts-ignore
['--antd-token-previewer-color-preview']: color.value,
...(attrs.style as CSSProperties),
},
]}
>
<div
style={{
content: '""',
width: '18px',
height: '18px',
borderRadius: '50%',
top: '1px',
insetInlineStart: '1px',
position: 'absolute',
zIndex: 1,
background: `${getColorBgImg(dark.value)} 0% 0% / 20px`,
}}
/>
</div>,
);
};
},
});
export default ColorPreview;

View File

@ -0,0 +1,133 @@
import type { CSSProperties, PropType } from 'vue';
import { defineComponent, toRefs, ref } from 'vue';
import makeStyle from './utils/makeStyle';
import classNames from 'ant-design-vue/es/_util/classNames';
import { Segmented, Tag } from 'ant-design-vue';
const useStyle = makeStyle('FilterPanel', token => ({
'.previewer-filter-panel': {
// boxShadow:
// '0 2px 4px 0 rgba(0,0,0,0.05), 0 1px 2px 0 rgba(25,15,15,0.07), 0 0 1px 0 rgba(0,0,0,0.08)',
// backgroundColor: '#fff',
// borderRadius: 6,
// padding: '8px 12px',
overflow: 'hidden',
display: 'flex',
alignItems: 'start',
'.component-tree-head': {
display: 'flex',
alignItems: 'center',
flex: 'none',
marginInlineEnd: 20,
'.component-tree-filter-type': {
color: token.colorTextSecondary,
marginInlineEnd: token.marginXS,
fontSize: token.fontSizeSM,
},
'.component-tree-filter-segmented': {
fontSize: token.fontSizeSM,
},
},
'.preview-panel-subtitle': {
fontSize: token.fontSizeSM,
color: token.colorTextSecondary,
},
[`${token.rootCls}-tag.previewer-token-filter-tag`]: {
color: token.colorPrimary,
backgroundColor: 'rgba(22,119,255,0.10)',
border: 'none',
borderRadius: 4,
'> .anticon': {
color: token.colorPrimary,
},
},
},
}));
export type FilterMode = 'highlight' | 'filter';
export type FilterPanelProps = {
filterMode?: FilterMode;
onFilterModeChange?: (mode: FilterMode) => void;
selectedTokens: string[];
onSelectedTokensChange?: (newTokens: string[]) => void;
onTokenClick?: (token: string) => void;
className?: string;
style?: CSSProperties;
};
const FilterPanel = defineComponent({
name: 'FilterPanel',
inheritAttrs: false,
props: {
filterMode: { type: String as PropType<FilterMode> },
onFilterModeChange: { type: Function as PropType<(mode: FilterMode) => void> },
selectedTokens: { type: Array as PropType<string[]> },
onSelectedTokensChange: { type: Function as PropType<(newTokens: string[]) => void> },
onTokenClick: { type: Function as PropType<(token: string) => void> },
},
setup(props, { attrs }) {
const { filterMode: customFilterMode, selectedTokens } = toRefs(props);
const [wrapSSR, hashId] = useStyle();
const filterMode = ref<FilterMode>(customFilterMode.value || 'filter');
return () => {
if (selectedTokens.value.length === 0) {
return null;
}
return wrapSSR(
<div {...attrs} class={classNames('previewer-filter-panel', hashId.value, attrs.class)}>
{selectedTokens.value && selectedTokens.value.length > 0 && (
<>
<div class="component-tree-head">
<div class="component-tree-filter-type">筛选方式</div>
<Segmented
class="component-tree-filter-segmented"
size="small"
value={filterMode.value}
onChange={value => {
props.onFilterModeChange?.(value as any);
filterMode.value = value as any;
}}
options={[
{ label: '过滤', value: 'filter' },
{ label: '高亮', value: 'highlight' },
]}
/>
</div>
<div>
<span class="preview-panel-subtitle">已选中</span>
{selectedTokens.value.map(token => (
<Tag
key={token}
closable
onClose={() =>
props.onSelectedTokensChange?.(
selectedTokens.value?.filter(item => item !== token),
)
}
style={{ marginBlock: '2px', cursor: 'pointer' }}
class="previewer-token-filter-tag"
onClick={() => props.onTokenClick?.(token)}
>
{token}
</Tag>
))}
</div>
</>
)}
</div>,
);
};
},
});
export default FilterPanel;

View File

@ -0,0 +1,101 @@
import classNames from 'ant-design-vue/es/_util/classNames';
import makeStyle from './utils/makeStyle';
import { defineComponent, PropType, toRefs } from 'vue';
const useStyle = makeStyle('IconSwitch', () => {
const activeBackground = '#314659';
return {
'.theme-editor-icon-switch': {
display: 'inline-block',
'.holder': {
position: 'relative',
display: 'inline-flex',
background: '#ebedf0',
borderRadius: '100vw',
cursor: 'pointer',
transition: 'all 0.3s',
'&::before': {
position: 'absolute',
top: 0,
left: 'calc(100% - 32px)',
width: 32,
height: 32,
background: activeBackground,
borderRadius: '100vw',
transition: 'all 0.3s',
content: '""',
},
'&.leftChecked::before': {
left: 0,
},
'&:hover': {
boxShadow: '0 0 3px fade(@active-background, 40%)',
},
},
'.icon': {
position: 'relative',
width: 32,
height: 32,
color: '#a3b1bf',
lineHeight: '32px',
textAlign: 'center',
transition: 'all 0.3s',
fontSize: 16,
'.anticon': {
fontSize: 14,
},
'&:first-child': {
marginInlineEnd: -4,
},
'&.active': {
color: '#fff',
},
},
},
};
});
export interface IconSwitchProps {
leftChecked?: boolean;
onChange?: (leftChecked: boolean) => void;
}
const IconSwitch = defineComponent({
name: 'IconSwitch',
props: {
leftChecked: { type: Boolean },
onChange: { type: Function as PropType<(leftChecked: boolean) => void> },
},
setup(props, { attrs, slots }) {
const { leftChecked } = toRefs(props);
const [wrapSSR, hashId] = useStyle();
return () => {
return wrapSSR(
<div {...attrs} class={classNames('theme-editor-icon-switch', attrs.class, hashId.value)}>
<div
class={classNames('holder', leftChecked.value && 'leftChecked')}
onClick={() => {
props.onChange(!leftChecked.value);
}}
>
<span class={classNames('icon', leftChecked.value && 'active')}>
{slots.leftIcon && slots.leftIcon()}
</span>
<span class={classNames('icon', !leftChecked.value && 'active')}>
{slots.rightIcon && slots.rightIcon()}
</span>
</div>
</div>,
);
};
},
});
export default IconSwitch;

View File

@ -0,0 +1,176 @@
import type { PropType } from 'vue';
import { defineComponent, toRefs, ref, computed } from 'vue';
import type { DerivativeFunc } from 'ant-design-vue/es/_util/cssinjs';
import classNames from 'ant-design-vue/es/_util/classNames';
import type { SelectedToken, Theme } from './interface';
import type { Locale } from './locale';
import { useProvideLocaleContext, zhCN } from './locale';
import { mapRelatedAlias, seedRelatedAlias, seedRelatedMap } from './meta/TokenRelation';
import { getRelatedComponents } from './utils/statistic';
import makeStyle from './utils/makeStyle';
import useControlledTheme from './hooks/useControlledTheme';
import type { TokenPanelProProps } from './token-panel-pro';
import TokenPanelPro from './token-panel-pro';
import ComponentDemoPro from './token-panel-pro/ComponentDemoPro';
import { antdComponents } from './component-panel';
const useStyle = makeStyle('ThemeEditor', token => ({
'.antd-theme-editor': {
backgroundColor: token.colorBgLayout,
display: 'flex',
},
}));
const defaultTheme: Theme = {
name: '默认主题',
key: 'default',
config: {},
};
export type ThemeEditorProps = {
/**
* @deprecated
* @default true
*/
simple?: boolean;
theme?: Theme;
onThemeChange?: (theme: Theme) => void;
darkAlgorithm?: DerivativeFunc<any, any>;
locale?: Locale;
};
const ThemeEditor = defineComponent({
name: 'ThemeEditor',
inheritAttrs: false,
props: {
simple: { type: Boolean },
theme: { type: Object as PropType<Theme> },
onThemeChange: { type: Function as PropType<(theme: Theme) => void> },
darkAlgorithm: { type: Function as PropType<DerivativeFunc<any, any>> },
locale: { type: Object as PropType<Locale>, default: zhCN },
},
setup(props, { attrs, expose }) {
const { theme: customTheme, darkAlgorithm, locale } = toRefs(props);
const [wrapSSR, hashId] = useStyle();
const selectedTokens = ref<SelectedToken>({
seed: ['colorPrimary'],
});
const aliasOpen = ref<boolean>(false);
const { theme, infoFollowPrimary, onInfoFollowPrimaryChange, updateRef } = useControlledTheme({
theme: customTheme,
defaultTheme,
onChange: props.onThemeChange,
darkAlgorithm,
});
const handleTokenSelect: TokenPanelProProps['onTokenSelect'] = (token, type) => {
const tokens = typeof token === 'string' ? (token ? [token] : []) : token;
if (type === 'seed') {
return {
seed: tokens,
};
}
let newSelectedTokens = { ...selectedTokens.value };
tokens.forEach(newToken => {
newSelectedTokens = {
...selectedTokens.value,
[type]: selectedTokens.value[type]?.includes(newToken)
? selectedTokens.value[type]?.filter(t => t !== newToken)
: [...(selectedTokens.value[type] ?? []), newToken],
};
});
if (type === 'map') {
delete newSelectedTokens.alias;
}
selectedTokens.value = newSelectedTokens;
};
const computedSelectedTokens = computed(() => {
if (
selectedTokens.value.seed?.length &&
!selectedTokens.value.map?.length &&
!selectedTokens.value.alias?.length
) {
return [
...selectedTokens.value.seed,
...((seedRelatedMap as any)[selectedTokens.value.seed[0]] ?? []),
...((seedRelatedAlias as any)[selectedTokens.value.seed[0]] ?? []),
];
}
if (selectedTokens.value.map?.length && !selectedTokens.value.alias?.length) {
return [
...selectedTokens.value.map,
...selectedTokens.value.map.reduce((result, item) => {
return result.concat((mapRelatedAlias as any)[item]);
}, []),
];
}
if (selectedTokens.value.alias?.length) {
return [...selectedTokens.value.alias];
}
return [];
});
const relatedComponents = computed(() => {
return computedSelectedTokens.value ? getRelatedComponents(computedSelectedTokens.value) : [];
});
expose({
updateRef,
});
useProvideLocaleContext(locale);
return () => {
return wrapSSR(
<div {...attrs} class={classNames(hashId.value, 'antd-theme-editor', attrs.class)}>
<div
style={{
flex: aliasOpen.value ? '0 0 860px' : `0 0 ${860 - 320}px`,
height: '100%',
backgroundColor: '#F7F8FA',
backgroundImage: 'linear-gradient(180deg, #FFFFFF 0%, rgba(246,247,249,0.00) 100%)',
display: 'flex',
transition: 'all 0.3s',
}}
>
<TokenPanelPro
aliasOpen={aliasOpen.value}
onAliasOpenChange={open => (aliasOpen.value = open)}
theme={theme.value}
style={{ flex: 1 }}
selectedTokens={selectedTokens.value}
onTokenSelect={handleTokenSelect}
infoFollowPrimary={infoFollowPrimary.value}
onInfoFollowPrimaryChange={onInfoFollowPrimaryChange}
/>
</div>
{/* <ComponentDemoPro
theme={theme.value}
components={antdComponents}
activeComponents={relatedComponents.value}
selectedTokens={computedSelectedTokens.value}
style={{ flex: 1, overflow: 'auto', height: '100%' }}
componentDrawer
/> */}
<ComponentDemoPro
theme={theme.value}
components={antdComponents}
activeComponents={relatedComponents.value}
selectedTokens={computedSelectedTokens.value}
style={{ flex: 1, overflow: 'auto' }}
componentDrawer
/>
</div>,
);
};
},
});
export default ThemeEditor;

View File

@ -0,0 +1,244 @@
import { Button, Dropdown, Input, InputNumber } from 'ant-design-vue';
import classNames from 'ant-design-vue/es/_util/classNames';
import type { PropType } from 'vue';
import { defineComponent, toRefs, computed, ref, watch } from 'vue';
import { debounce } from 'lodash';
import ColorPanel from './ColorPanel';
import ColorPreview from './ColorPreview';
import type { MutableTheme } from './interface';
import { useInjectLocaleContext } from './locale';
import isColor from './utils/isColor';
import makeStyle from './utils/makeStyle';
const useStyle = makeStyle('TokenInput', token => ({
'.previewer-token-input': {
[`${token.rootCls}-input-group-addon, ${token.rootCls}-input-number-group-addon`]: {
border: '0 !important',
color: `rgba(0, 0, 0, 0.25) !important`,
fontSize: `${token.fontSizeSM}px !important`,
padding: '0 !important',
backgroundColor: 'transparent !important',
'&:first-child': {
paddingInlineStart: 0,
},
'&:last-child': {
paddingInlineEnd: 0,
},
},
[`${token.rootCls}-input-group-wrapper, ${token.rootCls}-input-number-group-wrapper`]: {
padding: 0,
height: 24,
width: '100%',
input: {
fontSize: token.fontSizeSM,
lineHeight: token.lineHeightSM,
padding: `2px ${token.paddingXS}px`,
height: 24,
},
},
[`${token.rootCls}-input-group-wrapper ${token.rootCls}-input, ${token.rootCls}-input-number-group-wrapper ${token.rootCls}-input-number`]:
{
background: 'white',
borderRadius: `${token.borderRadiusLG}px !important`,
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
},
'&&-light': {
[`${token.rootCls}-input-group-addon, ${token.rootCls}-input-number-group-addon`]: {
backgroundColor: token.colorBgContainer,
},
[`${token.rootCls}-input-group-wrapper ${token.rootCls}-input,
${token.rootCls}-input-number-group-wrapper ${token.rootCls}-input-number-input`]: {
background: token.colorFillAlter,
},
},
'&&-readonly': {
input: {
cursor: 'text',
color: token.colorText,
},
},
},
}));
export type TokenInputProps = {
theme?: MutableTheme;
value?: string | number;
onChange?: (value: string | number) => void;
light?: boolean;
readonly?: boolean;
onReset?: () => void;
canReset?: boolean;
hideTheme?: boolean;
};
const TokenInput = defineComponent({
name: 'TokenInput',
inheritAttrs: false,
props: {
theme: { type: Object as PropType<MutableTheme> },
value: { type: [String, Number] },
onChange: { type: Function as PropType<(value: string | number) => void> },
light: { type: Boolean },
readonly: { type: Boolean },
onReset: { type: Function as PropType<() => void> },
canReset: { type: Boolean },
hideTheme: { type: Boolean },
},
setup(props, { attrs }) {
const { value, theme, light, readonly, canReset: customCanReset, hideTheme } = toRefs(props);
const valueRef = ref<number | string>(value.value || '');
const tokenValue = ref<string | number>(value.value || '');
const canReset = computed(() => customCanReset.value ?? valueRef.value !== tokenValue.value);
const locale = useInjectLocaleContext();
const [wrapSSR, hashId] = useStyle();
watch(
value,
val => {
if (val !== undefined) {
tokenValue.value = val;
}
},
{ immediate: true },
);
const debouncedOnChange = debounce((newValue: number | string) => {
props.onChange?.(newValue);
}, 500);
const handleTokenChange = (newValue: number | string) => {
if (!readonly.value) {
tokenValue.value = newValue;
debouncedOnChange(newValue);
}
};
const handleReset = () => {
if (props.onReset) {
props.onReset();
} else {
handleTokenChange(valueRef.value);
}
};
return () => {
const addonAfter = !readonly.value && (
<span
style={{
display: 'flex',
alignItems: 'center',
minWidth: hideTheme.value ? '' : '80px',
}}
>
{canReset.value || hideTheme.value ? (
<Button
style={{
fontSize: '12px',
}}
onClick={handleReset}
type="link"
size="small"
disabled={!canReset.value}
>
{locale.value.reset}
</Button>
) : (
<span style={{ padding: '0 8px' }}>{theme.value?.name}</span>
)}
</span>
);
let inputNode;
if (typeof valueRef.value === 'string' && isColor(valueRef.value)) {
inputNode = (
<Input
bordered={false}
addonAfter={addonAfter}
value={String(tokenValue.value)}
disabled={readonly.value}
addonBefore={
<Dropdown
trigger={['click']}
overlay={
<ColorPanel
alpha
color={String(tokenValue.value)}
onChange={(v: string) => {
handleTokenChange(v);
}}
/>
}
>
<ColorPreview
color={String(tokenValue.value)}
dark={theme.value?.key === 'dark'}
style={{
cursor: 'pointer',
marginInlineEnd: '8px',
verticalAlign: 'top',
}}
/>
</Dropdown>
}
onChange={e => {
handleTokenChange(e.target.value);
}}
/>
);
} else if (typeof valueRef.value === 'number') {
inputNode = (
<InputNumber
addonAfter={addonAfter}
bordered={false}
value={tokenValue.value}
disabled={readonly.value}
onChange={newValue => {
handleTokenChange(Number(newValue));
}}
/>
);
} else {
inputNode = (
<Input
addonAfter={addonAfter}
bordered={false}
value={String(tokenValue.value)}
disabled={readonly.value}
onChange={e => {
handleTokenChange(
typeof value.value === 'number' ? Number(e.target.value) : e.target.value,
);
}}
/>
);
}
return wrapSSR(
<div
{...attrs}
class={classNames('previewer-token-input', hashId.value, attrs.class, {
'previewer-token-input-light': light.value,
'previewer-token-input-readonly': readonly.value,
})}
>
{inputNode}
</div>,
);
};
},
});
export default TokenInput;

View File

@ -0,0 +1,24 @@
import { defineComponent } from 'vue';
import { Alert, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space direction={'vertical'}>
<Alert message="Success Tips" type="success" showIcon />
<Alert message="Informational Notes" type="info" showIcon />
<Alert message="Warning" type="warning" showIcon closable />
<Alert message="Error" type="error" showIcon />
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorIconHover', 'colorIcon', 'colorText'],
key: 'alert',
};
export default componentDemo;

View File

@ -0,0 +1,28 @@
import { defineComponent } from 'vue';
import { Alert, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space direction={'vertical'}>
<Alert message="Error" type="error" showIcon />
<Alert
message="Error"
description="This is an error message about copywriting."
type="error"
showIcon
/>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorErrorBg', 'colorErrorBorder', 'colorError'],
key: 'error',
};
export default componentDemo;

View File

@ -0,0 +1,11 @@
import Default from './alert';
import error from './error';
import info from './info';
import success from './success';
import warning from './warning';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, error, info, success, warning];
export default previewerDemo;

View File

@ -0,0 +1,27 @@
import { defineComponent } from 'vue';
import { Alert, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space direction={'vertical'}>
<Alert message="Informational Notes" type="info" showIcon />
<Alert
message="Informational Notes"
description="Additional description and information about copywriting."
type="info"
showIcon
/>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorInfo', 'colorInfoBorder', 'colorInfoBg'],
key: 'info',
};
export default componentDemo;

View File

@ -0,0 +1,27 @@
import { defineComponent } from 'vue';
import { Alert, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space direction={'vertical'}>
<Alert message="Success Tips" type="success" showIcon />
<Alert
message="Success Tips"
description="Detailed description and advice about successful copywriting."
type="success"
showIcon
/>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorSuccess', 'colorSuccessBorder', 'colorSuccessBg'],
key: 'success',
};
export default componentDemo;

View File

@ -0,0 +1,28 @@
import { defineComponent } from 'vue';
import { Alert, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space direction={'vertical'}>
<Alert message="Warning" type="warning" showIcon closable />
<Alert
message="Warning"
description="This is a warning notice about copywriting."
type="warning"
showIcon
closable
/>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorWarning', 'colorWarningBorder', 'colorWarningBg'],
key: 'warning',
};
export default componentDemo;

View File

@ -0,0 +1,26 @@
import { Anchor } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { Link } = Anchor;
const Demo = () => {
return (
<div style={{ padding: '12px' }}>
<Anchor>
<Link href="#" title="Basic demo" />
<Link href="#components-anchor-demo-static" title="Static demo" />
<Link href="#API" title="API">
<Link href="#Anchor-Props" title="Anchor Props" />
<Link href="#Link-Props" title="Link Props" />
</Link>
</Anchor>
</div>
);
};
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorPrimary', 'colorSplit', 'colorBgContainer'],
key: 'anchor',
};
export default componentDemo;

View File

@ -0,0 +1,33 @@
import { defineComponent } from 'vue';
import { Anchor, theme } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { Link } = Anchor;
const Demo = defineComponent({
setup() {
const { token } = theme.useToken();
return () => {
return (
<div style={{ background: token.value.colorBorderSecondary, padding: '12px' }}>
<Anchor>
<Link href="#components-anchor-demo-basic" title="Basic demo" />
<Link href="#components-anchor-demo-static" title="Static demo" />
<Link href="#API" title="API">
<Link href="#Anchor-Props" title="Anchor Props" />
<Link href="#Link-Props" title="Link Props" />
</Link>
</Anchor>
</div>
);
};
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorSplit'],
key: 'anchorInLayout',
};
export default componentDemo;

View File

@ -0,0 +1,8 @@
import Demo from './anchor';
import AnchorLayout from './anchorInLayout';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Demo, AnchorLayout];
export default previewerDemo;

View File

@ -0,0 +1,59 @@
import { defineComponent, ref } from 'vue';
import { AutoComplete } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const mockVal = (str: string, repeat: number = 1) => ({
value: str.repeat(repeat),
});
const Demo = defineComponent({
setup() {
const value = ref('');
const options = ref<{ value: string }[]>([]);
const onSearch = (searchText: string) => {
options.value = !searchText
? []
: [mockVal(searchText), mockVal(searchText, 2), mockVal(searchText, 3)];
};
const onSelect = (data: string) => {
// eslint-disable-next-line no-console
console.log('onSelect', data);
};
const onChange = (data: string) => {
value.value = data;
};
return () => {
return (
<>
{' '}
<AutoComplete
options={options.value}
style={{ width: 200 }}
onSelect={onSelect}
onSearch={onSearch}
placeholder="input here"
/>{' '}
<br /> <br />{' '}
<AutoComplete
value={value.value}
options={options.value}
style={{ width: 200 }}
onSelect={onSelect}
onSearch={onSearch}
onChange={onChange}
placeholder="control mode"
/>{' '}
</>
);
};
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: [],
key: 'autoComplete',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './auto-complete';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,19 @@
import { Avatar, Space } from 'ant-design-vue';
import { UserOutlined } from '@ant-design/icons-vue';
export default () => (
<Space direction="vertical">
<Space>
<Avatar size={64} icon={<UserOutlined />} />
<Avatar size="large" icon={<UserOutlined />} />
<Avatar icon={<UserOutlined />} />
<Avatar size="small" icon={<UserOutlined />} />
</Space>
<Space>
<Avatar shape="square" size={64} icon={<UserOutlined />} />
<Avatar shape="square" size="large" icon={<UserOutlined />} />
<Avatar shape="square" icon={<UserOutlined />} />
<Avatar shape="square" size="small" icon={<UserOutlined />} />
</Space>
</Space>
);

View File

@ -0,0 +1,13 @@
import Default from './avatar';
// import Progress from './progress';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [
{
demo: <Default />,
key: 'default',
},
];
export default previewerDemo;

View File

@ -0,0 +1,32 @@
import { defineComponent } from 'vue';
import { Badge, Avatar, Space, theme } from 'ant-design-vue';
import { ClockCircleFilled } from '@ant-design/icons-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
const { token } = theme.useToken();
return () => (
<Space size="large">
<Badge count={5}>
<Avatar shape="square" size="large" />
</Badge>
<Badge count={0} showZero>
<Avatar shape="square" size="large" />
</Badge>
<Badge count={<ClockCircleFilled style={{ color: token.value.colorError }} />}>
<Avatar shape="square" size="large" />
</Badge>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorError', 'colorBorderBg', 'colorBgContainer'],
key: 'badge',
};
export default componentDemo;

View File

@ -0,0 +1,10 @@
import Default from './badge';
import Progress from './progress';
import warning from './warning';
import success from './success';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, Progress, warning, success];
export default previewerDemo;

View File

@ -0,0 +1,22 @@
import { defineComponent } from 'vue';
import { Badge, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space size="small">
<Badge dot status={'processing'} />
Process
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorPrimary'],
key: 'progress',
};
export default componentDemo;

View File

@ -0,0 +1,22 @@
import { defineComponent } from 'vue';
import { Badge, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space size="small">
<Badge dot status={'success'} />
Success
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorSuccess'],
key: 'success',
};
export default componentDemo;

View File

@ -0,0 +1,22 @@
import { defineComponent } from 'vue';
import { Badge, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space size="small">
<Badge dot status={'warning'} />
Warning
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorWarning'],
key: 'warning',
};
export default componentDemo;

View File

@ -0,0 +1,28 @@
import { defineComponent } from 'vue';
import { Breadcrumb } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Breadcrumb>
<Breadcrumb.Item>Home</Breadcrumb.Item>
<Breadcrumb.Item>
<a href="">Application Center</a>
</Breadcrumb.Item>
<Breadcrumb.Item>
<a href="">Application List</a>
</Breadcrumb.Item>
<Breadcrumb.Item>An Application</Breadcrumb.Item>
</Breadcrumb>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorText', 'colorPrimary', 'colorPrimaryActive', 'colorPrimaryHover'],
key: 'breadcrumb',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './breadcrumb';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,32 @@
import { defineComponent } from 'vue';
import { Button, Space, Tooltip } from 'ant-design-vue';
import { SearchOutlined } from '@ant-design/icons-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space>
<Button type="primary">Primary Button</Button>
<Tooltip title="search">
<Button type="primary" shape="circle" icon={<SearchOutlined />} />
</Tooltip>
<Button type="primary" shape="circle">
A
</Button>
<Button type="primary" ghost icon={<SearchOutlined />}>
Search
</Button>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorPrimary'],
key: 'button-icon',
};
export default componentDemo;

View File

@ -0,0 +1,33 @@
import { defineComponent } from 'vue';
import { Button, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space>
<Button type="primary">Primary Button</Button>
<Button>Default Button</Button>
<Button type="dashed">Dashed Button</Button> <br />
<Button type="text">Text Button</Button>
<Button ghost>Ghost Button</Button>
<Button type="link">Link Button</Button>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: [
'colorText',
'colorPrimary',
'colorPrimaryActive',
'colorPrimaryHover',
'controlOutline',
'controlTmpOutline',
],
key: 'button',
};
export default componentDemo;

View File

@ -0,0 +1,41 @@
import { defineComponent } from 'vue';
import { Button, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space>
<Button type="primary" danger>
primary
</Button>
<Button type="default" danger>
default
</Button>
<Button type="text" danger>
text
</Button>
{/*<Button ghost danger>*/}
{/* ghost*/}
{/*</Button>*/}
<Button type="link" danger>
link
</Button>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: [
'colorError',
'colorErrorActive',
'colorErrorHover',
'colorErrorBorder',
'colorErrorOutline',
],
key: 'danger',
};
export default componentDemo;

View File

@ -0,0 +1,13 @@
import { Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <Button>default</Button>;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgContainer'],
key: 'defaultButton',
};
export default componentDemo;

View File

@ -0,0 +1,37 @@
import { defineComponent } from 'vue';
import { Button, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space>
<Button disabled type="primary">
Primary
</Button>
<Button disabled>Default</Button>
<Button disabled type="dashed">
Dashed
</Button>
<br />
<Button disabled type="text">
Text
</Button>
<Button disabled ghost>
Ghost
</Button>
<Button disabled type="link">
Link
</Button>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorTextDisabled', 'colorBgContainerDisabled'],
key: 'disabled',
};
export default componentDemo;

View File

@ -0,0 +1,17 @@
import Default from './button';
import DefaultButton from './defaultButton';
import ButtonIconDemo from './button-icon';
import DangerButton from './dangerButton';
import disabled from './disabled';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [
Default,
ButtonIconDemo,
DangerButton,
DefaultButton,
disabled,
];
export default previewerDemo;

View File

@ -0,0 +1,12 @@
import { Calendar } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <Calendar />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorPrimary', 'colorPrimaryHover', 'colorBgContainer'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,12 @@
import { Calendar } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <Calendar disabledDate={() => true} />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgContainerDisabled', 'colorTextDisabled'],
key: 'disabled',
};
export default componentDemo;

View File

@ -0,0 +1,8 @@
import Default from './calendar';
import disabled from './disabled';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, disabled];
export default previewerDemo;

View File

@ -0,0 +1,52 @@
import { defineComponent } from 'vue';
import { Card, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space>
<Card
title="Default size card"
style={{ width: '300px' }}
v-slots={{
extra: () => <a href="#">More</a>,
}}
>
<p>Card content</p>
<p>Card content</p>
<p>Card content</p>
</Card>
<Card
loading
size="small"
title="Small size card"
style={{ width: '300px' }}
v-slots={{
extra: () => <a href="#">More</a>,
}}
>
<p>Card content</p>
<p>Card content</p>
<p>Card content</p>
</Card>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: [
'colorText',
'colorTextHeading',
'colorTextSecondary',
'colorBgContainer',
'colorBorderSecondary',
'colorPrimary',
'colorBgContainer',
],
key: 'card',
};
export default componentDemo;

View File

@ -0,0 +1,36 @@
import { defineComponent } from 'vue';
import type { CSSProperties } from 'vue';
import { Card } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const gridStyle: CSSProperties = {
width: '25%',
textAlign: 'center',
};
const Demo = defineComponent({
setup() {
return () => (
<Card title="Card Title">
<Card.Grid style={gridStyle}>Content</Card.Grid>
<Card.Grid hoverable={false} style={gridStyle}>
Content
</Card.Grid>
<Card.Grid style={gridStyle}>Content</Card.Grid>
<Card.Grid style={gridStyle}>Content</Card.Grid>
<Card.Grid style={gridStyle}>Content</Card.Grid>
<Card.Grid style={gridStyle}>Content</Card.Grid>
<Card.Grid style={gridStyle}>Content</Card.Grid>
</Card>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBorderSecondary'],
key: 'cardGrid',
};
export default componentDemo;

View File

@ -0,0 +1,9 @@
import Default from './card';
import inner from './inner';
import cardGrid from './cardGrid';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, inner, cardGrid];
export default previewerDemo;

View File

@ -0,0 +1,23 @@
import { defineComponent } from 'vue';
import { Card, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space>
<Card type="inner" title="Inner Card title">
Inner Card content
</Card>
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorFillAlter'],
key: 'inner',
};
export default componentDemo;

View File

@ -0,0 +1,42 @@
import { defineComponent } from 'vue';
import type { CSSProperties } from 'vue';
import { Carousel } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const contentStyle = {
height: '160px',
color: '#fff',
lineHeight: '160px',
textAlign: 'center',
background: '#364d79',
};
const Demo = defineComponent({
setup() {
return () => (
<Carousel>
<div>
<h3 style={contentStyle as CSSProperties}>1</h3>
</div>
<div>
<h3 style={contentStyle as CSSProperties}>2</h3>
</div>
<div>
<h3 style={contentStyle as CSSProperties}>3</h3>
</div>
<div>
<h3 style={contentStyle as CSSProperties}>4</h3>
</div>
</Carousel>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorText', 'colorBgContainer'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './carousel';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,14 @@
import { Cascader } from 'ant-design-vue';
import options from './data';
import type { ComponentDemo } from '../../interface';
const Demo = (props: any) => <Cascader options={options} {...props} placeholder="Please select" />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgContainer', 'colorPrimary'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,26 @@
const options = [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [{ value: 'xihu', label: 'West Lake' }],
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{
value: 'nanjing',
label: 'Nanjing',
children: [{ value: 'zhonghuamen', label: 'Zhong Hua Men' }],
},
],
},
];
export default options;

View File

@ -0,0 +1,19 @@
import { defineComponent } from 'vue';
import { Cascader } from 'ant-design-vue';
import options from './data';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => <Cascader options={options} open disabled placeholder="Please select" />;
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgContainerDisabled'],
key: 'disabled',
};
export default componentDemo;

View File

@ -0,0 +1,18 @@
import { Cascader } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
import options from './data';
const Demo = () => {
return (
<Cascader options={options} placeholder="Please select" searchValue={'jiang'} showSearch />
);
};
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorHighlight'],
key: 'highlight',
};
export default componentDemo;

View File

@ -0,0 +1,9 @@
import Default from './cascader';
import HighLight from './highlight';
import disable from './disable';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, HighLight, disable];
export default previewerDemo;

View File

@ -0,0 +1,19 @@
import { Checkbox, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = (props: any) => (
<Space>
<Checkbox {...props}>Checkbox</Checkbox>
<Checkbox {...props} checked>
选中态
</Checkbox>
</Space>
);
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorPrimary', 'colorText', 'colorBgContainer'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,12 @@
import { Checkbox } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <Checkbox disabled>Checkbox</Checkbox>;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorTextDisabled', 'colorBgContainerDisabled'],
key: 'disabled',
};
export default componentDemo;

View File

@ -0,0 +1,8 @@
import Default from './checkbox';
import disabled from './disabled';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, disabled];
export default previewerDemo;

View File

@ -0,0 +1,32 @@
import { defineComponent } from 'vue';
import { Collapse } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { Panel } = Collapse;
const text = ` A dog is a type of domesticated animal. Known for its loyalty and faithfulness, it can be found as a welcome guest in many households across the world.`;
const Demo = defineComponent({
setup() {
return () => (
<Collapse defaultActiveKey={['1']}>
<Panel header="This is panel header 1" key="1">
<p>{text}</p>
</Panel>
<Panel header="This is panel header 2" key="2">
<p>{text}</p>
</Panel>
<Panel header="This is panel header 3" key="3">
<p>{text}</p>
</Panel>
</Collapse>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorTextSecondary', 'colorText', 'colorFillAlter', 'colorBgContainer'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './collapse';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,12 @@
import { DatePicker } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <DatePicker status={'error'} />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorError', 'colorErrorBorder', 'colorErrorHover', 'colorErrorOutline'],
key: 'danger',
};
export default componentDemo;

View File

@ -0,0 +1,31 @@
import { defineComponent } from 'vue';
import { DatePicker, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space direction="vertical">
<DatePicker picker="week" />
<DatePicker picker="month" />
<DatePicker picker="quarter" />
<DatePicker picker="year" />
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: [
'colorPrimary',
'colorPrimaryBorder',
'colorPrimaryHover',
'controlOutline',
'colorBgElevated',
'colorBgContainer',
],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,25 @@
import { defineComponent } from 'vue';
import { DatePicker, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space direction="vertical">
<DatePicker disabled />
<DatePicker disabled picker="week" />
<DatePicker disabled picker="month" />
<DatePicker disabled picker="quarter" />
<DatePicker disabled picker="year" />
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgContainerDisabled', 'colorTextDisabled'],
key: 'disabled',
};
export default componentDemo;

View File

@ -0,0 +1,12 @@
import { DatePicker } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <DatePicker />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorIcon', 'colorIconHover'],
key: 'icon',
};
export default componentDemo;

View File

@ -0,0 +1,11 @@
import Default from './date-picker';
import danger from './danger';
import warning from './warning';
import icon from './icon';
import disabled from './disabled';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, danger, warning, icon, disabled];
export default previewerDemo;

View File

@ -0,0 +1,12 @@
import { DatePicker } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <DatePicker status={'warning'} />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorWarning', 'colorWarningBorder', 'colorWarningHover', 'colorWarningOutline'],
key: 'warning',
};
export default componentDemo;

View File

@ -0,0 +1,24 @@
import { defineComponent } from 'vue';
import { Descriptions } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Descriptions title="User Info" bordered>
<Descriptions.Item label="Product">Cloud Database</Descriptions.Item>
<Descriptions.Item label="Billing Mode">Prepaid</Descriptions.Item>
<Descriptions.Item label="Automatic Renewal">YES</Descriptions.Item>
<Descriptions.Item label="Order time">2018-04-24 18:00:00</Descriptions.Item>
</Descriptions>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorSplit', 'colorText', 'colorFillAlter'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './descriptions';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,44 @@
import { defineComponent } from 'vue';
import { Divider } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi
ista probare, quae sunt a te dicta? Refert tamen, quo modo.
</p>
<Divider plain>Text</Divider>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi
ista probare, quae sunt a te dicta? Refert tamen, quo modo.
</p>
<Divider orientation="left" plain>
Left Text
</Divider>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi
ista probare, quae sunt a te dicta? Refert tamen, quo modo.
</p>
<Divider orientation="right" plain>
Right Text
</Divider>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nonne merninisti licere mihi
ista probare, quae sunt a te dicta? Refert tamen, quo modo.
</p>
</>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorSplit', 'colorText'],
key: 'divider',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './divider';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,39 @@
import { Button, Drawer } from 'ant-design-vue';
import { defineComponent, ref } from 'vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
() => {
const visible = ref(false);
const showDrawer = () => {
visible.value = true;
};
const onClose = () => {
visible.value = false;
};
return (
<>
<Button type="primary" onClick={showDrawer}>
Open
</Button>
<Drawer title="Basic Drawer" placement="right" onClose={onClose} open={visible.value}>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
</>
);
};
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgMask', 'colorBgElevated'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './drawer';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,33 @@
import { defineComponent } from 'vue';
import { Dropdown } from 'ant-design-vue';
import { DownOutlined } from '@ant-design/icons-vue';
import menu from './menu';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<div>
<Dropdown
v-slots={{
overlay: () => menu,
}}
>
<a class="ant-dropdown-link" onClick={e => e.preventDefault()}>
Hover me <DownOutlined />
</a>
</Dropdown>
</div>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorPrimary', 'colorError', 'colorErrorHover', 'colorBgElevated'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,48 @@
import { defineComponent } from 'vue';
import { DownOutlined } from '@ant-design/icons-vue';
import { Dropdown, Typography } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<div>
<Dropdown
menu={{
items: [
{
label: 'item 1',
key: '1',
},
{
label: 'a danger item',
danger: true,
key: '3',
},
{
label: 'danger disabled item',
danger: true,
disabled: true,
key: '2',
},
],
}}
>
{' '}
<Typography.Text type={'danger'}>
Hover me <DownOutlined />
</Typography.Text>
</Dropdown>
</div>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorError', 'colorErrorHover', 'colorBgElevated'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './dropdown';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,25 @@
import { Menu } from 'ant-design-vue';
import { DownOutlined } from '@ant-design/icons-vue';
const menu = (
<Menu>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="https://www.antgroup.com">
1st menu item
</a>
</Menu.Item>
<Menu.Item icon={<DownOutlined />} disabled>
<a target="_blank" rel="noopener noreferrer" href="https://www.aliyun.com">
2nd menu item (disabled)
</a>
</Menu.Item>
<Menu.Item disabled>
<a target="_blank" rel="noopener noreferrer" href="https://www.luohanacademy.com">
3rd menu item (disabled)
</a>
</Menu.Item>
<Menu.Item danger>a danger item</Menu.Item>
</Menu>
);
export default menu;

View File

@ -0,0 +1,12 @@
import { Empty } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <Empty />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorTextDisabled'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './empty';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,43 @@
import { defineComponent, ref, reactive } from 'vue';
import { Form, FormItem, Input } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => {
const onFinish = () => {};
const onFinishFailed = () => {};
const formRef = ref();
const formData = reactive({
username: '',
});
return (
<Form
ref={formRef}
model={formData}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<FormItem
label="Username"
name="username"
rules={[{ required: true, message: 'Please input your username!' }]}
>
<Input status={'error'} v-model={[formData.username, 'value']} />
</FormItem>
</Form>
);
};
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorError', 'colorErrorBorder', 'colorErrorHover'],
key: 'danger',
};
export default componentDemo;

View File

@ -0,0 +1,76 @@
import { defineComponent, ref, toRaw, reactive } from 'vue';
import { Form, FormItem, Input, Button, Checkbox } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => {
const onFinish = () => {};
const onFinishFailed = () => {};
const formRef = ref();
const formData = reactive({
username: '',
password: '',
});
const onSubmit = () => {
formRef.value
.validate()
.then(() => {
console.log('values', formData, toRaw(formData));
})
.catch(error => {
console.log('error', error);
});
};
const resetForm = () => {
formRef.value.resetFields();
};
return (
<Form
ref={formRef}
model={formData}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<FormItem
label="Username"
name="username"
rules={[{ required: true, message: 'Please input your username!' }]}
>
<Input v-model={[formData.username, 'value']} />
</FormItem>
<FormItem
label="Password"
name="password"
rules={[{ required: true, message: 'Please input your password!' }]}
>
<Input.Password v-model={[formData.password, 'value']} />
</FormItem>
<FormItem name="remember" wrapperCol={{ offset: 8, span: 16 }}>
<Checkbox>Remember me</Checkbox>
</FormItem>
<FormItem wrapperCol={{ offset: 8, span: 16 }}>
<Button type="primary" onClick={onSubmit}>
Submit
</Button>
<Button style={{ marginLeft: '16px' }} onClick={resetForm}>
Reset
</Button>
</FormItem>
</Form>
);
};
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorError', 'controlOutline', 'colorErrorBorder', 'colorErrorHover'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,10 @@
import Default from './form';
import warning from './warning';
import danger from './danger';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, warning, danger];
export default previewerDemo;

View File

@ -0,0 +1,43 @@
import { defineComponent, ref, reactive } from 'vue';
import { Form, FormItem, Input } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => {
const onFinish = () => {};
const onFinishFailed = () => {};
const formRef = ref();
const formData = reactive({
username: '',
});
return (
<Form
ref={formRef}
model={formData}
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<FormItem
label="Username"
name="username"
rules={[{ required: true, message: 'Please input your username!' }]}
>
<Input status={'warning'} v-model={[formData.username, 'value']} />
</FormItem>
</Form>
);
};
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorWarning', 'controlOutline', 'colorWarningBorder', 'colorWarningHover'],
key: 'warning',
};
export default componentDemo;

View File

@ -0,0 +1,56 @@
import { Row, Col } from 'ant-design-vue';
import makeStyle from '../../utils/makeStyle';
import type { ComponentDemo } from '../../interface';
import { defineComponent } from 'vue';
const useStyle = makeStyle('GridDemo', token => ({
'.previewer-grid-demo': {
[`${token.rootCls}-row`]: {
marginBottom: 16,
},
[`${token.rootCls}-row > div:not(.gutter-row)`]: {
padding: '16px 0',
background: '#0092ff',
color: '#fff',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
'&:nth-child(2n + 1)': {
background: 'rgba(0,146,255,.75)',
},
},
},
}));
const Demo = defineComponent({
setup() {
const [, hashId] = useStyle();
return () => (
<div class={['previewer-grid-demo', hashId.value]}>
<Row>
<Col span={24}>col</Col>
</Row>
<Row>
<Col span={12}>col-12</Col> <Col span={12}>col-12</Col>
</Row>
<Row>
<Col span={8}>col-8</Col> <Col span={8}>col-8</Col>
<Col span={8}>col-8</Col>
</Row>
<Row>
<Col span={6}>col-6</Col> <Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
<Col span={6}>col-6</Col>
</Row>
</div>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './grid';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,28 @@
import { defineComponent } from 'vue';
import { Space } from 'ant-design-vue';
import {
HomeOutlined,
SettingFilled,
SmileOutlined,
SyncOutlined,
LoadingOutlined,
} from '@ant-design/icons-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => (
<Space>
<HomeOutlined /> <SettingFilled /> <SmileOutlined /> <SyncOutlined spin />
<SmileOutlined rotate={180} /> <LoadingOutlined />
</Space>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './icon';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,15 @@
import { Image } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => {
return <Image width={200} height={200} src="error" placeholder />;
};
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgContainerDisabled'],
key: 'disabled',
};
export default componentDemo;

View File

@ -0,0 +1,20 @@
import { Image } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => {
return (
<Image
width={200}
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
/>
);
};
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgMask'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,8 @@
import Default from './image';
import disabled from './disabled';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, disabled];
export default previewerDemo;

View File

@ -0,0 +1,125 @@
import Alert from './alert';
import Anchor from './anchor';
import AutoComplete from './autoComplete';
import Avatar from './avatar';
import Badge from './badge';
import Breadcrumb from './breadcrumb';
import Button from './button';
import Calendar from './calendar';
import Card from './card';
import Carousel from './carousel';
import Cascader from './cascader';
import Checkbox from './checkbox';
import Collapse from './collapse';
import DatePicker from './datePicker';
import Descriptions from './descriptions';
import Dropdown from './dropdown';
import Empty from './empty';
import Form from './form';
import Grid from './grid';
import Icon from './icon';
import Image from './image';
import InputNumber from './inputNumber';
import Input from './input';
import List from './list';
import Mentions from './mentions';
import Modal from './modal';
import Notification from './notification';
import Pagination from './pagination';
import Popconfirm from './popconfirm';
import Popover from './popover';
import Radio from './radio';
import Rate from './rate';
import Select from './select';
import Skeleton from './skeleton';
import Slider from './slider';
import Spin from './spin';
import Statistic from './statistic';
import Switch from './switch';
import Table from './table';
import Tabs from './tabs';
import Tag from './tag';
import TimePicker from './timePicker';
import Timeline from './timeline';
import Tooltip from './tooltip';
import Transfer from './transfer';
import TreeSelect from './treeSelect';
import Tree from './tree';
import Typography from './typography';
import Upload from './upload';
import Divider from './divider';
import Space from './space';
import Menu from './menu';
import Steps from './steps';
import Segmented from './segmented';
import Drawer from './drawer';
import Message from './message';
import Progress from './progress';
import Result from './result';
import type { ComponentDemo } from '../interface';
export type PreviewerDemos = Record<string, ComponentDemo[]>;
const ComponentDemos: PreviewerDemos = {
Alert,
Anchor,
AutoComplete,
Avatar,
Badge,
Breadcrumb,
Button,
Calendar,
Card,
Carousel,
Cascader,
Checkbox,
Collapse,
DatePicker,
Descriptions,
Dropdown,
Empty,
Form,
Grid,
Icon,
Image,
InputNumber,
Input,
List,
Mentions,
Modal,
Notification,
Pagination,
Popconfirm,
Popover,
Radio,
Rate,
Select,
Skeleton,
Slider,
Spin,
Statistic,
Switch,
Table,
Tabs,
Tag,
TimePicker,
Timeline,
Tooltip,
Transfer,
TreeSelect,
Tree,
Typography,
Upload,
Divider,
Space,
Menu,
Steps,
Segmented,
Drawer,
Message,
Result,
Progress,
};
export default ComponentDemos;

View File

@ -0,0 +1,17 @@
import { defineComponent } from 'vue';
import { Input } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => <Input placeholder="Basic usage" value={'右侧的图标就是 colorIcon'} allowClear />;
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorIcon', 'colorIconHover'],
key: 'clearIcon',
};
export default componentDemo;

View File

@ -0,0 +1,19 @@
import { defineComponent } from 'vue';
import { Input } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
function onChange() {}
const Demo = defineComponent({
setup() {
return () => <Input status={'error'} defaultValue={'hello'} onChange={onChange} />;
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorError', 'colorErrorOutline', 'colorErrorBorder', 'colorErrorHover'],
key: 'danger',
};
export default componentDemo;

View File

@ -0,0 +1,12 @@
import { Input } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <Input placeholder="Basic usage" disabled />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgContainerDisabled'],
key: 'disabled',
};
export default componentDemo;

View File

@ -0,0 +1,12 @@
import Default from './input';
import clearIcon from './clearIcon';
import danger from './danger';
import warning from './warning';
import withAddon from './withAddon';
import disabled from './disabled';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, clearIcon, danger, warning, withAddon, disabled];
export default previewerDemo;

View File

@ -0,0 +1,12 @@
import { Input } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <Input placeholder="Basic usage" />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorPrimary', 'colorPrimaryHover', 'controlOutline', 'colorBgContainer'],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,30 @@
import { defineComponent } from 'vue';
import { Input, theme } from 'ant-design-vue';
import { CheckCircleFilled } from '@ant-design/icons-vue';
import type { ComponentDemo } from '../../interface';
function onChange() {}
const Demo = defineComponent({
setup() {
const { token } = theme.useToken();
return () => {
return (
<Input
defaultValue={"I'm the content"}
suffix={<CheckCircleFilled style={{ color: token.value.colorSuccess }} />}
onChange={onChange}
/>
);
};
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorSuccess'],
key: 'warning',
};
export default componentDemo;

View File

@ -0,0 +1,19 @@
import { defineComponent } from 'vue';
import { Input } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
function onChange() {}
const Demo = defineComponent({
setup() {
return () => <Input status={'warning'} defaultValue={3} onChange={onChange} />;
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorWarning', 'colorWarningBorder', 'colorWarningHover', 'colorWarningOutline'],
key: 'warning',
};
export default componentDemo;

View File

@ -0,0 +1,17 @@
import { defineComponent } from 'vue';
import { Input } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = defineComponent({
setup() {
return () => <Input addonBefore="http://" addonAfter=".com" defaultValue="mysite" />;
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorFillAlter'],
key: 'withAddon',
};
export default componentDemo;

View File

@ -0,0 +1,21 @@
import { defineComponent } from 'vue';
import { InputNumber } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
function onChange() {}
const Demo = defineComponent({
setup() {
return () => (
<InputNumber status={'error'} min={1} max={10} defaultValue={3} onChange={onChange} />
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorErrorBorder', 'colorErrorOutline', 'colorErrorHover', 'colorError'],
key: 'danger',
};
export default componentDemo;

View File

@ -0,0 +1,12 @@
import { InputNumber } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const Demo = () => <InputNumber min={1} max={10} defaultValue={3} disabled />;
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorBgContainerDisabled'],
key: 'disabled',
};
export default componentDemo;

View File

@ -0,0 +1,10 @@
import Default from './inputNumber';
import danger from './danger';
import warning from './warning';
import disabled from './disabled';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default, danger, warning, disabled];
export default previewerDemo;

View File

@ -0,0 +1,24 @@
import { defineComponent } from 'vue';
import { InputNumber } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
function onChange() {}
const Demo = defineComponent({
setup() {
return () => <InputNumber min={1} max={10} defaultValue={3} onChange={onChange} />;
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: [
'colorPrimaryBorder',
'controlOutline',
'colorPrimaryHover',
'colorPrimary',
'colorBgContainer',
],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,21 @@
import { defineComponent } from 'vue';
import { InputNumber } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
function onChange() {}
const Demo = defineComponent({
setup() {
return () => (
<InputNumber status={'warning'} min={1} max={10} defaultValue={3} onChange={onChange} />
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorWarning', 'colorWarningBorder', 'colorWarningOutline', 'colorWarningHover'],
key: 'warning',
};
export default componentDemo;

View File

@ -0,0 +1,7 @@
import Default from './list';
import type { ComponentDemo } from '../../interface';
const previewerDemo: ComponentDemo[] = [Default];
export default previewerDemo;

View File

@ -0,0 +1,41 @@
import { defineComponent } from 'vue';
import { List, ListItem, ListItemMeta, Avatar } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const data = [
{ title: 'Ant Design Vue Title 1' },
{ title: 'Ant Design Vue Title 2' },
{ title: 'Ant Design Vue Title 3' },
{ title: 'Ant Design Vue Title 4' },
];
const Demo = defineComponent({
setup() {
return () => (
<List
itemLayout="horizontal"
dataSource={data}
v-slots={{
renderItem: ({ item }: any) => (
<ListItem>
<ListItemMeta
v-slots={{
avatar: () => <Avatar src="https://joeschmoe.io/api/v1/random" />,
title: () => <a href="https://www.antdv.com">{item.title}</a>,
}}
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
/>
</ListItem>
),
}}
/>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: [],
key: 'default',
};
export default componentDemo;

View File

@ -0,0 +1,43 @@
import { defineComponent } from 'vue';
import { Mentions } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
function onChange() {}
function onSelect() {}
const Demo = defineComponent({
setup() {
const options = [
{
value: 'afc163',
label: 'afc163',
},
{
value: 'zombieJ',
label: 'zombieJ',
},
{
value: 'yesmeck',
label: 'yesmeck',
},
];
return () => (
<Mentions
style={{ width: '100%' }}
onChange={onChange}
onSelect={onSelect}
status={'error'}
defaultValue="@afc163"
options={options}
></Mentions>
);
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorError', 'colorErrorOutline', 'colorErrorBorder', 'colorErrorHover'],
key: 'danger',
};
export default componentDemo;

Some files were not shown because too many files have changed in this diff Show More