Feat v4 theme editor (#6349)

* 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

* add theme editor token drawer

* add theme editor token drawer

* fix bug

* open commment

* fix error demo

* fix theme editor bug
pull/6358/head
果冻橙 2023-03-13 09:54:21 +08:00 committed by GitHub
parent dde2ff140d
commit f819a1b209
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 1920 additions and 1304 deletions

View File

@ -1,5 +1,5 @@
import type { InputProps } from 'ant-design-vue';
import { Input, InputNumber, Select, theme } from 'ant-design-vue';
import { ConfigProvider, 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';
@ -175,7 +175,7 @@ const RgbColorInput = defineComponent({
return () => {
return (
<div class="color-panel-rgba-input">
{/* <ConfigProvider theme={{ components: { InputNumber: { handleWidth: 12 } } }}> */}
<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>
@ -188,7 +188,7 @@ const RgbColorInput = defineComponent({
<InputNumber min={0} max={255} size="small" v-model={[value.value.b, 'value']} />
<div class="color-panel-mode-title">B</div>
</div>
{alpha && (
{alpha.value && (
<div class="color-panel-rgba-input-part">
<InputNumber
min={0}
@ -200,7 +200,7 @@ const RgbColorInput = defineComponent({
<div class="color-panel-mode-title">A</div>
</div>
)}
{/* </ConfigProvider> */}
</ConfigProvider>
</div>
);
};
@ -282,7 +282,7 @@ const ColorPanel = defineComponent({
{(colorMode.value === 'RGBA' || colorMode.value === 'HEX8') && (
<RgbaColorPicker
style={{ height: '160px' }}
color={tinycolor(color).toRgb()}
color={tinycolor(color.value).toRgb()}
onChange={value => {
props.onChange(getColorStr(value, colorMode.value));
}}

View File

@ -0,0 +1,35 @@
import type { CSSProperties, PropType } from 'vue';
import { defineComponent, toRefs } from 'vue';
import { antdComponents } from './component-panel';
import type { Theme } from './interface';
import ComponentDemoPro from './token-panel-pro/ComponentDemoPro';
export type PreviewDemoProps = {
theme: Theme;
};
const PreviewDemo = defineComponent({
name: 'PreviewDemo',
props: {
theme: { type: Object as PropType<Theme> },
},
setup(props, { attrs }) {
const { theme } = toRefs(props);
return () => {
return (
<div {...attrs} style={{ ...(attrs.style as CSSProperties), overflow: 'auto' }}>
<ComponentDemoPro
theme={theme.value}
components={antdComponents}
componentDrawer={false}
showAll
style={{ minHeight: '100%' }}
/>
</div>
);
};
},
});
export default PreviewDemo;

View File

@ -0,0 +1,240 @@
import type { PropType } from 'vue';
import { defineComponent, toRefs, computed } from 'vue';
import makeStyle from './utils/makeStyle';
import classNames from 'ant-design-vue/es/_util/classNames';
import { Button, Dropdown, Menu } from 'ant-design-vue';
import { CloseOutlined, PlusOutlined } from '@ant-design/icons-vue';
import type { Theme } from './interface';
interface ThemeItem extends Theme {
icon?: any;
closable?: boolean;
fixed?: boolean;
}
export type ThemeSelectProps = {
onEnabledThemeChange: (themes: string[]) => void;
onShownThemeChange: (
themes: string[],
selectTheme: string,
info: { type: 'select' | 'deselect' },
) => void;
enabledThemes: string[];
shownThemes: string[];
themes: ThemeItem[];
showAddTheme?: boolean;
};
const useStyle = makeStyle('ThemeSelect', token => ({
'.previewer-theme-select': {
padding: `${token.paddingXXS}px ${token.paddingXS}px`,
borderRadius: 4,
backgroundColor: 'rgba(0, 0, 0, 0.02)',
height: token.controlHeight,
display: 'flex',
alignItems: 'center',
overflow: 'hidden',
[`${token.rootCls}-btn.previewer-theme-select-add-btn`]: {
minWidth: 0,
width: 16,
height: 16,
fontSize: 8,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
marginInlineStart: token.marginSM,
boxShadow: 'none',
},
'.previewer-theme-select-tag': {
height: 22,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
boxSizing: 'border-box',
borderRadius: 4,
backgroundColor: token.colorBgContainer,
border: `${token.lineWidth}px ${token.lineType} ${token.colorBorder}`,
paddingInline: 10,
fontSize: token.fontSizeSM,
position: 'relative',
cursor: 'pointer',
// transition: `all ${token.motionDurationMid}`,
'&:not(:last-child)': {
marginInlineEnd: token.marginXS,
},
'&.previewer-theme-select-tag-active': {
border: `${token.lineWidth}px ${token.lineType} ${token['blue-1']}`,
backgroundColor: 'rgba(22,119,255,0.10)',
color: token.colorPrimary,
'&::after': {
content: '""',
borderStartEndRadius: 2,
position: 'absolute',
insetInlineEnd: 2,
top: 2,
width: 6,
height: 6,
background: `linear-gradient(to right top, transparent, transparent 50%, ${token.colorPrimary} 50%, ${token.colorPrimary} 100%)`,
},
},
'.previewer-theme-select-tag-close-btn': {
position: 'absolute',
top: -2,
insetInlineEnd: -2,
width: 12,
height: 12,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: token.colorBgContainer,
boxShadow:
'0 2px 8px -2px rgba(0,0,0,0.05), 0 1px 4px -1px rgba(25,15,15,0.07), 0 0 1px 0 rgba(0,0,0,0.08)',
borderRadius: '50%',
opacity: 0,
pointerEvents: 'none',
zIndex: 2,
color: token.colorIcon,
'> .anticon': {
fontSize: 6,
},
},
'&:hover': {
'.previewer-theme-select-tag-close-btn': {
opacity: 1,
pointerEvents: 'initial',
},
},
},
},
'.previewer-theme-select-dropdown': {
'.previewer-theme-select-dropdown-title': {
[`${token.rootCls}-dropdown-menu-item-group-title`]: {
fontSize: token.fontSizeSM,
paddingBottom: token.padding,
paddingTop: 10,
},
},
},
}));
const ThemeSelect = defineComponent({
name: 'ThemeSelect',
inheritAttrs: false,
props: {
onEnabledThemeChange: { type: Function as PropType<(themes: string[]) => void> },
onShownThemeChange: {
type: Function as PropType<
(themes: string[], selectTheme: string, info: { type: 'select' | 'deselect' }) => void
>,
},
enabledThemes: { type: Array as PropType<string[]> },
shownThemes: { type: Array as PropType<string[]> },
themes: { type: Array as PropType<ThemeItem[]> },
showAddTheme: { type: Boolean },
},
setup(props, { attrs }) {
const { enabledThemes, shownThemes, themes, showAddTheme } = toRefs(props);
const [wrapSSR, hashId] = useStyle();
const dropdownItems = computed(() => [
{
disabled: true,
label: '添加主题即可预览',
className: 'previewer-theme-select-dropdown-title',
type: 'group',
key: 'add-theme-to-preview',
},
...themes.value
.filter(theme => !shownThemes.value.includes(theme.key))
.map(theme => ({
icon: theme.icon,
value: theme.key,
label: theme.name,
key: theme.key,
onClick: () => {
props.onShownThemeChange([...shownThemes.value, theme.key], theme.key, {
type: 'select',
});
},
})),
]);
const shownThemeEntities = computed(() =>
themes.value.filter(theme => shownThemes.value.includes(theme.key)),
);
return () => {
return wrapSSR(
<div {...attrs} class={classNames('previewer-theme-select', hashId.value, attrs.class)}>
{shownThemeEntities.value.map(theme => (
<span
onClick={() => {
if (theme.fixed) {
return;
}
props.onEnabledThemeChange(
enabledThemes.value.includes(theme.key)
? enabledThemes.value.filter(item => item !== theme.key)
: [...enabledThemes.value, theme.key],
);
}}
key={theme.key}
class={classNames('previewer-theme-select-tag', {
'previewer-theme-select-tag-active': enabledThemes.value.includes(theme.key),
})}
>
{theme.name}
{theme.closable && (
<span
class="previewer-theme-select-tag-close-btn"
onClick={e => {
e.stopPropagation();
props.onEnabledThemeChange(
enabledThemes.value.filter(item => item !== theme.key),
);
props.onShownThemeChange(
shownThemes.value.filter(item => item !== theme.key),
theme.key,
{ type: 'deselect' },
);
}}
>
<CloseOutlined />
</span>
)}
</span>
))}
{showAddTheme.value && (
<Dropdown
placement="bottomRight"
trigger={['click']}
overlayClassName={classNames('previewer-theme-select-dropdown', hashId.value)}
v-slots={{
overlay: () => <Menu items={dropdownItems.value} />,
}}
>
<Button
type="primary"
shape="circle"
class="previewer-theme-select-add-btn"
icon={<PlusOutlined />}
/>
</Dropdown>
)}
</div>,
);
};
},
});
export default ThemeSelect;

View File

@ -1,4 +1,4 @@
import { Button, Dropdown, Input, InputNumber } from 'ant-design-vue';
import { Button, Popover, 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';
@ -171,17 +171,23 @@ const TokenInput = defineComponent({
value={String(tokenValue.value)}
disabled={readonly.value}
addonBefore={
<Dropdown
trigger={['click']}
overlay={
<Popover
trigger="click"
placement="bottomRight"
arrow-point-at-center
overlayInnerStyle={{ padding: 0 }}
v-slots={{
content: () => (
<ColorPanel
alpha
color={String(tokenValue.value)}
style={{ border: 'none' }}
onChange={(v: string) => {
handleTokenChange(v);
}}
/>
}
),
}}
>
<ColorPreview
color={String(tokenValue.value)}
@ -192,7 +198,7 @@ const TokenInput = defineComponent({
verticalAlign: 'top',
}}
/>
</Dropdown>
</Popover>
}
onChange={e => {
handleTokenChange(e.target.value);

View File

@ -8,7 +8,7 @@ const text = ` A dog is a type of domesticated animal. Known for its loyalty a
const Demo = defineComponent({
setup() {
return () => (
<Collapse defaultActiveKey={['1']}>
<Collapse activeKey={['1']}>
<Panel header="This is panel header 1" key="1">
<p>{text}</p>
</Panel>

View File

@ -1,17 +1,14 @@
import { defineComponent } from 'vue';
import { message } from 'ant-design-vue';
import { message, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = message;
const Demo = defineComponent({
setup() {
return () => (
<_InternalPanelDoNotUseOrYouWillBeFired
type={'error'}
content={'这是一条异常消息,会主动消失'}
/>
);
const error = () => {
message.error('This is an error message');
};
return () => <Button onClick={error}>Error</Button>;
},
});

View File

@ -1,15 +1,16 @@
import { defineComponent } from 'vue';
import { message } from 'ant-design-vue';
import { message, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = message;
const Demo = defineComponent({
setup() {
return () => <_InternalPanelDoNotUseOrYouWillBeFired type={'info'} content={'Info'} />;
const info = () => {
message.info('This is an info message');
};
return () => <Button onClick={info}>Info</Button>;
},
});
const componentDemo: ComponentDemo = {
demo: <Demo />,
tokens: ['colorInfo'],

View File

@ -1,15 +1,14 @@
import { defineComponent } from 'vue';
import { message } from 'ant-design-vue';
import { message, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = message;
const Demo = defineComponent({
setup() {
return () => (
<_InternalPanelDoNotUseOrYouWillBeFired type={'info'} content={`Hello, Ant Design!`} />
);
const info = () => {
message.info('Hello, Ant Design Vue!');
};
return () => <Button onClick={info}>Info</Button>;
},
});

View File

@ -1,17 +1,14 @@
import { defineComponent } from 'vue';
import { message } from 'ant-design-vue';
import { message, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = message;
const Demo = defineComponent({
setup() {
return () => (
<_InternalPanelDoNotUseOrYouWillBeFired
type={'success'}
content={'这是一条成功消息,会主动消失'}
/>
);
const success = () => {
message.success('This is an success message');
};
return () => <Button onClick={success}>Success</Button>;
},
});

View File

@ -1,17 +1,14 @@
import { defineComponent } from 'vue';
import { message } from 'ant-design-vue';
import { message, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = message;
const Demo = defineComponent({
setup() {
return () => (
<_InternalPanelDoNotUseOrYouWillBeFired
type={'warning'}
content={'这是一条警告消息,会主动消失'}
/>
);
const warning = () => {
message.warning('This is an warning message');
};
return () => <Button onClick={warning}>Warning</Button>;
},
});

View File

@ -1,20 +1,18 @@
import { defineComponent } from 'vue';
import { notification } from 'ant-design-vue';
import { notification, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = notification;
const Demo = defineComponent({
setup() {
return () => (
<_InternalPanelDoNotUseOrYouWillBeFired
message={'Notification Title'}
type={'error'}
description={
'This is the content of the notification. This is the content of the notification. This is the content of the notification.'
}
/>
);
const error = () => {
notification.error({
message: 'Notification Title',
description:
'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
});
};
return () => <Button onClick={error}>Error</Button>;
},
});

View File

@ -1,20 +1,18 @@
import { defineComponent } from 'vue';
import { notification } from 'ant-design-vue';
import { notification, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = notification;
const Demo = defineComponent({
setup() {
return () => (
<_InternalPanelDoNotUseOrYouWillBeFired
message={'Notification Title'}
type={'info'}
description={
'This is the content of the notification. This is the content of the notification. This is the content of the notification.'
}
/>
);
const info = () => {
notification.info({
message: 'Notification Title',
description:
'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
});
};
return () => <Button onClick={info}>Info</Button>;
},
});

View File

@ -1,19 +1,18 @@
import { defineComponent } from 'vue';
import { notification } from 'ant-design-vue';
import { notification, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = notification;
const Demo = defineComponent({
setup() {
return () => (
<_InternalPanelDoNotUseOrYouWillBeFired
message={'Notification Title'}
description={
'This is the content of the notification. This is the content of the notification. This is the content of the notification.'
}
/>
);
const open = () => {
notification.open({
message: 'Notification Title',
description:
'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
});
};
return () => <Button onClick={open}>Open</Button>;
},
});

View File

@ -1,20 +1,18 @@
import { defineComponent } from 'vue';
import { notification } from 'ant-design-vue';
import { notification, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = notification;
const Demo = defineComponent({
setup() {
return () => (
<_InternalPanelDoNotUseOrYouWillBeFired
message={'Notification Title'}
type={'success'}
description={
'This is the content of the notification. This is the content of the notification. This is the content of the notification.'
}
/>
);
const success = () => {
notification.success({
message: 'Notification Title',
description:
'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
});
};
return () => <Button onClick={success}>Success</Button>;
},
});

View File

@ -1,20 +1,18 @@
import { defineComponent } from 'vue';
import { notification } from 'ant-design-vue';
import { notification, Button } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
const { _InternalPanelDoNotUseOrYouWillBeFired } = notification;
const Demo = defineComponent({
setup() {
return () => (
<_InternalPanelDoNotUseOrYouWillBeFired
message={'Notification Title'}
type={'warning'}
description={
'This is the content of the notification. This is the content of the notification. This is the content of the notification.'
}
/>
);
const warning = () => {
notification.warning({
message: 'Notification Title',
description:
'This is the content of the notification. This is the content of the notification. This is the content of the notification.',
});
};
return () => <Button onClick={warning}>Warning</Button>;
},
});

View File

@ -1,4 +1,4 @@
import { defineComponent, ref } from 'vue';
import { defineComponent } from 'vue';
import { Popconfirm, message } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';
@ -10,8 +10,6 @@ function cancel() {
}
const Demo = defineComponent({
setup() {
const open = ref(true);
return () => (
<div
style={{
@ -28,7 +26,6 @@ const Demo = defineComponent({
placement={'topLeft'}
getPopupContainer={node => {
if (node) {
console.log(node.parentNode);
return node.parentNode as HTMLElement;
}
return document.body;

View File

@ -1,4 +1,3 @@
import { defineComponent } from 'vue';
import { Progress, Space } from 'ant-design-vue';
import type { ComponentDemo } from '../../interface';

View File

@ -6,7 +6,7 @@ import classNames from 'ant-design-vue/es/_util/classNames';
import ComponentDemos from '../component-demos';
import type { AliasToken, ComponentDemo, MutableTheme, TokenName, TokenValue } from '../interface';
import { useInjectLocaleContext } from '../locale';
// import TokenCard from '../token-panel/token-card';
import TokenCard from '../token-panel/token-card';
import getDesignToken from '../utils/getDesignToken';
import makeStyle from '../utils/makeStyle';
import { getComponentToken } from '../utils/statistic';
@ -124,7 +124,7 @@ const ComponentTokenDrawer = defineComponent({
const componentTokenData = computed(() => Object.keys(componentToken.value ?? {}));
const aliasTokenData = computed(() => {
return aliasTokenNames.value.sort();
return aliasTokenNames.sort();
});
const handleComponentTokenChange = (token: string, value: TokenValue) => {
@ -165,17 +165,19 @@ const ComponentTokenDrawer = defineComponent({
<ComponentFullDemos demos={ComponentDemos[component.value]} />
</ConfigProvider>
</ConfigProvider>
<div style={{ flex: '0 0 400px', overflow: 'auto', padding: 24 }}>
<div
style={{ flex: '0 0 400px', overflow: 'auto', overflowX: 'hidden', padding: '24px' }}
>
<div class="previewer-component-drawer-subtitle">Related Tokens / 相关 token</div>
{/* <TokenCard
<TokenCard
icon={<BuildOutlined />}
hideUsageCount
defaultOpen
title="Component Token"
tokenArr={componentTokenData}
tokenPath={['components', component]}
themes={[theme]}
fallback={() => componentToken}
tokenArr={componentTokenData.value}
tokenPath={['components', component.value]}
themes={[theme.value]}
fallback={() => componentToken.value}
onTokenChange={(_, tokenName, value) =>
handleComponentTokenChange(tokenName, value)
}
@ -185,7 +187,7 @@ const ComponentTokenDrawer = defineComponent({
description="暂无相关 Component Token"
style={{
marginBlock: 0,
paddingBlock: 32,
paddingBlock: '32px',
}}
/>
}
@ -193,11 +195,11 @@ const ComponentTokenDrawer = defineComponent({
<TokenCard
icon={<CarOutlined />}
hideUsageCount
themes={[theme]}
themes={[theme.value]}
defaultOpen
title="Alias Token"
tokenArr={aliasTokenData}
tokenPath={['components', component]}
tokenArr={aliasTokenData.value}
tokenPath={['components', component.value]}
fallback={themeConfig => getDesignToken(themeConfig) as AliasToken}
onTokenChange={(_, tokenName, value) =>
handleComponentTokenChange(tokenName, value)
@ -208,11 +210,11 @@ const ComponentTokenDrawer = defineComponent({
description="暂无相关 Alias Token"
style={{
marginBlock: 0,
paddingBlock: 32,
paddingBlock: '32px',
}}
/>
}
/> */}
/>
</div>
</div>
</Drawer>
@ -232,14 +234,14 @@ export default defineComponent({
},
setup(props, { attrs }) {
return () => (
// <ConfigProvider
// theme={{
// algorithm: defaultAlgorithm,
// ...props.theme,
// }}
// >
<ConfigProvider
theme={{
algorithm: defaultAlgorithm,
...props.theme,
}}
>
<ComponentTokenDrawer {...props} {...attrs} />
// </ConfigProvider>
</ConfigProvider>
);
},
});

View File

@ -1,81 +0,0 @@
import { createVNode } from 'vue';
function Arrow(props) {
return /*#__PURE__*/ React.createElement(
'svg',
Object.assign(
{
width: '1em',
height: '1em',
viewBox: '0 0 16 16',
xmlns: 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink',
},
props,
{
style: Object.assign(
{
verticalAlign: '-0.125em',
},
props.style,
),
className: ['nanqu-token-panel-icon', props.className].filter(Boolean).join(' '),
},
),
/*#__PURE__*/ React.createElement(
'g',
{
id: 'Arrow-\u9875\u9762-1',
stroke: 'none',
strokeWidth: 1,
fill: 'none',
fillRule: 'evenodd',
},
/*#__PURE__*/ React.createElement(
'g',
{
id: 'Arrow-\u4E3B\u9898\u9884\u89C8\u5668---\u7EC4\u4EF6\u9884\u89C8',
transform: 'translate(-335.000000, -153.000000)',
fill: 'currentColor',
fillRule: 'nonzero',
},
/*#__PURE__*/ React.createElement(
'g',
{
id: 'Arrow-\u7F16\u7EC4-18',
transform: 'translate(0.000000, 70.000000)',
},
/*#__PURE__*/ React.createElement(
'g',
{
id: 'Arrow-\u7F16\u7EC4-13',
transform: 'translate(331.000000, 79.000000)',
},
/*#__PURE__*/ React.createElement(
'g',
{
id: 'Arrow-\u6298\u53E0\u7BAD\u5934_Black@2x',
transform:
'translate(12.000000, 12.000000) rotate(90.000000) translate(-12.000000, -12.000000) translate(4.000000, 4.000000)',
},
/*#__PURE__*/ React.createElement('rect', {
id: 'Arrow-\u77E9\u5F62',
opacity: 0,
x: 0,
y: 0,
width: 16,
height: 16,
}),
/*#__PURE__*/ React.createElement('path', {
d: 'M8.576,10.6224 C8.46400007,10.7357654 8.31136002,10.7997014 8.152,10.8 L7.848,10.8 C7.68897547,10.7980619 7.53693306,10.7343763 7.424,10.6224 L3.3184,6.4672 C3.16044703,6.30862179 3.16044703,6.05217821 3.3184,5.8936 L3.8864,5.3192 C3.95991079,5.24354153 4.06091047,5.20085176 4.1664,5.20085176 C4.27188953,5.20085176 4.37288921,5.24354153 4.4464,5.3192 L8,8.9168 L11.5536,5.3192 C11.6284927,5.24307539 11.7308111,5.20020394 11.8376,5.20020394 C11.9443889,5.20020394 12.0467073,5.24307539 12.1216,5.3192 L12.6816,5.8936 C12.839553,6.05217821 12.839553,6.30862179 12.6816,6.4672 L8.576,10.6224 Z',
id: 'Arrow-\u8DEF\u5F84',
}),
),
),
),
),
),
);
}
export default Arrow;

View File

@ -0,0 +1,67 @@
import type { CSSProperties } from 'vue';
import { defineComponent } from 'vue';
const Arrow = defineComponent({
name: 'Arrow',
props: {
rotate: { type: Number },
},
setup(props, { attrs }) {
return () => {
return (
<svg
{...attrs}
width="1em"
height="1em"
style={{
verticalAlign: '-0.125em',
transform: `rotate(${props.rotate})`,
...(attrs.style as CSSProperties),
}}
class={['nanqu-token-panel-icon', attrs.class].filter(Boolean).join(' ')}
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
<g
id="Arrow-\u9875\u9762-1"
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
>
<g
id="Arrow-\u4E3B\u9898\u9884\u89C8\u5668---\u7EC4\u4EF6\u9884\u89C8"
transform="translate(-335.000000, -153.000000)"
fill="currentColor"
fill-rule="nonzero"
>
<g id="Arrow-\u7F16\u7EC4-18" transform="translate(0.000000, 70.000000)">
<g id="Arrow-\u7F16\u7EC4-13" transform="translate(331.000000, 79.000000)">
<g
id="Arrow-\u6298\u53E0\u7BAD\u5934_Black@2x"
transform="translate(12.000000, 12.000000) rotate(90.000000) translate(-12.000000, -12.000000) translate(4.000000, 4.000000)"
>
<rect
id="Arrow-\u77E9\u5F62"
opacity="0"
x="0"
y="0"
width="16"
height="16"
></rect>
<path
d="M8.576,10.6224 C8.46400007,10.7357654 8.31136002,10.7997014 8.152,10.8 L7.848,10.8 C7.68897547,10.7980619 7.53693306,10.7343763 7.424,10.6224 L3.3184,6.4672 C3.16044703,6.30862179 3.16044703,6.05217821 3.3184,5.8936 L3.8864,5.3192 C3.95991079,5.24354153 4.06091047,5.20085176 4.1664,5.20085176 C4.27188953,5.20085176 4.37288921,5.24354153 4.4464,5.3192 L8,8.9168 L11.5536,5.3192 C11.6284927,5.24307539 11.7308111,5.20020394 11.8376,5.20020394 C11.9443889,5.20020394 12.0467073,5.24307539 12.1216,5.3192 L12.6816,5.8936 C12.839553,6.05217821 12.839553,6.30862179 12.6816,6.4672 L8.576,10.6224 Z"
id="Arrow-\u8DEF\u5F84"
></path>
</g>
</g>
</g>
</g>
</g>
</svg>
);
};
},
});
export default Arrow;

View File

@ -1,59 +0,0 @@
import { createVNode } from 'vue';
function Brush(props) {
return /*#__PURE__*/ createVNode(
'svg',
Object.assign(
{
width: '1em',
height: '1em',
viewBox: '0 0 14 18',
xmlns: 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink',
},
props,
{
style: Object.assign(
{
verticalAlign: '-0.125em',
},
props.style,
),
className: ['nanqu-token-panel-icon', props.className].filter(Boolean).join(' '),
},
),
/*#__PURE__*/ createVNode(
'g',
{
id: 'Brush-\u9875\u9762-1',
stroke: 'none',
strokeWidth: 1,
fill: 'none',
fillRule: 'evenodd',
fillOpacity: 0.649999976,
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'Brush-\u4E3B\u9898\u7F16\u8F91\u5668---\u591A\u4E3B\u9898',
transform: 'translate(-17.000000, -121.000000)',
fill: 'currentColor',
fillRule: 'nonzero',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'Brush-brush',
transform: 'translate(14.000000, 120.000000)',
},
/*#__PURE__*/ createVNode('path', {
d: 'M8.20652175,3.2826087 L8.20652175,4.10326086 C8.20652175,4.55649455 7.83910325,4.92391304 7.38586957,4.92391304 C6.93263588,4.92391304 6.56521738,4.55649455 6.56521738,4.10326086 L6.56521738,3.2826087 L4.92391304,3.2826087 L4.92391304,8.20652175 L14.7717391,8.20652175 L14.7717391,3.2826087 L13.1304348,3.2826087 L13.1304348,5.74456522 C13.1304348,6.19779891 12.7630163,6.5652174 12.3097826,6.5652174 C11.8565489,6.5652174 11.4891304,6.19779891 11.4891304,5.74456522 L11.4891304,3.2826087 L8.20652175,3.2826087 Z M4.92391304,9.84782609 L4.92391304,11.4891304 L7.72233695,11.4891304 C8.08431263,11.4890155 8.42799204,11.6482243 8.66197039,11.9244136 C8.89594874,12.2006029 8.99650752,12.5657753 8.93690217,12.9228098 L8.60043479,14.9399728 C8.51784643,15.435105 8.73592476,15.9322123 9.15616576,16.2067558 C9.57640676,16.4812994 10.1192454,16.4812994 10.5394864,16.2067558 C10.9597274,15.9322123 11.1778057,15.435105 11.0952174,14.9399728 L10.75875,12.9228098 C10.6991446,12.5657753 10.7997034,12.2006029 11.0336818,11.9244136 C11.2676601,11.6482243 11.6113395,11.4890155 11.9733152,11.4891304 L14.7717391,11.4891304 L14.7717391,9.84782609 L4.92391304,9.84782609 Z M12.7143641,14.6699783 C12.9035912,15.807501 12.4022968,16.9492894 11.4368082,17.5798421 C10.4713197,18.2103948 9.2243325,18.2103948 8.25884395,17.5798421 C7.2933554,16.9492894 6.79206095,15.807501 6.98128804,14.6699783 L7.23815217,13.1304348 L4.92391304,13.1304348 C4.48861206,13.1304348 4.07113988,12.9575121 3.76333561,12.6497079 C3.45553133,12.3419036 3.2826087,11.9244314 3.2826087,11.4891304 L3.2826087,3.2826087 C3.2826087,2.84730772 3.45553133,2.42983554 3.76333561,2.12203126 C4.07113988,1.81422698 4.48861206,1.64130434 4.92391304,1.64130434 L14.7717391,1.64130434 C15.2070401,1.64130434 15.6245123,1.81422698 15.9323166,2.12203126 C16.2401208,2.42983554 16.4130435,2.84730772 16.4130435,3.2826087 L16.4130435,11.4891304 C16.4130435,11.9244314 16.2401208,12.3419036 15.9323166,12.6497079 C15.6245123,12.9575121 15.2070401,13.1304348 14.7717391,13.1304348 L12.4575,13.1304348 L12.7143641,14.6699783 L12.7143641,14.6699783 Z',
id: 'Brush-\u5F62\u72B6',
}),
),
),
),
);
}
export default Brush;

View File

@ -0,0 +1,49 @@
import type { CSSProperties } from 'vue';
import { defineComponent } from 'vue';
const Brush = defineComponent({
name: 'Brush',
setup(_, { attrs }) {
return () => {
return (
<svg
{...attrs}
width="1em"
height="1em"
style={{
verticalAlign: '-0.125em',
...(attrs.style as CSSProperties),
}}
class={['nanqu-token-panel-icon', attrs.class].filter(Boolean).join(' ')}
viewBox="0 0 14 18"
xmlns="http://www.w3.org/2000/svg"
>
<g
id="Brush-\u9875\u9762-1"
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
fill-opacity="0.649999976"
>
<g
id="Brush-\u4E3B\u9898\u7F16\u8F91\u5668---\u591A\u4E3B\u9898"
transform="translate(-17.000000, -121.000000)"
fill="currentColor"
fill-rule="nonzero"
>
<g id="Brush-brush" transform="translate(14.000000, 120.000000)">
<path
d="M8.20652175,3.2826087 L8.20652175,4.10326086 C8.20652175,4.55649455 7.83910325,4.92391304 7.38586957,4.92391304 C6.93263588,4.92391304 6.56521738,4.55649455 6.56521738,4.10326086 L6.56521738,3.2826087 L4.92391304,3.2826087 L4.92391304,8.20652175 L14.7717391,8.20652175 L14.7717391,3.2826087 L13.1304348,3.2826087 L13.1304348,5.74456522 C13.1304348,6.19779891 12.7630163,6.5652174 12.3097826,6.5652174 C11.8565489,6.5652174 11.4891304,6.19779891 11.4891304,5.74456522 L11.4891304,3.2826087 L8.20652175,3.2826087 Z M4.92391304,9.84782609 L4.92391304,11.4891304 L7.72233695,11.4891304 C8.08431263,11.4890155 8.42799204,11.6482243 8.66197039,11.9244136 C8.89594874,12.2006029 8.99650752,12.5657753 8.93690217,12.9228098 L8.60043479,14.9399728 C8.51784643,15.435105 8.73592476,15.9322123 9.15616576,16.2067558 C9.57640676,16.4812994 10.1192454,16.4812994 10.5394864,16.2067558 C10.9597274,15.9322123 11.1778057,15.435105 11.0952174,14.9399728 L10.75875,12.9228098 C10.6991446,12.5657753 10.7997034,12.2006029 11.0336818,11.9244136 C11.2676601,11.6482243 11.6113395,11.4890155 11.9733152,11.4891304 L14.7717391,11.4891304 L14.7717391,9.84782609 L4.92391304,9.84782609 Z M12.7143641,14.6699783 C12.9035912,15.807501 12.4022968,16.9492894 11.4368082,17.5798421 C10.4713197,18.2103948 9.2243325,18.2103948 8.25884395,17.5798421 C7.2933554,16.9492894 6.79206095,15.807501 6.98128804,14.6699783 L7.23815217,13.1304348 L4.92391304,13.1304348 C4.48861206,13.1304348 4.07113988,12.9575121 3.76333561,12.6497079 C3.45553133,12.3419036 3.2826087,11.9244314 3.2826087,11.4891304 L3.2826087,3.2826087 C3.2826087,2.84730772 3.45553133,2.42983554 3.76333561,2.12203126 C4.07113988,1.81422698 4.48861206,1.64130434 4.92391304,1.64130434 L14.7717391,1.64130434 C15.2070401,1.64130434 15.6245123,1.81422698 15.9323166,2.12203126 C16.2401208,2.42983554 16.4130435,2.84730772 16.4130435,3.2826087 L16.4130435,11.4891304 C16.4130435,11.9244314 16.2401208,12.3419036 15.9323166,12.6497079 C15.6245123,12.9575121 15.2070401,13.1304348 14.7717391,13.1304348 L12.4575,13.1304348 L12.7143641,14.6699783 L12.7143641,14.6699783 Z"
id="Brush-\u5F62\u72B6"
></path>
</g>
</g>
</g>
</svg>
);
};
},
});
export default Brush;

View File

@ -3,7 +3,6 @@ import { defineComponent } from 'vue';
const Compact = defineComponent({
name: 'Compact',
emits: ['click'],
setup(_, { attrs }) {
return () => {
return (

View File

@ -3,7 +3,6 @@ import { defineComponent } from 'vue';
const Control = defineComponent({
name: 'Control',
emits: ['click'],
setup(_, { attrs }) {
return () => {
return (

View File

@ -3,7 +3,6 @@ import { defineComponent } from 'vue';
const Dark = defineComponent({
name: 'Dark',
emits: ['click'],
setup(_, { attrs }) {
return () => {
return (

View File

@ -3,7 +3,6 @@ import { defineComponent } from 'vue';
const Light = defineComponent({
name: 'Light',
emits: ['click'],
setup(_, { attrs }) {
return () => {
return (

View File

@ -1,59 +0,0 @@
import { createVNode } from 'vue';
function Margin(props) {
return /*#__PURE__*/ createVNode(
'svg',
Object.assign(
{
width: '1em',
height: '1em',
viewBox: '0 0 16 17',
xmlns: 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink',
},
props,
{
style: Object.assign(
{
verticalAlign: '-0.125em',
},
props.style,
),
className: ['nanqu-token-panel-icon', props.className].filter(Boolean).join(' '),
},
),
/*#__PURE__*/ createVNode(
'g',
{
id: 'Margin-\u9875\u9762-1',
stroke: 'none',
strokeWidth: 1,
fill: 'none',
fillRule: 'evenodd',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'Margin-margin',
transform: 'translate(0.000000, 0.942377)',
fill: 'currentColor',
fillRule: 'nonzero',
},
/*#__PURE__*/ createVNode('rect', {
id: 'Margin-\u77E9\u5F62',
opacity: 0,
x: 0,
y: 0,
width: 16,
height: 15.9807923,
}),
/*#__PURE__*/ createVNode('path', {
d: 'M11.6666667,2.75858915 L4.33333333,2.75858915 C4.01904762,2.75858915 3.80952382,2.54931688 3.80952382,2.23540845 C3.80952382,1.92150003 4.01904763,1.71222775 4.33333334,1.71222775 L11.6666667,1.71222775 C11.9809524,1.71222775 12.1904762,1.92150003 12.1904762,2.23540845 C12.1904762,2.54931688 11.9809524,2.75858915 11.6666667,2.75858915 Z M11.6666667,14.2685646 L4.33333333,14.2685646 C4.01904762,14.2685646 3.8095238,14.0592923 3.8095238,13.7453839 C3.8095238,13.4314755 4.01904762,13.2222032 4.33333333,13.2222032 L11.6666667,13.2222032 C11.9809524,13.2222032 12.1904762,13.4314755 12.1904762,13.7453839 C12.1904762,14.0592923 11.9809524,14.2685646 11.6666667,14.2685646 Z M13.7619048,12.1758418 C13.447619,12.1758418 13.2380952,11.9665695 13.2380952,11.6526611 L13.2380952,4.32813125 C13.2380952,4.01422283 13.4476191,3.80495055 13.7619048,3.80495055 C14.0761905,3.80495055 14.2857143,4.01422283 14.2857143,4.32813125 L14.2857143,11.6526611 C14.2857143,11.9665695 14.0761905,12.1758418 13.7619048,12.1758418 Z M2.23809524,12.1758418 C1.92380953,12.1758418 1.71428572,11.9665695 1.71428572,11.6526611 L1.71428572,4.32813125 C1.71428572,4.01422283 1.92380953,3.80495055 2.23809524,3.80495055 C2.55238096,3.80495055 2.76190477,4.01422283 2.76190477,4.32813125 L2.76190477,11.6526611 C2.76190477,11.9665695 2.55238096,12.1758418 2.23809524,12.1758418 Z M11.6666667,12.1758418 L4.33333333,12.1758418 C4.01904762,12.1758418 3.8095238,11.9665695 3.8095238,11.6526611 L3.8095238,4.32813125 C3.8095238,4.01422283 4.01904763,3.80495055 4.33333334,3.80495055 L11.6666667,3.80495055 C11.9809524,3.80495055 12.1904762,4.01422283 12.1904762,4.32813125 L12.1904762,11.6526611 C12.1904762,11.9665695 11.9809524,12.1758418 11.6666667,12.1758418 Z M4.85714286,11.1294804 L11.1428571,11.1294804 L11.1428571,4.85131196 L4.85714286,4.85131196 L4.85714286,11.1294804 Z',
id: 'Margin-\u5F62\u72B6',
}),
),
),
);
}
export default Margin;

View File

@ -0,0 +1,54 @@
import type { CSSProperties } from 'vue';
import { defineComponent } from 'vue';
const Margin = defineComponent({
name: 'Margin',
setup(_, { attrs }) {
return () => {
return (
<svg
{...attrs}
width="1em"
height="1em"
style={{
verticalAlign: '-0.125em',
...(attrs.style as CSSProperties),
}}
class={['nanqu-token-panel-icon', attrs.class].filter(Boolean).join(' ')}
viewBox="0 0 16 17"
xmlns="http://www.w3.org/2000/svg"
>
<g
id="Margin-\u9875\u9762-1"
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
>
<g
id="Margin-margin"
transform="translate(0.000000, 0.942377)"
fill="currentColor"
fill-rule="nonzero"
>
<rect
id="Margin-\u77E9\u5F62"
opacity="0"
x="0"
y="0"
width="16"
height="15.9807923"
></rect>
<path
d="M11.6666667,2.75858915 L4.33333333,2.75858915 C4.01904762,2.75858915 3.80952382,2.54931688 3.80952382,2.23540845 C3.80952382,1.92150003 4.01904763,1.71222775 4.33333334,1.71222775 L11.6666667,1.71222775 C11.9809524,1.71222775 12.1904762,1.92150003 12.1904762,2.23540845 C12.1904762,2.54931688 11.9809524,2.75858915 11.6666667,2.75858915 Z M11.6666667,14.2685646 L4.33333333,14.2685646 C4.01904762,14.2685646 3.8095238,14.0592923 3.8095238,13.7453839 C3.8095238,13.4314755 4.01904762,13.2222032 4.33333333,13.2222032 L11.6666667,13.2222032 C11.9809524,13.2222032 12.1904762,13.4314755 12.1904762,13.7453839 C12.1904762,14.0592923 11.9809524,14.2685646 11.6666667,14.2685646 Z M13.7619048,12.1758418 C13.447619,12.1758418 13.2380952,11.9665695 13.2380952,11.6526611 L13.2380952,4.32813125 C13.2380952,4.01422283 13.4476191,3.80495055 13.7619048,3.80495055 C14.0761905,3.80495055 14.2857143,4.01422283 14.2857143,4.32813125 L14.2857143,11.6526611 C14.2857143,11.9665695 14.0761905,12.1758418 13.7619048,12.1758418 Z M2.23809524,12.1758418 C1.92380953,12.1758418 1.71428572,11.9665695 1.71428572,11.6526611 L1.71428572,4.32813125 C1.71428572,4.01422283 1.92380953,3.80495055 2.23809524,3.80495055 C2.55238096,3.80495055 2.76190477,4.01422283 2.76190477,4.32813125 L2.76190477,11.6526611 C2.76190477,11.9665695 2.55238096,12.1758418 2.23809524,12.1758418 Z M11.6666667,12.1758418 L4.33333333,12.1758418 C4.01904762,12.1758418 3.8095238,11.9665695 3.8095238,11.6526611 L3.8095238,4.32813125 C3.8095238,4.01422283 4.01904763,3.80495055 4.33333334,3.80495055 L11.6666667,3.80495055 C11.9809524,3.80495055 12.1904762,4.01422283 12.1904762,4.32813125 L12.1904762,11.6526611 C12.1904762,11.9665695 11.9809524,12.1758418 11.6666667,12.1758418 Z M4.85714286,11.1294804 L11.1428571,11.1294804 L11.1428571,4.85131196 L4.85714286,4.85131196 L4.85714286,11.1294804 Z"
id="Margin-\u5F62\u72B6"
></path>
</g>
</g>
</svg>
);
};
},
});
export default Margin;

View File

@ -1,59 +0,0 @@
import { createVNode } from 'vue';
function Motion(props) {
return /*#__PURE__*/ createVNode(
'svg',
Object.assign(
{
width: '1em',
height: '1em',
viewBox: '0 0 16 17',
xmlns: 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink',
},
props,
{
style: Object.assign(
{
verticalAlign: '-0.125em',
},
props.style,
),
className: ['nanqu-token-panel-icon', props.className].filter(Boolean).join(' '),
},
),
/*#__PURE__*/ createVNode(
'g',
{
id: 'Motion-\u9875\u9762-1',
stroke: 'none',
strokeWidth: 1,
fill: 'none',
fillRule: 'evenodd',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'Motion-\u5BCC\u6587\u672C\u7F16\u8F91\u5668_\u52A8\u6548',
transform: 'translate(0.000000, 0.903962)',
fill: 'currentColor',
fillRule: 'nonzero',
},
/*#__PURE__*/ createVNode('rect', {
id: 'Motion-\u77E9\u5F62',
opacity: 0,
x: 0,
y: 0,
width: 16,
height: 15.9807923,
}),
/*#__PURE__*/ createVNode('path', {
d: 'M6.55644444,12.5262777 L7.99555556,13.9627734 C8.13290682,14.0984321 8.18701716,14.2971622 8.13737053,14.4836147 C8.0877239,14.6700672 7.94192169,14.8156943 7.75524511,14.8652814 C7.56856853,14.9148684 7.36959959,14.860823 7.23377778,14.7236366 L5.79555556,13.2862532 C5.60250935,13.0737079 5.61045949,12.7472435 5.8136232,12.5443237 C6.01678692,12.3414038 6.3436437,12.3334632 6.55644444,12.5262777 L6.55644444,12.5262777 Z M12.2435556,12.6630023 L13.3857778,13.8038533 C13.5231286,13.9395121 13.5772386,14.138242 13.527592,14.3246942 C13.4779453,14.5111464 13.3321433,14.6567734 13.145467,14.7063605 C12.9587906,14.7559476 12.7598219,14.7019025 12.624,14.5647165 L11.4817778,13.4238655 C11.3444269,13.2882067 11.2903169,13.0894768 11.3399636,12.9030246 C11.3896103,12.7165724 11.5354123,12.5709454 11.7220886,12.5213583 C11.9087649,12.4717712 12.1077337,12.5258163 12.2435556,12.6630023 L12.2435556,12.6630023 Z M7.29511111,0.990809123 C7.37066667,1.03342457 7.43377778,1.09645992 7.47644444,1.17192476 L9.23911111,4.29439403 L12.7564444,5.00376364 C12.9258902,5.03768098 13.0638332,5.16026877 13.1172645,5.32441904 C13.1706959,5.4885693 13.1313024,5.66874209 13.0142222,5.79570068 L10.5866667,8.43430705 L10.9982222,11.9953603 C11.018176,12.1667991 10.94398,12.3356549 10.8041422,12.4370491 C10.6643043,12.5384432 10.4805781,12.5566027 10.3235556,12.4845501 L7.06133333,10.9930095 L3.79733333,12.4845501 C3.64031082,12.5566027 3.45658456,12.5384432 3.3167467,12.4370491 C3.17690884,12.3356549 3.10271286,12.1667991 3.12266667,11.9953603 L3.53511111,8.43519487 L1.10577778,5.79570068 C0.988697555,5.66874209 0.949304077,5.4885693 1.00273546,5.32441904 C1.05616684,5.16026877 1.19410976,5.03768098 1.36355556,5.00376364 L4.88177778,4.29439403 L6.64266667,1.17192476 C6.70502264,1.06136833 6.80886024,0.980137913 6.93126543,0.94615878 C7.05367063,0.912179648 7.18458201,0.928244805 7.29511111,0.990809123 Z M7.05955556,2.62440123 L5.57688889,5.25235374 L2.61688889,5.84808216 L4.65955556,8.07030012 L4.31288889,11.0666987 L7.05955556,9.81131866 L9.80533333,11.0666987 L9.45866667,8.07030012 L11.5031111,5.84896999 L8.54222222,5.25235374 L7.05866667,2.62440123 L7.05955556,2.62440123 Z M13.1528889,7.76045031 L14.5911111,9.19694597 C14.7892424,9.40878705 14.7837079,9.73933037 14.5785954,9.9444359 C14.373483,10.1495414 14.0425491,10.1554552 13.8302222,9.95780926 L12.3911111,8.5213136 C12.2537603,8.38565475 12.1996502,8.18692487 12.2492969,8.00047265 C12.2989436,7.81402043 12.4447456,7.66839345 12.6314219,7.61880637 C12.8180983,7.56921929 13.017067,7.62326436 13.1528889,7.76045031 L13.1528889,7.76045031 Z',
id: 'Motion-\u5F62\u72B6',
}),
),
),
);
}
export default Motion;

View File

@ -0,0 +1,54 @@
import type { CSSProperties } from 'vue';
import { defineComponent } from 'vue';
const Motion = defineComponent({
name: 'Motion',
setup(_, { attrs }) {
return () => {
return (
<svg
{...attrs}
width="1em"
height="1em"
style={{
verticalAlign: '-0.125em',
...(attrs.style as CSSProperties),
}}
class={['nanqu-token-panel-icon', attrs.class].filter(Boolean).join(' ')}
viewBox="0 0 16 17"
xmlns="http://www.w3.org/2000/svg"
>
<g
id="Motion-\u9875\u9762-1"
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
>
<g
id="Motion-\u5BCC\u6587\u672C\u7F16\u8F91\u5668_\u52A8\u6548"
transform="translate(0.000000, 0.903962)"
fill="currentColor"
fill-rule="nonzero"
>
<rect
id="Motion-\u77E9\u5F62"
opacity="0"
x="0"
y="0"
width="16"
height="15.9807923"
></rect>
<path
d="M6.55644444,12.5262777 L7.99555556,13.9627734 C8.13290682,14.0984321 8.18701716,14.2971622 8.13737053,14.4836147 C8.0877239,14.6700672 7.94192169,14.8156943 7.75524511,14.8652814 C7.56856853,14.9148684 7.36959959,14.860823 7.23377778,14.7236366 L5.79555556,13.2862532 C5.60250935,13.0737079 5.61045949,12.7472435 5.8136232,12.5443237 C6.01678692,12.3414038 6.3436437,12.3334632 6.55644444,12.5262777 L6.55644444,12.5262777 Z M12.2435556,12.6630023 L13.3857778,13.8038533 C13.5231286,13.9395121 13.5772386,14.138242 13.527592,14.3246942 C13.4779453,14.5111464 13.3321433,14.6567734 13.145467,14.7063605 C12.9587906,14.7559476 12.7598219,14.7019025 12.624,14.5647165 L11.4817778,13.4238655 C11.3444269,13.2882067 11.2903169,13.0894768 11.3399636,12.9030246 C11.3896103,12.7165724 11.5354123,12.5709454 11.7220886,12.5213583 C11.9087649,12.4717712 12.1077337,12.5258163 12.2435556,12.6630023 L12.2435556,12.6630023 Z M7.29511111,0.990809123 C7.37066667,1.03342457 7.43377778,1.09645992 7.47644444,1.17192476 L9.23911111,4.29439403 L12.7564444,5.00376364 C12.9258902,5.03768098 13.0638332,5.16026877 13.1172645,5.32441904 C13.1706959,5.4885693 13.1313024,5.66874209 13.0142222,5.79570068 L10.5866667,8.43430705 L10.9982222,11.9953603 C11.018176,12.1667991 10.94398,12.3356549 10.8041422,12.4370491 C10.6643043,12.5384432 10.4805781,12.5566027 10.3235556,12.4845501 L7.06133333,10.9930095 L3.79733333,12.4845501 C3.64031082,12.5566027 3.45658456,12.5384432 3.3167467,12.4370491 C3.17690884,12.3356549 3.10271286,12.1667991 3.12266667,11.9953603 L3.53511111,8.43519487 L1.10577778,5.79570068 C0.988697555,5.66874209 0.949304077,5.4885693 1.00273546,5.32441904 C1.05616684,5.16026877 1.19410976,5.03768098 1.36355556,5.00376364 L4.88177778,4.29439403 L6.64266667,1.17192476 C6.70502264,1.06136833 6.80886024,0.980137913 6.93126543,0.94615878 C7.05367063,0.912179648 7.18458201,0.928244805 7.29511111,0.990809123 Z M7.05955556,2.62440123 L5.57688889,5.25235374 L2.61688889,5.84808216 L4.65955556,8.07030012 L4.31288889,11.0666987 L7.05955556,9.81131866 L9.80533333,11.0666987 L9.45866667,8.07030012 L11.5031111,5.84896999 L8.54222222,5.25235374 L7.05866667,2.62440123 L7.05955556,2.62440123 Z M13.1528889,7.76045031 L14.5911111,9.19694597 C14.7892424,9.40878705 14.7837079,9.73933037 14.5785954,9.9444359 C14.373483,10.1495414 14.0425491,10.1554552 13.8302222,9.95780926 L12.3911111,8.5213136 C12.2537603,8.38565475 12.1996502,8.18692487 12.2492969,8.00047265 C12.2989436,7.81402043 12.4447456,7.66839345 12.6314219,7.61880637 C12.8180983,7.56921929 13.017067,7.62326436 13.1528889,7.76045031 L13.1528889,7.76045031 Z"
id="Motion-\u5F62\u72B6"
></path>
</g>
</g>
</svg>
);
};
},
});
export default Motion;

View File

@ -3,7 +3,6 @@ import { defineComponent } from 'vue';
const Pick = defineComponent({
name: 'Pick',
emits: ['click'],
setup(_, { attrs }) {
return () => {
return (

View File

@ -1,86 +0,0 @@
import { createVNode } from 'vue';
function SearchDropdown(props) {
return /*#__PURE__*/ createVNode(
'svg',
Object.assign(
{
width: '1em',
height: '1em',
viewBox: '0 0 18 18',
xmlns: 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink',
},
props,
{
style: Object.assign(
{
verticalAlign: '-0.125em',
},
props.style,
),
className: ['nanqu-token-panel-icon', props.className].filter(Boolean).join(' '),
},
),
/*#__PURE__*/ createVNode(
'g',
{
id: 'SearchDropdown-\u9875\u9762-1',
stroke: 'none',
strokeWidth: 1,
fill: 'none',
fillRule: 'evenodd',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'SearchDropdown-\u4E3B\u9898\u9884\u89C8\u5668---\u7EC4\u4EF6\u9884\u89C8',
transform: 'translate(-23.000000, -198.000000)',
fillRule: 'nonzero',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'SearchDropdown-\u7F16\u7EC4-18',
transform: 'translate(0.000000, 70.000000)',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'SearchDropdown-\u7F16\u7EC4-15',
transform: 'translate(16.000000, 123.000000)',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'SearchDropdown-search-outlined',
transform: 'translate(7.000000, 5.000000)',
},
/*#__PURE__*/ createVNode('rect', {
id: 'SearchDropdown-\u77E9\u5F62',
fill: '#000000',
opacity: 0,
x: 0,
y: 0,
width: 18,
height: 18,
}),
/*#__PURE__*/ createVNode('path', {
d: 'M15.958,14.99375 L11.41325,10.449 C12.1185,9.53725 12.5,8.4225 12.5,7.25 C12.5,5.8465 11.95225,4.5305 10.96175,3.53825 C9.97125,2.546 8.65175,2 7.25,2 C5.84825,2 4.52875,2.54775 3.53825,3.53825 C2.546,4.52875 2,5.8465 2,7.25 C2,8.65175 2.54775,9.97125 3.53825,10.96175 C4.52875,11.954 5.8465,12.5 7.25,12.5 C8.4225,12.5 9.5355,12.1185 10.44725,11.415 L14.992,15.958 C15.048,16.014 15.139,16.014 15.195,15.958 L15.958,15.19675 C16.014,15.14075 16.014,15.04975 15.958,14.99375 Z M10.022,10.022 C9.28,10.76225 8.2965,11.17 7.25,11.17 C6.2035,11.17 5.22,10.76225 4.478,10.022 C3.73775,9.28 3.33,8.2965 3.33,7.25 C3.33,6.2035 3.73775,5.21825 4.478,4.478 C5.22,3.73775 6.2035,3.33 7.25,3.33 C8.2965,3.33 9.28175,3.736 10.022,4.478 C10.76225,5.22 11.17,6.2035 11.17,7.25 C11.17,8.2965 10.76225,9.28175 10.022,10.022 Z',
id: 'SearchDropdown-\u5F62\u72B6',
fill: 'currentColor',
}),
/*#__PURE__*/ createVNode('path', {
d: 'M17.8616348,7.7578125 L14.0131973,7.7578125 C13.8977676,7.7578125 13.8333145,7.8796875 13.9047988,7.96289062 L15.8290176,10.1941406 C15.8840957,10.2580078 15.9901504,10.2580078 16.0458145,10.1941406 L17.9700332,7.96289062 C18.0415176,7.8796875 17.9770645,7.7578125 17.8616348,7.7578125 Z',
id: 'SearchDropdown-\u8DEF\u5F84',
fill: 'currentColor',
}),
),
),
),
),
),
);
}
export default SearchDropdown;

View File

@ -0,0 +1,64 @@
import type { CSSProperties } from 'vue';
import { defineComponent } from 'vue';
const SearchDropdown = defineComponent({
name: 'SearchDropdown',
setup(_, { attrs }) {
return () => {
return (
<svg
{...attrs}
width="1em"
height="1em"
style={{
verticalAlign: '-0.125em',
...(attrs.style as CSSProperties),
}}
class={['nanqu-token-panel-icon', attrs.class].filter(Boolean).join(' ')}
viewBox="0 0 18 18"
xmlns="http://www.w3.org/2000/svg"
>
<g
id="SearchDropdown-\u9875\u9762-1"
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
>
<g
id="SearchDropdown-\u4E3B\u9898\u9884\u89C8\u5668---\u7EC4\u4EF6\u9884\u89C8"
transform="translate(-23.000000, -198.000000)"
fill-rule="nonzero"
>
<g id="SearchDropdown-\u7F16\u7EC4-18" transform="translate(0.000000, 70.000000)">
<g id="SearchDropdown-search-outlined" transform="translate(7.000000, 5.000000)">
<rect
id="SearchDropdown-\u77E9\u5F62"
fill="#000000"
opacity="0"
x="0"
y="0"
width="18"
height="18"
></rect>
<path
d="M15.958,14.99375 L11.41325,10.449 C12.1185,9.53725 12.5,8.4225 12.5,7.25 C12.5,5.8465 11.95225,4.5305 10.96175,3.53825 C9.97125,2.546 8.65175,2 7.25,2 C5.84825,2 4.52875,2.54775 3.53825,3.53825 C2.546,4.52875 2,5.8465 2,7.25 C2,8.65175 2.54775,9.97125 3.53825,10.96175 C4.52875,11.954 5.8465,12.5 7.25,12.5 C8.4225,12.5 9.5355,12.1185 10.44725,11.415 L14.992,15.958 C15.048,16.014 15.139,16.014 15.195,15.958 L15.958,15.19675 C16.014,15.14075 16.014,15.04975 15.958,14.99375 Z M10.022,10.022 C9.28,10.76225 8.2965,11.17 7.25,11.17 C6.2035,11.17 5.22,10.76225 4.478,10.022 C3.73775,9.28 3.33,8.2965 3.33,7.25 C3.33,6.2035 3.73775,5.21825 4.478,4.478 C5.22,3.73775 6.2035,3.33 7.25,3.33 C8.2965,3.33 9.28175,3.736 10.022,4.478 C10.76225,5.22 11.17,6.2035 11.17,7.25 C11.17,8.2965 10.76225,9.28175 10.022,10.022 Z"
id="SearchDropdown-\u5F62\u72B6"
fill="currentColor"
></path>
<path
d="M17.8616348,7.7578125 L14.0131973,7.7578125 C13.8977676,7.7578125 13.8333145,7.8796875 13.9047988,7.96289062 L15.8290176,10.1941406 C15.8840957,10.2580078 15.9901504,10.2580078 16.0458145,10.1941406 L17.9700332,7.96289062 C18.0415176,7.8796875 17.9770645,7.7578125 17.8616348,7.7578125 Z"
id="SearchDropdown-\u8DEF\u5F84"
fill="currentColor"
></path>
</g>
</g>
</g>
</g>
</svg>
);
};
},
});
export default SearchDropdown;

View File

@ -1,59 +0,0 @@
import { createVNode } from 'vue';
function ShapeLine(props) {
return /*#__PURE__*/ createVNode(
'svg',
Object.assign(
{
width: '1em',
height: '1em',
viewBox: '0 0 16 17',
xmlns: 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink',
},
props,
{
style: Object.assign(
{
verticalAlign: '-0.125em',
},
props.style,
),
className: ['nanqu-token-panel-icon', props.className].filter(Boolean).join(' '),
},
),
/*#__PURE__*/ createVNode(
'g',
{
id: 'ShapeLine-\u9875\u9762-1',
stroke: 'none',
strokeWidth: 1,
fill: 'none',
fillRule: 'evenodd',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'ShapeLine-shape-line',
transform: 'translate(0.000000, 0.923169)',
fill: 'currentColor',
fillRule: 'nonzero',
},
/*#__PURE__*/ createVNode('rect', {
id: 'ShapeLine-\u77E9\u5F62',
opacity: 0,
x: 0,
y: 0,
width: 16,
height: 15.9807923,
}),
/*#__PURE__*/ createVNode('path', {
d: 'M5.22,13.3173269 C4.90928357,14.1946577 4.03334945,14.7416208 3.10760502,14.6363783 C2.18186059,14.5311359 1.45139881,13.801551 1.34602985,12.8769179 C1.24066088,11.9522848 1.78828141,11.0774022 2.66666667,10.7670588 L2.66666667,5.21373349 C1.78828141,4.90339007 1.24066088,4.02850749 1.34602985,3.1038744 C1.45139881,2.1792413 2.18186059,1.44965643 3.10760502,1.34441396 C4.03334945,1.23917149 4.90928357,1.78613461 5.22,2.66346539 L10.78,2.66346539 C11.0907164,1.78613461 11.9666505,1.23917149 12.892395,1.34441396 C13.8181394,1.44965643 14.5486012,2.1792413 14.6539702,3.1038744 C14.7593391,4.02850749 14.2117186,4.90339007 13.3333333,5.21373349 L13.3333333,10.7670588 C14.2117186,11.0774022 14.7593391,11.9522848 14.6539702,12.8769179 C14.5486012,13.801551 13.8181394,14.5311359 12.892395,14.6363783 C11.9666505,14.7416208 11.0907164,14.1946577 10.78,13.3173269 L5.22,13.3173269 Z M5.22,11.9855942 L10.78,11.9855942 C10.9819939,11.4165133 11.430235,10.9688103 12,10.7670588 L12,5.21373349 C11.430235,5.01198206 10.9819939,4.56427905 10.78,3.99519808 L5.22,3.99519808 C5.01800608,4.56427905 4.56976496,5.01198206 4,5.21373349 L4,10.7670588 C4.56976496,10.9688103 5.01800608,11.4165133 5.22,11.9855942 Z M3.33333333,3.99519809 C3.5715347,3.9952345 3.79165744,3.86832906 3.91076865,3.66229434 C4.02987987,3.45625961 4.02987987,3.20240385 3.91076865,2.99636913 C3.79165744,2.79033441 3.5715347,2.66342897 3.33333333,2.66346538 C2.96518335,2.66352168 2.66676872,2.96162371 2.66676872,3.32933173 C2.66676872,3.69703976 2.96518335,3.99514178 3.33333333,3.99519809 L3.33333333,3.99519809 Z M12.6666667,3.99519809 C12.904868,3.9952345 13.1249908,3.86832906 13.244102,3.66229434 C13.3632132,3.45625961 13.3632132,3.20240385 13.244102,2.99636913 C13.1249908,2.79033441 12.904868,2.66342897 12.6666667,2.66346538 C12.2985167,2.66352168 12.0001021,2.96162371 12.0001021,3.32933173 C12.0001021,3.69703976 12.2985167,3.99514178 12.6666667,3.99519809 L12.6666667,3.99519809 Z M12.6666667,13.3173269 C12.904868,13.3173633 13.1249908,13.1904579 13.244102,12.9844232 C13.3632132,12.7783885 13.3632132,12.5245327 13.244102,12.318498 C13.1249908,12.1124633 12.904868,11.9855578 12.6666667,11.9855942 C12.2985167,11.9856505 12.0001021,12.2837526 12.0001021,12.6514606 C12.0001021,13.0191686 12.2985167,13.3172706 12.6666667,13.3173269 L12.6666667,13.3173269 Z M3.33333333,13.3173269 C3.5715347,13.3173633 3.79165744,13.1904579 3.91076865,12.9844232 C4.02987987,12.7783885 4.02987987,12.5245327 3.91076865,12.318498 C3.79165744,12.1124633 3.5715347,11.9855578 3.33333333,11.9855942 C2.96518335,11.9856505 2.66676872,12.2837526 2.66676872,12.6514606 C2.66676872,13.0191686 2.96518335,13.3172706 3.33333333,13.3173269 L3.33333333,13.3173269 Z',
id: 'ShapeLine-\u5F62\u72B6',
}),
),
),
);
}
export default ShapeLine;

View File

@ -0,0 +1,54 @@
import type { CSSProperties } from 'vue';
import { defineComponent } from 'vue';
const ShapeLine = defineComponent({
name: 'ShapeLine',
setup(_, { attrs }) {
return () => {
return (
<svg
{...attrs}
width="1em"
height="1em"
style={{
verticalAlign: '-0.125em',
...(attrs.style as CSSProperties),
}}
class={['nanqu-token-panel-icon', attrs.class].filter(Boolean).join(' ')}
viewBox="0 0 16 17"
xmlns="http://www.w3.org/2000/svg"
>
<g
id="ShapeLine-\u9875\u9762-1"
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
>
<g
id="ShapeLine-shape-line"
transform="translate(0.000000, 0.923169)"
fill="currentColor"
fill-rule="nonzero"
>
<rect
id="ShapeLine-\u77E9\u5F62"
opacity="0"
x="0"
y="0"
width="16"
height="15.9807923"
></rect>
<path
d="M5.22,13.3173269 C4.90928357,14.1946577 4.03334945,14.7416208 3.10760502,14.6363783 C2.18186059,14.5311359 1.45139881,13.801551 1.34602985,12.8769179 C1.24066088,11.9522848 1.78828141,11.0774022 2.66666667,10.7670588 L2.66666667,5.21373349 C1.78828141,4.90339007 1.24066088,4.02850749 1.34602985,3.1038744 C1.45139881,2.1792413 2.18186059,1.44965643 3.10760502,1.34441396 C4.03334945,1.23917149 4.90928357,1.78613461 5.22,2.66346539 L10.78,2.66346539 C11.0907164,1.78613461 11.9666505,1.23917149 12.892395,1.34441396 C13.8181394,1.44965643 14.5486012,2.1792413 14.6539702,3.1038744 C14.7593391,4.02850749 14.2117186,4.90339007 13.3333333,5.21373349 L13.3333333,10.7670588 C14.2117186,11.0774022 14.7593391,11.9522848 14.6539702,12.8769179 C14.5486012,13.801551 13.8181394,14.5311359 12.892395,14.6363783 C11.9666505,14.7416208 11.0907164,14.1946577 10.78,13.3173269 L5.22,13.3173269 Z M5.22,11.9855942 L10.78,11.9855942 C10.9819939,11.4165133 11.430235,10.9688103 12,10.7670588 L12,5.21373349 C11.430235,5.01198206 10.9819939,4.56427905 10.78,3.99519808 L5.22,3.99519808 C5.01800608,4.56427905 4.56976496,5.01198206 4,5.21373349 L4,10.7670588 C4.56976496,10.9688103 5.01800608,11.4165133 5.22,11.9855942 Z M3.33333333,3.99519809 C3.5715347,3.9952345 3.79165744,3.86832906 3.91076865,3.66229434 C4.02987987,3.45625961 4.02987987,3.20240385 3.91076865,2.99636913 C3.79165744,2.79033441 3.5715347,2.66342897 3.33333333,2.66346538 C2.96518335,2.66352168 2.66676872,2.96162371 2.66676872,3.32933173 C2.66676872,3.69703976 2.96518335,3.99514178 3.33333333,3.99519809 L3.33333333,3.99519809 Z M12.6666667,3.99519809 C12.904868,3.9952345 13.1249908,3.86832906 13.244102,3.66229434 C13.3632132,3.45625961 13.3632132,3.20240385 13.244102,2.99636913 C13.1249908,2.79033441 12.904868,2.66342897 12.6666667,2.66346538 C12.2985167,2.66352168 12.0001021,2.96162371 12.0001021,3.32933173 C12.0001021,3.69703976 12.2985167,3.99514178 12.6666667,3.99519809 L12.6666667,3.99519809 Z M12.6666667,13.3173269 C12.904868,13.3173633 13.1249908,13.1904579 13.244102,12.9844232 C13.3632132,12.7783885 13.3632132,12.5245327 13.244102,12.318498 C13.1249908,12.1124633 12.904868,11.9855578 12.6666667,11.9855942 C12.2985167,11.9856505 12.0001021,12.2837526 12.0001021,12.6514606 C12.0001021,13.0191686 12.2985167,13.3172706 12.6666667,13.3173269 L12.6666667,13.3173269 Z M3.33333333,13.3173269 C3.5715347,13.3173633 3.79165744,13.1904579 3.91076865,12.9844232 C4.02987987,12.7783885 4.02987987,12.5245327 3.91076865,12.318498 C3.79165744,12.1124633 3.5715347,11.9855578 3.33333333,11.9855942 C2.96518335,11.9856505 2.66676872,12.2837526 2.66676872,12.6514606 C2.66676872,13.0191686 2.96518335,13.3172706 3.33333333,13.3173269 L3.33333333,13.3173269 Z"
id="ShapeLine-\u5F62\u72B6"
></path>
</g>
</g>
</svg>
);
};
},
});
export default ShapeLine;

View File

@ -1,87 +0,0 @@
import { createVNode } from 'vue';
function TokenPanel(props) {
return /*#__PURE__*/ createVNode(
'svg',
Object.assign(
{
width: '1em',
height: '1em',
viewBox: '0 0 20 19',
xmlns: 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink',
},
props,
{
style: Object.assign(
{
verticalAlign: '-0.125em',
},
props.style,
),
className: ['nanqu-token-panel-icon', props.className].filter(Boolean).join(' '),
},
),
/*#__PURE__*/ createVNode(
'g',
{
id: 'TokenPanel-\u9875\u9762-1',
stroke: 'none',
strokeWidth: 1,
fill: 'none',
fillRule: 'evenodd',
fillOpacity: 0.85,
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'TokenPanel-\u4E3B\u9898\u7F16\u8F91\u5668---\u591A\u4E3B\u9898',
transform: 'translate(-14.000000, -70.000000)',
fill: 'currentColor',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'TokenPanel-\u7F16\u7EC4-3',
transform: 'translate(10.000000, 66.000000)',
},
/*#__PURE__*/ createVNode(
'g',
{
id: 'TokenPanel-\u7F16\u7EC4-20',
transform: 'translate(4.000000, 4.000000)',
},
/*#__PURE__*/ createVNode('rect', {
id: 'TokenPanel-\u77E9\u5F62',
opacity: 0.600000024,
x: 1,
y: 12,
width: 7,
height: 7,
rx: 0.434782594,
}),
/*#__PURE__*/ createVNode('path', {
d: 'M12.3540059,0 L19.5652174,0 C19.8053412,8.08981097e-16 20,0.194658804 20,0.434782609 L20,7.6459941 C20,7.88611791 19.8053412,8.08077671 19.5652174,8.08077671 C19.4499059,8.08077671 19.3393172,8.03496939 19.2577797,7.95343183 L12.0465682,0.74222034 C11.876775,0.572427169 11.876775,0.297138048 12.0465682,0.127344878 C12.1281057,0.0458073219 12.2386944,-6.44951433e-16 12.3540059,0 Z',
id: 'TokenPanel-\u77E9\u5F62',
opacity: 0.400000006,
}),
/*#__PURE__*/ createVNode('circle', {
id: 'TokenPanel-\u692D\u5706\u5F62',
cx: 4.34782609,
cy: 4.34782609,
r: 4.34782609,
}),
/*#__PURE__*/ createVNode('circle', {
id: 'TokenPanel-\u692D\u5706\u5F62',
cx: 15.5,
cy: 15.5,
r: 3.5,
}),
),
),
),
),
);
}
export default TokenPanel;

View File

@ -0,0 +1,67 @@
import type { CSSProperties } from 'vue';
import { defineComponent } from 'vue';
const TokenPanel = defineComponent({
name: 'TokenPanel',
setup(_, { attrs }) {
return () => {
return (
<svg
{...attrs}
width="1em"
height="1em"
style={{
verticalAlign: '-0.125em',
...(attrs.style as CSSProperties),
}}
class={['nanqu-token-panel-icon', attrs.class].filter(Boolean).join(' ')}
viewBox="0 0 20 19"
xmlns="http://www.w3.org/2000/svg"
>
<g
id="TokenPanel-\u9875\u9762-1"
stroke="none"
stroke-width="1"
fill="none"
fill-rule="evenodd"
fill-opacity="0.85"
>
<g
id="TokenPanel-\u4E3B\u9898\u7F16\u8F91\u5668---\u591A\u4E3B\u9898"
transform="translate(-14.000000, -70.000000)"
fill="currentColor"
>
<g id="TokenPanel-\u7F16\u7EC4-3" transform="translate(10.000000, 66.000000)">
<g id="TokenPanel-\u7F16\u7EC4-20" transform="translate(4.000000, 4.000000)">
<rect
id="TokenPanel-\u77E9\u5F62"
opacity="0.600000024"
x="1"
y="12"
width="7"
height="7"
rx="0.434782594"
></rect>
<path
d="M12.3540059,0 L19.5652174,0 C19.8053412,8.08981097e-16 20,0.194658804 20,0.434782609 L20,7.6459941 C20,7.88611791 19.8053412,8.08077671 19.5652174,8.08077671 C19.4499059,8.08077671 19.3393172,8.03496939 19.2577797,7.95343183 L12.0465682,0.74222034 C11.876775,0.572427169 11.876775,0.297138048 12.0465682,0.127344878 C12.1281057,0.0458073219 12.2386944,-6.44951433e-16 12.3540059,0 Z"
id="TokenPanel-\u77E9\u5F62"
opacity="0.400000006"
></path>
<circle
id="TokenPanel-\u692D\u5706\u5F62"
cx="4.34782609"
cy="4.34782609"
r="4.34782609"
></circle>
<circle id="TokenPanel-\u692D\u5706\u5F62" cx="15.5" cy="15.5" r="3.5"></circle>
</g>
</g>
</g>
</g>
</svg>
);
};
},
});
export default TokenPanel;

View File

@ -1,15 +1,16 @@
export { default as Margin } from './Margin.js';
export { default as Motion } from './Motion.js';
export { default as ShapeLine } from './ShapeLine.js';
export { default as Arrow } from './Arrow.js';
export { default as SearchDropdown } from './SearchDropdown.js';
export { default as TokenPanelIcon } from './TokenPanel.js';
export { default as Brush } from './Brush.js';
export { default as Light } from './Light';
export { default as DarkTheme } from './Dark';
export { default as Pick } from './Pick';
export { default as CompactTheme } from './Compact';
export { default as Control } from './Control';
export { default as Motion } from './Motion';
export { default as ShapeLine } from './ShapeLine';
export { default as Arrow } from './Arrow';
export { default as SearchDropdown } from './SearchDropdown';
export { default as Brush } from './Brush';
export { default as Margin } from './Margin';
export { default as TokenPanelIcon } from './TokenPanel';

View File

@ -1,2 +1,12 @@
export type { MutableTheme, PreviewerProps, Theme } from './interface';
export * from './locale';
export * from './meta';
export * from './overviews';
export { default as PreviewDemo } from './PreviewDemo';
export type { PreviewDemoProps } from './PreviewDemo';
export { default as Previewer } from './previewer';
export { default as ThemeEditor } from './ThemeEditor';
export type { ThemeEditorProps } from './ThemeEditor';
export { default as TokenPanel } from './token-panel';
export type { TokenPanelRef, TokenPreviewProps } from './token-panel';
export { default as getDesignToken } from './utils/getDesignToken';

View File

@ -0,0 +1,348 @@
import { Button, Layout, message, theme as antdTheme } from 'ant-design-vue';
import type { ThemeConfig } from 'ant-design-vue/es/config-provider/context';
import classNames from 'ant-design-vue/es/_util/classNames';
import { PropType } from 'vue';
import { defineComponent, toRefs, watchEffect, computed, ref } from 'vue';
import ComponentPanel from './component-panel';
import type { FilterMode } from './FilterPanel';
import FilterPanel from './FilterPanel';
import { Arrow, CompactTheme, DarkTheme } from './icons';
import type { MutableTheme, PreviewerProps, Theme } from './interface';
import type { ThemeSelectProps } from './ThemeSelect';
import ThemeSelect from './ThemeSelect';
import type { TokenPanelRef } from './token-panel';
import TokenPanel from './token-panel';
import type { TokenType } from './utils/classifyToken';
import makeStyle from './utils/makeStyle';
const { darkAlgorithm } = antdTheme;
const { Header, Sider, Content } = Layout;
const SIDER_WIDTH = 340;
const useStyle = makeStyle('layout', token => ({
[`.previewer-layout${token.rootCls}-layout`]: {
[`${token.rootCls}-layout-header`]: {
backgroundColor: 'white !important',
display: 'flex',
alignItems: 'center',
borderBottom: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
paddingInline: `${token.paddingLG}px !important`,
},
[`${token.rootCls}-layout-sider`]: {
padding: 0,
borderInlineEnd: `${token.lineWidth}px ${token.lineType} ${token.colorSplit}`,
transition: `all ${token.motionDurationSlow}`,
overflow: 'visible !important',
[`${token.rootCls}-btn${token.rootCls}-btn-circle.previewer-sider-collapse-btn`]: {
position: 'absolute',
transform: 'translateX(50%)',
border: 'none',
boxShadow:
'0 2px 8px -2px rgba(0,0,0,0.05), 0 1px 4px -1px rgba(25,15,15,0.07), 0 0 1px 0 rgba(0,0,0,0.08)',
marginTop: token.margin,
insetInlineEnd: 0,
color: 'rgba(0,0,0,0.25)',
'&:hover': {
color: 'rgba(0,0,0,0.45)',
boxShadow:
'0 2px 8px -2px rgba(0,0,0,0.18), 0 1px 4px -1px rgba(25,15,15,0.18), 0 0 1px 0 rgba(0,0,0,0.18)',
},
'.previewer-sider-collapse-btn-icon': {
fontSize: 16,
marginTop: 4,
transition: 'transform 0.3s',
},
'&-collapsed': {
borderRadius: { _skip_check_: true, value: '0 100px 100px 0' },
transform: 'translateX(90%)',
'.previewer-sider-collapse-btn-icon': {
transform: 'rotate(180deg)',
},
},
},
'.previewer-sider-handler': {
position: 'absolute',
insetInlineEnd: 0,
height: '100%',
width: 8,
transform: 'translateX(50%)',
cursor: 'ew-resize',
opacity: 0,
backgroundColor: 'transparent',
},
},
},
}));
const Previewer = defineComponent({
name: 'Previewer',
inheritAttrs: false,
props: {
onSave: { type: Function as PropType<(themeConfig: ThemeConfig) => void> },
showTheme: { type: Boolean },
theme: { type: Object as PropType<Theme> },
onThemeChange: { type: Function as PropType<(config: ThemeConfig) => void> },
},
setup(props, { attrs }) {
const { showTheme, theme } = toRefs(props);
const [wrapSSR, hashId] = useStyle();
const selectedTokens = ref<string[]>([]);
const siderVisible = ref<boolean>(true);
const siderWidth = ref<number>(SIDER_WIDTH);
const filterMode = ref<FilterMode>('filter');
const filterTypes = ref<TokenType[]>([]);
const tokenPanelRef = ref<TokenPanelRef>(null);
const dragRef = ref(false);
const siderRef = ref<HTMLDivElement>(null);
const defaultThemes = computed<ThemeSelectProps['themes']>(() => [
{
name: '默认主题',
key: 'default',
config: {},
fixed: true,
},
{
name: '暗色主题',
key: 'dark',
config: {
algorithm: darkAlgorithm,
},
icon: <DarkTheme style={{ fontSize: '16px' }} />,
closable: true,
},
{
name: '紧凑主题',
key: 'compact',
config: {},
icon: <CompactTheme style={{ fontSize: '16px' }} />,
closable: true,
},
]);
const themes = ref<ThemeSelectProps['themes']>(
theme.value
? [
{
...theme.value,
fixed: true,
},
]
: defaultThemes.value,
);
const shownThemes = ref<string[]>(
showTheme.value && !theme.value ? ['default', 'dark'] : [themes.value[0].key],
);
const enabledThemes = ref<string[]>(
showTheme.value && !theme.value ? ['default', 'dark'] : [themes.value[0].key],
);
watchEffect(() => {
themes.value = theme.value
? [
{
...theme.value,
fixed: true,
},
]
: defaultThemes.value;
shownThemes.value = theme.value ? [theme.value.key] : shownThemes.value;
enabledThemes.value = theme.value ? [theme.value.key] : enabledThemes.value;
});
watchEffect(() => {
const handleMouseUp = () => {
dragRef.value = false;
document.body.style.cursor = '';
if (siderRef.value) {
siderRef.value.style.transition = 'all 0.3s';
}
};
const handleMouseMove = (e: MouseEvent) => {
if (dragRef.value) {
e.preventDefault();
siderWidth.value = e.clientX > SIDER_WIDTH ? e.clientX : SIDER_WIDTH;
}
};
window.addEventListener('mouseup', handleMouseUp);
window.addEventListener('mousemove', handleMouseMove);
return () => {
window.removeEventListener('mouseup', handleMouseUp);
window.removeEventListener('mousemove', handleMouseMove);
};
});
const handleTokenClick = (tokenName: string) => {
tokenPanelRef.value?.scrollToToken(tokenName);
};
const mutableThemes = computed(() =>
enabledThemes.value.map<MutableTheme>(item => {
const themeEntity = themes.value.find(themeItem => themeItem.key === item)!;
return {
name: themeEntity.name,
key: themeEntity.key,
config: themeEntity.config,
onThemeChange: newTheme => {
if (themeEntity.key === theme.value?.key) {
props.onThemeChange?.(newTheme);
} else {
themes.value = themes.value.map(themeItem =>
themeItem.key === themeEntity.key
? {
...themeItem,
config: newTheme,
}
: themeItem,
);
}
},
};
}),
);
const componentPanel = computed(() => (
<ComponentPanel
filterMode={filterMode.value}
selectedTokens={selectedTokens.value}
themes={mutableThemes.value}
onTokenClick={handleTokenClick}
style={{ flex: 1, height: 0, marginTop: '12px' }}
/>
));
return () => {
return wrapSSR(
<Layout {...attrs} class={classNames('previewer-layout', hashId.value, attrs.class)}>
<Header class="previewer-header">
<span style={{ fontSize: '16px', fontWeight: 'bold', marginRight: '16px' }}>
主题预览器
</span>
{showTheme.value && (
<div>
<ThemeSelect
showAddTheme
enabledThemes={enabledThemes.value}
shownThemes={shownThemes.value}
themes={themes.value}
onEnabledThemeChange={value => {
if (value.length > 2) {
message.warning({
content: '最多同时展示两个主题',
});
return;
}
enabledThemes.value = value;
}}
onShownThemeChange={(value, selectTheme, { type }) => {
if (type === 'select' && enabledThemes.value.length < 2) {
enabledThemes.value = [...enabledThemes.value, selectTheme];
}
shownThemes.value = value;
}}
/>
</div>
)}
<Button
type="primary"
style={{ marginLeft: 'auto' }}
onClick={() => props.onSave?.(themes.value[0].config)}
>
保存
</Button>
</Header>
<Layout
style={{
height: 'calc(100vh - 64px)',
}}
>
<Sider
style={{
backgroundColor: 'white',
height: '100%',
overflow: 'auto',
flex: `0 0 ${siderWidth.value}px`,
willChange: 'auto',
}}
width={siderVisible.value ? siderWidth.value : 0}
ref={siderRef}
>
<div
class="previewer-sider-handler"
onMousedown={() => {
dragRef.value = true;
document.body.style.cursor = 'ew-resize';
if (siderRef.value) {
siderRef.value.style.transition = 'none';
}
}}
/>
<Button
onClick={() => (siderVisible.value = !siderVisible.value)}
class={classNames(
'previewer-sider-collapse-btn',
!siderVisible.value && 'previewer-sider-collapse-btn-collapsed',
)}
size="small"
icon={
<Arrow
rotate={siderVisible.value ? 0 : 180}
class="previewer-sider-collapse-btn-icon"
/>
}
shape="circle"
/>
<TokenPanel
ref={tokenPanelRef}
filterTypes={filterTypes.value}
onFilterTypesChange={types => (filterTypes.value = types)}
themes={mutableThemes.value}
selectedTokens={selectedTokens.value}
enableTokenSelect
onTokenSelect={tokenName =>
(selectedTokens.value = selectedTokens.value.includes(tokenName)
? selectedTokens.value.filter(item => item !== tokenName)
: [...selectedTokens.value, tokenName])
}
/>
</Sider>
<Content
style={{
padding: '16px 20px 28px 24px',
height: '100%',
overflow: 'hidden',
display: 'flex',
flexDirection: 'column',
}}
>
<FilterPanel
selectedTokens={selectedTokens.value}
onSelectedTokensChange={tokens => (selectedTokens.value = tokens)}
filterMode={filterMode.value}
onFilterModeChange={mode => (filterMode.value = mode)}
onTokenClick={handleTokenClick}
/>
{componentPanel.value}
</Content>
</Layout>
</Layout>,
);
};
},
});
export { PreviewerProps };
export default Previewer;

View File

@ -80,7 +80,7 @@ const ComponentDemoPro = defineComponent({
style={{ margin: '12px 0 0 12px' }}
/>
{/* <ConfigProvider
<ConfigProvider
theme={{
components: {
Select: {
@ -106,7 +106,7 @@ const ComponentDemoPro = defineComponent({
},
},
}}
> */}
>
{mode.value === 'overview' ? (
<div style={{ margin: '12px' }}>{overviewDemo.value}</div>
) : (
@ -119,7 +119,7 @@ const ComponentDemoPro = defineComponent({
hideTokens
/>
)}
{/* </ConfigProvider> */}
</ConfigProvider>
</div>
</div>
);
@ -140,9 +140,9 @@ export default defineComponent({
},
setup(props, { attrs }) {
return () => (
// <ConfigProvider theme={props.theme.config}>
<ConfigProvider theme={props.theme.config}>
<ComponentDemoPro {...props} {...attrs} />
// </ConfigProvider>
</ConfigProvider>
);
},
});

View File

@ -3,7 +3,7 @@ import {
Button,
Checkbox,
Collapse,
// ConfigProvider,
ConfigProvider,
Popover,
Switch,
Tooltip,
@ -519,7 +519,7 @@ const MapTokenCollapse = defineComponent({
return (
<Collapse
class="token-panel-pro-grouped-map-collapse"
defaultActiveKey={Object.keys(groupedTokens.value)}
activeKey={Object.keys(groupedTokens.value)}
expandIconPosition="end"
expandIcon={({ isActive }) => (
<CaretRightOutlined rotate={isActive ? 450 : 360} style={{ fontSize: '12px' }} />
@ -544,7 +544,7 @@ const MapTokenCollapse = defineComponent({
return (
<Collapse
class="token-panel-pro-grouped-map-collapse"
defaultActiveKey={group.value.groups.map(item => item.key)}
activeKey={group.value.groups.map(item => item.key)}
expandIconPosition="end"
expandIcon={({ isActive }) => (
<CaretRightOutlined rotate={isActive ? 450 : 360} style={{ fontSize: '12px' }} />
@ -707,13 +707,13 @@ const TokenContent = defineComponent({
/>
)}
</div>
{/* <ConfigProvider
<ConfigProvider
theme={{
token: {
colorBorder: '#f0f0f0',
},
}}
> */}
>
<Collapse
class="token-panel-pro-token-collapse"
expandIconPosition={'end'}
@ -722,7 +722,10 @@ const TokenContent = defineComponent({
v-model={[curActiveGroup.value, 'activeKey']}
v-slots={{
expandIcon: ({ isActive }) => (
<CaretRightOutlined rotate={isActive ? 450 : 360} style={{ fontSize: '12px' }} />
<CaretRightOutlined
rotate={isActive ? 450 : 360}
style={{ fontSize: '12px' }}
/>
),
}}
>
@ -769,7 +772,9 @@ const TokenContent = defineComponent({
<Checkbox
style={{ marginLeft: '12px' }}
checked={infoFollowPrimary.value}
onChange={e => props.onInfoFollowPrimaryChange(e.target.checked)}
onChange={e =>
props.onInfoFollowPrimaryChange(e.target.checked)
}
>
{locale.value.followPrimary}
</Checkbox>
@ -849,7 +854,7 @@ const TokenContent = defineComponent({
);
})}
</Collapse>
{/* </ConfigProvider> */}
</ConfigProvider>
</div>
</div>,
);

View File

@ -1,15 +1,8 @@
import { CheckOutlined } from '@ant-design/icons';
import { Dropdown, Input, Menu, Switch, theme as antdTheme } from 'antd';
import classNames from 'classnames';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import React, {
forwardRef,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
} from 'react';
import type { PropType } from 'vue';
import { defineComponent, toRefs, ref, watchEffect, computed } from 'vue';
import { CheckOutlined } from '@ant-design/icons-vue';
import { Dropdown, Input, Menu, Switch, theme as antdTheme } from 'ant-design-vue';
import classNames from 'ant-design-vue/es/_util/classNames';
import { SearchDropdown } from '../icons';
import type { AliasToken, MutableTheme, TokenValue } from '../interface';
import type { TokenType } from '../utils/classifyToken';
@ -121,49 +114,54 @@ export interface TokenPreviewProps {
export type TokenPanelRef = {
scrollToToken: (token: string) => void;
};
export default defineComponent({
name: 'TokenPreview',
props: {
themes: { type: Array as PropType<MutableTheme[]> },
selectedTokens: { type: Array as PropType<string[]> },
onTokenSelect: { type: Function as PropType<(token: string) => void> },
filterTypes: { type: Array as PropType<TokenType[]> },
onFilterTypesChange: { type: Function as PropType<(types: TokenType[]) => void> },
enableTokenSelect: { type: Boolean },
},
setup(props, { attrs, expose }) {
const { filterTypes, themes, selectedTokens, enableTokenSelect } = toRefs(props);
export default forwardRef<TokenPanelRef, TokenPreviewProps>((props: TokenPreviewProps, ref) => {
const {
filterTypes,
onFilterTypesChange,
themes,
selectedTokens,
onTokenSelect,
enableTokenSelect,
} = props;
const [wrapSSR, hashId] = useStyle();
const [search, setSearch] = useState<string>('');
const [showAll, setShowAll] = useState<boolean>(false);
const [showTokenListShadowTop, setShowTokenListShadowTop] = useState<boolean>(false);
const cardWrapperRef = useRef<HTMLDivElement>(null);
const [activeCards, setActiveCards] = useState<TokenType[]>([]);
const [activeToken, setActiveToken] = useState<string | undefined>();
const { token } = useToken();
const [mergedFilterTypes, setMergedFilterTypes] = useMergedState<TokenType[]>(filterTypes || []);
const search = ref<string>('');
const showAll = ref<boolean>(false);
const showTokenListShadowTop = ref<boolean>(false);
const cardWrapperRef = ref<HTMLDivElement>(null);
const activeCards = ref<TokenType[]>([]);
const activeToken = ref<string | undefined>();
const mergedFilterTypes = ref<TokenType[]>(filterTypes.value || []);
// TODO: Split AliasToken and SeedToken
const groupedToken = useMemo(() => classifyToken(token as any), [token]);
const groupedToken = computed(() => classifyToken(token.value as any));
useEffect(() => {
watchEffect(() => {
const handleTokenListScroll = () => {
setShowTokenListShadowTop((cardWrapperRef.current?.scrollTop ?? 0) > 0);
showTokenListShadowTop.value = (cardWrapperRef.value?.scrollTop ?? 0) > 0;
};
cardWrapperRef.current?.addEventListener('scroll', handleTokenListScroll);
const wrapper = cardWrapperRef.current;
cardWrapperRef.value?.addEventListener('scroll', handleTokenListScroll);
const wrapper = cardWrapperRef.value;
return () => {
wrapper?.removeEventListener('scroll', handleTokenListScroll);
};
}, []);
});
useImperativeHandle(ref, () => ({
expose({
scrollToToken: tokenName => {
const type = getTypeOfToken(tokenName);
if (!activeCards.includes(type)) {
setActiveCards(prev => [...prev, type]);
if (!activeCards.value.includes(type)) {
activeCards.value = [...activeCards.value, type];
}
setActiveToken(tokenName);
activeToken.value = tokenName;
setTimeout(() => {
const node = cardWrapperRef.current?.querySelector<HTMLElement>(
const node = cardWrapperRef.value?.querySelector<HTMLElement>(
`#${getTokenItemId(tokenName)}`,
);
if (!node) {
@ -175,7 +173,7 @@ export default forwardRef<TokenPanelRef, TokenPreviewProps>((props: TokenPreview
});
}, 100);
},
}));
});
const handleAliasTokenChange = (theme: MutableTheme, tokenName: string, value: TokenValue) => {
theme.onThemeChange?.(
@ -190,43 +188,49 @@ export default forwardRef<TokenPanelRef, TokenPreviewProps>((props: TokenPreview
);
};
return () => {
return wrapSSR(
<div className={classNames('preview-panel-wrapper', hashId)}>
<div className={classNames('preview-panel')}>
<div style={{ padding: 16 }}>
<h3 className={classNames('preview-panel-space', hashId)}>
<div {...attrs} class={classNames('preview-panel-wrapper', hashId.value)}>
<div class={classNames('preview-panel')}>
<div style={{ padding: '16px' }}>
<h3 class={classNames('preview-panel-space', hashId.value)}>
<span>Alias Token 预览</span>
<span className="preview-hide-token">
<span class="preview-hide-token">
<span>显示所有</span>
<Switch checked={showAll} onChange={value => setShowAll(value)} size="small" />
<Switch
checked={showAll.value}
onChange={value => (showAll.value = value as any)}
size="small"
/>
</span>
</h3>
<Input
allowClear
onChange={e => {
setSearch(e.target.value);
search.value = e.target.value;
}}
bordered={false}
addonBefore={
<>
<Dropdown
overlay={
v-slots={{
overlay: () => (
<Menu
items={[
{
label: '筛选项',
type: 'group',
key: 'title-key',
style: { fontSize: 12 },
style: { fontSize: '12px' },
},
...TOKEN_SORTS.map(type => ({
icon: (
<span>
<CheckOutlined
style={{
opacity: mergedFilterTypes.includes(type) ? 1 : 0,
marginInlineEnd: 8,
fontSize: 12,
opacity: mergedFilterTypes.value.includes(type) ? 1 : 0,
marginInlineEnd: '8px',
fontSize: '12px',
}}
/>
{IconMap[type]}
@ -235,51 +239,57 @@ export default forwardRef<TokenPanelRef, TokenPreviewProps>((props: TokenPreview
label: TextMap[type],
key: type,
onClick: () => {
const newTypes = mergedFilterTypes.includes(type)
? mergedFilterTypes.filter(item => type !== item)
: [...mergedFilterTypes, type];
setMergedFilterTypes(newTypes);
onFilterTypesChange?.(newTypes);
const newTypes = mergedFilterTypes.value.includes(type)
? mergedFilterTypes.value.filter(item => type !== item)
: [...mergedFilterTypes.value, type];
mergedFilterTypes.value = newTypes;
props.onFilterTypesChange?.(newTypes);
},
})),
]}
/>
}
),
}}
trigger={['click']}
>
<SearchDropdown
style={{
width: 32,
width: '32px',
cursor: 'pointer',
fontSize: 18,
paddingTop: 2,
fontSize: '18px',
paddingTop: '2px',
transition: 'color 0.3s',
}}
className={classNames({
'previewer-token-type-dropdown-icon-active': mergedFilterTypes.length > 0,
class={classNames({
'previewer-token-type-dropdown-icon-active':
mergedFilterTypes.value.length > 0,
})}
/>
</Dropdown>
</>
}
className="preview-panel-search"
class="preview-panel-search"
placeholder="搜索 Token / 色值 / 文本 / 圆角等"
/>
</div>
<div
className={classNames('preview-panel-token-wrapper', {
'preview-panel-token-wrapper-ping-top': showTokenListShadowTop,
class={classNames('preview-panel-token-wrapper', {
'preview-panel-token-wrapper-ping-top': showTokenListShadowTop.value,
})}
>
<div ref={cardWrapperRef} style={{ height: '100%', overflow: 'auto', padding: '0 16px' }}>
<div
ref={cardWrapperRef}
style={{ height: '100%', overflow: 'auto', padding: '0 16px' }}
>
<div>
{TOKEN_SORTS.filter(
type =>
type !== 'seed' &&
(mergedFilterTypes.includes(type) || mergedFilterTypes.length === 0) &&
(!search ||
groupedToken[type].some(item =>
item.toLowerCase().includes(search.toLowerCase()),
(mergedFilterTypes.value.includes(type) ||
mergedFilterTypes.value.length === 0) &&
(!search.value ||
groupedToken.value[type].some(item =>
item.toLowerCase().includes(search.value.toLowerCase()),
)),
).map(key => (
<TokenCard
@ -287,22 +297,22 @@ export default forwardRef<TokenPanelRef, TokenPreviewProps>((props: TokenPreview
icon={IconMap[key]}
key={key}
tokenPath={['token']}
tokenArr={groupedToken[key]}
keyword={search}
hideUseless={!showAll}
open={activeCards.includes(key)}
onOpenChange={open =>
setActiveCards(prev =>
open ? [...prev, key] : prev.filter(item => item !== key),
)
}
tokenArr={groupedToken.value[key]}
keyword={search.value}
hideUseless={!showAll.value}
open={activeCards.value.includes(key)}
onOpenChange={open => {
activeCards.value = open
? [...activeCards.value, key]
: activeCards.value.filter(item => item !== key);
}}
onTokenChange={handleAliasTokenChange}
activeToken={activeToken}
onActiveTokenChange={tokenName => setActiveToken(tokenName)}
themes={themes}
selectedTokens={selectedTokens}
onTokenSelect={onTokenSelect}
enableTokenSelect={enableTokenSelect}
activeToken={activeToken.value}
onActiveTokenChange={tokenName => (activeToken.value = tokenName)}
themes={themes.value}
selectedTokens={selectedTokens.value}
onTokenSelect={props.onTokenSelect}
enableTokenSelect={enableTokenSelect.value}
fallback={config => getDesignToken(config) as AliasToken}
/>
))}
@ -312,4 +322,6 @@ export default forwardRef<TokenPanelRef, TokenPreviewProps>((props: TokenPreview
</div>
</div>,
);
};
},
});

View File

@ -1,3 +1,5 @@
import type { PropType } from 'vue';
import { defineComponent, toRefs, ref } from 'vue';
import {
AlignLeftOutlined,
BgColorsOutlined,
@ -12,13 +14,11 @@ import {
HighlightOutlined,
RadiusSettingOutlined,
TabletOutlined,
} from '@ant-design/icons';
import { Collapse, Space } from 'antd';
import type { ThemeConfig } from 'antd/es/config-provider/context';
import classNames from 'classnames';
import useMergedState from 'rc-util/es/hooks/useMergedState';
import type { ReactNode } from 'react';
import React from 'react';
} from '@ant-design/icons-vue';
import { Collapse, Space } from 'ant-design-vue';
import type { ThemeConfig } from 'ant-design-vue/es/config-provider/context';
import classNames from 'ant-design-vue/es/_util/classNames';
import PropTypes from 'ant-design-vue/es/_util/vue-types';
import { Motion, ShapeLine } from '../../icons';
import type { MutableTheme, TokenValue } from '../../interface';
import type { TokenType } from '../../utils/classifyToken';
@ -28,9 +28,9 @@ import TokenItem from '../token-item';
const { Panel } = Collapse;
interface TokenCardProps {
export interface TokenCardProps {
title: string;
icon?: ReactNode;
icon?: any;
tokenArr: string[];
tokenPath: string[];
keyword?: string;
@ -46,11 +46,11 @@ interface TokenCardProps {
onTokenSelect?: (token: string) => void;
enableTokenSelect?: boolean;
hideUsageCount?: boolean;
placeholder?: ReactNode;
placeholder?: any;
fallback?: (config: ThemeConfig) => Record<string, TokenValue>;
}
export const IconMap: Record<TokenType, ReactNode> = {
export const IconMap: Record<TokenType, any> = {
seed: <BulbOutlined />,
colorText: <FontColorsOutlined />,
colorBg: <BgColorsOutlined />,
@ -108,86 +108,120 @@ const useStyle = makeStyle('TokenCard', token => ({
},
}));
export default ({
export default defineComponent({
name: 'TokenCard',
props: {
title: { type: String as PropType<string> },
icon: PropTypes.any,
tokenArr: { type: Array as PropType<string[]> },
tokenPath: { type: Array as PropType<string[]> },
keyword: { type: String as PropType<string> },
hideUseless: { type: Boolean },
defaultOpen: { type: Boolean },
open: { type: Boolean },
activeToken: { type: String as PropType<string> },
themes: { type: Array as PropType<MutableTheme[]> },
selectedTokens: { type: Array as PropType<string[]> },
enableTokenSelect: { type: Boolean },
hideUsageCount: { type: Boolean },
placeholder: PropTypes.any,
onOpenChange: { type: Function as PropType<(open: boolean) => void> },
onActiveTokenChange: { type: Function as PropType<(token: string | undefined) => void> },
onTokenChange: {
type: Function as PropType<
(theme: MutableTheme, tokenName: string, value: TokenValue) => void
>,
},
onTokenSelect: { type: Function as PropType<(token: string) => void> },
fallback: { type: Function as PropType<(config: ThemeConfig) => Record<string, TokenValue>> },
},
setup(props, { attrs, slots }) {
const {
title,
icon,
tokenArr,
keyword,
hideUseless,
defaultOpen,
open: customOpen,
onOpenChange,
activeToken,
onActiveTokenChange,
onTokenChange,
tokenPath,
selectedTokens,
themes,
onTokenSelect,
enableTokenSelect,
hideUsageCount,
fallback,
placeholder,
}: TokenCardProps) => {
} = toRefs(props);
const [wrapSSR, hashId] = useStyle();
const [open, setOpen] = useMergedState(false, {
onChange: onOpenChange,
defaultValue: defaultOpen,
value: customOpen,
});
const activeKeys = ref(!!defaultOpen.value ? ['1'] : []);
return () => {
const icon = slots.icon ? slots.icon() : props.icon;
const placeholder = slots.placeholder ? slots.placeholder() : props.placeholder;
return wrapSSR(
<div className={classNames('token-card', hashId)}>
<div {...attrs} class={classNames('token-card', hashId.value)}>
<Collapse
ghost
expandIcon={({ isActive }) => (
v-slots={{
expandIcon: ({ isActive }) => (
<CaretRightOutlined
rotate={isActive ? 450 : 360}
style={{ fontSize: 12, color: 'rgba(0,0,0,0.45)' }}
style={{ fontSize: '12px', color: 'rgba(0,0,0,0.45)' }}
/>
)}
expandIconPosition="right"
className="token-card-collapse"
activeKey={open ? '1' : undefined}
onChange={keys => {
),
}}
expandIconPosition="end"
class="token-card-collapse"
v-model={[activeKeys.value, 'activeKey']}
onChange={() => {
// onOpenChange?.(keys.length > 0);
setOpen(keys.length > 0);
props.onOpenChange(activeKeys.value.length > 0);
}}
>
<Panel
header={
v-slots={{
header: () => (
<Space size="small">
<span>{title}</span>
<span>{title.value}</span>
<span>{icon}</span>
</Space>
}
),
}}
key="1"
>
{tokenArr
{tokenArr.value
.filter(
tokenName =>
(!keyword || tokenName.toLowerCase().includes(keyword.toLowerCase())) &&
(!hideUseless || getRelatedComponents(tokenName).length > 0),
(!keyword.value ||
tokenName.toLowerCase().includes(keyword.value.toLowerCase())) &&
(!hideUseless.value || getRelatedComponents(tokenName).length > 0),
)
.map(tokenName => (
.map(tokenName => {
return (
<TokenItem
tokenPath={tokenPath}
onActiveChange={active => onActiveTokenChange?.(active ? tokenName : undefined)}
active={activeToken === tokenName}
tokenPath={tokenPath.value}
onActiveChange={active =>
props.onActiveTokenChange?.(active ? tokenName : undefined)
}
active={activeToken.value === tokenName}
tokenName={tokenName}
key={tokenName}
onTokenChange={onTokenChange}
themes={themes}
selectedTokens={selectedTokens}
onTokenSelect={onTokenSelect}
enableTokenSelect={enableTokenSelect}
hideUsageCount={hideUsageCount}
fallback={fallback}
onTokenChange={props.onTokenChange}
themes={themes.value}
selectedTokens={selectedTokens.value}
onTokenSelect={props.onTokenSelect}
enableTokenSelect={enableTokenSelect.value}
hideUsageCount={hideUsageCount.value}
fallback={props.fallback}
/>
))}
{tokenArr.length === 0 && placeholder}
);
})}
{tokenArr.value.length === 0 && placeholder}
</Panel>
</Collapse>
</div>,
);
};
},
});

View File

@ -1,9 +1,9 @@
import { CaretRightOutlined } from '@ant-design/icons';
import { Collapse, Space } from 'antd';
import type { ThemeConfig } from 'antd/es/config-provider/context';
import classNames from 'classnames';
import type { CSSProperties } from 'react';
import React, { useEffect, useMemo } from 'react';
import { CaretRightOutlined } from '@ant-design/icons-vue';
import { Collapse, Space } from 'ant-design-vue';
import type { ThemeConfig } from 'ant-design-vue/es/config-provider/context';
import classNames from 'ant-design-vue/es/_util/classNames';
import type { PropType, CSSProperties } from 'vue';
import { defineComponent, toRefs, watch, computed, ref } from 'vue';
import ColorPreview from '../../ColorPreview';
import { Pick } from '../../icons';
import type { MutableTheme, TokenValue } from '../../interface';
@ -15,7 +15,7 @@ import { getRelatedComponents } from '../../utils/statistic';
const { Panel } = Collapse;
interface TokenItemProps {
export interface TokenItemProps {
tokenName: string;
tokenPath: string[];
active?: boolean;
@ -29,53 +29,52 @@ interface TokenItemProps {
fallback?: (config: ThemeConfig) => Record<string, TokenValue>;
}
const AdditionInfo = ({
info,
visible,
tokenName,
style,
dark,
...rest
}: {
info: string | number;
visible: boolean;
tokenName: string;
dark?: boolean;
style?: CSSProperties;
className?: string;
}) => {
if (typeof info === 'string' && isColor(info)) {
const AdditionInfo = defineComponent({
name: 'AdditionInfo',
props: {
info: { type: [String, Number] },
visible: { type: Boolean },
tokenName: { type: String },
dark: { type: Boolean },
},
setup(props, { attrs }) {
const { info, visible, dark } = toRefs(props);
return () => {
if (typeof info.value === 'string' && isColor(info.value)) {
return (
<ColorPreview
dark={dark}
color={String(info)}
style={{ display: visible ? 'block' : 'none', ...style }}
dark={dark.value}
color={String(info.value)}
style={{ display: visible.value ? 'block' : 'none', ...(attrs.style as CSSProperties) }}
/>
);
}
if (info.toString().length < 6 && String(info) !== '') {
if (info.value.toString().length < 6 && String(info.value) !== '') {
return (
<div
{...attrs}
style={{
height: 20,
height: '20px',
overflow: 'hidden',
backgroundColor: 'rgba(0,0,0,0.04)',
borderRadius: '8px',
display: visible ? 'block' : 'none',
display: visible.value ? 'block' : 'none',
padding: '0 6px',
lineHeight: '20px',
...style,
...(attrs.style as CSSProperties),
}}
{...rest}
>
{info}
{info.value}
</div>
);
}
return null;
};
},
});
const ShowUsageButton = ({
selected,
@ -85,17 +84,18 @@ const ShowUsageButton = ({
toggleSelected: (v: boolean) => void;
}) => {
return (
<span
style={{ marginInlineStart: '12px', verticalAlign: 'middle', cursor: 'pointer' }}
onClick={() => toggleSelected(!selected)}
>
<Pick
style={{
color: selected ? '#1890ff' : undefined,
cursor: 'pointer',
fontSize: 16,
fontSize: '16px',
transition: 'color 0.3s',
marginInlineStart: 12,
verticalAlign: 'middle',
}}
onClick={() => toggleSelected(!selected)}
/>
</span>
);
};
@ -177,52 +177,74 @@ const useStyle = makeStyle('TokenItem', token => ({
export const getTokenItemId = (token: string) => `previewer-token-panel-item-${token}`;
export default ({
export default defineComponent({
name: 'TokenItem',
props: {
tokenName: { type: String },
tokenPath: { type: Array as PropType<string[]> },
active: { type: Boolean },
themes: { type: Array as PropType<MutableTheme[]> },
selectedTokens: { type: Array as PropType<string[]> },
enableTokenSelect: { type: Boolean },
hideUsageCount: { type: Boolean },
onActiveChange: { type: Function as PropType<(active: boolean) => void> },
onTokenChange: {
type: Function as PropType<
(theme: MutableTheme, tokenName: string, value: TokenValue) => void
>,
},
onTokenSelect: { type: Function as PropType<(token: string) => void> },
fallback: { type: Function as PropType<(config: ThemeConfig) => Record<string, TokenValue>> },
},
setup(props, { attrs }) {
const {
tokenName,
active,
onActiveChange,
onTokenChange,
tokenPath,
selectedTokens,
themes,
onTokenSelect,
enableTokenSelect,
hideUsageCount,
fallback,
}: TokenItemProps) => {
const [infoVisible, setInfoVisible] = React.useState(false);
} = toRefs(props);
const infoVisible = ref(false);
const [wrapSSR, hashId] = useStyle();
useEffect(() => {
if (active) {
setInfoVisible(true);
watch(
active,
val => {
if (val) {
infoVisible.value = true;
}
}, [active]);
},
{ immediate: true },
);
const handleTokenChange = (theme: MutableTheme, value: TokenValue) => {
onTokenChange?.(theme, tokenName, value);
props.onTokenChange?.(theme, tokenName.value, value);
};
const count = useMemo(() => getRelatedComponents(tokenName).length, [tokenName]);
const count = computed(() => getRelatedComponents(tokenName.value).length);
return () => {
return wrapSSR(
<div onMouseEnter={() => onActiveChange?.(false)}>
<div {...attrs} onMouseenter={() => props.onActiveChange?.(false)}>
<Collapse
collapsible="header"
ghost
onChange={key => setInfoVisible(key.length > 0)}
className={classNames('previewer-token-item-collapse', hashId)}
onChange={key => (infoVisible.value = Array.isArray(key) ? key.length > 0 : !!key)}
class={classNames('previewer-token-item-collapse', hashId.value)}
expandIcon={({ isActive }) => (
<CaretRightOutlined
rotate={isActive ? 90 : 0}
style={{ fontSize: 12, cursor: 'pointer' }}
style={{ fontSize: '12px', cursor: 'pointer' }}
/>
)}
activeKey={infoVisible ? tokenName : undefined}
activeKey={infoVisible.value ? tokenName.value : undefined}
>
<Panel
key={tokenName}
className="previewer-token-item"
key={tokenName.value}
class="previewer-token-item"
header={
<div
style={{
@ -230,7 +252,7 @@ export default ({
alignItems: 'center',
gap: 8,
}}
id={getTokenItemId(tokenName)}
id={getTokenItemId(tokenName.value)}
>
<span
style={{
@ -242,9 +264,9 @@ export default ({
}}
>
<span
title={tokenName}
className={classNames('previewer-token-item-name', {
'previewer-token-item-highlighted': active,
title={tokenName.value}
class={classNames('previewer-token-item-name', {
'previewer-token-item-highlighted': active.value,
})}
style={{
marginInlineEnd: '5px',
@ -252,29 +274,31 @@ export default ({
textOverflow: 'ellipsis',
}}
>
{tokenName}
{tokenName.value}
</span>
{!hideUsageCount && <span className="previewer-token-count">{count}</span>}
{!hideUsageCount.value && (
<span class="previewer-token-count">{count.value}</span>
)}
</span>
{!infoVisible && (
{!infoVisible.value && (
<div
className="previewer-token-preview"
class="previewer-token-preview"
style={{
minWidth: themes.length * 20 + (themes.length - 1) * 4,
minWidth: themes.value.length * 20 + (themes.value.length - 1) * 4,
}}
>
{themes.map(({ config, key }, index) => {
{themes.value.map(({ config, key }, index) => {
return (
<AdditionInfo
key={key}
dark={key === 'dark'}
tokenName={tokenName}
tokenName={tokenName.value}
info={
getValueByPath(config, [...tokenPath, tokenName]) ??
fallback?.(config)[tokenName] ??
getValueByPath(config, [...tokenPath.value, tokenName.value]) ??
props.fallback?.(config)[tokenName.value] ??
''
}
visible={!infoVisible}
visible={!infoVisible.value}
style={{
zIndex: 10 - index,
}}
@ -286,11 +310,11 @@ export default ({
</div>
}
extra={
enableTokenSelect ? (
enableTokenSelect.value ? (
<ShowUsageButton
selected={!!selectedTokens?.includes(tokenName)}
selected={!!selectedTokens.value?.includes(tokenName.value)}
toggleSelected={() => {
onTokenSelect?.(tokenName);
props.onTokenSelect?.(tokenName.value);
}}
/>
) : undefined
@ -300,21 +324,21 @@ export default ({
direction="vertical"
style={{
background: '#fafafa',
borderRadius: 4,
padding: 8,
borderRadius: '4px',
padding: '8px',
width: '100%',
}}
>
{themes.map(theme => {
{themes.value.map(theme => {
return (
<div key={theme.key}>
<TokenInput
hideTheme={themes.length === 1}
hideTheme={themes.value.length === 1}
theme={theme}
onChange={value => handleTokenChange(theme, value)}
value={
getValueByPath(theme.config, [...tokenPath, tokenName]) ??
fallback?.(theme.config)[tokenName]
getValueByPath(theme.config, [...tokenPath.value, tokenName.value]) ??
props.fallback?.(theme.config)[tokenName.value]
}
/>
</div>
@ -326,3 +350,5 @@ export default ({
</div>,
);
};
},
});

View File

@ -1,5 +1,5 @@
import type { PropType } from 'vue';
import { defineComponent, toRefs, computed, ref } from 'vue';
import { defineComponent, toRefs, ref, computed } from 'vue';
import { Hue } from './Hue';
import { Saturation } from './Saturation';
@ -10,7 +10,8 @@ import { useColorManipulation } from '../../hooks/useColorManipulation';
import { useStyleSheet } from '../../hooks/useStyleSheet';
import { formatClassName } from '../../utils/format';
export interface AlphaColorPicker<T extends AnyColor> extends Partial<ColorPickerBaseProps<T>> {
export interface AlphaColorPickerProps<T extends AnyColor>
extends Partial<ColorPickerBaseProps<T>> {
colorModel: ColorModel<T>;
}
@ -29,7 +30,11 @@ export const AlphaColorPicker = defineComponent({
const mergedColor = computed(() => color.value || colorModel.value.defaultColor);
const [hsva, updateHsva] = useColorManipulation(colorModel, mergedColor, props.onChange);
const [hsva, updateHsva] = useColorManipulation<AnyColor>(
colorModel,
mergedColor,
props.onChange,
);
return () => {
const nodeClassName = formatClassName(['vue-colorful', attrs.class]);