diff --git a/guide/I18n.md b/guide/I18n.md new file mode 100644 index 0000000..7b152f1 --- /dev/null +++ b/guide/I18n.md @@ -0,0 +1,25 @@ +通过 `Provider.themeConfigFunc` 配置: + +```jsx +// preview + + { + return { + ...defaultConfig, + emptyTxtDesc: "Empty data!", + loadingTipTxtEmpty: 'Empty data', + loadingTipTxtLoading: 'Loading', + loadingTipTxtFinish: 'Finish', + loadingTipTxtError: 'Error', + loadingTipTxtMore: 'Load more', + commonTxtBtn: 'button', + commonTxtChecked: 'checked', + }; + }} +> + + + +``` diff --git a/guide/Scale.md b/guide/Scale.md new file mode 100644 index 0000000..ab841d0 --- /dev/null +++ b/guide/Scale.md @@ -0,0 +1,277 @@ +通过 `Provider.renderInfo` 配置: + +```jsx +// preview + +/** + * 功能:文字放大1.5倍,宽高放大1.2倍 + * 参数:SetStyleWithScaleOptions { + ignore?: string[]; + overwrite?: Record number>; +} + * */ +function setStyleWithScale(style, options) { + if (Object.prototype.toString.call(style).slice(8, -1) === 'Object') { + const _style = style; + const { ignore = [], overwrite = {} } = options || {}; + Object.keys(_style).forEach(key => { + if (typeof _style[key] === "number" && !ignore.includes(key)) { + if (["fontSize", "lineHeight"].includes(key)) { + _style[key] = overwrite[key] ? overwrite[key](_style[key]) : (_style[key] * 1.5); + } else if ( + [ + "height", + "width", + "borderRadius", + "minWidth", + "maxWidth", + "minHeight", + "maxHeight", + "borderTopLeftRadius", + "borderTopRightRadius", + "borderBottomLeftRadius", + "borderBottomRightRadius" + ].includes(key) + ) { + _style[key] = overwrite[key] ? overwrite[key](_style[key]) : (_style[key] * 1.2); + } + } + }); + } else if (Array.isArray(style)) { + style.forEach((item) => { + setStyleWithScale(item); + }); + } + return style; +} +/** + * 功能:自动转化renderInfo里各种自定义style + * 参数:params: { + defaultRenderInfo: T; + propsKey?: (string | ({ propsKey: string } & SetStyleWithScaleOptions))[]; // 如 renderInfo.cascader 包含 itemTxtProps: {style: Style} | Array<{style: Style}> + styleKey?: string[]; // 如 renderInfo.cascader 包含 wrapStyle: Style + fnPropsKey?: string[]; // 如 renderInfo.cascader 包含 scrollViewPropsFn: () => {style: Style} + fnStyleKey?: string[]; // 如 renderInfo.table 包含 rowStyleFn: () => Style + elementKey?: string[]; // 如 renderInfo.empty 包含 img: ReactElement | ReactElement[] +} + * */ +function renderInfoPropsStyleWithScale(params) { + const { defaultRenderInfo, propsKey, styleKey, fnPropsKey, fnStyleKey } = params; + if (getObjectType(defaultRenderInfo) !== ObjectType.Object) { + return defaultRenderInfo; + } + propsKey && propsKey.forEach(key => { + const propsOptions = typeof key === "string" ? { propsKey: key } : key; + const { propsKey, ...options } = propsOptions; + const propsList = Array.isArray(defaultRenderInfo[propsKey]) + ? defaultRenderInfo[propsKey] + : [defaultRenderInfo[propsKey]]; + propsList.forEach(props => { + if (props && props.style) { + props.style = setStyleWithScale(props.style, options); + } + }); + }); + styleKey && styleKey.forEach(key => { + if (defaultRenderInfo[key]) { + defaultRenderInfo[key] = setStyleWithScale(defaultRenderInfo[key]); + } + }); + fnPropsKey && fnPropsKey.forEach(key => { + if (typeof defaultRenderInfo[key] === "function") { + const defaultFn = defaultRenderInfo[key]; + defaultRenderInfo[key] = function() { + const result = defaultFn.apply(this, arguments); + if (getObjectType(result) === ObjectType.Object && result && result.style) { + result.style = setStyleWithScale(result.style); + } + return result; + }; + } + }); + fnStyleKey && fnStyleKey.forEach(key => { + if (typeof defaultRenderInfo[key] === "function") { + const defaultFn = defaultRenderInfo[key]; + defaultRenderInfo[key] = function() { + const result = defaultFn.apply(this, arguments); + return setStyleWithScale(result); + }; + } + }); + return defaultRenderInfo; +} + + { + return renderInfoPropsStyleWithScale({ defaultRenderInfo, propsKey: ["badgeProps", "wrapProps"] }); + }, + button: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["textProps", "wrapProps", "imageProps", "badgeProps", "pressProps"] + }); + }, + cascader: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["itemActiveTxtProps", "itemTxtProps"], + styleKey: ["wrapStyle", "markStyle", "itemStyle", "itemActiveStyle"], + fnPropsKey: ["scrollViewPropsFn"] + }); + }, + divider: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["dividerProps"] + }); + }, + empty: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["wrapProps"], + elementKey: ["img", "text"] + }); + }, + hiText: ({ defaultRenderInfo, props }) => { + + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["textProps"] + }); + }, + indicator: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["wrapProps"], + elementKey: ["itemList"] + }); + }, + listItem: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["wrapProps", "leftProps", "leftInfoProps", "buttonProps"], + elementKey: ["rank", "thumb", "title", "note", "moreNote"] + }); + }, + loading: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["loadingProps"], + elementKey: ["txt"] + }); + }, + mask: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["maskProps"] + }); + }, + modal: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: [ + "modalProps", + "footerDefaultBtnCancelProps", + "footerDefaultBtnConfirmProps", + "footerDefaultTxtConfirmProps", + "footerDefaultTxtCancelProps", + "footerPrimaryBtnCancelProps", + "footerPrimaryBtnConfirmProps", + "footerVerticalBtnCancelProps", + "footerVerticalBtnConfirmProps", + "footerVerticalTxtConfirmProps", + "footerVerticalTxtCancelProps" + ], + elementKey: ["title", "content", "closeIcon"], + styleKey: ["footerDefaultWrapStyle", "footerPrimaryWrapStyle", "footerVerticalWrapStyle"] + }); + }, + navigator: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + elementKey: ["title", "back"], + styleKey: ["wrapStyle", "statusBarStyle", "navigatorStyle"] + }); + }, + popup: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["mainProps"] + }); + }, + radio: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["wrapProps", "imgProps"] + }); + }, + search: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["wrapProps", "inputProps"], + elementKey: ["leftIcon", "rightIcon", "clearIcon"] + }); + }, + slider: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["wrapProps", "lineProps", "activeLineProps", "blockProps", "blockImageProps"] + }); + }, + switch: ({ defaultRenderInfo }) => { + const result = renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["wrapProps", "circleProps", "activeLineProps", "blockProps", "blockImageProps"] + }); + return result; + }, + table: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["wrapProps", "lineProps", "activeLineProps", "blockProps", "blockImageProps"], + fnStyleKey: ["rowStyleFn", "cellStyleFn", "headerCellStyleFn"], + styleKey: ["headerStyle"] + }); + }, + tabs: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: [ + "wrapProps", + { + propsKey: "itemPropsList", + overwrite: { + fontSize: n => revertFontToLayoutScale(n), + lineHeight: n => revertFontToLayoutScale(n) + } + } + ], + elementKey: ["underline"] + }); + }, + tag: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["tagProps"], + elementKey: ["txtNode"] + }); + }, + toast: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["mainProps"] + }); + }, + uImage: ({ defaultRenderInfo }) => { + return renderInfoPropsStyleWithScale({ + defaultRenderInfo, + propsKey: ["imgProps"] + }); + } + }} +> + + +``` diff --git a/packages/hippy_ui_react/src/components/Empty/config.ts b/packages/hippy_ui_react/src/components/Empty/config.ts index 75c1543..8d747d8 100644 --- a/packages/hippy_ui_react/src/components/Empty/config.ts +++ b/packages/hippy_ui_react/src/components/Empty/config.ts @@ -9,6 +9,7 @@ export interface ThemeConfigEmpty { emptyWrap: ViewProps; emptyImg: ImageProps; emptyText: HiTextProps; + emptyTxtDesc: ReactNode; } /** 自定义渲染:空状态 */ @@ -49,4 +50,5 @@ export const emptyConfig: ThemeConfigEmpty = { marginTop: 15, }, }, + emptyTxtDesc: '数据为空', }; diff --git a/packages/hippy_ui_react/src/components/Empty/index.tsx b/packages/hippy_ui_react/src/components/Empty/index.tsx index 19d173e..c414377 100644 --- a/packages/hippy_ui_react/src/components/Empty/index.tsx +++ b/packages/hippy_ui_react/src/components/Empty/index.tsx @@ -8,10 +8,6 @@ import getRenderInfo from './renderInfo'; * @visibleName Empty 空状态 */ export class Empty extends Component { - static defaultProps = { - desc: '数据为空', - }; - render() { return ( diff --git a/packages/hippy_ui_react/src/components/Empty/renderInfo.tsx b/packages/hippy_ui_react/src/components/Empty/renderInfo.tsx index d09c4a0..ef9aa25 100644 --- a/packages/hippy_ui_react/src/components/Empty/renderInfo.tsx +++ b/packages/hippy_ui_react/src/components/Empty/renderInfo.tsx @@ -3,15 +3,17 @@ import { Image } from '@hippy/react'; import HiText from '../HiText'; import { transferStyle } from '../../utils/Styles'; import { EmptyRenderInfo, EmptyRenderParams, emptyConfig } from './config'; +import { ThemeConfig } from '../../themeConfig'; /** Empty:获取渲染信息 */ export default function getRenderInfo(params: EmptyRenderParams): EmptyRenderInfo { const { consumerValue: { themeConfig: _themeConfig, renderInfo }, - props: { onPress, style, image, desc }, + props, } = params; + const themeConfig: ThemeConfig = { ...emptyConfig, ..._themeConfig }; + const { onPress, style, image, desc = themeConfig.emptyTxtDesc } = props; - const themeConfig = { ...emptyConfig, ..._themeConfig }; const result: EmptyRenderInfo = { wrapProps: { ...themeConfig.emptyWrap, diff --git a/packages/hippy_ui_react/src/components/LoadingTip/config.ts b/packages/hippy_ui_react/src/components/LoadingTip/config.ts new file mode 100644 index 0000000..32011d5 --- /dev/null +++ b/packages/hippy_ui_react/src/components/LoadingTip/config.ts @@ -0,0 +1,21 @@ +import { ReactNode } from 'react'; + +/** 主题配置:加载提示 */ +export interface ThemeConfigLoadingTip { + loadingTipTxtEmpty: ReactNode; + loadingTipTxtLoading: ReactNode; + loadingTipTxtFinish: ReactNode; + loadingTipTxtError: ReactNode; + loadingTipTxtMore: ReactNode; +} + +/** + * LoadingTip 组件 + */ +export const loadingTipConfig: ThemeConfigLoadingTip = { + loadingTipTxtEmpty: '数据为空', + loadingTipTxtLoading: '加载中', + loadingTipTxtFinish: '加载完成', + loadingTipTxtError: '加载异常', + loadingTipTxtMore: '加载更多', +}; diff --git a/packages/hippy_ui_react/src/components/LoadingTip/index.tsx b/packages/hippy_ui_react/src/components/LoadingTip/index.tsx index 601201e..5ee004d 100644 --- a/packages/hippy_ui_react/src/components/LoadingTip/index.tsx +++ b/packages/hippy_ui_react/src/components/LoadingTip/index.tsx @@ -1,30 +1,37 @@ import React, { Component, ReactNode } from 'react'; -import { TextStyle } from '@hippy/react'; import { LoadingTipProps, LoadingTipStatus } from './PropsType'; import HiText from '../HiText'; import Empty from '../Empty'; import Loading from '../Loading'; import Consumer from '../../provider/Consumer'; +import { ConsumerValue } from '../../provider'; +import { loadingTipConfig } from './config'; +import { ThemeConfig } from '../../themeConfig'; /** * @visibleName LoadingTip 加载提示 */ export class LoadingTip extends Component { - static defaultProps = { - txtFinish: '加载完成', - txtMore: '加载更多', - txtEmpty: '数据为空', - txtError: '加载异常', - txtLoading: '加载中', - }; - static status = LoadingTipStatus; // 渲染:提示语 - renderTip = (params: { tipStyle?: TextStyle }) => { - const { tipStyle } = params; - const { status, txtLoading, txtEmpty, txtError, txtMore, txtFinish, hasData, textStyle, onPress, loadingProps } = - this.props; + renderTip = (params: { consumerValue: ConsumerValue }) => { + const { + consumerValue: { themeConfig: _themeConfig }, + } = params; + const themeConfig: ThemeConfig = { ...loadingTipConfig, ..._themeConfig }; + const { + status, + txtLoading = themeConfig.loadingTipTxtLoading, + txtEmpty = themeConfig.loadingTipTxtEmpty, + txtError = themeConfig.loadingTipTxtError, + txtMore = themeConfig.loadingTipTxtMore, + txtFinish = themeConfig.loadingTipTxtFinish, + hasData, + textStyle, + onPress, + loadingProps, + } = this.props; const text = status === LoadingTipStatus.loading ? txtLoading @@ -38,7 +45,7 @@ export class LoadingTip extends Component { let loading; if (typeof text === 'string' || typeof text === 'number') { const desc = ( - + {text} ); @@ -60,9 +67,7 @@ export class LoadingTip extends Component { {(consumerValue) => { const tip = this.renderTip({ - tipStyle: { - color: consumerValue.themeConfig.colorTextSecondary, - }, + consumerValue, }); return this.renderHasData(tip); }} diff --git a/packages/hippy_ui_react/src/components/Slider/index.tsx b/packages/hippy_ui_react/src/components/Slider/index.tsx index 79ce4a9..62d8aa2 100644 --- a/packages/hippy_ui_react/src/components/Slider/index.tsx +++ b/packages/hippy_ui_react/src/components/Slider/index.tsx @@ -367,7 +367,7 @@ export class Slider extends Component { this.setState({ ...this.state, sliderWidth: e.layout.width }); }} accessible={!disabled} - accessibilityLabel={`${limitValues[0]}到${limitValues[1]}`} + accessibilityLabel={`${limitValues[0]}~${limitValues[1]}`} {...this.getEvents()} > diff --git a/packages/hippy_ui_react/src/components/Tabs/renderInfo.tsx b/packages/hippy_ui_react/src/components/Tabs/renderInfo.tsx index 1eccd97..814d60b 100644 --- a/packages/hippy_ui_react/src/components/Tabs/renderInfo.tsx +++ b/packages/hippy_ui_react/src/components/Tabs/renderInfo.tsx @@ -40,9 +40,9 @@ export default function getRenderInfo(params: TabsRenderParams): TabsRenderInfo ...activeProps, accessible: true, accessibilityLabel: - (isActive && values.length > 1 ? '已选中 ' : '') + + (isActive && values.length > 1 ? `${themeConfig.commonTxtChecked} ` : '') + Tabs.getTabInfo(v).text + - (values.length > 1 ? ' 按钮' : ''), + (values.length > 1 ? ` ${themeConfig.commonTxtBtn}` : ''), style: transferStyle([ { color: themeConfig.colorTextSecondary, fontWeight: themeConfig.hiTextWeightRegular }, themeConfig.tabsItemProps.style, diff --git a/packages/hippy_ui_react/src/provider/ConfigCommon.ts b/packages/hippy_ui_react/src/provider/ConfigCommon.ts index df30c6f..82b572f 100644 --- a/packages/hippy_ui_react/src/provider/ConfigCommon.ts +++ b/packages/hippy_ui_react/src/provider/ConfigCommon.ts @@ -2,7 +2,7 @@ import { ThemeConfigCommon } from '../themeConfig/common'; import { ThemeConfig } from '../themeConfig/index'; // 全局通用配置 -export const ConfigCommon: ThemeConfigCommon = {}; +export const ConfigCommon: Partial = {}; export const setConfigCommon = (config: ThemeConfig) => { ConfigCommon.commonListenActiveRemove = config.commonListenActiveRemove; diff --git a/packages/hippy_ui_react/src/themeConfig/common.ts b/packages/hippy_ui_react/src/themeConfig/common.ts index 3325f14..8809c70 100644 --- a/packages/hippy_ui_react/src/themeConfig/common.ts +++ b/packages/hippy_ui_react/src/themeConfig/common.ts @@ -2,6 +2,8 @@ import { BackAndroid, Platform } from '@hippy/react'; /** 主题配置:通用 */ export interface ThemeConfigCommon { + commonTxtBtn: string; + commonTxtChecked: string; commonListenActiveAdd?: (callBack: (active: boolean) => void) => void; commonListenActiveRemove?: (callBack: (active: boolean) => void) => void; commonListenBackAdd?: (callBack: () => boolean) => void; @@ -12,6 +14,8 @@ export interface ThemeConfigCommon { * Common 通用配置 */ export const commonConfig: ThemeConfigCommon = { + commonTxtBtn: '按钮', + commonTxtChecked: '已选中', commonListenBackAdd(cb) { if (Platform.OS === 'android') { BackAndroid.addListener(cb); diff --git a/packages/hippy_ui_react/src/themeConfig/index.ts b/packages/hippy_ui_react/src/themeConfig/index.ts index 83f7536..a131f2a 100644 --- a/packages/hippy_ui_react/src/themeConfig/index.ts +++ b/packages/hippy_ui_react/src/themeConfig/index.ts @@ -13,6 +13,7 @@ import { RenderInfoUImage, ThemeConfigUImage } from '../components/UImage/config import { RenderInfoListItem, ThemeConfigListItem } from '../components/ListItem/config'; import { ThemeConfigLoadingGif } from '../components/LoadingGif/config'; import { RenderInfoLoading, ThemeConfigLoading } from '../components/Loading/config'; +import { ThemeConfigLoadingTip } from '../components/LoadingTip/config'; import { RenderInfoDivider, ThemeConfigDivider } from '../components/Divider/config'; import { RenderInfoSearch, ThemeConfigSearch } from '../components/Search/config'; import { RenderInfoIndicator, ThemeConfigIndicator } from '../components/Indicator/config'; @@ -49,6 +50,7 @@ export type ThemeConfig = ThemeConfigCommon & ThemeConfigListItem & ThemeConfigLoadingGif & ThemeConfigLoading & + ThemeConfigLoadingTip & ThemeConfigDivider & ThemeConfigSearch & ThemeConfigIndicator & diff --git a/styleguide.config.js b/styleguide.config.js index 334f8e9..3465900 100644 --- a/styleguide.config.js +++ b/styleguide.config.js @@ -23,6 +23,14 @@ module.exports = { name: "全局配置", content: "./guide/Provider.md", }, + { + name: "国际化", + content: "./guide/I18n.md", + }, + { + name: "放大模式", + content: "./guide/Scale.md", + }, { name: "色彩", content: "./guide/Color.md"