diff --git a/components/_util/util.ts b/components/_util/util.ts
index 8140af3fa..172f5a4c8 100644
--- a/components/_util/util.ts
+++ b/components/_util/util.ts
@@ -1,11 +1,11 @@
-export const isFunction = val => typeof val === 'function';
+export const isFunction = (val: unknown): val is Function => typeof val === 'function';
export const isArray = Array.isArray;
-export const isString = val => typeof val === 'string';
-export const isSymbol = val => typeof val === 'symbol';
-export const isObject = val => val !== null && typeof val === 'object';
+export const isString = (val: unknown): val is string => typeof val === 'string';
+export const isSymbol = (val: unknown): val is symbol => typeof val === 'symbol';
+export const isObject = (val: unknown): val is object => val !== null && typeof val === 'object';
const onRE = /^on[^a-z]/;
-const isOn = key => onRE.test(key);
+const isOn = (key: string) => onRE.test(key);
const cacheStringFunction = fn => {
const cache = Object.create(null);
@@ -20,16 +20,16 @@ const camelize = cacheStringFunction(str => {
});
const hyphenateRE = /\B([A-Z])/g;
-const hyphenate = cacheStringFunction(str => {
+const hyphenate = cacheStringFunction((str: string) => {
return str.replace(hyphenateRE, '-$1').toLowerCase();
});
-const capitalize = cacheStringFunction(str => {
+const capitalize = cacheStringFunction((str: string) => {
return str.charAt(0).toUpperCase() + str.slice(1);
});
const hasOwnProperty = Object.prototype.hasOwnProperty;
-const hasOwn = (val, key) => hasOwnProperty.call(val, key);
+const hasOwn = (val: object, key: string) => hasOwnProperty.call(val, key);
// change from vue sourcecode
function resolvePropValue(options, props, key, value) {
diff --git a/components/comment/index.jsx b/components/comment/index.jsx
deleted file mode 100644
index 8811bd461..000000000
--- a/components/comment/index.jsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import { inject } from 'vue';
-import PropsTypes from '../_util/vue-types';
-import { getComponent, getSlot } from '../_util/props-util';
-import { ConfigConsumerProps } from '../config-provider';
-export const CommentProps = {
- actions: PropsTypes.array,
- /** The element to display as the comment author. */
- author: PropsTypes.any,
- /** The element to display as the comment avatar - generally an antd Avatar */
- avatar: PropsTypes.any,
- /** The main content of the comment */
- content: PropsTypes.any,
- /** Comment prefix defaults to '.ant-comment' */
- prefixCls: PropsTypes.string,
- /** A datetime element containing the time to be displayed */
- datetime: PropsTypes.any,
-};
-
-const Comment = {
- name: 'AComment',
- props: CommentProps,
- setup() {
- return {
- configProvider: inject('configProvider', ConfigConsumerProps),
- };
- },
- methods: {
- getAction(actions) {
- if (!actions || !actions.length) {
- return null;
- }
- const actionList = actions.map((action, index) =>
{action});
- return actionList;
- },
- renderNested(prefixCls, children) {
- return {children}
;
- },
- },
-
- render() {
- const { prefixCls: customizePrefixCls } = this.$props;
-
- const getPrefixCls = this.configProvider.getPrefixCls;
- const prefixCls = getPrefixCls('comment', customizePrefixCls);
-
- const actions = getComponent(this, 'actions');
- const author = getComponent(this, 'author');
- const avatar = getComponent(this, 'avatar');
- const content = getComponent(this, 'content');
- const datetime = getComponent(this, 'datetime');
-
- const avatarDom = (
-
- {typeof avatar === 'string' ?

: avatar}
-
- );
-
- const actionDom = actions ? (
-
- {this.getAction(Array.isArray(actions) ? actions : [actions])}
-
- ) : null;
-
- const authorContent = (
-
- {author && {author}}
- {datetime && {datetime}}
-
- );
-
- const contentDom = (
-
- {authorContent}
-
{content}
- {actionDom}
-
- );
-
- const comment = (
-
- {avatarDom}
- {contentDom}
-
- );
- const children = getSlot(this);
- return (
-
- {comment}
- {children && children.length ? this.renderNested(prefixCls, children) : null}
-
- );
- },
-};
-
-/* istanbul ignore next */
-Comment.install = function(app) {
- app.component(Comment.name, Comment);
-};
-export default Comment;
diff --git a/components/comment/index.tsx b/components/comment/index.tsx
new file mode 100644
index 000000000..600bb489a
--- /dev/null
+++ b/components/comment/index.tsx
@@ -0,0 +1,93 @@
+import { inject, VNodeTypes, CSSProperties, App, SetupContext } from 'vue';
+import classNames from '../_util/classNames';
+import { ConfigConsumerProps } from '../config-provider';
+
+export interface CommentProps {
+ /** List of action items rendered below the comment content */
+ actions?: Array;
+ /** The element to display as the comment author. */
+ author?: VNodeTypes;
+ /** The element to display as the comment avatar - generally an antd Avatar */
+ avatar?: VNodeTypes;
+ /** The main content of the comment */
+ content: VNodeTypes;
+ /** Comment prefix defaults to '.ant-comment' */
+ prefixCls?: string;
+ /** Additional style for the comment */
+ style?: CSSProperties;
+ /** A datetime element containing the time to be displayed */
+ datetime?: VNodeTypes;
+}
+
+const Comment = (
+ {
+ actions,
+ author,
+ avatar,
+ content,
+ prefixCls: customizePrefixCls,
+ datetime,
+ ...otherProps
+ }: CommentProps,
+ { slots }: SetupContext,
+) => {
+ const { getPrefixCls } = inject('configProvider', ConfigConsumerProps);
+
+ const renderNested = (prefixCls: string, nestedChildren: any) => {
+ return {nestedChildren}
;
+ };
+
+ const prefixCls = getPrefixCls('comment', customizePrefixCls);
+
+ const avatarDom = avatar ? (
+
+ {typeof avatar === 'string' ?

: avatar}
+
+ ) : null;
+
+ const actionDom =
+ actions && actions.length ? (
+
+ {actions.map((action, index) => (
+ - {action}
// eslint-disable-line react/no-array-index-key
+ ))}
+
+ ) : null;
+
+ const authorContent = (author || datetime) && (
+
+ {author && {author}}
+ {datetime && {datetime}}
+
+ );
+
+ const contentDom = (
+
+ {authorContent}
+
{content}
+ {actionDom}
+
+ );
+ const cls = classNames(prefixCls);
+
+ const children = slots.default?.();
+
+ return (
+
+
+ {avatarDom}
+ {contentDom}
+
+ {children ? renderNested(prefixCls, children) : null}
+
+ );
+};
+
+Comment.displayName = 'AComment';
+
+/* istanbul ignore next */
+Comment.install = function(app: App) {
+ app.component(Comment.name, Comment);
+};
+
+export default Comment;
diff --git a/components/icon/index.js b/components/icon/index.js
deleted file mode 100644
index 191d98f00..000000000
--- a/components/icon/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import warning from '../_util/warning';
-
-const Icon = {
- name: 'AIcon',
- render() {
- warning(false, 'Icon', 'Empty Icon');
- return null;
- },
-};
-
-/* istanbul ignore next */
-Icon.install = function(app) {
- app.component(Icon.name, Icon);
-};
-
-export default Icon;
diff --git a/components/icon/index.tsx b/components/icon/index.tsx
new file mode 100644
index 000000000..4f0884a2c
--- /dev/null
+++ b/components/icon/index.tsx
@@ -0,0 +1,16 @@
+import { App } from 'vue';
+import warning from '../_util/warning';
+
+const Icon = () => {
+ warning(false, 'Icon', 'Empty Icon');
+ return null;
+};
+
+Icon.displayName = 'AIcon';
+
+/* istanbul ignore next */
+Icon.install = function(app: App) {
+ app.component(Icon.displayName, Icon);
+};
+
+export default Icon;
diff --git a/components/icon/style/index.js b/components/icon/style/index.ts
similarity index 100%
rename from components/icon/style/index.js
rename to components/icon/style/index.ts