refactor: image
parent
e8918ce589
commit
c7b15a96a8
|
@ -1,3 +1,4 @@
|
||||||
|
import type { PreviewGroupPreview } from '../vc-image/src/PreviewGroup';
|
||||||
import PreviewGroup from '../vc-image/src/PreviewGroup';
|
import PreviewGroup from '../vc-image/src/PreviewGroup';
|
||||||
import { computed, defineComponent } from 'vue';
|
import { computed, defineComponent } from 'vue';
|
||||||
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
|
@ -9,6 +10,8 @@ import ZoomOutOutlined from '@ant-design/icons-vue/ZoomOutOutlined';
|
||||||
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
|
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
|
||||||
import LeftOutlined from '@ant-design/icons-vue/LeftOutlined';
|
import LeftOutlined from '@ant-design/icons-vue/LeftOutlined';
|
||||||
import RightOutlined from '@ant-design/icons-vue/RightOutlined';
|
import RightOutlined from '@ant-design/icons-vue/RightOutlined';
|
||||||
|
import useStyle from './style';
|
||||||
|
import { anyType } from '../_util/type';
|
||||||
|
|
||||||
export const icons = {
|
export const icons = {
|
||||||
rotateLeft: <RotateLeftOutlined />,
|
rotateLeft: <RotateLeftOutlined />,
|
||||||
|
@ -24,18 +27,32 @@ const InternalPreviewGroup = defineComponent({
|
||||||
compatConfig: { MODE: 3 },
|
compatConfig: { MODE: 3 },
|
||||||
name: 'AImagePreviewGroup',
|
name: 'AImagePreviewGroup',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: { previewPrefixCls: String },
|
props: { previewPrefixCls: String, preview: anyType<boolean | PreviewGroupPreview>() },
|
||||||
setup(props, { attrs, slots }) {
|
setup(props, { attrs, slots }) {
|
||||||
const { getPrefixCls } = useConfigInject('image', props);
|
const { prefixCls } = useConfigInject('image', props);
|
||||||
const prefixCls = computed(() => getPrefixCls('image-preview', props.previewPrefixCls));
|
const previewPrefixCls = computed(() => `${prefixCls.value}-preview`);
|
||||||
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
|
const mergedPreview = computed(() => {
|
||||||
|
const { preview } = props;
|
||||||
|
if (preview === false) {
|
||||||
|
return preview;
|
||||||
|
}
|
||||||
|
const _preview = typeof preview === 'object' ? preview : {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
..._preview,
|
||||||
|
rootClassName: hashId.value,
|
||||||
|
};
|
||||||
|
});
|
||||||
return () => {
|
return () => {
|
||||||
return (
|
return wrapSSR(
|
||||||
<PreviewGroup
|
<PreviewGroup
|
||||||
{...{ ...attrs, ...props }}
|
{...{ ...attrs, ...props }}
|
||||||
|
preview={mergedPreview.value}
|
||||||
icons={icons}
|
icons={icons}
|
||||||
previewPrefixCls={prefixCls.value}
|
previewPrefixCls={previewPrefixCls.value}
|
||||||
v-slots={slots}
|
v-slots={slots}
|
||||||
></PreviewGroup>
|
></PreviewGroup>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
category: Components
|
category: Components
|
||||||
type: Data Display
|
type: Data Display
|
||||||
title: Image
|
title: Image
|
||||||
cover: https://gw.alipayobjects.com/zos/antfincdn/D1dXz9PZqa/image.svg
|
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*FbOCS6aFMeUAAAAAAAAAAAAADrJ8AQ/original
|
||||||
---
|
---
|
||||||
|
|
||||||
Previewable image.
|
Previewable image.
|
||||||
|
@ -33,7 +33,7 @@ Previewable image.
|
||||||
|
|
||||||
### previewType
|
### previewType
|
||||||
|
|
||||||
```js
|
```ts
|
||||||
{
|
{
|
||||||
visible?: boolean;
|
visible?: boolean;
|
||||||
onVisibleChange?: (visible, prevVisible) => void;
|
onVisibleChange?: (visible, prevVisible) => void;
|
||||||
|
|
|
@ -7,7 +7,8 @@ import useConfigInject from '../config-provider/hooks/useConfigInject';
|
||||||
import PreviewGroup, { icons } from './PreviewGroup';
|
import PreviewGroup, { icons } from './PreviewGroup';
|
||||||
import EyeOutlined from '@ant-design/icons-vue/EyeOutlined';
|
import EyeOutlined from '@ant-design/icons-vue/EyeOutlined';
|
||||||
import { getTransitionName } from '../_util/transition';
|
import { getTransitionName } from '../_util/transition';
|
||||||
|
import useStyle from './style';
|
||||||
|
import classNames from '../_util/classNames';
|
||||||
export type ImageProps = Partial<
|
export type ImageProps = Partial<
|
||||||
ExtractPropTypes<ReturnType<typeof imageProps>> &
|
ExtractPropTypes<ReturnType<typeof imageProps>> &
|
||||||
Omit<ImgHTMLAttributes, 'placeholder' | 'onClick'>
|
Omit<ImgHTMLAttributes, 'placeholder' | 'onClick'>
|
||||||
|
@ -18,6 +19,8 @@ const Image = defineComponent<ImageProps>({
|
||||||
props: imageProps() as any,
|
props: imageProps() as any,
|
||||||
setup(props, { slots, attrs }) {
|
setup(props, { slots, attrs }) {
|
||||||
const { prefixCls, rootPrefixCls, configProvider } = useConfigInject('image', props);
|
const { prefixCls, rootPrefixCls, configProvider } = useConfigInject('image', props);
|
||||||
|
// Style
|
||||||
|
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||||
|
|
||||||
const mergedPreview = computed(() => {
|
const mergedPreview = computed(() => {
|
||||||
const { preview } = props;
|
const { preview } = props;
|
||||||
|
@ -48,15 +51,16 @@ const Image = defineComponent<ImageProps>({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
const { previewMask = slots.previewMask || defaultPreviewMask } = props;
|
const { previewMask = slots.previewMask || defaultPreviewMask } = props;
|
||||||
return (
|
return wrapSSR(
|
||||||
<ImageInternal
|
<ImageInternal
|
||||||
{...{ ...attrs, ...props, prefixCls: prefixCls.value }}
|
{...{ ...attrs, ...props, prefixCls: prefixCls.value }}
|
||||||
preview={mergedPreview.value}
|
preview={mergedPreview.value}
|
||||||
|
rootClassName={classNames(props.rootClassName, hashId.value)}
|
||||||
v-slots={{
|
v-slots={{
|
||||||
...slots,
|
...slots,
|
||||||
previewMask: typeof previewMask === 'function' ? previewMask : null,
|
previewMask: typeof previewMask === 'function' ? previewMask : null,
|
||||||
}}
|
}}
|
||||||
></ImageInternal>
|
></ImageInternal>,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@ category: Components
|
||||||
type: 数据展示
|
type: 数据展示
|
||||||
title: Image
|
title: Image
|
||||||
subtitle: 图片
|
subtitle: 图片
|
||||||
cover: https://gw.alipayobjects.com/zos/antfincdn/D1dXz9PZqa/image.svg
|
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*FbOCS6aFMeUAAAAAAAAAAAAADrJ8AQ/original
|
||||||
---
|
---
|
||||||
|
|
||||||
可预览的图片。
|
可预览的图片。
|
||||||
|
@ -34,7 +34,7 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/D1dXz9PZqa/image.svg
|
||||||
|
|
||||||
### previewType
|
### previewType
|
||||||
|
|
||||||
```js
|
```ts
|
||||||
{
|
{
|
||||||
visible?: boolean;
|
visible?: boolean;
|
||||||
onVisibleChange?: (visible, prevVisible) => void;
|
onVisibleChange?: (visible, prevVisible) => void;
|
||||||
|
|
|
@ -1,187 +0,0 @@
|
||||||
@import '../../style/themes/index';
|
|
||||||
@import '../../style/mixins/index';
|
|
||||||
|
|
||||||
@image-prefix-cls: ~'@{ant-prefix}-image';
|
|
||||||
@image-preview-prefix-cls: ~'@{image-prefix-cls}-preview';
|
|
||||||
|
|
||||||
.@{image-prefix-cls} {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
&-img {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
vertical-align: middle;
|
|
||||||
|
|
||||||
&-placeholder {
|
|
||||||
background-color: @image-bg;
|
|
||||||
background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTQuNSAyLjVoLTEzQS41LjUgMCAwIDAgMSAzdjEwYS41LjUgMCAwIDAgLjUuNWgxM2EuNS41IDAgMCAwIC41LS41VjNhLjUuNSAwIDAgMC0uNS0uNXpNNS4yODEgNC43NWExIDEgMCAwIDEgMCAyIDEgMSAwIDAgMSAwLTJ6bTguMDMgNi44M2EuMTI3LjEyNyAwIDAgMS0uMDgxLjAzSDIuNzY5YS4xMjUuMTI1IDAgMCAxLS4wOTYtLjIwN2wyLjY2MS0zLjE1NmEuMTI2LjEyNiAwIDAgMSAuMTc3LS4wMTZsLjAxNi4wMTZMNy4wOCAxMC4wOWwyLjQ3LTIuOTNhLjEyNi4xMjYgMCAwIDEgLjE3Ny0uMDE2bC4wMTUuMDE2IDMuNTg4IDQuMjQ0YS4xMjcuMTI3IDAgMCAxLS4wMi4xNzV6IiBmaWxsPSIjOEM4QzhDIiBmaWxsLXJ1bGU9Im5vbnplcm8iLz48L3N2Zz4=');
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center center;
|
|
||||||
background-size: 30%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-mask {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: @text-color-inverse;
|
|
||||||
background: fade(@black, 50%);
|
|
||||||
cursor: pointer;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity @animation-duration-slow;
|
|
||||||
|
|
||||||
&-info {
|
|
||||||
padding: 0 @padding-xss;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
.@{iconfont-css-prefix} {
|
|
||||||
margin-inline-end: @margin-xss;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-placeholder {
|
|
||||||
.box();
|
|
||||||
}
|
|
||||||
|
|
||||||
&-preview {
|
|
||||||
.modal-mask();
|
|
||||||
|
|
||||||
height: 100%;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
&-body {
|
|
||||||
.box();
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-img {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
vertical-align: middle;
|
|
||||||
transform: scale3d(1, 1, 1);
|
|
||||||
cursor: grab;
|
|
||||||
transition: transform 0.3s @ease-out 0s;
|
|
||||||
user-select: none;
|
|
||||||
pointer-events: auto;
|
|
||||||
|
|
||||||
&-wrapper {
|
|
||||||
.box();
|
|
||||||
transition: transform 0.3s @ease-out 0s;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
display: inline-block;
|
|
||||||
width: 1px;
|
|
||||||
height: 50%;
|
|
||||||
margin-right: -1px;
|
|
||||||
content: '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-moving {
|
|
||||||
.@{image-prefix-cls}-preview-img {
|
|
||||||
cursor: grabbing;
|
|
||||||
|
|
||||||
&-wrapper {
|
|
||||||
transition-duration: 0s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-wrap {
|
|
||||||
z-index: @zindex-image;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-operations {
|
|
||||||
.reset-component();
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
color: @image-preview-operation-color;
|
|
||||||
list-style: none;
|
|
||||||
background: fade(@modal-mask-bg, 10%);
|
|
||||||
pointer-events: auto;
|
|
||||||
|
|
||||||
&-operation {
|
|
||||||
margin-left: @control-padding-horizontal;
|
|
||||||
padding: @control-padding-horizontal;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&-disabled {
|
|
||||||
color: @image-preview-operation-disabled-color;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-of-type {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-progress {
|
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&-icon {
|
|
||||||
font-size: @image-preview-operation-size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-switch-left,
|
|
||||||
&-switch-right {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 10px;
|
|
||||||
z-index: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
margin-top: -22px;
|
|
||||||
color: @image-preview-operation-color;
|
|
||||||
background: fade(@modal-mask-bg, 10%);
|
|
||||||
border-radius: 50%;
|
|
||||||
cursor: pointer;
|
|
||||||
pointer-events: auto;
|
|
||||||
|
|
||||||
&-disabled {
|
|
||||||
color: @image-preview-operation-disabled-color;
|
|
||||||
cursor: not-allowed;
|
|
||||||
> .@{iconfont-css-prefix} {
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
> .@{iconfont-css-prefix} {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-switch-left {
|
|
||||||
left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-switch-right {
|
|
||||||
right: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,322 @@
|
||||||
|
import { CSSObject } from '../../_util/cssinjs';
|
||||||
|
import { TinyColor } from '@ctrl/tinycolor';
|
||||||
|
import { genModalMaskStyle } from '../../modal/style';
|
||||||
|
import { initZoomMotion, initFadeMotion } from '../../_style/motion';
|
||||||
|
import type { FullToken, GenerateStyle } from '../../theme/internal';
|
||||||
|
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
|
||||||
|
import { resetComponent, textEllipsis } from '../../_style';
|
||||||
|
|
||||||
|
export interface ComponentToken {
|
||||||
|
zIndexPopup: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImageToken extends FullToken<'Image'> {
|
||||||
|
previewCls: string;
|
||||||
|
modalMaskBg: string;
|
||||||
|
imagePreviewOperationDisabledColor: string;
|
||||||
|
imagePreviewOperationSize: number;
|
||||||
|
imagePreviewSwitchSize: number;
|
||||||
|
imagePreviewOperationColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PositionType = 'static' | 'relative' | 'fixed' | 'absolute' | 'sticky' | undefined;
|
||||||
|
|
||||||
|
export const genBoxStyle = (position?: PositionType): CSSObject => ({
|
||||||
|
position: position || 'absolute',
|
||||||
|
inset: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const genImageMaskStyle = (token: ImageToken): CSSObject => {
|
||||||
|
const { iconCls, motionDurationSlow, paddingXXS, marginXXS, prefixCls } = token;
|
||||||
|
return {
|
||||||
|
position: 'absolute',
|
||||||
|
inset: 0,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
color: '#fff',
|
||||||
|
background: new TinyColor('#000').setAlpha(0.5).toRgbString(),
|
||||||
|
cursor: 'pointer',
|
||||||
|
opacity: 0,
|
||||||
|
transition: `opacity ${motionDurationSlow}`,
|
||||||
|
|
||||||
|
[`.${prefixCls}-mask-info`]: {
|
||||||
|
...textEllipsis,
|
||||||
|
padding: `0 ${paddingXXS}px`,
|
||||||
|
[iconCls]: {
|
||||||
|
marginInlineEnd: marginXXS,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const genPreviewOperationsStyle = (token: ImageToken): CSSObject => {
|
||||||
|
const {
|
||||||
|
previewCls,
|
||||||
|
modalMaskBg,
|
||||||
|
paddingSM,
|
||||||
|
imagePreviewOperationDisabledColor,
|
||||||
|
motionDurationSlow,
|
||||||
|
} = token;
|
||||||
|
|
||||||
|
const operationBg = new TinyColor(modalMaskBg).setAlpha(0.1);
|
||||||
|
const operationBgHover = operationBg.clone().setAlpha(0.2);
|
||||||
|
|
||||||
|
return {
|
||||||
|
[`${previewCls}-operations`]: {
|
||||||
|
...resetComponent(token),
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row-reverse',
|
||||||
|
alignItems: 'center',
|
||||||
|
color: token.imagePreviewOperationColor,
|
||||||
|
listStyle: 'none',
|
||||||
|
background: operationBg.toRgbString(),
|
||||||
|
pointerEvents: 'auto',
|
||||||
|
|
||||||
|
'&-operation': {
|
||||||
|
marginInlineStart: paddingSM,
|
||||||
|
padding: paddingSM,
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: `all ${motionDurationSlow}`,
|
||||||
|
|
||||||
|
'&:hover': {
|
||||||
|
background: operationBgHover.toRgbString(),
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-disabled': {
|
||||||
|
color: imagePreviewOperationDisabledColor,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:last-of-type': {
|
||||||
|
marginInlineStart: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-progress': {
|
||||||
|
position: 'absolute',
|
||||||
|
left: { _skip_check_: true, value: '50%' },
|
||||||
|
transform: 'translateX(-50%)',
|
||||||
|
},
|
||||||
|
|
||||||
|
'&-icon': {
|
||||||
|
fontSize: token.imagePreviewOperationSize,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const genPreviewSwitchStyle = (token: ImageToken): CSSObject => {
|
||||||
|
const {
|
||||||
|
modalMaskBg,
|
||||||
|
iconCls,
|
||||||
|
imagePreviewOperationDisabledColor,
|
||||||
|
previewCls,
|
||||||
|
zIndexPopup,
|
||||||
|
motionDurationSlow,
|
||||||
|
} = token;
|
||||||
|
|
||||||
|
const operationBg = new TinyColor(modalMaskBg).setAlpha(0.1);
|
||||||
|
const operationBgHover = operationBg.clone().setAlpha(0.2);
|
||||||
|
|
||||||
|
return {
|
||||||
|
[`${previewCls}-switch-left, ${previewCls}-switch-right`]: {
|
||||||
|
position: 'fixed',
|
||||||
|
insetBlockStart: '50%',
|
||||||
|
zIndex: zIndexPopup + 1,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
width: token.imagePreviewSwitchSize,
|
||||||
|
height: token.imagePreviewSwitchSize,
|
||||||
|
marginTop: -token.imagePreviewSwitchSize / 2,
|
||||||
|
color: token.imagePreviewOperationColor,
|
||||||
|
background: operationBg.toRgbString(),
|
||||||
|
borderRadius: '50%',
|
||||||
|
transform: `translateY(-50%)`,
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: `all ${motionDurationSlow}`,
|
||||||
|
pointerEvents: 'auto',
|
||||||
|
|
||||||
|
'&:hover': {
|
||||||
|
background: operationBgHover.toRgbString(),
|
||||||
|
},
|
||||||
|
|
||||||
|
[`&-disabled`]: {
|
||||||
|
'&, &:hover': {
|
||||||
|
color: imagePreviewOperationDisabledColor,
|
||||||
|
background: 'transparent',
|
||||||
|
cursor: 'not-allowed',
|
||||||
|
[`> ${iconCls}`]: {
|
||||||
|
cursor: 'not-allowed',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[`> ${iconCls}`]: {
|
||||||
|
fontSize: token.imagePreviewOperationSize,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${previewCls}-switch-left`]: {
|
||||||
|
insetInlineStart: token.marginSM,
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${previewCls}-switch-right`]: {
|
||||||
|
insetInlineEnd: token.marginSM,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const genImagePreviewStyle: GenerateStyle<ImageToken> = (token: ImageToken) => {
|
||||||
|
const { motionEaseOut, previewCls, motionDurationSlow, componentCls } = token;
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
[`${componentCls}-preview-root`]: {
|
||||||
|
[previewCls]: {
|
||||||
|
height: '100%',
|
||||||
|
textAlign: 'center',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${previewCls}-body`]: {
|
||||||
|
...genBoxStyle(),
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${previewCls}-img`]: {
|
||||||
|
maxWidth: '100%',
|
||||||
|
maxHeight: '100%',
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
transform: 'scale3d(1, 1, 1)',
|
||||||
|
cursor: 'grab',
|
||||||
|
transition: `transform ${motionDurationSlow} ${motionEaseOut} 0s`,
|
||||||
|
userSelect: 'none',
|
||||||
|
pointerEvents: 'auto',
|
||||||
|
|
||||||
|
'&-wrapper': {
|
||||||
|
...genBoxStyle(),
|
||||||
|
transition: `transform ${motionDurationSlow} ${motionEaseOut} 0s`,
|
||||||
|
|
||||||
|
// https://github.com/ant-design/ant-design/issues/39913
|
||||||
|
// TailwindCSS will reset img default style.
|
||||||
|
// Let's set back.
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
|
||||||
|
'&::before': {
|
||||||
|
display: 'inline-block',
|
||||||
|
width: 1,
|
||||||
|
height: '50%',
|
||||||
|
marginInlineEnd: -1,
|
||||||
|
content: '""',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
[`${previewCls}-moving`]: {
|
||||||
|
[`${previewCls}-preview-img`]: {
|
||||||
|
cursor: 'grabbing',
|
||||||
|
|
||||||
|
'&-wrapper': {
|
||||||
|
transitionDuration: '0s',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Override
|
||||||
|
{
|
||||||
|
[`${componentCls}-preview-root`]: {
|
||||||
|
[`${previewCls}-wrap`]: {
|
||||||
|
zIndex: token.zIndexPopup,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Preview operations & switch
|
||||||
|
{
|
||||||
|
[`${componentCls}-preview-operations-wrapper`]: {
|
||||||
|
position: 'fixed',
|
||||||
|
insetBlockStart: 0,
|
||||||
|
insetInlineEnd: 0,
|
||||||
|
zIndex: token.zIndexPopup + 1,
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
'&': [genPreviewOperationsStyle(token), genPreviewSwitchStyle(token)],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const genImageStyle: GenerateStyle<ImageToken> = (token: ImageToken) => {
|
||||||
|
const { componentCls } = token;
|
||||||
|
return {
|
||||||
|
// ============================== image ==============================
|
||||||
|
[componentCls]: {
|
||||||
|
position: 'relative',
|
||||||
|
display: 'inline-block',
|
||||||
|
[`${componentCls}-img`]: {
|
||||||
|
width: '100%',
|
||||||
|
height: 'auto',
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
},
|
||||||
|
[`${componentCls}-img-placeholder`]: {
|
||||||
|
backgroundColor: token.colorBgContainerDisabled,
|
||||||
|
backgroundImage:
|
||||||
|
"url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTQuNSAyLjVoLTEzQS41LjUgMCAwIDAgMSAzdjEwYS41LjUgMCAwIDAgLjUuNWgxM2EuNS41IDAgMCAwIC41LS41VjNhLjUuNSAwIDAgMC0uNS0uNXpNNS4yODEgNC43NWExIDEgMCAwIDEgMCAyIDEgMSAwIDAgMSAwLTJ6bTguMDMgNi44M2EuMTI3LjEyNyAwIDAgMS0uMDgxLjAzSDIuNzY5YS4xMjUuMTI1IDAgMCAxLS4wOTYtLjIwN2wyLjY2MS0zLjE1NmEuMTI2LjEyNiAwIDAgMSAuMTc3LS4wMTZsLjAxNi4wMTZMNy4wOCAxMC4wOWwyLjQ3LTIuOTNhLjEyNi4xMjYgMCAwIDEgLjE3Ny0uMDE2bC4wMTUuMDE2IDMuNTg4IDQuMjQ0YS4xMjcuMTI3IDAgMCAxLS4wMi4xNzV6IiBmaWxsPSIjOEM4QzhDIiBmaWxsLXJ1bGU9Im5vbnplcm8iLz48L3N2Zz4=')",
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'center center',
|
||||||
|
backgroundSize: '30%',
|
||||||
|
},
|
||||||
|
[`${componentCls}-mask`]: {
|
||||||
|
...genImageMaskStyle(token),
|
||||||
|
},
|
||||||
|
[`${componentCls}-mask:hover`]: {
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
[`${componentCls}-placeholder`]: {
|
||||||
|
...genBoxStyle(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const genPreviewMotion: GenerateStyle<ImageToken> = token => {
|
||||||
|
const { previewCls } = token;
|
||||||
|
|
||||||
|
return {
|
||||||
|
[`${previewCls}-root`]: initZoomMotion(token, 'zoom'),
|
||||||
|
[`&`]: initFadeMotion(token, true),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============================== Export ==============================
|
||||||
|
export default genComponentStyleHook(
|
||||||
|
'Image',
|
||||||
|
token => {
|
||||||
|
const imagePreviewOperationColor = new TinyColor(token.colorTextLightSolid);
|
||||||
|
const previewCls = `${token.componentCls}-preview`;
|
||||||
|
|
||||||
|
const imageToken = mergeToken<ImageToken>(token, {
|
||||||
|
previewCls,
|
||||||
|
imagePreviewOperationColor: imagePreviewOperationColor.toRgbString(),
|
||||||
|
imagePreviewOperationDisabledColor: new TinyColor(imagePreviewOperationColor)
|
||||||
|
.setAlpha(0.25)
|
||||||
|
.toRgbString(),
|
||||||
|
modalMaskBg: new TinyColor('#000').setAlpha(0.45).toRgbString(), // FIXME: Shared Token
|
||||||
|
imagePreviewOperationSize: token.fontSizeIcon * 1.5, // FIXME: fontSizeIconLG
|
||||||
|
imagePreviewSwitchSize: token.controlHeightLG,
|
||||||
|
});
|
||||||
|
|
||||||
|
return [
|
||||||
|
genImageStyle(imageToken),
|
||||||
|
genImagePreviewStyle(imageToken),
|
||||||
|
genModalMaskStyle(mergeToken<ImageToken>(imageToken, { componentCls: previewCls })),
|
||||||
|
genPreviewMotion(imageToken),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
token => ({
|
||||||
|
zIndexPopup: token.zIndexPopupBase + 80,
|
||||||
|
}),
|
||||||
|
);
|
|
@ -1,2 +0,0 @@
|
||||||
import '../../style/index.less';
|
|
||||||
import './index.less';
|
|
|
@ -59,6 +59,6 @@ import './drawer/style';
|
||||||
// import './page-header/style';
|
// import './page-header/style';
|
||||||
import './form/style';
|
import './form/style';
|
||||||
// import './space/style';
|
// import './space/style';
|
||||||
import './image/style';
|
// import './image/style';
|
||||||
// import './typography/style';
|
// import './typography/style';
|
||||||
// import './color-picker/style';
|
// import './color-picker/style';
|
||||||
|
|
|
@ -15,7 +15,7 @@ import type { ComponentToken as DividerComponentToken } from '../../divider/styl
|
||||||
import type { ComponentToken as DropdownComponentToken } from '../../dropdown/style';
|
import type { ComponentToken as DropdownComponentToken } from '../../dropdown/style';
|
||||||
// import type { ComponentToken as DrawerComponentToken } from '../../drawer/style';
|
// import type { ComponentToken as DrawerComponentToken } from '../../drawer/style';
|
||||||
import type { ComponentToken as EmptyComponentToken } from '../../empty/style';
|
import type { ComponentToken as EmptyComponentToken } from '../../empty/style';
|
||||||
// import type { ComponentToken as ImageComponentToken } from '../../image/style';
|
import type { ComponentToken as ImageComponentToken } from '../../image/style';
|
||||||
import type { ComponentToken as InputNumberComponentToken } from '../../input-number/style';
|
import type { ComponentToken as InputNumberComponentToken } from '../../input-number/style';
|
||||||
import type { ComponentToken as LayoutComponentToken } from '../../layout/style';
|
import type { ComponentToken as LayoutComponentToken } from '../../layout/style';
|
||||||
import type { ComponentToken as ListComponentToken } from '../../list/style';
|
import type { ComponentToken as ListComponentToken } from '../../list/style';
|
||||||
|
@ -75,7 +75,7 @@ export interface ComponentTokenMap {
|
||||||
// FloatButton?: FloatButtonComponentToken;
|
// FloatButton?: FloatButtonComponentToken;
|
||||||
Form?: {};
|
Form?: {};
|
||||||
Grid?: {};
|
Grid?: {};
|
||||||
// Image?: ImageComponentToken;
|
Image?: ImageComponentToken;
|
||||||
Input?: {};
|
Input?: {};
|
||||||
InputNumber?: InputNumberComponentToken;
|
InputNumber?: InputNumberComponentToken;
|
||||||
Layout?: LayoutComponentToken;
|
Layout?: LayoutComponentToken;
|
||||||
|
@ -89,7 +89,7 @@ export interface ComponentTokenMap {
|
||||||
Rate?: RateComponentToken;
|
Rate?: RateComponentToken;
|
||||||
// Radio?: RadioComponentToken;
|
// Radio?: RadioComponentToken;
|
||||||
Result?: ResultComponentToken;
|
Result?: ResultComponentToken;
|
||||||
// Segmented?: SegmentedComponentToken;
|
Segmented?: SegmentedComponentToken;
|
||||||
Select?: SelectComponentToken;
|
Select?: SelectComponentToken;
|
||||||
Skeleton?: SkeletonComponentToken;
|
Skeleton?: SkeletonComponentToken;
|
||||||
Slider?: SliderComponentToken;
|
Slider?: SliderComponentToken;
|
||||||
|
@ -119,5 +119,4 @@ export interface ComponentTokenMap {
|
||||||
|
|
||||||
// /** @private Internal TS definition. Do not use. */
|
// /** @private Internal TS definition. Do not use. */
|
||||||
// Wave?: WaveToken;
|
// Wave?: WaveToken;
|
||||||
Segmented?: SegmentedComponentToken;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue