diff --git a/src/packages/switch/demo.taro.tsx b/src/packages/switch/demo.taro.tsx index ac961c8b0d..cf8e3ffc3e 100644 --- a/src/packages/switch/demo.taro.tsx +++ b/src/packages/switch/demo.taro.tsx @@ -10,6 +10,7 @@ import Demo4 from './demos/taro/demo4' import Demo5 from './demos/taro/demo5' import Demo6 from './demos/taro/demo6' import Demo7 from './demos/taro/demo7' +import Demo8 from './demos/taro/demo8' const SwitchDemo = () => { const [translated] = useTranslate({ @@ -17,6 +18,7 @@ const SwitchDemo = () => { basic: '非受控', disabled: '禁用状态', asyncControl: '受控', + loadingControl: 'loading 态受控', customColor: '自定义颜色', supportText: '支持文字', supportIcon: '支持Icon', @@ -26,6 +28,7 @@ const SwitchDemo = () => { basic: '非受控', disabled: '禁用狀態', asyncControl: '受控', + loadingControl: 'loading 態受控', customColor: '自定義顏色', supportText: '支持文字', supportIcon: '支持Icon', @@ -35,6 +38,7 @@ const SwitchDemo = () => { basic: 'Uncontrolled', disabled: 'Disabled', asyncControl: 'controlled', + loadingControl: 'Controlled with loading', customColor: 'Custom Color', supportText: 'Support Text', supportIcon: 'Support Icon', @@ -49,6 +53,8 @@ const SwitchDemo = () => { {translated.asyncControl} + {translated.loadingControl} + {translated.disabled} {translated.supportText} diff --git a/src/packages/switch/demo.tsx b/src/packages/switch/demo.tsx index 7d33a634d2..758aeaf5ad 100644 --- a/src/packages/switch/demo.tsx +++ b/src/packages/switch/demo.tsx @@ -7,6 +7,7 @@ import Demo4 from './demos/h5/demo4' import Demo5 from './demos/h5/demo5' import Demo6 from './demos/h5/demo6' import Demo7 from './demos/h5/demo7' +import Demo8 from './demos/h5/demo8' const SwitchDemo = () => { const [translated] = useTranslate({ @@ -14,6 +15,7 @@ const SwitchDemo = () => { basic: '非受控', disabled: '禁用状态', asyncControl: '受控', + loadingControl: 'loading 态受控', customColor: '自定义颜色', supportText: '支持文字', supportIcon: '支持Icon', @@ -23,6 +25,7 @@ const SwitchDemo = () => { basic: '非受控', disabled: '禁用狀態', asyncControl: '受控', + loadingControl: 'loading 態受控', customColor: '自定義顏色', supportText: '支持文字', supportIcon: '支持Icon', @@ -32,6 +35,7 @@ const SwitchDemo = () => { basic: 'Uncontrolled', disabled: 'Disabled', asyncControl: 'controlled', + loadingControl: 'Controlled with loading', customColor: 'Custom Color', supportText: 'Support Text', supportIcon: 'Support Icon', @@ -45,6 +49,8 @@ const SwitchDemo = () => {

{translated.asyncControl}

+

{translated.loadingControl}

+

{translated.disabled}

{translated.supportText}

diff --git a/src/packages/switch/demos/h5/demo8.tsx b/src/packages/switch/demos/h5/demo8.tsx new file mode 100644 index 0000000000..c137687c35 --- /dev/null +++ b/src/packages/switch/demos/h5/demo8.tsx @@ -0,0 +1,35 @@ +import React, { useState } from 'react' +import { Cell, Switch, Toast } from '@nutui/nutui-react' + +const Demo8 = () => { + const [checkedAsync, setCheckedAsync] = useState(true) + const [externalLoading, setExternalLoading] = useState(false) + + const mockRequest = (): Promise => { + return new Promise((resolve) => { + setTimeout(() => { + resolve() + }, 2000) + }) + } + + const onChangeAsync = async (value: boolean) => { + Toast.show(`2秒后异步触发 ${value}`) + await mockRequest() + setCheckedAsync(value) + // setExternalLoading(false) + } + return ( + + { + setExternalLoading(loading) + }} + checked={checkedAsync} + onChange={(value) => onChangeAsync(value)} + /> + + ) +} +export default Demo8 diff --git a/src/packages/switch/demos/taro/demo8.tsx b/src/packages/switch/demos/taro/demo8.tsx new file mode 100644 index 0000000000..13f847b6f9 --- /dev/null +++ b/src/packages/switch/demos/taro/demo8.tsx @@ -0,0 +1,46 @@ +import React, { useState } from 'react' +import { Cell, Switch, Toast } from '@nutui/nutui-react-taro' + +const Demo8 = () => { + const [checkedAsync, setCheckedAsync] = useState(true) + const [value, setValue] = useState(false) + const [showToast, setShowToast] = useState(false) + const [externalLoading, setExternalLoading] = useState(false) + const mockRequest = (): Promise => { + return new Promise((resolve) => { + setTimeout(() => { + resolve() + }, 2000) + }) + } + + const onChangeAsync = async (value: boolean) => { + setValue(value) + setShowToast(true) + await mockRequest() + setCheckedAsync(value) + // setExternalLoading(false) + } + return ( + <> + + { + setExternalLoading(loading) + }} + checked={checkedAsync} + onChange={(value) => onChangeAsync(value)} + /> + + { + setShowToast(false) + }} + /> + + ) +} +export default Demo8 diff --git a/src/packages/switch/doc.en-US.md b/src/packages/switch/doc.en-US.md index b4090e42d0..3495efdb10 100644 --- a/src/packages/switch/doc.en-US.md +++ b/src/packages/switch/doc.en-US.md @@ -26,6 +26,14 @@ import { Switch } from '@nutui/nutui-react' ::: +### loading 态受控 + +:::demo + + + +::: + ### disabled status :::demo @@ -77,8 +85,10 @@ import { Switch } from '@nutui/nutui-react' | disabled | Disabled | `boolean` | `false` | | activeText | Text description when opening | `ReactNode` | `-` | | inactiveText | Text description when closed | `ReactNode` | `-` | -| loadingIcon | Controlled loading state icon | `ReactNode` | `` | -| onChange | Trigger when switching switches | `onChange:(value: boolean, event: Event)` | `-` | +| loadingIcon | Control the loading state icon, disable the loading state when a null | `ReactNode` | `` | +| loading | loading state, controlled | `boolean` | `-` | +| onLoadingChange | Triggered when switching loading | `onLoadingChange:(value: boolean)` | `-` | +| onChange | Trigger when switching switches | `onChange:(value: boolean)` | `-` | ## Theming diff --git a/src/packages/switch/doc.md b/src/packages/switch/doc.md index d699265bd2..3a9e7b2afc 100644 --- a/src/packages/switch/doc.md +++ b/src/packages/switch/doc.md @@ -26,6 +26,14 @@ import { Switch } from '@nutui/nutui-react' ::: +### loading 态受控 + +:::demo + + + +::: + ### 禁用状态 :::demo @@ -77,8 +85,10 @@ import { Switch } from '@nutui/nutui-react' | disabled | 禁用状态 | `boolean` | `false` | | activeText | 打开时文字描述 | `ReactNode` | `-` | | inactiveText | 关闭时文字描述 | `ReactNode` | `-` | -| loadingIcon | 受控 loading 态图标 | `ReactNode` | `` | -| onChange | 切换开关时触发 | `onChange:(value: boolean, event: Event)` | `-` | +| loadingIcon | 控制加载状态的图标,传入空值时禁用 loading 态 | `ReactNode` | `` | +| loading | loading 态,受控 | `boolean` | `-` | +| onLoadingChange | 切换 loading 态时触发 | `onLoadingChange:(value: boolean)` | `-` | +| onChange | 切换开关时触发 | `onChange:(value: boolean)` | `-` | ## 主题定制 diff --git a/src/packages/switch/doc.taro.md b/src/packages/switch/doc.taro.md index 77a4646b2f..c11f5a5581 100644 --- a/src/packages/switch/doc.taro.md +++ b/src/packages/switch/doc.taro.md @@ -26,6 +26,14 @@ import { Switch } from '@nutui/nutui-react-taro' ::: +### loading 态受控 + +:::demo + + + +::: + ### 禁用状态 :::demo @@ -77,8 +85,10 @@ import { Switch } from '@nutui/nutui-react-taro' | disabled | 禁用状态 | `boolean` | `false` | | activeText | 打开时文字描述 | `ReactNode` | `-` | | inactiveText | 关闭时文字描述 | `ReactNode` | `-` | -| loadingIcon | 受控 loading 态图标 | `ReactNode` | `` | -| onChange | 切换开关时触发 | `onChange:(value: boolean, event: Event)` | `-` | +| loadingIcon | 控制加载状态的图标,传入空值时禁用 loading 态 | `ReactNode` | `` | +| loading | loading 态,受控 | `boolean` | `-` | +| onLoadingChange | 切换 loading 态时触发 | `onLoadingChange:(value: boolean)` | `-` | +| onChange | 切换开关时触发 | `onChange:(value: boolean)` | `-` | ## 主题定制 diff --git a/src/packages/switch/doc.zh-TW.md b/src/packages/switch/doc.zh-TW.md index 0f12e4205a..e392e58924 100644 --- a/src/packages/switch/doc.zh-TW.md +++ b/src/packages/switch/doc.zh-TW.md @@ -26,6 +26,14 @@ import { Switch } from '@nutui/nutui-react' ::: +### loading 態受控 + +:::demo + + + +::: + ### 禁用狀態 :::demo @@ -77,8 +85,10 @@ import { Switch } from '@nutui/nutui-react' | disabled | 禁用狀態 | `boolean` | `false` | | activeText | 打開時文字描述 | `ReactNode` | `-` | | inactiveText | 關閉時文字描述 | `ReactNode` | `-` | -| loadingIcon | 受控 loading 態圖標 | `ReactNode` | `` | -| onChange | 切換開關時觸發 | `onChange:(value: boolean, event: Event)` | `-` | +| loadingIcon | 控制加載狀態的圖標,當傳入空值時禁用 loading 狀態 | `ReactNode` | `` | +| loading | loading 態,受控 | `boolean` | `-` | +| onLoadingChange | 切換 loading 態時觸發 | `onLoadingChange:(value: boolean)` | `-` | +| onChange | 切換開關時觸發 | `onChange:(value: boolean)` | `-` | ## 主題定製 diff --git a/src/packages/switch/switch.taro.tsx b/src/packages/switch/switch.taro.tsx index 1d71905a6d..5d72b21c7f 100644 --- a/src/packages/switch/switch.taro.tsx +++ b/src/packages/switch/switch.taro.tsx @@ -1,5 +1,4 @@ import React, { FunctionComponent, useEffect, useState } from 'react' - import { View } from '@tarojs/components' import classNames from 'classnames' import { Loading1 } from '@nutui/icons-react-taro' @@ -14,6 +13,8 @@ const defaultProps = { activeText: '', inactiveText: '', loadingIcon: , + loading: undefined, + onLoadingChange: (loading: boolean) => {}, } as TaroSwitchProps export const Switch: FunctionComponent> = (props) => { const { @@ -26,6 +27,8 @@ export const Switch: FunctionComponent> = (props) => { className, style, onChange, + loading: propLoading, + onLoadingChange, ...rest } = { ...defaultProps, @@ -38,12 +41,21 @@ export const Switch: FunctionComponent> = (props) => { defaultValue: defaultChecked, }) + const [internalLoading, setInternalLoading] = useState(false) + const loading = propLoading !== undefined ? propLoading : internalLoading + + const setLoading = (val: boolean) => { + if (propLoading !== undefined) { + onLoadingChange(val) + } else { + setInternalLoading(val) + } + } + useEffect(() => { - changing && setChanging(false) + loading && setLoading(false) }, [value]) - const [changing, setChanging] = useState(false) - const classes = () => { return classNames([ classPrefix, @@ -57,13 +69,14 @@ export const Switch: FunctionComponent> = (props) => { } const onClick = async () => { - if (disabled || changing) return + if (disabled || loading) return if (onChange) { - setChanging(true) + loadingIcon && setLoading(true) + onChange(!value) try { await onChange(!value) } catch (e) { - setChanging(false) + setLoading(false) } } setValue(!value) @@ -84,7 +97,7 @@ export const Switch: FunctionComponent> = (props) => { }, ])} > - {changing && loadingIcon ? ( + {loading && loadingIcon ? ( <>{loadingIcon} ) : ( <> diff --git a/src/packages/switch/switch.tsx b/src/packages/switch/switch.tsx index b8a9d487fe..7622a9d50d 100644 --- a/src/packages/switch/switch.tsx +++ b/src/packages/switch/switch.tsx @@ -12,6 +12,8 @@ const defaultProps = { activeText: '', inactiveText: '', loadingIcon: , + loading: undefined, + onLoadingChange: (loading: boolean) => {}, } as WebSwitchProps export const Switch: FunctionComponent> = (props) => { const { @@ -24,6 +26,8 @@ export const Switch: FunctionComponent> = (props) => { className, style, onChange, + loading: propLoading, + onLoadingChange, ...rest } = { ...defaultProps, @@ -38,12 +42,21 @@ export const Switch: FunctionComponent> = (props) => { defaultValue: defaultChecked, }) + const [internalLoading, setInternalLoading] = useState(false) + const loading = propLoading !== undefined ? propLoading : internalLoading + + const setLoading = (val: boolean) => { + if (propLoading !== undefined) { + onLoadingChange(val) + } else { + setInternalLoading(val) + } + } + useEffect(() => { - changing && setChanging(false) + loading && setLoading(false) }, [value]) - const [changing, setChanging] = useState(false) - const classes = () => { return classNames([ classPrefix, @@ -57,13 +70,13 @@ export const Switch: FunctionComponent> = (props) => { } const onClick = async () => { - if (disabled || changing) return + if (disabled || loading) return if (onChange) { - setChanging(true) + loadingIcon && setLoading(true) try { await onChange(!value) } catch (e) { - setChanging(false) + setLoading(false) } } setValue(!value) @@ -84,7 +97,7 @@ export const Switch: FunctionComponent> = (props) => { }, ])} > - {changing && loadingIcon ? ( + {loading && loadingIcon ? ( <>{loadingIcon} ) : ( <> diff --git a/src/sites/sites-react/doc/docs/react/migrate-from-v2.md b/src/sites/sites-react/doc/docs/react/migrate-from-v2.md index f986185539..aa80122103 100644 --- a/src/sites/sites-react/doc/docs/react/migrate-from-v2.md +++ b/src/sites/sites-react/doc/docs/react/migrate-from-v2.md @@ -239,6 +239,8 @@ plugins: [ - `activeText` 属性类型更改为`ReactNode` - `inactiveText` 属性类型更改为 `ReactNode` - 新增 `loadingIcon` 属性,受控 loading 态图标 +- 新增 `loading` 属性,loading 态受控 +- 新增 `onLodingingChange` ,切换 loading 态时触发 [//]: # '#### Toast' diff --git a/src/sites/sites-react/doc/docs/react/official-theme-react.md b/src/sites/sites-react/doc/docs/react/official-theme-react.md index e851e1c5b8..3d641eb27c 100644 --- a/src/sites/sites-react/doc/docs/react/official-theme-react.md +++ b/src/sites/sites-react/doc/docs/react/official-theme-react.md @@ -12,7 +12,6 @@ NutUI 默认提供多套官方`UI`主题,同时允许在一定程度上定制 | 京东 JDesign 主题 ([预览](https://nutui.jd.com/h5/react/jdesign-3x/#/zh-CN/component/button)) | `variables-jmapp.scss` | | 京东 JRKF 主题 | `variables-jrkf.scss` | - ## 使用方式 需要注意的是,配置主题时,你还需要在入口文件中引入 global 类的文件来加载一些 NutUI React 的全局性逻辑和样式: diff --git a/src/sites/sites-react/doc/docs/taro/migrate-from-v2.md b/src/sites/sites-react/doc/docs/taro/migrate-from-v2.md index e7f888b66d..5391e76faa 100644 --- a/src/sites/sites-react/doc/docs/taro/migrate-from-v2.md +++ b/src/sites/sites-react/doc/docs/taro/migrate-from-v2.md @@ -238,6 +238,8 @@ plugins: [ - `activeText` 属性类型更改为`ReactNode` - `inactiveText` 属性类型更改为 `ReactNode` - 新增 `loadingIcon` 属性,受控 loading 态图标 +- 新增 `loading` 属性,loading 态受控 +- 新增 `onLodingingChange` ,切换 loading 态时触发 [//]: # '#### Toast' diff --git a/src/types/spec/switch/base.ts b/src/types/spec/switch/base.ts index 156821089c..e0b81fd5d0 100644 --- a/src/types/spec/switch/base.ts +++ b/src/types/spec/switch/base.ts @@ -8,5 +8,7 @@ export interface BaseSwitch extends BaseProps { activeText: ReactNode inactiveText: ReactNode loadingIcon: ReactNode + loading: boolean | undefined + onLoadingChange: (loading: boolean) => void onChange: (val: boolean) => void }