diff --git a/packages/renderless/src/user-head/index.ts b/packages/renderless/src/user-head/index.ts index fa636a327..1322b82c8 100644 --- a/packages/renderless/src/user-head/index.ts +++ b/packages/renderless/src/user-head/index.ts @@ -10,8 +10,10 @@ * */ +import type { IUserHeadRenderlessParams } from '@/types' + export const computedStyle = - ({ state, props }) => + ({ state, props }: Pick) => () => { return { fill: state.color, @@ -22,13 +24,13 @@ export const computedStyle = } export const computedMessage = - ({ props }) => + ({ props }: Pick) => () => { let result = '' - const total = Math.floor(props.messageTotal) + const total = Math.floor(props.messageTotal || NaN) if (props.messageType === 'details' && !isNaN(total) && total > 0) { - result = total + result = String(total) if (props.messageUpperLimit && total > props.messageUpperLimit) { result = `${props.messageUpperLimit}+` @@ -39,7 +41,7 @@ export const computedMessage = } export const computedFontSize = - ({ props, state, mode }) => + ({ props, state, mode }: Pick) => () => { let fontSize = '' @@ -74,12 +76,12 @@ export const computedFontSize = } export const computedLabel = - ({ state, props }) => + ({ state, props }: Pick) => () => props.min ? state.internalValue.substr(0, 2) : state.internalValue.substr(0, 6) export const getInternalValue = - ({ props }) => + ({ props }: Pick) => () => { if (props.modelValue === null) { let result = '' diff --git a/packages/renderless/src/user-head/vue.ts b/packages/renderless/src/user-head/vue.ts index 82fc80641..829affb8e 100644 --- a/packages/renderless/src/user-head/vue.ts +++ b/packages/renderless/src/user-head/vue.ts @@ -10,6 +10,7 @@ * */ +import type { IUserHeadApi, IUserHeadProps, IUserHeadRenderlessParamUtils, IUserHeadState } from 'types/user-head.type' import { computedMessage, computedStyle, @@ -19,13 +20,18 @@ import { handleClick, mouseEnter } from './index' +import type { ISharedRenderlessParamHooks } from 'types/shared.type' export const api = ['state', 'handleClick', 'mouseEnter'] -export const renderless = (props, { reactive, computed, inject }, { mode, emit }) => { +export const renderless = ( + props: IUserHeadProps, + { reactive, computed, inject }: ISharedRenderlessParamHooks, + { mode, emit }: IUserHeadRenderlessParamUtils +): IUserHeadApi => { const groupSize = inject('groupSize', null) - const state = reactive({ + const state: IUserHeadState = reactive({ internalValue: computed(() => api.getInternalValue()), label: computed(() => api.computedLabel()), style: computed(() => api.computedStyle()), @@ -36,7 +42,7 @@ export const renderless = (props, { reactive, computed, inject }, { mode, emit } backgroundColor: inject('backgroundColor', null) || props.backgroundColor }) - const api = { + const api: IUserHeadApi = { state, computedLabel: computedLabel({ state, props }), computedStyle: computedStyle({ state, props }), diff --git a/packages/renderless/types/user-head.type.ts b/packages/renderless/types/user-head.type.ts index e69de29bb..4917bbdaa 100644 --- a/packages/renderless/types/user-head.type.ts +++ b/packages/renderless/types/user-head.type.ts @@ -0,0 +1,38 @@ +import type { ExtractPropTypes } from 'vue' +import type { userHeadProps, $constants } from '@/user-head/src' +import type { ISharedRenderlessFunctionParams, ISharedRenderlessParamUtils } from './shared.type' +import type { computedFontSize, computedLabel, computedMessage, computedStyle, getInternalValue } from 'src/user-head' + +export interface IUserHeadState { + internalValue: string | Record + label: string + style: ReturnType> + message: string + fontSize: { fontSize: string } + size: number + color: string + backgroundColor: string +} + +export type IUserHeadProps = ExtractPropTypes + +export type IUserHeadConstants = typeof $constants + +export type IUserHeadRenderlessParams = ISharedRenderlessFunctionParams & { + api: IUserHeadApi + state: IUserHeadState + props: IUserHeadProps +} + +export interface IUserHeadApi { + state: IUserHeadState + computedLabel: ReturnType + computedStyle: ReturnType + computedMessage: ReturnType + computedFontSize: ReturnType + getInternalValue: ReturnType + handleClick: (event: Event) => void + mouseEnter: (event: Event) => void +} + +export type IUserHeadRenderlessParamUtils = ISharedRenderlessParamUtils diff --git a/packages/vue/src/user-head/src/index.ts b/packages/vue/src/user-head/src/index.ts index ec79b56d7..ea09ccf8f 100644 --- a/packages/vue/src/user-head/src/index.ts +++ b/packages/vue/src/user-head/src/index.ts @@ -12,97 +12,99 @@ import { $props, $prefix, $setup, defineComponent } from '@opentiny/vue-common' import template from 'virtual-template?pc|mobile|mobile-first' -const $constants = { +export const $constants = { ITEM_NAME: '.user-head-item' } +export const userHeadProps = { + ...$props, + _constants: { + type: Object, + default: () => $constants + }, + /** + * @property {Boolean} [min=false] - 小尺寸模式 + */ + min: Boolean, + + /** + * @property {Boolean} [round=true] - 圆形模式 + */ + round: Boolean, + + /** + * @property {String} [color=#ffffff] - 文字颜色 + */ + color: { + type: String, + default: '#ffffff' + }, + + /** + * @property {String} [backgroundColor=#BBBBBB] - 背景色 + */ + backgroundColor: { + type: String, + default: '#B5BBC1' + }, + + /** + * @property {String} [type=label] - 头像类型,icon|image|label 可选 + */ + type: { + type: String, + default: 'label', + validator: (value: string) => Boolean(~['icon', 'image', 'label'].indexOf(value)) + }, + + /** + * @property {String} - 头像资源 + * type=icon 时为图标类名,type=label时为字体串,type=image时为资源路径 + */ + value: { + type: [Object, String], + default: null + }, + + /** + * @property {String} - 头像资源 + * type=icon 时为图标类名,type=label时为字体串,type=image时为资源路径 + */ + modelValue: { + type: [Object, String], + default: null + }, + + /** + * @property {Number} - 消息计数 + */ + messageTotal: Number, + + /** + * @property {String} [messageType=details] - 消息类型 details|basic 可选 + */ + messageType: { + type: String, + default: 'details', + validator: (value: string) => Boolean(~['details', 'basic'].indexOf(value)) + }, + + /** + * @property {Number} [messageUpperLimit=0] - 消息显示上限 + */ + messageUpperLimit: { + type: Number, + default: 0 + }, + size: { + type: Number, + default: 40 + } +} + export default defineComponent({ name: $prefix + 'UserHead', - props: { - ...$props, - _constants: { - type: Object, - default: () => $constants - }, - /** - * @property {Boolean} [min=false] - 小尺寸模式 - */ - min: Boolean, - - /** - * @property {Boolean} [round=true] - 圆形模式 - */ - round: Boolean, - - /** - * @property {String} [color=#ffffff] - 文字颜色 - */ - color: { - type: String, - default: '#ffffff' - }, - - /** - * @property {String} [backgroundColor=#BBBBBB] - 背景色 - */ - backgroundColor: { - type: String, - default: '#B5BBC1' - }, - - /** - * @property {String} [type=label] - 头像类型,icon|image|label 可选 - */ - type: { - type: String, - default: 'label', - validator: (value: string) => Boolean(~['icon', 'image', 'label'].indexOf(value)) - }, - - /** - * @property {String} - 头像资源 - * type=icon 时为图标类名,type=label时为字体串,type=image时为资源路径 - */ - value: { - type: [Object, String], - default: null - }, - - /** - * @property {String} - 头像资源 - * type=icon 时为图标类名,type=label时为字体串,type=image时为资源路径 - */ - modelValue: { - type: [Object, String], - default: null - }, - - /** - * @property {Number} - 消息计数 - */ - messageTotal: Number, - - /** - * @property {String} [messageType=details] - 消息类型 details|basic 可选 - */ - messageType: { - type: String, - default: 'details', - validator: (value: string) => Boolean(~['details', 'basic'].indexOf(value)) - }, - - /** - * @property {Number} [messageUpperLimit=0] - 消息显示上限 - */ - messageUpperLimit: { - type: Number, - default: 0 - }, - size: { - type: Number, - default: 40 - } - }, + props: userHeadProps, setup(props, context) { return $setup({ props, context, template }) }