From 10b343c424887e68c26c8deacdff90d1c49000c0 Mon Sep 17 00:00:00 2001 From: lv jiabiao <1160388820@qq.com> Date: Thu, 16 May 2024 14:38:46 +0800 Subject: [PATCH 1/7] Refactoring Icon and Navbar component codes according to code specifications. --- .../components/icon/src/icon.component.tsx | 35 ++++----- .../components/icon/src/icon.props.ts | 15 ++++ .../components/icon/src/icon.scss | 15 ++++ .../mobile-ui-vue/components/navbar/index.ts | 15 ++++ .../navbar/src/navbar.component.tsx | 71 ++++++++++--------- .../components/navbar/src/navbar.props.ts | 15 ++++ .../components/navbar/src/navbar.scss | 15 ++++ 7 files changed, 132 insertions(+), 49 deletions(-) diff --git a/packages/mobile-ui-vue/components/icon/src/icon.component.tsx b/packages/mobile-ui-vue/components/icon/src/icon.component.tsx index bc3e03c03b..01eb9a13e8 100644 --- a/packages/mobile-ui-vue/components/icon/src/icon.component.tsx +++ b/packages/mobile-ui-vue/components/icon/src/icon.component.tsx @@ -14,28 +14,31 @@ * limitations under the License. */ -import { defineComponent, computed } from "vue"; -import { addUnit } from "@/components/utils"; -import { iconProps } from "./icon.props"; -import './icon.scss' +import { defineComponent, computed, CSSProperties, ComputedRef, SetupContext } from 'vue'; +import { addUnit } from '@/components/utils'; +import { IconProps, iconProps } from './icon.props'; +import './icon.scss'; export default defineComponent({ - name: "FmIcon", + name: 'FmIcon', props: iconProps, emits: ['click'], - setup(props, { emit }) { - const style = computed(() => { - return { color: props.color, "font-size": props.size ? addUnit(props.size) : '' }; + setup(props: IconProps, context: SetupContext) { + const { emit } = context; + const iconClass: ComputedRef = computed(() => { + const { classPrefix, name } = props; + return [classPrefix, name ? `${classPrefix}-${name}` : '']; }); - const className = computed(() => { - return [ - props.classPrefix, - props.name ? props.classPrefix + "-" + props.name : "", - ]; + + const iconStyle: ComputedRef = computed(() => { + return { color: props.color, 'font-size': props.size ? addUnit(props.size) : '' }; }); - return ()=> ( - emit('click', event)}> + return () => ( + emit('click', event)}> ); - }, + } }); diff --git a/packages/mobile-ui-vue/components/icon/src/icon.props.ts b/packages/mobile-ui-vue/components/icon/src/icon.props.ts index 97cc89d013..33c6949881 100644 --- a/packages/mobile-ui-vue/components/icon/src/icon.props.ts +++ b/packages/mobile-ui-vue/components/icon/src/icon.props.ts @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import { ExtractPropTypes } from 'vue'; export const iconProps = { diff --git a/packages/mobile-ui-vue/components/icon/src/icon.scss b/packages/mobile-ui-vue/components/icon/src/icon.scss index f3d844f73e..7925e21092 100644 --- a/packages/mobile-ui-vue/components/icon/src/icon.scss +++ b/packages/mobile-ui-vue/components/icon/src/icon.scss @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ @import '@/theme/index.scss'; @font-face { diff --git a/packages/mobile-ui-vue/components/navbar/index.ts b/packages/mobile-ui-vue/components/navbar/index.ts index bb62eb0ce4..eec9c3a57a 100644 --- a/packages/mobile-ui-vue/components/navbar/index.ts +++ b/packages/mobile-ui-vue/components/navbar/index.ts @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import { withInstall } from '../utils' import _Navbar from './src/navbar.component' diff --git a/packages/mobile-ui-vue/components/navbar/src/navbar.component.tsx b/packages/mobile-ui-vue/components/navbar/src/navbar.component.tsx index bce987d930..98ab37cf59 100644 --- a/packages/mobile-ui-vue/components/navbar/src/navbar.component.tsx +++ b/packages/mobile-ui-vue/components/navbar/src/navbar.component.tsx @@ -1,46 +1,51 @@ -import { defineComponent } from "vue"; -import { navbarProps } from './navbar.props' -import './navbar.scss' +import { SetupContext, defineComponent } from 'vue'; +import { NavbarProps, navbarProps } from './navbar.props'; +import './navbar.scss'; export default defineComponent({ name: 'fm-navbar', props: navbarProps, emits: ['click-left', 'click-right'], - setup(props, { emit, slots }) { + setup(props: NavbarProps, context: SetupContext) { + const { emit, slots } = context; + const handlerClickLeft = (event) => { - emit('click-left', event) - } + emit('click-left', event); + }; + const handlerClickRight = (event) => { - emit('click-right', event) - } - const className = { + emit('click-right', event); + }; + + const navbarClass = { 'fm-navbar': true, 'fm-navbar-fixed': props.fixed, 'fm-navbar-border-bottom': props.border - } - return () => <> -
- { - (props.leftArrow || props.leftText) &&
- { - slots.left ? slots.left() : <> - {props.leftArrow && } - {props.leftText && { props.leftText }} - - } + }; + + return () => ( + <> +
+ {(props.leftArrow || props.leftText) && ( +
+ {slots.left ? ( + slots.left() + ) : ( + <> + {props.leftArrow && ( + + )} + {props.leftText && {props.leftText}} + + )} +
+ )} +
{slots.title ? slots.title() : props.title}
+
+ {slots.right ? slots.right() : {props.rightText}}
- } -
- { - slots.title ? slots.title() : props.title - } -
-
- { - slots.right ? slots.right() : {props.rightText} - }
-
- + + ); } -}) \ No newline at end of file +}); diff --git a/packages/mobile-ui-vue/components/navbar/src/navbar.props.ts b/packages/mobile-ui-vue/components/navbar/src/navbar.props.ts index 329a8acc5e..fb07cb2365 100644 --- a/packages/mobile-ui-vue/components/navbar/src/navbar.props.ts +++ b/packages/mobile-ui-vue/components/navbar/src/navbar.props.ts @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import { ExtractPropTypes } from 'vue'; export const navbarProps = { diff --git a/packages/mobile-ui-vue/components/navbar/src/navbar.scss b/packages/mobile-ui-vue/components/navbar/src/navbar.scss index e6f86101ac..7551cf4776 100644 --- a/packages/mobile-ui-vue/components/navbar/src/navbar.scss +++ b/packages/mobile-ui-vue/components/navbar/src/navbar.scss @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ @import '@/theme/index.scss'; @import '@/theme/src/mixins/hairline.scss'; @import '@/theme/src/mixins/ellipsis.scss'; -- Gitee From 81454d276527a9104ce8994f796540e894dbe6f6 Mon Sep 17 00:00:00 2001 From: lv jiabiao <1160388820@qq.com> Date: Tue, 21 May 2024 14:15:15 +0800 Subject: [PATCH 2/7] feature:Add switch component --- packages/mobile-ui-vue/components/index.ts | 4 +- .../mobile-ui-vue/components/switch/index.ts | 21 +++++ .../switch/src/switch.component.tsx | 76 +++++++++++++++++++ .../components/switch/src/switch.props.ts | 58 ++++++++++++++ .../components/switch/src/switch.scss | 69 +++++++++++++++++ .../mobile-ui-vue/demos/switch/index.html | 30 ++++++++ packages/mobile-ui-vue/demos/switch/index.js | 13 ++++ packages/mobile-ui-vue/demos/switch/index.vue | 5 ++ .../docs/.vitepress/config/sidebar.ts | 1 + .../docs/components/switch/index.md | 5 ++ packages/mobile-ui-vue/src/menu-data.ts | 8 +- 11 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 packages/mobile-ui-vue/components/switch/index.ts create mode 100644 packages/mobile-ui-vue/components/switch/src/switch.component.tsx create mode 100644 packages/mobile-ui-vue/components/switch/src/switch.props.ts create mode 100644 packages/mobile-ui-vue/components/switch/src/switch.scss create mode 100644 packages/mobile-ui-vue/demos/switch/index.html create mode 100644 packages/mobile-ui-vue/demos/switch/index.js create mode 100644 packages/mobile-ui-vue/demos/switch/index.vue create mode 100644 packages/mobile-ui-vue/docs/components/switch/index.md diff --git a/packages/mobile-ui-vue/components/index.ts b/packages/mobile-ui-vue/components/index.ts index ca644553a3..02a8e1db6d 100644 --- a/packages/mobile-ui-vue/components/index.ts +++ b/packages/mobile-ui-vue/components/index.ts @@ -20,6 +20,7 @@ import Cell from './cell'; import Icon from './icon'; import Input from './input'; import Navbar from './navbar'; +import Switch from './switch'; import { Checkbox, CheckboxGroupItem, CheckboxGroup } from './checkbox'; import { RadioGroupItem, RadioGroup } from './radio'; import Rate from './rate'; @@ -39,6 +40,7 @@ const components = [ Icon, Input, Navbar, + Switch, RadioGroupItem, RadioGroup, Rate, @@ -54,7 +56,7 @@ const install = (app: App): void => { app.use(component); }); }; -export { Button, Cell, Checkbox, CheckboxGroupItem, CheckboxGroup, Icon, Input, Navbar, RadioGroupItem, RadioGroup, Rate, Form, FormItem, Popup, Overlay }; +export { Button, Cell, Checkbox, CheckboxGroupItem, CheckboxGroup, Icon, Input, Navbar, RadioGroupItem, RadioGroup, Rate, Switch, Form, FormItem, Popup, Overlay }; export default { install }; diff --git a/packages/mobile-ui-vue/components/switch/index.ts b/packages/mobile-ui-vue/components/switch/index.ts new file mode 100644 index 0000000000..c0abdfc081 --- /dev/null +++ b/packages/mobile-ui-vue/components/switch/index.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { withInstall } from '../utils'; +import _Switch from "./src/switch.component"; +const Switch = withInstall(_Switch); + +export { Switch }; +export default Switch; diff --git a/packages/mobile-ui-vue/components/switch/src/switch.component.tsx b/packages/mobile-ui-vue/components/switch/src/switch.component.tsx new file mode 100644 index 0000000000..36ddf68de9 --- /dev/null +++ b/packages/mobile-ui-vue/components/switch/src/switch.component.tsx @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { CSSProperties, SetupContext, computed, defineComponent, Ref } from 'vue'; +import { SwitchProps, switchProps } from './switch.props'; +import { useBem } from '@/components/hook'; +import './switch.scss'; + +const name = 'fm-switch'; + +export default defineComponent({ + name, + props: switchProps, + emits: ['click', 'update:modelValue', 'change'] as (string[] & ThisType) | undefined, + setup(props: SwitchProps, context: SetupContext) { + const { emit } = context; + const { bem } = useBem(name); + + const checked = computed(() => { + return props.modelValue === props.activeValue; + }); + + const onClick = (event) => { + emit('click', event); + const shouldEmitValue = !props.disabled && !props.loading && !props.readonly; + if (shouldEmitValue) { + const innerValue = checked.value ? props.inactiveValue : props.activeValue; + emit('update:modelValue', innerValue); + emit('change', innerValue); + } + }; + + const switchClass = computed(() => ({ + [name]: true, + [bem('', 'on')]: checked.value, + [bem('', 'loading')]: props.loading, + [bem('', 'disabled')]: props.disabled, + [bem('', 'readonly')]: props.readonly + })); + + const switchStyle: Ref = computed(() => { + return { + fontSize: props.size + 'px', + backgroundColor: checked.value ? props.activeColor : props.inactiveColor + }; + }); + + const renderLoading = () => { + return ( + + + + + + ); + }; + + return () => ( +
+
{props.loading && renderLoading()}
+
+ ); + } +}); diff --git a/packages/mobile-ui-vue/components/switch/src/switch.props.ts b/packages/mobile-ui-vue/components/switch/src/switch.props.ts new file mode 100644 index 0000000000..7c2e235522 --- /dev/null +++ b/packages/mobile-ui-vue/components/switch/src/switch.props.ts @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ExtractPropTypes } from 'vue'; + + +export const switchProps = { + modelValue: { + type: Boolean, + default: false, + }, + disabled: { + type: Boolean, + default: false, + }, + readonly: { + type: Boolean, + default: false, + }, + loading: { + type: Boolean, + default: false, + }, + size: { + type: Number, + default: 28, + }, + activeColor: { + type: String, + default: '', + }, + inactiveColor: { + type: String, + default: '', + }, + activeValue: { + type: [Boolean, Number, String], + default: true, + }, + inactiveValue: { + type: [Boolean, Number, String], + default: false, + }, +}; + +export type SwitchProps = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/switch/src/switch.scss b/packages/mobile-ui-vue/components/switch/src/switch.scss new file mode 100644 index 0000000000..fe6f09ca9f --- /dev/null +++ b/packages/mobile-ui-vue/components/switch/src/switch.scss @@ -0,0 +1,69 @@ +@import '@/theme/src/mixins/hairline.scss'; + +:root { + --fm-switch-background: var(--fm-text-color-light); + --fm-switch-on-color: var(--fm-primary-color); +} + +.fm-switch { + position: relative; + display: inline-block; + width: 50px; + height: 30px; + font-size: 30px; + border-radius: 40px; + cursor: pointer; + transition: background-color var(--fm-duration-base); + background-color: var(--fm-switch-background); + &-node { + position: absolute; + top: 1px; + left: 1px; + z-index: 1; + width: 28px; + height: 28px; + border-radius: 100%; + background-color: var(--fm-white); + transition: transform var(--fm-duration-base) cubic-bezier(0.3, 1.05, 0.4, 1.05); + .fm-switch-loading-icon { + position: absolute; + top: 25%; + left: 25%; + width: 50%; + height: 50%; + line-height: 1; + color: var(--fm-switch-on-color); + circle { + animation: fm-circular 1.5s ease-in-out infinite; + stroke: currentColor; + stroke-width: 3; + stroke-linecap: round; + } + &-circular { + vertical-align: super; + } + } + } + + &--on { + background-color: var(--fm-switch-on-color); + .fm-switch-node { + transform: translateX(calc(50px - 30px)); + } + .fm-switch-loading { + color: var(--fm-switch-on-color); + } + } + &--disabled { + cursor: not-allowed; + opacity: var(--fm-disabled-opacity); + } + &--readonly { + cursor: default; + opacity: var(--fm-readonly-opacity); + } + + &--loading { + cursor: default; + } +} diff --git a/packages/mobile-ui-vue/demos/switch/index.html b/packages/mobile-ui-vue/demos/switch/index.html new file mode 100644 index 0000000000..832858f76f --- /dev/null +++ b/packages/mobile-ui-vue/demos/switch/index.html @@ -0,0 +1,30 @@ +
+

基础用法

+
+ + +
+

禁用状态

+
+ + +
+

只读状态

+
+ + +
+

加载状态

+
+ + +
+

大小

+
+
+ + +
+

指定颜色

+
+ \ No newline at end of file diff --git a/packages/mobile-ui-vue/demos/switch/index.js b/packages/mobile-ui-vue/demos/switch/index.js new file mode 100644 index 0000000000..7640d6cc82 --- /dev/null +++ b/packages/mobile-ui-vue/demos/switch/index.js @@ -0,0 +1,13 @@ +import { ref } from 'vue'; +export default { + name: 'switch-demo', + setup() { + const checkValue = ref(true); + const unCheckValue = ref(false); + + return { + checkValue, + unCheckValue + }; + } +}; diff --git a/packages/mobile-ui-vue/demos/switch/index.vue b/packages/mobile-ui-vue/demos/switch/index.vue new file mode 100644 index 0000000000..d8d182aebc --- /dev/null +++ b/packages/mobile-ui-vue/demos/switch/index.vue @@ -0,0 +1,5 @@ + + + diff --git a/packages/mobile-ui-vue/docs/.vitepress/config/sidebar.ts b/packages/mobile-ui-vue/docs/.vitepress/config/sidebar.ts index b83fcbfcb0..f30ec28aaa 100644 --- a/packages/mobile-ui-vue/docs/.vitepress/config/sidebar.ts +++ b/packages/mobile-ui-vue/docs/.vitepress/config/sidebar.ts @@ -17,6 +17,7 @@ const sidebar = [ { text: 'RadioGroup 单选组', link: '/components/radio/' }, { text: 'Checkbox Group 复选框', link: '/components/checkbox/' }, { text: 'Rate 评分', link: '/components/rate/' }, + { text: 'Switch 开关', link: '/components/switch/' }, ] }, { diff --git a/packages/mobile-ui-vue/docs/components/switch/index.md b/packages/mobile-ui-vue/docs/components/switch/index.md new file mode 100644 index 0000000000..c7b616ae24 --- /dev/null +++ b/packages/mobile-ui-vue/docs/components/switch/index.md @@ -0,0 +1,5 @@ +--- +demo: switch +--- + +# Switch 开关 diff --git a/packages/mobile-ui-vue/src/menu-data.ts b/packages/mobile-ui-vue/src/menu-data.ts index 3a7bce107c..f81ab23545 100644 --- a/packages/mobile-ui-vue/src/menu-data.ts +++ b/packages/mobile-ui-vue/src/menu-data.ts @@ -73,7 +73,13 @@ export default { name: "picker", url: "/demos/picker", component: "/picker", - } + }, + { + title: "开关", + name: "switch", + url: "/demos/switch", + component: "/switch", + }, ], } ] -- Gitee From e2975b7084083a18f5a6f4f20f360d346a152cb0 Mon Sep 17 00:00:00 2001 From: lv jiabiao <1160388820@qq.com> Date: Tue, 21 May 2024 14:55:03 +0800 Subject: [PATCH 3/7] Add switch component docs --- packages/mobile-ui-vue/demos/switch/index.vue | 5 +- .../docs/components/switch/index.md | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/packages/mobile-ui-vue/demos/switch/index.vue b/packages/mobile-ui-vue/demos/switch/index.vue index d8d182aebc..69956a31f4 100644 --- a/packages/mobile-ui-vue/demos/switch/index.vue +++ b/packages/mobile-ui-vue/demos/switch/index.vue @@ -1,5 +1,2 @@ - - + diff --git a/packages/mobile-ui-vue/docs/components/switch/index.md b/packages/mobile-ui-vue/docs/components/switch/index.md index c7b616ae24..12fcd8b0a9 100644 --- a/packages/mobile-ui-vue/docs/components/switch/index.md +++ b/packages/mobile-ui-vue/docs/components/switch/index.md @@ -3,3 +3,77 @@ demo: switch --- # Switch 开关 + +### 介绍 + +用于设置一个开关操作。 + +## 代码演示 + +### 基础用法 + +通过 `v-model` 来绑定当前值。 + +```html + +``` + +### 禁用状态 + +通过设置 `disabled` 属性来禁用组件。 + +```html + +``` + +### 只读状态 + +通过设置 `readonly` 属性来阻止组件状态改变。 + +```html + +``` + +### 加载状态 + +通过设置 `loading` 属性来显示加载状态。 + +```html + +``` + +### 大小 + +通过设置 `size` 属性可以改变组件的大小。 + +```html +
+``` + +### 指定颜色 + +通过设置 `active-color` 和 `inactive-color` 属性可以分别定义打开和关闭时的颜色。 + +```html + +``` + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| -------------- | ------------------------------------------ | ------------------ | --------- | +| v-model | 绑定值 | _string_ | `default` | +| disabled | 是否禁用 | _boolean_ | `false` | +| readonly | 是否为只读状态,只读状态下无法修改组件状态 | _boolean_ | `false` | +| loading | 是否为加载状态 | _boolean_ | `false` | +| size | 组件尺寸 | _string \| number_ | `-` | +| active-color | 打开时的颜色 | _string_ | `-` | +| inactive-color | 关闭时的颜色 | _string_ | `-` | + +### Events + +| 事件名 | 说明 | 回调参数 | +| ------ | -------------- | -------- | +| change | 值变化之后触发 | - | -- Gitee From 9a0f23f169a7deb654944571c51bc21499ab6015 Mon Sep 17 00:00:00 2001 From: lv jiabiao <1160388820@qq.com> Date: Tue, 21 May 2024 16:39:41 +0800 Subject: [PATCH 4/7] Feature:add toast components --- packages/mobile-ui-vue/components/index.ts | 4 +- .../switch/src/switch.component.tsx | 2 +- .../components/switch/src/switch.scss | 6 +- .../mobile-ui-vue/components/toast/index.ts | 21 +++++ .../components/toast/src/toast.component.tsx | 83 +++++++++++++++++++ .../components/toast/src/toast.props.ts | 49 +++++++++++ .../components/toast/src/toast.scss | 79 ++++++++++++++++++ packages/mobile-ui-vue/demos/toast/index.html | 30 +++++++ packages/mobile-ui-vue/demos/toast/index.js | 13 +++ packages/mobile-ui-vue/demos/toast/index.vue | 2 + packages/mobile-ui-vue/src/menu-data.ts | 6 ++ 11 files changed, 290 insertions(+), 5 deletions(-) create mode 100644 packages/mobile-ui-vue/components/toast/index.ts create mode 100644 packages/mobile-ui-vue/components/toast/src/toast.component.tsx create mode 100644 packages/mobile-ui-vue/components/toast/src/toast.props.ts create mode 100644 packages/mobile-ui-vue/components/toast/src/toast.scss create mode 100644 packages/mobile-ui-vue/demos/toast/index.html create mode 100644 packages/mobile-ui-vue/demos/toast/index.js create mode 100644 packages/mobile-ui-vue/demos/toast/index.vue diff --git a/packages/mobile-ui-vue/components/index.ts b/packages/mobile-ui-vue/components/index.ts index 02a8e1db6d..44f1f33848 100644 --- a/packages/mobile-ui-vue/components/index.ts +++ b/packages/mobile-ui-vue/components/index.ts @@ -21,6 +21,7 @@ import Icon from './icon'; import Input from './input'; import Navbar from './navbar'; import Switch from './switch'; +import Toast from './toast'; import { Checkbox, CheckboxGroupItem, CheckboxGroup } from './checkbox'; import { RadioGroupItem, RadioGroup } from './radio'; import Rate from './rate'; @@ -41,6 +42,7 @@ const components = [ Input, Navbar, Switch, + Toast, RadioGroupItem, RadioGroup, Rate, @@ -56,7 +58,7 @@ const install = (app: App): void => { app.use(component); }); }; -export { Button, Cell, Checkbox, CheckboxGroupItem, CheckboxGroup, Icon, Input, Navbar, RadioGroupItem, RadioGroup, Rate, Switch, Form, FormItem, Popup, Overlay }; +export { Button, Cell, Checkbox, CheckboxGroupItem, CheckboxGroup, Icon, Input, Navbar, RadioGroupItem, RadioGroup, Rate, Switch, Toast, Form, FormItem, Popup, Overlay }; export default { install }; diff --git a/packages/mobile-ui-vue/components/switch/src/switch.component.tsx b/packages/mobile-ui-vue/components/switch/src/switch.component.tsx index 36ddf68de9..03637c3cc9 100644 --- a/packages/mobile-ui-vue/components/switch/src/switch.component.tsx +++ b/packages/mobile-ui-vue/components/switch/src/switch.component.tsx @@ -52,7 +52,7 @@ export default defineComponent({ const switchStyle: Ref = computed(() => { return { - fontSize: props.size + 'px', + fontSize: props.size + 'px !important', backgroundColor: checked.value ? props.activeColor : props.inactiveColor }; }); diff --git a/packages/mobile-ui-vue/components/switch/src/switch.scss b/packages/mobile-ui-vue/components/switch/src/switch.scss index fe6f09ca9f..6c28a76730 100644 --- a/packages/mobile-ui-vue/components/switch/src/switch.scss +++ b/packages/mobile-ui-vue/components/switch/src/switch.scss @@ -1,6 +1,6 @@ -@import '@/theme/src/mixins/hairline.scss'; - -:root { +@import '@/theme/index.scss'; +:root, +:host { --fm-switch-background: var(--fm-text-color-light); --fm-switch-on-color: var(--fm-primary-color); } diff --git a/packages/mobile-ui-vue/components/toast/index.ts b/packages/mobile-ui-vue/components/toast/index.ts new file mode 100644 index 0000000000..74c81b3ff9 --- /dev/null +++ b/packages/mobile-ui-vue/components/toast/index.ts @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { withInstall } from '../utils'; +import _Toast from "./src/toast.component"; +const Toast = withInstall(_Toast); + +export { Toast }; +export default Toast; diff --git a/packages/mobile-ui-vue/components/toast/src/toast.component.tsx b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx new file mode 100644 index 0000000000..43715bbbe7 --- /dev/null +++ b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { SetupContext, computed, defineComponent } from 'vue'; +import { ToastProps, toastProps } from './toast.props'; +import { useBem } from '@/components/hook'; +import { FmIcon } from '@/components/icon'; +import './toast.scss'; + +const name = 'fm-toast'; + +export default defineComponent({ + name, + props: toastProps, + components: {}, + emits: ['click', 'update:modelValue', 'change'] as (string[] & ThisType) | undefined, + setup(props: ToastProps, context: SetupContext) { + const { emit } = context; + const { bem } = useBem(name); + + const isLoadding = computed(() => { + return props.type === 'loading'; + }); + const iconName = computed(() => { + if (props.icon) { + return props.icon; + } + let name = ''; + switch (props.type) { + case 'success': + name = 'successfulhints'; + break; + case 'info': + case 'warning': + name = 'warningmessage'; + break; + case 'error': + name = 'failureprompt'; + break; + default: + name = ''; + break; + } + return name; + }); + + const toastClass = computed(() => ({ + [name]: true, + [`${name + props.type}`]: true, + [`${name + props.position}`]: true + })); + const { show } = props; + return () => ( +
+ {isLoadding.value ? ( + + + + + + ) : iconName.value ? ( + + ) : null} + {props.message} +
+ ); + } +}); diff --git a/packages/mobile-ui-vue/components/toast/src/toast.props.ts b/packages/mobile-ui-vue/components/toast/src/toast.props.ts new file mode 100644 index 0000000000..2522f15821 --- /dev/null +++ b/packages/mobile-ui-vue/components/toast/src/toast.props.ts @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ExtractPropTypes } from 'vue'; + + +export const toastProps = { + show: { + type: Boolean, + default: false, + }, + type: { + type: String, + default: 'info', + validator: function (value: string) { + // 这个值必须匹配下列字符串中的一个 + return ( + ['success', 'warning', 'error', 'info', 'default', `loading`].indexOf( + value + ) !== -1 + ) + }, + }, + position: { + type: String, + default: 'middle', + }, + message: String, + icon: String, + duration: { + type: Number, + default: 3000, + }, + overlay: Boolean +}; + +export type ToastProps = ExtractPropTypes; diff --git a/packages/mobile-ui-vue/components/toast/src/toast.scss b/packages/mobile-ui-vue/components/toast/src/toast.scss new file mode 100644 index 0000000000..e165328a5b --- /dev/null +++ b/packages/mobile-ui-vue/components/toast/src/toast.scss @@ -0,0 +1,79 @@ +@import '@/theme/index.scss'; + +:root { + --fm-toast-zindex: var(--fm-zindex-5); + --fm-toast-color: var(--fm-white); + --fm-toast-font-size: 16px; + --fm-toast-background: var(--fm-gray-8); + --fm-toast-icon-font-size: 48px; +} + +.fm-toast { + position: fixed; + top: 50%; + left: 50%; + display: -webkit-box; + display: -webkit-flex; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + box-sizing: content-box; + max-width: 70%; + padding: 16px; + line-height: 20px; + white-space: pre-wrap; + text-align: center; + word-wrap: break-word; + border-radius: 7px; + transform: translate(-50%, -50%); + color: var(--fm-toast-color); + z-index: var(--fm-toast-zindex); + font-size: var(--fm-toast-font-size); + background-color: var(--fm-toast-background); + &-text { + background-color: red; + } + &-top { + top: 50px; + transform: translate(-50%, 0); + } + &-bottom { + top: auto; + bottom: 50px; + } + &-info, + &-success, + &-warning, + &-error { + width: 88px; + min-height: 88px; + } + + &-icon { + margin-bottom: 8px; + font-size: var(--fm-toast-icon-font-size); + } + &-default { + padding: 8px 16px; + } + &-loading { + min-width: 84px; + min-height: 84px; + } + &-loading-icon { + position: relative; + display: inline-block; + width: 30px; + height: 30px; + margin-bottom: 8px; + vertical-align: middle; + animation: fm-rotate 2s linear infinite; + circle { + animation: fm-circular 1.5s ease-in-out infinite; + stroke: currentColor; + stroke-width: 4; + stroke-linecap: round; + } + } +} diff --git a/packages/mobile-ui-vue/demos/toast/index.html b/packages/mobile-ui-vue/demos/toast/index.html new file mode 100644 index 0000000000..d460cc5868 --- /dev/null +++ b/packages/mobile-ui-vue/demos/toast/index.html @@ -0,0 +1,30 @@ +
+

基础用法

+
+ + +
+

禁用状态

+
+ + +
+

只读状态

+
+ + +
+

加载状态

+
+ + +
+

大小

+
+
+ + +
+

指定颜色

+
+ \ No newline at end of file diff --git a/packages/mobile-ui-vue/demos/toast/index.js b/packages/mobile-ui-vue/demos/toast/index.js new file mode 100644 index 0000000000..5c113f30f0 --- /dev/null +++ b/packages/mobile-ui-vue/demos/toast/index.js @@ -0,0 +1,13 @@ +import { ref } from 'vue'; +export default { + name: 'toast-demo', + setup() { + const checkValue = ref(true); + const unCheckValue = ref(false); + + return { + checkValue, + unCheckValue + }; + } +}; diff --git a/packages/mobile-ui-vue/demos/toast/index.vue b/packages/mobile-ui-vue/demos/toast/index.vue new file mode 100644 index 0000000000..69956a31f4 --- /dev/null +++ b/packages/mobile-ui-vue/demos/toast/index.vue @@ -0,0 +1,2 @@ + + diff --git a/packages/mobile-ui-vue/src/menu-data.ts b/packages/mobile-ui-vue/src/menu-data.ts index f81ab23545..3f6c8fed08 100644 --- a/packages/mobile-ui-vue/src/menu-data.ts +++ b/packages/mobile-ui-vue/src/menu-data.ts @@ -80,6 +80,12 @@ export default { url: "/demos/switch", component: "/switch", }, + { + title: "轻提示", + name: "toast", + url: "/demos/toast", + component: "/toast", + }, ], } ] -- Gitee From 1bfdffae0e76dbe3e15a9d2f49efa8fcc27fde4d Mon Sep 17 00:00:00 2001 From: lv jiabiao <1160388820@qq.com> Date: Tue, 21 May 2024 20:02:34 +0800 Subject: [PATCH 5/7] init toast component --- packages/mobile-ui-vue/components/index.scss | 4 +- .../switch/src/switch.component.tsx | 2 +- .../mobile-ui-vue/components/toast/index.ts | 105 +++++++++++++++++- .../components/toast/src/toast.component.tsx | 52 +++++---- packages/mobile-ui-vue/demos/toast/index.html | 27 +---- 5 files changed, 141 insertions(+), 49 deletions(-) diff --git a/packages/mobile-ui-vue/components/index.scss b/packages/mobile-ui-vue/components/index.scss index f11af2eb19..bbaff71bad 100644 --- a/packages/mobile-ui-vue/components/index.scss +++ b/packages/mobile-ui-vue/components/index.scss @@ -9,4 +9,6 @@ @import './rate/src/rate.scss'; @import './form/src/form-item.scss'; @import './overlay/src/overlay.scss'; -@import './popup/src/popup.scss'; \ No newline at end of file +@import './popup/src/popup.scss'; +@import './switch/src/switch.scss'; +@import './toast/src/toast.scss'; diff --git a/packages/mobile-ui-vue/components/switch/src/switch.component.tsx b/packages/mobile-ui-vue/components/switch/src/switch.component.tsx index 03637c3cc9..36ddf68de9 100644 --- a/packages/mobile-ui-vue/components/switch/src/switch.component.tsx +++ b/packages/mobile-ui-vue/components/switch/src/switch.component.tsx @@ -52,7 +52,7 @@ export default defineComponent({ const switchStyle: Ref = computed(() => { return { - fontSize: props.size + 'px !important', + fontSize: props.size + 'px', backgroundColor: checked.value ? props.activeColor : props.inactiveColor }; }); diff --git a/packages/mobile-ui-vue/components/toast/index.ts b/packages/mobile-ui-vue/components/toast/index.ts index 74c81b3ff9..32e5f0bf28 100644 --- a/packages/mobile-ui-vue/components/toast/index.ts +++ b/packages/mobile-ui-vue/components/toast/index.ts @@ -15,7 +15,108 @@ */ import { withInstall } from '../utils'; import _Toast from "./src/toast.component"; -const Toast = withInstall(_Toast); +const FMToast = withInstall(_Toast); + +import { isObject, inBrowser } from '@/components/utils'; +import { mountComponent, usePopupState } from '@/components/hook'; +import { App } from 'vue'; + + +let instance +let timer +function defaultOptions() { + return { + type: 'default', + message: '', + icon: '', + duration: 3000, + position: 'middle', + overlay: false + } +} + +function parseOptions(message) { + return isObject(message) ? message : { message } +} + +const initInstance = () => { + ; ({ instance } = mountComponent({ + setup() { + const { state, toggle } = usePopupState() + return () => + }, + })) +} + +function Toast(options) { + if (!inBrowser) { + return + } + + if (!instance) { + initInstance() + } + + options = { + ...Toast.currentOptions, + ...parseOptions(options), + } + + instance.open(options) + clearTimeout(timer) + + if (options.duration > 0) { + timer = setTimeout(Toast.clear, options.duration) + } + + return instance +} + +Toast.clear = () => { + if (instance) { + instance.toggle(false) + } +} + +Toast.info = (options) => { + // Toast.resetDefaultOptions() + return Toast({ ...parseOptions(options), type: 'info' }) +} +Toast.success = (options) => { + // Toast.resetDefaultOptions() + return Toast({ ...parseOptions(options), type: 'success' }) +} +Toast.error = (options) => { + // Toast.resetDefaultOptions() + return Toast({ ...parseOptions(options), type: 'error' }) +} +Toast.warning = (options) => { + // Toast.resetDefaultOptions() + return Toast({ ...parseOptions(options), type: 'warning' }) +} +Toast.loading = (options) => { + // Toast.resetDefaultOptions() + return Toast({ ...parseOptions(options), type: 'loading', duration: 0 }) +} + +Toast.currentOptions = defaultOptions() + +Toast.setDefaultOptions = options => { + Object.assign(Toast.currentOptions, options) +} + +Toast.resetDefaultOptions = () => { + Toast.currentOptions = defaultOptions() +} + +Toast.install = (app: App) => { + // app.use(FMDialog) + app.component(FMToast.name, FMToast) + app.config.globalProperties.$toast = Toast +} + +Toast.Component = FMToast export { Toast }; -export default Toast; + +export default Toast diff --git a/packages/mobile-ui-vue/components/toast/src/toast.component.tsx b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx index 43715bbbe7..f13fb4f637 100644 --- a/packages/mobile-ui-vue/components/toast/src/toast.component.tsx +++ b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx @@ -16,7 +16,8 @@ import { SetupContext, computed, defineComponent } from 'vue'; import { ToastProps, toastProps } from './toast.props'; import { useBem } from '@/components/hook'; -import { FmIcon } from '@/components/icon'; +import Icon from '@/components/icon'; +import Overlay from '@/components/overlay'; import './toast.scss'; const name = 'fm-toast'; @@ -24,15 +25,12 @@ const name = 'fm-toast'; export default defineComponent({ name, props: toastProps, - components: {}, + components: { [Overlay.name]: Overlay, [Icon.name]: Icon }, emits: ['click', 'update:modelValue', 'change'] as (string[] & ThisType) | undefined, setup(props: ToastProps, context: SetupContext) { const { emit } = context; const { bem } = useBem(name); - const isLoadding = computed(() => { - return props.type === 'loading'; - }); const iconName = computed(() => { if (props.icon) { return props.icon; @@ -61,23 +59,35 @@ export default defineComponent({ [`${name + props.type}`]: true, [`${name + props.position}`]: true })); - const { show } = props; + + const isLoadding = computed(() => { + return props.type === 'loading'; + }); + + const { show, overlay } = props; + return () => ( -
- {isLoadding.value ? ( - - - - - - ) : iconName.value ? ( - - ) : null} - {props.message} -
+ <> +
+ {isLoadding.value ? ( + + + + + + ) : iconName.value ? ( + + ) : null} + {props.message} +
+ + ); } }); diff --git a/packages/mobile-ui-vue/demos/toast/index.html b/packages/mobile-ui-vue/demos/toast/index.html index d460cc5868..32139fea7c 100644 --- a/packages/mobile-ui-vue/demos/toast/index.html +++ b/packages/mobile-ui-vue/demos/toast/index.html @@ -1,30 +1,9 @@

基础用法

- +
-

禁用状态

+

overlay

- - -
-

只读状态

-
- - -
-

加载状态

-
- - -
-

大小

-
-
- - -
-

指定颜色

-
- \ No newline at end of file + \ No newline at end of file -- Gitee From 7970f52bb2b918bf5998375268538f8a14ec3ffe Mon Sep 17 00:00:00 2001 From: lv jiabiao <1160388820@qq.com> Date: Wed, 22 May 2024 19:32:29 +0800 Subject: [PATCH 6/7] feature:add toast component --- .../button/src/button.component.tsx | 4 +- .../mobile-ui-vue/components/hook/index.ts | 2 + .../components/hook/use-expose/index.ts | 9 ++ .../hook/use-mount-component/index.ts | 48 +++++++ .../mobile-ui-vue/components/toast/index.ts | 125 +----------------- .../components/toast/src/index.tsx | 99 ++++++++++++++ .../components/toast/src/toast.component.tsx | 58 ++++---- .../components/toast/src/toast.scss | 25 ++-- .../mobile-ui-vue/demos/button/index.html | 6 +- packages/mobile-ui-vue/demos/toast/index.html | 12 +- packages/mobile-ui-vue/demos/toast/index.js | 36 ++++- .../docs/components/button/index.md | 9 +- 12 files changed, 245 insertions(+), 188 deletions(-) create mode 100644 packages/mobile-ui-vue/components/hook/use-expose/index.ts create mode 100644 packages/mobile-ui-vue/components/hook/use-mount-component/index.ts create mode 100644 packages/mobile-ui-vue/components/toast/src/index.tsx diff --git a/packages/mobile-ui-vue/components/button/src/button.component.tsx b/packages/mobile-ui-vue/components/button/src/button.component.tsx index 4113364767..2859928593 100644 --- a/packages/mobile-ui-vue/components/button/src/button.component.tsx +++ b/packages/mobile-ui-vue/components/button/src/button.component.tsx @@ -24,9 +24,9 @@ export default defineComponent({ props: buttonProps, emits: ['click'] as (string[] & ThisType) | undefined, setup(props: ButtonProps, context: SetupContext) { - const slots = context.slots; + const { slots } = context; const { buttonClass, buttonStyle, onClickButton } = useButton(props, context); - const iconName = toRef(props.icon); + const iconName = toRef(props, 'icon'); const renderLoading = () => { return ( diff --git a/packages/mobile-ui-vue/components/hook/index.ts b/packages/mobile-ui-vue/components/hook/index.ts index 7a88ba7c16..e4c96b9f61 100644 --- a/packages/mobile-ui-vue/components/hook/index.ts +++ b/packages/mobile-ui-vue/components/hook/index.ts @@ -11,3 +11,5 @@ export * from './use-link' export * from './use-click-away' export * from './use-lock-scroll' export * from './use-momentum' +export * from './use-expose' +export * from './use-mount-component' \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/hook/use-expose/index.ts b/packages/mobile-ui-vue/components/hook/use-expose/index.ts new file mode 100644 index 0000000000..3a06d4ac46 --- /dev/null +++ b/packages/mobile-ui-vue/components/hook/use-expose/index.ts @@ -0,0 +1,9 @@ +import { getCurrentInstance } from 'vue'; + +// expose public api +export function useExpose(apis: Record) { + const instance = getCurrentInstance(); + if (instance) { + Object.assign(instance.proxy, apis); + } +} diff --git a/packages/mobile-ui-vue/components/hook/use-mount-component/index.ts b/packages/mobile-ui-vue/components/hook/use-mount-component/index.ts new file mode 100644 index 0000000000..bef519dafd --- /dev/null +++ b/packages/mobile-ui-vue/components/hook/use-mount-component/index.ts @@ -0,0 +1,48 @@ +import { useExpose } from "../use-expose"; +import { Component, createApp, nextTick, reactive } from "vue"; + +export function usePopupState() { + const state = reactive({ + show: false, + }); + + const toggle = (show: boolean) => { + state.show = show; + }; + + const open = (props: Record) => { + Object.assign(state, props); + + nextTick(() => { + toggle(true); + }); + }; + + const close = () => { + toggle(false); + }; + + useExpose({ open, close, toggle }); + + return { + open, + close, + state, + toggle, + }; +} + +export function mountComponent(RootComponent: Component) { + const app = createApp(RootComponent); + const root = document.createElement('div'); + + document.body.appendChild(root); + + return { + instance: app.mount(root), + unmount() { + app.unmount(); + document.body.removeChild(root); + }, + }; +} diff --git a/packages/mobile-ui-vue/components/toast/index.ts b/packages/mobile-ui-vue/components/toast/index.ts index 32e5f0bf28..482d5a789c 100644 --- a/packages/mobile-ui-vue/components/toast/index.ts +++ b/packages/mobile-ui-vue/components/toast/index.ts @@ -1,122 +1,3 @@ -/** - * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { withInstall } from '../utils'; -import _Toast from "./src/toast.component"; -const FMToast = withInstall(_Toast); - -import { isObject, inBrowser } from '@/components/utils'; -import { mountComponent, usePopupState } from '@/components/hook'; -import { App } from 'vue'; - - -let instance -let timer -function defaultOptions() { - return { - type: 'default', - message: '', - icon: '', - duration: 3000, - position: 'middle', - overlay: false - } -} - -function parseOptions(message) { - return isObject(message) ? message : { message } -} - -const initInstance = () => { - ; ({ instance } = mountComponent({ - setup() { - const { state, toggle } = usePopupState() - return () => - }, - })) -} - -function Toast(options) { - if (!inBrowser) { - return - } - - if (!instance) { - initInstance() - } - - options = { - ...Toast.currentOptions, - ...parseOptions(options), - } - - instance.open(options) - clearTimeout(timer) - - if (options.duration > 0) { - timer = setTimeout(Toast.clear, options.duration) - } - - return instance -} - -Toast.clear = () => { - if (instance) { - instance.toggle(false) - } -} - -Toast.info = (options) => { - // Toast.resetDefaultOptions() - return Toast({ ...parseOptions(options), type: 'info' }) -} -Toast.success = (options) => { - // Toast.resetDefaultOptions() - return Toast({ ...parseOptions(options), type: 'success' }) -} -Toast.error = (options) => { - // Toast.resetDefaultOptions() - return Toast({ ...parseOptions(options), type: 'error' }) -} -Toast.warning = (options) => { - // Toast.resetDefaultOptions() - return Toast({ ...parseOptions(options), type: 'warning' }) -} -Toast.loading = (options) => { - // Toast.resetDefaultOptions() - return Toast({ ...parseOptions(options), type: 'loading', duration: 0 }) -} - -Toast.currentOptions = defaultOptions() - -Toast.setDefaultOptions = options => { - Object.assign(Toast.currentOptions, options) -} - -Toast.resetDefaultOptions = () => { - Toast.currentOptions = defaultOptions() -} - -Toast.install = (app: App) => { - // app.use(FMDialog) - app.component(FMToast.name, FMToast) - app.config.globalProperties.$toast = Toast -} - -Toast.Component = FMToast - -export { Toast }; - -export default Toast +import Toast from './src/index' +export { Toast } +export default Toast \ No newline at end of file diff --git a/packages/mobile-ui-vue/components/toast/src/index.tsx b/packages/mobile-ui-vue/components/toast/src/index.tsx new file mode 100644 index 0000000000..608403ae5a --- /dev/null +++ b/packages/mobile-ui-vue/components/toast/src/index.tsx @@ -0,0 +1,99 @@ +import FMToast from './toast.component'; +import { isObject, inBrowser } from '@/components/utils'; +import { mountComponent, usePopupState } from '@/components/hook'; +import { App } from 'vue'; + +let instance; +let timer; +function defaultOptions() { + return { + type: 'default', + message: '', + icon: '', + duration: 3000, + position: 'middle', + overlay: false + }; +} + +function parseOptions(message) { + return isObject(message) ? message : { message }; +} + +const initInstance = () => { + ({ instance } = mountComponent({ + setup() { + const { state, toggle } = usePopupState(); + return () => ; + } + })); +}; + +function Toast(options) { + if (!inBrowser) { + return; + } + + if (!instance) { + initInstance(); + } + + options = { + ...Toast.currentOptions, + ...parseOptions(options) + }; + + instance.open(options); + clearTimeout(timer); + + if (options.duration > 0) { + timer = setTimeout(Toast.clear, options.duration); + } + + return instance; +} + +Toast.clear = () => { + if (instance) { + instance.toggle(false); + } +}; + +Toast.info = (options) => { + return Toast({ ...parseOptions(options), type: 'info' }); +}; + +Toast.success = (options) => { + return Toast({ ...parseOptions(options), type: 'success' }); +}; + +Toast.error = (options) => { + return Toast({ ...parseOptions(options), type: 'error' }); +}; + +Toast.warning = (options) => { + return Toast({ ...parseOptions(options), type: 'warning' }); +}; + +Toast.loading = (options) => { + return Toast({ ...parseOptions(options), type: 'loading', duration: 0 }); +}; + +Toast.currentOptions = defaultOptions(); + +Toast.setDefaultOptions = (options) => { + Object.assign(Toast.currentOptions, options); +}; + +Toast.resetDefaultOptions = () => { + Toast.currentOptions = defaultOptions(); +}; + +Toast.install = (app: App) => { + app.component(FMToast.name, FMToast); + app.config.globalProperties.$toast = Toast; +}; + +Toast.Component = FMToast; + +export default Toast; diff --git a/packages/mobile-ui-vue/components/toast/src/toast.component.tsx b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx index f13fb4f637..088ed75ac7 100644 --- a/packages/mobile-ui-vue/components/toast/src/toast.component.tsx +++ b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx @@ -16,8 +16,8 @@ import { SetupContext, computed, defineComponent } from 'vue'; import { ToastProps, toastProps } from './toast.props'; import { useBem } from '@/components/hook'; -import Icon from '@/components/icon'; -import Overlay from '@/components/overlay'; +import { Icon } from '@/components/icon'; +import { Overlay } from '@/components/overlay'; import './toast.scss'; const name = 'fm-toast'; @@ -25,10 +25,8 @@ const name = 'fm-toast'; export default defineComponent({ name, props: toastProps, - components: { [Overlay.name]: Overlay, [Icon.name]: Icon }, - emits: ['click', 'update:modelValue', 'change'] as (string[] & ThisType) | undefined, + emits: ['click', 'update:modelValue', 'change'], setup(props: ToastProps, context: SetupContext) { - const { emit } = context; const { bem } = useBem(name); const iconName = computed(() => { @@ -56,37 +54,39 @@ export default defineComponent({ const toastClass = computed(() => ({ [name]: true, - [`${name + props.type}`]: true, - [`${name + props.position}`]: true + [bem('', props.type)]: true, + [bem('', props.position)]: true })); const isLoadding = computed(() => { return props.type === 'loading'; }); - - const { show, overlay } = props; - + const iconClassPrefix = `${bem('icon')} fm-icon`; return () => ( <> -
- {isLoadding.value ? ( - - - - - - ) : iconName.value ? ( - - ) : null} - {props.message} -
- + {props.show && ( +
+ {isLoadding.value ? ( + + + + + + ) : iconName.value ? ( + + ) : null} + + {props.message} +
+ )} + {props.overlay && ( + + )} ); } diff --git a/packages/mobile-ui-vue/components/toast/src/toast.scss b/packages/mobile-ui-vue/components/toast/src/toast.scss index e165328a5b..10fe643adc 100644 --- a/packages/mobile-ui-vue/components/toast/src/toast.scss +++ b/packages/mobile-ui-vue/components/toast/src/toast.scss @@ -4,7 +4,7 @@ --fm-toast-zindex: var(--fm-zindex-5); --fm-toast-color: var(--fm-white); --fm-toast-font-size: 16px; - --fm-toast-background: var(--fm-gray-8); + --fm-toast-background: var(--fm-gray-7); --fm-toast-icon-font-size: 48px; } @@ -31,37 +31,34 @@ z-index: var(--fm-toast-zindex); font-size: var(--fm-toast-font-size); background-color: var(--fm-toast-background); - &-text { - background-color: red; - } - &-top { + &--top { top: 50px; transform: translate(-50%, 0); } - &-bottom { + &--bottom { top: auto; bottom: 50px; } - &-info, - &-success, - &-warning, - &-error { + &--info, + &--success, + &--warning, + &--error { width: 88px; min-height: 88px; } - &-icon { + &__icon { margin-bottom: 8px; font-size: var(--fm-toast-icon-font-size); } - &-default { + &--default { padding: 8px 16px; } - &-loading { + &--loading { min-width: 84px; min-height: 84px; } - &-loading-icon { + &--loading-icon { position: relative; display: inline-block; width: 30px; diff --git a/packages/mobile-ui-vue/demos/button/index.html b/packages/mobile-ui-vue/demos/button/index.html index 7193af54cd..ad1dc7fcf5 100644 --- a/packages/mobile-ui-vue/demos/button/index.html +++ b/packages/mobile-ui-vue/demos/button/index.html @@ -47,12 +47,12 @@

添加按钮

- +

图标按钮

- - 按钮 + + 按钮

自定义颜色

diff --git a/packages/mobile-ui-vue/demos/toast/index.html b/packages/mobile-ui-vue/demos/toast/index.html index 32139fea7c..438ef96a41 100644 --- a/packages/mobile-ui-vue/demos/toast/index.html +++ b/packages/mobile-ui-vue/demos/toast/index.html @@ -1,9 +1,9 @@

基础用法

- - -
-

overlay

-
- \ No newline at end of file + + + + + + \ No newline at end of file diff --git a/packages/mobile-ui-vue/demos/toast/index.js b/packages/mobile-ui-vue/demos/toast/index.js index 5c113f30f0..84b296bceb 100644 --- a/packages/mobile-ui-vue/demos/toast/index.js +++ b/packages/mobile-ui-vue/demos/toast/index.js @@ -1,13 +1,37 @@ -import { ref } from 'vue'; +import { Toast } from '../../components/toast/index'; export default { name: 'toast-demo', + inheritAttrs: false, + components: [Toast], setup() { - const checkValue = ref(true); - const unCheckValue = ref(false); - + const showInfo = () => { + Toast.info('info'); + }; + const showSuccess = () => { + Toast.success('成功'); + }; + const showWarning = () => { + Toast.warning('警告'); + }; + const showError = () => { + Toast.error('错误'); + }; + const showCustom = () => { + Toast('自定义'); + }; + const showLoading = () => { + Toast.loading({ message: '加载中...', overlay: true }); + setTimeout(() => { + Toast.clear(); + }, 2000); + }; return { - checkValue, - unCheckValue + showInfo, + showSuccess, + showWarning, + showError, + showCustom, + showLoading }; } }; diff --git a/packages/mobile-ui-vue/docs/components/button/index.md b/packages/mobile-ui-vue/docs/components/button/index.md index dfb353bae0..b20105c69e 100644 --- a/packages/mobile-ui-vue/docs/components/button/index.md +++ b/packages/mobile-ui-vue/docs/components/button/index.md @@ -83,14 +83,13 @@ demo: button ### 添加按钮 ```html - + ``` ### 图标按钮 ```html - -按钮 + 按钮 ``` ### 自定义颜色 @@ -100,9 +99,7 @@ demo: button ```html 单色按钮 单色按钮 -渐变色按钮 +渐变色按钮 ``` ## API -- Gitee From 493417800b66aa2473a64ab62ac95ea10195dfd7 Mon Sep 17 00:00:00 2001 From: lv jiabiao <1160388820@qq.com> Date: Thu, 23 May 2024 10:02:40 +0800 Subject: [PATCH 7/7] fix:toast component --- .../components/toast/src/index.tsx | 15 +++++++ .../components/toast/src/toast.component.tsx | 40 ++++++++++++------- .../components/toast/src/toast.scss | 4 +- packages/mobile-ui-vue/demos/toast/index.html | 1 + packages/mobile-ui-vue/demos/toast/index.js | 7 ++++ 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/packages/mobile-ui-vue/components/toast/src/index.tsx b/packages/mobile-ui-vue/components/toast/src/index.tsx index 608403ae5a..0032da0770 100644 --- a/packages/mobile-ui-vue/components/toast/src/index.tsx +++ b/packages/mobile-ui-vue/components/toast/src/index.tsx @@ -1,3 +1,18 @@ +/** + * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import FMToast from './toast.component'; import { isObject, inBrowser } from '@/components/utils'; import { mountComponent, usePopupState } from '@/components/hook'; diff --git a/packages/mobile-ui-vue/components/toast/src/toast.component.tsx b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx index 088ed75ac7..b447ba9d18 100644 --- a/packages/mobile-ui-vue/components/toast/src/toast.component.tsx +++ b/packages/mobile-ui-vue/components/toast/src/toast.component.tsx @@ -61,24 +61,34 @@ export default defineComponent({ const isLoadding = computed(() => { return props.type === 'loading'; }); - const iconClassPrefix = `${bem('icon')} fm-icon`; + + const renderLoading = () => { + return ( + + + + + + ); + }; + + const renderIconContent = () => { + const iconSize = '48'; + return ( +
+ +
+ ); + }; + return () => ( <> - {props.show && ( + {true && (
- {isLoadding.value ? ( - - - - - - ) : iconName.value ? ( - - ) : null} - + {isLoadding.value ? renderLoading() : iconName.value ? renderIconContent() : null} {props.message}
)} diff --git a/packages/mobile-ui-vue/components/toast/src/toast.scss b/packages/mobile-ui-vue/components/toast/src/toast.scss index 10fe643adc..0334b56ef4 100644 --- a/packages/mobile-ui-vue/components/toast/src/toast.scss +++ b/packages/mobile-ui-vue/components/toast/src/toast.scss @@ -46,10 +46,8 @@ width: 88px; min-height: 88px; } - - &__icon { + &__icon-wrapper { margin-bottom: 8px; - font-size: var(--fm-toast-icon-font-size); } &--default { padding: 8px 16px; diff --git a/packages/mobile-ui-vue/demos/toast/index.html b/packages/mobile-ui-vue/demos/toast/index.html index 438ef96a41..ce87a4ae01 100644 --- a/packages/mobile-ui-vue/demos/toast/index.html +++ b/packages/mobile-ui-vue/demos/toast/index.html @@ -6,4 +6,5 @@ + \ No newline at end of file diff --git a/packages/mobile-ui-vue/demos/toast/index.js b/packages/mobile-ui-vue/demos/toast/index.js index 84b296bceb..ee3d2e6cf2 100644 --- a/packages/mobile-ui-vue/demos/toast/index.js +++ b/packages/mobile-ui-vue/demos/toast/index.js @@ -19,6 +19,12 @@ export default { const showCustom = () => { Toast('自定义'); }; + const showCustomIcon = () => { + Toast({ + message: '自定义图标', + icon: 'back' + }); + }; const showLoading = () => { Toast.loading({ message: '加载中...', overlay: true }); setTimeout(() => { @@ -31,6 +37,7 @@ export default { showWarning, showError, showCustom, + showCustomIcon, showLoading }; } -- Gitee