From cbf117d76924644845509da09e2aed39d380710b Mon Sep 17 00:00:00 2001 From: EmberSpirit <85718018+wangKBweb@users.noreply.github.com> Date: Wed, 14 Sep 2022 22:32:18 +0800 Subject: [PATCH] feat(ui/menu): replace menuV2 with menu (#690) --- packages/varlet-cli/lib/index.js | 94 ++--- .../__snapshots__/index.spec.js.snap | 8 +- .../__snapshots__/index.spec.js.snap | 55 --- .../src/menu-v2/__tests__/index.spec.js | 172 -------- packages/varlet-ui/src/menu-v2/docs/en-US.md | 0 packages/varlet-ui/src/menu-v2/docs/zh-CN.md | 0 .../varlet-ui/src/menu-v2/example/index.vue | 21 - packages/varlet-ui/src/menu-v2/index.ts | 10 - packages/varlet-ui/src/menu-v2/menuV2.less | 25 -- packages/varlet-ui/src/menu-v2/props.ts | 97 ----- packages/varlet-ui/src/menu/Menu.tsx | 143 ------- .../src/{menu-v2/MenuV2.vue => menu/Menu.vue} | 6 +- .../__snapshots__/index.spec.js.snap | 85 ++-- .../src/menu/__tests__/index.spec.js | 200 ++++++--- packages/varlet-ui/src/menu/docs/en-US.md | 223 ---------- packages/varlet-ui/src/menu/docs/zh-CN.md | 217 ---------- packages/varlet-ui/src/menu/example/index.vue | 150 +------ .../src/menu/example/locale/en-US.ts | 12 - .../src/menu/example/locale/index.ts | 23 -- .../src/menu/example/locale/zh-CN.ts | 12 - packages/varlet-ui/src/menu/index.ts | 2 +- packages/varlet-ui/src/menu/menu.less | 14 +- packages/varlet-ui/src/menu/props.ts | 69 +++- .../__snapshots__/index.spec.js.snap | 270 +----------- packages/varlet-ui/src/select/Select.vue | 4 +- .../__snapshots__/index.spec.js.snap | 30 +- .../src/select/__tests__/index.spec.js | 2 +- packages/varlet-ui/src/themes/dark/index.ts | 4 +- packages/varlet-ui/src/themes/dark/menu.ts | 3 + packages/varlet-ui/src/themes/dark/menuV2.ts | 3 - packages/varlet-ui/types/index.d.ts | 2 - packages/varlet-ui/types/menu.d.ts | 27 +- packages/varlet-ui/types/menuV2.d.ts | 46 --- packages/varlet-ui/varlet.config.js | 8 - pnpm-lock.yaml | 383 ++++++++++-------- 35 files changed, 616 insertions(+), 1804 deletions(-) delete mode 100644 packages/varlet-ui/src/menu-v2/__tests__/__snapshots__/index.spec.js.snap delete mode 100644 packages/varlet-ui/src/menu-v2/__tests__/index.spec.js delete mode 100644 packages/varlet-ui/src/menu-v2/docs/en-US.md delete mode 100644 packages/varlet-ui/src/menu-v2/docs/zh-CN.md delete mode 100644 packages/varlet-ui/src/menu-v2/example/index.vue delete mode 100644 packages/varlet-ui/src/menu-v2/index.ts delete mode 100644 packages/varlet-ui/src/menu-v2/menuV2.less delete mode 100644 packages/varlet-ui/src/menu-v2/props.ts delete mode 100644 packages/varlet-ui/src/menu/Menu.tsx rename packages/varlet-ui/src/{menu-v2/MenuV2.vue => menu/Menu.vue} (98%) delete mode 100644 packages/varlet-ui/src/menu/example/locale/en-US.ts delete mode 100644 packages/varlet-ui/src/menu/example/locale/index.ts delete mode 100644 packages/varlet-ui/src/menu/example/locale/zh-CN.ts create mode 100644 packages/varlet-ui/src/themes/dark/menu.ts delete mode 100644 packages/varlet-ui/src/themes/dark/menuV2.ts delete mode 100644 packages/varlet-ui/types/menuV2.d.ts diff --git a/packages/varlet-cli/lib/index.js b/packages/varlet-cli/lib/index.js index e8c140ccc85..15b7796413d 100755 --- a/packages/varlet-cli/lib/index.js +++ b/packages/varlet-cli/lib/index.js @@ -1,7 +1,7 @@ #!/usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; + return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const logger_1 = __importDefault(require("./shared/logger")); @@ -21,64 +21,64 @@ const commitLint_1 = require("./commands/commitLint"); const program = new commander_1.Command(); program.version(`varlet-cli ${require('../package.json').version}`).usage(' [options]'); program - .command('dev') - .option('-f --force', 'Force dep pre-optimization regardless of whether deps have changed') - .description('Run varlet development environment') - .action(dev_1.dev); + .command('dev') + .option('-f --force', 'Force dep pre-optimization regardless of whether deps have changed') + .description('Run varlet development environment') + .action(dev_1.dev); program.command('build').description('Build varlet site for production').action(build_1.build); program - .command('build:vite') - .description('Use vite build app for production') - .action(() => (0, vite_1.vite)('build')); + .command('build:vite') + .description('Use vite build app for production') + .action(() => (0, vite_1.vite)('build')); program - .command('dev:vite') - .description('Use vite start server for development') - .action(() => (0, vite_1.vite)('dev')); + .command('dev:vite') + .description('Use vite start server for development') + .action(() => (0, vite_1.vite)('dev')); program.command('preview').description('Preview varlet site for production').action(preview_1.preview); program - .command('compile') - .description('Compile varlet components library code') - .option('-nu, --noUmd', 'Do not compile umd target code') - .action(compile_1.compile); + .command('compile') + .description('Compile varlet components library code') + .option('-nu, --noUmd', 'Do not compile umd target code') + .action(compile_1.compile); program.command('lint').description('Lint code').action(lint_1.lint); program - .command('create') - .description('Create a component directory') - .option('-n, --name ', 'Component name') - .option('-s, --sfc', 'Generate files in sfc format') - .option('-t, --tsx', 'Generate files in tsx format') - .option('-l, --locale', 'Generator internationalized files') - .action(create_1.create); + .command('create') + .description('Create a component directory') + .option('-n, --name ', 'Component name') + .option('-s, --sfc', 'Generate files in sfc format') + .option('-t, --tsx', 'Generate files in tsx format') + .option('-l, --locale', 'Generator internationalized files') + .action(create_1.create); program - .command('test') - .description('Run test in work directory') - .option('-w, --watch', 'Watch files for changes and rerun tests related to changed files') - .option('-c, --component ', 'Test a specific component') - .option('-cov, --coverage', 'Generate the coverage') - .action(test_1.test); + .command('test') + .description('Run test in work directory') + .option('-w, --watch', 'Watch files for changes and rerun tests related to changed files') + .option('-c, --component ', 'Test a specific component') + .option('-cov, --coverage', 'Generate the coverage') + .action(test_1.test); program - .command('gen') - .description('Generate cli application') - .option('-n, --name ', 'Application name') - .option('-s, --sfc', 'Generate files in sfc format') - .option('-t, --tsx', 'Generate files in tsx format') - .option('-l, --locale', 'Generator internationalized files') - .action(gen_1.gen); + .command('gen') + .description('Generate cli application') + .option('-n, --name ', 'Application name') + .option('-s, --sfc', 'Generate files in sfc format') + .option('-t, --tsx', 'Generate files in tsx format') + .option('-l, --locale', 'Generator internationalized files') + .action(gen_1.gen); program - .command('changelog') - .option('-rc --releaseCount ', 'Release count') - .option('-f --file ', 'Changelog filename') - .description('Generate changelog') - .action(changelog_1.changelog); + .command('changelog') + .option('-rc --releaseCount ', 'Release count') + .option('-f --file ', 'Changelog filename') + .description('Generate changelog') + .action(changelog_1.changelog); program - .command('release') - .option('-r --remote ', 'Remote name') - .description('Release all packages and generate changelogs') - .action(release_1.release); + .command('release') + .option('-r --remote ', 'Remote name') + .description('Release all packages and generate changelogs') + .action(release_1.release); program.command('commit-lint ').description('Lint commit message').action(commitLint_1.commitLint); program.on('command:*', ([cmd]) => { - program.outputHelp(); - logger_1.default.error(`\nUnknown command ${cmd}.\n`); - process.exitCode = 1; + program.outputHelp(); + logger_1.default.error(`\nUnknown command ${cmd}.\n`); + process.exitCode = 1; }); program.parse(); diff --git a/packages/varlet-ui/src/form/__tests__/__snapshots__/index.spec.js.snap b/packages/varlet-ui/src/form/__tests__/__snapshots__/index.spec.js.snap index b71b39f1093..6f9bff8bd74 100644 --- a/packages/varlet-ui/src/form/__tests__/__snapshots__/index.spec.js.snap +++ b/packages/varlet-ui/src/form/__tests__/__snapshots__/index.spec.js.snap @@ -316,7 +316,7 @@ exports[`test form with select 1`] = `
-
+
@@ -346,7 +346,7 @@ exports[`test form with select 2`] = `
-
+
@@ -376,7 +376,7 @@ exports[`test form with select 3`] = `
-
+
@@ -409,7 +409,7 @@ exports[`test form with select 4`] = `
-
+
diff --git a/packages/varlet-ui/src/menu-v2/__tests__/__snapshots__/index.spec.js.snap b/packages/varlet-ui/src/menu-v2/__tests__/__snapshots__/index.spec.js.snap deleted file mode 100644 index aa57fe3e742..00000000000 --- a/packages/varlet-ui/src/menu-v2/__tests__/__snapshots__/index.spec.js.snap +++ /dev/null @@ -1,55 +0,0 @@ -// Vitest Snapshot v1 - -exports[`test menu v2 click trigger 1`] = `"
"`; - -exports[`test menu v2 click trigger 2`] = `"
"`; - -exports[`test menu v2 default style 1`] = `"
"`; - -exports[`test menu v2 hover the menu list 1`] = `"
"`; - -exports[`test menu v2 hover trigger and events 1`] = `"
"`; - -exports[`test menu v2 hover trigger and events 2`] = `"
"`; - -exports[`test menu v2 offset 1`] = `"
"`; - -exports[`test menu v2 placement 1`] = `"
"`; - -exports[`test menu v2 placement 2`] = `"
"`; - -exports[`test menu v2 placement 3`] = `"
"`; - -exports[`test menu v2 placement 4`] = `"
"`; - -exports[`test menu v2 placement 5`] = `"
"`; - -exports[`test menu v2 placement 6`] = `"
"`; - -exports[`test menu v2 placement 7`] = `"
"`; - -exports[`test menu v2 placement 8`] = `"
"`; - -exports[`test menu v2 placement 9`] = `"
"`; - -exports[`test menu v2 placement 10`] = `"
"`; - -exports[`test menu v2 placement 11`] = `"
"`; - -exports[`test menu v2 placement 12`] = `"
"`; - -exports[`test menu v2 placement 13`] = `"
"`; - -exports[`test menu v2 placement 14`] = `"
"`; - -exports[`test menu v2 placement 15`] = `"
"`; - -exports[`test menu v2 placement 16`] = `"
"`; - -exports[`test menu v2 placement 17`] = `"
"`; - -exports[`test menu v2 placement 18`] = `"
"`; - -exports[`test menu v2 placement 19`] = `"
"`; - -exports[`test menu v2 placement 20`] = `"
"`; diff --git a/packages/varlet-ui/src/menu-v2/__tests__/index.spec.js b/packages/varlet-ui/src/menu-v2/__tests__/index.spec.js deleted file mode 100644 index 0dd42a46bd6..00000000000 --- a/packages/varlet-ui/src/menu-v2/__tests__/index.spec.js +++ /dev/null @@ -1,172 +0,0 @@ -import MenuV2 from '..' -import { createApp, h } from 'vue' -import { mount } from '@vue/test-utils' -import { delay, mockStubs, trigger } from '../../utils/test' -import { doubleRaf } from '../../utils/elements' - -test('test menu v2 plugin', () => { - const app = createApp({}).use(MenuV2) - expect(app.component(MenuV2.name)).toBeTruthy() -}) - -test('test menu v2 placement', async () => { - const { mockRestore } = mockStubs() - - for (const placement of [ - 'top', - 'top-start', - 'top-end', - 'bottom', - 'bottom-start', - 'bottom-end', - 'right', - 'right-start', - 'right-end', - 'left', - 'left-start', - 'left-end', - 'cover-top', - 'cover-top-start', - 'cover-top-end', - 'cover-bottom', - 'cover-bottom-start', - 'cover-bottom-end', - 'cover-left', - 'cover-right', - ]) { - const root = document.createElement('div') - - mount(MenuV2, { - props: { - placement, - teleport: root, - }, - }) - - await doubleRaf() - - expect(root.innerHTML).toMatchSnapshot() - } - - mockRestore() -}) - -test('test menu v2 click trigger', async () => { - const { mockRestore } = mockStubs() - - const wrapper = mount(MenuV2, { - attachTo: document.body, - }) - - await wrapper.trigger('click') - await delay(300) - expect(document.body.innerHTML).toMatchSnapshot() - - await trigger(document, 'click') - await delay(300) - expect(document.body.innerHTML).toMatchSnapshot() - - document.body.innerHTML = '' - - mockRestore() -}) - -test('test menu v2 hover trigger and events', async () => { - const { mockRestore } = mockStubs() - - const onOpen = vi.fn() - const onOpened = vi.fn() - const onClose = vi.fn() - const onClosed = vi.fn() - - const root = document.createElement('div') - - const wrapper = mount(MenuV2, { - props: { - trigger: 'hover', - teleport: root, - onOpen, - onOpened, - onClose, - onClosed, - }, - }) - - await wrapper.trigger('mouseenter') - expect(onOpen).toHaveBeenCalledTimes(1) - - await delay(300) - - expect(onOpened).toHaveBeenCalledTimes(1) - expect(root.innerHTML).toMatchSnapshot() - - await wrapper.trigger('mouseleave') - - await doubleRaf() - await delay(0) - expect(onClose).toHaveBeenCalledTimes(1) - await delay(300) - - expect(onClosed).toHaveBeenCalledTimes(1) - expect(root.innerHTML).toMatchSnapshot() - - wrapper.unmount() - mockRestore() -}) - -test('test menu v2 default style', async () => { - const root = document.createElement('div') - - mount(MenuV2, { - props: { - defaultStyle: false, - teleport: root, - }, - }) - - await doubleRaf() - - expect(root.innerHTML).toMatchSnapshot() -}) - -test('test menu v2 offset', async () => { - const { mockRestore } = mockStubs() - - const root = document.createElement('div') - - mount(MenuV2, { - props: { - offsetX: 100, - offsetY: 100, - teleport: root, - }, - }) - - await doubleRaf() - - expect(root.innerHTML).toMatchSnapshot() - - mockRestore() -}) - -test('test menu v2 hover the menu list', async () => { - const { mockRestore } = mockStubs() - - const root = document.createElement('div') - - mount(MenuV2, { - props: { - show: true, - trigger: 'hover', - teleport: root, - }, - }) - - await doubleRaf() - await trigger(root.querySelector('.var-menu-v2__menu'), 'mouseenter') - await trigger(root.querySelector('.var-menu-v2__menu'), 'mouseleave') - await delay(300) - expect(root.innerHTML).toMatchSnapshot() - - mockRestore() -}) diff --git a/packages/varlet-ui/src/menu-v2/docs/en-US.md b/packages/varlet-ui/src/menu-v2/docs/en-US.md deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/varlet-ui/src/menu-v2/docs/zh-CN.md b/packages/varlet-ui/src/menu-v2/docs/zh-CN.md deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/varlet-ui/src/menu-v2/example/index.vue b/packages/varlet-ui/src/menu-v2/example/index.vue deleted file mode 100644 index f286569806b..00000000000 --- a/packages/varlet-ui/src/menu-v2/example/index.vue +++ /dev/null @@ -1,21 +0,0 @@ - - - diff --git a/packages/varlet-ui/src/menu-v2/index.ts b/packages/varlet-ui/src/menu-v2/index.ts deleted file mode 100644 index 2bfcc7d3584..00000000000 --- a/packages/varlet-ui/src/menu-v2/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { App } from 'vue' -import MenuV2 from './MenuV2.vue' - -MenuV2.install = function (app: App) { - app.component(MenuV2.name, MenuV2) -} - -export const _MenuV2Component = MenuV2 - -export default MenuV2 diff --git a/packages/varlet-ui/src/menu-v2/menuV2.less b/packages/varlet-ui/src/menu-v2/menuV2.less deleted file mode 100644 index 9fb40df3094..00000000000 --- a/packages/varlet-ui/src/menu-v2/menuV2.less +++ /dev/null @@ -1,25 +0,0 @@ -:root { - --menu-v2-background-color: #fff; -} - -.var { - &-menu-v2-enter-from, - &-menu-v2-leave-to { - opacity: 0; - } - - &-menu-v2-enter-active, - &-menu-v2-leave-active { - transition-property: opacity; - transition-duration: 0.25s; - } -} - -.var-menu-v2 { - display: inline-block; - - &--menu-background-color { - background: var(--menu-v2-background-color); - transition: opacity 0.25s, background-color 0.25s; - } -} diff --git a/packages/varlet-ui/src/menu-v2/props.ts b/packages/varlet-ui/src/menu-v2/props.ts deleted file mode 100644 index e00a1f0c785..00000000000 --- a/packages/varlet-ui/src/menu-v2/props.ts +++ /dev/null @@ -1,97 +0,0 @@ -import type { PropType } from 'vue' -import type { Placement as PopperPlacement } from '@popperjs/core' -import { TeleportProps } from 'vue' - -export type NeededPopperPlacement = Exclude - -export type Placement = - | NeededPopperPlacement - | 'cover-top' - | 'cover-top-start' - | 'cover-top-end' - | 'cover-bottom' - | 'cover-bottom-start' - | 'cover-bottom-end' - | 'cover-left' - | 'cover-right' - -function triggerValidator(trigger: string) { - return ['click', 'hover'].includes(trigger) -} - -function placementValidator(alignment: string) { - return [ - 'top', - 'top-start', - 'top-end', - 'bottom', - 'bottom-start', - 'bottom-end', - 'right', - 'right-start', - 'right-end', - 'left', - 'left-start', - 'left-end', - 'cover-top', - 'cover-top-start', - 'cover-top-end', - 'cover-bottom', - 'cover-bottom-start', - 'cover-bottom-end', - 'cover-left', - 'cover-right', - ].includes(alignment) -} - -export const props = { - show: { - type: Boolean, - default: false, - }, - disabled: { - type: Boolean, - default: false, - }, - trigger: { - type: String as PropType<'click' | 'hover'>, - default: 'click', - validator: triggerValidator, - }, - placement: { - type: String as PropType, - default: 'cover-top-start', - validator: placementValidator, - }, - offsetX: { - type: [Number, String], - default: 0, - }, - offsetY: { - type: [Number, String], - default: 0, - }, - teleport: { - type: [String, Object] as PropType, - default: 'body', - }, - defaultStyle: { - type: Boolean, - default: true, - }, - onOpen: { - type: Function as PropType<() => void>, - }, - onOpened: { - type: Function as PropType<() => void>, - }, - onClose: { - type: Function as PropType<() => void>, - }, - onClosed: { - type: Function as PropType<() => void>, - }, - 'onUpdate:show': { - type: Function as PropType<(show: boolean) => void>, - }, -} diff --git a/packages/varlet-ui/src/menu/Menu.tsx b/packages/varlet-ui/src/menu/Menu.tsx deleted file mode 100644 index 1ff191e8f0b..00000000000 --- a/packages/varlet-ui/src/menu/Menu.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import { - defineComponent, - ref, - computed, - watch, - onMounted, - onUnmounted, - Transition, - Teleport, - nextTick, - TeleportProps, -} from 'vue' -import { props } from './props' -import { getLeft, getTop, toSizeUnit } from '../utils/elements' -import { useZIndex } from '../context/zIndex' -import type { Ref } from 'vue' -import { call, createNamespace, exposeApis, useTeleport } from '../utils/components' - -import '../styles/common.less' -import '../styles/elevation.less' -import './menu.less' - -const { n, classes } = createNamespace('menu') - -export default defineComponent({ - name: 'VarMenu', - props, - setup(props, { slots }) { - const host: Ref = ref(null) - const menu: Ref = ref(null) - const to: Ref = ref() - const top: Ref = ref(0) - const left: Ref = ref(0) - const { zIndex } = useZIndex(() => props.show, 1) - const { disabled } = useTeleport() - let clickSelf = false - - const computeTop = (alignment: string): number => { - return alignment === 'top' - ? getTop(host.value as HTMLElement) - : getTop(host.value as HTMLElement) - (menu.value as HTMLElement).offsetHeight - } - - const handleClick = () => { - clickSelf = true - } - - const handleMenuClose = () => { - if (clickSelf) { - clickSelf = false - return - } - - if (!props.show) { - return - } - - call(props['onUpdate:show'], false) - } - - // expose - const resize = () => { - top.value = computeTop(props.alignment) - left.value = getLeft(host.value as HTMLElement) - } - - // Transition style use computed place here - const transitionStyle = computed(() => { - return { - top: `calc(${top.value}px + ${toSizeUnit(props.offsetY)})`, - left: `calc(${left.value}px + ${toSizeUnit(props.offsetX)})`, - zIndex: zIndex.value, - } - }) - - const renderTransition = () => ( - -
{ - event.stopPropagation() - }} - > - {call(slots.menu)} -
-
- ) - - watch(() => props.alignment, resize) - - watch( - () => props.show, - async (newValue: boolean) => { - const { onOpen, onClose } = props - if (newValue) { - await nextTick() - resize() - } - newValue ? call(onOpen) : call(onClose) - } - ) - - watch( - () => props.teleport, - (newValue) => { - to.value = newValue - } - ) - - onMounted(() => { - // Synchronously transfer the state to the mount hook to support server-side rendering to prevent hydration errors - to.value = props.teleport - resize() - - document.addEventListener('click', handleMenuClose) - window.addEventListener('resize', resize) - }) - - onUnmounted(() => { - document.removeEventListener('click', handleMenuClose) - window.removeEventListener('resize', resize) - }) - - exposeApis({ resize }) - - return () => ( -
- {call(slots.default)} - - {to.value ? ( - - {renderTransition()} - - ) : ( - renderTransition() - )} -
- ) - }, -}) diff --git a/packages/varlet-ui/src/menu-v2/MenuV2.vue b/packages/varlet-ui/src/menu/Menu.vue similarity index 98% rename from packages/varlet-ui/src/menu-v2/MenuV2.vue rename to packages/varlet-ui/src/menu/Menu.vue index 2d69c0f356c..18ae59e8434 100644 --- a/packages/varlet-ui/src/menu-v2/MenuV2.vue +++ b/packages/varlet-ui/src/menu/Menu.vue @@ -33,7 +33,7 @@ import type { Ref } from 'vue' import type { Instance } from '@popperjs/core/lib/types' import type { NeededPopperPlacement } from './props' -const { n, classes } = createNamespace('menu-v2') +const { n, classes } = createNamespace('menu') export interface HostSize { width: number @@ -47,7 +47,7 @@ export interface Position { } export default defineComponent({ - name: 'VarMenuV2', + name: 'VarMenu', props, setup(props) { const host: Ref = ref(null) @@ -353,7 +353,7 @@ export default defineComponent({ diff --git a/packages/varlet-ui/src/menu/__tests__/__snapshots__/index.spec.js.snap b/packages/varlet-ui/src/menu/__tests__/__snapshots__/index.spec.js.snap index 9c85abc5223..3373a6fa21f 100644 --- a/packages/varlet-ui/src/menu/__tests__/__snapshots__/index.spec.js.snap +++ b/packages/varlet-ui/src/menu/__tests__/__snapshots__/index.spec.js.snap @@ -1,34 +1,55 @@ // Vitest Snapshot v1 -exports[`test menu click forbid trigger 1`] = ` -"
-
- -
-
-
-
-
" -`; - -exports[`test menu trigger 1`] = ` -"
-
- -
-
-
-
-
" -`; - -exports[`test menu trigger 2`] = ` -"
-
- -
-
-
-
-
" -`; +exports[`test menu click trigger 1`] = `"
"`; + +exports[`test menu click trigger 2`] = `"
"`; + +exports[`test menu default style 1`] = `"
"`; + +exports[`test menu hover the menu list 1`] = `"
"`; + +exports[`test menu hover trigger and events 1`] = `"
"`; + +exports[`test menu hover trigger and events 2`] = `"
"`; + +exports[`test menu offset 1`] = `"
"`; + +exports[`test menu placement 1`] = `"
"`; + +exports[`test menu placement 2`] = `"
"`; + +exports[`test menu placement 3`] = `"
"`; + +exports[`test menu placement 4`] = `"
"`; + +exports[`test menu placement 5`] = `"
"`; + +exports[`test menu placement 6`] = `"
"`; + +exports[`test menu placement 7`] = `"
"`; + +exports[`test menu placement 8`] = `"
"`; + +exports[`test menu placement 9`] = `"
"`; + +exports[`test menu placement 10`] = `"
"`; + +exports[`test menu placement 11`] = `"
"`; + +exports[`test menu placement 12`] = `"
"`; + +exports[`test menu placement 13`] = `"
"`; + +exports[`test menu placement 14`] = `"
"`; + +exports[`test menu placement 15`] = `"
"`; + +exports[`test menu placement 16`] = `"
"`; + +exports[`test menu placement 17`] = `"
"`; + +exports[`test menu placement 18`] = `"
"`; + +exports[`test menu placement 19`] = `"
"`; + +exports[`test menu placement 20`] = `"
"`; diff --git a/packages/varlet-ui/src/menu/__tests__/index.spec.js b/packages/varlet-ui/src/menu/__tests__/index.spec.js index 647b63f80b2..de73fa91c33 100644 --- a/packages/varlet-ui/src/menu/__tests__/index.spec.js +++ b/packages/varlet-ui/src/menu/__tests__/index.spec.js @@ -1,82 +1,172 @@ -import Menu from '..' -import VarMenu from '../Menu' +import VarMenu from '..' +import { createApp, h } from 'vue' import { mount } from '@vue/test-utils' -import { createApp } from 'vue' -import { delay, mockStubs } from '../../utils/test' +import { delay, mockStubs, trigger } from '../../utils/test' +import { doubleRaf } from '../../utils/elements' test('test menu plugin', () => { - const app = createApp({}).use(Menu) - expect(app.component(Menu.name)).toBeTruthy() + const app = createApp({}).use(VarMenu) + expect(app.component(VarMenu.name)).toBeTruthy() }) -const Wrapper = { - components: { - [VarMenu.name]: VarMenu, - }, - data: () => ({ - show: false, - }), - template: ` -
- - - -
- `, -} - -test('test menu trigger', async () => { +test('test menu placement', async () => { const { mockRestore } = mockStubs() - const wrapper = mount(Wrapper, { attachTo: document.body }) - await wrapper.setData({ show: true }) - expect(wrapper.find('.menu-content').isVisible()).toBeTruthy() - expect(wrapper.html()).toMatchSnapshot() + for (const placement of [ + 'top', + 'top-start', + 'top-end', + 'bottom', + 'bottom-start', + 'bottom-end', + 'right', + 'right-start', + 'right-end', + 'left', + 'left-start', + 'left-end', + 'cover-top', + 'cover-top-start', + 'cover-top-end', + 'cover-bottom', + 'cover-bottom-start', + 'cover-bottom-end', + 'cover-left', + 'cover-right', + ]) { + const root = document.createElement('div') - await wrapper.find('.container').trigger('click') - await delay(300) - expect(wrapper.find('.menu-content').isVisible()).toBeFalsy() - expect(wrapper.html()).toMatchSnapshot() + mount(VarMenu, { + props: { + placement, + teleport: root, + }, + }) + + await doubleRaf() + + expect(root.innerHTML).toMatchSnapshot() + } mockRestore() - wrapper.unmount() }) -test('test menu click forbid trigger', async () => { +test('test menu click trigger', async () => { const { mockRestore } = mockStubs() - const wrapper = mount(Wrapper, { attachTo: document.body }) - await wrapper.setData({ show: true }) - await wrapper.find('.menu-content').trigger('click') - expect(wrapper.find('.menu-content').isVisible()).toBeTruthy() - expect(wrapper.html()).toMatchSnapshot() + const wrapper = mount(VarMenu, { + attachTo: document.body, + }) + + await wrapper.trigger('click') + await delay(300) + expect(document.body.innerHTML).toMatchSnapshot() + + await trigger(document, 'click') + await delay(300) + expect(document.body.innerHTML).toMatchSnapshot() + + document.body.innerHTML = '' mockRestore() - wrapper.unmount() }) -test('test menu z-index', async () => { +test('test menu hover trigger and events', async () => { const { mockRestore } = mockStubs() - const wrapper = mount(Wrapper, { attachTo: document.body }) - await wrapper.setData({ show: true }) - await delay(300) - const prevIndex = +wrapper.find('.var-menu__menu').element.style.zIndex + const onOpen = vi.fn() + const onOpened = vi.fn() + const onClose = vi.fn() + const onClosed = vi.fn() + + const root = document.createElement('div') + + const wrapper = mount(VarMenu, { + props: { + trigger: 'hover', + teleport: root, + onOpen, + onOpened, + onClose, + onClosed, + }, + }) + + await wrapper.trigger('mouseenter') + expect(onOpen).toHaveBeenCalledTimes(1) - await wrapper.setData({ show: false }) await delay(300) - await wrapper.setData({ show: true }) + + expect(onOpened).toHaveBeenCalledTimes(1) + expect(root.innerHTML).toMatchSnapshot() + + await wrapper.trigger('mouseleave') + + await doubleRaf() + await delay(0) + expect(onClose).toHaveBeenCalledTimes(1) await delay(300) - expect(+wrapper.find('.var-menu__menu').element.style.zIndex).toBe(prevIndex + 1) + expect(onClosed).toHaveBeenCalledTimes(1) + expect(root.innerHTML).toMatchSnapshot() - mockRestore() wrapper.unmount() + mockRestore() +}) + +test('test menu default style', async () => { + const root = document.createElement('div') + + mount(VarMenu, { + props: { + defaultStyle: false, + teleport: root, + }, + }) + + await doubleRaf() + + expect(root.innerHTML).toMatchSnapshot() +}) + +test('test menu offset', async () => { + const { mockRestore } = mockStubs() + + const root = document.createElement('div') + + mount(VarMenu, { + props: { + offsetX: 100, + offsetY: 100, + teleport: root, + }, + }) + + await doubleRaf() + + expect(root.innerHTML).toMatchSnapshot() + + mockRestore() +}) + +test('test menu hover the menu list', async () => { + const { mockRestore } = mockStubs() + + const root = document.createElement('div') + + mount(VarMenu, { + props: { + show: true, + trigger: 'hover', + teleport: root, + }, + }) + + await doubleRaf() + await trigger(root.querySelector('.var-menu__menu'), 'mouseenter') + await trigger(root.querySelector('.var-menu__menu'), 'mouseleave') + await delay(300) + expect(root.innerHTML).toMatchSnapshot() + + mockRestore() }) diff --git a/packages/varlet-ui/src/menu/docs/en-US.md b/packages/varlet-ui/src/menu/docs/en-US.md index d53d4646f53..e69de29bb2d 100644 --- a/packages/varlet-ui/src/menu/docs/en-US.md +++ b/packages/varlet-ui/src/menu/docs/en-US.md @@ -1,223 +0,0 @@ -# Menu - -### Intro - -Enable elements to display a menu when clicked, freely control the display position of the menu by controlling the alignment and offset of the menu. - -### Attention - -Menu is an `inline block` element. When you click through the default slot, the menu will be displayed. -If you want menu to monopolize a line, it is recommended to package a `block` element -Menu is automatically closed in the area beyond the scope of the component, -so you can't use the same state to bind `v-model:show`. Otherwise, when the display is triggered, -other menu pairs are also triggered Menu cannot be displayed due to the modification of `v-model:show`. - - -### Alignment Methods -```html - - - - - -``` - -### Offset - -```html - - - - - -``` - -### 注册事件 - -```html - - - - - -``` - -## API - -### Props - -| Prop | Description | Type | Default | -| --- | --- | --- | --- | -| `v-model:show` | Whether to display the menu | _string_ | `default` | -| `alignment` | The alignment of the menu, The optional value is' `top` `bottom`, the origin is the top left corner of the default slot,top is the top of the menu to align the origin,bottom is the bottom of the menu to align the origin | _string_ | `top` | -| `offset-x` | offset x, Relative to the aligned position of the menu | _number \| string_ | `0` | -| `offset-y` | offset y, Relative to the aligned position of the menu | _number \| string_ | `0` | -| `teleport` | The location of the Menu to mount | _TeleportProps['to']_ | `body` | - -### Methods -| Method | Description | Arguments | Return | -| --- | --- | --- | --- | -| `resize` | You can call this method to redraw when a default slot element changes position size | `-` | `-` | - -### Events - -| Event | Description | Arguments | -| --- | --- | --- | -| `open` | Triggered when the menu is open | `-` | -| `opened` | Triggered when open-animation ends | `-` | -| `close` | Triggered when the menu is close | `-` | -| `closed` | Triggered when close-animation ends | `-` | - -### Slots - -| Slot | Description | Arguments | -| --- | --- | --- | -| `default` | The trigger element associated with the menu | `-` | -| `menu` | Menu content | `-` | \ No newline at end of file diff --git a/packages/varlet-ui/src/menu/docs/zh-CN.md b/packages/varlet-ui/src/menu/docs/zh-CN.md index 692da05ae92..e69de29bb2d 100644 --- a/packages/varlet-ui/src/menu/docs/zh-CN.md +++ b/packages/varlet-ui/src/menu/docs/zh-CN.md @@ -1,217 +0,0 @@ -# 菜单 - -### 介绍 -使元素点击时显示一个菜单,通过控制菜单的对齐方式和偏移量自由的控制菜单的显示位置。 - -### 注意 -Menu 是一个 `inline-block` 元素,通过默认插槽点击时显示菜单,如果希望 Menu 独占一行推荐包裹一个 `block` 元素。 -Menu 在点击组件范围以外的区域自动关闭,所以不可以使用同一个状态绑定多个 Menu 的 `v-model:show`,否则在触发显示时也同时触发了其他 Menu 对 `v-model:show` 的修改,导致 Menu 无法显示。 - -### 对齐方式 -```html - - - - - -``` - -### 偏移量 - -```html - - - - - -``` - -### 注册事件 - -```html - - - - - -``` - -## API - -### 属性 - -| 参数 | 说明 | 类型 | 默认值 | -| --- | --- | --- | --- | -| `v-model:show` | 是否显示菜单 | _string_ | `default` | -| `alignment` | 菜单的对齐方式, 可选值为 `top` `bottom`, 源点为默认插槽的左上角,top 为菜单顶部对齐源点,bottom 为菜单底部对齐 | _string_ | `top` | -| `offset-x` | x 轴偏移量, 相对于菜单对齐后的位置 | _number \| string_ | `0` | -| `offset-y` | y 轴偏移量, 相对于菜单对齐后的位置 | _number \| string_ | `0` | -| `teleport` | 菜单挂载的位置 | _TeleportProps['to']_ | `body` | - -### 方法 -| 方法名 | 说明 | 参数 | 返回值 | -| --- | --- | --- | --- | -| `resize` | Menu 默认插槽元素产生位置大小变化时可以调用此方法进行重绘 | `-` | `-` | - -### 事件 - -| 事件名 | 说明 | 参数 | -| --- | --- | --- | -| `open` | 打开菜单时触发 | `-` | -| `opened` | 打开菜单动画结束时触发 | `-` | -| `close` | 关闭菜单时触发 | `-` | -| `closed` | 关闭菜单动画结束时触发 | `-` | - -### 插槽 - -| 插槽名 | 说明 | 参数 | -| --- | --- | --- | -| `default` | 菜单关联的触发元素 | `-` | -| `menu` | 菜单内容 | `-` | diff --git a/packages/varlet-ui/src/menu/example/index.vue b/packages/varlet-ui/src/menu/example/index.vue index e795a6b22b6..22da6aa496b 100644 --- a/packages/varlet-ui/src/menu/example/index.vue +++ b/packages/varlet-ui/src/menu/example/index.vue @@ -2,154 +2,20 @@ import VarMenu from '..' import VarButton from '../../button' import VarCell from '../../cell' -import Snackbar from '../../snackbar' -import AppType from '@varlet/cli/site/mobile/components/AppType' -import { reactive, toRefs, ref } from 'vue' -import { pack, use } from './locale' -import { watchLang, watchDarkMode } from '@varlet/cli/site/utils' -import dark from '../../themes/dark' +import dark from '../../themes/dark/index' +import { watchDarkMode } from '@varlet/cli/site/utils' -const values = reactive({ - top: false, - bottom: false, - offsetX: false, - offsetX1: false, - offsetY: false, - offsetY1: false, - event: false, -}) -const bgColor = ref('#fff') -const { top, bottom, offsetX, offsetX1, offsetY, offsetY1, event } = toRefs(values) - -watchLang(use) -watchDarkMode(dark, (theme) => { - bgColor.value = theme === 'darkTheme' ? '#272727' : '#fff' -}) +watchDarkMode(dark) - - diff --git a/packages/varlet-ui/src/menu/example/locale/en-US.ts b/packages/varlet-ui/src/menu/example/locale/en-US.ts deleted file mode 100644 index bafcaf7b6d2..00000000000 --- a/packages/varlet-ui/src/menu/example/locale/en-US.ts +++ /dev/null @@ -1,12 +0,0 @@ -export default { - alignmentMethods: 'Alignment Methods', - topAlignment: 'Top Alignment', - menuOption: 'Menu Option', - bottomAlignment: 'Bottom Alignment', - offset: 'Offset', - offsetRight: 'Offset Right', - offsetLeft: 'Offset Left', - offsetBottom: 'Offset Bottom', - offsetTop: 'Offset Top', - events: 'Events', -} diff --git a/packages/varlet-ui/src/menu/example/locale/index.ts b/packages/varlet-ui/src/menu/example/locale/index.ts deleted file mode 100644 index d2e375e6090..00000000000 --- a/packages/varlet-ui/src/menu/example/locale/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -// lib -import _zhCN from '../../../locale/zh-CN' -import _enCN from '../../../locale/en-US' -// mobile example doc -import zhCN from './zh-CN' -import enUS from './en-US' -import { useLocale, add as _add, use as _use } from '../../../locale' - -const { add, use: exampleUse, pack, packs, merge } = useLocale() - -const use = (lang: string) => { - _use(lang) - exampleUse(lang) -} - -export { add, pack, packs, merge, use } - -// lib -_add('zh-CN', _zhCN) -_add('en-US', _enCN) -// mobile example doc -add('zh-CN', zhCN as any) -add('en-US', enUS as any) diff --git a/packages/varlet-ui/src/menu/example/locale/zh-CN.ts b/packages/varlet-ui/src/menu/example/locale/zh-CN.ts deleted file mode 100644 index c69413307fd..00000000000 --- a/packages/varlet-ui/src/menu/example/locale/zh-CN.ts +++ /dev/null @@ -1,12 +0,0 @@ -export default { - alignmentMethods: '对齐方式', - topAlignment: '顶部对齐', - menuOption: '菜单项', - bottomAlignment: '底部对齐', - offset: '偏移量', - offsetRight: '右偏移', - offsetLeft: '左偏移', - offsetBottom: '下偏移', - offsetTop: '上偏移', - events: '注册事件', -} diff --git a/packages/varlet-ui/src/menu/index.ts b/packages/varlet-ui/src/menu/index.ts index 17a6bc800e3..4735145de3d 100644 --- a/packages/varlet-ui/src/menu/index.ts +++ b/packages/varlet-ui/src/menu/index.ts @@ -1,5 +1,5 @@ import type { App } from 'vue' -import Menu from './Menu' +import Menu from './Menu.vue' Menu.install = function (app: App) { app.component(Menu.name, Menu) diff --git a/packages/varlet-ui/src/menu/menu.less b/packages/varlet-ui/src/menu/menu.less index a2c6a4dd0f3..73b0a9010c6 100644 --- a/packages/varlet-ui/src/menu/menu.less +++ b/packages/varlet-ui/src/menu/menu.less @@ -1,21 +1,25 @@ +:root { + --menu-background-color: #fff; +} + .var { &-menu-enter-from, &-menu-leave-to { - transform: scale(0.8); opacity: 0; } + &-menu-enter-active, &-menu-leave-active { - transition-property: opacity, transform; + transition-property: opacity; transition-duration: 0.25s; } } .var-menu { display: inline-block; - transition: background-color 0.25s; - &__menu { - position: absolute; + &--menu-background-color { + background: var(--menu-background-color); + transition: opacity 0.25s, background-color 0.25s; } } diff --git a/packages/varlet-ui/src/menu/props.ts b/packages/varlet-ui/src/menu/props.ts index 9f5bdc2dff2..e00a1f0c785 100644 --- a/packages/varlet-ui/src/menu/props.ts +++ b/packages/varlet-ui/src/menu/props.ts @@ -1,7 +1,47 @@ -import type { PropType, TeleportProps } from 'vue' +import type { PropType } from 'vue' +import type { Placement as PopperPlacement } from '@popperjs/core' +import { TeleportProps } from 'vue' -function alignmentValidator(alignment: string) { - return ['top', 'bottom'].includes(alignment) +export type NeededPopperPlacement = Exclude + +export type Placement = + | NeededPopperPlacement + | 'cover-top' + | 'cover-top-start' + | 'cover-top-end' + | 'cover-bottom' + | 'cover-bottom-start' + | 'cover-bottom-end' + | 'cover-left' + | 'cover-right' + +function triggerValidator(trigger: string) { + return ['click', 'hover'].includes(trigger) +} + +function placementValidator(alignment: string) { + return [ + 'top', + 'top-start', + 'top-end', + 'bottom', + 'bottom-start', + 'bottom-end', + 'right', + 'right-start', + 'right-end', + 'left', + 'left-start', + 'left-end', + 'cover-top', + 'cover-top-start', + 'cover-top-end', + 'cover-bottom', + 'cover-bottom-start', + 'cover-bottom-end', + 'cover-left', + 'cover-right', + ].includes(alignment) } export const props = { @@ -9,10 +49,19 @@ export const props = { type: Boolean, default: false, }, - alignment: { - type: String as PropType<'top' | 'bottom'>, - default: 'top', - validator: alignmentValidator, + disabled: { + type: Boolean, + default: false, + }, + trigger: { + type: String as PropType<'click' | 'hover'>, + default: 'click', + validator: triggerValidator, + }, + placement: { + type: String as PropType, + default: 'cover-top-start', + validator: placementValidator, }, offsetX: { type: [Number, String], @@ -23,9 +72,13 @@ export const props = { default: 0, }, teleport: { - type: String as PropType, + type: [String, Object] as PropType, default: 'body', }, + defaultStyle: { + type: Boolean, + default: true, + }, onOpen: { type: Function as PropType<() => void>, }, diff --git a/packages/varlet-ui/src/pagination/__tests__/__snapshots__/index.spec.js.snap b/packages/varlet-ui/src/pagination/__tests__/__snapshots__/index.spec.js.snap index 326645042fa..3844db8ccb2 100644 --- a/packages/varlet-ui/src/pagination/__tests__/__snapshots__/index.spec.js.snap +++ b/packages/varlet-ui/src/pagination/__tests__/__snapshots__/index.spec.js.snap @@ -8,7 +8,7 @@ exports[`Size related props 1`] = `
- +
@@ -43,7 +43,7 @@ exports[`Size related props 2`] = `
- +
@@ -71,42 +71,8 @@ exports[`basic mode > disabled prop 1`] = `
  • 10条 / 页
    - -
    -
    - -
    -
    10条 / 页
    - -
    - -
    -
    - -
    -
    20条 / 页
    - -
    - -
    -
    - -
    -
    50条 / 页
    - -
    - -
    -
    - -
    -
    100条 / 页
    - -
    - -
    -
    -
    + +
  • @@ -128,42 +94,8 @@ exports[`basic mode > mount 1`] = `
  • 10条 / 页
    - -
    -
    - -
    -
    10条 / 页
    - -
    - -
    -
    - -
    -
    20条 / 页
    - -
    - -
    -
    - -
    -
    50条 / 页
    - -
    - -
    -
    - -
    -
    100条 / 页
    - -
    - -
    -
    -
    + +
  • 前往
    @@ -214,42 +146,8 @@ exports[`simple mode > disabled prop 1`] = `
  • 10条 / 页
    - -
    -
    - -
    -
    10条 / 页
    - -
    - -
    -
    - -
    -
    20条 / 页
    - -
    - -
    -
    - -
    -
    50条 / 页
    - -
    - -
    -
    - -
    -
    100条 / 页
    - -
    - -
    -
    -
    + +
  • @@ -283,42 +181,8 @@ exports[`simple mode > mount 1`] = `
  • 10条 / 页
    - -
    -
    - -
    -
    10条 / 页
    - -
    - -
    -
    - -
    -
    20条 / 页
    - -
    - -
    -
    - -
    -
    50条 / 页
    - -
    - -
    -
    - -
    -
    100条 / 页
    - -
    - -
    -
    -
    + +
  • @@ -354,42 +218,8 @@ exports[`test pagination example 1`] = `
  • 10条 / 页
    - -
    -
    - -
    -
    10条 / 页
    - -
    - -
    -
    - -
    -
    20条 / 页
    - -
    - -
    -
    - -
    -
    50条 / 页
    - -
    - -
    -
    - -
    -
    100条 / 页
    - -
    - -
    -
    -
    + +
  • @@ -452,42 +282,8 @@ exports[`test pagination example 1`] = `
  • 10条 / 页
    - -
    -
    - -
    -
    10条 / 页
    - -
    - -
    -
    - -
    -
    20条 / 页
    - -
    - -
    -
    - -
    -
    50条 / 页
    - -
    - -
    -
    - -
    -
    100条 / 页
    - -
    - -
    -
    -
    + +
  • @@ -521,42 +317,8 @@ exports[`test pagination example 1`] = `
  • 10条 / 页
    - -
    -
    - -
    -
    10条 / 页
    - -
    - -
    -
    - -
    -
    20条 / 页
    - -
    - -
    -
    - -
    -
    50条 / 页
    - -
    - -
    -
    - -
    -
    100条 / 页
    - -
    - -
    -
    -
    + +
  • diff --git a/packages/varlet-ui/src/select/Select.vue b/packages/varlet-ui/src/select/Select.vue index 00adaf484d3..ce5511b8ed4 100644 --- a/packages/varlet-ui/src/select/Select.vue +++ b/packages/varlet-ui/src/select/Select.vue @@ -122,7 +122,7 @@