diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..b401f46a5b --- /dev/null +++ b/.eslintignore @@ -0,0 +1,15 @@ +node_modules/* +packages/**/node_modules/* +packages/**/dist/* +packages/**/build/* +packages/**/lib/* + +packages/devui-vue/devui/accordion/src/accordion-open-icon.tsx +packages/devui-vue/devui/auto-complete/src/auto-complete.tsx +packages/devui-vue/devui/editable-select/src/editable-select.tsx +packages/devui-vue/devui/gantt/src/gantt-milestone/milestone-icon.tsx +packages/devui-vue/devui/modal/src/modal.tsx +packages/devui-vue/devui/pagination/src/components/jump-page.tsx +packages/devui-vue/devui/search/src/search.tsx +packages/devui-vue/devui/table/src/header/filter/filter.tsx +packages/devui-vue/devui/table/src/header/sort/sort.tsx diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index d8646c75e5..b8d64215de 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -2,9 +2,9 @@ name: Pull Request on: push: - branches: [ dev, main ] + branches: [ dev, main, 1.0.0 ] pull_request: - branches: [ dev, main ] + branches: [ dev, main, 1.0.0 ] jobs: build: @@ -38,4 +38,4 @@ jobs: run: pnpm build # - name: Test vue-devui - # run: yarn test + # run: pnpm test diff --git a/packages/devui-cli/src/bin.ts b/packages/devui-cli/src/bin.ts index b802d9943f..054e82a366 100644 --- a/packages/devui-cli/src/bin.ts +++ b/packages/devui-cli/src/bin.ts @@ -1,18 +1,18 @@ #!/usr/bin/env node -import { Command } from 'commander' -import type { CliConfig } from '../types/config' -import baseAction from './commands/base' -import createAction, { validateCreateType } from './commands/create' -import { detectCliConfig } from './shared/config' -import { VERSION } from './shared/constant' +import { Command } from 'commander'; +import type { CliConfig } from '../types/config'; +import baseAction from './commands/base'; +import createAction, { validateCreateType } from './commands/create'; +import { detectCliConfig } from './shared/config'; +import { VERSION } from './shared/constant'; import { DEFAULT_CLI_CONFIG_FILE_NAME -} from './shared/generate-config' +} from './shared/generate-config'; // detect cli config -detectCliConfig() +detectCliConfig(); -const program = new Command() +const program = new Command(); program .command('create [name...]') @@ -26,7 +26,7 @@ program .option('--directive', 'Include service when creating a component.') .option('-f --force', 'For force overwriting.') .description('Create a component structure, library entry file or other...') - .action(createAction) + .action(createAction); program .option('--init', 'Initialize the cli configuration file in the current working directory.') @@ -37,10 +37,10 @@ program .usage('[command] [options]') .version(VERSION, '-v --version') .description('Cli of devui.') - .action(baseAction) + .action(baseAction); -program.parse(process.argv) +program.parse(process.argv); export function defineCliConfig(config: Partial = {}) { - return config + return config; } diff --git a/packages/devui-cli/src/commands/base.ts b/packages/devui-cli/src/commands/base.ts index 78122a6910..392ff8e922 100644 --- a/packages/devui-cli/src/commands/base.ts +++ b/packages/devui-cli/src/commands/base.ts @@ -10,7 +10,7 @@ import buildAction from './build'; import createAction from './create'; function getActions() { - const actionMap = new Map(); + const actionMap = new Map(); actionMap.set('create', { title: 'create', value: 'create', @@ -23,8 +23,8 @@ function getActions() { } export type BaseCmd = { - init?: boolean - config?: string + init?: boolean; + config?: string; }; export default async function baseAction(cmd: BaseCmd) { @@ -38,7 +38,7 @@ export default async function baseAction(cmd: BaseCmd) { } export function loadCliConfig(cmd: Pick) { - if (!cmd.config) return; + if (!cmd.config) {return;} const configPath = resolve(CWD, cmd.config); diff --git a/packages/devui-cli/src/commands/build.ts b/packages/devui-cli/src/commands/build.ts index bdfdf67aaf..b7d0e09e85 100644 --- a/packages/devui-cli/src/commands/build.ts +++ b/packages/devui-cli/src/commands/build.ts @@ -2,4 +2,4 @@ function buildAction() { } -export default buildAction \ No newline at end of file +export default buildAction; diff --git a/packages/devui-cli/src/commands/create-component.ts b/packages/devui-cli/src/commands/create-component.ts index caaef584e5..444529bcf5 100644 --- a/packages/devui-cli/src/commands/create-component.ts +++ b/packages/devui-cli/src/commands/create-component.ts @@ -1,35 +1,35 @@ -import prompts from 'prompts' -import { cliConfig } from '../shared/config' -import genComponent from '../shared/generate-component' -import logger from '../shared/logger' -import { canSafelyOverwrite, onPromptsCancel, resolveComponentDir } from '../shared/utils' -import { CreateCMD } from './create' +import prompts from 'prompts'; +import { cliConfig } from '../shared/config'; +import genComponent from '../shared/generate-component'; +import logger from '../shared/logger'; +import { canSafelyOverwrite, onPromptsCancel, resolveComponentDir } from '../shared/utils'; +import { CreateCMD } from './create'; export function isValidComponentName(name: string) { - if (!name) return false + if (!name) {return false;} - const flag = /^[a-zA-Z]([\w-\d]*)$/.test(name) + const flag = /^[a-zA-Z]([\w-\d]*)$/.test(name); if (!flag) { - logger.warn(`The component name "${name}" is invalid.`) - logger.info(`The component name rule: letters, numbers, "-", and must start with a letter.`) + logger.warn(`The component name "${name}" is invalid.`); + logger.info(`The component name rule: letters, numbers, "-", and must start with a letter.`); } - return flag + return flag; } export default async function createComponentAction(names: string[] = [], cmd: CreateCMD = {}) { - let [name = '', title = '', category = ''] = names - const parts = [] - let targetDir = resolveComponentDir(name) + let [name = '', title = '', category = ''] = names; + const parts = []; + let targetDir = resolveComponentDir(name); - cmd.core && parts.push('core') - cmd.service && parts.push('service') - cmd.directive && parts.push('directive') + cmd.core && parts.push('core'); + cmd.service && parts.push('service'); + cmd.directive && parts.push('directive'); if (!isValidComponentName(name)) { - name = '' - targetDir = '' + name = ''; + targetDir = ''; } try { @@ -40,31 +40,31 @@ export default async function createComponentAction(names: string[] = [], cmd: C type: () => (name ? null : 'text'), message: 'Component name:', validate: () => { - console.log('') // 防止错误输出于同一行 + console.log(''); // 防止错误输出于同一行 - const isValid = isValidComponentName(name) + const isValid = isValidComponentName(name); - return isValid + return isValid; }, onState: (state) => { - name = String(state.value).trim() - targetDir = resolveComponentDir(name) + name = String(state.value).trim(); + targetDir = resolveComponentDir(name); } }, { name: 'shouldOverwrite', type: () => (canSafelyOverwrite(targetDir) || cmd.force ? null : 'confirm'), message: () => { - return `Target directory "${targetDir}" is not empty. Remove existing files and continue?` + return `Target directory "${targetDir}" is not empty. Remove existing files and continue?`; } }, { name: 'overwriteChecker', type: (prev, values: any = {}) => { if (values.shouldOverwrite === false) { - throw new Error('Operation cancelled') + throw new Error('Operation cancelled'); } - return null + return null; } }, { @@ -112,7 +112,7 @@ export default async function createComponentAction(names: string[] = [], cmd: C } ], { onCancel: onPromptsCancel } - ) + ); genComponent({ name, @@ -120,9 +120,9 @@ export default async function createComponentAction(names: string[] = [], cmd: C category: meta.category ?? category, parts: meta.parts ?? parts, dir: targetDir - }) + }); } catch (e: any) { - logger.error(e.message) - process.exit(1) + logger.error(e.message); + process.exit(1); } } diff --git a/packages/devui-cli/src/commands/create-lib-entry.ts b/packages/devui-cli/src/commands/create-lib-entry.ts index 5b47aa2b22..e0e3ed1136 100644 --- a/packages/devui-cli/src/commands/create-lib-entry.ts +++ b/packages/devui-cli/src/commands/create-lib-entry.ts @@ -1,14 +1,14 @@ -import { cliConfig } from '../shared/config' -import genLibEntry from '../shared/generate-lib-entry' -import logger from '../shared/logger' -import { resolveLibEntryDir } from '../shared/utils' -import { CreateCMD } from './create' +import { cliConfig } from '../shared/config'; +import genLibEntry from '../shared/generate-lib-entry'; +import logger from '../shared/logger'; +import { resolveLibEntryDir } from '../shared/utils'; +import { CreateCMD } from './create'; export default async function createLibEntryAction(names: string[] = [], cmd: CreateCMD) { try { - const [name = cliConfig.libEntryFileName] = names - genLibEntry(resolveLibEntryDir(name)) + const [name = cliConfig.libEntryFileName] = names; + genLibEntry(resolveLibEntryDir(name)); } catch (e: any) { - logger.error(e.message) + logger.error(e.message); } } diff --git a/packages/devui-cli/src/commands/create.ts b/packages/devui-cli/src/commands/create.ts index 67b1458a3c..ccbb5b85f7 100644 --- a/packages/devui-cli/src/commands/create.ts +++ b/packages/devui-cli/src/commands/create.ts @@ -1,45 +1,45 @@ -import prompts from 'prompts' -import logger from '../shared/logger' -import { onPromptsCancel } from '../shared/utils' -import { loadCliConfig } from './base' -import createComponentAction from './create-component' -import createLibEntryAction from './create-lib-entry' +import prompts from 'prompts'; +import logger from '../shared/logger'; +import { onPromptsCancel } from '../shared/utils'; +import { loadCliConfig } from './base'; +import createComponentAction from './create-component'; +import createLibEntryAction from './create-lib-entry'; export type CreateCMD = { - config?: string - type?: keyof typeof CREATE_TYPE_ACTION - core?: boolean - service?: boolean - directive?: boolean - force?: boolean -} + config?: string; + type?: keyof typeof CREATE_TYPE_ACTION; + core?: boolean; + service?: boolean; + directive?: boolean; + force?: boolean; +}; -const CREATE_TYPES = ['component', 'component-test', 'component-doc', 'lib-entry', 'doc-nav'] -const UNFINISHED_CREATE_TYPES = ['component-test', 'component-doc', 'doc-nav'] +const CREATE_TYPES = ['component', 'component-test', 'component-doc', 'lib-entry', 'doc-nav']; +const UNFINISHED_CREATE_TYPES = ['component-test', 'component-doc', 'doc-nav']; const CREATE_TYPE_ACTION = { component: createComponentAction, 'lib-entry': createLibEntryAction -} +}; export function validateCreateType(type: string) { - const valid = CREATE_TYPES.includes(type) + const valid = CREATE_TYPES.includes(type); if (!valid) { - logger.error(`Create type error!.`) + logger.error(`Create type error!.`); logger.info( `Optional type list: ${CREATE_TYPES.map((type) => UNFINISHED_CREATE_TYPES.includes(type) ? `${type}(Unfinished)` : type ).join(', ')}` - ) + ); } - return valid ? type : '' + return valid ? type : ''; } export default async function createAction(names: string[] = [], cmd: CreateCMD = {}) { - loadCliConfig(cmd) + loadCliConfig(cmd); - let { type } = cmd + let { type } = cmd; if (!type) { try { @@ -59,19 +59,19 @@ export default async function createAction(names: string[] = [], cmd: CreateCMD { onCancel: onPromptsCancel } - ) + ); - type = result.type + type = result.type; } catch (e: any) { - logger.error(e.message) - process.exit(1) + logger.error(e.message); + process.exit(1); } } - const action = CREATE_TYPE_ACTION[type!] + const action = CREATE_TYPE_ACTION[type!]; if (action) { - action(names, cmd) + action(names, cmd); } else { - logger.warn('Sorry! The type is not completed.') + logger.warn('Sorry! The type is not completed.'); } } diff --git a/packages/devui-cli/src/shared/config.ts b/packages/devui-cli/src/shared/config.ts index c52a78cc7a..6b8a60cd10 100644 --- a/packages/devui-cli/src/shared/config.ts +++ b/packages/devui-cli/src/shared/config.ts @@ -1,10 +1,10 @@ -import { readdirSync, statSync } from 'fs-extra' -import { merge } from 'lodash-es' -import { resolve } from 'path' -import type { CliConfig } from '../../types/config' -import { loadCliConfig } from '../commands/base' -import { CWD } from './constant' -import { DEFAULT_CLI_CONFIG_NAME } from './generate-config' +import { readdirSync, statSync } from 'fs-extra'; +import { merge } from 'lodash-es'; +import { resolve } from 'path'; +import type { CliConfig } from '../../types/config'; +import { loadCliConfig } from '../commands/base'; +import { CWD } from './constant'; +import { DEFAULT_CLI_CONFIG_NAME } from './generate-config'; export const cliConfig: CliConfig = { cwd: CWD, @@ -16,17 +16,17 @@ export const cliConfig: CliConfig = { libEntryRootDir: '.', libEntryFileName: 'index', version: '0.0.0' -} +}; export function mergeCliConfig(config: Partial = {}) { - return merge(cliConfig, config) + return merge(cliConfig, config); } export function detectCliConfig() { - const re = new RegExp(`^${DEFAULT_CLI_CONFIG_NAME}\.(js|ts)$`) - const file = readdirSync(CWD).find((f) => statSync(resolve(CWD, f)).isFile() && re.test(f)) + const re = new RegExp(`^${DEFAULT_CLI_CONFIG_NAME}\.(js|ts)$`); + const file = readdirSync(CWD).find((f) => statSync(resolve(CWD, f)).isFile() && re.test(f)); - if (!file) return + if (!file) {return;} - loadCliConfig({ config: resolve(CWD, file) }) + loadCliConfig({ config: resolve(CWD, file) }); } diff --git a/packages/devui-cli/src/shared/constant.ts b/packages/devui-cli/src/shared/constant.ts index bc3cab5616..e806791a1d 100644 --- a/packages/devui-cli/src/shared/constant.ts +++ b/packages/devui-cli/src/shared/constant.ts @@ -1,7 +1,7 @@ -import { name, version } from '../../package.json' +import { name, version } from '../../package.json'; -export const CWD = process.cwd() +export const CWD = process.cwd(); -export const VERSION = version +export const VERSION = version; -export const PKG_NAME = name \ No newline at end of file +export const PKG_NAME = name; diff --git a/packages/devui-cli/src/shared/generate-component.ts b/packages/devui-cli/src/shared/generate-component.ts index 2a55d64e20..f720874f06 100644 --- a/packages/devui-cli/src/shared/generate-component.ts +++ b/packages/devui-cli/src/shared/generate-component.ts @@ -1,82 +1,82 @@ -import { WriteFileOptions } from 'fs' -import { mkdirSync, writeFileSync } from 'fs-extra' -import { resolve } from 'path' -import genIndexTemplate from '../templates/component' -import genCoreTemplate from '../templates/component/core' -import genDirectiveTemplate from '../templates/component/directive' -import genDocTemplate from '../templates/component/doc' -import genMetaTemplate, { ComponentMeta, genMetaObj } from '../templates/component/meta' -import genServiceTemplate from '../templates/component/service' -import genStyleTemplate from '../templates/component/style' -import genTestTemplate from '../templates/component/test' -import genTypesTemplate from '../templates/component/types' +import { WriteFileOptions } from 'fs'; +import { mkdirSync, writeFileSync } from 'fs-extra'; +import { resolve } from 'path'; +import genIndexTemplate from '../templates/component'; +import genCoreTemplate from '../templates/component/core'; +import genDirectiveTemplate from '../templates/component/directive'; +import genDocTemplate from '../templates/component/doc'; +import genMetaTemplate, { ComponentMeta, genMetaObj } from '../templates/component/meta'; +import genServiceTemplate from '../templates/component/service'; +import genStyleTemplate from '../templates/component/style'; +import genTestTemplate from '../templates/component/test'; +import genTypesTemplate from '../templates/component/types'; import { coreFileName, directiveFileName, serviceFileName, typesFileName -} from '../templates/component/utils' -import { cliConfig } from './config' -import logger from './logger' -import { bigCamelCase } from './utils' +} from '../templates/component/utils'; +import { cliConfig } from './config'; +import logger from './logger'; +import { bigCamelCase } from './utils'; -const WRITE_FILE_OPTIONS: WriteFileOptions = { encoding: 'utf-8' } +const WRITE_FILE_OPTIONS: WriteFileOptions = { encoding: 'utf-8' }; export default function genComponent(meta: ComponentMeta) { - const componentDir = resolve(meta.dir!, 'src') - const docDir = resolve(meta.dir!, 'docs') - const testDir = resolve(meta.dir!, '__tests__') + const componentDir = resolve(meta.dir!, 'src'); + const docDir = resolve(meta.dir!, 'docs'); + const testDir = resolve(meta.dir!, '__tests__'); - mkdirSync(componentDir, { recursive: true }) - mkdirSync(docDir, { recursive: true }) - mkdirSync(testDir, { recursive: true }) + mkdirSync(componentDir, { recursive: true }); + mkdirSync(docDir, { recursive: true }); + mkdirSync(testDir, { recursive: true }); - let needsTypes = false - meta = genMetaObj(meta) + let needsTypes = false; + meta = genMetaObj(meta); if (meta.parts.includes('core')) { - needsTypes = true + needsTypes = true; - const coreFilePath = resolve(componentDir, coreFileName(meta.name)) - writeFileSync(coreFilePath + '.tsx', genCoreTemplate(meta.name), WRITE_FILE_OPTIONS) + const coreFilePath = resolve(componentDir, coreFileName(meta.name)); + writeFileSync(coreFilePath + '.tsx', genCoreTemplate(meta.name), WRITE_FILE_OPTIONS); writeFileSync( coreFilePath + cliConfig.libStyleFileSuffix, genStyleTemplate(meta.name), WRITE_FILE_OPTIONS - ) + ); } if (meta.parts.includes('service')) { - needsTypes = true + needsTypes = true; - const serviceFilePath = resolve(componentDir, serviceFileName(meta.name) + '.ts') - writeFileSync(serviceFilePath, genServiceTemplate(meta.name), WRITE_FILE_OPTIONS) + const serviceFilePath = resolve(componentDir, serviceFileName(meta.name) + '.ts'); + writeFileSync(serviceFilePath, genServiceTemplate(meta.name), WRITE_FILE_OPTIONS); } if (meta.parts.includes('directive')) { - const directiveFilePath = resolve(componentDir, directiveFileName(meta.name) + '.ts') - writeFileSync(directiveFilePath, genDirectiveTemplate(), WRITE_FILE_OPTIONS) + const directiveFilePath = resolve(componentDir, directiveFileName(meta.name) + '.ts'); + writeFileSync(directiveFilePath, genDirectiveTemplate(), WRITE_FILE_OPTIONS); } if (needsTypes) { - const typesFilePath = resolve(componentDir, typesFileName(meta.name) + '.ts') - writeFileSync(typesFilePath, genTypesTemplate(meta.name), WRITE_FILE_OPTIONS) + const typesFilePath = resolve(componentDir, typesFileName(meta.name) + '.ts'); + writeFileSync(typesFilePath, genTypesTemplate(meta.name), WRITE_FILE_OPTIONS); } if (meta.parts.length > 0) { - const indexFilePath = resolve(meta.dir!, 'index.ts') - const metaFilePath = resolve(meta.dir!, 'meta.json') - const testFilePath = resolve(testDir, 'index.spec.ts') - const docFilePath = resolve(docDir, 'index.md') + const indexFilePath = resolve(meta.dir!, 'index.ts'); + const metaFilePath = resolve(meta.dir!, 'meta.json'); + const testFilePath = resolve(testDir, 'index.spec.ts'); + const docFilePath = resolve(docDir, 'index.md'); - writeFileSync(indexFilePath, genIndexTemplate(meta.name, meta.parts), WRITE_FILE_OPTIONS) - writeFileSync(metaFilePath, genMetaTemplate(meta), WRITE_FILE_OPTIONS) - writeFileSync(testFilePath, genTestTemplate(meta), WRITE_FILE_OPTIONS) - writeFileSync(docFilePath, genDocTemplate(meta), WRITE_FILE_OPTIONS) + writeFileSync(indexFilePath, genIndexTemplate(meta.name, meta.parts), WRITE_FILE_OPTIONS); + writeFileSync(metaFilePath, genMetaTemplate(meta), WRITE_FILE_OPTIONS); + writeFileSync(testFilePath, genTestTemplate(meta), WRITE_FILE_OPTIONS); + writeFileSync(docFilePath, genDocTemplate(meta), WRITE_FILE_OPTIONS); } logger.success( `The component "${bigCamelCase(meta.name)}" directory has been generated successfully.` - ) - logger.info(`Target directory: ${meta.dir}`) + ); + logger.info(`Target directory: ${meta.dir}`); } diff --git a/packages/devui-cli/src/shared/generate-config.ts b/packages/devui-cli/src/shared/generate-config.ts index 109f5e55dd..7e52d68545 100644 --- a/packages/devui-cli/src/shared/generate-config.ts +++ b/packages/devui-cli/src/shared/generate-config.ts @@ -1,23 +1,23 @@ -import { existsSync, writeFileSync } from 'fs-extra' -import { resolve } from 'path' -import genConfigTemplate from '../templates/base/config' -import { CWD } from './constant' -import logger from './logger' +import { existsSync, writeFileSync } from 'fs-extra'; +import { resolve } from 'path'; +import genConfigTemplate from '../templates/base/config'; +import { CWD } from './constant'; +import logger from './logger'; -export const DEFAULT_CLI_CONFIG_NAME = 'dc.config' -export const DEFAULT_CLI_CONFIG_EXT_NAME = '.ts' -export const DEFAULT_CLI_CONFIG_FILE_NAME = DEFAULT_CLI_CONFIG_NAME + DEFAULT_CLI_CONFIG_EXT_NAME +export const DEFAULT_CLI_CONFIG_NAME = 'dc.config'; +export const DEFAULT_CLI_CONFIG_EXT_NAME = '.ts'; +export const DEFAULT_CLI_CONFIG_FILE_NAME = DEFAULT_CLI_CONFIG_NAME + DEFAULT_CLI_CONFIG_EXT_NAME; export default function generateConfig() { - const configPath = resolve(CWD, DEFAULT_CLI_CONFIG_FILE_NAME) + const configPath = resolve(CWD, DEFAULT_CLI_CONFIG_FILE_NAME); if (existsSync(configPath)) { - logger.error(`The configuration path "${configPath}" already exists.`) - process.exit(1) + logger.error(`The configuration path "${configPath}" already exists.`); + process.exit(1); } - writeFileSync(configPath, genConfigTemplate(), { encoding: 'utf-8' }) + writeFileSync(configPath, genConfigTemplate(), { encoding: 'utf-8' }); - logger.success(`The configuration file has been generated successfully.`) - logger.info(`Target file: ${configPath}`) + logger.success(`The configuration file has been generated successfully.`); + logger.info(`Target file: ${configPath}`); } diff --git a/packages/devui-cli/src/shared/generate-lib-entry.ts b/packages/devui-cli/src/shared/generate-lib-entry.ts index 9e7a705e53..7993128579 100644 --- a/packages/devui-cli/src/shared/generate-lib-entry.ts +++ b/packages/devui-cli/src/shared/generate-lib-entry.ts @@ -1,15 +1,15 @@ -import { writeFileSync } from 'fs-extra' -import { getComponentsMeta } from '../templates/component/utils' -import genLibEntryTemplate from '../templates/lib-entry/lib-entry' -import logger from './logger' +import { writeFileSync } from 'fs-extra'; +import { getComponentsMeta } from '../templates/component/utils'; +import genLibEntryTemplate from '../templates/lib-entry/lib-entry'; +import logger from './logger'; export default async function genLibEntry(filePath = '') { - const componentsMeta = await getComponentsMeta() + const componentsMeta = await getComponentsMeta(); writeFileSync(filePath, genLibEntryTemplate(componentsMeta), { encoding: 'utf-8' - }) + }); - logger.success(`The component library entry file has been generated successfully.`) - logger.info(`Target file: ${filePath}`) + logger.success(`The component library entry file has been generated successfully.`); + logger.info(`Target file: ${filePath}`); } diff --git a/packages/devui-cli/src/shared/logger.ts b/packages/devui-cli/src/shared/logger.ts index b1f1e76681..3d72d0b782 100644 --- a/packages/devui-cli/src/shared/logger.ts +++ b/packages/devui-cli/src/shared/logger.ts @@ -1,19 +1,19 @@ -import { lightBlue, lightGreen, lightRed, lightYellow } from 'kolorist' +import { lightBlue, lightGreen, lightRed, lightYellow } from 'kolorist'; const logger = { PREFIX: '[dev-cli]', info(text: string) { - console.log(lightBlue(`✈ ${logger.PREFIX} - ${text}`)) + console.log(lightBlue(`✈ ${logger.PREFIX} - ${text}`)); }, success(text: string) { - console.log(lightGreen(`✔ ${logger.PREFIX} - ${text}`)) + console.log(lightGreen(`✔ ${logger.PREFIX} - ${text}`)); }, warn(text: string) { - console.log(lightYellow(`▶ ${logger.PREFIX} - ${text}`)) + console.log(lightYellow(`▶ ${logger.PREFIX} - ${text}`)); }, error(text: string) { - console.log(lightRed(`✖ ${logger.PREFIX} - ${text}`)) + console.log(lightRed(`✖ ${logger.PREFIX} - ${text}`)); } -} +}; -export default logger +export default logger; diff --git a/packages/devui-cli/src/shared/utils.ts b/packages/devui-cli/src/shared/utils.ts index 3ff20f8142..b342bc3267 100644 --- a/packages/devui-cli/src/shared/utils.ts +++ b/packages/devui-cli/src/shared/utils.ts @@ -1,34 +1,34 @@ -import { buildSync } from 'esbuild' -import { existsSync, readdirSync, unlinkSync } from 'fs-extra' -import { camelCase, upperFirst } from 'lodash-es' -import { extname, relative, resolve } from 'path' -import { coreFileName } from '../templates/component/utils' -import { cliConfig } from './config' -import { PKG_NAME } from './constant' +import { buildSync } from 'esbuild'; +import { existsSync, readdirSync, unlinkSync } from 'fs-extra'; +import { camelCase, upperFirst } from 'lodash-es'; +import { extname, relative, resolve } from 'path'; +import { coreFileName } from '../templates/component/utils'; +import { cliConfig } from './config'; +import { PKG_NAME } from './constant'; export function bigCamelCase(str: string) { - return upperFirst(camelCase(str)) + return upperFirst(camelCase(str)); } export function onPromptsCancel() { - throw new Error('Operation cancelled.') + throw new Error('Operation cancelled.'); } export function canSafelyOverwrite(dir: string) { - return !existsSync(dir) || readdirSync(dir).length === 0 + return !existsSync(dir) || readdirSync(dir).length === 0; } export function resolveComponentDir(name: string) { - return resolve(cliConfig.cwd, cliConfig.componentRootDir, coreFileName(name)) + return resolve(cliConfig.cwd, cliConfig.componentRootDir, coreFileName(name)); } export function resolveLibEntryDir(name: string) { - return resolve(cliConfig.cwd, cliConfig.libEntryRootDir, name + '.ts') + return resolve(cliConfig.cwd, cliConfig.libEntryRootDir, name + '.ts'); } export function dynamicImport(path: string) { - const tempPath = path.replace(extname(path), Date.now() + '.js') - const relativePath = relative(__dirname, tempPath) + const tempPath = path.replace(extname(path), Date.now() + '.js'); + const relativePath = relative(__dirname, tempPath); buildSync({ bundle: true, @@ -37,10 +37,10 @@ export function dynamicImport(path: string) { platform: 'node', format: 'cjs', external: ['esbuild', PKG_NAME] - }) + }); - const config = require(relativePath).default ?? {} - unlinkSync(tempPath) + const config = require(relativePath).default ?? {}; + unlinkSync(tempPath); - return config + return config; } diff --git a/packages/devui-cli/src/templates/base/config.ts b/packages/devui-cli/src/templates/base/config.ts index 14b00105b5..6cc97792c3 100644 --- a/packages/devui-cli/src/templates/base/config.ts +++ b/packages/devui-cli/src/templates/base/config.ts @@ -6,5 +6,5 @@ export default function genConfigTemplate(config: Partial = {}) { import { defineCliConfig } from '${PKG_NAME}' export default defineCliConfig(${JSON.stringify(config, null, 2)}) -` -} \ No newline at end of file +`; +} diff --git a/packages/devui-cli/src/templates/component/core.ts b/packages/devui-cli/src/templates/component/core.ts index 1843148246..b50e64a0fb 100644 --- a/packages/devui-cli/src/templates/component/core.ts +++ b/packages/devui-cli/src/templates/component/core.ts @@ -1,4 +1,4 @@ -import { coreClassName, coreRealName, propsName, propsTypesName, typesFileName } from './utils' +import { coreClassName, coreRealName, propsName, propsTypesName, typesFileName } from './utils'; export default function genCoreTemplate(name: string) { return `\ @@ -15,5 +15,5 @@ export default defineComponent({ } } }) -` +`; } diff --git a/packages/devui-cli/src/templates/component/directive.ts b/packages/devui-cli/src/templates/component/directive.ts index 5333f99f4d..4ae0b3b735 100644 --- a/packages/devui-cli/src/templates/component/directive.ts +++ b/packages/devui-cli/src/templates/component/directive.ts @@ -9,5 +9,5 @@ export default { updated() { }, beforeUnmount() { }, unmounted() { } -}` +}`; } diff --git a/packages/devui-cli/src/templates/component/doc.ts b/packages/devui-cli/src/templates/component/doc.ts index aad6bb48b7..d57fefe8a6 100644 --- a/packages/devui-cli/src/templates/component/doc.ts +++ b/packages/devui-cli/src/templates/component/doc.ts @@ -51,5 +51,5 @@ ${meta.realName} 事件 | | | | | | | | | | | | | | | -` +`; } diff --git a/packages/devui-cli/src/templates/component/index.ts b/packages/devui-cli/src/templates/component/index.ts index 8f712e3085..a4202c7db6 100644 --- a/packages/devui-cli/src/templates/component/index.ts +++ b/packages/devui-cli/src/templates/component/index.ts @@ -1,4 +1,4 @@ -import { camelCase } from 'lodash-es' +import { camelCase } from 'lodash-es'; import { coreFileName, coreName, @@ -8,42 +8,42 @@ import { serviceFileName, serviceName, typesFileName -} from './utils' +} from './utils'; export default function genIndexTemplate(name: string, parts: string[]) { - const importParts = [] - const exportParts = [] - const installParts = [] + const importParts = []; + const exportParts = []; + const installParts = []; - let needsTypes = false + let needsTypes = false; if (parts.includes('core')) { - needsTypes = true + needsTypes = true; - importParts.push(`import ${coreName(name)} from './src/${coreFileName(name)}'`) - exportParts.push(coreName(name)) - installParts.push(`\tapp.component(${coreName(name)}.name, ${coreName(name)})`) + importParts.push(`import ${coreName(name)} from './src/${coreFileName(name)}'`); + exportParts.push(coreName(name)); + installParts.push(`\tapp.component(${coreName(name)}.name, ${coreName(name)})`); } if (parts.includes('service')) { - needsTypes = true + needsTypes = true; - importParts.push(`import ${serviceName(name)} from './src/${serviceFileName(name)}'`) - exportParts.push(serviceName(name)) + importParts.push(`import ${serviceName(name)} from './src/${serviceFileName(name)}'`); + exportParts.push(serviceName(name)); installParts.push( `\tapp.config.globalProperties.$${camelCase(serviceName(name))} = ${serviceName(name)}` - ) + ); } if (parts.includes('directive')) { - importParts.push(`import ${directiveName(name)} from './src/${directiveFileName(name)}'`) - exportParts.push(directiveName(name)) - installParts.push(`\tapp.directive('${coreName(name)}', ${directiveName(name)})`) + importParts.push(`import ${directiveName(name)} from './src/${directiveFileName(name)}'`); + exportParts.push(directiveName(name)); + installParts.push(`\tapp.directive('${coreName(name)}', ${directiveName(name)})`); } if (needsTypes) { - importParts.push(`import { ${propsTypesName(name)} } from './src/${typesFileName(name)}'`) - exportParts.push(propsTypesName(name)) + importParts.push(`import { ${propsTypesName(name)} } from './src/${typesFileName(name)}'`); + exportParts.push(propsTypesName(name)); } return `\ @@ -61,5 +61,5 @@ export default { app.use(${coreName(name)} as any) } } -` +`; } diff --git a/packages/devui-cli/src/templates/component/meta.ts b/packages/devui-cli/src/templates/component/meta.ts index a5c37e25ab..0051e594a7 100644 --- a/packages/devui-cli/src/templates/component/meta.ts +++ b/packages/devui-cli/src/templates/component/meta.ts @@ -1,19 +1,19 @@ -import { isPlainObject } from 'lodash-es' -import { coreName, coreRealName } from './utils' +import { isPlainObject } from 'lodash-es'; +import { coreName, coreRealName } from './utils'; export type ComponentMeta = { - name: string - realName?: string - title: string - fullTitle?: string - category: string - parts: string[] - status?: string - dir?: string -} + name: string; + realName?: string; + title: string; + fullTitle?: string; + category: string; + parts: string[]; + status?: string; + dir?: string; +}; export function isValidComponentMeta(obj: any) { - return isPlainObject(obj) && !!obj.name && Array.isArray(obj.parts) + return isPlainObject(obj) && !!obj.name && Array.isArray(obj.parts); } export function genMetaObj(meta: Partial = {}) { @@ -41,9 +41,9 @@ export function genMetaObj(meta: Partial = {}) { $dir: '组件目录', dir: meta.dir ?? '' - } + }; } export default function genMetaTemplate(meta: Partial = {}) { - return JSON.stringify(genMetaObj(meta), null, 2) + return JSON.stringify(genMetaObj(meta), null, 2); } diff --git a/packages/devui-cli/src/templates/component/service.ts b/packages/devui-cli/src/templates/component/service.ts index 2b67f135ae..fc2a99a87c 100644 --- a/packages/devui-cli/src/templates/component/service.ts +++ b/packages/devui-cli/src/templates/component/service.ts @@ -1,4 +1,4 @@ -import { propsTypesName, serviceName, typesFileName } from './utils' +import { propsTypesName, serviceName, typesFileName } from './utils'; export default function genServiceTemplate(name: string) { return `\ @@ -9,5 +9,5 @@ const ${serviceName(name)} = { } export default ${serviceName(name)} -` +`; } diff --git a/packages/devui-cli/src/templates/component/style.ts b/packages/devui-cli/src/templates/component/style.ts index 57a00df38e..dc1f733a27 100644 --- a/packages/devui-cli/src/templates/component/style.ts +++ b/packages/devui-cli/src/templates/component/style.ts @@ -1,8 +1,8 @@ -import { coreClassName } from './utils' +import { coreClassName } from './utils'; export default function genStyleTemplate(name: string) { return `\ .${coreClassName(name)} { /* your style */ -}` -} \ No newline at end of file +}`; +} diff --git a/packages/devui-cli/src/templates/component/test.ts b/packages/devui-cli/src/templates/component/test.ts index 78c56b9216..d9147cdf86 100644 --- a/packages/devui-cli/src/templates/component/test.ts +++ b/packages/devui-cli/src/templates/component/test.ts @@ -1,5 +1,5 @@ -import { getPartName } from '../lib-entry/lib-entry' -import { ComponentMeta } from './meta' +import { getPartName } from '../lib-entry/lib-entry'; +import { ComponentMeta } from './meta'; export default function genTestTemplate(meta: ComponentMeta) { return `\ @@ -11,5 +11,5 @@ describe('${meta.name} test', () => { \/\/ todo }) }) -` +`; } diff --git a/packages/devui-cli/src/templates/component/types.ts b/packages/devui-cli/src/templates/component/types.ts index 1d2656474b..c033cd0d4f 100644 --- a/packages/devui-cli/src/templates/component/types.ts +++ b/packages/devui-cli/src/templates/component/types.ts @@ -1,4 +1,4 @@ -import { propsName, propsTypesName } from './utils' +import { propsName, propsTypesName } from './utils'; export default function genTypesTemplate(name: string) { return `\ @@ -11,5 +11,5 @@ export const ${propsName(name)}Props = { } as const export type ${propsTypesName(name)}Props = ExtractPropTypes -` +`; } diff --git a/packages/devui-cli/src/templates/component/utils.ts b/packages/devui-cli/src/templates/component/utils.ts index 7e87005af8..5a6e6fbc7b 100644 --- a/packages/devui-cli/src/templates/component/utils.ts +++ b/packages/devui-cli/src/templates/component/utils.ts @@ -1,35 +1,35 @@ -import glob from 'fast-glob' -import { readFileSync } from 'fs-extra' -import { camelCase, kebabCase } from 'lodash-es' -import { cliConfig } from '../../shared/config' -import { bigCamelCase } from '../../shared/utils' -import { ComponentMeta } from './meta' +import glob from 'fast-glob'; +import { readFileSync } from 'fs-extra'; +import { camelCase, kebabCase } from 'lodash-es'; +import { cliConfig } from '../../shared/config'; +import { bigCamelCase } from '../../shared/utils'; +import { ComponentMeta } from './meta'; -export const coreFileName = (name: string) => kebabCase(name) -export const typesFileName = (name: string) => kebabCase(name + '-types') -export const serviceFileName = (name: string) => kebabCase(name + '-service') -export const directiveFileName = (name: string) => kebabCase(name + '-directive') +export const coreFileName = (name: string) => kebabCase(name); +export const typesFileName = (name: string) => kebabCase(name + '-types'); +export const serviceFileName = (name: string) => kebabCase(name + '-service'); +export const directiveFileName = (name: string) => kebabCase(name + '-directive'); -export const getRealLibPrefix = () => (cliConfig.libPrefix ? cliConfig.libPrefix + '-' : '') +export const getRealLibPrefix = () => (cliConfig.libPrefix ? cliConfig.libPrefix + '-' : ''); export const getRealClassPrefix = () => - cliConfig.libClassPrefix ? cliConfig.libClassPrefix + '-' : '' + cliConfig.libClassPrefix ? cliConfig.libClassPrefix + '-' : ''; -export const coreName = (name: string) => bigCamelCase(name) -export const coreRealName = (name: string) => bigCamelCase(getRealLibPrefix() + name) -export const coreClassName = (name: string) => kebabCase(getRealClassPrefix() + name) -export const propsName = (name: string) => camelCase(name + 'Props') -export const propsTypesName = (name: string) => bigCamelCase(name + 'Props') -export const serviceName = (name: string) => bigCamelCase(name + 'Service') -export const directiveName = (name: string) => bigCamelCase(name + 'Directive') +export const coreName = (name: string) => bigCamelCase(name); +export const coreRealName = (name: string) => bigCamelCase(getRealLibPrefix() + name); +export const coreClassName = (name: string) => kebabCase(getRealClassPrefix() + name); +export const propsName = (name: string) => camelCase(name + 'Props'); +export const propsTypesName = (name: string) => bigCamelCase(name + 'Props'); +export const serviceName = (name: string) => bigCamelCase(name + 'Service'); +export const directiveName = (name: string) => bigCamelCase(name + 'Directive'); export async function getComponentMetaFiles() { return glob('./**/meta.json', { cwd: cliConfig.componentRootDir, absolute: true - }) + }); } export async function getComponentsMeta() { - const metaFiles = await getComponentMetaFiles() - return metaFiles.map((f) => JSON.parse(readFileSync(f, { encoding: 'utf-8' })) as ComponentMeta) + const metaFiles = await getComponentMetaFiles(); + return metaFiles.map((f) => JSON.parse(readFileSync(f, { encoding: 'utf-8' })) as ComponentMeta); } diff --git a/packages/devui-cli/src/templates/lib-entry/lib-entry.ts b/packages/devui-cli/src/templates/lib-entry/lib-entry.ts index 7ad6221b62..aab8164a48 100644 --- a/packages/devui-cli/src/templates/lib-entry/lib-entry.ts +++ b/packages/devui-cli/src/templates/lib-entry/lib-entry.ts @@ -1,20 +1,20 @@ -import { relative, resolve } from 'path' -import { cliConfig } from '../../shared/config' -import logger from '../../shared/logger' -import { ComponentMeta, isValidComponentMeta } from '../component/meta' -import { coreFileName, coreName, directiveName, serviceName } from '../component/utils' +import { relative, resolve } from 'path'; +import { cliConfig } from '../../shared/config'; +import logger from '../../shared/logger'; +import { ComponentMeta, isValidComponentMeta } from '../component/meta'; +import { coreFileName, coreName, directiveName, serviceName } from '../component/utils'; export function resolveImportRelativePath(coreName: string) { - const libEntryPath = resolve(cliConfig.cwd, cliConfig.libEntryRootDir) - const corePath = resolve(cliConfig.cwd, cliConfig.componentRootDir, coreName) + const libEntryPath = resolve(cliConfig.cwd, cliConfig.libEntryRootDir); + const corePath = resolve(cliConfig.cwd, cliConfig.componentRootDir, coreName); - let relativePath = relative(libEntryPath, corePath) + let relativePath = relative(libEntryPath, corePath); if (relativePath.startsWith(coreName)) { - relativePath = './' + relativePath + relativePath = './' + relativePath; } - return relativePath.replace(/\\/g, '/') + return relativePath.replace(/\\/g, '/'); } export function getPartName(part: string, name: string) { @@ -22,37 +22,37 @@ export function getPartName(part: string, name: string) { core: coreName, service: serviceName, directive: directiveName - }[part] + }[part]; if (partNameFn === undefined) { logger.warn( `The component part must be one of core, service, or directive, but it gets an invalid value ${part}.` - ) + ); } - return partNameFn?.(name) ?? name + return partNameFn?.(name) ?? name; } export default function genLibEntryTemplate(componentsMeta: ComponentMeta[]) { - const imports = [] - const installs = [] - const packages = [] + const imports = []; + const installs = []; + const packages = []; for (const meta of componentsMeta) { if (!isValidComponentMeta(meta)) { logger.warn( `The component meta information must include the name and parts attributes, and the parts attribute must be an array.` - ) - continue + ); + continue; } - const parts = meta.parts.map((part) => getPartName(part, meta.name)) - const install = coreName(meta.name) + 'Install' - const importPkgPath = resolveImportRelativePath(coreFileName(meta.name)) + const parts = meta.parts.map((part) => getPartName(part, meta.name)); + const install = coreName(meta.name) + 'Install'; + const importPkgPath = resolveImportRelativePath(coreFileName(meta.name)); - installs.push(install) - imports.push(`import ${install}, { ${parts.join(', ')} } from '${importPkgPath}'`) - packages.push(...parts) + installs.push(install); + imports.push(`import ${install}, { ${parts.join(', ')} } from '${importPkgPath}'`); + packages.push(...parts); } return `\ @@ -74,5 +74,5 @@ export default { installs.forEach((p) => app.use(p as any)) } } -` +`; } diff --git a/packages/devui-theme/src/theme/theme-management.ts b/packages/devui-theme/src/theme/theme-management.ts index 91d34b4258..2797888239 100644 --- a/packages/devui-theme/src/theme/theme-management.ts +++ b/packages/devui-theme/src/theme/theme-management.ts @@ -16,15 +16,15 @@ import { EventBus } from './utils'; * */ export function ThemeServiceInit( - themes?: { [themeName: string]: Theme; }, + themes?: { [themeName: string]: Theme }, defaultThemeName?: string, extraData?: { [themeName: string]: { - appendClasses?: Array + appendClasses?: Array; cssVariables?: { - [cssVarName: string]: string - } - } + [cssVarName: string]: string; + }; + }; }, ieSupport = false, // TODO:css-var-ponyflll 仍有一些问题待定位 allowDynamicTheme = false @@ -54,7 +54,7 @@ export function ThemeServiceInit( return themeService; } -export function ThemeServiceFollowSystemOn(themeConfig?: { lightThemeName: string; darkThemeName: string; }): Subscription { +export function ThemeServiceFollowSystemOn(themeConfig?: { lightThemeName: string; darkThemeName: string }): Subscription { if (typeof window === 'undefined') { return null; } diff --git a/packages/devui-theme/src/theme/theme-service.ts b/packages/devui-theme/src/theme/theme-service.ts index 8fcec9c922..28fd31d7a1 100644 --- a/packages/devui-theme/src/theme/theme-service.ts +++ b/packages/devui-theme/src/theme/theme-service.ts @@ -16,10 +16,10 @@ export class ThemeService { extraData: { [themeId: string]: { cssVariables?: { - [varname: string]: string - } - appendClasses?: Array - } + [varname: string]: string; + }; + appendClasses?: Array; + }; }; private _appendedClasses: Array; set appendClasses(classes: Array) { diff --git a/packages/devui-theme/src/theme/theme.ts b/packages/devui-theme/src/theme/theme.ts index 977192b188..753dbe9cb8 100644 --- a/packages/devui-theme/src/theme/theme.ts +++ b/packages/devui-theme/src/theme/theme.ts @@ -5,31 +5,31 @@ export class Theme { name: string; cnName?: string; data: { - [cssVarName: string]: string + [cssVarName: string]: string; }; extends?: ThemeId; isDark?: boolean; isPreview?: boolean; isExtendable?: boolean; extra?: { - appendClass?: Array + appendClass?: Array; cssVariables?: { - [cssVarName: string]: string - } - [prop: string]: any + [cssVarName: string]: string; + }; + [prop: string]: any; } | any; constructor(theme: { - id: ThemeId - name: string - cnName?: string + id: ThemeId; + name: string; + cnName?: string; data: { - [cssVarName: string]: string - } - extends?: ThemeId - isDark?: boolean - isPreview?: boolean - isExtendable?: boolean + [cssVarName: string]: string; + }; + extends?: ThemeId; + isDark?: boolean; + isPreview?: boolean; + isExtendable?: boolean; }) { this.id = theme.id; this.name = theme.name; diff --git a/packages/devui-theme/src/theme/utils/interface.ts b/packages/devui-theme/src/theme/utils/interface.ts index f10233e9bd..0c14534949 100644 --- a/packages/devui-theme/src/theme/utils/interface.ts +++ b/packages/devui-theme/src/theme/utils/interface.ts @@ -1,15 +1,15 @@ export interface IStorageService { - tryGetLocalStorage(key: string): any - trySetLocalStorage(key: string, value: any): void + tryGetLocalStorage(key: string): any; + trySetLocalStorage(key: string, value: any): void; } export interface IContextService { - getDataFromNameSpace(nameSpace: string): any - setDataFromNameSpace(nameSpace: string, value: any): any + getDataFromNameSpace(nameSpace: string): any; + setDataFromNameSpace(nameSpace: string, value: any): any; } export interface IEventBus { - add(eventName: string, callbacks: Function): void - remove(eventName: string, callbacks: Function): void - trigger(eventName: string, data: any): void + add(eventName: string, callbacks: Function): void; + remove(eventName: string, callbacks: Function): void; + trigger(eventName: string, data: any): void; } diff --git a/packages/devui-theme/vite.config.ts b/packages/devui-theme/vite.config.ts index d89419e5fb..04db98f840 100644 --- a/packages/devui-theme/vite.config.ts +++ b/packages/devui-theme/vite.config.ts @@ -1,5 +1,5 @@ -import { defineConfig } from 'vite' -import { resolve } from 'path' +import { defineConfig } from 'vite'; +import { resolve } from 'path'; // https://vitejs.dev/config/ export default defineConfig({ @@ -21,4 +21,4 @@ export default defineConfig({ } } } -}) +}); diff --git a/packages/devui-vue/__mocks__/file-mock.ts b/packages/devui-vue/__mocks__/file-mock.ts index 7c645e42fb..ff8b4c5632 100644 --- a/packages/devui-vue/__mocks__/file-mock.ts +++ b/packages/devui-vue/__mocks__/file-mock.ts @@ -1 +1 @@ -export default {}; \ No newline at end of file +export default {}; diff --git a/packages/devui-vue/__mocks__/style-mock.ts b/packages/devui-vue/__mocks__/style-mock.ts index 7c645e42fb..ff8b4c5632 100644 --- a/packages/devui-vue/__mocks__/style-mock.ts +++ b/packages/devui-vue/__mocks__/style-mock.ts @@ -1 +1 @@ -export default {}; \ No newline at end of file +export default {}; diff --git a/packages/devui-vue/dc.config.ts b/packages/devui-vue/dc.config.ts index 6b5ac6d109..51128eca24 100644 --- a/packages/devui-vue/dc.config.ts +++ b/packages/devui-vue/dc.config.ts @@ -7,4 +7,4 @@ export default defineCliConfig({ libEntryRootDir: './devui', libPrefix: 'D', libStyleFileSuffix: '.scss' -}) +}); diff --git a/packages/devui-vue/devui-cli/commands/build-nuxt-auto-import.js b/packages/devui-vue/devui-cli/commands/build-nuxt-auto-import.js index 99a4b27cca..113c4b90fc 100644 --- a/packages/devui-vue/devui-cli/commands/build-nuxt-auto-import.js +++ b/packages/devui-vue/devui-cli/commands/build-nuxt-auto-import.js @@ -1,8 +1,8 @@ -const path = require('path') -const fsExtra = require('fs-extra') +const path = require('path'); +const fsExtra = require('fs-extra'); -const outputDir = path.resolve(__dirname, '../../build') -const outputNuxtDir = path.resolve(__dirname, '../../build/nuxt') +const outputDir = path.resolve(__dirname, '../../build'); +const outputNuxtDir = path.resolve(__dirname, '../../build/nuxt'); exports.createNuxtPlugin = () => { const fileStr = `import { join } from 'pathe' @@ -17,23 +17,23 @@ exports.createNuxtPlugin = () => { }) } } - })` + })`; - fsExtra.outputFile(path.resolve(outputNuxtDir, `index.js`), fileStr, 'utf-8') -} + fsExtra.outputFile(path.resolve(outputNuxtDir, `index.js`), fileStr, 'utf-8'); +}; exports.createAutoImportedComponent = (dirName) => { const importStyle = fsExtra.pathExistsSync(path.resolve(outputDir, `${dirName}/style.css`)) ? `import '../../${dirName}/style.css' \n` - : `` + : ``; - const comps = require(path.resolve(outputDir, `${dirName}/index.es.js`)) + const comps = require(path.resolve(outputDir, `${dirName}/index.es.js`)); Object.keys(comps).forEach((compName) => { if (compName !== 'default' && compName.indexOf('Directive') === -1) { - const fileStr = `${importStyle}\nexport { ${compName} as default } from '../../${dirName}/index.es.js'` + const fileStr = `${importStyle}\nexport { ${compName} as default } from '../../${dirName}/index.es.js'`; - fsExtra.outputFile(path.resolve(outputNuxtDir, `components/${compName}.js`), fileStr, 'utf-8') + fsExtra.outputFile(path.resolve(outputNuxtDir, `components/${compName}.js`), fileStr, 'utf-8'); } - }) -} + }); +}; diff --git a/packages/devui-vue/devui-cli/commands/create.js b/packages/devui-vue/devui-cli/commands/create.js index 15b2e4f501..a1be5168cf 100644 --- a/packages/devui-vue/devui-cli/commands/create.js +++ b/packages/devui-vue/devui-cli/commands/create.js @@ -1,12 +1,12 @@ -const logger = require('../shared/logger') +const logger = require('../shared/logger'); const { bigCamelCase, resolveDirFilesInfo, parseExportByFileInfo, parseComponentInfo -} = require('../shared/utils') -const fs = require('fs-extra') -const { resolve } = require('path') +} = require('../shared/utils'); +const fs = require('fs-extra'); +const { resolve } = require('path'); const { DEVUI_DIR, TESTS_DIR_NAME, @@ -23,11 +23,11 @@ const { VITEPRESS_SIDEBAR_FILE_NAME, VITEPRESS_SIDEBAR_FILE_EN, VITEPRESS_SIDEBAR_FILE_NAME_EN -} = require('../shared/constant') -const { isEmpty, kebabCase } = require('lodash') -const inquirer = require('inquirer') -const { selectCreateType } = require('../inquirers/create') -const { selectCategory, selectParts, typeName, typeTitle } = require('../inquirers/component') +} = require('../shared/constant'); +const { isEmpty, kebabCase } = require('lodash'); +const inquirer = require('inquirer'); +const { selectCreateType } = require('../inquirers/create'); +const { selectCategory, selectParts, typeName, typeTitle } = require('../inquirers/component'); const { createComponentTemplate, createStyleTemplate, @@ -37,70 +37,70 @@ const { createIndexTemplate, createTestsTemplate, createDocumentTemplate -} = require('../templates/component') -const { createVueDevuiTemplate } = require('../templates/vue-devui') -const ora = require('ora') -const { createVitepressSidebarTemplates } = require('../templates/vitepress-sidebar') +} = require('../templates/component'); +const { createVueDevuiTemplate } = require('../templates/vue-devui'); +const ora = require('ora'); +const { createVitepressSidebarTemplates } = require('../templates/vitepress-sidebar'); exports.validateCreateType = (type) => { - const re = new RegExp('^(' + CREATE_SUPPORT_TYPES.map((t) => `(${t})`).join('|') + ')$') - const flag = re.test(type) + const re = new RegExp('^(' + CREATE_SUPPORT_TYPES.map((t) => `(${t})`).join('|') + ')$'); + const flag = re.test(type); - !flag && logger.error(`类型错误,可选类型为:${CREATE_SUPPORT_TYPES.join(', ')}`) + !flag && logger.error(`类型错误,可选类型为:${CREATE_SUPPORT_TYPES.join(', ')}`); - return flag ? type : null -} + return flag ? type : null; +}; // TODO: 待优化代码结构 exports.create = async (cwd) => { - let { type } = cwd + let { type } = cwd; if (isEmpty(type)) { - const result = await inquirer.prompt([selectCreateType()]) - type = result.type + const result = await inquirer.prompt([selectCreateType()]); + type = result.type; } if (CREATE_UNFINISHED_TYPES.includes(type)) { - logger.info('抱歉,该功能暂未完成!') - process.exit(0) + logger.info('抱歉,该功能暂未完成!'); + process.exit(0); } - let params = {} + let params = {}; try { switch (type) { - case CREATE_SUPPORT_TYPE_MAP.component: - params = await inquirer.prompt([typeName(), typeTitle(), selectCategory(), selectParts()]) - params.hasComponent = params.parts.includes('component') - params.hasDirective = params.parts.includes('directive') - params.hasService = params.parts.includes('service') - - await createComponent(params, cwd) - break - case CREATE_SUPPORT_TYPE_MAP['vue-devui']: - // 创建 devui/vue-devui.ts - await createVueDevui(params, cwd) - // 创建 docs/.vitepress/config/sidebar.ts enSidebar.ts - await createVitepressSidebar() - break - default: - break + case CREATE_SUPPORT_TYPE_MAP.component: + params = await inquirer.prompt([typeName(), typeTitle(), selectCategory(), selectParts()]); + params.hasComponent = params.parts.includes('component'); + params.hasDirective = params.parts.includes('directive'); + params.hasService = params.parts.includes('service'); + + await createComponent(params, cwd); + break; + case CREATE_SUPPORT_TYPE_MAP['vue-devui']: + // 创建 devui/vue-devui.ts + await createVueDevui(params, cwd); + // 创建 docs/.vitepress/config/sidebar.ts enSidebar.ts + await createVitepressSidebar(); + break; + default: + break; } } catch (e) { - logger.error(e.toString()) - process.exit(1) + logger.error(e.toString()); + process.exit(1); } -} +}; async function createComponent(params = {}) { - let { name, hasComponent, hasDirective, hasService } = params + const { name, hasComponent, hasDirective, hasService } = params; - const componentName = kebabCase(name) - const styleName = kebabCase(name) - const typesName = kebabCase(name) + '-types' - const directiveName = kebabCase(name) + '-directive' - const serviceName = kebabCase(name) + '-service' - const testName = kebabCase(name) + '.spec' + const componentName = kebabCase(name); + const styleName = kebabCase(name); + const typesName = kebabCase(name) + '-types'; + const directiveName = kebabCase(name) + '-directive'; + const serviceName = kebabCase(name) + '-service'; + const testName = kebabCase(name) + '.spec'; const _params = { ...params, @@ -110,101 +110,101 @@ async function createComponent(params = {}) { serviceName, styleName, testName - } - - const componentTemplate = createComponentTemplate(_params) - const styleTemplate = createStyleTemplate(_params) - const typesTemplate = createTypesTemplate(_params) - const directiveTemplate = createDirectiveTemplate(_params) - const serviceTemplate = createServiceTemplate(_params) - const indexTemplate = createIndexTemplate(_params) + }; + + const componentTemplate = createComponentTemplate(_params); + const styleTemplate = createStyleTemplate(_params); + const typesTemplate = createTypesTemplate(_params); + const directiveTemplate = createDirectiveTemplate(_params); + const serviceTemplate = createServiceTemplate(_params); + const indexTemplate = createIndexTemplate(_params); // 增加测试模板 - const testsTemplate = createTestsTemplate(_params) + const testsTemplate = createTestsTemplate(_params); // 增加文档模板 - const docTemplate = createDocumentTemplate(_params) + const docTemplate = createDocumentTemplate(_params); - const componentDir = resolve(DEVUI_DIR, componentName) - const srcDir = resolve(componentDir, 'src') - const testsDir = resolve(DEVUI_DIR, componentName, TESTS_DIR_NAME) - const docsDir = resolve(SITES_COMPONENTS_DIR, componentName) + const componentDir = resolve(DEVUI_DIR, componentName); + const srcDir = resolve(componentDir, 'src'); + const testsDir = resolve(DEVUI_DIR, componentName, TESTS_DIR_NAME); + const docsDir = resolve(SITES_COMPONENTS_DIR, componentName); if (fs.pathExistsSync(componentDir)) { - logger.error(`${bigCamelCase(componentName)} 组件目录已存在!`) - process.exit(1) + logger.error(`${bigCamelCase(componentName)} 组件目录已存在!`); + process.exit(1); } - let spinner = ora(`创建组件 ${bigCamelCase(componentName)} 开始...`).start() + const spinner = ora(`创建组件 ${bigCamelCase(componentName)} 开始...`).start(); try { - await Promise.all([fs.mkdirs(componentDir), fs.mkdirs(srcDir), fs.mkdirs(testsDir)]) + await Promise.all([fs.mkdirs(componentDir), fs.mkdirs(srcDir), fs.mkdirs(testsDir)]); const writeFiles = [ fs.writeFile(resolve(componentDir, INDEX_FILE_NAME), indexTemplate), fs.writeFile(resolve(testsDir, `${testName}.ts`), testsTemplate) - ] + ]; if (!fs.existsSync(docsDir)) { - fs.mkdirSync(docsDir) - writeFiles.push(fs.writeFile(resolve(docsDir, DOCS_FILE_NAME), docTemplate)) + fs.mkdirSync(docsDir); + writeFiles.push(fs.writeFile(resolve(docsDir, DOCS_FILE_NAME), docTemplate)); } else { logger.warning( `\n${bigCamelCase(componentName)} 组件文档已存在:${resolve(docsDir, DOCS_FILE_NAME)}` - ) + ); } if (hasComponent || hasService) { - writeFiles.push(fs.writeFile(resolve(srcDir, `${typesName}.ts`), typesTemplate)) + writeFiles.push(fs.writeFile(resolve(srcDir, `${typesName}.ts`), typesTemplate)); } if (hasComponent) { writeFiles.push( fs.writeFile(resolve(srcDir, `${componentName}.tsx`), componentTemplate), fs.writeFile(resolve(srcDir, `${styleName}.scss`), styleTemplate) - ) + ); } if (hasDirective) { - writeFiles.push(fs.writeFile(resolve(srcDir, `${directiveName}.ts`), directiveTemplate)) + writeFiles.push(fs.writeFile(resolve(srcDir, `${directiveName}.ts`), directiveTemplate)); } if (hasService) { - writeFiles.push(fs.writeFile(resolve(srcDir, `${serviceName}.ts`), serviceTemplate)) + writeFiles.push(fs.writeFile(resolve(srcDir, `${serviceName}.ts`), serviceTemplate)); } - await Promise.all(writeFiles) + await Promise.all(writeFiles); - spinner.succeed(`创建组件 ${bigCamelCase(componentName)} 成功!`) - logger.info(`组件目录:${componentDir}`) + spinner.succeed(`创建组件 ${bigCamelCase(componentName)} 成功!`); + logger.info(`组件目录:${componentDir}`); } catch (e) { - spinner.fail(e.toString()) - process.exit(1) + spinner.fail(e.toString()); + process.exit(1); } } async function createVueDevui(params, { ignoreParseError }) { - const fileInfo = resolveDirFilesInfo(DEVUI_DIR, VUE_DEVUI_IGNORE_DIRS) - const exportModules = [] + const fileInfo = resolveDirFilesInfo(DEVUI_DIR, VUE_DEVUI_IGNORE_DIRS); + const exportModules = []; fileInfo.forEach((f) => { - const em = parseExportByFileInfo(f, ignoreParseError) + const em = parseExportByFileInfo(f, ignoreParseError); - if (isEmpty(em)) return + if (isEmpty(em)) {return;} - exportModules.push(em) - }) + exportModules.push(em); + }); - const template = createVueDevuiTemplate(exportModules) + const template = createVueDevuiTemplate(exportModules); - let spinner = ora(`创建 ${VUE_DEVUI_FILE_NAME} 文件开始...`).start() + const spinner = ora(`创建 ${VUE_DEVUI_FILE_NAME} 文件开始...`).start(); try { - await fs.writeFile(VUE_DEVUI_FILE, template, { encoding: 'utf-8' }) + await fs.writeFile(VUE_DEVUI_FILE, template, { encoding: 'utf-8' }); - spinner.succeed(`创建 ${VUE_DEVUI_FILE_NAME} 文件成功!`) - logger.info(`文件地址:${VUE_DEVUI_FILE}`) + spinner.succeed(`创建 ${VUE_DEVUI_FILE_NAME} 文件成功!`); + logger.info(`文件地址:${VUE_DEVUI_FILE}`); } catch (e) { - spinner.fail(e.toString()) - process.exit(1) + spinner.fail(e.toString()); + process.exit(1); } } @@ -218,30 +218,30 @@ async function createVitepressSidebar() { fileName: VITEPRESS_SIDEBAR_FILE_NAME_EN, location: VITEPRESS_SIDEBAR_FILE_EN } - } - const fileInfo = resolveDirFilesInfo(DEVUI_DIR, VUE_DEVUI_IGNORE_DIRS) - const componentsInfo = [] + }; + const fileInfo = resolveDirFilesInfo(DEVUI_DIR, VUE_DEVUI_IGNORE_DIRS); + const componentsInfo = []; fileInfo.forEach((f) => { - const info = parseComponentInfo(f.dirname) + const info = parseComponentInfo(f.dirname); - if (isEmpty(info)) return + if (isEmpty(info)) {return;} - componentsInfo.push(info) - }) + componentsInfo.push(info); + }); - const templates = createVitepressSidebarTemplates(componentsInfo) + const templates = createVitepressSidebarTemplates(componentsInfo); templates.forEach((template) => { - const { fileName, location } = generateFileConfig[template.lang] - const spinner = ora(`创建 ${fileName} 文件开始...`).start() + const { fileName, location } = generateFileConfig[template.lang]; + const spinner = ora(`创建 ${fileName} 文件开始...`).start(); try { - fs.writeFile(location, template.content, { encoding: 'utf-8' }) + fs.writeFile(location, template.content, { encoding: 'utf-8' }); - spinner.succeed(`创建 ${fileName} 文件成功!`) - logger.info(`文件地址:${location}`) + spinner.succeed(`创建 ${fileName} 文件成功!`); + logger.info(`文件地址:${location}`); } catch (e) { - spinner.fail(e.toString()) - process.exit(1) + spinner.fail(e.toString()); + process.exit(1); } - }) + }); } diff --git a/packages/devui-vue/devui-cli/commands/generate-dts.js b/packages/devui-vue/devui-cli/commands/generate-dts.js index 96e820e089..3269ca72d4 100644 --- a/packages/devui-vue/devui-cli/commands/generate-dts.js +++ b/packages/devui-vue/devui-cli/commands/generate-dts.js @@ -1,10 +1,10 @@ -const path = require('path') -const fs = require('fs') -const fse = require('fs-extra') -const logger = require('../shared/logger') +const path = require('path'); +const fs = require('fs'); +const fse = require('fs-extra'); +const logger = require('../shared/logger'); -const entryDir = path.resolve(__dirname, '../../devui') -const outputDir = path.resolve(__dirname, '../../build') +const entryDir = path.resolve(__dirname, '../../devui'); +const outputDir = path.resolve(__dirname, '../../build'); function generateIndexDts(buildDir) { const fileStr = `import { App } from 'vue'; @@ -13,26 +13,26 @@ function generateIndexDts(buildDir) { install: typeof install; version: string; }; - export default _default;` - fse.outputFileSync(path.resolve(buildDir, 'index.d.ts'), fileStr, 'utf8') + export default _default;`; + fse.outputFileSync(path.resolve(buildDir, 'index.d.ts'), fileStr, 'utf8'); } exports.generateDts = () => { - generateIndexDts(outputDir) + generateIndexDts(outputDir); const components = fs.readdirSync(entryDir).filter(name => { - const componentDir = path.resolve(entryDir, name) - const isDir = fs.lstatSync(componentDir).isDirectory() - return isDir && fs.readdirSync(componentDir).includes('index.ts') - }) - const srcDts = path.resolve(outputDir, 'index.d.ts') + const componentDir = path.resolve(entryDir, name); + const isDir = fs.lstatSync(componentDir).isDirectory(); + return isDir && fs.readdirSync(componentDir).includes('index.ts'); + }); + const srcDts = path.resolve(outputDir, 'index.d.ts'); for(const name of components) { - const destDts = path.resolve(outputDir, `${name}/index.d.ts`) + const destDts = path.resolve(outputDir, `${name}/index.d.ts`); fs.copyFile(srcDts, destDts, (err) => { if (err) { - logger.error(`拷贝组件${name}的ts类型文件失败!`) + logger.error(`拷贝组件${name}的ts类型文件失败!`); } - }) + }); } -} \ No newline at end of file +}; diff --git a/packages/devui-vue/devui-cli/commands/generate-theme.js b/packages/devui-vue/devui-cli/commands/generate-theme.js index 3acfa026b8..ab36696daa 100644 --- a/packages/devui-vue/devui-cli/commands/generate-theme.js +++ b/packages/devui-vue/devui-cli/commands/generate-theme.js @@ -1,16 +1,16 @@ -require('esbuild-register') -const path = require('path') -const fs = require('fs-extra') -const theme = require('../../devui/theme/themes/light.ts').default +require('esbuild-register'); +const path = require('path'); +const fs = require('fs-extra'); +const theme = require('../../devui/theme/themes/light.ts').default; const fileStr = Object.entries(theme) -.map(([key, value]) => `$${key}: var(--${key}, ${value})`) -.join(';\n') + .map(([key, value]) => `$${key}: var(--${key}, ${value})`) + .join(';\n'); exports.generateTheme = async () => { await fs.outputFile( path.resolve(__dirname, '../../devui/theme/theme.scss'), fileStr, 'utf-8' - ) -} \ No newline at end of file + ); +}; diff --git a/packages/devui-vue/devui-cli/index.js b/packages/devui-vue/devui-cli/index.js index 2e714064bb..6de3b5aba9 100755 --- a/packages/devui-vue/devui-cli/index.js +++ b/packages/devui-vue/devui-cli/index.js @@ -1,12 +1,12 @@ #!/usr/bin/env node -const { Command } = require('commander') -const { create, validateCreateType } = require('./commands/create') -const { build } = require('./commands/build') -const { generateTheme } = require('./commands/generate-theme') -const { generateDts } = require('./commands/generate-dts') -const { VERSION, CREATE_SUPPORT_TYPES } = require('./shared/constant') +const { Command } = require('commander'); +const { create, validateCreateType } = require('./commands/create'); +const { build } = require('./commands/build'); +const { generateTheme } = require('./commands/generate-theme'); +const { generateDts } = require('./commands/generate-dts'); +const { VERSION, CREATE_SUPPORT_TYPES } = require('./shared/constant'); -const program = new Command() +const program = new Command(); program .command('create') @@ -14,23 +14,23 @@ program .option('-t --type ', `创建类型,可选值:${CREATE_SUPPORT_TYPES.join(', ')}`, validateCreateType) .option('--ignore-parse-error', '忽略解析错误', false) .option('--cover', '覆盖原文件', false) - .action(create) + .action(create); program .command('build') .description('打包组件库') .hook('postAction', generateTheme) .hook('postAction', generateDts) - .action(build) + .action(build); program .command('generate:theme') .description('生成主题变量文件') - .action(generateTheme) + .action(generateTheme); program .command('generate:dts') .description('生成ts类型文件') - .action(generateDts) + .action(generateDts); -program.parse().version(VERSION) +program.parse().version(VERSION); diff --git a/packages/devui-vue/devui-cli/inquirers/component.js b/packages/devui-vue/devui-cli/inquirers/component.js index 355a2b0947..672a7af8d7 100644 --- a/packages/devui-vue/devui-cli/inquirers/component.js +++ b/packages/devui-vue/devui-cli/inquirers/component.js @@ -1,4 +1,4 @@ -const { COMPONENT_PARTS_MAP, VITEPRESS_SIDEBAR_CATEGORY } = require('../shared/constant') +const { COMPONENT_PARTS_MAP, VITEPRESS_SIDEBAR_CATEGORY } = require('../shared/constant'); exports.typeName = () => ({ name: 'name', @@ -6,11 +6,11 @@ exports.typeName = () => ({ message: '(必填)请输入组件 name ,将用作目录及文件名:', validate: (value) => { if (value.trim() === '') { - return '组件 name 是必填项!' + return '组件 name 是必填项!'; } - return true + return true; } -}) +}); exports.typeTitle = () => ({ name: 'title', @@ -18,11 +18,11 @@ exports.typeTitle = () => ({ message: '(必填)请输入组件中文名称,将用作文档列表显示:', validate: (value) => { if (value.trim() === '') { - return '组件名称是必填项!' + return '组件名称是必填项!'; } - return true + return true; } -}) +}); exports.selectCategory = () => ({ name: 'category', @@ -30,13 +30,13 @@ exports.selectCategory = () => ({ message: '(必填)请选择组件分类,将用作文档列表分类:', choices: VITEPRESS_SIDEBAR_CATEGORY, default: 0 -}) +}); exports.typeAliasName = () => ({ name: 'alias', type: 'input', message: '(选填)请输入组件 name 别名,将用作组件别名被导出:' -}) +}); exports.selectParts = () => ({ name: 'parts', @@ -46,8 +46,8 @@ exports.selectParts = () => ({ default: [], validate: (value) => { if (value.length === 0) { - return '部件必须包含至少一项' + return '部件必须包含至少一项'; } - return true + return true; } -}) +}); diff --git a/packages/devui-vue/devui-cli/inquirers/create.js b/packages/devui-vue/devui-cli/inquirers/create.js index 5bc07766b5..1c0cad92df 100644 --- a/packages/devui-vue/devui-cli/inquirers/create.js +++ b/packages/devui-vue/devui-cli/inquirers/create.js @@ -1,4 +1,4 @@ -const { CREATE_SUPPORT_TYPES } = require('../shared/constant') +const { CREATE_SUPPORT_TYPES } = require('../shared/constant'); exports.selectCreateType = () => ({ name: 'type', @@ -6,4 +6,4 @@ exports.selectCreateType = () => ({ message: '(必填)请选择创建类型:', choices: CREATE_SUPPORT_TYPES, default: 0 -}) +}); diff --git a/packages/devui-vue/devui-cli/shared/constant.js b/packages/devui-vue/devui-cli/shared/constant.js index 9a27665b7c..853f8f6e7f 100644 --- a/packages/devui-vue/devui-cli/shared/constant.js +++ b/packages/devui-vue/devui-cli/shared/constant.js @@ -1,34 +1,34 @@ -const { resolve } = require('path') -const { version } = require('../../package.json') +const { resolve } = require('path'); +const { version } = require('../../package.json'); -exports.VERSION = version -exports.CWD = process.cwd() -exports.DEVUI_DIR = resolve(this.CWD, 'devui') -exports.DEVUI_NAMESPACE = 'd' -exports.CSS_CLASS_PREFIX = 'devui' -exports.TESTS_DIR_NAME = '__tests__' -exports.INDEX_FILE_NAME = 'index.ts' -exports.DOCS_FILE_NAME = 'index.md' -exports.VUE_DEVUI_IGNORE_DIRS = ['shared', 'style'] -exports.VUE_DEVUI_FILE_NAME = 'vue-devui.ts' -exports.VUE_DEVUI_FILE = resolve(this.DEVUI_DIR, this.VUE_DEVUI_FILE_NAME) -exports.SITES_DIR = resolve(this.CWD, 'docs') -exports.SITES_COMPONENTS_DIR_NAME = 'components' -exports.SITES_COMPONENTS_DIR_NAME_EN = 'en-US/components' -exports.SITES_COMPONENTS_DIR = resolve(this.SITES_DIR, this.SITES_COMPONENTS_DIR_NAME) -exports.VITEPRESS_DIR = resolve(this.SITES_DIR, '.vitepress') -exports.VITEPRESS_SIDEBAR_FILE_NAME = 'sidebar.ts' +exports.VERSION = version; +exports.CWD = process.cwd(); +exports.DEVUI_DIR = resolve(this.CWD, 'devui'); +exports.DEVUI_NAMESPACE = 'd'; +exports.CSS_CLASS_PREFIX = 'devui'; +exports.TESTS_DIR_NAME = '__tests__'; +exports.INDEX_FILE_NAME = 'index.ts'; +exports.DOCS_FILE_NAME = 'index.md'; +exports.VUE_DEVUI_IGNORE_DIRS = ['shared', 'style']; +exports.VUE_DEVUI_FILE_NAME = 'vue-devui.ts'; +exports.VUE_DEVUI_FILE = resolve(this.DEVUI_DIR, this.VUE_DEVUI_FILE_NAME); +exports.SITES_DIR = resolve(this.CWD, 'docs'); +exports.SITES_COMPONENTS_DIR_NAME = 'components'; +exports.SITES_COMPONENTS_DIR_NAME_EN = 'en-US/components'; +exports.SITES_COMPONENTS_DIR = resolve(this.SITES_DIR, this.SITES_COMPONENTS_DIR_NAME); +exports.VITEPRESS_DIR = resolve(this.SITES_DIR, '.vitepress'); +exports.VITEPRESS_SIDEBAR_FILE_NAME = 'sidebar.ts'; exports.VITEPRESS_SIDEBAR_FILE = resolve( this.VITEPRESS_DIR, `config/${this.VITEPRESS_SIDEBAR_FILE_NAME}` -) -exports.VITEPRESS_SIDEBAR_FILE_NAME_EN = 'enSidebar.ts' +); +exports.VITEPRESS_SIDEBAR_FILE_NAME_EN = 'enSidebar.ts'; exports.VITEPRESS_SIDEBAR_FILE_EN = resolve( this.VITEPRESS_DIR, `config/${this.VITEPRESS_SIDEBAR_FILE_NAME_EN}` -) +); // 这里的分类顺序将会影响最终生成的页面侧边栏顺序 -exports.VITEPRESS_SIDEBAR_CATEGORY = ['通用', '导航', '反馈', '数据录入', '数据展示', '布局'] +exports.VITEPRESS_SIDEBAR_CATEGORY = ['通用', '导航', '反馈', '数据录入', '数据展示', '布局']; exports.VITEPRESS_SIDEBAR_CATEGORY_EN = [ 'General', 'Navigation', @@ -36,7 +36,7 @@ exports.VITEPRESS_SIDEBAR_CATEGORY_EN = [ 'Data Entry', 'Data Display', 'Layout' -] +]; exports.VITEPRESS_SIDEBAR_CATEGORY_ZH_TO_EN = { 通用: 'General', 导航: 'Navigation', @@ -44,7 +44,7 @@ exports.VITEPRESS_SIDEBAR_CATEGORY_ZH_TO_EN = { 数据录入: 'Data Entry', 数据展示: 'Data Display', 布局: 'Layout' -} +}; exports.COMPONENT_PARTS_MAP = [ { name: 'component(组件)', @@ -58,12 +58,12 @@ exports.COMPONENT_PARTS_MAP = [ name: 'service(服务)', value: 'service' } -] +]; exports.CREATE_SUPPORT_TYPE_MAP = Object.freeze({ component: 'component', 'vue-devui': 'vue-devui', 'theme-variable': 'theme-variable' -}) -exports.CREATE_SUPPORT_TYPES = Object.keys(this.CREATE_SUPPORT_TYPE_MAP) -exports.CREATE_UNFINISHED_TYPES = [] +}); +exports.CREATE_SUPPORT_TYPES = Object.keys(this.CREATE_SUPPORT_TYPE_MAP); +exports.CREATE_UNFINISHED_TYPES = []; diff --git a/packages/devui-vue/devui-cli/shared/logger.js b/packages/devui-vue/devui-cli/shared/logger.js index 4b97da0e33..de68146c86 100644 --- a/packages/devui-vue/devui-cli/shared/logger.js +++ b/packages/devui-vue/devui-cli/shared/logger.js @@ -1,16 +1,16 @@ -const chalk = require('chalk') +const chalk = require('chalk'); module.exports = { info(text) { - console.log(chalk.hex('#00afef')(text)) + console.log(chalk.hex('#00afef')(text)); }, success(text) { - console.log(chalk.hex('#00c48f')(text)) + console.log(chalk.hex('#00c48f')(text)); }, warning(text) { - console.log(chalk.hex('#ff9800')(text)) + console.log(chalk.hex('#ff9800')(text)); }, error(text) { - console.log(chalk.hex('#f44336')(text)) + console.log(chalk.hex('#f44336')(text)); } -} +}; diff --git a/packages/devui-vue/devui-cli/shared/utils.js b/packages/devui-vue/devui-cli/shared/utils.js index 0b1f1c4b8e..de76ecd8d6 100644 --- a/packages/devui-vue/devui-cli/shared/utils.js +++ b/packages/devui-vue/devui-cli/shared/utils.js @@ -1,14 +1,14 @@ -const { camelCase, upperFirst } = require('lodash') -const { INDEX_FILE_NAME, DEVUI_DIR } = require('./constant') -const { resolve } = require('path') -const logger = require('./logger') -const fs = require('fs-extra') -const traverse = require('@babel/traverse').default -const babelParser = require('@babel/parser') +const { camelCase, upperFirst } = require('lodash'); +const { INDEX_FILE_NAME, DEVUI_DIR } = require('./constant'); +const { resolve } = require('path'); +const logger = require('./logger'); +const fs = require('fs-extra'); +const traverse = require('@babel/traverse').default; +const babelParser = require('@babel/parser'); exports.bigCamelCase = (str) => { - return upperFirst(camelCase(str)) -} + return upperFirst(camelCase(str)); +}; exports.resolveDirFilesInfo = (targetDir, ignoreDirs = []) => { return fs @@ -24,101 +24,101 @@ exports.resolveDirFilesInfo = (targetDir, ignoreDirs = []) => { name: this.bigCamelCase(dir), dirname: dir, path: resolve(targetDir, dir, INDEX_FILE_NAME) - })) -} + })); +}; exports.parseExportByFileInfo = (fileInfo, ignoreParseError) => { - const exportModule = {} - const indexContent = fs.readFileSync(fileInfo.path, { encoding: 'utf-8' }) + const exportModule = {}; + const indexContent = fs.readFileSync(fileInfo.path, { encoding: 'utf-8' }); const ast = babelParser.parse(indexContent, { sourceType: 'module', plugins: [ 'typescript' ] - }) + }); - const exportName = [] - let exportDefault = null + const exportName = []; + let exportDefault = null; traverse(ast, { ExportNamedDeclaration({node}) { if (node.specifiers.length) { node.specifiers.forEach(specifier => { - exportName.push(specifier.local.name) - }) + exportName.push(specifier.local.name); + }); } else if (node.declaration) { if (node.declaration.declarations) { node.declaration.declarations.forEach(dec => { - exportName.push(dec.id.name) - }) + exportName.push(dec.id.name); + }); } else if (node.declaration.id) { - exportName.push(node.declaration.id.name) + exportName.push(node.declaration.id.name); } } }, ExportDefaultDeclaration() { - exportDefault = fileInfo.name + 'Install' + exportDefault = fileInfo.name + 'Install'; } - }) + }); if (!exportDefault) { - logger.error(`${fileInfo.path} must have "export default".`) + logger.error(`${fileInfo.path} must have "export default".`); if (ignoreParseError) { - return exportModule + return exportModule; } else { - process.exit(1) + process.exit(1); } } if (!exportName.length) { - logger.error(`${fileInfo.path} must have "export xxx".`) - + logger.error(`${fileInfo.path} must have "export xxx".`); + if (ignoreParseError) { - return exportModule + return exportModule; } else { - process.exit(1) + process.exit(1); } } - exportModule.default = exportDefault - exportModule.parts = exportName - exportModule.fileInfo = fileInfo + exportModule.default = exportDefault; + exportModule.parts = exportName; + exportModule.fileInfo = fileInfo; - return exportModule -} + return exportModule; +}; exports.parseComponentInfo = (name) => { const componentInfo = { name: this.bigCamelCase(name) - } - let hasExportDefault = false - const indexContent = fs.readFileSync(resolve(DEVUI_DIR, name, INDEX_FILE_NAME), { encoding: 'utf-8' }) + }; + let hasExportDefault = false; + const indexContent = fs.readFileSync(resolve(DEVUI_DIR, name, INDEX_FILE_NAME), { encoding: 'utf-8' }); const ast = babelParser.parse(indexContent, { sourceType: 'module', plugins: [ 'typescript' ] - }) + }); traverse(ast, { ExportDefaultDeclaration({node}) { - hasExportDefault = true + hasExportDefault = true; if (node.declaration && node.declaration.properties) { - const properties = node.declaration.properties + const properties = node.declaration.properties; properties.forEach(pro => { if (pro.type === 'ObjectProperty') { - componentInfo[pro.key.name] = pro.value.value + componentInfo[pro.key.name] = pro.value.value; } - }) + }); } } - }) + }); if (!hasExportDefault) { - logger.warning(`${componentInfo.name} must have "export default" and component info.`) + logger.warning(`${componentInfo.name} must have "export default" and component info.`); } - return componentInfo -} + return componentInfo; +}; diff --git a/packages/devui-vue/devui-cli/templates/component.js b/packages/devui-vue/devui-cli/templates/component.js index e9bf2a9ed1..9ae6812305 100644 --- a/packages/devui-vue/devui-cli/templates/component.js +++ b/packages/devui-vue/devui-cli/templates/component.js @@ -1,6 +1,6 @@ -const { DEVUI_NAMESPACE, CSS_CLASS_PREFIX } = require('../shared/constant') -const { camelCase } = require('lodash') -const { bigCamelCase } = require('../shared/utils') +const { DEVUI_NAMESPACE, CSS_CLASS_PREFIX } = require('../shared/constant'); +const { camelCase } = require('lodash'); +const { bigCamelCase } = require('../shared/utils'); // 创建组件模板 exports.createComponentTemplate = ({ styleName, componentName, typesName }) => `\ @@ -20,7 +20,7 @@ export default defineComponent({ } } }) -` +`; // 创建类型声明模板 exports.createTypesTemplate = ({ componentName }) => `\ @@ -35,7 +35,7 @@ export const ${camelCase(componentName)}Props = { export type ${bigCamelCase(componentName)}Props = ExtractPropTypes -` +`; // 创建指令模板 exports.createDirectiveTemplate = () => `\ @@ -49,7 +49,7 @@ export default { beforeUnmount() { }, unmounted() { } } -` +`; // 创建server模板 exports.createServiceTemplate = ({ componentName, typesName, serviceName }) => `\ import { ${bigCamelCase(componentName)}Props } from './${typesName}' @@ -59,14 +59,14 @@ const ${bigCamelCase(serviceName)} = { } export default ${bigCamelCase(serviceName)} -` +`; // 创建scss模板 exports.createStyleTemplate = ({ componentName }) => `\ .${CSS_CLASS_PREFIX}-${componentName} { // } -` +`; // 创建index模板 exports.createIndexTemplate = ({ @@ -79,29 +79,29 @@ exports.createIndexTemplate = ({ directiveName, serviceName }) => { - const importComponentStr = `\nimport ${bigCamelCase(componentName)} from './src/${componentName}'` - const importDirectiveStr = `\nimport ${bigCamelCase(directiveName)} from './src/${directiveName}'` - const importServiceStr = `\nimport ${bigCamelCase(serviceName)} from './src/${serviceName}'` + const importComponentStr = `\nimport ${bigCamelCase(componentName)} from './src/${componentName}'`; + const importDirectiveStr = `\nimport ${bigCamelCase(directiveName)} from './src/${directiveName}'`; + const importServiceStr = `\nimport ${bigCamelCase(serviceName)} from './src/${serviceName}'`; - const installComponentStr = ` app.use(${bigCamelCase(componentName)} as any)` + const installComponentStr = ` app.use(${bigCamelCase(componentName)} as any)`; const installDirectiveStr = `\n app.directive('${bigCamelCase(componentName)}', ${bigCamelCase( directiveName - )})` + )})`; const installServiceStr = `\n app.config.globalProperties.$${camelCase( serviceName - )} = ${bigCamelCase(serviceName)}` + )} = ${bigCamelCase(serviceName)}`; - const getPartStr = (state, str) => (state ? str : '') + const getPartStr = (state, str) => (state ? str : ''); const importStr = getPartStr(hasComponent, importComponentStr) + getPartStr(hasDirective, importDirectiveStr) + - getPartStr(hasService, importServiceStr) + getPartStr(hasService, importServiceStr); const installStr = getPartStr(hasComponent, installComponentStr) + getPartStr(hasDirective, installDirectiveStr) + - getPartStr(hasService, installServiceStr) + getPartStr(hasService, installServiceStr); return `\ import type { App } from 'vue'\ @@ -129,8 +129,8 @@ export default { ${installStr} } } -` -} +`; +}; // 创建测试模板 exports.createTestsTemplate = ({ @@ -143,19 +143,19 @@ exports.createTestsTemplate = ({ }) => `\ import { mount } from '@vue/test-utils'; import { ${[ - hasComponent ? bigCamelCase(componentName) : null, - hasDirective ? bigCamelCase(directiveName) : null, - hasService ? bigCamelCase(serviceName) : null -] - .filter((p) => p !== null) - .join(', ')} } from '../index'; + hasComponent ? bigCamelCase(componentName) : null, + hasDirective ? bigCamelCase(directiveName) : null, + hasService ? bigCamelCase(serviceName) : null + ] + .filter((p) => p !== null) + .join(', ')} } from '../index'; describe('${componentName} test', () => { it('${componentName} init render', async () => { // todo }) }) -` +`; // 创建文档模板 exports.createDocumentTemplate = ({ componentName, title }) => `\ @@ -214,4 +214,4 @@ d-${componentName} 事件 | | | | | | | | | | -` +`; diff --git a/packages/devui-vue/devui-cli/templates/vue-devui.js b/packages/devui-vue/devui-cli/templates/vue-devui.js index c6def01b38..f91de6f989 100644 --- a/packages/devui-vue/devui-cli/templates/vue-devui.js +++ b/packages/devui-vue/devui-cli/templates/vue-devui.js @@ -1,24 +1,24 @@ -const { relative } = require('path') -const { INDEX_FILE_NAME, VERSION, VUE_DEVUI_FILE } = require('../shared/constant') +const { relative } = require('path'); +const { INDEX_FILE_NAME, VERSION, VUE_DEVUI_FILE } = require('../shared/constant'); exports.createVueDevuiTemplate = (exportModules = []) => { - const packages = [] - const imports = [] - const installs = [] + const packages = []; + const imports = []; + const installs = []; exportModules.forEach((m) => { - const { fileInfo } = m + const { fileInfo } = m; const relativePath = relative(VUE_DEVUI_FILE, fileInfo.path) .replace(/\\/g, '/') .replace('..', '.') - .replace('/' + INDEX_FILE_NAME, '') + .replace('/' + INDEX_FILE_NAME, ''); - const importStr = `import ${m.default}, { ${m.parts.join(', ')} } from '${relativePath}'` + const importStr = `import ${m.default}, { ${m.parts.join(', ')} } from '${relativePath}'`; - packages.push(...m.parts) - imports.push(importStr) - installs.push(m.default) - }) + packages.push(...m.parts); + imports.push(importStr); + installs.push(m.default); + }); const template = `\ import type { App } from 'vue' @@ -39,7 +39,7 @@ export default { installs.forEach((p) => app.use(p as any)) } } -` +`; - return template -} + return template; +}; diff --git a/packages/devui-vue/devui/accordion/index.ts b/packages/devui-vue/devui/accordion/index.ts index 0bd6b8014d..c4f094e1b1 100644 --- a/packages/devui-vue/devui/accordion/index.ts +++ b/packages/devui-vue/devui/accordion/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Accordion from './src/accordion' +import type { App } from 'vue'; +import Accordion from './src/accordion'; Accordion.install = function(app: App) { - app.component(Accordion.name, Accordion) -} + app.component(Accordion.name, Accordion); +}; -export { Accordion } +export { Accordion }; export default { title: 'Accordion 手风琴', category: '导航', status: '10%', install(app: App): void { - app.use(Accordion as any) + app.use(Accordion as any); } -} +}; diff --git a/packages/devui-vue/devui/accordion/src/accordion-item-hreflink.tsx b/packages/devui-vue/devui/accordion/src/accordion-item-hreflink.tsx index 9ac9501716..355d9b3de6 100644 --- a/packages/devui-vue/devui/accordion/src/accordion-item-hreflink.tsx +++ b/packages/devui-vue/devui/accordion/src/accordion-item-hreflink.tsx @@ -1,8 +1,8 @@ -import { defineComponent, toRefs, computed, inject } from 'vue' -import { accordionProps } from './accordion-types' -import { AccordionItemClickEvent, AccordionMenuItem, AccordionLinkableItem } from './accordion.type' -import DAccordionItem from './accordion-item' -import { getRootSlots } from './utils' +import { defineComponent, toRefs, computed, inject } from 'vue'; +import { accordionProps } from './accordion-types'; +import { AccordionItemClickEvent, AccordionMenuItem, AccordionLinkableItem } from './accordion.type'; +import DAccordionItem from './accordion-item'; +import { getRootSlots } from './utils'; export default defineComponent({ name: 'DAccordionItemHreflink', @@ -33,18 +33,18 @@ export default defineComponent({ // activeKey, disabledKey, itemTemplate - } = toRefs(props) + } = toRefs(props); - const rootSlots = getRootSlots() - const accordionCtx = inject('accordionContext') as any + const rootSlots = getRootSlots(); + const accordionCtx = inject('accordionContext') as any; const title = computed(() => { - return item.value && item.value[titleKey.value] - }) + return item.value && item.value[titleKey.value]; + }); const link = computed(() => { - return item.value && item.value[linkKey.value] - }) + return item.value && item.value[linkKey.value]; + }); // const active = computed(() => { // return item.value && item.value[activeKey.value] @@ -55,21 +55,21 @@ export default defineComponent({ // }) const target = computed(() => { - return item.value && (item.value[linkTargetKey.value] || linkDefaultTarget.value) - }) + return item.value && (item.value[linkTargetKey.value] || linkDefaultTarget.value); + }); const disabled = computed(() => { - return item.value && item.value[disabledKey.value] - }) + return item.value && item.value[disabledKey.value]; + }); - const parentValue = parent.value - const deepValue = deepth.value + const parentValue = parent.value; + const deepValue = deepth.value; const linkItemClickFn = (itemEvent: AccordionItemClickEvent) => { if (item.value && !disabled.value) { - accordionCtx.itemClickFn(itemEvent) + accordionCtx.itemClickFn(itemEvent); } - } + }; const renderContent = () => { return ( @@ -87,8 +87,8 @@ export default defineComponent({ item: item.value })} - ) - } + ); + }; return () => { return ( @@ -121,7 +121,7 @@ export default defineComponent({ )} - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/accordion/src/accordion-item-routerlink.tsx b/packages/devui-vue/devui/accordion/src/accordion-item-routerlink.tsx index 44e55522bb..6f9577d72f 100644 --- a/packages/devui-vue/devui/accordion/src/accordion-item-routerlink.tsx +++ b/packages/devui-vue/devui/accordion/src/accordion-item-routerlink.tsx @@ -1,9 +1,9 @@ -import { defineComponent, toRefs, computed, inject } from 'vue' -import { useRoute } from 'vue-router' -import { accordionProps } from './accordion-types' -import { AccordionItemClickEvent, AccordionMenuItem, AccordionLinkableItem } from './accordion.type' -import DAccordionItem from './accordion-item' -import { getRootSlots } from './utils' +import { defineComponent, toRefs, computed, inject } from 'vue'; +import { useRoute } from 'vue-router'; +import { accordionProps } from './accordion-types'; +import { AccordionItemClickEvent, AccordionMenuItem, AccordionLinkableItem } from './accordion.type'; +import DAccordionItem from './accordion-item'; +import { getRootSlots } from './utils'; export default defineComponent({ name: 'DAccordionItemRouterlink', @@ -32,39 +32,39 @@ export default defineComponent({ linkDefaultTarget, disabledKey, itemTemplate - } = toRefs(props) + } = toRefs(props); - const route = useRoute() - const rootSlots = getRootSlots() - const accordionCtx = inject('accordionContext') as any - console.log(useRoute()) + const route = useRoute(); + const rootSlots = getRootSlots(); + const accordionCtx = inject('accordionContext') as any; + console.log(useRoute()); const title = computed(() => { - return item.value && item.value[titleKey.value] - }) + return item.value && item.value[titleKey.value]; + }); const link = computed(() => { - return item.value && item.value[linkKey.value] - }) + return item.value && item.value[linkKey.value]; + }); - const isUsedVueRouter = computed(() => route !== undefined) + const isUsedVueRouter = computed(() => route !== undefined); const routerLinkActive = computed(() => { - return route === link.value - }) + return route === link.value; + }); const disabled = computed(() => { - return item.value && item.value[disabledKey.value] - }) + return item.value && item.value[disabledKey.value]; + }); - const parentValue = parent.value - const deepValue = deepth.value + const parentValue = parent.value; + const deepValue = deepth.value; const linkItemClickFn = (itemEvent: AccordionItemClickEvent) => { if (item.value && !disabled.value) { - accordionCtx.itemClickFn(itemEvent) + accordionCtx.itemClickFn(itemEvent); } - } + }; const renderContent = () => { return ( @@ -82,8 +82,8 @@ export default defineComponent({ item: item.value })} - ) - } + ); + }; return () => { return ( @@ -141,7 +141,7 @@ export default defineComponent({ )} - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/accordion/src/accordion-item.tsx b/packages/devui-vue/devui/accordion/src/accordion-item.tsx index a20b8a919d..d7aeaa99ba 100644 --- a/packages/devui-vue/devui/accordion/src/accordion-item.tsx +++ b/packages/devui-vue/devui/accordion/src/accordion-item.tsx @@ -1,7 +1,7 @@ -import { defineComponent, toRefs, computed, inject } from 'vue' -import { accordionProps } from './accordion-types' -import { AccordionItemClickEvent, AccordionMenuItem } from './accordion.type' -import { getRootSlots } from '../src/utils' +import { defineComponent, toRefs, computed, inject } from 'vue'; +import { accordionProps } from './accordion-types'; +import { AccordionItemClickEvent, AccordionMenuItem } from './accordion.type'; +import { getRootSlots } from '../src/utils'; export default defineComponent({ name: 'DAccordionItem', @@ -26,33 +26,33 @@ export default defineComponent({ activeKey, disabledKey, itemTemplate - } = toRefs(props) + } = toRefs(props); - const rootSlots = getRootSlots() - const accordionCtx = inject('accordionContext') as any + const rootSlots = getRootSlots(); + const accordionCtx = inject('accordionContext') as any; - const parentValue = parent.value - const deepValue = deepth.value + const parentValue = parent.value; + const deepValue = deepth.value; const disabled = computed(() => { - return item.value && item.value[disabledKey.value] - }) + return item.value && item.value[disabledKey.value]; + }); const title = computed(() => { - return item.value && item.value[titleKey.value] - }) + return item.value && item.value[titleKey.value]; + }); const active = computed(() => { - return item.value && item.value[activeKey.value] - }) + return item.value && item.value[activeKey.value]; + }); const childActived = computed(() => { - return active.value - }) + return active.value; + }); const itemClick = (itemEvent: AccordionItemClickEvent) => { if (item.value && !disabled.value) { - accordionCtx.itemClickFn(itemEvent) + accordionCtx.itemClickFn(itemEvent); } - } + }; return () => { return ( @@ -87,7 +87,7 @@ export default defineComponent({ })} - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/accordion/src/accordion-list.tsx b/packages/devui-vue/devui/accordion/src/accordion-list.tsx index e079dcc030..3e07b1e763 100644 --- a/packages/devui-vue/devui/accordion/src/accordion-list.tsx +++ b/packages/devui-vue/devui/accordion/src/accordion-list.tsx @@ -1,11 +1,11 @@ -import { computed, defineComponent, inject, toRefs } from 'vue' -import type { AccordionMenuItem } from './accordion.type' -import DAccordionMenu from './accordion-menu' -import DAccordionItem from './accordion-item' -import DAccordionItemHreflink from './accordion-item-hreflink' -import DAccordionItemRouterlink from './accordion-item-routerlink' -import { accordionProps } from './accordion-types' -import { getRootSlots } from '../src/utils' +import { computed, defineComponent, inject, toRefs } from 'vue'; +import type { AccordionMenuItem } from './accordion.type'; +import DAccordionMenu from './accordion-menu'; +import DAccordionItem from './accordion-item'; +import DAccordionItemHreflink from './accordion-item-hreflink'; +import DAccordionItemRouterlink from './accordion-item-routerlink'; +import { accordionProps } from './accordion-types'; +import { getRootSlots } from '../src/utils'; export default defineComponent({ name: 'DAccordionList', @@ -13,24 +13,24 @@ export default defineComponent({ DAccordionMenu, DAccordionItem, DAccordionItemHreflink, - DAccordionItemRouterlink + DAccordionItemRouterlink, }, inheritAttrs: false, props: { data: { type: Array as () => Array, - default: null + default: null, }, deepth: { type: Number, - default: 0 + default: 0, }, parent: { type: Object as () => AccordionMenuItem, - default: null + default: null, }, innerListTemplate: Boolean, - ...accordionProps + ...accordionProps, }, setup(props, { attrs }) { @@ -46,31 +46,29 @@ export default defineComponent({ linkTypeKey, loadingTemplate, noContentTemplate, - innerListTemplate - } = toRefs(props) + innerListTemplate, + } = toRefs(props); - const parentValue = parent.value - const deepValue = deepth.value + const parentValue = parent.value; + const deepValue = deepth.value; - const rootSlots = getRootSlots() + const rootSlots = getRootSlots(); - const accordionCtx = inject('accordionContext') as any + const accordionCtx = inject('accordionContext') as any; const loading = computed(() => { - return parentValue && parentValue[loadingKey.value] - }) + return parentValue && parentValue[loadingKey.value]; + }); const noContent = computed(() => { - const dataValue = data.value - return dataValue === undefined || dataValue === null || dataValue.length === 0 - }) + const dataValue = data.value; + return dataValue === undefined || dataValue === null || dataValue.length === 0; + }); return () => { return ( <> - {(!rootSlots.innerListTemplate || - deepth.value === 0 || - innerListTemplate.value === false) && ( + {(!rootSlots.innerListTemplate || deepth.value === 0 || innerListTemplate.value === false) && (
    {data.value.map((item) => { return ( @@ -78,12 +76,7 @@ export default defineComponent({ {/* // TODO 菜单类型 d-accordion-menu */} {item[childrenKey.value] !== undefined && (
    - +
    )} {/* 非菜单类型 */} @@ -91,12 +84,7 @@ export default defineComponent({ <> {/* 普通类型 */} {(!linkType.value || linkType.value === '') && ( - + )} {/* 路由链接类型 */} {linkType.value === 'routerLink' && ( @@ -104,8 +92,7 @@ export default defineComponent({ {...(props as any)} item={item} deepth={deepValue} - parent={parentValue} - > + parent={parentValue}> )} {/* 普通链接类型 */} {linkType.value === 'hrefLink' && ( @@ -113,8 +100,7 @@ export default defineComponent({ {...(props as any)} item={item} deepth={deepValue} - parent={parentValue} - > + parent={parentValue}> )} {/* 动态链接类型 */} {linkType.value === 'dependOnLinkTypeKey' && ( @@ -124,32 +110,24 @@ export default defineComponent({ {...(props as any)} item={item} deepth={deepValue} - parent={parentValue} - > + parent={parentValue}> )} {item[linkTypeKey.value] === 'hrefLink' && ( + parent={parentValue}> + )} + {item[linkTypeKey.value] !== 'routerLink' && item[linkTypeKey.value] !== 'hrefLink' && ( + )} - {item[linkTypeKey.value] !== 'routerLink' && - item[linkTypeKey.value] !== 'hrefLink' && ( - - )} )} )} - ) + ); })}
)} @@ -160,69 +138,62 @@ export default defineComponent({ item: parentValue, deepth: deepValue, itemClickFn: accordionCtx.itemClickFn, - menuToggleFn: accordionCtx.menuToggleFn + menuToggleFn: accordionCtx.menuToggleFn, })} {(!rootSlots.innerListTemplate || innerListTemplate.value === false) && (loading.value || (noContent.value && showNoContent.value)) && ( -
    - { - // 加载中 - loading.value && (!rootSlots.loadingTemplate || loadingTemplate.value === false) && ( -
  • -
    +
      + { + // 加载中 + loading.value && (!rootSlots.loadingTemplate || loadingTemplate.value === false) && ( +
    • +
      加载中... -
      -
    • - ) - } - { - // 自定义加载 - loading.value && +
    +
  • + ) + } + { + // 自定义加载 + loading.value && rootSlots.loadingTemplate && loadingTemplate.value !== false && rootSlots.loadingTemplate?.({ item: parentValue, - deepth: deepValue + deepth: deepValue, }) - } - { - // 无数据 - showNoContent.value && + } + { + // 无数据 + showNoContent.value && !loading.value && noContent.value && (!rootSlots.noContentTemplate || noContentTemplate.value === false) && ( -
  • -
    +
  • +
    没有数据 -
    -
  • - ) - } - { - // 自定义加载 - showNoContent.value && + + + ) + } + { + // 自定义加载 + showNoContent.value && !loading.value && noContent.value && rootSlots.noContentTemplate && noContentTemplate.value !== false && rootSlots.noContentTemplate?.({ item: parentValue, - deepth: deepValue + deepth: deepValue, }) - } -
- )} + } + + )} - ) - } - } -}) + ); + }; + }, +}); diff --git a/packages/devui-vue/devui/accordion/src/accordion-menu.tsx b/packages/devui-vue/devui/accordion/src/accordion-menu.tsx index 94d525a751..23f4cec4f2 100644 --- a/packages/devui-vue/devui/accordion/src/accordion-menu.tsx +++ b/packages/devui-vue/devui/accordion/src/accordion-menu.tsx @@ -1,9 +1,9 @@ -import { computed, defineComponent, toRefs, inject } from 'vue' -import { AccordionMenuItem, AccordionMenuToggleEvent } from './accordion.type' -import AccordionList from './accordion-list' -import { accordionProps } from './accordion-types' -import OpenIcon from './accordion-open-icon' -import { getRootSlots } from '../src/utils' +import { computed, defineComponent, toRefs, inject } from 'vue'; +import { AccordionMenuItem, AccordionMenuToggleEvent } from './accordion.type'; +import AccordionList from './accordion-list'; +import { accordionProps } from './accordion-types'; +import OpenIcon from './accordion-open-icon'; +import { getRootSlots } from '../src/utils'; export default defineComponent({ name: 'DAccordionMenu', @@ -34,62 +34,62 @@ export default defineComponent({ childrenKey, titleKey, menuItemTemplate - } = toRefs(props) + } = toRefs(props); - const rootSlots = getRootSlots() - const accordionCtx = inject('accordionContext') as any + const rootSlots = getRootSlots(); + const accordionCtx = inject('accordionContext') as any; - const parentValue = parent.value - const deepValue = deepth.value + const parentValue = parent.value; + const deepValue = deepth.value; const toggle = (itemEvent: AccordionMenuToggleEvent) => { - accordionCtx.menuToggleFn(itemEvent) - } + accordionCtx.menuToggleFn(itemEvent); + }; const hasActiveChildren = (item) => { - if (item[activeKey.value] === true) return true + if (item[activeKey.value] === true) {return true;} if (item[childrenKey.value]) { - return hasChildActive(item[childrenKey.value]) + return hasChildActive(item[childrenKey.value]); } - } + }; const hasChildActive = (arr) => { - let flag = false - if (!arr.length) return false + let flag = false; + if (!arr.length) {return false;} for (let i = 0; i < arr.length; i++) { if (arr[i][activeKey.value] === true) { - flag = true - break + flag = true; + break; } if (arr[i][childrenKey.value]) { - flag = hasChildActive(arr[i][childrenKey.value]) - if (flag) break + flag = hasChildActive(arr[i][childrenKey.value]); + if (flag) {break;} } } - return flag - } + return flag; + }; const keyOpen = computed(() => { - return item.value && item.value[openKey.value] - }) + return item.value && item.value[openKey.value]; + }); const disabled = computed(() => { - return item.value && item.value[disabledKey.value] - }) + return item.value && item.value[disabledKey.value]; + }); const title = computed(() => { - return item.value && item.value[titleKey.value] - }) + return item.value && item.value[titleKey.value]; + }); const children = computed(() => { - return item.value && item.value[childrenKey.value] - }) + return item.value && item.value[childrenKey.value]; + }); const childActived = computed(() => { - return hasActiveChildren(item.value) - }) + return hasActiveChildren(item.value); + }); const open = computed(() => { return keyOpen.value === undefined && autoOpenActiveMenu.value ? childActived.value - : keyOpen.value - }) + : keyOpen.value; + }); return () => { return ( @@ -145,7 +145,7 @@ export default defineComponent({ > - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/accordion/src/accordion-open-icon.tsx b/packages/devui-vue/devui/accordion/src/accordion-open-icon.tsx index 2e6d956b97..063bef1c11 100644 --- a/packages/devui-vue/devui/accordion/src/accordion-open-icon.tsx +++ b/packages/devui-vue/devui/accordion/src/accordion-open-icon.tsx @@ -16,5 +16,5 @@ const OpenIcon = () => { ) -} -export default OpenIcon +}; +export default OpenIcon; diff --git a/packages/devui-vue/devui/accordion/src/accordion-types.ts b/packages/devui-vue/devui/accordion/src/accordion-types.ts index a2cf54dacc..fb47c91637 100644 --- a/packages/devui-vue/devui/accordion/src/accordion-types.ts +++ b/packages/devui-vue/devui/accordion/src/accordion-types.ts @@ -2,62 +2,62 @@ import { ExtractPropTypes } from 'vue'; import { AccordionMenuType } from './accordion.type'; export const accordionProps = { - data: { - type: Array as () => Array | AccordionMenuType, - default: null, - }, - /* Key值定义, 用于自定义数据结构 */ - titleKey: { type: String, default: 'title' }, // 标题的key,item[titleKey]类型为string,为标题显示内容 - loadingKey: { type: String, default: 'loading' }, // 子菜单动态加载item[loadingKey]类型为boolean - childrenKey: { type: String, default: 'children' }, // 子菜单Key - disabledKey: { type: String, default: 'disabled' }, // 是否禁用Key - activeKey: { type: String, default: 'active' }, // 菜单是否激活/选中 - openKey: { type: String, default: 'open' }, // 菜单是否打开 + data: { + type: Array as () => Array | AccordionMenuType, + default: null, + }, + /* Key值定义, 用于自定义数据结构 */ + titleKey: { type: String, default: 'title' }, // 标题的key,item[titleKey]类型为string,为标题显示内容 + loadingKey: { type: String, default: 'loading' }, // 子菜单动态加载item[loadingKey]类型为boolean + childrenKey: { type: String, default: 'children' }, // 子菜单Key + disabledKey: { type: String, default: 'disabled' }, // 是否禁用Key + activeKey: { type: String, default: 'active' }, // 菜单是否激活/选中 + openKey: { type: String, default: 'open' }, // 菜单是否打开 - /* 菜单模板 */ - menuItemTemplate: { type: Boolean, default: true }, // 可展开菜单内容条模板 - itemTemplate: { type: Boolean, default: true }, // 可点击菜单内容条模板 + /* 菜单模板 */ + menuItemTemplate: { type: Boolean, default: true }, // 可展开菜单内容条模板 + itemTemplate: { type: Boolean, default: true }, // 可点击菜单内容条模板 - menuToggle: { - type: Function as unknown as () => (event: MouseEvent) => void, - default: null, - }, // 可展开菜单展开事件 - itemClick: { - type: Function as unknown as () => (event: MouseEvent) => void, - default: null, - }, // 可点击菜单点击事件 - activeItemChange: { - type: Function as unknown as () => (event: MouseEvent) => void, - default: null, - }, + menuToggle: { + type: Function as unknown as () => (event: MouseEvent) => void, + default: null, + }, // 可展开菜单展开事件 + itemClick: { + type: Function as unknown as () => (event: MouseEvent) => void, + default: null, + }, // 可点击菜单点击事件 + activeItemChange: { + type: Function as unknown as () => (event: MouseEvent) => void, + default: null, + }, - /** 高级选项和模板 */ - restrictOneOpen: { type: Boolean, default: false }, // 限制一级菜单同时只能打开一个 - autoOpenActiveMenu: { type: Boolean, default: false }, // 自动展开活跃菜单 - showNoContent: { type: Boolean, default: true }, // 没有内容的时候是否显示没有数据 - noContentTemplate: { type: Boolean, default: true }, // 没有内容的时候使用自定义模板 - loadingTemplate: { type: Boolean, default: true }, // 加载中使用自定义模板 - innerListTemplate: { type: Boolean, default: true }, // 可折叠菜单内容完全自定义,用做折叠面板 + /** 高级选项和模板 */ + restrictOneOpen: { type: Boolean, default: false }, // 限制一级菜单同时只能打开一个 + autoOpenActiveMenu: { type: Boolean, default: false }, // 自动展开活跃菜单 + showNoContent: { type: Boolean, default: true }, // 没有内容的时候是否显示没有数据 + noContentTemplate: { type: Boolean, default: true }, // 没有内容的时候使用自定义模板 + loadingTemplate: { type: Boolean, default: true }, // 加载中使用自定义模板 + innerListTemplate: { type: Boolean, default: true }, // 可折叠菜单内容完全自定义,用做折叠面板 - /* 内置路由/链接/动态判断路由或链接类型 */ - linkType: { - type: String as () => - | 'routerLink' - | 'hrefLink' - | 'dependOnLinkTypeKey' - | '' - | string, - default: '', - }, - linkTypeKey: { type: String, default: 'linkType' }, // linkType为'dependOnLinkTypeKey'时指定对象linkType定义区 - linkKey: { type: String, default: 'link' }, // 链接内容的key - linkTargetKey: { type: String, default: 'target' }, // 链接目标窗口的key - linkDefaultTarget: { type: String, default: '_self' }, // 不设置target的时候target默认值 + /* 内置路由/链接/动态判断路由或链接类型 */ + linkType: { + type: String as () => + | 'routerLink' + | 'hrefLink' + | 'dependOnLinkTypeKey' + | '' + | string, + default: '', + }, + linkTypeKey: { type: String, default: 'linkType' }, // linkType为'dependOnLinkTypeKey'时指定对象linkType定义区 + linkKey: { type: String, default: 'link' }, // 链接内容的key + linkTargetKey: { type: String, default: 'target' }, // 链接目标窗口的key + linkDefaultTarget: { type: String, default: '_self' }, // 不设置target的时候target默认值 - accordionType: { - type: String as () => 'normal' | 'embed', - default: 'normal', - }, + accordionType: { + type: String as () => 'normal' | 'embed', + default: 'normal', + }, } as const; export type AccordionProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/accordion/src/accordion.tsx b/packages/devui-vue/devui/accordion/src/accordion.tsx index e9b21b77cf..5f8c567673 100644 --- a/packages/devui-vue/devui/accordion/src/accordion.tsx +++ b/packages/devui-vue/devui/accordion/src/accordion.tsx @@ -4,15 +4,15 @@ import { provide, toRefs, watch -} from 'vue' -import AccordionList from './accordion-list' -import { accordionProps, AccordionProps } from './accordion-types' +} from 'vue'; +import AccordionList from './accordion-list'; +import { accordionProps, AccordionProps } from './accordion-types'; import { AccordionItemClickEvent, AccordionMenuItem, AccordionMenuToggleEvent -} from './accordion.type' -import './accordion.scss' +} from './accordion.type'; +import './accordion.scss'; export default defineComponent({ name: 'DAccordion', @@ -26,9 +26,9 @@ export default defineComponent({ accordionType, autoOpenActiveMenu, restrictOneOpen, - } = toRefs(props) + } = toRefs(props); - let clickActiveItem: AccordionMenuItem | undefined = undefined //记录用户点击的激活菜单项 + let clickActiveItem: AccordionMenuItem | undefined = undefined; // 记录用户点击的激活菜单项 const flatten = ( arr: Array, @@ -37,108 +37,108 @@ export default defineComponent({ includeLeaf = true ) => { return arr.reduce((acc, cur) => { - const children = cur[childrenKey] + const children = cur[childrenKey]; if (children === undefined) { if (includeLeaf) { - acc.push(cur) + acc.push(cur); } } else { if (includeParent) { - acc.push(cur) + acc.push(cur); } if (Array.isArray(children)) { - acc.push(...flatten(children, childrenKey, includeParent)) + acc.push(...flatten(children, childrenKey, includeParent)); } } - return acc - }, []) - } + return acc; + }, []); + }; const initActiveItem = () => { const activeItem = flatten(data.value, childrenKey.value) .filter((item) => item[activeKey.value]) - .pop() + .pop(); if (activeItem) { if (!clickActiveItem) { - activeItemFn(activeItem) + activeItemFn(activeItem); } } else { - clickActiveItem = undefined + clickActiveItem = undefined; } - } + }; // 激活子菜单项并去掉其他子菜单的激活 const activeItemFn = (item) => { if (clickActiveItem && clickActiveItem[activeKey.value]) { - clickActiveItem[activeKey.value] = false + clickActiveItem[activeKey.value] = false; } - item[activeKey.value] = true - clickActiveItem = item - emit('activeItemChange', clickActiveItem) - } + item[activeKey.value] = true; + clickActiveItem = item; + emit('activeItemChange', clickActiveItem); + }; // 打开或关闭一级菜单,如果有限制只能展开一项则关闭其他一级菜单 const openMenuFn = (item, open) => { if (open && restrictOneOpen.value) { data.value.forEach((itemtemp) => { - itemtemp[openKey.value] = false - }) + itemtemp[openKey.value] = false; + }); } - item[openKey.value] = open - } + item[openKey.value] = open; + }; // 点击了可点击菜单 const itemClickFn = (itemEvent: AccordionItemClickEvent) => { - const prevActiveItem = clickActiveItem - activeItemFn(itemEvent.item) - emit('itemClick', { ...itemEvent, prevActiveItem: prevActiveItem }) - } + const prevActiveItem = clickActiveItem; + activeItemFn(itemEvent.item); + emit('itemClick', { ...itemEvent, prevActiveItem: prevActiveItem }); + }; const linkItemClickFn = (itemEvent: AccordionItemClickEvent) => { - const prevActiveItem = clickActiveItem - clickActiveItem = itemEvent.item - emit('linkItemClick', { ...itemEvent, prevActiveItem: prevActiveItem }) - } + const prevActiveItem = clickActiveItem; + clickActiveItem = itemEvent.item; + emit('linkItemClick', { ...itemEvent, prevActiveItem: prevActiveItem }); + }; // 打开或关闭可折叠菜单 const menuToggleFn = (menuEvent: AccordionMenuToggleEvent) => { - openMenuFn(menuEvent.item, menuEvent.open) - emit('menuToggle', menuEvent) - } + openMenuFn(menuEvent.item, menuEvent.open); + emit('menuToggle', menuEvent); + }; const cleanOpenData = () => { flatten(data.value, childrenKey.value, true, false).forEach( (item) => (item[openKey.value] = undefined) - ) - } + ); + }; provide('accordionContext', { itemClickFn, linkItemClickFn, menuToggleFn - }) + }); onMounted(() => { if (data.value) { - initActiveItem() + initActiveItem(); } - }) + }); watch( () => autoOpenActiveMenu.value, (current, preV) => { if (current && preV === false) { - cleanOpenData() + cleanOpenData(); } } - ) + ); watch( data.value, (current, preV) => { - initActiveItem() + initActiveItem(); }, { deep: true } - ) + ); return () => { return ( @@ -157,7 +157,7 @@ export default defineComponent({ parent={null} > - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/accordion/src/accordion.type.ts b/packages/devui-vue/devui/accordion/src/accordion.type.ts index 2a4cb0bf28..33d75650d9 100755 --- a/packages/devui-vue/devui/accordion/src/accordion.type.ts +++ b/packages/devui-vue/devui/accordion/src/accordion.type.ts @@ -1,23 +1,23 @@ /* 基础数据类型 */ type AccordionMenuItemLinkType = 'routerLink' | 'hrefLink' | string; export interface AccordionBase { - title: string - disabled?: boolean - [prop: string]: any + title: string; + disabled?: boolean; + [prop: string]: any; } interface IAccordionActiveable { - active?: boolean + active?: boolean; } interface IAccordionFoldable { - open?: boolean - loading?: boolean - children?: Array + open?: boolean; + loading?: boolean; + children?: Array; } interface IAccordionLinkable { - link?: string - target?: boolean - linkType?: AccordionMenuItemLinkType + link?: string; + target?: boolean; + linkType?: AccordionMenuItemLinkType; } export interface AccordionBaseItem extends AccordionBase, @@ -44,51 +44,51 @@ export type AccordionMenuType = Array; /* 基础事件类型 */ export interface AccordionMenuToggleEvent { - item: any - open: boolean - parent: any - event: MouseEvent + item: any; + open: boolean; + parent: any; + event: MouseEvent; } export interface AccordionItemClickEvent { - item: any - prevActiveItem?: any - parent: any - event: MouseEvent + item: any; + prevActiveItem?: any; + parent: any; + event: MouseEvent; } /* 废弃接口 */ /** @deprecated merge into `AccordionMenuItem`*/ export interface AccordionSubMenuItem { - title: string - active?: boolean - disabled?: boolean - [prop: string]: any + title: string; + active?: boolean; + disabled?: boolean; + [prop: string]: any; } /** @deprecated use `AccordionLinkableItem` instead*/ export interface AccordionSubMenuItemHrefLink { - title: string - link: string - target?: string - active?: boolean - disabled?: boolean - [prop: string]: any + title: string; + link: string; + target?: string; + active?: boolean; + disabled?: boolean; + [prop: string]: any; } /** @deprecated use `AccordionLinkableItem` instead*/ export interface AccordionSubMenuItemRouterLink { - title: string - link: string - target?: string - active?: boolean - disabled?: boolean - [prop: string]: any + title: string; + link: string; + target?: string; + active?: boolean; + disabled?: boolean; + [prop: string]: any; } /** @deprecated use `AccordionLinkableItem` instead*/ export interface AccordionSubMenuItemDynamicLink { - title: string - link: string - linkType: 'routerLink' | 'hrefLink' | string - target?: string - active?: boolean - disabled?: boolean - [prop: string]: any + title: string; + link: string; + linkType: 'routerLink' | 'hrefLink' | string; + target?: string; + active?: boolean; + disabled?: boolean; + [prop: string]: any; } diff --git a/packages/devui-vue/devui/accordion/src/utils.ts b/packages/devui-vue/devui/accordion/src/utils.ts index e4d01bb755..b0f6013090 100644 --- a/packages/devui-vue/devui/accordion/src/utils.ts +++ b/packages/devui-vue/devui/accordion/src/utils.ts @@ -1,51 +1,51 @@ -import { AccordionMenuItem, AccordionMenuType } from './accordion.type' -import { ComponentInternalInstance, getCurrentInstance } from 'vue' +import { AccordionMenuItem, AccordionMenuType } from './accordion.type'; +import { ComponentInternalInstance, getCurrentInstance } from 'vue'; const flatten = ( - arr: Array, - childrenKey = 'children', - includeParent = false, - includeLeaf = true + arr: Array, + childrenKey = 'children', + includeParent = false, + includeLeaf = true ): Array => { - return arr.reduce((acc, cur) => { - const children = cur[childrenKey] - if (children === undefined) { - if (includeLeaf) { - acc.push(cur) - } - } else { - if (includeParent) { - acc.push(cur) - } - if (Array.isArray(children)) { - acc.push(...flatten(children, childrenKey, includeParent)) - } - } - return acc - }, []) -} + return arr.reduce((acc, cur) => { + const children = cur[childrenKey]; + if (children === undefined) { + if (includeLeaf) { + acc.push(cur); + } + } else { + if (includeParent) { + acc.push(cur); + } + if (Array.isArray(children)) { + acc.push(...flatten(children, childrenKey, includeParent)); + } + } + return acc; + }, []); +}; const precheckNodeId = (d: AccordionMenuItem): AccordionMenuItem => { - const random = parseInt((Math.random() * 10 ** 8).toString().padEnd(8, '0')) - return { ...d, id: d.id ? `${d.id}_${random}` : `${d.title.replaceAll(' ', '-')}_${random}` } -} + const random = parseInt((Math.random() * 10 ** 8).toString().padEnd(8, '0')); + return { ...d, id: d.id ? `${d.id}_${random}` : `${d.title.replaceAll(' ', '-')}_${random}` }; +}; const precheckTree = (ds: AccordionMenuType): AccordionMenuType => { - return ds.map((d) => { - const dd = precheckNodeId(d) - if (d.children) { - return { - ...dd, - children: precheckTree(d.children) - } - } - return dd - }) -} + return ds.map((d) => { + const dd = precheckNodeId(d); + if (d.children) { + return { + ...dd, + children: precheckTree(d.children) + }; + } + return dd; + }); +}; const getRootSlots = () => { - const rootComponentName = 'DAccordion' + const rootComponentName = 'DAccordion'; /** * 获取父组件 */ @@ -53,19 +53,19 @@ const getRootSlots = () => { component: ComponentInternalInstance | null ): ComponentInternalInstance | undefined => { if (component && component.type.name === rootComponentName) { - return component + return component; } if (component && component.parent) { - const parent = component.parent - return getRootComponent(parent) + const parent = component.parent; + return getRootComponent(parent); } - } + }; // 获取根节点 - const rootComponent = getRootComponent(getCurrentInstance()) - return rootComponent?.slots -} + const rootComponent = getRootComponent(getCurrentInstance()); + return rootComponent?.slots; +}; export { @@ -73,4 +73,4 @@ export { precheckNodeId, precheckTree, getRootSlots -} +}; diff --git a/packages/devui-vue/devui/alert/__tests__/alert.spec.ts b/packages/devui-vue/devui/alert/__tests__/alert.spec.ts index 1ed2d1cafe..a21b22a2dc 100644 --- a/packages/devui-vue/devui/alert/__tests__/alert.spec.ts +++ b/packages/devui-vue/devui/alert/__tests__/alert.spec.ts @@ -1,21 +1,21 @@ -import { mount } from '@vue/test-utils' -import { h } from 'vue' -import Alert from '../src/alert' +import { mount } from '@vue/test-utils'; +import { h } from 'vue'; +import Alert from '../src/alert'; describe('alert', () => { describe('alert basic', () => { it('should create alert component correctly', () => { - const wrapper = mount(Alert) - expect(wrapper.find('.devui-alert').exists()).toBe(true) - }) + const wrapper = mount(Alert); + expect(wrapper.find('.devui-alert').exists()).toBe(true); + }); it('should alert show content correct', () => { const wrapper = mount(Alert, { slots: { default: h('span', {}, 'Vue DevUI'), }, - }) - expect(wrapper.find('.devui-alert').text()).toBe('Vue DevUI') - }) - }) + }); + expect(wrapper.find('.devui-alert').text()).toBe('Vue DevUI'); + }); + }); describe('alert type', () => { it('alert should has success type', () => { @@ -23,38 +23,38 @@ describe('alert', () => { props: { type: 'success', }, - }) - expect(wrapper.find('.devui-icon-success').exists()).toBe(true) - }) + }); + expect(wrapper.find('.devui-icon-success').exists()).toBe(true); + }); it('alert should has warning type', () => { const wrapper = mount(Alert, { props: { type: 'warning', }, - }) - expect(wrapper.find('.devui-icon-warning').exists()).toBe(true) - }) + }); + expect(wrapper.find('.devui-icon-warning').exists()).toBe(true); + }); it('alert should has error type', () => { const wrapper = mount(Alert, { props: { type: 'danger', }, - }) - expect(wrapper.find('.devui-icon-error').exists()).toBe(true) - }) + }); + expect(wrapper.find('.devui-icon-error').exists()).toBe(true); + }); it('alert should has info type', () => { - const wrapper = mount(Alert) - expect(wrapper.find('.devui-icon-info').exists()).toBe(true) - }) + const wrapper = mount(Alert); + expect(wrapper.find('.devui-icon-info').exists()).toBe(true); + }); it('alert should has simple type', () => { const wrapper = mount(Alert, { props: { type: 'simple', }, - }) - expect(wrapper.find('.devui-alert-icon').exists()).toBe(false) - }) - }) + }); + expect(wrapper.find('.devui-alert-icon').exists()).toBe(false); + }); + }); describe('alert cssClass', () => { it('alert should append cssClass', () => { @@ -62,60 +62,60 @@ describe('alert', () => { props: { cssClass: 'cssClass', }, - }) - expect(wrapper.find('.cssClass').exists()).toBe(true) - }) - }) + }); + expect(wrapper.find('.cssClass').exists()).toBe(true); + }); + }); describe('alert icon', () => { it('alert should show icon', () => { - const wrapper = mount(Alert) - expect(wrapper.find('.devui-alert-icon').exists()).toBe(true) - }) + const wrapper = mount(Alert); + expect(wrapper.find('.devui-alert-icon').exists()).toBe(true); + }); it('alert should not show icon', () => { const wrapper = mount(Alert, { props: { showIcon: false, }, - }) - expect(wrapper.find('.devui-alert-icon').exists()).toBe(false) - }) - }) + }); + expect(wrapper.find('.devui-alert-icon').exists()).toBe(false); + }); + }); describe('alert close', () => { it('alert should close', async () => { - const wrapper = mount(Alert) - await wrapper.find('.devui-close').trigger('click') + const wrapper = mount(Alert); + await wrapper.find('.devui-close').trigger('click'); setTimeout(() => { - expect(wrapper.find('.devui-alert').exists()).toBe(false) - }, 0) - }) + expect(wrapper.find('.devui-alert').exists()).toBe(false); + }, 0); + }); it('alert should emit close event', async () => { - const wrapper = mount(Alert) - await wrapper.find('.devui-close').trigger('click') - expect(wrapper.emitted()).toHaveProperty('close') - expect(wrapper.emitted().close).toHaveLength(1) - }) - }) + const wrapper = mount(Alert); + await wrapper.find('.devui-close').trigger('click'); + expect(wrapper.emitted()).toHaveProperty('close'); + expect(wrapper.emitted().close).toHaveLength(1); + }); + }); describe('alert dismiss', () => { beforeEach(() => { - jest.useFakeTimers() - }) + jest.useFakeTimers(); + }); it('alert should not dismiss before 3000ms', async () => { const wrapper = mount(Alert, { props: { dismissTime: 3000, }, - }) - expect(wrapper.find('.devui-alert').exists()).toBe(true) - await wrapper.find('.devui-close').trigger('click') - jest.advanceTimersByTime(2000) - expect(wrapper.find('.devui-alert').exists()).toBe(true) - jest.advanceTimersByTime(1000) + }); + expect(wrapper.find('.devui-alert').exists()).toBe(true); + await wrapper.find('.devui-close').trigger('click'); + jest.advanceTimersByTime(2000); + expect(wrapper.find('.devui-alert').exists()).toBe(true); + jest.advanceTimersByTime(1000); setTimeout(() => { - expect(wrapper.find('.devui-alert').exists()).toBe(false) - }, 0) - }) - }) -}) + expect(wrapper.find('.devui-alert').exists()).toBe(false); + }, 0); + }); + }); +}); diff --git a/packages/devui-vue/devui/alert/index.ts b/packages/devui-vue/devui/alert/index.ts index afbfed0c42..c906b85153 100644 --- a/packages/devui-vue/devui/alert/index.ts +++ b/packages/devui-vue/devui/alert/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Alert from './src/alert' +import type { App } from 'vue'; +import Alert from './src/alert'; Alert.install = function (app: App) { - app.component(Alert.name, Alert) -} + app.component(Alert.name, Alert); +}; -export { Alert } +export { Alert }; export default { title: 'Alert 警告', category: '反馈', status: '100%', install(app: App): void { - app.use(Alert as any) + app.use(Alert as any); }, -} +}; diff --git a/packages/devui-vue/devui/alert/src/alert-close-icon.tsx b/packages/devui-vue/devui/alert/src/alert-close-icon.tsx index 869b979aa6..d8025b3a81 100644 --- a/packages/devui-vue/devui/alert/src/alert-close-icon.tsx +++ b/packages/devui-vue/devui/alert/src/alert-close-icon.tsx @@ -12,5 +12,5 @@ const AlertCloseIcon = () => ( -) -export default AlertCloseIcon +); +export default AlertCloseIcon; diff --git a/packages/devui-vue/devui/alert/src/alert-type-icon.tsx b/packages/devui-vue/devui/alert/src/alert-type-icon.tsx index e409dbb719..171ba01899 100644 --- a/packages/devui-vue/devui/alert/src/alert-type-icon.tsx +++ b/packages/devui-vue/devui/alert/src/alert-type-icon.tsx @@ -1,6 +1,6 @@ -import { AlertType } from './alert' +import { AlertType } from './alert'; -const AlertTypeIcon = (props: { type: AlertType; }) => ( +const AlertTypeIcon = (props: { type: AlertType }) => ( ( > {(() => { switch (props.type) { - case 'success': - return ( - + case 'success': + return ( + + + + + ); + case 'warning': + return ( + + + + + ); + case 'info': + return ( + + - + - ) - case 'warning': - return ( - + + ); + case 'danger': + return ( + + - ) - case 'info': - return ( - - - - - - - ) - case 'danger': - return ( - - - - - - - ) - default: - return null + + ); + default: + return null; } })()} -) +); -export default AlertTypeIcon +export default AlertTypeIcon; diff --git a/packages/devui-vue/devui/alert/src/alert.tsx b/packages/devui-vue/devui/alert/src/alert.tsx index bb3889e960..827874df05 100644 --- a/packages/devui-vue/devui/alert/src/alert.tsx +++ b/packages/devui-vue/devui/alert/src/alert.tsx @@ -1,11 +1,11 @@ -import { defineComponent, ref, Transition, onMounted } from 'vue' +import { defineComponent, ref, Transition, onMounted } from 'vue'; -import AlertCloseIcon from './alert-close-icon' -import AlertTypeIcon from './alert-type-icon' +import AlertCloseIcon from './alert-close-icon'; +import AlertTypeIcon from './alert-type-icon'; -import './alert.scss' +import './alert.scss'; -export type AlertType = 'success' | 'danger' | 'warning' | 'info' | 'simple' +export type AlertType = 'success' | 'danger' | 'warning' | 'info' | 'simple'; export default defineComponent({ name: 'DAlert', @@ -33,29 +33,29 @@ export default defineComponent({ }, emits: ['close'], setup(props, ctx) { - const hide = ref(false) - const closing = ref(false) - const alertEl = ref() + const hide = ref(false); + const closing = ref(false); + const alertEl = ref(); let dismissTimer: undefined | number = undefined; const close = (event?: MouseEvent) => { - dismissTimer && clearTimeout(dismissTimer) - closing.value = true - ctx.emit('close', event) - } + dismissTimer && clearTimeout(dismissTimer); + closing.value = true; + ctx.emit('close', event); + }; const afterLeave = () => { dismissTimer = undefined; - hide.value = true - closing.value = false - } + hide.value = true; + closing.value = false; + }; onMounted(() => { if (props.dismissTime) { dismissTimer = window.setTimeout(() => { - close() - }, props.dismissTime) + close(); + }, props.dismissTime); } - }) + }); return () => { return !hide.value ? ( @@ -64,7 +64,7 @@ export default defineComponent({ ref={alertEl} v-show={!closing.value} class={`devui-alert devui-alert-${props.type} ${props.cssClass} ${closing.value ? 'devui-alter-close' : '' - }`} + }`} > {props.closeable ? (
@@ -79,7 +79,7 @@ export default defineComponent({ {ctx.slots.default?.()}
- ) : null - } + ) : null; + }; }, -}) +}); diff --git a/packages/devui-vue/devui/anchor/index.ts b/packages/devui-vue/devui/anchor/index.ts index 37726e1ba5..980c3f5d98 100644 --- a/packages/devui-vue/devui/anchor/index.ts +++ b/packages/devui-vue/devui/anchor/index.ts @@ -1,24 +1,24 @@ -import { App } from 'vue' -import Anchor from './src/anchor' -import dAnchorBox from './src/d-anchor-box' -import dAnchorLink from './src/d-anchor-link' -import dAnchor from './src/d-anchor' +import { App } from 'vue'; +import Anchor from './src/anchor'; +import dAnchorBox from './src/d-anchor-box'; +import dAnchorLink from './src/d-anchor-link'; +import dAnchor from './src/d-anchor'; import './src/anchor.scss'; Anchor.install = function(Vue: App) { Vue.directive(dAnchor.name, dAnchor); Vue.directive(dAnchorLink.name, dAnchorLink); Vue.directive(dAnchorBox.name, dAnchorBox); - Vue.component(Anchor.name, Anchor) + Vue.component(Anchor.name, Anchor); }; - -export { Anchor } + +export { Anchor }; export default { title: 'Anchor 锚点', category: '导航', status: '50%', install(app: App): void { - app.use(Anchor as any) + app.use(Anchor as any); } -} +}; diff --git a/packages/devui-vue/devui/anchor/src/anchor.tsx b/packages/devui-vue/devui/anchor/src/anchor.tsx index 297b31c873..990682e956 100644 --- a/packages/devui-vue/devui/anchor/src/anchor.tsx +++ b/packages/devui-vue/devui/anchor/src/anchor.tsx @@ -1,4 +1,4 @@ -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; export default defineComponent({ name: 'DAnchor', @@ -8,7 +8,7 @@ export default defineComponent({ return () => { return (
- ) - } + ); + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/anchor/src/d-anchor-box.ts b/packages/devui-vue/devui/anchor/src/d-anchor-box.ts index 0ad8a390bc..e9a2607bc3 100644 --- a/packages/devui-vue/devui/anchor/src/d-anchor-box.ts +++ b/packages/devui-vue/devui/anchor/src/d-anchor-box.ts @@ -23,12 +23,12 @@ export default { cssChange(mysidebar, 'absolute', 0, 0); }); window.onscroll = function () { - //为了保证兼容性,这里取两个值,哪个有值取哪一个 - //scrollTop就是触发滚轮事件时滚轮的高度 + // 为了保证兼容性,这里取两个值,哪个有值取哪一个 + // scrollTop就是触发滚轮事件时滚轮的高度 windoScrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 16为padding 8px *2 (上下边距) if (!document.getElementsByClassName('scrollTarget').length) { - if ( windoScrollTop + mysidebarHeight - 16 >= div.offsetTop + div.clientHeight ) { + if (windoScrollTop + mysidebarHeight - 16 >= div.offsetTop + div.clientHeight) { // 看不见 d-anchor-box区域 cssChange( mysidebar, diff --git a/packages/devui-vue/devui/anchor/src/d-anchor-link.ts b/packages/devui-vue/devui/anchor/src/d-anchor-link.ts index 743106942d..199fe5c42c 100644 --- a/packages/devui-vue/devui/anchor/src/d-anchor-link.ts +++ b/packages/devui-vue/devui/anchor/src/d-anchor-link.ts @@ -1,7 +1,7 @@ import { scrollToControl } from './util'; interface Bind { - value: string -} + value: string; +} export default { name: 'd-anchor-link', @@ -9,23 +9,23 @@ export default { // 1.点击滚动到对应位置,并且高亮 // 2.到对应位置后,改变url后hash - mounted(el: HTMLElement,binding: Bind):void { + mounted(el: HTMLElement,binding: Bind): void { const parent: Element = el.parentNode as Element; if (!parent.className) { - parent.className = 'mysidebar step-nav'; + parent.className = 'mysidebar step-nav'; } el.className = 'bar-link-item'; el.innerHTML += ''; el.setAttribute('id', binding.value); - + el.onclick = () => { - let scrollContainer: any; - const scollToDomY = document.getElementsByName(binding.value)[0]; - document.getElementsByClassName('scrollTarget').length - ? scrollContainer = document.getElementsByClassName('scrollTarget')[0] - : scrollContainer = window - scrollToControl(scollToDomY, scrollContainer); - - } + let scrollContainer: any; + const scollToDomY = document.getElementsByName(binding.value)[0]; + document.getElementsByClassName('scrollTarget').length + ? scrollContainer = document.getElementsByClassName('scrollTarget')[0] + : scrollContainer = window; + scrollToControl(scollToDomY, scrollContainer); + + }; } }; diff --git a/packages/devui-vue/devui/anchor/src/d-anchor.ts b/packages/devui-vue/devui/anchor/src/d-anchor.ts index c594a4524f..c82a6687d2 100644 --- a/packages/devui-vue/devui/anchor/src/d-anchor.ts +++ b/packages/devui-vue/devui/anchor/src/d-anchor.ts @@ -1,28 +1,27 @@ -import {hightLightFn} from './util' +import {hightLightFn} from './util'; interface Bind { - value: string - } - + value: string; +} + export default { name: 'd-anchor', // 挂载事件到dom // 1.点击对应link高亮 // 2.href+#+bing.value - mounted(el: HTMLElement, binding: Bind):void { + mounted(el: HTMLElement, binding: Bind): void { const parent: Element = el.parentNode as Element; if (!parent.className) { - parent.className = 'mycontent' + parent.className = 'mycontent'; } - el.innerHTML = '' + el.innerHTML + el.innerHTML = '' + el.innerHTML; el.className = 'section-block'; // anchor-active-by-scroll el.setAttribute('name',binding.value); el.onclick = e => { - hightLightFn(binding.value); - - } + hightLightFn(binding.value); + + }; } }; - - \ No newline at end of file + diff --git a/packages/devui-vue/devui/anchor/src/util.ts b/packages/devui-vue/devui/anchor/src/util.ts index 3ddbbece99..c1660c29ad 100644 --- a/packages/devui-vue/devui/anchor/src/util.ts +++ b/packages/devui-vue/devui/anchor/src/util.ts @@ -1,7 +1,7 @@ let repeatCount = 0; let cTimeout; const timeoutIntervalSpeed = 10; -let hashName:string; +let hashName: string; // 滚动是由于点击产生 let scollFlag = false; function elementPosition(obj: HTMLElement) { @@ -11,189 +11,188 @@ function elementPosition(obj: HTMLElement) { return { x: curleft, y: curtop }; } -export function scrollToControl(elem: HTMLElement, container: HTMLElement):void { +export function scrollToControl(elem: HTMLElement, container: HTMLElement): void { hashName = elem.getAttribute('name'); scollFlag = true; const tops = container.scrollTop>=0 ? container.scrollTop : -(document.getElementsByClassName('mycontainer')[0] as HTMLElement).offsetTop; let scrollPos: number = elementPosition(elem).y - tops ; - + scrollPos = scrollPos - document.documentElement.scrollTop; const remainder: number = scrollPos % timeoutIntervalSpeed; const repeatTimes = Math.abs((scrollPos - remainder) / timeoutIntervalSpeed); if (scrollPos < 0 && container || elem.getBoundingClientRect().top < container.offsetTop) { - window.scrollBy(0, elem.getBoundingClientRect().top-container.offsetTop-16) + window.scrollBy(0, elem.getBoundingClientRect().top-container.offsetTop-16); } // 多个计时器达到平滑滚动效果 - scrollSmoothly(scrollPos, repeatTimes, container) + scrollSmoothly(scrollPos, repeatTimes, container); } - -function scrollSmoothly(scrollPos: number, repeatTimes: number, container: HTMLElement):void { + +function scrollSmoothly(scrollPos: number, repeatTimes: number, container: HTMLElement): void { if (repeatCount <= repeatTimes) { scrollPos > 0 ? container.scrollBy(0, timeoutIntervalSpeed) - : container.scrollBy(0, -timeoutIntervalSpeed) + : container.scrollBy(0, -timeoutIntervalSpeed); } else { repeatCount = 0; clearTimeout(cTimeout); history.replaceState(null, null, document.location.pathname + '#' + hashName); - - hightLightFn(hashName) + + hightLightFn(hashName); setTimeout(() => { scollFlag = false; - }, 310) + }, 310); return ; - + } repeatCount++; cTimeout = setTimeout(() => { - scrollSmoothly(scrollPos, repeatTimes, container) - }, 10) + scrollSmoothly(scrollPos, repeatTimes, container); + }, 10); } // 高亮切换 -export function hightLightFn(hashName:string):void { - +export function hightLightFn(hashName: string): void { + const childLength = document.getElementsByClassName('mysidebar')[0].children.length; - + for (let i = 0; i < childLength; i++) { - + if (document.getElementsByClassName('mysidebar')[0].children[i].classList.value.indexOf('active') > -1) { - - document.getElementsByClassName('mysidebar')[0].children[i].classList.remove('active') + + document.getElementsByClassName('mysidebar')[0].children[i].classList.remove('active'); } } document.getElementById(hashName).classList.add('active'); - } let activeLink = null; let rootActiveLink = null; let rootClassName = ''; -export const setActiveLink = (timeId:string):void => { - if (scollFlag) { return } - timeId ? rootClassName = timeId : rootClassName = document.getElementsByClassName('mymain')[0].id - +export const setActiveLink = (timeId: string): void => { + if (scollFlag) { return; } + timeId ? rootClassName = timeId : rootClassName = document.getElementsByClassName('mymain')[0].id; + const sidebarLinks = getSidebarLinks(rootClassName); const anchors = getAnchors(sidebarLinks); try { anchors.forEach((index,i)=> { - - const anchor:HTMLAnchorElement = anchors[i]; - const nextAnchor:HTMLAnchorElement = anchors[i + 1]; - - const [isActive, hash] = isAnchorActive(i, anchor, nextAnchor); - if (isActive) { - history.replaceState(null, document.title, hash ? hash as string : ' '); - activateLink(hash); - throw Error(hash+''); - } - }) - } catch (e) { - } - -} -function throttleAndDebounce(fn:any, delay:number):any { - let timeout:any; + const anchor: HTMLAnchorElement = anchors[i]; + const nextAnchor: HTMLAnchorElement = anchors[i + 1]; + + const [isActive, hash] = isAnchorActive(i, anchor, nextAnchor); + if (isActive) { + history.replaceState(null, document.title, hash ? hash as string : ' '); + activateLink(hash); + throw Error(hash+''); + } + }); + } catch (e) { + } + +}; + +function throttleAndDebounce(fn: any, delay: number): any { + let timeout: any; let called = false; return () => { - if (timeout) { - clearTimeout(timeout); - } - if (!called) { - fn(); - called = true; - setTimeout(() => { - called = false; - }, delay); - } - else { - timeout = setTimeout(fn, delay); - } + if (timeout) { + clearTimeout(timeout); + } + if (!called) { + fn(); + called = true; + setTimeout(() => { + called = false; + }, delay); + } + else { + timeout = setTimeout(fn, delay); + } }; } export const onScroll = throttleAndDebounce(setActiveLink, 300); -function activateLink(hash:string | boolean):void { +function activateLink(hash: string | boolean): void { deactiveLink(activeLink); deactiveLink(rootActiveLink); hash ? activeLink = document.querySelector(`${hash}`) - : activeLink = document.querySelector(`.${rootClassName} ul li`) + : activeLink = document.querySelector(`.${rootClassName} ul li`); if (!activeLink) { - return; + return; } - + if (!scollFlag) { - hash && hightLightFn((hash as string).split('#')[1] ) + hash && hightLightFn((hash as string).split('#')[1]); }else { - hightLightFn(hashName) + hightLightFn(hashName); } - // + // // also add active class to parent h2 anchors const rootLi = activeLink.closest('.mycontainer > ul > li'); if (rootLi && rootLi !== activeLink.parentElement) { - rootActiveLink = rootLi; - rootActiveLink && rootActiveLink.classList.add('active'); + rootActiveLink = rootLi; + rootActiveLink && rootActiveLink.classList.add('active'); } else { - rootActiveLink = null; + rootActiveLink = null; } } -function deactiveLink(link:HTMLElement):void { +function deactiveLink(link: HTMLElement): void { link && link.classList.remove('active'); } -function getPageOffset():number { +function getPageOffset(): number { return (document.querySelector('.mysidebar ') as HTMLElement).getBoundingClientRect().y; } -function getAnchorTop(anchor:HTMLAnchorElement):number { +function getAnchorTop(anchor: HTMLAnchorElement): number { const pageOffset = getPageOffset(); return anchor.parentElement.offsetTop - pageOffset - 5; } -function isAnchorActive(index:number, anchor:HTMLAnchorElement, nextAnchor:HTMLAnchorElement) { - let scrollTop:number; - document.getElementsByClassName('scrollTarget').length +function isAnchorActive(index: number, anchor: HTMLAnchorElement, nextAnchor: HTMLAnchorElement) { + let scrollTop: number; + document.getElementsByClassName('scrollTarget').length ? scrollTop = document.getElementsByClassName('scrollTarget')[0].scrollTop - : scrollTop = document.documentElement.scrollTop || document.body.scrollTop + : scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (index === 0 && scrollTop === 0) { - return [true, null]; + return [true, null]; } - + if (scrollTop < getAnchorTop(anchor)) { - return [false, null]; + return [false, null]; } if (!nextAnchor || scrollTop < getAnchorTop(nextAnchor)) { - - return [true, decodeURIComponent(anchor.hash)]; + + return [true, decodeURIComponent(anchor.hash)]; } - + return [false, null]; } -function getSidebarLinks(rootClassName:string):Array { +function getSidebarLinks(rootClassName: string): Array { return [].slice.call(document.querySelectorAll(`.${rootClassName} > .step-nav > li.bar-link-item > a`)); } -function getAnchors(sidebarLinks:Array):Array { +function getAnchors(sidebarLinks: Array): Array { return [].slice - .call(document.querySelectorAll('.box-anchor')) - .filter((anchor:HTMLAnchorElement) => sidebarLinks.some(( sidebarLink:HTMLAnchorElement ) => sidebarLink.hash === anchor.hash )); + .call(document.querySelectorAll('.box-anchor')) + .filter((anchor: HTMLAnchorElement) => sidebarLinks.some((sidebarLink: HTMLAnchorElement) => sidebarLink.hash === anchor.hash)); } - -export const randomId = function(n=8):string { // 生成n位长度的字符串 - const str = 'abcdefghijklmnopqrstuvwxyz0123456789'; // 可以作为常量放到random外面 - let result = ''; - for(let i = 0; i < n; i++) { - result += str[parseInt((Math.random() * str.length).toString())]; - } - return result; -} + +export const randomId = function(n=8): string { // 生成n位长度的字符串 + const str = 'abcdefghijklmnopqrstuvwxyz0123456789'; // 可以作为常量放到random外面 + let result = ''; + for(let i = 0; i < n; i++) { + result += str[parseInt((Math.random() * str.length).toString())]; + } + return result; +}; diff --git a/packages/devui-vue/devui/auto-complete/__tests__/auto-complete.spec.ts b/packages/devui-vue/devui/auto-complete/__tests__/auto-complete.spec.ts index 85df305ba4..3df59b01c4 100644 --- a/packages/devui-vue/devui/auto-complete/__tests__/auto-complete.spec.ts +++ b/packages/devui-vue/devui/auto-complete/__tests__/auto-complete.spec.ts @@ -4,7 +4,7 @@ import DAutoComplete from '../src/auto-complete'; // delay api const wait = (delay = 300) => - new Promise(resolve => setTimeout(() => resolve(true), delay)) + new Promise(resolve => setTimeout(() => resolve(true), delay)); describe('auto-complete', () => { it('init render & KeyboardEvent ', async () => { const wrapper = mount({ @@ -17,51 +17,51 @@ describe('auto-complete', () => { /> `, setup() { - const value = ref('') + const value = ref(''); const source = [ 'C#', 'C', 'C++', 'CPython', 'CoffeeScript', - ] + ]; return { value, source, - } + }; } - }) - expect(wrapper.find('.devui-auto-complete').exists()).toBe(true) - const input = wrapper.find('input') - expect(input.element.value).toBe('') - await input.trigger('click') - await nextTick() - expect(wrapper.find('.devui-select-open').exists()).toBe(true) - expect(wrapper.find('.devui-dropdown-item').exists()).toBe(false) + }); + expect(wrapper.find('.devui-auto-complete').exists()).toBe(true); + const input = wrapper.find('input'); + expect(input.element.value).toBe(''); + await input.trigger('click'); + await nextTick(); + expect(wrapper.find('.devui-select-open').exists()).toBe(true); + expect(wrapper.find('.devui-dropdown-item').exists()).toBe(false); expect(wrapper.find('.devui-auto-complete').attributes('style')).toContain( 'width: 450px' - ) - await input.setValue('c') - await nextTick() - expect(wrapper.find('.devui-dropdown-menu').exists()).toBe(true) - await wait(300) - await nextTick() - expect(wrapper.find('.devui-list-unstyled').element.childElementCount).toBe(5) - input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })) - await nextTick() - input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })) - await nextTick() - input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' })) - await nextTick() - input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })) - await nextTick() - input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' })) - await nextTick() - expect(wrapper.vm.value).toBe('C++') - input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })) - await nextTick() - expect(wrapper.find('.devui-select-open').exists()).toBe(false) - }) + ); + await input.setValue('c'); + await nextTick(); + expect(wrapper.find('.devui-dropdown-menu').exists()).toBe(true); + await wait(300); + await nextTick(); + expect(wrapper.find('.devui-list-unstyled').element.childElementCount).toBe(5); + input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })); + await nextTick(); + input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })); + await nextTick(); + input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' })); + await nextTick(); + input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })); + await nextTick(); + input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' })); + await nextTick(); + expect(wrapper.vm.value).toBe('C++'); + input.element.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); + await nextTick(); + expect(wrapper.find('.devui-select-open').exists()).toBe(false); + }); it('disabled ', async () => { const wrapper = mount({ components: {'d-auto-complete': DAutoComplete }, @@ -76,48 +76,48 @@ describe('auto-complete', () => { `, setup() { - const value = ref('') - const isDisabled = ref(false) + const value = ref(''); + const isDisabled = ref(false); const source = [ 'C#', 'C', 'C++', 'CPython', 'CoffeeScript', - ] + ]; function toggle(){ - isDisabled.value= !isDisabled.value + isDisabled.value= !isDisabled.value; } return { value, source, isDisabled, toggle - } + }; } - }) - expect(wrapper.find('.devui-auto-complete').exists()).toBe(true) - const input = wrapper.find('input') - const button = wrapper.find('button') - expect(input.element.value).toBe('') - expect(button.element.innerHTML).toBe('Disable AutoComplete') - await input.trigger('click') - await nextTick() - await input.setValue('c') - await nextTick() - await wait(300) - await nextTick() - expect(wrapper.find('ul .selected').exists()).toBe(true) - const li = wrapper.find('ul .selected') - li.trigger('click') - await nextTick() - expect(wrapper.vm.value).toBe('C#') - expect(wrapper.find('.devui-select-open').exists()).toBe(false) - button.trigger('click') - await nextTick() - expect(button.element.innerHTML).toBe('Enable AutoComplete') - expect(input.element.disabled).toBe(true) - }) + }); + expect(wrapper.find('.devui-auto-complete').exists()).toBe(true); + const input = wrapper.find('input'); + const button = wrapper.find('button'); + expect(input.element.value).toBe(''); + expect(button.element.innerHTML).toBe('Disable AutoComplete'); + await input.trigger('click'); + await nextTick(); + await input.setValue('c'); + await nextTick(); + await wait(300); + await nextTick(); + expect(wrapper.find('ul .selected').exists()).toBe(true); + const li = wrapper.find('ul .selected'); + li.trigger('click'); + await nextTick(); + expect(wrapper.vm.value).toBe('C#'); + expect(wrapper.find('.devui-select-open').exists()).toBe(false); + button.trigger('click'); + await nextTick(); + expect(button.element.innerHTML).toBe('Enable AutoComplete'); + expect(input.element.disabled).toBe(true); + }); it('Customized data matching method ', async () => { const wrapper = mount({ components: {'d-auto-complete': DAutoComplete }, @@ -137,7 +137,7 @@ describe('auto-complete', () => { `, setup() { - const value = ref('') + const value = ref(''); const mySource = ref([ { label:'C#', @@ -176,56 +176,56 @@ describe('auto-complete', () => { label:'CoffeeScript', disabled:false } - ]) + ]); const formatter = (item) =>{ return item.label; - } - //trem:input输入内容 + }; + // trem:input输入内容 const searchFn =async (trem)=>{ - const arr = [] + const arr = []; await new Promise((resolve)=>{ setTimeout(() => { - resolve(1) + resolve(1); }, 500); - }) + }); mySource.value.forEach((item) => { - let cur = item.label - cur = cur.toLowerCase() + let cur = item.label; + cur = cur.toLowerCase(); if (cur.startsWith(trem)) { - arr.push(item) + arr.push(item); } - }) - return arr - } + }); + return arr; + }; return { value, searchFn, formatter - } + }; } - }) - expect(wrapper.find('.devui-auto-complete').exists()).toBe(true) - const input = wrapper.find('input') - expect(input.element.value).toBe('') - await input.trigger('click') - await nextTick() - expect(wrapper.find('.devui-select-open').exists()).toBe(true) - await input.setValue('c') - await nextTick() - await wait(300) - expect(wrapper.find('#devui-is-searching-template').exists()).toBe(true) - expect(wrapper.find('#devui-is-searching-template').element.innerHTML).toBe('c') - await wait(500) - await nextTick() - expect(wrapper.find('.devui-list-unstyled').element.childElementCount).toBe(4) - await input.setValue('s') - await nextTick() - await wait(300) - await nextTick() - await wait(500) - expect(wrapper.find('li.disabled').exists()).toBe(true) - expect(wrapper.find('li.disabled').element.innerHTML).toBe('SQL') - }) + }); + expect(wrapper.find('.devui-auto-complete').exists()).toBe(true); + const input = wrapper.find('input'); + expect(input.element.value).toBe(''); + await input.trigger('click'); + await nextTick(); + expect(wrapper.find('.devui-select-open').exists()).toBe(true); + await input.setValue('c'); + await nextTick(); + await wait(300); + expect(wrapper.find('#devui-is-searching-template').exists()).toBe(true); + expect(wrapper.find('#devui-is-searching-template').element.innerHTML).toBe('c'); + await wait(500); + await nextTick(); + expect(wrapper.find('.devui-list-unstyled').element.childElementCount).toBe(4); + await input.setValue('s'); + await nextTick(); + await wait(300); + await nextTick(); + await wait(500); + expect(wrapper.find('li.disabled').exists()).toBe(true); + expect(wrapper.find('li.disabled').element.innerHTML).toBe('SQL'); + }); it('Customized template display', async () => { const wrapper = mount({ @@ -248,7 +248,7 @@ describe('auto-complete', () => { `, setup() { - const value = ref('') + const value = ref(''); const source = ref([ 'C#', 'C', @@ -264,37 +264,37 @@ describe('auto-complete', () => { 'SQL', 'LiveScript', 'CoffeeScript', - ]) - + ]); + return { value, source - } + }; } - }) - expect(wrapper.find('.devui-auto-complete').exists()).toBe(true) - const input = wrapper.find('input') - expect(input.element.value).toBe('') - await input.trigger('click') - await nextTick() - expect(wrapper.find('.devui-select-open').exists()).toBe(true) - await input.setValue('c') - await nextTick() - await wait(300) - expect(wrapper.find('.devui-list-unstyled').exists()).toBe(true) - expect(wrapper.find('.devui-list-unstyled').element.childElementCount).toBe(5) - expect(wrapper.find('.selected div').element.innerHTML).toBe(' 第0项: C#') - await input.setValue('cc') - await nextTick() - await wait(300) - await nextTick() - expect(wrapper.find('#noResultItemTemplate').exists()).toBe(true) - expect(wrapper.find('#noResultItemTemplate').element.innerHTML).toBe('cc') - }) + }); + expect(wrapper.find('.devui-auto-complete').exists()).toBe(true); + const input = wrapper.find('input'); + expect(input.element.value).toBe(''); + await input.trigger('click'); + await nextTick(); + expect(wrapper.find('.devui-select-open').exists()).toBe(true); + await input.setValue('c'); + await nextTick(); + await wait(300); + expect(wrapper.find('.devui-list-unstyled').exists()).toBe(true); + expect(wrapper.find('.devui-list-unstyled').element.childElementCount).toBe(5); + expect(wrapper.find('.selected div').element.innerHTML).toBe(' 第0项: C#'); + await input.setValue('cc'); + await nextTick(); + await wait(300); + await nextTick(); + expect(wrapper.find('#noResultItemTemplate').exists()).toBe(true); + expect(wrapper.find('#noResultItemTemplate').element.innerHTML).toBe('cc'); + }); it('selectValue & transInputFocusEmit ', async () => { - const transInputFocusEmitCB = jest.fn() - const selectValueCB = jest.fn() + const transInputFocusEmitCB = jest.fn(); + const selectValueCB = jest.fn(); const wrapper = mount({ components: {'d-auto-complete': DAutoComplete }, template: ` @@ -307,43 +307,43 @@ describe('auto-complete', () => { /> `, setup() { - const value = ref('') + const value = ref(''); const source = [ 'C#', 'C', 'C++', 'CPython', 'CoffeeScript', - ] + ]; const selectValue = (e)=>{ - selectValueCB(e) - } + selectValueCB(e); + }; const transInputFocusEmit = (e)=>{ - transInputFocusEmitCB(e) - } + transInputFocusEmitCB(e); + }; return { value, source, selectValue, transInputFocusEmit - } + }; } - }) - expect(wrapper.find('.devui-auto-complete').exists()).toBe(true) - const input = wrapper.find('input') - expect(input.element.value).toBe('') - await input.trigger('focus') - await nextTick() - await input.setValue('c') - await nextTick() - await wait(300) - await nextTick() - expect(transInputFocusEmitCB).toHaveBeenCalledTimes(1) - const li = wrapper.find('ul .selected') - li.trigger('click') - await nextTick() - expect(selectValueCB).toHaveBeenCalledTimes(1) - }) + }); + expect(wrapper.find('.devui-auto-complete').exists()).toBe(true); + const input = wrapper.find('input'); + expect(input.element.value).toBe(''); + await input.trigger('focus'); + await nextTick(); + await input.setValue('c'); + await nextTick(); + await wait(300); + await nextTick(); + expect(transInputFocusEmitCB).toHaveBeenCalledTimes(1); + const li = wrapper.find('ul .selected'); + li.trigger('click'); + await nextTick(); + expect(selectValueCB).toHaveBeenCalledTimes(1); + }); it('allowEmptyValueSearch ', async () => { const wrapper = mount({ components: {'d-auto-complete': DAutoComplete }, @@ -355,30 +355,30 @@ describe('auto-complete', () => { /> `, setup() { - const value = ref('') - const allowEmptyValueSearch = ref(true) + const value = ref(''); + const allowEmptyValueSearch = ref(true); const source = [ 'C#', 'C', 'C++', 'CPython', 'CoffeeScript', - ] - + ]; + return { value, source, allowEmptyValueSearch - } + }; } - }) - expect(wrapper.find('.devui-auto-complete').exists()).toBe(true) - const input = wrapper.find('input') - expect(input.element.value).toBe('') - await input.trigger('focus') - await nextTick() - expect(wrapper.find('ul').element.childElementCount).toBe(5) - }) + }); + expect(wrapper.find('.devui-auto-complete').exists()).toBe(true); + const input = wrapper.find('input'); + expect(input.element.value).toBe(''); + await input.trigger('focus'); + await nextTick(); + expect(wrapper.find('ul').element.childElementCount).toBe(5); + }); it('appendToBody & appendToBodyDirections', async () => { const wrapper = mount({ @@ -392,41 +392,41 @@ describe('auto-complete', () => { /> `, setup() { - const value = ref('') - const allowEmptyValueSearch = ref(true) + const value = ref(''); + const allowEmptyValueSearch = ref(true); const source = [ 'CC#', 'C', 'C++', 'CPython', 'CoffeeScript', - ] + ]; const appendToBodyDirections = ref({ originX: 'left', originY: 'bottom', overlayX: 'left', overlayY: 'top', - }) + }); return { value, source, allowEmptyValueSearch, appendToBodyDirections - } + }; } - }) - expect(wrapper.find('.devui-auto-complete').exists()).toBe(true) - const input = wrapper.find('input') - expect(input.element.value).toBe('') - await input.trigger('focus') - await nextTick() - await input.setValue('c') - await nextTick() - await wait(300) - await nextTick() - expect(wrapper.find('ul').element.childElementCount).toBe(5) - expect(wrapper.find('.selected').element.innerHTML).toBe('CC#') - }) + }); + expect(wrapper.find('.devui-auto-complete').exists()).toBe(true); + const input = wrapper.find('input'); + expect(input.element.value).toBe(''); + await input.trigger('focus'); + await nextTick(); + await input.setValue('c'); + await nextTick(); + await wait(300); + await nextTick(); + expect(wrapper.find('ul').element.childElementCount).toBe(5); + expect(wrapper.find('.selected').element.innerHTML).toBe('CC#'); + }); it('latestSource',async () => { const wrapper = mount({ @@ -441,37 +441,37 @@ describe('auto-complete', () => { `, setup(){ - const value = ref('') - const latestSource = ref(['JavaScript','TypeScript']) + const value = ref(''); + const latestSource = ref(['JavaScript','TypeScript']); const source = ref([ 'C#', 'C', 'C++', 'Java', 'JavaScript' - ]) - + ]); + return { value, source, latestSource - } + }; } - }) - expect(wrapper.find('.devui-auto-complete').exists()).toBe(true) - const input = wrapper.find('input') - expect(input.element.value).toBe('') - await input.trigger('click') - await nextTick() - expect(wrapper.find('ul .devui-popup-tips').exists()).toBe(true) - await input.setValue('j') - await wait(300) - await nextTick() - const li = wrapper.find('ul .selected') - li.trigger('click') - await nextTick() - expect(wrapper.vm.value).toBe('Java') - }) + }); + expect(wrapper.find('.devui-auto-complete').exists()).toBe(true); + const input = wrapper.find('input'); + expect(input.element.value).toBe(''); + await input.trigger('click'); + await nextTick(); + expect(wrapper.find('ul .devui-popup-tips').exists()).toBe(true); + await input.setValue('j'); + await wait(300); + await nextTick(); + const li = wrapper.find('ul .selected'); + li.trigger('click'); + await nextTick(); + expect(wrapper.vm.value).toBe('Java'); + }); it('enableLazyLoad',async () => { const wrapper = mount({ components: {'d-auto-complete': DAutoComplete }, @@ -487,7 +487,7 @@ describe('auto-complete', () => { `, setup(){ - const value = ref('') + const value = ref(''); const source = ref([ 'C#', 'C', @@ -510,61 +510,61 @@ describe('auto-complete', () => { 'C5', 'C6', 'C7', - ]) - const autoCompleteRef =ref(null) - + ]); + const autoCompleteRef =ref(null); + const loadMore = () => { setTimeout(() => { - source.value.push('lazyData'+source.value.length) - autoCompleteRef.value?.loadFinish() - },3000) - } + source.value.push('lazyData'+source.value.length); + autoCompleteRef.value?.loadFinish(); + },3000); + }; return { value, source, loadMore, autoCompleteRef - } + }; } - }) - expect(wrapper.find('.devui-auto-complete').exists()).toBe(true) - const input = wrapper.find('input') - expect(input.element.value).toBe('') - await input.setValue('c') - await nextTick() - expect(wrapper.find('.devui-dropdown-menu').exists()).toBe(true) - await wait(300) - await nextTick() - expect(wrapper.find('.devui-dropdown-item').exists()).toBe(true) - const ul = wrapper.find('.devui-list-unstyled') + }); + expect(wrapper.find('.devui-auto-complete').exists()).toBe(true); + const input = wrapper.find('input'); + expect(input.element.value).toBe(''); + await input.setValue('c'); + await nextTick(); + expect(wrapper.find('.devui-dropdown-menu').exists()).toBe(true); + await wait(300); + await nextTick(); + expect(wrapper.find('.devui-dropdown-item').exists()).toBe(true); + const ul = wrapper.find('.devui-list-unstyled'); const makeScroll = async ( dom: Element, name: 'scrollTop', offset: number ) => { - const eventTarget = dom === document.documentElement ? window : dom - dom[name] = offset + const eventTarget = dom === document.documentElement ? window : dom; + dom[name] = offset; const evt = new CustomEvent('scroll', { detail: { target: { [name]: offset, }, }, - }) - eventTarget.dispatchEvent(evt) - return await wait(3000) - } - await makeScroll(ul.element, 'scrollTop', 500) - await nextTick() - expect(wrapper.vm.value).toBe('c') - await nextTick() - await input.setValue('') - const length = wrapper.vm.source.length - expect(wrapper.vm.source[length - 1]).toBe('lazyData21') - await input.setValue('la') - await wait(300) - await nextTick() - expect(wrapper.find('.devui-dropdown-item').element.innerHTML).toBe('lazyData21') - }) -}) + }); + eventTarget.dispatchEvent(evt); + return await wait(3000); + }; + await makeScroll(ul.element, 'scrollTop', 500); + await nextTick(); + expect(wrapper.vm.value).toBe('c'); + await nextTick(); + await input.setValue(''); + const length = wrapper.vm.source.length; + expect(wrapper.vm.source[length - 1]).toBe('lazyData21'); + await input.setValue('la'); + await wait(300); + await nextTick(); + expect(wrapper.find('.devui-dropdown-item').element.innerHTML).toBe('lazyData21'); + }); +}); diff --git a/packages/devui-vue/devui/auto-complete/index.ts b/packages/devui-vue/devui/auto-complete/index.ts index ecfbe3545b..3924ccab54 100644 --- a/packages/devui-vue/devui/auto-complete/index.ts +++ b/packages/devui-vue/devui/auto-complete/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import AutoComplete from './src/auto-complete' +import type { App } from 'vue'; +import AutoComplete from './src/auto-complete'; AutoComplete.install = function(app: App): void { - app.component(AutoComplete.name, AutoComplete) -} + app.component(AutoComplete.name, AutoComplete); +}; -export { AutoComplete } +export { AutoComplete }; export default { title: 'AutoComplete 自动补全', category: '数据录入', status: '100%', install(app: App): void { - app.use(AutoComplete as any) + app.use(AutoComplete as any); } -} +}; diff --git a/packages/devui-vue/devui/auto-complete/src/auto-complete-types.ts b/packages/devui-vue/devui/auto-complete/src/auto-complete-types.ts index b3618cd2f2..779b6d65bf 100644 --- a/packages/devui-vue/devui/auto-complete/src/auto-complete-types.ts +++ b/packages/devui-vue/devui/auto-complete/src/auto-complete-types.ts @@ -1,14 +1,14 @@ -import type { PropType, ExtractPropTypes, InjectionKey, SetupContext, Ref } from 'vue' +import type { PropType, ExtractPropTypes, InjectionKey, SetupContext, Ref } from 'vue'; const defaultFormatter = (item) => (item ? item.label || item.toString() : ''); const defaultValueParse = (item) => item; // appendToBody使用 export type HorizontalConnectionPos = 'left' | 'center' | 'right'; export type VerticalConnectionPos = 'top' | 'center' | 'bottom'; export interface ConnectionPosition { - originX: HorizontalConnectionPos - originY: VerticalConnectionPos - overlayX: HorizontalConnectionPos - overlayY: VerticalConnectionPos + originX: HorizontalConnectionPos; + originY: VerticalConnectionPos; + overlayX: HorizontalConnectionPos; + overlayY: VerticalConnectionPos; } export const autoCompleteProps = { modelValue: { @@ -104,37 +104,37 @@ export const autoCompleteProps = { type:Function as PropType<() => void>, default:null } -} as const +} as const; -export type AutoCompleteProps = ExtractPropTypes +export type AutoCompleteProps = ExtractPropTypes; export interface AutoCompleteRootType { - ctx:SetupContext - props:AutoCompleteProps + ctx: SetupContext; + props: AutoCompleteProps; } -export type SearchFnType = (term: string) => Array -export type FormatterType = (item: any) => string -export type DefaultFuncType = (any?) => any -export type HandleSearch = (term?:string | string,enableLazyLoad?:boolean) => void -export type RecentlyFocus = (latestSource:Array) => void -export type InputDebounceCb = (...rest:any) => Promise -export type TransInputFocusEmit = (any?: any) => void -export type SelectOptionClick = (any?: any) => void -//弹出选择框参数 +export type SearchFnType = (term: string) => Array; +export type FormatterType = (item: any) => string; +export type DefaultFuncType = (any?) => any; +export type HandleSearch = (term?: string | string,enableLazyLoad?: boolean) => void; +export type RecentlyFocus = (latestSource: Array) => void; +export type InputDebounceCb = (...rest: any) => Promise; +export type TransInputFocusEmit = (any?: any) => void; +export type SelectOptionClick = (any?: any) => void; +// 弹出选择框参数 export type DropdownProps = { - props:AutoCompleteProps - searchList:Ref - searchStatus?:Ref - showNoResultItemTemplate:Ref - term?: string - visible: Ref - selectedIndex:Ref - selectOptionClick:HandleSearch - dropDownRef - showLoading:Ref - loadMore - latestSource - modelValue:Ref - hoverIndex:Ref -} -export const DropdownPropsKey:InjectionKey=Symbol('DropdownPropsKey') + props: AutoCompleteProps; + searchList: Ref; + searchStatus?: Ref; + showNoResultItemTemplate: Ref; + term?: string; + visible: Ref; + selectedIndex: Ref; + selectOptionClick: HandleSearch; + dropDownRef; + showLoading: Ref; + loadMore; + latestSource; + modelValue: Ref; + hoverIndex: Ref; +}; +export const DropdownPropsKey: InjectionKey=Symbol('DropdownPropsKey'); diff --git a/packages/devui-vue/devui/auto-complete/src/auto-complete.tsx b/packages/devui-vue/devui/auto-complete/src/auto-complete.tsx index 0f70a1e350..f508f92ec4 100644 --- a/packages/devui-vue/devui/auto-complete/src/auto-complete.tsx +++ b/packages/devui-vue/devui/auto-complete/src/auto-complete.tsx @@ -10,6 +10,7 @@ import './auto-complete.scss' import DAutoCompleteDropdown from './components/dropdown' import ClickOutside from '../../shared/devui-directive/clickoutside' import {FlexibleOverlay} from '../../overlay/src/flexible-overlay' + export default defineComponent({ name: 'DAutoComplete', directives: { ClickOutside }, diff --git a/packages/devui-vue/devui/auto-complete/src/components/dropdown.tsx b/packages/devui-vue/devui/auto-complete/src/components/dropdown.tsx index 38dd7ed3a3..6a5199276f 100644 --- a/packages/devui-vue/devui/auto-complete/src/components/dropdown.tsx +++ b/packages/devui-vue/devui/auto-complete/src/components/dropdown.tsx @@ -1,12 +1,12 @@ -import { defineComponent, inject } from 'vue' -import { DropdownPropsKey } from '../auto-complete-types' -import dLoading from '../../../loading/src/directive' +import { defineComponent, inject } from 'vue'; +import { DropdownPropsKey } from '../auto-complete-types'; +import dLoading from '../../../loading/src/directive'; // 后续会对接自带下拉组件,相关功能将全部抽离 export default defineComponent({ name: 'DAutoCompleteDropdown', directives: {dLoading}, setup(props,ctx) { - const propsData = inject(DropdownPropsKey) + const propsData = inject(DropdownPropsKey); const { visible, selectedIndex, @@ -20,7 +20,7 @@ export default defineComponent({ latestSource, modelValue, hoverIndex - } = propsData + } = propsData; const { disabled, maxHeight, @@ -28,12 +28,12 @@ export default defineComponent({ formatter, disabledKey, isSearching, - } = propsData.props + } = propsData.props; - const onSelect =(item:any)=>{ - if(item[disabledKey]){return} - selectOptionClick(item) - } + const onSelect =(item: any)=>{ + if(item[disabledKey]){return;} + selectOptionClick(item); + }; return () => { return (
0)||(ctx.slots.noResultItemTemplate&&showNoResultItemTemplate.value)||(isSearching&&ctx.slots.searchingTemplate&&searchStatus.value)} > -
    - {/* 搜索中展示 */} - { - isSearching&&ctx.slots.searchingTemplate&&searchStatus.value +
      + {/* 搜索中展示 */} + { + isSearching&&ctx.slots.searchingTemplate&&searchStatus.value &&
    • -
      - { - ctx.slots.searchingTemplate() - } -
      +
      + { + ctx.slots.searchingTemplate() + } +
      + +
    • + } + { + latestSource.value&&!modelValue.value&&
    • 最近输入
    • + } + {/* 展示 */} + { + !showNoResultItemTemplate.value&&!searchStatus.value&&searchList!=null&&searchList.value.length>0&&searchList.value.map((item,index)=>{ + return ( +
    • onSelect(item)} + class={[ + 'devui-dropdown-item',selectedIndex.value==index&&'selected', + {'disabled': disabledKey && item[disabledKey]}, + {'devui-dropdown-bg': hoverIndex.value== index}, -
    • - } - { - latestSource.value&&!modelValue.value&&
    • 最近输入
    • - } - {/* 展示 */} - { - !showNoResultItemTemplate.value&&!searchStatus.value&&searchList!=null&&searchList.value.length>0&&searchList.value.map((item,index)=>{ - return ( -
    • onSelect(item)} - class={[ - 'devui-dropdown-item',selectedIndex.value==index&&'selected', - {'disabled': disabledKey && item[disabledKey]}, - {'devui-dropdown-bg': hoverIndex.value== index}, - - ]} - title={formatter(item)} - key={formatter(item)} - > - { - ctx.slots.itemTemplate?ctx.slots.itemTemplate(item,index):formatter(item) - } -
    • - ) - }) - } + ]} + title={formatter(item)} + key={formatter(item)} + > + { + ctx.slots.itemTemplate?ctx.slots.itemTemplate(item,index):formatter(item) + } + + ); + }) + } - {/* 没有匹配结果传入了noResultItemTemplate*/} - { - !searchStatus.value&&searchList.value.length==0&&ctx.slots.noResultItemTemplate&&showNoResultItemTemplate.value&& + {/* 没有匹配结果传入了noResultItemTemplate*/} + { + !searchStatus.value&&searchList.value.length==0&&ctx.slots.noResultItemTemplate&&showNoResultItemTemplate.value&&
    • -
      - {ctx.slots.noResultItemTemplate()} -
      +
      + {ctx.slots.noResultItemTemplate()} +
    • - } -
    -
- ) - } + } + + + ); + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/auto-complete/src/composables/use-custom-template.ts b/packages/devui-vue/devui/auto-complete/src/composables/use-custom-template.ts index 5ddd8a3ec9..006c9a924e 100644 --- a/packages/devui-vue/devui/auto-complete/src/composables/use-custom-template.ts +++ b/packages/devui-vue/devui/auto-complete/src/composables/use-custom-template.ts @@ -1,37 +1,37 @@ import { Ref, SetupContext } from 'vue'; -export default function useCustomTemplate(ctx:SetupContext,modelValue:Ref): any { - const itemTemplate = (item, index) => { - const arr = { item, index } - if (ctx.slots.itemTemplate) { - return ctx.slots.itemTemplate(arr) - } - return null +export default function useCustomTemplate(ctx: SetupContext,modelValue: Ref): any { + const itemTemplate = (item, index) => { + const arr = { item, index }; + if (ctx.slots.itemTemplate) { + return ctx.slots.itemTemplate(arr); } - const noResultItemTemplate = () => { - if (ctx.slots.noResultItemTemplate) { - return ctx.slots.noResultItemTemplate(modelValue.value) - } - return null + return null; + }; + const noResultItemTemplate = () => { + if (ctx.slots.noResultItemTemplate) { + return ctx.slots.noResultItemTemplate(modelValue.value); } - const searchingTemplate = () => { - if (ctx.slots.searchingTemplate) { - return ctx.slots.searchingTemplate(modelValue.value) - } - return null + return null; + }; + const searchingTemplate = () => { + if (ctx.slots.searchingTemplate) { + return ctx.slots.searchingTemplate(modelValue.value); } - const customRenderSolts = () => { - const slots = {} - if (ctx.slots.itemTemplate) { - slots['itemTemplate'] = itemTemplate - } - if (ctx.slots.noResultItemTemplate) { - slots['noResultItemTemplate'] = noResultItemTemplate - } - if (ctx.slots.searchingTemplate) { - slots['searchingTemplate'] = searchingTemplate - } - return slots + return null; + }; + const customRenderSolts = () => { + const slots = {}; + if (ctx.slots.itemTemplate) { + slots['itemTemplate'] = itemTemplate; } - return {customRenderSolts} -} \ No newline at end of file + if (ctx.slots.noResultItemTemplate) { + slots['noResultItemTemplate'] = noResultItemTemplate; + } + if (ctx.slots.searchingTemplate) { + slots['searchingTemplate'] = searchingTemplate; + } + return slots; + }; + return {customRenderSolts}; +} diff --git a/packages/devui-vue/devui/auto-complete/src/composables/use-input-handle.ts b/packages/devui-vue/devui/auto-complete/src/composables/use-input-handle.ts index 090a867276..559ee9d2aa 100644 --- a/packages/devui-vue/devui/auto-complete/src/composables/use-input-handle.ts +++ b/packages/devui-vue/devui/auto-complete/src/composables/use-input-handle.ts @@ -1,63 +1,63 @@ import { ref, Ref, SetupContext } from 'vue'; -import {HandleSearch,RecentlyFocus,InputDebounceCb,TransInputFocusEmit} from '../auto-complete-types' -export default function useInputHandle(ctx: SetupContext,searchList:Ref,showNoResultItemTemplate:Ref, modelValue:Ref,disabled:Ref,delay:Ref,handleSearch: HandleSearch, transInputFocusEmit:Ref,recentlyFocus:RecentlyFocus,latestSource:Ref>): any { - const visible = ref(false) - const inputRef = ref() - const searchStatus = ref(false) - const debounce =(cb:InputDebounceCb,time:number) =>{ - let timer - return (...args)=>{ - if(timer){ - clearTimeout(timer) - } - timer = setTimeout(async ()=>{ - searchStatus.value=true - await cb(...args) - searchStatus.value=false - },time) +import {HandleSearch,RecentlyFocus,InputDebounceCb,TransInputFocusEmit} from '../auto-complete-types'; +export default function useInputHandle(ctx: SetupContext,searchList: Ref,showNoResultItemTemplate: Ref, modelValue: Ref,disabled: Ref,delay: Ref,handleSearch: HandleSearch, transInputFocusEmit: Ref,recentlyFocus: RecentlyFocus,latestSource: Ref>): any { + const visible = ref(false); + const inputRef = ref(); + const searchStatus = ref(false); + const debounce =(cb: InputDebounceCb,time: number) =>{ + let timer; + return (...args)=>{ + if(timer){ + clearTimeout(timer); + } + timer = setTimeout(async ()=>{ + searchStatus.value=true; + await cb(...args); + searchStatus.value=false; + },time); + }; + }; + const onInputCb = async(value: string)=>{ + await handleSearch(value); + visible.value = true; + }; + const onInputDebounce = debounce(onInputCb,delay.value); + const onInput =(e: Event) => { + const inp = e.target as HTMLInputElement; + searchStatus.value=false; + showNoResultItemTemplate.value=false; + ctx.emit('update:modelValue', inp.value); + onInputDebounce(inp.value); + }; + const onFocus =() => { + handleSearch(modelValue.value); + recentlyFocus(latestSource.value); + transInputFocusEmit.value && transInputFocusEmit.value(); + }; + const handleClose = ()=>{ + visible.value=false; + searchStatus.value=false; + showNoResultItemTemplate.value=false; + }; + const toggleMenu =()=>{ + if(!disabled.value){ + if(visible.value){ + handleClose(); + }else{ + visible.value=true; + if (ctx.slots.noResultItemTemplate&&searchList.value.length==0&&modelValue.value.trim()!='') { + showNoResultItemTemplate.value=true; } + } } - const onInputCb = async(value:string)=>{ - await handleSearch(value) - visible.value = true - } - const onInputDebounce = debounce(onInputCb,delay.value) - const onInput =(e: Event) => { - const inp = e.target as HTMLInputElement - searchStatus.value=false - showNoResultItemTemplate.value=false - ctx.emit('update:modelValue', inp.value) - onInputDebounce(inp.value) - } - const onFocus =() => { - handleSearch(modelValue.value) - recentlyFocus(latestSource.value) - transInputFocusEmit.value && transInputFocusEmit.value() - } - const handleClose = ()=>{ - visible.value=false - searchStatus.value=false - showNoResultItemTemplate.value=false - } - const toggleMenu =()=>{ - if(!disabled.value){ - if(visible.value){ - handleClose() - }else{ - visible.value=true - if (ctx.slots.noResultItemTemplate&&searchList.value.length==0&&modelValue.value.trim()!='') { - showNoResultItemTemplate.value=true - } - } - } - } - return { - handleClose, - toggleMenu, - onInput, - onFocus, - inputRef, - visible, - searchStatus - } -} \ No newline at end of file + }; + return { + handleClose, + toggleMenu, + onInput, + onFocus, + inputRef, + visible, + searchStatus + }; +} diff --git a/packages/devui-vue/devui/auto-complete/src/composables/use-keyboard-select.ts b/packages/devui-vue/devui/auto-complete/src/composables/use-keyboard-select.ts index ad04b34793..3ddc8abd0a 100644 --- a/packages/devui-vue/devui/auto-complete/src/composables/use-keyboard-select.ts +++ b/packages/devui-vue/devui/auto-complete/src/composables/use-keyboard-select.ts @@ -2,54 +2,54 @@ import { nextTick, ref, Ref } from 'vue'; import { DefaultFuncType, SelectOptionClick } from '../auto-complete-types'; export default function useKeyBoardHandle(dropDownRef: Ref, visible: Ref, searchList: Ref>, selectedIndex: Ref, searchStatus: Ref, showNoResultItemTemplate: Ref, selectOptionClick: SelectOptionClick, handleClose: DefaultFuncType): any { - const hoverIndex = ref(selectedIndex.value??0) - const scrollToActive = (index: number) => { - const ul = dropDownRef.value - const li = ul.children[index] - nextTick(() => { - if (li.scrollIntoViewIfNeeded) { - li.scrollIntoViewIfNeeded(false) - } else { - const containerInfo = ul.getBoundingClientRect() - const elementInfo = li.getBoundingClientRect() - if (elementInfo.bottom > containerInfo.bottom || elementInfo.top < containerInfo.top) { - li.scrollIntoView(false) - } - } - }) - } - const handlekeyDown = (e: KeyboardEvent) => { - const keyCode = e.key || e.code - if (keyCode === 'Escape' && ( (visible.value && searchList.value.length) || searchStatus.value||showNoResultItemTemplate.value)) { - handleClose() - return - } - const status = visible.value && searchList.value.length && !searchStatus.value && !showNoResultItemTemplate.value - if (keyCode === 'ArrowDown' && status) { - if (hoverIndex.value === searchList.value.length - 1) { - hoverIndex.value = 0; - scrollToActive(hoverIndex.value); - return; - } - hoverIndex.value = hoverIndex.value + 1; - scrollToActive(hoverIndex.value); - } else if (keyCode === 'ArrowUp' && status) { - if (hoverIndex.value === 0) { - hoverIndex.value = searchList.value.length - 1; - scrollToActive(hoverIndex.value); - return; - } - hoverIndex.value = hoverIndex.value - 1; - scrollToActive(hoverIndex.value); - } - if (keyCode === 'Enter' && status) { - selectOptionClick(searchList.value[hoverIndex.value]) - hoverIndex.value=selectedIndex.value??0 - return + const hoverIndex = ref(selectedIndex.value??0); + const scrollToActive = (index: number) => { + const ul = dropDownRef.value; + const li = ul.children[index]; + nextTick(() => { + if (li.scrollIntoViewIfNeeded) { + li.scrollIntoViewIfNeeded(false); + } else { + const containerInfo = ul.getBoundingClientRect(); + const elementInfo = li.getBoundingClientRect(); + if (elementInfo.bottom > containerInfo.bottom || elementInfo.top < containerInfo.top) { + li.scrollIntoView(false); } + } + }); + }; + const handlekeyDown = (e: KeyboardEvent) => { + const keyCode = e.key || e.code; + if (keyCode === 'Escape' && ((visible.value && searchList.value.length) || searchStatus.value||showNoResultItemTemplate.value)) { + handleClose(); + return; + } + const status = visible.value && searchList.value.length && !searchStatus.value && !showNoResultItemTemplate.value; + if (keyCode === 'ArrowDown' && status) { + if (hoverIndex.value === searchList.value.length - 1) { + hoverIndex.value = 0; + scrollToActive(hoverIndex.value); + return; + } + hoverIndex.value = hoverIndex.value + 1; + scrollToActive(hoverIndex.value); + } else if (keyCode === 'ArrowUp' && status) { + if (hoverIndex.value === 0) { + hoverIndex.value = searchList.value.length - 1; + scrollToActive(hoverIndex.value); + return; + } + hoverIndex.value = hoverIndex.value - 1; + scrollToActive(hoverIndex.value); } - return { - hoverIndex, - handlekeyDown + if (keyCode === 'Enter' && status) { + selectOptionClick(searchList.value[hoverIndex.value]); + hoverIndex.value=selectedIndex.value??0; + return; } -} \ No newline at end of file + }; + return { + hoverIndex, + handlekeyDown + }; +} diff --git a/packages/devui-vue/devui/auto-complete/src/composables/use-lazy-handle.ts b/packages/devui-vue/devui/auto-complete/src/composables/use-lazy-handle.ts index 96add63862..445f3a66a8 100644 --- a/packages/devui-vue/devui/auto-complete/src/composables/use-lazy-handle.ts +++ b/packages/devui-vue/devui/auto-complete/src/composables/use-lazy-handle.ts @@ -1,30 +1,30 @@ -import { ref,SetupContext } from 'vue' -import { AutoCompleteProps,HandleSearch } from '../auto-complete-types' -export default function useLazyHandle(props: AutoCompleteProps,ctx:SetupContext,handleSearch:HandleSearch):any { - const showLoading = ref(false) - const dropDownRef = ref() +import { ref,SetupContext } from 'vue'; +import { AutoCompleteProps,HandleSearch } from '../auto-complete-types'; +export default function useLazyHandle(props: AutoCompleteProps,ctx: SetupContext,handleSearch: HandleSearch): any { + const showLoading = ref(false); + const dropDownRef = ref(); const loadMore = () => { - if(!props.enableLazyLoad && showLoading) return - const dropDownValue = dropDownRef.value - const height = dropDownValue.scrollHeight - const scrollTop = dropDownValue.clientHeight + dropDownValue.scrollTop + if(!props.enableLazyLoad && showLoading) {return;} + const dropDownValue = dropDownRef.value; + const height = dropDownValue.scrollHeight; + const scrollTop = dropDownValue.clientHeight + dropDownValue.scrollTop; if(scrollTop >= height && scrollTop >= props.maxHeight) { - props.loadMore() - showLoading.value = true + props.loadMore(); + showLoading.value = true; } - } - ctx.expose({loadFinish}) + }; + ctx.expose({loadFinish}); async function loadFinish (){ - await handleSearch(props.modelValue,props.enableLazyLoad) - showLoading.value = false + await handleSearch(props.modelValue,props.enableLazyLoad); + showLoading.value = false; } return { showLoading, dropDownRef, loadMore, - } + }; } diff --git a/packages/devui-vue/devui/auto-complete/src/composables/use-searchfn.ts b/packages/devui-vue/devui/auto-complete/src/composables/use-searchfn.ts index 8d90a98811..aae2dd84c2 100644 --- a/packages/devui-vue/devui/auto-complete/src/composables/use-searchfn.ts +++ b/packages/devui-vue/devui/auto-complete/src/composables/use-searchfn.ts @@ -1,45 +1,45 @@ import { ref, Ref, SetupContext } from 'vue'; import { FormatterType, SearchFnType } from '../auto-complete-types'; -export default function useSearchFn(ctx: SetupContext,allowEmptyValueSearch:Ref,source:Ref>,searchFn:Ref,formatter:Ref): any { - const searchList = ref([]) - const showNoResultItemTemplate = ref(false) - const handleSearch = async (term: string,enableLazyLoad:boolean) => { - if (term == ''&&!allowEmptyValueSearch.value) { - searchList.value = [] - showNoResultItemTemplate.value=false - return - } - let arr = [] - term = term.toLowerCase() - if(enableLazyLoad) { - arr = source.value - }else if (!searchFn.value) { - source.value.forEach((item) => { - let cur = formatter.value(item) - cur = cur.toLowerCase() - if (cur.startsWith(term)) { - arr.push(item) - } - }) - } else { - arr = await searchFn.value(term) - } - searchList.value = arr - if(searchList.value.length==0){ - showNoResultItemTemplate.value=true - }else{ - showNoResultItemTemplate.value=false - } +export default function useSearchFn(ctx: SetupContext,allowEmptyValueSearch: Ref,source: Ref>,searchFn: Ref,formatter: Ref): any { + const searchList = ref([]); + const showNoResultItemTemplate = ref(false); + const handleSearch = async (term: string,enableLazyLoad: boolean) => { + if (term == ''&&!allowEmptyValueSearch.value) { + searchList.value = []; + showNoResultItemTemplate.value=false; + return; } - const recentlyFocus = (latestSource:Array) => { - if(latestSource) { - searchList.value = latestSource + let arr = []; + term = term.toLowerCase(); + if(enableLazyLoad) { + arr = source.value; + }else if (!searchFn.value) { + source.value.forEach((item) => { + let cur = formatter.value(item); + cur = cur.toLowerCase(); + if (cur.startsWith(term)) { + arr.push(item); } + }); + } else { + arr = await searchFn.value(term); + } + searchList.value = arr; + if(searchList.value.length==0){ + showNoResultItemTemplate.value=true; + }else{ + showNoResultItemTemplate.value=false; } - return { - handleSearch, - recentlyFocus, - searchList, - showNoResultItemTemplate + }; + const recentlyFocus = (latestSource: Array) => { + if(latestSource) { + searchList.value = latestSource; } + }; + return { + handleSearch, + recentlyFocus, + searchList, + showNoResultItemTemplate + }; } diff --git a/packages/devui-vue/devui/auto-complete/src/composables/use-select-handle.ts b/packages/devui-vue/devui/auto-complete/src/composables/use-select-handle.ts index 8261410c70..1f60202f00 100644 --- a/packages/devui-vue/devui/auto-complete/src/composables/use-select-handle.ts +++ b/packages/devui-vue/devui/auto-complete/src/composables/use-select-handle.ts @@ -1,25 +1,25 @@ import { ref, Ref, SetupContext } from 'vue'; import { DefaultFuncType,FormatterType,HandleSearch } from '../auto-complete-types'; -export default function useSelectHandle(ctx: SetupContext,searchList: Ref>, selectValue: Ref, handleSearch: HandleSearch,formatter: Ref,handleClose:DefaultFuncType): any { - const selectedIndex = ref(0) +export default function useSelectHandle(ctx: SetupContext,searchList: Ref>, selectValue: Ref, handleSearch: HandleSearch,formatter: Ref,handleClose: DefaultFuncType): any { + const selectedIndex = ref(0); const getListIndex = (item: string) => { if (searchList.value.length == 0) { - return 0 + return 0; } - const ind = searchList.value.indexOf(item) - return ind == -1 ? 0 : ind - } + const ind = searchList.value.indexOf(item); + return ind == -1 ? 0 : ind; + }; const selectOptionClick = async(item: any) => { - const cur = formatter.value(item) - ctx.emit('update:modelValue', cur) - handleClose() - await handleSearch(cur) - selectedIndex.value = getListIndex(cur) - selectValue.value && selectValue.value() - } + const cur = formatter.value(item); + ctx.emit('update:modelValue', cur); + handleClose(); + await handleSearch(cur); + selectedIndex.value = getListIndex(cur); + selectValue.value && selectValue.value(); + }; return { selectedIndex, selectOptionClick - } -} \ No newline at end of file + }; +} diff --git a/packages/devui-vue/devui/avatar/__tests__/avatar.spec.ts b/packages/devui-vue/devui/avatar/__tests__/avatar.spec.ts index 18dc946597..9c7e925ef7 100644 --- a/packages/devui-vue/devui/avatar/__tests__/avatar.spec.ts +++ b/packages/devui-vue/devui/avatar/__tests__/avatar.spec.ts @@ -1,5 +1,5 @@ -import { mount } from '@vue/test-utils' -import Avatar from '../src/avatar' +import { mount } from '@vue/test-utils'; +import Avatar from '../src/avatar'; describe('avatar', () => { describe('name text shown correctly', () => { @@ -8,52 +8,52 @@ describe('avatar', () => { props: { name: '组件头像', }, - }) - expect(wrapper.find('.devui-avatar-style').text()).toBe('头像') - }) + }); + expect(wrapper.find('.devui-avatar-style').text()).toBe('头像'); + }); it('should only show one character when width less than 30', () => { const wrapper = mount(Avatar, { props: { name: '组件头像', width: 25, }, - }) - expect(wrapper.find('.devui-avatar-style').text()).toBe('组') - }) + }); + expect(wrapper.find('.devui-avatar-style').text()).toBe('组'); + }); it('one word name pick first two character', () => { - const name = 'MyAvatar' + const name = 'MyAvatar'; const wrapper = mount(Avatar, { props: { name, }, - }) - expect(wrapper.find('.devui-avatar-style').text()).toBe('MY') - }) + }); + expect(wrapper.find('.devui-avatar-style').text()).toBe('MY'); + }); it('display origin name when name length less than 2', () => { const wrapper = mount(Avatar, { props: { name: 'A', }, - }) - expect(wrapper.find('.devui-avatar-style').text()).toBe('A') - }) + }); + expect(wrapper.find('.devui-avatar-style').text()).toBe('A'); + }); it('should empty name display none text', () => { const wrapper = mount(Avatar, { props: { name: '', }, - }) - expect(wrapper.find('svg').exists()).toBe(true) - }) + }); + expect(wrapper.find('svg').exists()).toBe(true); + }); it('two words name pick first character of two words', () => { const wrapper = mount(Avatar, { props: { name: 'Avatar1 Avatar2', }, - }) - expect(wrapper.find('.devui-avatar-style').text()).toBe('AA') - }) - }) + }); + expect(wrapper.find('.devui-avatar-style').text()).toBe('AA'); + }); + }); describe('background should be ok', () => { it('should be male background', () => { @@ -62,18 +62,18 @@ describe('avatar', () => { name: 'avatar', gender: 'male', }, - }) - expect(wrapper.find('.devui-avatar-background-1').exists()).toBe(true) - }) + }); + expect(wrapper.find('.devui-avatar-background-1').exists()).toBe(true); + }); it('should be female background', () => { const wrapper = mount(Avatar, { props: { name: 'avatar', gender: 'female', }, - }) - expect(wrapper.find('.devui-avatar-background-0').exists()).toBe(true) - }) + }); + expect(wrapper.find('.devui-avatar-background-0').exists()).toBe(true); + }); it('gender error should throw error', () => { expect(() => { mount(Avatar, { @@ -81,10 +81,10 @@ describe('avatar', () => { name: 'avatar', gender: 'unknown', }, - }) - }).toThrowError('gender must be "Male" or "Female"') - }) - }) + }); + }).toThrowError('gender must be "Male" or "Female"'); + }); + }); describe('custom avatar', () => { it('should custom text display correct', () => { @@ -94,20 +94,20 @@ describe('avatar', () => { width: 80, height: 80, }, - }) - expect(wrapper.find('.devui-avatar-style').text()).toBe('自定义') + }); + expect(wrapper.find('.devui-avatar-style').text()).toBe('自定义'); expect( wrapper .find('.devui-avatar-style') .attributes('style') .includes('height: 80px') - ).toBe(true) + ).toBe(true); expect( wrapper .find('.devui-avatar-style') .attributes('style') .includes('width: 80px') - ).toBe(true) - }) - }) -}) + ).toBe(true); + }); + }); +}); diff --git a/packages/devui-vue/devui/avatar/index.ts b/packages/devui-vue/devui/avatar/index.ts index d7700bf75f..bbebb53186 100644 --- a/packages/devui-vue/devui/avatar/index.ts +++ b/packages/devui-vue/devui/avatar/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Avatar from './src/avatar' +import type { App } from 'vue'; +import Avatar from './src/avatar'; Avatar.install = function (app: App) { - app.component(Avatar.name, Avatar) -} + app.component(Avatar.name, Avatar); +}; -export { Avatar } +export { Avatar }; export default { title: 'Avatar 头像', category: '数据展示', status: '100%', install(app: App): void { - app.use(Avatar as any) + app.use(Avatar as any); }, -} +}; diff --git a/packages/devui-vue/devui/avatar/src/avatar-body-icon.tsx b/packages/devui-vue/devui/avatar/src/avatar-body-icon.tsx index 361bf136ae..47ae4a4e35 100644 --- a/packages/devui-vue/devui/avatar/src/avatar-body-icon.tsx +++ b/packages/devui-vue/devui/avatar/src/avatar-body-icon.tsx @@ -1,5 +1,5 @@ -import { defineComponent } from 'vue' -import { IconBody } from './icon-body' +import { defineComponent } from 'vue'; +import { IconBody } from './icon-body'; export default defineComponent({ name: 'AvatarBodyIcon', props: { @@ -13,7 +13,7 @@ export default defineComponent({ }, }, render() { - const { width, height } = this - return + const { width, height } = this; + return ; }, -}) +}); diff --git a/packages/devui-vue/devui/avatar/src/avatar-nobody-icon.tsx b/packages/devui-vue/devui/avatar/src/avatar-nobody-icon.tsx index 9553ad45ca..8d66fb2d9b 100644 --- a/packages/devui-vue/devui/avatar/src/avatar-nobody-icon.tsx +++ b/packages/devui-vue/devui/avatar/src/avatar-nobody-icon.tsx @@ -1,5 +1,5 @@ -import { defineComponent } from 'vue' -import { IconNobody } from './icon-nobody' +import { defineComponent } from 'vue'; +import { IconNobody } from './icon-nobody'; export default defineComponent({ name: 'AvatarNobodyIcon', @@ -14,7 +14,7 @@ export default defineComponent({ }, }, render() { - const { width, height } = this - return + const { width, height } = this; + return ; }, -}) +}); diff --git a/packages/devui-vue/devui/avatar/src/avatar.tsx b/packages/devui-vue/devui/avatar/src/avatar.tsx index 3eda9d2b79..0cc11f4d2c 100644 --- a/packages/devui-vue/devui/avatar/src/avatar.tsx +++ b/packages/devui-vue/devui/avatar/src/avatar.tsx @@ -1,9 +1,9 @@ -import { defineComponent, watch, toRefs, ref } from 'vue' +import { defineComponent, watch, toRefs, ref } from 'vue'; -import AvatarBodyIcon from './avatar-body-icon' -import AvatarNoBodyIcon from './avatar-nobody-icon' +import AvatarBodyIcon from './avatar-body-icon'; +import AvatarNoBodyIcon from './avatar-nobody-icon'; -import './avatar.scss' +import './avatar.scss'; export default defineComponent({ name: 'DAvatar', @@ -39,87 +39,87 @@ export default defineComponent({ }, setup(props) { const { name, width, height, customText, gender, imgSrc, isRound } = - toRefs(props) - const isNobody = ref(true) - const isErrorImg = ref(false) - const fontSize = ref(12) - const code = ref() - const nameDisplay = ref() + toRefs(props); + const isNobody = ref(true); + const isErrorImg = ref(false); + const fontSize = ref(12); + const code = ref(); + const nameDisplay = ref(); const calcValues = (nameInput: string): void => { - const userName = nameInput - const minNum = Math.min(width.value, height.value) + const userName = nameInput; + const minNum = Math.min(width.value, height.value); if (userName) { - isNobody.value = false - setDisplayName(userName, minNum) + isNobody.value = false; + setDisplayName(userName, minNum); } else if (userName === '') { - isNobody.value = false - nameDisplay.value = '' + isNobody.value = false; + nameDisplay.value = ''; } else { - isNobody.value = true + isNobody.value = true; } - fontSize.value = minNum / 4 + 3 - } + fontSize.value = minNum / 4 + 3; + }; const setDisplayName = (name: string, width: number): void => { if (customText.value) { - nameDisplay.value = customText.value - getBackgroundColor(customText.value.substr(0, 1)) - return + nameDisplay.value = customText.value; + getBackgroundColor(customText.value.substr(0, 1)); + return; } if (name.length < 2) { - nameDisplay.value = name + nameDisplay.value = name; } else { // 以中文开头显示最后两个字符 if (/^[\u4e00-\u9fa5]/.test(name)) { - nameDisplay.value = name.substr(name.length - 2, 2) + nameDisplay.value = name.substr(name.length - 2, 2); // 英文开头 } else if (/^[A-Za-z]/.test(name)) { // 含有两个及以上,包含空格,下划线,中划线分隔符的英文名取前两个字母的首字母 if (/[_ -]/.test(name)) { - const str_before = name.split(/_|-|\s+/)[0] - const str_after = name.split(/_|-|\s+/)[1] + const str_before = name.split(/_|-|\s+/)[0]; + const str_after = name.split(/_|-|\s+/)[1]; nameDisplay.value = str_before.substr(0, 1).toUpperCase() + - str_after.substr(0, 1).toUpperCase() + str_after.substr(0, 1).toUpperCase(); } else { // 一个英文名的情况显示前两个字母 - nameDisplay.value = name.substr(0, 2).toUpperCase() + nameDisplay.value = name.substr(0, 2).toUpperCase(); } } else { // 非中英文开头默认取前两个字符 - nameDisplay.value = name.substr(0, 2) + nameDisplay.value = name.substr(0, 2); } } if (width < 30) { - nameDisplay.value = name.substr(0, 1).toUpperCase() + nameDisplay.value = name.substr(0, 1).toUpperCase(); } - getBackgroundColor(name.substr(0, 1)) - } + getBackgroundColor(name.substr(0, 1)); + }; const getBackgroundColor = (char: string): void => { if (gender.value) { if (gender.value.toLowerCase() === 'male') { - code.value = 1 + code.value = 1; } else if (gender.value.toLowerCase() === 'female') { - code.value = 0 + code.value = 0; } else { - throw new Error('gender must be "Male" or "Female"') + throw new Error('gender must be "Male" or "Female"'); } - return + return; } - const unicode = char.charCodeAt(0) - code.value = unicode % 2 - } + const unicode = char.charCodeAt(0); + code.value = unicode % 2; + }; const showErrorAvatar = (): void => { - isErrorImg.value = true - } + isErrorImg.value = true; + }; - calcValues(customText.value ? customText.value : name.value) + calcValues(customText.value ? customText.value : name.value); watch([name, width, height, customText, gender], () => { - calcValues(customText.value ? customText.value : name.value) - }) + calcValues(customText.value ? customText.value : name.value); + }); return { showErrorAvatar, isErrorImg, @@ -127,7 +127,7 @@ export default defineComponent({ fontSize, nameDisplay, isNobody, - } + }; }, render() { const { @@ -141,7 +141,7 @@ export default defineComponent({ fontSize, nameDisplay, isNobody, - } = this + } = this; const imgElement = ( - ) - const hasImgSrc = imgSrc && !isErrorImg ? imgElement : null + ); + const hasImgSrc = imgSrc && !isErrorImg ? imgElement : null; const nameElement = ( {nameDisplay} - ) + ); const hasNameDisplay = - !imgSrc && !isNobody && nameDisplay?.length !== 0 ? nameElement : null + !imgSrc && !isNobody && nameDisplay?.length !== 0 ? nameElement : null; const noNameElement = ( - ) + ); const hasNoDisplayName = - !imgSrc && !isNobody && nameDisplay?.length === 0 ? noNameElement : null + !imgSrc && !isNobody && nameDisplay?.length === 0 ? noNameElement : null; const noBodyElement = ( - ) - const noBody = (!imgSrc && isNobody) || isErrorImg ? noBodyElement : null + ); + const noBody = (!imgSrc && isNobody) || isErrorImg ? noBodyElement : null; return ( {hasImgSrc} @@ -202,6 +202,6 @@ export default defineComponent({ {hasNoDisplayName} {noBody} - ) + ); }, -}) +}); diff --git a/packages/devui-vue/devui/avatar/src/icon-body.tsx b/packages/devui-vue/devui/avatar/src/icon-body.tsx index f9078521a8..df6bcc6b4a 100644 --- a/packages/devui-vue/devui/avatar/src/icon-body.tsx +++ b/packages/devui-vue/devui/avatar/src/icon-body.tsx @@ -1,5 +1,5 @@ -export const IconBody = (props: { width: number; height: number; }) => { - const { width, height } = props +export const IconBody = (props: { width: number; height: number }) => { + const { width, height } = props; return ( { > - ) -} + ); +}; diff --git a/packages/devui-vue/devui/avatar/src/icon-nobody.tsx b/packages/devui-vue/devui/avatar/src/icon-nobody.tsx index 20359e40f3..cded157eba 100644 --- a/packages/devui-vue/devui/avatar/src/icon-nobody.tsx +++ b/packages/devui-vue/devui/avatar/src/icon-nobody.tsx @@ -1,5 +1,5 @@ -export const IconNobody = (props: { width: number; height: number; }) => { - const { width, height } = props +export const IconNobody = (props: { width: number; height: number }) => { + const { width, height } = props; return ( { > - ) -} + ); +}; diff --git a/packages/devui-vue/devui/back-top/__tests__/back-top.spec.ts b/packages/devui-vue/devui/back-top/__tests__/back-top.spec.ts index 81a160a5a1..7f5a96b48f 100644 --- a/packages/devui-vue/devui/back-top/__tests__/back-top.spec.ts +++ b/packages/devui-vue/devui/back-top/__tests__/back-top.spec.ts @@ -4,5 +4,5 @@ import { BackTop } from '../index'; describe('back-top test', () => { it('back-top init render', async () => { // todo - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/back-top/index.ts b/packages/devui-vue/devui/back-top/index.ts index cdc6e7eb8b..ec89d6f80c 100644 --- a/packages/devui-vue/devui/back-top/index.ts +++ b/packages/devui-vue/devui/back-top/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import BackTop from './src/back-top' +import type { App } from 'vue'; +import BackTop from './src/back-top'; BackTop.install = function (app: App): void { - app.component(BackTop.name, BackTop) -} + app.component(BackTop.name, BackTop); +}; -export { BackTop } +export { BackTop }; export default { title: 'BackTop 回到顶部', category: '导航', status: '60%', // TODO: 组件若开发完成则填入"已完成",并删除该注释 install(app: App): void { - app.use(BackTop as any) - } -} + app.use(BackTop as any); + }, +}; diff --git a/packages/devui-vue/devui/back-top/src/back-top-types.ts b/packages/devui-vue/devui/back-top/src/back-top-types.ts index 1209ed581c..fc0e2b859b 100644 --- a/packages/devui-vue/devui/back-top/src/back-top-types.ts +++ b/packages/devui-vue/devui/back-top/src/back-top-types.ts @@ -1,9 +1,9 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; export type Position = { - bottom: string - right: string -} + bottom: string; + right: string; +}; export const backTopProps = { bottom: { @@ -22,6 +22,6 @@ export const backTopProps = { type: Number, default: 300 } -} as const +} as const; -export type BackTopProps = ExtractPropTypes +export type BackTopProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/back-top/src/back-top.tsx b/packages/devui-vue/devui/back-top/src/back-top.tsx index fa08d4857c..2c05b691d6 100644 --- a/packages/devui-vue/devui/back-top/src/back-top.tsx +++ b/packages/devui-vue/devui/back-top/src/back-top.tsx @@ -1,19 +1,19 @@ -import { defineComponent, onMounted, ref } from 'vue' -import { backTopProps, BackTopProps } from './back-top-types' -import { usePosition, useVisibility } from './hooks' -import './back-top.scss' -import IconTop from './assets/top.svg' +import { defineComponent, onMounted, ref } from 'vue'; +import { backTopProps, BackTopProps } from './back-top-types'; +import { usePosition, useVisibility } from './hooks'; +import './back-top.scss'; +import IconTop from './assets/top.svg'; export default defineComponent({ name: 'DBackTop', props: backTopProps, emits: [], setup(props: BackTopProps, ctx) { - const slots = ctx.slots - const backTopRef = ref(null) + const slots = ctx.slots; + const backTopRef = ref(null); - const position = usePosition(props) - const isVisible = useVisibility(props, backTopRef) + const position = usePosition(props); + const isVisible = useVisibility(props, backTopRef); const scrollToTop = () => { // toTop方法暂定 @@ -21,9 +21,9 @@ export default defineComponent({ window.scrollTo({ top: 0, left: 0, - behavior: 'smooth' //平滑滚动 - }) - } + behavior: 'smooth' // 平滑滚动 + }); + }; return () => (
}
- ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/back-top/src/hooks/index.ts b/packages/devui-vue/devui/back-top/src/hooks/index.ts index b9fd2b4d96..c0b8f66846 100644 --- a/packages/devui-vue/devui/back-top/src/hooks/index.ts +++ b/packages/devui-vue/devui/back-top/src/hooks/index.ts @@ -1,7 +1,7 @@ -import usePosition from './use-position.ts' -import useTarget from './use-target.ts' -import useVisibility from './use-visibility.ts' -import useEventListener from './use-event-listener.ts' -import useThrottle from './use-throttle.ts' +import usePosition from './use-position.ts'; +import useTarget from './use-target.ts'; +import useVisibility from './use-visibility.ts'; +import useEventListener from './use-event-listener.ts'; +import useThrottle from './use-throttle.ts'; -export { usePosition, useTarget, useVisibility, useEventListener, useThrottle } +export { usePosition, useTarget, useVisibility, useEventListener, useThrottle }; diff --git a/packages/devui-vue/devui/back-top/src/hooks/use-event-listener.ts b/packages/devui-vue/devui/back-top/src/hooks/use-event-listener.ts index 18e12e3105..47bbf6f3cf 100644 --- a/packages/devui-vue/devui/back-top/src/hooks/use-event-listener.ts +++ b/packages/devui-vue/devui/back-top/src/hooks/use-event-listener.ts @@ -1,7 +1,7 @@ -type cbFn = () => void +type cbFn = () => void; /* 简陋版待完善 */ function useEventListener(target: HTMLElement, event: string, cb: cbFn) { - if (target) target.addEventListener(event, cb) + if (target) {target.addEventListener(event, cb);} } -export default useEventListener +export default useEventListener; diff --git a/packages/devui-vue/devui/back-top/src/hooks/use-position.ts b/packages/devui-vue/devui/back-top/src/hooks/use-position.ts index c66c16d531..f4b65d1e71 100644 --- a/packages/devui-vue/devui/back-top/src/hooks/use-position.ts +++ b/packages/devui-vue/devui/back-top/src/hooks/use-position.ts @@ -1,10 +1,10 @@ -import { BackTopProps, Position } from '../back-top-types' +import { BackTopProps, Position } from '../back-top-types'; export default function (props: BackTopProps): Position { - const { bottom, right } = props + const { bottom, right } = props; return { bottom, right - } + }; } diff --git a/packages/devui-vue/devui/back-top/src/hooks/use-target.ts b/packages/devui-vue/devui/back-top/src/hooks/use-target.ts index f0a1139b79..9137461716 100644 --- a/packages/devui-vue/devui/back-top/src/hooks/use-target.ts +++ b/packages/devui-vue/devui/back-top/src/hooks/use-target.ts @@ -1,19 +1,19 @@ -import { BackTopProps } from '../back-top-types' +import { BackTopProps } from '../back-top-types'; export default function (props: BackTopProps, backTopRef) { - const target = props.target // target为元素选择器 + const target = props.target; // target为元素选择器 const getTargetEl = () => { - const targetEl = document.querySelector(target) - if (!targetEl) throw new Error(`props ${target} is not existed`) + const targetEl = document.querySelector(target); + if (!targetEl) {throw new Error(`props ${target} is not existed`);} // 设置定位 - targetEl.parentElement.style.position = 'relative' - backTopRef.value.style.position = 'absolute' - return targetEl - } + targetEl.parentElement.style.position = 'relative'; + backTopRef.value.style.position = 'absolute'; + return targetEl; + }; const currTarget = - target === 'window' ? window || document.documentElement || document.body : getTargetEl() + target === 'window' ? window || document.documentElement || document.body : getTargetEl(); - return currTarget + return currTarget; } diff --git a/packages/devui-vue/devui/back-top/src/hooks/use-throttle.ts b/packages/devui-vue/devui/back-top/src/hooks/use-throttle.ts index ab5278fc31..6c271b11b8 100644 --- a/packages/devui-vue/devui/back-top/src/hooks/use-throttle.ts +++ b/packages/devui-vue/devui/back-top/src/hooks/use-throttle.ts @@ -1,10 +1,10 @@ export default function (fn, delay) { - let last = null + let last = null; return (...args) => { - const now = +Date.now() + const now = +Date.now(); if (now - last > delay) { - last = now - return fn.apply(this, args) + last = now; + return fn.apply(this, args); } - } + }; } diff --git a/packages/devui-vue/devui/back-top/src/hooks/use-visibility.ts b/packages/devui-vue/devui/back-top/src/hooks/use-visibility.ts index 5dc7061f95..e3774b4bf5 100644 --- a/packages/devui-vue/devui/back-top/src/hooks/use-visibility.ts +++ b/packages/devui-vue/devui/back-top/src/hooks/use-visibility.ts @@ -1,21 +1,21 @@ -import { onMounted, computed, ref } from 'vue' -import { BackTopProps } from '../back-top-types' -import { useTarget, useEventListener, useThrottle } from '.' +import { onMounted, computed, ref } from 'vue'; +import { BackTopProps } from '../back-top-types'; +import { useTarget, useEventListener, useThrottle } from '.'; export default function (props: BackTopProps, backTopRef) { - const visibleHeight = props.visibleHeight - const currScrollTop = ref(0) + const visibleHeight = props.visibleHeight; + const currScrollTop = ref(0); const ThrottleCBFn = function () { - currScrollTop.value = currTarget === window ? window.pageYOffset : currTarget.scrollTop - } + currScrollTop.value = currTarget === window ? window.pageYOffset : currTarget.scrollTop; + }; - let currTarget = null + let currTarget = null; onMounted(() => { - currTarget = useTarget(props, backTopRef) + currTarget = useTarget(props, backTopRef); // 监听滚动事件 手动更新ScrollTop - useEventListener(currTarget, 'scroll', useThrottle(ThrottleCBFn, 150)) - }) + useEventListener(currTarget, 'scroll', useThrottle(ThrottleCBFn, 150)); + }); - const isVisible = computed(() => currScrollTop.value >= visibleHeight) + const isVisible = computed(() => currScrollTop.value >= visibleHeight); - return isVisible + return isVisible; } diff --git a/packages/devui-vue/devui/badge/__tests__/badge.spec.ts b/packages/devui-vue/devui/badge/__tests__/badge.spec.ts index f18aa0e254..8601fbd860 100644 --- a/packages/devui-vue/devui/badge/__tests__/badge.spec.ts +++ b/packages/devui-vue/devui/badge/__tests__/badge.spec.ts @@ -1,50 +1,50 @@ -import { mount } from '@vue/test-utils' -import DBadge from '../src/badge' +import { mount } from '@vue/test-utils'; +import DBadge from '../src/badge'; -const SLOT = 'This is a slot test' +const SLOT = 'This is a slot test'; describe('badge', () => { it('badge base', () => { const wrapper = mount(DBadge, { props: { count: 80 }, slots: { default: SLOT } - }) - expect(wrapper.vm.count).toEqual(80) - }) + }); + expect(wrapper.vm.count).toEqual(80); + }); it('badge dot', () => { const wrapper = mount(DBadge, { props: { showDot: true }, slots: { default: SLOT } - }) - expect(wrapper.find('.devui-badge-content.devui-badge-content-dot').exists()).toBe(true) - }) + }); + expect(wrapper.find('.devui-badge-content.devui-badge-content-dot').exists()).toBe(true); + }); it('badge max', () => { const wrapper = mount(DBadge, { props: { count: 100 } - }) - expect(wrapper.find('.devui-badge-content').text()).toBe('99+') + }); + expect(wrapper.find('.devui-badge-content').text()).toBe('99+'); const wrapper2 = mount(DBadge, { props: { count: 100, maxCount: 1000 } - }) - expect(wrapper2.find('.devui-badge-content').text()).toBe('100') - }) + }); + expect(wrapper2.find('.devui-badge-content').text()).toBe('100'); + }); it('badge bgColor', () => { const wrapper = mount(DBadge, { props: { bgColor: 'red' }, slots: { default: SLOT } - }) - expect(wrapper.find('.devui-badge-content').attributes().style).toBe('background: red;') - }) + }); + expect(wrapper.find('.devui-badge-content').attributes().style).toBe('background: red;'); + }); it('badge offsetXY', () => { const wrapper = mount(DBadge, { props: { offsetXY: [-10, 10], badgePos: 'top-right' }, slots: { default: SLOT } - }) - expect(wrapper.find('.devui-badge-content').attributes().style).toBe('top: 10px; right: -10px;') - }) -}) + }); + expect(wrapper.find('.devui-badge-content').attributes().style).toBe('top: 10px; right: -10px;'); + }); +}); diff --git a/packages/devui-vue/devui/breadcrumb/__tests__/breadcrumb.spec.ts b/packages/devui-vue/devui/breadcrumb/__tests__/breadcrumb.spec.ts index f05cf80d70..0261853d30 100644 --- a/packages/devui-vue/devui/breadcrumb/__tests__/breadcrumb.spec.ts +++ b/packages/devui-vue/devui/breadcrumb/__tests__/breadcrumb.spec.ts @@ -1,6 +1,6 @@ -import { mount } from '@vue/test-utils' -import DBreadcrumb from '../src/breadcrumb' -import DBreadcrumbItem from '../src/breadcrumb-item' +import { mount } from '@vue/test-utils'; +import DBreadcrumb from '../src/breadcrumb'; +import DBreadcrumbItem from '../src/breadcrumb-item'; describe('breadcrumb', () => { it('should breadcrumb display correctly', () => { @@ -17,12 +17,12 @@ describe('breadcrumb', () => { Breadcrumb ` - }) - const items = wrapper.findAll('.devui-breadcrumb-item') - const separators = wrapper.findAll('.devui-breadcrumb-separator') - expect(items.length).toBe(2) - expect(separators.length).toBe(2) - }) + }); + const items = wrapper.findAll('.devui-breadcrumb-item'); + const separators = wrapper.findAll('.devui-breadcrumb-separator'); + expect(items.length).toBe(2); + expect(separators.length).toBe(2); + }); it('should separator support custom', () => { const wrapper = mount({ components: { @@ -34,9 +34,9 @@ describe('breadcrumb', () => { A ` - }) - expect(wrapper.find('.devui-breadcrumb-separator').text()).toBe('?') - }) + }); + expect(wrapper.find('.devui-breadcrumb-separator').text()).toBe('?'); + }); it('should `to` work correctly', () => { const wrapper = mount({ @@ -49,7 +49,7 @@ describe('breadcrumb', () => { A ` - }) - expect(wrapper.find('.is-link')).toBeTruthy() - }) -}) + }); + expect(wrapper.find('.is-link')).toBeTruthy(); + }); +}); diff --git a/packages/devui-vue/devui/breadcrumb/index.ts b/packages/devui-vue/devui/breadcrumb/index.ts index d481edf86e..2d60a9bdde 100644 --- a/packages/devui-vue/devui/breadcrumb/index.ts +++ b/packages/devui-vue/devui/breadcrumb/index.ts @@ -1,19 +1,19 @@ -import type { App } from 'vue' -import Breadcrumb from './src/breadcrumb' -import BreadcrumbItem from './src/breadcrumb-item' +import type { App } from 'vue'; +import Breadcrumb from './src/breadcrumb'; +import BreadcrumbItem from './src/breadcrumb-item'; Breadcrumb.install = function (app: App): void { - app.component(Breadcrumb.name, Breadcrumb) - app.component(BreadcrumbItem.name, BreadcrumbItem) -} + app.component(Breadcrumb.name, Breadcrumb); + app.component(BreadcrumbItem.name, BreadcrumbItem); +}; -export { Breadcrumb } +export { Breadcrumb }; export default { title: 'Breadcrumb 面包屑', category: '导航', status: '50%', install(app: App): void { - app.use(Breadcrumb as any) + app.use(Breadcrumb as any); }, -} +}; diff --git a/packages/devui-vue/devui/breadcrumb/src/breadcrumb-item-types.ts b/packages/devui-vue/devui/breadcrumb/src/breadcrumb-item-types.ts index a118789c0d..e4e0436182 100644 --- a/packages/devui-vue/devui/breadcrumb/src/breadcrumb-item-types.ts +++ b/packages/devui-vue/devui/breadcrumb/src/breadcrumb-item-types.ts @@ -1,9 +1,9 @@ -import type { ExtractPropTypes, PropType } from 'vue' +import type { ExtractPropTypes, PropType } from 'vue'; export interface MenuConfig { - name: string // 显示的名称 - link: string // 跳转的路径,可为绝对路径与相对路径,注意需要与路由的配置一致 - target?: string // 规定在何处打开链接文档 + name: string; // 显示的名称 + link: string; // 跳转的路径,可为绝对路径与相对路径,注意需要与路由的配置一致 + target?: string; // 规定在何处打开链接文档 } export const breadcrumbItemProps = { @@ -41,6 +41,6 @@ export const breadcrumbItemProps = { type: Boolean, default: false } -} as const +} as const; -export type BreadcrumbItemProps = ExtractPropTypes +export type BreadcrumbItemProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/breadcrumb/src/breadcrumb-item.tsx b/packages/devui-vue/devui/breadcrumb/src/breadcrumb-item.tsx index f8f1ff686f..e388e077a4 100644 --- a/packages/devui-vue/devui/breadcrumb/src/breadcrumb-item.tsx +++ b/packages/devui-vue/devui/breadcrumb/src/breadcrumb-item.tsx @@ -5,39 +5,39 @@ import { onBeforeUnmount, ref, getCurrentInstance -} from 'vue' +} from 'vue'; import { breadcrumbItemProps, BreadcrumbItemProps -} from './breadcrumb-item-types' -import './breadcrumb-item.scss' +} from './breadcrumb-item-types'; +import './breadcrumb-item.scss'; export default defineComponent({ name: 'DBreadcrumbItem', props: breadcrumbItemProps, setup(props: BreadcrumbItemProps, { slots }) { - const separatorIcon = inject('separatorIcon') - const linkClass = props.to ? 'is-link' : '' - const link = ref(null) - const instance = getCurrentInstance() - const router = instance.appContext.config.globalProperties.$router + const separatorIcon = inject('separatorIcon'); + const linkClass = props.to ? 'is-link' : ''; + const link = ref(null); + const instance = getCurrentInstance(); + const router = instance.appContext.config.globalProperties.$router; const handleClickLink = () => { - if (!props.to || !router) return - props.replace ? router.replace(props.to) : router.push(props.to) - } + if (!props.to || !router) {return;} + props.replace ? router.replace(props.to) : router.push(props.to); + }; onMounted(() => { - link.value.addEventListener('click', handleClickLink) - }) + link.value.addEventListener('click', handleClickLink); + }); onBeforeUnmount(() => { - link.value.removeEventListener('click', handleClickLink) - }) + link.value.removeEventListener('click', handleClickLink); + }); return () => { const renderBreadcrumbSperator = () => { - return {separatorIcon} - } + return {separatorIcon}; + }; return (
@@ -45,7 +45,7 @@ export default defineComponent({ {renderBreadcrumbSperator()}
- ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/breadcrumb/src/breadcrumb-types.ts b/packages/devui-vue/devui/breadcrumb/src/breadcrumb-types.ts index caebf81bf3..76d5620b1c 100644 --- a/packages/devui-vue/devui/breadcrumb/src/breadcrumb-types.ts +++ b/packages/devui-vue/devui/breadcrumb/src/breadcrumb-types.ts @@ -1,12 +1,12 @@ -import type { ExtractPropTypes, PropType } from 'vue' +import type { ExtractPropTypes, PropType } from 'vue'; export interface SourceConfig { - title: string // 显示的名称 - link?: string // 跳转的路径 - target?: string // 规定在何处打开链接文档 - noNavigation?: boolean // 链接是否不可跳转,一般用于当前所处位置不可跳转的配置 - linkType?: 'hrefLink' | 'routerLink' // 链接类型,默认为'hrefLink'方式,可选'hrefLink' 或 'routerLink' - replace: boolean // 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录 + title: string; // 显示的名称 + link?: string; // 跳转的路径 + target?: string; // 规定在何处打开链接文档 + noNavigation?: boolean; // 链接是否不可跳转,一般用于当前所处位置不可跳转的配置 + linkType?: 'hrefLink' | 'routerLink'; // 链接类型,默认为'hrefLink'方式,可选'hrefLink' 或 'routerLink' + replace: boolean; // 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录 } export const breadcrumbProps = { @@ -23,6 +23,6 @@ export const breadcrumbProps = { separatorIcon: { type: String } -} as const +} as const; -export type BreadcrumbProps = ExtractPropTypes +export type BreadcrumbProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/breadcrumb/src/breadcrumb.tsx b/packages/devui-vue/devui/breadcrumb/src/breadcrumb.tsx index 6b5ffeb24d..4310d6089f 100644 --- a/packages/devui-vue/devui/breadcrumb/src/breadcrumb.tsx +++ b/packages/devui-vue/devui/breadcrumb/src/breadcrumb.tsx @@ -1,12 +1,12 @@ -import { defineComponent, provide } from 'vue' +import { defineComponent, provide } from 'vue'; import { breadcrumbProps, BreadcrumbProps, SourceConfig -} from './breadcrumb-types' -import DBreadcrumbItem from './breadcrumb-item' -import { getPropsSlot } from '../../shared/util/props-util' -import './breadcrumb.scss' +} from './breadcrumb-types'; +import DBreadcrumbItem from './breadcrumb-item'; +import { getPropsSlot } from '../../shared/util/props-util'; +import './breadcrumb.scss'; export default defineComponent({ name: 'DBreadcrumb', @@ -15,36 +15,36 @@ export default defineComponent({ }, props: breadcrumbProps, setup(props: BreadcrumbProps, { slots }) { - const separatorIcon = getPropsSlot(slots, props, 'separatorIcon') ?? '/' - provide('separatorIcon', separatorIcon) + const separatorIcon = getPropsSlot(slots, props, 'separatorIcon') ?? '/'; + provide('separatorIcon', separatorIcon); const renderBreadcrumbItemRouted = (item) => { return ( {item.title} - ) - } + ); + }; const renderBreadItemList = (source: SourceConfig[]) => { return source.map((item: SourceConfig) => { if (!item.noNavigation && item.linkType === 'routerLink') { - return renderBreadcrumbItemRouted(item) + return renderBreadcrumbItemRouted(item); } return ( {/* hrefLink */} {!item.noNavigation && (!item.linkType || item.linkType === 'hrefLink') ? ( - - {item.title} - - ) : null} + + {item.title} + + ) : null} {/* normal */} {item.noNavigation ? {item.title} : null} - ) - }) - } + ); + }); + }; return () => { return (
@@ -52,7 +52,7 @@ export default defineComponent({ ? renderBreadItemList(props.source) : slots?.default()}
- ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/card/__tests__/card.spec.ts b/packages/devui-vue/devui/card/__tests__/card.spec.ts index f5bc553100..b6913cf9fd 100644 --- a/packages/devui-vue/devui/card/__tests__/card.spec.ts +++ b/packages/devui-vue/devui/card/__tests__/card.spec.ts @@ -5,8 +5,8 @@ import DAvatar from '../../avatar/src/avatar'; describe('card', () => { it('should render correctly', async () => { const wrapper = mount(DCard); - expect(wrapper.element).toMatchSnapshot() - }) + expect(wrapper.element).toMatchSnapshot(); + }); it('should render correctly avatar', async () => { const wrapper = mount({ components: { @@ -23,7 +23,7 @@ describe('card', () => { }); const avatar = wrapper.findAllComponents({ name: 'dAvatar' })[0]; expect(avatar.classes()).toContain('devui-avatar'); - }) + }); it('in v-slot mode should render correctly avatar', async () => { const wrapper = mount({ components: { @@ -40,7 +40,7 @@ describe('card', () => { }); const avatar = wrapper.findAllComponents({ name: 'dAvatar' })[0]; expect(avatar.classes()).toContain('devui-avatar'); - }) + }); it('should render correctly title', async () => { const wrapper = mount({ components: { @@ -54,8 +54,8 @@ describe('card', () => { `, }); - expect(wrapper.find('.devui-card-title').text()).toBe('DevUI') - }) + expect(wrapper.find('.devui-card-title').text()).toBe('DevUI'); + }); it('in v-slot mode should render title', async () => { const wrapper = mount({ components: { @@ -69,8 +69,8 @@ describe('card', () => { `, }); - expect(wrapper.find('.devui-card-title').text()).toBe('DEVUI Course') - }) + expect(wrapper.find('.devui-card-title').text()).toBe('DEVUI Course'); + }); it('should render correctly subtitle', async () => { const wrapper = mount({ components: { @@ -84,8 +84,8 @@ describe('card', () => { `, }); - expect(wrapper.find('.devui-card-subtitle').text()).toBe('DevUI') - }) + expect(wrapper.find('.devui-card-subtitle').text()).toBe('DevUI'); + }); it('in v-slot mode should render subtitle', async () => { const wrapper = mount({ components: { @@ -99,8 +99,8 @@ describe('card', () => { `, }); - expect(wrapper.find('.devui-card-subtitle').text()).toBe('DevUI') - }) + expect(wrapper.find('.devui-card-subtitle').text()).toBe('DevUI'); + }); it('should render correctly content', async () => { const wrapper = mount({ components: { @@ -114,8 +114,8 @@ describe('card', () => { `, }); - expect(wrapper.find('.devui-card-content').text()).toBe('DevUI') - }) + expect(wrapper.find('.devui-card-content').text()).toBe('DevUI'); + }); it('in v-slot mode should render content', async () => { const wrapper = mount({ components: { @@ -129,8 +129,8 @@ describe('card', () => { `, }); - expect(wrapper.find('.devui-card-content').text()).toBe('DevUI') - }) + expect(wrapper.find('.devui-card-content').text()).toBe('DevUI'); + }); it('should render correctly actions', async () => { const wrapper = mount({ components: { @@ -147,8 +147,8 @@ describe('card', () => { `, }); expect(wrapper.find('.devui-card-actions').exists()).toBeTruthy(); - expect(wrapper.find('.card-block').text()).toBe('btn') - }) + expect(wrapper.find('.card-block').text()).toBe('btn'); + }); it('in v-slot mode should render actions', async () => { const wrapper = mount({ components: { @@ -165,8 +165,8 @@ describe('card', () => { `, }); expect(wrapper.find('.devui-card-actions').exists()).toBeTruthy(); - expect(wrapper.find('.card-block').text()).toBe('btn') - }) + expect(wrapper.find('.card-block').text()).toBe('btn'); + }); it('should render correctly image', async () => { const wrapper = mount({ components: { @@ -178,7 +178,7 @@ describe('card', () => { `, }); expect(wrapper.find('.devui-card-meta').attributes('src').includes('https://devui.design/components/assets/image1.png')).toBeTruthy(); - }) + }); it('should render correctly align', async () => { const wrapper = mount({ components: { @@ -190,5 +190,5 @@ describe('card', () => { `, }); expect(wrapper.find('.devui-card-actions-align-spaceBetween').exists()).toBeTruthy(); - }) -}) \ No newline at end of file + }); +}); diff --git a/packages/devui-vue/devui/card/index.ts b/packages/devui-vue/devui/card/index.ts index 69032ab068..c0fe7ee7ed 100644 --- a/packages/devui-vue/devui/card/index.ts +++ b/packages/devui-vue/devui/card/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Card from './src/card' +import type { App } from 'vue'; +import Card from './src/card'; Card.install = function(app: App) { - app.component(Card.name, Card) -} + app.component(Card.name, Card); +}; -export { Card } +export { Card }; export default { title: 'Card 卡片', category: '数据展示', status: '100%', install(app: App): void { - app.use(Card as any) + app.use(Card as any); } -} +}; diff --git a/packages/devui-vue/devui/card/src/card.tsx b/packages/devui-vue/devui/card/src/card.tsx index 249a3cc882..5e53d04f8e 100644 --- a/packages/devui-vue/devui/card/src/card.tsx +++ b/packages/devui-vue/devui/card/src/card.tsx @@ -30,9 +30,9 @@ export default defineComponent({
{this.$slots.default?.()}
- { this.$slots.cardAvatar?.()?
- {this.$slots.cardAvatar?.()} -
:'' } + { this.$slots.cardAvatar?.()?
+ {this.$slots.cardAvatar?.()} +
:'' }
{this.$slots.cardTitle?.()} @@ -52,4 +52,4 @@ export default defineComponent({
); } -}); \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/carousel/__tests__/carousel.spec.ts b/packages/devui-vue/devui/carousel/__tests__/carousel.spec.ts index a900c84833..ec85b304d2 100644 --- a/packages/devui-vue/devui/carousel/__tests__/carousel.spec.ts +++ b/packages/devui-vue/devui/carousel/__tests__/carousel.spec.ts @@ -1,15 +1,15 @@ -import { ref, nextTick } from 'vue' +import { ref, nextTick } from 'vue'; import { mount } from '@vue/test-utils'; import { CarouselItem, Carousel } from '../index'; -import { Button } from '../../button' +import { Button } from '../../button'; const wait = (ms = 100) => - new Promise(resolve => setTimeout(() => resolve(), ms)) + new Promise(resolve => setTimeout(() => resolve(), ms)); describe('d-carousel', () => { it('arrowTrigger-never', () => { const wrapper = mount(Carousel, { - props: { + props: { arrowTrigger: 'never', height: '200px', }, @@ -19,7 +19,7 @@ describe('d-carousel', () => { it('arrowTrigger-hover-out', () => { const wrapper = mount(Carousel, { - props: { + props: { arrowTrigger: 'hover', height: '200px', }, @@ -28,19 +28,19 @@ describe('d-carousel', () => { }); it('arrowTrigger-hover-in', async () => { const wrapper = mount(Carousel, { - props: { + props: { arrowTrigger: 'hover', height: '200px', }, }); - wrapper.find('.devui-carousel-container').trigger('mouseenter') - await nextTick() + wrapper.find('.devui-carousel-container').trigger('mouseenter'); + await nextTick(); expect(wrapper.find('.devui-carousel-arrow').exists()).toBe(true); }); it('arrowTrigger-always', () => { const wrapper = mount(Carousel, { - props: { + props: { arrowTrigger: 'always', height: '200px', }, @@ -50,7 +50,7 @@ describe('d-carousel', () => { it('showDots-false', () => { const wrapper = mount(Carousel, { - props: { + props: { showDots: false, height: '200px', }, @@ -62,7 +62,7 @@ describe('d-carousel', () => { const wrapper = mount({ components: { 'd-carousel': Carousel, - 'd-carousel-item': CarouselItem, + 'd-carousel-item': CarouselItem, }, template: ` @@ -73,23 +73,23 @@ describe('d-carousel', () => { `, setup() { - const activeIndex = ref(0) + const activeIndex = ref(0); const onChange = (index: number) => { - activeIndex.value = index - } - + activeIndex.value = index; + }; + return { activeIndex, onChange, - } + }; } }); - await nextTick() - wrapper.findAll('.dot-item')[1].trigger('click') - await nextTick() + await nextTick(); + wrapper.findAll('.dot-item')[1].trigger('click'); + await nextTick(); expect(wrapper.vm.activeIndex).toBe(1); }); @@ -97,7 +97,7 @@ describe('d-carousel', () => { const wrapper = mount({ components: { 'd-carousel': Carousel, - 'd-carousel-item': CarouselItem, + 'd-carousel-item': CarouselItem, }, template: ` @@ -108,22 +108,22 @@ describe('d-carousel', () => { `, setup() { - const activeIndex = ref(0) + const activeIndex = ref(0); const onChange = (index: number) => { - activeIndex.value = index - } - + activeIndex.value = index; + }; + return { activeIndex, onChange, - } + }; } }); - await nextTick() - wrapper.findAll('.dot-item')[1].trigger('mouseenter') - await nextTick() + await nextTick(); + wrapper.findAll('.dot-item')[1].trigger('mouseenter'); + await nextTick(); expect(wrapper.vm.activeIndex).toBe(1); }); @@ -131,7 +131,7 @@ describe('d-carousel', () => { const wrapper = mount({ components: { 'd-carousel': Carousel, - 'd-carousel-item': CarouselItem, + 'd-carousel-item': CarouselItem, 'd-button': Button, }, template: ` @@ -145,65 +145,65 @@ describe('d-carousel', () => {
`, setup() { - const items = ref(['page 1', 'page 2', 'page 3', 'page 4']) - const activeIndex = ref(0) - - const carousel = ref() - + const items = ref(['page 1', 'page 2', 'page 3', 'page 4']); + const activeIndex = ref(0); + + const carousel = ref(); + const onPrev = () => { - carousel.value?.prev?.() - } + carousel.value?.prev?.(); + }; const onNext = () => { - carousel.value?.next?.() - } + carousel.value?.next?.(); + }; const onGoFirst = () => { - carousel.value?.goto?.(0) - } + carousel.value?.goto?.(0); + }; const onChange = (index: number) => { - activeIndex.value = index - } - + activeIndex.value = index; + }; + return { activeIndex, items, - + carousel, onPrev, onNext, onGoFirst, onChange, - } + }; } }); - await nextTick() - wrapper.find('.arrow-left').trigger('click') - await nextTick() - expect(wrapper.vm.activeIndex).toBe(3) - wrapper.find('.arrow-right').trigger('click') - await nextTick() - expect(wrapper.vm.activeIndex).toBe(0) - - wrapper.findAll('.devui-btn')[0].trigger('click') - await nextTick() - wrapper.findAll('.devui-btn')[0].trigger('click') - await nextTick() - expect(wrapper.vm.activeIndex).toBe(2) - - wrapper.findAll('.devui-btn')[1].trigger('click') - await nextTick() - expect(wrapper.vm.activeIndex).toBe(3) - - wrapper.findAll('.devui-btn')[2].trigger('click') - await nextTick() - expect(wrapper.vm.activeIndex).toBe(0) + await nextTick(); + wrapper.find('.arrow-left').trigger('click'); + await nextTick(); + expect(wrapper.vm.activeIndex).toBe(3); + wrapper.find('.arrow-right').trigger('click'); + await nextTick(); + expect(wrapper.vm.activeIndex).toBe(0); + + wrapper.findAll('.devui-btn')[0].trigger('click'); + await nextTick(); + wrapper.findAll('.devui-btn')[0].trigger('click'); + await nextTick(); + expect(wrapper.vm.activeIndex).toBe(2); + + wrapper.findAll('.devui-btn')[1].trigger('click'); + await nextTick(); + expect(wrapper.vm.activeIndex).toBe(3); + + wrapper.findAll('.devui-btn')[2].trigger('click'); + await nextTick(); + expect(wrapper.vm.activeIndex).toBe(0); }); it('autoplay', async () => { const wrapper = mount({ components: { 'd-carousel': Carousel, - 'd-carousel-item': CarouselItem, + 'd-carousel-item': CarouselItem, }, template: ` @@ -214,23 +214,23 @@ describe('d-carousel', () => { `, setup() { - const activeIndex = ref(2) + const activeIndex = ref(2); const onChange = (index: number) => { - activeIndex.value = index - } - + activeIndex.value = index; + }; + return { activeIndex, onChange, - } + }; } }); - await wait(4500) - expect(wrapper.vm.activeIndex).toBe(1) - await wait(4600) - expect(wrapper.vm.activeIndex).toBe(3) + await wait(4500); + expect(wrapper.vm.activeIndex).toBe(1); + await wait(4600); + expect(wrapper.vm.activeIndex).toBe(3); }, 10000); }); diff --git a/packages/devui-vue/devui/carousel/index.ts b/packages/devui-vue/devui/carousel/index.ts index 6f05109ddf..a1e3bd5770 100644 --- a/packages/devui-vue/devui/carousel/index.ts +++ b/packages/devui-vue/devui/carousel/index.ts @@ -1,24 +1,24 @@ -import type { App } from 'vue' -import Carousel from './src/carousel' -import CarouselItem from './src/item' +import type { App } from 'vue'; +import Carousel from './src/carousel'; +import CarouselItem from './src/item'; Carousel.install = function(app: App) { - app.component(Carousel.name, Carousel) -} + app.component(Carousel.name, Carousel); +}; CarouselItem.install = function(app: App) { app.component(CarouselItem.name, CarouselItem); -} +}; -export { Carousel } -export { CarouselItem } +export { Carousel }; +export { CarouselItem }; export default { title: 'Carousel 走马灯', category: '数据展示', status: '80%', install(app: App): void { - app.use(Carousel as any) - app.use(CarouselItem as any) + app.use(Carousel as any); + app.use(CarouselItem as any); } -} +}; diff --git a/packages/devui-vue/devui/carousel/src/item.tsx b/packages/devui-vue/devui/carousel/src/item.tsx index c5c367ac12..584bac3adf 100644 --- a/packages/devui-vue/devui/carousel/src/item.tsx +++ b/packages/devui-vue/devui/carousel/src/item.tsx @@ -1,17 +1,17 @@ -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; export default defineComponent({ name: 'DCarouselItem', render() { const { $slots - } = this - const children = $slots.default?.() + } = this; + const children = $slots.default?.(); return ( - ) + ); } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/carousel/src/types.ts b/packages/devui-vue/devui/carousel/src/types.ts index fc35b2d6ac..5596004b73 100644 --- a/packages/devui-vue/devui/carousel/src/types.ts +++ b/packages/devui-vue/devui/carousel/src/types.ts @@ -40,4 +40,4 @@ export const carouselProps = { activeIndexChange: { type: Function as unknown as () => ((index: number) => void) }, -} as const; \ No newline at end of file +} as const; diff --git a/packages/devui-vue/devui/cascader/components/cascader-item/index.tsx b/packages/devui-vue/devui/cascader/components/cascader-item/index.tsx index c221a86aec..be97e66f70 100644 --- a/packages/devui-vue/devui/cascader/components/cascader-item/index.tsx +++ b/packages/devui-vue/devui/cascader/components/cascader-item/index.tsx @@ -1,50 +1,50 @@ -import { computed, ref } from 'vue' -import { CascaderItemPropsType } from '../../src/cascader-types' -import { useListClassName } from '../../hooks/use-cascader-class' -import { updateCheckOptionStatus } from '../../hooks/use-cascader-multiple' -import { singleChoose } from '../../hooks/use-cascader-single' -import './index.scss' +import { computed, ref } from 'vue'; +import { CascaderItemPropsType } from '../../src/cascader-types'; +import { useListClassName } from '../../hooks/use-cascader-class'; +import { updateCheckOptionStatus } from '../../hooks/use-cascader-multiple'; +import { singleChoose } from '../../hooks/use-cascader-single'; +import './index.scss'; export const DCascaderItem = (props: CascaderItemPropsType) => { // console.log('item index',props) - const { cascaderItem, ulIndex, liIndex, cascaderItemNeedProps, cascaderOptions } = props - const { multiple, stopDefault, valueCache, activeIndexs, trigger, confirmInputValueFlg, tagList} = cascaderItemNeedProps - const isTriggerHover = trigger === 'hover' - const rootClasses = useListClassName(props) - const { updateStatus } = updateCheckOptionStatus(tagList) - const disbaled = computed(() => cascaderItem?.disabled) // 当前项是否被禁用 + const { cascaderItem, ulIndex, liIndex, cascaderItemNeedProps, cascaderOptions } = props; + const { multiple, stopDefault, valueCache, activeIndexs, trigger, confirmInputValueFlg, tagList} = cascaderItemNeedProps; + const isTriggerHover = trigger === 'hover'; + const rootClasses = useListClassName(props); + const { updateStatus } = updateCheckOptionStatus(tagList); + const disbaled = computed(() => cascaderItem?.disabled); // 当前项是否被禁用 // 触发联动更新 const updateValues = () => { - if (stopDefault.value) return + if (stopDefault.value) {return;} // 删除当前联动级之后的所有级 - activeIndexs.splice(ulIndex, activeIndexs.length - ulIndex) + activeIndexs.splice(ulIndex, activeIndexs.length - ulIndex); // 更新当前渲染视图的下标数组 - activeIndexs[ulIndex] = liIndex + activeIndexs[ulIndex] = liIndex; if (!multiple) { // 单选点击选项就更新,多选是通过点击checkbox触发数据更新 - singleChoose(ulIndex, valueCache, cascaderItem) + singleChoose(ulIndex, valueCache, cascaderItem); } - } + }; // 鼠标hover(多选模式下只能点击操作触发) const mouseEnter = () => { - if (disbaled.value || multiple) return - updateValues() - } + if (disbaled.value || multiple) {return;} + updateValues(); + }; const mouseenter = { [ isTriggerHover && 'onMouseenter' ]: mouseEnter - } + }; // 鼠标click const mouseClick = () => { - if (disbaled.value) return - updateValues() + if (disbaled.value) {return;} + updateValues(); if (!multiple && (!cascaderItem.children || cascaderItem?.children?.length === 0)) { - confirmInputValueFlg.value = !confirmInputValueFlg.value + confirmInputValueFlg.value = !confirmInputValueFlg.value; } - } + }; const checkboxChange = () => { - updateStatus(cascaderItem, cascaderOptions, ulIndex) - } + updateStatus(cascaderItem, cascaderOptions, ulIndex); + }; return (
  • - { multiple && + { multiple &&
    @@ -63,5 +63,5 @@ export const DCascaderItem = (props: CascaderItemPropsType) => { }
  • - ) -} + ); +}; diff --git a/packages/devui-vue/devui/cascader/components/cascader-list/index.tsx b/packages/devui-vue/devui/cascader/components/cascader-list/index.tsx index fb367f22f1..8fedec6ebc 100644 --- a/packages/devui-vue/devui/cascader/components/cascader-list/index.tsx +++ b/packages/devui-vue/devui/cascader/components/cascader-list/index.tsx @@ -1,27 +1,27 @@ -import { defineComponent } from 'vue' -import { useUlClassName } from '../../hooks/use-cascader-class' -import { useDropdownStyle } from '../../hooks/use-cascader-style' -import { cascaderulProps, CascaderulProps } from '../../src/cascader-types' +import { defineComponent } from 'vue'; +import { useUlClassName } from '../../hooks/use-cascader-class'; +import { useDropdownStyle } from '../../hooks/use-cascader-style'; +import { cascaderulProps, CascaderulProps } from '../../src/cascader-types'; -import { DCascaderItem } from '../cascader-item' -import './index.scss' +import { DCascaderItem } from '../cascader-item'; +import './index.scss'; export default defineComponent({ name: 'DCascaderList', props: cascaderulProps, setup(props: CascaderulProps) { - const ulClass = useUlClassName(props) - const ulStyle = useDropdownStyle(props) + const ulClass = useUlClassName(props); + const ulStyle = useDropdownStyle(props); // console.log('props', props) return () => (
      { props?.cascaderItems?.length > 0 - ? props.cascaderItems.map((item, index) => { - return - }) - : 没有数据 + ? props.cascaderItems.map((item, index) => { + return ; + }) + : 没有数据 }
    - ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/cascader/components/cascader-multiple/index.tsx b/packages/devui-vue/devui/cascader/components/cascader-multiple/index.tsx index 932c4a3f3b..7e30102df3 100644 --- a/packages/devui-vue/devui/cascader/components/cascader-multiple/index.tsx +++ b/packages/devui-vue/devui/cascader/components/cascader-multiple/index.tsx @@ -1,20 +1,20 @@ /** * 多选模式下的内容框 */ -import DTag from '../cascader-tag/' -import { MultiplePropsType } from '../../src/cascader-types' -import './index.scss' +import DTag from '../cascader-tag/'; +import { MultiplePropsType } from '../../src/cascader-types'; +import './index.scss'; export default (props: MultiplePropsType) => { return (
    { props.activeOptions.length > 0 ? props.activeOptions.map(item => { - return - }) + return ; + }) :
    { props.placeholder }
    }
    - ) -} \ No newline at end of file + ); +}; diff --git a/packages/devui-vue/devui/cascader/components/cascader-tag/index.tsx b/packages/devui-vue/devui/cascader/components/cascader-tag/index.tsx index 4b68406c5f..902345df13 100644 --- a/packages/devui-vue/devui/cascader/components/cascader-tag/index.tsx +++ b/packages/devui-vue/devui/cascader/components/cascader-tag/index.tsx @@ -2,19 +2,19 @@ * 多选模式下的内容框中的选中tag * tag组件还未开发完成,所以暂时使用自定义组件 */ -import { CascaderItem } from '../../src/cascader-types' -import { multipleDeleteTag } from '../../hooks/use-cascader-multiple' -import './index.scss' +import { CascaderItem } from '../../src/cascader-types'; +import { multipleDeleteTag } from '../../hooks/use-cascader-multiple'; +import './index.scss'; interface PropsType { - tag: CascaderItem - tagList: CascaderItem[] + tag: CascaderItem; + tagList: CascaderItem[]; } export default (props: PropsType) => { - const { tagList, tag } = props + const { tagList, tag } = props; const deleteCurrentTag = (e: Event) => { - e.stopPropagation() - multipleDeleteTag(tagList, tag) - } + e.stopPropagation(); + multipleDeleteTag(tagList, tag); + }; return (
    {tag?.label} @@ -22,5 +22,5 @@ export default (props: PropsType) => {
    - ) -} + ); +}; diff --git a/packages/devui-vue/devui/cascader/hooks/use-cascader-class.ts b/packages/devui-vue/devui/cascader/hooks/use-cascader-class.ts index 576dc61c01..f8a408f626 100644 --- a/packages/devui-vue/devui/cascader/hooks/use-cascader-class.ts +++ b/packages/devui-vue/devui/cascader/hooks/use-cascader-class.ts @@ -2,39 +2,39 @@ * 定义组件class */ import { computed, ComputedRef, Ref } from 'vue'; -import { CascaderProps, CascaderulProps, CascaderItemPropsType } from '../src/cascader-types' +import { CascaderProps, CascaderulProps, CascaderItemPropsType } from '../src/cascader-types'; // import { UseClassNameType } from '../components/cascader-item/cascader-item-types' // 根节点class -export const useRootClassName = (props: CascaderProps, menuShow: Ref ): ComputedRef => { +export const useRootClassName = (props: CascaderProps, menuShow: Ref): ComputedRef => { return computed(() => ({ 'devui-cascader devui-dropdown devui-dropdown-animation': true, 'devui-dropdown__open': menuShow.value, 'devui-cascader__disbaled': props.disabled, - })) -} + })); +}; // 弹出层项 class export const useListClassName = (props: CascaderItemPropsType): ComputedRef => { - const itemProps = props?.cascaderItemNeedProps - const isActive = itemProps?.valueCache[props.ulIndex] === props.cascaderItem?.value - const isDisabled = props.cascaderItem?.disabled + const itemProps = props?.cascaderItemNeedProps; + const isActive = itemProps?.valueCache[props.ulIndex] === props.cascaderItem?.value; + const isDisabled = props.cascaderItem?.disabled; return computed(() => ({ 'devui-cascader-li devui-dropdown-item': true, 'devui-leaf-active': isActive, 'disabled': isDisabled - })) -} + })); +}; // 弹出层列 class export const useUlClassName = (props: CascaderulProps): ComputedRef => { return computed(() => ({ 'devui-cascader-ul': true, 'devui-drop-no-data': props?.cascaderItems?.length === 0 - })) -} + })); +}; // 为弹出层打开添加全局class export const dropdownOpenClass = (status: boolean): string => { - return status ? 'devui-drop-menu-wrapper' : '' -} \ No newline at end of file + return status ? 'devui-drop-menu-wrapper' : ''; +}; diff --git a/packages/devui-vue/devui/cascader/hooks/use-cascader-item.ts b/packages/devui-vue/devui/cascader/hooks/use-cascader-item.ts index de4a70fbe0..7194c0722c 100644 --- a/packages/devui-vue/devui/cascader/hooks/use-cascader-item.ts +++ b/packages/devui-vue/devui/cascader/hooks/use-cascader-item.ts @@ -1,9 +1,9 @@ /** * 处理cascader-item中需要的参数 */ -import { cloneDeep } from 'lodash' -import { ref, reactive, Ref } from 'vue' -import { CascaderProps, UseCascaderItemCallback, CascaderItem } from '../src/cascader-types' +import { cloneDeep } from 'lodash'; +import { ref, reactive, Ref } from 'vue'; +import { CascaderProps, UseCascaderItemCallback, CascaderItem } from '../src/cascader-types'; export const useCascaderItem = (props?: CascaderProps, stopDefault?: Ref, tagList?: CascaderItem[]): UseCascaderItemCallback => { /** @@ -19,10 +19,10 @@ export const useCascaderItem = (props?: CascaderProps, stopDefault?: Ref([]), // 维护用于视图更新的选中下标 tagList, // 多选模式下选中的值数组,用于生成tag stopDefault, - } + }; return { cascaderItemNeedProps, // getInputValue - } -} \ No newline at end of file + }; +}; diff --git a/packages/devui-vue/devui/cascader/hooks/use-cascader-multiple.ts b/packages/devui-vue/devui/cascader/hooks/use-cascader-multiple.ts index 4a2caaf4f7..e29b9ca4e1 100644 --- a/packages/devui-vue/devui/cascader/hooks/use-cascader-multiple.ts +++ b/packages/devui-vue/devui/cascader/hooks/use-cascader-multiple.ts @@ -1,36 +1,36 @@ /** * 多选模式 */ -import { CascaderItem, UpdateStatusCallback, CaascaderOptionsType, CheckedType, CascaderItemNeedType } from '../src/cascader-types' +import { CascaderItem, UpdateStatusCallback, CaascaderOptionsType, CheckedType, CascaderItemNeedType } from '../src/cascader-types'; /** * 初始化选中项,将选中的数组集合置为空 * @param tagList 前被选中的tagList集合 */ export const initTagList = (tagList: CascaderItem[]): void => { - tagList.splice(0, tagList.length) -} + tagList.splice(0, tagList.length); +}; /** * 添加选中项 * @param tagList 当前被选中的tagList集合 * @param singleItem 当前选中项 - * + * */ export const multipleAddTag = (tagList: CascaderItem[], singleItem: CascaderItem): void => { - tagList.push(singleItem) -} + tagList.push(singleItem); +}; /** * 删除选中项 * @param tagList 前被选中的tagList集合 * @param singleItem 当前选中项 - * + * */ export const multipleDeleteTag = (tagList: CascaderItem[], singleItem: CascaderItem): void => { // console.log(arr) - const i = tagList.findIndex(item => item.value === singleItem.value) - tagList.splice(i, 1) -} + const i = tagList.findIndex(item => item.value === singleItem.value); + tagList.splice(i, 1); +}; /** * 多选模式初始化选中的节点 @@ -39,8 +39,8 @@ export const multipleDeleteTag = (tagList: CascaderItem[], singleItem: CascaderI * @param tagList 选中的tag集合 */ export const initMultipleCascaderItem = (targetValues: number[], rootColumn: CascaderItem[], tagList: CascaderItem[]): void => { - findNextColumn(targetValues, rootColumn, 0, tagList) -} + findNextColumn(targetValues, rootColumn, 0, tagList); +}; /** * 根据values集合递归获取选中的节点 @@ -50,32 +50,32 @@ export const initMultipleCascaderItem = (targetValues: number[], rootColumn: Cas * @param tagList 选中的tag集合 */ const findNextColumn = (targetValues: number[], options: CascaderItem[], index: number, tagList: CascaderItem[]): void => { - let targetNode = options.find(t => t.value === targetValues[index]) // 根据value获取当前选中的项 + let targetNode = options.find(t => t.value === targetValues[index]); // 根据value获取当前选中的项 if (targetNode?.children?.length > 0) { // 递归的限制条件,是否还有子级 - index += 1 // 进入下一级 - targetNode = setChildrenParent(targetNode) // 为children设置parent,方便后续通过child使用parent - findNextColumn(targetValues, targetNode.children, index, tagList) + index += 1; // 进入下一级 + targetNode = setChildrenParent(targetNode); // 为children设置parent,方便后续通过child使用parent + findNextColumn(targetValues, targetNode.children, index, tagList); } else { // 没有子节点说明此时已经是最终结点了 - multipleAddTag(tagList, targetNode) // 新增tag + multipleAddTag(tagList, targetNode); // 新增tag + + targetNode['checked'] = true; - targetNode['checked'] = true - // 从最终结点往上寻找父节点更新状态 // 通过父亲节点查询所有子节点状态从而更新父节点状态 - findChildrenCheckedStatusToUpdateParent(targetNode?.parent) + findChildrenCheckedStatusToUpdateParent(targetNode?.parent); } -} - /** - * +}; +/** + * * @param parentNode 父节点 * @returns parentNode 父节点 */ - const setChildrenParent = (parentNode) => { - parentNode?.children.forEach(child => { - child.parent = parentNode - }) - return parentNode - } +const setChildrenParent = (parentNode) => { + parentNode?.children.forEach(child => { + child.parent = parentNode; + }); + return parentNode; +}; export const updateCheckOptionStatus = (tagList: CascaderItem[]): UpdateStatusCallback => { /** @@ -86,12 +86,12 @@ export const updateCheckOptionStatus = (tagList: CascaderItem[]): UpdateStatusCa */ const updateStatus = (node: CascaderItem, options: CaascaderOptionsType, ulIndex: number) => { // 更新当前点击的node - updateCurNodeStatus(node, ulIndex) - ulIndex -= 1 + updateCurNodeStatus(node, ulIndex); + ulIndex -= 1; // const parentNode = getParentNode(node.value, options, ulIndex) - const parentNode = node?.parent - updateParentNodeStatus(parentNode, options, ulIndex) - } + const parentNode = node?.parent; + updateParentNodeStatus(parentNode, options, ulIndex); + }; /** * 更新当前选中的结点状态 * @param node 当前结点 @@ -100,49 +100,49 @@ export const updateCheckOptionStatus = (tagList: CascaderItem[]): UpdateStatusCa const updateCurNodeStatus = (node: CascaderItem, ulIndex: number) => { // 如果是半选状态,更新为false,其他状态则更新为与checked相反 if (node?.halfChecked) { // 更新半选状态 - node['halfChecked'] = false - node['checked'] = false - updateCheckStatusLoop(node, 'halfChecked', ulIndex) + node['halfChecked'] = false; + node['checked'] = false; + updateCheckStatusLoop(node, 'halfChecked', ulIndex); } else { - node['checked'] = !node.checked + node['checked'] = !node.checked; // 更新是否选中状态 - updateCheckStatusLoop(node, 'checked', ulIndex, node.checked) + updateCheckStatusLoop(node, 'checked', ulIndex, node.checked); } - } + }; /** * 父节点改变子节点check状态 * @param node 节点 */ - const updateCheckStatusLoop = (node: CascaderItem, type: CheckedType, ulIndex: number, status?: boolean) => { + const updateCheckStatusLoop = (node: CascaderItem, type: CheckedType, ulIndex: number, status?: boolean) => { if (node?.children?.length > 0) { node.children.forEach(item => { // 当需要改变checked时 // halfChecked一定是false - if (item.disabled) return // 禁用不可更改状态 + if (item.disabled) {return;} // 禁用不可更改状态 if (type === 'checked') { - item[type] = status - item['halfChecked'] = false - updateCheckStatusLoop(item, type, ulIndex, status) + item[type] = status; + item['halfChecked'] = false; + updateCheckStatusLoop(item, type, ulIndex, status); } else if (type === 'halfChecked') { /** * halfChecked为false时,取消子节点所有选中 */ - item['halfChecked'] = false - item['checked'] = false - !status && updateCheckStatusLoop(item, type, ulIndex) + item['halfChecked'] = false; + item['checked'] = false; + !status && updateCheckStatusLoop(item, type, ulIndex); } - }) + }); } else { // 增加或者删除选中的项 !node.checked - ? multipleDeleteTag(tagList, node) - : multipleAddTag(tagList, node) + ? multipleDeleteTag(tagList, node) + : multipleAddTag(tagList, node); } - } + }; return { updateStatus, - } -} + }; +}; /** * 子节点获取父节点 * 已在子节点创建父节点,此段代码不再使用 @@ -166,26 +166,26 @@ export const updateCheckOptionStatus = (tagList: CascaderItem[]): UpdateStatusCa * 根据当前节点的子节点更新当前节点状态 * @param node - 当前节点 */ - const findChildrenCheckedStatusToUpdateParent = (node) => { - const checkedChild = node?.children?.find(t => t['checked']) - const halfcheckedChild = node?.children?.find(t => t['halfChecked']) - const uncheckedChild = node?.children?.find(t => !t['halfChecked'] && !t['checked']) +const findChildrenCheckedStatusToUpdateParent = (node) => { + const checkedChild = node?.children?.find(t => t['checked']); + const halfcheckedChild = node?.children?.find(t => t['halfChecked']); + const uncheckedChild = node?.children?.find(t => !t['halfChecked'] && !t['checked']); if (halfcheckedChild || (checkedChild && uncheckedChild)) { - node['checked'] = false - node['halfChecked'] = true + node['checked'] = false; + node['halfChecked'] = true; } else if (!checkedChild && !halfcheckedChild) { - node['checked'] = false - node['halfChecked'] = false + node['checked'] = false; + node['halfChecked'] = false; } else { - node['checked'] = true - node['halfChecked'] = false + node['checked'] = true; + node['halfChecked'] = false; } -} +}; const updateParentNodeStatus = (node: CascaderItem, options: CaascaderOptionsType, ulIndex: number) => { - if (ulIndex < 0) return - findChildrenCheckedStatusToUpdateParent(node) - ulIndex -= 1 + if (ulIndex < 0) {return;} + findChildrenCheckedStatusToUpdateParent(node); + ulIndex -= 1; // const parentNode = getParentNode(node.value, options, ulIndex) - const parentNode = node?.parent - updateParentNodeStatus(parentNode, options, ulIndex) -} \ No newline at end of file + const parentNode = node?.parent; + updateParentNodeStatus(parentNode, options, ulIndex); +}; diff --git a/packages/devui-vue/devui/cascader/hooks/use-cascader-options.ts b/packages/devui-vue/devui/cascader/hooks/use-cascader-options.ts index 1c3c897aa0..5bb7607db4 100644 --- a/packages/devui-vue/devui/cascader/hooks/use-cascader-options.ts +++ b/packages/devui-vue/devui/cascader/hooks/use-cascader-options.ts @@ -1,27 +1,27 @@ /** * 处理传入options数据 */ -import { CascaderItem, OptionsCallback, CaascaderOptionsType } from '../src/cascader-types' +import { CascaderItem, OptionsCallback, CaascaderOptionsType } from '../src/cascader-types'; export const optionsHandles = (cascaderOptions?: CaascaderOptionsType): OptionsCallback => { /** * change时修改展示项 * @param optionItem - 项 * @param ulIndex - 当前选中的第几级 - * + * */ const changeCascaderIndexs = (optionItem: CascaderItem, ulIndex: number) => { - if (!cascaderOptions) return + if (!cascaderOptions) {return;} if (optionItem?.children?.length > 0) { - cascaderOptions[ulIndex + 1] = optionItem.children + cascaderOptions[ulIndex + 1] = optionItem.children; } else { // 选择的项没有子项时清除多余的ul - cascaderOptions.splice(ulIndex + 1, cascaderOptions.length - 1 - ulIndex) + cascaderOptions.splice(ulIndex + 1, cascaderOptions.length - 1 - ulIndex); } - } + }; return { cascaderOptions, changeCascaderIndexs - } -} + }; +}; diff --git a/packages/devui-vue/devui/cascader/hooks/use-cascader-popup.ts b/packages/devui-vue/devui/cascader/hooks/use-cascader-popup.ts index 2f4bb5f1ad..6e1f4e6e1c 100644 --- a/packages/devui-vue/devui/cascader/hooks/use-cascader-popup.ts +++ b/packages/devui-vue/devui/cascader/hooks/use-cascader-popup.ts @@ -2,26 +2,26 @@ * 控制窗口打开收起 */ import { ref, watch, computed } from 'vue'; -import { PopupTypes, CascaderProps } from '../src/cascader-types' -import { dropdownOpenClass } from './use-cascader-class' +import { PopupTypes, CascaderProps } from '../src/cascader-types'; +import { dropdownOpenClass } from './use-cascader-class'; export const popupHandles = (props: CascaderProps): PopupTypes => { - const menuShow = ref(false) - const menuOpenClass = ref('') - const disabled = computed(() => props.disabled) // select是否被禁用 - const stopDefault = ref(false) + const menuShow = ref(false); + const menuOpenClass = ref(''); + const disabled = computed(() => props.disabled); // select是否被禁用 + const stopDefault = ref(false); const updateStopDefaultType = () => { - stopDefault.value = !menuShow.value - } + stopDefault.value = !menuShow.value; + }; const openPopup = () => { - if (disabled.value) return - menuShow.value = !menuShow.value - updateStopDefaultType() - } + if (disabled.value) {return;} + menuShow.value = !menuShow.value; + updateStopDefaultType(); + }; watch(menuShow, (status) => { - menuOpenClass.value = dropdownOpenClass(status) - }) + menuOpenClass.value = dropdownOpenClass(status); + }); return { menuShow, @@ -29,5 +29,5 @@ export const popupHandles = (props: CascaderProps): PopupTypes => { menuOpenClass, updateStopDefaultType, openPopup, - } -} + }; +}; diff --git a/packages/devui-vue/devui/cascader/hooks/use-cascader-single.ts b/packages/devui-vue/devui/cascader/hooks/use-cascader-single.ts index 52409fa989..affde31ffd 100644 --- a/packages/devui-vue/devui/cascader/hooks/use-cascader-single.ts +++ b/packages/devui-vue/devui/cascader/hooks/use-cascader-single.ts @@ -1,8 +1,8 @@ /** * 单选模式 - * */ -import { Ref } from 'vue' -import { CascaderItem, CascaderValueType } from '../src/cascader-types' + * */ +import { Ref } from 'vue'; +import { CascaderItem, CascaderValueType } from '../src/cascader-types'; /** * 初始化打开时的视图选中状态 * 通过value集合获取下标集合 @@ -12,27 +12,27 @@ import { CascaderItem, CascaderValueType } from '../src/cascader-types' * @param activeIndexs 当前渲染到视图列的下标集合 */ export const initActiveIndexs = (values: CascaderValueType, curColumn: CascaderItem[], index: number, activeIndexs: number[]): void => { - let nextOption = null + let nextOption = null; for (let i = 0; i < curColumn.length; i++) { if (curColumn[i]?.value === values[index]) { - nextOption = curColumn[i]?.children - activeIndexs[index] = i - break + nextOption = curColumn[i]?.children; + activeIndexs[index] = i; + break; } } if (index < values.length - 1 && nextOption) { - index += 1 - initActiveIndexs(values, nextOption, index, activeIndexs) + index += 1; + initActiveIndexs(values, nextOption, index, activeIndexs); } -} +}; /** * 缓存输入框内容 * @param inputValueCache 缓存的输入框内容,当最终确定时输出内容 */ export const initSingleIptValue = (inputValueCache: Ref): void => { - inputValueCache.value = '' -} + inputValueCache.value = ''; +}; /** * 单选选中 @@ -42,7 +42,7 @@ export const initSingleIptValue = (inputValueCache: Ref): void => { */ export const singleChoose = (ulIndex: number, valueCache: CascaderValueType, cascaderItem: CascaderItem): void => { // 删除当前联动级之后的所有级 - valueCache.splice(ulIndex, valueCache.length - ulIndex) + valueCache.splice(ulIndex, valueCache.length - ulIndex); // 更新当前active的value数组 - valueCache[ulIndex] = cascaderItem?.value as number -} \ No newline at end of file + valueCache[ulIndex] = cascaderItem?.value as number; +}; diff --git a/packages/devui-vue/devui/cascader/hooks/use-cascader-style.ts b/packages/devui-vue/devui/cascader/hooks/use-cascader-style.ts index e2374e98d5..42ca86018a 100644 --- a/packages/devui-vue/devui/cascader/hooks/use-cascader-style.ts +++ b/packages/devui-vue/devui/cascader/hooks/use-cascader-style.ts @@ -1,17 +1,17 @@ /** * 定义组件 style */ -import { CascaderProps, RootStyleFeedback, CascaderulProps, DropdownStyleFeedback } from '../src/cascader-types' +import { CascaderProps, RootStyleFeedback, CascaderulProps, DropdownStyleFeedback } from '../src/cascader-types'; // 根节点样式 export const useRootStyle = (props: CascaderProps): RootStyleFeedback => { return { inputWidth: `width: ${props.width}px`, - } -} + }; +}; // 弹出层样式 export const useDropdownStyle = (props: CascaderulProps): DropdownStyleFeedback => { return { dropdownWidth: `width: ${props?.dropdownWidth}px` - } -} \ No newline at end of file + }; +}; diff --git a/packages/devui-vue/devui/cascader/index.ts b/packages/devui-vue/devui/cascader/index.ts index 1e95f9128f..1366a94dac 100644 --- a/packages/devui-vue/devui/cascader/index.ts +++ b/packages/devui-vue/devui/cascader/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Cascader from './src/cascader' +import type { App } from 'vue'; +import Cascader from './src/cascader'; Cascader.install = function(app: App): void { - app.component(Cascader.name, Cascader) -} + app.component(Cascader.name, Cascader); +}; -export { Cascader } +export { Cascader }; export default { title: 'Cascader 级联菜单', category: '数据录入', status: '30%', install(app: App): void { - app.use(Cascader as any) + app.use(Cascader as any); } -} +}; diff --git a/packages/devui-vue/devui/cascader/src/cascader-types.ts b/packages/devui-vue/devui/cascader/src/cascader-types.ts index f88ae148ce..e216d742c0 100644 --- a/packages/devui-vue/devui/cascader/src/cascader-types.ts +++ b/packages/devui-vue/devui/cascader/src/cascader-types.ts @@ -1,25 +1,25 @@ -import type { PropType, ExtractPropTypes, Ref } from 'vue' -import { UnwrapNestedRefs } from '@vue/reactivity' +import type { PropType, ExtractPropTypes, Ref } from 'vue'; +import { UnwrapNestedRefs } from '@vue/reactivity'; -type TriggerTypes = 'hover'|'click' +type TriggerTypes = 'hover'|'click'; export interface CascaderItem { - label: string - value: number | string - isLeaf?: boolean - children?: CascaderItem[] - checked?: boolean - halfChecked?: boolean - disabled?: boolean - active?: boolean - _loading?: boolean - icon?: string + label: string; + value: number | string; + isLeaf?: boolean; + children?: CascaderItem[]; + checked?: boolean; + halfChecked?: boolean; + disabled?: boolean; + active?: boolean; + _loading?: boolean; + icon?: string; // 用户可以传入自定义属性,并在dropDownItemTemplate中使用 - [prop: string]: any + [prop: string]: any; } -type CascaderModelValue = number[] -export type CascaderValueType = CascaderModelValue | [CascaderModelValue] +type CascaderModelValue = number[]; +export type CascaderValueType = CascaderModelValue | [CascaderModelValue]; export const cascaderProps = { /** * 可选,指定展开次级菜单方式 @@ -45,7 +45,7 @@ export const cascaderProps = { * @type { Number | String } * @default 200 */ - dropdownWidth: { + dropdownWidth: { type: Number || String, default: 200 }, @@ -106,47 +106,47 @@ export const cascaderProps = { type: Function as PropType<(v: CascaderValueType, k: CascaderItem[]) => void>, default: undefined }, -} as const +} as const; -export type CascaderProps = ExtractPropTypes +export type CascaderProps = ExtractPropTypes; export interface PopupTypes { - menuShow: Ref - menuOpenClass: Ref - stopDefault: Ref - openPopup: (e?: MouseEvent) => void - updateStopDefaultType: () => void + menuShow: Ref; + menuOpenClass: Ref; + stopDefault: Ref; + openPopup: (e?: MouseEvent) => void; + updateStopDefaultType: () => void; } -export type CaascaderOptionsType = UnwrapNestedRefs<[CascaderItem[]]> +export type CaascaderOptionsType = UnwrapNestedRefs<[CascaderItem[]]>; export interface OptionsCallback { - cascaderOptions: never | CaascaderOptionsType - changeCascaderIndexs: (optionItem: CascaderItem, ulIndex: number) => void + cascaderOptions: never | CaascaderOptionsType; + changeCascaderIndexs: (optionItem: CascaderItem, ulIndex: number) => void; } // type cascaderItemExtendsProps = 'trigger' // export type PickCascader = Pick // export interface CascaderItemNeedType extends PickCascader { - export interface CascaderItemNeedType { - valueCache?: CascaderValueType - trigger?: TriggerTypes - value?: CascaderValueType - inputValueCache?: Ref - confirmInputValueFlg?: Ref - multiple?: boolean - stopDefault?: Ref - activeIndexs?: number[] - tagList?: UnwrapNestedRefs +export interface CascaderItemNeedType { + valueCache?: CascaderValueType; + trigger?: TriggerTypes; + value?: CascaderValueType; + inputValueCache?: Ref; + confirmInputValueFlg?: Ref; + multiple?: boolean; + stopDefault?: Ref; + activeIndexs?: number[]; + tagList?: UnwrapNestedRefs; } export interface UseCascaderItemCallback { - cascaderItemNeedProps: CascaderItemNeedType + cascaderItemNeedProps: CascaderItemNeedType; // getInputValue: (a: string, b?: CascaderItem[], c?: Ref) => void } -export type CheckedType = 'checked' | 'halfChecked' +export type CheckedType = 'checked' | 'halfChecked'; export interface RootStyleFeedback { - inputWidth: string + inputWidth: string; } export const cascaderulProps = { @@ -157,7 +157,7 @@ export const cascaderulProps = { */ cascaderItems: { type: Array as PropType, - default: ():CascaderItem[] => ([{ + default: (): CascaderItem[] => ([{ label: '', value: null }]), @@ -167,7 +167,7 @@ export const cascaderulProps = { * @type { Number | String } * @default 200 */ - dropdownWidth: { + dropdownWidth: { type: Number || String, default: 200 }, @@ -182,7 +182,7 @@ export const cascaderulProps = { }, cascaderItemNeedProps: { type: Object as PropType, - default: ():CascaderItemNeedType => ({}) + default: (): CascaderItemNeedType => ({}) }, stopDefault: { type: Boolean, @@ -190,29 +190,29 @@ export const cascaderulProps = { }, cascaderOptions: { type: Array as unknown as PropType<[CascaderItem[]]>, - default: ():[CascaderItem[]] => ([[{ + default: (): [CascaderItem[]] => ([[{ label: '', value: null }]]) } -} -export type CascaderulProps = ExtractPropTypes +}; +export type CascaderulProps = ExtractPropTypes; export interface CascaderItemPropsType extends CascaderulProps { - cascaderItem: CascaderItem - liIndex: number - cascaderItemNeedProps: CascaderItemNeedType + cascaderItem: CascaderItem; + liIndex: number; + cascaderItemNeedProps: CascaderItemNeedType; } export interface DropdownStyleFeedback { - dropdownWidth: string + dropdownWidth: string; } export interface MultiplePropsType { - activeOptions: CascaderItem[] - placeholder: string + activeOptions: CascaderItem[]; + placeholder: string; } export interface UpdateStatusCallback { - updateStatus: (node: CascaderItem, options: CaascaderOptionsType, ulIndex: number) => void -} \ No newline at end of file + updateStatus: (node: CascaderItem, options: CaascaderOptionsType, ulIndex: number) => void; +} diff --git a/packages/devui-vue/devui/cascader/src/cascader.tsx b/packages/devui-vue/devui/cascader/src/cascader.tsx index 4ff039a2ea..7f06a8ea04 100644 --- a/packages/devui-vue/devui/cascader/src/cascader.tsx +++ b/packages/devui-vue/devui/cascader/src/cascader.tsx @@ -1,51 +1,51 @@ // 公共库 -import { cloneDeep } from 'lodash' -import { defineComponent, ref, Ref, reactive, watch, toRef } from 'vue' +import { cloneDeep } from 'lodash'; +import { defineComponent, ref, Ref, reactive, watch, toRef } from 'vue'; // 组件 -import DCascaderList from '../components/cascader-list' -import DMultipleBox from '../components/cascader-multiple/index' +import DCascaderList from '../components/cascader-list'; +import DMultipleBox from '../components/cascader-multiple/index'; // 事件 -import { cascaderProps, CascaderItem, CascaderProps, CascaderValueType } from './cascader-types' -import { useCascaderItem } from '../hooks/use-cascader-item' -import { useRootClassName } from '../hooks/use-cascader-class' -import { useRootStyle } from '../hooks/use-cascader-style' -import { popupHandles } from '../hooks/use-cascader-popup' -import { initMultipleCascaderItem, initTagList } from '../hooks/use-cascader-multiple' -import { initSingleIptValue, initActiveIndexs } from '../hooks/use-cascader-single' -import './cascader.scss' +import { cascaderProps, CascaderItem, CascaderProps, CascaderValueType } from './cascader-types'; +import { useCascaderItem } from '../hooks/use-cascader-item'; +import { useRootClassName } from '../hooks/use-cascader-class'; +import { useRootStyle } from '../hooks/use-cascader-style'; +import { popupHandles } from '../hooks/use-cascader-popup'; +import { initMultipleCascaderItem, initTagList } from '../hooks/use-cascader-multiple'; +import { initSingleIptValue, initActiveIndexs } from '../hooks/use-cascader-single'; +import './cascader.scss'; export default defineComponent({ name: 'DCascader', props: cascaderProps, setup(props: CascaderProps, ctx) { - const origin = ref(null) - const cascaderOptions = reactive<[CascaderItem[]]>(cloneDeep([ props?.options ])) - const multiple = toRef(props, 'multiple') - const inputValue = ref('') - const tagList = reactive([]) // 多选模式下选中的值数组,用于生成tag - const rootStyle = useRootStyle(props) - let initIptValue = props.value.length > 0 ? true : false // 有value默认值时,初始化输出内容 - + const origin = ref(null); + const cascaderOptions = reactive<[CascaderItem[]]>(cloneDeep([ props?.options ])); + const multiple = toRef(props, 'multiple'); + const inputValue = ref(''); + const tagList = reactive([]); // 多选模式下选中的值数组,用于生成tag + const rootStyle = useRootStyle(props); + let initIptValue = props.value.length > 0 ? true : false; // 有value默认值时,初始化输出内容 + const position = reactive({ originX: 'left', originY: 'bottom', overlayX: 'left', overlayY: 'top' - } as const) + } as const); // popup弹出层 - const { menuShow, menuOpenClass, openPopup, stopDefault, updateStopDefaultType } = popupHandles(props) + const { menuShow, menuOpenClass, openPopup, stopDefault, updateStopDefaultType } = popupHandles(props); // 配置class - const rootClasses = useRootClassName(props, menuShow) + const rootClasses = useRootClassName(props, menuShow); // 传递给cascaderItem的props - const { cascaderItemNeedProps } = useCascaderItem(props, stopDefault, tagList) + const { cascaderItemNeedProps } = useCascaderItem(props, stopDefault, tagList); const getInputValue = (label: string, arr: CascaderItem[], inputValueCache: Ref, showPath?: boolean) => { if (!showPath) { - inputValueCache.value = label + inputValueCache.value = label; } else { - inputValueCache.value += (label + (arr?.length > 0 ? ' / ' : '')) + inputValueCache.value += (label + (arr?.length > 0 ? ' / ' : '')); } - } + }; /** * 控制视图更新 * 注意视图更新不区分单选或者多选 @@ -54,21 +54,21 @@ export default defineComponent({ * @param index value的下标,起始为0 */ const updateCascaderView = (value: CascaderValueType, currentOption: CascaderItem[], index: number) => { - if (index === value.length) return - const i = value[index] as number + if (index === value.length) {return;} + const i = value[index] as number; // 当前的子级 - const current = currentOption[i] - const children = current?.children + const current = currentOption[i]; + const children = current?.children; if (children?.length > 0) { // 为下一级增添数据 - cascaderOptions[index + 1] = children + cascaderOptions[index + 1] = children; // 递归添加 - updateCascaderView(value, children, index + 1) + updateCascaderView(value, children, index + 1); } else { // 当最新的ul(级)没有下一级时删除之前选中ul的数据 - cascaderOptions.splice(index + 1, cascaderOptions.length - 1) + cascaderOptions.splice(index + 1, cascaderOptions.length - 1); } - } + }; /** * 选中项输出 * 需要区分单选或多选模式 @@ -79,37 +79,37 @@ export default defineComponent({ const updateCascaderValue = (value: CascaderValueType, currentOption: CascaderItem[], index: number) => { if (!multiple.value) { // 单选模式 - if (index === value.length) return - const i = value[index] as number + if (index === value.length) {return;} + const i = value[index] as number; // 当前的子级 - const current = getCurrentOption(currentOption, i) - const children = current?.children - getInputValue(current.label, children, cascaderItemNeedProps.inputValueCache, props.showPath) + const current = getCurrentOption(currentOption, i); + const children = current?.children; + getInputValue(current.label, children, cascaderItemNeedProps.inputValueCache, props.showPath); if (children?.length > 0) { - updateCascaderValue(value, children, index + 1) + updateCascaderValue(value, children, index + 1); } } else { // 多选模式 - const rootColumn = cascaderOptions[0] || [] // 第一列 + const rootColumn = cascaderOptions[0] || []; // 第一列 value.forEach((targetValue) => { - initMultipleCascaderItem(targetValue, rootColumn, tagList) - }) + initMultipleCascaderItem(targetValue, rootColumn, tagList); + }); } - } + }; /** * 根据value筛选每列中选中item */ const getCurrentOption = (currentOption: CascaderItem[], i: number) => { - return currentOption.filter(item => item?.value === i)[0] - } + return currentOption.filter(item => item?.value === i)[0]; + }; /** * 监听视图更新 */ watch(cascaderItemNeedProps.activeIndexs, val => { // TODO 多选模式下优化切换选择后的视图切换 - cascaderOptions.splice(val.length, cascaderOptions.length - 1) - updateCascaderView(val, cascaderOptions[0], 0) - }) + cascaderOptions.splice(val.length, cascaderOptions.length - 1); + updateCascaderView(val, cascaderOptions[0], 0); + }); /** * 监听点击最终的节点输出内容 */ @@ -117,24 +117,24 @@ export default defineComponent({ // 单选和多选模式初始化 multiple.value ? initTagList(tagList) - : initSingleIptValue(cascaderItemNeedProps.inputValueCache) + : initSingleIptValue(cascaderItemNeedProps.inputValueCache); // 输出确认的选中值 - cascaderItemNeedProps.value = reactive(cloneDeep(cascaderItemNeedProps.valueCache)) - menuShow.value = false + cascaderItemNeedProps.value = reactive(cloneDeep(cascaderItemNeedProps.valueCache)); + menuShow.value = false; // 点击确定过后禁止再次选中 - updateStopDefaultType() + updateStopDefaultType(); // 更新值 - updateCascaderValue(cascaderItemNeedProps.value, cascaderOptions[0], 0) - inputValue.value = cascaderItemNeedProps.inputValueCache.value + updateCascaderValue(cascaderItemNeedProps.value, cascaderOptions[0], 0); + inputValue.value = cascaderItemNeedProps.inputValueCache.value; // 单选模式默认回显视图的选中态 // 多选模式不默认视图打开状态,因为选中了太多个,无法确定展示哪一种选中态 if (initIptValue && !multiple.value) { - initActiveIndexs(props.value, cascaderOptions[0], 0, cascaderItemNeedProps.activeIndexs) - initIptValue = false // 只需要初始化一次,之后不再执行 + initActiveIndexs(props.value, cascaderOptions[0], 0, cascaderItemNeedProps.activeIndexs); + initIptValue = false; // 只需要初始化一次,之后不再执行 } }, { immediate: true - }) + }); return () => ( <> @@ -142,10 +142,10 @@ export default defineComponent({ { multiple.value ? : + disabled={props.disabled} + placeholder={props.placeholder} + modelValue={inputValue.value} + > }
    @@ -162,12 +162,12 @@ export default defineComponent({ cascaderOptions={cascaderOptions} dropdownWidth={props.dropdownWidth} {...props} - > + >; })}
    - ) + ); }, -}) +}); diff --git a/packages/devui-vue/devui/checkbox/__tests__/checkbox.spec.ts b/packages/devui-vue/devui/checkbox/__tests__/checkbox.spec.ts index 999edf453a..14928d8979 100644 --- a/packages/devui-vue/devui/checkbox/__tests__/checkbox.spec.ts +++ b/packages/devui-vue/devui/checkbox/__tests__/checkbox.spec.ts @@ -105,7 +105,7 @@ describe('checkbox', () => { halfchecked: true }); expect(container.classes()).toContain('halfchecked'); - expect(container.find('.devui-checkbox-default-background').exists()).toBe(false) + expect(container.find('.devui-checkbox-default-background').exists()).toBe(false); }); it('checkbox beforeChange work', async () => { diff --git a/packages/devui-vue/devui/checkbox/index.ts b/packages/devui-vue/devui/checkbox/index.ts index a602139f60..0daeda5fa1 100644 --- a/packages/devui-vue/devui/checkbox/index.ts +++ b/packages/devui-vue/devui/checkbox/index.ts @@ -1,16 +1,16 @@ -import type { App } from 'vue' -import Checkbox from './src/checkbox' -import CheckboxGroup from './src/checkbox-group' +import type { App } from 'vue'; +import Checkbox from './src/checkbox'; +import CheckboxGroup from './src/checkbox-group'; Checkbox.install = function (app: App) { - app.component(Checkbox.name, Checkbox) -} + app.component(Checkbox.name, Checkbox); +}; CheckboxGroup.install = function (app: App) { - app.component(CheckboxGroup.name, CheckboxGroup) -} + app.component(CheckboxGroup.name, CheckboxGroup); +}; -export { Checkbox } +export { Checkbox }; export default { title: 'Checkbox 复选框', @@ -20,4 +20,4 @@ export default { app.use(Checkbox as any); app.use(CheckboxGroup as any); } -} +}; diff --git a/packages/devui-vue/devui/checkbox/src/checkbox-group.tsx b/packages/devui-vue/devui/checkbox/src/checkbox-group.tsx index 58551aeaf5..c748ac97e9 100644 --- a/packages/devui-vue/devui/checkbox/src/checkbox-group.tsx +++ b/packages/devui-vue/devui/checkbox/src/checkbox-group.tsx @@ -1,14 +1,14 @@ -import { defineComponent, ExtractPropTypes, provide, toRef } from 'vue' -import { checkboxGroupProps, checkboxGroupInjectionKey } from './use-checkbox' -import DCheckbox from './checkbox' -import './checkbox-group.scss' +import { defineComponent, ExtractPropTypes, provide, toRef } from 'vue'; +import { checkboxGroupProps, checkboxGroupInjectionKey } from './use-checkbox'; +import DCheckbox from './checkbox'; +import './checkbox-group.scss'; export default defineComponent({ name: 'DCheckboxGroup', props: checkboxGroupProps, emits: ['change', 'update:modelValue'], setup(props: ExtractPropTypes, ctx) { - const valList = toRef(props, 'modelValue') + const valList = toRef(props, 'modelValue'); const defaultOpt = { checked: false, @@ -16,39 +16,39 @@ export default defineComponent({ halfchecked: false, showAnimation: true, disabled: false, - } + }; const toggleGroupVal = (val: string) => { - let index = -1 + let index = -1; if (typeof valList.value[0] === 'string') { - index = valList.value.findIndex((item) => item === val) + index = valList.value.findIndex((item) => item === val); } else if (typeof valList.value[0] === 'object') { - index = valList.value.findIndex((item) => item.value === val) + index = valList.value.findIndex((item) => item.value === val); } if (index === -1) { if (typeof props.options[0] === 'object') { - const newOne = props.options.find((item) => item.value === val) - const res = [...valList.value, newOne] - ctx.emit('update:modelValue', res) - ctx.emit('change', res) - return + const newOne = props.options.find((item) => item.value === val); + const res = [...valList.value, newOne]; + ctx.emit('update:modelValue', res); + ctx.emit('change', res); + return; } - const res = [...valList.value, val] - ctx.emit('update:modelValue', res) - ctx.emit('change', res) - return + const res = [...valList.value, val]; + ctx.emit('update:modelValue', res); + ctx.emit('change', res); + return; } - valList.value.splice(index, 1) - ctx.emit('update:modelValue', valList.value) - ctx.emit('change', valList.value) - } + valList.value.splice(index, 1); + ctx.emit('update:modelValue', valList.value); + ctx.emit('change', valList.value); + }; const isItemChecked = (itemVal: string) => { if (typeof valList.value[0] === 'string') { - return valList.value.includes(itemVal) + return valList.value.includes(itemVal); } else if (typeof valList.value[0] === 'object') { - return valList.value.some((item) => item.value === itemVal) + return valList.value.some((item) => item.value === itemVal); } - } + }; provide(checkboxGroupInjectionKey, { disabled: toRef(props, 'disabled'), @@ -60,33 +60,33 @@ export default defineComponent({ toggleGroupVal, itemWidth: toRef(props, 'itemWidth'), direction: toRef(props, 'direction'), - }) + }); return { defaultOpt, - } + }; }, render() { - const { direction, $slots, defaultOpt, options } = this - let children = $slots.default?.() + const { direction, $slots, defaultOpt, options } = this; + let children = $slots.default?.(); if (options?.length > 0) { children = options.map((opt) => { - let mergedOpt = null + let mergedOpt = null; if (typeof opt === 'string') { mergedOpt = Object.assign({}, defaultOpt, { label: opt, value: opt, - }) + }); } else if (typeof opt === 'object') { mergedOpt = Object.assign({}, defaultOpt, { ...opt, label: opt.name, - }) + }); } - return - }) + return ; + }); } return ( @@ -95,6 +95,6 @@ export default defineComponent({ {children} - ) + ); }, -}) +}); diff --git a/packages/devui-vue/devui/checkbox/src/checkbox.tsx b/packages/devui-vue/devui/checkbox/src/checkbox.tsx index d4bf54e8bd..38e4bbcd87 100644 --- a/packages/devui-vue/devui/checkbox/src/checkbox.tsx +++ b/packages/devui-vue/devui/checkbox/src/checkbox.tsx @@ -1,62 +1,62 @@ -import { defineComponent, inject, computed } from 'vue' -import './checkbox.scss' +import { defineComponent, inject, computed } from 'vue'; +import './checkbox.scss'; import { checkboxGroupInjectionKey, checkboxProps, CheckboxProps, -} from './use-checkbox' +} from './use-checkbox'; export default defineComponent({ name: 'DCheckbox', props: checkboxProps, emits: ['change', 'update:checked', 'update:modelValue'], setup(props: CheckboxProps, ctx) { - const checkboxGroupConf = inject(checkboxGroupInjectionKey, null) + const checkboxGroupConf = inject(checkboxGroupInjectionKey, null); - const isChecked = computed(() => props.checked || props.modelValue) + const isChecked = computed(() => props.checked || props.modelValue); const mergedDisabled = computed(() => { - return checkboxGroupConf?.disabled.value || props.disabled - }) + return checkboxGroupConf?.disabled.value || props.disabled; + }); const mergedChecked = computed(() => { - return checkboxGroupConf?.isItemChecked?.(props.value) ?? isChecked.value - }) + return checkboxGroupConf?.isItemChecked?.(props.value) ?? isChecked.value; + }); const mergedIsShowTitle = computed(() => { - return checkboxGroupConf?.isShowTitle.value ?? props.isShowTitle - }) + return checkboxGroupConf?.isShowTitle.value ?? props.isShowTitle; + }); const mergedShowAnimation = computed(() => { - return checkboxGroupConf?.showAnimation.value ?? props.showAnimation - }) + return checkboxGroupConf?.showAnimation.value ?? props.showAnimation; + }); const mergedColor = computed(() => { - return checkboxGroupConf?.color.value ?? props.color - }) - const itemWidth = checkboxGroupConf?.itemWidth.value - const direction = checkboxGroupConf?.direction.value + return checkboxGroupConf?.color.value ?? props.color; + }); + const itemWidth = checkboxGroupConf?.itemWidth.value; + const direction = checkboxGroupConf?.direction.value; const canChange = (isChecked: boolean, val: string) => { if (mergedDisabled.value) { - return Promise.resolve(false) + return Promise.resolve(false); } - const beforeChange = props.beforeChange ?? checkboxGroupConf?.beforeChange + const beforeChange = props.beforeChange ?? checkboxGroupConf?.beforeChange; if (beforeChange) { - const res = beforeChange(isChecked, val) + const res = beforeChange(isChecked, val); if (typeof res === 'boolean') { - return Promise.resolve(res) + return Promise.resolve(res); } - return res + return res; } - return Promise.resolve(true) - } + return Promise.resolve(true); + }; const toggle = () => { - const current = !isChecked.value - checkboxGroupConf?.toggleGroupVal(props.value) - ctx.emit('update:checked', current) - ctx.emit('update:modelValue', current) - ctx.emit('change', current) - } + const current = !isChecked.value; + checkboxGroupConf?.toggleGroupVal(props.value); + ctx.emit('update:checked', current); + ctx.emit('update:modelValue', current); + ctx.emit('change', current); + }; const handleClick = () => { - canChange(!isChecked.value, props.label).then((res) => res && toggle()) - } + canChange(!isChecked.value, props.label).then((res) => res && toggle()); + }; return { itemWidth, @@ -67,7 +67,7 @@ export default defineComponent({ mergedChecked, mergedShowAnimation, handleClick, - } + }; }, render() { const { @@ -85,48 +85,48 @@ export default defineComponent({ value, mergedColor, $slots, - } = this + } = this; const wrapperCls = { 'devui-checkbox-column-margin': direction === 'column', 'devui-checkbox-wrap': typeof itemWidth !== 'undefined', - } - const wrapperStyle = itemWidth ? [`width: ${itemWidth}px`] : [] + }; + const wrapperStyle = itemWidth ? [`width: ${itemWidth}px`] : []; const checkboxCls = { 'devui-checkbox': true, active: mergedChecked, halfchecked, disabled: mergedDisabled, unchecked: !mergedChecked, - } - const labelTitle = mergedIsShowTitle ? title || label : '' + }; + const labelTitle = mergedIsShowTitle ? title || label : ''; const bgImgStyle = (mergedColor && halfchecked) || mergedColor ? `linear-gradient(${mergedColor}, ${mergedColor})` - : '' + : ''; const spanStyle = [ `border-color:${ (mergedChecked || halfchecked) && mergedColor ? mergedColor : '' }`, `background-image:${bgImgStyle}`, `background-color:${mergedColor && halfchecked ? mergedColor : ''}`, - ] + ]; const spanCls = { 'devui-checkbox-material': true, 'custom-color': mergedColor, 'devui-checkbox-no-label': !label && !$slots.default, 'devui-no-animation': !mergedShowAnimation, 'devui-checkbox-default-background': !halfchecked, - } + }; const polygonCls = { 'devui-tick': true, 'devui-no-animation': !mergedShowAnimation, - } - const stopPropagation = ($event: Event) => $event.stopPropagation() + }; + const stopPropagation = ($event: Event) => $event.stopPropagation(); const inputProps = { indeterminate: halfchecked, - } + }; return (
    @@ -168,6 +168,6 @@ export default defineComponent({
    - ) + ); }, -}) +}); diff --git a/packages/devui-vue/devui/checkbox/src/use-checkbox.ts b/packages/devui-vue/devui/checkbox/src/use-checkbox.ts index 6a77a78fca..37070e14df 100644 --- a/packages/devui-vue/devui/checkbox/src/use-checkbox.ts +++ b/packages/devui-vue/devui/checkbox/src/use-checkbox.ts @@ -1,6 +1,6 @@ -import { PropType, InjectionKey, Ref, ExtractPropTypes } from 'vue' +import { PropType, InjectionKey, Ref, ExtractPropTypes } from 'vue'; -type Direction = 'row' | 'column' +type Direction = 'row' | 'column'; const commonProps = { name: { @@ -32,11 +32,11 @@ const commonProps = { }, beforeChange: { type: Function as PropType< - (isChecked: boolean, v: string) => boolean | Promise + (isChecked: boolean, v: string) => boolean | Promise >, default: undefined, }, -} as const +} as const; export const checkboxProps = { ...commonProps, @@ -73,9 +73,9 @@ export const checkboxProps = { 'onUpdate:modelValue': { type: Function as PropType<(v: boolean) => void>, }, -} as const +} as const; -export type CheckboxProps = ExtractPropTypes +export type CheckboxProps = ExtractPropTypes; export const checkboxGroupProps = { ...commonProps, @@ -92,7 +92,7 @@ export const checkboxGroupProps = { default: undefined, }, options: { - type: Array as PropType<({ value: string; } & Partial)[]>, + type: Array as PropType<({ value: string } & Partial)[]>, default: () => [], }, onChange: { @@ -103,21 +103,21 @@ export const checkboxGroupProps = { type: Function as PropType<(v: string[]) => void>, default: undefined, }, -} as const +} as const; interface checkboxGroupInjection { - disabled: Ref - isShowTitle: Ref - color: Ref - showAnimation: Ref + disabled: Ref; + isShowTitle: Ref; + color: Ref; + showAnimation: Ref; beforeChange: - | undefined - | ((isChecked: boolean, v: string) => boolean | Promise) - toggleGroupVal: (v: string) => void - isItemChecked: (v: string) => boolean - itemWidth: Ref - direction: Ref + | undefined + | ((isChecked: boolean, v: string) => boolean | Promise); + toggleGroupVal: (v: string) => void; + isItemChecked: (v: string) => boolean; + itemWidth: Ref; + direction: Ref; } export const checkboxGroupInjectionKey: InjectionKey = - Symbol('d-checkbox-group') + Symbol('d-checkbox-group'); diff --git a/packages/devui-vue/devui/color-picker/__tests__/color-picker.spec.ts b/packages/devui-vue/devui/color-picker/__tests__/color-picker.spec.ts index a4cd0eb1f6..f1a352d261 100644 --- a/packages/devui-vue/devui/color-picker/__tests__/color-picker.spec.ts +++ b/packages/devui-vue/devui/color-picker/__tests__/color-picker.spec.ts @@ -4,5 +4,5 @@ import { ColorPicker } from '../index'; describe('color-picker test', () => { it('color-picker init render', async () => { // todo - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/color-picker/index.ts b/packages/devui-vue/devui/color-picker/index.ts index 0b15cd3019..fa10a2b8e8 100644 --- a/packages/devui-vue/devui/color-picker/index.ts +++ b/packages/devui-vue/devui/color-picker/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import ColorPicker from './src/color-picker' +import type { App } from 'vue'; +import ColorPicker from './src/color-picker'; ColorPicker.install = function (app: App): void { - app.component(ColorPicker.name, ColorPicker) -} + app.component(ColorPicker.name, ColorPicker); +}; -export { ColorPicker } +export { ColorPicker }; export default { title: 'ColorPicker 颜色选择器', category: '数据录入', status: '80%', // TODO: 组件若开发完成则填入"100%",并删除该注释 install(app: App): void { - app.use(ColorPicker as any) + app.use(ColorPicker as any); } -} +}; diff --git a/packages/devui-vue/devui/color-picker/src/color-picker-types.ts b/packages/devui-vue/devui/color-picker/src/color-picker-types.ts index 7d6c4164bf..3087a4f8fc 100644 --- a/packages/devui-vue/devui/color-picker/src/color-picker-types.ts +++ b/packages/devui-vue/devui/color-picker/src/color-picker-types.ts @@ -1,4 +1,4 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; export const colorPickerProps = { modelValue: { type: [Object, String] as PropType @@ -21,6 +21,6 @@ export const colorPickerProps = { type: Boolean, default: true } -} as const +} as const; -export type ColorPickerProps = ExtractPropTypes +export type ColorPickerProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/color-picker/src/color-picker.tsx b/packages/devui-vue/devui/color-picker/src/color-picker.tsx index a3c91a2132..294b9c6b8a 100644 --- a/packages/devui-vue/devui/color-picker/src/color-picker.tsx +++ b/packages/devui-vue/devui/color-picker/src/color-picker.tsx @@ -10,18 +10,18 @@ import { unref, readonly, Transition -} from 'vue' +} from 'vue'; import { useReactive, colorPickerResize, isExhibitionColorPicker, changeColorValue -} from './utils/composeable' -import { colorPickerProps, ColorPickerProps } from './color-picker-types' -import colorPanel from './components/color-picker-panel/color-picker-panel' -import './color-picker.scss' -import { parseColor, extractColor, RGBAtoCSS } from './utils/color-utils' -import { ColorPickerColor } from './utils/color-utils-types' +} from './utils/composeable'; +import { colorPickerProps, ColorPickerProps } from './color-picker-types'; +import colorPanel from './components/color-picker-panel/color-picker-panel'; +import './color-picker.scss'; +import { parseColor, extractColor, RGBAtoCSS } from './utils/color-utils'; +import { ColorPickerColor } from './utils/color-utils-types'; export default defineComponent({ name: 'DColorPicker', components: { @@ -30,106 +30,106 @@ export default defineComponent({ props: colorPickerProps, emits: ['update:modelValue'], setup(props: ColorPickerProps, { emit }) { - const DEFAUTL_MODE = 'rgb' + const DEFAUTL_MODE = 'rgb'; const provideData = { showAlpha: useReactive(() => props.showAlpha), swatches: useReactive(() => props.swatches), dotSize: useReactive(() => props.dotSize), showHistory: useReactive(() => props.showHistory) - } - provide('provideData', readonly(provideData)) - const initialColor = ref(null) - const colorCubeRef = ref() - const pickerRef = ref() - const containerRef = ref() - const left = ref(0) - const top = ref(0) - const isChangeTextColor = ref(true) - const showColorPicker = ref(false) - const formItemText = ref(`${props.mode ?? DEFAUTL_MODE}`) - const mode = ref(unref(props.mode)) + }; + provide('provideData', readonly(provideData)); + const initialColor = ref(null); + const colorCubeRef = ref(); + const pickerRef = ref(); + const containerRef = ref(); + const left = ref(0); + const top = ref(0); + const isChangeTextColor = ref(true); + const showColorPicker = ref(false); + const formItemText = ref(`${props.mode ?? DEFAUTL_MODE}`); + const mode = ref(unref(props.mode)); onMounted(() => { // resize 响应式 colorpicker - window.addEventListener('resize', resize) + window.addEventListener('resize', resize); // 点击展示 colorpicker - window.addEventListener('click', isExhibition) - }) + window.addEventListener('click', isExhibition); + }); // ** computeds // colorpicker panel 组件位置 const colorPickerPostion = computed(() => { if (colorCubeRef.value) { return { transform: `translate(${left.value}px, ${top.value}px)` - } + }; } - return null - }) + return null; + }); // 交互触发item 颜色 面板 动态修改alpha后要还原 alpha 2021.12.18 const tiggerColor = computed(() => { - const currentColor = initialColor.value.rgba - const trigger = { ...currentColor, a: props.showAlpha ? currentColor.a : 1 } + const currentColor = initialColor.value.rgba; + const trigger = { ...currentColor, a: props.showAlpha ? currentColor.a : 1 }; return { backgroundColor: `${RGBAtoCSS(trigger)}` - } - }) + }; + }); // 交互面板 的value 值 动态展示 根据不同 type const formItemValue = computed(() => { - return extractColor(initialColor.value, '', formItemText.value, props.showAlpha) - }) + return extractColor(initialColor.value, '', formItemText.value, props.showAlpha); + }); // 动态 根据当前 透明度修改文本颜色 tips:根据不同 面板颜色 目前 不够优雅 const textColor = computed(() => { // 数字代表 hsv 中的value 值 纵轴 动态切换 文本颜色 - return changeColorValue(initialColor.value, 0.5) - }) + return changeColorValue(initialColor.value, 0.5); + }); // ** emits // 动态 交互面板 文本展示颜色 tips:根据不同 面板颜色 目前 不够优雅 function changeTextColor(value: boolean): void { - isChangeTextColor.value = value + isChangeTextColor.value = value; } // 通过修改画板 颜色 修改 v-model 颜色 function changePaletteColor(colorMap: ColorPickerColor): void { - updateUserColor(colorMap) + updateUserColor(colorMap); } // 通过用户点击触发修改 交互面板 文本类型 function changeTextModeType(type: string): void { - mode.value = type - formItemText.value = type + mode.value = type; + formItemText.value = type; } // 初始化的时候 确定 colopicker位置 由于 pickerref 默认 为 undefined 所以监听 showcolorpicker watch( () => showColorPicker.value, (newValue) => { - const textPalette = colorCubeRef.value?.getBoundingClientRect() + const textPalette = colorCubeRef.value?.getBoundingClientRect(); newValue && nextTick(() => { pickerRef.value.style.transform = `translate(${textPalette.left + 'px'}, ${ textPalette.top + window.scrollY + textPalette.height + 'px' - })` - }) + })`; + }); } - ) + ); // 监听用户输入 2021.12.10 watch( () => props.modelValue, (newValue) => { // 全部转换成对象 - updateUserColor(parseColor(newValue, initialColor.value)) + updateUserColor(parseColor(newValue, initialColor.value)); }, { immediate: true } - ) + ); // 更新用户输入颜色 2021.12.10 function updateUserColor(color) { - initialColor.value = color + initialColor.value = color; // 提取颜色 2021.12.10 - const value = extractColor(initialColor.value, props.modelValue, mode.value, props.showAlpha) - emit('update:modelValue', value) + const value = extractColor(initialColor.value, props.modelValue, mode.value, props.showAlpha); + emit('update:modelValue', value); } function resize() { - return colorPickerResize(colorCubeRef, top, left) + return colorPickerResize(colorCubeRef, top, left); } function isExhibition(event: Event) { - return isExhibitionColorPicker(event, colorCubeRef, pickerRef, showColorPicker) + return isExhibitionColorPicker(event, colorCubeRef, pickerRef, showColorPicker); } return () => { return ( @@ -172,7 +172,7 @@ export default defineComponent({ - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/color-picker/src/components/color-alpha-slider/color-picker-alpha-slider-types.ts b/packages/devui-vue/devui/color-picker/src/components/color-alpha-slider/color-picker-alpha-slider-types.ts index 51f23d935d..888edb6e4d 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-alpha-slider/color-picker-alpha-slider-types.ts +++ b/packages/devui-vue/devui/color-picker/src/components/color-alpha-slider/color-picker-alpha-slider-types.ts @@ -1,5 +1,5 @@ -import type { PropType, ExtractPropTypes } from 'vue' -import type { ColorPickerColor } from '../../utils/color-utils-types' +import type { PropType, ExtractPropTypes } from 'vue'; +import type { ColorPickerColor } from '../../utils/color-utils-types'; export const colorPickerAlphaSliderProps = { color: { @@ -20,6 +20,6 @@ export const colorPickerAlphaSliderProps = { type: Number, default: 300 } -} as const +} as const; -export type colorPickerAlphaSliderProps = ExtractPropTypes +export type colorPickerAlphaSliderProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/color-picker/src/components/color-basic/color-basic-types.ts b/packages/devui-vue/devui/color-picker/src/components/color-basic/color-basic-types.ts index b719464714..0a57b4e82a 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-basic/color-basic-types.ts +++ b/packages/devui-vue/devui/color-picker/src/components/color-basic/color-basic-types.ts @@ -1,10 +1,10 @@ -import type { PropType, ExtractPropTypes } from 'vue' -import type { ColorPickerColor } from '../../utils/color-utils-types' +import type { PropType, ExtractPropTypes } from 'vue'; +import type { ColorPickerColor } from '../../utils/color-utils-types'; export const colorPickerBasicColorProps = { color: { type: Object as PropType } -} as const +} as const; -export type colorPickerBasicColorProps = ExtractPropTypes +export type colorPickerBasicColorProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/color-picker/src/components/color-basic/color-basic.tsx b/packages/devui-vue/devui/color-picker/src/components/color-basic/color-basic.tsx index 3117b00cb1..ebda17ace7 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-basic/color-basic.tsx +++ b/packages/devui-vue/devui/color-picker/src/components/color-basic/color-basic.tsx @@ -1,20 +1,20 @@ -import { defineComponent, ref, inject } from 'vue' -import { colorPickerBasicColorProps } from './color-basic-types' -import { provideColorOptions } from '../../utils/color-utils-types' -import { fromHex } from '../../utils/color-utils' -import './color-basic.scss' -import { color } from '../../utils/color' +import { defineComponent, ref, inject } from 'vue'; +import { colorPickerBasicColorProps } from './color-basic-types'; +import { provideColorOptions } from '../../utils/color-utils-types'; +import { fromHex } from '../../utils/color-utils'; +import './color-basic.scss'; +import { color } from '../../utils/color'; export default defineComponent({ name: 'ColorBasic', props: colorPickerBasicColorProps, setup(props) { - const swatchesInject: provideColorOptions = inject('provideData') + const swatchesInject: provideColorOptions = inject('provideData'); - const currentColor = ref(props.color) + const currentColor = ref(props.color); function changeBasicColor(hex: string) { - currentColor.value = fromHex(hex) + currentColor.value = fromHex(hex); } - const swatches = ref(Object.values(swatchesInject.swatches ?? [])) + const swatches = ref(Object.values(swatchesInject.swatches ?? [])); return () => { return (
    @@ -26,7 +26,7 @@ export default defineComponent({ >
    ))} - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/color-picker/src/components/color-edit/color-edit.tsx b/packages/devui-vue/devui/color-picker/src/components/color-edit/color-edit.tsx index baa4b92bc5..60f39b4b16 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-edit/color-edit.tsx +++ b/packages/devui-vue/devui/color-picker/src/components/color-edit/color-edit.tsx @@ -1,14 +1,14 @@ -import { defineComponent, computed, ref, inject } from 'vue' -import { ColorPickerEditProps, colorPickerEditProps } from './color-picker-edit-types' -import { provideColorOptions, ColorPickerColor } from '../../utils/color-utils-types' -import './color-edit.scss' -import { fromHex, fromHexa, fromHSLA, fromHSVA, fromRGBA } from '../../utils/color-utils' -import Schema, { Rules } from 'async-validator' +import { defineComponent, computed, ref, inject } from 'vue'; +import { ColorPickerEditProps, colorPickerEditProps } from './color-picker-edit-types'; +import { provideColorOptions, ColorPickerColor } from '../../utils/color-utils-types'; +import './color-edit.scss'; +import { fromHex, fromHexa, fromHSLA, fromHSVA, fromRGBA } from '../../utils/color-utils'; +import Schema, { Rules } from 'async-validator'; // 默认 mode -const DEFAUTL_MODE = 'rgb' +const DEFAUTL_MODE = 'rgb'; // MODE支持模式 -const MODE_SUPPORT = ['rgb', 'hex', 'hsl', 'hsv'] as const +const MODE_SUPPORT = ['rgb', 'hex', 'hsl', 'hsv'] as const; // 色值校验规则 const colorRules: Rules = { @@ -52,7 +52,7 @@ const colorRules: Rules = { a: { type: 'number', required: true, min: 0, max: 1 } } } -} +}; export default defineComponent({ name: 'ColorEdit', @@ -60,17 +60,17 @@ export default defineComponent({ emits: ['changeTextModeColor', 'update:modelValue'], setup(props: ColorPickerEditProps, { emit }) { // 设置showalpha 为false 会报错 2021.12.14 - const isShowAlpha: provideColorOptions = inject('provideData') + const isShowAlpha: provideColorOptions = inject('provideData'); // 模式值 const modelValue = computed( () => `${props.mode ?? DEFAUTL_MODE}${isShowAlpha.showAlpha ? 'a' : ''}` - ) + ); // 颜色值 - const colorValue = ref(props.color) + const colorValue = ref(props.color); // 模式值类型 const modelValueType = computed(() => (props.mode ?? DEFAUTL_MODE) === 'hex' ? 'string' : 'number' - ) + ); /** * 获取有效颜色值 @@ -78,15 +78,15 @@ export default defineComponent({ * @returns */ function getValidColor(color: ColorPickerColor) { - const validator = new Schema(colorRules) + const validator = new Schema(colorRules); // 使用ColorRules验证有效性 return new Promise((resolve, reject) => { validator.validate(color, (errors) => { - errors && console.warn('色值校验异常:', errors) - errors ? reject() : resolve(color) - }) - }) + errors && console.warn('色值校验异常:', errors); + errors ? reject() : resolve(color); + }); + }); } /** @@ -94,9 +94,9 @@ export default defineComponent({ */ function onChangeModel() { // 安装MODE_SUPPORT列表进行更换 - const currentIndex = MODE_SUPPORT.findIndex((x) => x === props.mode ?? DEFAUTL_MODE) - const mode = MODE_SUPPORT[(currentIndex + 1) % MODE_SUPPORT.length] - emit('changeTextModeColor', mode) + const currentIndex = MODE_SUPPORT.findIndex((x) => x === props.mode ?? DEFAUTL_MODE); + const mode = MODE_SUPPORT[(currentIndex + 1) % MODE_SUPPORT.length]; + emit('changeTextModeColor', mode); } /** @@ -104,32 +104,32 @@ export default defineComponent({ */ function renderStringValue() { // 绑定KEy - const key = modelValue.value - const value = colorValue.value[key] + const key = modelValue.value; + const value = colorValue.value[key]; const getConvertColor = (v: string) => { // 获取转换函数 - const from = isShowAlpha.showAlpha ? fromHexa : fromHex + const from = isShowAlpha.showAlpha ? fromHexa : fromHex; // 获取颜色值 - const color = from(v) + const color = from(v); // 获取色值有效性 - return getValidColor(color) - } + return getValidColor(color); + }; /** * 更新输入值 */ const updateValue = async (event: Event) => { - const target = event.target as HTMLInputElement + const target = event.target as HTMLInputElement; getConvertColor(target.value) // 如果Color为有效值则进行更新 .then((color) => (colorValue.value = color)) // 如果Color为无效值则还原数值 - .catch(() => (target.value = value)) - } + .catch(() => (target.value = value)); + }; return (
    @@ -141,7 +141,7 @@ export default defineComponent({ />
    - ) + ); } /** @@ -151,12 +151,12 @@ export default defineComponent({ */ function renderNumberValue() { // 绑定缩放KEYS - const scaleKeys = ['s', 'v', 'l'] as const - const percentKeys = ['a'] as const + const scaleKeys = ['s', 'v', 'l'] as const; + const percentKeys = ['a'] as const; - const key = modelValue.value + const key = modelValue.value; // 对指定数值进行缩放处理 - const value = colorValue.value[key.replace(/a?$/, 'a')] + const value = colorValue.value[key.replace(/a?$/, 'a')]; const getConvertColor = (model) => { // 获取转换函数 @@ -164,19 +164,19 @@ export default defineComponent({ { mode: ['rgb', 'rgba'], from: fromRGBA }, { mode: ['hsv', 'hsva'], from: fromHSVA }, { mode: ['hsl', 'hsla'], from: fromHSLA } - ].find((x) => x.mode.includes(key)) + ].find((x) => x.mode.includes(key)); // 获取颜色值 - const color = from(isShowAlpha.showAlpha ? model : { ...model, a: 1 }) + const color = from(isShowAlpha.showAlpha ? model : { ...model, a: 1 }); // 通过RGBA进行验证有效性 - return getValidColor(color) - } + return getValidColor(color); + }; /** * 更新输入值 */ const updateValue = (k: string) => async (event: Event) => { - const target = event.target as HTMLInputElement + const target = event.target as HTMLInputElement; // 获取有效颜色值 // 无效则进行还原 @@ -185,8 +185,8 @@ export default defineComponent({ // 如果Color为有效值则进行更新 .then((color) => (colorValue.value = color)) // 如果Color为无效值则还原数值 - .catch(() => (target.value = formatValue(k, value[k]))) - } + .catch(() => (target.value = formatValue(k, value[k]))); + }; /** * 将存储值转换为显示值 @@ -196,12 +196,12 @@ export default defineComponent({ */ function formatValue(k, v: number): string { switch (true) { - case scaleKeys.includes(k): - return (v * 100).toFixed() - case percentKeys.includes(k): - return `${Math.round(v * 100)}%` - default: - return v.toString() + case scaleKeys.includes(k): + return (v * 100).toFixed(); + case percentKeys.includes(k): + return `${Math.round(v * 100)}%`; + default: + return v.toString(); } } @@ -213,12 +213,12 @@ export default defineComponent({ */ function parseValue(k, v: string): number { switch (true) { - case scaleKeys.includes(k): - return parseFloat((parseInt(v) / 100).toFixed(2)) - case percentKeys.includes(k): - return parseFloat((parseInt(v.replace(/%$/, '')) / 100).toFixed(2)) - default: - return Number(v) + case scaleKeys.includes(k): + return parseFloat((parseInt(v) / 100).toFixed(2)); + case percentKeys.includes(k): + return parseFloat((parseInt(v.replace(/%$/, '')) / 100).toFixed(2)); + default: + return Number(v); } } @@ -228,22 +228,22 @@ export default defineComponent({ */ function onKeyChangeValue() { return (e: KeyboardEvent) => { - const target = e.target as HTMLInputElement + const target = e.target as HTMLInputElement; const changeValue = { ArrowUp: 1, ArrowDown: -1 - }[e.code] + }[e.code]; if (changeValue !== undefined) { - e.preventDefault() - const [v] = target.value.match(/\d+/g) - const newValue = (parseInt(v) + changeValue).toString() - target.value = target.value.replace(/\d+/g, newValue) + e.preventDefault(); + const [v] = target.value.match(/\d+/g); + const newValue = (parseInt(v) + changeValue).toString(); + target.value = target.value.replace(/\d+/g, newValue); // 发送数值修改事件 - target.dispatchEvent(new CustomEvent('change')) + target.dispatchEvent(new CustomEvent('change')); } - } + }; } return ( @@ -259,7 +259,7 @@ export default defineComponent({ ))} - ) + ); } /** @@ -268,10 +268,10 @@ export default defineComponent({ */ function renderValueInput() { switch (modelValueType.value) { - case 'string': - return renderStringValue() - case 'number': - return renderNumberValue() + case 'string': + return renderStringValue(); + case 'number': + return renderNumberValue(); } } @@ -282,6 +282,6 @@ export default defineComponent({ {renderValueInput()} - ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/color-picker/src/components/color-edit/color-picker-edit-types.ts b/packages/devui-vue/devui/color-picker/src/components/color-edit/color-picker-edit-types.ts index e7310ebe00..44cfd47981 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-edit/color-picker-edit-types.ts +++ b/packages/devui-vue/devui/color-picker/src/components/color-edit/color-picker-edit-types.ts @@ -1,5 +1,5 @@ -import type { PropType, ExtractPropTypes } from 'vue' -import { ColorPickerColor } from '../../utils/color-utils-types' +import type { PropType, ExtractPropTypes } from 'vue'; +import { ColorPickerColor } from '../../utils/color-utils-types'; export const colorPickerEditProps = { /* test: { type: Object as PropType<{ xxx: xxx }> @@ -17,6 +17,6 @@ export const colorPickerEditProps = { color: { type: Object as PropType } -} as const +} as const; -export type ColorPickerEditProps = ExtractPropTypes +export type ColorPickerEditProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/color-picker/src/components/color-history/color-history.tsx b/packages/devui-vue/devui/color-picker/src/components/color-history/color-history.tsx index 266b13e8ee..6f95b22a82 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-history/color-history.tsx +++ b/packages/devui-vue/devui/color-picker/src/components/color-history/color-history.tsx @@ -1,13 +1,13 @@ -import { defineComponent, Ref, ref, UnwrapRef, watch, inject } from 'vue' -import { ColorPickerHistoryProps, colorPickerHistoryProps } from './color-picker-history-types' -import { Icon } from '../../../../icon' -import './color-history.scss' -import { fromHexa } from '../../utils/color-utils' -import { provideColorOptions, ColorPickerColor } from '../../utils/color-utils-types' -import { debounce } from 'lodash' +import { defineComponent, Ref, ref, UnwrapRef, watch, inject } from 'vue'; +import { ColorPickerHistoryProps, colorPickerHistoryProps } from './color-picker-history-types'; +import { Icon } from '../../../../icon'; +import './color-history.scss'; +import { fromHexa } from '../../utils/color-utils'; +import { provideColorOptions, ColorPickerColor } from '../../utils/color-utils-types'; +import { debounce } from 'lodash'; -const STORAGE_KEY = 'STORAGE_COLOR_PICKER_HISTORY_KEY' -const MAX_HISOTRY_COUNT = 8 +const STORAGE_KEY = 'STORAGE_COLOR_PICKER_HISTORY_KEY'; +const MAX_HISOTRY_COUNT = 8; /** * 创建支持存储Store @@ -15,27 +15,27 @@ const MAX_HISOTRY_COUNT = 8 * @param params * @returns */ -function useStore(v: T, { storage }: { storage?: boolean; } = {}): Ref> { +function useStore(v: T, { storage }: { storage?: boolean } = {}): Ref> { // 获取默认值 const getDefaultValue = (): T => { if (storage) { - return JSON.parse(localStorage.getItem(STORAGE_KEY)) || v + return JSON.parse(localStorage.getItem(STORAGE_KEY)) || v; } else { - return v + return v; } - } + }; // 创建Store - const store = ref(getDefaultValue()) + const store = ref(getDefaultValue()); // 监听Store修改 watch(store, (value) => { if (storage) { - localStorage.setItem(STORAGE_KEY, JSON.stringify(value)) + localStorage.setItem(STORAGE_KEY, JSON.stringify(value)); } - }) + }); - return store + return store; } export default defineComponent({ @@ -47,39 +47,39 @@ export default defineComponent({ emits: ['update:color'], setup(props: ColorPickerHistoryProps) { // 获取 是否showalpha - const alphaInject: provideColorOptions = inject('provideData') + const alphaInject: provideColorOptions = inject('provideData'); // 创建历史存储 - const history = useStore([], { storage: true }) - const color = ref(props.color) + const history = useStore([], { storage: true }); + const color = ref(props.color); // 更新历史值函数 // 进行缓冲处理 const updateHistory = debounce((value: ColorPickerColor) => { const index = history.value.findIndex( (x) => x === value.hexa || (x.endsWith('00') && value.alpha === 0) - ) + ); if (index >= 0) { - history.value.splice(index, 1) + history.value.splice(index, 1); } history.value = [alphaInject.showAlpha ? value.hexa : value.hex, ...history.value].slice( 0, MAX_HISOTRY_COUNT - ) - }, 100) + ); + }, 100); // 更新历史值 watch(props.color, (value) => { - updateHistory(value) - }) + updateHistory(value); + }); /** * 选择历史色 * @param value */ function onChangeColor(value: string) { - color.value = fromHexa(value) + color.value = fromHexa(value); } return () => ( @@ -95,6 +95,6 @@ export default defineComponent({ > ))} - ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/color-picker/src/components/color-history/color-picker-history-types.ts b/packages/devui-vue/devui/color-picker/src/components/color-history/color-picker-history-types.ts index 454b44d98d..ad3956459e 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-history/color-picker-history-types.ts +++ b/packages/devui-vue/devui/color-picker/src/components/color-history/color-picker-history-types.ts @@ -1,10 +1,10 @@ -import type { PropType, ExtractPropTypes } from 'vue' -import type { ColorPickerColor } from '../../utils/color-utils-types' +import type { PropType, ExtractPropTypes } from 'vue'; +import type { ColorPickerColor } from '../../utils/color-utils-types'; export const colorPickerHistoryProps = { color: { type: Object as PropType } -} as const +} as const; -export type ColorPickerHistoryProps = ExtractPropTypes +export type ColorPickerHistoryProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/color-picker/src/components/color-hue-slider/color-picker-hue-slider-types.ts b/packages/devui-vue/devui/color-picker/src/components/color-hue-slider/color-picker-hue-slider-types.ts index c4bcd4314a..3c4e951069 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-hue-slider/color-picker-hue-slider-types.ts +++ b/packages/devui-vue/devui/color-picker/src/components/color-hue-slider/color-picker-hue-slider-types.ts @@ -1,5 +1,5 @@ -import type { PropType, ExtractPropTypes } from 'vue' -import type { ColorPickerColor } from '../../utils/color-utils-types' +import type { PropType, ExtractPropTypes } from 'vue'; +import type { ColorPickerColor } from '../../utils/color-utils-types'; export const colorPickerHueSliderProps = { /* test: { @@ -22,6 +22,6 @@ export const colorPickerHueSliderProps = { type: Number, default: 15 } -} as const +} as const; -export type colorPickerHueSliderProps = ExtractPropTypes +export type colorPickerHueSliderProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/color-picker/src/components/color-palette/color-picker-palette-types.ts b/packages/devui-vue/devui/color-picker/src/components/color-palette/color-picker-palette-types.ts index 577f8a4328..a60bd3ed84 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-palette/color-picker-palette-types.ts +++ b/packages/devui-vue/devui/color-picker/src/components/color-palette/color-picker-palette-types.ts @@ -1,6 +1,6 @@ -import type { PropType, ExtractPropTypes } from 'vue' -import { fromRGBA } from '../../utils/color-utils' -import type { ColorPickerColor } from '../../utils/color-utils-types' +import type { PropType, ExtractPropTypes } from 'vue'; +import { fromRGBA } from '../../utils/color-utils'; +import type { ColorPickerColor } from '../../utils/color-utils-types'; export const colorPickerPaletteProps = { modelValue: { @@ -11,6 +11,6 @@ export const colorPickerPaletteProps = { type: Number, default: 200 } -} as const +} as const; -export type colorPickerPaletteProps = ExtractPropTypes +export type colorPickerPaletteProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/color-picker/src/components/color-picker-panel/color-picker-panel-types.ts b/packages/devui-vue/devui/color-picker/src/components/color-picker-panel/color-picker-panel-types.ts index f6194b8264..7f6f6d76bb 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-picker-panel/color-picker-panel-types.ts +++ b/packages/devui-vue/devui/color-picker/src/components/color-picker-panel/color-picker-panel-types.ts @@ -1,5 +1,5 @@ -import type { PropType, ExtractPropTypes } from 'vue' -import { ColorPickerColor } from '../../utils/color-utils-types' +import type { PropType, ExtractPropTypes } from 'vue'; +import { ColorPickerColor } from '../../utils/color-utils-types'; export const colorPickerProps = { colorMap: { @@ -15,6 +15,6 @@ export const colorPickerProps = { mode: { type: String } -} as const +} as const; -export type ColorPickerProps = ExtractPropTypes +export type ColorPickerProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/color-picker/src/components/color-picker-panel/color-picker-panel.tsx b/packages/devui-vue/devui/color-picker/src/components/color-picker-panel/color-picker-panel.tsx index a47afcc54e..da72e3a0f7 100644 --- a/packages/devui-vue/devui/color-picker/src/components/color-picker-panel/color-picker-panel.tsx +++ b/packages/devui-vue/devui/color-picker/src/components/color-picker-panel/color-picker-panel.tsx @@ -1,14 +1,14 @@ -import { defineComponent, ref, watch, nextTick, inject } from 'vue' -import { colorPickerProps, ColorPickerProps } from './color-picker-panel-types' -import { provideColorOptions } from '../../utils/color-utils-types' -import { Tabs } from '../../../../tabs' -import colorPalette from '../color-palette/color-palette' -import colorHueSlider from '../color-hue-slider/color-hue-slider' -import colorAlphaSlider from '../color-alpha-slider/color-alpha-slider' -import colorEdit from '../color-edit/color-edit' -import colorBasic from '../color-basic/color-basic' -import './color-picker-panel.scss' -import colorHistory from '../color-history/color-history' +import { defineComponent, ref, watch, nextTick, inject } from 'vue'; +import { colorPickerProps, ColorPickerProps } from './color-picker-panel-types'; +import { provideColorOptions } from '../../utils/color-utils-types'; +import { Tabs } from '../../../../tabs'; +import colorPalette from '../color-palette/color-palette'; +import colorHueSlider from '../color-hue-slider/color-hue-slider'; +import colorAlphaSlider from '../color-alpha-slider/color-alpha-slider'; +import colorEdit from '../color-edit/color-edit'; +import colorBasic from '../color-basic/color-basic'; +import './color-picker-panel.scss'; +import colorHistory from '../color-history/color-history'; export default defineComponent({ name: 'ColorPanel', components: { @@ -29,30 +29,30 @@ export default defineComponent({ 'changeTextModeType' ], setup(props: ColorPickerProps, { emit }) { - const injectData: provideColorOptions = inject('provideData') - const paletteElement = ref(null) - const showAlpha = injectData.showAlpha - const tab = ref('basic') + const injectData: provideColorOptions = inject('provideData'); + const paletteElement = ref(null); + const showAlpha = injectData.showAlpha; + const tab = ref('basic'); function changeTextColor(isChange: boolean) { - emit('changeTextColor', isChange) + emit('changeTextColor', isChange); } function changeTextModeColor(currentType: string) { - emit('changeTextModeType', currentType) + emit('changeTextModeType', currentType); } // 画板值 - const paletteColorMap = ref(props.modelValue) + const paletteColorMap = ref(props.modelValue); // hue slider 值 watch( () => paletteColorMap.value, (newValue) => { - emit('update:modelValue', newValue) - emit('changePaletteColor', newValue) + emit('update:modelValue', newValue); + emit('changePaletteColor', newValue); nextTick(() => { - paletteElement.value && paletteElement.value.renderCanvas() - }) + paletteElement.value && paletteElement.value.renderCanvas(); + }); } - ) + ); return () => { return (
    @@ -80,7 +80,7 @@ export default defineComponent({ > {injectData.showHistory ? : null}
    - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/color-picker/src/utils/color-utils-types.ts b/packages/devui-vue/devui/color-picker/src/utils/color-utils-types.ts index 6260930b5a..69ffa94ed6 100644 --- a/packages/devui-vue/devui/color-picker/src/utils/color-utils-types.ts +++ b/packages/devui-vue/devui/color-picker/src/utils/color-utils-types.ts @@ -1,42 +1,42 @@ -import { Ref } from 'vue' +import { Ref } from 'vue'; -export type ColorModeType = 'hsl' | 'rgb' | 'hsv' | 'hsv' | 'hex' +export type ColorModeType = 'hsl' | 'rgb' | 'hsv' | 'hsv' | 'hex'; export interface provideColorOptions { - mode?: ColorModeType - showAlpha?: boolean - tab?: string - dotSize?: number - swatches?: string[] - showHistory?: boolean + mode?: ColorModeType; + showAlpha?: boolean; + tab?: string; + dotSize?: number; + swatches?: string[]; + showHistory?: boolean; } export interface CssColorObject { - color?: Hex + color?: Hex; } export interface ColorPickerColor { - alpha: number - hex: Hex - hexa: Hexa - hsla: HSLA - hsva: HSVA - hue: number - rgba: RGBA - hsv?: any - hsl?: any + alpha: number; + hex: Hex; + hexa: Hexa; + hsla: HSLA; + hsva: HSVA; + hue: number; + rgba: RGBA; + hsv?: any; + hsl?: any; } export interface position { - left?: Ref - top?: Ref - right?: Ref - bottom?: Ref + left?: Ref; + top?: Ref; + right?: Ref; + bottom?: Ref; } // Types -export type ColorInt = number -export type HSV = { h: number; s: number; v: number; } -export type HSVA = HSV & { a: number; } -export type RGB = { r: number; g: number; b: number; } -export type RGBA = RGB & { a: number; } -export type HSL = { h: number; s: number; l: number; } -export type HSLA = HSL & { a: number; } -export type Hex = string -export type Hexa = string -export type Color = string | number | {} +export type ColorInt = number; +export type HSV = { h: number; s: number; v: number }; +export type HSVA = HSV & { a: number }; +export type RGB = { r: number; g: number; b: number }; +export type RGBA = RGB & { a: number }; +export type HSL = { h: number; s: number; l: number }; +export type HSLA = HSL & { a: number }; +export type Hex = string; +export type Hexa = string; +export type Color = string | number | {}; diff --git a/packages/devui-vue/devui/color-picker/src/utils/color-utils.ts b/packages/devui-vue/devui/color-picker/src/utils/color-utils.ts index eec542f0e1..96c267031b 100644 --- a/packages/devui-vue/devui/color-picker/src/utils/color-utils.ts +++ b/packages/devui-vue/devui/color-picker/src/utils/color-utils.ts @@ -1,6 +1,6 @@ // Utilities -import { ref } from 'vue' -import { chunk, padEnd, has, keepDecimal } from './helpers' +import { ref } from 'vue'; +import { chunk, padEnd, has, keepDecimal } from './helpers'; import { ColorPickerColor, position, @@ -14,56 +14,56 @@ import { Hex, Hexa, Color -} from './color-utils-types' +} from './color-utils-types'; export function isCssColor(color?: string | false): boolean { - return !!color && !!color.match(/^(#|var\(--|(rgb|hsl)a?\()/) + return !!color && !!color.match(/^(#|var\(--|(rgb|hsl)a?\()/); } export function colorToInt(color: Color): ColorInt { - let rgb + let rgb; if (typeof color === 'number') { - rgb = color + rgb = color; } else if (typeof color === 'string') { - let c = color[0] === '#' ? color.substring(1) : color + let c = color[0] === '#' ? color.substring(1) : color; if (c.length === 3) { c = c .split('') .map((char) => char + char) - .join('') + .join(''); } if (c.length !== 6) { // consoleWarn(`'${color}' is not a valid rgb color`) } - rgb = parseInt(c, 16) + rgb = parseInt(c, 16); } else { throw new TypeError( `Colors can only be numbers or strings, recieved ${ color == null ? color : color.constructor.name } instead` - ) + ); } if (rgb < 0) { // consoleWarn(`Colors cannot be negative: '${color}'`) - rgb = 0 + rgb = 0; } else if (rgb > 0xffffff || isNaN(rgb)) { // consoleWarn(`'${color}' is not a valid rgb color`) - rgb = 0xffffff + rgb = 0xffffff; } - return rgb + return rgb; } export function intToHex(color: ColorInt): string { - let hexColor: string = color.toString(16) + let hexColor: string = color.toString(16); - if (hexColor.length < 6) hexColor = '0'.repeat(6 - hexColor.length) + hexColor + if (hexColor.length < 6) {hexColor = '0'.repeat(6 - hexColor.length) + hexColor;} - return '#' + hexColor + return '#' + hexColor; } export function colorToHex(color: Color): string { - return intToHex(colorToInt(color)) + return intToHex(colorToInt(color)); } /** @@ -72,15 +72,15 @@ export function colorToHex(color: Color): string { * @param color HSVA color as an array [0-360, 0-1, 0-1, 0-1] */ export function HSVAtoRGBA(hsva: HSVA): RGBA { - const { h, s, v, a } = hsva + const { h, s, v, a } = hsva; const f = (n: number) => { - const k = (n + h / 60) % 6 - return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0) - } + const k = (n + h / 60) % 6; + return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0); + }; - const rgb = [f(5), f(3), f(1)].map((v) => Math.round(v * 255)) + const rgb = [f(5), f(3), f(1)].map((v) => Math.round(v * 255)); - return { r: rgb[0], g: rgb[1], b: rgb[2], a } + return { r: rgb[0], g: rgb[1], b: rgb[2], a }; } /** @@ -89,125 +89,125 @@ export function HSVAtoRGBA(hsva: HSVA): RGBA { * @param color RGBA color as an array [0-255, 0-255, 0-255, 0-1] */ export function RGBAtoHSVA(rgba: RGBA): HSVA { - if (!rgba) return { h: 0, s: 1, v: 1, a: 1 } + if (!rgba) {return { h: 0, s: 1, v: 1, a: 1 };} - const r = rgba.r / 255 - const g = rgba.g / 255 - const b = rgba.b / 255 - const max = Math.max(r, g, b) - const min = Math.min(r, g, b) + const r = rgba.r / 255; + const g = rgba.g / 255; + const b = rgba.b / 255; + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); - let h = 0 + let h = 0; if (max !== min) { if (max === r) { - h = 60 * (0 + (g - b) / (max - min)) + h = 60 * (0 + (g - b) / (max - min)); } else if (max === g) { - h = 60 * (2 + (b - r) / (max - min)) + h = 60 * (2 + (b - r) / (max - min)); } else if (max === b) { - h = 60 * (4 + (r - g) / (max - min)) + h = 60 * (4 + (r - g) / (max - min)); } } - if (h < 0) h = h + 360 + if (h < 0) {h = h + 360;} - const s = max === 0 ? 0 : (max - min) / max - const hsv = [h, s, max] + const s = max === 0 ? 0 : (max - min) / max; + const hsv = [h, s, max]; - return { h: Math.round(hsv[0]), s: hsv[1], v: hsv[2], a: rgba.a } + return { h: Math.round(hsv[0]), s: hsv[1], v: hsv[2], a: rgba.a }; } export function HSVAtoHSLA(hsva: HSVA): HSLA { - const { h, s, v, a } = hsva + const { h, s, v, a } = hsva; - const l = v - (v * s) / 2 + const l = v - (v * s) / 2; - const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l) + const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l); - return { h: Math.round(h), s: sprime, l, a } + return { h: Math.round(h), s: sprime, l, a }; } export function HSLAtoHSVA(hsl: HSLA): HSVA { - const { h, s, l, a } = hsl + const { h, s, l, a } = hsl; - const v = l + s * Math.min(l, 1 - l) + const v = l + s * Math.min(l, 1 - l); - const sprime = v === 0 ? 0 : 2 - (2 * l) / v + const sprime = v === 0 ? 0 : 2 - (2 * l) / v; - return { h: Math.round(h), s: sprime, v, a } + return { h: Math.round(h), s: sprime, v, a }; } export function RGBAtoCSS(rgba: RGBA): string { - return `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})` + return `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`; } export function RGBtoCSS(rgba: RGBA): string { - return RGBAtoCSS({ ...rgba, a: 1 }) + return RGBAtoCSS({ ...rgba, a: 1 }); } export function RGBAtoHex(rgba: RGBA): Hex { const toHex = (v: number) => { - const h = Math.round(v).toString(16) - return ('00'.substring(0, 2 - h.length) + h).toUpperCase() - } + const h = Math.round(v).toString(16); + return ('00'.substring(0, 2 - h.length) + h).toUpperCase(); + }; return `#${[toHex(rgba.r), toHex(rgba.g), toHex(rgba.b), toHex(Math.round(rgba.a * 255))].join( '' - )}` + )}`; } export function HexToRGBA(hex: Hex): RGBA { - const rgba = chunk(hex.slice(1), 2).map((c: string) => parseInt(c, 16)) + const rgba = chunk(hex.slice(1), 2).map((c: string) => parseInt(c, 16)); return { r: rgba[0], g: rgba[1], b: rgba[2], a: Math.round((rgba[3] / 255) * 100) / 100 - } + }; } export function HexToHSVA(hex: Hex): HSVA { - const rgb = HexToRGBA(hex) - return RGBAtoHSVA(rgb) + const rgb = HexToRGBA(hex); + return RGBAtoHSVA(rgb); } export function HSVAtoHex(hsva: HSVA): Hex { - return RGBAtoHex(HSVAtoRGBA(hsva)) + return RGBAtoHex(HSVAtoRGBA(hsva)); } export function parseHex(hex: string): Hex { if (hex.startsWith('#')) { - hex = hex.slice(1) + hex = hex.slice(1); } - hex = hex.replace(/([^0-9a-f])/gi, 'F') + hex = hex.replace(/([^0-9a-f])/gi, 'F'); if (hex.length === 3 || hex.length === 4) { hex = hex .split('') .map((x) => x + x) - .join('') + .join(''); } if (hex.length === 6) { - hex = padEnd(hex, 8, 'F') + hex = padEnd(hex, 8, 'F'); } else { - hex = padEnd(padEnd(hex, 6), 8, 'F') + hex = padEnd(padEnd(hex, 6), 8, 'F'); } - return `#${hex}`.toUpperCase().substring(0, 9) + return `#${hex}`.toUpperCase().substring(0, 9); } export function RGBtoInt(rgba: RGBA): ColorInt { - return (rgba.r << 16) + (rgba.g << 8) + rgba.b + return (rgba.r << 16) + (rgba.g << 8) + rgba.b; } export function fromHSVA(hsva: HSVA): ColorPickerColor { - hsva = { ...hsva } - const hexa = HSVAtoHex(hsva) - const hsla = HSVAtoHSLA(hsva) - const rgba = HSVAtoRGBA(hsva) + hsva = { ...hsva }; + const hexa = HSVAtoHex(hsva); + const hsla = HSVAtoHSLA(hsva); + const rgba = HSVAtoRGBA(hsva); return { alpha: hsva.a, hex: hexa.substring(0, 7), @@ -216,14 +216,14 @@ export function fromHSVA(hsva: HSVA): ColorPickerColor { hsva, hue: hsva.h, rgba - } + }; } export function fromRGBA(rgba: RGBA): ColorPickerColor { - const hsva = RGBAtoHSVA(rgba) - const hexa = RGBAtoHex(rgba) - const hsla = HSVAtoHSLA(hsva) - const hsv = { h: hsva.h, s: hsva.s, v: hsva.v } - const hsl = { h: hsla.h, s: hsla.s, l: hsla.l } + const hsva = RGBAtoHSVA(rgba); + const hexa = RGBAtoHex(rgba); + const hsla = HSVAtoHSLA(hsva); + const hsv = { h: hsva.h, s: hsva.s, v: hsva.v }; + const hsl = { h: hsla.h, s: hsla.s, l: hsla.l }; return { alpha: hsva.a, hex: hexa.substring(0, 7), @@ -234,12 +234,12 @@ export function fromRGBA(rgba: RGBA): ColorPickerColor { hsl, hue: hsva.h, rgba - } + }; } export function fromHexa(hexa: Hexa): ColorPickerColor { - const hsva = HexToHSVA(hexa) - const hsla = HSVAtoHSLA(hsva) - const rgba = HSVAtoRGBA(hsva) + const hsva = HexToHSVA(hexa); + const hsla = HSVAtoHSLA(hsva); + const rgba = HSVAtoRGBA(hsva); return { alpha: hsva.a, hex: hexa.substring(0, 7), @@ -248,12 +248,12 @@ export function fromHexa(hexa: Hexa): ColorPickerColor { hsva, hue: hsva.h, rgba - } + }; } export function fromHSLA(hsla: HSLA): ColorPickerColor { - const hsva = HSLAtoHSVA(hsla) - const hexa = HSVAtoHex(hsva) - const rgba = HSVAtoRGBA(hsva) + const hsva = HSLAtoHSVA(hsla); + const hexa = HSVAtoHex(hsva); + const rgba = HSVAtoRGBA(hsva); return { alpha: hsva.a, hex: hexa.substring(0, 7), @@ -262,220 +262,220 @@ export function fromHSLA(hsla: HSLA): ColorPickerColor { hsva, hue: hsva.h, rgba - } + }; } export function fromHex(hex: Hex): ColorPickerColor { - return fromHexa(parseHex(hex)) + return fromHexa(parseHex(hex)); } export function parseColor(color: Color, oldColor?: ColorPickerColor | null): ColorPickerColor { - if (!color) return fromRGBA({ r: 0, g: 0, b: 0, a: 1 }) + if (!color) {return fromRGBA({ r: 0, g: 0, b: 0, a: 1 });} if (typeof color === 'string') { if (color.indexOf('#') !== -1) { // const hex = color.replace('#', '').trim() // return fromHexa(hex) } else if (color.indexOf('hsl') !== -1) { - let alpha = null + let alpha = null; const parts = color .replace(/hsla|hsl|\(|\)/gm, '') .split(/\s|,/g) .filter((val) => val !== '') - .map((val) => parseFloat(val)) + .map((val) => parseFloat(val)); if (parts.length === 4) { - alpha = parts[3] + alpha = parts[3]; } else if (parts.length === 3) { - alpha = 1 + alpha = 1; } - return fromHSLA({ h: parts[0], s: parts[1], l: parts[2], a: alpha }) + return fromHSLA({ h: parts[0], s: parts[1], l: parts[2], a: alpha }); } else if (color.indexOf('rgb') !== -1) { - let alpha = null + let alpha = null; const parts = color .replace(/rgba|rgb|\(|\)/gm, '') .split(/\s|,/g) .filter((val) => val !== '') - .map((val) => parseFloat(val)) + .map((val) => parseFloat(val)); if (parts.length === 4) { - alpha = parts[3] + alpha = parts[3]; } else if (parts.length === 3) { - alpha = 1 + alpha = 1; } - return fromRGBA({ r: parts[0], g: parts[1], b: parts[2], a: alpha }) + return fromRGBA({ r: parts[0], g: parts[1], b: parts[2], a: alpha }); } else if (color.indexOf('hsv') !== -1) { - let alpha = null + let alpha = null; const parts = color .replace(/hsva|hsv|\(|\)/gm, '') .split(/\s|,/g) .filter((val) => val !== '') - .map((val) => parseFloat(val)) + .map((val) => parseFloat(val)); if (parts.length === 4) { - alpha = parts[3] + alpha = parts[3]; } else if (parts.length === 3) { - alpha = 1 + alpha = 1; } - return fromHSVA({ h: parts[0], s: parts[1], v: parts[2], a: alpha }) + return fromHSVA({ h: parts[0], s: parts[1], v: parts[2], a: alpha }); } - if (color === 'transparent') return fromHexa('#00000000') - const hex = parseHex(color) + if (color === 'transparent') {return fromHexa('#00000000');} + const hex = parseHex(color); if (oldColor && hex === oldColor.hexa) { - return oldColor + return oldColor; } else { - return fromHexa(hex) + return fromHexa(hex); } } if (typeof color === 'object') { - if (color.hasOwnProperty('alpha')) return color + if (color.hasOwnProperty('alpha')) {return color;} - const a = color.hasOwnProperty('a') ? parseFloat(color.a) : 1 + const a = color.hasOwnProperty('a') ? parseFloat(color.a) : 1; if (has(color, ['r', 'g', 'b'])) { - if (oldColor && color === oldColor.rgba) return oldColor - else return fromRGBA({ ...color, a }) + if (oldColor && color === oldColor.rgba) {return oldColor;} + else {return fromRGBA({ ...color, a });} } else if (has(color, ['h', 's', 'l'])) { - if (oldColor && color === oldColor.hsla) return oldColor - else return fromHSLA({ ...color, a }) + if (oldColor && color === oldColor.hsla) {return oldColor;} + else {return fromHSLA({ ...color, a });} } else if (has(color, ['h', 's', 'v'])) { - if (oldColor && color === oldColor.hsva) return oldColor - else return fromHSVA({ ...color, a }) + if (oldColor && color === oldColor.hsva) {return oldColor;} + else {return fromHSVA({ ...color, a });} } } - return fromRGBA({ r: 255, g: 0, b: 0, a: 1 }) + return fromRGBA({ r: 255, g: 0, b: 0, a: 1 }); } function stripAlpha(color: Color, stripAlpha: boolean) { if (stripAlpha) { - const { a, ...rest } = color + const { a, ...rest } = color; - return rest + return rest; } - return color + return color; } export function extractColor(color: ColorPickerColor, input: Color, mode, showAlpha: boolean): any { // 色相 - const hue = keepDecimal(color.hsla.h, 2) + const hue = keepDecimal(color.hsla.h, 2); // 饱和度 - const hslSaturation = keepDecimal(color.hsla.s, 2) + const hslSaturation = keepDecimal(color.hsla.s, 2); // 亮度 - const lightness = keepDecimal(color.hsla.l, 2) + const lightness = keepDecimal(color.hsla.l, 2); // red - const red = keepDecimal(color.rgba.r) + const red = keepDecimal(color.rgba.r); // green - const green = keepDecimal(color.rgba.g) + const green = keepDecimal(color.rgba.g); // blue - const blue = keepDecimal(color.rgba.b) + const blue = keepDecimal(color.rgba.b); // HSV饱和度 - const hsvSaturation = keepDecimal(color.hsva.s, 2) + const hsvSaturation = keepDecimal(color.hsva.s, 2); // value - const value = keepDecimal(color.hsva.v, 2) - if (input == null) return color + const value = keepDecimal(color.hsva.v, 2); + if (input == null) {return color;} function isShowAlpha(mode) { - return showAlpha ? mode + 'a' : mode + return showAlpha ? mode + 'a' : mode; } if (typeof input === 'string') { if (mode === 'hex') { - return showAlpha ? color.hexa : color.hex + return showAlpha ? color.hexa : color.hex; } else if (mode === 'hsl') { return `${isShowAlpha(mode)}(${hue}, ${hslSaturation}, ${lightness}${ showAlpha ? ', ' + color.alpha : '' - })` + })`; } else if (mode === 'rgb') { - return `${isShowAlpha(mode)}(${red}, ${green}, ${blue}${showAlpha ? ', ' + color.alpha : ''})` + return `${isShowAlpha(mode)}(${red}, ${green}, ${blue}${showAlpha ? ', ' + color.alpha : ''})`; } else if (mode === 'hsv') { return `${isShowAlpha(mode)}(${hue}, ${hsvSaturation}, ${value}${ showAlpha ? ', ' + color.alpha : '' - })` + })`; } - return input.length === 7 ? color.hex : color.hexa + return input.length === 7 ? color.hex : color.hexa; } if (typeof input === 'object') { - const shouldStrip = typeof input.a === 'number' && input.a === 0 ? !!input.a : !input.a - if (has(input, ['r', 'g', 'b'])) return stripAlpha(color.rgba, shouldStrip) - else if (has(input, ['h', 's', 'l'])) return stripAlpha(color.hsla, shouldStrip) - else if (has(input, ['h', 's', 'v'])) return stripAlpha(color.hsva, shouldStrip) + const shouldStrip = typeof input.a === 'number' && input.a === 0 ? !!input.a : !input.a; + if (has(input, ['r', 'g', 'b'])) {return stripAlpha(color.rgba, shouldStrip);} + else if (has(input, ['h', 's', 'l'])) {return stripAlpha(color.hsla, shouldStrip);} + else if (has(input, ['h', 's', 'v'])) {return stripAlpha(color.hsva, shouldStrip);} } } export function hasAlpha(color: Color): boolean { - if (!color) return false + if (!color) {return false;} if (typeof color === 'string') { - return color.length > 7 + return color.length > 7; } if (typeof color === 'object') { - return has(color, ['a']) || has(color, ['alpha']) + return has(color, ['a']) || has(color, ['alpha']); } - return false + return false; } export const elementResize = (parentElement: HTMLElement): position => { - const left = ref(0) - const top = ref(0) + const left = ref(0); + const top = ref(0); window.addEventListener('resize', () => { - left.value = parentElement?.getBoundingClientRect().left + left.value = parentElement?.getBoundingClientRect().left; top.value = - parentElement?.getBoundingClientRect().top + parentElement?.getBoundingClientRect().height - }) + parentElement?.getBoundingClientRect().top + parentElement?.getBoundingClientRect().height; + }); return { left, top - } -} + }; +}; export function RGBtoRGBA(rgba: RGBA): RGBA { if (typeof rgba === 'string') { - rgba = (/rgba?\((.*?)\)/.exec(rgba) || ['', '0,0,0,1'])[1].split(',') + rgba = (/rgba?\((.*?)\)/.exec(rgba) || ['', '0,0,0,1'])[1].split(','); return { r: Number(rgba[0]) || 0, g: Number(rgba[1]) || 0, b: Number(rgba[2]) || 0, a: Number(rgba[3] ? rgba[3] : 1) // Avoid the case of 0 - } + }; } else { - return rgba + return rgba; } } export function RGBtoHSV(rgb: RGB): HSV { - if (!rgb) return { h: 0, s: 1, v: 1 } + if (!rgb) {return { h: 0, s: 1, v: 1 };} - const r = rgb.r / 255 - const g = rgb.g / 255 - const b = rgb.b / 255 - const max = Math.max(r, g, b) - const min = Math.min(r, g, b) + const r = rgb.r / 255; + const g = rgb.g / 255; + const b = rgb.b / 255; + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); - let h = 0 + let h = 0; if (max !== min) { if (max === r) { - h = 60 * (0 + (g - b) / (max - min)) + h = 60 * (0 + (g - b) / (max - min)); } else if (max === g) { - h = 60 * (2 + (b - r) / (max - min)) + h = 60 * (2 + (b - r) / (max - min)); } else if (max === b) { - h = 60 * (4 + (r - g) / (max - min)) + h = 60 * (4 + (r - g) / (max - min)); } } - if (h < 0) h = h + 360 + if (h < 0) {h = h + 360;} - const s = max === 0 ? 0 : (max - min) / max - const hsv = [h, s, max] + const s = max === 0 ? 0 : (max - min) / max; + const hsv = [h, s, max]; - return { h: hsv[0], s: hsv[1].toFixed(2), v: hsv[2].toFixed(2) } + return { h: hsv[0], s: hsv[1].toFixed(2), v: hsv[2].toFixed(2) }; } export function HSVtoHSL(hsv: HSV): HSL { - const { h, s, v } = hsv + const { h, s, v } = hsv; - const l = Number((v - (v * s) / 2).toFixed(2)) + const l = Number((v - (v * s) / 2).toFixed(2)); - const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l) + const sprime = l === 1 || l === 0 ? 0 : (v - l) / Math.min(l, 1 - l); - return { h, s: Number(sprime.toFixed(2)), l } + return { h, s: Number(sprime.toFixed(2)), l }; } diff --git a/packages/devui-vue/devui/color-picker/src/utils/color.ts b/packages/devui-vue/devui/color-picker/src/utils/color.ts index 435f0913c4..5b5153086e 100644 --- a/packages/devui-vue/devui/color-picker/src/utils/color.ts +++ b/packages/devui-vue/devui/color-picker/src/utils/color.ts @@ -44,4 +44,4 @@ export const color: string[] = [ '#021eaa', '#797baa', '#ab1942' -] +]; diff --git a/packages/devui-vue/devui/color-picker/src/utils/composeable.ts b/packages/devui-vue/devui/color-picker/src/utils/composeable.ts index 507f2cf1ad..952e12246e 100644 --- a/packages/devui-vue/devui/color-picker/src/utils/composeable.ts +++ b/packages/devui-vue/devui/color-picker/src/utils/composeable.ts @@ -1,13 +1,13 @@ -import { Ref, ref, watch } from 'vue' -import { ColorPickerColor, CssColorObject } from './color-utils-types' +import { Ref, ref, watch } from 'vue'; +import { ColorPickerColor, CssColorObject } from './color-utils-types'; export function colorPickerResize( colorCubeRef: Ref, top: Ref, left: Ref ): void { - const rect = colorCubeRef.value?.getBoundingClientRect() - left.value = rect?.left - top.value = rect?.top + window.scrollY + rect.height + const rect = colorCubeRef.value?.getBoundingClientRect(); + left.value = rect?.left; + top.value = rect?.top + window.scrollY + rect.height; } export function isExhibitionColorPicker( event: PointerEvent, @@ -16,19 +16,19 @@ export function isExhibitionColorPicker( showColorPicker: Ref ): void { if (colorCubeRef.value?.contains(event.target)) { - showColorPicker.value = true + showColorPicker.value = true; } if (!!pickerRef.value && !pickerRef.value?.contains(event.target)) { - showColorPicker.value = !showColorPicker.value + showColorPicker.value = !showColorPicker.value; } } export function useReactive(source: () => T): Ref { - const model = ref() - model.value = source() + const model = ref(); + model.value = source(); watch(source, (newValue) => { - model.value = newValue - }) - return model + model.value = newValue; + }); + return model; } // 根据 value 饱和度 判断文本颜色 @@ -36,8 +36,8 @@ export function changeColorValue(value: ColorPickerColor, maxValue: number): Css if (value.alpha > maxValue) { return value.hsva.v > maxValue && value.hsva.s < maxValue ? { color: '#000' } - : { color: '#fff' } + : { color: '#fff' }; } else { - return { color: '#000' } + return { color: '#000' }; } } diff --git a/packages/devui-vue/devui/color-picker/src/utils/helpers.ts b/packages/devui-vue/devui/color-picker/src/utils/helpers.ts index 9052074fb2..134b98c6fe 100644 --- a/packages/devui-vue/devui/color-picker/src/utils/helpers.ts +++ b/packages/devui-vue/devui/color-picker/src/utils/helpers.ts @@ -1,48 +1,48 @@ export function padEnd(str: string, length: number, char = '0'): string { - return str + char.repeat(Math.max(0, length - str.length)) + return str + char.repeat(Math.max(0, length - str.length)); } export function chunk(str: string, size = 1): string[] { - const chunked: string[] = [] - let index = 0 + const chunked: string[] = []; + let index = 0; while (index < str.length) { - chunked.push(str.substr(index, size)) - index += size + chunked.push(str.substr(index, size)); + index += size; } - return chunked + return chunked; } export function mergeObjects(source, target): any { - return Object.assign(source, target) + return Object.assign(source, target); } export function parseHex(value: string): number { - return parseInt(value, 16) + return parseInt(value, 16); } export const clamp = (value: number, min: number, max: number): number => { return min < max ? value < min ? min : value > max - ? max - : value + ? max + : value : value < max - ? max - : value > min - ? min - : value -} + ? max + : value > min + ? min + : value; +}; export const upperCase = (word: string): string => { - return word.toLocaleUpperCase() -} + return word.toLocaleUpperCase(); +}; export const lowerCase = (word: string): string => { - return word.toLocaleLowerCase() -} + return word.toLocaleLowerCase(); +}; export function splitStr(str: string, chars: string): string { - return str.split(chars)[0] + return str.split(chars)[0]; } // 保留小数工具 export function keepDecimal(value: number, digits = 0): number { - const COUNT_VALUE = 10 ** digits - return Math.round(value * COUNT_VALUE) / COUNT_VALUE + const COUNT_VALUE = 10 ** digits; + return Math.round(value * COUNT_VALUE) / COUNT_VALUE; } export function has(obj: any, key: string[]): boolean { - return key.every((k) => obj.hasOwnProperty(k)) + return key.every((k) => obj.hasOwnProperty(k)); } diff --git a/packages/devui-vue/devui/comment/__tests__/comment.spec.ts b/packages/devui-vue/devui/comment/__tests__/comment.spec.ts index 1d2277d449..2452db8a50 100644 --- a/packages/devui-vue/devui/comment/__tests__/comment.spec.ts +++ b/packages/devui-vue/devui/comment/__tests__/comment.spec.ts @@ -4,5 +4,5 @@ import { Comment } from '../index'; describe('comment test', () => { it('comment init render', async () => { // todo - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/comment/index.ts b/packages/devui-vue/devui/comment/index.ts index c55970c9e5..d0027d09f3 100644 --- a/packages/devui-vue/devui/comment/index.ts +++ b/packages/devui-vue/devui/comment/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Comment from './src/comment' +import type { App } from 'vue'; +import Comment from './src/comment'; Comment.install = function(app: App): void { - app.component(Comment.name, Comment) -} + app.component(Comment.name, Comment); +}; -export { Comment } +export { Comment }; export default { title: 'Comment 评论', category: '数据展示', status: '100%', install(app: App): void { - app.use(Comment as any) + app.use(Comment as any); } -} +}; diff --git a/packages/devui-vue/devui/comment/src/comment-types.ts b/packages/devui-vue/devui/comment/src/comment-types.ts index 4c9ad684d7..52bf7f5e90 100644 --- a/packages/devui-vue/devui/comment/src/comment-types.ts +++ b/packages/devui-vue/devui/comment/src/comment-types.ts @@ -1,6 +1,6 @@ -import type { PropType, ExtractPropTypes, VNode } from 'vue' +import type { PropType, ExtractPropTypes, VNode } from 'vue'; export interface IcommentProps { - [prop: string]: any + [prop: string]: any; } export const commentProps = { @@ -25,6 +25,6 @@ export const commentProps = { default:null }, -} as const +} as const; -export type CommentProps = ExtractPropTypes +export type CommentProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/comment/src/comment.tsx b/packages/devui-vue/devui/comment/src/comment.tsx index 438063c82d..ace7e71746 100644 --- a/packages/devui-vue/devui/comment/src/comment.tsx +++ b/packages/devui-vue/devui/comment/src/comment.tsx @@ -1,10 +1,10 @@ -import { defineComponent } from 'vue' -import { commentProps, CommentProps } from './comment-types' -import './comment.scss' -/* - * date:2021-12-18 +import { defineComponent } from 'vue'; +import { commentProps, CommentProps } from './comment-types'; +import './comment.scss'; +/* + * date:2021-12-18 * author:njl - * + * * actions 底部操作栏 * author 作者区域 * avatar 头像区域 @@ -12,7 +12,7 @@ import './comment.scss' * datetime 时间区域 * avatarDom 头像可只传入地址 * actionDom 操作区域根据传入的组件数量来生成相应的li标签 - * + * * 目前可成为参数的为 avatar,actions 其他均为具名插槽的形式,后期可继续根据需要改造 **/ export default defineComponent({ @@ -22,15 +22,15 @@ export default defineComponent({ slots: ['actions', 'author', 'avatar', 'content', 'datetime'], setup(props, { slots }) { return () => { - const getAction = (actions:any) => { - + const getAction = (actions: any) => { + if (!actions || !actions.length) { return null; } - const actionList = actions.map((action:any, index:number) =>
  • {action}
  • ); + const actionList = actions.map((action: any, index: number) =>
  • {action}
  • ); return actionList; }; - + const actions = props.actions ?? slots.actions?.(); const author = props.author ?? slots.author?.(); const avatar = props.avatar ?? slots.avatar?.(); @@ -62,7 +62,7 @@ export default defineComponent({ {actionDom} - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/countdown/__tests__/countdown.spec.ts b/packages/devui-vue/devui/countdown/__tests__/countdown.spec.ts index 4eeb18c5d9..7081d9851d 100644 --- a/packages/devui-vue/devui/countdown/__tests__/countdown.spec.ts +++ b/packages/devui-vue/devui/countdown/__tests__/countdown.spec.ts @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils'; import { Countdown } from '../index'; -import { nextTick } from 'vue' +import { nextTick } from 'vue'; describe('countdown test', () => { it('countdown default render', async () => { @@ -9,10 +9,10 @@ describe('countdown test', () => { props: { value: +new Date() } - }) + }); expect(wrapper.get('.countdown-content')); - - }) + + }); it('countdown text', () => { // todo @@ -23,15 +23,15 @@ describe('countdown test', () => { ['YY-MM-DD mm:ss', '00-00-11 520:40'], ].forEach(async ([format, value]) => { const wrapper = await mount(Countdown, { - props: { - format, - value: time, - } - }) - expect(wrapper.find('.countdown-value').text()).toEqual(value) - }) - - }) + props: { + format, + value: time, + } + }); + expect(wrapper.find('.countdown-value').text()).toEqual(value); + }); + + }); it('countdown millisecond', async () => { const time = Date.now() + 11 * 24 * 60 * 60 * 1000 + 8 * 60 * 60 * 1000 + 40 * 60 * 1000 + 40 * 1000 + 5; @@ -40,10 +40,10 @@ describe('countdown test', () => { format: 'HHH:mm:ss SSS', value: time, } - }) + }); await nextTick(); expect(Math.abs(time -Date.now() - wrapper.emitted('onChange')[0][0].leftTime) < 16).toEqual(true); - }) + }); it('countdown prefix and suffix', async () => { const time = Date.now() + 5000; @@ -56,10 +56,10 @@ describe('countdown test', () => { prefix, suffix } - }) + }); expect(wrapper.find('.countdown-prefix').text()).toEqual(prefix); expect(wrapper.find('.countdown-suffix').text()).toEqual(suffix); - }) + }); it('countdown valueStyle', async () => { const time = Date.now() + 5000; @@ -70,14 +70,14 @@ describe('countdown test', () => { value: time, valueStyle } - }) + }); const { style } = wrapper.find('.countdown-content').attributes(); let styleStr = ''; for (const k in valueStyle) { - styleStr += `${k}: ${valueStyle[k]}; ` + styleStr += `${k}: ${valueStyle[k]}; `; } expect(style).toEqual(styleStr.slice(0,-1)); - }) + }); it('countdown slot', async () => { const time = Date.now() + 5000; @@ -88,7 +88,7 @@ describe('countdown test', () => { slots: { default: 'test slot' } - }) + }); expect(wrapper.find('.devui-countdown').text()).toEqual('test slot'); - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/countdown/index.ts b/packages/devui-vue/devui/countdown/index.ts index b6b5d27206..6e39b43eaf 100644 --- a/packages/devui-vue/devui/countdown/index.ts +++ b/packages/devui-vue/devui/countdown/index.ts @@ -1,18 +1,17 @@ -import type { App } from 'vue' -import Countdown from './src/countdown' +import type { App } from 'vue'; +import Countdown from './src/countdown'; Countdown.install = function(app: App): void { - app.component(Countdown.name, Countdown) -} + app.component(Countdown.name, Countdown); +}; -export { Countdown } +export { Countdown }; export default { title: 'Countdown 倒计时', category: '数据展示', - status: '100%', + status: '100%', install(app: App): void { - app.use(Countdown as any) + app.use(Countdown as any); } -} - \ No newline at end of file +}; diff --git a/packages/devui-vue/devui/countdown/src/countdown-types.ts b/packages/devui-vue/devui/countdown/src/countdown-types.ts index 91a13a1ff0..0ca9c3c197 100644 --- a/packages/devui-vue/devui/countdown/src/countdown-types.ts +++ b/packages/devui-vue/devui/countdown/src/countdown-types.ts @@ -1,4 +1,4 @@ -import type { ExtractPropTypes } from 'vue' +import type { ExtractPropTypes } from 'vue'; export const countdownProps = { value: { @@ -20,18 +20,18 @@ export const countdownProps = { valueStyle: { type: Object, default: ()=>{ - return {} + return {}; } } -} as const +} as const; export interface DateFormat{ - Y?: string | number - M?: string | number - D?: string | number - H?: string | number - m?: string | number - s?: string | number - S?: string | number + Y?: string | number; + M?: string | number; + D?: string | number; + H?: string | number; + m?: string | number; + s?: string | number; + S?: string | number; } -export type CountdownProps = ExtractPropTypes +export type CountdownProps = ExtractPropTypes; diff --git a/packages/devui-vue/devui/countdown/src/countdown.tsx b/packages/devui-vue/devui/countdown/src/countdown.tsx index 1486b2b757..a5fe6044c1 100644 --- a/packages/devui-vue/devui/countdown/src/countdown.tsx +++ b/packages/devui-vue/devui/countdown/src/countdown.tsx @@ -1,32 +1,32 @@ -import { defineComponent, ref, onUnmounted ,onMounted } from 'vue' -import { countdownProps, CountdownProps } from './countdown-types' -import './countdown.scss' -import { getFormatTime, getLegalTime, getTimeSplit, getDeduplication, numFormat } from './utils' +import { defineComponent, ref, onUnmounted ,onMounted } from 'vue'; +import { countdownProps, CountdownProps } from './countdown-types'; +import './countdown.scss'; +import { getFormatTime, getLegalTime, getTimeSplit, getDeduplication, numFormat } from './utils'; export default defineComponent({ name: 'DCountdown', props: countdownProps, emits: ['onChange', 'onFinish'], setup(props: CountdownProps, ctx) { - const countdown = ref() + const countdown = ref(); const s = getDeduplication(props.format); const timeFormat = getTimeSplit(props.format); - const timeStr = ref('') + const timeStr = ref(''); const getTimeStr = (legalTime: Map) => { const fomatMap = new Set(['Y', 'M', 'D', 'H', 'm', 's', 'S']); const t = timeFormat.reduce((pre, cur) => { if (fomatMap.has(cur.k)) { - return pre + numFormat(legalTime.get(cur.k), cur.n) + return pre + numFormat(legalTime.get(cur.k), cur.n); } return pre + cur.k; - }, '') - timeStr.value = t; - } + }, ''); + timeStr.value = t; + }; const getTime = () => { const value = new Date(props.value).getTime(); - const leftTime = value > new Date().getTime() ? value - new Date().getTime() : 0 + const leftTime = value > new Date().getTime() ? value - new Date().getTime() : 0; const formatTime = getFormatTime(leftTime); const legalTime = getLegalTime(s, formatTime); !ctx.slots.default && getTimeStr(legalTime); @@ -36,27 +36,27 @@ export default defineComponent({ legalTime }); return leftTime; - } + }; const startTime = () => { getTime(); - if (countdown.value) return; + if (countdown.value) {return;} countdown.value = setInterval(() => { const t = getTime(); if (t === 0) { ctx.emit('onFinish'); - clearInterval(countdown.value) + clearInterval(countdown.value); } - }, s.has('S') ? 100 : 1000) - - } + }, s.has('S') ? 100 : 1000); + + }; onMounted(()=>{ - startTime() - }) + startTime(); + }); onUnmounted(() => { clearInterval(countdown.value); - }) + }); return () => { return (
    { @@ -75,7 +75,7 @@ export default defineComponent({ ) }
    - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/countdown/src/utils.ts b/packages/devui-vue/devui/countdown/src/utils.ts index e700f59873..1715b80196 100644 --- a/packages/devui-vue/devui/countdown/src/utils.ts +++ b/packages/devui-vue/devui/countdown/src/utils.ts @@ -16,15 +16,15 @@ export const getFormatTime = (leftTime: number): Map => { timeformat.set('s', second); timeformat.set('S', millsecond); return timeformat; -} +}; export const getLegalTime = (s: Set, timeformat: Map): Map => { - const dateValue = new Map([['Y', 0], ['M', 0], ['D', 0], ['H', 0], ['m', 0], ['s', 0], ['S', 0]]) - const m = new Map([['Y', 12], ['M', 30], ['D', 24], ['H', 60], ['m', 60], ['s', 1000], ['S', 1]]) + const dateValue = new Map([['Y', 0], ['M', 0], ['D', 0], ['H', 0], ['m', 0], ['s', 0], ['S', 0]]); + const m = new Map([['Y', 12], ['M', 30], ['D', 24], ['H', 60], ['m', 60], ['s', 1000], ['S', 1]]); let storage = 0; for (const k of dateValue.keys()) { if (s.has(k)) { - dateValue.set(k, timeformat.get(k) + storage) + dateValue.set(k, timeformat.get(k) + storage); storage = 0; } else { storage += timeformat.get(k) * m.get(k); @@ -33,13 +33,13 @@ export const getLegalTime = (s: Set, timeformat: Map): M if (!s.has('S') && timeformat.get('S') > 500) { dateValue.set('s', dateValue.get('s') + 1); } - return dateValue -} + return dateValue; +}; interface ITimeSplit { - k: string - n: number + k: string; + n: number; } export const getTimeSplit = (format: string): ITimeSplit[] => { const fomatMap = new Set(['Y', 'M', 'D', 'H', 'm', 's', 'S']); @@ -47,24 +47,24 @@ export const getTimeSplit = (format: string): ITimeSplit[] => { for (let i = 0; i < format.length; i++) { const k = format[i]; if (m.length === 0 || m[m.length - 1].k !== k || !fomatMap.has(k)) { - m.push({ k, n: 1 }) + m.push({ k, n: 1 }); } else { - m[m.length - 1].n++ + m[m.length - 1].n++; } } return m; -} +}; export const getDeduplication = (format: string): Set => { const fomatMap = new Set(['Y', 'M', 'D', 'H', 'm', 's', 'S']); const s: Set = new Set(); for (let i = 0; i < format.length; i++) { const k = format[i]; if (fomatMap.has(k)) { - s.add(k) + s.add(k); } } return s; -} +}; export const numFormat = (n: number, len: number): number | string => { const maxNum = 10 ** len - 1; @@ -72,10 +72,10 @@ export const numFormat = (n: number, len: number): number | string => { return n; } else { const carryLen = len - n.toString().length; - let str = '' + let str = ''; for (let i = 0; i < carryLen; i++) { - str += '0' + str += '0'; } return str + n; } -} \ No newline at end of file +}; diff --git a/packages/devui-vue/devui/date-picker/index.ts b/packages/devui-vue/devui/date-picker/index.ts index f38643d148..7fd3821b4e 100644 --- a/packages/devui-vue/devui/date-picker/index.ts +++ b/packages/devui-vue/devui/date-picker/index.ts @@ -1,19 +1,19 @@ -import { App } from 'vue' -import DatePicker from './src/date-picker' -import StickSlider from './src/stick-slider' +import { App } from 'vue'; +import DatePicker from './src/date-picker'; +import StickSlider from './src/stick-slider'; DatePicker.install = function(app: App) { - app.component(DatePicker.name, DatePicker) - app.component(StickSlider.name, StickSlider) -} + app.component(DatePicker.name, DatePicker); + app.component(StickSlider.name, StickSlider); +}; -export { DatePicker, StickSlider } +export { DatePicker, StickSlider }; export default { title: 'DatePicker 日期选择器', category: '数据录入', status: '50%', install(app: App): void { - app.use(DatePicker as any) + app.use(DatePicker as any); } -} +}; diff --git a/packages/devui-vue/devui/date-picker/src/components/calendar/index.tsx b/packages/devui-vue/devui/date-picker/src/components/calendar/index.tsx index 2834b42ab8..8f3334f4dc 100644 --- a/packages/devui-vue/devui/date-picker/src/components/calendar/index.tsx +++ b/packages/devui-vue/devui/date-picker/src/components/calendar/index.tsx @@ -1,19 +1,19 @@ -import { TProps } from '../types' -import CalendarDatePanel from '../panel' -import TimePicker from '../timepicker' +import { TProps } from '../types'; +import CalendarDatePanel from '../panel'; +import TimePicker from '../timepicker'; -import './index.scss' +import './index.scss'; const Calendar = (props: TProps) => { - const { showTime = false } = props - let { current } = props + const { showTime = false } = props; + let { current } = props; if (!(current instanceof Date)) { - current = new Date + current = new Date; } if (props.type === 'range') { - let { next } = props + let { next } = props; if (!(next instanceof Date)) { - next = new Date(current.getFullYear(), current.getMonth() + 1, 1) + next = new Date(current.getFullYear(), current.getMonth() + 1, 1); } return (
    @@ -22,15 +22,15 @@ const Calendar = (props: TProps) => { { showTime ? : null }
    - ) + ); } else { return (
    { showTime ? : null }
    - ) + ); } -} +}; -export default Calendar \ No newline at end of file +export default Calendar; diff --git a/packages/devui-vue/devui/date-picker/src/components/helper.ts b/packages/devui-vue/devui/date-picker/src/components/helper.ts index 805d977b50..85f94257a0 100644 --- a/packages/devui-vue/devui/date-picker/src/components/helper.ts +++ b/packages/devui-vue/devui/date-picker/src/components/helper.ts @@ -1,79 +1,79 @@ -import { invokeCallback, subDateDay, betweenDate } from './utils' -import { TDateCell, TDatePanelDataProps, TDatePanelProps } from './types' +import { invokeCallback, subDateDay, betweenDate } from './utils'; +import { TDateCell, TDatePanelDataProps, TDatePanelProps } from './types'; export const getDateKey = (date: Date): string => { - return date.toDateString() -} + return date.toDateString(); +}; export const cellClassName = (props: TDatePanelDataProps, day: TDateCell, base = 'cell'): string => { - - if(!betweenDate(day.date, props.dateMin, props.dateMax)) { - return `${base} disabled` - } else if(day.current !== 0) { - return `${base} not-current` - } - const key = getDateKey(day.date) - if (props.type === 'range') { - if (props.dateStart) { - if (getDateKey(props.dateStart) === key) { - return `${base} selected` - } - if (props.dateEnd && getDateKey(props.dateEnd) === key) { - return `${base} selected` - } - const innerEnd = props.dateEnd || props.dateHover - if (innerEnd) { - const range = innerEnd > props.dateStart ? [props.dateStart, innerEnd] : [innerEnd, props.dateStart] - if (day.date > range[0] && day.date < range[1]) { - return `${base} innerday` - } - } + if(!betweenDate(day.date, props.dateMin, props.dateMax)) { + return `${base} disabled`; + } else if(day.current !== 0) { + return `${base} not-current`; + } + + const key = getDateKey(day.date); + if (props.type === 'range') { + if (props.dateStart) { + if (getDateKey(props.dateStart) === key) { + return `${base} selected`; + } + if (props.dateEnd && getDateKey(props.dateEnd) === key) { + return `${base} selected`; + } + const innerEnd = props.dateEnd || props.dateHover; + if (innerEnd) { + const range = innerEnd > props.dateStart ? [props.dateStart, innerEnd] : [innerEnd, props.dateStart]; + if (day.date > range[0] && day.date < range[1]) { + return `${base} innerday`; } - return base - } else { - return props.dateStart && getDateKey(props.dateStart) === key ? `${base} selected` : base + } } -} + return base; + } else { + return props.dateStart && getDateKey(props.dateStart) === key ? `${base} selected` : base; + } +}; export const trigEvent = (props: TDatePanelProps, day: TDateCell): void => { - if(!betweenDate(day.date, props.dateMin, props.dateMax)) { - return - } + if(!betweenDate(day.date, props.dateMin, props.dateMax)) { + return; + } - if (props.type === 'range') { - if (!props.dateStart) { - invokeCallback(props.onSelectStart, day.date) - } else if (!props.dateEnd) { - if(subDateDay(props.dateStart, day.date) !== 0) { - invokeCallback(props.onSelectEnd, day.date) - typeof props.onChange === 'function' && props.onChange(props.type, props) - } - } else { - invokeCallback(props.onReset, day.date) - } + if (props.type === 'range') { + if (!props.dateStart) { + invokeCallback(props.onSelectStart, day.date); + } else if (!props.dateEnd) { + if(subDateDay(props.dateStart, day.date) !== 0) { + invokeCallback(props.onSelectEnd, day.date); + typeof props.onChange === 'function' && props.onChange(props.type, props); + } } else { - invokeCallback(props.onSelected, day.date) - typeof props.onChange === 'function' && props.onChange(props.type, props) + invokeCallback(props.onReset, day.date); } -} + } else { + invokeCallback(props.onSelected, day.date); + typeof props.onChange === 'function' && props.onChange(props.type, props); + } +}; export const handleDateEnter = (props: TDatePanelProps, day: TDateCell): void => { - if(day.current !== 0) { - return - } - const { dateMin, dateMax } = props - if(dateMin && subDateDay(day.date, dateMin) < 0) { - return - } - if(dateMax && subDateDay(dateMax, day.date) < 0) { - return - } - if (props.type === 'range') { - const key = getDateKey(day.date) - if (!props.dateStart || getDateKey(props.dateStart) === key || props.dateEnd) { - return - } - invokeCallback(props.onSelecting, day.date) + if(day.current !== 0) { + return; + } + const { dateMin, dateMax } = props; + if(dateMin && subDateDay(day.date, dateMin) < 0) { + return; + } + if(dateMax && subDateDay(dateMax, day.date) < 0) { + return; + } + if (props.type === 'range') { + const key = getDateKey(day.date); + if (!props.dateStart || getDateKey(props.dateStart) === key || props.dateEnd) { + return; } -} \ No newline at end of file + invokeCallback(props.onSelecting, day.date); + } +}; diff --git a/packages/devui-vue/devui/date-picker/src/components/panel/index.tsx b/packages/devui-vue/devui/date-picker/src/components/panel/index.tsx index 71526888a6..a7de390b3c 100644 --- a/packages/devui-vue/devui/date-picker/src/components/panel/index.tsx +++ b/packages/devui-vue/devui/date-picker/src/components/panel/index.tsx @@ -1,53 +1,53 @@ -import { TDatePanelProps } from '../types' -import { getMonthWeeklyDays, WEEK_DAYS, betweenDate } from '../utils' -import { handleDateEnter, cellClassName, trigEvent } from '../helper' -import Toolbar from '../toolbar' -import TodayDefault from '../today-default' -import './index.scss' +import { TDatePanelProps } from '../types'; +import { getMonthWeeklyDays, WEEK_DAYS, betweenDate } from '../utils'; +import { handleDateEnter, cellClassName, trigEvent } from '../helper'; +import Toolbar from '../toolbar'; +import TodayDefault from '../today-default'; +import './index.scss'; const CalendarDatePanel = (props: TDatePanelProps) => { - const today = new Date() - return ( -
    - -
      { - WEEK_DAYS.map(day =>
    1. {day}
    2. ) - }
    -
      { - getMonthWeeklyDays(props.current).map(row =>
    • { - row.map(day => { - return ( - trigEvent(props, day)} - onMouseenter={() => handleDateEnter(props, day)} - >{day.date.getDate()} - ) - }) - }
    • ) - }
    - {props.type !== 'range' ? ( - { - typeof props.onToday === 'function' && props.onToday(today, 0) - }} - /> - ) : null} -
    - ) -} + const today = new Date(); + return ( +
    + +
      { + WEEK_DAYS.map(day =>
    1. {day}
    2. ) + }
    +
      { + getMonthWeeklyDays(props.current).map(row =>
    • { + row.map(day => { + return ( + trigEvent(props, day)} + onMouseenter={() => handleDateEnter(props, day)} + >{day.date.getDate()} + ); + }) + }
    • ) + }
    + {props.type !== 'range' ? ( + { + typeof props.onToday === 'function' && props.onToday(today, 0); + }} + /> + ) : null} +
    + ); +}; -export default CalendarDatePanel \ No newline at end of file +export default CalendarDatePanel; diff --git a/packages/devui-vue/devui/date-picker/src/components/popup/index.tsx b/packages/devui-vue/devui/date-picker/src/components/popup/index.tsx index 162863434d..c614fabaff 100644 --- a/packages/devui-vue/devui/date-picker/src/components/popup/index.tsx +++ b/packages/devui-vue/devui/date-picker/src/components/popup/index.tsx @@ -1,107 +1,107 @@ -import { defineComponent, reactive, renderSlot, ref, useSlots, onMounted, onUnmounted, onBeforeUpdate } from 'vue' -import { EventManager, isIn, traceNode, invokeFunction } from '../../utils' +import { defineComponent, reactive, renderSlot, ref, useSlots, onMounted, onUnmounted, onBeforeUpdate } from 'vue'; +import { EventManager, isIn, traceNode, invokeFunction } from '../../utils'; import { - handlePositionFactory, - getAttachInputDom, -} from '../../helper' + handlePositionFactory, + getAttachInputDom, +} from '../../helper'; -import './index.scss' +import './index.scss'; type TState = { - x?: string - y?: string - attachInputDom?: string - show: boolean - st: boolean -} + x?: string; + y?: string; + attachInputDom?: string; + show: boolean; + st: boolean; +}; export default defineComponent({ - name: 'DDatePickerPopup', - props: { - attach: { type: String }, - onBinding: { type: Function }, - onClosed: { type: Function }, - onOpen: { type: Function }, - show: { type: Boolean }, - }, - setup(props) { + name: 'DDatePickerPopup', + props: { + attach: { type: String }, + onBinding: { type: Function }, + onClosed: { type: Function }, + onOpen: { type: Function }, + show: { type: Boolean }, + }, + setup(props) { - const container = ref() - const evtman = new EventManager() - const state = reactive({ - x: '0', - y: '0', - st: true, - show: !!props.show, - }) + const container = ref(); + const evtman = new EventManager(); + const state = reactive({ + x: '0', + y: '0', + st: true, + show: !!props.show, + }); - let el: Element | null = null + let el: Element | null = null; - // 弹出层跟踪 - const handlePosition = handlePositionFactory(state, props, container) + // 弹出层跟踪 + const handlePosition = handlePositionFactory(state, props, container); - onBeforeUpdate(() => { - state.show = !!props.show - }) + onBeforeUpdate(() => { + state.show = !!props.show; + }); - onMounted(() => { - // 获取绑定节点(默认input) - el = getAttachInputDom(props) - // 绑定节点不存在,作为普通组件展示。 - if (!el) { - state.st = true - state.show = true - return - } else { - state.show = false - state.st = false - } + onMounted(() => { + // 获取绑定节点(默认input) + el = getAttachInputDom(props); + // 绑定节点不存在,作为普通组件展示。 + if (!el) { + state.st = true; + state.show = true; + return; + } else { + state.show = false; + state.st = false; + } - invokeFunction(props.onBinding) + invokeFunction(props.onBinding); - // 绑定节点click事件处理弹出层显示 - evtman.append(el, 'click', () => { - if(!state.show) { - state.show = true - invokeFunction(props.onOpen) - } - }) - // document层处理`点击其他区域隐藏` - evtman.append(document, 'click', (e: MouseEvent) => { - if (!state.show || e.target === el || isIn(e.target as Node, container.value)) { - return - } - state.show = false - invokeFunction(props.onClosed) - // reset() - }) - // 对绑定节点做scroll跟踪,并绑定跟踪事件 - traceNode(el).forEach(node => { - evtman.append(node, 'scroll', handlePosition) - }) - }) + // 绑定节点click事件处理弹出层显示 + evtman.append(el, 'click', () => { + if(!state.show) { + state.show = true; + invokeFunction(props.onOpen); + } + }); + // document层处理`点击其他区域隐藏` + evtman.append(document, 'click', (e: MouseEvent) => { + if (!state.show || e.target === el || isIn(e.target as Node, container.value)) { + return; + } + state.show = false; + invokeFunction(props.onClosed); + // reset() + }); + // 对绑定节点做scroll跟踪,并绑定跟踪事件 + traceNode(el).forEach(node => { + evtman.append(node, 'scroll', handlePosition); + }); + }); - onUnmounted(() => { - evtman.dispose() - }) + onUnmounted(() => { + evtman.dispose(); + }); - return () => { - const defaultSlot = renderSlot(useSlots(), 'default') - if (state.st) { - return defaultSlot - } - handlePosition() - return ( -
    - -
    - ) - } - } -}) \ No newline at end of file + return () => { + const defaultSlot = renderSlot(useSlots(), 'default'); + if (state.st) { + return defaultSlot; + } + handlePosition(); + return ( +
    + +
    + ); + }; + } +}); diff --git a/packages/devui-vue/devui/date-picker/src/components/timepicker/index.tsx b/packages/devui-vue/devui/date-picker/src/components/timepicker/index.tsx index ab6740cdf4..30ddf2e062 100644 --- a/packages/devui-vue/devui/date-picker/src/components/timepicker/index.tsx +++ b/packages/devui-vue/devui/date-picker/src/components/timepicker/index.tsx @@ -1,7 +1,7 @@ -import { defineComponent, reactive } from 'vue' -import VerticalSliderFunction from '../vertical-slider' +import { defineComponent, reactive } from 'vue'; +import VerticalSliderFunction from '../vertical-slider'; -import './index.scss' +import './index.scss'; const TimePicker = defineComponent({ props: { @@ -9,15 +9,15 @@ const TimePicker = defineComponent({ }, setup(props) { - const { time = new Date() } = props || {} + const { time = new Date() } = props || {}; const state = reactive({ hour: time.getHours(), minute: time.getMinutes(), second: time.getSeconds() - }) + }); - const hours = Array(24).fill(0).map((_, i) => `${i}`.padStart(2, '0')) - const minutes = Array(60).fill(0).map((_, i) => `${i}`.padStart(2, '0')) + const hours = Array(24).fill(0).map((_, i) => `${i}`.padStart(2, '0')); + const minutes = Array(60).fill(0).map((_, i) => `${i}`.padStart(2, '0')); return () => { return ( @@ -51,9 +51,9 @@ const TimePicker = defineComponent({ /> - ) - } + ); + }; } -}) +}); -export default TimePicker \ No newline at end of file +export default TimePicker; diff --git a/packages/devui-vue/devui/date-picker/src/components/today-default/index.tsx b/packages/devui-vue/devui/date-picker/src/components/today-default/index.tsx index 9ed09cbf7b..fd8dcda077 100644 --- a/packages/devui-vue/devui/date-picker/src/components/today-default/index.tsx +++ b/packages/devui-vue/devui/date-picker/src/components/today-default/index.tsx @@ -1,19 +1,19 @@ type TProps = { - onSelected?: (date: Date) => void - disabled?: boolean -} + onSelected?: (date: Date) => void; + disabled?: boolean; +}; const TodayDefault = (props: TProps) => { - const { onSelected = () => 0, disabled = false } = props - return ( -
    - -
    - ) -} + const { onSelected = () => 0, disabled = false } = props; + return ( +
    + +
    + ); +}; -export default TodayDefault \ No newline at end of file +export default TodayDefault; diff --git a/packages/devui-vue/devui/date-picker/src/components/toolbar/index.tsx b/packages/devui-vue/devui/date-picker/src/components/toolbar/index.tsx index 61b6d809e6..56fd83bc57 100644 --- a/packages/devui-vue/devui/date-picker/src/components/toolbar/index.tsx +++ b/packages/devui-vue/devui/date-picker/src/components/toolbar/index.tsx @@ -1,75 +1,75 @@ -import { compareDate, invokeCallback } from '../utils' -import { Year, Month } from './svg-icon' -import { TCalendarToolbarItemProps, TDateToolbarProps } from '../types' -import './index.scss' +import { compareDate, invokeCallback } from '../utils'; +import { Year, Month } from './svg-icon'; +import { TCalendarToolbarItemProps, TDateToolbarProps } from '../types'; +import './index.scss'; const Item = (props: TCalendarToolbarItemProps) => { - const { - button: Btn, - disabled = false, - rotate = 0, - date, - pos, - } = props - const color = disabled ? '#cfd0d3' : '#585d6b' - const className = `${disabled ? 'disabled' : ''}` - const handleClick = disabled ? undefined : () => invokeCallback(props.cb, date, pos) - return ( - - - - ) -} + const { + button: Btn, + disabled = false, + rotate = 0, + date, + pos, + } = props; + const color = disabled ? '#cfd0d3' : '#585d6b'; + const className = `${disabled ? 'disabled' : ''}`; + const handleClick = disabled ? undefined : () => invokeCallback(props.cb, date, pos); + return ( + + + + ); +}; -export const Title = (props: { date: Date; }) => { - const { date } = props - return ( - { - `${date.getFullYear()}年${(date.getMonth() + 1 + '').padStart(2, '0')}月` - } - ) -} +export const Title = (props: { date: Date }) => { + const { date } = props; + return ( + { + `${date.getFullYear()}年${(date.getMonth() + 1 + '').padStart(2, '0')}月` + } + ); +}; const CalendarToolbar = (props: TDateToolbarProps) => { - const { - type, current, compare, pos, - dateMax, dateMin, - onPreviousYear, - onPreviousMonth, - onNextMonth, - onNextYear, - } = props + const { + type, current, compare, pos, + dateMax, dateMin, + onPreviousYear, + onPreviousMonth, + onNextMonth, + onNextYear, + } = props; - const dis = [false, false, false, false] + const dis = [false, false, false, false]; - if (type === 'range') { - if (pos === 1) { - dis[0] = !compareDate(compare, current, 'year', 1) - dis[1] = !compareDate(compare, current, 'month', 1) - dis[2] = !compareDate(current, dateMax, 'month', 0) - dis[3] = !compareDate(current, dateMax, 'year', 0) - } else { - dis[0] = !compareDate(dateMin, current, 'year', 0) - dis[1] = !compareDate(dateMin, current, 'month', 0) - dis[2] = !compareDate(current, compare, 'month', 1) - dis[3] = !compareDate(current, compare, 'year', 1) - } + if (type === 'range') { + if (pos === 1) { + dis[0] = !compareDate(compare, current, 'year', 1); + dis[1] = !compareDate(compare, current, 'month', 1); + dis[2] = !compareDate(current, dateMax, 'month', 0); + dis[3] = !compareDate(current, dateMax, 'year', 0); } else { - dis[0] = !compareDate(dateMin, current, 'year', 0) - dis[1] = !compareDate(dateMin, current, 'month', 0) - dis[2] = !compareDate(current, dateMax, 'month', 0) - dis[3] = !compareDate(current, dateMax, 'year', 0) + dis[0] = !compareDate(dateMin, current, 'year', 0); + dis[1] = !compareDate(dateMin, current, 'month', 0); + dis[2] = !compareDate(current, compare, 'month', 1); + dis[3] = !compareDate(current, compare, 'year', 1); } + } else { + dis[0] = !compareDate(dateMin, current, 'year', 0); + dis[1] = !compareDate(dateMin, current, 'month', 0); + dis[2] = !compareDate(current, dateMax, 'month', 0); + dis[3] = !compareDate(current, dateMax, 'year', 0); + } - return ( -
    - - - - <Item disabled={dis[2]} date={current} pos={pos} button={Month} rotate={90} cb={onNextMonth} /> - <Item disabled={dis[3]} date={current} pos={pos} button={Year} rotate={180} cb={onNextYear} /> - </div> - ) -} + return ( + <div class="devui-calendar-toolbar"> + <Item disabled={dis[0]} date={current} pos={pos} button={Year} cb={onPreviousYear} /> + <Item disabled={dis[1]} date={current} pos={pos} button={Month} rotate={-90} cb={onPreviousMonth} /> + <Title date={current} /> + <Item disabled={dis[2]} date={current} pos={pos} button={Month} rotate={90} cb={onNextMonth} /> + <Item disabled={dis[3]} date={current} pos={pos} button={Year} rotate={180} cb={onNextYear} /> + </div> + ); +}; -export default CalendarToolbar \ No newline at end of file +export default CalendarToolbar; diff --git a/packages/devui-vue/devui/date-picker/src/components/toolbar/svg-icon.tsx b/packages/devui-vue/devui/date-picker/src/components/toolbar/svg-icon.tsx index 01d9a31a3e..6e0298a7fa 100644 --- a/packages/devui-vue/devui/date-picker/src/components/toolbar/svg-icon.tsx +++ b/packages/devui-vue/devui/date-picker/src/components/toolbar/svg-icon.tsx @@ -1,23 +1,23 @@ -import { TIconSvgProps } from '../types' +import { TIconSvgProps } from '../types'; export const Year = (props: TIconSvgProps) => { - const { color = '#585d6b', rotate = 0 } = props - return ( - <svg style={{ transform: `rotate(${rotate}deg)` }} width="10px" height="10px" viewBox="0 0 10 10" version="1.1" xmlns="http://www.w3.org/2000/svg"> - <g fill={color} transform="translate(-1.000000, -1.000000)"> - <path d="M11,1.83333333 L11,10.1666667 L7,7.38833333 L7,10.1666667 L1,6 L7,1.83333333 L7,4.61033333 L11,1.83333333 Z" /> - </g> - </svg> - ) -} + const { color = '#585d6b', rotate = 0 } = props; + return ( + <svg style={{ transform: `rotate(${rotate}deg)` }} width="10px" height="10px" viewBox="0 0 10 10" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <g fill={color} transform="translate(-1.000000, -1.000000)"> + <path d="M11,1.83333333 L11,10.1666667 L7,7.38833333 L7,10.1666667 L1,6 L7,1.83333333 L7,4.61033333 L11,1.83333333 Z" /> + </g> + </svg> + ); +}; export const Month = (props: TIconSvgProps) => { - const { color = '#585d6b', rotate = 0 } = props - return ( - <svg style={{ transform: `rotate(${rotate}deg)` }} width="6px" height="10px" viewBox="0 0 6 10" version="1.1" xmlns="http://www.w3.org/2000/svg"> - <g fill={color} transform="translate(-3.000000, -1.000000)"> - <polygon points="6 3 10.1666667 9 1.83333333 9" /> - </g> - </svg> - ) -} \ No newline at end of file + const { color = '#585d6b', rotate = 0 } = props; + return ( + <svg style={{ transform: `rotate(${rotate}deg)` }} width="6px" height="10px" viewBox="0 0 6 10" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <g fill={color} transform="translate(-3.000000, -1.000000)"> + <polygon points="6 3 10.1666667 9 1.83333333 9" /> + </g> + </svg> + ); +}; diff --git a/packages/devui-vue/devui/date-picker/src/components/types.ts b/packages/devui-vue/devui/date-picker/src/components/types.ts index d11595ee19..12f83b2d27 100644 --- a/packages/devui-vue/devui/date-picker/src/components/types.ts +++ b/packages/devui-vue/devui/date-picker/src/components/types.ts @@ -1,70 +1,70 @@ -export type TDateCell = { date: Date; current: -1 | 0 | 1; } -export type TDatePanelMode = 'month' | 'year' -export type TDatePanelType = 'select' | 'range' -export type TEventCallback = (date: Date, position?: number) => void +export type TDateCell = { date: Date; current: -1 | 0 | 1 }; +export type TDatePanelMode = 'month' | 'year'; +export type TDatePanelType = 'select' | 'range'; +export type TEventCallback = (date: Date, position?: number) => void; export type TDateConfig = { - type?: TDatePanelType - mode?: TDatePanelMode - current: Date - showTime: boolean - dateMin?: Date - dateMax?: Date -} + type?: TDatePanelType; + mode?: TDatePanelMode; + current: Date; + showTime: boolean; + dateMin?: Date; + dateMax?: Date; +}; export type TDateSelectingBase = { - dateStart?: Date - dateEnd?: Date - dateHover?: Date -} + dateStart?: Date; + dateEnd?: Date; + dateHover?: Date; +}; export type TDateToolbarEventProps = { - onPreviousYear?: TEventCallback - onPreviousMonth?: TEventCallback - onNextMonth?: TEventCallback - onNextYear?: TEventCallback -} + onPreviousYear?: TEventCallback; + onPreviousMonth?: TEventCallback; + onNextMonth?: TEventCallback; + onNextYear?: TEventCallback; +}; export type TDateToolbarDataProps = TDateConfig & { - pos?: number - compare?: Date -} + pos?: number; + compare?: Date; +}; -export type TDateToolbarProps = TDateToolbarDataProps & TDateToolbarEventProps +export type TDateToolbarProps = TDateToolbarDataProps & TDateToolbarEventProps; export type TDatePanelEventProps = TDateToolbarEventProps & { - onSelected?: TEventCallback - onReset?: TEventCallback - onSelectStart?: TEventCallback - onSelectEnd?: TEventCallback - onSelecting?: TEventCallback - onToday?: TEventCallback - onChange?: (type: TDatePanelType, config: TDateSelectingBase) => void -} + onSelected?: TEventCallback; + onReset?: TEventCallback; + onSelectStart?: TEventCallback; + onSelectEnd?: TEventCallback; + onSelecting?: TEventCallback; + onToday?: TEventCallback; + onChange?: (type: TDatePanelType, config: TDateSelectingBase) => void; +}; -export type TDatePanelDataProps = TDateToolbarDataProps & TDateSelectingBase +export type TDatePanelDataProps = TDateToolbarDataProps & TDateSelectingBase; -export type TDatePanelProps = { showToday?: boolean; } & TDatePanelDataProps & TDatePanelEventProps +export type TDatePanelProps = { showToday?: boolean } & TDatePanelDataProps & TDatePanelEventProps; export type TProps = ({ - type: 'select' + type: 'select'; } | { - type: 'range' - next: Date -}) & TDateConfig & TDateSelectingBase & TDatePanelEventProps + type: 'range'; + next: Date; +}) & TDateConfig & TDateSelectingBase & TDatePanelEventProps; export type TIconSvgProps = { - color?: string - rotate?: number -} -export type TIconSvg = (props: TIconSvgProps) => any + color?: string; + rotate?: number; +}; +export type TIconSvg = (props: TIconSvgProps) => any; export type TCalendarToolbarItemProps = { - disabled?: boolean - rotate?: number - cb?: (...args: any[]) => void - pos: number - date: Date - button: TIconSvg -} \ No newline at end of file + disabled?: boolean; + rotate?: number; + cb?: (...args: any[]) => void; + pos: number; + date: Date; + button: TIconSvg; +}; diff --git a/packages/devui-vue/devui/date-picker/src/components/utils.ts b/packages/devui-vue/devui/date-picker/src/components/utils.ts index 23150961ab..cbad58b61f 100644 --- a/packages/devui-vue/devui/date-picker/src/components/utils.ts +++ b/packages/devui-vue/devui/date-picker/src/components/utils.ts @@ -1,99 +1,99 @@ -import { TDateCell } from './types' +import { TDateCell } from './types'; const getHumanDate = (d: Date) => { - const year = d.getFullYear() - const month = d.getMonth() + 1 - const date = d.getDate() - const day = d.getDay() - const hour = d.getHours() - const minute = d.getMinutes() - const second = d.getSeconds() - const ms = d.getMilliseconds() - - return { - year, y: year, month, M: month, date, d: date, day, - hour, H: hour, h: hour, - minute, m: minute, - second, s: second, - ms, - } -} + const year = d.getFullYear(); + const month = d.getMonth() + 1; + const date = d.getDate(); + const day = d.getDay(); + const hour = d.getHours(); + const minute = d.getMinutes(); + const second = d.getSeconds(); + const ms = d.getMilliseconds(); + + return { + year, y: year, month, M: month, date, d: date, day, + hour, H: hour, h: hour, + minute, m: minute, + second, s: second, + ms, + }; +}; const getMonthDays = (year: number, month: number) => { - const first = new Date(year, month - 1, 1) - const last = new Date(year, month, 0) - const dates: TDateCell[] = [] - - let day = first.getDay() - while (day > 0) { - day -= 1 - dates.push({ date: new Date(year, month - 1, -day), current: -1 }) - } - - day = last.getDate() - first.getDate() - for (let i = 0; i <= day; i++) { - const date = new Date(first) - date.setDate(i + 1) - dates.push({ date, current: 0 }) - } - - day = last.getDay() - let tail: Date = last - for (let i = day; i < 6; i++) { - tail = new Date(year, month, i - day + 1) - dates.push({ date: tail, current: 1 }) - } - if(dates.length < 42) { - day = tail.getDate() - for (let i = 1; i <= 7; i++) { - tail = new Date(year, month, day + i) - dates.push({ date: tail, current: 1 }) - } - } - return dates -} + const first = new Date(year, month - 1, 1); + const last = new Date(year, month, 0); + const dates: TDateCell[] = []; + + let day = first.getDay(); + while (day > 0) { + day -= 1; + dates.push({ date: new Date(year, month - 1, -day), current: -1 }); + } + + day = last.getDate() - first.getDate(); + for (let i = 0; i <= day; i++) { + const date = new Date(first); + date.setDate(i + 1); + dates.push({ date, current: 0 }); + } + + day = last.getDay(); + let tail: Date = last; + for (let i = day; i < 6; i++) { + tail = new Date(year, month, i - day + 1); + dates.push({ date: tail, current: 1 }); + } + if(dates.length < 42) { + day = tail.getDate(); + for (let i = 1; i <= 7; i++) { + tail = new Date(year, month, day + i); + dates.push({ date: tail, current: 1 }); + } + } + return dates; +}; export const getMonthWeeklyDays = (date: any = new Date()) => { - if (!(date instanceof Date)) { - date = new Date() - } - const { year, month } = getHumanDate(date) - const days = getMonthDays(year, month) - const dayRows: TDateCell[][] = [] - while (days.length > 0) { - dayRows.push(days.splice(0, 7)) - } - return dayRows -} - -export const WEEK_DAYS = ['日', '一', '二', '三', '四', '五', '六'] + if (!(date instanceof Date)) { + date = new Date(); + } + const { year, month } = getHumanDate(date); + const days = getMonthDays(year, month); + const dayRows: TDateCell[][] = []; + while (days.length > 0) { + dayRows.push(days.splice(0, 7)); + } + return dayRows; +}; + +export const WEEK_DAYS = ['日', '一', '二', '三', '四', '五', '六']; export const invokeCallback = (cb: any, ...args: any[]) => { - typeof cb === 'function' && cb(...args) -} + typeof cb === 'function' && cb(...args); +}; /** * a - b 的月数 */ export const subDateMonth = (a: Date, b: Date) => { - const am = a.getFullYear() * 12 + a.getMonth() - const bm = b.getFullYear() * 12 + b.getMonth() - return am - bm -} + const am = a.getFullYear() * 12 + a.getMonth(); + const bm = b.getFullYear() * 12 + b.getMonth(); + return am - bm; +}; -const ONE_DAY = 1000 * 60 * 60 * 24 +const ONE_DAY = 1000 * 60 * 60 * 24; /** * a - b 的天数 - * @param a - * @param b - * @returns + * @param a + * @param b + * @returns */ export const subDateDay = (a: Date, b: Date) => { - const ad = new Date(a.getFullYear(), a.getMonth(), a.getDate()).getTime() - const bd = new Date(b.getFullYear(), b.getMonth(), b.getDate()).getTime() - return (ad - bd) / ONE_DAY -} + const ad = new Date(a.getFullYear(), a.getMonth(), a.getDate()).getTime(); + const bd = new Date(b.getFullYear(), b.getMonth(), b.getDate()).getTime(); + return (ad - bd) / ONE_DAY; +}; /** * 比较日期单位 @@ -101,72 +101,72 @@ export const subDateDay = (a: Date, b: Date) => { * @param big 相对晚的日期 * @param mode 比较单位 * @param min 不能小于这个值 -* @returns +* @returns */ export const compareDate = (small: Date | undefined, big: Date | undefined, mode: 'year' | 'month', min: number) => { - if (!small || !big) { - return true - } - if (mode === 'year') { - return big.getFullYear() - small.getFullYear() > min - } else { - return subDateMonth(big, small) > min - } -} - -export const parseDate = (str?: string) : Date | null => { - if(!str || typeof str !== 'string') { - return null - } - - const [dateStr = '', timeStr = ''] = str.split(/([ ]|T)+/) - if(!dateStr) { - return null - } - const [y, m, d] = dateStr.split(/[^\d]+/) - const year = _parseInt(y), month = _parseInt(m), date = _parseInt(d) || 1 - if(!year || !month) { - return null - } - const time = parseTime(timeStr) - return new Date(year, month - 1, date, ...time) -} + if (!small || !big) { + return true; + } + if (mode === 'year') { + return big.getFullYear() - small.getFullYear() > min; + } else { + return subDateMonth(big, small) > min; + } +}; + +export const parseDate = (str?: string): Date | null => { + if(!str || typeof str !== 'string') { + return null; + } + + const [dateStr = '', timeStr = ''] = str.split(/([ ]|T)+/); + if(!dateStr) { + return null; + } + const [y, m, d] = dateStr.split(/[^\d]+/); + const year = _parseInt(y), month = _parseInt(m), date = _parseInt(d) || 1; + if(!year || !month) { + return null; + } + const time = parseTime(timeStr); + return new Date(year, month - 1, date, ...time); +}; const _parseInt = (str: any, dftVal?: number) => { - if(!str || typeof str !== 'string') { - return dftVal - } - const n = parseInt(str) - if(isNaN(n)) { - return dftVal - } - return n -} - -export const parseTime = (str?: string) : [number, number, number, number] => { - const [h, m, s, ms] = str.split(/[\:\.]+/) - return [_parseInt(h, 0), _parseInt(m, 0), _parseInt(s, 0), _parseInt(ms, 0)] -} - -type TDateCounterType = 'd' | 'm' | 'y' + if(!str || typeof str !== 'string') { + return dftVal; + } + const n = parseInt(str); + if(isNaN(n)) { + return dftVal; + } + return n; +}; + +export const parseTime = (str?: string): [number, number, number, number] => { + const [h, m, s, ms] = str.split(/[\:\.]+/); + return [_parseInt(h, 0), _parseInt(m, 0), _parseInt(s, 0), _parseInt(ms, 0)]; +}; + +type TDateCounterType = 'd' | 'm' | 'y'; export const compareDateSort = (d1: Date, d2: Date, type: TDateCounterType = 'd') => { - const t1 = dateCounter(d1, type), t2 = dateCounter(d2, type) - return t1 < t2 ? -1 : t1 > t2 ? 1 : 0 -} + const t1 = dateCounter(d1, type), t2 = dateCounter(d2, type); + return t1 < t2 ? -1 : t1 > t2 ? 1 : 0; +}; export const dateCounter = (date: Date, type: TDateCounterType) => { - switch(type) { - case 'y': return date.getFullYear() - case 'm': return date.getFullYear() * 12 + date.getMonth() - } - return date.getTime() / ONE_DAY >> 0 -} + switch(type) { + case 'y': return date.getFullYear(); + case 'm': return date.getFullYear() * 12 + date.getMonth(); + } + return date.getTime() / ONE_DAY >> 0; +}; export const borderDateFactory = (factor: (d1: Date, d2: Date) => Date) => (...ds: Date[]) => { - return ds.length < 2 ? ds[0] || new Date() : ds.reduce((r, v) => factor(r, v)) -} -export const getMinDate = borderDateFactory((d1: Date, d2: Date) => compareDateSort(d1, d2) < 0 ? d1 : d2) -export const getMaxDate = borderDateFactory((d1: Date, d2: Date) => compareDateSort(d1, d2) < 0 ? d2 : d1) + return ds.length < 2 ? ds[0] || new Date() : ds.reduce((r, v) => factor(r, v)); +}; +export const getMinDate = borderDateFactory((d1: Date, d2: Date) => compareDateSort(d1, d2) < 0 ? d1 : d2); +export const getMaxDate = borderDateFactory((d1: Date, d2: Date) => compareDateSort(d1, d2) < 0 ? d2 : d1); /** * d 是否在 [left, right] 区间 @@ -176,11 +176,11 @@ export const getMaxDate = borderDateFactory((d1: Date, d2: Date) => compareDateS * @returns boolean */ export const betweenDate = (date: Date, left: any, right: any): boolean => { - if(left instanceof Date && compareDateSort(left, date, 'd') > 0) { - return false - } - if(right instanceof Date && compareDateSort(date, right, 'd') > 0) { - return false - } - return true -} \ No newline at end of file + if(left instanceof Date && compareDateSort(left, date, 'd') > 0) { + return false; + } + if(right instanceof Date && compareDateSort(date, right, 'd') > 0) { + return false; + } + return true; +}; diff --git a/packages/devui-vue/devui/date-picker/src/components/vertical-slider/index.tsx b/packages/devui-vue/devui/date-picker/src/components/vertical-slider/index.tsx index 07f0265daa..de8282cb91 100644 --- a/packages/devui-vue/devui/date-picker/src/components/vertical-slider/index.tsx +++ b/packages/devui-vue/devui/date-picker/src/components/vertical-slider/index.tsx @@ -1,6 +1,6 @@ -import { defineComponent, reactive, onMounted, ref } from 'vue' +import { defineComponent, reactive, onMounted, ref } from 'vue'; -import './index.scss' +import './index.scss'; const VerticalSlider = defineComponent({ props: { @@ -22,72 +22,72 @@ const VerticalSlider = defineComponent({ itemClassNormal = '', itemClassSelected = 'selected', onChange, - } = props || {} + } = props || {}; - let max_y = 0, min_y = 0 - const container = ref<Element>() - const movbar = ref<Element>() + let max_y = 0, min_y = 0; + const container = ref<Element>(); + const movbar = ref<Element>(); - let pos_start: [number, number] | null = null - let pos_cache: [number, number] | null = null + let pos_start: [number, number] | null = null; + let pos_cache: [number, number] | null = null; const state = reactive<{ - selectedIndex: number - barOpacity: number - x: number - y: number - transition: string + selectedIndex: number; + barOpacity: number; + x: number; + y: number; + transition: string; }>({ selectedIndex, barOpacity: 0, x: 0, y: 0, transition: 'none', - }) + }); const handleMouseDown = (e: MouseEvent) => { - e.stopPropagation() - e.preventDefault() - pos_start = [e.clientX, e.clientY] - state.transition = 'none' - } + e.stopPropagation(); + e.preventDefault(); + pos_start = [e.clientX, e.clientY]; + state.transition = 'none'; + }; const handleMouseMove = (e: MouseEvent) => { - e.stopPropagation() - e.preventDefault() + e.stopPropagation(); + e.preventDefault(); if(!pos_start || !pos_cache) { - return + return; } - state.x = pos_cache[0] + e.clientX - pos_start[0] - state.y = Math.min(max_y, Math.max(min_y, pos_cache[1] + e.clientY - pos_start[1])) - state.selectedIndex = (max_y - state.y + size / 2) / size >> 0 - } + state.x = pos_cache[0] + e.clientX - pos_start[0]; + state.y = Math.min(max_y, Math.max(min_y, pos_cache[1] + e.clientY - pos_start[1])); + state.selectedIndex = (max_y - state.y + size / 2) / size >> 0; + }; const handleMouseUp = (e: MouseEvent) => { - e.stopPropagation() - e.preventDefault() - pos_start = null + e.stopPropagation(); + e.preventDefault(); + pos_start = null; state.y = max_y - state.selectedIndex * size; - state.transition = 'transform 0.1s' - pos_cache[0] = state.x - pos_cache[1] = state.y + state.transition = 'transform 0.1s'; + pos_cache[0] = state.x; + pos_cache[1] = state.y; if(typeof onChange === 'function') { - const idx = state.selectedIndex - const val = items[idx] - onChange(val, idx) + const idx = state.selectedIndex; + const val = items[idx]; + onChange(val, idx); } - } + }; onMounted(() => { - const { height: ch } = container.value.getBoundingClientRect() - const { height: mh } = movbar.value.getBoundingClientRect() - max_y = (ch - size) / 2 - min_y = (ch + size) / 2 - mh - pos_cache = [0, max_y - state.selectedIndex * size] - state.x = pos_cache[0] - state.y = pos_cache[1] - state.barOpacity = 1 - state.transition = 'transform 0.1s' + const { height: ch } = container.value.getBoundingClientRect(); + const { height: mh } = movbar.value.getBoundingClientRect(); + max_y = (ch - size) / 2; + min_y = (ch + size) / 2 - mh; + pos_cache = [0, max_y - state.selectedIndex * size]; + state.x = pos_cache[0]; + state.y = pos_cache[1]; + state.barOpacity = 1; + state.transition = 'transform 0.1s'; // console.log(ch, mh) - }) + }); return () => { return ( @@ -99,12 +99,12 @@ const VerticalSlider = defineComponent({ }}> { items.map((c, i) => { - const className = i === state.selectedIndex ? itemClassSelected : itemClassNormal - return <span class={`slider-item ${className}`} style={{ height: `${size}px`, lineHeight: `${size}px` }}>{c}</span> + const className = i === state.selectedIndex ? itemClassSelected : itemClassNormal; + return <span class={`slider-item ${className}`} style={{ height: `${size}px`, lineHeight: `${size}px` }}>{c}</span>; }) } </div> - <div + <div class="slider-mask" onMousedown={handleMouseDown} onMousemove={handleMouseMove} @@ -112,9 +112,9 @@ const VerticalSlider = defineComponent({ onMouseout={handleMouseUp} ></div> </div> - ) - } + ); + }; } -}) +}); -export default VerticalSlider \ No newline at end of file +export default VerticalSlider; diff --git a/packages/devui-vue/devui/date-picker/src/date-picker.tsx b/packages/devui-vue/devui/date-picker/src/date-picker.tsx index e3b6eef31d..9f878f4674 100644 --- a/packages/devui-vue/devui/date-picker/src/date-picker.tsx +++ b/packages/devui-vue/devui/date-picker/src/date-picker.tsx @@ -1,38 +1,38 @@ -import { onUnmounted, UnwrapRef , defineComponent, reactive, onMounted, ref } from 'vue' -import { invokeFunction, isIn } from './utils' -import { compareDateSort , parseDate } from './components/utils' -import { Input } from '../../input' -import { Icon } from '../../icon' +import { onUnmounted, UnwrapRef , defineComponent, reactive, onMounted, ref } from 'vue'; +import { invokeFunction, isIn } from './utils'; +import { compareDateSort , parseDate } from './components/utils'; +import { Input } from '../../input'; +import { Icon } from '../../icon'; import { TState, handleCalendarSwitchState, formatValue, formatPlaceholder, -} from './helper' +} from './helper'; -import Calendar from './components/calendar' +import Calendar from './components/calendar'; -import './date-picker.scss' +import './date-picker.scss'; const formatRange = (state: UnwrapRef<TState>) => { - const [start, end] = [state.start, state.end].sort((a, b) => a.getTime() - b.getTime()) + const [start, end] = [state.start, state.end].sort((a, b) => a.getTime() - b.getTime()); - state.start = start - state.end = end + state.start = start; + state.end = end; if (compareDateSort(start, end, 'm') !== 0) { - state.current = start - state.next = end + state.current = start; + state.next = end; } else { if (compareDateSort(start, state.current) < 0) { - state.current = start + state.current = start; } if (compareDateSort(state.next, end) < 0) { - state.next = end + state.next = end; } } -} +}; export default defineComponent({ name: 'DDatepicker', @@ -49,11 +49,11 @@ export default defineComponent({ }, setup(props) { - const panel = ref<Node>(null) - const input = ref<Node>(null) + const panel = ref<Node>(null); + const input = ref<Node>(null); - const current = parseDate(props.dateMin) || new Date() - const next = new Date(current.getFullYear(), current.getMonth() + 1, 1) + const current = parseDate(props.dateMin) || new Date(); + const next = new Date(current.getFullYear(), current.getMonth() + 1, 1); const state = reactive<TState>({ @@ -62,30 +62,30 @@ export default defineComponent({ placeholder: formatPlaceholder(props), current, next, - }) + }); - state.value = formatValue(state, props) - state.placeholder = formatPlaceholder(props) + state.value = formatValue(state, props); + state.placeholder = formatPlaceholder(props); const documentClick = (e: MouseEvent) => { - e.stopPropagation() + e.stopPropagation(); if( isIn(e.target as Node, panel.value) || isIn(e.target as Node, input.value) ) { - return + return; } - state.show = false - } + state.show = false; + }; onMounted(() => { - document.addEventListener('click', documentClick) - }) + document.addEventListener('click', documentClick); + }); onUnmounted(() => { - document.removeEventListener('click', documentClick) - }) + document.removeEventListener('click', documentClick); + }); return () => { return ( @@ -112,37 +112,37 @@ export default defineComponent({ dateEnd={state.end} dateHover={state.hover} onReset={(date: Date) => { - state.end = state.hover = undefined - state.start = date + state.end = state.hover = undefined; + state.start = date; }} onChange={() => { - state.value = formatValue(state, props) - state.placeholder = formatPlaceholder(props) - invokeFunction(props.selectedDateChange, state.value) + state.value = formatValue(state, props); + state.placeholder = formatPlaceholder(props); + invokeFunction(props.selectedDateChange, state.value); if (props.autoClose) { - state.show = false + state.show = false; } }} onToday={(date: Date) => { - state.current = date - state.start = date - state.value = formatValue(state, props) - state.placeholder = formatPlaceholder(props) - invokeFunction(props.selectedDateChange, state.value) + state.current = date; + state.start = date; + state.value = formatValue(state, props); + state.placeholder = formatPlaceholder(props); + invokeFunction(props.selectedDateChange, state.value); if (props.autoClose) { - state.show = false + state.show = false; } }} onSelected={(date: Date) => { - state.start = date + state.start = date; if (compareDateSort(state.current, date) !== 0) { - state.current = date + state.current = date; } }} onSelectStart={(date: Date) => state.start = date} onSelectEnd={(date: Date) => { - state.end = date - formatRange(state) + state.end = date; + formatRange(state); }} onSelecting={(date: Date) => state.hover = date} onPreviousYear={(date: Date, pos: number) => handleCalendarSwitchState(state, 0, pos, date)} @@ -152,7 +152,7 @@ export default defineComponent({ /> : null} </div> </div> - ) - } + ); + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/date-picker/src/helper.ts b/packages/devui-vue/devui/date-picker/src/helper.ts index 4fa82a2b85..c5a3c60853 100644 --- a/packages/devui-vue/devui/date-picker/src/helper.ts +++ b/packages/devui-vue/devui/date-picker/src/helper.ts @@ -1,18 +1,18 @@ -import type { Ref } from 'vue' -import { formatDate, formatRange } from './utils' +import type { Ref } from 'vue'; +import { formatDate, formatRange } from './utils'; export type TState = { - range?: boolean - current?: Date - next?: Date - start?: Date - end?: Date - hover?: Date - show?: boolean - input?: string - value?: string - placeholder?: string -} + range?: boolean; + current?: Date; + next?: Date; + start?: Date; + end?: Date; + hover?: Date; + show?: boolean; + input?: string; + value?: string; + placeholder?: string; +}; /** * Calendar 面板年月切换逻辑 @@ -22,29 +22,29 @@ export type TState = { * @param date */ export const handleCalendarSwitchState = (state: TState, index: number, pos: number, date: Date) => { - switch (index) { - case 0: // previous year - const preYear = new Date(date) - preYear.setFullYear(preYear.getFullYear() - 1) - pos === 0 ? (state.current = preYear) : (state.next = preYear) - break - case 1: // previous month - const preMonth = new Date(date) - preMonth.setMonth(preMonth.getMonth() - 1) - pos === 0 ? (state.current = preMonth) : (state.next = preMonth) - break - case 2: // next month - const nextMonth = new Date(date) - nextMonth.setMonth(nextMonth.getMonth() + 1) - pos === 0 ? (state.current = nextMonth) : (state.next = nextMonth) - break - case 3: // next year - const nextYear = new Date(date) - nextYear.setFullYear(nextYear.getFullYear() + 1) - pos === 0 ? (state.current = nextYear) : (state.next = nextYear) - break - } -} + switch (index) { + case 0: // previous year + const preYear = new Date(date); + preYear.setFullYear(preYear.getFullYear() - 1); + pos === 0 ? (state.current = preYear) : (state.next = preYear); + break; + case 1: // previous month + const preMonth = new Date(date); + preMonth.setMonth(preMonth.getMonth() - 1); + pos === 0 ? (state.current = preMonth) : (state.next = preMonth); + break; + case 2: // next month + const nextMonth = new Date(date); + nextMonth.setMonth(nextMonth.getMonth() + 1); + pos === 0 ? (state.current = nextMonth) : (state.next = nextMonth); + break; + case 3: // next year + const nextYear = new Date(date); + nextYear.setFullYear(nextYear.getFullYear() + 1); + pos === 0 ? (state.current = nextYear) : (state.next = nextYear); + break; + } +}; /** * 格式化输入日期字符串 @@ -53,30 +53,30 @@ export const handleCalendarSwitchState = (state: TState, index: number, pos: num * @returns */ export const formatValue = (state: TState, props: any) => { - const { format = 'y/MM/dd', range, rangeSpliter = '-' } = props || {} - if (range) { - if (!state.start) { - return '' - } else if(!state.end) { - return formatDate(format, state.start) - } - if(state.end < state.start) { - const end = state.end - state.end = state.start - state.start = end - } - return formatRange(format, - state.start, - state.end, - rangeSpliter - ) - } else { - if (!state.start) { - return '' - } - return formatDate(format, state.start) + const { format = 'y/MM/dd', range, rangeSpliter = '-' } = props || {}; + if (range) { + if (!state.start) { + return ''; + } else if(!state.end) { + return formatDate(format, state.start); + } + if(state.end < state.start) { + const end = state.end; + state.end = state.start; + state.start = end; } -} + return formatRange(format, + state.start, + state.end, + rangeSpliter + ); + } else { + if (!state.start) { + return ''; + } + return formatDate(format, state.start); + } +}; /** * 格式化placeholder显示 @@ -84,11 +84,11 @@ export const formatValue = (state: TState, props: any) => { * @returns */ export const formatPlaceholder = (props: any) => { - if (!props) return '' - const format = props.format || `y/MM/dd` - const sp = props.rangeSpliter || '-' - return props.range ? `${format} ${sp} ${format}` : format -} + if (!props) {return '';} + const format = props.format || `y/MM/dd`; + const sp = props.rangeSpliter || '-'; + return props.range ? `${format} ${sp} ${format}` : format; +}; /** * 输出日期选择结果 @@ -96,29 +96,29 @@ export const formatPlaceholder = (props: any) => { * @param output */ export const handleValue = (id: string | undefined, output: string) => { - if (id && typeof id === 'string') { - const el = document.querySelector(id) - if (el instanceof HTMLInputElement) { - el.value = output - } + if (id && typeof id === 'string') { + const el = document.querySelector(id); + if (el instanceof HTMLInputElement) { + el.value = output; } -} + } +}; /** * 获取绑定节点 * @returns */ export const getAttachInputDom = (props: any) => { - const { attach, attachInputDom = attach } = props || {} - if (!attachInputDom || typeof attachInputDom !== 'string') { - return null - } - const el = document.querySelector(attachInputDom) - if (!el) { - return null - } - return el -} + const { attach, attachInputDom = attach } = props || {}; + if (!attachInputDom || typeof attachInputDom !== 'string') { + return null; + } + const el = document.querySelector(attachInputDom); + if (!el) { + return null; + } + return el; +}; /** * 绑定弹出层场景,计算弹出层位置。 @@ -128,29 +128,29 @@ export const getAttachInputDom = (props: any) => { * @returns */ export const handlePositionFactory = (state: { - x?: string - y?: string - attachInputDom?: string - show?: boolean - st?: boolean + x?: string; + y?: string; + attachInputDom?: string; + show?: boolean; + st?: boolean; }, props: any, container: Ref<Element>) => () => { - if (!state.show) { - state.x = `-100%` - state.y = `-100%` - return - } - const el = getAttachInputDom(props) - if (!el) { - state.st = true - return - } - const { left, top, height } = el.getBoundingClientRect() - const { height: _height } = container.value.getBoundingClientRect() - const bottom = window.innerHeight - top - height - state.x = `${left}px` - if (bottom > top) { - state.y = `${top + height}px` - } else { - state.y = `${top - _height}px` - } -} \ No newline at end of file + if (!state.show) { + state.x = `-100%`; + state.y = `-100%`; + return; + } + const el = getAttachInputDom(props); + if (!el) { + state.st = true; + return; + } + const { left, top, height } = el.getBoundingClientRect(); + const { height: _height } = container.value.getBoundingClientRect(); + const bottom = window.innerHeight - top - height; + state.x = `${left}px`; + if (bottom > top) { + state.y = `${top + height}px`; + } else { + state.y = `${top - _height}px`; + } +}; diff --git a/packages/devui-vue/devui/date-picker/src/stick-slider/index.tsx b/packages/devui-vue/devui/date-picker/src/stick-slider/index.tsx index 5958215b73..2d009b4505 100644 --- a/packages/devui-vue/devui/date-picker/src/stick-slider/index.tsx +++ b/packages/devui-vue/devui/date-picker/src/stick-slider/index.tsx @@ -1,58 +1,57 @@ -import { defineComponent, reactive } from 'vue' +import { defineComponent, reactive } from 'vue'; -import './index.scss' +import './index.scss'; const StickSlider = defineComponent({ - name: 'DStickSlider', - props: {}, - setup() { - - const state = reactive({ - showButtons: false, - selectedIndex: 0, - }) - - const reset = () => { - state.showButtons = false - } - - const handleMainButtonMouseDown = (e: MouseEvent) => { - e.stopPropagation() - state.showButtons = true - } - const handleMainButtonMouseUp = (e: MouseEvent) => { - e.stopPropagation() - reset() - } - - return () => { - return ( - <div - class="devui-stick-slider" - onMousedown={handleMainButtonMouseDown} - onMouseup={handleMainButtonMouseUp} - onMouseleave={handleMainButtonMouseUp} - > - <div - class="sub-buttons" - style={{ display: state.showButtons ? '' : 'none' }} - > - { - Array(16).fill(null).map((_, i) => { - return (<div - class={`button ${i === state.selectedIndex ? 'selected' : ''}`} - onMouseenter={() => state.selectedIndex = i} - >{i}</div>) - }) - } - </div> - <div class="main-button"></div> - </div> - ) - } - } -}) - - - -export default StickSlider \ No newline at end of file + name: 'DStickSlider', + props: {}, + setup() { + + const state = reactive({ + showButtons: false, + selectedIndex: 0, + }); + + const reset = () => { + state.showButtons = false; + }; + + const handleMainButtonMouseDown = (e: MouseEvent) => { + e.stopPropagation(); + state.showButtons = true; + }; + const handleMainButtonMouseUp = (e: MouseEvent) => { + e.stopPropagation(); + reset(); + }; + + return () => { + return ( + <div + class="devui-stick-slider" + onMousedown={handleMainButtonMouseDown} + onMouseup={handleMainButtonMouseUp} + onMouseleave={handleMainButtonMouseUp} + > + <div + class="sub-buttons" + style={{ display: state.showButtons ? '' : 'none' }} + > + { + Array(16).fill(null).map((_, i) => { + return (<div + class={`button ${i === state.selectedIndex ? 'selected' : ''}`} + onMouseenter={() => state.selectedIndex = i} + >{i}</div>); + }) + } + </div> + <div class="main-button"></div> + </div> + ); + }; + } +}); + + +export default StickSlider; diff --git a/packages/devui-vue/devui/date-picker/src/utils.ts b/packages/devui-vue/devui/date-picker/src/utils.ts index e2e59c7bd7..fa0f114062 100644 --- a/packages/devui-vue/devui/date-picker/src/utils.ts +++ b/packages/devui-vue/devui/date-picker/src/utils.ts @@ -1,18 +1,18 @@ const getDateTime = (d: Date) => { - const year = d.getFullYear() - const month = d.getMonth() + 1 - const date = d.getDate() - const day = d.getDay() - const hour = d.getHours() - const minute = d.getMinutes() - const second = d.getSeconds() - const ms = d.getMilliseconds() - return [year, month, date, day, hour, minute, second, ms] -} + const year = d.getFullYear(); + const month = d.getMonth() + 1; + const date = d.getDate(); + const day = d.getDay(); + const hour = d.getHours(); + const minute = d.getMinutes(); + const second = d.getSeconds(); + const ms = d.getMilliseconds(); + return [year, month, date, day, hour, minute, second, ms]; +}; const fixStart = (n: number, m: string, max = 2, ch = '0') => { - return (n + '').padStart(Math.min(m.length, max), ch) -} + return (n + '').padStart(Math.min(m.length, max), ch); +}; /** * - y: year yy 取后2位,其他情况取4位 @@ -21,30 +21,30 @@ const fixStart = (n: number, m: string, max = 2, ch = '0') => { * @param d */ export const formatDate = (fmt: string, d: Date) => { - const usage = getDateTime(d) - let res = fmt - res = res.replace(/y+/g, m => { - const year = usage[0] + '' - if (m.length === 2) { - return year.substring(2) - } - return year - }) - res = res.replace(/M+/g, m => fixStart(usage[1], m)) - res = res.replace(/d+/g, m => fixStart(usage[2], m)) - res = res.replace(/h+/g, m => fixStart(usage[4], m)) - res = res.replace(/m+/g, m => fixStart(usage[5], m)) - res = res.replace(/s+/g, m => fixStart(usage[6], m)) - return res -} + const usage = getDateTime(d); + let res = fmt; + res = res.replace(/y+/g, m => { + const year = usage[0] + ''; + if (m.length === 2) { + return year.substring(2); + } + return year; + }); + res = res.replace(/M+/g, m => fixStart(usage[1], m)); + res = res.replace(/d+/g, m => fixStart(usage[2], m)); + res = res.replace(/h+/g, m => fixStart(usage[4], m)); + res = res.replace(/m+/g, m => fixStart(usage[5], m)); + res = res.replace(/s+/g, m => fixStart(usage[6], m)); + return res; +}; export const formatRange = (fmt: string, a: Date, b: Date, conn = '-') => { - const ab = [a, b] - if(a.getTime() > b.getTime()) { - ab.reverse() - } - return `${formatDate(fmt, ab[0])} ${conn} ${formatDate(fmt, ab[1])}` -} + const ab = [a, b]; + if(a.getTime() > b.getTime()) { + ab.reverse(); + } + return `${formatDate(fmt, ab[0])} ${conn} ${formatDate(fmt, ab[1])}`; +}; /** * 判断节点a是否在节点b中 @@ -53,58 +53,58 @@ export const formatRange = (fmt: string, a: Date, b: Date, conn = '-') => { * @returns */ export const isIn = (a: Node | null, b: any) => { - if (!b) { - return false + if (!b) { + return false; + } + while (a) { + if (a === b) { + return true; } - while (a) { - if (a === b) { - return true - } - a = a.parentNode - } - return false -} + a = a.parentNode; + } + return false; +}; -type EventItem = { el: Node | Window; cb: (...args: any[]) => any; name: string; capture: boolean; } +type EventItem = { el: Node | Window; cb: (...args: any[]) => any; name: string; capture: boolean }; export class EventManager { - private readonly items: EventItem[] - constructor() { - this.items = [] - } + private readonly items: EventItem[]; + constructor() { + this.items = []; + } - append(el: Node | Window, name: string, cb: (...args: any[]) => any, capture = false) { - el.addEventListener(name, cb, capture) - this.items.push({ el, name, cb, capture }) - } + append(el: Node | Window, name: string, cb: (...args: any[]) => any, capture = false) { + el.addEventListener(name, cb, capture); + this.items.push({ el, name, cb, capture }); + } - dispose() { - this.items.splice(0, this.items.length).forEach(({ el, name, cb, capture }) => { - el.removeEventListener(name, cb, capture) - }) - } + dispose() { + this.items.splice(0, this.items.length).forEach(({ el, name, cb, capture }) => { + el.removeEventListener(name, cb, capture); + }); + } } export const traceNode = (el: Node) => { - const els: Node[] = [] - while (el.parentNode) { - els.push(el.parentNode) - el = el.parentNode - } - return els -} + const els: Node[] = []; + while (el.parentNode) { + els.push(el.parentNode); + el = el.parentNode; + } + return els; +}; /** * 函数安全调用 */ export const invokeFunction = (fn: any, ...args: any[]) => { - if (typeof fn === 'function') { - fn(...args) - } -} + if (typeof fn === 'function') { + fn(...args); + } +}; export const getMinDate = (a?: Date, b?: Date) => { - if(a && b) { - return a > b ? b : a - } - return a || b || undefined -} \ No newline at end of file + if(a && b) { + return a > b ? b : a; + } + return a || b || undefined; +}; diff --git a/packages/devui-vue/devui/dragdrop/__tests__/dragdrop.spec.ts b/packages/devui-vue/devui/dragdrop/__tests__/dragdrop.spec.ts index 83981b23ee..c98d4ff08c 100644 --- a/packages/devui-vue/devui/dragdrop/__tests__/dragdrop.spec.ts +++ b/packages/devui-vue/devui/dragdrop/__tests__/dragdrop.spec.ts @@ -4,5 +4,5 @@ import { DragdropDirective } from '../index'; describe('dragdrop test', () => { it('dragdrop init render', async () => { // todo - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/dragdrop/index.ts b/packages/devui-vue/devui/dragdrop/index.ts index d1953c4993..937219c020 100644 --- a/packages/devui-vue/devui/dragdrop/index.ts +++ b/packages/devui-vue/devui/dragdrop/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import DraggableDirective from './src/draggable-directive' -import DroppableDirective from './src/droppable-directive' -import SortableDirective from './src/sortable-directive' +import type { App } from 'vue'; +import DraggableDirective from './src/draggable-directive'; +import DroppableDirective from './src/droppable-directive'; +import SortableDirective from './src/sortable-directive'; -export { DraggableDirective, DroppableDirective, SortableDirective } +export { DraggableDirective, DroppableDirective, SortableDirective }; export default { title: 'Dragdrop 拖拽', category: '通用', status: '10%', install(app: App): void { - app.directive('DDraggable', DraggableDirective) - app.directive('DDroppable', DroppableDirective) - app.directive('DSortable', SortableDirective) + app.directive('DDraggable', DraggableDirective); + app.directive('DDroppable', DroppableDirective); + app.directive('DSortable', SortableDirective); } -} +}; diff --git a/packages/devui-vue/devui/dragdrop/src/constant.ts b/packages/devui-vue/devui/dragdrop/src/constant.ts index 98c9224ec4..04d8438851 100644 --- a/packages/devui-vue/devui/dragdrop/src/constant.ts +++ b/packages/devui-vue/devui/dragdrop/src/constant.ts @@ -1 +1 @@ -export const shadowId = 'shadow0611' \ No newline at end of file +export const shadowId = 'shadow0611'; diff --git a/packages/devui-vue/devui/dragdrop/src/draggable-directive.ts b/packages/devui-vue/devui/dragdrop/src/draggable-directive.ts index fa333e2bdf..414b8674d2 100644 --- a/packages/devui-vue/devui/dragdrop/src/draggable-directive.ts +++ b/packages/devui-vue/devui/dragdrop/src/draggable-directive.ts @@ -1,41 +1,41 @@ -import { changeDragState, deleteInsertedSortableShadow } from './utils' -import { shadowId } from './constant' +import { changeDragState, deleteInsertedSortableShadow } from './utils'; +import { shadowId } from './constant'; export default { /** - * - * @param el + * + * @param el * @description * 1、绑定该指令的element将会具备拖拽能力 * 2、为各元素进行初始化配置 * 2.1、dragFlag: 是否处于拖拽中 * 2.2、dragOverFlag: 是否处于可放置区域 - * + * * 1、整体思路 * 1.1、为每个绑定drag指令的元素维护状态 * 1.1.1、状态集合:dragStart、drag、dragover、drop、shouldCreateShadow - * + * * 1.2、进入drop区域后,确保drop区域能够获取正在进行drag的元素 */ mounted(el: HTMLElement, binding: unknown): void { el.setAttribute('draggable', 'true'); - el.style.cursor = 'grab' + el.style.cursor = 'grab'; // dragstart/drag/dragend el.addEventListener('drag', () => { - changeDragState(el, el.id, 'true', 'true', 'false', 'false', 'false', 'true') + changeDragState(el, el.id, 'true', 'true', 'false', 'false', 'false', 'true'); if (binding.instance.$root.dropElement && document.getElementById(shadowId)){ - deleteInsertedSortableShadow(binding.instance.$root.dropElement) // 如何让它仅执行1次? - binding.instance.$root.dropElement = null + deleteInsertedSortableShadow(binding.instance.$root.dropElement); // 如何让它仅执行1次? + binding.instance.$root.dropElement = null; } - }, false) + }, false); // dragStart事件为每个绑定元素进行初始化 el.addEventListener('dragstart', ()=>{ // el or binding.instance or vnode.context - changeDragState(el, el.id, 'true', 'true', 'false', 'false', 'false', 'false') - binding.instance.$root.identity = el.id - el.dataset.dragArea = el.parentNode.className - }, false) + changeDragState(el, el.id, 'true', 'true', 'false', 'false', 'false', 'false'); + binding.instance.$root.identity = el.id; + el.dataset.dragArea = el.parentNode.className; + }, false); }, -} +}; diff --git a/packages/devui-vue/devui/dragdrop/src/droppable-directive.ts b/packages/devui-vue/devui/dragdrop/src/droppable-directive.ts index 289ad8ef7e..189ac82c4f 100644 --- a/packages/devui-vue/devui/dragdrop/src/droppable-directive.ts +++ b/packages/devui-vue/devui/dragdrop/src/droppable-directive.ts @@ -1,49 +1,49 @@ -import { changeDragState } from './utils' +import { changeDragState } from './utils'; export default { /** - * - * @param el + * + * @param el * @description * dragOver: * 1、生成与清除阴影的时机 * 1.1、生成时机(只生成一次): dragFlag === true && dragOverFlag === true - * drop: + * drop: * 1、完成放的操作 * 1.1、清除相应的阴影 */ - mounted(el: HTMLElement, binding:unknown): void { - // dragenter/dragover/dragend/drop + mounted(el: HTMLElement, binding: unknown): void { + // dragenter/dragover/dragend/drop el.addEventListener('dragover', (event: DragEvent) => { - event.preventDefault() - const dragId = binding.instance.$root.identity - changeDragState(document.getElementById(dragId), dragId, 'true', 'false', 'true', 'false', 'false', 'false') - document.getElementById(dragId).dataset.dropArea = [...el.childNodes][1].className - }, false) + event.preventDefault(); + const dragId = binding.instance.$root.identity; + changeDragState(document.getElementById(dragId), dragId, 'true', 'false', 'true', 'false', 'false', 'false'); + document.getElementById(dragId).dataset.dropArea = [...el.childNodes][1].className; + }, false); // 新增两个标识解决战斗,即dragStart区域、drop区域、sortableDrop区域 el.addEventListener('drop', (event: DragEvent) => { - event.preventDefault() - const dragId = binding.instance.$root.identity + event.preventDefault(); + const dragId = binding.instance.$root.identity; if (document.getElementById(dragId).dataset.dropArea == document.getElementById(dragId).dataset.dragArea){ - return + return; } // 如何定义可放置区域这个问题得商榷一下 - const childrenArr = [...Array.from(el.children)[1].children] + const childrenArr = [...Array.from(el.children)[1].children]; if (childrenArr.length > 0){ for (let index = 0; index < childrenArr.length; index++){ - const childrenYRange = childrenArr[index].getBoundingClientRect().top + childrenArr[index].offsetHeight / 2 + const childrenYRange = childrenArr[index].getBoundingClientRect().top + childrenArr[index].offsetHeight / 2; if (parseFloat(event.clientY) < parseFloat(childrenYRange)){ - el.children[1].insertBefore(document.getElementById(dragId), childrenArr[index]) - break + el.children[1].insertBefore(document.getElementById(dragId), childrenArr[index]); + break; } if (index === childrenArr.length-1){ - el.children[1].appendChild(document.getElementById(dragId)) + el.children[1].appendChild(document.getElementById(dragId)); } } }else { - el.childNodes[1].appendChild(document.getElementById(dragId)) + el.childNodes[1].appendChild(document.getElementById(dragId)); } - }) + }); }, -} +}; diff --git a/packages/devui-vue/devui/dragdrop/src/sortable-directive.ts b/packages/devui-vue/devui/dragdrop/src/sortable-directive.ts index 2066b831d4..f6a71982f1 100644 --- a/packages/devui-vue/devui/dragdrop/src/sortable-directive.ts +++ b/packages/devui-vue/devui/dragdrop/src/sortable-directive.ts @@ -1,11 +1,11 @@ -import { shadowId } from './constant' -import { changeDragState, createInsertSortableShadow, insertDragElement } from './utils' +import { shadowId } from './constant'; +import { changeDragState, createInsertSortableShadow, insertDragElement } from './utils'; export default { - /** - * - * @param el + /** + * + * @param el * @description * 此命令用于将元素变为可放置的元素并且支持排序 * dragover: @@ -15,34 +15,34 @@ export default { * 1、可放置区域里如果没有拖拽元素,直接放置 * 2、可放置区域里如果有其他的可拖拽元素,需要对比放置到正确的位置上 */ - mounted(el: HTMLElement, binding:unknown):void { - el.addEventListener('dragover', function (event: DragEvent){ - event.preventDefault() - const targetNode: any = event.target; - const dragId = binding.instance.$root.identity - if (!binding.instance.$root.dropElement){ - binding.instance.$root.dropElement = [...el.childNodes][1] - } - changeDragState(document.getElementById(binding.instance.$root.identity), binding.instance.$root.identity, 'true', 'false', 'true', 'false', 'true', 'false') - const { dragover, shouldCreateShadow } = document.getElementById(dragId).dataset - if (dragover == 'true'){ - if (shouldCreateShadow == 'true'){ - createInsertSortableShadow([...targetNode.children][1], event, dragId) - } - } - - }) - el.addEventListener('drop', function (event: DragEvent){ - // 获取可放置区域 - const dropArea = [...el.childNodes][1] - const dragId = binding.instance.$root.identity - dropArea.removeChild(document.getElementById(shadowId)) - if ([...dropArea.childNodes].length == 0){ - dropArea.appendChild(document.getElementById(dragId)) - }else { - insertDragElement(dropArea, dragId, event) - } - changeDragState(document.getElementById(dragId), dragId, 'false', 'false', 'false', 'true', 'false', 'false') - }) - } -} \ No newline at end of file + mounted(el: HTMLElement, binding: unknown): void { + el.addEventListener('dragover', function (event: DragEvent){ + event.preventDefault(); + const targetNode: any = event.target; + const dragId = binding.instance.$root.identity; + if (!binding.instance.$root.dropElement){ + binding.instance.$root.dropElement = [...el.childNodes][1]; + } + changeDragState(document.getElementById(binding.instance.$root.identity), binding.instance.$root.identity, 'true', 'false', 'true', 'false', 'true', 'false'); + const { dragover, shouldCreateShadow } = document.getElementById(dragId).dataset; + if (dragover == 'true'){ + if (shouldCreateShadow == 'true'){ + createInsertSortableShadow([...targetNode.children][1], event, dragId); + } + } + + }); + el.addEventListener('drop', function (event: DragEvent){ + // 获取可放置区域 + const dropArea = [...el.childNodes][1]; + const dragId = binding.instance.$root.identity; + dropArea.removeChild(document.getElementById(shadowId)); + if ([...dropArea.childNodes].length == 0){ + dropArea.appendChild(document.getElementById(dragId)); + }else { + insertDragElement(dropArea, dragId, event); + } + changeDragState(document.getElementById(dragId), dragId, 'false', 'false', 'false', 'true', 'false', 'false'); + }); + } +}; diff --git a/packages/devui-vue/devui/dragdrop/src/utils.ts b/packages/devui-vue/devui/dragdrop/src/utils.ts index 0b07447eba..3298df348c 100644 --- a/packages/devui-vue/devui/dragdrop/src/utils.ts +++ b/packages/devui-vue/devui/dragdrop/src/utils.ts @@ -1,143 +1,143 @@ -import { shadowId } from './constant' +import { shadowId } from './constant'; /** - * - * @param id + * + * @param id * @descriprion * 根据id获取非内联样式元素的样式 */ -function getElementStyle (id: string, styleName: string):string { - return document.getElementById(id).currentStyle ? document.getElementById(id).currentStyle[styleName] : window.getComputedStyle( - document.getElementById(id), - styleName - ) +function getElementStyle (id: string, styleName: string): string { + return document.getElementById(id).currentStyle ? document.getElementById(id).currentStyle[styleName] : window.getComputedStyle( + document.getElementById(id), + styleName + ); } /** - * - * @param originId + * + * @param originId * @description * 根据拖拽的id生成相应的阴影 * 如何生成shadow? * 情况一: dragable -> drop without sortable * 情况二: anything -> drop without anything */ -function createShadow (originId:string):HTMLElement { - const shadow = document.createElement('div'); - shadow.id = shadowId - shadow.style.background = 'rgb(206, 215, 255)' - shadow.style.width = getElementStyle(originId, 'width') - shadow.style.height = '20px' - return shadow +function createShadow (originId: string): HTMLElement { + const shadow = document.createElement('div'); + shadow.id = shadowId; + shadow.style.background = 'rgb(206, 215, 255)'; + shadow.style.width = getElementStyle(originId, 'width'); + shadow.style.height = '20px'; + return shadow; } /** - * - * @param el - * @param originId - * @param dragStart - * @param drag - * @param dragover - * @param drop - * @param shouldCreateShadow + * + * @param el + * @param originId + * @param dragStart + * @param drag + * @param dragover + * @param drop + * @param shouldCreateShadow * @param dragFlag * @description - * 改变拖拽元素相应的状态 + * 改变拖拽元素相应的状态 */ -function changeDragState (el:string, originId:string, dragStart:string, drag:string, dragover:string, drop:string, shouldCreateShadow:string, dragFlag: string): void{ - el.dataset.originId = originId - el.dataset.dragStart = dragStart - el.dataset.dragover = dragover - el.dataset.drop = drop - el.dataset.shouldCreateShadow = shouldCreateShadow - el.dataset.dragFlag = dragFlag +function changeDragState (el: string, originId: string, dragStart: string, drag: string, dragover: string, drop: string, shouldCreateShadow: string, dragFlag: string): void{ + el.dataset.originId = originId; + el.dataset.dragStart = dragStart; + el.dataset.dragover = dragover; + el.dataset.drop = drop; + el.dataset.shouldCreateShadow = shouldCreateShadow; + el.dataset.dragFlag = dragFlag; } /** - * - * @param compareElement - * @returns + * + * @param compareElement + * @returns * @description * 计算可对比元素的高度 */ function computeCompareElementHeight (compareElement: HTMLCollection): unknown{ - return compareElement.getBoundingClientRect().top + Math.floor(compareElement.offsetHeight / 2) + return compareElement.getBoundingClientRect().top + Math.floor(compareElement.offsetHeight / 2); } /** - * - * @param sortDropArea - * @param mouseObject + * + * @param sortDropArea + * @param mouseObject * 1、首先确认可放置区域 * 2、确保每个元素只生成一次shadow * 3、 */ -function createInsertSortableShadow (sortDropArea: unknown, mouseObject: unknown, originId: string):void { - const sortDropAreaArr: Array = [...sortDropArea.children] - if (sortDropAreaArr.length == 0){ - if (!document.getElementById(shadowId)){ - const shadowElement = createShadow(originId) - sortDropArea.appendChild(shadowElement) - } - }else { - for (let index = 0; index < sortDropAreaArr.length; index++){ - const compareHeight = computeCompareElementHeight(sortDropAreaArr[index]) - document.getElementById(shadowId) ? sortDropArea.removeChild(document.getElementById(shadowId)) : null - if (index == sortDropAreaArr.length-1){ - sortDropArea.appendChild(createShadow(originId)) - break - } - if (Math.floor(mouseObject.clientY)<= compareHeight){ - sortDropArea.insertBefore(createShadow(originId), sortDropAreaArr[index]) - break - } - } +function createInsertSortableShadow (sortDropArea: unknown, mouseObject: unknown, originId: string): void { + const sortDropAreaArr: Array = [...sortDropArea.children]; + if (sortDropAreaArr.length == 0){ + if (!document.getElementById(shadowId)){ + const shadowElement = createShadow(originId); + sortDropArea.appendChild(shadowElement); } + }else { + for (let index = 0; index < sortDropAreaArr.length; index++){ + const compareHeight = computeCompareElementHeight(sortDropAreaArr[index]); + document.getElementById(shadowId) ? sortDropArea.removeChild(document.getElementById(shadowId)) : null; + if (index == sortDropAreaArr.length-1){ + sortDropArea.appendChild(createShadow(originId)); + break; + } + if (Math.floor(mouseObject.clientY)<= compareHeight){ + sortDropArea.insertBefore(createShadow(originId), sortDropAreaArr[index]); + break; + } + } + } } /** - * - * @param dropAreaContainer - * @param dragId - * @param mouseObject + * + * @param dropAreaContainer + * @param dragId + * @param mouseObject * @description * 向sortable区域插入拖拽元素 */ function insertDragElement (dropAreaContainer: HTMLCollection, dragId: string, mouseObject: MouseEvent): void { - for (let index = 0; index < [...dropAreaContainer.children].length; index++){ - if (index == [...dropAreaContainer.children].length-1){ - dropAreaContainer.appendChild(document.getElementById(dragId)) - break - } - if (Math.floor(mouseObject.clientY) <= computeCompareElementHeight([...dropAreaContainer.children][index])){ - dropAreaContainer.insertBefore(document.getElementById(dragId), [...dropAreaContainer.children][index]) - break - } + for (let index = 0; index < [...dropAreaContainer.children].length; index++){ + if (index == [...dropAreaContainer.children].length-1){ + dropAreaContainer.appendChild(document.getElementById(dragId)); + break; + } + if (Math.floor(mouseObject.clientY) <= computeCompareElementHeight([...dropAreaContainer.children][index])){ + dropAreaContainer.insertBefore(document.getElementById(dragId), [...dropAreaContainer.children][index]); + break; } + } } /** - * - * @param dropSortArea + * + * @param dropSortArea * @description * 删除可排序区域中的shadow */ -function deleteInsertedSortableShadow (dropSortArea: unknown):void{ - if (dropSortArea){ - if (document.getElementById(shadowId)){ - if (dropSortArea.contains(document.getElementById(shadowId))){ - dropSortArea.removeChild(document.getElementById(shadowId)) - } - } +function deleteInsertedSortableShadow (dropSortArea: unknown): void{ + if (dropSortArea){ + if (document.getElementById(shadowId)){ + if (dropSortArea.contains(document.getElementById(shadowId))){ + dropSortArea.removeChild(document.getElementById(shadowId)); + } } + } } export { - createShadow, - changeDragState, - createInsertSortableShadow, - deleteInsertedSortableShadow, - computeCompareElementHeight, - insertDragElement -} \ No newline at end of file + createShadow, + changeDragState, + createInsertSortableShadow, + deleteInsertedSortableShadow, + computeCompareElementHeight, + insertDragElement +}; diff --git a/packages/devui-vue/devui/dropdown/__tests__/dropdown.spec.ts b/packages/devui-vue/devui/dropdown/__tests__/dropdown.spec.ts index f842c738ef..6950fd151c 100644 --- a/packages/devui-vue/devui/dropdown/__tests__/dropdown.spec.ts +++ b/packages/devui-vue/devui/dropdown/__tests__/dropdown.spec.ts @@ -4,5 +4,5 @@ import { Dropdown } from '../index'; describe('dropdown test', () => { it('dropdown init render', async () => { // todo - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/editable-select/src/composables/use-filter-options.ts b/packages/devui-vue/devui/editable-select/src/composables/use-filter-options.ts index 87c2e3514a..afdbd4bfc7 100644 --- a/packages/devui-vue/devui/editable-select/src/composables/use-filter-options.ts +++ b/packages/devui-vue/devui/editable-select/src/composables/use-filter-options.ts @@ -23,6 +23,6 @@ export const userFilterOptions: ( filteredOptions.push(option); } }); - + return filteredOptions; }); diff --git a/packages/devui-vue/devui/editable-select/src/composables/use-input.ts b/packages/devui-vue/devui/editable-select/src/composables/use-input.ts index d553ad362a..0b76eb99ab 100644 --- a/packages/devui-vue/devui/editable-select/src/composables/use-input.ts +++ b/packages/devui-vue/devui/editable-select/src/composables/use-input.ts @@ -1,6 +1,6 @@ import { SetupContext, Ref } from 'vue'; interface userInputReturnType { - handleInput: (event: Event) => void + handleInput: (event: Event) => void; } export const useInput: (inputValue: Ref<string>, ctx: SetupContext) => userInputReturnType = ( inputValue, diff --git a/packages/devui-vue/devui/editable-select/src/composables/use-keyboard-select.ts b/packages/devui-vue/devui/editable-select/src/composables/use-keyboard-select.ts index 45e6760d36..9955362e50 100644 --- a/packages/devui-vue/devui/editable-select/src/composables/use-keyboard-select.ts +++ b/packages/devui-vue/devui/editable-select/src/composables/use-keyboard-select.ts @@ -2,7 +2,7 @@ import { ComputedRef, nextTick, Ref } from 'vue'; import { OptionObjectItem } from '../editable-select-type'; interface useKeyboardSelectReturnType { - handleKeydown: (event: KeyboardEvent) => void + handleKeydown: (event: KeyboardEvent) => void; } export const useKeyboardSelect: ( dropdownRef: Ref<any>, @@ -48,7 +48,7 @@ export const useKeyboardSelect: ( if (!newIndex) { newIndex = hoverIndex.value; } - if (!['ArrowDown', 'ArrowUp'].includes(direction)) return; + if (!['ArrowDown', 'ArrowUp'].includes(direction)) {return;} if (direction === 'ArrowUp') { if (newIndex === 0) { newIndex = options.value.length - 1; @@ -78,7 +78,7 @@ export const useKeyboardSelect: ( const handleKeydown = (event: KeyboardEvent) => { const keyCode = event.key || event.code; - if (options.value.length === 0) return; + if (options.value.length === 0) {return;} if (!visible.value) { return toggleMenu(); @@ -94,14 +94,14 @@ export const useKeyboardSelect: ( }; switch (keyCode) { - case 'Enter': - onKeydownEnter(); - break; - case 'Escape': - onKeydownEsc(); - break; - default: - onKeyboardNavigation(keyCode); + case 'Enter': + onKeydownEnter(); + break; + case 'Escape': + onKeydownEsc(); + break; + default: + onKeyboardNavigation(keyCode); } }; return { diff --git a/packages/devui-vue/devui/editable-select/src/composables/use-lazy-load.ts b/packages/devui-vue/devui/editable-select/src/composables/use-lazy-load.ts index 2580eaf9ae..581192df8a 100644 --- a/packages/devui-vue/devui/editable-select/src/composables/use-lazy-load.ts +++ b/packages/devui-vue/devui/editable-select/src/composables/use-lazy-load.ts @@ -2,7 +2,7 @@ import { Ref } from 'vue'; import { OptionObjectItem } from '../editable-select-type'; interface useLazyLoadReturenType { - loadMore: () => void + loadMore: () => void; } export const useLazyLoad: ( dropdownRef: Ref, @@ -11,7 +11,7 @@ export const useLazyLoad: ( load: (val: string) => void ) => useLazyLoadReturenType = (dropdownRef, inputValue, filterOtion, load) => { const loadMore = () => { - if (filterOtion !== false) return; + if (filterOtion !== false) {return;} if ( dropdownRef.value.clientHeight + dropdownRef.value.scrollTop >= @@ -20,6 +20,6 @@ export const useLazyLoad: ( load(inputValue.value); } }; - + return { loadMore }; }; diff --git a/packages/devui-vue/devui/editable-select/src/editable-select-type.ts b/packages/devui-vue/devui/editable-select/src/editable-select-type.ts index 87a4508326..ab59f76999 100644 --- a/packages/devui-vue/devui/editable-select/src/editable-select-type.ts +++ b/packages/devui-vue/devui/editable-select/src/editable-select-type.ts @@ -1,7 +1,7 @@ export type OptionsType = Array<OptionType>; export type OptionType = string | number | OptionObjectItem; export interface OptionObjectItem { - label: string - value: string | number - [key: string]: any + label: string; + value: string | number; + [key: string]: any; } diff --git a/packages/devui-vue/devui/editable-select/src/editable-select-types.ts b/packages/devui-vue/devui/editable-select/src/editable-select-types.ts index 8ee593c50d..8726182399 100644 --- a/packages/devui-vue/devui/editable-select/src/editable-select-types.ts +++ b/packages/devui-vue/devui/editable-select/src/editable-select-types.ts @@ -36,7 +36,7 @@ export const editableSelectProps = { }, filterOption: { type: [Function, Boolean] as PropType< - boolean | ((input: string, option: OptionObjectItem) => boolean) + boolean | ((input: string, option: OptionObjectItem) => boolean) > }, loadMore: { diff --git a/packages/devui-vue/devui/editable-select/src/utils/index.ts b/packages/devui-vue/devui/editable-select/src/utils/index.ts index 8b81777a72..da7b6f33c0 100644 --- a/packages/devui-vue/devui/editable-select/src/utils/index.ts +++ b/packages/devui-vue/devui/editable-select/src/utils/index.ts @@ -4,16 +4,16 @@ * @param classOpt 是一个对象,key表示class名,value为布尔值,true则添加,否则不添加 * @returns 最终的class字符串 */ - export function className( - classStr: string, - classOpt?: { [key: string]: boolean; } - ): string { - let classname = classStr; - if (typeof classOpt === 'object') { - Object.keys(classOpt).forEach((key) => { - classOpt[key] && (classname += ` ${key}`); - }); - } - - return classname; - } \ No newline at end of file +export function className( + classStr: string, + classOpt?: { [key: string]: boolean } +): string { + let classname = classStr; + if (typeof classOpt === 'object') { + Object.keys(classOpt).forEach((key) => { + classOpt[key] && (classname += ` ${key}`); + }); + } + + return classname; +} diff --git a/packages/devui-vue/devui/form/index.ts b/packages/devui-vue/devui/form/index.ts index bdbb61bbf6..6da1c16a32 100644 --- a/packages/devui-vue/devui/form/index.ts +++ b/packages/devui-vue/devui/form/index.ts @@ -1,5 +1,5 @@ -import type { App } from 'vue' -import Form from './src/form' +import type { App } from 'vue'; +import Form from './src/form'; import FormLabel from './src/form-label/form-label'; import FormItem from './src/form-item/form-item'; import FormControl from './src/form-control/form-control'; @@ -9,25 +9,25 @@ import dValidateRules from './src/directive/d-validate-rules'; Form.install = function(app: App) { app.component(Form.name, Form); app.directive('d-validate-rules', dValidateRules); -} +}; FormLabel.install = function(app: App) { - app.component(FormLabel.name, FormLabel) -} + app.component(FormLabel.name, FormLabel); +}; FormItem.install = function(app: App) { - app.component(FormItem.name, FormItem) -} + app.component(FormItem.name, FormItem); +}; FormControl.install = function(app: App) { - app.component(FormControl.name, FormControl) -} + app.component(FormControl.name, FormControl); +}; FormOperation.install = function(app: App) { - app.component(FormOperation.name, FormOperation) -} + app.component(FormOperation.name, FormOperation); +}; -export { Form, FormLabel, FormItem, FormControl, FormOperation } +export { Form, FormLabel, FormItem, FormControl, FormOperation }; export default { title: 'Form 表单', @@ -40,4 +40,4 @@ export default { app.use(FormControl as any); app.use(FormOperation as any); } -} +}; diff --git a/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts b/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts index 89aa54e664..b1099ad447 100644 --- a/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts +++ b/packages/devui-vue/devui/form/src/directive/d-validate-rules.ts @@ -5,49 +5,49 @@ import { EventBus, isObject, hasKey } from '../util'; import './style.scss'; interface ValidateFnParam { - validator: AsyncValidator - modelValue: Record<string, unknown> - el: HTMLElement - tipEl: HTMLElement - isFormTag: boolean - message: string - messageShowType: MessageShowType - dfcUID: string - popPosition: PopPosition | Array<BasePopPosition> - updateOn?: UpdateOn + validator: AsyncValidator; + modelValue: Record<string, unknown>; + el: HTMLElement; + tipEl: HTMLElement; + isFormTag: boolean; + message: string; + messageShowType: MessageShowType; + dfcUID: string; + popPosition: PopPosition | Array<BasePopPosition>; + updateOn?: UpdateOn; } interface CustomValidatorRuleObject { - message: string - validator: (rule, value) => boolean - asyncValidator: (rule, value) => Promise<boolean> + message: string; + validator: (rule, value) => boolean; + asyncValidator: (rule, value) => Promise<boolean>; } interface DirectiveValidateRuleOptions { - updateOn?: UpdateOn - errorStrategy?: ErrorStrategy - asyncDebounceTime?: number - popPosition?: PopPosition | Array<BasePopPosition> + updateOn?: UpdateOn; + errorStrategy?: ErrorStrategy; + asyncDebounceTime?: number; + popPosition?: PopPosition | Array<BasePopPosition>; } interface DirectiveBindingValue { - rules: Partial<DirectiveCustomRuleItem>[] - options: DirectiveValidateRuleOptions - messageShowType: MessageShowType - errorStrategy: ErrorStrategy + rules: Partial<DirectiveCustomRuleItem>[]; + options: DirectiveValidateRuleOptions; + messageShowType: MessageShowType; + errorStrategy: ErrorStrategy; } interface DirectiveCustomRuleItem extends RuleItem { - validators: CustomValidatorRuleObject[] - asyncValidators: CustomValidatorRuleObject[] + validators: CustomValidatorRuleObject[]; + asyncValidators: CustomValidatorRuleObject[]; } export interface ShowPopoverErrorMessageEventData { - showPopover?: boolean - message?: string - uid?: string, - popPosition?: PopPosition - [prop : string]: any + showPopover?: boolean; + message?: string; + uid?: string; + popPosition?: PopPosition; + [prop: string]: any; } type MessageShowType = 'popover' | 'text' | 'none' | 'toast'; @@ -83,117 +83,117 @@ function getAvaliableRuleObj(ruleName: string, value: any) { return null; } switch(ruleName) { - case 'maxlength': - return { - type: 'string', - max: value, - asyncValidator: (rule, val) => { - return new Promise((resolve, reject) => { - if(val.length > value) { - reject('最大长度为' + value); - }else { - resolve('校验通过'); - } - }) - } - }; - case 'minlength': - return { - type: 'string', - min: value, - asyncValidator: (rule, val) => { - return new Promise((resolve, reject) => { - if(val.length < value) { - reject('最小长度为' + value); - }else { - resolve('校验通过'); - } - }) - } - }; - case 'min': - return { - type: 'number', - asyncValidator: (rule, val) => { - return new Promise((resolve, reject) => { - if(val < value) { - reject('最小值为' + value); - }else { - resolve('校验通过'); - } - }) - } - }; - case 'max': - return { - type: 'number', - asyncValidator: (rule, val) => { - return new Promise((resolve, reject) => { - if(val > value) { - reject('最大值为' + value); - }else { - resolve('校验通过'); - } - }) - } - }; - case 'required': - return { - reqiured: true, - asyncValidator: (rule, val) => { - return new Promise((resolve, reject) => { - if(!val) { - reject('必填项'); - }else { - resolve('校验通过'); - } - }) - } - }; - case 'requiredTrue': - return { - asyncValidator: (rule, val) => { - return new Promise((resolve, reject) => { - if(!val) { - reject('必须为true值'); - }else { - resolve('校验通过'); - } - }) - } - }; - case 'email': - return { - type: 'email', - message: '邮箱格式不正确' - }; - case 'pattern': - return { - type: 'regexp', - pattern: value, - message: '只能包含数字与大小写字符', - validator: (rule, val) => value.test(val), - }; - case 'whitespace': - return { - message: '输入不能全部为空格或空字符', - validator: (rule, val) => !!val.trim() - }; - default: - return { - [ruleName]: value, - }; + case 'maxlength': + return { + type: 'string', + max: value, + asyncValidator: (rule, val) => { + return new Promise((resolve, reject) => { + if(val.length > value) { + reject('最大长度为' + value); + }else { + resolve('校验通过'); + } + }); + } + }; + case 'minlength': + return { + type: 'string', + min: value, + asyncValidator: (rule, val) => { + return new Promise((resolve, reject) => { + if(val.length < value) { + reject('最小长度为' + value); + }else { + resolve('校验通过'); + } + }); + } + }; + case 'min': + return { + type: 'number', + asyncValidator: (rule, val) => { + return new Promise((resolve, reject) => { + if(val < value) { + reject('最小值为' + value); + }else { + resolve('校验通过'); + } + }); + } + }; + case 'max': + return { + type: 'number', + asyncValidator: (rule, val) => { + return new Promise((resolve, reject) => { + if(val > value) { + reject('最大值为' + value); + }else { + resolve('校验通过'); + } + }); + } + }; + case 'required': + return { + reqiured: true, + asyncValidator: (rule, val) => { + return new Promise((resolve, reject) => { + if(!val) { + reject('必填项'); + }else { + resolve('校验通过'); + } + }); + } + }; + case 'requiredTrue': + return { + asyncValidator: (rule, val) => { + return new Promise((resolve, reject) => { + if(!val) { + reject('必须为true值'); + }else { + resolve('校验通过'); + } + }); + } + }; + case 'email': + return { + type: 'email', + message: '邮箱格式不正确' + }; + case 'pattern': + return { + type: 'regexp', + pattern: value, + message: '只能包含数字与大小写字符', + validator: (rule, val) => value.test(val), + }; + case 'whitespace': + return { + message: '输入不能全部为空格或空字符', + validator: (rule, val) => !!val.trim() + }; + default: + return { + [ruleName]: value, + }; } } -function getKeyValueOfObjectList(obj): {key: string; value: any;}[] { +function getKeyValueOfObjectList(obj): {key: string; value: any}[] { const kvArr = []; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { kvArr.push({ key, value: obj[key] - }) + }); } } return kvArr; @@ -213,8 +213,8 @@ function handleErrorStrategyPass(el: HTMLElement): void { } function getFormControlUID(el: HTMLElement): string { - if(el.tagName.toLocaleLowerCase() === 'body') return ''; - let uid = '' + if(el.tagName.toLocaleLowerCase() === 'body') {return '';} + let uid = ''; if(el.parentElement.id.startsWith('dfc-')) { return el.parentElement.id; }else { @@ -233,7 +233,7 @@ function handleValidateError({el, tipEl, message = '', isFormTag, messageShowTyp if(!dfcUID) { dfcUID = getFormControlUID(el); } - + // messageShowType为popover时,设置popover if(MessageShowTypeEnum.popover === messageShowType) { EventBus.emit('showPopoverErrorMessage', {showPopover: true, message, uid: dfcUID, popPosition, updateOn} as ShowPopoverErrorMessageEventData); @@ -271,7 +271,7 @@ function validateFn({validator, modelValue, el, tipEl, isFormTag, messageShowTyp handleValidatePass(el, tipEl); }).catch((err) => { const { errors } = err; - if(!errors || errors.length === 0) return; + if(!errors || errors.length === 0) {return;} let msg = ''; // todo: 待支持国际化 @@ -282,7 +282,7 @@ function validateFn({validator, modelValue, el, tipEl, isFormTag, messageShowTyp } handleValidateError({el, tipEl, message: msg, isFormTag, messageShowType, dfcUID, popPosition, updateOn}); - }) + }); } // 检测popover的position是否是正确值 @@ -290,7 +290,7 @@ function checkValidPopsition(positionStr: string): boolean { const validPosition = ['left', 'right', 'top', 'bottom', 'left-top', 'left-bottom', 'top-left', 'top-right', 'right-top', 'right-bottom', 'bottom-left', 'bottom-right']; const isValid = validPosition.includes(positionStr); !isValid && console.warn(`invalid popPosition value '${positionStr}'.`); - return isValid + return isValid; } export default { @@ -302,9 +302,9 @@ export default { const hasOptions = isObject(binding.value) && hasKey(binding.value, 'options'); // 获取指令绑定的值 - let { - rules: bindingRules, - options = {}, + let { + rules: bindingRules, + options = {}, messageShowType = MessageShowTypeEnum.popover }: DirectiveBindingValue = binding.value; let { errorStrategy }: DirectiveBindingValue = binding.value; @@ -315,9 +315,9 @@ export default { } // errorStrategy可配置在options对象中 - let { - updateOn = UpdateOnEnum.change, - errorStrategy: ErrorStrategy = ErrorStrategyEnum.dirty, + let { + updateOn = UpdateOnEnum.change, + errorStrategy: ErrorStrategy = ErrorStrategyEnum.dirty, asyncDebounceTime = 300, popPosition = ['right', 'bottom'] }: DirectiveValidateRuleOptions = options; @@ -341,13 +341,13 @@ export default { // 判断是否有options,有就取binding.value对象中的rules对象,再判断有没有rules对象,没有就取binding.value let customRule: Partial<DirectiveCustomRuleItem> | DirectiveBindingValue = {}; if(hasOptions) { - customRule = bindingRules ?? binding.value + customRule = bindingRules ?? binding.value; }else { - customRule = binding.value as DirectiveBindingValue + customRule = binding.value as DirectiveBindingValue; } const isCustomValidator = customRule && isObject(customRule) && (hasKey(customRule, 'validators') || hasKey(customRule, 'asyncValidators')); - + const rules = Array.isArray(customRule) ? customRule : [customRule]; const tipEl = document.createElement('span'); @@ -381,7 +381,7 @@ export default { const ruleObj: Partial<CustomValidatorRuleObject> = { message: item?.message || '', validator: (rule, value) => item.validator(rule, value), - } + }; descriptor.modelName.push(ruleObj); }); @@ -397,9 +397,9 @@ export default { }else { reject(rule.message); } - }, asyncDebounceTime)) - }, - } + }, asyncDebounceTime)); + }, + }; descriptor.modelName.push(ruleObj); }); } @@ -413,16 +413,16 @@ export default { EventBus.emit('showPopoverErrorMessage', {showPopover: false, message: '', uid: dfcUID, popPosition, updateOn} as ShowPopoverErrorMessageEventData); } validateFn({validator, modelValue, el, tipEl, isFormTag: false, messageShowType, dfcUID, popPosition, updateOn}); - } + }; // 监听事件验证 - vnode.children[0].el.addEventListener(updateOn, htmlEventValidateHandler); + vnode.children[0].el.addEventListener(updateOn, htmlEventValidateHandler); // 如果校验时机为change,则在focus时关闭popover if(messageShowType === MessageShowTypeEnum.popover && updateOn === UpdateOnEnum.change) { vnode.children[0].el.addEventListener('focus', () => { EventBus.emit('showPopoverErrorMessage', {showPopover: false, uid: dfcUID, updateOn} as ShowPopoverErrorMessageEventData); - }); + }); } // 设置errorStrategy @@ -436,10 +436,10 @@ export default { // 处理表单提交验证 formName && EventBus.on(`formSubmit:${formName}`, () => { const modelValue = isFormTag ? '' : vnode.children[0].el.value; - + // 进行提交验证 validateFn({validator, modelValue, el, tipEl, isFormTag, messageShowType, updateOn: 'submit'}); }); - + } -} +}; diff --git a/packages/devui-vue/devui/form/src/directive/d-validate.ts b/packages/devui-vue/devui/form/src/directive/d-validate.ts index 76d5e03e96..34c66c8d0e 100644 --- a/packages/devui-vue/devui/form/src/directive/d-validate.ts +++ b/packages/devui-vue/devui/form/src/directive/d-validate.ts @@ -7,40 +7,40 @@ import {DFormValidateSubmitData, positionType} from '../form-types'; import './style.scss'; interface BindingValueRules { - [prop:string]: unknown + [prop: string]: unknown; } interface BindingValue { - prop: string - modelName?: string - rules: BindingValueRules - validators?: any - asyncValidators?: any - errorStrategy?: 'pristine' | 'dirty' - updateOn: 'change' | 'input' | 'submit' - asyncDebounceTime?: number | string - messageShowType?: 'popover' | 'text' | 'none' - popPosition: string | string[] - messageChange?: (msg, { errors, fields }) => {} - [prop: string]: any + prop: string; + modelName?: string; + rules: BindingValueRules; + validators?: any; + asyncValidators?: any; + errorStrategy?: 'pristine' | 'dirty'; + updateOn: 'change' | 'input' | 'submit'; + asyncDebounceTime?: number | string; + messageShowType?: 'popover' | 'text' | 'none'; + popPosition: string | string[]; + messageChange?: (msg, { errors, fields }) => {}; + [prop: string]: any; } const getTargetElement = (el: HTMLElement, targetTag: string) => { - if (!el) return; - let tempEl:HTMLElement = el; + if (!el) {return;} + let tempEl: HTMLElement = el; while(tempEl?.tagName && tempEl.tagName.toLocaleLowerCase() !== 'body') { if(tempEl.tagName.toLocaleLowerCase() === targetTag) { return tempEl; } tempEl = tempEl.parentElement; } -} +}; export default { mounted(el: HTMLElement, binding: DirectiveBinding): void { let { prop, rules, validators, asyncValidators, errorStrategy, updateOn = 'input', asyncDebounceTime = 300, messageShowType = 'popover', messageChange, popPosition = ['right', 'bottom'] }: BindingValue = binding.value; const {instance, arg: modelName} = binding; - + const instanceRef = instance[Object.keys(instance.$refs)[0]]; if(instanceRef && instanceRef?.messageShowType) { messageShowType = instanceRef.messageShowType; @@ -50,18 +50,18 @@ export default { const objToStyleString = (obj: any = {}) => { let style = ''; for (const key in obj) { - style += `${transformCamelToDash(key)}: ${obj[key]};` + style += `${transformCamelToDash(key)}: ${obj[key]};`; } return style; - } + }; const renderPopover = (msg, visible = true) => { - if(messageShowType !== 'popover') return; + if(messageShowType !== 'popover') {return;} el.style.position = 'relative'; const popoverPosition = () => { return Array.isArray(popPosition) ? popPosition.join('-') : popPosition; - } - + }; + const popover = h(dPopover, { visible: visible, controlled: updateOn !== 'change', @@ -73,22 +73,22 @@ export default { // 这里使用比较hack的方法控制popover显隐,因为点击popover外部元素隐藏popover之后,再重新传入visible不起作用了,popover不会重新渲染了 nextTick(() => { if(visible) { - addElClass(popover.el as HTMLElement, 'devui-popover-isVisible') + addElClass(popover.el as HTMLElement, 'devui-popover-isVisible'); }else { - removeElClass(popover.el as HTMLElement, 'devui-popover-isVisible') + removeElClass(popover.el as HTMLElement, 'devui-popover-isVisible'); } - }) + }); const popoverWrapperStyle = () => { - let rect = el.getBoundingClientRect(); - let style: any = { + const rect = el.getBoundingClientRect(); + const style: any = { position: 'absolute', height: 0, top: (rect.height / 2) + 'px', right: 0, - } + }; - let p = popoverPosition(); + const p = popoverPosition(); if(popPosition === 'bottom' || popPosition === 'top') { style.left = '50%'; } @@ -116,15 +116,15 @@ export default { if(p.startsWith('top')) { delete style.bottom; } - + return objToStyleString(style); }; - + const vn = h('div', { style: popoverWrapperStyle() - }, popover) + }, popover); render(vn, el); - } + }; const tipEl = document.createElement('div'); if(messageShowType === 'text') { @@ -135,7 +135,7 @@ export default { tipEl.innerText = msg; tipEl.style.display = visible ? 'block' : 'none'; tipEl.setAttribute('class', 'devui-validate-tip'); - } + }; const addElClass = (el: HTMLElement, className: string) => { let currentClasses = el.getAttribute('class'); @@ -143,16 +143,16 @@ export default { currentClasses = currentClasses.trim() + (currentClasses.trim() ? ' ' : '') + className; } el.setAttribute('class', currentClasses); - } + }; const removeElClass = (el: HTMLElement, className: string) => { let currentClasses = el.getAttribute('class'); currentClasses = currentClasses.replace(className, ''); el.setAttribute('class', currentClasses); - } + }; const {validate, createDevUIBuiltinValidator} = useValidate(); - let propRule = {} || [] as any; // 值为对象数组或单个对象 + const propRule = {} || [] as any; // 值为对象数组或单个对象 const isCustomValidator = validators !== undefined || asyncValidators !== undefined; if(isCustomValidator) { @@ -165,7 +165,7 @@ export default { time = 300; } rules = asyncValidators.map(item => { - let res = { + const res = { message: item.message, asyncValidator: (rule, value) => { return new Promise(debounce((resolve, reject) => { @@ -175,11 +175,11 @@ export default { }else { reject(rule.message); } - }, time)) - }, + }, time)); + }, } as any; return res; - }) + }); } }else { if(Array.isArray(rules)) { @@ -191,9 +191,9 @@ export default { } } - let descriptor: any = { + const descriptor: any = { [prop]: rules - } + }; const validateFn = async () => { const validateModel = { [prop]: hasModelName ? instance[modelName][prop] : instance[prop] @@ -204,7 +204,7 @@ export default { messageShowType === 'text' && renderTipEl('', true); return res; }).catch(({ errors, fields }) => { - let msg = propRule.message ?? fields[prop][0].message; + const msg = propRule.message ?? fields[prop][0].message; renderPopover(msg); addElClass(el, 'devui-error'); messageShowType === 'text' && renderTipEl(msg, true); @@ -212,19 +212,19 @@ export default { messageChange(msg, { errors, fields }); } return { errors, fields }; - }) - } + }); + }; if(errorStrategy === 'pristine') { validateFn(); }else { el.childNodes[0].addEventListener(updateOn, () => { validateFn(); - }) + }); if(updateOn === 'change') { el.childNodes[0].addEventListener('focus', () => { renderPopover('', false); - }) + }); } } @@ -256,4 +256,4 @@ export default { EventBus.off(`formSubmit:${formName}`); EventBus.off(`formReset:${formName}:${prop}`); } -} +}; diff --git a/packages/devui-vue/devui/form/src/form-control/form-control.tsx b/packages/devui-vue/devui/form/src/form-control/form-control.tsx index 90d6397b9c..9a514f5f4a 100644 --- a/packages/devui-vue/devui/form/src/form-control/form-control.tsx +++ b/packages/devui-vue/devui/form/src/form-control/form-control.tsx @@ -1,8 +1,8 @@ import { defineComponent, inject, ref, computed, reactive, onMounted, Teleport } from 'vue'; import { uniqueId } from 'lodash'; import { IForm, formControlProps, formInjectionKey } from '../form-types'; -import { ShowPopoverErrorMessageEventData } from '../directive/d-validate-rules' -import clickoutsideDirective from '../../../shared/devui-directive/clickoutside' +import { ShowPopoverErrorMessageEventData } from '../directive/d-validate-rules'; +import clickoutsideDirective from '../../../shared/devui-directive/clickoutside'; import { EventBus, getElOffset } from '../util'; import Icon from '../../../icon/src/icon'; import Popover from '../../../popover/src/popover'; @@ -33,7 +33,7 @@ export default defineComponent({ let elOffset = { left: 0, top: 0 - } + }; let popoverLeftPosition = 0 ; let popoverTopPosition = 0 ; @@ -55,22 +55,22 @@ export default defineComponent({ const iconData = computed(() => { switch (props.feedbackStatus) { - case 'pending': - return { name: 'priority', color: '#e9edfa' }; - case 'success': - return { name: 'right-o', color: 'rgb(61, 204, 166)' }; - case 'error': - return { name: 'error-o', color: 'rgb(249, 95, 91)' }; - default: - return { name: '', color: '' }; + case 'pending': + return { name: 'priority', color: '#e9edfa' }; + case 'success': + return { name: 'right-o', color: 'rgb(61, 204, 166)' }; + case 'error': + return { name: 'error-o', color: 'rgb(249, 95, 91)' }; + default: + return { name: '', color: '' }; } - }) + }); const handleClickOutside = () => { if(updateOn.value !== 'change') { showPopover.value = false; } - } + }; return () => { const { @@ -78,7 +78,7 @@ export default defineComponent({ extraInfo, } = props; return <div class="devui-form-control" ref={formControl} data-uid={uid} v-clickoutside={handleClickOutside}> - { showPopover.value && + { showPopover.value && <Teleport to="body"> <div style={{ position: 'absolute', @@ -103,7 +103,7 @@ export default defineComponent({ } </div> {extraInfo && <div class="devui-form-control-extra-info">{extraInfo}</div>} - </div> - } + </div>; + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/form/src/form-item/form-item.tsx b/packages/devui-vue/devui/form/src/form-item/form-item.tsx index 5e49d25cbe..88c66b75bd 100644 --- a/packages/devui-vue/devui/form/src/form-item/form-item.tsx +++ b/packages/devui-vue/devui/form/src/form-item/form-item.tsx @@ -16,21 +16,21 @@ export default defineComponent({ const initFormItemData = formData[props.prop]; const labelData = reactive(dForm.labelData); const rules = reactive(dForm.rules); - + const resetField = () => { if(Array.isArray(initFormItemData)) { formData[props.prop] = [...initFormItemData]; }else { formData[props.prop] = initFormItemData; } - } + }; const formItem = reactive({ dHasFeedback: props.dHasFeedback, prop: props.prop, formItemMitt, - resetField - }) + resetField + }); provide(formItemInjectionKey, formItem); const isHorizontal = labelData.layout === 'horizontal'; @@ -42,12 +42,12 @@ export default defineComponent({ const validate = (trigger: string) => { // console.log('trigger', trigger); - + const ruleKey = props.prop; const ruleItem = rules[ruleKey]; const descriptor: Rules = {}; descriptor[ruleKey] = ruleItem; - + const validator = new AsyncValidator(descriptor); validator.validate({[ruleKey]: formData[ruleKey]}).then(() => { @@ -58,7 +58,7 @@ export default defineComponent({ showMessage.value = true; tipMessage.value = errors[0].message; }); - } + }; const validateEvents = []; const addValidateEvents = () => { @@ -79,7 +79,7 @@ export default defineComponent({ ruleItem && formItem.formItemMitt.on(dFormItemEvents[eventName], cb); } } - } + }; const removeValidateEvents = () => { if(rules && rules[props.prop] && validateEvents.length > 0) { @@ -87,7 +87,7 @@ export default defineComponent({ formItem.formItemMitt.off(item.eventName, item.cb); }); } - } + }; onMounted(() => { dForm.formMitt.emit(dFormEvents.addField, formItem); @@ -104,7 +104,7 @@ export default defineComponent({ {ctx.slots.default?.()} <div class={`devui-validate-tip${isHorizontal ? ' devui-validate-tip-horizontal' : ''}`}>{showMessage.value && tipMessage.value}</div> </div> - ) - } + ); + }; }, -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/form/src/form-label/form-label.tsx b/packages/devui-vue/devui/form/src/form-label/form-label.tsx index c1b4ec755c..abd9ccafde 100644 --- a/packages/devui-vue/devui/form/src/form-label/form-label.tsx +++ b/packages/devui-vue/devui/form/src/form-label/form-label.tsx @@ -16,15 +16,15 @@ export default defineComponent({ const isSm = computed(() => labelData.labelSize === 'sm').value; const isCenter = computed(() => labelData.labelAlign === 'center').value; const isEnd = computed(() => labelData.labelAlign === 'end').value; - + const wrapperCls = `devui-form-label${isHorizontal ? (isSm ? ' devui-form-label_sm' : (isLg ? ' devui-form-label_lg' : ' devui-form-label_sd')) : ''}${isCenter ? ' devui-form-label_center' : (isEnd ? ' devui-form-label_end' : '')}`; const className = `${props.required ? ' devui-required' : ''}`; const style = {display: isHorizontal ? 'inline' : 'inline-block'}; - + return () => { return <span class={wrapperCls} style={style}> <span class={className} > - {ctx.slots.default?.()} + {ctx.slots.default?.()} { props.hasHelp && props.helpTips && ( <Popover content={props.helpTips} showAnimation={false} position={'top'} trigger={'hover'} v-slots={{ @@ -38,7 +38,7 @@ export default defineComponent({ ) } </span> - </span> - } + </span>; + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/form/src/form-operation/form-operation.tsx b/packages/devui-vue/devui/form/src/form-operation/form-operation.tsx index f9da081ffa..f31e68b5f1 100644 --- a/packages/devui-vue/devui/form/src/form-operation/form-operation.tsx +++ b/packages/devui-vue/devui/form/src/form-operation/form-operation.tsx @@ -4,13 +4,13 @@ import './form-operation.scss'; export default defineComponent({ name: 'DFormOperation', props: { - + }, setup(props, ctx) { return () => { return <div class="devui-form-operation"> {ctx.slots.default?.()} - </div> - } + </div>; + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/form/src/form-types.ts b/packages/devui-vue/devui/form/src/form-types.ts index fb09461b8c..db5d54f051 100644 --- a/packages/devui-vue/devui/form/src/form-types.ts +++ b/packages/devui-vue/devui/form/src/form-types.ts @@ -1,5 +1,5 @@ -import { Emitter } from 'mitt' -import type { PropType, ExtractPropTypes, InjectionKey, Ref } from 'vue' +import { Emitter } from 'mitt'; +import type { PropType, ExtractPropTypes, InjectionKey, Ref } from 'vue'; export const formProps = { formData: { @@ -8,33 +8,33 @@ export const formProps = { }, layout: { type: String as PropType<'horizontal' | 'vertical' | 'columns'>, - default: 'horizontal', + default: 'horizontal', }, labelSize: { type: String as PropType<'sm' | '' | 'lg'>, - default: '', + default: '', }, labelAlign: { type: String as PropType<'start' | 'center' | 'end'>, - default: 'start', + default: 'start', }, rules: { type: Object, - default: {}, + default: {}, }, columnsClass: { type: String as PropType<'u-1-3'>, - default: '', + default: '', }, name: { type: String, - default: '', + default: '', }, messageShowType: { type: String as PropType<'popover' | 'text' | 'toast' | 'none'>, - default: 'popover', + default: 'popover', }, -} as const +} as const; export const formItemProps = { dHasFeedback: { @@ -45,7 +45,7 @@ export const formItemProps = { type: String, default: '' } -} as const +} as const; export const formLabelProps = { required: { @@ -60,7 +60,7 @@ export const formLabelProps = { type: String, default: '' } -} as const +} as const; export const formControlProps = { feedbackStatus: { @@ -71,18 +71,18 @@ export const formControlProps = { type: String, default: '' } -} as const +} as const; export const dFormEvents = { addField: 'd.form.addField', removeField: 'd.form.removeField', -} as const +} as const; type LabelData = { - layout: string - labelSize: string - labelAlign: string -} + layout: string; + labelSize: string; + labelAlign: string; +}; export const formInjectionKey: InjectionKey<IForm> = Symbol('dForm'); export const formItemInjectionKey: InjectionKey<IFormItem> = Symbol('dFormItem'); @@ -91,54 +91,54 @@ export const dFormItemEvents = { blur: 'd.form.blur', change: 'd.form.change', input: 'd.form.input', -} as const +} as const; export interface IForm { - formData: any - labelData: IFormLabel - formMitt: Emitter<any> - rules: any - columnsClass: string - messageShowType: string -} + formData: any; + labelData: IFormLabel; + formMitt: Emitter<any>; + rules: any; + columnsClass: string; + messageShowType: string; +} export interface IFormLabel { - layout: string - labelSize: string - labelAlign: string + layout: string; + labelSize: string; + labelAlign: string; } export interface IFormItem { - dHasFeedback: boolean - prop: string - formItemMitt: Emitter<any> - resetField(): void + dHasFeedback: boolean; + prop: string; + formItemMitt: Emitter<any>; + resetField(): void; } export interface IFormControl { - feedbackStatus: string - extraInfo: string - formItemMitt: Emitter<any> - resetField(): void + feedbackStatus: string; + extraInfo: string; + formItemMitt: Emitter<any>; + resetField(): void; } -export type FormProps = ExtractPropTypes<typeof formProps> -export type FormItemProps = ExtractPropTypes<typeof formItemProps> -export type FormLabelProps = ExtractPropTypes<typeof formLabelProps> -export type FormControlProps = ExtractPropTypes<typeof formControlProps> +export type FormProps = ExtractPropTypes<typeof formProps>; +export type FormItemProps = ExtractPropTypes<typeof formItemProps>; +export type FormLabelProps = ExtractPropTypes<typeof formLabelProps>; +export type FormControlProps = ExtractPropTypes<typeof formControlProps>; export interface IValidators { - required: boolean - minlength: number - maxlength: number - min: number - max: number - requiredTrue: boolean - email: boolean - pattern: RegExp - whiteSpace: boolean + required: boolean; + minlength: number; + maxlength: number; + min: number; + max: number; + requiredTrue: boolean; + email: boolean; + pattern: RegExp; + whiteSpace: boolean; } const Validators: IValidators = { @@ -151,7 +151,7 @@ const Validators: IValidators = { email: false, pattern: undefined, whiteSpace: false -} +}; export const dDefaultValidators = { 'required': Validators.required, // 配置不能为空限制,rule中使用:{ required: true } @@ -166,13 +166,13 @@ export const dDefaultValidators = { }; -export type positionType = 'top' | 'right' | 'bottom' | 'left' | 'left-top' | 'left-bottom' | 'top-left' | 'top-right' | 'right-top' | 'right-bottom' | 'bottom-left' | 'bottom-right' +export type positionType = 'top' | 'right' | 'bottom' | 'left' | 'left-top' | 'left-bottom' | 'top-left' | 'top-right' | 'right-top' | 'right-bottom' | 'bottom-left' | 'bottom-right'; export interface DValidateResult { - errors: any - fields: any + errors: any; + fields: any; } export interface DFormValidateSubmitData { - callback(valid: boolean, result: DValidateResult): void + callback(valid: boolean, result: DValidateResult): void; } diff --git a/packages/devui-vue/devui/form/src/form.tsx b/packages/devui-vue/devui/form/src/form.tsx index 5eb73f8009..dc01d02c17 100644 --- a/packages/devui-vue/devui/form/src/form.tsx +++ b/packages/devui-vue/devui/form/src/form.tsx @@ -1,9 +1,9 @@ -import { defineComponent, provide } from 'vue' -import mitt from 'mitt' -import { formProps, FormProps, IFormItem, dFormEvents, formInjectionKey, IForm } from './form-types' -import { EventBus } from './util' -import './form.scss' +import { defineComponent, provide } from 'vue'; +import mitt from 'mitt'; +import { formProps, FormProps, IFormItem, dFormEvents, formInjectionKey, IForm } from './form-types'; +import { EventBus } from './util'; +import './form.scss'; export default defineComponent({ @@ -16,21 +16,21 @@ export default defineComponent({ const resetFormFields = () => { fields.forEach((field: IFormItem) => { field.resetField(); - }) - } + }); + }; formMitt.on(dFormEvents.addField, (field: any) => { if(field) { fields.push(field); } - }) + }); formMitt.on(dFormEvents.removeField, (field: any) => { if(field.prop) { fields.splice(fields.indexOf(field), 1); } - }) - + }); + provide(formInjectionKey, { formData: props.formData, formMitt, @@ -48,14 +48,14 @@ export default defineComponent({ e.preventDefault(); ctx.emit('submit', e); EventBus.emit(`formSubmit:${props.name}`); - } - + }; + return { fields, formMitt, onSubmit, resetFormFields - } + }; }, render() { const {onSubmit} = this; @@ -65,4 +65,4 @@ export default defineComponent({ </form> ); } -}) +}); diff --git a/packages/devui-vue/devui/form/src/use-validate.ts b/packages/devui-vue/devui/form/src/use-validate.ts index 62c01d5bda..e4722d20bd 100644 --- a/packages/devui-vue/devui/form/src/use-validate.ts +++ b/packages/devui-vue/devui/form/src/use-validate.ts @@ -1,12 +1,12 @@ import AsyncValidator from 'async-validator'; export default function useValidate() { - + // 校验函数 const validate = (descriptor, validateObject) => { const validator = new AsyncValidator(descriptor); return validator.validate(validateObject); - } + }; // 创建内置校验器 const createDevUIBuiltinValidator = (rule) => { @@ -22,11 +22,11 @@ export default function useValidate() { }else { resolve('校验通过'); } - }) + }); } - } + }; } - + if(res.max !== undefined) { res = { ...res, @@ -38,9 +38,9 @@ export default function useValidate() { }else { resolve('校验通过'); } - }) + }); } - } + }; } if(res.maxlength !== undefined) { @@ -48,7 +48,7 @@ export default function useValidate() { ...res, max: res.maxlength, message: res.message ?? `最大长度为${res.maxlength}` - } + }; delete res.maxlength; delete res.asyncValidator; } @@ -58,7 +58,7 @@ export default function useValidate() { ...res, min: res.minlength, message: res.message ?? `最小长度为${res.minlength}` - } + }; delete res.minlength; delete res.asyncValidator; } @@ -75,16 +75,16 @@ export default function useValidate() { }else { resolve('校验通过'); } - }) + }); } - } + }; } if(res.email !== undefined){ res = { ...res, type: 'email', message: res.message ?? '邮箱格式不正确' - } + }; delete res.asyncValidator; } if(res.pattern !== undefined){ @@ -92,7 +92,7 @@ export default function useValidate() { ...res, type: 'pattern', message: res.message ?? '正则不匹配' - } + }; delete res.asyncValidator; } if(res.whitespace === true){ @@ -107,13 +107,13 @@ export default function useValidate() { }else { resolve('校验通过'); } - }) + }); } - } + }; } return res; - } + }; return {validate, createDevUIBuiltinValidator}; } diff --git a/packages/devui-vue/devui/form/src/util/event-bus.ts b/packages/devui-vue/devui/form/src/util/event-bus.ts index 3411bb73f8..907d3b626b 100644 --- a/packages/devui-vue/devui/form/src/util/event-bus.ts +++ b/packages/devui-vue/devui/form/src/util/event-bus.ts @@ -1,3 +1,3 @@ import mitt from 'mitt'; -export default mitt(); \ No newline at end of file +export default mitt(); diff --git a/packages/devui-vue/devui/form/src/util/index.ts b/packages/devui-vue/devui/form/src/util/index.ts index f388442618..95fb40c1ae 100644 --- a/packages/devui-vue/devui/form/src/util/index.ts +++ b/packages/devui-vue/devui/form/src/util/index.ts @@ -1,5 +1,5 @@ -import eventBus from './event-bus' +import eventBus from './event-bus'; export const EventBus = eventBus; export function isObject(obj: any): boolean { @@ -7,7 +7,7 @@ export function isObject(obj: any): boolean { } export function hasKey(obj: any, key: string | number | symbol): boolean { - if (!isObject(obj)) return false; + if (!isObject(obj)) {return false;} return Object.prototype.hasOwnProperty.call(obj, key); } @@ -15,24 +15,24 @@ export function getElOffset(curEl: HTMLElement) { let totalLeft = 0; let totalTop = 0; let par: Partial<HTMLElement> = curEl.offsetParent; - //首先把自己本身的相加 + // 首先把自己本身的相加 totalLeft += curEl.offsetLeft; totalTop += curEl.offsetTop; - //现在开始一级一级往上查找,只要没有遇到body,把父级参照物的边框和偏移相加 + // 现在开始一级一级往上查找,只要没有遇到body,把父级参照物的边框和偏移相加 while (par){ - if (navigator.userAgent.indexOf('MSIE 8.0') === -1){ //不是IE8才进行累加父级参照物的边框 - totalTop += par.clientTop; - totalLeft += par.clientLeft; - } - totalTop += par.offsetTop; - totalLeft += par.offsetLeft; - par = par.offsetParent; + if (navigator.userAgent.indexOf('MSIE 8.0') === -1){ // 不是IE8才进行累加父级参照物的边框 + totalTop += par.clientTop; + totalLeft += par.clientLeft; + } + totalTop += par.offsetTop; + totalLeft += par.offsetLeft; + par = par.offsetParent; } return {left: totalLeft, top: totalTop}; } // 将驼峰转化为中间连接符 -export function transformCamelToDash(str: string = '') { +export function transformCamelToDash(str = '') { let res = ''; for(let i = 0; i < str.length; i++) { if(/[A-Z]/.test(str[i])) { diff --git a/packages/devui-vue/devui/fullscreen/__tests__/fullscreen.spec.ts b/packages/devui-vue/devui/fullscreen/__tests__/fullscreen.spec.ts index e8ed761ea3..85ce243629 100644 --- a/packages/devui-vue/devui/fullscreen/__tests__/fullscreen.spec.ts +++ b/packages/devui-vue/devui/fullscreen/__tests__/fullscreen.spec.ts @@ -1,8 +1,8 @@ -import { mount, VueWrapper } from '@vue/test-utils' -import { ref, nextTick } from 'vue' +import { mount, VueWrapper } from '@vue/test-utils'; +import { ref, nextTick } from 'vue'; describe('fullscreen', () => { - let wrapper: VueWrapper<any> + let wrapper: VueWrapper<any>; beforeEach(() => { wrapper = mount({ @@ -14,40 +14,40 @@ describe('fullscreen', () => { </d-fullscreen> `, setup() { - const btnContent = ref('FullScreen') + const btnContent = ref('FullScreen'); const fullscreenLaunch = (val) => { if (val) { - btnContent.value = 'Exit' + btnContent.value = 'Exit'; } else { - btnContent.value = 'FullScreen' + btnContent.value = 'FullScreen'; } - } + }; return { btnContent, fullscreenLaunch - } + }; } - }) - }) + }); + }); // 样式判断 it('judge html class correctly', async () => { // 初始样式 - expect(document.getElementsByTagName('html')[0].classList.value).toEqual('') + expect(document.getElementsByTagName('html')[0].classList.value).toEqual(''); // 点击之后,增加class - await wrapper.find('[test]').trigger('click') - await nextTick() - expect(document.getElementsByTagName('html')[0].classList.value).not.toContain('devui-fullscreen') - + await wrapper.find('[test]').trigger('click'); + await nextTick(); + expect(document.getElementsByTagName('html')[0].classList.value).not.toContain('devui-fullscreen'); + // 再次点击,删除class - await wrapper.find('[test]').trigger('click') - await nextTick() - expect(document.getElementsByTagName('html')[0].classList.value).toEqual('') - }) + await wrapper.find('[test]').trigger('click'); + await nextTick(); + expect(document.getElementsByTagName('html')[0].classList.value).toEqual(''); + }); // 判断属性 it('attr', () => { - expect(wrapper.attributes('mode')).toBe('normal') - }) -}) \ No newline at end of file + expect(wrapper.attributes('mode')).toBe('normal'); + }); +}); diff --git a/packages/devui-vue/devui/fullscreen/index.ts b/packages/devui-vue/devui/fullscreen/index.ts index 49214f0fec..f231d15afc 100644 --- a/packages/devui-vue/devui/fullscreen/index.ts +++ b/packages/devui-vue/devui/fullscreen/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Fullscreen from './src/fullscreen' +import type { App } from 'vue'; +import Fullscreen from './src/fullscreen'; Fullscreen.install = function(app: App): void { - app.component(Fullscreen.name, Fullscreen) -} + app.component(Fullscreen.name, Fullscreen); +}; -export { Fullscreen } +export { Fullscreen }; export default { title: 'Fullscreen 全屏', category: '通用', status: '100%', install(app: App): void { - app.use(Fullscreen as any) + app.use(Fullscreen as any); } -} +}; diff --git a/packages/devui-vue/devui/fullscreen/src/composables/use-fullscreen.ts b/packages/devui-vue/devui/fullscreen/src/composables/use-fullscreen.ts index 798ed9001d..f44e0a197b 100644 --- a/packages/devui-vue/devui/fullscreen/src/composables/use-fullscreen.ts +++ b/packages/devui-vue/devui/fullscreen/src/composables/use-fullscreen.ts @@ -20,7 +20,7 @@ export default function useFullscreen(props, slotElement, ctx) { if (mode.value === 'immersive') { handleImmersiveFullscreen(newVal); } - }) + }); const handleNormalFullscreen = (isOpen) => { if (isOpen) { @@ -30,7 +30,7 @@ export default function useFullscreen(props, slotElement, ctx) { exitNormalFullscreen(slotElement.value); removeFullScreenStyle(); } - } + }; const handleImmersiveFullscreen = (isOpen) => { if (isOpen) { @@ -40,7 +40,7 @@ export default function useFullscreen(props, slotElement, ctx) { exitImmersiveFullScreen(document); } } - } + }; const handleFullscreenChange = () => { if (!document.fullscreenElement) { @@ -50,7 +50,7 @@ export default function useFullscreen(props, slotElement, ctx) { } else { exitByKeydown = false; } - } + }; onMounted(() => { document.addEventListener('fullscreenchange', handleFullscreenChange); diff --git a/packages/devui-vue/devui/fullscreen/src/composables/use-keydown.ts b/packages/devui-vue/devui/fullscreen/src/composables/use-keydown.ts index c6a5ffc850..25cee30c69 100644 --- a/packages/devui-vue/devui/fullscreen/src/composables/use-keydown.ts +++ b/packages/devui-vue/devui/fullscreen/src/composables/use-keydown.ts @@ -9,7 +9,7 @@ export default function useKeydown(props, ctx) { if (event.keyCode === ESC_KEY_CODE && modelValue) { ctx.emit('update:modelValue', false); } - } + }; onMounted(() => { document.addEventListener('keydown', handleKeydown); diff --git a/packages/devui-vue/devui/fullscreen/src/fullscreen-types.ts b/packages/devui-vue/devui/fullscreen/src/fullscreen-types.ts index d60e50b227..6ec5a0eb6b 100644 --- a/packages/devui-vue/devui/fullscreen/src/fullscreen-types.ts +++ b/packages/devui-vue/devui/fullscreen/src/fullscreen-types.ts @@ -1,6 +1,6 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; -type ModeType = PropType<'normal' | 'immersive'> +type ModeType = PropType<'normal' | 'immersive'>; export const fullscreenProps = { modelValue: { type: Boolean, @@ -14,6 +14,6 @@ export const fullscreenProps = { type: Number, default: 10 } -} as const +} as const; -export type FullscreenProps = ExtractPropTypes<typeof fullscreenProps> +export type FullscreenProps = ExtractPropTypes<typeof fullscreenProps>; diff --git a/packages/devui-vue/devui/gantt/__tests__/gantt.spec.ts b/packages/devui-vue/devui/gantt/__tests__/gantt.spec.ts index 321977ee72..1db9cffc7e 100644 --- a/packages/devui-vue/devui/gantt/__tests__/gantt.spec.ts +++ b/packages/devui-vue/devui/gantt/__tests__/gantt.spec.ts @@ -4,5 +4,5 @@ import { Gantt } from '../index'; describe('gantt test', () => { it('gantt init render', async () => { // todo - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/gantt/index.ts b/packages/devui-vue/devui/gantt/index.ts index 4f79701c05..cb901ad590 100644 --- a/packages/devui-vue/devui/gantt/index.ts +++ b/packages/devui-vue/devui/gantt/index.ts @@ -1,21 +1,21 @@ -import type { App } from 'vue' -import Gantt from './src/gantt' -import GanttTools from './src/gantt-tools' -import ganttMarkerDirective from './src/gantt-scale/gantt-marker-directive' +import type { App } from 'vue'; +import Gantt from './src/gantt'; +import GanttTools from './src/gantt-tools'; +import ganttMarkerDirective from './src/gantt-scale/gantt-marker-directive'; Gantt.install = function (app: App): void { - app.component(Gantt.name, Gantt) - app.component(GanttTools.name, GanttTools) - app.directive('gantt-marker', ganttMarkerDirective) -} + app.component(Gantt.name, Gantt); + app.component(GanttTools.name, GanttTools); + app.directive('gantt-marker', ganttMarkerDirective); +}; -export { Gantt } +export { Gantt }; export default { title: 'Gantt 甘特图', category: '数据展示', status: '10%', // TODO: 组件若开发完成则填入"已完成",并删除该注释 install(app: App): void { - app.use(Gantt as any) + app.use(Gantt as any); }, -} +}; diff --git a/packages/devui-vue/devui/gantt/src/gantt-bar-parent/index.tsx b/packages/devui-vue/devui/gantt/src/gantt-bar-parent/index.tsx index ae31182b29..9d8cf40efd 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-bar-parent/index.tsx +++ b/packages/devui-vue/devui/gantt/src/gantt-bar-parent/index.tsx @@ -1,154 +1,154 @@ import {defineComponent , ref , toRefs } from 'vue'; -import {GanttService} from '../gantt-service' +import {GanttService} from '../gantt-service'; import { Subscription } from 'rxjs'; // import { GanttProps } from '../gantt-types' import './gantt-bar-parent.scss'; -const ganttService = new GanttService() +const ganttService = new GanttService(); export default defineComponent({ - name:'DGanttBarParent', - props:{ - // 开始时间 - startDate:{ - type:Date, - }, - // 结束时间 - endDate:{ - type:Date - }, - // 进度 - progressRate:{ - type:Number, - default:0 - }, - data:{}, - id:{ - type:String, - }, - tip:{ - type:String, - }, - ganttScaleStatusHandler:{ - type:Subscription - } + name:'DGanttBarParent', + props:{ + // 开始时间 + startDate:{ + type:Date, + }, + // 结束时间 + endDate:{ + type:Date + }, + // 进度 + progressRate:{ + type:Number, + default:0 }, - setup(props){ - const {startDate,endDate,data,id,tip } = toRefs(props) - let { progressRate, ganttScaleStatusHandler } = toRefs(props) - // const ganttScaleStatusHandler:Subscription = ref<Subscription>() - const tipHovered = ref(false) - const percentage = ref(0) - let left = ref(0) - let width = ref(0) - const max = 100 - const min = 0 - let duration = ref('') + data:{}, + id:{ + type:String, + }, + tip:{ + type:String, + }, + ganttScaleStatusHandler:{ + type:Subscription + } + }, + setup(props){ + const {startDate,endDate,data,id,tip } = toRefs(props); + let { progressRate, ganttScaleStatusHandler } = toRefs(props); + // const ganttScaleStatusHandler:Subscription = ref<Subscription>() + const tipHovered = ref(false); + const percentage = ref(0); + let left = ref(0); + let width = ref(0); + const max = 100; + const min = 0; + let duration = ref(''); - const setValue = (value: number | null): void => { - if (progressRate !== value) { - progressRate = value; - updateTrackAndHandle(); - } - } - const ensureValueInRange = (value: number | null): number => { - let safeValue; - if (!valueMustBeValid(value)) { - safeValue = min; - } else { - safeValue = clamp(min, value as number, max); - } - return safeValue; - } - const valueMustBeValid = (value: number): boolean => { - return !isNaN(typeof value !== 'number' ? parseFloat(value) : value); - } - const clamp = (min: number, n: number, max: number) => { - return Math.max(min, Math.min(n, max)); - } - const updateTrackAndHandle = (): void => { - const value = progressRate; - const offset = valueToOffset(value); - updateStyle(offset / 100); - this.cdr.markForCheck(); - } - const valueToOffset = (value: number): number => { - return ((value - min.value) / (max.value - min.value)) * 100; - } - const updateStyle = (percentage) => { - percentage = Math.min(1, Math.max(0, percentage)); - if (this.ganttBarTrack && this.ganttBarTrack.nativeElement) { - this.ganttBarTrack.nativeElement.style.width = `${percentage * 100}%`; - } - - if (this.ganttBarProgress && this.ganttBarProgress.nativeElement) { - this.ganttBarProgress.nativeElement.style.left = `${percentage * 100}%`; - } + const setValue = (value: number | null): void => { + if (progressRate !== value) { + progressRate = value; + updateTrackAndHandle(); + } + }; + const ensureValueInRange = (value: number | null): number => { + let safeValue; + if (!valueMustBeValid(value)) { + safeValue = min; + } else { + safeValue = clamp(min, value as number, max); + } + return safeValue; + }; + const valueMustBeValid = (value: number): boolean => { + return !isNaN(typeof value !== 'number' ? parseFloat(value) : value); + }; + const clamp = (min: number, n: number, max: number) => { + return Math.max(min, Math.min(n, max)); + }; + const updateTrackAndHandle = (): void => { + const value = progressRate; + const offset = valueToOffset(value); + updateStyle(offset / 100); + this.cdr.markForCheck(); + }; + const valueToOffset = (value: number): number => { + return ((value - min.value) / (max.value - min.value)) * 100; + }; + const updateStyle = (percentage) => { + percentage = Math.min(1, Math.max(0, percentage)); + if (this.ganttBarTrack && this.ganttBarTrack.nativeElement) { + this.ganttBarTrack.nativeElement.style.width = `${percentage * 100}%`; + } + + if (this.ganttBarProgress && this.ganttBarProgress.nativeElement) { + this.ganttBarProgress.nativeElement.style.left = `${percentage * 100}%`; + } + }; + const onInit = () => { + if (progressRate === null) { + this.setValue(this.ensureValueInRange(null)); + } + + duration = ganttService.getDuration(startDate, endDate) + 'd'; + + ganttScaleStatusHandler = ganttService.ganttScaleConfigChange.subscribe((config) => { + if (config.startDate) { + left = ganttService.getDatePostionOffset(startDate); } - const onInit = () => { - if (progressRate === null) { - this.setValue(this.ensureValueInRange(null)); - } - - duration = ganttService.getDuration(startDate, endDate) + 'd'; - - ganttScaleStatusHandler = ganttService.ganttScaleConfigChange.subscribe((config) => { - if (config.startDate) { - left = ganttService.getDatePostionOffset(startDate); - } - if (config.unit) { - left = ganttService.getDatePostionOffset(startDate); - width = ganttService.getDurationWidth(startDate, endDate); - } - }) as Subscription; + if (config.unit) { + left = ganttService.getDatePostionOffset(startDate); + width = ganttService.getDurationWidth(startDate, endDate); } + }) as Subscription; + }; - const ngOnChanges = (changes) => { - if (changes['progressRate'] && progressRate > 0) { - updateTrackAndHandle(); - } - - if (changes['startDate']) { - left = ganttService.getDatePostionOffset(startDate); - width = ganttService.getDurationWidth(startDate, endDate); - } - - if (changes['endDate']) { - width = ganttService.getDurationWidth(startDate, endDate); - } - } + const ngOnChanges = (changes) => { + if (changes['progressRate'] && progressRate > 0) { + updateTrackAndHandle(); + } - const AfterViewInit = () => { - if (progressRate && progressRate > 0) { - updateTrackAndHandle(); - } - } + if (changes['startDate']) { + left = ganttService.getDatePostionOffset(startDate); + width = ganttService.getDurationWidth(startDate, endDate); + } - const OnDestroy= (): void => { - if (ganttScaleStatusHandler.value) { - ganttScaleStatusHandler.value.unsubscribe(); - ganttScaleStatusHandler = null; - } - } + if (changes['endDate']) { + width = ganttService.getDurationWidth(startDate, endDate); + } + }; - return { - left, - width - } - }, - render() { - const { - left, - width - } = this - const style = { - position:'', - left:left, - width:width - } - return ( - <div class="devui-gantt-bar-parent"> - <div class="devui-gantt-bar-rail"></div> - <div class="devui-gantt-bar-track"></div> - </div> - ) - }, -}) \ No newline at end of file + const AfterViewInit = () => { + if (progressRate && progressRate > 0) { + updateTrackAndHandle(); + } + }; + + const OnDestroy= (): void => { + if (ganttScaleStatusHandler.value) { + ganttScaleStatusHandler.value.unsubscribe(); + ganttScaleStatusHandler = null; + } + }; + + return { + left, + width + }; + }, + render() { + const { + left, + width + } = this; + const style = { + position:'', + left:left, + width:width + }; + return ( + <div class="devui-gantt-bar-parent"> + <div class="devui-gantt-bar-rail"></div> + <div class="devui-gantt-bar-track"></div> + </div> + ); + }, +}); diff --git a/packages/devui-vue/devui/gantt/src/gantt-bar/index.tsx b/packages/devui-vue/devui/gantt/src/gantt-bar/index.tsx index 8370cf8053..a80e261f91 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-bar/index.tsx +++ b/packages/devui-vue/devui/gantt/src/gantt-bar/index.tsx @@ -1,14 +1,14 @@ -import {defineComponent} from 'vue' +import {defineComponent} from 'vue'; -import './gantt-bar.scss' +import './gantt-bar.scss'; export default defineComponent({ - name:'GantBar', - props:{}, - render(){ - return ( - <div class="gantt-bar"></div> - ) - } -}) \ No newline at end of file + name:'GantBar', + props:{}, + render(){ + return ( + <div class="gantt-bar"></div> + ); + } +}); diff --git a/packages/devui-vue/devui/gantt/src/gantt-milestone/index.tsx b/packages/devui-vue/devui/gantt/src/gantt-milestone/index.tsx index 38aae3c74b..e61a75c1c7 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-milestone/index.tsx +++ b/packages/devui-vue/devui/gantt/src/gantt-milestone/index.tsx @@ -1,6 +1,6 @@ -import { defineComponent, ref } from 'vue' -import { MilestoneIcon } from './milestone-icon' -import './gantt-milestone.scss' +import { defineComponent, ref } from 'vue'; +import { MilestoneIcon } from './milestone-icon'; +import './gantt-milestone.scss'; export default defineComponent({ name: 'DGanttMilestone', @@ -19,7 +19,7 @@ export default defineComponent({ // todo }, render() { - const { title } = this + const { title } = this; return ( <div class="devui-gantt-milestone"> <span class="icon"> @@ -27,6 +27,6 @@ export default defineComponent({ </span> <span>{title}</span> </div> - ) + ); }, -}) +}); diff --git a/packages/devui-vue/devui/gantt/src/gantt-model.ts b/packages/devui-vue/devui/gantt/src/gantt-model.ts index 91b5456bd7..7b52532462 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-model.ts +++ b/packages/devui-vue/devui/gantt/src/gantt-model.ts @@ -1,17 +1,17 @@ export interface GanttScaleDateInfo { - dayOfMonthLabel: string - dayOfWeekLabel: string - monthLabel: string - yearLabel: string - date: Date - monthStart?: boolean - weekend?: boolean - today?: boolean - highlight?: boolean - highlightStart?: boolean - milestone?: string - scaleStartVisable?: boolean - index?: number + dayOfMonthLabel: string; + dayOfWeekLabel: string; + monthLabel: string; + yearLabel: string; + date: Date; + monthStart?: boolean; + weekend?: boolean; + today?: boolean; + highlight?: boolean; + highlightStart?: boolean; + milestone?: string; + scaleStartVisable?: boolean; + index?: number; } export enum GanttScaleUnit { @@ -20,15 +20,15 @@ export enum GanttScaleUnit { month = 'month', } export interface GanttBarStatus { - focused: boolean - startDate: Date - endDate: Date + focused: boolean; + startDate: Date; + endDate: Date; } export interface GanttScaleConfig { - startDate?: Date - endDate?: Date - unit?: GanttScaleUnit + startDate?: Date; + endDate?: Date; + unit?: GanttScaleUnit; } export enum GanttMarkerType { @@ -38,20 +38,20 @@ export enum GanttMarkerType { } export interface GanttMilestone { - date: Date - lable: string + date: Date; + lable: string; } export interface GanttTaskInfo { - id: string - startDate: Date - endDate: Date - title?: string - progress: string - duration: string - moveOffset?: number - left?: number - width?: number + id: string; + startDate: Date; + endDate: Date; + title?: string; + progress: string; + duration: string; + moveOffset?: number; + left?: number; + width?: number; } export enum UnitRole { diff --git a/packages/devui-vue/devui/gantt/src/gantt-scale/gantt-marker-directive.ts b/packages/devui-vue/devui/gantt/src/gantt-scale/gantt-marker-directive.ts index 9156a42a6d..50ece3f019 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-scale/gantt-marker-directive.ts +++ b/packages/devui-vue/devui/gantt/src/gantt-scale/gantt-marker-directive.ts @@ -1,16 +1,16 @@ -import { GanttScaleUnit } from '../gantt-model' +import { GanttScaleUnit } from '../gantt-model'; interface BindingType { value: { - ganttBarContainerElement: HTMLElement - ganttScaleContainerOffsetLeft: number - monthMark: boolean - weekend: boolean - today: boolean - milestone: string - unit: GanttScaleUnit - date: Date - last: boolean - } + ganttBarContainerElement: HTMLElement; + ganttScaleContainerOffsetLeft: number; + monthMark: boolean; + weekend: boolean; + today: boolean; + milestone: string; + unit: GanttScaleUnit; + date: Date; + last: boolean; + }; } const ganttMarkerDirective = { ganttBarContainerElement: null, @@ -20,19 +20,19 @@ const ganttMarkerDirective = { milestoneElement: null, monthMark: '', mounted(el: HTMLElement, binding: BindingType): void { - const { ganttBarContainerElement, monthMark } = binding.value + const { ganttBarContainerElement, monthMark } = binding.value; if (ganttBarContainerElement) { - this.ganttBarContainerElement = ganttBarContainerElement + this.ganttBarContainerElement = ganttBarContainerElement; } if (monthMark) { - this.monthMark = this.monthMark + this.monthMark = this.monthMark; } }, updated(el: HTMLElement, binding: BindingType): void { // todo - const { monthMark, weekend, today, milestone, unit } = binding.value + const { monthMark, weekend, today, milestone, unit } = binding.value; if (monthMark) { - this.initMarkElement() + this.initMarkElement(); } }, initMarkElement(): void { @@ -42,6 +42,6 @@ const ganttMarkerDirective = { } } }, -} +}; -export default ganttMarkerDirective +export default ganttMarkerDirective; diff --git a/packages/devui-vue/devui/gantt/src/gantt-scale/index.tsx b/packages/devui-vue/devui/gantt/src/gantt-scale/index.tsx index 00cb52decf..6d81aba5c6 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-scale/index.tsx +++ b/packages/devui-vue/devui/gantt/src/gantt-scale/index.tsx @@ -1,12 +1,12 @@ -import { defineComponent, ref, PropType, onMounted, toRefs, watch } from 'vue' -import './gantt-scale.scss' +import { defineComponent, ref, PropType, onMounted, toRefs, watch } from 'vue'; +import './gantt-scale.scss'; import { GanttScaleUnit, GanttMilestone, GanttScaleDateInfo, -} from '../gantt-model' -import { useScaleData } from './use-scale-data' -import { i18nText } from '../i18n-gantt' +} from '../gantt-model'; +import { useScaleData } from './use-scale-data'; +import { i18nText } from '../i18n-gantt'; export default defineComponent({ name: 'DGanttScale', props: { @@ -44,43 +44,43 @@ export default defineComponent({ emits: ['addMilestone'], setup(props, ctx) { const { startDate, endDate, milestoneList, scrollElement, unit } = - toRefs(props) - const scaleData = ref<GanttScaleDateInfo[]>([]) - const viewSCaleData = ref<GanttScaleDateInfo[]>([]) + toRefs(props); + const scaleData = ref<GanttScaleDateInfo[]>([]); + const viewSCaleData = ref<GanttScaleDateInfo[]>([]); const scaleWidth = ref({ day: 40, week: 30, month: 20, - }) - const highlight = ref(false) - const highlightStartText = ref('') - const highlightEndText = ref('') - const { generateScaleData } = useScaleData(milestoneList) - let viewScaleRange = [0, 0] + }); + const highlight = ref(false); + const highlightStartText = ref(''); + const highlightEndText = ref(''); + const { generateScaleData } = useScaleData(milestoneList); + let viewScaleRange = [0, 0]; const addMilestone = (info: GanttScaleDateInfo) => { - ctx.emit('addMilestone', info) - } + ctx.emit('addMilestone', info); + }; const getViewScaleData = () => { if (scrollElement.value) { - const containerWidth = scrollElement.value.clientWidth - const scrollLeft = scrollElement.value.scrollLeft + const containerWidth = scrollElement.value.clientWidth; + const scrollLeft = scrollElement.value.scrollLeft; - const start = Math.floor(scrollLeft / scaleWidth.value[unit.value]) - const offset = Math.ceil(containerWidth / scaleWidth.value[unit.value]) - viewScaleRange = [start - 2, start + offset + 2] + const start = Math.floor(scrollLeft / scaleWidth.value[unit.value]); + const offset = Math.ceil(containerWidth / scaleWidth.value[unit.value]); + viewScaleRange = [start - 2, start + offset + 2]; viewSCaleData.value = scaleData.value.filter( (i: GanttScaleDateInfo) => { - return i.index >= viewScaleRange[0] && i.index <= viewScaleRange[1] + return i.index >= viewScaleRange[0] && i.index <= viewScaleRange[1]; } - ) + ); } - } + }; onMounted(() => { if (startDate.value && endDate.value) { - scaleData.value = generateScaleData(startDate.value, endDate.value) - getViewScaleData() + scaleData.value = generateScaleData(startDate.value, endDate.value); + getViewScaleData(); } - }) + }); watch( () => props.scrollElement, @@ -89,11 +89,11 @@ export default defineComponent({ ;(props.scrollElement as HTMLDivElement).addEventListener( 'scroll', () => { - getViewScaleData() + getViewScaleData(); } - ) + ); } - ) + ); return { viewSCaleData, @@ -102,7 +102,7 @@ export default defineComponent({ highlight, highlightStartText, highlightEndText, - } + }; }, render() { const { @@ -114,7 +114,7 @@ export default defineComponent({ highlightStartText, highlightEndText, ganttBarContainerElement, - } = this + } = this; return ( <div class="devui-gantt-scale-wrapper"> {viewSCaleData.map((data, index) => ( @@ -143,9 +143,9 @@ export default defineComponent({ ? unit === 'month' ? i18nText.zh.yearDisplay(data.yearLabel) : i18nText.zh.yearAndMonthDisplay( - data.yearLabel, - data.monthLabel - ) + data.yearLabel, + data.monthLabel + ) : ''} </div> <div class="devui-scale-unit"> @@ -190,6 +190,6 @@ export default defineComponent({ </div> ))} </div> - ) + ); }, -}) +}); diff --git a/packages/devui-vue/devui/gantt/src/gantt-scale/use-scale-data.ts b/packages/devui-vue/devui/gantt/src/gantt-scale/use-scale-data.ts index 72f2f14c9f..d712915364 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-scale/use-scale-data.ts +++ b/packages/devui-vue/devui/gantt/src/gantt-scale/use-scale-data.ts @@ -1,13 +1,13 @@ -import { Ref } from 'vue' -import { GanttMilestone, GanttScaleDateInfo } from '../gantt-model' -import { isSameDate } from '../utils' +import { Ref } from 'vue'; +import { GanttMilestone, GanttScaleDateInfo } from '../gantt-model'; +import { isSameDate } from '../utils'; export const useScaleData = ( milestoneList: Ref<GanttMilestone[]> ): { - generateScaleData: (startDate: Date, endDate: Date) => GanttScaleDateInfo[] -} => { - const SCALE_START_LABLE_OFFSET = 7 + generateScaleData: (startDate: Date, endDate: Date) => GanttScaleDateInfo[]; + } => { + const SCALE_START_LABLE_OFFSET = 7; const generateDateInfo = (date: Date, index: number): GanttScaleDateInfo => { const dateInfo: GanttScaleDateInfo = { @@ -23,24 +23,24 @@ export const useScaleData = ( highlightStart: false, scaleStartVisable: true, index, - } - const dayOfMonth = date.getDate() - dateInfo.dayOfMonthLabel = dayOfMonth + '' + }; + const dayOfMonth = date.getDate(); + dateInfo.dayOfMonthLabel = dayOfMonth + ''; if (dayOfMonth === 1) { - dateInfo.monthStart = true + dateInfo.monthStart = true; } - const dayOfWeek = date.getDay() - dateInfo.dayOfWeekLabel = dayOfWeek + '' + const dayOfWeek = date.getDay(); + dateInfo.dayOfWeekLabel = dayOfWeek + ''; if (dayOfWeek === 6) { - dateInfo.weekend = true + dateInfo.weekend = true; } - const month = date.getMonth() + 1 - dateInfo.monthLabel = month + '' - const year = date.getFullYear() - dateInfo.yearLabel = year + '' + const month = date.getMonth() + 1; + dateInfo.monthLabel = month + ''; + const year = date.getFullYear(); + dateInfo.yearLabel = year + ''; if (isSameDate(date, new Date())) { - dateInfo.today = true + dateInfo.today = true; } if ( @@ -51,43 +51,43 @@ export const useScaleData = ( ).getMonth() > month - 1 ) { - dateInfo.scaleStartVisable = false + dateInfo.scaleStartVisable = false; } if (milestoneList.value) { milestoneList.value.forEach((milestone) => { if (milestone.date) { if (isSameDate(milestone.date, dateInfo.date)) { - dateInfo.milestone = milestone.lable + dateInfo.milestone = milestone.lable; } } - }) + }); } - return dateInfo - } + return dateInfo; + }; const getNextDay = (date: Date) => { - const nextDayDate = date.setDate(date.getDate() + 1) - return new Date(nextDayDate) - } + const nextDayDate = date.setDate(date.getDate() + 1); + return new Date(nextDayDate); + }; const generateScaleData = ( startDate: Date, endDate: Date ): GanttScaleDateInfo[] => { - const scaleData = [] - let handleDate = startDate - let index = 0 + const scaleData = []; + let handleDate = startDate; + let index = 0; while (!isSameDate(handleDate, endDate)) { - const dateInfo = generateDateInfo(handleDate, index) - scaleData.push(dateInfo) - handleDate = getNextDay(new Date(handleDate)) - index++ + const dateInfo = generateDateInfo(handleDate, index); + scaleData.push(dateInfo); + handleDate = getNextDay(new Date(handleDate)); + index++; } - console.log({ scaleData }) - return scaleData - } + console.log({ scaleData }); + return scaleData; + }; return { generateScaleData, - } -} + }; +}; diff --git a/packages/devui-vue/devui/gantt/src/gantt-service.ts b/packages/devui-vue/devui/gantt/src/gantt-service.ts index 22e8881321..e10f73d8b5 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-service.ts +++ b/packages/devui-vue/devui/gantt/src/gantt-service.ts @@ -2,109 +2,109 @@ import { fromEvent, merge, Observable, ReplaySubject, Subject } from 'rxjs'; import { pluck } from 'rxjs/operators'; import { GanttBarStatus, GanttScaleConfig, GanttScaleUnit } from './gantt-model'; export class GanttService { - static DAY_DURATION = 24 * 60 * 60 * 1000; - scaleUnit = GanttScaleUnit.day; - scaleStartDate: Date; - scaleEndDate: Date; - ganttBarStatusChange = new Subject<GanttBarStatus>(); - ganttScaleConfigChange = new ReplaySubject<GanttScaleConfig>(1); + static DAY_DURATION = 24 * 60 * 60 * 1000; + scaleUnit = GanttScaleUnit.day; + scaleStartDate: Date; + scaleEndDate: Date; + ganttBarStatusChange = new Subject<GanttBarStatus>(); + ganttScaleConfigChange = new ReplaySubject<GanttScaleConfig>(1); - mouseDownListener: Observable<number>; - mouseMoveListener = new Observable(); - mouseEndListener = new Observable(); + mouseDownListener: Observable<number>; + mouseMoveListener = new Observable(); + mouseEndListener = new Observable(); - changeGanttBarStatus(status: GanttBarStatus):void { - this.ganttBarStatusChange.next(status); - } + changeGanttBarStatus(status: GanttBarStatus): void { + this.ganttBarStatusChange.next(status); + } - registContainerEvents(scrollContainer: HTMLElement):void { - // 背景拖拽 - this.mouseDownListener = fromEvent(scrollContainer, 'mousedown').pipe(pluck<Event, number>('pageX')); + registContainerEvents(scrollContainer: HTMLElement): void { + // 背景拖拽 + this.mouseDownListener = fromEvent(scrollContainer, 'mousedown').pipe(pluck<Event, number>('pageX')); - this.mouseMoveListener = fromEvent(scrollContainer, 'mousemove').pipe(pluck<Event, number>('pageX')); + this.mouseMoveListener = fromEvent(scrollContainer, 'mousemove').pipe(pluck<Event, number>('pageX')); - this.mouseEndListener = merge(fromEvent(scrollContainer, 'mouseup'), fromEvent(scrollContainer, 'mouseout')).pipe( - pluck<Event, number>('pageX') - ); - } + this.mouseEndListener = merge(fromEvent(scrollContainer, 'mouseup'), fromEvent(scrollContainer, 'mouseout')).pipe( + pluck<Event, number>('pageX') + ); + } - changeGanttScaleConfig(status: GanttScaleConfig):void { - this.ganttScaleConfigChange.next(status); - } + changeGanttScaleConfig(status: GanttScaleConfig): void { + this.ganttScaleConfigChange.next(status); + } - setScaleConfig(config: GanttScaleConfig):void { - if (config.startDate) { - this.scaleStartDate = config.startDate; - } - if (config.endDate) { - this.scaleEndDate = config.endDate; - } - if (config.unit) { - this.scaleUnit = config.unit; - } - this.changeGanttScaleConfig(config); + setScaleConfig(config: GanttScaleConfig): void { + if (config.startDate) { + this.scaleStartDate = config.startDate; + } + if (config.endDate) { + this.scaleEndDate = config.endDate; } + if (config.unit) { + this.scaleUnit = config.unit; + } + this.changeGanttScaleConfig(config); + } - getScaleUnitPixel():number { - switch (this.scaleUnit) { - case GanttScaleUnit.day: - return 40; - break; - case GanttScaleUnit.week: - return 30; - break; - case GanttScaleUnit.month: - return 20; - break; - default: - break; - } + getScaleUnitPixel(): number { + switch (this.scaleUnit) { + case GanttScaleUnit.day: + return 40; + break; + case GanttScaleUnit.week: + return 30; + break; + case GanttScaleUnit.month: + return 20; + break; + default: + break; } + } - getDatePostionOffset(date: Date): number { - if (date && this.scaleStartDate) { - const timeOffset = date.getTime() - this.scaleStartDate.getTime(); - const units = timeOffset / GanttService.DAY_DURATION; - return units * this.getScaleUnitPixel(); - } + getDatePostionOffset(date: Date): number { + if (date && this.scaleStartDate) { + const timeOffset = date.getTime() - this.scaleStartDate.getTime(); + const units = timeOffset / GanttService.DAY_DURATION; + return units * this.getScaleUnitPixel(); } + } - getDuration(startDate: Date, endDate: Date): number { - if (startDate && endDate) { - const timeOffset = endDate.getTime() - startDate.getTime(); - const duration = timeOffset / GanttService.DAY_DURATION + 1; - return Math.round(duration); - } + getDuration(startDate: Date, endDate: Date): number { + if (startDate && endDate) { + const timeOffset = endDate.getTime() - startDate.getTime(); + const duration = timeOffset / GanttService.DAY_DURATION + 1; + return Math.round(duration); } + } - getDurationWidth(startDate: Date, endDate: Date): number { - if (startDate && endDate) { - const duration = this.getDuration(startDate, endDate); - return duration * this.getScaleUnitPixel(); - } + getDurationWidth(startDate: Date, endDate: Date): number { + if (startDate && endDate) { + const duration = this.getDuration(startDate, endDate); + return duration * this.getScaleUnitPixel(); } + } - isSomeDate(date: Date, compareDate: Date):boolean { - if (date.getFullYear() !== compareDate.getFullYear()) { - return false; - } + isSomeDate(date: Date, compareDate: Date): boolean { + if (date.getFullYear() !== compareDate.getFullYear()) { + return false; + } - if (date.getMonth() !== compareDate.getMonth()) { - return false; - } + if (date.getMonth() !== compareDate.getMonth()) { + return false; + } - if (date.getDate() !== compareDate.getDate()) { - return false; - } - return true; + if (date.getDate() !== compareDate.getDate()) { + return false; } + return true; + } - roundDate(date: Date):void { - if (date.getHours() >= 12) { - date.setDate(date.getDate() + 1); - date.setHours(0, 0, 0); - } else if (date.getHours() < 12) { - date.setHours(0, 0, 0); - } + roundDate(date: Date): void { + if (date.getHours() >= 12) { + date.setDate(date.getDate() + 1); + date.setHours(0, 0, 0); + } else if (date.getHours() < 12) { + date.setHours(0, 0, 0); } -} \ No newline at end of file + } +} diff --git a/packages/devui-vue/devui/gantt/src/gantt-tools/index.tsx b/packages/devui-vue/devui/gantt/src/gantt-tools/index.tsx index 2557914363..85882ae2b7 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-tools/index.tsx +++ b/packages/devui-vue/devui/gantt/src/gantt-tools/index.tsx @@ -1,6 +1,6 @@ -import { defineComponent, ref } from 'vue' -import './gantt-tools.scss' -import { GanttScaleUnit } from '../gantt-model' +import { defineComponent, ref } from 'vue'; +import './gantt-tools.scss'; +import { GanttScaleUnit } from '../gantt-model'; export default defineComponent({ name: 'DGanttTools', @@ -16,7 +16,7 @@ export default defineComponent({ }, emits: ['goToday', 'reduceUnit', 'increaseUnit', 'switchView'], setup(props, ctx) { - const currentUnitLabel = ref(props.unit) + const currentUnitLabel = ref(props.unit); const views = ref([ { name: 'Day', @@ -30,32 +30,32 @@ export default defineComponent({ name: 'Month', value: 'month', }, - ]) + ]); const actionHandle = (type: string) => { switch (type) { - case 'today': - ctx.emit('goToday') - break - case 'reduce': - ctx.emit('reduceUnit') - break - case 'increase': - ctx.emit('increaseUnit') - break + case 'today': + ctx.emit('goToday'); + break; + case 'reduce': + ctx.emit('reduceUnit'); + break; + case 'increase': + ctx.emit('increaseUnit'); + break; } - } - const selectView = (selectItem: { name: string; value: string; }) => { - ctx.emit('switchView', selectItem.value) - } + }; + const selectView = (selectItem: { name: string; value: string }) => { + ctx.emit('switchView', selectItem.value); + }; return { actionHandle, currentUnitLabel, views, selectView, - } + }; }, render() { - const { isFullScreen, actionHandle, views, selectView, $slots } = this + const { isFullScreen, actionHandle, views, selectView, $slots } = this; return ( <div @@ -102,6 +102,6 @@ export default defineComponent({ </d-button> {$slots.default && $slots.default()} </div> - ) + ); }, -}) +}); diff --git a/packages/devui-vue/devui/gantt/src/gantt-types.ts b/packages/devui-vue/devui/gantt/src/gantt-types.ts index 02cf168da2..9be84dae78 100644 --- a/packages/devui-vue/devui/gantt/src/gantt-types.ts +++ b/packages/devui-vue/devui/gantt/src/gantt-types.ts @@ -1,5 +1,5 @@ -import type { PropType, ExtractPropTypes } from 'vue' -import { GanttScaleUnit } from './gantt-model' +import type { PropType, ExtractPropTypes } from 'vue'; +import { GanttScaleUnit } from './gantt-model'; export const ganttProps = { startDate: { type: Date, @@ -14,7 +14,7 @@ export const ganttProps = { progressRate:{ type:Number }, -} as const +} as const; -export type GanttProps = ExtractPropTypes<typeof ganttProps> +export type GanttProps = ExtractPropTypes<typeof ganttProps>; diff --git a/packages/devui-vue/devui/gantt/src/gantt.tsx b/packages/devui-vue/devui/gantt/src/gantt.tsx index e2ddae9b4d..12540de4f5 100644 --- a/packages/devui-vue/devui/gantt/src/gantt.tsx +++ b/packages/devui-vue/devui/gantt/src/gantt.tsx @@ -1,25 +1,25 @@ -import { defineComponent, onMounted, ref, toRefs } from 'vue' -import DGanttScale from './gantt-scale/index' -import DGanttTools from './gantt-tools/index' -import { ganttProps, GanttProps } from './gantt-types' -import './gantt.scss' -import { useGantt } from './use-gantt' +import { defineComponent, onMounted, ref, toRefs } from 'vue'; +import DGanttScale from './gantt-scale/index'; +import DGanttTools from './gantt-tools/index'; +import { ganttProps, GanttProps } from './gantt-types'; +import './gantt.scss'; +import { useGantt } from './use-gantt'; export default defineComponent({ name: 'DGantt', components: { DGanttScale, DGanttTools }, props: ganttProps, setup(props: GanttProps, ctx) { - const { startDate, endDate } = toRefs(props) - const ganttContainer = ref() - const ganttScaleWidth = ref<number>() - const { getDurationWidth } = useGantt() + const { startDate, endDate } = toRefs(props); + const ganttContainer = ref(); + const ganttScaleWidth = ref<number>(); + const { getDurationWidth } = useGantt(); onMounted(() => { - ganttScaleWidth.value = getDurationWidth(startDate.value, endDate.value) - }) + ganttScaleWidth.value = getDurationWidth(startDate.value, endDate.value); + }); return { ganttContainer, ganttScaleWidth, - } + }; }, render() { const { @@ -29,7 +29,7 @@ export default defineComponent({ unit, ganttContainer, ganttScaleWidth, - } = this + } = this; return ( <div style={{ position: 'relative' }}> <div class="devui-gantt gantt-container" ref="ganttContainer"> @@ -45,6 +45,6 @@ export default defineComponent({ <div class="body" style={{ width: `${ganttScaleWidth}px` }}></div> </div> </div> - ) + ); }, -}) +}); diff --git a/packages/devui-vue/devui/gantt/src/i18n-gantt.ts b/packages/devui-vue/devui/gantt/src/i18n-gantt.ts index 82d0363b64..140c887b72 100644 --- a/packages/devui-vue/devui/gantt/src/i18n-gantt.ts +++ b/packages/devui-vue/devui/gantt/src/i18n-gantt.ts @@ -16,13 +16,13 @@ export const i18nText = { 'December', ], yearDisplay(year: string): string { - return `${year}` + return `${year}`; }, monthDisplay(strMonthIndex: string): string { - return this.monthsOfYear[Number(strMonthIndex) - 1] + return this.monthsOfYear[Number(strMonthIndex) - 1]; }, yearAndMonthDisplay(year: string, strMonthIndex: string): string { - return this.yearDisplay(year) + this.monthDisplay(strMonthIndex) + return this.yearDisplay(year) + this.monthDisplay(strMonthIndex); }, }, zh: { @@ -42,13 +42,13 @@ export const i18nText = { '12月', ], yearDisplay(year: string): string { - return `${year}年` + return `${year}年`; }, monthDisplay(strMonthIndex: string): string { - return this.monthsOfYear[Number(strMonthIndex) - 1] + return this.monthsOfYear[Number(strMonthIndex) - 1]; }, yearAndMonthDisplay(year: string, strMonthIndex: string): string { - return this.yearDisplay(year) + this.monthDisplay(strMonthIndex) + return this.yearDisplay(year) + this.monthDisplay(strMonthIndex); }, }, -} +}; diff --git a/packages/devui-vue/devui/gantt/src/use-gantt.ts b/packages/devui-vue/devui/gantt/src/use-gantt.ts index 3a59908c97..29ee52a9db 100644 --- a/packages/devui-vue/devui/gantt/src/use-gantt.ts +++ b/packages/devui-vue/devui/gantt/src/use-gantt.ts @@ -1,36 +1,36 @@ -import { GanttScaleUnit } from './gantt-model' +import { GanttScaleUnit } from './gantt-model'; export const useGantt = (scaleUnit = GanttScaleUnit.day) => { - const DAY_DURATION = 24 * 60 * 60 * 1000 + const DAY_DURATION = 24 * 60 * 60 * 1000; const getScaleUnitPixel = () => { switch (scaleUnit) { - case GanttScaleUnit.day: - return 40 - case GanttScaleUnit.week: - return 30 - case GanttScaleUnit.month: - return 20 - default: - break + case GanttScaleUnit.day: + return 40; + case GanttScaleUnit.week: + return 30; + case GanttScaleUnit.month: + return 20; + default: + break; } - } + }; const getDuration = (startDate: Date, endDate: Date): number => { if (startDate && endDate) { - const timeOffset = endDate.getTime() - startDate.getTime() - const duration = timeOffset / DAY_DURATION + 1 - console.log('duration => ', duration) + const timeOffset = endDate.getTime() - startDate.getTime(); + const duration = timeOffset / DAY_DURATION + 1; + console.log('duration => ', duration); - return Math.round(duration) + return Math.round(duration); } - } + }; const getDurationWidth = (startDate: Date, endDate: Date): number => { if (startDate && endDate) { - const duration = getDuration(startDate, endDate) - return duration * getScaleUnitPixel() + const duration = getDuration(startDate, endDate); + return duration * getScaleUnitPixel(); } - } + }; return { getDurationWidth, - } -} + }; +}; diff --git a/packages/devui-vue/devui/gantt/src/utils.ts b/packages/devui-vue/devui/gantt/src/utils.ts index a232b179f9..019de4441d 100644 --- a/packages/devui-vue/devui/gantt/src/utils.ts +++ b/packages/devui-vue/devui/gantt/src/utils.ts @@ -4,5 +4,5 @@ export const isSameDate = (date: Date, compareDate: Date): boolean => { date.getFullYear() === compareDate.getFullYear() && date.getMonth() === compareDate.getMonth() && date.getDate() === compareDate.getDate() - ) -} + ); +}; diff --git a/packages/devui-vue/devui/grid/__tests__/grid.spec.tsx b/packages/devui-vue/devui/grid/__tests__/grid.spec.tsx index 318a472f70..d25cfd8995 100644 --- a/packages/devui-vue/devui/grid/__tests__/grid.spec.tsx +++ b/packages/devui-vue/devui/grid/__tests__/grid.spec.tsx @@ -1,7 +1,7 @@ -import { mount } from '@vue/test-utils' -import { Row, Col } from '../index' -import { Justify, Align, ColProps } from '../src/grid-types' -import { screenMedias } from '../src/use-screen' +import { mount } from '@vue/test-utils'; +import { Row, Col } from '../index'; +import { Justify, Align, ColProps } from '../src/grid-types'; +import { screenMedias } from '../src/use-screen'; describe('d-row', () => { window.matchMedia = jest.fn().mockImplementation(query => { @@ -14,103 +14,103 @@ describe('d-row', () => { addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), - } - }) + }; + }); it('d-row init', () => { - const wrapper = mount(Row) - expect(wrapper.classes()).toEqual(['devui-row', 'devui-row-align-top', 'devui-row-justify-start']) - }) - - const justify: Justify[] = ['start', 'end', 'center', 'around', 'between'] + const wrapper = mount(Row); + expect(wrapper.classes()).toEqual(['devui-row', 'devui-row-align-top', 'devui-row-justify-start']); + }); + + const justify: Justify[] = ['start', 'end', 'center', 'around', 'between']; justify.forEach(item => { it(`d-row justify ${item}`, () => { const wrapper = mount(Row, { props: { justify: item } - }) - expect(wrapper.classes(`devui-row-justify-${item}`)).toBe(true) - }) - }) + }); + expect(wrapper.classes(`devui-row-justify-${item}`)).toBe(true); + }); + }); - const align: Align[] = ['top', 'middle', 'bottom'] + const align: Align[] = ['top', 'middle', 'bottom']; align.forEach(item => { it(`d-row align ${item}`, () => { const wrapper = mount(Row, { props: { align: item } - }) - expect(wrapper.classes(`devui-row-align-${item}`)).toBe(true) - }) - }) + }); + expect(wrapper.classes(`devui-row-align-${item}`)).toBe(true); + }); + }); it('d-row wrap', () => { const wrapper = mount(Row, { props: { wrap: true } - }) - expect(wrapper.classes('devui-row-wrap')).toBe(true) - }) -}) + }); + expect(wrapper.classes('devui-row-wrap')).toBe(true); + }); +}); describe('d-col', () => { - const value = 8 + const value = 8; it('d-col flex', () => { const component = <Row> <Col flex={value}></Col> - </Row> - const wrapper = mount(component) - expect(wrapper.find('.devui-col').attributes()).toMatchObject({ style: `flex: ${value} ${value} auto;` }) - }) + </Row>; + const wrapper = mount(component); + expect(wrapper.find('.devui-col').attributes()).toMatchObject({ style: `flex: ${value} ${value} auto;` }); + }); it('d-col order', () => { const component = <Row> <Col order={value}></Col> - </Row> - const wrapper = mount(component) - expect(wrapper.find('.devui-col').attributes()).toMatchObject({ style: `order: ${value};` }) - }) + </Row>; + const wrapper = mount(component); + expect(wrapper.find('.devui-col').attributes()).toMatchObject({ style: `order: ${value};` }); + }); - const props: (keyof ColProps)[] = ['span', 'offset', 'pull', 'push'] + const props: (keyof ColProps)[] = ['span', 'offset', 'pull', 'push']; props.forEach(item => { - const prop = { [item]: value } + const prop = { [item]: value }; const component = <Row> <Col { ...prop }></Col> - </Row> + </Row>; it(`d-col ${item}`, () => { - const wrapper = mount(component) - expect(wrapper.findAll(`.devui-col-${item}-${value}`).length).toBe(1) - }) - }) + const wrapper = mount(component); + expect(wrapper.findAll(`.devui-col-${item}-${value}`).length).toBe(1); + }); + }); - const sizes = Object.keys(screenMedias) as (keyof typeof screenMedias)[] + const sizes = Object.keys(screenMedias) as (keyof typeof screenMedias)[]; sizes.forEach(item => { - const prop = { [item]: value } + const prop = { [item]: value }; const component = <Row> <Col { ...prop }></Col> - </Row> + </Row>; it(`d-col ${item} span`, () => { - const wrapper = mount(component) - console.log(wrapper.html()) - expect(wrapper.findAll(`.devui-col-${item}-span-${value}`).length).toBe(1) - }) - }) - + const wrapper = mount(component); + console.log(wrapper.html()); + expect(wrapper.findAll(`.devui-col-${item}-span-${value}`).length).toBe(1); + }); + }); + it('d-row gutter', () => { const component1 = <Row gutter={8}> <Col></Col> - </Row> + </Row>; const component2 = <Row gutter={[8, 8]}> <Col></Col> - </Row> + </Row>; // const component3 = <Row gutter={{ xs: 8, sm: 8, md: 8, lg: 8, xl: 8, xxl: 8 }}> // <Col></Col> // </Row> - const wrapper1 = mount(component1) - const wrapper2 = mount(component2) + const wrapper1 = mount(component1); + const wrapper2 = mount(component2); // const wrapper3 = mount(component3) - expect(wrapper1.find('.devui-col').attributes()).toMatchObject({ style: 'padding: 0px 4px 0px 4px;' }) - expect(wrapper2.find('.devui-col').attributes()).toMatchObject({ style: 'padding: 4px 4px 4px 4px;' }) + expect(wrapper1.find('.devui-col').attributes()).toMatchObject({ style: 'padding: 0px 4px 0px 4px;' }); + expect(wrapper2.find('.devui-col').attributes()).toMatchObject({ style: 'padding: 4px 4px 4px 4px;' }); // expect(wrapper3.find('.devui-col').attributes()).toMatchObject({ style: 'padding: 4px 4px 4px 4px;' }) - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/grid/index.ts b/packages/devui-vue/devui/grid/index.ts index d5f01ab2d6..06d3e36724 100644 --- a/packages/devui-vue/devui/grid/index.ts +++ b/packages/devui-vue/devui/grid/index.ts @@ -1,22 +1,22 @@ -import type { App } from 'vue' -import Row from './src/row' -import Col from './src/col' +import type { App } from 'vue'; +import Row from './src/row'; +import Col from './src/col'; Row.install = function(app: App): void { - app.component(Row.name, Row) -} + app.component(Row.name, Row); +}; Col.install = function(app: App): void { - app.component(Col.name, Col) -} -export { Row, Col } + app.component(Col.name, Col); +}; +export { Row, Col }; export default { title: 'Grid 栅格', category: '布局', status: '100%', install(app: App): void { - app.use(Col as any) - app.use(Row as any) + app.use(Col as any); + app.use(Row as any); } -} +}; diff --git a/packages/devui-vue/devui/grid/src/col.tsx b/packages/devui-vue/devui/grid/src/col.tsx index 596cb8a73c..5e94ac1f40 100644 --- a/packages/devui-vue/devui/grid/src/col.tsx +++ b/packages/devui-vue/devui/grid/src/col.tsx @@ -1,35 +1,35 @@ -import { defineComponent, computed, CSSProperties, Ref, inject } from 'vue' -import { colProps, ColProps } from './grid-types' -import { useSize, CLASS_PREFIX, useColClassNames } from './use-grid' -import './col.scss' +import { defineComponent, computed, CSSProperties, Ref, inject } from 'vue'; +import { colProps, ColProps } from './grid-types'; +import { useSize, CLASS_PREFIX, useColClassNames } from './use-grid'; +import './col.scss'; export default defineComponent({ - name: 'DCol', - props: colProps, - setup (props: ColProps, { slots }) { - - const formatFlex = (flex: typeof props.flex) => { - if (typeof flex === 'number') { - return `${flex} ${flex} auto` - } - if (/^\d+(\.\d+)?(px|rem|em|%)$/.test(flex)) { - return `0 0 ${flex}` - } - return flex - } - - const colClassNames= useColClassNames(props) - - const sizeClassNames = useSize(props) - - const colStyle = computed<CSSProperties>(() => ({ - flex: formatFlex(props.flex), - order: props.order - })) - - const gutterStyle = inject<Ref<CSSProperties>>('gutterStyle') - - return () => <div class={`${CLASS_PREFIX}${colClassNames.value}${sizeClassNames.value}`} style={{ ...colStyle.value, ...gutterStyle.value }}>{slots.default?.()}</div> - } -}) + name: 'DCol', + props: colProps, + setup (props: ColProps, { slots }) { + + const formatFlex = (flex: typeof props.flex) => { + if (typeof flex === 'number') { + return `${flex} ${flex} auto`; + } + if (/^\d+(\.\d+)?(px|rem|em|%)$/.test(flex)) { + return `0 0 ${flex}`; + } + return flex; + }; + + const colClassNames= useColClassNames(props); + + const sizeClassNames = useSize(props); + + const colStyle = computed<CSSProperties>(() => ({ + flex: formatFlex(props.flex), + order: props.order + })); + + const gutterStyle = inject<Ref<CSSProperties>>('gutterStyle'); + + return () => <div class={`${CLASS_PREFIX}${colClassNames.value}${sizeClassNames.value}`} style={{ ...colStyle.value, ...gutterStyle.value }}>{slots.default?.()}</div>; + } +}); diff --git a/packages/devui-vue/devui/grid/src/grid-types.ts b/packages/devui-vue/devui/grid/src/grid-types.ts index 4d4328b721..ef92f1c177 100644 --- a/packages/devui-vue/devui/grid/src/grid-types.ts +++ b/packages/devui-vue/devui/grid/src/grid-types.ts @@ -1,19 +1,19 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; -export type Align = 'top' | 'middle' | 'bottom' +export type Align = 'top' | 'middle' | 'bottom'; -export type Justify = 'start' | 'end' | 'center' | 'around' | 'between' +export type Justify = 'start' | 'end' | 'center' | 'around' | 'between'; export interface GutterScreenSizes { - xs?: number | number[] - sm?: number | number[] - md?: number | number[] - lg?: number | number[] - xl?: number | number[] - xxl?: number | number[] + xs?: number | number[]; + sm?: number | number[]; + md?: number | number[]; + lg?: number | number[]; + xl?: number | number[]; + xxl?: number | number[]; // 如果没有必选项,gutter将是unknown类型 - [key: string]: number | number[] -} + [key: string]: number | number[]; +} export const rowProps = { align: { @@ -32,11 +32,11 @@ export const rowProps = { type: Boolean as PropType<boolean>, default: false } -} as const +} as const; -export type RowProps = ExtractPropTypes<typeof rowProps> +export type RowProps = ExtractPropTypes<typeof rowProps>; -const screenSizesProp = [Number, Object] as PropType<number | ColPropsBaseClass> +const screenSizesProp = [Number, Object] as PropType<number | ColPropsBaseClass>; export const screenSizes = { xs: screenSizesProp, @@ -45,28 +45,28 @@ export const screenSizes = { lg: screenSizesProp, xl: screenSizesProp, xxl: screenSizesProp, -} as const +} as const; -const numberProp = Number as PropType<number> +const numberProp = Number as PropType<number>; export const colPropsBaseStyle = { flex: [String, Number] as PropType<string | number>, order: numberProp, -} as const +} as const; export const colPropsBaseClass = { offset: numberProp, pull: numberProp, push: numberProp, span: numberProp -} as const +} as const; -export type ColPropsBaseStyle = ExtractPropTypes<typeof colPropsBaseStyle> +export type ColPropsBaseStyle = ExtractPropTypes<typeof colPropsBaseStyle>; -export type ColPropsBaseClass = ExtractPropTypes<typeof colPropsBaseClass> +export type ColPropsBaseClass = ExtractPropTypes<typeof colPropsBaseClass>; -export type ScreenSizes = ExtractPropTypes<typeof screenSizes> +export type ScreenSizes = ExtractPropTypes<typeof screenSizes>; -export const colProps = { ...colPropsBaseStyle, ...colPropsBaseClass, ...screenSizes} +export const colProps = { ...colPropsBaseStyle, ...colPropsBaseClass, ...screenSizes}; -export type ColProps = ExtractPropTypes<typeof colProps> +export type ColProps = ExtractPropTypes<typeof colProps>; diff --git a/packages/devui-vue/devui/grid/src/row.tsx b/packages/devui-vue/devui/grid/src/row.tsx index 6e6bb5b35c..cb77432bc5 100644 --- a/packages/devui-vue/devui/grid/src/row.tsx +++ b/packages/devui-vue/devui/grid/src/row.tsx @@ -1,69 +1,69 @@ -import { defineComponent, computed, ref, Ref, CSSProperties, onMounted, onUnmounted, provide } from 'vue' -import { rowProps, RowProps } from './grid-types' -import { formatClass } from './use-grid' -import { responesScreen, Screen, RESULT_SCREEN, removeSubscribeCb } from './use-screen' -import './row.scss' +import { defineComponent, computed, ref, Ref, CSSProperties, onMounted, onUnmounted, provide } from 'vue'; +import { rowProps, RowProps } from './grid-types'; +import { formatClass } from './use-grid'; +import { responesScreen, Screen, RESULT_SCREEN, removeSubscribeCb } from './use-screen'; +import './row.scss'; -const CLASS_PREFIX = 'devui-row' +const CLASS_PREFIX = 'devui-row'; export default defineComponent({ name: 'DRow', props: rowProps, emits: [], setup(props: RowProps, { slots }) { - const gutterScreenSize = ref<Screen>({}) + const gutterScreenSize = ref<Screen>({}); const rowClass = computed<string>(() => { - const alignClass = formatClass(`${CLASS_PREFIX}-align`, props.align) - const justifyClass = formatClass(`${CLASS_PREFIX}-justify`, props.justify) - const wrapClass = props.wrap ? ` ${CLASS_PREFIX}-wrap` : '' - return `${alignClass}${justifyClass}${wrapClass}` - }) + const alignClass = formatClass(`${CLASS_PREFIX}-align`, props.align); + const justifyClass = formatClass(`${CLASS_PREFIX}-justify`, props.justify); + const wrapClass = props.wrap ? ` ${CLASS_PREFIX}-wrap` : ''; + return `${alignClass}${justifyClass}${wrapClass}`; + }); - let token + let token; onMounted(() => { token = responesScreen(screen => { - gutterScreenSize.value = screen - }) - }) + gutterScreenSize.value = screen; + }); + }); onUnmounted(() => { - removeSubscribeCb(token) - }) + removeSubscribeCb(token); + }); const gutterStyle = computed<CSSProperties>(() => { if (!props.gutter) { - return {} + return {}; } - let currentGutter = [0, 0] + let currentGutter = [0, 0]; if (Array.isArray(props.gutter)) { - currentGutter = props.gutter as number[] + currentGutter = props.gutter as number[]; } else if (typeof props.gutter === 'number') { - currentGutter = [props.gutter as number, 0] + currentGutter = [props.gutter as number, 0]; } else { RESULT_SCREEN.some(size => { - const gzs = props.gutter[size] + const gzs = props.gutter[size]; if (gutterScreenSize.value[size] && gzs) { if (typeof gzs === 'number') { - currentGutter = [gzs, 0] + currentGutter = [gzs, 0]; } else { - currentGutter = gzs + currentGutter = gzs; } - return true + return true; } - return false - }) + return false; + }); } - const paddingLeft = `${(currentGutter[0] || 0) / 2}px` - const paddingRight = `${(currentGutter[0] || 0) / 2}px` - const paddingTop = `${(currentGutter[1] || 0) / 2}px` - const paddingBottom = `${(currentGutter[1] || 0) / 2}px` - return { paddingLeft, paddingRight, paddingTop, paddingBottom } - }) + const paddingLeft = `${(currentGutter[0] || 0) / 2}px`; + const paddingRight = `${(currentGutter[0] || 0) / 2}px`; + const paddingTop = `${(currentGutter[1] || 0) / 2}px`; + const paddingBottom = `${(currentGutter[1] || 0) / 2}px`; + return { paddingLeft, paddingRight, paddingTop, paddingBottom }; + }); - provide<Ref<CSSProperties>>('gutterStyle', gutterStyle) + provide<Ref<CSSProperties>>('gutterStyle', gutterStyle); - return () => <div class={`${CLASS_PREFIX}${rowClass.value}`}>{slots.default?.()}</div> + return () => <div class={`${CLASS_PREFIX}${rowClass.value}`}>{slots.default?.()}</div>; } -}) +}); diff --git a/packages/devui-vue/devui/grid/src/use-grid.ts b/packages/devui-vue/devui/grid/src/use-grid.ts index b32211bf4f..b3a3d0df6d 100644 --- a/packages/devui-vue/devui/grid/src/use-grid.ts +++ b/packages/devui-vue/devui/grid/src/use-grid.ts @@ -1,47 +1,47 @@ -import { computed } from 'vue' -import { ScreenSizes, ColPropsBaseClass, screenSizes, colPropsBaseClass } from './grid-types' +import { computed } from 'vue'; +import { ScreenSizes, ColPropsBaseClass, screenSizes, colPropsBaseClass } from './grid-types'; -export const CLASS_PREFIX = 'devui-col' +export const CLASS_PREFIX = 'devui-col'; export function formatClass (prefix: string, val: number | string | undefined) { - return val !== undefined ? ` ${prefix}-${val}` : '' + return val !== undefined ? ` ${prefix}-${val}` : ''; } export function useColClassNames (props: ColPropsBaseClass) { - return computed<string>(() => { - const spanClass = formatClass(`${CLASS_PREFIX}-span`, props.span) - const offsetClass = formatClass(`${CLASS_PREFIX}-offset`, props.offset) - const pullClass = formatClass(`${CLASS_PREFIX}-pull`, props.pull) - const pushClass = formatClass(`${CLASS_PREFIX}-push`, props.push) - return `${spanClass}${offsetClass}${pullClass}${pushClass}` - }) + return computed<string>(() => { + const spanClass = formatClass(`${CLASS_PREFIX}-span`, props.span); + const offsetClass = formatClass(`${CLASS_PREFIX}-offset`, props.offset); + const pullClass = formatClass(`${CLASS_PREFIX}-pull`, props.pull); + const pushClass = formatClass(`${CLASS_PREFIX}-push`, props.push); + return `${spanClass}${offsetClass}${pullClass}${pushClass}`; + }); } -function setSpace (val:string) { - return ` ${val.trim()}${val && ' '}` +function setSpace (val: string) { + return ` ${val.trim()}${val && ' '}`; } export function useSize (colSizes: ScreenSizes) { - const keys = Object.keys(colSizes).filter(key => key in screenSizes) as (keyof ScreenSizes)[] - return computed<string>(() => { - return keys.reduce((total, key) => { - const valueType = typeof colSizes[key] - - if (valueType === 'number') { - total = `${setSpace(total)}${CLASS_PREFIX}-${key}-span-${colSizes[key]}` - } else if (valueType === 'object') { - const colSizesKeys = Object.keys(colSizes[key]) as (keyof ColPropsBaseClass)[] - const sum = colSizesKeys.filter(item => item in colPropsBaseClass).reduce((tot, k) => { - if (typeof colSizes[key][k] !== 'number') { - return '' - } else { - tot = `${setSpace(tot)}${CLASS_PREFIX}-${key}-${k}-${colSizes[key][k]}` - } - return tot - }, '') - total = `${setSpace(total)}${sum}` - } - return total - }, '') - }) + const keys = Object.keys(colSizes).filter(key => key in screenSizes) as (keyof ScreenSizes)[]; + return computed<string>(() => { + return keys.reduce((total, key) => { + const valueType = typeof colSizes[key]; + + if (valueType === 'number') { + total = `${setSpace(total)}${CLASS_PREFIX}-${key}-span-${colSizes[key]}`; + } else if (valueType === 'object') { + const colSizesKeys = Object.keys(colSizes[key]) as (keyof ColPropsBaseClass)[]; + const sum = colSizesKeys.filter(item => item in colPropsBaseClass).reduce((tot, k) => { + if (typeof colSizes[key][k] !== 'number') { + return ''; + } else { + tot = `${setSpace(tot)}${CLASS_PREFIX}-${key}-${k}-${colSizes[key][k]}`; + } + return tot; + }, ''); + total = `${setSpace(total)}${sum}`; + } + return total; + }, ''); + }); } diff --git a/packages/devui-vue/devui/grid/src/use-screen.ts b/packages/devui-vue/devui/grid/src/use-screen.ts index 2c99c63048..86355d2a9b 100644 --- a/packages/devui-vue/devui/grid/src/use-screen.ts +++ b/packages/devui-vue/devui/grid/src/use-screen.ts @@ -1,84 +1,84 @@ -export const RESULT_SCREEN = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs'] +export const RESULT_SCREEN = ['xxl', 'xl', 'lg', 'md', 'sm', 'xs']; export const screenMedias = { - xs: 'screen and (max-width: 575px)', - sm: 'screen and (min-width: 576px)', - md: 'screen and (min-width: 768px)', - lg: 'screen and (min-width: 992px)', - xl: 'screen and (min-width: 1200px)', - xxl: 'screen and (min-width: 1600px)', -} as const + xs: 'screen and (max-width: 575px)', + sm: 'screen and (min-width: 576px)', + md: 'screen and (min-width: 768px)', + lg: 'screen and (min-width: 992px)', + xl: 'screen and (min-width: 1200px)', + xxl: 'screen and (min-width: 1600px)', +} as const; export interface Screen { - xs?: boolean - sm?: boolean - md?: boolean - lg?: boolean - xl?: boolean - xxl?: boolean + xs?: boolean; + sm?: boolean; + md?: boolean; + lg?: boolean; + xl?: boolean; + xxl?: boolean; } -export type ScreenMediasKey = keyof typeof screenMedias -type SubscribeCb = (screen: Screen) => void +export type ScreenMediasKey = keyof typeof screenMedias; +type SubscribeCb = (screen: Screen) => void; -const subscribers = new Map<number, SubscribeCb>() -let subUid = -1 -const screen: Screen = {} +const subscribers = new Map<number, SubscribeCb>(); +let subUid = -1; +const screen: Screen = {}; const results: { - [key: string]: { - res: MediaQueryList - listener: (this: MediaQueryList, ev: MediaQueryListEvent) => void - } - } = {}; + [key: string]: { + res: MediaQueryList; + listener: (this: MediaQueryList, ev: MediaQueryListEvent) => void; + }; +} = {}; export function responesScreen (func: SubscribeCb) { - if (!subscribers.size) { - register() - } - subUid += 1 - subscribers.set(subUid, func) - func({ ...screen }) - return subUid + if (!subscribers.size) { + register(); + } + subUid += 1; + subscribers.set(subUid, func); + func({ ...screen }); + return subUid; } export function removeSubscribeCb (id: number) { - subscribers.delete(id) - if (subscribers.size === 0) { - unRegister() - } + subscribers.delete(id); + if (subscribers.size === 0) { + unRegister(); + } } function register () { - Object.keys(screenMedias).forEach(key => { - const result = window.matchMedia(screenMedias[key]) - if (result.matches) { - screen[key as ScreenMediasKey] = true - dispatch() - } - const listener = e => { - screen[key as ScreenMediasKey] = e.matches - dispatch() - } - result.addEventListener('change', listener) + Object.keys(screenMedias).forEach(key => { + const result = window.matchMedia(screenMedias[key]); + if (result.matches) { + screen[key as ScreenMediasKey] = true; + dispatch(); + } + const listener = e => { + screen[key as ScreenMediasKey] = e.matches; + dispatch(); + }; + result.addEventListener('change', listener); - results[key] = { - res: result, - listener - } - }) + results[key] = { + res: result, + listener + }; + }); } function unRegister () { - Object.keys(screenMedias).forEach(key => { - const handler = results[key] - handler.res.removeEventListener('change', handler.listener) - }) - subscribers.clear() + Object.keys(screenMedias).forEach(key => { + const handler = results[key]; + handler.res.removeEventListener('change', handler.listener); + }); + subscribers.clear(); } function dispatch () { - subscribers.forEach(value => { - value({ ...screen }) - }) + subscribers.forEach(value => { + value({ ...screen }); + }); } diff --git a/packages/devui-vue/devui/icon/__tests__/icon.spec.ts b/packages/devui-vue/devui/icon/__tests__/icon.spec.ts index 91424ad144..a608cb2b2f 100644 --- a/packages/devui-vue/devui/icon/__tests__/icon.spec.ts +++ b/packages/devui-vue/devui/icon/__tests__/icon.spec.ts @@ -2,29 +2,29 @@ import { mount } from '@vue/test-utils'; import Icon from '../src/icon'; describe('d-icon', () => { - it('name', () => { - const wrapper = mount(Icon, { - props: { name:'add' }, - }); - expect(wrapper.find('.icon-add').exists()).toBeTruthy(); - }); + it('name', () => { + const wrapper = mount(Icon, { + props: { name:'add' }, + }); + expect(wrapper.find('.icon-add').exists()).toBeTruthy(); + }); - it('classPrefix', () => { - const wrapper = mount(Icon, { - props: { name:'add',classPrefix:'dev' }, - }); - expect(wrapper.find('.dev-add').exists()).toBeTruthy(); + it('classPrefix', () => { + const wrapper = mount(Icon, { + props: { name:'add',classPrefix:'dev' }, }); - it('size', () => { - const wrapper = mount(Icon, { - props: { name:'add',size:'80px'}, - }); - expect(wrapper.find('.icon-add').attributes('style').includes('font-size: 80px')).toBeTruthy(); + expect(wrapper.find('.dev-add').exists()).toBeTruthy(); + }); + it('size', () => { + const wrapper = mount(Icon, { + props: { name:'add',size:'80px'}, }); - it('color', () => { - const wrapper = mount(Icon, { - props: { name:'add',color:'red'}, - }); - expect(wrapper.find('.icon-add').attributes('style').includes('color: red')).toBeTruthy(); + expect(wrapper.find('.icon-add').attributes('style').includes('font-size: 80px')).toBeTruthy(); + }); + it('color', () => { + const wrapper = mount(Icon, { + props: { name:'add',color:'red'}, }); -}) \ No newline at end of file + expect(wrapper.find('.icon-add').attributes('style').includes('color: red')).toBeTruthy(); + }); +}); diff --git a/packages/devui-vue/devui/icon/index.ts b/packages/devui-vue/devui/icon/index.ts index fd1972adb8..59f52e618f 100644 --- a/packages/devui-vue/devui/icon/index.ts +++ b/packages/devui-vue/devui/icon/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Icon from './src/icon' +import type { App } from 'vue'; +import Icon from './src/icon'; Icon.install = function(app: App) { - app.component(Icon.name, Icon) -} + app.component(Icon.name, Icon); +}; -export { Icon } +export { Icon }; export default { title: 'Icon 图标', category: '通用', status: '100%', install(app: App): void { - app.use(Icon as any) + app.use(Icon as any); } -} +}; diff --git a/packages/devui-vue/devui/icon/src/icon.tsx b/packages/devui-vue/devui/icon/src/icon.tsx index 0d03ef7610..22f486f837 100644 --- a/packages/devui-vue/devui/icon/src/icon.tsx +++ b/packages/devui-vue/devui/icon/src/icon.tsx @@ -1,4 +1,4 @@ -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; export default defineComponent({ name: 'DIcon', @@ -23,10 +23,10 @@ export default defineComponent({ setup(props) { return { ...props - } + }; }, render() { - const { name, size, color, classPrefix } = this + const { name, size, color, classPrefix } = this; return /^((https?):)?\/\//.test(name) ? ( <img src={name} @@ -44,6 +44,6 @@ export default defineComponent({ color }} ></i> - ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/image-preview/__tests__/image-preview.spec.ts b/packages/devui-vue/devui/image-preview/__tests__/image-preview.spec.ts index 519e4e62b1..e28a04e70e 100644 --- a/packages/devui-vue/devui/image-preview/__tests__/image-preview.spec.ts +++ b/packages/devui-vue/devui/image-preview/__tests__/image-preview.spec.ts @@ -1,18 +1,18 @@ -import { mount } from '@vue/test-utils' -import { ImagePreviewDirective } from '../index' -import { ref } from 'vue' +import { mount } from '@vue/test-utils'; +import { ImagePreviewDirective } from '../index'; +import { ref } from 'vue'; // 指令图片模板 const imageTemplate = ` <img id="testImg" src="https://devui.design/components/assets/image1.png" /> <img src="https://devui.design/components/assets/image3.png" /> -` +`; // 全局属性 const global = { directives: { dImagePreview: ImagePreviewDirective } -} +}; describe('image-preview', () => { it('image-preview click', async () => { @@ -27,14 +27,14 @@ describe('image-preview', () => { { global } - ) - const img = wrapper.find('#testImg') - await img.trigger('click') - const ele = document.querySelector('.devui-image-preview-main-image') - expect(ele).toBeTruthy() - const closeBtn = document.querySelector('.devui-image-preview-close-btn') as any - closeBtn.click() - }) + ); + const img = wrapper.find('#testImg'); + await img.trigger('click'); + const ele = document.querySelector('.devui-image-preview-main-image'); + expect(ele).toBeTruthy(); + const closeBtn = document.querySelector('.devui-image-preview-close-btn') as any; + closeBtn.click(); + }); it('image-preview disableDefault', async () => { const wrapper = mount( @@ -48,16 +48,16 @@ describe('image-preview', () => { { global } - ) - const img = wrapper.find('#testImg') - await img.trigger('click') - const ele = document.querySelector('.devui-image-preview-main-image') - expect(ele).toBeFalsy() - }) + ); + const img = wrapper.find('#testImg'); + await img.trigger('click'); + const ele = document.querySelector('.devui-image-preview-main-image'); + expect(ele).toBeFalsy(); + }); it('image-preview custom', async () => { - const custom: any = ref({}) - const open = () => custom.value.open() + const custom: any = ref({}); + const open = () => custom.value.open(); const wrapper = mount( { template: ` @@ -70,18 +70,18 @@ describe('image-preview', () => { return { custom, open - } + }; } }, { global } - ) - const customBtn = wrapper.find('#open') - await customBtn.trigger('click') - const ele = document.querySelector('.devui-image-preview-main-image') - expect(ele).toBeTruthy() - const closeBtn = document.querySelector('.devui-image-preview-close-btn') as any - closeBtn.click() - }) -}) + ); + const customBtn = wrapper.find('#open'); + await customBtn.trigger('click'); + const ele = document.querySelector('.devui-image-preview-main-image'); + expect(ele).toBeTruthy(); + const closeBtn = document.querySelector('.devui-image-preview-close-btn') as any; + closeBtn.click(); + }); +}); diff --git a/packages/devui-vue/devui/image-preview/index.ts b/packages/devui-vue/devui/image-preview/index.ts index 375a16e51c..ecc2ef444e 100644 --- a/packages/devui-vue/devui/image-preview/index.ts +++ b/packages/devui-vue/devui/image-preview/index.ts @@ -1,15 +1,15 @@ -import type { App } from 'vue' -import ImagePreviewDirective from './src/image-preview-directive' -import ImagePreviewService from './src/image-preview-service' +import type { App } from 'vue'; +import ImagePreviewDirective from './src/image-preview-directive'; +import ImagePreviewService from './src/image-preview-service'; -export { ImagePreviewDirective, ImagePreviewService } +export { ImagePreviewDirective, ImagePreviewService }; export default { title: 'ImagePreview 图片预览', category: '数据展示', status: '100%', install(app: App): void { - app.directive('d-image-preview', ImagePreviewDirective) - app.config.globalProperties.$imagePreviewService = ImagePreviewService + app.directive('d-image-preview', ImagePreviewDirective); + app.config.globalProperties.$imagePreviewService = ImagePreviewService; } -} +}; diff --git a/packages/devui-vue/devui/image-preview/src/image-preview-directive.ts b/packages/devui-vue/devui/image-preview/src/image-preview-directive.ts index 7372989e73..0b66ba0fab 100644 --- a/packages/devui-vue/devui/image-preview/src/image-preview-directive.ts +++ b/packages/devui-vue/devui/image-preview/src/image-preview-directive.ts @@ -1,9 +1,9 @@ -import { BindingTypes, ImagePreviewProps, UpdateBindingTypes } from './image-preview-types' -import ImagePreviewService from './image-preview-service' +import { BindingTypes, ImagePreviewProps, UpdateBindingTypes } from './image-preview-types'; +import ImagePreviewService from './image-preview-service'; interface PreviewHTMLElement extends HTMLElement { - zIndex?: number - backDropZIndex?: number + zIndex?: number; + backDropZIndex?: number; } function mountedPreviewImages(props: ImagePreviewProps): void { @@ -12,82 +12,82 @@ function mountedPreviewImages(props: ImagePreviewProps): void { previewUrlList: props.previewUrlList, zIndex: props.zIndex, backDropZIndex: props.backDropZIndex - }) + }); } function unmountedPreviewImages() { - ImagePreviewService.close() + ImagePreviewService.close(); } function getImgByEl(el: HTMLElement): Array<string> { const urlList = [...el.querySelectorAll('img')].map((item: HTMLImageElement) => item.getAttribute('src') - ) - return urlList + ); + return urlList; } function handleImgByEl(el: PreviewHTMLElement) { - el.addEventListener('click', handleImg) + el.addEventListener('click', handleImg); } function removeHandle(el: PreviewHTMLElement) { - el.removeEventListener('click', handleImg) + el.removeEventListener('click', handleImg); } function handleImg(e: MouseEvent) { - e.stopPropagation() - const el = e.currentTarget as PreviewHTMLElement - const target = e.target as PreviewHTMLElement + e.stopPropagation(); + const el = e.currentTarget as PreviewHTMLElement; + const target = e.target as PreviewHTMLElement; if (target?.nodeName?.toLowerCase() === 'img') { - const urlList = getImgByEl(el) - const url = target.getAttribute('src') + const urlList = getImgByEl(el); + const url = target.getAttribute('src'); mountedPreviewImages({ url, previewUrlList: urlList, zIndex: el?.zIndex, backDropZIndex: el?.backDropZIndex - }) + }); } } export default { mounted(el: PreviewHTMLElement, binding: BindingTypes | undefined) { if (!binding.value) { - return handleImgByEl(el) + return handleImgByEl(el); } - const { custom, disableDefault } = binding.value + const { custom, disableDefault } = binding.value; // console.log('指令参数:', custom, disableDefault, zIndex, backDropZIndex) if (custom instanceof Object) { custom.open = () => { - const urlList = getImgByEl(el) + const urlList = getImgByEl(el); mountedPreviewImages({ url: urlList?.[0], previewUrlList: urlList, zIndex: el?.zIndex, backDropZIndex: el?.backDropZIndex - }) - } - custom.close = () => unmountedPreviewImages() + }); + }; + custom.close = () => unmountedPreviewImages(); } if (disableDefault) { - return + return; } - handleImgByEl(el) + handleImgByEl(el); }, unmounted() { - unmountedPreviewImages() + unmountedPreviewImages(); }, updated(el: PreviewHTMLElement, binding: UpdateBindingTypes | undefined) { - el.zIndex = binding.value?.zIndex - el.backDropZIndex = binding.value?.backDropZIndex + el.zIndex = binding.value?.zIndex; + el.backDropZIndex = binding.value?.backDropZIndex; if (binding.value) { const { value: { disableDefault }, oldValue: { disableDefault: oldDisableDefault } - } = binding + } = binding; if (disableDefault !== oldDisableDefault) { if (disableDefault) { - removeHandle(el) + removeHandle(el); } else { - handleImgByEl(el) + handleImgByEl(el); } } } } -} +}; diff --git a/packages/devui-vue/devui/image-preview/src/image-preview-service.ts b/packages/devui-vue/devui/image-preview/src/image-preview-service.ts index fd26b5c9e4..866f12464e 100644 --- a/packages/devui-vue/devui/image-preview/src/image-preview-service.ts +++ b/packages/devui-vue/devui/image-preview/src/image-preview-service.ts @@ -1,34 +1,34 @@ -import { createApp } from 'vue' -import { ImagePreviewProps } from './image-preview-types' -import imagePreview from './image-preview' +import { createApp } from 'vue'; +import { ImagePreviewProps } from './image-preview-types'; +import imagePreview from './image-preview'; function createComponent(props: ImagePreviewProps) { - return createApp(imagePreview, props) + return createApp(imagePreview, props); } class ImagePreviewService { - static $body: HTMLElement | null = null - static $div: HTMLDivElement | null = null + static $body: HTMLElement | null = null; + static $div: HTMLDivElement | null = null; // 暂时的禁止滚动穿透,后续应该考虑用modal组件来渲染预览组件 - static $overflow = '' + static $overflow = ''; static open(props: ImagePreviewProps) { - this.$body = document.body - this.$div = document.createElement('div') - this.$overflow = this.$body.style.overflow - this.$body.appendChild(this.$div) - createComponent(props).mount(this.$div) + this.$body = document.body; + this.$div = document.createElement('div'); + this.$overflow = this.$body.style.overflow; + this.$body.appendChild(this.$div); + createComponent(props).mount(this.$div); - this.$body.style.setProperty('overflow', 'hidden', 'important') + this.$body.style.setProperty('overflow', 'hidden', 'important'); } static close() { - this.$body?.style.setProperty('overflow', this.$overflow) - this.$overflow = null + this.$body?.style.setProperty('overflow', this.$overflow); + this.$overflow = null; - this.$div && this.$body.removeChild(this.$div) - this.$body = null - this.$div = null + this.$div && this.$body.removeChild(this.$div); + this.$body = null; + this.$div = null; } } -export default ImagePreviewService +export default ImagePreviewService; diff --git a/packages/devui-vue/devui/image-preview/src/image-preview-types.ts b/packages/devui-vue/devui/image-preview/src/image-preview-types.ts index 3f2cfa62ea..89d5698be3 100644 --- a/packages/devui-vue/devui/image-preview/src/image-preview-types.ts +++ b/packages/devui-vue/devui/image-preview/src/image-preview-types.ts @@ -1,4 +1,4 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; export const imagePreviewProps = { url: { @@ -19,18 +19,18 @@ export const imagePreviewProps = { type: Number, required: false } -} as const +} as const; export interface BindingTypes { value: { - custom?: any - disableDefault?: boolean - zIndex?: number - backDropZIndex?: number - } - [key: string]: any + custom?: any; + disableDefault?: boolean; + zIndex?: number; + backDropZIndex?: number; + }; + [key: string]: any; } export interface UpdateBindingTypes extends BindingTypes { - oldValue: BindingTypes['value'] + oldValue: BindingTypes['value']; } -export type ImagePreviewProps = ExtractPropTypes<typeof imagePreviewProps> +export type ImagePreviewProps = ExtractPropTypes<typeof imagePreviewProps>; diff --git a/packages/devui-vue/devui/image-preview/src/image-preview.tsx b/packages/devui-vue/devui/image-preview/src/image-preview.tsx index 052e73dbbc..78d3145b50 100644 --- a/packages/devui-vue/devui/image-preview/src/image-preview.tsx +++ b/packages/devui-vue/devui/image-preview/src/image-preview.tsx @@ -1,81 +1,81 @@ -import './image-preview.scss' -import { defineComponent, Fragment, ref, computed, onMounted, onUnmounted } from 'vue' -import { imagePreviewProps, ImagePreviewProps } from './image-preview-types' -import ImagePreviewService from './image-preview-service' -import Transform from './transform' +import './image-preview.scss'; +import { defineComponent, Fragment, ref, computed, onMounted, onUnmounted } from 'vue'; +import { imagePreviewProps, ImagePreviewProps } from './image-preview-types'; +import ImagePreviewService from './image-preview-service'; +import Transform from './transform'; export default defineComponent({ name: 'DImagePreview', props: imagePreviewProps, emits: [], setup(props: ImagePreviewProps) { - let transform: Transform = null - const index = ref(0) - const url = computed(() => props.previewUrlList[index.value]) + let transform: Transform = null; + const index = ref(0); + const url = computed(() => props.previewUrlList[index.value]); - const imageStyle = props.zIndex ? { zIndex: props.zIndex } : {} - const bgStyle = props.backDropZIndex ? { zIndex: props.backDropZIndex } : {} + const imageStyle = props.zIndex ? { zIndex: props.zIndex } : {}; + const bgStyle = props.backDropZIndex ? { zIndex: props.backDropZIndex } : {}; function initTransform() { const imageElement: HTMLImageElement = document.querySelector( '.devui-image-preview-main-image' - ) - transform = new Transform(imageElement) + ); + transform = new Transform(imageElement); } function initIndex() { - index.value = props.previewUrlList.findIndex((curUrl) => curUrl === props.url) + index.value = props.previewUrlList.findIndex((curUrl) => curUrl === props.url); } function onPrev() { - index.value = index.value <= 0 ? props.previewUrlList.length - 1 : index.value - 1 + index.value = index.value <= 0 ? props.previewUrlList.length - 1 : index.value - 1; } function onNext() { - index.value = index.value >= props.previewUrlList.length - 1 ? 0 : index.value + 1 + index.value = index.value >= props.previewUrlList.length - 1 ? 0 : index.value + 1; } function onClose() { - ImagePreviewService.close() + ImagePreviewService.close(); } function onZoomIn() { - transform.setZoomIn() + transform.setZoomIn(); } function onZoomOut() { - transform.setZoomOut() + transform.setZoomOut(); } function onRotate() { - transform.setRotate() + transform.setRotate(); } function onZoomBest() { - transform.setZoomBest() + transform.setZoomBest(); } function onZoomOriginal() { - transform.setZoomOriginal() + transform.setZoomOriginal(); } function onKeyDown(event: KeyboardEvent) { - if (event.defaultPrevented) return + if (event.defaultPrevented) {return;} if (event.code == 'Escape') { - onClose() + onClose(); } else if (event.code == 'ArrowLeft') { - onPrev() + onPrev(); } else if (event.code == 'ArrowRight') { - onNext() + onNext(); } } function initKeyboard() { - document.addEventListener('keydown', onKeyDown, false) + document.addEventListener('keydown', onKeyDown, false); } function unKeyBoard() { - document.removeEventListener('keydown', onKeyDown, false) + document.removeEventListener('keydown', onKeyDown, false); } onMounted(() => { - initIndex() - initTransform() - initKeyboard() - }) + initIndex(); + initTransform(); + initKeyboard(); + }); onUnmounted(() => { - unKeyBoard() - }) + unKeyBoard(); + }); return () => { return ( @@ -192,7 +192,7 @@ export default defineComponent({ </div> <div class='devui-image-preview-bg' style={bgStyle}></div> </Fragment> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/image-preview/src/transform.ts b/packages/devui-vue/devui/image-preview/src/transform.ts index ff35f90fab..4861727737 100644 --- a/packages/devui-vue/devui/image-preview/src/transform.ts +++ b/packages/devui-vue/devui/image-preview/src/transform.ts @@ -1,130 +1,130 @@ interface Options { - transformX?: number - transformY?: number - zoom?: number - rotate?: number + transformX?: number; + transformY?: number; + zoom?: number; + rotate?: number; } interface HTMLElementPlus extends HTMLElement { - onmousewheel?: (...args: any[]) => void + onmousewheel?: (...args: any[]) => void; } export default class Transform { - private el: HTMLElementPlus + private el: HTMLElementPlus; - private oTransformX = 0 - private oTransformY = 0 - private transformX: number - private transformY: number - private zoom: number - private rotate: number + private oTransformX = 0; + private oTransformY = 0; + private transformX: number; + private transformY: number; + private zoom: number; + private rotate: number; - private STEP = 0.25 - private MIN_SCALE = 0.2 - private MAX_SCALE = 2.5 - private TRANSFORMX = 0 - private TRANSFORMY = 0 - private ZOOM = 1 - private ROTATE = 0 + private STEP = 0.25; + private MIN_SCALE = 0.2; + private MAX_SCALE = 2.5; + private TRANSFORMX = 0; + private TRANSFORMY = 0; + private ZOOM = 1; + private ROTATE = 0; constructor(el: HTMLElementPlus, options: Options = {}) { - this.el = el - this.transformX = options.transformX || this.TRANSFORMX - this.transformY = options.transformY || this.TRANSFORMY - this.zoom = options.zoom || this.ZOOM - this.rotate = options.rotate || this.ROTATE + this.el = el; + this.transformX = options.transformX || this.TRANSFORMX; + this.transformY = options.transformY || this.TRANSFORMY; + this.zoom = options.zoom || this.ZOOM; + this.rotate = options.rotate || this.ROTATE; - this.handleDefaultDraggable() - this.onDraggable() - this.onMouseWheel() + this.handleDefaultDraggable(); + this.onDraggable(); + this.onMouseWheel(); } handleDefaultDraggable() { document.body.ondragstart = () => { - window.event.returnValue = false - return false - } + window.event.returnValue = false; + return false; + }; } onDraggable() { this.el.onmousedown = (e: MouseEvent) => { - const ox = e.clientX - const oy = e.clientY + const ox = e.clientX; + const oy = e.clientY; document.onmousemove = (e1: MouseEvent) => { - const disX = e1.clientX - ox - const disY = e1.clientY - oy - this.transformX = this.oTransformX + disX - this.transformY = this.oTransformY + disY - this.el.style.cursor = 'grabbing' - this.setPosition() - } - } + const disX = e1.clientX - ox; + const disY = e1.clientY - oy; + this.transformX = this.oTransformX + disX; + this.transformY = this.oTransformY + disY; + this.el.style.cursor = 'grabbing'; + this.setPosition(); + }; + }; document.onmouseup = () => { - document.onmousemove = null - this.oTransformX = this.transformX - this.oTransformY = this.transformY - this.el.style.cursor = 'grab' - } + document.onmousemove = null; + this.oTransformX = this.transformX; + this.oTransformY = this.transformY; + this.el.style.cursor = 'grab'; + }; } onMouseWheel() { - const handleWheel = this.throttle(this.setMouseWheel, 100) + const handleWheel = this.throttle(this.setMouseWheel, 100); this.el.onmousewheel = e => { - const value: number = -e.wheelDelta || e.deltaY || e.detail - handleWheel(value) - } + const value: number = -e.wheelDelta || e.deltaY || e.detail; + handleWheel(value); + }; } throttle(fn: (...args: any[]) => void, t: number) { - let timer = null + let timer = null; return (...args) => { if (!timer) { setTimeout(() => { - timer = null - fn.apply(this, args) - }, t) + timer = null; + fn.apply(this, args); + }, t); } - } + }; } setMouseWheel(value: number) { if (value < 0) { if (this.zoom >= this.MAX_SCALE) { - this.el.style.cursor = 'not-allowed' - return + this.el.style.cursor = 'not-allowed'; + return; } - this.el.style.cursor = 'zoom-in' - this.setZoomIn(this.STEP) + this.el.style.cursor = 'zoom-in'; + this.setZoomIn(this.STEP); } else { if (this.zoom <= this.MIN_SCALE) { - this.el.style.cursor = 'not-allowed' - return + this.el.style.cursor = 'not-allowed'; + return; } - this.el.style.cursor = 'zoom-out' - this.setZoomOut(this.STEP) + this.el.style.cursor = 'zoom-out'; + this.setZoomOut(this.STEP); } - this.setPosition() + this.setPosition(); } setZoomIn(step = this.STEP) { - this.zoom = Math.min(this.MAX_SCALE, this.zoom + step) - this.setPosition() + this.zoom = Math.min(this.MAX_SCALE, this.zoom + step); + this.setPosition(); } setZoomOut(step = this.STEP) { - this.zoom = Math.max(this.MIN_SCALE, this.zoom - step) - this.setPosition() + this.zoom = Math.max(this.MIN_SCALE, this.zoom - step); + this.setPosition(); } setZoomBest() { - this.reset() - this.setPosition() + this.reset(); + this.setPosition(); } setZoomOriginal() { - this.reset() - this.setPosition() + this.reset(); + this.setPosition(); } setRotate() { - this.rotate += 0.25 - this.setPosition() + this.rotate += 0.25; + this.setPosition(); } reset() { - this.transformX = this.TRANSFORMX - this.transformY = this.TRANSFORMY - this.zoom = this.ZOOM + this.transformX = this.TRANSFORMX; + this.transformY = this.TRANSFORMY; + this.zoom = this.ZOOM; } setPosition() { - this.el.style.transform = `translate(${this.transformX}px, ${this.transformY}px) scale(${this.zoom}) rotate(${this.rotate}turn)` + this.el.style.transform = `translate(${this.transformX}px, ${this.transformY}px) scale(${this.zoom}) rotate(${this.rotate}turn)`; } } diff --git a/packages/devui-vue/devui/input-icon/index.ts b/packages/devui-vue/devui/input-icon/index.ts index 01e76773fb..e03ff63f32 100644 --- a/packages/devui-vue/devui/input-icon/index.ts +++ b/packages/devui-vue/devui/input-icon/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import InputIcon from './src/input-icon' +import type { App } from 'vue'; +import InputIcon from './src/input-icon'; InputIcon.install = function(app: App) { - app.component(InputIcon.name, InputIcon) -} + app.component(InputIcon.name, InputIcon); +}; -export { InputIcon } +export { InputIcon }; export default { title: 'InputIcon输入框', category: '数据录入', status: '75%', install(app: App): void { - app.use(InputIcon as any) + app.use(InputIcon as any); } -} +}; diff --git a/packages/devui-vue/devui/input-icon/src/input-icon.tsx b/packages/devui-vue/devui/input-icon/src/input-icon.tsx index 34a9b34c01..2fe009c2e1 100644 --- a/packages/devui-vue/devui/input-icon/src/input-icon.tsx +++ b/packages/devui-vue/devui/input-icon/src/input-icon.tsx @@ -1,55 +1,55 @@ -import { defineComponent, reactive, PropType } from 'vue' -import Input from '../../input/src/input' -import { inputProps } from '../../input/src/use-input' -import Icon from '../../icon/src/icon' +import { defineComponent, reactive, PropType } from 'vue'; +import Input from '../../input/src/input'; +import { inputProps } from '../../input/src/use-input'; +import Icon from '../../icon/src/icon'; -import './input-icon.scss' +import './input-icon.scss'; const inputIconProps = { - ...inputProps, - name: { - type: String, - value: 'calendar', - required: false, - }, - onIconclick: { - type: Function as PropType<(e: MouseEvent) => void>, - required: false, - }, - iconBgColor: { - type: String, - value: 'transparent', - }, - iconColor: { - type: String, - value: '#000000', - } -} + ...inputProps, + name: { + type: String, + value: 'calendar', + required: false, + }, + onIconclick: { + type: Function as PropType<(e: MouseEvent) => void>, + required: false, + }, + iconBgColor: { + type: String, + value: 'transparent', + }, + iconColor: { + type: String, + value: '#000000', + } +}; export default defineComponent({ - name: 'DInputIcon', - props: inputIconProps, - setup(props, ctx) { - const { name, onIconclick, onChange, iconBgColor, iconColor, ...inputProps } = props - const state = reactive({ value: '' }) - const onInputChange = (v: string) => { - state.value = v - typeof onChange === 'function' && onChange(state.value) - } - const onIconClick = (e: MouseEvent) => { - typeof onIconclick === 'function' && onIconclick(state.value, e) - } - return () => { - return ( - <div class="d-input-icon-container"> - <label> - <Input { ...inputProps } onChange={onInputChange} /> - </label> - <span onClick={onIconClick} style={{ backgroundColor: iconBgColor }}> - <Icon size="small" name={name} color={iconColor} /> - </span> - </div> - ) - } - }, -}) + name: 'DInputIcon', + props: inputIconProps, + setup(props, ctx) { + const { name, onIconclick, onChange, iconBgColor, iconColor, ...inputProps } = props; + const state = reactive({ value: '' }); + const onInputChange = (v: string) => { + state.value = v; + typeof onChange === 'function' && onChange(state.value); + }; + const onIconClick = (e: MouseEvent) => { + typeof onIconclick === 'function' && onIconclick(state.value, e); + }; + return () => { + return ( + <div class="d-input-icon-container"> + <label> + <Input { ...inputProps } onChange={onInputChange} /> + </label> + <span onClick={onIconClick} style={{ backgroundColor: iconBgColor }}> + <Icon size="small" name={name} color={iconColor} /> + </span> + </div> + ); + }; + }, +}); diff --git a/packages/devui-vue/devui/input-number/index.ts b/packages/devui-vue/devui/input-number/index.ts index d2fea5f95f..98a7902e71 100644 --- a/packages/devui-vue/devui/input-number/index.ts +++ b/packages/devui-vue/devui/input-number/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import InputNumber from './src/input-number' +import type { App } from 'vue'; +import InputNumber from './src/input-number'; InputNumber.install = function(app: App) { - app.component(InputNumber.name, InputNumber) -} + app.component(InputNumber.name, InputNumber); +}; -export { InputNumber } +export { InputNumber }; export default { title: 'InputNumber 数字输入框', category: '数据录入', status: '50%', - install(app: App):void { - app.use(InputNumber as any) + install(app: App): void { + app.use(InputNumber as any); } -} +}; diff --git a/packages/devui-vue/devui/input-number/src/input-number-types.ts b/packages/devui-vue/devui/input-number/src/input-number-types.ts index 9dc1b00223..c8d356a4f7 100644 --- a/packages/devui-vue/devui/input-number/src/input-number-types.ts +++ b/packages/devui-vue/devui/input-number/src/input-number-types.ts @@ -1,4 +1,4 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; export const inputNumberProps = { placeholder: { @@ -49,6 +49,6 @@ export const inputNumberProps = { type: Function as PropType<() => void>, default: undefined } -} as const +} as const; -export type InputNumberProps = ExtractPropTypes<typeof inputNumberProps> +export type InputNumberProps = ExtractPropTypes<typeof inputNumberProps>; diff --git a/packages/devui-vue/devui/input-number/src/input-number.tsx b/packages/devui-vue/devui/input-number/src/input-number.tsx index 842f0a192d..de60d57698 100644 --- a/packages/devui-vue/devui/input-number/src/input-number.tsx +++ b/packages/devui-vue/devui/input-number/src/input-number.tsx @@ -22,10 +22,10 @@ export default defineComponent({ return props.disabled; }); - //新增 + // 新增 const add = () => { - if (props.disabled) return; - if (inputVal.value >= props.max) return; + if (props.disabled) {return;} + if (inputVal.value >= props.max) {return;} inputVal.value += props.step != 0 ? props.step : 1; focusVal.value = 'active'; ctx.emit('change', inputVal.value); @@ -33,8 +33,8 @@ export default defineComponent({ }; // 减少 const subtract = () => { - if (props.disabled) return; - if (inputVal.value <= props.min) return; + if (props.disabled) {return;} + if (inputVal.value <= props.min) {return;} inputVal.value -= props.step != 0 ? props.step : 1; focusVal.value = 'active'; ctx.emit('change', inputVal.value); diff --git a/packages/devui-vue/devui/input/__tests__/input.spec.ts b/packages/devui-vue/devui/input/__tests__/input.spec.ts index 3377eac590..14e5505dcc 100644 --- a/packages/devui-vue/devui/input/__tests__/input.spec.ts +++ b/packages/devui-vue/devui/input/__tests__/input.spec.ts @@ -1,10 +1,10 @@ -import { mount } from '@vue/test-utils' -import { ref, nextTick } from 'vue' -import DInput from '../src/input' +import { mount } from '@vue/test-utils'; +import { ref, nextTick } from 'vue'; +import DInput from '../src/input'; describe('d-input', () => { it('d-input render work', async () => { - const value = ref('abc') + const value = ref('abc'); const wrapper = mount({ components: { DInput }, template: ` @@ -13,26 +13,26 @@ describe('d-input', () => { setup() { return { value - } + }; } - }) - const input = wrapper.find('input') - expect(input.attributes('dinput')).toBe('true') - expect(input.element.value).toBe('abc') + }); + const input = wrapper.find('input'); + expect(input.attributes('dinput')).toBe('true'); + expect(input.element.value).toBe('abc'); - await input.setValue('def') - expect(value.value).toBe('def') + await input.setValue('def'); + expect(value.value).toBe('def'); - value.value = 'thx' - await nextTick() - expect(input.element.value).toBe('thx') - }) + value.value = 'thx'; + await nextTick(); + expect(input.element.value).toBe('thx'); + }); it('d-input bindEvents work', async () => { const onChange = jest.fn(), onFocus = jest.fn(), onBlur = jest.fn(), - onKeydown = jest.fn() + onKeydown = jest.fn(); const wrapper = mount({ components: { DInput }, template: ` @@ -48,82 +48,82 @@ describe('d-input', () => { onFocus, onBlur, onKeydown - } + }; } - }) - const input = wrapper.find('input') + }); + const input = wrapper.find('input'); - await input.trigger('change') - expect(onChange).toBeCalledTimes(1) + await input.trigger('change'); + expect(onChange).toBeCalledTimes(1); - await input.trigger('focus') - expect(onFocus).toBeCalledTimes(1) + await input.trigger('focus'); + expect(onFocus).toBeCalledTimes(1); - await input.trigger('blur') - expect(onBlur).toBeCalledTimes(1) + await input.trigger('blur'); + expect(onBlur).toBeCalledTimes(1); - await input.trigger('keydown') - expect(onKeydown).toBeCalledTimes(1) - }) + await input.trigger('keydown'); + expect(onKeydown).toBeCalledTimes(1); + }); it('d-input disabled work', async () => { const wrapper = mount(DInput, { props: { disabled: false } - }) - const input = wrapper.find('input') - expect(input.attributes('disabled')).toBe(undefined) + }); + const input = wrapper.find('input'); + expect(input.attributes('disabled')).toBe(undefined); await wrapper.setProps({ disabled: true - }) - expect(input.attributes('disabled')).toBe('') - }) + }); + expect(input.attributes('disabled')).toBe(''); + }); it('d-input error work', async () => { const wrapper = mount(DInput, { props: { error: false } - }) - const input = wrapper.find('input') - expect(input.classes()).not.toContain('error') + }); + const input = wrapper.find('input'); + expect(input.classes()).not.toContain('error'); await wrapper.setProps({ error: true - }) - expect(input.classes()).toContain('error') - }) + }); + expect(input.classes()).toContain('error'); + }); it('d-input size work', async () => { - const wrapper = mount(DInput) - const input = wrapper.find('input') - expect(input.classes()).not.toContain('devui-input-sm') - expect(input.classes()).not.toContain('devui-input-lg') + const wrapper = mount(DInput); + const input = wrapper.find('input'); + expect(input.classes()).not.toContain('devui-input-sm'); + expect(input.classes()).not.toContain('devui-input-lg'); await wrapper.setProps({ size: 'sm' - }) - expect(input.classes()).toContain('devui-input-sm') - expect(input.classes()).not.toContain('devui-input-lg') + }); + expect(input.classes()).toContain('devui-input-sm'); + expect(input.classes()).not.toContain('devui-input-lg'); await wrapper.setProps({ size: 'lg' - }) - expect(input.classes()).not.toContain('devui-input-sm') - expect(input.classes()).toContain('devui-input-lg') - }) + }); + expect(input.classes()).not.toContain('devui-input-sm'); + expect(input.classes()).toContain('devui-input-lg'); + }); it('d-input showPassword work', async () => { - const wrapper = mount(DInput) - const input = wrapper.find('input') + const wrapper = mount(DInput); + const input = wrapper.find('input'); - expect(input.attributes('type')).toBe('text') + expect(input.attributes('type')).toBe('text'); await wrapper.setProps({ showPassword: true - }) - expect(input.attributes('type')).toBe('password') - }) -}) + }); + expect(input.attributes('type')).toBe('password'); + }); +}); diff --git a/packages/devui-vue/devui/input/index.ts b/packages/devui-vue/devui/input/index.ts index 94c018b840..9821ac7c86 100644 --- a/packages/devui-vue/devui/input/index.ts +++ b/packages/devui-vue/devui/input/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Input from './src/input' +import type { App } from 'vue'; +import Input from './src/input'; Input.install = function(app: App) { - app.component(Input.name, Input) -} + app.component(Input.name, Input); +}; -export { Input } +export { Input }; export default { title: 'Input 输入框', category: '数据录入', status: '100%', install(app: App): void { - app.use(Input as any) + app.use(Input as any); } -} +}; diff --git a/packages/devui-vue/devui/input/src/input.tsx b/packages/devui-vue/devui/input/src/input.tsx index bc204c44cd..1b30ae17f5 100644 --- a/packages/devui-vue/devui/input/src/input.tsx +++ b/packages/devui-vue/devui/input/src/input.tsx @@ -1,7 +1,7 @@ -import { defineComponent, computed, ref, watch, inject } from 'vue' -import { inputProps, InputType } from './use-input' -import './input.scss' -import { dFormItemEvents, IFormItem, formItemInjectionKey } from '../../form/src/form-types' +import { defineComponent, computed, ref, watch, inject } from 'vue'; +import { inputProps, InputType } from './use-input'; +import './input.scss'; +import { dFormItemEvents, IFormItem, formItemInjectionKey } from '../../form/src/form-types'; export default defineComponent({ name: 'DInput', @@ -9,7 +9,7 @@ export default defineComponent({ focus: { mounted: function (el, binding) { if (binding.value) { - el.focus() + el.focus(); } } } @@ -17,50 +17,50 @@ export default defineComponent({ props: inputProps, emits: ['update:modelValue', 'focus', 'blur', 'change', 'keydown'], setup(props, ctx) { - const formItem = inject(formItemInjectionKey, {} as IFormItem) - const hasFormItem = Object.keys(formItem).length > 0 - const sizeCls = computed(() => `devui-input-${props.size}`) - const showPwdIcon = ref(false) - const inputType = ref<InputType>('text') + const formItem = inject(formItemInjectionKey, {} as IFormItem); + const hasFormItem = Object.keys(formItem).length > 0; + const sizeCls = computed(() => `devui-input-${props.size}`); + const showPwdIcon = ref(false); + const inputType = ref<InputType>('text'); const inputCls = computed(() => { return { error: props.error, [props.cssClass]: true, 'devui-input-restore': showPwdIcon.value, [sizeCls.value]: props.size !== '' - } - }) - const showPreviewIcon = computed(() => inputType.value === 'password') + }; + }); + const showPreviewIcon = computed(() => inputType.value === 'password'); watch( () => props.showPassword, (flg) => { - inputType.value = flg ? 'password' : 'text' - showPwdIcon.value = props.showPassword + inputType.value = flg ? 'password' : 'text'; + showPwdIcon.value = props.showPassword; }, { immediate: true } - ) + ); const onInput = ($event: Event) => { - ctx.emit('update:modelValue', ($event.target as HTMLInputElement).value) - hasFormItem && formItem.formItemMitt.emit(dFormItemEvents.input) + ctx.emit('update:modelValue', ($event.target as HTMLInputElement).value); + hasFormItem && formItem.formItemMitt.emit(dFormItemEvents.input); }, onFocus = () => { - ctx.emit('focus') + ctx.emit('focus'); }, onBlur = () => { - ctx.emit('blur') - hasFormItem && formItem.formItemMitt.emit(dFormItemEvents.blur) + ctx.emit('blur'); + hasFormItem && formItem.formItemMitt.emit(dFormItemEvents.blur); }, onChange = ($event: Event) => { - ctx.emit('change', ($event.target as HTMLInputElement).value) - hasFormItem && formItem.formItemMitt.emit(dFormItemEvents.change) + ctx.emit('change', ($event.target as HTMLInputElement).value); + hasFormItem && formItem.formItemMitt.emit(dFormItemEvents.change); }, onKeydown = ($event: KeyboardEvent) => { - ctx.emit('keydown', $event) + ctx.emit('keydown', $event); }, onChangeInputType = () => { - inputType.value = inputType.value === 'password' ? 'text' : 'password' - } + inputType.value = inputType.value === 'password' ? 'text' : 'password'; + }; return { inputCls, inputType, @@ -72,7 +72,7 @@ export default defineComponent({ onChange, onKeydown, onChangeInputType - } + }; }, render() { const { @@ -91,7 +91,7 @@ export default defineComponent({ onChange, onKeydown, onChangeInputType - } = this + } = this; return ( <div class='devui-input__wrap'> <input @@ -119,6 +119,6 @@ export default defineComponent({ </div> )} </div> - ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/input/src/use-input.tsx b/packages/devui-vue/devui/input/src/use-input.tsx index 8a46ec40a2..7042d4f3b4 100644 --- a/packages/devui-vue/devui/input/src/use-input.tsx +++ b/packages/devui-vue/devui/input/src/use-input.tsx @@ -1,4 +1,4 @@ -import { PropType } from 'vue' +import { PropType } from 'vue'; export const inputProps = { placeholder: { @@ -57,7 +57,7 @@ export const inputProps = { type: Function as PropType<() => void>, default: undefined } -} as const +} as const; -export type PreviewIconType = 'preview' | 'icon-preview-forbidden' -export type InputType = 'password' | 'text' +export type PreviewIconType = 'preview' | 'icon-preview-forbidden'; +export type InputType = 'password' | 'text'; diff --git a/packages/devui-vue/devui/layout/index.ts b/packages/devui-vue/devui/layout/index.ts index fe207d20ca..7129e0a3a6 100644 --- a/packages/devui-vue/devui/layout/index.ts +++ b/packages/devui-vue/devui/layout/index.ts @@ -1,41 +1,41 @@ -import type { App } from 'vue' -import Layout from './src/layout' -import Content from './src/content' -import Header from './src/header' -import Footer from './src/footer' -import Aside from './src/aside' +import type { App } from 'vue'; +import Layout from './src/layout'; +import Content from './src/content'; +import Header from './src/header'; +import Footer from './src/footer'; +import Aside from './src/aside'; Layout.install = function(app: App): void { - app.component(Layout.name, Layout) -} + app.component(Layout.name, Layout); +}; Content.install = function(app: App): void { - app.component(Content.name, Content) -} + app.component(Content.name, Content); +}; Header.install = function(app: App): void { - app.component(Header.name, Header) -} + app.component(Header.name, Header); +}; Footer.install = function(app: App): void { - app.component(Footer.name, Footer) -} + app.component(Footer.name, Footer); +}; Aside.install = function(app: App): void { - app.component(Aside.name, Aside) -} + app.component(Aside.name, Aside); +}; -export { Layout, Content, Header, Footer, Aside } +export { Layout, Content, Header, Footer, Aside }; export default { title: 'Layout 布局', category: '布局', status: '100%', install(app: App): void { - app.use(Layout as any) - app.use(Content as any) - app.use(Header as any) - app.use(Footer as any) - app.use(Aside as any) + app.use(Layout as any); + app.use(Content as any); + app.use(Header as any); + app.use(Footer as any); + app.use(Aside as any); } -} +}; diff --git a/packages/devui-vue/devui/layout/src/aside.tsx b/packages/devui-vue/devui/layout/src/aside.tsx index ca650fdce7..1db9229866 100644 --- a/packages/devui-vue/devui/layout/src/aside.tsx +++ b/packages/devui-vue/devui/layout/src/aside.tsx @@ -1,8 +1,8 @@ -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; export default defineComponent({ - name: 'DAside', - setup (props, { slots }) { - return () => <div>{ slots.default?.() }</div> - } -}) \ No newline at end of file + name: 'DAside', + setup (props, { slots }) { + return () => <div>{ slots.default?.() }</div>; + } +}); diff --git a/packages/devui-vue/devui/layout/src/content.tsx b/packages/devui-vue/devui/layout/src/content.tsx index d2caaecd19..b19b24e171 100644 --- a/packages/devui-vue/devui/layout/src/content.tsx +++ b/packages/devui-vue/devui/layout/src/content.tsx @@ -1,10 +1,10 @@ -import './content.scss' +import './content.scss'; -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; export default defineComponent({ - name: 'DContent', - setup (props, { slots }) { - return () => <div class="devui-content">{slots.default?.()}</div> - } -}) \ No newline at end of file + name: 'DContent', + setup (props, { slots }) { + return () => <div class="devui-content">{slots.default?.()}</div>; + } +}); diff --git a/packages/devui-vue/devui/layout/src/footer.tsx b/packages/devui-vue/devui/layout/src/footer.tsx index 457ae984d5..defe2f730f 100644 --- a/packages/devui-vue/devui/layout/src/footer.tsx +++ b/packages/devui-vue/devui/layout/src/footer.tsx @@ -1,10 +1,10 @@ -import './footer.scss' +import './footer.scss'; -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; export default defineComponent({ - name: 'DFooter', - setup (props, { slots }) { - return () => <div class="devui-footer">{ slots.default?.() }</div> - } -}) \ No newline at end of file + name: 'DFooter', + setup (props, { slots }) { + return () => <div class="devui-footer">{ slots.default?.() }</div>; + } +}); diff --git a/packages/devui-vue/devui/layout/src/header.tsx b/packages/devui-vue/devui/layout/src/header.tsx index e723aff3ab..a0f368cf8b 100644 --- a/packages/devui-vue/devui/layout/src/header.tsx +++ b/packages/devui-vue/devui/layout/src/header.tsx @@ -1,10 +1,10 @@ -import './header.scss' +import './header.scss'; -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; export default defineComponent({ - name: 'DHeader', - setup (props, { slots }) { - return () => <div class="devui-header">{ slots.default?.() }</div> - } -}) \ No newline at end of file + name: 'DHeader', + setup (props, { slots }) { + return () => <div class="devui-header">{ slots.default?.() }</div>; + } +}); diff --git a/packages/devui-vue/devui/layout/src/layout.tsx b/packages/devui-vue/devui/layout/src/layout.tsx index da9306451c..52817a5c68 100644 --- a/packages/devui-vue/devui/layout/src/layout.tsx +++ b/packages/devui-vue/devui/layout/src/layout.tsx @@ -1,16 +1,16 @@ -import './layout.scss' +import './layout.scss'; -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; export default defineComponent({ name: 'DLayout', emits: [], setup(props, { slots }) { return () => { - const slotDefault = slots.default?.() - const isAside = slotDefault.some(item => (item.type as any).name === 'DAside') - const classNames = `${isAside ? 'devui-layout-aside ': ''}devui-layout` - return <div class={classNames}>{ slotDefault }</div> - } + const slotDefault = slots.default?.(); + const isAside = slotDefault.some(item => (item.type as any).name === 'DAside'); + const classNames = `${isAside ? 'devui-layout-aside ': ''}devui-layout`; + return <div class={classNames}>{ slotDefault }</div>; + }; } -}) +}); diff --git a/packages/devui-vue/devui/loading/index.ts b/packages/devui-vue/devui/loading/index.ts index 64c98597c6..7f68b056d0 100644 --- a/packages/devui-vue/devui/loading/index.ts +++ b/packages/devui-vue/devui/loading/index.ts @@ -1,18 +1,18 @@ -import { App } from 'vue' -import Loading from './src/directive' -import LoadingService from './src/service' +import { App } from 'vue'; +import Loading from './src/directive'; +import LoadingService from './src/service'; export { LoadingService, Loading -} +}; export default { title: 'Loading 加载提示', category: '反馈', status: '100%', install(app: App): void { - app.directive('dLoading', Loading) - app.config.globalProperties.$loadingService = LoadingService + app.directive('dLoading', Loading); + app.config.globalProperties.$loadingService = LoadingService; } -} +}; diff --git a/packages/devui-vue/devui/loading/src/loading.tsx b/packages/devui-vue/devui/loading/src/loading.tsx index 60234c0a46..64e2185cb8 100644 --- a/packages/devui-vue/devui/loading/src/loading.tsx +++ b/packages/devui-vue/devui/loading/src/loading.tsx @@ -1,5 +1,5 @@ -import { CSSProperties, defineComponent, ref } from 'vue' -import { componentProps, ComponentProps } from './types' +import { CSSProperties, defineComponent, ref } from 'vue'; +import { componentProps, ComponentProps } from './types'; import './loading.scss'; @@ -13,26 +13,26 @@ export default defineComponent({ top: props.view.top, left: props.view.left, zIndex: props.zIndex - } + }; if (!props.message) { - style.background = 'none' + style.background = 'none'; } - const isShow = ref(false) + const isShow = ref(false); const open = () => { - isShow.value = true - } + isShow.value = true; + }; const close = () => { - isShow.value = false - } + isShow.value = false; + }; return { style, isShow, open, close - } + }; }, render() { const { @@ -42,7 +42,7 @@ export default defineComponent({ style, message, $slots - } = this + } = this; return ( isShow && @@ -71,6 +71,6 @@ export default defineComponent({ </div> } </div> - ) + ); } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/loading/src/types.ts b/packages/devui-vue/devui/loading/src/types.ts index 32e3dd03d3..f23abf9f4f 100644 --- a/packages/devui-vue/devui/loading/src/types.ts +++ b/packages/devui-vue/devui/loading/src/types.ts @@ -1,22 +1,22 @@ -import { ExtractPropTypes, PropType, VNode } from 'vue' +import { ExtractPropTypes, PropType, VNode } from 'vue'; -type PositionType = 'static' | 'relative' | 'absolute' | 'fixed' |'sticky' +type PositionType = 'static' | 'relative' | 'absolute' | 'fixed' |'sticky'; export interface LoadingType { - value: Promise<any> | Array<Promise<any>> | undefined + value: Promise<any> | Array<Promise<any>> | undefined; } export interface BindingType extends LoadingType { - [key: string] : any + [key: string]: any; } export interface TargetHTMLElement extends HTMLElement { - mask ?: HTMLElement - instance ?: VNode | any - options ?: LoadingProps + mask?: HTMLElement; + instance?: VNode | any; + options?: LoadingProps; } class View { - top ?: string = '50%' - left?: string = '50%' + top?: string = '50%'; + left?: string = '50%'; } export const componentProps = { message: String, @@ -30,16 +30,16 @@ export const componentProps = { type: Boolean, default: false } -} as const +} as const; export class LoadingProps { - target ?: Element | null - message ?: string - loadingTemplateRef ?: any - backdrop ?: boolean = true - positionType ?: PositionType = 'relative' - view ?: View = new View() - zIndex ?: number + target?: Element | null; + message?: string; + loadingTemplateRef?: any; + backdrop?: boolean = true; + positionType?: PositionType = 'relative'; + view?: View = new View(); + zIndex?: number; } -export type ComponentProps = ExtractPropTypes<typeof componentProps> \ No newline at end of file +export type ComponentProps = ExtractPropTypes<typeof componentProps>; diff --git a/packages/devui-vue/devui/modal/src/services/common-modal-service.ts b/packages/devui-vue/devui/modal/src/services/common-modal-service.ts index befc1d0521..424085e10e 100644 --- a/packages/devui-vue/devui/modal/src/services/common-modal-service.ts +++ b/packages/devui-vue/devui/modal/src/services/common-modal-service.ts @@ -1,7 +1,7 @@ import { h, render, Slots, VNode } from 'vue'; export interface ModalOpenResult { - hide(): void + hide(): void; } export abstract class CommonModalService<Options, Props> { @@ -21,7 +21,7 @@ export abstract class CommonModalService<Options, Props> { protected renderNull(anchor: HTMLElement): void { // 动画运行完毕后 setTimeout(() => { - render(null, anchor); + render(null, anchor); }, 500); } -} \ No newline at end of file +} diff --git a/packages/devui-vue/devui/modal/src/use-moveable.ts b/packages/devui-vue/devui/modal/src/use-moveable.ts index 4f8b50b69f..55246323e1 100644 --- a/packages/devui-vue/devui/modal/src/use-moveable.ts +++ b/packages/devui-vue/devui/modal/src/use-moveable.ts @@ -4,16 +4,16 @@ import { readonly, Ref, isRef, -} from 'vue' +} from 'vue'; export interface MoveableResult { - movingX: Ref<number> - movingY: Ref<number> + movingX: Ref<number>; + movingY: Ref<number>; // 可拖拽的元素 - handleRef: Ref<HTMLElement | null> + handleRef: Ref<HTMLElement | null>; // 可移动的元素 - moveElRef: Ref<HTMLElement | null> - reset(): void + moveElRef: Ref<HTMLElement | null>; + reset(): void; } // 当前某个元素被拖拽时鼠标的偏移量 @@ -24,7 +24,7 @@ export const useMoveable = (moveable: Ref<boolean> | boolean = true): MoveableRe const reset = () => { movingX.value = 0; movingY.value = 0; - } + }; // 可拖拽的元素 const handleRef = ref<HTMLElement | null>(); @@ -73,7 +73,7 @@ export const useMoveable = (moveable: Ref<boolean> | boolean = true): MoveableRe bodyRect = document.body.getBoundingClientRect(); containerRect = container.getBoundingClientRect(); } - } + }; const handleMouseMove = (event: MouseEvent) => { event.preventDefault(); @@ -86,7 +86,7 @@ export const useMoveable = (moveable: Ref<boolean> | boolean = true): MoveableRe const containerOriginY = containerRect.y - prevMovingY; movingX.value = getRangeValueOf(currentX, -containerOriginX, bodyRect.width - containerRect.width - containerOriginX); movingY.value = getRangeValueOf(currentY, -containerOriginY, bodyRect.height - containerRect.height - containerOriginY); - } + }; const handleMouseUp = (event: MouseEvent) => { event.preventDefault(); @@ -94,7 +94,7 @@ export const useMoveable = (moveable: Ref<boolean> | boolean = true): MoveableRe return; } isDown = false; - } + }; window.addEventListener('mousedown', handleMouseDown); window.addEventListener('mousemove', handleMouseMove); @@ -112,8 +112,8 @@ export const useMoveable = (moveable: Ref<boolean> | boolean = true): MoveableRe handleRef, moveElRef, reset - } -} + }; +}; const getRangeValueOf = (value: number, min: number, max: number) => { @@ -124,4 +124,4 @@ const getRangeValueOf = (value: number, min: number, max: number) => { return max; } return value; -} +}; diff --git a/packages/devui-vue/devui/nav-sprite/src/nav-sprite-types.ts b/packages/devui-vue/devui/nav-sprite/src/nav-sprite-types.ts index b786c855d0..75e9743bd4 100644 --- a/packages/devui-vue/devui/nav-sprite/src/nav-sprite-types.ts +++ b/packages/devui-vue/devui/nav-sprite/src/nav-sprite-types.ts @@ -2,73 +2,73 @@ import { PropType } from 'vue'; export type SpriteMode = 'default' | 'sprite'; export interface SpriteOption { - top: string - left: string - zIndex: number + top: string; + left: string; + zIndex: number; } export interface NavMenu { - originEle: HTMLElement - label: string - level: number - scrollPosition: { - top: number - startLine: number - } + originEle: HTMLElement; + label: string; + level: number; + scrollPosition: { + top: number; + startLine: number; + }; } export const navSpriteProps = { - // // 爬取目录的容器 - target: { - type: Object, + // // 爬取目录的容器 + target: { + type: Object, + }, + // // 指定滚动的DOM + scrollTarget: { + type: Object, + }, + // // 矫正参数 + view: { + type: Object as () => { + top?: number; + bottom?: number; }, - // // 指定滚动的DOM - scrollTarget: { - type: Object, - }, - // // 矫正参数 - view: { - type: Object as () => { - top?: number - bottom?: number - }, - default: { top: 0, bottom: 0 } - }, - // // 支持锚点 - hashSupport: { - type: Boolean, - default: false - }, - mode: { - type: String as () => SpriteMode, - default: 'default' - }, - maxLevel: { - type: Number, - default: 3 - }, - title: { - type: String, - default: 'menu' - }, - // 缩进 - indent: { - type: Number, - default: 2 - }, - width: { - type: Number, - default: 300 - }, - height: { - type: Number, - default: 400 - }, - // sprite模式下的初始状态 - isOpen: { - type: Boolean, - default: true - }, - // sprite模式下的初始位置 - spriteOption: { - type: Object as () => SpriteOption, - } -} + default: { top: 0, bottom: 0 } + }, + // // 支持锚点 + hashSupport: { + type: Boolean, + default: false + }, + mode: { + type: String as () => SpriteMode, + default: 'default' + }, + maxLevel: { + type: Number, + default: 3 + }, + title: { + type: String, + default: 'menu' + }, + // 缩进 + indent: { + type: Number, + default: 2 + }, + width: { + type: Number, + default: 300 + }, + height: { + type: Number, + default: 400 + }, + // sprite模式下的初始状态 + isOpen: { + type: Boolean, + default: true + }, + // sprite模式下的初始位置 + spriteOption: { + type: Object as () => SpriteOption, + } +}; diff --git a/packages/devui-vue/devui/overlay/__tests__/overlay.spec.ts b/packages/devui-vue/devui/overlay/__tests__/overlay.spec.ts index 8499b9e6c6..47033be3f9 100644 --- a/packages/devui-vue/devui/overlay/__tests__/overlay.spec.ts +++ b/packages/devui-vue/devui/overlay/__tests__/overlay.spec.ts @@ -8,191 +8,191 @@ let overlayContianerElement: HTMLElement; let origin: OriginOrDomRef; describe('overlay', () => { - beforeEach(() => { - const div = document.createElement('div'); - div.id = 'd-overlay-anchor'; - document.body.append(div); - overlayContianerElement = document.querySelector('#d-overlay-anchor'); - }) + beforeEach(() => { + const div = document.createElement('div'); + div.id = 'd-overlay-anchor'; + document.body.append(div); + overlayContianerElement = document.querySelector('#d-overlay-anchor'); + }); - describe('fixed overlay', () => { + describe('fixed overlay', () => { - it('should be create', async() => { - const wrapper = mount(FixedOverlay, { - props: { - visible: true - } - }) - await nextTick(); - let bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.getAttribute('style')).toBeNull(); - await wrapper.setProps({visible: false}); - await nextTick(); - bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.style.display).toBe('none'); - wrapper.unmount() - }) - it('test backgroundClass, backgroundStyle, overlayStyle', async() => { - const wrapper = mount(FixedOverlay, { - props: { - visible: true, - backgroundClass: 'bgColor', - backgroundStyle: 'width: 100px', - overlayStyle: 'width: 100%' - } - }) - await nextTick(); - const bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.classList).toContain('bgColor'); - expect(bgElement.style.width).toBe('100px'); - expect((overlayContianerElement.querySelector('.devui-overlay') as HTMLElement).style.width).toBe('100%'); - wrapper.unmount(); - }) - it('test hasBackdrop', async() => { - const wrapper = mount(FixedOverlay, { - props: { - visible: true, - hasBackdrop: false - } - }) - await nextTick(); - let bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.classList).toContain('devui-overlay-background__disabled'); - await wrapper.setProps({hasBackdrop: true}); - await nextTick(); - bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.classList).toContain('devui-overlay-background__color'); - wrapper.unmount(); - }) - it('test emit update:visible and onBackdropClick', async() => { - const wrapper = mount(FixedOverlay, { - props: { - visible: true - } - }) - await nextTick(); - const bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - const fn = jest.fn(); - await wrapper.setProps({onBackdropClick: fn}) - bgElement.click(); - expect(wrapper.emitted('update:visible').length).toBe(1); - expect(fn).toHaveBeenCalled(); - wrapper.unmount(); - }) - }) + it('should be create', async() => { + const wrapper = mount(FixedOverlay, { + props: { + visible: true + } + }); + await nextTick(); + let bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.getAttribute('style')).toBeNull(); + await wrapper.setProps({visible: false}); + await nextTick(); + bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.style.display).toBe('none'); + wrapper.unmount(); + }); + it('test backgroundClass, backgroundStyle, overlayStyle', async() => { + const wrapper = mount(FixedOverlay, { + props: { + visible: true, + backgroundClass: 'bgColor', + backgroundStyle: 'width: 100px', + overlayStyle: 'width: 100%' + } + }); + await nextTick(); + const bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.classList).toContain('bgColor'); + expect(bgElement.style.width).toBe('100px'); + expect((overlayContianerElement.querySelector('.devui-overlay') as HTMLElement).style.width).toBe('100%'); + wrapper.unmount(); + }); + it('test hasBackdrop', async() => { + const wrapper = mount(FixedOverlay, { + props: { + visible: true, + hasBackdrop: false + } + }); + await nextTick(); + let bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.classList).toContain('devui-overlay-background__disabled'); + await wrapper.setProps({hasBackdrop: true}); + await nextTick(); + bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.classList).toContain('devui-overlay-background__color'); + wrapper.unmount(); + }); + it('test emit update:visible and onBackdropClick', async() => { + const wrapper = mount(FixedOverlay, { + props: { + visible: true + } + }); + await nextTick(); + const bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + const fn = jest.fn(); + await wrapper.setProps({onBackdropClick: fn}); + bgElement.click(); + expect(wrapper.emitted('update:visible').length).toBe(1); + expect(fn).toHaveBeenCalled(); + wrapper.unmount(); + }); + }); - describe('flexible overlay', () => { - beforeEach(() => { - origin = {x:100, y: 100, width: 100, height: 100} as Rect; - // 解决 ResizeObserver is not defined - global.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ - disconnect: jest.fn(), - observe: jest.fn(), - unobserve: jest.fn(), - })); - }) + describe('flexible overlay', () => { + beforeEach(() => { + origin = {x:100, y: 100, width: 100, height: 100} as Rect; + // 解决 ResizeObserver is not defined + global.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), + })); + }); - it('should be creat', async() => { - const wrapper = mount(FlexibleOverlay, { - props: { - origin: origin, - visible: true - } - }) - await nextTick(); - let bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.getAttribute('style')).toBeNull(); - await wrapper.setProps({ visible: false }); - await nextTick(); - bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.style.display).toBe('none'); - wrapper.unmount(); - }) - it('test backgroundClass, backgroundStyle', async() => { - const wrapper = mount(FlexibleOverlay, { - props: { - origin: origin, - visible: true, - backgroundClass: 'bgColor', - backgroundStyle: 'width: 100px' - } - }) - await nextTick(); - const bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.classList).toContain('bgColor'); - expect(bgElement.style.width).toBe('100px'); - wrapper.unmount(); - }) - it('test hasBackdrop', async() => { - const wrapper = mount(FlexibleOverlay, { - props: { - origin: origin, - visible: true, - hasBackdrop: false - } - }) - await nextTick(); - let bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.classList).toContain('devui-overlay-background__disabled'); - await wrapper.setProps({hasBackdrop: true}); - await nextTick(); - bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - expect(bgElement.classList).toContain('devui-overlay-background__color'); - wrapper.unmount(); - }) - it('test emit update:visible and onBackdropClick', async() => { - const wrapper = mount(FlexibleOverlay, { - props: { - origin: origin, - visible: true - } - }) - await nextTick(); - const bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; - const fn = jest.fn(); - await wrapper.setProps({onBackdropClick: fn}) - bgElement.click(); - expect(wrapper.emitted('update:visible').length).toBe(1); - expect(fn).toHaveBeenCalled(); - wrapper.unmount(); - }) - it('test position', async() => { - const position = { - originX: 'left', - originY: 'top', - overlayX: 'left', - overlayY: 'top' - } as ConnectionPosition - const wrapper = mount(FlexibleOverlay, { - props: { - origin: origin, - visible: true, - }, - slots: { - default: '<div style="width:100px; height: 100px;"></div>' - } - }) - await wrapper.setProps({position: position}) - await nextTick(); - let overlayElement = overlayContianerElement.querySelector('.devui-overlay') as HTMLElement; - expect(overlayElement.style.left).toBe('100px'); - expect(overlayElement.style.top).toBe('100px'); - position.originX = 'center'; - position.originY = 'center'; - await wrapper.setProps({position: Object.assign({}, position)}) - await nextTick(); - overlayElement = overlayContianerElement.querySelector('.devui-overlay') as HTMLElement; - expect(overlayElement.style.left).toBe('150px'); - expect(overlayElement.style.top).toBe('150px'); - position.originX = 'right'; - position.originY = 'bottom' - await wrapper.setProps({position: Object.assign({}, position)}) - await nextTick(); - overlayElement = overlayContianerElement.querySelector('.devui-overlay') as HTMLElement; - expect(overlayElement.style.left).toBe('200px'); - expect(overlayElement.style.top).toBe('200px'); - wrapper.unmount(); - }) - }) -}) + it('should be creat', async() => { + const wrapper = mount(FlexibleOverlay, { + props: { + origin: origin, + visible: true + } + }); + await nextTick(); + let bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.getAttribute('style')).toBeNull(); + await wrapper.setProps({ visible: false }); + await nextTick(); + bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.style.display).toBe('none'); + wrapper.unmount(); + }); + it('test backgroundClass, backgroundStyle', async() => { + const wrapper = mount(FlexibleOverlay, { + props: { + origin: origin, + visible: true, + backgroundClass: 'bgColor', + backgroundStyle: 'width: 100px' + } + }); + await nextTick(); + const bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.classList).toContain('bgColor'); + expect(bgElement.style.width).toBe('100px'); + wrapper.unmount(); + }); + it('test hasBackdrop', async() => { + const wrapper = mount(FlexibleOverlay, { + props: { + origin: origin, + visible: true, + hasBackdrop: false + } + }); + await nextTick(); + let bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.classList).toContain('devui-overlay-background__disabled'); + await wrapper.setProps({hasBackdrop: true}); + await nextTick(); + bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + expect(bgElement.classList).toContain('devui-overlay-background__color'); + wrapper.unmount(); + }); + it('test emit update:visible and onBackdropClick', async() => { + const wrapper = mount(FlexibleOverlay, { + props: { + origin: origin, + visible: true + } + }); + await nextTick(); + const bgElement = overlayContianerElement.querySelector('.devui-overlay-background') as HTMLElement; + const fn = jest.fn(); + await wrapper.setProps({onBackdropClick: fn}); + bgElement.click(); + expect(wrapper.emitted('update:visible').length).toBe(1); + expect(fn).toHaveBeenCalled(); + wrapper.unmount(); + }); + it('test position', async() => { + const position = { + originX: 'left', + originY: 'top', + overlayX: 'left', + overlayY: 'top' + } as ConnectionPosition; + const wrapper = mount(FlexibleOverlay, { + props: { + origin: origin, + visible: true, + }, + slots: { + default: '<div style="width:100px; height: 100px;"></div>' + } + }); + await wrapper.setProps({position: position}); + await nextTick(); + let overlayElement = overlayContianerElement.querySelector('.devui-overlay') as HTMLElement; + expect(overlayElement.style.left).toBe('100px'); + expect(overlayElement.style.top).toBe('100px'); + position.originX = 'center'; + position.originY = 'center'; + await wrapper.setProps({position: Object.assign({}, position)}); + await nextTick(); + overlayElement = overlayContianerElement.querySelector('.devui-overlay') as HTMLElement; + expect(overlayElement.style.left).toBe('150px'); + expect(overlayElement.style.top).toBe('150px'); + position.originX = 'right'; + position.originY = 'bottom'; + await wrapper.setProps({position: Object.assign({}, position)}); + await nextTick(); + overlayElement = overlayContianerElement.querySelector('.devui-overlay') as HTMLElement; + expect(overlayElement.style.left).toBe('200px'); + expect(overlayElement.style.top).toBe('200px'); + wrapper.unmount(); + }); + }); +}); diff --git a/packages/devui-vue/devui/overlay/src/utils.ts b/packages/devui-vue/devui/overlay/src/utils.ts index efc55d1690..1b0fec935f 100644 --- a/packages/devui-vue/devui/overlay/src/utils.ts +++ b/packages/devui-vue/devui/overlay/src/utils.ts @@ -2,10 +2,10 @@ import { onUnmounted, watch, computed, ComputedRef, onMounted, SetupContext } fr import { overlayEmits, OverlayProps } from './overlay-types'; interface CommonInfo { - backgroundClass: ComputedRef<string[]> - overlayClass: ComputedRef<string> - handleBackdropClick: (e: Event) => void - handleOverlayBubbleCancel: (e: Event) => void + backgroundClass: ComputedRef<string[]>; + overlayClass: ComputedRef<string>; + handleBackdropClick: (e: Event) => void; + handleOverlayBubbleCancel: (e: Event) => void; } export function useOverlayLogic(props: OverlayProps, ctx: SetupContext<typeof overlayEmits>): CommonInfo { @@ -59,5 +59,5 @@ export function useOverlayLogic(props: OverlayProps, ctx: SetupContext<typeof ov overlayClass, handleBackdropClick, handleOverlayBubbleCancel - } + }; } diff --git a/packages/devui-vue/devui/pagination/__tests__/pagination.spec.ts b/packages/devui-vue/devui/pagination/__tests__/pagination.spec.ts index 99bc8f7699..b3fdd71287 100644 --- a/packages/devui-vue/devui/pagination/__tests__/pagination.spec.ts +++ b/packages/devui-vue/devui/pagination/__tests__/pagination.spec.ts @@ -1,8 +1,8 @@ import { mount } from '@vue/test-utils'; import { reactive } from 'vue'; -import { Pagination } from '../index' -import { Select } from '../../select' -import { Input } from '../../input' +import { Pagination } from '../index'; +import { Select } from '../../select'; +import { Input } from '../../input'; const globalOption = { global: { @@ -11,7 +11,7 @@ const globalOption = { DInput: Input } } -} +}; describe('pagination: ', () => { it('test pageSize', async () => { @@ -37,40 +37,40 @@ describe('pagination: ', () => { total: 306, pageSize: 20, pageIndex: 5 - }) - return { pager } + }); + return { pager }; } - }, globalOption) + }, globalOption); - expect(wrapper.find('.devui-pagination-item.active').text()).toEqual('5') - expect((wrapper.find('.devui-select-input').element as HTMLInputElement).value).toEqual('20') + expect(wrapper.find('.devui-pagination-item.active').text()).toEqual('5'); + expect((wrapper.find('.devui-select-input').element as HTMLInputElement).value).toEqual('20'); - const btns = wrapper.findAll('a.devui-pagination-link') + const btns = wrapper.findAll('a.devui-pagination-link'); expect(btns.map((ele: any) => ele.text()).join()).toEqual('<,1,...,4,5,6,...,16,>'); - expect(wrapper.find('.devui-pagination-list').classes()).toContain('devui-pagination-sm') + expect(wrapper.find('.devui-pagination-list').classes()).toContain('devui-pagination-sm'); // 跳转按钮 - expect(wrapper.find('.devui-jump-container').exists()).toBeTruthy() - expect(wrapper.find('.devui-jump-button').exists()).toBeTruthy() + expect(wrapper.find('.devui-jump-container').exists()).toBeTruthy(); + expect(wrapper.find('.devui-jump-button').exists()).toBeTruthy(); // 翻页 - await btns[0].trigger('click') - expect(wrapper.find('.devui-pagination-item.active').text()).toEqual('4') - const btns1 = wrapper.findAll('a.devui-pagination-link') + await btns[0].trigger('click'); + expect(wrapper.find('.devui-pagination-item.active').text()).toEqual('4'); + const btns1 = wrapper.findAll('a.devui-pagination-link'); expect(btns1.map((ele: any) => ele.text()).join()).toEqual('<,1,...,3,4,5,...,16,>'); // 改变每页条数 - await wrapper.find('.devui-select-input').trigger('click') - await wrapper.findAll('.devui-select-item')[1].trigger('click') + await wrapper.find('.devui-select-input').trigger('click'); + await wrapper.findAll('.devui-select-item')[1].trigger('click'); - expect((wrapper.find('.devui-select-input').element as HTMLInputElement).value).toEqual('10') - const btns2 = wrapper.findAll('a.devui-pagination-link') + expect((wrapper.find('.devui-select-input').element as HTMLInputElement).value).toEqual('10'); + const btns2 = wrapper.findAll('a.devui-pagination-link'); expect(btns2.map((ele: any) => ele.text()).join()).toEqual('<,1,...,3,4,5,...,31,>'); - }) + }); it('test callback', async () => { - const pageIndexChange = jest.fn() - const pageSizeChange = jest.fn() + const pageIndexChange = jest.fn(); + const pageSizeChange = jest.fn(); const wrapper = mount({ components: { DPagination: Pagination @@ -94,25 +94,25 @@ describe('pagination: ', () => { total: 306, pageSize: 10, pageIndex: 10 - }) - return { pager, pageIndexChange, pageSizeChange } + }); + return { pager, pageIndexChange, pageSizeChange }; } - }, globalOption) + }, globalOption); - expect(wrapper.find('.devui-pagination-list').classes()).toContain('devui-pagination-lg') - const btns = wrapper.findAll('a.devui-pagination-link') - const pageIndexs = btns.map((ele: any) => ele.text()) + expect(wrapper.find('.devui-pagination-list').classes()).toContain('devui-pagination-lg'); + const btns = wrapper.findAll('a.devui-pagination-link'); + const pageIndexs = btns.map((ele: any) => ele.text()); expect(pageIndexs.join()).toEqual('<,1,...,6,7,8,9,10,11,12,13,...,31,>'); // 当前页改变回调 - await btns[0].trigger('click') - expect(pageIndexChange).toHaveBeenCalled() - + await btns[0].trigger('click'); + expect(pageIndexChange).toHaveBeenCalled(); + // 每页条数改变回调 - await wrapper.find('.devui-select-input').trigger('click') - await wrapper.findAll('.devui-select-item')[1].trigger('click') - expect(pageSizeChange).toHaveBeenCalled() - }) + await wrapper.find('.devui-select-input').trigger('click'); + await wrapper.findAll('.devui-select-item')[1].trigger('click'); + expect(pageSizeChange).toHaveBeenCalled(); + }); it('test first or lastest pageIndex disabled', async () => { const wrapper = mount({ @@ -136,19 +136,19 @@ describe('pagination: ', () => { total: 306, pageSize: 20, pageIndex: 1 - }) - return { pager } + }); + return { pager }; } - }, globalOption) + }, globalOption); - const btns = wrapper.findAll('.devui-pagination-item') - expect(btns[0].classes()).toContain('disabled') + const btns = wrapper.findAll('.devui-pagination-item'); + expect(btns[0].classes()).toContain('disabled'); - await btns[btns.length - 2].trigger('click') - const btns1 = wrapper.findAll('.devui-pagination-item') - expect(btns1[btns1.length - 1].classes()).toContain('disabled') + await btns[btns.length - 2].trigger('click'); + const btns1 = wrapper.findAll('.devui-pagination-item'); + expect(btns1[btns1.length - 1].classes()).toContain('disabled'); - }) + }); it('test lite', () => { const wrapper = mount({ @@ -171,16 +171,16 @@ describe('pagination: ', () => { total: 306, pageSize: 10, pageIndex: 10 - }) - return { pager } + }); + return { pager }; } - }, globalOption) + }, globalOption); + + expect(wrapper.find('.devui-total-size').text()).toContain('Total'); + expect(wrapper.findAll('a.devui-pagination-link').length).toBe(2); + expect(wrapper.find('.devui-jump-container').exists()).toBeFalsy(); + }); - expect(wrapper.find('.devui-total-size').text()).toContain('Total') - expect(wrapper.findAll('a.devui-pagination-link').length).toBe(2) - expect(wrapper.find('.devui-jump-container').exists()).toBeFalsy() - }) - it('test super lite', () => { const wrapper = mount({ components: { @@ -201,17 +201,17 @@ describe('pagination: ', () => { total: 306, pageSize: 10, pageIndex: 10 - }) - return { pager } + }); + return { pager }; } - }, globalOption) + }, globalOption); + + expect(wrapper.find('.devui-total-size').exists()).toBeFalsy(); + expect(wrapper.find('.devui-page-size').exists()).toBeFalsy(); + expect(wrapper.findAll('a.devui-pagination-link').length).toBe(2); + expect(wrapper.find('.devui-jump-container').exists()).toBeFalsy(); + }); - expect(wrapper.find('.devui-total-size').exists()).toBeFalsy() - expect(wrapper.find('.devui-page-size').exists()).toBeFalsy() - expect(wrapper.findAll('a.devui-pagination-link').length).toBe(2) - expect(wrapper.find('.devui-jump-container').exists()).toBeFalsy() - }) - it('test haveConfigMenu', async () => { const wrapper = mount({ components: { @@ -245,20 +245,20 @@ describe('pagination: ', () => { total: 306, pageSize: 10, pageIndex: 10 - }) - return { pager } + }); + return { pager }; } - }, globalOption) + }, globalOption); - expect(wrapper.findAll('a.devui-pagination-link').length).toBe(2) - expect(wrapper.find('.devui-pagination-config').exists()).toBeTruthy() - expect(wrapper.find('.devui-config-container').exists()).toBeFalsy() - - await wrapper.find('.devui-pagination-config').trigger('click') - expect(wrapper.find('.devui-config-container').exists()).toBeTruthy() - expect(wrapper.find('.config-item-words').exists()).toBeTruthy() - expect(wrapper.find('.choosed').text()).toBe('10') - }) + expect(wrapper.findAll('a.devui-pagination-link').length).toBe(2); + expect(wrapper.find('.devui-pagination-config').exists()).toBeTruthy(); + expect(wrapper.find('.devui-config-container').exists()).toBeFalsy(); + + await wrapper.find('.devui-pagination-config').trigger('click'); + expect(wrapper.find('.devui-config-container').exists()).toBeTruthy(); + expect(wrapper.find('.config-item-words').exists()).toBeTruthy(); + expect(wrapper.find('.choosed').text()).toBe('10'); + }); it('test special', async () => { const wrapper = mount({ @@ -282,26 +282,26 @@ describe('pagination: ', () => { total: 10, pageIndex: 3, pageSize: 10 - }) - return { pager } + }); + return { pager }; } - }, globalOption) + }, globalOption); - const btns = wrapper.findAll('.devui-pagination-item') - expect(btns.length).toBe(5) - expect(wrapper.findAll('.devui-pagination-item.disabled').length).toBe(3) - expect(wrapper.find('.devui-pagination-item.active.disabled').text()).toBe('3') + const btns = wrapper.findAll('.devui-pagination-item'); + expect(btns.length).toBe(5); + expect(wrapper.findAll('.devui-pagination-item.disabled').length).toBe(3); + expect(wrapper.find('.devui-pagination-item.active.disabled').text()).toBe('3'); - await btns[0].trigger('click') - expect(wrapper.findAll('.devui-pagination-item').length).toBe(4) - expect(wrapper.findAll('.devui-pagination-item.disabled').length).toBe(2) + await btns[0].trigger('click'); + expect(wrapper.findAll('.devui-pagination-item').length).toBe(4); + expect(wrapper.findAll('.devui-pagination-item.disabled').length).toBe(2); await wrapper.setProps({ showTruePageIndex: false - }) - - expect(wrapper.findAll('.devui-pagination-item').length).toBe(3) - expect(wrapper.findAll('.devui-pagination-item.disabled').length).toBe(2) - expect(wrapper.find('.devui-pagination-item.active').text()).toBe('1') - }) -}) \ No newline at end of file + }); + + expect(wrapper.findAll('.devui-pagination-item').length).toBe(3); + expect(wrapper.findAll('.devui-pagination-item.disabled').length).toBe(2); + expect(wrapper.find('.devui-pagination-item.active').text()).toBe('1'); + }); +}); diff --git a/packages/devui-vue/devui/pagination/index.ts b/packages/devui-vue/devui/pagination/index.ts index e881885cb4..a4d82a7882 100644 --- a/packages/devui-vue/devui/pagination/index.ts +++ b/packages/devui-vue/devui/pagination/index.ts @@ -1,17 +1,17 @@ -import { App } from 'vue' -import Pagination from './src/pagination' +import { App } from 'vue'; +import Pagination from './src/pagination'; Pagination.install = (app: App): void => { - app.component(Pagination.name, Pagination) -} + app.component(Pagination.name, Pagination); +}; -export { Pagination } +export { Pagination }; export default { title: 'Pagination 分页', category: '导航', status: '100%', install(app: App): void { - app.use(Pagination as any) + app.use(Pagination as any); } -} +}; diff --git a/packages/devui-vue/devui/pagination/src/components/config-menu.tsx b/packages/devui-vue/devui/pagination/src/components/config-menu.tsx index 2f1f1f0bed..a9790d3e26 100644 --- a/packages/devui-vue/devui/pagination/src/components/config-menu.tsx +++ b/packages/devui-vue/devui/pagination/src/components/config-menu.tsx @@ -1,7 +1,7 @@ import { defineComponent, onMounted, onUnmounted, PropType, ref } from 'vue'; -import { on, off } from '../../../shared/devui-directive/utils' +import { on, off } from '../../../shared/devui-directive/utils'; -import clickoutsideDirective from '../../../shared/devui-directive/clickoutside' +import clickoutsideDirective from '../../../shared/devui-directive/clickoutside'; export default defineComponent({ directives: { @@ -13,24 +13,24 @@ export default defineComponent({ pageSizeOptions: Array as PropType<Array<number>> } as const, setup() { - const paginationConfig = ref(null) - const isShowConfig = ref(false) - + const paginationConfig = ref(null); + const isShowConfig = ref(false); + onMounted(() => { - on(paginationConfig.value, 'click', closeConfigMenu) - }) + on(paginationConfig.value, 'click', closeConfigMenu); + }); onUnmounted(() => { - off(paginationConfig.value, 'click', closeConfigMenu) - }) + off(paginationConfig.value, 'click', closeConfigMenu); + }); const closeConfigMenu = (e: Event) => { - isShowConfig.value = isShowConfig.value ? false : !!e - } + isShowConfig.value = isShowConfig.value ? false : !!e; + }; return { paginationConfig, isShowConfig, closeConfigMenu - } + }; }, render() { const { @@ -40,7 +40,7 @@ export default defineComponent({ pageSizeOptions, isShowConfig, $slots - } = this + } = this; return ( <div class="devui-pagination-config" v-clickoutside={closeConfigMenu} ref="paginationConfig"> @@ -51,7 +51,7 @@ export default defineComponent({ isShowConfig && <div class="devui-config-container"> {$slots.default?.()} - + <div class="pagination-config-item"> <div class="config-item-title">每页条数</div> <div class="devui-page-number"> @@ -63,7 +63,7 @@ export default defineComponent({ key={v} onClick={pageSizeChange.bind(null, {value: v})} >{v}</div> - ) + ); }) } </div> @@ -71,6 +71,6 @@ export default defineComponent({ </div> } </div> - ) + ); } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/pagination/src/components/page-nums.tsx b/packages/devui-vue/devui/pagination/src/components/page-nums.tsx index eaccee591e..cf79d968b0 100644 --- a/packages/devui-vue/devui/pagination/src/components/page-nums.tsx +++ b/packages/devui-vue/devui/pagination/src/components/page-nums.tsx @@ -1,5 +1,5 @@ import { defineComponent, PropType, computed, ExtractPropTypes } from 'vue'; -import { handlePages } from '../utils' +import { handlePages } from '../utils'; const pageNumBtnProps = { size: { @@ -14,9 +14,9 @@ const pageNumBtnProps = { totalPages: Number, onChangeCursorEmit: Function as PropType<(v: number) => void>, showTruePageIndex: Boolean -} as const +} as const; -type PageNumBtnProps = ExtractPropTypes<typeof pageNumBtnProps> +type PageNumBtnProps = ExtractPropTypes<typeof pageNumBtnProps>; export default defineComponent({ props: pageNumBtnProps, @@ -24,38 +24,38 @@ export default defineComponent({ setup(props: PageNumBtnProps, { emit }) { // 页码较多时,计算中间的显示页码的起始页码数 - const showPageNum = computed(() => handlePages(props.cursor, props.maxItems, props.totalPages)) - + const showPageNum = computed(() => handlePages(props.cursor, props.maxItems, props.totalPages)); + // 点击页码 const changeCursor = (pageSize: number) => { - if (isNaN(pageSize)) return - const page = pageSize < 1 ? 1 : pageSize > props.totalPages ? props.totalPages : pageSize | 0 + if (isNaN(pageSize)) {return;} + const page = pageSize < 1 ? 1 : pageSize > props.totalPages ? props.totalPages : pageSize | 0; - emit('changeCursorEmit', page) - } + emit('changeCursorEmit', page); + }; // 上一页 const prevChange = (page: number) => { if (props.cursor > 1) { - const toPage = page === -1 ? props.cursor - 1 : page - - emit('changeCursorEmit', toPage) + const toPage = page === -1 ? props.cursor - 1 : page; + + emit('changeCursorEmit', toPage); } - } + }; // 下一页 const nextChange = (page: number) => { if (props.cursor < props.totalPages) { - const toPage = page === -1 ? props.cursor + 1 : page + const toPage = page === -1 ? props.cursor + 1 : page; - emit('changeCursorEmit', toPage) + emit('changeCursorEmit', toPage); } - } + }; return { showPageNum, changeCursor, prevChange, nextChange - } + }; }, render() { const { @@ -70,7 +70,7 @@ export default defineComponent({ totalPages, nextChange, showTruePageIndex - } = this + } = this; return ( <ul class={['devui-pagination-list', size ? 'devui-pagination-' + size : '']}> @@ -97,15 +97,15 @@ export default defineComponent({ { // 中间显示页码 (() => { - const list = [] + const list = []; for(let i = showPageNum[0]; i <= showPageNum[1]; i++) { list.push( <li onClick={changeCursor.bind(null, i)} key={i} class={{'devui-pagination-item': true, active: cursor === i}}> <a class="devui-pagination-link">{i}</a> </li> - ) + ); } - return list + return list; })() } { @@ -122,7 +122,7 @@ export default defineComponent({ <li onClick={changeCursor.bind(null, totalPages)} class={{'devui-pagination-item': true, active: cursor === totalPages}}> <a class="devui-pagination-link">{totalPages}</a> </li> - ) + ) } { // 在默认页码超出总页码的时候 @@ -146,6 +146,6 @@ export default defineComponent({ <a v-html={nextLink} class="devui-pagination-link"></a> </li> </ul> - ) + ); } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/pagination/src/pagination.tsx b/packages/devui-vue/devui/pagination/src/pagination.tsx index a27c319bc5..1101400ae1 100644 --- a/packages/devui-vue/devui/pagination/src/pagination.tsx +++ b/packages/devui-vue/devui/pagination/src/pagination.tsx @@ -1,12 +1,12 @@ -import { defineComponent, computed, nextTick } from 'vue' -import { ComponentProps, componentProps } from './use-pagination' -import { liteSelectOptions } from './utils' +import { defineComponent, computed, nextTick } from 'vue'; +import { ComponentProps, componentProps } from './use-pagination'; +import { liteSelectOptions } from './utils'; -import ConfigMenu from './components/config-menu' -import JumpPage from './components/jump-page' -import PageNumBtn from './components/page-nums' +import ConfigMenu from './components/config-menu'; +import JumpPage from './components/jump-page'; +import PageNumBtn from './components/page-nums'; -import './pagination.scss' +import './pagination.scss'; export default defineComponent({ name: 'DPagination', @@ -18,59 +18,59 @@ export default defineComponent({ props: componentProps, emits: ['pageIndexChange', 'pageSizeChange', 'update:pageSize', 'update:pageIndex'], setup(props: ComponentProps, { emit }) { - + // 极简模式下,可选的下拉选择页码 - const litePageOptions = computed(() => liteSelectOptions(totalPages.value)) + const litePageOptions = computed(() => liteSelectOptions(totalPages.value)); // 当前页码 const cursor = computed({ get() { // 是否需要修正错误的pageIndex if (!props.showTruePageIndex && props.pageIndex > totalPages.value) { - emit('update:pageIndex', totalPages.value || 1) - return totalPages.value || 1 + emit('update:pageIndex', totalPages.value || 1); + return totalPages.value || 1; } - return props.pageIndex || 1 + return props.pageIndex || 1; }, set(val: number) { - emit('update:pageIndex', val) + emit('update:pageIndex', val); } - }) + }); // 每页显示最大条目数量 const currentPageSize = computed({ get() { - return props.pageSize + return props.pageSize; }, set(val: number) { - emit('update:pageSize', val) + emit('update:pageSize', val); } - }) + }); // 总页数 - const totalPages = computed(() => Math.ceil(props.total / props.pageSize)) + const totalPages = computed(() => Math.ceil(props.total / props.pageSize)); const changeCursorEmit = (val: number) => { - cursor.value = val - emit('pageIndexChange', val) - } + cursor.value = val; + emit('pageIndexChange', val); + }; // 每页条数改变 const pageSizeChange = (val: Record<string, string | number>) => { - currentPageSize.value = val.value as number + currentPageSize.value = val.value as number; // 页数改变后,如果当前页码超出最大页码时修正 if (props.autoFixPageIndex) { nextTick(() => { if (cursor.value > totalPages.value) { - changeCursorEmit(totalPages.value) + changeCursorEmit(totalPages.value); } - }) + }); } - emit('pageSizeChange', val.value as number) - } + emit('pageSizeChange', val.value as number); + }; // 极简模式下的跳转页码 - const litePageIndexChange = (page: {name: string; value: number;}) => { - changeCursorEmit(page.value) - } - + const litePageIndexChange = (page: {name: string; value: number}) => { + changeCursorEmit(page.value); + }; + return { cursor, totalPages, @@ -79,7 +79,7 @@ export default defineComponent({ pageSizeChange, litePageOptions, litePageIndexChange - } + }; }, render() { @@ -112,15 +112,15 @@ export default defineComponent({ changeCursorEmit, litePageOptions, litePageIndexChange - } = this + } = this; return ( // autoHide为 true 并且 pageSizeOptions最小值 > total 不展示分页 autoHide && Math.min(...pageSizeOptions) > total - ? null - : <div class="devui-pagination"> - { - canChangePageSize && !lite && + ? null + : <div class="devui-pagination"> + { + canChangePageSize && !lite && <div class={['devui-page-size', size ? 'devui-page-size-' + size : '']}> <d-select options={pageSizeOptions} @@ -129,15 +129,15 @@ export default defineComponent({ pageSizeDirection={pageSizeDirection} /> </div> - } - { + } + { // 总页数显示 - ((!lite || (lite && showPageSelector)) && canViewTotal) && + ((!lite || (lite && showPageSelector)) && canViewTotal) && <div class="devui-total-size">{totalItemText}: {total}</div> - } - { + } + { // 极简模式下的选择页码下拉框 - lite && showPageSelector && + lite && showPageSelector && <div class="devui-page-size"> <d-select options={litePageOptions} @@ -147,27 +147,27 @@ export default defineComponent({ pageSizeDirection={pageSizeDirection} /> </div> - } + } - {/* 页码展示 */} - <page-num-btn - {...{ - cursor, - totalPages, - size, - lite, - maxItems, - preLink, - nextLink, - showTruePageIndex - }} - onChangeCursorEmit={changeCursorEmit} - /> + {/* 页码展示 */} + <page-num-btn + {...{ + cursor, + totalPages, + size, + lite, + maxItems, + preLink, + nextLink, + showTruePageIndex + }} + onChangeCursorEmit={changeCursorEmit} + /> - { + { // 跳转页码 - canJumpPage && !lite && - <jump-page + canJumpPage && !lite && + <jump-page {...{ goToText, size, @@ -178,10 +178,10 @@ export default defineComponent({ }} onChangeCursorEmit={changeCursorEmit} /> - } - { + } + { // 极简模式下是否显示配置 - lite && haveConfigMenu && + lite && haveConfigMenu && <config-menu {...{ currentPageSize, @@ -191,8 +191,8 @@ export default defineComponent({ > {$slots.default?.()} </config-menu> - } - </div> - ) + } + </div> + ); } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/pagination/src/use-pagination.ts b/packages/devui-vue/devui/pagination/src/use-pagination.ts index c6663598c3..53c3ba2882 100644 --- a/packages/devui-vue/devui/pagination/src/use-pagination.ts +++ b/packages/devui-vue/devui/pagination/src/use-pagination.ts @@ -3,19 +3,19 @@ import { PropType, ExtractPropTypes } from 'vue'; type AppendToBodyDirection = 'rightDown' | 'rightUp' | 'leftUp' | 'leftDown' | 'centerDown' | 'centerUp'; interface ConnectedPosition { - originX : 'start' | 'center' | 'end' - originY : 'top' | 'center' | 'bottom' + originX: 'start' | 'center' | 'end'; + originY: 'top' | 'center' | 'bottom'; - overlayX : 'start' | 'center' | 'end' - overlayY : 'top' | 'center' | 'bottom' + overlayX: 'start' | 'center' | 'end'; + overlayY: 'top' | 'center' | 'bottom'; - weight ?: number - offsetX ?: number - offsetY ?: number - panelClass ?: string | string[] + weight?: number; + offsetX?: number; + offsetY?: number; + panelClass?: string | string[]; } -type Size = 'lg' | '' | 'sm' +type Size = 'lg' | '' | 'sm'; export const componentProps = { pageSize: { @@ -114,7 +114,7 @@ export const componentProps = { 'onPageSizeChange': { type: Function as PropType<(v: number) => void> } -} as const +} as const; // 组件props -export type ComponentProps = ExtractPropTypes<typeof componentProps> +export type ComponentProps = ExtractPropTypes<typeof componentProps>; diff --git a/packages/devui-vue/devui/pagination/src/utils.ts b/packages/devui-vue/devui/pagination/src/utils.ts index 095b5a4360..25a835959f 100644 --- a/packages/devui-vue/devui/pagination/src/utils.ts +++ b/packages/devui-vue/devui/pagination/src/utils.ts @@ -5,38 +5,38 @@ // 处理页码显示 // 1 ... 5 6 7 8 ... 11 export const handlePages = (cursor: number, maxItems: number, totalPages: number): number[] => { - const currentPage = cursor // 当前页码 - const maxPages = maxItems // 能显示的最大页码 + const currentPage = cursor; // 当前页码 + const maxPages = maxItems; // 能显示的最大页码 if (maxPages >= totalPages) { - return [2, totalPages] + return [2, totalPages]; } - const midPages = maxPages - 2 // 中间显示的页码 + const midPages = maxPages - 2; // 中间显示的页码 // 1 ... 5 6 7 8 ... 11 // 获取 5 和 8 - let midStart = currentPage - (midPages >> 1) - let midEnd = currentPage + (midPages - 1 >> 1) + let midStart = currentPage - (midPages >> 1); + let midEnd = currentPage + (midPages - 1 >> 1); if (midStart < 2) { - midStart = 2 - midEnd = maxPages - 2 + midStart = 2; + midEnd = maxPages - 2; } if (midEnd > totalPages) { - midStart = totalPages - maxPages + 3 - midEnd = totalPages + midStart = totalPages - maxPages + 3; + midEnd = totalPages; } - return [midStart, midEnd] -} + return [midStart, midEnd]; +}; // 处理极简模式下的页码下拉多选显示 -export function liteSelectOptions(total: number): Array<{name: string; value: number;}> { +export function liteSelectOptions(total: number): Array<{name: string; value: number}> { return new Array(total || 1).fill(0).map((v: number, index: number) => { return { name: `${index + 1}/${total}`, value: index + 1 - } - }) + }; + }); } diff --git a/packages/devui-vue/devui/panel/__tests__/panel.spec.ts b/packages/devui-vue/devui/panel/__tests__/panel.spec.ts index 696c2bb15b..ae6709cfeb 100644 --- a/packages/devui-vue/devui/panel/__tests__/panel.spec.ts +++ b/packages/devui-vue/devui/panel/__tests__/panel.spec.ts @@ -1,7 +1,7 @@ import { mount } from '@vue/test-utils'; import {ref } from 'vue'; import DButton from '../../button/index'; -import DPanel from '../src/panel' +import DPanel from '../src/panel'; import DPanelHeader from '../src/header/panel-header'; import DPanelBody from '../src/body/panel-body'; import DPanelFooter from '../src/foot/panel-footer'; @@ -9,18 +9,18 @@ import DPanelFooter from '../src/foot/panel-footer'; describe('DPanel',()=>{ - // 渲染测试 - it('Render',()=>{ - // except(wrapper.html()) - const wrapper = mount({ - components:{ - DPanel, - DPanelBody, - DPanelHeader, - DPanelFooter, - DButton - }, - template: ` + // 渲染测试 + it('Render',()=>{ + // except(wrapper.html()) + const wrapper = mount({ + components:{ + DPanel, + DPanelBody, + DPanelHeader, + DPanelFooter, + DButton + }, + template: ` <d-panel> <d-panel-header> Panel with foldable @@ -30,19 +30,19 @@ describe('DPanel',()=>{ </d-panel-body> </d-panel> `, - }); - expect(wrapper.find('transition-stub').html()).toContain('<transition-stub><!----></transition-stub>'); - }) + }); + expect(wrapper.find('transition-stub').html()).toContain('<transition-stub><!----></transition-stub>'); + }); - it('isCollapsed', async ()=>{ - const wrapper = mount({ - components:{ - DPanel, - DPanelBody, - DPanelHeader, - DPanelFooter, - }, - template: ` + it('isCollapsed', async ()=>{ + const wrapper = mount({ + components:{ + DPanel, + DPanelBody, + DPanelHeader, + DPanelFooter, + }, + template: ` <d-panel :isCollapsed="isCollapsed"> <d-panel-header> Panel with foldable @@ -52,23 +52,23 @@ describe('DPanel',()=>{ </d-panel-body> </d-panel> `, - setup(){ - const isCollapsed = ref(false); - return {isCollapsed} - } - }); - expect(wrapper.find('.devui-panel .devui-panel-default').element.children[0].innerHTML).toBe('<!---->'); - }) - it('padding-dynamic', async ()=>{ - const wrapper = mount({ - components:{ - DPanel, - DPanelBody, - DPanelHeader, - DPanelFooter, - DButton - }, - template: ` + setup(){ + const isCollapsed = ref(false); + return {isCollapsed}; + } + }); + expect(wrapper.find('.devui-panel .devui-panel-default').element.children[0].innerHTML).toBe('<!---->'); + }); + it('padding-dynamic', async ()=>{ + const wrapper = mount({ + components:{ + DPanel, + DPanelBody, + DPanelHeader, + DPanelFooter, + DButton + }, + template: ` <d-panel :hasLeftPadding = "leftPadding" isCollapsed> <d-panel-header> Panel with foldable @@ -82,32 +82,32 @@ describe('DPanel',()=>{ 切换LeftPadding </button> `, - setup(){ - const leftPadding = ref(false); - const change = () => { - leftPadding.value = !leftPadding.value; - } - return { - leftPadding, - change - } - } - }); - expect(wrapper.find('.devui-panel-body-collapse').classes().length).toBe(3); - await wrapper.find('button').trigger('click'); - expect(wrapper.find('.devui-panel-body-collapse').classes().length).toBe(2); - }) + setup(){ + const leftPadding = ref(false); + const change = () => { + leftPadding.value = !leftPadding.value; + }; + return { + leftPadding, + change + }; + } + }); + expect(wrapper.find('.devui-panel-body-collapse').classes().length).toBe(3); + await wrapper.find('button').trigger('click'); + expect(wrapper.find('.devui-panel-body-collapse').classes().length).toBe(2); + }); - it('beforeToggle-dynamic',async ()=>{ - const wrapper = mount({ - components:{ - DPanel, - DPanelBody, - DPanelHeader, - DPanelFooter, - }, - template: ` + it('beforeToggle-dynamic',async ()=>{ + const wrapper = mount({ + components:{ + DPanel, + DPanelBody, + DPanelHeader, + DPanelFooter, + }, + template: ` <d-panel :beforeToggle="beforeToggle" isCollapsed> <d-panel-header> Panel with foldable @@ -121,18 +121,18 @@ describe('DPanel',()=>{ {{ panelToggle ? '阻止折叠' : '允许折叠' }} </button> `, - setup(){ - const panelToggle = ref(false); - const beforeToggle = () => panelToggle.value; - return { - panelToggle, - beforeToggle, - } - } - }); - await wrapper.find('button').trigger('click'); - expect(wrapper.vm.panelToggle).toBe(true); - await wrapper.find('button').trigger('click'); - expect(wrapper.vm.panelToggle).toBe(false); - }) -}) \ No newline at end of file + setup(){ + const panelToggle = ref(false); + const beforeToggle = () => panelToggle.value; + return { + panelToggle, + beforeToggle, + }; + } + }); + await wrapper.find('button').trigger('click'); + expect(wrapper.vm.panelToggle).toBe(true); + await wrapper.find('button').trigger('click'); + expect(wrapper.vm.panelToggle).toBe(false); + }); +}); diff --git a/packages/devui-vue/devui/panel/index.ts b/packages/devui-vue/devui/panel/index.ts index 56eaba1e71..800b2bd274 100644 --- a/packages/devui-vue/devui/panel/index.ts +++ b/packages/devui-vue/devui/panel/index.ts @@ -1,24 +1,24 @@ -import type { App } from 'vue' -import Panel from './src/panel' +import type { App } from 'vue'; +import Panel from './src/panel'; import PanelHeader from './src/header/panel-header'; import PanelBody from './src/body/panel-body'; import PanelFooter from './src/foot/panel-footer'; Panel.install = function(app: App) { - app.component(Panel.name, Panel) + app.component(Panel.name, Panel); app.component(PanelHeader.name, PanelHeader); app.component(PanelBody.name, PanelBody); app.component(PanelFooter.name, PanelFooter); -} +}; -export { Panel } +export { Panel }; export default { title: 'Panel 面板', category: '通用', status: '100%', install(app: App): void { - app.use(Panel as any) + app.use(Panel as any); } -} +}; diff --git a/packages/devui-vue/devui/panel/src/body/panel-body.tsx b/packages/devui-vue/devui/panel/src/body/panel-body.tsx index 9868678615..345b13baed 100644 --- a/packages/devui-vue/devui/panel/src/body/panel-body.tsx +++ b/packages/devui-vue/devui/panel/src/body/panel-body.tsx @@ -3,49 +3,49 @@ import { PanelProps } from '../panel.type'; import Store from '../store/store'; export default defineComponent({ - name: 'DPanelBody', - props:PanelProps, - setup(props,ctx){ - const animationName = inject('showAnimation') as Ref<any>; - const hasLeftPadding = inject('hasLeftPadding') as Ref<any>; - const keys = Object.keys(Store.state()); - const key = keys.pop(); - const isCollapsed = Store.state(); - const bodyEl = ref(); - onMounted(() => { - if(bodyEl.value) { - const dom = bodyEl.value; - if(isCollapsed[key]) - dom.style.height = `${dom.offsetHeight}px`; - } - }) - - const enter = (element: Element ) => { - const el = (element as HTMLElement); - el.style.height = ''; - const height = el.offsetHeight; - el.style.height = '0px'; - // 需要执行一次才会生效 - el.offsetHeight; - el.style.height = `${height}px`; - } - const leave = (element: Element) => { - const el = (element as HTMLElement); - el.style.height = '0px'; - } - return () => { - return ( - <div class={`devui-panel devui-panel-${props.type} ${props.cssClass}`}> - <Transition name={animationName.value ? 'devui-panel' : ''} onEnter={ enter } onLeave={leave}> - {isCollapsed[key] === undefined || isCollapsed[key] ? - <div ref={bodyEl} class={`devui-panel-body ${isCollapsed[key] !== undefined ? 'devui-panel-body-collapse': ''} ${!hasLeftPadding.value ? 'no-left-padding' : ''}`}> - <div class="devui-panel-content"> - {ctx.slots.default?.()} - </div> - </div>: null } - </Transition> - </div> - ) - } - }, -}) \ No newline at end of file + name: 'DPanelBody', + props:PanelProps, + setup(props,ctx){ + const animationName = inject('showAnimation') as Ref<any>; + const hasLeftPadding = inject('hasLeftPadding') as Ref<any>; + const keys = Object.keys(Store.state()); + const key = keys.pop(); + const isCollapsed = Store.state(); + const bodyEl = ref(); + onMounted(() => { + if(bodyEl.value) { + const dom = bodyEl.value; + if(isCollapsed[key]) + {dom.style.height = `${dom.offsetHeight}px`;} + } + }); + + const enter = (element: Element) => { + const el = (element as HTMLElement); + el.style.height = ''; + const height = el.offsetHeight; + el.style.height = '0px'; + // 需要执行一次才会生效 + el.offsetHeight; + el.style.height = `${height}px`; + }; + const leave = (element: Element) => { + const el = (element as HTMLElement); + el.style.height = '0px'; + }; + return () => { + return ( + <div class={`devui-panel devui-panel-${props.type} ${props.cssClass}`}> + <Transition name={animationName.value ? 'devui-panel' : ''} onEnter={ enter } onLeave={leave}> + {isCollapsed[key] === undefined || isCollapsed[key] ? + <div ref={bodyEl} class={`devui-panel-body ${isCollapsed[key] !== undefined ? 'devui-panel-body-collapse': ''} ${!hasLeftPadding.value ? 'no-left-padding' : ''}`}> + <div class="devui-panel-content"> + {ctx.slots.default?.()} + </div> + </div>: null } + </Transition> + </div> + ); + }; + }, +}); diff --git a/packages/devui-vue/devui/panel/src/foot/panel-footer.tsx b/packages/devui-vue/devui/panel/src/foot/panel-footer.tsx index 65d7a3ad6e..551dcd6a8f 100644 --- a/packages/devui-vue/devui/panel/src/foot/panel-footer.tsx +++ b/packages/devui-vue/devui/panel/src/foot/panel-footer.tsx @@ -1,14 +1,14 @@ import {ref,defineComponent} from 'vue'; export default defineComponent({ - name: 'DPanelFooter', - setup(props,ctx){ - return () => { - const footerContent = (ctx.slots.default ? - <div class="devui-panel-footer"> - { ctx.slots.default?.() } - </div> : null); - return footerContent - } - } -}) \ No newline at end of file + name: 'DPanelFooter', + setup(props,ctx){ + return () => { + const footerContent = (ctx.slots.default ? + <div class="devui-panel-footer"> + { ctx.slots.default?.() } + </div> : null); + return footerContent; + }; + } +}); diff --git a/packages/devui-vue/devui/panel/src/header/panel-header.tsx b/packages/devui-vue/devui/panel/src/header/panel-header.tsx index 25e36da9d2..2262c09551 100644 --- a/packages/devui-vue/devui/panel/src/header/panel-header.tsx +++ b/packages/devui-vue/devui/panel/src/header/panel-header.tsx @@ -3,68 +3,68 @@ import {PanelProps} from '../panel.type'; import Store from '../store/store'; export default defineComponent({ - name: 'DPanelHeader', - props: PanelProps, - setup(props,ctx){ - const beforeToggle = inject('beforeToggle'); - const keys = Object.keys(Store.state()); - const key = keys.pop(); - const isCollapsed = ref(Store.state()[key]); - // 当beforeToggle为fals时 - // 最好cursor是default 而不是 pointer; - // pointer一般用于可点击的 - // 用changeFlag - const changeFlag = ref(); - let header = null; + name: 'DPanelHeader', + props: PanelProps, + setup(props,ctx){ + const beforeToggle = inject('beforeToggle'); + const keys = Object.keys(Store.state()); + const key = keys.pop(); + const isCollapsed = ref(Store.state()[key]); + // 当beforeToggle为fals时 + // 最好cursor是default 而不是 pointer; + // pointer一般用于可点击的 + // 用changeFlag + const changeFlag = ref(); + let header = null; - const canToggle = (): Promise<boolean> => { - let changeResult = Promise.resolve(true); - if(beforeToggle) { - const result = beforeToggle(isCollapsed); - if(typeof result !== undefined) { - if(result instanceof Promise) { - changeResult = result; - } else { - changeResult = Promise.resolve(result); - } - } + const canToggle = (): Promise<boolean> => { + let changeResult = Promise.resolve(true); + if(beforeToggle) { + const result = beforeToggle(isCollapsed); + if(typeof result !== undefined) { + if(result instanceof Promise) { + changeResult = result; + } else { + changeResult = Promise.resolve(result); } - return changeResult; } + } + return changeResult; + }; - // 需要执行一次才能生效; - canToggle().then((val)=>changeFlag.value = val) - - const toggleBody = (): void => { - canToggle().then((val) => { - changeFlag.value = val; - if (!val){ - // 禁止折叠不影响展开 - if (!isCollapsed.value){ - Store.setData(`${key}`, !isCollapsed.value); - isCollapsed.value = !isCollapsed.value; - props.toggle?.(isCollapsed.value); - } - return; - } - if (isCollapsed.value !== undefined) { - Store.setData(`${key}`, !isCollapsed.value); - isCollapsed.value = !isCollapsed.value; - props.toggle?.(isCollapsed.value); - } - }) - - }; - return () => { - if (ctx.slots.default){ - header = ( - <div class="devui-panel-heading" onClick={toggleBody} style={{ 'cursor': changeFlag.value ? 'pointer' : 'auto' }}> - {ctx.slots.default?.()} - </div> - ) - } - return header + // 需要执行一次才能生效; + canToggle().then((val)=>changeFlag.value = val); + + const toggleBody = (): void => { + canToggle().then((val) => { + changeFlag.value = val; + if (!val){ + // 禁止折叠不影响展开 + if (!isCollapsed.value){ + Store.setData(`${key}`, !isCollapsed.value); + isCollapsed.value = !isCollapsed.value; + props.toggle?.(isCollapsed.value); + } + return; } - }, -}) \ No newline at end of file + if (isCollapsed.value !== undefined) { + Store.setData(`${key}`, !isCollapsed.value); + isCollapsed.value = !isCollapsed.value; + props.toggle?.(isCollapsed.value); + } + }); + + }; + return () => { + if (ctx.slots.default){ + header = ( + <div class="devui-panel-heading" onClick={toggleBody} style={{ 'cursor': changeFlag.value ? 'pointer' : 'auto' }}> + {ctx.slots.default?.()} + </div> + ); + } + return header; + }; + }, +}); diff --git a/packages/devui-vue/devui/panel/src/panel.tsx b/packages/devui-vue/devui/panel/src/panel.tsx index 5c601aee23..90c2b1733d 100644 --- a/packages/devui-vue/devui/panel/src/panel.tsx +++ b/packages/devui-vue/devui/panel/src/panel.tsx @@ -14,7 +14,7 @@ export default defineComponent({ const type = computed(()=>props.type); const cssClass = computed(()=>props.cssClass); const onToggle = ()=> { - props.toggle?.(Store.getByKey(`isCollapsed[${timeStamp}]`)) + props.toggle?.(Store.getByKey(`isCollapsed[${timeStamp}]`)); }; const timeStamp = new Date().getTime().toString(); Store.setData(`isCollapsed[${timeStamp}]`, isCollapsed.value); @@ -23,7 +23,7 @@ export default defineComponent({ <div onClick = {onToggle} class={`devui-panel devui-panel-${type.value} ${cssClass.value}`}> {ctx.slots.default?.()} </div> - ) - } + ); + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/panel/src/panel.type.ts b/packages/devui-vue/devui/panel/src/panel.type.ts index ed23606652..634550e232 100644 --- a/packages/devui-vue/devui/panel/src/panel.type.ts +++ b/packages/devui-vue/devui/panel/src/panel.type.ts @@ -19,8 +19,8 @@ export const PanelProps = { type: Function as unknown as () => (value: boolean) => boolean | Promise<boolean>, default: null }, - toggle: { - type: Function as unknown as ()=> ((value: boolean) => void), + toggle: { + type: Function as unknown as () => ((value: boolean) => void), default: null }, showAnimation: { @@ -31,6 +31,6 @@ export const PanelProps = { type: Boolean, default: true, } -} +}; -export type PanelPropsType = ExtractPropTypes<typeof PanelProps>; \ No newline at end of file +export type PanelPropsType = ExtractPropTypes<typeof PanelProps>; diff --git a/packages/devui-vue/devui/panel/src/store/store.ts b/packages/devui-vue/devui/panel/src/store/store.ts index d274bff295..a85617322d 100644 --- a/packages/devui-vue/devui/panel/src/store/store.ts +++ b/packages/devui-vue/devui/panel/src/store/store.ts @@ -1,18 +1,18 @@ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ import {ref,reactive} from 'vue'; -export const option = reactive({}) +export const option = reactive({}); class Store { - public static getByKey(timeStamp){ - return option[timeStamp]; - } - public static state() { - return option; - } - public static setData(key,value){ - option[key] = ref(value); - } + public static getByKey(timeStamp){ + return option[timeStamp]; + } + public static state() { + return option; + } + public static setData(key,value){ + option[key] = ref(value); + } } -export default Store \ No newline at end of file +export default Store; diff --git a/packages/devui-vue/devui/popover/__tests__/popover.spec.ts b/packages/devui-vue/devui/popover/__tests__/popover.spec.ts index 387c5b3545..a2500da34c 100644 --- a/packages/devui-vue/devui/popover/__tests__/popover.spec.ts +++ b/packages/devui-vue/devui/popover/__tests__/popover.spec.ts @@ -1,100 +1,100 @@ import { shallowMount } from '@vue/test-utils'; -import DPopover from '../src/popover' +import DPopover from '../src/popover'; describe('DPopover', () => { - it('visible', () => { - const wrapper = shallowMount(DPopover, { - props: { - visible: true - } - }) - expect(wrapper.props().visible).toBeTruthy() - expect(wrapper.classes().includes('devui-popover-isVisible')).toBeTruthy() - }) + it('visible', () => { + const wrapper = shallowMount(DPopover, { + props: { + visible: true + } + }); + expect(wrapper.props().visible).toBeTruthy(); + expect(wrapper.classes().includes('devui-popover-isVisible')).toBeTruthy(); + }); - it('position', () => { - const left = 'left' - const wrapper = shallowMount(DPopover, { - props: { - position: left - } - }) - expect(wrapper.props().position).toBe(left) - expect(wrapper.classes().includes(left)).toBeTruthy() - }) + it('position', () => { + const left = 'left'; + const wrapper = shallowMount(DPopover, { + props: { + position: left + } + }); + expect(wrapper.props().position).toBe(left); + expect(wrapper.classes().includes(left)).toBeTruthy(); + }); - it('content', () => { - const content = '自定义内容' - const wrapper = shallowMount(DPopover, { - props: { - content - } - }) - expect(wrapper.props().content).toBe(content) - expect(wrapper.find('.devui-popover-content').text()).toBe(content) - }) + it('content', () => { + const content = '自定义内容'; + const wrapper = shallowMount(DPopover, { + props: { + content + } + }); + expect(wrapper.props().content).toBe(content); + expect(wrapper.find('.devui-popover-content').text()).toBe(content); + }); - it('trigger click', async () => { - const wrapper = shallowMount(DPopover, { - props: { - controlled: true - } - }) - const isVisible = () => expect(wrapper.classes().includes('devui-popover-isVisible')) - isVisible().toBeFalsy() - await wrapper.find('.devui-popover-reference').trigger('click') - isVisible().toBeTruthy(); - }) + it('trigger click', async () => { + const wrapper = shallowMount(DPopover, { + props: { + controlled: true + } + }); + const isVisible = () => expect(wrapper.classes().includes('devui-popover-isVisible')); + isVisible().toBeFalsy(); + await wrapper.find('.devui-popover-reference').trigger('click'); + isVisible().toBeTruthy(); + }); - it('trigger mouse', async () => { - const wrapper = shallowMount(DPopover, { - props: { - trigger: 'hover' - } - }) - const isVisible = () => expect(wrapper.classes().includes('devui-popover-isVisible')) - isVisible().toBeFalsy() - wrapper.find('.devui-popover-reference').trigger('onMouseenter') - wrapper.vm.$nextTick(() => { - isVisible().toBeTruthy() - }) - }) + it('trigger mouse', async () => { + const wrapper = shallowMount(DPopover, { + props: { + trigger: 'hover' + } + }); + const isVisible = () => expect(wrapper.classes().includes('devui-popover-isVisible')); + isVisible().toBeFalsy(); + wrapper.find('.devui-popover-reference').trigger('onMouseenter'); + wrapper.vm.$nextTick(() => { + isVisible().toBeTruthy(); + }); + }); - it('zIndex', () => { - const zIndex = 1000 - const wrapper = shallowMount(DPopover, { - props: { - zIndex - } - }) - expect(wrapper.props().zIndex).toBe(zIndex); - }) + it('zIndex', () => { + const zIndex = 1000; + const wrapper = shallowMount(DPopover, { + props: { + zIndex + } + }); + expect(wrapper.props().zIndex).toBe(zIndex); + }); - it('popType', () => { - const wrapper = shallowMount(DPopover, { - props: { - popType: 'warning' - } - }) - expect(wrapper.find('.devui-popover-icon').attributes().name).toBe('warning-o') - }) + it('popType', () => { + const wrapper = shallowMount(DPopover, { + props: { + popType: 'warning' + } + }); + expect(wrapper.find('.devui-popover-icon').attributes().name).toBe('warning-o'); + }); - it('showAnimation', () => { - const wrapper = shallowMount(DPopover, { - props: { - showAnimation: false, - } - }) - expect(wrapper.classes().includes('devui-popover-animation')).toBeFalsy() - }) + it('showAnimation', () => { + const wrapper = shallowMount(DPopover, { + props: { + showAnimation: false, + } + }); + expect(wrapper.classes().includes('devui-popover-animation')).toBeFalsy(); + }); - it('popMaxWidth', () => { - const popMaxWidth = 30 - const wrapper = shallowMount(DPopover, { - props: { - popMaxWidth - } - }) - expect(wrapper.props().popMaxWidth).toBe(popMaxWidth) - }) + it('popMaxWidth', () => { + const popMaxWidth = 30; + const wrapper = shallowMount(DPopover, { + props: { + popMaxWidth + } + }); + expect(wrapper.props().popMaxWidth).toBe(popMaxWidth); + }); -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/progress/__tests__/progress.spec.ts b/packages/devui-vue/devui/progress/__tests__/progress.spec.ts index bbba5df871..e63eae4983 100644 --- a/packages/devui-vue/devui/progress/__tests__/progress.spec.ts +++ b/packages/devui-vue/devui/progress/__tests__/progress.spec.ts @@ -2,72 +2,72 @@ import { mount } from '@vue/test-utils'; import Progress from '../src/progress'; describe('progress', () => { - describe('progress basic', () => { - const TestComponent = { - components: { - 'd-progress': Progress, - }, - template: ` + describe('progress basic', () => { + const TestComponent = { + components: { + 'd-progress': Progress, + }, + template: ` <div class="progress-container"> <d-progress :percentage="80" percentageText="80%"></d-progress> </div> `, - } - const wrapper = mount(TestComponent) - it('Progress demo has created successfully', async () => { - expect(wrapper).toBeTruthy() - }) - }) + }; + const wrapper = mount(TestComponent); + it('Progress demo has created successfully', async () => { + expect(wrapper).toBeTruthy(); + }); + }); - describe('read only', () => { - it('percentage should be rendered correctly', () => { - const wrapper = mount(Progress, { - props: { percentage: 20 }, - }); - expect(wrapper.props().percentage).toBe(20); - }); + describe('read only', () => { + it('percentage should be rendered correctly', () => { + const wrapper = mount(Progress, { + props: { percentage: 20 }, + }); + expect(wrapper.props().percentage).toBe(20); + }); - it('percentageText should be rendered correctly', () => { - const wrapper = mount(Progress, { - props: { percentageText: '30%' }, - }); - expect(wrapper.props().percentageText).toBe('30%'); - }); + it('percentageText should be rendered correctly', () => { + const wrapper = mount(Progress, { + props: { percentageText: '30%' }, + }); + expect(wrapper.props().percentageText).toBe('30%'); + }); - it('barbgcolor should be rendered correctly', () => { - const wrapper = mount(Progress, { - props: { barBgColor: '#5170ff' }, - }); - expect(wrapper.props().barBgColor).toBe('#5170ff'); - }); + it('barbgcolor should be rendered correctly', () => { + const wrapper = mount(Progress, { + props: { barBgColor: '#5170ff' }, + }); + expect(wrapper.props().barBgColor).toBe('#5170ff'); + }); - it('height should be rendered correctly', () => { - const wrapper = mount(Progress, { - props: { height: '20px' }, - }); - expect(wrapper.props().height).toBe('20px'); - }); + it('height should be rendered correctly', () => { + const wrapper = mount(Progress, { + props: { height: '20px' }, + }); + expect(wrapper.props().height).toBe('20px'); + }); - it('isCircle should be rendered correctly', () => { - const wrapper = mount(Progress, { - props: { isCircle: false }, - }); - expect(wrapper.props().isCircle).toBe(false); - }); + it('isCircle should be rendered correctly', () => { + const wrapper = mount(Progress, { + props: { isCircle: false }, + }); + expect(wrapper.props().isCircle).toBe(false); + }); - it('strokeWidth should be rendered correctly', () => { - const wrapper = mount(Progress, { - props: { strokeWidth: 6 }, - }); - expect(wrapper.props().strokeWidth).toBe(6); - }); + it('strokeWidth should be rendered correctly', () => { + const wrapper = mount(Progress, { + props: { strokeWidth: 6 }, + }); + expect(wrapper.props().strokeWidth).toBe(6); + }); - it('showContent should be rendered correctly', () => { - const wrapper = mount(Progress, { - props: { showContent: true }, - }); - expect(wrapper.props().showContent).toBe(true); - }); - }) + it('showContent should be rendered correctly', () => { + const wrapper = mount(Progress, { + props: { showContent: true }, + }); + expect(wrapper.props().showContent).toBe(true); + }); + }); }); diff --git a/packages/devui-vue/devui/progress/index.ts b/packages/devui-vue/devui/progress/index.ts index 420816c02b..7c6a728151 100644 --- a/packages/devui-vue/devui/progress/index.ts +++ b/packages/devui-vue/devui/progress/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Progress from './src/progress' +import type { App } from 'vue'; +import Progress from './src/progress'; Progress.install = function(app: App) { - app.component(Progress.name, Progress) -} + app.component(Progress.name, Progress); +}; -export { Progress } +export { Progress }; export default { title: 'Progress 进度条', category: '数据展示', status: '100%', install(app: App): void { - app.use(Progress as any) + app.use(Progress as any); } -} +}; diff --git a/packages/devui-vue/devui/progress/src/progress.tsx b/packages/devui-vue/devui/progress/src/progress.tsx index 2c380bdc03..acaf66e723 100644 --- a/packages/devui-vue/devui/progress/src/progress.tsx +++ b/packages/devui-vue/devui/progress/src/progress.tsx @@ -3,46 +3,46 @@ import { reactive, toRefs, watch, -} from 'vue' +} from 'vue'; -import './progress.scss' +import './progress.scss'; interface data { - pathString: string - trailPath: any - strokePath: any + pathString: string; + trailPath: any; + strokePath: any; } export default defineComponent({ name: 'DProgress', props: { height: { - type: String, - default: '20px', + type: String, + default: '20px', }, percentage: { - type: Number, - default: 0, + type: Number, + default: 0, }, percentageText: { - type: String, - default: '', + type: String, + default: '', }, barBgColor: { - type: String, - default: '#5170ff', + type: String, + default: '#5170ff', }, isCircle: { - type: Boolean, - default: false, + type: Boolean, + default: false, }, strokeWidth: { - type: Number, - default: 6, + type: Number, + default: 6, }, showContent: { - type: Boolean, - default: true, + type: Boolean, + default: true, } }, setup(props) { @@ -64,7 +64,7 @@ export default defineComponent({ const setCircleProgress = () => { if (!isCircle) { - return; + return; } const radius = 50 - strokeWidth.value / 2; @@ -78,10 +78,10 @@ export default defineComponent({ const len = Math.PI * 2 * radius; data.trailPath = { - stroke: '#dfe1e6', - strokeDasharray: `${len}px ${len}px`, - strokeDashoffset: `0`, - transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s' + stroke: '#dfe1e6', + strokeDasharray: `${len}px ${len}px`, + strokeDashoffset: `0`, + transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s' }; data.strokePath = { @@ -90,13 +90,13 @@ export default defineComponent({ strokeDashoffset: `0`, transition: 'stroke-dashoffset .3s ease 0s, stroke-dasharray .3s ease 0s, stroke .3s, stroke-width .06s ease .3s' }; - } + }; setCircleProgress(); watch([height, percentage, percentageText, barBgColor, isCircle, strokeWidth, showContent], () => { setCircleProgress(); - }) + }); return { data, @@ -177,4 +177,4 @@ export default defineComponent({ </div> ); } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/quadrant-diagram/__tests__/quadrant-diagram.spec.ts b/packages/devui-vue/devui/quadrant-diagram/__tests__/quadrant-diagram.spec.ts index bb4f8a5688..c261e0b3a5 100644 --- a/packages/devui-vue/devui/quadrant-diagram/__tests__/quadrant-diagram.spec.ts +++ b/packages/devui-vue/devui/quadrant-diagram/__tests__/quadrant-diagram.spec.ts @@ -22,11 +22,11 @@ describe('d-quadrant-diagram', () => { }; } }); - console.log(wrapper.html()) + console.log(wrapper.html()); expect(wrapper.find('#devui-quadrant-axis-1').element['height']).toEqual(200); view.height = 400; await nextTick(); expect(wrapper.find('#devui-quadrant-axis-1').element['height']).toEqual(400); - }) -}); \ No newline at end of file + }); +}); diff --git a/packages/devui-vue/devui/quadrant-diagram/config.ts b/packages/devui-vue/devui/quadrant-diagram/config.ts index c89a9443fa..17d708dc6b 100644 --- a/packages/devui-vue/devui/quadrant-diagram/config.ts +++ b/packages/devui-vue/devui/quadrant-diagram/config.ts @@ -32,7 +32,7 @@ export const DEFAULT_QUADRANT_CONFIGS = [ export const DEFAULT_VIEW_CONFIGS = { height: 900, width: 950, -} +}; export const AXIS_TITLE_SPACE = 15; export const SMALL_LABEL_SIZE_CENTER_POINT = { x: 6, y: 6 diff --git a/packages/devui-vue/devui/quadrant-diagram/index.ts b/packages/devui-vue/devui/quadrant-diagram/index.ts index db4125190f..bb6b80123e 100644 --- a/packages/devui-vue/devui/quadrant-diagram/index.ts +++ b/packages/devui-vue/devui/quadrant-diagram/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import QuadrantDiagram from './src/quadrant-diagram' +import type { App } from 'vue'; +import QuadrantDiagram from './src/quadrant-diagram'; QuadrantDiagram.install = function (app: App) { - app.component(QuadrantDiagram.name, QuadrantDiagram) -} + app.component(QuadrantDiagram.name, QuadrantDiagram); +}; -export { QuadrantDiagram } +export { QuadrantDiagram }; export default { title: 'QuadrantDiagram 象限图', category: '数据展示', status: '10%', install(app: App): void { - app.use(QuadrantDiagram as any) + app.use(QuadrantDiagram as any); } -} +}; diff --git a/packages/devui-vue/devui/quadrant-diagram/src/components/axis/index.tsx b/packages/devui-vue/devui/quadrant-diagram/src/components/axis/index.tsx index 8929a29847..bd685b37f2 100644 --- a/packages/devui-vue/devui/quadrant-diagram/src/components/axis/index.tsx +++ b/packages/devui-vue/devui/quadrant-diagram/src/components/axis/index.tsx @@ -1,22 +1,22 @@ -import { defineComponent, toRefs, onMounted, ExtractPropTypes, reactive, ref, watch } from 'vue' -import { IViewConfigs, IAxisConfigs } from '../../../type' -import { AXIS_TITLE_SPACE } from '../../../config' -import { quadrantDiagramAxisProps, QuadrantDiagramAxisProps } from './types' -import { debounce } from 'lodash' +import { defineComponent, toRefs, onMounted, ExtractPropTypes, reactive, ref, watch } from 'vue'; +import { IViewConfigs, IAxisConfigs } from '../../../type'; +import { AXIS_TITLE_SPACE } from '../../../config'; +import { quadrantDiagramAxisProps, QuadrantDiagramAxisProps } from './types'; +import { debounce } from 'lodash'; -import './index.scss' +import './index.scss'; export default defineComponent({ name: 'DQuadrantDiagramAxis', props: quadrantDiagramAxisProps, setup(props: QuadrantDiagramAxisProps) { - const { diagramId, view, axisConfigs } = toRefs(props) - const AXIS_COLOR = ref('#0000ff') - const AXIS_LABEL_COLOR = ref('#ff0000') + const { diagramId, view, axisConfigs } = toRefs(props); + const AXIS_COLOR = ref('#0000ff'); + const AXIS_LABEL_COLOR = ref('#ff0000'); - const quadrantAxis = ref() - const context = ref() + const quadrantAxis = ref(); + const context = ref(); const axisInnerAttr = reactive({ axisOrigin: { x: 0, @@ -30,195 +30,195 @@ export default defineComponent({ xAxisTicksNum: 0, xTickSpacing: 0, yTickSpacing: 0, - }) + }); + + const axisConfigsVal: IAxisConfigs = axisConfigs.value; - const axisConfigsVal: IAxisConfigs = axisConfigs.value - onMounted(() => { - resetAxis() - }) - + resetAxis(); + }); + watch(view.value, () => { - resetAxis() - }) + resetAxis(); + }); const resetAxis = debounce(() => { - initAxisData() - setAxisData() - drawAxis() - drawAxisLabels() - }, 200) + initAxisData(); + setAxisData(); + drawAxis(); + drawAxisLabels(); + }, 200); /** * 获取 canvas 并赋值宽高 */ const initAxisData = () => { - quadrantAxis.value = document.querySelector('#devui-quadrant-axis-' + diagramId.value) - } + quadrantAxis.value = document.querySelector('#devui-quadrant-axis-' + diagramId.value); + }; const setAxisData = () => { - context.value = quadrantAxis.value.getContext('2d') - axisInnerAttr.axisOrigin = axisConfigsVal.axisOrigin - axisInnerAttr.axisTop = axisConfigsVal.axisTop - axisInnerAttr.axisRight = axisConfigsVal.axisRight - axisInnerAttr.axisWidth = axisConfigsVal.axisWidth - axisInnerAttr.axisHeight = axisConfigsVal.axisHeight - axisInnerAttr.yAxisTicksNum = axisConfigsVal.yAxisTicksNum - axisInnerAttr.xAxisTicksNum = axisConfigsVal.xAxisTicksNum - axisInnerAttr.xTickSpacing = axisConfigsVal.xTickSpacing - axisInnerAttr.yTickSpacing = axisConfigsVal.yTickSpacing - } - - /** - * 执行绘制 + context.value = quadrantAxis.value.getContext('2d'); + axisInnerAttr.axisOrigin = axisConfigsVal.axisOrigin; + axisInnerAttr.axisTop = axisConfigsVal.axisTop; + axisInnerAttr.axisRight = axisConfigsVal.axisRight; + axisInnerAttr.axisWidth = axisConfigsVal.axisWidth; + axisInnerAttr.axisHeight = axisConfigsVal.axisHeight; + axisInnerAttr.yAxisTicksNum = axisConfigsVal.yAxisTicksNum; + axisInnerAttr.xAxisTicksNum = axisConfigsVal.xAxisTicksNum; + axisInnerAttr.xTickSpacing = axisConfigsVal.xTickSpacing; + axisInnerAttr.yTickSpacing = axisConfigsVal.yTickSpacing; + }; + + /** + * 执行绘制 */ const drawAxis = () => { - context.value.save() - context.value.fillStyle = AXIS_COLOR.value - context.value.strokeStyle = AXIS_COLOR.value - drawXAxis() - drawYAxis() - context.value.lineWidth = 0.5 - drawXAxisTicks() - drawYAxisTicks() - context.value.restore() - } + context.value.save(); + context.value.fillStyle = AXIS_COLOR.value; + context.value.strokeStyle = AXIS_COLOR.value; + drawXAxis(); + drawYAxis(); + context.value.lineWidth = 0.5; + drawXAxisTicks(); + drawYAxisTicks(); + context.value.restore(); + }; /** * 绘制 XY 轴 */ const drawYAxis = () => { - context.value.beginPath() - context.value.moveTo(axisInnerAttr.axisOrigin.x, axisInnerAttr.axisOrigin.y) - context.value.lineTo(axisInnerAttr.axisOrigin.x, axisInnerAttr.axisTop - axisConfigsVal.axisMargin) - context.value.stroke() - context.value.moveTo(axisInnerAttr.axisOrigin.x, axisInnerAttr.axisTop - axisConfigsVal.axisMargin) - context.value.lineTo(axisInnerAttr.axisOrigin.x + 5, axisInnerAttr.axisTop - axisConfigsVal.axisMargin + 10) - context.value.lineTo(axisInnerAttr.axisOrigin.x - 5, axisInnerAttr.axisTop - axisConfigsVal.axisMargin + 10) - context.value.fill() - - } + context.value.beginPath(); + context.value.moveTo(axisInnerAttr.axisOrigin.x, axisInnerAttr.axisOrigin.y); + context.value.lineTo(axisInnerAttr.axisOrigin.x, axisInnerAttr.axisTop - axisConfigsVal.axisMargin); + context.value.stroke(); + context.value.moveTo(axisInnerAttr.axisOrigin.x, axisInnerAttr.axisTop - axisConfigsVal.axisMargin); + context.value.lineTo(axisInnerAttr.axisOrigin.x + 5, axisInnerAttr.axisTop - axisConfigsVal.axisMargin + 10); + context.value.lineTo(axisInnerAttr.axisOrigin.x - 5, axisInnerAttr.axisTop - axisConfigsVal.axisMargin + 10); + context.value.fill(); + + }; const drawXAxis = () => { - context.value.beginPath() - context.value.moveTo(axisInnerAttr.axisOrigin.x, axisInnerAttr.axisOrigin.y) - context.value.lineTo(axisInnerAttr.axisRight + axisConfigsVal.axisMargin - 10, axisInnerAttr.axisOrigin.y) - context.value.stroke() + context.value.beginPath(); + context.value.moveTo(axisInnerAttr.axisOrigin.x, axisInnerAttr.axisOrigin.y); + context.value.lineTo(axisInnerAttr.axisRight + axisConfigsVal.axisMargin - 10, axisInnerAttr.axisOrigin.y); + context.value.stroke(); // 绘制坐标轴三角形 - context.value.moveTo(axisInnerAttr.axisRight + axisConfigsVal.axisMargin, axisInnerAttr.axisOrigin.y) - context.value.lineTo(axisInnerAttr.axisRight + axisConfigsVal.axisMargin - 10, axisInnerAttr.axisOrigin.y + 5) - context.value.lineTo(axisInnerAttr.axisRight + axisConfigsVal.axisMargin - 10, axisInnerAttr.axisOrigin.y - 5) - context.value.fill() - } + context.value.moveTo(axisInnerAttr.axisRight + axisConfigsVal.axisMargin, axisInnerAttr.axisOrigin.y); + context.value.lineTo(axisInnerAttr.axisRight + axisConfigsVal.axisMargin - 10, axisInnerAttr.axisOrigin.y + 5); + context.value.lineTo(axisInnerAttr.axisRight + axisConfigsVal.axisMargin - 10, axisInnerAttr.axisOrigin.y - 5); + context.value.fill(); + }; /** * 绘制轴线刻度 */ const drawXAxisTicks = () => { - let deltaY: number + let deltaY: number; for (let i = 1; i < axisInnerAttr.xAxisTicksNum; i++) { - context.value.beginPath() + context.value.beginPath(); // 判断显示长刻度还是短刻度 if (i % axisConfigsVal.xAxisRange.step === 0) { - deltaY = axisConfigsVal.tickWidth + deltaY = axisConfigsVal.tickWidth; } else { - deltaY = axisConfigsVal.tickWidth / 2 + deltaY = axisConfigsVal.tickWidth / 2; } context.value.moveTo(axisInnerAttr.axisOrigin.x + i * axisInnerAttr.xTickSpacing, - axisInnerAttr.axisOrigin.y - deltaY) + axisInnerAttr.axisOrigin.y - deltaY); context.value.lineTo(axisInnerAttr.axisOrigin.x + i * axisInnerAttr.xTickSpacing, - axisInnerAttr.axisOrigin.y + deltaY) - context.value.stroke() + axisInnerAttr.axisOrigin.y + deltaY); + context.value.stroke(); } - } + }; const drawYAxisTicks = () => { - let deltaX: number + let deltaX: number; for (let i = 1; i < axisInnerAttr.yAxisTicksNum; i++) { - context.value.beginPath() + context.value.beginPath(); if (i % axisConfigsVal.yAxisRange.step === 0) { - deltaX = axisConfigsVal.tickWidth + deltaX = axisConfigsVal.tickWidth; } else { - deltaX = axisConfigsVal.tickWidth / 2 + deltaX = axisConfigsVal.tickWidth / 2; } context.value.moveTo(axisInnerAttr.axisOrigin.x - deltaX, - axisInnerAttr.axisOrigin.y - i * axisInnerAttr.yTickSpacing) + axisInnerAttr.axisOrigin.y - i * axisInnerAttr.yTickSpacing); context.value.lineTo(axisInnerAttr.axisOrigin.x + deltaX, - axisInnerAttr.axisOrigin.y - i * axisInnerAttr.yTickSpacing) - context.value.stroke() + axisInnerAttr.axisOrigin.y - i * axisInnerAttr.yTickSpacing); + context.value.stroke(); } - } + }; /** * 绘制轴线标签 */ const drawAxisLabels = () => { - context.value.save() - context.value.fillStyle = AXIS_LABEL_COLOR.value - drawXTicksLabels() - drawYTicksLabels() - context.value.restore() - drawAxisTitle() - } + context.value.save(); + context.value.fillStyle = AXIS_LABEL_COLOR.value; + drawXTicksLabels(); + drawYTicksLabels(); + context.value.restore(); + drawAxisTitle(); + }; const drawXTicksLabels = () => { - context.value.textAlign = 'center' - context.value.textBaseline = 'top' + context.value.textAlign = 'center'; + context.value.textBaseline = 'top'; for (let i = 0; i <= axisInnerAttr.xAxisTicksNum; i++) { if (i % axisConfigsVal.xAxisRange.step === 0) { context.value.fillText(i, axisInnerAttr.axisOrigin.x + i * axisInnerAttr.xTickSpacing, - axisInnerAttr.axisOrigin.y + axisConfigsVal.spaceBetweenLabelsAxis) + axisInnerAttr.axisOrigin.y + axisConfigsVal.spaceBetweenLabelsAxis); } } - } + }; const drawYTicksLabels = () => { - context.value.textAlign = 'center' - context.value.textBaseline = 'middle' + context.value.textAlign = 'center'; + context.value.textBaseline = 'middle'; for (let i = 0; i <= axisInnerAttr.yAxisTicksNum; i++) { if (i % axisConfigsVal.yAxisRange.step === 0) { context.value.fillText(i, axisInnerAttr.axisOrigin.x - axisConfigsVal.spaceBetweenLabelsAxis, - axisInnerAttr.axisOrigin.y - i * axisInnerAttr.yTickSpacing) + axisInnerAttr.axisOrigin.y - i * axisInnerAttr.yTickSpacing); } } - } + }; const drawAxisTitle = () => { - context.value.font = '12px Microsoft YaHei' - context.value.textAlign = 'left' - context.value.fillStyle = AXIS_LABEL_COLOR.value - const xLabelWidth = context.value.measureText(axisConfigsVal.xAxisLabel).width + context.value.font = '12px Microsoft YaHei'; + context.value.textAlign = 'left'; + context.value.fillStyle = AXIS_LABEL_COLOR.value; + const xLabelWidth = context.value.measureText(axisConfigsVal.xAxisLabel).width; rotateLabel(axisConfigsVal.xAxisLabel, axisInnerAttr.axisRight + axisConfigsVal.axisMargin / 2, - axisInnerAttr.axisOrigin.y - xLabelWidth - AXIS_TITLE_SPACE) + axisInnerAttr.axisOrigin.y - xLabelWidth - AXIS_TITLE_SPACE); context.value.fillText(axisConfigsVal.yAxisLabel, - axisInnerAttr.axisOrigin.x + AXIS_TITLE_SPACE, axisInnerAttr.axisTop - axisConfigsVal.axisMargin / 2) - } + axisInnerAttr.axisOrigin.x + AXIS_TITLE_SPACE, axisInnerAttr.axisTop - axisConfigsVal.axisMargin / 2); + }; const rotateLabel = (name: string, x: number, y: number) => { for (let i = 0; i < name.length; i++) { - const str = name.slice(i, i + 1).toString() + const str = name.slice(i, i + 1).toString(); if (str.match(/[A-Za-z0-9]/)) { - context.value.save() - context.value.translate(x, y) - context.value.rotate(Math.PI / 180 * 90) - context.value.textBaseline = 'bottom' - context.value.fillText(str, 0, 0) - context.value.restore() - y += context.value.measureText(str).width + context.value.save(); + context.value.translate(x, y); + context.value.rotate(Math.PI / 180 * 90); + context.value.textBaseline = 'bottom'; + context.value.fillText(str, 0, 0); + context.value.restore(); + y += context.value.measureText(str).width; } else if (str.match(/[\u4E00-\u9FA5]/)) { - context.value.save() - context.value.textBaseline = 'top' - context.value.fillText(str, x, y) - context.value.restore() - y += context.value.measureText(str).width + context.value.save(); + context.value.textBaseline = 'top'; + context.value.fillText(str, x, y); + context.value.restore(); + y += context.value.measureText(str).width; } } - } + }; }, render() { - const { diagramId, view } = this + const { diagramId, view } = this; return ( <div> <canvas id={'devui-quadrant-axis-' + diagramId} height={view.height} width={view.width}></canvas> </div> - ) + ); } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/quadrant-diagram/src/components/axis/types.ts b/packages/devui-vue/devui/quadrant-diagram/src/components/axis/types.ts index c6c84fdd4d..d7cd94f288 100644 --- a/packages/devui-vue/devui/quadrant-diagram/src/components/axis/types.ts +++ b/packages/devui-vue/devui/quadrant-diagram/src/components/axis/types.ts @@ -1,5 +1,5 @@ -import type { ExtractPropTypes, PropType } from 'vue' -import { IViewConfigs, IAxisConfigs } from '../../../type' +import type { ExtractPropTypes, PropType } from 'vue'; +import { IViewConfigs, IAxisConfigs } from '../../../type'; export const quadrantDiagramAxisProps = { diagramId: { @@ -11,6 +11,6 @@ export const quadrantDiagramAxisProps = { view: { type: Object as PropType<IViewConfigs>, }, -} as const +} as const; -export type QuadrantDiagramAxisProps = ExtractPropTypes<typeof quadrantDiagramAxisProps> \ No newline at end of file +export type QuadrantDiagramAxisProps = ExtractPropTypes<typeof quadrantDiagramAxisProps>; diff --git a/packages/devui-vue/devui/quadrant-diagram/src/quadrant-diagram-types.ts b/packages/devui-vue/devui/quadrant-diagram/src/quadrant-diagram-types.ts index 26f9e8df23..4817c0df48 100644 --- a/packages/devui-vue/devui/quadrant-diagram/src/quadrant-diagram-types.ts +++ b/packages/devui-vue/devui/quadrant-diagram/src/quadrant-diagram-types.ts @@ -1,6 +1,6 @@ -import type { ExtractPropTypes, PropType } from 'vue' -import { DEFAULT_AXIS_CONFIGS, DEFAULT_VIEW_CONFIGS } from '../config' -import { IViewConfigs, IAxisConfigs } from '../type' +import type { ExtractPropTypes, PropType } from 'vue'; +import { DEFAULT_AXIS_CONFIGS, DEFAULT_VIEW_CONFIGS } from '../config'; +import { IViewConfigs, IAxisConfigs } from '../type'; export const quadrantDiagramProps = { diagramId: { @@ -15,6 +15,6 @@ export const quadrantDiagramProps = { type: Object as PropType<IViewConfigs>, default: DEFAULT_VIEW_CONFIGS, }, -} as const +} as const; -export type QuadrantDiagramProps = ExtractPropTypes<typeof quadrantDiagramProps> +export type QuadrantDiagramProps = ExtractPropTypes<typeof quadrantDiagramProps>; diff --git a/packages/devui-vue/devui/quadrant-diagram/src/quadrant-diagram.tsx b/packages/devui-vue/devui/quadrant-diagram/src/quadrant-diagram.tsx index 8c15874ef7..3abe6c95d2 100644 --- a/packages/devui-vue/devui/quadrant-diagram/src/quadrant-diagram.tsx +++ b/packages/devui-vue/devui/quadrant-diagram/src/quadrant-diagram.tsx @@ -1,13 +1,13 @@ -import { defineComponent, toRefs, reactive, watch } from 'vue' -import { quadrantDiagramProps, QuadrantDiagramProps } from './quadrant-diagram-types' -import DQuadrantDiagramAxis from './components/axis' -import { DEFAULT_AXIS_CONFIGS } from '../config' +import { defineComponent, toRefs, reactive, watch } from 'vue'; +import { quadrantDiagramProps, QuadrantDiagramProps } from './quadrant-diagram-types'; +import DQuadrantDiagramAxis from './components/axis'; +import { DEFAULT_AXIS_CONFIGS } from '../config'; export default defineComponent({ name: 'DQuadrantDiagram', props: quadrantDiagramProps, setup(props: QuadrantDiagramProps) { - const { diagramId, axisConfigs, view } = toRefs(props) + const { diagramId, axisConfigs, view } = toRefs(props); const calAxisConfig = reactive({ axisOrigin: { x: null, y: null }, @@ -19,44 +19,44 @@ export default defineComponent({ xAxisTicksNum: null, xTickSpacing: null, yTickSpacing: null, - }) + }); const initAxisData = () => { - const axisConfigKeys = Object.keys(DEFAULT_AXIS_CONFIGS) + const axisConfigKeys = Object.keys(DEFAULT_AXIS_CONFIGS); for (let i = 0; i < axisConfigKeys.length; i++) { if (calAxisConfig[axisConfigKeys[i]] === undefined) { - calAxisConfig[axisConfigKeys[i]] = DEFAULT_AXIS_CONFIGS[axisConfigKeys[i]] + calAxisConfig[axisConfigKeys[i]] = DEFAULT_AXIS_CONFIGS[axisConfigKeys[i]]; } } calAxisConfig.axisOrigin = { x: axisConfigs.value.originPosition.left, y: view.value.height - axisConfigs.value.originPosition.bottom - } - calAxisConfig.axisTop = axisConfigs.value.axisMargin - calAxisConfig.axisRight = view.value.width - axisConfigs.value.axisMargin - calAxisConfig.axisWidth = calAxisConfig.axisRight - calAxisConfig.axisOrigin.x - calAxisConfig.axisHeight = calAxisConfig.axisOrigin.y - calAxisConfig.axisTop - calAxisConfig.yAxisTicksNum = axisConfigs.value.yAxisRange.max - axisConfigs.value.yAxisRange.min - calAxisConfig.xAxisTicksNum = axisConfigs.value.xAxisRange.max - axisConfigs.value.xAxisRange.min - calAxisConfig.xTickSpacing = calAxisConfig.axisWidth / calAxisConfig.xAxisTicksNum - calAxisConfig.yTickSpacing = calAxisConfig.axisHeight / calAxisConfig.yAxisTicksNum - } + }; + calAxisConfig.axisTop = axisConfigs.value.axisMargin; + calAxisConfig.axisRight = view.value.width - axisConfigs.value.axisMargin; + calAxisConfig.axisWidth = calAxisConfig.axisRight - calAxisConfig.axisOrigin.x; + calAxisConfig.axisHeight = calAxisConfig.axisOrigin.y - calAxisConfig.axisTop; + calAxisConfig.yAxisTicksNum = axisConfigs.value.yAxisRange.max - axisConfigs.value.yAxisRange.min; + calAxisConfig.xAxisTicksNum = axisConfigs.value.xAxisRange.max - axisConfigs.value.xAxisRange.min; + calAxisConfig.xTickSpacing = calAxisConfig.axisWidth / calAxisConfig.xAxisTicksNum; + calAxisConfig.yTickSpacing = calAxisConfig.axisHeight / calAxisConfig.yAxisTicksNum; + }; - initAxisData() + initAxisData(); watch(view.value, () => { - initAxisData() - }) + initAxisData(); + }); - return { diagramId, calAxisConfig, } + return { diagramId, calAxisConfig, }; }, render() { - const { diagramId, calAxisConfig, view } = this + const { diagramId, calAxisConfig, view } = this; return ( <div class="devui-quadrant-diagram" id={diagramId}> <DQuadrantDiagramAxis diagramId={diagramId} axisConfigs={calAxisConfig} view={view} /> </div> - ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/quadrant-diagram/type.ts b/packages/devui-vue/devui/quadrant-diagram/type.ts index f7a13a7fcb..8d3c7a83b2 100644 --- a/packages/devui-vue/devui/quadrant-diagram/type.ts +++ b/packages/devui-vue/devui/quadrant-diagram/type.ts @@ -1,44 +1,44 @@ export interface IAxisConfigs { - tickWidth?: number // 刻度的宽(高)度,默认为10 - spaceBetweenLabelsAxis?: number // 刻度值和坐标轴之间的距离,默认为20 - axisMargin?: number // 右侧留出的空白区域 - xAxisLabel?: string // X轴名称,默认值为'紧急度' - yAxisLabel?: string // Y轴名称,默认值为'重要度' - xWeight?: number // X轴权重,默认值为1 - yWeight?: number // Y轴权重,默认值为1 - xAxisRange?: IRangeConfigs // X轴的坐标值范围和间距设置,默认值为{min:0,max:100,step:10} - yAxisRange?: IRangeConfigs // Y轴的坐标值范围和间距设置,默认值为{min:0,max:100,step:10} + tickWidth?: number; // 刻度的宽(高)度,默认为10 + spaceBetweenLabelsAxis?: number; // 刻度值和坐标轴之间的距离,默认为20 + axisMargin?: number; // 右侧留出的空白区域 + xAxisLabel?: string; // X轴名称,默认值为'紧急度' + yAxisLabel?: string; // Y轴名称,默认值为'重要度' + xWeight?: number; // X轴权重,默认值为1 + yWeight?: number; // Y轴权重,默认值为1 + xAxisRange?: IRangeConfigs; // X轴的坐标值范围和间距设置,默认值为{min:0,max:100,step:10} + yAxisRange?: IRangeConfigs; // Y轴的坐标值范围和间距设置,默认值为{min:0,max:100,step:10} originPosition?: { - left: number - bottom: number - } // 原点的位置设置,默认值为{left:30,bottom:30} - [propName: string]: any + left: number; + bottom: number; + }; // 原点的位置设置,默认值为{left:30,bottom:30} + [propName: string]: any; } export interface IQuadrantConfigs { - backgroundColor?: any - color?: any - title?: string - top?: number - left?: number + backgroundColor?: any; + color?: any; + title?: string; + top?: number; + left?: number; } export interface ILabelDataConfigs { - x: number // X轴坐标值 - y: number // Y轴坐标值 - title: string // 标签的名称 - content?: string // 鼠标悬浮在标签上时的提示内容 - progress?: number // 标签对应事项的进度 - [propName: string]: any // 其他数据 + x: number; // X轴坐标值 + y: number; // Y轴坐标值 + title: string; // 标签的名称 + content?: string; // 鼠标悬浮在标签上时的提示内容 + progress?: number; // 标签对应事项的进度 + [propName: string]: any; // 其他数据 } export interface IViewConfigs { - height: number // 象限图高度 - width: number // 象限图宽度 + height: number; // 象限图高度 + width: number; // 象限图宽度 } export interface IRangeConfigs { - min: number // 坐标轴起始值 - max: number // 坐标轴终止值 - step: number // 坐标轴刻度值的间隔 + min: number; // 坐标轴起始值 + max: number; // 坐标轴终止值 + step: number; // 坐标轴刻度值的间隔 } -export type labelSize = 'small' | 'normal' | 'large' +export type labelSize = 'small' | 'normal' | 'large'; diff --git a/packages/devui-vue/devui/radio/__tests__/radio.spec.ts b/packages/devui-vue/devui/radio/__tests__/radio.spec.ts index 5cd8274e51..a14b3e5c30 100644 --- a/packages/devui-vue/devui/radio/__tests__/radio.spec.ts +++ b/packages/devui-vue/devui/radio/__tests__/radio.spec.ts @@ -1,31 +1,31 @@ -import { mount } from '@vue/test-utils' -import { ref } from 'vue' -import DRadio from '../src/radio' +import { mount } from '@vue/test-utils'; +import { ref } from 'vue'; +import DRadio from '../src/radio'; describe('Radio', () => { /** 测试是否正常渲染 */ it('radio render work', async () => { - const onChange = jest.fn() + const onChange = jest.fn(); const wrapper = mount({ components: { DRadio }, template: `<d-radio v-model="modelValue" value="A" @change="onChange">ItemA</d-radio>`, setup() { - const modelValue = ref('Item1') + const modelValue = ref('Item1'); return { modelValue, onChange, - } + }; }, - }) + }); - expect(wrapper.classes()).toContain('devui-radio') - expect(wrapper.classes()).not.toContain('active') - expect(wrapper.text()).toEqual('ItemA') + expect(wrapper.classes()).toContain('devui-radio'); + expect(wrapper.classes()).not.toContain('active'); + expect(wrapper.text()).toEqual('ItemA'); - const input = wrapper.find('input') - await input.trigger('change') - expect(onChange).toBeCalledTimes(1) - }) + const input = wrapper.find('input'); + await input.trigger('change'); + expect(onChange).toBeCalledTimes(1); + }); /** 测试 value */ it('radio value work', () => { @@ -33,69 +33,69 @@ describe('Radio', () => { props: { value: 'Item1', }, - }) - const input = wrapper.find('input') - expect(input.attributes()['value']).toEqual('Item1') - }) + }); + const input = wrapper.find('input'); + expect(input.attributes()['value']).toEqual('Item1'); + }); /** 测试 disabled */ it('radio disabled work', async () => { - const onChange = jest.fn() + const onChange = jest.fn(); const wrapper = mount(DRadio, { props: { value: 'Item1', disabled: true, onChange, }, - }) - expect(wrapper.classes()).toContain('disabled') - const input = wrapper.find('input') - await input.trigger('change') - expect(onChange).toBeCalledTimes(0) - }) + }); + expect(wrapper.classes()).toContain('disabled'); + const input = wrapper.find('input'); + await input.trigger('change'); + expect(onChange).toBeCalledTimes(0); + }); /** 测试 disabled 切换 */ it('radio disabled change', async () => { - const onChange = jest.fn() + const onChange = jest.fn(); const wrapper = mount(DRadio, { props: { value: 'Item1', disabled: true, onChange, }, - }) - expect(wrapper.classes()).toContain('disabled') + }); + expect(wrapper.classes()).toContain('disabled'); await wrapper.setProps({ disabled: false, - }) - expect(wrapper.classes()).not.toContain('disabled') - }) + }); + expect(wrapper.classes()).not.toContain('disabled'); + }); /** 测试 beforeChange */ it('radio beforeChange work', async () => { - const beforeChange = jest.fn(() => true) - const onChange = jest.fn() + const beforeChange = jest.fn(() => true); + const onChange = jest.fn(); const wrapper = mount(DRadio, { props: { value: 'Item1', onChange, beforeChange, }, - }) - const input = wrapper.find('input') - await input.trigger('change') - expect(beforeChange).toHaveBeenCalledTimes(1) - expect(onChange).toHaveBeenCalledTimes(1) + }); + const input = wrapper.find('input'); + await input.trigger('change'); + expect(beforeChange).toHaveBeenCalledTimes(1); + expect(onChange).toHaveBeenCalledTimes(1); - const beforeChangeFalse = jest.fn(() => false) - onChange.mockReset() + const beforeChangeFalse = jest.fn(() => false); + onChange.mockReset(); await wrapper.setProps({ value: 'Item2', beforeChange: beforeChangeFalse, onChange, - }) - await input.trigger('change') - expect(beforeChangeFalse).toHaveBeenCalledTimes(1) - expect(onChange).toHaveBeenCalledTimes(0) - }) -}) + }); + await input.trigger('change'); + expect(beforeChangeFalse).toHaveBeenCalledTimes(1); + expect(onChange).toHaveBeenCalledTimes(0); + }); +}); diff --git a/packages/devui-vue/devui/radio/index.ts b/packages/devui-vue/devui/radio/index.ts index 75c93739b4..1f001f32a6 100644 --- a/packages/devui-vue/devui/radio/index.ts +++ b/packages/devui-vue/devui/radio/index.ts @@ -1,23 +1,23 @@ -import type { App } from 'vue' -import Radio from './src/radio' -import RadioGroup from './src/radio-group' +import type { App } from 'vue'; +import Radio from './src/radio'; +import RadioGroup from './src/radio-group'; Radio.install = function(app: App) { - app.component(Radio.name, Radio) -} + app.component(Radio.name, Radio); +}; RadioGroup.install = function(app: App) { - app.component(RadioGroup.name, RadioGroup) -} + app.component(RadioGroup.name, RadioGroup); +}; -export { Radio, RadioGroup } +export { Radio, RadioGroup }; export default { title: 'Radio 单选框', category: '数据录入', status: '100%', install(app: App): void { - app.use(Radio as any) - app.use(RadioGroup as any) + app.use(Radio as any); + app.use(RadioGroup as any); } -} +}; diff --git a/packages/devui-vue/devui/radio/src/radio-group.tsx b/packages/devui-vue/devui/radio/src/radio-group.tsx index b851a19010..c38edb33ed 100644 --- a/packages/devui-vue/devui/radio/src/radio-group.tsx +++ b/packages/devui-vue/devui/radio/src/radio-group.tsx @@ -1,7 +1,7 @@ -import { defineComponent, provide, toRef, ExtractPropTypes } from 'vue' -import DRadio from './radio' -import { radioGroupProps, radioGroupInjectionKey } from './radio-types' -import './radio-group.scss' +import { defineComponent, provide, toRef, ExtractPropTypes } from 'vue'; +import DRadio from './radio'; +import { radioGroupProps, radioGroupInjectionKey } from './radio-types'; +import './radio-group.scss'; export default defineComponent({ name: 'DRadioGroup', @@ -10,9 +10,9 @@ export default defineComponent({ setup(props: ExtractPropTypes<typeof radioGroupProps>, { emit }) { /** change 事件 */ const emitChange = (radioValue: string) => { - emit('update:modelValue', radioValue) - emit('change', radioValue) - } + emit('update:modelValue', radioValue); + emit('change', radioValue); + }; // 注入给子组件 provide(radioGroupInjectionKey, { @@ -21,16 +21,16 @@ export default defineComponent({ disabled: toRef(props, 'disabled'), beforeChange: props.beforeChange, emitChange - }) + }); }, render() { - const { values, direction } = this + const { values, direction } = this; /** 获取展示内容 */ const getContent = () => { - const defaultSlot = this.$slots.default + const defaultSlot = this.$slots.default; // 有默认插槽则使用默认插槽 if (defaultSlot) { - return defaultSlot() + return defaultSlot(); } // 有数据列表则使用数据列表 else if (Array.isArray(values)) { @@ -39,14 +39,14 @@ export default defineComponent({ <DRadio key={item} value={item}> {item} </DRadio> - ) - }) + ); + }); } // 什么都没有则返回空 else { - return '' + return ''; } - } + }; return ( <div @@ -60,6 +60,6 @@ export default defineComponent({ > {getContent()} </div> - ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/radio/src/radio-types.ts b/packages/devui-vue/devui/radio/src/radio-types.ts index 8448f86e9e..d241c9d8f0 100644 --- a/packages/devui-vue/devui/radio/src/radio-types.ts +++ b/packages/devui-vue/devui/radio/src/radio-types.ts @@ -1,4 +1,4 @@ -import type { InjectionKey, PropType, Ref } from 'vue' +import type { InjectionKey, PropType, Ref } from 'vue'; /** radio、radio-group 共用 props */ const radioCommonProps = { @@ -22,7 +22,7 @@ const radioCommonProps = { type: Boolean, default: false, }, -} +}; /** radio 的 props */ export const radioProps = { @@ -33,7 +33,7 @@ export const radioProps = { required: true, default: null, }, -} as const +} as const; /** radio-group 的 props */ export const radioGroupProps = { @@ -48,16 +48,16 @@ export const radioGroupProps = { type: String as PropType<'row' | 'column'>, default: 'column', }, -} as const +} as const; /** radio-group 注入字段的接口 */ interface RadioGroupInjection { - modelValue: Ref<string> - name: Ref<string> - disabled: Ref<boolean> - beforeChange: (value: string) => boolean | Promise<boolean> - emitChange: (value: string) => void + modelValue: Ref<string>; + name: Ref<string>; + disabled: Ref<boolean>; + beforeChange: (value: string) => boolean | Promise<boolean>; + emitChange: (value: string) => void; } /** radio-group 注入 radio 的 key 值 */ -export const radioGroupInjectionKey: InjectionKey<RadioGroupInjection> = Symbol('DRadioGroup') +export const radioGroupInjectionKey: InjectionKey<RadioGroupInjection> = Symbol('DRadioGroup'); diff --git a/packages/devui-vue/devui/radio/src/radio.tsx b/packages/devui-vue/devui/radio/src/radio.tsx index 1023e705d4..260eb55a6e 100644 --- a/packages/devui-vue/devui/radio/src/radio.tsx +++ b/packages/devui-vue/devui/radio/src/radio.tsx @@ -11,7 +11,7 @@ export default defineComponent({ /** 是否禁用 */ const isDisabled = computed(() => { - return props.disabled || radioGroupConf?.disabled.value + return props.disabled || radioGroupConf?.disabled.value; }); /** 判断是否勾选 */ const isChecked = computed(() => { diff --git a/packages/devui-vue/devui/rate/__tests__/rate.spec.ts b/packages/devui-vue/devui/rate/__tests__/rate.spec.ts index 647572d45a..0a88168251 100644 --- a/packages/devui-vue/devui/rate/__tests__/rate.spec.ts +++ b/packages/devui-vue/devui/rate/__tests__/rate.spec.ts @@ -1,6 +1,6 @@ -import { mount } from '@vue/test-utils' -import { ref, nextTick } from 'vue' -import DRate from '../src/rate' +import { mount } from '@vue/test-utils'; +import { ref, nextTick } from 'vue'; +import DRate from '../src/rate'; describe('rate', () => { describe('rate basic', () => { @@ -14,23 +14,23 @@ describe('rate', () => { </div> `, setup() { - const value = ref(0) + const value = ref(0); return { value, - } + }; }, - } - const wrapper = mount(TestComponent) + }; + const wrapper = mount(TestComponent); it('Rate demo has created successfully', async () => { - expect(wrapper).toBeTruthy() - }) + expect(wrapper).toBeTruthy(); + }); it('Rate should have content', () => { - const container = wrapper.find('.devui-star-container') - expect(container.exists()).toBeTruthy() - }) - }) + const container = wrapper.find('.devui-star-container'); + expect(container.exists()).toBeTruthy(); + }); + }); describe('rate change', () => { it('Rate can be changed', async () => { @@ -45,50 +45,50 @@ describe('rate', () => { </div> `, setup() { - const value = ref(0) + const value = ref(0); return { value, - } + }; }, - }) - await nextTick() + }); + await nextTick(); - const starEles = wrapper.findAll('.devui-star-align') + const starEles = wrapper.findAll('.devui-star-align'); - const container = wrapper.find('.devui-star-container') - const firstStarEle = starEles[0] - const thirdStarEle = starEles[2] - const fourthStarEle = starEles[3] + const container = wrapper.find('.devui-star-container'); + const firstStarEle = starEles[0]; + const thirdStarEle = starEles[2]; + const fourthStarEle = starEles[3]; - expect(starEles.length).toBe(5) + expect(starEles.length).toBe(5); - await fourthStarEle.trigger('mouseover') + await fourthStarEle.trigger('mouseover'); expect( fourthStarEle.find('.devui-star-color-active').attributes('style') - ).toBe('width: 100%;') + ).toBe('width: 100%;'); - await container.trigger('mouseleave') + await container.trigger('mouseleave'); expect( fourthStarEle.find('.devui-star-color-active').attributes('style') - ).toBe('width: 0px;') - expect(wrapper.find('.count').html()).toContain('0') + ).toBe('width: 0px;'); + expect(wrapper.find('.count').html()).toContain('0'); - await firstStarEle.trigger('click') + await firstStarEle.trigger('click'); - expect(wrapper.find('.count').html()).toContain('1') + expect(wrapper.find('.count').html()).toContain('1'); - await thirdStarEle.trigger('click') - expect(wrapper.find('.count').html()).toContain('3') + await thirdStarEle.trigger('click'); + expect(wrapper.find('.count').html()).toContain('3'); - await container.trigger('mouseleave') + await container.trigger('mouseleave'); expect( fourthStarEle.find('.devui-star-color-active').attributes('style') - ).toBe('width: 0px;') - expect(wrapper.find('.count').html()).toContain('3') - }) - }) + ).toBe('width: 0px;'); + expect(wrapper.find('.count').html()).toContain('3'); + }); + }); describe('read only', () => { const TestComponent = { @@ -102,34 +102,34 @@ describe('rate', () => { </div> `, setup() { - const value = ref(3) + const value = ref(3); return { value, - } + }; }, - } - const wrapper = mount(TestComponent) + }; + const wrapper = mount(TestComponent); it('Rate should have content', async () => { - expect(wrapper.find('.devui-star-container').exists()).toBeTruthy() - }) + expect(wrapper.find('.devui-star-container').exists()).toBeTruthy(); + }); it('Rate should not be changed', async () => { - const starEles = wrapper.findAll('.devui-star-align') + const starEles = wrapper.findAll('.devui-star-align'); - const firstStarEle = starEles[0] - const thirdStarEle = starEles[2] - const fourthStarEle = starEles[3] + const firstStarEle = starEles[0]; + const thirdStarEle = starEles[2]; + const fourthStarEle = starEles[3]; - await firstStarEle.trigger('click') - expect(wrapper.find('.count').html()).toContain('3') + await firstStarEle.trigger('click'); + expect(wrapper.find('.count').html()).toContain('3'); - await thirdStarEle.trigger('click') - expect(wrapper.find('.count').html()).toContain('3') + await thirdStarEle.trigger('click'); + expect(wrapper.find('.count').html()).toContain('3'); - await fourthStarEle.trigger('click') - expect(wrapper.find('.count').html()).toContain('3') - }) - }) -}) + await fourthStarEle.trigger('click'); + expect(wrapper.find('.count').html()).toContain('3'); + }); + }); +}); diff --git a/packages/devui-vue/devui/rate/index.ts b/packages/devui-vue/devui/rate/index.ts index e9829330d6..760eb08e6e 100644 --- a/packages/devui-vue/devui/rate/index.ts +++ b/packages/devui-vue/devui/rate/index.ts @@ -1,11 +1,11 @@ -import type { App } from 'vue' -import Rate from './src/rate' +import type { App } from 'vue'; +import Rate from './src/rate'; Rate.install = function (app: App) { - app.component(Rate.name, Rate) -} + app.component(Rate.name, Rate); +}; -export { Rate } +export { Rate }; export default { title: 'Rate 评分', @@ -14,4 +14,4 @@ export default { install(app: App): void { app.use(Rate as any); }, -} +}; diff --git a/packages/devui-vue/devui/rate/src/rate.tsx b/packages/devui-vue/devui/rate/src/rate.tsx index d9ccd7595d..5520202478 100644 --- a/packages/devui-vue/devui/rate/src/rate.tsx +++ b/packages/devui-vue/devui/rate/src/rate.tsx @@ -1,94 +1,94 @@ -import { defineComponent, onMounted, reactive, ref } from 'vue' -import { rateProps } from './use-rate' -import './rate.scss' +import { defineComponent, onMounted, reactive, ref } from 'vue'; +import { rateProps } from './use-rate'; +import './rate.scss'; export default defineComponent({ name: 'DRate', props: rateProps, emits: ['change', 'update:modelValue'], setup(props, ctx) { - const totalLevelArray = reactive<Record<string, any>[]>([]) - const chooseValue = ref(0) + const totalLevelArray = reactive<Record<string, any>[]>([]); + const chooseValue = ref(0); // 根据mouseMove,mouseLeave,select等操作,改变颜色与是否选中 const setChange = (start: number, end: number, width: string) => { for (let i = start; i < end; i++) { - totalLevelArray[i]['width'] = width + totalLevelArray[i]['width'] = width; } - } + }; // 初始化设置 const initRating = () => { if (!props.modelValue) { - return + return; } - chooseValue.value = props.modelValue - 1 - const halfStar = chooseValue.value % 1 - const intCurrentLevel = Math.floor(chooseValue.value) - setChange(0, intCurrentLevel + 1, '100%') + chooseValue.value = props.modelValue - 1; + const halfStar = chooseValue.value % 1; + const intCurrentLevel = Math.floor(chooseValue.value); + setChange(0, intCurrentLevel + 1, '100%'); if (halfStar > 0) { - totalLevelArray[intCurrentLevel + 1]['width'] = halfStar * 100 + '%' - setChange(intCurrentLevel + 2, props.count, '0') + totalLevelArray[intCurrentLevel + 1]['width'] = halfStar * 100 + '%'; + setChange(intCurrentLevel + 2, props.count, '0'); } else { - setChange(intCurrentLevel + 1, props.count, '0') + setChange(intCurrentLevel + 1, props.count, '0'); } - } + }; onMounted(() => { for (let i = 0; i < props.count; i++) { - totalLevelArray.push({ width: '0' }) + totalLevelArray.push({ width: '0' }); } - initRating() - }) + initRating(); + }); const hoverToggle = (e, index: number, reset = false) => { if (props.read) { - return + return; } if (reset) { if (chooseValue.value >= 0) { - setChange(0, chooseValue.value + 1, '100%') - setChange(chooseValue.value + 1, props.count, '0') + setChange(0, chooseValue.value + 1, '100%'); + setChange(chooseValue.value + 1, props.count, '0'); } else { - setChange(0, props.count, '0') + setChange(0, props.count, '0'); } } else { - setChange(0, index + 1, '100%') + setChange(0, index + 1, '100%'); // 判断是否是半选模式并且判断鼠标所在图标区域 if (props.allowHalf && (e.offsetX * 2 <= e.target.clientWidth)) { - setChange(index, index + 1, '50%') + setChange(index, index + 1, '50%'); } else { - setChange(index, index + 1, '100%') + setChange(index, index + 1, '100%'); } - setChange(index + 1, props.count, '0') + setChange(index + 1, props.count, '0'); } - } + }; const selectValue = (e, index: number) => { if (props.read) { - return + return; } - setChange(0, index, '100%') + setChange(0, index, '100%'); // 判断是否是半选模式 if (props.allowHalf && (e.offsetX * 2 <= e.target.clientWidth)) { - setChange(index, index + 1, '50%') - chooseValue.value = index - 0.5 + setChange(index, index + 1, '50%'); + chooseValue.value = index - 0.5; } else { - setChange(index, index + 1, '100%') - chooseValue.value = index + setChange(index, index + 1, '100%'); + chooseValue.value = index; } - setChange(index + 1, props.count, '0') - index = chooseValue.value - props.onChange && props.onChange(index + 1) - props.onTouched && props.onTouched() - ctx.emit('update:modelValue', index + 1) - } + setChange(index + 1, props.count, '0'); + index = chooseValue.value; + props.onChange && props.onChange(index + 1); + props.onTouched && props.onTouched(); + ctx.emit('update:modelValue', index + 1); + }; return { totalLevelArray, chooseValue, hoverToggle, selectValue, - } + }; }, render() { const { @@ -101,7 +101,7 @@ export default defineComponent({ color, hoverToggle, selectValue - } = this + } = this; return ( <div class="devui-star-container" @@ -110,7 +110,7 @@ export default defineComponent({ {totalLevelArray.map((item, index) => ( <div class={`devui-star-align devui-pointer ${read ? 'devui-only-read' : '' - }`} + }`} key={index} onMouseover={(e) => hoverToggle(e, index)} onClick={(e) => selectValue(e, index)} @@ -191,6 +191,6 @@ export default defineComponent({ </div> ))} </div> - ) + ); }, -}) +}); diff --git a/packages/devui-vue/devui/rate/src/use-rate.ts b/packages/devui-vue/devui/rate/src/use-rate.ts index d5ced884be..f676204aad 100644 --- a/packages/devui-vue/devui/rate/src/use-rate.ts +++ b/packages/devui-vue/devui/rate/src/use-rate.ts @@ -1,6 +1,6 @@ -import { PropType } from 'vue' +import { PropType } from 'vue'; -type RateStatusType = PropType<'success' | 'warning' | 'error'> +type RateStatusType = PropType<'success' | 'warning' | 'error'>; export const rateProps = { modelValue: { type: Number, @@ -41,4 +41,4 @@ export const rateProps = { type: Function as PropType<() => void>, default: undefined, }, -} +}; diff --git a/packages/devui-vue/devui/read-tip/__tests__/read-tip-template.spec.ts b/packages/devui-vue/devui/read-tip/__tests__/read-tip-template.spec.ts index aaab9d604e..97ad474077 100644 --- a/packages/devui-vue/devui/read-tip/__tests__/read-tip-template.spec.ts +++ b/packages/devui-vue/devui/read-tip/__tests__/read-tip-template.spec.ts @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils'; import { ReadTip, } from '../index'; -import { nextTick } from 'vue' +import { nextTick } from 'vue'; import TipsTemplate from '../src/read-tip-template'; @@ -8,15 +8,15 @@ describe('read-tip test', () => { beforeEach(() => { // create teleport target - const el = document.createElement('div') - el.id = 'readtip-target' - document.body.appendChild(el) - }) + const el = document.createElement('div'); + el.id = 'readtip-target'; + document.body.appendChild(el); + }); afterEach(() => { // clean up - document.body.outerHTML = '' - }) + document.body.outerHTML = ''; + }); it('read-tip init render', async () => { // 基础用法 @@ -26,21 +26,21 @@ describe('read-tip test', () => { selector: '#readtip-target', title: 'Name: Jack', content: 'This is Jack\'s profile', - } + }; const wrapper = mount(TipsTemplate, { props: { defaultTemplateProps } - }) + }); - expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain(defaultTemplateProps.title) + expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain(defaultTemplateProps.title); - expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain(defaultTemplateProps.content) + expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain(defaultTemplateProps.content); - }) + }); - const position = ['top', 'left', 'right', 'bottom'] + const position = ['top', 'left', 'right', 'bottom']; position.forEach(pos => { it(`read-tip position ${pos}`, async () => { @@ -52,17 +52,17 @@ describe('read-tip test', () => { selector: '#readtip-target', title: 'Name: Jack', content: 'This is Jack\'s profile', - } + }; const wrapper = mount(TipsTemplate, { props: { defaultTemplateProps } - }) + }); - expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain('read-tip-container ' + defaultTemplateProps.position) + expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain('read-tip-container ' + defaultTemplateProps.position); - }) - }) + }); + }); it('read-tip appendToBody = true', async () => { // 基础用法 @@ -73,21 +73,21 @@ describe('read-tip test', () => { selector: '#readtip-target', title: 'Name: Jack', content: 'This is Jack\'s profile', - } + }; const wrapper = mount(TipsTemplate, { props: { defaultTemplateProps } - }) + }); - expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toBe('') + expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toBe(''); - expect(document.querySelector(defaultTemplateProps.selector).innerHTML).not.toContain(defaultTemplateProps.title) + expect(document.querySelector(defaultTemplateProps.selector).innerHTML).not.toContain(defaultTemplateProps.title); - expect(document.querySelector(defaultTemplateProps.selector).innerHTML).not.toContain(defaultTemplateProps.content) + expect(document.querySelector(defaultTemplateProps.selector).innerHTML).not.toContain(defaultTemplateProps.content); - }) + }); it('read-tip contentTemplate', async () => { // 基础用法 @@ -97,7 +97,7 @@ describe('read-tip test', () => { appendToBody: false, selector: '#readtip-target', contentTemplate: true - } + }; const wrapper = mount(TipsTemplate, { props: { defaultTemplateProps @@ -105,12 +105,12 @@ describe('read-tip test', () => { slots: { default: `<div> I am test </div>` } - }) + }); - expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain('<div> I am test </div>') + expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain('<div> I am test </div>'); - }) + }); it('read-tip dataFn', async () => { // 基础用法 @@ -120,19 +120,19 @@ describe('read-tip test', () => { selector: '#readtip-target', dataFn: getDataFromDB, key: 'GetData' - } + }; function getDataFromDB({ element, rule }) { - return { content: element.innerHTML, title: rule.key } + return { content: element.innerHTML, title: rule.key }; } const wrapper = mount(TipsTemplate, { props: { defaultTemplateProps }, - }) + }); - expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain('GetData') - }) + expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain('GetData'); + }); it('read-tip overlayClassName', async () => { // 基础用法 @@ -142,19 +142,19 @@ describe('read-tip test', () => { dataFn: getDataFromDB, key: 'GetData', overlayClassName: 'red' - } + }; function getDataFromDB({ element, rule }) { - return { content: element.innerHTML, title: rule.key } + return { content: element.innerHTML, title: rule.key }; } const wrapper = mount(TipsTemplate, { props: { defaultTemplateProps }, - }) + }); - expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain(defaultTemplateProps.overlayClassName) - }) -}) + expect(document.querySelector(defaultTemplateProps.selector).innerHTML).toContain(defaultTemplateProps.overlayClassName); + }); +}); diff --git a/packages/devui-vue/devui/read-tip/__tests__/read-tip.spec.ts b/packages/devui-vue/devui/read-tip/__tests__/read-tip.spec.ts index 3b5e72e14d..348948a578 100644 --- a/packages/devui-vue/devui/read-tip/__tests__/read-tip.spec.ts +++ b/packages/devui-vue/devui/read-tip/__tests__/read-tip.spec.ts @@ -1,20 +1,20 @@ import { mount } from '@vue/test-utils'; import { ReadTip, } from '../index'; -import { nextTick } from 'vue' +import { nextTick } from 'vue'; import Template from '../src/read-tip-template'; describe('read-tip test', () => { beforeEach(() => { // create teleport target - const el = document.createElement('div') - el.className = 'readtip-target' - document.body.appendChild(el) - }) + const el = document.createElement('div'); + el.className = 'readtip-target'; + document.body.appendChild(el); + }); afterEach(() => { // clean up - document.body.outerHTML = '' - }) + document.body.outerHTML = ''; + }); it('read-tip init render', async () => { // 基础用法 const readTipOptions = { @@ -35,27 +35,27 @@ describe('read-tip test', () => { slots: { default: `<span class="readtip-target">@Jack</span>` } - }) - - expect(wrapper.find('.readtip-target').classes()).toContain('readtip-target') - + }); + + expect(wrapper.find('.readtip-target').classes()).toContain('readtip-target'); + // dom元素被点击 template会进行展示 - await wrapper.find('.readtip-target').trigger('click') - await nextTick() - - let template = wrapper.findComponent(Template) + await wrapper.find('.readtip-target').trigger('click'); + await nextTick(); + + let template = wrapper.findComponent(Template); - expect(template.exists()).toBe(true) - expect(wrapper.findAll('[data-test="todo"]')).toHaveLength(1) + expect(template.exists()).toBe(true); + expect(wrapper.findAll('[data-test="todo"]')).toHaveLength(1); - // body元素被点击 template会消失 - await document.body.click() - await nextTick() + // body元素被点击 template会消失 + await document.body.click(); + await nextTick(); - template = wrapper.findComponent(Template) - expect(template.exists()).toBe(false) - expect(wrapper.findAll('[data-test="todo"]')).toHaveLength(1) - }) + template = wrapper.findComponent(Template); + expect(template.exists()).toBe(false); + expect(wrapper.findAll('[data-test="todo"]')).toHaveLength(1); + }); it('read-tip more show tip', async () => { // 基础用法 @@ -78,19 +78,19 @@ describe('read-tip test', () => { <span class="readtip-target">@Mary</span> ` } - }) - - + }); + + // dom元素被移入 template会进行展示 - await wrapper.find('.readtip-target').trigger('mouseover') - - expect(wrapper.findAll('[data-test="todo"]')).toHaveLength(2) + await wrapper.find('.readtip-target').trigger('mouseover'); + + expect(wrapper.findAll('[data-test="todo"]')).toHaveLength(2); - // dom元素被移出 template会消失 - await wrapper.find('.readtip-target').trigger('mouseout') - await nextTick() + // dom元素被移出 template会消失 + await wrapper.find('.readtip-target').trigger('mouseout'); + await nextTick(); - expect(wrapper.findAll('[data-test="todo"]')).toHaveLength(2) + expect(wrapper.findAll('[data-test="todo"]')).toHaveLength(2); - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/read-tip/index.ts b/packages/devui-vue/devui/read-tip/index.ts index ec9f38284e..e5cedd9012 100644 --- a/packages/devui-vue/devui/read-tip/index.ts +++ b/packages/devui-vue/devui/read-tip/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import ReadTip from './src/read-tip' +import type { App } from 'vue'; +import ReadTip from './src/read-tip'; ReadTip.install = function (app: App): void { - app.component(ReadTip.name, ReadTip) -} + app.component(ReadTip.name, ReadTip); +}; -export { ReadTip, } +export { ReadTip, }; export default { title: 'ReadTip 阅读提示', category: '反馈', - status: '100%', + status: '100%', install(app: App): void { - app.use(ReadTip as any) + app.use(ReadTip as any); } -} +}; diff --git a/packages/devui-vue/devui/read-tip/src/read-tip-directive.ts b/packages/devui-vue/devui/read-tip/src/read-tip-directive.ts index 788dde30ee..e2c9f6f505 100644 --- a/packages/devui-vue/devui/read-tip/src/read-tip-directive.ts +++ b/packages/devui-vue/devui/read-tip/src/read-tip-directive.ts @@ -7,4 +7,4 @@ export default { // updated() { }, // beforeUnmount() { }, // unmounted() { } -} +}; diff --git a/packages/devui-vue/devui/read-tip/src/read-tip-template.tsx b/packages/devui-vue/devui/read-tip/src/read-tip-template.tsx index 5da83d2889..185dbc0d59 100644 --- a/packages/devui-vue/devui/read-tip/src/read-tip-template.tsx +++ b/packages/devui-vue/devui/read-tip/src/read-tip-template.tsx @@ -1,40 +1,40 @@ -import { defineComponent, reactive, ref, onMounted, Teleport, toRefs } from 'vue' -import { readTipProps, ReadTipProps, DefaultTemplateProps } from './read-tip-types' -import './read-tip.scss' +import { defineComponent, reactive, ref, onMounted, Teleport, toRefs } from 'vue'; +import { readTipProps, ReadTipProps, DefaultTemplateProps } from './read-tip-types'; +import './read-tip.scss'; export default defineComponent({ name: 'DReadTipTemplate', props: readTipProps, emits: [], setup(props: ReadTipProps, ctx) { - const { defaultTemplateProps, } = toRefs(props) - let rule: DefaultTemplateProps = defaultTemplateProps.value + const { defaultTemplateProps, } = toRefs(props); + let rule: DefaultTemplateProps = defaultTemplateProps.value; const query = rule?.id ? `#${rule.id}` : rule.selector; const styles: any = reactive({}); if (typeof rule.dataFn === 'function') { - const dataFn = rule.dataFn({ element: document.querySelector(query), rule }) - rule = { ...rule, ...dataFn } + const dataFn = rule.dataFn({ element: document.querySelector(query), rule }); + rule = { ...rule, ...dataFn }; } const temp = ref(null); const deviation = (x: number) => { - let deviationConstant = x > 24 ? 0 : -(x / 2) + 2 + let deviationConstant = x > 24 ? 0 : -(x / 2) + 2; if (x <= 10) { - deviationConstant = -10 + deviationConstant = -10; } - return deviationConstant - } + return deviationConstant; + }; onMounted(() => { const domBounding = document.querySelector(query).getBoundingClientRect(); - const { width, height } = domBounding + const { width, height } = domBounding; const distance = 10; let positionTop = 0; // 当前元素如果小于24px 会对渲染模板进行偏移 以免小箭头对不准指向的当前元素 - const heightDeviation = deviation(height) - const widthDeviation = deviation(width) + const heightDeviation = deviation(height); + const widthDeviation = deviation(width); let positionLeft = 0; @@ -44,24 +44,24 @@ export default defineComponent({ positionLeft = domBounding.x; } switch (rule.position) { - case 'top': - styles.top = positionTop - targetDom.height - distance + 'px'; - styles.left = positionLeft + widthDeviation + 'px'; - break; - case 'left': - styles.top = positionTop + heightDeviation + 'px'; - styles.left = positionLeft - targetDom.width - distance + 'px'; - break; - case 'bottom': - styles.top = positionTop + domBounding.height + distance + 'px' - styles.left = positionLeft + widthDeviation + 'px'; - break; - case 'right': - styles.top = positionTop + heightDeviation + 'px'; - styles.left = positionLeft + domBounding.width + distance + 'px'; - break; + case 'top': + styles.top = positionTop - targetDom.height - distance + 'px'; + styles.left = positionLeft + widthDeviation + 'px'; + break; + case 'left': + styles.top = positionTop + heightDeviation + 'px'; + styles.left = positionLeft - targetDom.width - distance + 'px'; + break; + case 'bottom': + styles.top = positionTop + domBounding.height + distance + 'px'; + styles.left = positionLeft + widthDeviation + 'px'; + break; + case 'right': + styles.top = positionTop + heightDeviation + 'px'; + styles.left = positionLeft + domBounding.width + distance + 'px'; + break; } - }) + }); return () => { return ( <Teleport to={rule.appendToBody ? 'body' : query} > @@ -86,7 +86,7 @@ export default defineComponent({ } </div> </Teleport> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/read-tip/src/read-tip-types.ts b/packages/devui-vue/devui/read-tip/src/read-tip-types.ts index 7e67346984..c9171aab4a 100644 --- a/packages/devui-vue/devui/read-tip/src/read-tip-types.ts +++ b/packages/devui-vue/devui/read-tip/src/read-tip-types.ts @@ -1,4 +1,4 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; export const readTipProps = { readTipOptions: { @@ -7,60 +7,60 @@ export const readTipProps = { defaultTemplateProps: { type: Object as PropType<DefaultTemplateProps> } -} as const +} as const; -export type Position = 'top' | 'left' | 'right' | 'bottom' -export type Trigger = 'hover' | 'click' +export type Position = 'top' | 'left' | 'right' | 'bottom'; +export type Trigger = 'hover' | 'click'; export type DefaultTemplateProps = { - title?: string - content?: string - selector?: string - position?: string - id?: string - temp?: string - dom?: Element - contentTemplate?: boolean - overlayClassName?: string + title?: string; + content?: string; + selector?: string; + position?: string; + id?: string; + temp?: string; + dom?: Element; + contentTemplate?: boolean; + overlayClassName?: string; dataFn?: ({ element, rule: ReadTipRule, - }) => { title?: string; content?: string; } - appendToBody?: boolean -} + }) => { title?: string; content?: string }; + appendToBody?: boolean; +}; export interface ReadTipOptions { - trigger?: Trigger - showAnimate?: boolean - mouseenterTime?: number - mouseleaveTime?: number - position?: Position - overlayClassName?: string - appendToBody?: boolean - rules: ReadTipRules + trigger?: Trigger; + showAnimate?: boolean; + mouseenterTime?: number; + mouseleaveTime?: number; + position?: Position; + overlayClassName?: string; + appendToBody?: boolean; + rules: ReadTipRules; } export type ReadTipRules = ReadTipRule | ReadTipRule[]; export interface ReadTipRule { - key?: string - selector: string - trigger?: Trigger - title?: string - content?: string - showAnimate?: boolean - mouseenterTime?: number - mouseleaveTime?: number - position?: Position - overlayClassName?: string - appendToBody?: boolean - //customData与template搭配使用,customData为传入模板的上下文,可以自定义模板内容 + key?: string; + selector: string; + trigger?: Trigger; + title?: string; + content?: string; + showAnimate?: boolean; + mouseenterTime?: number; + mouseleaveTime?: number; + position?: Position; + overlayClassName?: string; + appendToBody?: boolean; + // customData与template搭配使用,customData为传入模板的上下文,可以自定义模板内容 dataFn?: ({ element, rule: ReadTipRule, - }) => { title?: string; content?: string; } + }) => { title?: string; content?: string }; } -export type ReadTipProps = ExtractPropTypes<typeof readTipProps> +export type ReadTipProps = ExtractPropTypes<typeof readTipProps>; diff --git a/packages/devui-vue/devui/read-tip/src/read-tip.tsx b/packages/devui-vue/devui/read-tip/src/read-tip.tsx index 0ba6cce678..08305403e4 100644 --- a/packages/devui-vue/devui/read-tip/src/read-tip.tsx +++ b/packages/devui-vue/devui/read-tip/src/read-tip.tsx @@ -1,6 +1,6 @@ -import { defineComponent, ref, onMounted, reactive, onUnmounted } from 'vue' -import { readTipProps, ReadTipProps, ReadTipOptions } from './read-tip-types' -import './read-tip.scss' +import { defineComponent, ref, onMounted, reactive, onUnmounted } from 'vue'; +import { readTipProps, ReadTipProps, ReadTipOptions } from './read-tip-types'; +import './read-tip.scss'; import TipsTemplate from './read-tip-template'; export default defineComponent({ @@ -20,91 +20,91 @@ export default defineComponent({ rules: { selector: null }, }; // 合并基础配置 - const options = { ...defaultOptions, ...props.readTipOptions } - const defaultSlot = ref(null) + const options = { ...defaultOptions, ...props.readTipOptions }; + const defaultSlot = ref(null); const onMouseenter = (rule) => () => { setTimeout(() => { if (rule.id) { - const a = refRules.find(u => u.id === rule.id) - a.status = true + const a = refRules.find(u => u.id === rule.id); + a.status = true; } - rule.status = true + rule.status = true; }, rule.mouseenterTime || options.mouseenterTime); - } + }; const onMouseleave = (rule) => () => { setTimeout(() => { if (rule.id) { - const a = refRules.find(u => u.id === rule.id) - a.status = false + const a = refRules.find(u => u.id === rule.id); + a.status = false; } - rule.status = false + rule.status = false; }, rule.mouseleaveTime || options.mouseleaveTime); - } + }; const init = (rules, trigger = 'hover') => { rules.map(rule => { - rule.status = false - trigger = rule.trigger || trigger - rule.overlayClassName = rule.overlayClassName || options.overlayClassName - rule.position = rule.position || options.position - rule.contentTemplate = !!(ctx.slots.contentTemplate) - if (!('appendToBody' in rule)) rule.appendToBody = options.appendToBody + rule.status = false; + trigger = rule.trigger || trigger; + rule.overlayClassName = rule.overlayClassName || options.overlayClassName; + rule.position = rule.position || options.position; + rule.contentTemplate = !!(ctx.slots.contentTemplate); + if (!('appendToBody' in rule)) {rule.appendToBody = options.appendToBody;} const doms = defaultSlot.value.querySelectorAll(rule.selector); [...doms].map((dom, index) => { - if (rule.appendToBody === false) dom.style.position = 'relative'; + if (rule.appendToBody === false) {dom.style.position = 'relative';} let newRule = reactive({ id: null - }) + }); const id = rule.selector.slice(rule.selector[0] === '.' ? 1 : 0) + index; if (index > 0) { - newRule = { ...rule } - dom.id = id - newRule.id = id - rules.push(newRule) + newRule = { ...rule }; + dom.id = id; + newRule.id = id; + rules.push(newRule); } if (trigger === 'hover') { - dom.addEventListener('mouseenter', onMouseenter(newRule.id ? newRule : rule,)) - dom.addEventListener('mouseleave', onMouseleave(newRule.id ? newRule : rule)) + dom.addEventListener('mouseenter', onMouseenter(newRule.id ? newRule : rule,)); + dom.addEventListener('mouseleave', onMouseleave(newRule.id ? newRule : rule)); } - }) + }); - }) - return rules - } + }); + return rules; + }; function show(dom, rule) { - rule.status = true + rule.status = true; } // 把传入的props.rules统一转为数组对象格式 const rules = (rules) => { - if (rules === null) return + if (rules === null) {return;} if (typeof rules === 'object' && !Array.isArray(rules)) { - rules = [rules] + rules = [rules]; } - rules = [...rules] + rules = [...rules]; Array.isArray(rules) && rules.map(rule => { - rule.status = false - }) - return rules - } - const refRules = reactive(rules(options.rules)) + rule.status = false; + }); + return rules; + }; + const refRules = reactive(rules(options.rules)); const clickFn = () => { refRules.forEach(element => { - element.status = false - }) - } + element.status = false; + }); + }; onMounted(() => { - init(refRules, options.trigger) + init(refRules, options.trigger); // 点击其他位置 关闭弹框 - document.addEventListener('click', clickFn, true) + document.addEventListener('click', clickFn, true); - }) + }); onUnmounted(() => { // 取消事件 - document.removeEventListener('click', clickFn) - }) + document.removeEventListener('click', clickFn); + }); // 添加点击事件 当前元素是click事件目标则弹框展示 const onClick = (e: Event) => { @@ -113,27 +113,27 @@ export default defineComponent({ for (const dom of doms) { if (doms.length > 1) { if (dom === e.target && rule.id) { - show(dom, rule) - return + show(dom, rule); + return; } else if (dom === e.target && !rule.id && !dom.id) { - show(dom, rule) - return + show(dom, rule); + return; } } else - if (dom === e.target) { - show(dom, rule) - return - } else { - rule.status = false - } + if (dom === e.target) { + show(dom, rule); + return; + } else { + rule.status = false; + } } } - } + }; return () => { return ( <div class="devui-read-tip" > @@ -160,7 +160,7 @@ export default defineComponent({ ) )} </div> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/result/__tests__/result.spec.ts b/packages/devui-vue/devui/result/__tests__/result.spec.ts index a546e9af05..e023b3eaf2 100644 --- a/packages/devui-vue/devui/result/__tests__/result.spec.ts +++ b/packages/devui-vue/devui/result/__tests__/result.spec.ts @@ -3,28 +3,28 @@ import { Result } from '../index'; describe('result test', () => { it('result init render', async () => { - const wrapper = mount(Result) - expect(wrapper.classes()).toContain('devui-result') - }) + const wrapper = mount(Result); + expect(wrapper.classes()).toContain('devui-result'); + }); it('icon', async () => { - const wrapper = mount(Result, { props: { icon: 'info' } }) + const wrapper = mount(Result, { props: { icon: 'info' } }); - let firstChild: Element = wrapper.element.firstElementChild - expect(firstChild.classList).toContain('devui-result__icon-info') + let firstChild: Element = wrapper.element.firstElementChild; + expect(firstChild.classList).toContain('devui-result__icon-info'); await wrapper.setProps({ icon: 'success' }); - firstChild = wrapper.element.firstElementChild - expect(firstChild.classList).toContain('devui-result__icon-success') + firstChild = wrapper.element.firstElementChild; + expect(firstChild.classList).toContain('devui-result__icon-success'); await wrapper.setProps({ icon: 'danger' }); - firstChild = wrapper.element.firstElementChild - expect(firstChild.classList).toContain('devui-result__icon-danger') + firstChild = wrapper.element.firstElementChild; + expect(firstChild.classList).toContain('devui-result__icon-danger'); await wrapper.setProps({ icon: 'warning' }); - firstChild = wrapper.element.firstElementChild - expect(firstChild.classList).toContain('devui-result__icon-warning') - }) + firstChild = wrapper.element.firstElementChild; + expect(firstChild.classList).toContain('devui-result__icon-warning'); + }); it('slot', async ()=>{ const wrapper = mount(Result, { @@ -34,11 +34,11 @@ describe('result test', () => { desc: 'This is desc slot', extra: 'This is extra slot' } - }) - - expect(wrapper.element.children[0].innerHTML).toEqual('This is icon slot') - expect(wrapper.element.children[1].innerHTML).toEqual('This is title slot') - expect(wrapper.element.children[2].innerHTML).toEqual('This is desc slot') - expect(wrapper.element.children[3].innerHTML).toEqual('This is extra slot') - }) -}) + }); + + expect(wrapper.element.children[0].innerHTML).toEqual('This is icon slot'); + expect(wrapper.element.children[1].innerHTML).toEqual('This is title slot'); + expect(wrapper.element.children[2].innerHTML).toEqual('This is desc slot'); + expect(wrapper.element.children[3].innerHTML).toEqual('This is extra slot'); + }); +}); diff --git a/packages/devui-vue/devui/result/index.ts b/packages/devui-vue/devui/result/index.ts index dec2964906..5b4a9500fa 100644 --- a/packages/devui-vue/devui/result/index.ts +++ b/packages/devui-vue/devui/result/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Result from './src/result' +import type { App } from 'vue'; +import Result from './src/result'; Result.install = function(app: App): void { - app.component(Result.name, Result) -} + app.component(Result.name, Result); +}; -export { Result } +export { Result }; export default { title: 'Result 结果', category: '反馈', status: '100%', install(app: App): void { - app.use(Result as any) + app.use(Result as any); } -} +}; diff --git a/packages/devui-vue/devui/result/src/result-types.ts b/packages/devui-vue/devui/result/src/result-types.ts index b2588a2847..953825ce8e 100644 --- a/packages/devui-vue/devui/result/src/result-types.ts +++ b/packages/devui-vue/devui/result/src/result-types.ts @@ -1,6 +1,6 @@ -import type { ExtractPropTypes } from 'vue' +import type { ExtractPropTypes } from 'vue'; -export type ResultIcon = 'success' | 'danger' | 'warning' | 'info' +export type ResultIcon = 'success' | 'danger' | 'warning' | 'info'; export const resultProps = { icon: { @@ -15,6 +15,6 @@ export const resultProps = { type: String, default: '' } -} as const +} as const; -export type ResultProps = ExtractPropTypes<typeof resultProps> +export type ResultProps = ExtractPropTypes<typeof resultProps>; diff --git a/packages/devui-vue/devui/result/src/result.tsx b/packages/devui-vue/devui/result/src/result.tsx index b54671ead0..c1de885dce 100644 --- a/packages/devui-vue/devui/result/src/result.tsx +++ b/packages/devui-vue/devui/result/src/result.tsx @@ -1,14 +1,14 @@ -import { defineComponent } from 'vue' -import { resultProps, ResultProps } from './result-types' -import Icon from '../../icon/src/icon' -import './result.scss' +import { defineComponent } from 'vue'; +import { resultProps, ResultProps } from './result-types'; +import Icon from '../../icon/src/icon'; +import './result.scss'; export default defineComponent({ name: 'DResult', props: resultProps, setup(props: ResultProps, ctx) { enum IconEnum {success = 'right-o', danger='error-o', warning='warning-o', info='info-o'} - + return () => { return ( <div class='devui-result'> @@ -21,7 +21,7 @@ export default defineComponent({ <div class='devui-result__desc'>{ctx.slots.desc ? ctx.slots?.desc() : props.desc}</div> <div class='devui-result__extra'>{ctx.slots.extra ? ctx.slots?.extra() : ''}</div> </div> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/ripple/__tests__/ripple.spec.ts b/packages/devui-vue/devui/ripple/__tests__/ripple.spec.ts index e4e3fddc36..8a4fb312c6 100644 --- a/packages/devui-vue/devui/ripple/__tests__/ripple.spec.ts +++ b/packages/devui-vue/devui/ripple/__tests__/ripple.spec.ts @@ -1,13 +1,13 @@ -import { nextTick, createApp } from 'vue' -import { mount } from '@vue/test-utils' -import Ripple from '../index' -import { DEFAULT_PLUGIN_OPTIONS } from '../src/options' +import { nextTick, createApp } from 'vue'; +import { mount } from '@vue/test-utils'; +import Ripple from '../index'; +import { DEFAULT_PLUGIN_OPTIONS } from '../src/options'; // 全局属性 const global = { directives: { ripple: Ripple } -} +}; describe('ripple', () => { it('ripple should render correctly', async () => { const wrapper = mount( @@ -19,18 +19,18 @@ describe('ripple', () => { { global } - ) - await nextTick() - const rippleElement = wrapper.find('.ripple-container') as any - await rippleElement.trigger('click') - console.log(rippleElement.element.childElementCount) + ); + await nextTick(); + const rippleElement = wrapper.find('.ripple-container') as any; + await rippleElement.trigger('click'); + console.log(rippleElement.element.childElementCount); - expect(wrapper.find('div').exists()).toBeTruthy() - }) + expect(wrapper.find('div').exists()).toBeTruthy(); + }); it('test ripple plugin', () => { - const app = createApp({}).use(Ripple) - expect(app.directive('ripple', Ripple)).toBeTruthy() - }) + const app = createApp({}).use(Ripple); + expect(app.directive('ripple', Ripple)).toBeTruthy(); + }); it('ripple default options', () => { expect(DEFAULT_PLUGIN_OPTIONS).toEqual({ @@ -42,6 +42,6 @@ describe('ripple', () => { easing: 'ease-out', delayTime: 75, disabled: false - }) - }) -}) + }); + }); +}); diff --git a/packages/devui-vue/devui/ripple/index.ts b/packages/devui-vue/devui/ripple/index.ts index d7602a359f..ace90d7e76 100644 --- a/packages/devui-vue/devui/ripple/index.ts +++ b/packages/devui-vue/devui/ripple/index.ts @@ -1,13 +1,13 @@ -import type { App } from 'vue' -import RippleDirective from './src/ripple-directive' +import type { App } from 'vue'; +import RippleDirective from './src/ripple-directive'; -export { RippleDirective } +export { RippleDirective }; export default { title: 'Ripple 水波纹', category: '通用', status: '100%', install(app: App): void { - app.directive('Ripple', RippleDirective) + app.directive('Ripple', RippleDirective); } -} +}; diff --git a/packages/devui-vue/devui/ripple/src/options.ts b/packages/devui-vue/devui/ripple/src/options.ts index 18f04ca94b..dff61e55fd 100644 --- a/packages/devui-vue/devui/ripple/src/options.ts +++ b/packages/devui-vue/devui/ripple/src/options.ts @@ -7,35 +7,35 @@ interface IRippleDirectiveOptions { * @default * 'currentColor' */ - color: string + color: string; /** * 第一次出现的透明度 * * @default * 0.2 默认opacity 0.2 */ - initialOpacity: number + initialOpacity: number; /** * 在透明度 结束的时候 stopped 的时候 我们设置透明度的大小 * * @default * 0.1 */ - finalOpacity: number + finalOpacity: number; /** * 动画持续事件 * * @default * 0.4 */ - duration: number + duration: number; /** * css 动画 从开始到结束 以相同的时间来执行动画 * * @default * 'ease-out' */ - easing: string + easing: string; /** * 取消延迟时间 * @@ -44,7 +44,7 @@ interface IRippleDirectiveOptions { * @default * 75 */ - delayTime: number + delayTime: number; /** * 禁止 水波 * @@ -53,7 +53,7 @@ interface IRippleDirectiveOptions { * @default * 75 */ - disabled: boolean + disabled: boolean; } interface IRipplePluginOptions extends IRippleDirectiveOptions { @@ -67,13 +67,13 @@ interface IRipplePluginOptions extends IRippleDirectiveOptions { * @default * 默认指令 ripple */ - directive: string + directive: string; } // 给可预见值 value 添加类型 interface IRippleDirectiveOptionWithBinding { - value: IRippleDirectiveOptions + value: IRippleDirectiveOptions; } const DEFAULT_PLUGIN_OPTIONS: IRipplePluginOptions = { @@ -85,11 +85,11 @@ const DEFAULT_PLUGIN_OPTIONS: IRipplePluginOptions = { easing: 'ease-out', delayTime: 75, disabled: false -} +}; export { DEFAULT_PLUGIN_OPTIONS, IRipplePluginOptions, IRippleDirectiveOptions, IRippleDirectiveOptionWithBinding -} +}; diff --git a/packages/devui-vue/devui/ripple/src/ripple-directive.ts b/packages/devui-vue/devui/ripple/src/ripple-directive.ts index e4ad61ebdb..f8e7633d0e 100644 --- a/packages/devui-vue/devui/ripple/src/ripple-directive.ts +++ b/packages/devui-vue/devui/ripple/src/ripple-directive.ts @@ -3,28 +3,28 @@ import { DEFAULT_PLUGIN_OPTIONS, IRippleDirectiveOptions, IRippleDirectiveOptionWithBinding -} from './options' -import { ripple } from './v-ripple' -const optionMap = new WeakMap<HTMLElement, Partial<IRippleDirectiveOptions> | false>() -const globalOptions = { ...DEFAULT_PLUGIN_OPTIONS } +} from './options'; +import { ripple } from './v-ripple'; +const optionMap = new WeakMap<HTMLElement, Partial<IRippleDirectiveOptions> | false>(); +const globalOptions = { ...DEFAULT_PLUGIN_OPTIONS }; export default { mounted(el: HTMLElement, binding: IRippleDirectiveOptionWithBinding) { - optionMap.set(el, binding.value ?? {}) + optionMap.set(el, binding.value ?? {}); el.addEventListener('pointerdown', (event) => { - const options = optionMap.get(el) + const options = optionMap.get(el); // 必须确保disabled 属性存在 否则指令终止报错 - if (binding.value && binding.value.disabled) return + if (binding.value && binding.value.disabled) {return;} - if (options === false) return + if (options === false) {return;} ripple(event, el, { ...globalOptions, ...options - }) - }) + }); + }); }, updated(el: HTMLElement, binding: IRippleDirectiveOptionWithBinding) { - optionMap.set(el, binding.value ?? {}) + optionMap.set(el, binding.value ?? {}); } -} +}; diff --git a/packages/devui-vue/devui/ripple/src/utils/create-container-element.ts b/packages/devui-vue/devui/ripple/src/utils/create-container-element.ts index 36cfee3e6d..98fb6fa033 100644 --- a/packages/devui-vue/devui/ripple/src/utils/create-container-element.ts +++ b/packages/devui-vue/devui/ripple/src/utils/create-container-element.ts @@ -4,18 +4,18 @@ export const createContainer = ({ borderBottomLeftRadius, borderBottomRightRadius }: CSSStyleDeclaration): HTMLElement => { - const rippleContainer = document.createElement('div') - rippleContainer.style.top = '0' - rippleContainer.style.left = '0' - rippleContainer.style.width = '100%' - rippleContainer.style.height = '100%' - rippleContainer.style.position = 'absolute' - rippleContainer.style.borderRadius = `${borderTopLeftRadius} ${borderTopRightRadius} ${borderBottomRightRadius} ${borderBottomLeftRadius}` - rippleContainer.style.overflow = 'hidden' - rippleContainer.style.pointerEvents = 'none' + const rippleContainer = document.createElement('div'); + rippleContainer.style.top = '0'; + rippleContainer.style.left = '0'; + rippleContainer.style.width = '100%'; + rippleContainer.style.height = '100%'; + rippleContainer.style.position = 'absolute'; + rippleContainer.style.borderRadius = `${borderTopLeftRadius} ${borderTopRightRadius} ${borderBottomRightRadius} ${borderBottomLeftRadius}`; + rippleContainer.style.overflow = 'hidden'; + rippleContainer.style.pointerEvents = 'none'; // 兼容 ie 苹果 - rippleContainer.style.webkitMaskImage = '-webkit-radial-gradient(white, black)' + rippleContainer.style.webkitMaskImage = '-webkit-radial-gradient(white, black)'; - return rippleContainer -} + return rippleContainer; +}; diff --git a/packages/devui-vue/devui/ripple/src/utils/create-ripple-element.ts b/packages/devui-vue/devui/ripple/src/utils/create-ripple-element.ts index 87a69faf51..aafb4a649f 100644 --- a/packages/devui-vue/devui/ripple/src/utils/create-ripple-element.ts +++ b/packages/devui-vue/devui/ripple/src/utils/create-ripple-element.ts @@ -1,4 +1,4 @@ -import { IRippleDirectiveOptions } from '../options' +import { IRippleDirectiveOptions } from '../options'; export const createrippleElement = ( x: number, @@ -6,18 +6,18 @@ export const createrippleElement = ( size: number, options: IRippleDirectiveOptions ): HTMLElement => { - const rippleElement = document.createElement('div') + const rippleElement = document.createElement('div'); - rippleElement.style.position = 'absolute' - rippleElement.style.width = `${size}px` - rippleElement.style.height = `${size}px` - rippleElement.style.top = `${y}px` - rippleElement.style.left = `${x}px` - rippleElement.style.background = options.color - rippleElement.style.borderRadius = '50%' - rippleElement.style.opacity = `${options.initialOpacity}` - rippleElement.style.transform = `translate(-50%,-50%) scale(0)` - rippleElement.style.transition = `transform ${options.duration}s ${options.easing}, opacity ${options.duration}s ${options.easing}` + rippleElement.style.position = 'absolute'; + rippleElement.style.width = `${size}px`; + rippleElement.style.height = `${size}px`; + rippleElement.style.top = `${y}px`; + rippleElement.style.left = `${x}px`; + rippleElement.style.background = options.color; + rippleElement.style.borderRadius = '50%'; + rippleElement.style.opacity = `${options.initialOpacity}`; + rippleElement.style.transform = `translate(-50%,-50%) scale(0)`; + rippleElement.style.transition = `transform ${options.duration}s ${options.easing}, opacity ${options.duration}s ${options.easing}`; - return rippleElement -} + return rippleElement; +}; diff --git a/packages/devui-vue/devui/ripple/src/utils/getdistance-tofurthestcorner.ts b/packages/devui-vue/devui/ripple/src/utils/getdistance-tofurthestcorner.ts index cadb428d91..d6d99e6e12 100644 --- a/packages/devui-vue/devui/ripple/src/utils/getdistance-tofurthestcorner.ts +++ b/packages/devui-vue/devui/ripple/src/utils/getdistance-tofurthestcorner.ts @@ -1,4 +1,4 @@ -import { magnitude } from './magnitude' +import { magnitude } from './magnitude'; export function getDistanceToFurthestCorner( x: number, @@ -6,9 +6,9 @@ export function getDistanceToFurthestCorner( { width, height }: DOMRect ): number { // 获取点击目标的位置到块级作用域边界的距离 - const topLeft = magnitude(x, y, 0, 0) - const topRight = magnitude(x, y, width, 0) - const bottomLeft = magnitude(x, y, 0, height) - const bottomRight = magnitude(x, y, width, height) - return Math.max(topLeft, topRight, bottomLeft, bottomRight) + const topLeft = magnitude(x, y, 0, 0); + const topRight = magnitude(x, y, width, 0); + const bottomLeft = magnitude(x, y, 0, height); + const bottomRight = magnitude(x, y, width, height); + return Math.max(topLeft, topRight, bottomLeft, bottomRight); } diff --git a/packages/devui-vue/devui/ripple/src/utils/getrelative-pointer.ts b/packages/devui-vue/devui/ripple/src/utils/getrelative-pointer.ts index 44d75b8127..2e1ec58712 100644 --- a/packages/devui-vue/devui/ripple/src/utils/getrelative-pointer.ts +++ b/packages/devui-vue/devui/ripple/src/utils/getrelative-pointer.ts @@ -4,4 +4,4 @@ export const getRelativePointer = ( ) => ({ x: x - left, y: y - top -}) +}); diff --git a/packages/devui-vue/devui/ripple/src/utils/magnitude.ts b/packages/devui-vue/devui/ripple/src/utils/magnitude.ts index ed2202498f..a5175b4171 100644 --- a/packages/devui-vue/devui/ripple/src/utils/magnitude.ts +++ b/packages/devui-vue/devui/ripple/src/utils/magnitude.ts @@ -1,6 +1,6 @@ export function magnitude(x1: number, y1: number, x2: number, y2: number): number { - const deltaX = x1 - x2 - const deltaY = y1 - y2 + const deltaX = x1 - x2; + const deltaY = y1 - y2; - return Math.sqrt(deltaX * deltaX + deltaY * deltaY) + return Math.sqrt(deltaX * deltaX + deltaY * deltaY); } diff --git a/packages/devui-vue/devui/ripple/src/utils/ripple-count.ts b/packages/devui-vue/devui/ripple/src/utils/ripple-count.ts index 6d9720d166..0c762dc3ac 100644 --- a/packages/devui-vue/devui/ripple/src/utils/ripple-count.ts +++ b/packages/devui-vue/devui/ripple/src/utils/ripple-count.ts @@ -1,23 +1,23 @@ -const RIPPLE_COUNT = 'vRippleCountInternal' +const RIPPLE_COUNT = 'vRippleCountInternal'; export function incrementRippleCount(el: HTMLElement) { - const count = getRippleCount(el) - setRippleCount(el, count + 1) + const count = getRippleCount(el); + setRippleCount(el, count + 1); } export function decrementRippleCount(el: HTMLElement) { - const count = getRippleCount(el) - setRippleCount(el, count - 1) + const count = getRippleCount(el); + setRippleCount(el, count - 1); } function setRippleCount(el: HTMLElement, count: number) { - el.dataset[RIPPLE_COUNT] = count.toString() + el.dataset[RIPPLE_COUNT] = count.toString(); } export function getRippleCount(el: HTMLElement): number { - return parseInt(el.dataset[RIPPLE_COUNT] ?? '0', 10) + return parseInt(el.dataset[RIPPLE_COUNT] ?? '0', 10); } export function deleteRippleCount(el: HTMLElement) { - delete el.dataset[RIPPLE_COUNT] + delete el.dataset[RIPPLE_COUNT]; } diff --git a/packages/devui-vue/devui/ripple/src/v-ripple.ts b/packages/devui-vue/devui/ripple/src/v-ripple.ts index 7d7586cc8e..f2977d1bbc 100644 --- a/packages/devui-vue/devui/ripple/src/v-ripple.ts +++ b/packages/devui-vue/devui/ripple/src/v-ripple.ts @@ -1,90 +1,90 @@ -import { createContainer } from './utils/create-container-element' -import { createrippleElement } from './utils/create-ripple-element' -import { getDistanceToFurthestCorner } from './utils/getdistance-tofurthestcorner' -import { getRelativePointer } from './utils/getrelative-pointer' +import { createContainer } from './utils/create-container-element'; +import { createrippleElement } from './utils/create-ripple-element'; +import { getDistanceToFurthestCorner } from './utils/getdistance-tofurthestcorner'; +import { getRelativePointer } from './utils/getrelative-pointer'; import { decrementRippleCount, deleteRippleCount, getRippleCount, incrementRippleCount -} from './utils/ripple-count' -import { IRippleDirectiveOptions } from './options' -const MULTIPLE_NUMBER = 2.05 +} from './utils/ripple-count'; +import { IRippleDirectiveOptions } from './options'; +const MULTIPLE_NUMBER = 2.05; const ripple = ( event: PointerEvent, el: HTMLElement, options: IRippleDirectiveOptions ) => { - const rect = el.getBoundingClientRect() - const computedStyles = window.getComputedStyle(el) - const { x, y } = getRelativePointer(event, rect) - const size = MULTIPLE_NUMBER * getDistanceToFurthestCorner(x, y, rect) + const rect = el.getBoundingClientRect(); + const computedStyles = window.getComputedStyle(el); + const { x, y } = getRelativePointer(event, rect); + const size = MULTIPLE_NUMBER * getDistanceToFurthestCorner(x, y, rect); - const rippleContainer = createContainer(computedStyles) - const rippleEl = createrippleElement(x, y, size, options) + const rippleContainer = createContainer(computedStyles); + const rippleEl = createrippleElement(x, y, size, options); - incrementRippleCount(el) + incrementRippleCount(el); - let originalPositionValue = '' + let originalPositionValue = ''; if (computedStyles.position === 'static') { - if (el.style.position) originalPositionValue = el.style.position - el.style.position = 'relative' + if (el.style.position) {originalPositionValue = el.style.position;} + el.style.position = 'relative'; } - rippleContainer.appendChild(rippleEl) - el.appendChild(rippleContainer) + rippleContainer.appendChild(rippleEl); + el.appendChild(rippleContainer); - let shouldDissolveripple = false + let shouldDissolveripple = false; const releaseripple = (e?: any) => { if (typeof e !== 'undefined') { - document.removeEventListener('pointerup', releaseripple) - document.removeEventListener('pointercancel', releaseripple) + document.removeEventListener('pointerup', releaseripple); + document.removeEventListener('pointercancel', releaseripple); } - if (shouldDissolveripple) dissolveripple() - else shouldDissolveripple = true - } + if (shouldDissolveripple) {dissolveripple();} + else {shouldDissolveripple = true;} + }; const dissolveripple = () => { - rippleEl.style.transition = 'opacity 150ms linear' - rippleEl.style.opacity = '0' + rippleEl.style.transition = 'opacity 150ms linear'; + rippleEl.style.opacity = '0'; setTimeout(() => { - rippleContainer.remove() + rippleContainer.remove(); - decrementRippleCount(el) + decrementRippleCount(el); if (getRippleCount(el) === 0) { - deleteRippleCount(el) - el.style.position = originalPositionValue + deleteRippleCount(el); + el.style.position = originalPositionValue; } - }, 150) - } + }, 150); + }; - document.addEventListener('pointerup', releaseripple) - document.addEventListener('pointercancel', releaseripple) + document.addEventListener('pointerup', releaseripple); + document.addEventListener('pointercancel', releaseripple); const token = setTimeout(() => { - document.removeEventListener('pointercancel', cancelripple) + document.removeEventListener('pointercancel', cancelripple); requestAnimationFrame(() => { - rippleEl.style.transform = `translate(-50%,-50%) scale(1)` - rippleEl.style.opacity = `${options.finalOpacity}` + rippleEl.style.transform = `translate(-50%,-50%) scale(1)`; + rippleEl.style.opacity = `${options.finalOpacity}`; - setTimeout(() => releaseripple(), options.duration * 1000) - }) - }, options.delayTime) + setTimeout(() => releaseripple(), options.duration * 1000); + }); + }, options.delayTime); const cancelripple = () => { - clearTimeout(token) + clearTimeout(token); - rippleContainer.remove() - document.removeEventListener('pointerup', releaseripple) - document.removeEventListener('pointercancel', releaseripple) - document.removeEventListener('pointercancel', cancelripple) - } + rippleContainer.remove(); + document.removeEventListener('pointerup', releaseripple); + document.removeEventListener('pointercancel', releaseripple); + document.removeEventListener('pointercancel', cancelripple); + }; - document.addEventListener('pointercancel', cancelripple) -} + document.addEventListener('pointercancel', cancelripple); +}; -export { ripple } +export { ripple }; diff --git a/packages/devui-vue/devui/search/__tests__/search.spec.ts b/packages/devui-vue/devui/search/__tests__/search.spec.ts index dab7f78755..8077b0bc5f 100644 --- a/packages/devui-vue/devui/search/__tests__/search.spec.ts +++ b/packages/devui-vue/devui/search/__tests__/search.spec.ts @@ -1,12 +1,12 @@ import { mount } from '@vue/test-utils'; -import DSearch from '../src//search' -import { ref, nextTick } from 'vue' +import DSearch from '../src//search'; +import { ref, nextTick } from 'vue'; describe('search test', () => { it('should render correctly', async () => { - const value = ref('test') - const size = ref('') - const disabled = ref(false) + const value = ref('test'); + const size = ref(''); + const disabled = ref(false); const wrapper = mount({ components: { DSearch }, template: ` @@ -21,54 +21,54 @@ describe('search test', () => { value, size, disabled, - } + }; } - }) - expect(wrapper.classes()).toContain('devui-search') - const search = wrapper.find('.devui-search') - const input = search.find('input') - expect(input.element.value).toBe('test') + }); + expect(wrapper.classes()).toContain('devui-search'); + const search = wrapper.find('.devui-search'); + const input = search.find('input'); + expect(input.element.value).toBe('test'); // test size - expect(input.classes()).not.toContain('devui-input-sm') - expect(input.classes()).not.toContain('devui-input-lg') + expect(input.classes()).not.toContain('devui-input-sm'); + expect(input.classes()).not.toContain('devui-input-lg'); - size.value = 'sm' - await nextTick() - expect(wrapper.classes()).toContain(`devui-search__sm`) - expect(wrapper.classes()).not.toContain('devui-search__lg') - size.value = 'lg' - await nextTick() - expect(wrapper.classes()).not.toContain('devui-search__sm') - expect(wrapper.classes()).toContain(`devui-search__lg`) + size.value = 'sm'; + await nextTick(); + expect(wrapper.classes()).toContain(`devui-search__sm`); + expect(wrapper.classes()).not.toContain('devui-search__lg'); + size.value = 'lg'; + await nextTick(); + expect(wrapper.classes()).not.toContain('devui-search__sm'); + expect(wrapper.classes()).toContain(`devui-search__lg`); // test v-model - await input.setValue('def') - expect(value.value).toBe('def') + await input.setValue('def'); + expect(value.value).toBe('def'); - value.value = 'change value' - await nextTick() - expect(input.element.value).toBe('change value') + value.value = 'change value'; + await nextTick(); + expect(input.element.value).toBe('change value'); // test clear - const clear = wrapper.find('.devui-search__clear') - await clear.trigger('click') - expect(input.element.value).toBe('') - expect(value.value).toBe('') + const clear = wrapper.find('.devui-search__clear'); + await clear.trigger('click'); + expect(input.element.value).toBe(''); + expect(value.value).toBe(''); // test disabled - expect(input.attributes('disabled')).toBe(undefined) - expect(wrapper.classes()).not.toContain('devui-search__disbaled') + expect(input.attributes('disabled')).toBe(undefined); + expect(wrapper.classes()).not.toContain('devui-search__disbaled'); - disabled.value = true - await nextTick() - expect(wrapper.classes()).toContain('devui-search__disbaled') - expect(input.attributes('disabled')).toBe('') - }) + disabled.value = true; + await nextTick(); + expect(wrapper.classes()).toContain('devui-search__disbaled'); + expect(input.attributes('disabled')).toBe(''); + }); it('should event correctly', async () => { - const value = ref('test') - const onSearch = jest.fn() + const value = ref('test'); + const onSearch = jest.fn(); const wrapper = mount({ components: { DSearch }, template: ` @@ -81,15 +81,15 @@ describe('search test', () => { return { value, onSearch - } + }; } - }) - const search = wrapper.find('.devui-search') - const searchBtn = search.find('.devui-search__icon') - await searchBtn.trigger('click') + }); + const search = wrapper.find('.devui-search'); + const searchBtn = search.find('.devui-search__icon'); + await searchBtn.trigger('click'); await onSearch((str) => { - expect(str).toBe('test') - }) + expect(str).toBe('test'); + }); expect(onSearch).toBeCalledTimes(1); - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/search/index.ts b/packages/devui-vue/devui/search/index.ts index 16f4e75180..c9a4ca6c91 100644 --- a/packages/devui-vue/devui/search/index.ts +++ b/packages/devui-vue/devui/search/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Search from './src/search' +import type { App } from 'vue'; +import Search from './src/search'; Search.install = function(app: App) { - app.component(Search.name, Search) -} + app.component(Search.name, Search); +}; -export { Search } +export { Search }; export default { title: 'Search 搜索框', category: '通用', status: '100%', install(app: App): void { - app.use(Search as any) + app.use(Search as any); } -} +}; diff --git a/packages/devui-vue/devui/search/src/hooks/use-search-class.ts b/packages/devui-vue/devui/search/src/hooks/use-search-class.ts index dec0969b18..59b7311550 100644 --- a/packages/devui-vue/devui/search/src/hooks/use-search-class.ts +++ b/packages/devui-vue/devui/search/src/hooks/use-search-class.ts @@ -2,15 +2,15 @@ * 定义组件class */ import { computed, ComputedRef } from 'vue'; -import { SearchProps } from '../search-types' +import { SearchProps } from '../search-types'; const SIZE_CLASS = { lg: 'lg', sm: 'sm', -} as const +} as const; const ICON_POSITION = { right: 'right', left: 'left', -} +}; export const getRootClass = (props: SearchProps): ComputedRef => { return computed(() => ({ 'devui-search': true, @@ -18,5 +18,5 @@ export const getRootClass = (props: SearchProps): ComputedRef => { 'devui-search__no-border': props.noBorder, [`devui-search__${props.size}`]: SIZE_CLASS[props.size], [`devui-search__${props.iconPosition}`]: ICON_POSITION[props.iconPosition], - })) -} + })); +}; diff --git a/packages/devui-vue/devui/select/__tests__/select.spec.ts b/packages/devui-vue/devui/select/__tests__/select.spec.ts index d724b6fa8e..0a342fa3a7 100644 --- a/packages/devui-vue/devui/select/__tests__/select.spec.ts +++ b/packages/devui-vue/devui/select/__tests__/select.spec.ts @@ -113,8 +113,8 @@ describe('select', () => { }); it('select v-model work', async () => { - const value = ref() - const options = reactive([1,2,3]) + const value = ref(); + const options = reactive([1,2,3]); const wrapper = mount({ components: { DSelect }, template: `<d-select v-model="value" :options="options" />`, @@ -129,14 +129,14 @@ describe('select', () => { const container = wrapper.find('.devui-select'); const item = container.findAll('.devui-select-item'); - await container.trigger('click') - await item[1].trigger('click') - expect(value.value).toBe(2) - value.value = 1 - await nextTick() - const input = container.find<HTMLInputElement>('.devui-select-input') - expect(input.element.value).toBe('1') - + await container.trigger('click'); + await item[1].trigger('click'); + expect(value.value).toBe(2); + value.value = 1; + await nextTick(); + const input = container.find<HTMLInputElement>('.devui-select-input'); + expect(input.element.value).toBe('1'); + }); it('select disabled work', async () => { @@ -150,25 +150,25 @@ describe('select', () => { expect(container.classes()).toContain('devui-select-disabled'); const input = wrapper.find('.devui-select-input'); - expect(input.attributes()).toHaveProperty('disabled') + expect(input.attributes()).toHaveProperty('disabled'); }); it('select item disabled work', async () => { - const value = ref([]) + const value = ref([]); const options = reactive([ - { - name: '多选', - value: 0 - }, { - name: '多选很重要呢', - value: 1, - disabled: true - }, { - name: '多选真的很重要呢', - value: 2, - disabled: false - } - ]) + { + name: '多选', + value: 0 + }, { + name: '多选很重要呢', + value: 1, + disabled: true + }, { + name: '多选真的很重要呢', + value: 2, + disabled: false + } + ]); const wrapper = mount({ components: { DSelect }, template: `<d-select v-model="value" :options="options" :multiple="true" option-disabled-key="disabled" />`, @@ -183,19 +183,19 @@ describe('select', () => { const container = wrapper.find('.devui-select'); const item = container.findAll('.devui-select-item'); - await container.trigger('click') - await nextTick() - expect(item[1].classes()).toContain('disabled') - await item[1].trigger('click') - expect(value.value).toEqual([]) - await item[0].trigger('click') - expect(value.value).toEqual([0]) + await container.trigger('click'); + await nextTick(); + expect(item[1].classes()).toContain('disabled'); + await item[1].trigger('click'); + expect(value.value).toEqual([]); + await item[0].trigger('click'); + expect(value.value).toEqual([0]); }); it('select clear work', async () => { - const value = ref(1) - const options = reactive([1,2,3]) + const value = ref(1); + const options = reactive([1,2,3]); const wrapper = mount({ components: { DSelect }, template: `<d-select v-model="value" :options="options" :allow-clear="true" />`, @@ -210,8 +210,8 @@ describe('select', () => { const container = wrapper.find('.devui-select'); const clearIcon = container.find('.devui-select-clear'); - expect(clearIcon.exists()).toBeTruthy() - await clearIcon.trigger('click') - expect(value.value).toBe('') + expect(clearIcon.exists()).toBeTruthy(); + await clearIcon.trigger('click'); + expect(value.value).toBe(''); }); }); diff --git a/packages/devui-vue/devui/select/index.ts b/packages/devui-vue/devui/select/index.ts index 432604f95e..d2550f5e48 100644 --- a/packages/devui-vue/devui/select/index.ts +++ b/packages/devui-vue/devui/select/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Select from './src/select' +import type { App } from 'vue'; +import Select from './src/select'; Select.install = function(app: App) { - app.component(Select.name, Select) -} + app.component(Select.name, Select); +}; -export { Select } +export { Select }; export default { title: 'Select 下拉框', category: '数据录入', status: '10%', install(app: App): void { - app.use(Select as any) + app.use(Select as any); } -} +}; diff --git a/packages/devui-vue/devui/select/src/select.tsx b/packages/devui-vue/devui/select/src/select.tsx index 008fe96ffc..a937a8ba54 100644 --- a/packages/devui-vue/devui/select/src/select.tsx +++ b/packages/devui-vue/devui/select/src/select.tsx @@ -17,7 +17,7 @@ export default defineComponent({ // 控制弹窗开合 const isOpen = ref<boolean>(false); function toggleChange(bool: boolean) { - if (props.disabled) return; + if (props.disabled) {return;} isOpen.value = bool; ctx.emit('toggleChange', bool); } @@ -78,7 +78,7 @@ export default defineComponent({ function valueChange(item: OptionObjectItem, index: number) { const { multiple, optionDisabledKey: disabledKey } = props; let { modelValue } = props; - if (disabledKey && !!item[disabledKey]) return; + if (disabledKey && !!item[disabledKey]) {return;} if (multiple) { item._checked = !item._checked; modelValue = mergeOptions.value diff --git a/packages/devui-vue/devui/select/src/use-select.ts b/packages/devui-vue/devui/select/src/use-select.ts index a796cab82a..71044c3f37 100644 --- a/packages/devui-vue/devui/select/src/use-select.ts +++ b/packages/devui-vue/devui/select/src/use-select.ts @@ -1,16 +1,16 @@ import { PropType, ExtractPropTypes } from 'vue'; export interface OptionObjectItem { - name: string - value: string | number - _checked: boolean - [key: string]: any + name: string; + value: string | number; + _checked: boolean; + [key: string]: any; } export type OptionItem = | number | string - | ({ value: string | number; } & Partial<OptionObjectItem>); + | ({ value: string | number } & Partial<OptionObjectItem>); export type Options = Array<OptionItem>; export type ModelValue = number | string | Array<number | string>; diff --git a/packages/devui-vue/devui/select/src/utils.ts b/packages/devui-vue/devui/select/src/utils.ts index 1bab126858..139afe2160 100644 --- a/packages/devui-vue/devui/select/src/utils.ts +++ b/packages/devui-vue/devui/select/src/utils.ts @@ -6,7 +6,7 @@ */ export function className( classStr: string, - classOpt?: { [key: string]: boolean; } + classOpt?: { [key: string]: boolean } ): string { let classname = classStr; if (typeof classOpt === 'object') { @@ -18,4 +18,4 @@ export function className( return classname; } -export type KeyType<T, K extends keyof T> = T[K] +export type KeyType<T, K extends keyof T> = T[K]; diff --git a/packages/devui-vue/devui/shared/devui-api-table/devui-api-table.tsx b/packages/devui-vue/devui/shared/devui-api-table/devui-api-table.tsx index a1076a67df..f5b0a53072 100644 --- a/packages/devui-vue/devui/shared/devui-api-table/devui-api-table.tsx +++ b/packages/devui-vue/devui/shared/devui-api-table/devui-api-table.tsx @@ -1,23 +1,23 @@ -import { defineComponent } from 'vue' -import { apiTableProps, ITableColumn, ITableDataRow } from './devui-api-table.type' +import { defineComponent } from 'vue'; +import { apiTableProps, ITableColumn, ITableDataRow } from './devui-api-table.type'; export default defineComponent({ name: 'DevuiApiTable', props: apiTableProps, render() { - const { columns, data } = this + const { columns, data } = this; - const renderTd = (params: { col: ITableColumn; row: ITableDataRow; }) => { - const { col, row } = params + const renderTd = (params: { col: ITableColumn; row: ITableDataRow }) => { + const { col, row } = params; - const value = row[col.key] + const value = row[col.key]; if ('type' in col) { - return <a href={`#${value}`}>{value}</a> + return <a href={`#${value}`}>{value}</a>; } - return value - } + return value; + }; return ( <table> @@ -34,6 +34,6 @@ export default defineComponent({ </tr> ))} </table> - ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/shared/devui-api-table/devui-api-table.type.ts b/packages/devui-vue/devui/shared/devui-api-table/devui-api-table.type.ts index 359f59df2b..64f6943e27 100644 --- a/packages/devui-vue/devui/shared/devui-api-table/devui-api-table.type.ts +++ b/packages/devui-vue/devui/shared/devui-api-table/devui-api-table.type.ts @@ -1,12 +1,12 @@ -import type { ExtractPropTypes, PropType } from 'vue' +import type { ExtractPropTypes, PropType } from 'vue'; export type ITableColumn = { - key: string - title: string - type?: 'turn' -} + key: string; + title: string; + type?: 'turn'; +}; -export type ITableDataRow = Record<string, any> +export type ITableDataRow = Record<string, any>; export const apiTableProps = { columns: { @@ -18,6 +18,6 @@ export const apiTableProps = { type: Array as PropType<ITableDataRow[]>, default: () => [] } -} as const +} as const; -export type ApiTableProps = ExtractPropTypes<typeof apiTableProps> +export type ApiTableProps = ExtractPropTypes<typeof apiTableProps>; diff --git a/packages/devui-vue/devui/shared/devui-api-table/index.ts b/packages/devui-vue/devui/shared/devui-api-table/index.ts index fb6d8d0b45..46c3d4307e 100644 --- a/packages/devui-vue/devui/shared/devui-api-table/index.ts +++ b/packages/devui-vue/devui/shared/devui-api-table/index.ts @@ -1 +1 @@ -export { default } from './devui-api-table' +export { default } from './devui-api-table'; diff --git a/packages/devui-vue/devui/shared/devui-api/devui-api.tsx b/packages/devui-vue/devui/shared/devui-api/devui-api.tsx index 8bb1359b07..1cfe6546e1 100644 --- a/packages/devui-vue/devui/shared/devui-api/devui-api.tsx +++ b/packages/devui-vue/devui/shared/devui-api/devui-api.tsx @@ -1,16 +1,16 @@ -import { defineComponent } from 'vue' -import { useRoute } from 'vue-router' +import { defineComponent } from 'vue'; +import { useRoute } from 'vue-router'; export default defineComponent({ name: 'DApi', props: { }, setup(props, ctx) { - const route = useRoute() - const ApiCn = route.meta['zh-cn'] + const route = useRoute(); + const ApiCn = route.meta['zh-cn']; return () => { - return <div class="markdown"><ApiCn></ApiCn></div> - } + return <div class="markdown"><ApiCn></ApiCn></div>; + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/shared/devui-codebox/codebox-collapse-icon.tsx b/packages/devui-vue/devui/shared/devui-codebox/codebox-collapse-icon.tsx index 585ab8053d..64b4a040de 100644 --- a/packages/devui-vue/devui/shared/devui-codebox/codebox-collapse-icon.tsx +++ b/packages/devui-vue/devui/shared/devui-codebox/codebox-collapse-icon.tsx @@ -1,15 +1,15 @@ import { defineComponent } from 'vue'; export default defineComponent({ - setup() { - return () => { - return ( - <svg width="16px" height="16px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"> - <path - d="M1003.46892,474.447037 L750.118678,246.329458 C730.418156,228.591027 700.067888,230.181618 682.329458,249.88214 L682.329458,249.88214 L682.329458,249.88214 C664.591027,269.582663 666.181618,299.932931 685.88214,317.671361 L902.31217,512.545835 L686.384104,706.968338 C666.683581,724.706768 665.092991,755.057036 682.831421,774.757559 C700.569852,794.458082 730.92012,796.048672 750.620642,778.310241 L1006.26246,548.129313 C1025.96298,530.390883 1027.55357,500.040615 1009.81514,480.340092 C1007.84473,478.151722 1005.71869,476.186813 1003.46892,474.447037 Z M120.832433,512.545835 L337.262462,317.671361 C356.962985,299.932931 358.553575,269.582663 340.815145,249.88214 L340.815145,249.88214 L340.815145,249.88214 C323.076714,230.181618 292.726447,228.591027 273.025924,246.329458 L19.6756857,474.447037 C17.4259125,476.186813 15.2998752,478.151722 13.3294577,480.340092 L13.3294577,480.340092 L13.3294577,480.340092 C-4.40897251,500.040615 -2.81838236,530.390883 16.8821402,548.129313 L272.52396,778.310241 C292.224483,796.048672 322.574751,794.458082 340.313181,774.757559 C358.051611,755.057036 356.461021,724.706768 336.760498,706.968338 L120.832433,512.545835 Z" - id="Combined-Shape" - ></path> - </svg> - ) - } - } -}) \ No newline at end of file + setup() { + return () => { + return ( + <svg width="16px" height="16px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"> + <path + d="M1003.46892,474.447037 L750.118678,246.329458 C730.418156,228.591027 700.067888,230.181618 682.329458,249.88214 L682.329458,249.88214 L682.329458,249.88214 C664.591027,269.582663 666.181618,299.932931 685.88214,317.671361 L902.31217,512.545835 L686.384104,706.968338 C666.683581,724.706768 665.092991,755.057036 682.831421,774.757559 C700.569852,794.458082 730.92012,796.048672 750.620642,778.310241 L1006.26246,548.129313 C1025.96298,530.390883 1027.55357,500.040615 1009.81514,480.340092 C1007.84473,478.151722 1005.71869,476.186813 1003.46892,474.447037 Z M120.832433,512.545835 L337.262462,317.671361 C356.962985,299.932931 358.553575,269.582663 340.815145,249.88214 L340.815145,249.88214 L340.815145,249.88214 C323.076714,230.181618 292.726447,228.591027 273.025924,246.329458 L19.6756857,474.447037 C17.4259125,476.186813 15.2998752,478.151722 13.3294577,480.340092 L13.3294577,480.340092 L13.3294577,480.340092 C-4.40897251,500.040615 -2.81838236,530.390883 16.8821402,548.129313 L272.52396,778.310241 C292.224483,796.048672 322.574751,794.458082 340.313181,774.757559 C358.051611,755.057036 356.461021,724.706768 336.760498,706.968338 L120.832433,512.545835 Z" + id="Combined-Shape" + ></path> + </svg> + ); + }; + } +}); diff --git a/packages/devui-vue/devui/shared/devui-codebox/codebox-copied-icon.tsx b/packages/devui-vue/devui/shared/devui-codebox/codebox-copied-icon.tsx index 218e779436..c8d46a823c 100644 --- a/packages/devui-vue/devui/shared/devui-codebox/codebox-copied-icon.tsx +++ b/packages/devui-vue/devui/shared/devui-codebox/codebox-copied-icon.tsx @@ -1,23 +1,23 @@ import { defineComponent } from 'vue'; export default defineComponent({ - setup() { - return () => { - return ( - <svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 16 16" version="1.1"> - <defs> - <polygon - id="path-1" - points="6.53553391 9.77817459 12.1923882 4.12132034 13.6066017 5.53553391 6.53553391 12.6066017 3 9.07106781 4.41421356 7.65685425 6.53553391 9.77817459" - /> - </defs> - <g id="status/whiteBG/correct" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> - <mask id="mask-2" fill="white"> - <use xlinkHref="#path-1" /> - </mask> - <use id="Mask" fill="#3DCCA6" xlinkHref="#path-1" /> - </g> - </svg> - ) - } - } -}) \ No newline at end of file + setup() { + return () => { + return ( + <svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 16 16" version="1.1"> + <defs> + <polygon + id="path-1" + points="6.53553391 9.77817459 12.1923882 4.12132034 13.6066017 5.53553391 6.53553391 12.6066017 3 9.07106781 4.41421356 7.65685425 6.53553391 9.77817459" + /> + </defs> + <g id="status/whiteBG/correct" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <mask id="mask-2" fill="white"> + <use xlinkHref="#path-1" /> + </mask> + <use id="Mask" fill="#3DCCA6" xlinkHref="#path-1" /> + </g> + </svg> + ); + }; + } +}); diff --git a/packages/devui-vue/devui/shared/devui-codebox/codebox-copy-icon.tsx b/packages/devui-vue/devui/shared/devui-codebox/codebox-copy-icon.tsx index c5499dade3..05a5aaa59b 100644 --- a/packages/devui-vue/devui/shared/devui-codebox/codebox-copy-icon.tsx +++ b/packages/devui-vue/devui/shared/devui-codebox/codebox-copy-icon.tsx @@ -1,14 +1,14 @@ import { defineComponent } from 'vue'; export default defineComponent({ - setup() { - return () => { - return ( - <svg class="devui-code-copy" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> - <path - d="M10 4v-4h-7l-3 3v9h6v4h10v-12h-6zM3 1.414v1.586h-1.586l1.586-1.586zM1 11v-7h3v-3h5v3l-3 3v4h-5zM9 5.414v1.586h-1.586l1.586-1.586zM15 15h-8v-7h3v-3h5v10z" - ></path> - </svg> - ) - } - } -}) \ No newline at end of file + setup() { + return () => { + return ( + <svg class="devui-code-copy" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> + <path + d="M10 4v-4h-7l-3 3v9h6v4h10v-12h-6zM3 1.414v1.586h-1.586l1.586-1.586zM1 11v-7h3v-3h5v3l-3 3v4h-5zM9 5.414v1.586h-1.586l1.586-1.586zM15 15h-8v-7h3v-3h5v10z" + ></path> + </svg> + ); + }; + } +}); diff --git a/packages/devui-vue/devui/shared/devui-codebox/devui-codebox.tsx b/packages/devui-vue/devui/shared/devui-codebox/devui-codebox.tsx index df358302a9..e336750748 100644 --- a/packages/devui-vue/devui/shared/devui-codebox/devui-codebox.tsx +++ b/packages/devui-vue/devui/shared/devui-codebox/devui-codebox.tsx @@ -1,4 +1,4 @@ -import { defineComponent, ref } from 'vue' +import { defineComponent, ref } from 'vue'; import { DevuiSourceData } from './devui-source-data'; import CollapseIcon from './codebox-collapse-icon'; import CopyIcon from './codebox-copy-icon'; @@ -27,44 +27,44 @@ export default defineComponent({ const toggleCode = () => { expanded.value = !expanded.value; - } + }; const copyCode = (code: string) => { copy(code).then(() => { - _copied.value = true; - setTimeout(() => { - _copied.value = false; - }, 1000) - }) - } + _copied.value = true; + setTimeout(() => { + _copied.value = false; + }, 1000); + }); + }; const copy = (value: string): Promise<string> => { const promise = new Promise<string>((resolve, reject): void => { - let copyTextArea = null as unknown as HTMLTextAreaElement; - try { - copyTextArea = document.createElement('textarea'); - copyTextArea.style.height = '0px'; - copyTextArea.style.opacity = '0'; - copyTextArea.style.width = '0px'; - document.body.appendChild(copyTextArea); - copyTextArea.value = value; - copyTextArea.select(); - document.execCommand('copy'); - resolve(value); - } finally { - if (copyTextArea && copyTextArea.parentNode) { - copyTextArea.parentNode.removeChild(copyTextArea); - } + let copyTextArea = null as unknown as HTMLTextAreaElement; + try { + copyTextArea = document.createElement('textarea'); + copyTextArea.style.height = '0px'; + copyTextArea.style.opacity = '0'; + copyTextArea.style.width = '0px'; + document.body.appendChild(copyTextArea); + copyTextArea.value = value; + copyTextArea.select(); + document.execCommand('copy'); + resolve(value); + } finally { + if (copyTextArea && copyTextArea.parentNode) { + copyTextArea.parentNode.removeChild(copyTextArea); } - }) + } + }); return (promise); - } + }; return () => { return ( <section class={{'code-box': true, 'expand': expanded.value}}> <section class='code-box-demo'> <div> - {ctx.slots.default && ctx.slots.default()} + {ctx.slots.default && ctx.slots.default()} </div> </section> <section class="code-box-meta markdown"> @@ -88,13 +88,13 @@ export default defineComponent({ <DevuiHighlight code={item.code.default || item.code} language={item.language}></DevuiHighlight> </div> </DevuiTab> - ) + ); })} </DevuiTabs> </div> </section> </section> - ) - } + ); + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/shared/devui-codebox/devui-source-data.ts b/packages/devui-vue/devui/shared/devui-codebox/devui-source-data.ts index c243bf2359..2d371b6be3 100644 --- a/packages/devui-vue/devui/shared/devui-codebox/devui-source-data.ts +++ b/packages/devui-vue/devui/shared/devui-codebox/devui-source-data.ts @@ -1,5 +1,5 @@ export interface DevuiSourceData { - title?: string - language?: string - code?: any -} \ No newline at end of file + title?: string; + language?: string; + code?: any; +} diff --git a/packages/devui-vue/devui/shared/devui-directive/utils.ts b/packages/devui-vue/devui/shared/devui-directive/utils.ts index 5af8184df1..aa73b531ba 100644 --- a/packages/devui-vue/devui/shared/devui-directive/utils.ts +++ b/packages/devui-vue/devui/shared/devui-directive/utils.ts @@ -2,22 +2,22 @@ export function on(element: HTMLElement | Document, eventName: string, handler: (this: Element, ev: Event) => any): void { if (document.addEventListener) { if (element && eventName && handler) { - element.addEventListener(eventName, handler, false) + element.addEventListener(eventName, handler, false); } } else { if (element && eventName && handler) { - (element as any).attachEvent('on' + eventName, handler) + (element as any).attachEvent('on' + eventName, handler); } } } export function off(element: HTMLElement | Document, eventName: string, handler: (this: Element, ev: Event) => any): void { if (document.removeEventListener) { if (element && eventName && handler) { - element.removeEventListener(eventName, handler, false) + element.removeEventListener(eventName, handler, false); } } else { if (element && eventName && handler) { - (element as any).detachEvent('on' + eventName, handler) + (element as any).detachEvent('on' + eventName, handler); } } -} \ No newline at end of file +} diff --git a/packages/devui-vue/devui/shared/devui-highlight/devui-highlight.tsx b/packages/devui-vue/devui/shared/devui-highlight/devui-highlight.tsx index 23ba77bebf..3035218818 100644 --- a/packages/devui-vue/devui/shared/devui-highlight/devui-highlight.tsx +++ b/packages/devui-vue/devui/shared/devui-highlight/devui-highlight.tsx @@ -1,4 +1,4 @@ -import { defineComponent } from 'vue' +import { defineComponent } from 'vue'; export default defineComponent({ name: 'DHighlight', @@ -13,7 +13,7 @@ export default defineComponent({ {/* 暂做处理避免tsx语法被解析为html标签 */} <code innerHTML={props.code?.replace(/(<)/g, '<')}></code> </pre> - ) - } + ); + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/shared/hooks/use-demo.tsx b/packages/devui-vue/devui/shared/hooks/use-demo.tsx index 13e094c31b..84c4341d33 100644 --- a/packages/devui-vue/devui/shared/hooks/use-demo.tsx +++ b/packages/devui-vue/devui/shared/hooks/use-demo.tsx @@ -1,11 +1,11 @@ import CodeBox from '../devui-codebox/devui-codebox'; interface ExampleItem { - id: `${string}-${string}` - title: string - text?: string - code: string - content: JSX.Element + id: `${string}-${string}`; + title: string; + text?: string; + code: string; + content: JSX.Element; } export function useDemo (exampleList: ExampleItem[]): JSX.Element { diff --git a/packages/devui-vue/devui/shared/scripts/component.ts b/packages/devui-vue/devui/shared/scripts/component.ts index 090fd7a3ca..d809a5980b 100644 --- a/packages/devui-vue/devui/shared/scripts/component.ts +++ b/packages/devui-vue/devui/shared/scripts/component.ts @@ -1,6 +1,6 @@ -import { h, render } from 'vue' +import { h, render } from 'vue'; -const COMPONENT_CONTAINER_SYMBOL = Symbol('dev_component_container') +const COMPONENT_CONTAINER_SYMBOL = Symbol('dev_component_container'); /** * 创建组件实例对象 @@ -8,11 +8,11 @@ const COMPONENT_CONTAINER_SYMBOL = Symbol('dev_component_container') * @param {*} Component */ export function createComponent(Component: any, props: any, children: any = null) { - const vnode: any = h(Component, { ...props }, children) - const container = document.createElement('div') - vnode[COMPONENT_CONTAINER_SYMBOL] = container - render(vnode, container) - return vnode.component + const vnode: any = h(Component, { ...props }, children); + const container = document.createElement('div'); + vnode[COMPONENT_CONTAINER_SYMBOL] = container; + render(vnode, container); + return vnode.component; } /** @@ -20,5 +20,5 @@ export function createComponent(Component: any, props: any, children: any = null * @param {*} ComponnetInstance 通过createComponent方法得到的组件实例对象 */ export function unmountComponent(ComponnetInstance: any) { - render(null, ComponnetInstance?.vnode[COMPONENT_CONTAINER_SYMBOL]) + render(null, ComponnetInstance?.vnode[COMPONENT_CONTAINER_SYMBOL]); } diff --git a/packages/devui-vue/devui/shared/util/common-var.ts b/packages/devui-vue/devui/shared/util/common-var.ts index a8ba4f7e34..6ea623bfcf 100644 --- a/packages/devui-vue/devui/shared/util/common-var.ts +++ b/packages/devui-vue/devui/shared/util/common-var.ts @@ -1 +1 @@ -export const inBrowser = typeof window !== 'undefined'; \ No newline at end of file +export const inBrowser = typeof window !== 'undefined'; diff --git a/packages/devui-vue/devui/shared/util/debounce.ts b/packages/devui-vue/devui/shared/util/debounce.ts index b76b9c7951..096f06e86e 100644 --- a/packages/devui-vue/devui/shared/util/debounce.ts +++ b/packages/devui-vue/devui/shared/util/debounce.ts @@ -1,25 +1,25 @@ /** - * + * * @param func The function to debounce. * @param wait The number of milliseconds to delay. * @param immediate Whether to execute immediately * @returns Returns the new debounced function. */ export function debounce<A extends Array<any>, R = void>(func: (...args: A) => R, wait: number, immediate: boolean): (...args: A) => R { - let timer: number, result: R; - return function (...args: A) { - if (timer) clearTimeout(timer) - if (immediate) { - const localImmediate = !timer - timer = window.setTimeout(() => { - timer = null - }, wait); - if (localImmediate) result = func.apply(this, args) - } else { - timer = window.setTimeout(() => { - func.apply(this, args) - }, wait); - } - return result + let timer: number, result: R; + return function (...args: A) { + if (timer) {clearTimeout(timer);} + if (immediate) { + const localImmediate = !timer; + timer = window.setTimeout(() => { + timer = null; + }, wait); + if (localImmediate) {result = func.apply(this, args);} + } else { + timer = window.setTimeout(() => { + func.apply(this, args); + }, wait); } + return result; + }; } diff --git a/packages/devui-vue/devui/shared/util/dom.ts b/packages/devui-vue/devui/shared/util/dom.ts index dbd487234a..d3637a3c30 100644 --- a/packages/devui-vue/devui/shared/util/dom.ts +++ b/packages/devui-vue/devui/shared/util/dom.ts @@ -1,9 +1,9 @@ import { ComponentPublicInstance } from '@vue/runtime-core'; /** - * - * @param {any} origin - * @returns + * + * @param {any} origin + * @returns */ export function isComponent(target: any): target is ComponentPublicInstance { return !!(target?.$el); @@ -28,4 +28,4 @@ export function getElement( return element.$el; } return null; -} \ No newline at end of file +} diff --git a/packages/devui-vue/devui/shared/util/props-util.ts b/packages/devui-vue/devui/shared/util/props-util.ts index 9411ed4d2e..f7105e9ad9 100644 --- a/packages/devui-vue/devui/shared/util/props-util.ts +++ b/packages/devui-vue/devui/shared/util/props-util.ts @@ -1,8 +1,8 @@ -import type { Slots, VNode } from 'vue' +import type { Slots, VNode } from 'vue'; export function getPropsSlot( slots: Slots, props: unknown, prop = 'default' ): VNode | string | undefined { - return props[prop] ?? slots[prop]?.() + return props[prop] ?? slots[prop]?.(); } diff --git a/packages/devui-vue/devui/shared/util/set-style.ts b/packages/devui-vue/devui/shared/util/set-style.ts index 8ce5065bc5..241389bf71 100644 --- a/packages/devui-vue/devui/shared/util/set-style.ts +++ b/packages/devui-vue/devui/shared/util/set-style.ts @@ -2,9 +2,9 @@ import type { CSSProperties } from 'vue'; /** * 设置元素的样式,返回上一次的样式 - * @param element - * @param style - * @returns + * @param element + * @param style + * @returns */ export function setStyle( element: HTMLElement, @@ -23,4 +23,4 @@ export function setStyle( }); return oldStyle; -} \ No newline at end of file +} diff --git a/packages/devui-vue/devui/skeleton/__tests__/skeleton-item.spec.ts b/packages/devui-vue/devui/skeleton/__tests__/skeleton-item.spec.ts index d32567b522..b8d52cc6db 100644 --- a/packages/devui-vue/devui/skeleton/__tests__/skeleton-item.spec.ts +++ b/packages/devui-vue/devui/skeleton/__tests__/skeleton-item.spec.ts @@ -6,30 +6,30 @@ describe('skeleton-item module', () => { const wrapper = mount({ components: { DSkeletonItem }, template: `<d-skeleton-item :shape="'avatar'" style="margin-left:55px;width:80px;height:80px;" />`, - }) + }); - expect(wrapper.find('.devui-skeleton__shape__avatar').element.getAttribute('style')).toBe('border-radius: 50%; margin-left: 55px; width: 80px; height: 80px;') - }) + expect(wrapper.find('.devui-skeleton__shape__avatar').element.getAttribute('style')).toBe('border-radius: 50%; margin-left: 55px; width: 80px; height: 80px;'); + }); it('render skeleton-item-avatar without animation', () => { const wrapper = mount({ components: { DSkeletonItem }, template: `<d-skeleton-item :shape="'avatar'" :animate="false" />`, - }) + }); - expect(wrapper.find('.devui-skeleton__shape__avatar').classes()).not.toContain('devui-skeleton__animated') - }) + expect(wrapper.find('.devui-skeleton__shape__avatar').classes()).not.toContain('devui-skeleton__animated'); + }); it('render skeleton-item-paragraph', () => { const wrapper = mount({ components: { DSkeletonItem }, template: `<d-skeleton-item :shape="'paragraph'" :row="3" :row-width="['75%','50%']" />`, - }) - const target = wrapper.find('.devui-skeleton__shape__paragraph') - - expect(target.element.childElementCount).toBe(3) - expect(target.element.children[0].getAttribute('style')).toBe('width: 75%;') - expect(target.element.children[1].getAttribute('style')).toBe('width: 50%;') - expect(target.element.children[2].getAttribute('style')).toBe('') - }) -}) \ No newline at end of file + }); + const target = wrapper.find('.devui-skeleton__shape__paragraph'); + + expect(target.element.childElementCount).toBe(3); + expect(target.element.children[0].getAttribute('style')).toBe('width: 75%;'); + expect(target.element.children[1].getAttribute('style')).toBe('width: 50%;'); + expect(target.element.children[2].getAttribute('style')).toBe(''); + }); +}); diff --git a/packages/devui-vue/devui/skeleton/__tests__/skeleton.spec.ts b/packages/devui-vue/devui/skeleton/__tests__/skeleton.spec.ts index 0a151f5956..b6d9cb3021 100644 --- a/packages/devui-vue/devui/skeleton/__tests__/skeleton.spec.ts +++ b/packages/devui-vue/devui/skeleton/__tests__/skeleton.spec.ts @@ -4,40 +4,40 @@ import DSkeleton from '../src/skeleton'; describe('skeleton module', () => { it('render basic skeleton', () => { - const row = ref(4) + const row = ref(4); const wrapper = mount({ components: { DSkeleton }, template: `<d-skeleton :row="row" />`, setup() { return { row - } + }; }, - }) - - expect(wrapper.classes()).toEqual(['devui-skeleton', 'devui-skeleton__animated']) - expect(wrapper.element.childElementCount).toBe(2) - expect(wrapper.element.children[1].children[1].childElementCount).toBe(4) - }) + }); + + expect(wrapper.classes()).toEqual(['devui-skeleton', 'devui-skeleton__animated']); + expect(wrapper.element.childElementCount).toBe(2); + expect(wrapper.element.children[1].children[1].childElementCount).toBe(4); + }); it('render skeleton without animate', () => { - const animate = ref(false) + const animate = ref(false); const wrapper = mount({ components: { DSkeleton }, template: `<d-skeleton :animate="animate" />`, setup() { return { animate - } + }; }, - }) + }); - expect(wrapper.classes()).toEqual(['devui-skeleton']) - }) + expect(wrapper.classes()).toEqual(['devui-skeleton']); + }); it('render skeleton without title and paragraph', () => { - const title = ref(false) - const paragraph = ref(false) + const title = ref(false); + const paragraph = ref(false); const wrapper = mount({ components: { DSkeleton }, template: `<d-skeleton :title="title" :paragraph="paragraph" />`, @@ -45,11 +45,11 @@ describe('skeleton module', () => { return { title, paragraph - } + }; }, - }) + }); - expect(wrapper.element.children[1].childElementCount).toBe(2) - }) + expect(wrapper.element.children[1].childElementCount).toBe(2); + }); -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/skeleton/index.ts b/packages/devui-vue/devui/skeleton/index.ts index 7ede865581..36b1fc76b4 100644 --- a/packages/devui-vue/devui/skeleton/index.ts +++ b/packages/devui-vue/devui/skeleton/index.ts @@ -1,19 +1,19 @@ -import type { App } from 'vue' -import Skeleton from './src/skeleton' -import SkeletonItem from './src/item/item' +import type { App } from 'vue'; +import Skeleton from './src/skeleton'; +import SkeletonItem from './src/item/item'; Skeleton.install = function(app: App): void { - app.component(Skeleton.name, Skeleton) - app.component(SkeletonItem.name, SkeletonItem) -} + app.component(Skeleton.name, Skeleton); + app.component(SkeletonItem.name, SkeletonItem); +}; -export { Skeleton,SkeletonItem } +export { Skeleton,SkeletonItem }; export default { title: 'Skeleton 骨架屏', category: '数据展示', status: '100%', install(app: App): void { - app.use(Skeleton as any) + app.use(Skeleton as any); } -} +}; diff --git a/packages/devui-vue/devui/skeleton/src/item/item-types.ts b/packages/devui-vue/devui/skeleton/src/item/item-types.ts index e1a9324fb0..bc83f594e6 100644 --- a/packages/devui-vue/devui/skeleton/src/item/item-types.ts +++ b/packages/devui-vue/devui/skeleton/src/item/item-types.ts @@ -1,6 +1,6 @@ -import type { ExtractPropTypes, PropType } from 'vue' +import type { ExtractPropTypes, PropType } from 'vue'; -export type ModelValue = number | string +export type ModelValue = number | string; export const itemProps = { row: { @@ -34,6 +34,6 @@ export const itemProps = { shape: { type: String as PropType<'avatar' | 'image' | 'title' | 'paragraph' | 'button'>, } -} as const +} as const; -export type ItemProps = ExtractPropTypes<typeof itemProps> +export type ItemProps = ExtractPropTypes<typeof itemProps>; diff --git a/packages/devui-vue/devui/skeleton/src/item/item.tsx b/packages/devui-vue/devui/skeleton/src/item/item.tsx index ddadd8b06d..6f91279ed2 100644 --- a/packages/devui-vue/devui/skeleton/src/item/item.tsx +++ b/packages/devui-vue/devui/skeleton/src/item/item.tsx @@ -1,7 +1,7 @@ -import './item.scss' +import './item.scss'; -import { defineComponent } from 'vue' -import { itemProps, ItemProps } from './item-types' +import { defineComponent } from 'vue'; +import { itemProps, ItemProps } from './item-types'; export default defineComponent({ name: 'DSkeletonItem', @@ -10,15 +10,15 @@ export default defineComponent({ const { slots } = ctx; function renderAnimate(isAnimated) { - return isAnimated ? 'devui-skeleton__animated' : '' + return isAnimated ? 'devui-skeleton__animated' : ''; } function renderShapeParagraph(rowNum, rowWidth, round) { - const arr = [] + const arr = []; function pushIntoArray(type) { for (let index = 0; index < rowNum; index++) { - arr.push({ width: type }) + arr.push({ width: type }); } } (function handleRowWidth() { @@ -26,61 +26,61 @@ export default defineComponent({ for (let index = 0; index < rowNum; index++) { if (rowWidth[index]) { switch (typeof rowWidth[index]) { - case 'string': - arr.push({ width: rowWidth[index] }) - break - case 'number': - arr.push({ width: `${rowWidth[index]}px` }) + case 'string': + arr.push({ width: rowWidth[index] }); + break; + case 'number': + arr.push({ width: `${rowWidth[index]}px` }); } } else { - arr.push({ width: 1 }) + arr.push({ width: 1 }); } } } else { switch (typeof rowWidth) { - case 'string': - pushIntoArray(rowWidth) - break - case 'number': - pushIntoArray(`${rowWidth}px`) - break + case 'string': + pushIntoArray(rowWidth); + break; + case 'number': + pushIntoArray(`${rowWidth}px`); + break; } } - })() + })(); return <div class={`devui-skeleton__shape__paragraph ${renderAnimate(props.animate)}`} {...ctx.attrs}>{ arr.map(item => { - return <div class="devui-skeleton__shape__paragraph__item" style={round ? 'border-radius: 1em;' : '' + `width: ${item.width}`} /> + return <div class="devui-skeleton__shape__paragraph__item" style={round ? 'border-radius: 1em;' : '' + `width: ${item.width}`} />; }) - }</div> + }</div>; } function renderAvatarStyle(avatarShape) { function renderAvatarShape(avatarShape) { - return avatarShape === 'square' ? '' : 'border-radius:50%;' + return avatarShape === 'square' ? '' : 'border-radius:50%;'; } - return (renderAvatarShape(avatarShape)) + return (renderAvatarShape(avatarShape)); } return () => { if (props.loading && props.shape) { switch (props.shape) { - case 'avatar': - return <> - <div class={`devui-skeleton__shape__avatar ${renderAnimate(props.animate)}`} style={renderAvatarStyle(props.avatarShape)} {...ctx.attrs} /> - </> - case 'paragraph': - return <> - {renderShapeParagraph(props.row, props.rowWidth, props.round)} - </> - default: - return <> - <div class={`devui-skeleton__shape__${props.shape} ${renderAnimate(props.animate)}`} {...ctx.attrs}/> - </> + case 'avatar': + return <> + <div class={`devui-skeleton__shape__avatar ${renderAnimate(props.animate)}`} style={renderAvatarStyle(props.avatarShape)} {...ctx.attrs} /> + </>; + case 'paragraph': + return <> + {renderShapeParagraph(props.row, props.rowWidth, props.round)} + </>; + default: + return <> + <div class={`devui-skeleton__shape__${props.shape} ${renderAnimate(props.animate)}`} {...ctx.attrs}/> + </>; } } - return <>{slots.default?.()}</> - } + return <>{slots.default?.()}</>; + }; } -}) +}); diff --git a/packages/devui-vue/devui/skeleton/src/skeleton-types.ts b/packages/devui-vue/devui/skeleton/src/skeleton-types.ts index 5e8e5f371b..3404de303b 100644 --- a/packages/devui-vue/devui/skeleton/src/skeleton-types.ts +++ b/packages/devui-vue/devui/skeleton/src/skeleton-types.ts @@ -1,6 +1,6 @@ -import type { ExtractPropTypes, PropType } from 'vue' +import type { ExtractPropTypes, PropType } from 'vue'; -export type ModelValue = number | string +export type ModelValue = number | string; export const skeletonProps = { row: { @@ -47,6 +47,6 @@ export const skeletonProps = { type: [Number, String, Array] as PropType<number | string | Array<number | string>>, default: ['100%'] } -} as const +} as const; -export type SkeletonProps = ExtractPropTypes<typeof skeletonProps> +export type SkeletonProps = ExtractPropTypes<typeof skeletonProps>; diff --git a/packages/devui-vue/devui/skeleton/src/skeleton.tsx b/packages/devui-vue/devui/skeleton/src/skeleton.tsx index d69bd02af2..c5258d538a 100644 --- a/packages/devui-vue/devui/skeleton/src/skeleton.tsx +++ b/packages/devui-vue/devui/skeleton/src/skeleton.tsx @@ -1,7 +1,7 @@ -import './skeleton.scss' +import './skeleton.scss'; -import { defineComponent } from 'vue' -import { skeletonProps, SkeletonProps } from './skeleton-types' +import { defineComponent } from 'vue'; +import { skeletonProps, SkeletonProps } from './skeleton-types'; export default defineComponent({ name: 'DSkeleton', @@ -10,17 +10,17 @@ export default defineComponent({ const { slots } = ctx; function renderAnimate(isAnimated) { - return isAnimated ? 'devui-skeleton__animated' : '' + return isAnimated ? 'devui-skeleton__animated' : ''; } function renderBorderRadius(isRound) { - return isRound ? 'border-radius: 1em;' : '' + return isRound ? 'border-radius: 1em;' : ''; } function renderParagraph(isShown, rowNum, rowWidth, round) { - const arr = [] + const arr = []; function pushIntoArray(type) { for (let index = 0; index < rowNum; index++) { - arr.push({ width: type }) + arr.push({ width: type }); } } (function handleRowWidth() { @@ -28,64 +28,64 @@ export default defineComponent({ for (let index = 0; index < rowNum; index++) { if (rowWidth[index]) { switch (typeof rowWidth[index]) { - case 'string': - arr.push({ width: rowWidth[index] }) - break - case 'number': - arr.push({ width: `${rowWidth[index]}px` }) + case 'string': + arr.push({ width: rowWidth[index] }); + break; + case 'number': + arr.push({ width: `${rowWidth[index]}px` }); } } else { - arr.push({ width: 1 }) + arr.push({ width: 1 }); } } } else { switch (typeof rowWidth) { - case 'string': - pushIntoArray(rowWidth) - break - case 'number': - pushIntoArray(`${rowWidth}px`) - break + case 'string': + pushIntoArray(rowWidth); + break; + case 'number': + pushIntoArray(`${rowWidth}px`); + break; } } - })() + })(); return <div class="devui-skeleton__paragraph" v-show={isShown}>{ arr.map(item => { - return <div class="devui-skeleton__item" style={round ? 'border-radius: 1em;' : '' + `width: ${item.width}`} /> + return <div class="devui-skeleton__item" style={round ? 'border-radius: 1em;' : '' + `width: ${item.width}`} />; }) - }</div> + }</div>; } function renderAvatarStyle(avatarSize, avatarShape) { function renderAvatarShape(avatarShape) { - return avatarShape === 'square' ? '' : 'border-radius:50%;' + return avatarShape === 'square' ? '' : 'border-radius:50%;'; } function renderAvatarSize(avatarSize) { switch (typeof avatarSize) { - case 'string': - return `width:${avatarSize};height:${avatarSize};` - case 'number': - return `width:${avatarSize}px;height:${avatarSize}px;` + case 'string': + return `width:${avatarSize};height:${avatarSize};`; + case 'number': + return `width:${avatarSize}px;height:${avatarSize}px;`; } } - return (renderAvatarSize(avatarSize) + renderAvatarShape(avatarShape)) + return (renderAvatarSize(avatarSize) + renderAvatarShape(avatarShape)); } function renderTitle(isVisible, titleWidth, isRound) { function renderTitleWidth(titleWidth) { switch (typeof titleWidth) { - case 'string': - return `width: ${titleWidth};` - case 'number': - return `width: ${titleWidth}px;` + case 'string': + return `width: ${titleWidth};`; + case 'number': + return `width: ${titleWidth}px;`; } } function renderTitleVisibility(isVisible) { - return isVisible ? null : 'visibility: hidden;' + return isVisible ? null : 'visibility: hidden;'; } - return (renderTitleWidth(titleWidth) + renderBorderRadius(isRound) + renderTitleVisibility(isVisible)) + return (renderTitleWidth(titleWidth) + renderBorderRadius(isRound) + renderTitleVisibility(isVisible)); } function renderDefaultSkeleton() { return <> @@ -96,16 +96,16 @@ export default defineComponent({ <div class="devui-skeleton__title" style={renderTitle(props.title, props.titleWidth, props.round)} /> {renderParagraph(props.paragraph, props.row, props.rowWidth, props.round)} </div> - </> + </>; } return () => { if (props.loading) { return <div class={`devui-skeleton ${renderAnimate(props.animate)}`}> {renderDefaultSkeleton()} - </div> + </div>; } - return <>{slots.default?.()}</> - } + return <>{slots.default?.()}</>; + }; } -}) +}); diff --git a/packages/devui-vue/devui/slider/__tests__/slider.spec.ts b/packages/devui-vue/devui/slider/__tests__/slider.spec.ts index 35fd4dea12..a74fed251b 100644 --- a/packages/devui-vue/devui/slider/__tests__/slider.spec.ts +++ b/packages/devui-vue/devui/slider/__tests__/slider.spec.ts @@ -1,6 +1,6 @@ -import { mount } from '@vue/test-utils' -import { nextTick, ref } from 'vue' -import DSlider from '../src/slider' +import { mount } from '@vue/test-utils'; +import { nextTick, ref } from 'vue'; +import DSlider from '../src/slider'; describe('d-slider', () => { it('slider maxValue && minValue work', () => { @@ -9,14 +9,14 @@ describe('d-slider', () => { max: 50, min: 2 } - }) - const max = wrapper.find('.devui-max_count') - const min = wrapper.find('.devui-min_count') - expect(min.text()).toBe('2') - expect(max.text()).toBe('50') - }) + }); + const max = wrapper.find('.devui-max_count'); + const min = wrapper.find('.devui-min_count'); + expect(min.text()).toBe('2'); + expect(max.text()).toBe('50'); + }); it('slider v-model work', async () => { - const value = ref(5) + const value = ref(5); const wrapper = mount({ components: { DSlider }, template: ` @@ -25,44 +25,44 @@ describe('d-slider', () => { setup() { return { modelValue: value - } + }; } - }) - const input = wrapper.find('input') - expect(input.element.value).toBe('5') - input.setValue(10) - await nextTick() - expect(value.value).toBe(10) - }) + }); + const input = wrapper.find('input'); + expect(input.element.value).toBe('5'); + input.setValue(10); + await nextTick(); + expect(value.value).toBe(10); + }); it('slider showInput work', () => { const wrapper = mount(DSlider, { props: { showInput: true } - }) - const dInput = wrapper.find('.devui-input__out-wrap') - expect(dInput.exists()).toBeTruthy() - }) + }); + const dInput = wrapper.find('.devui-input__out-wrap'); + expect(dInput.exists()).toBeTruthy(); + }); it('slider disabled work', () => { const wrapper = mount(DSlider, { props: { disabled: true } - }) - const slider = wrapper.find('.devui-slider__runway') - expect(slider.classes()).toContain('disabled') - }) + }); + const slider = wrapper.find('.devui-slider__runway'); + expect(slider.classes()).toContain('disabled'); + }); it('slider tipsRenderer work', () => { const wrapper = mount(DSlider, { props: { tipsRenderer: 'null' } - }) - const slider = wrapper.find('.devui-slider_popover') - expect(slider.exists()).toBe(false) - }) + }); + const slider = wrapper.find('.devui-slider_popover'); + expect(slider.exists()).toBe(false); + }); it('slider popover work', () => { const wrapper = mount(DSlider, { @@ -70,8 +70,8 @@ describe('d-slider', () => { tipsRenderer: 'bananas', modelValue: 10 } - }) - const slider = wrapper.find('.devui-slider_popover-content') - expect(slider.text()).toBe('10 bananas') - }) -}) + }); + const slider = wrapper.find('.devui-slider_popover-content'); + expect(slider.text()).toBe('10 bananas'); + }); +}); diff --git a/packages/devui-vue/devui/slider/index.ts b/packages/devui-vue/devui/slider/index.ts index 52d1430fbe..4acfcca082 100644 --- a/packages/devui-vue/devui/slider/index.ts +++ b/packages/devui-vue/devui/slider/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Slider from './src/slider' +import type { App } from 'vue'; +import Slider from './src/slider'; Slider.install = function (app: App): void { - app.component(Slider.name, Slider) -} + app.component(Slider.name, Slider); +}; -export { Slider } +export { Slider }; export default { title: 'Slider 滑块', category: '数据录入', status: '100%', install(app: App): void { - app.use(Slider as any) + app.use(Slider as any); } -} +}; diff --git a/packages/devui-vue/devui/slider/src/slider.tsx b/packages/devui-vue/devui/slider/src/slider.tsx index be8c1ce926..03c6ccfd36 100644 --- a/packages/devui-vue/devui/slider/src/slider.tsx +++ b/packages/devui-vue/devui/slider/src/slider.tsx @@ -16,7 +16,7 @@ export default defineComponent({ const inputValue = ref<number>(props.modelValue); const currentPosition = ref<number>(0); const newPostion = ref<number>(0); - //当前的位置以百分比显示 + // 当前的位置以百分比显示 const percentDispaly = ref<string>(''); const renderShowInput = () => { return props.showInput ? ( @@ -27,7 +27,7 @@ export default defineComponent({ '' ); }; - //当传入modelValue时用以定位button的位置 + // 当传入modelValue时用以定位button的位置 if (props.modelValue > props.max) { percentDispaly.value = '100%'; } else if (props.modelValue < props.min) { @@ -35,29 +35,29 @@ export default defineComponent({ } else { percentDispaly.value = ((props.modelValue - props.min) * 100) / (props.max - props.min) + '%'; } - //一挂载就进行当前位置的计算,以后的移动基于当前的位置移动 + // 一挂载就进行当前位置的计算,以后的移动基于当前的位置移动 onMounted(() => { const sliderWidth = sliderRunway.value.clientWidth; currentPosition.value = (sliderWidth * (inputValue.value - props.min)) / (props.max - props.min); }); function handleButtonMousedown(event: MouseEvent) { popoverShow.value = true; - //props.disabled状态是不能点击拖拽的 - if (props.disabled) return; - //阻止默认事件 + // props.disabled状态是不能点击拖拽的 + if (props.disabled) {return;} + // 阻止默认事件 event.preventDefault(); dragStart(event); - //当鼠标开始移动时,进行坐标计算 + // 当鼠标开始移动时,进行坐标计算 window.addEventListener('mousemove', onDragging); - //当鼠标抬起时,停止计算 + // 当鼠标抬起时,停止计算 window.addEventListener('mouseup', onDragEnd); } function dragStart(event: MouseEvent) { - //防止mouseup触发父元素的click事件 + // 防止mouseup触发父元素的click事件 isClick = false; - //获取当前的x坐标值 + // 获取当前的x坐标值 startX = event.clientX; - //把当前值给startPosition,以便后面再重新拖拽时,会以当前的位置计算偏移 + // 把当前值给startPosition,以便后面再重新拖拽时,会以当前的位置计算偏移 startPosition = currentPosition.value; newPostion.value = startPosition; } @@ -72,14 +72,14 @@ export default defineComponent({ popoverShow.value = true; const currentX = event.clientX; const pxOffset = currentX - startX; - //移动的x方向上的偏移+初始位置等于新位置 + // 移动的x方向上的偏移+初始位置等于新位置 newPostion.value = startPosition + pxOffset; setPostion(newPostion.value); } function onDragEnd() { popoverShow.value = false; - //防止mouseup后立即执行click事件,mouseup后 - //会立即执行click,但是isClick=true 是100ms才出发,因此不会执行click事件,就跳出来了 + // 防止mouseup后立即执行click事件,mouseup后 + // 会立即执行click,但是isClick=true 是100ms才出发,因此不会执行click事件,就跳出来了 setTimeout(() => { isClick = true; }, 100); @@ -87,18 +87,18 @@ export default defineComponent({ window.removeEventListener('mouseup', onDragEnd); } function setPostion(newPosition: number) { - //获取slider的实际长度的像素 + // 获取slider的实际长度的像素 const sliderWidth: number = Math.round(sliderRunway.value.clientWidth); if (newPosition < 0) { newPosition = 0; } - //计算slider的实际像素每段的长度 + // 计算slider的实际像素每段的长度 const LengthPerStep = sliderWidth / ((props.max - props.min) / props.step); - //计算实际位移的取整段数 + // 计算实际位移的取整段数 const steps = Math.round(newPosition / LengthPerStep); - //实际的偏移像素 + // 实际的偏移像素 const value: number = steps * LengthPerStep; - //要是刚好划过半段切刚好超出最大长度的情况进行限定 + // 要是刚好划过半段切刚好超出最大长度的情况进行限定 if (Math.round(value) >= sliderWidth) { currentPosition.value = sliderWidth; inputValue.value = props.max; @@ -106,15 +106,15 @@ export default defineComponent({ ctx.emit('update:modelValue', props.max); return; } - //向左偏移百分比的值 + // 向左偏移百分比的值 percentDispaly.value = Math.round((value * 100) / sliderWidth) + '%'; - //更新输入框的值 + // 更新输入框的值 inputValue.value = Math.round((value * (props.max - props.min)) / sliderWidth) + props.min; - //设置当前所在的位置 + // 设置当前所在的位置 currentPosition.value = newPosition; ctx.emit('update:modelValue', inputValue.value); } - //当在滑动条触发鼠标事件时处理, + // 当在滑动条触发鼠标事件时处理, function handleRunwayMousedown(event) { if (!props.disabled && isClick) { startX = event.target.getBoundingClientRect().left; @@ -125,7 +125,7 @@ export default defineComponent({ return; } } - //输入框内的值 + // 输入框内的值 function handleOnInput(event) { inputValue.value = parseInt(event.target.value); if (!inputValue.value) { @@ -133,7 +133,7 @@ export default defineComponent({ percentDispaly.value = '0%'; } else { if (inputValue.value < props.min || inputValue.value > props.max) { - return + return; } const re = /^(?:[1-9]?\d|100)$/; if (re.test(`${inputValue.value}`)) { @@ -142,7 +142,7 @@ export default defineComponent({ } } } - //添加disabled类 + // 添加disabled类 const disableClass = computed(() => { return props.disabled ? ' disabled' : ''; }); diff --git a/packages/devui-vue/devui/splitter/__mocks__/event-helper.ts b/packages/devui-vue/devui/splitter/__mocks__/event-helper.ts index 6fecff132e..c446a820f4 100644 --- a/packages/devui-vue/devui/splitter/__mocks__/event-helper.ts +++ b/packages/devui-vue/devui/splitter/__mocks__/event-helper.ts @@ -1,14 +1,14 @@ export function mouseMoveTrigger( el: HTMLElement, - from: { x: number; y: number; }, - to: { x: number; y: number; } + from: { x: number; y: number }, + to: { x: number; y: number } ): void { if (typeof window === 'undefined') { - return + return; } - dispatchMouseEvent(el, 'mousedown', from.x, from.y) - dispatchMouseEvent(window.document, 'mousemove', to.x, to.y) - dispatchMouseEvent(window.document, 'mouseup') + dispatchMouseEvent(el, 'mousedown', from.x, from.y); + dispatchMouseEvent(window.document, 'mousemove', to.x, to.y); + dispatchMouseEvent(window.document, 'mouseup'); } export function dispatchMouseEvent( @@ -18,7 +18,7 @@ export function dispatchMouseEvent( y = 0, event: MouseEvent = createMouseEvent(type, x, y) ): void { - node.dispatchEvent(event) + node.dispatchEvent(event); } export function createMouseEvent( @@ -31,6 +31,6 @@ export function createMouseEvent( cancelable: false, clientX: x, clientY: y, - }) - return event + }); + return event; } diff --git a/packages/devui-vue/devui/splitter/__tests__/splitter.spec.ts b/packages/devui-vue/devui/splitter/__tests__/splitter.spec.ts index a9ec9c417b..f26044d22d 100644 --- a/packages/devui-vue/devui/splitter/__tests__/splitter.spec.ts +++ b/packages/devui-vue/devui/splitter/__tests__/splitter.spec.ts @@ -1,16 +1,16 @@ -import { mount } from '@vue/test-utils' -import { ref } from 'vue' -import DSplitter from '../src/splitter' -import DSplitterPane from '../src/splitter-pane' -import { mouseMoveTrigger } from '../__mocks__/event-helper' +import { mount } from '@vue/test-utils'; +import { ref } from 'vue'; +import DSplitter from '../src/splitter'; +import DSplitterPane from '../src/splitter-pane'; +import { mouseMoveTrigger } from '../__mocks__/event-helper'; // 因为 jest 不支持 ResizeObserver,需要 mock 实现 window.ResizeObserver = window.ResizeObserver || jest.fn().mockImplementation(() => ({ - disconnect: jest.fn(), - observe: jest.fn(), - unobserve: jest.fn(), + disconnect: jest.fn(), + observe: jest.fn(), + unobserve: jest.fn(), })); describe('splitter', () => { @@ -45,16 +45,16 @@ describe('splitter', () => { </d-splitter> `, setup() { - const orientation = ref('horizontal') - const collapsible = ref(true) - const collapsed = ref(false) - const splitBarSize = ref('2px') - const size = ref('30%') - const minSize = ref('20%') - const maxSize = ref('60%') + const orientation = ref('horizontal'); + const collapsible = ref(true); + const collapsed = ref(false); + const splitBarSize = ref('2px'); + const size = ref('30%'); + const minSize = ref('20%'); + const maxSize = ref('60%'); const sizeChange = (size) => { - console.log(size) - } + console.log(size); + }; return { orientation, collapsible, @@ -64,64 +64,64 @@ describe('splitter', () => { minSize, maxSize, sizeChange, - } + }; }, - } + }; - let wrapper = null - let splitterElement: HTMLElement + let wrapper = null; + let splitterElement: HTMLElement; beforeEach(() => { - wrapper = mount(testComponent) - splitterElement = wrapper.vm.$el - }) + wrapper = mount(testComponent); + splitterElement = wrapper.vm.$el; + }); it('should create testComponent', () => { - expect(wrapper.vm).toBeTruthy() - }) + expect(wrapper.vm).toBeTruthy(); + }); it('should create splitter container', () => { - expect(splitterElement).toBeTruthy() - expect(wrapper.classes()).toContain('devui-splitter-horizontal') - }) + expect(splitterElement).toBeTruthy(); + expect(wrapper.classes()).toContain('devui-splitter-horizontal'); + }); it('should render splitter-bar', () => { - const handles = wrapper.findAll('.devui-splitter-bar') - expect(handles.length).toBe(2) - }) + const handles = wrapper.findAll('.devui-splitter-bar'); + expect(handles.length).toBe(2); + }); it('should collapse left pane when collapseButton clicked', async () => { - const handleButton = wrapper.find('.prev.devui-collapse') - handleButton.trigger('click') - await wrapper.vm.$nextTick() + const handleButton = wrapper.find('.prev.devui-collapse'); + handleButton.trigger('click'); + await wrapper.vm.$nextTick(); const pane = wrapper.find('.devui-splitter-pane').element; // jsdom 不支持 clientWidth 属性,需要 mock Object.defineProperty(pane, 'clientWidth', { get: jest.fn().mockImplementation(() => 0), set: jest.fn().mockImplementation(() => {}), }); - expect(pane.clientWidth).toBe(0) - }) + expect(pane.clientWidth).toBe(0); + }); it('should add collapsed class when collapseButton clicked', async () => { - const handleButton = wrapper.find('.prev.devui-collapse') - handleButton.trigger('click') - await wrapper.vm.$nextTick() - expect(handleButton.classes()).toContain('collapsed') - }) + const handleButton = wrapper.find('.prev.devui-collapse'); + handleButton.trigger('click'); + await wrapper.vm.$nextTick(); + expect(handleButton.classes()).toContain('collapsed'); + }); it('should change collapse state', () => { wrapper = mount( Object.assign(testComponent, { setup() { - const orientation = ref('horizontal') - const collapsible = ref(false) - const collapsed = ref(false) - const splitBarSize = ref('2px') - const size = ref('30%') - const minSize = ref('20%') - const maxSize = ref('60%') + const orientation = ref('horizontal'); + const collapsible = ref(false); + const collapsed = ref(false); + const splitBarSize = ref('2px'); + const size = ref('30%'); + const minSize = ref('20%'); + const maxSize = ref('60%'); const sizeChange = (size) => { - console.log(size) - } + console.log(size); + }; return { orientation, collapsible, @@ -131,27 +131,27 @@ describe('splitter', () => { minSize, maxSize, sizeChange, - } + }; }, }) - ) - expect(wrapper.find('.prev').classes()).not.toContain('devui-collapse') - }) + ); + expect(wrapper.find('.prev').classes()).not.toContain('devui-collapse'); + }); it('should be collapsed', () => { wrapper = mount( Object.assign(testComponent, { setup() { - const orientation = ref('horizontal') - const collapsible = ref(true) - const collapsed = ref(true) - const splitBarSize = ref('2px') - const size = ref('30%') - const minSize = ref('20%') - const maxSize = ref('60%') + const orientation = ref('horizontal'); + const collapsible = ref(true); + const collapsed = ref(true); + const splitBarSize = ref('2px'); + const size = ref('30%'); + const minSize = ref('20%'); + const maxSize = ref('60%'); const sizeChange = (size) => { - console.log(size) - } + console.log(size); + }; return { orientation, collapsible, @@ -161,14 +161,14 @@ describe('splitter', () => { minSize, maxSize, sizeChange, - } + }; }, }) - ) + ); expect(wrapper.find('.prev.devui-collapse').classes()).toContain( 'collapsed' - ) - }) + ); + }); it('should change splitterBar size', async () => { const element = wrapper.find('.devui-splitter-bar').element; @@ -177,23 +177,23 @@ describe('splitter', () => { get: jest.fn().mockImplementation(() => 2), set: jest.fn().mockImplementation(() => {}), }); - expect(wrapper.find('.devui-splitter-bar').element.clientWidth).toBe(2) - }) + expect(wrapper.find('.devui-splitter-bar').element.clientWidth).toBe(2); + }); it('should change splitter direction', () => { wrapper = mount( Object.assign(testComponent, { setup() { - const orientation = ref('vertical') - const collapsible = ref(true) - const collapsed = ref(true) - const splitBarSize = ref('2px') - const size = ref('30%') - const minSize = ref('20%') - const maxSize = ref('60%') + const orientation = ref('vertical'); + const collapsible = ref(true); + const collapsed = ref(true); + const splitBarSize = ref('2px'); + const size = ref('30%'); + const minSize = ref('20%'); + const maxSize = ref('60%'); const sizeChange = (size) => { - console.log(size) - } + console.log(size); + }; return { orientation, collapsible, @@ -203,27 +203,27 @@ describe('splitter', () => { minSize, maxSize, sizeChange, - } + }; }, }) - ) - expect(wrapper.classes()).toContain('devui-splitter-vertical') - }) + ); + expect(wrapper.classes()).toContain('devui-splitter-vertical'); + }); it('should change pane size', async () => { wrapper = mount( Object.assign(testComponent, { setup() { - const orientation = ref('vertical') - const collapsible = ref(true) - const collapsed = ref(true) - const splitBarSize = ref('2px') - const size = ref('40%') - const minSize = ref('20%') - const maxSize = ref('60%') + const orientation = ref('vertical'); + const collapsible = ref(true); + const collapsed = ref(true); + const splitBarSize = ref('2px'); + const size = ref('40%'); + const minSize = ref('20%'); + const maxSize = ref('60%'); const sizeChange = (size) => { - console.log(size) - } + console.log(size); + }; return { orientation, collapsible, @@ -233,31 +233,31 @@ describe('splitter', () => { minSize, maxSize, sizeChange, - } + }; }, }) - ) - await wrapper.vm.$nextTick() + ); + await wrapper.vm.$nextTick(); const computedStyle = getComputedStyle( wrapper.find('.devui-splitter-pane').element - ) - expect(computedStyle.flexBasis).toContain('40%') - }) + ); + expect(computedStyle.flexBasis).toContain('40%'); + }); it('should change pane size', () => { wrapper = mount( Object.assign(testComponent, { setup() { - const orientation = ref('vertical') - const collapsible = ref(true) - const collapsed = ref(true) - const splitBarSize = ref('2px') - const size = ref(undefined) - const minSize = ref('20%') - const maxSize = ref('60%') + const orientation = ref('vertical'); + const collapsible = ref(true); + const collapsed = ref(true); + const splitBarSize = ref('2px'); + const size = ref(undefined); + const minSize = ref('20%'); + const maxSize = ref('60%'); const sizeChange = (size) => { - console.log(size) - } + console.log(size); + }; return { orientation, collapsible, @@ -267,15 +267,15 @@ describe('splitter', () => { minSize, maxSize, sizeChange, - } + }; }, }) - ) + ); expect(wrapper.find('.devui-splitter-pane').classes()).not.toContain( 'devui-splitter-pane-fixed' - ) - }) - }) + ); + }); + }); describe('vertical', () => { const testComponent = { @@ -306,28 +306,28 @@ describe('splitter', () => { </d-splitter> `, setup() { - const orientation = ref('vertical') - const size = ref('100px') - const minSize = ref('50px') - const maxSize = ref('200px') + const orientation = ref('vertical'); + const size = ref('100px'); + const minSize = ref('50px'); + const maxSize = ref('200px'); return { orientation, size, minSize, maxSize, - } + }; }, - } + }; - let wrapper = null + let wrapper = null; beforeEach(() => { - wrapper = mount(testComponent) - }) + wrapper = mount(testComponent); + }); it('should create vertical container', () => { - expect(wrapper.vm.$el).toBeTruthy() - expect(wrapper.classes()).toContain('devui-splitter-vertical') - }) + expect(wrapper.vm.$el).toBeTruthy(); + expect(wrapper.classes()).toContain('devui-splitter-vertical'); + }); - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/splitter/index.ts b/packages/devui-vue/devui/splitter/index.ts index db6651c449..7f3d960b83 100644 --- a/packages/devui-vue/devui/splitter/index.ts +++ b/packages/devui-vue/devui/splitter/index.ts @@ -1,19 +1,19 @@ -import type { App } from 'vue' -import Splitter from './src/splitter' -import SplitterPane from './src/splitter-pane' +import type { App } from 'vue'; +import Splitter from './src/splitter'; +import SplitterPane from './src/splitter-pane'; Splitter.install = function (app: App): void { - app.component(Splitter.name, Splitter) - app.component(SplitterPane.name, SplitterPane) -} + app.component(Splitter.name, Splitter); + app.component(SplitterPane.name, SplitterPane); +}; -export { Splitter } +export { Splitter }; export default { title: 'Splitter 分割器', category: '布局', status: '100%', install(app: App): void { - app.use(Splitter as any) + app.use(Splitter as any); }, -} +}; diff --git a/packages/devui-vue/devui/splitter/src/splitter-bar-type.tsx b/packages/devui-vue/devui/splitter/src/splitter-bar-type.tsx index 8d245b435e..237f32ed3b 100644 --- a/packages/devui-vue/devui/splitter/src/splitter-bar-type.tsx +++ b/packages/devui-vue/devui/splitter/src/splitter-bar-type.tsx @@ -1,5 +1,5 @@ -import { PropType, ExtractPropTypes } from 'vue' -import { SplitterOrientation } from './splitter-types' +import { PropType, ExtractPropTypes } from 'vue'; +import { SplitterOrientation } from './splitter-types'; export const splitterBarProps = { /** @@ -35,6 +35,6 @@ export const splitterBarProps = { showCollapseButton: { type: Boolean, }, -} as const +} as const; -export type SplitterBarProps = ExtractPropTypes<typeof splitterBarProps> +export type SplitterBarProps = ExtractPropTypes<typeof splitterBarProps>; diff --git a/packages/devui-vue/devui/splitter/src/splitter-bar.tsx b/packages/devui-vue/devui/splitter/src/splitter-bar.tsx index bfc8b08f29..3bfedcc520 100644 --- a/packages/devui-vue/devui/splitter/src/splitter-bar.tsx +++ b/packages/devui-vue/devui/splitter/src/splitter-bar.tsx @@ -7,15 +7,15 @@ import { withDirectives, onMounted, inject, -} from 'vue' +} from 'vue'; -import DToolTip from '../../tooltip/src/tooltip' -import { setStyle } from '../../shared/util/set-style' -import type { SplitterStore } from './splitter-store' -import { addClass, removeClass } from '../../shared/util/class' -import dresize, { ResizeDirectiveProp } from './util/d-resize-directive' -import { splitterBarProps, SplitterBarProps } from './splitter-bar-type' -import './splitter-bar.scss' +import DToolTip from '../../tooltip/src/tooltip'; +import { setStyle } from '../../shared/util/set-style'; +import type { SplitterStore } from './splitter-store'; +import { addClass, removeClass } from '../../shared/util/class'; +import dresize, { ResizeDirectiveProp } from './util/d-resize-directive'; +import { splitterBarProps, SplitterBarProps } from './splitter-bar-type'; +import './splitter-bar.scss'; export default defineComponent({ name: 'DSplitterBar', @@ -24,151 +24,151 @@ export default defineComponent({ }, props: splitterBarProps, setup(props: SplitterBarProps) { - const store: SplitterStore = inject('splitterStore') + const store: SplitterStore = inject('splitterStore'); const state = reactive({ wrapperClass: `devui-splitter-bar devui-splitter-bar-${props.orientation}`, - }) - const domRef = ref<null | HTMLElement>() + }); + const domRef = ref<null | HTMLElement>(); watch([() => props.splitBarSize, domRef], ([curSplitBarSize, ele]) => { if (!(ele instanceof HTMLElement)) { return; } - setStyle(ele, { flexBasis: curSplitBarSize }) - }, { immediate: true }) + setStyle(ele, { flexBasis: curSplitBarSize }); + }, { immediate: true }); watch([() => store.state.panes, domRef], ([panes, ele]) => { if (!store.isStaticBar(props.index)) { - state.wrapperClass += ' resizable' + state.wrapperClass += ' resizable'; } else { - setStyle(ele, { flexBasis: props.disabledBarSize }) + setStyle(ele, { flexBasis: props.disabledBarSize }); } - }, { deep: true }) + }, { deep: true }); // 指令输入值 - const coordinate = { pageX: 0, pageY: 0, originalX: 0, originalY: 0 } - let initState + const coordinate = { pageX: 0, pageY: 0, originalX: 0, originalY: 0 }; + let initState; // TODO 待优化,如何像 angular rxjs 操作一样优雅 const resizeProp: ResizeDirectiveProp = { enableResize: true, onPressEvent: function ({ originalEvent }): void { - originalEvent.stopPropagation() // 按下的时候,阻止事件冒泡 - if (!store.isResizable(props.index)) return - initState = store.dragState(props.index) - coordinate.originalX = originalEvent.pageX - coordinate.originalY = originalEvent.pageY + originalEvent.stopPropagation(); // 按下的时候,阻止事件冒泡 + if (!store.isResizable(props.index)) {return;} + initState = store.dragState(props.index); + coordinate.originalX = originalEvent.pageX; + coordinate.originalY = originalEvent.pageY; }, onDragEvent: function ({ originalEvent }): void { - originalEvent.stopPropagation() // 移动的时候,阻止事件冒泡 - if (!store.isResizable(props.index)) return - coordinate.pageX = originalEvent.pageX - coordinate.pageY = originalEvent.pageY - let distance + originalEvent.stopPropagation(); // 移动的时候,阻止事件冒泡 + if (!store.isResizable(props.index)) {return;} + coordinate.pageX = originalEvent.pageX; + coordinate.pageY = originalEvent.pageY; + let distance; if (props.orientation === 'vertical') { - distance = coordinate.pageY - coordinate.originalY + distance = coordinate.pageY - coordinate.originalY; } else { - distance = coordinate.pageX - coordinate.originalX + distance = coordinate.pageX - coordinate.originalX; } - store.setSize(initState, distance) + store.setSize(initState, distance); }, onReleaseEvent: function ({ originalEvent }): void { - originalEvent.stopPropagation() // 释放的时候,阻止事件冒泡 - if (!store.isResizable(props.index)) return - coordinate.pageX = originalEvent.pageX - coordinate.pageY = originalEvent.pageY - let distance + originalEvent.stopPropagation(); // 释放的时候,阻止事件冒泡 + if (!store.isResizable(props.index)) {return;} + coordinate.pageX = originalEvent.pageX; + coordinate.pageY = originalEvent.pageY; + let distance; if (props.orientation === 'vertical') { - distance = coordinate.pageY - coordinate.originalY + distance = coordinate.pageY - coordinate.originalY; } else { - distance = coordinate.pageX - coordinate.originalX + distance = coordinate.pageX - coordinate.originalX; } - store.setSize(initState, distance) + store.setSize(initState, distance); }, - } + }; const queryPanes = (index, nearIndex) => { - const pane = store.getPane(index) - const nearPane = store.getPane(nearIndex) + const pane = store.getPane(index); + const nearPane = store.getPane(nearIndex); return { pane, nearPane, - } - } + }; + }; // 根据当前状态生成收起按钮样式 const generateCollapseClass = (pane, nearPane, showIcon) => { // 是否允许收起 - const isCollapsible = pane?.component?.props?.collapsible && showIcon + const isCollapsible = pane?.component?.props?.collapsible && showIcon; // 当前收起状态 - const isCollapsed = pane?.component?.props?.collapsed + const isCollapsed = pane?.component?.props?.collapsed; // 一个 pane 收起的时候,隐藏相邻 pane 的收起按钮 - const isNearPaneCollapsed = nearPane.collapsed + const isNearPaneCollapsed = nearPane.collapsed; return { 'devui-collapse': isCollapsible, collapsed: isCollapsed, hidden: isNearPaneCollapsed, - } - } + }; + }; // 计算前面板收起操作样式 const prevClass = computed(() => { - const { pane, nearPane } = queryPanes(props.index, props.index + 1) + const { pane, nearPane } = queryPanes(props.index, props.index + 1); // 第一个面板或者其它面板折叠方向不是向后的, 显示操作按钮 const showIcon = pane?.component?.props?.collapseDirection !== 'after' || - props.index === 0 - return generateCollapseClass(pane, nearPane, showIcon) - }) + props.index === 0; + return generateCollapseClass(pane, nearPane, showIcon); + }); // 计算相邻面板收起操作样式 const nextClass = computed(() => { - const { pane, nearPane } = queryPanes(props.index + 1, props.index) + const { pane, nearPane } = queryPanes(props.index + 1, props.index); // 最后一个面板或者其它面板折叠方向不是向前的显示操作按钮 const showIcon = pane?.component?.props?.collapseDirection !== 'before' || - props.index + 1 === store.state.paneCount - 1 - return generateCollapseClass(pane, nearPane, showIcon) - }) + props.index + 1 === store.state.paneCount - 1; + return generateCollapseClass(pane, nearPane, showIcon); + }); // 切换是否允许拖拽,收起时不能拖拽 const toggleResize = () => { - const { pane, nearPane } = queryPanes(props.index, props.index + 1) + const { pane, nearPane } = queryPanes(props.index, props.index + 1); const isCollapsed = pane?.component?.props?.collapsed || - nearPane?.component?.props?.collapsed + nearPane?.component?.props?.collapsed; if (isCollapsed) { - addClass(domRef.value, 'none-resizable') + addClass(domRef.value, 'none-resizable'); } else { - removeClass(domRef.value, 'none-resizable') + removeClass(domRef.value, 'none-resizable'); } - } + }; const handleCollapsePrePane = (lockStatus?: boolean) => { - store.tooglePane(props.index, props.index + 1, lockStatus) - toggleResize() - } + store.tooglePane(props.index, props.index + 1, lockStatus); + toggleResize(); + }; const handleCollapseNextPane = (lockStatus?: boolean) => { - store.tooglePane(props.index + 1, props.index, lockStatus) - toggleResize() - } + store.tooglePane(props.index + 1, props.index, lockStatus); + toggleResize(); + }; const initialCollapseStatus = () => { - handleCollapsePrePane(true) - handleCollapseNextPane(true) - } - + handleCollapsePrePane(true); + handleCollapseNextPane(true); + }; + onMounted(() => { - initialCollapseStatus() - }) - + initialCollapseStatus(); + }); + const renderCollapsedTip = () => { - const { pane, nearPane } = queryPanes(props.index, props.index + 1) + const { pane, nearPane } = queryPanes(props.index, props.index + 1); const isCollapsed = pane?.component?.props?.collapsed || - nearPane?.component?.props?.collapsed - return isCollapsed ? '展开' : '收起' - } + nearPane?.component?.props?.collapsed; + return isCollapsed ? '展开' : '收起'; + }; return () => { return withDirectives( @@ -178,7 +178,7 @@ export default defineComponent({ <div class={['prev', prevClass.value]} onClick={() => { - handleCollapsePrePane() + handleCollapsePrePane(); }} ></div> </DToolTip> @@ -194,7 +194,7 @@ export default defineComponent({ )} </div>, [[dresize, resizeProp]] - ) - } + ); + }; }, -}) +}); diff --git a/packages/devui-vue/devui/splitter/src/splitter-store.ts b/packages/devui-vue/devui/splitter/src/splitter-store.ts index 50787194b5..6d7ab9ffa9 100644 --- a/packages/devui-vue/devui/splitter/src/splitter-store.ts +++ b/packages/devui-vue/devui/splitter/src/splitter-store.ts @@ -1,66 +1,66 @@ -import SplitterPane from './splitter-pane' -import { reactive } from 'vue' +import SplitterPane from './splitter-pane'; +import { reactive } from 'vue'; export interface Pane { - getPaneSize: () => number + getPaneSize: () => number; } export interface PaneState { - index: number - initialSize: number - minSize: number - maxSize: number + index: number; + initialSize: number; + minSize: number; + maxSize: number; } export interface DragState { - prev: PaneState - next: PaneState + prev: PaneState; + next: PaneState; } -type SplitterPane = typeof SplitterPane & Pane +type SplitterPane = typeof SplitterPane & Pane; export interface splitterState { - panes: Array<SplitterPane> // 所有 pane 对象的一些关键信息 - paneCount: number - splitterContainerSize: number + panes: Array<SplitterPane>; // 所有 pane 对象的一些关键信息 + paneCount: number; + splitterContainerSize: number; } export class SplitterStore { - state: splitterState + state: splitterState; constructor() { this.state = reactive({ panes: [], splitterContainerSize: 0, paneCount: 0, - }) + }); } // 配置 pane 信息,panes 列表,方便后续计算使用 setPanes({ panes }): void { this.state.panes = panes.map((pane: SplitterPane, index: number) => { if (pane.component) { - pane.component.exposed.order.value = index * 2 + pane.component.exposed.order.value = index * 2; } - pane.getPaneSize = pane?.component?.exposed.getPaneSize - return pane - }) - this.state.paneCount = panes.length + pane.getPaneSize = pane?.component?.exposed.getPaneSize; + return pane; + }); + this.state.paneCount = panes.length; } - setSplitter({ containerSize }: { containerSize: number; }): void { - this.state.splitterContainerSize = containerSize + setSplitter({ containerSize }: { containerSize: number }): void { + this.state.splitterContainerSize = containerSize; } // 获取 pane,防止没有初始化的时候调用内部方法取值 getPane(index: number): SplitterPane { if (!this.state.panes || index < 0 || index >= this.state.panes.length) { - throw new Error('no pane can return.') + throw new Error('no pane can return.'); } - return this.state.panes[index] + return this.state.panes[index]; } // 按下的时候计算 pane 的 size 信息 dragState(splitbarIndex: number): DragState { - const prev = this.getPane(splitbarIndex) - const next = this.getPane(splitbarIndex + 1) - const total = prev.getPaneSize() + next.getPaneSize() + const prev = this.getPane(splitbarIndex); + const next = this.getPane(splitbarIndex + 1); + const total = prev.getPaneSize() + next.getPaneSize(); return { prev: { index: splitbarIndex, @@ -88,70 +88,70 @@ export class SplitterStore { total - this.toPixels(prev.component.props.minSize) || total, }, - } + }; } // 大小限制函数,(max)小于最小值时取最小值,(min)大于最大值时取最大值 clamp(minSize: number, maxSize: number, initialSize: number): number { - return Math.min(maxSize, Math.max(minSize, initialSize)) + return Math.min(maxSize, Math.max(minSize, initialSize)); } // resize pane的大小 resize(paneState: PaneState, moveSize: number): void { - const pane = this.getPane(paneState.index) - const splitterSize = this.state.splitterContainerSize + const pane = this.getPane(paneState.index); + const splitterSize = this.state.splitterContainerSize; const newSize = this.clamp( paneState.minSize, paneState.maxSize, paneState.initialSize + moveSize - ) - let size = '' + ); + let size = ''; if (this.isPercent(pane.component.props.size)) { - size = (newSize / splitterSize) * 100 + '%' + size = (newSize / splitterSize) * 100 + '%'; } else { - size = newSize + 'px' + size = newSize + 'px'; } - pane.component.props.size = size - pane.component.emit('sizeChange', size) + pane.component.props.size = size; + pane.component.emit('sizeChange', size); } // 判断 pane 是否可以调整大小,只要有一边设置了不可调整或者收起,相邻 pane 调整就失效 isResizable(splitBarIndex: number): boolean { - const prevPane = this.getPane(splitBarIndex) - const nextPane = this.getPane(splitBarIndex + 1) + const prevPane = this.getPane(splitBarIndex); + const nextPane = this.getPane(splitBarIndex + 1); const paneCollapsed = prevPane?.component?.props?.collapsed || - nextPane?.component?.props?.collapsed + nextPane?.component?.props?.collapsed; return ( prevPane?.component?.props?.resizable && nextPane?.component?.props?.resizable && !paneCollapsed - ) + ); } // 判断分割条是否是固定的,只要有一边不能调整, 就是禁用状态固定 bar isStaticBar(splitBarIndex: number): boolean { - const prevPane = this.getPane(splitBarIndex) - const nextPane = this.getPane(splitBarIndex + 1) + const prevPane = this.getPane(splitBarIndex); + const nextPane = this.getPane(splitBarIndex + 1); return !( prevPane?.component?.props?.resizable && nextPane?.component?.props?.resizable - ) + ); } // 判断是不是百分比设置宽度 isPercent(size: string) { - return /%$/.test(size) + return /%$/.test(size); } // 计算时把百分比转换为像素 toPixels(size: string): number { // 值不满足转换时,result 为 NaN,方便计算最小、最大宽度判断 - let result = parseFloat(size) + let result = parseFloat(size); if (this.isPercent(size)) { - result = (this.state.splitterContainerSize * result) / 100 + result = (this.state.splitterContainerSize * result) / 100; } - return result + return result; } // 切换 pane 展开,收起 @@ -160,36 +160,36 @@ export class SplitterStore { nearPaneIndex: number, lockStatus?: boolean ): void { - const pane = this.getPane(paneIndex) - const nearPane = this.getPane(nearPaneIndex) + const pane = this.getPane(paneIndex); + const nearPane = this.getPane(nearPaneIndex); if (pane?.component?.props?.collapsible) { pane.component.props.collapsed = lockStatus ? pane?.component?.props?.collapsed - : !pane?.component?.props?.collapsed + : !pane?.component?.props?.collapsed; nearPane?.component?.exposed?.toggleNearPaneFlexGrow( pane?.component?.props?.collapsed - ) + ); pane?.component?.emit( 'collapsedChange', pane?.component?.props?.collapsed - ) + ); } } // 设置 pane 大小 setSize(state: DragState, distance: number): void { - const prev = this.getPane(state.prev.index) - const next = this.getPane(state.next.index) + const prev = this.getPane(state.prev.index); + const next = this.getPane(state.next.index); if (prev.component.props.size && next.component.props.size) { // 相邻的两个 pane 都指定了 size,需要同时修改 size - this.resize(state.prev, distance) - this.resize(state.next, -distance) + this.resize(state.prev, distance); + this.resize(state.next, -distance); } else if (next.component.props.size) { // 只有 next pane指定了 size,直接修改 next pane - this.resize(state.next, -distance) + this.resize(state.next, -distance); } else { // 最后都没有指定 size,直接修改 pre pane - this.resize(state.prev, distance) + this.resize(state.prev, distance); } } } diff --git a/packages/devui-vue/devui/splitter/src/splitter-types.ts b/packages/devui-vue/devui/splitter/src/splitter-types.ts index 8bf2ec19af..b612be0669 100644 --- a/packages/devui-vue/devui/splitter/src/splitter-types.ts +++ b/packages/devui-vue/devui/splitter/src/splitter-types.ts @@ -1,6 +1,6 @@ -import type { PropType, ExtractPropTypes } from 'vue' -export type SplitterOrientation = 'vertical' | 'horizontal' -export type CollapseDirection = 'before' | 'after' | 'both' +import type { PropType, ExtractPropTypes } from 'vue'; +export type SplitterOrientation = 'vertical' | 'horizontal'; +export type CollapseDirection = 'before' | 'after' | 'both'; export const splitterProps = { /** @@ -31,6 +31,6 @@ export const splitterProps = { type: Boolean, default: true, }, -} as const +} as const; -export type SplitterProps = ExtractPropTypes<typeof splitterProps> +export type SplitterProps = ExtractPropTypes<typeof splitterProps>; diff --git a/packages/devui-vue/devui/splitter/src/splitter.tsx b/packages/devui-vue/devui/splitter/src/splitter.tsx index e49ebec1b4..a2b80c88f1 100644 --- a/packages/devui-vue/devui/splitter/src/splitter.tsx +++ b/packages/devui-vue/devui/splitter/src/splitter.tsx @@ -1,8 +1,8 @@ -import { defineComponent, reactive, ref, provide, onMounted, onUnmounted, watch } from 'vue' -import { splitterProps, SplitterProps } from './splitter-types' -import DSplitterBar from './splitter-bar' -import { SplitterStore } from './splitter-store' -import './splitter.scss' +import { defineComponent, reactive, ref, provide, onMounted, onUnmounted, watch } from 'vue'; +import { splitterProps, SplitterProps } from './splitter-types'; +import DSplitterBar from './splitter-bar'; +import { SplitterStore } from './splitter-store'; +import './splitter.scss'; export default defineComponent({ name: 'DSplitter', @@ -12,45 +12,45 @@ export default defineComponent({ props: splitterProps, emits: [], setup(props: SplitterProps, ctx) { - const store: SplitterStore = new SplitterStore() + const store: SplitterStore = new SplitterStore(); const state = reactive({ panes: [] // 内嵌面板 - }) + }); - state.panes = ctx.slots.DSplitterPane?.() || [] + state.panes = ctx.slots.DSplitterPane?.() || []; - store.setPanes({ panes: state.panes }) - provide('orientation', props.orientation) - provide('splitterStore', store) + store.setPanes({ panes: state.panes }); + provide('orientation', props.orientation); + provide('splitterStore', store); - const domRef = ref<HTMLElement>() + const domRef = ref<HTMLElement>(); const refreshSplitterContainerSize = () => { - if (!domRef.value) return - let containerSize = 0 + if (!domRef.value) {return;} + let containerSize = 0; if (props.orientation === 'vertical') { - containerSize = domRef.value.clientHeight + containerSize = domRef.value.clientHeight; } else { - containerSize = domRef.value.clientWidth + containerSize = domRef.value.clientWidth; } - store.setSplitter({ containerSize }) - } + store.setSplitter({ containerSize }); + }; - const observer = new ResizeObserver(refreshSplitterContainerSize) + const observer = new ResizeObserver(refreshSplitterContainerSize); watch(domRef, (ele) => { if (!ele) { - return + return; } - refreshSplitterContainerSize() - observer.observe(domRef.value) - }) + refreshSplitterContainerSize(); + observer.observe(domRef.value); + }); onUnmounted(() => { - observer.disconnect() - }) + observer.disconnect(); + }); return () => { - const { splitBarSize, orientation, showCollapseButton } = props - const wrapperClass = ['devui-splitter', `devui-splitter-${orientation}`] + const { splitBarSize, orientation, showCollapseButton } = props; + const wrapperClass = ['devui-splitter', `devui-splitter-${orientation}`]; return ( <div class={wrapperClass} ref={domRef}> @@ -67,10 +67,10 @@ export default defineComponent({ index={index} showCollapseButton={showCollapseButton} ></d-splitter-bar> - ) + ); })} </div> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/splitter/src/util/d-resize-directive.ts b/packages/devui-vue/devui/splitter/src/util/d-resize-directive.ts index 69dfda5aca..4f18deff64 100644 --- a/packages/devui-vue/devui/splitter/src/util/d-resize-directive.ts +++ b/packages/devui-vue/devui/splitter/src/util/d-resize-directive.ts @@ -1,70 +1,68 @@ -import type { Directive, DirectiveBinding } from 'vue' -export interface OnResizeEvent { - (coordinateInfo: CoordinateInfo): void -} +import type { Directive, DirectiveBinding } from 'vue'; +export type OnResizeEvent = (coordinateInfo: CoordinateInfo) => void; export interface ResizeDirectiveProp { - enableResize: true // 是否允许拖动 - onPressEvent: OnResizeEvent - onDragEvent: OnResizeEvent - onReleaseEvent: OnResizeEvent + enableResize: true; // 是否允许拖动 + onPressEvent: OnResizeEvent; + onDragEvent: OnResizeEvent; + onReleaseEvent: OnResizeEvent; } export interface CoordinateInfo { - pageX: number - pageY: number - clientX: number - clientY: number - offsetX: number - offsetY: number - type: string - originalEvent: MouseEvent + pageX: number; + pageY: number; + clientX: number; + clientY: number; + offsetX: number; + offsetY: number; + type: string; + originalEvent: MouseEvent; } const resize: Directive = { mounted(el, { value }: DirectiveBinding<ResizeDirectiveProp>) { - el.$value = value + el.$value = value; // 是否允许拖动 if (value.enableResize) { - bindEvent(el) + bindEvent(el); } }, unmounted(el, { value }: DirectiveBinding<ResizeDirectiveProp>) { if (value.enableResize) { - unbind(el, 'mousedown', onMousedown) + unbind(el, 'mousedown', onMousedown); } }, -} +}; function bindEvent(el) { // 绑定 mousedown 事件 - bind(el, 'mousedown', onMousedown) + bind(el, 'mousedown', onMousedown); // TODO 绑定触屏事件 } function bind(el, event, callback) { - el.addEventListener && el.addEventListener(event, callback) + el.addEventListener && el.addEventListener(event, callback); } function unbind(el, event, callback) { - el.removeEventListener && el.removeEventListener(event, callback) + el.removeEventListener && el.removeEventListener(event, callback); } function onMousedown(e) { - const $value = e?.target?.$value - if (!$value) return // 提前退出,避免 splitter-bar 子元素响应导致错误 + const $value = e?.target?.$value; + if (!$value) {return;} // 提前退出,避免 splitter-bar 子元素响应导致错误 - bind(document, 'mousemove', onMousemove) - bind(document, 'mouseup', onMouseup) - $value.onPressEvent(normalizeEvent(e)) + bind(document, 'mousemove', onMousemove); + bind(document, 'mouseup', onMouseup); + $value.onPressEvent(normalizeEvent(e)); function onMousemove(e) { - $value.onDragEvent(normalizeEvent(e)) + $value.onDragEvent(normalizeEvent(e)); } function onMouseup(e) { - unbind(document, 'mousemove', onMousemove) - unbind(document, 'mouseup', onMouseup) - $value.onReleaseEvent(normalizeEvent(e)) + unbind(document, 'mousemove', onMousemove); + unbind(document, 'mouseup', onMouseup); + $value.onReleaseEvent(normalizeEvent(e)); } } @@ -79,7 +77,7 @@ function normalizeEvent(e) { offsetY: e.offsetY, type: e.type, originalEvent: e, - } + }; } -export default resize +export default resize; diff --git a/packages/devui-vue/devui/statistic/__tests__/statistic.spec.ts b/packages/devui-vue/devui/statistic/__tests__/statistic.spec.ts index fb9c9e8903..2be17ca8a7 100644 --- a/packages/devui-vue/devui/statistic/__tests__/statistic.spec.ts +++ b/packages/devui-vue/devui/statistic/__tests__/statistic.spec.ts @@ -1,8 +1,8 @@ -import { mount } from '@vue/test-utils' -import { Statistic } from '../index' +import { mount } from '@vue/test-utils'; +import { Statistic } from '../index'; describe('statistic test', () => { it('statistic init render', async () => { // todo - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/statistic/index.ts b/packages/devui-vue/devui/statistic/index.ts index 711001409c..3af3272295 100644 --- a/packages/devui-vue/devui/statistic/index.ts +++ b/packages/devui-vue/devui/statistic/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Statistic from './src/statistic' +import type { App } from 'vue'; +import Statistic from './src/statistic'; Statistic.install = function(app: App): void { - app.component(Statistic.name, Statistic) -} + app.component(Statistic.name, Statistic); +}; -export { Statistic } +export { Statistic }; export default { title: 'Statistic 统计数值', category: '数据展示', status: '100%', // TODO: 组件若开发完成则填入"已完成",并删除该注释 install(app: App): void { - app.use(Statistic as any) + app.use(Statistic as any); } -} +}; diff --git a/packages/devui-vue/devui/statistic/src/statistic-types.ts b/packages/devui-vue/devui/statistic/src/statistic-types.ts index d183ec80ca..af2059aca0 100644 --- a/packages/devui-vue/devui/statistic/src/statistic-types.ts +++ b/packages/devui-vue/devui/statistic/src/statistic-types.ts @@ -1,4 +1,4 @@ -import type { PropType, ExtractPropTypes, CSSProperties } from 'vue' +import type { PropType, ExtractPropTypes, CSSProperties } from 'vue'; // import type { easingType } from './utils/animation' export const statisticProps = { title: { @@ -43,6 +43,6 @@ export const statisticProps = { type: String, default: '' } -} as const +} as const; -export type StatisticProps = ExtractPropTypes<typeof statisticProps> +export type StatisticProps = ExtractPropTypes<typeof statisticProps>; diff --git a/packages/devui-vue/devui/statistic/src/statistic.tsx b/packages/devui-vue/devui/statistic/src/statistic.tsx index 25f36c499a..afc73ea316 100644 --- a/packages/devui-vue/devui/statistic/src/statistic.tsx +++ b/packages/devui-vue/devui/statistic/src/statistic.tsx @@ -1,16 +1,16 @@ -import { defineComponent, computed, ref, onMounted, watch } from 'vue' -import { statisticProps, StatisticProps } from './statistic-types' -import { analysisValueType } from './utils/separator' -import { Tween } from './utils/animation' -import './statistic.scss' +import { defineComponent, computed, ref, onMounted, watch } from 'vue'; +import { statisticProps, StatisticProps } from './statistic-types'; +import { analysisValueType } from './utils/separator'; +import { Tween } from './utils/animation'; +import './statistic.scss'; export default defineComponent({ name: 'DStatistic', inheritAttrs: false, props: statisticProps, setup(props: StatisticProps, ctx) { - const innerValue = ref(props.valueFrom ?? props.value) - const tween = ref(null) + const innerValue = ref(props.valueFrom ?? props.value); + const tween = ref(null); const animation = ( from: number = props.valueFrom ?? 0, @@ -28,37 +28,37 @@ export default defineComponent({ duration: props.animationDuration, easing: 'easeOutCubic', onUpdate: (keys: any) => { - innerValue.value = keys.value + innerValue.value = keys.value; }, onFinish: () => { - innerValue.value = to + innerValue.value = to; } - }) - tween.value.start() + }); + tween.value.start(); } - } + }; const statisticValue = computed(() => { return analysisValueType( innerValue.value, props.value, props.groupSeparator, props.precision - ) - }) + ); + }); onMounted(() => { if (props.animation && props.start) { - animation() + animation(); } - }) + }); // 我们可以手动控制animation watch( () => props.start, (value) => { if (value && !tween.value) { - animation() + animation(); } } - ) + ); return () => { return ( <div class='devui-statistic' {...ctx.attrs}> @@ -78,7 +78,7 @@ export default defineComponent({ <div class='devui-statistic-extra'> {ctx.slots.extra?.() || props.extra}</div> ) : null} </div> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/statistic/src/utils/animation.ts b/packages/devui-vue/devui/statistic/src/utils/animation.ts index 9ab7230108..54ebf717b1 100644 --- a/packages/devui-vue/devui/statistic/src/utils/animation.ts +++ b/packages/devui-vue/devui/statistic/src/utils/animation.ts @@ -1,128 +1,122 @@ -import * as easing from './easing' +import * as easing from './easing'; -export type easingType = 'easeOutCubic' | 'linear' | 'easeOutExpo' | 'easeInOutExpo' -export interface startFunc { - (key: number): number -} -export interface updateFunc { - (key: any): any -} -export interface finishFunc { - (key: any): any -} +export type easingType = 'easeOutCubic' | 'linear' | 'easeOutExpo' | 'easeInOutExpo'; +export type startFunc = (key: number) => number; +export type updateFunc = (key: any) => any; +export type finishFunc = (key: any) => any; export interface fromType { - value: number + value: number; } export interface toType { - value: number + value: number; } export interface AnimationOptions { - from: fromType - to: toType - duration?: number - delay?: number - easing?: easingType - onStart?: startFunc - onUpdate?: updateFunc - onFinish?: finishFunc + from: fromType; + to: toType; + duration?: number; + delay?: number; + easing?: easingType; + onStart?: startFunc; + onUpdate?: updateFunc; + onFinish?: finishFunc; } export class Tween { - from: fromType - to: toType - duration?: number - delay?: number - easing?: easingType - onStart?: startFunc - onUpdate?: updateFunc - onFinish?: finishFunc - startTime?: number - started?: boolean - finished?: boolean - timer?: null | number - time?: number - elapsed?: number - keys?: any + from: fromType; + to: toType; + duration?: number; + delay?: number; + easing?: easingType; + onStart?: startFunc; + onUpdate?: updateFunc; + onFinish?: finishFunc; + startTime?: number; + started?: boolean; + finished?: boolean; + timer?: null | number; + time?: number; + elapsed?: number; + keys?: any; constructor(options: AnimationOptions) { - const { from, to, duration, delay, easing, onStart, onUpdate, onFinish } = options + const { from, to, duration, delay, easing, onStart, onUpdate, onFinish } = options; for (const key in from) { if (to[key] === undefined) { - to[key] = from[key] + to[key] = from[key]; } } for (const key in to) { if (from[key] === undefined) { - from[key] = to[key] + from[key] = to[key]; } } - this.from = from - this.to = to - this.duration = duration - this.delay = delay - this.easing = easing - this.onStart = onStart - this.onUpdate = onUpdate - this.onFinish = onFinish - this.startTime = Date.now() + this.delay - this.started = false - this.finished = false - this.timer = null - this.keys = {} + this.from = from; + this.to = to; + this.duration = duration; + this.delay = delay; + this.easing = easing; + this.onStart = onStart; + this.onUpdate = onUpdate; + this.onFinish = onFinish; + this.startTime = Date.now() + this.delay; + this.started = false; + this.finished = false; + this.timer = null; + this.keys = {}; } update(): void { - this.time = Date.now() + this.time = Date.now(); // delay some time if (this.time < this.startTime) { - return + return; } if (this.finished) { - return + return; } // finish animation if (this.elapsed === this.duration) { if (!this.finished) { - this.finished = true - this.onFinish && this.onFinish(this.keys) + this.finished = true; + this.onFinish && this.onFinish(this.keys); } - return + return; } // elapsed 时间 和 duration 时间比较 逝去光阴 - this.elapsed = this.time - this.startTime + this.elapsed = this.time - this.startTime; // 防止 时间 一直 流逝 ~ - this.elapsed = this.elapsed > this.duration ? this.duration : this.elapsed + this.elapsed = this.elapsed > this.duration ? this.duration : this.elapsed; // 从0 到 1 elapsed time for (const key in this.to) { this.keys[key] = this.from[key] + - (this.to[key] - this.from[key]) * easing[this.easing](this.elapsed / this.duration) + (this.to[key] - this.from[key]) * easing[this.easing](this.elapsed / this.duration); } if (!this.started) { - this.onStart && this.onStart(this.keys) - this.started = true + this.onStart && this.onStart(this.keys); + this.started = true; } - this.onUpdate(this.keys) + this.onUpdate(this.keys); } // 递归 重绘 start(): void { - this.startTime = Date.now() + this.delay + this.startTime = Date.now() + this.delay; const tick = () => { - this.update() - this.timer = requestAnimationFrame(tick) + this.update(); + this.timer = requestAnimationFrame(tick); if (this.finished) { // 在判断 update中 结束后 停止 重绘 - cancelAnimationFrame(this.timer) - this.timer = null + cancelAnimationFrame(this.timer); + this.timer = null; } - } - tick() + }; + tick(); } stop(): void { - cancelAnimationFrame(this.timer) - this.timer = null + cancelAnimationFrame(this.timer); + this.timer = null; } } diff --git a/packages/devui-vue/devui/statistic/src/utils/easing.ts b/packages/devui-vue/devui/statistic/src/utils/easing.ts index 4b0fb02fdc..242ab4b70d 100644 --- a/packages/devui-vue/devui/statistic/src/utils/easing.ts +++ b/packages/devui-vue/devui/statistic/src/utils/easing.ts @@ -1,27 +1,27 @@ // pow 返回 基数的指数次幂 t ** power -const pow = Math.pow -const sqrt = Math.sqrt +const pow = Math.pow; +const sqrt = Math.sqrt; export const easeOutCubic = function (x: number): number { - return 1 - pow(1 - x, 3) -} -export const linear = (x: number): number => x + return 1 - pow(1 - x, 3); +}; +export const linear = (x: number): number => x; export const easeOutExpo = function (x: number): number { - return x === 1 ? 1 : 1 - pow(2, -10 * x) -} + return x === 1 ? 1 : 1 - pow(2, -10 * x); +}; export const easeInOutExpo = function (x: number): number { return x === 0 ? 0 : x === 1 - ? 1 - : x < 0.5 - ? pow(2, 20 * x - 10) / 2 - : (2 - pow(2, -20 * x + 10)) / 2 -} + ? 1 + : x < 0.5 + ? pow(2, 20 * x - 10) / 2 + : (2 - pow(2, -20 * x + 10)) / 2; +}; export const easeInExpo = function (x: number): number { - return x === 0 ? 0 : pow(2, 10 * x - 10) -} + return x === 0 ? 0 : pow(2, 10 * x - 10); +}; export const easeInOutCirc = function (x: number): number { - return x < 0.5 ? (1 - sqrt(1 - pow(2 * x, 2))) / 2 : (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2 -} + return x < 0.5 ? (1 - sqrt(1 - pow(2 * x, 2))) / 2 : (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2; +}; diff --git a/packages/devui-vue/devui/statistic/src/utils/separator.ts b/packages/devui-vue/devui/statistic/src/utils/separator.ts index 17143eda8a..bd55400a26 100644 --- a/packages/devui-vue/devui/statistic/src/utils/separator.ts +++ b/packages/devui-vue/devui/statistic/src/utils/separator.ts @@ -1,4 +1,4 @@ -export type valueType = string | number +export type valueType = string | number; export const separator = ( SeparatorString: string, // value @@ -7,17 +7,17 @@ export const separator = ( const res = SeparatorString.replace(/\d+/, function (n) { // 先提取整数部分 return n.replace(/(\d)(?=(\d{3})+$)/g, function ($1) { - return $1 + `${groupSeparator}` - }) - }) - return res -} + return $1 + `${groupSeparator}`; + }); + }); + return res; +}; export const isHasDot = (value: number): boolean => { if (!isNaN(value)) { - return (value + '').indexOf('.') !== -1 + return (value + '').indexOf('.') !== -1; } -} +}; export const analysisValueType = ( value: valueType, // 动态value 值 propsValue: valueType, // 用户传入value @@ -27,18 +27,18 @@ export const analysisValueType = ( const fixedNumber = propsValue.toString().indexOf('.') !== -1 ? propsValue.toString().length - propsValue.toString().indexOf('.') - 1 - : 0 + : 0; if (typeof value === 'number') { if (isHasDot(value)) { return splitPrecisionNumber ? separator(value.toFixed(splitPrecisionNumber).toString(), groupSeparator) - : separator(value.toFixed(fixedNumber).toString(), groupSeparator) + : separator(value.toFixed(fixedNumber).toString(), groupSeparator); } else { return splitPrecisionNumber ? separator(value.toFixed(splitPrecisionNumber).toString(), groupSeparator) - : separator(value.toString(), groupSeparator) + : separator(value.toString(), groupSeparator); } } else { - return value + return value; } -} +}; diff --git a/packages/devui-vue/devui/status/__tests__/status.spec.ts b/packages/devui-vue/devui/status/__tests__/status.spec.ts index 28f1887806..1b341de29f 100644 --- a/packages/devui-vue/devui/status/__tests__/status.spec.ts +++ b/packages/devui-vue/devui/status/__tests__/status.spec.ts @@ -6,7 +6,7 @@ describe('d-status', () => { const wrapper = mount(Status, { props: { type: 'success' } }); - + expect(wrapper.classes()).toContain('devui-status-bg-success'); await wrapper.setProps({type: ''}); @@ -20,9 +20,9 @@ describe('d-status', () => { await wrapper.setProps({type: undefined}); expect(wrapper.classes()).toContain('devui-status-bg-invalid'); - + await wrapper.setProps({ type: 'error' }); - + expect(wrapper.classes()).toContain('devui-status-bg-error'); await wrapper.setProps({ type: 'warning' }); @@ -30,7 +30,7 @@ describe('d-status', () => { expect(wrapper.classes()).toContain('devui-status-bg-warning'); await wrapper.setProps({type: 'initial'}); - + expect(wrapper.classes()).toContain('devui-status-bg-initial'); await wrapper.setProps({type: 'waiting'}); @@ -42,10 +42,10 @@ describe('d-status', () => { expect(wrapper.classes()).toContain('devui-status-bg-running'); await wrapper.setProps({type: 'invalid'}); - + expect(wrapper.classes()).toContain('devui-status-bg-invalid'); - + }); it('slot', () => { diff --git a/packages/devui-vue/devui/status/index.ts b/packages/devui-vue/devui/status/index.ts index 43bcf996ce..847e4b77ed 100644 --- a/packages/devui-vue/devui/status/index.ts +++ b/packages/devui-vue/devui/status/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Status from './src/status' +import type { App } from 'vue'; +import Status from './src/status'; Status.install = function(app: App) { - app.component(Status.name, Status) -} + app.component(Status.name, Status); +}; -export { Status } +export { Status }; export default { title: 'Status 状态', category: '通用', status: '100%', install(app: App): void { - app.use(Status as any) + app.use(Status as any); } -} +}; diff --git a/packages/devui-vue/devui/status/src/status.tsx b/packages/devui-vue/devui/status/src/status.tsx index 45dead7f03..ee9929a313 100644 --- a/packages/devui-vue/devui/status/src/status.tsx +++ b/packages/devui-vue/devui/status/src/status.tsx @@ -23,8 +23,8 @@ export default defineComponent({ }); return () => { return <span class={typeClass.value}> - {ctx.slots.default?.()} - </span> - } + {ctx.slots.default?.()} + </span>; + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/steps-guide/__tests__/steps-guide-demo.tsx b/packages/devui-vue/devui/steps-guide/__tests__/steps-guide-demo.tsx index 29c4caf23e..1e530eaab1 100644 --- a/packages/devui-vue/devui/steps-guide/__tests__/steps-guide-demo.tsx +++ b/packages/devui-vue/devui/steps-guide/__tests__/steps-guide-demo.tsx @@ -1,5 +1,5 @@ -import { ref, defineComponent, reactive } from 'vue' -import DStepsGuide from '../src/steps-guide' +import { ref, defineComponent, reactive } from 'vue'; +import DStepsGuide from '../src/steps-guide'; export default defineComponent({ name: 'StepsGuideDemo', components: { @@ -7,53 +7,53 @@ export default defineComponent({ }, setup() { const steps = reactive([{ title: '弹出位置 top-left', - content: 'Steps Guide', - trigger: '.top-left', - position: 'top-left' - },{ title: '弹出位置 top', - content: 'Steps Guide', - trigger: '.top', - position: 'top' - },{ title: '弹出位置 top-right', content: 'Steps Guide', - trigger: '.top-right', + trigger: '.top-left', + position: 'top-left' + },{ title: '弹出位置 top', + content: 'Steps Guide', + trigger: '.top', + position: 'top' + },{ title: '弹出位置 top-right', + content: 'Steps Guide', + trigger: '.top-right', position: 'top-right' }, { title: '弹出位置 right', - content: 'Steps Guide', - trigger: '.right', - position: 'right' - },{ title: '弹出位置 bottom-right', - content: 'Steps Guide', - trigger: '.bottom-right', - position: 'bottom-right' - },{ title: '弹出位置 bottom', - content: 'Steps Guide', - trigger: '.bottom', - position: 'bottom' - },{ title: '弹出位置 bottom-left', - content: 'Steps Guide', - trigger: '.bottom-left', - position: 'bottom-left' - },{ title: '弹出位置 left', - content: 'Steps Guide', - trigger: '.left', - position: 'left' - }]) - const stepRef = ref(null), stepIndex = ref(0) + content: 'Steps Guide', + trigger: '.right', + position: 'right' + },{ title: '弹出位置 bottom-right', + content: 'Steps Guide', + trigger: '.bottom-right', + position: 'bottom-right' + },{ title: '弹出位置 bottom', + content: 'Steps Guide', + trigger: '.bottom', + position: 'bottom' + },{ title: '弹出位置 bottom-left', + content: 'Steps Guide', + trigger: '.bottom-left', + position: 'bottom-left' + },{ title: '弹出位置 left', + content: 'Steps Guide', + trigger: '.left', + position: 'left' + }]); + const stepRef = ref(null), stepIndex = ref(0); const handleClick = (index) => { - stepRef.value.setCurrentIndex(index) - } + stepRef.value.setCurrentIndex(index); + }; const handleClose = () => { - stepRef.value.closeGuide() - } + stepRef.value.closeGuide(); + }; return { steps, stepRef, stepIndex, handleClick, handleClose - } + }; }, render(props){ return (<> @@ -66,6 +66,6 @@ export default defineComponent({ <button class="bottom-left" onClick={ () => props.handleClick(6) }>Bottom-left</button> <button class="left" onClick={ () => props.handleClick(7) }>Left</button> <button class="close" onClick={ props.handleClose }>Close</button> - <d-steps-guide ref="stepRef" steps={ props.steps } v-model:step-index={ props.stepIndex }></d-steps-guide></>) + <d-steps-guide ref="stepRef" steps={ props.steps } v-model:step-index={ props.stepIndex }></d-steps-guide></>); } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/steps-guide/__tests__/steps-guide.spec.ts b/packages/devui-vue/devui/steps-guide/__tests__/steps-guide.spec.ts index 86fb4534ed..9e643e6a82 100644 --- a/packages/devui-vue/devui/steps-guide/__tests__/steps-guide.spec.ts +++ b/packages/devui-vue/devui/steps-guide/__tests__/steps-guide.spec.ts @@ -8,46 +8,46 @@ document.body.innerHTML = ` <button class="bottom-right">Bottom-right</button> <button class="bottom">Bottom</button> <button class="bottom-left">Bottom-left</button> - <button class="left">Left</button>` - + <button class="left">Left</button>`; + describe('d-steps-guide', () => { it('test steps change', async () => { - const wrapper = mount(StepsGuideDemo) - - await wrapper.get('.top').trigger('click') - expect(wrapper.vm.stepIndex).toBe(1) - expect(document.querySelector('.devui-steps-guide').className).toContain('top') - - await wrapper.get('.right').trigger('click') - expect(wrapper.vm.stepIndex).toBe(3) - expect(document.querySelector('.devui-steps-guide').className).toContain('right') - - await wrapper.get('.bottom').trigger('click') - expect(wrapper.vm.stepIndex).toBe(5) - expect(document.querySelector('.devui-steps-guide').className).toContain('bottom') - - await wrapper.get('.left').trigger('click') - expect(wrapper.vm.stepIndex).toBe(7) - expect(document.querySelector('.devui-steps-guide').className).toContain('left') - - await wrapper.get('.top-left').trigger('click') - expect(wrapper.vm.stepIndex).toBe(0) - expect(document.querySelector('.devui-steps-guide').className).toContain('top-left') - - await wrapper.get('.top-right').trigger('click') - expect(wrapper.vm.stepIndex).toBe(2) - expect(document.querySelector('.devui-steps-guide').className).toContain('top-right') - - await wrapper.get('.bottom-right').trigger('click') - expect(wrapper.vm.stepIndex).toBe(4) - expect(document.querySelector('.devui-steps-guide').className).toContain('bottom-right') - - await wrapper.get('.bottom-left').trigger('click') - expect(wrapper.vm.stepIndex).toBe(6) - expect(document.querySelector('.devui-steps-guide').className).toContain('bottom-left') - - await wrapper.get('.close').trigger('click') - expect(wrapper.vm.stepIndex).toBe(-1) - expect(document.querySelector('.devui-steps-guide')).toBe(null) + const wrapper = mount(StepsGuideDemo); + + await wrapper.get('.top').trigger('click'); + expect(wrapper.vm.stepIndex).toBe(1); + expect(document.querySelector('.devui-steps-guide').className).toContain('top'); + + await wrapper.get('.right').trigger('click'); + expect(wrapper.vm.stepIndex).toBe(3); + expect(document.querySelector('.devui-steps-guide').className).toContain('right'); + + await wrapper.get('.bottom').trigger('click'); + expect(wrapper.vm.stepIndex).toBe(5); + expect(document.querySelector('.devui-steps-guide').className).toContain('bottom'); + + await wrapper.get('.left').trigger('click'); + expect(wrapper.vm.stepIndex).toBe(7); + expect(document.querySelector('.devui-steps-guide').className).toContain('left'); + + await wrapper.get('.top-left').trigger('click'); + expect(wrapper.vm.stepIndex).toBe(0); + expect(document.querySelector('.devui-steps-guide').className).toContain('top-left'); + + await wrapper.get('.top-right').trigger('click'); + expect(wrapper.vm.stepIndex).toBe(2); + expect(document.querySelector('.devui-steps-guide').className).toContain('top-right'); + + await wrapper.get('.bottom-right').trigger('click'); + expect(wrapper.vm.stepIndex).toBe(4); + expect(document.querySelector('.devui-steps-guide').className).toContain('bottom-right'); + + await wrapper.get('.bottom-left').trigger('click'); + expect(wrapper.vm.stepIndex).toBe(6); + expect(document.querySelector('.devui-steps-guide').className).toContain('bottom-left'); + + await wrapper.get('.close').trigger('click'); + expect(wrapper.vm.stepIndex).toBe(-1); + expect(document.querySelector('.devui-steps-guide')).toBe(null); }); }); diff --git a/packages/devui-vue/devui/steps-guide/directive/steps-guide.ts b/packages/devui-vue/devui/steps-guide/directive/steps-guide.ts index cc2088fc41..685765bce8 100644 --- a/packages/devui-vue/devui/steps-guide/directive/steps-guide.ts +++ b/packages/devui-vue/devui/steps-guide/directive/steps-guide.ts @@ -1,7 +1,6 @@ export default { - mounted(el: HTMLElement, binding, vNode) { - }, - updated(el: HTMLElement, binding) { - } + mounted(el: HTMLElement, binding, vNode) { + }, + updated(el: HTMLElement, binding) { } - \ No newline at end of file +}; diff --git a/packages/devui-vue/devui/steps-guide/hooks/index.ts b/packages/devui-vue/devui/steps-guide/hooks/index.ts index 2cc49d128a..3b8adcd839 100644 --- a/packages/devui-vue/devui/steps-guide/hooks/index.ts +++ b/packages/devui-vue/devui/steps-guide/hooks/index.ts @@ -1,2 +1,2 @@ -export * from './use-steps-guide-position' -export * from './use-steps-guide-ctrl' \ No newline at end of file +export * from './use-steps-guide-position'; +export * from './use-steps-guide-ctrl'; diff --git a/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-ctrl.ts b/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-ctrl.ts index c35b6ce8f2..f9b6621aff 100644 --- a/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-ctrl.ts +++ b/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-ctrl.ts @@ -1,38 +1,38 @@ -import { ref, nextTick, computed, WritableComputedRef, SetupContext } from 'vue' -import { StepsGuideProps, Step } from '../src/steps-guide-types' +import { ref, nextTick, computed, WritableComputedRef, SetupContext } from 'vue'; +import { StepsGuideProps, Step } from '../src/steps-guide-types'; export function useStepsGuideCtrl( - props: StepsGuideProps, - ctx: SetupContext<('guide-close'|'update:stepIndex')[]>, - updateGuidePosition: Function, - stepIndex: WritableComputedRef<number> - ) { - const stepsCount = computed<number>(() => props.steps.length) - + props: StepsGuideProps, + ctx: SetupContext<('guide-close'|'update:stepIndex')[]>, + updateGuidePosition: Function, + stepIndex: WritableComputedRef<number> +) { + const stepsCount = computed<number>(() => props.steps.length); + const closeGuide = () => { // 缓存关闭前的index, 并在关闭后触发事件 - const _index = stepIndex.value - stepIndex.value = -1 + const _index = stepIndex.value; + stepIndex.value = -1; nextTick(() => { - ctx.emit('guide-close', _index) - }) - } - const setCurrentIndex = (index:number):void => { + ctx.emit('guide-close', _index); + }); + }; + const setCurrentIndex = (index: number): void => { if(index !== -1 && props.stepChange()){ if(index > -1 && index < stepsCount.value) { - stepIndex.value = index + stepIndex.value = index; nextTick(() => { - updateGuidePosition() - }) + updateGuidePosition(); + }); } else { - console.error(`stepIndex is not within the value range`) + console.error(`stepIndex is not within the value range`); } } - if(index === -1) closeGuide() - } + if(index === -1) {closeGuide();} + }; return { stepsCount, closeGuide, setCurrentIndex - } -} \ No newline at end of file + }; +} diff --git a/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-position.ts b/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-position.ts index 01eeea5d25..7270aa6a74 100644 --- a/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-position.ts +++ b/packages/devui-vue/devui/steps-guide/hooks/use-steps-guide-position.ts @@ -1,81 +1,81 @@ -import { ref, reactive, ComputedRef, nextTick } from 'vue' -import { Step, positionConf, StepsGuideProps } from '../src/steps-guide-types' +import { ref, reactive, ComputedRef, nextTick } from 'vue'; +import { Step, positionConf, StepsGuideProps } from '../src/steps-guide-types'; export function useStepsGuidePosition( - props: StepsGuideProps, + props: StepsGuideProps, currentStep: ComputedRef<Step>) { - const guideClassList = reactive(['devui-steps-guide']) - const stepsRef = ref(null) + const guideClassList = reactive(['devui-steps-guide']); + const stepsRef = ref(null); const guidePosition = reactive({ left: '', top: '', zIndex: props.zIndex - }) - + }); + const updateGuidePosition = () => { - if(!currentStep.value || !stepsRef.value) return; - const baseTop = window.pageYOffset - document.documentElement.clientTop - const baseLeft = window.pageXOffset - document.documentElement.clientLeft - const currentStepPosition:positionConf = currentStep.value.position - const stepGuideElement = stepsRef.value - let _left, _top + if(!currentStep.value || !stepsRef.value) {return;} + const baseTop = window.pageYOffset - document.documentElement.clientTop; + const baseLeft = window.pageXOffset - document.documentElement.clientLeft; + const currentStepPosition: positionConf = currentStep.value.position; + const stepGuideElement = stepsRef.value; + let _left, _top; // 自定义 position位置 if (typeof currentStepPosition !== 'string') { - const { top = 0, left = 0, type = 'top' } = currentStepPosition - guideClassList.splice(1, 1, type) - _left = left - _top = top + const { top = 0, left = 0, type = 'top' } = currentStepPosition; + guideClassList.splice(1, 1, type); + _left = left; + _top = top; } else { - guideClassList.splice(1, 1, currentStepPosition) - const triggerSelector = currentStep.value.target || currentStep.value.trigger - const triggerElement = document.querySelector(triggerSelector) + guideClassList.splice(1, 1, currentStepPosition); + const triggerSelector = currentStep.value.target || currentStep.value.trigger; + const triggerElement = document.querySelector(triggerSelector); if(!triggerElement) { - console.warn(`${triggerSelector} 不存在!`) - return false + console.warn(`${triggerSelector} 不存在!`); + return false; } - const targetRect = triggerElement.getBoundingClientRect() - _left = targetRect.left + triggerElement.clientWidth / 2 - stepGuideElement.clientWidth / 2 + baseLeft - _top = targetRect.top + triggerElement.clientHeight / 2 - stepGuideElement.clientHeight / 2 + baseTop - - const positionTypes = currentStepPosition.split('-') + const targetRect = triggerElement.getBoundingClientRect(); + _left = targetRect.left + triggerElement.clientWidth / 2 - stepGuideElement.clientWidth / 2 + baseLeft; + _top = targetRect.top + triggerElement.clientHeight / 2 - stepGuideElement.clientHeight / 2 + baseTop; + + const positionTypes = currentStepPosition.split('-'); switch (positionTypes[0]) { - case 'top': - _top += (-stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) - break - case 'bottom': - _top += (stepGuideElement.clientHeight / 2 + triggerElement.clientHeight) - break - case 'left': - _top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) - _left += (-stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2) - break - case 'right': - _top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight) - _left += (stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2) - break + case 'top': + _top += (-stepGuideElement.clientHeight / 2 - triggerElement.clientHeight); + break; + case 'bottom': + _top += (stepGuideElement.clientHeight / 2 + triggerElement.clientHeight); + break; + case 'left': + _top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight); + _left += (-stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2); + break; + case 'right': + _top += (stepGuideElement.clientHeight / 2 - triggerElement.clientHeight); + _left += (stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2); + break; } switch (positionTypes[1]) { - case 'left': - _left += (stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2) - break - case 'right': - _left += (-stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2) - break + case 'left': + _left += (stepGuideElement.clientWidth / 2 - triggerElement.clientWidth / 2); + break; + case 'right': + _left += (-stepGuideElement.clientWidth / 2 + triggerElement.clientWidth / 2); + break; } } - guidePosition.left = _left + 'px' - guidePosition.top = _top + 'px' + guidePosition.left = _left + 'px'; + guidePosition.top = _top + 'px'; if(props.scrollToTargetSwitch && typeof stepGuideElement.scrollIntoView === 'function') { nextTick(() => { // 位置更新后滚动视图 - stepGuideElement.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'nearest'}) - }) + stepGuideElement.scrollIntoView({behavior: 'smooth', block: 'nearest', inline: 'nearest'}); + }); } - } + }; return { stepsRef, guidePosition, guideClassList, updateGuidePosition - } -} \ No newline at end of file + }; +} diff --git a/packages/devui-vue/devui/steps-guide/index.ts b/packages/devui-vue/devui/steps-guide/index.ts index f783ba87f3..9b2bde3dab 100644 --- a/packages/devui-vue/devui/steps-guide/index.ts +++ b/packages/devui-vue/devui/steps-guide/index.ts @@ -1,19 +1,19 @@ -import type { App } from 'vue' -import StepsGuide from './src/steps-guide' +import type { App } from 'vue'; +import StepsGuide from './src/steps-guide'; -import StepsGuideDirective from './directive/steps-guide' +import StepsGuideDirective from './directive/steps-guide'; StepsGuide.install = function(app: App): void { - app.component(StepsGuide.name, StepsGuide) -} + app.component(StepsGuide.name, StepsGuide); +}; -export { StepsGuide } +export { StepsGuide }; export default { title: 'StepsGuide 操作指引', category: '导航', status: '80%', install(app: App): void { - app.use(StepsGuide as any) - app.directive('StepsGuide', StepsGuideDirective) + app.use(StepsGuide as any); + app.directive('StepsGuide', StepsGuideDirective); } -} +}; diff --git a/packages/devui-vue/devui/steps-guide/src/steps-guide-types.ts b/packages/devui-vue/devui/steps-guide/src/steps-guide-types.ts index 83219f7933..0782a60b22 100644 --- a/packages/devui-vue/devui/steps-guide/src/steps-guide-types.ts +++ b/packages/devui-vue/devui/steps-guide/src/steps-guide-types.ts @@ -1,17 +1,17 @@ -import type { ExtractPropTypes, PropType } from 'vue' -type positionType = 'top-left' | 'top' | 'top-right' | 'left' | 'right' | 'bottom-left' | 'bottom' | 'bottom-right' +import type { ExtractPropTypes, PropType } from 'vue'; +type positionType = 'top-left' | 'top' | 'top-right' | 'left' | 'right' | 'bottom-left' | 'bottom' | 'bottom-right'; export type positionConf = { - left: number - top: number - type: string -} | positionType + left: number; + top: number; + type: string; +} | positionType; export type Step = { - title: string - content: string - trigger: string - target?: string - position?: positionConf -} + title: string; + content: string; + trigger: string; + target?: string; + position?: positionConf; +}; export const stepsGuideProps = { steps: Array as PropType<Step[]>, stepIndex: { @@ -37,9 +37,9 @@ export const stepsGuideProps = { stepChange: { type: Function, default(){ - return true + return true; } } -} as const +} as const; -export type StepsGuideProps = ExtractPropTypes<typeof stepsGuideProps> +export type StepsGuideProps = ExtractPropTypes<typeof stepsGuideProps>; diff --git a/packages/devui-vue/devui/steps-guide/src/steps-guide.tsx b/packages/devui-vue/devui/steps-guide/src/steps-guide.tsx index 14c621ce73..ebe08a0c83 100644 --- a/packages/devui-vue/devui/steps-guide/src/steps-guide.tsx +++ b/packages/devui-vue/devui/steps-guide/src/steps-guide.tsx @@ -1,47 +1,47 @@ -import './steps-guide.scss' -import { computed, ref, defineComponent, Teleport, onMounted } from 'vue' -import { stepsGuideProps, StepsGuideProps, Step } from './steps-guide-types' -import { useStepsGuidePosition, useStepsGuideCtrl } from '../hooks' +import './steps-guide.scss'; +import { computed, ref, defineComponent, Teleport, onMounted } from 'vue'; +import { stepsGuideProps, StepsGuideProps, Step } from './steps-guide-types'; +import { useStepsGuidePosition, useStepsGuideCtrl } from '../hooks'; export default defineComponent({ name: 'DStepsGuide', props: stepsGuideProps, emits: ['guide-close', 'update:stepIndex'], setup(props: StepsGuideProps, ctx) { - const stepIndexData = ref<number>((props.stepIndex ?? 0) as number) + const stepIndexData = ref<number>((props.stepIndex ?? 0) as number); const stepIndex = computed<number>({ set: val => { if(props.stepIndex != null) { - ctx.emit('update:stepIndex', val) + ctx.emit('update:stepIndex', val); } - stepIndexData.value = val + stepIndexData.value = val; }, get: () => stepIndexData.value - }) + }); const currentStep = computed<Step>(() => { - const _step = props.steps[stepIndex.value] - if(_step) _step.position = _step.position || 'top' - return _step - }) + const _step = props.steps[stepIndex.value]; + if(_step) {_step.position = _step.position || 'top';} + return _step; + }); const { stepsRef, guidePosition, guideClassList, - updateGuidePosition } = useStepsGuidePosition(props, currentStep) - const { + updateGuidePosition } = useStepsGuidePosition(props, currentStep); + const { stepsCount, closeGuide, - setCurrentIndex } = useStepsGuideCtrl(props, ctx, updateGuidePosition, stepIndex) + setCurrentIndex } = useStepsGuideCtrl(props, ctx, updateGuidePosition, stepIndex); onMounted(() => { - updateGuidePosition() - }) + updateGuidePosition(); + }); ctx.expose({ closeGuide, setCurrentIndex - }) - return () => stepIndex.value > -1 && stepsCount.value > 0 ? + }); + return () => stepIndex.value > -1 && stepsCount.value > 0 ? (<Teleport to="body"> <div style={ guidePosition } class={guideClassList} ref={ stepsRef }> <div class="devui-shining-dot"></div> @@ -56,7 +56,7 @@ export default defineComponent({ props.showDots ? <div class="devui-dots"> {props.steps.map((step, index) => { - return <em class={ ['icon icon-dot-status', currentStep.value === step ? 'devui-active' : ''] } key={ index }></em> + return <em class={ ['icon icon-dot-status', currentStep.value === step ? 'devui-active' : ''] } key={ index }></em>; })} </div> : null } @@ -64,11 +64,11 @@ export default defineComponent({ {stepIndex.value > 0 ? <div class="devui-prev-step" onClick={() => setCurrentIndex(stepIndex.value - 1)}>{'上一步'}</div> : null} {stepIndex.value === stepsCount.value - 1 ? <div onClick={closeGuide}>{'我知道啦'}</div> : - <div class="devui-next-step" onClick={() => { setCurrentIndex(stepIndex.value + 1) }}>{'我知道啦,继续'}</div>} + <div class="devui-next-step" onClick={() => { setCurrentIndex(stepIndex.value + 1); }}>{'我知道啦,继续'}</div>} </div> </div> </div> </div> - </Teleport>) : null + </Teleport>) : null; } -}) +}); diff --git a/packages/devui-vue/devui/sticky/index.ts b/packages/devui-vue/devui/sticky/index.ts index e6e10417ce..46a75c1c39 100644 --- a/packages/devui-vue/devui/sticky/index.ts +++ b/packages/devui-vue/devui/sticky/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Sticky from './src/sticky' +import type { App } from 'vue'; +import Sticky from './src/sticky'; Sticky.install = function(app: App): void { - app.component(Sticky.name, Sticky) -} + app.component(Sticky.name, Sticky); +}; -export { Sticky } +export { Sticky }; export default { title: 'Sticky 便贴', category: '通用', status: '50%', install(app: App): void { - app.use(Sticky as any) + app.use(Sticky as any); } -} +}; diff --git a/packages/devui-vue/devui/sticky/src/sticky.tsx b/packages/devui-vue/devui/sticky/src/sticky.tsx index 95d733e7cd..30ae427af0 100644 --- a/packages/devui-vue/devui/sticky/src/sticky.tsx +++ b/packages/devui-vue/devui/sticky/src/sticky.tsx @@ -1,4 +1,4 @@ -import { defineComponent, onMounted, reactive, ref, watch, PropType } from 'vue' +import { defineComponent, onMounted, reactive, ref, watch, PropType } from 'vue'; export default defineComponent({ @@ -12,7 +12,7 @@ export default defineComponent({ }, view: { type: Object, - default: () => { return { top: 0, bottom: 0 } }, + default: () => { return { top: 0, bottom: 0 }; }, }, scrollTarget: { type: Object as PropType<Element> @@ -20,64 +20,64 @@ export default defineComponent({ }, emits: ['statusChange'], setup(props, ctx) { - const { slots } = ctx - let container: Element - let scrollTarget: Element | Window + const { slots } = ctx; + let container: Element; + let scrollTarget: Element | Window; - let scrollTimer: any - let scrollPreStart: number | null + let scrollTimer: any; + let scrollPreStart: number | null; const THROTTLE_DELAY = 16; const THROTTLE_TRIGGER = 100; - let parentNode: Element - let containerLeft = 0 + let parentNode: Element; + let containerLeft = 0; const state = reactive({ status: 'normal' - }) + }); watch( () => props.zIndex, () => { - init() + init(); } ); watch( () => props.container, () => { - init() + init(); } ); watch( () => props.scrollTarget, () => { - init() + init(); } ); watch( () => state.status, () => { - ctx.emit('statusChange', state.status) + ctx.emit('statusChange', state.status); }, { immediate: true } ); const init = () => { - parentNode = stickyRef.value.parentElement + parentNode = stickyRef.value.parentElement; if (!props.container) { container = parentNode; } else { - container = props.container + container = props.container; } - stickyRef.value.style.zIndex = props.zIndex + stickyRef.value.style.zIndex = props.zIndex; scrollTarget = props.scrollTarget || window; scrollTarget.addEventListener('scroll', throttle); initScrollStatus(scrollTarget); - } + }; // 初始化,判断位置,如果有滚用动则用handler处理 const initScrollStatus = (target: any) => { @@ -92,45 +92,45 @@ export default defineComponent({ if (flag) { setTimeout(scrollHandler); } - } + }; const statusProcess = (status: any) => { - const wrapper = stickyRef.value || document.createElement('div') + const wrapper = stickyRef.value || document.createElement('div'); switch (status) { - case 'normal': - wrapper.style.top = 'auto'; - wrapper.style.left = 'auto'; - wrapper.style.position = 'static'; - break; - case 'follow': - const scrollTargetElement: any = scrollTarget - const viewOffset = scrollTarget && scrollTarget !== window ? - scrollTargetElement.getBoundingClientRect().top : 0; - wrapper.style.top = +viewOffset + ((props.view && props.view.top) || 0) + 'px'; - wrapper.style.left = wrapper.getBoundingClientRect().left + 'px'; - wrapper.style.position = 'fixed'; - break; - case 'stay': + case 'normal': + wrapper.style.top = 'auto'; + wrapper.style.left = 'auto'; + wrapper.style.position = 'static'; + break; + case 'follow': + const scrollTargetElement: any = scrollTarget; + const viewOffset = scrollTarget && scrollTarget !== window ? + scrollTargetElement.getBoundingClientRect().top : 0; + wrapper.style.top = +viewOffset + ((props.view && props.view.top) || 0) + 'px'; + wrapper.style.left = wrapper.getBoundingClientRect().left + 'px'; + wrapper.style.position = 'fixed'; + break; + case 'stay': + wrapper.style.top = calculateRelativePosition(wrapper, parentNode, 'top') + 'px'; + wrapper.style.left = 'auto'; + wrapper.style.position = 'relative'; + break; + case 'remain': + if (wrapper.style.position !== 'fixed' && wrapper.style.position !== 'absolute') { wrapper.style.top = calculateRelativePosition(wrapper, parentNode, 'top') + 'px'; wrapper.style.left = 'auto'; - wrapper.style.position = 'relative'; - break; - case 'remain': - if (wrapper.style.position !== 'fixed' && wrapper.style.position !== 'absolute') { - wrapper.style.top = calculateRelativePosition(wrapper, parentNode, 'top') + 'px'; - wrapper.style.left = 'auto'; - wrapper.style.position = 'absolute'; - } - wrapper.style.top = + wrapper.style.position = 'absolute'; + } + wrapper.style.top = calculateRemainPosition(wrapper, parentNode, container) + 'px'; - wrapper.style.left = calculateRelativePosition(wrapper, parentNode, 'left') + 'px'; - wrapper.style.position = 'relative'; - break; - default: - break; + wrapper.style.left = calculateRelativePosition(wrapper, parentNode, 'left') + 'px'; + wrapper.style.position = 'relative'; + break; + default: + break; } - } + }; const throttle = () => { const fn = scrollAndResizeHock; @@ -152,7 +152,7 @@ export default defineComponent({ scrollTimer = null; }, THROTTLE_DELAY); } - } + }; const scrollAndResizeHock = () => { if (container.getBoundingClientRect().left - (containerLeft || 0) !== 0) { @@ -161,11 +161,11 @@ export default defineComponent({ } else { scrollHandler(); } - } + }; const scrollHandler = () => { - const scrollTargetElement: any = scrollTarget - const wrapper = stickyRef.value || document.createElement('div') + const scrollTargetElement: any = scrollTarget; + const wrapper = stickyRef.value || document.createElement('div'); const viewOffsetTop = scrollTarget && scrollTarget !== window ? scrollTargetElement.getBoundingClientRect().top : 0; const computedStyle = window.getComputedStyle(container); @@ -199,7 +199,7 @@ export default defineComponent({ state.status = 'follow'; statusProcess(state.status); } - } + }; const calculateRelativePosition = (element: any, relativeElement: any, direction: 'left' | 'top') => { @@ -216,7 +216,7 @@ export default defineComponent({ parseInt(computedStyle[direction === 'left' ? 'borderLeftWidth' : 'borderTopWidth'], 10) ); } - } + }; const calculateRemainPosition = (element: any, relativeElement: any, container: any) => { if (window && window.getComputedStyle) { @@ -232,13 +232,13 @@ export default defineComponent({ parseInt(computedStyle['borderBottomWidth'], 10); return result < 0 ? 0 : result; } - } + }; onMounted(() => { - init() - }) + init(); + }); - const stickyRef = ref() + const stickyRef = ref(); return () => { @@ -246,7 +246,7 @@ export default defineComponent({ <div ref={stickyRef}> {slots.default ? slots.default() : ''} </div> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/switch/index.ts b/packages/devui-vue/devui/switch/index.ts index c834c231e8..bf1478aacf 100644 --- a/packages/devui-vue/devui/switch/index.ts +++ b/packages/devui-vue/devui/switch/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Switch from './src/switch' +import type { App } from 'vue'; +import Switch from './src/switch'; Switch.install = function(app: App) { - app.component(Switch.name, Switch) -} + app.component(Switch.name, Switch); +}; -export { Switch } +export { Switch }; export default { title: 'Switch 开关', category: '数据录入', status: '100%', install(app: App): void { - app.use(Switch as any) + app.use(Switch as any); } -} +}; diff --git a/packages/devui-vue/devui/switch/src/switch.tsx b/packages/devui-vue/devui/switch/src/switch.tsx index 95e6902f15..33df3653a7 100644 --- a/packages/devui-vue/devui/switch/src/switch.tsx +++ b/packages/devui-vue/devui/switch/src/switch.tsx @@ -82,8 +82,8 @@ export default defineComponent({ `border-color: ${checked && !disabled ? color : ''}` ]; - const checkedContent = renderSlot(useSlots(), 'checkedContent') - const uncheckedContent = renderSlot(useSlots(), 'uncheckedContent') + const checkedContent = renderSlot(useSlots(), 'checkedContent'); + const uncheckedContent = renderSlot(useSlots(), 'uncheckedContent'); return ( <span class={outerCls} style={outerStyle} onClick={toggle}> <span class="devui-switch-inner-wrapper"> @@ -95,4 +95,4 @@ export default defineComponent({ </span> ); } -}); \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/table/__tests__/table.spec.ts b/packages/devui-vue/devui/table/__tests__/table.spec.ts index 35e37e75c5..0a744335bf 100644 --- a/packages/devui-vue/devui/table/__tests__/table.spec.ts +++ b/packages/devui-vue/devui/table/__tests__/table.spec.ts @@ -4,5 +4,5 @@ import { Table } from '../index'; describe('table test', () => { it('table init render', async () => { // todo - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/table/index.ts b/packages/devui-vue/devui/table/index.ts index 8a9d848e41..130d3ba525 100644 --- a/packages/devui-vue/devui/table/index.ts +++ b/packages/devui-vue/devui/table/index.ts @@ -1,21 +1,21 @@ -import type { App } from 'vue' -import Table from './src/table' -import Column from './src/column/column' -import { Loading } from '../loading/index' +import type { App } from 'vue'; +import Table from './src/table'; +import Column from './src/column/column'; +import { Loading } from '../loading/index'; Table.install = function (app: App): void { - app.directive('dLoading', Loading) - app.component(Table.name, Table) - app.component(Column.name, Column) -} + app.directive('dLoading', Loading); + app.component(Table.name, Table); + app.component(Column.name, Column); +}; -export { Table, Column } +export { Table, Column }; export default { title: 'Table 表格', category: '数据展示', status: '10%', install(app: App): void { - app.use(Table as any) + app.use(Table as any); } -} +}; diff --git a/packages/devui-vue/devui/table/src/body/body.tsx b/packages/devui-vue/devui/table/src/body/body.tsx index 6e140aa8ac..8a1d9c8a8e 100644 --- a/packages/devui-vue/devui/table/src/body/body.tsx +++ b/packages/devui-vue/devui/table/src/body/body.tsx @@ -44,7 +44,7 @@ export default defineComponent({ ); })} </tbody> - ) + ); } }); @@ -61,7 +61,7 @@ const TD = defineComponent({ type: Number, } }, - setup(props: { column: Column; row: any; index: number; }) { + setup(props: { column: Column; row: any; index: number }) { const column = toRef(props, 'column'); // 固定列 diff --git a/packages/devui-vue/devui/table/src/body/use-body.ts b/packages/devui-vue/devui/table/src/body/use-body.ts index 49d6726547..d12cc220fb 100644 --- a/packages/devui-vue/devui/table/src/body/use-body.ts +++ b/packages/devui-vue/devui/table/src/body/use-body.ts @@ -1,7 +1,7 @@ import { computed, ComputedRef } from 'vue'; import { Column } from '../column/column.type'; -import { TableBodyPropsTypes } from './body.type' +import { TableBodyPropsTypes } from './body.type'; interface Data { - rowColumns: ComputedRef<(Record<string, any> & { columns: Column[]; })[]> + rowColumns: ComputedRef<(Record<string, any> & { columns: Column[] })[]>; } diff --git a/packages/devui-vue/devui/table/src/colgroup/colgroup.tsx b/packages/devui-vue/devui/table/src/colgroup/colgroup.tsx index fa16eaea3b..fe4b6d7c90 100644 --- a/packages/devui-vue/devui/table/src/colgroup/colgroup.tsx +++ b/packages/devui-vue/devui/table/src/colgroup/colgroup.tsx @@ -19,4 +19,4 @@ export default defineComponent({ ); } -}); \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/table/src/column/column.tsx b/packages/devui-vue/devui/table/src/column/column.tsx index bf92f239ec..62f7be7ce5 100644 --- a/packages/devui-vue/devui/table/src/column/column.tsx +++ b/packages/devui-vue/devui/table/src/column/column.tsx @@ -3,7 +3,7 @@ import { Column, TableColumnProps, TableColumnPropsTypes, -} from './column.type' +} from './column.type'; import { TABLE_TOKEN } from '../table.type'; import { createColumn } from './use-column'; @@ -12,8 +12,8 @@ export default defineComponent({ props: TableColumnProps, setup(props: TableColumnPropsTypes, ctx) { /* - ctx.slots : { - customFilterTemplate: Slot + ctx.slots : { + customFilterTemplate: Slot } */ const column = createColumn(toRefs(props), ctx.slots); @@ -34,4 +34,4 @@ export default defineComponent({ render() { return null; }, -}); \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/table/src/column/column.type.ts b/packages/devui-vue/devui/table/src/column/column.type.ts index 99b4700ad1..5e900f4a0e 100644 --- a/packages/devui-vue/devui/table/src/column/column.type.ts +++ b/packages/devui-vue/devui/table/src/column/column.type.ts @@ -61,35 +61,35 @@ export type CompareFn<T = any> = (field: string, a: T, b: T) => boolean; export type FilterResults = (string | number)[]; export interface CustomFilterProps { - value: FilterResults - onChange: (value: FilterResults) => void + value: FilterResults; + onChange: (value: FilterResults) => void; } export type CustomFilterSlot = (props: CustomFilterProps) => VNode[]; export interface FilterConfig { - id: number | string - name: string - value: any - checked?: boolean + id: number | string; + name: string; + value: any; + checked?: boolean; } export interface Column<T extends Record<string, unknown> = any> { - field?: string - width?: number - minWidth?: number - realWidth?: number - header?: string - order?: number - sortable?: boolean - filterable?: boolean - filterMultiple?: boolean - filterList?: FilterConfig[] - fixedLeft?: string - fixedRight?: string - renderHeader?: () => void - renderCell?: (row: T, index: number) => void - formatter?: Formatter<T> - compareFn?: CompareFn<T> - customFilterTemplate?: CustomFilterSlot - subColumns?: Slot -} \ No newline at end of file + field?: string; + width?: number; + minWidth?: number; + realWidth?: number; + header?: string; + order?: number; + sortable?: boolean; + filterable?: boolean; + filterMultiple?: boolean; + filterList?: FilterConfig[]; + fixedLeft?: string; + fixedRight?: string; + renderHeader?: () => void; + renderCell?: (row: T, index: number) => void; + formatter?: Formatter<T>; + compareFn?: CompareFn<T>; + customFilterTemplate?: CustomFilterSlot; + subColumns?: Slot; +} diff --git a/packages/devui-vue/devui/table/src/header/filter/index.ts b/packages/devui-vue/devui/table/src/header/filter/index.ts index 998668a1df..009bf07636 100644 --- a/packages/devui-vue/devui/table/src/header/filter/index.ts +++ b/packages/devui-vue/devui/table/src/header/filter/index.ts @@ -1 +1 @@ -export * from './filter'; \ No newline at end of file +export * from './filter'; diff --git a/packages/devui-vue/devui/table/src/header/header.tsx b/packages/devui-vue/devui/table/src/header/header.tsx index f765821bd4..b8ef672ec9 100644 --- a/packages/devui-vue/devui/table/src/header/header.tsx +++ b/packages/devui-vue/devui/table/src/header/header.tsx @@ -47,8 +47,8 @@ export default defineComponent({ ))} </tr> </thead> - ) - } + ); + }; } }); @@ -59,7 +59,7 @@ const Th = defineComponent({ required: true } }, - setup(props: { column: Column; }) { + setup(props: { column: Column }) { const table = inject(TABLE_TOKEN); const { column } = toRefs(props); @@ -84,6 +84,6 @@ const Th = defineComponent({ </div> {props.column.sortable && <Sort v-model={directionRef.value} />} </th> - ) + ); } -}); \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/table/src/header/sort/index.ts b/packages/devui-vue/devui/table/src/header/sort/index.ts index 72099fcbdd..3577964f8a 100644 --- a/packages/devui-vue/devui/table/src/header/sort/index.ts +++ b/packages/devui-vue/devui/table/src/header/sort/index.ts @@ -1 +1 @@ -export { Sort } from './sort'; \ No newline at end of file +export { Sort } from './sort'; diff --git a/packages/devui-vue/devui/table/src/header/use-header.ts b/packages/devui-vue/devui/table/src/header/use-header.ts index 5953c57d85..3ddffdd8c8 100644 --- a/packages/devui-vue/devui/table/src/header/use-header.ts +++ b/packages/devui-vue/devui/table/src/header/use-header.ts @@ -13,7 +13,7 @@ export const useSort = (store: TableStore, column: Ref<Column>): Ref<SortDirecti }, { immediate: true }); return directionRef; -} +}; export const useFliter = (store: TableStore, column: Ref<Column>): Ref<FilterResults> => { const filteredRef = shallowRef<FilterResults>(); @@ -21,4 +21,4 @@ export const useFliter = (store: TableStore, column: Ref<Column>): Ref<FilterRes store.filterData(column.value.field, results); }); return filteredRef; -} +}; diff --git a/packages/devui-vue/devui/table/src/table-types.ts b/packages/devui-vue/devui/table/src/table-types.ts index 1f9cbcf673..c54e6b81e3 100644 --- a/packages/devui-vue/devui/table/src/table-types.ts +++ b/packages/devui-vue/devui/table/src/table-types.ts @@ -1,14 +1,14 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; type TableData = Array<{ - [key: string]: any -}> + [key: string]: any; +}>; export const tableProps = { data: { type: Array as PropType<TableData>, required: true, } -} as const +} as const; -export type TableProps = ExtractPropTypes<typeof tableProps> +export type TableProps = ExtractPropTypes<typeof tableProps>; diff --git a/packages/devui-vue/devui/table/src/table.type.ts b/packages/devui-vue/devui/table/src/table.type.ts index 369441f95e..e02ae30b9b 100644 --- a/packages/devui-vue/devui/table/src/table.type.ts +++ b/packages/devui-vue/devui/table/src/table.type.ts @@ -66,8 +66,8 @@ export const TableProps = { export type TablePropsTypes = ExtractPropTypes<typeof TableProps>; export interface Table<T = Record<string, any>> extends ComponentInternalInstance { - store: TableStore<T> - props: TablePropsTypes + store: TableStore<T>; + props: TablePropsTypes; } // export interface TableCheckStatusArg { @@ -81,7 +81,7 @@ export interface Table<T = Record<string, any>> extends ComponentInternalInstanc // } export interface TableMethods<T = Record<string, any>> { - getCheckedRows(): T[] + getCheckedRows(): T[]; // setRowCheckStatus(arg: TableCheckStatusArg): void // setTableCheckStatus(arg: RowToggleStatusEventArg): void // setRowChildToggleStatus(): void diff --git a/packages/devui-vue/devui/table/src/use-table.ts b/packages/devui-vue/devui/table/src/use-table.ts index 641e775f5f..2d19e4fb2f 100644 --- a/packages/devui-vue/devui/table/src/use-table.ts +++ b/packages/devui-vue/devui/table/src/use-table.ts @@ -3,8 +3,8 @@ import { Column } from './column/column.type'; import { TablePropsTypes } from './table.type'; interface TableConfig { - classes: ComputedRef<Record<string, boolean>> - style: ComputedRef<CSSProperties> + classes: ComputedRef<Record<string, boolean>>; + style: ComputedRef<CSSProperties>; } export function useTable(props: TablePropsTypes): TableConfig { @@ -24,7 +24,7 @@ export function useTable(props: TablePropsTypes): TableConfig { } -export const useFixedColumn = (column: Ref<Column>): ToRefs<{ stickyCell: string; offsetStyle: string; }> => { +export const useFixedColumn = (column: Ref<Column>): ToRefs<{ stickyCell: string; offsetStyle: string }> => { const stickyCell = computed(() => { const col = column.value; if (col.fixedLeft) { @@ -54,4 +54,4 @@ export const useFixedColumn = (column: Ref<Column>): ToRefs<{ stickyCell: string stickyCell, offsetStyle }; -} +}; diff --git a/packages/devui-vue/devui/table/src/utils.ts b/packages/devui-vue/devui/table/src/utils.ts index 9043fe1a3f..95b22063c9 100644 --- a/packages/devui-vue/devui/table/src/utils.ts +++ b/packages/devui-vue/devui/table/src/utils.ts @@ -8,4 +8,4 @@ export function formatWidth(width: number | string): number { export function formatMinWidth(minWidth: number | string): number { return formatWidth(minWidth) || 80; -} \ No newline at end of file +} diff --git a/packages/devui-vue/devui/tag-input/index.ts b/packages/devui-vue/devui/tag-input/index.ts index 45a127cf32..7614645cb1 100644 --- a/packages/devui-vue/devui/tag-input/index.ts +++ b/packages/devui-vue/devui/tag-input/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import TagInput from './src/tag-input' +import type { App } from 'vue'; +import TagInput from './src/tag-input'; TagInput.install = function (app: App) { - app.component(TagInput.name, TagInput) -} + app.component(TagInput.name, TagInput); +}; -export { TagInput } +export { TagInput }; export default { title: 'TagInput 标签输入框', category: '数据录入', status: '100%', install(app: App): void { - app.use(TagInput as any) + app.use(TagInput as any); } -} +}; diff --git a/packages/devui-vue/devui/tag-input/src/tag-input.tsx b/packages/devui-vue/devui/tag-input/src/tag-input.tsx index 64ca8ee63b..2672d5709d 100644 --- a/packages/devui-vue/devui/tag-input/src/tag-input.tsx +++ b/packages/devui-vue/devui/tag-input/src/tag-input.tsx @@ -3,8 +3,8 @@ import removeBtnSvg from './remove-btn'; import './tag-input.scss'; interface Suggestion { - __index: number - [x: string]: any + __index: number; + [x: string]: any; } const tagInputProps = { @@ -107,7 +107,7 @@ export default defineComponent({ } return suggestions = props.caseSensitivity ? suggestions.filter(item => item[props.displayProperty].indexOf(tagInputVal.value) !== -1) - : suggestions.filter(item => item[props.displayProperty].toLowerCase().indexOf(tagInputVal.value.toLowerCase()) !== -1) + : suggestions.filter(item => item[props.displayProperty].toLowerCase().indexOf(tagInputVal.value.toLowerCase()) !== -1); }); const selectIndex = ref(0); @@ -132,15 +132,15 @@ export default defineComponent({ }; const handleEnter = () => { let res = { [props.displayProperty]: tagInputVal.value }; - if (tagInputVal.value === '' && mergedSuggestions.value.length === 0) return false + if (tagInputVal.value === '' && mergedSuggestions.value.length === 0) {return false;} if (props.tags.findIndex((item) => item[props.displayProperty] === tagInputVal.value) > -1) { - tagInputVal.value = '' - return false + tagInputVal.value = ''; + return false; } if (mergedSuggestions.value.length === 0 && (tagInputVal.value.length < props.minLength || tagInputVal.value.length > props.maxLength)) { - tagInputVal.value = '' - return false + tagInputVal.value = ''; + return false; } if (mergedSuggestions.value.length) { const target = mergedSuggestions.value[selectIndex.value]; @@ -155,20 +155,20 @@ export default defineComponent({ }; const onInputKeydown = ($event: KeyboardEvent) => { switch ($event.key) { - case KEYS_MAP.tab: - case KEYS_MAP.enter: - case KEYS_MAP.space: - if (!props.isAddBySpace && KEYS_MAP.space) return - handleEnter(); - break; - case KEYS_MAP.down: - onSelectIndexChange(true); - break; - case KEYS_MAP.up: - onSelectIndexChange(); - break; - default: - break; + case KEYS_MAP.tab: + case KEYS_MAP.enter: + case KEYS_MAP.space: + if (!props.isAddBySpace && KEYS_MAP.space) {return;} + handleEnter(); + break; + case KEYS_MAP.down: + onSelectIndexChange(true); + break; + case KEYS_MAP.up: + onSelectIndexChange(); + break; + default: + break; } }; diff --git a/packages/devui-vue/devui/tag/__tests__/tag.spec.ts b/packages/devui-vue/devui/tag/__tests__/tag.spec.ts index c46756f57c..432e257c6c 100644 --- a/packages/devui-vue/devui/tag/__tests__/tag.spec.ts +++ b/packages/devui-vue/devui/tag/__tests__/tag.spec.ts @@ -1,117 +1,117 @@ -import { mount } from '@vue/test-utils' -import { Tag } from '../index' +import { mount } from '@vue/test-utils'; +import { Tag } from '../index'; describe('tag test', () => { it('init render', async () => { - const wrapper = mount(Tag) - expect(wrapper.find('.devui-tag').exists()).toBeTruthy() - }) + const wrapper = mount(Tag); + expect(wrapper.find('.devui-tag').exists()).toBeTruthy(); + }); it('props type', () => { const wrapper = mount(Tag, { propsData: { type: 'primary' } - }) - expect(wrapper.find('.devui-tag span').classes()).toContain('devui-tag-primary') - }) + }); + expect(wrapper.find('.devui-tag span').classes()).toContain('devui-tag-primary'); + }); it('props color', () => { const wrapper = mount(Tag, { propsData: { - color: 'red-w98' //#f66f6a rgb(246, 111, 106) + color: 'red-w98' // #f66f6a rgb(246, 111, 106) } - }) - expect(wrapper.find('.devui-tag span').attributes('style')).toContain('rgb(246, 111, 106)') - }) + }); + expect(wrapper.find('.devui-tag span').attributes('style')).toContain('rgb(246, 111, 106)'); + }); it('props color custom', () => { const wrapper = mount(Tag, { propsData: { - color: '#aa2116' //rgb(170, 33, 22) + color: '#aa2116' // rgb(170, 33, 22) } - }) - expect(wrapper.find('.devui-tag span').attributes('style')).toContain('rgb(170, 33, 22)') - }) + }); + expect(wrapper.find('.devui-tag span').attributes('style')).toContain('rgb(170, 33, 22)'); + }); it('props titleContent', () => { - const titleContent = 'tagTitle test' + const titleContent = 'tagTitle test'; const wrapper = mount(Tag, { props: { titleContent } - }) - expect(wrapper.get('.devui-tag span').attributes('title')).toBe(titleContent) - }) + }); + expect(wrapper.get('.devui-tag span').attributes('title')).toBe(titleContent); + }); it('props deletable show', async () => { const wrapper = mount(Tag, { propsData: { deletable: false } - }) - expect(wrapper.find('.remove-button').exists()).toBeFalsy() - await wrapper.setProps({ deletable: true }) - expect(wrapper.find('.remove-button').exists()).toBeTruthy() - }) + }); + expect(wrapper.find('.remove-button').exists()).toBeFalsy(); + await wrapper.setProps({ deletable: true }); + expect(wrapper.find('.remove-button').exists()).toBeTruthy(); + }); it('props deletable hide', async () => { const wrapper = mount(Tag, { propsData: { deletable: true } - }) - const btn = wrapper.find('.remove-button') - expect(btn.exists()).toBeTruthy() - await btn.trigger('click') - expect(wrapper.find('.devui-tag').exists()).toBeFalsy() - }) + }); + const btn = wrapper.find('.remove-button'); + expect(btn.exists()).toBeTruthy(); + await btn.trigger('click'); + expect(wrapper.find('.devui-tag').exists()).toBeFalsy(); + }); it('event tagDelete', async () => { const wrapper = mount(Tag, { propsData: { deletable: true } - }) - await wrapper.find('.remove-button').trigger('click') - expect(wrapper.emitted('tagDelete').length).toBeGreaterThan(0) - }) + }); + await wrapper.find('.remove-button').trigger('click'); + expect(wrapper.emitted('tagDelete').length).toBeGreaterThan(0); + }); it('props checked', async () => { const wrapper = mount(Tag, { propsData: { - type: 'primary' //对应颜色:rgb(94, 124, 224) + type: 'primary' // 对应颜色:rgb(94, 124, 224) } - }) + }); expect(wrapper.find('.devui-tag span').attributes('style')).toContain( 'color: rgb(94, 124, 224);' - ) - await wrapper.setProps({ checked: true }) + ); + await wrapper.setProps({ checked: true }); expect(wrapper.find('.devui-tag span').attributes('style')).toContain( 'background-color: rgb(94, 124, 224);' - ) - expect(wrapper.emitted('checkedChange').length).toBeGreaterThan(0) - }) + ); + expect(wrapper.emitted('checkedChange').length).toBeGreaterThan(0); + }); it('event checkedChange', async () => { - const wrapper = mount(Tag) - await wrapper.setProps({ checked: true }) - expect(wrapper.emitted('checkedChange').length).toBeGreaterThan(0) - expect(wrapper.emitted('checkedChange')[0]).toEqual([true]) - await wrapper.setProps({ checked: false }) - expect(wrapper.emitted('checkedChange').length).toBeGreaterThan(1) - expect(wrapper.emitted('checkedChange')[1]).toEqual([false]) - }) + const wrapper = mount(Tag); + await wrapper.setProps({ checked: true }); + expect(wrapper.emitted('checkedChange').length).toBeGreaterThan(0); + expect(wrapper.emitted('checkedChange')[0]).toEqual([true]); + await wrapper.setProps({ checked: false }); + expect(wrapper.emitted('checkedChange').length).toBeGreaterThan(1); + expect(wrapper.emitted('checkedChange')[1]).toEqual([false]); + }); it('event click', async () => { - const wrapper = mount(Tag) - await wrapper.find('.devui-tag').trigger('click') - expect(wrapper.emitted('click').length).toBeGreaterThan(0) - }) + const wrapper = mount(Tag); + await wrapper.find('.devui-tag').trigger('click'); + expect(wrapper.emitted('click').length).toBeGreaterThan(0); + }); it('slot default string', async () => { const wrapper = mount(Tag, { slots: { default: 'default slot test' } - }) - expect(wrapper.text()).toContain('default slot test') - }) + }); + expect(wrapper.text()).toContain('default slot test'); + }); it('slot default component', async () => { const wrapper = mount(Tag, { slots: { default: ['<d-icon name="like"></d-icon>', 'icon component test'] } - }) - expect(wrapper.find('i').classes()).toContain('icon-like') - }) -}) + }); + expect(wrapper.find('i').classes()).toContain('icon-like'); + }); +}); diff --git a/packages/devui-vue/devui/tag/index.ts b/packages/devui-vue/devui/tag/index.ts index d3b5f9167e..0cf01636f7 100644 --- a/packages/devui-vue/devui/tag/index.ts +++ b/packages/devui-vue/devui/tag/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Tag from './src/tag' +import type { App } from 'vue'; +import Tag from './src/tag'; Tag.install = function (app: App): void { - app.component(Tag.name, Tag) -} + app.component(Tag.name, Tag); +}; -export { Tag } +export { Tag }; export default { title: 'Tag 标签', category: '数据展示', status: '70%', // TODO: 组件若开发完成则填入"已完成",并删除该注释 install(app: App): void { - app.use(Tag as any) + app.use(Tag as any); } -} +}; diff --git a/packages/devui-vue/devui/tag/src/hooks/index.ts b/packages/devui-vue/devui/tag/src/hooks/index.ts index ff702f1951..46d28e7d26 100644 --- a/packages/devui-vue/devui/tag/src/hooks/index.ts +++ b/packages/devui-vue/devui/tag/src/hooks/index.ts @@ -1,4 +1,4 @@ -import useClass from './use-class' -import useColor from './use-color' +import useClass from './use-class'; +import useColor from './use-color'; -export { useClass, useColor } +export { useClass, useColor }; diff --git a/packages/devui-vue/devui/tag/src/hooks/use-class.ts b/packages/devui-vue/devui/tag/src/hooks/use-class.ts index e5afcc476a..d5588def2d 100644 --- a/packages/devui-vue/devui/tag/src/hooks/use-class.ts +++ b/packages/devui-vue/devui/tag/src/hooks/use-class.ts @@ -1,11 +1,11 @@ -import { computed } from 'vue' -import { tagProps, TagProps } from '../tag-types' +import { computed } from 'vue'; +import { tagProps, TagProps } from '../tag-types'; export default function (props: TagProps) { return computed(() => { - const { type, color, deletable } = props + const { type, color, deletable } = props; return `devui-tag devui-tag-${type || (color ? 'colorful' : '') || 'default'} ${ deletable ? 'devui-tag-deletable' : '' - }` - }) + }`; + }); } diff --git a/packages/devui-vue/devui/tag/src/hooks/use-color.ts b/packages/devui-vue/devui/tag/src/hooks/use-color.ts index 82adf0c413..c2a1166b0b 100644 --- a/packages/devui-vue/devui/tag/src/hooks/use-color.ts +++ b/packages/devui-vue/devui/tag/src/hooks/use-color.ts @@ -1,15 +1,15 @@ -import { computed } from 'vue' -import { TagProps } from '../tag-types' +import { computed } from 'vue'; +import { TagProps } from '../tag-types'; export default function (props: TagProps) { return computed(() => { - const { color, type } = props + const { color, type } = props; const typeMap = { primary: '#5e7ce0', success: '#50d4ab', warning: '#fac20a', danger: '#f66f6a' - } + }; const colorMap = { 'blue-w98': '#3383ff', 'aqua-w98': '#39afcc', @@ -20,11 +20,11 @@ export default function (props: TagProps) { 'red-w98': '#f66f6a', 'pink-w98': '#f3689a', 'purple-w98': '#a97af8' - } + }; - if (!color && type) return typeMap[type] + if (!color && type) {return typeMap[type];} // 判断传入的color是colorMap成员or颜色码 - const themeColor = colorMap[color] || color - return themeColor - }) + const themeColor = colorMap[color] || color; + return themeColor; + }); } diff --git a/packages/devui-vue/devui/tag/src/tag-types.ts b/packages/devui-vue/devui/tag/src/tag-types.ts index cccdb2f147..d0a0528fb1 100644 --- a/packages/devui-vue/devui/tag/src/tag-types.ts +++ b/packages/devui-vue/devui/tag/src/tag-types.ts @@ -1,6 +1,6 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; -export type tagType = 'primary' | 'success' | 'warning' | 'danger' +export type tagType = 'primary' | 'success' | 'warning' | 'danger'; export const tagProps = { type: { @@ -23,6 +23,6 @@ export const tagProps = { type: Boolean as PropType<boolean>, default: false } -} as const +} as const; -export type TagProps = ExtractPropTypes<typeof tagProps> +export type TagProps = ExtractPropTypes<typeof tagProps>; diff --git a/packages/devui-vue/devui/tag/src/tag.tsx b/packages/devui-vue/devui/tag/src/tag.tsx index 7d86daa167..fef91b36ab 100644 --- a/packages/devui-vue/devui/tag/src/tag.tsx +++ b/packages/devui-vue/devui/tag/src/tag.tsx @@ -1,7 +1,7 @@ -import { defineComponent, toRefs, ref, watch, onUnmounted } from 'vue' -import { tagProps, TagProps } from './tag-types' -import { useClass, useColor } from './hooks' -import './tag.scss' +import { defineComponent, toRefs, ref, watch, onUnmounted } from 'vue'; +import { tagProps, TagProps } from './tag-types'; +import { useClass, useColor } from './hooks'; +import './tag.scss'; // 类型声明 export default defineComponent({ @@ -9,20 +9,20 @@ export default defineComponent({ props: tagProps, emits: ['click', 'tagDelete', 'checkedChange'], setup(props: TagProps, { slots, emit }) { - const { type, color, checked, titleContent, deletable } = toRefs(props) - const tagClass = useClass(props) - const themeColor = useColor(props) - const tagTitle = titleContent.value || '' - const isDefaultTag = () => !type.value && !color.value - const isShow = ref(true) + const { type, color, checked, titleContent, deletable } = toRefs(props); + const tagClass = useClass(props); + const themeColor = useColor(props); + const tagTitle = titleContent.value || ''; + const isDefaultTag = () => !type.value && !color.value; + const isShow = ref(true); // 子组件的点击事件 const handleClick = () => { - emit('click') - } + emit('click'); + }; const handleDelete = () => { - isShow.value = false - emit('tagDelete') - } + isShow.value = false; + emit('tagDelete'); + }; const closeIconEl = () => { return deletable.value ? ( <a class='remove-button' onClick={handleDelete}> @@ -32,15 +32,15 @@ export default defineComponent({ <d-icon size='12px' name='close' color={themeColor.value} /> )} </a> - ) : null - } - //tag 的 check 状态改变时触发的事件checkedChange + ) : null; + }; + // tag 的 check 状态改变时触发的事件checkedChange const unWatch = watch(checked, (newVal) => { - console.log('checkedChange') + console.log('checkedChange'); - emit('checkedChange', newVal) - }) - onUnmounted(() => unWatch()) + emit('checkedChange', newVal); + }); + onUnmounted(() => unWatch()); return () => isShow.value && ( <div class='devui-tag' onClick={handleClick} v-show={isShow.value}> @@ -57,6 +57,6 @@ export default defineComponent({ {closeIconEl()} </span> </div> - ) + ); } -}) +}); diff --git a/packages/devui-vue/devui/textarea/__tests__/textarea.spec.ts b/packages/devui-vue/devui/textarea/__tests__/textarea.spec.ts index d064cdf1cc..00ad5a354d 100644 --- a/packages/devui-vue/devui/textarea/__tests__/textarea.spec.ts +++ b/packages/devui-vue/devui/textarea/__tests__/textarea.spec.ts @@ -4,5 +4,5 @@ import { Textarea } from '../index'; describe('textarea test', () => { it('textarea init render', async () => { // todo - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/textarea/index.ts b/packages/devui-vue/devui/textarea/index.ts index ef2b47cc9a..35d3775f7c 100644 --- a/packages/devui-vue/devui/textarea/index.ts +++ b/packages/devui-vue/devui/textarea/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Textarea from './src/textarea' +import type { App } from 'vue'; +import Textarea from './src/textarea'; Textarea.install = function(app: App): void { - app.component(Textarea.name, Textarea) -} + app.component(Textarea.name, Textarea); +}; -export { Textarea } +export { Textarea }; export default { title: 'Textarea 多行文本框', category: '数据录入', status: '100%', // TODO: 组件若开发完成则填入"已完成",并删除该注释 install(app: App): void { - app.use(Textarea as any) + app.use(Textarea as any); } -} +}; diff --git a/packages/devui-vue/devui/textarea/src/textarea-types.ts b/packages/devui-vue/devui/textarea/src/textarea-types.ts index 57acdbb2df..95f1a01a5c 100644 --- a/packages/devui-vue/devui/textarea/src/textarea-types.ts +++ b/packages/devui-vue/devui/textarea/src/textarea-types.ts @@ -39,7 +39,7 @@ export const textareaProps = { }, resize: { type: String as PropType< - 'none' | 'vertical' | 'horizontal' | 'both' | 'inherit' + 'none' | 'vertical' | 'horizontal' | 'both' | 'inherit' >, default: 'none', }, diff --git a/packages/devui-vue/devui/theme/core/theme.ts b/packages/devui-vue/devui/theme/core/theme.ts index a21bfd182c..f66b8eb61a 100644 --- a/packages/devui-vue/devui/theme/core/theme.ts +++ b/packages/devui-vue/devui/theme/core/theme.ts @@ -1,49 +1,49 @@ -import { inBrowser } from '../../shared/util/common-var' +import { inBrowser } from '../../shared/util/common-var'; class Theme { - static imports: any = {} + static imports: any = {}; static import(name: string): any { - return this.imports[name] + return this.imports[name]; } static register(name: string, target: any): void { - this.imports[name] = target + this.imports[name] = target; } constructor(theme: string) { - this.applyTheme(theme) + this.applyTheme(theme); } applyTheme(name: string): void { - const theme = Theme.imports[name] + const theme = Theme.imports[name]; if (!inBrowser) { return; } if (!theme) { - console.error(`主题 ${theme} 未注册!`) - return + console.error(`主题 ${theme} 未注册!`); + return; } - const id = 'devui-theme-variable' - const themeVariable = `:root { ${stringify(theme)} }` - let styleElement = document.getElementById(id) + const id = 'devui-theme-variable'; + const themeVariable = `:root { ${stringify(theme)} }`; + let styleElement = document.getElementById(id); if (styleElement) { - styleElement.innerText = themeVariable + styleElement.innerText = themeVariable; } else { - styleElement = document.createElement('style') - styleElement.id = id - styleElement.innerText = themeVariable - document.head.appendChild(styleElement) + styleElement = document.createElement('style'); + styleElement.id = id; + styleElement.innerText = themeVariable; + document.head.appendChild(styleElement); } } } function stringify(theme: any) { return Object.entries(theme) - .map(([key, value]) => `--${key}:${value}`) - .join(';') + .map(([key, value]) => `--${key}:${value}`) + .join(';'); } -export default Theme +export default Theme; diff --git a/packages/devui-vue/devui/theme/theme.ts b/packages/devui-vue/devui/theme/theme.ts index a2de3bcb99..6f7b4f0423 100644 --- a/packages/devui-vue/devui/theme/theme.ts +++ b/packages/devui-vue/devui/theme/theme.ts @@ -1,10 +1,10 @@ -import Theme from './core/theme' -import dark from './themes/dark' -import light from './themes/light' +import Theme from './core/theme'; +import dark from './themes/dark'; +import light from './themes/light'; -Theme.register('dark', dark) -Theme.register('light', light) +Theme.register('dark', dark); +Theme.register('light', light); -export { Theme } +export { Theme }; -export default Theme +export default Theme; diff --git a/packages/devui-vue/devui/theme/themes/dark.ts b/packages/devui-vue/devui/theme/themes/dark.ts index f21377b65f..49a096b4d9 100644 --- a/packages/devui-vue/devui/theme/themes/dark.ts +++ b/packages/devui-vue/devui/theme/themes/dark.ts @@ -89,4 +89,4 @@ export default { 'devui-primary-bg': '#383D4F', 'devui-default-line': '#5e7ce0', 'devui-default-bg': '#383838', -} \ No newline at end of file +}; diff --git a/packages/devui-vue/devui/theme/themes/light.ts b/packages/devui-vue/devui/theme/themes/light.ts index b86c08ca99..d77dc1dae8 100644 --- a/packages/devui-vue/devui/theme/themes/light.ts +++ b/packages/devui-vue/devui/theme/themes/light.ts @@ -132,4 +132,4 @@ export default { 'devui-z-index-modal': '1050', 'devui-z-index-drawer': '1040', 'devui-z-index-framework': '1000' -} \ No newline at end of file +}; diff --git a/packages/devui-vue/devui/time-picker/__tests__/time-picker.spec.ts b/packages/devui-vue/devui/time-picker/__tests__/time-picker.spec.ts index 865b5c9d45..ef9bc36125 100644 --- a/packages/devui-vue/devui/time-picker/__tests__/time-picker.spec.ts +++ b/packages/devui-vue/devui/time-picker/__tests__/time-picker.spec.ts @@ -10,18 +10,18 @@ describe('time-picker test', () => { template: `<d-time-picker></d-time-picker>`, setup() { - return + return; } }); const container = wrapper.find('.devui-time-picker'); - const timeUl = wrapper.findAll('.time-ul') - await nextTick() - expect(timeUl[0].element.childElementCount).toBe(24) - expect(timeUl[1].element.childElementCount).toBe(60) - expect(timeUl[2].element.childElementCount).toBe(60) - expect(container.classes()).toContain('devui-time-picker') - }) + const timeUl = wrapper.findAll('.time-ul'); + await nextTick(); + expect(timeUl[0].element.childElementCount).toBe(24); + expect(timeUl[1].element.childElementCount).toBe(60); + expect(timeUl[2].element.childElementCount).toBe(60); + expect(container.classes()).toContain('devui-time-picker'); + }); it('time-picker default open work', async () => { @@ -30,22 +30,22 @@ describe('time-picker test', () => { template: `<d-time-picker v-model="vModelValue" :time-picker-width="300" :autoOpen="autoOpen"></d-time-picker>`, setup() { - const vModelValue = ref('12:30:40') - const autoOpen = ref(true) + const vModelValue = ref('12:30:40'); + const autoOpen = ref(true); return { vModelValue, autoOpen - } + }; } }); - const timeInput = wrapper.find<HTMLInputElement>('.time-input') - const tiemPopup = wrapper.find('.devui-time-popup') + const timeInput = wrapper.find<HTMLInputElement>('.time-input'); + const tiemPopup = wrapper.find('.devui-time-popup'); - await nextTick() - expect(timeInput.element.value).toBe('12:30:40') - expect(tiemPopup.classes()).toContain('devui-show-time-popup') + await nextTick(); + expect(timeInput.element.value).toBe('12:30:40'); + expect(tiemPopup.classes()).toContain('devui-show-time-popup'); expect(tiemPopup.attributes('style')).toMatch('width: 300px'); }); @@ -57,120 +57,120 @@ describe('time-picker test', () => { }, }); - expect(wrapper.find('.devui-time-picker').classes()).toContain('picker-disabled') - expect(wrapper.find<HTMLInputElement>('.time-input').element.disabled).toBe(true) - }) + expect(wrapper.find('.devui-time-picker').classes()).toContain('picker-disabled'); + expect(wrapper.find<HTMLInputElement>('.time-input').element.disabled).toBe(true); + }); it('time-picker min-time work', async () => { const wrapper = mount({ components: { DTimePicker }, template: `<d-time-picker min-time='01:04:30' v-model="vModelValue"></d-time-picker>`, setup() { - const vModelValue = ref('01:03:00') + const vModelValue = ref('01:03:00'); return { vModelValue - } + }; } - }) + }); - const timeInput = wrapper.find<HTMLInputElement>('.time-input') - await nextTick() + const timeInput = wrapper.find<HTMLInputElement>('.time-input'); + await nextTick(); // 如果 v-mode 的时间超出 限制范围,将返回最小时间值 - expect(timeInput.element.value).toBe('01:04:30') - }) + expect(timeInput.element.value).toBe('01:04:30'); + }); it('time-picker max-time work', async () => { const wrapper = mount({ components: { DTimePicker }, template: `<d-time-picker max-time='22:46:20' v-model="vModelValue"></d-time-picker>`, setup() { - const vModelValue = ref('23:30:00') + const vModelValue = ref('23:30:00'); return { vModelValue - } + }; } - }) + }); - const timeInput = wrapper.find<HTMLInputElement>('.time-input') - await nextTick() - expect(timeInput.element.value).toBe('22:46:20') - }) + const timeInput = wrapper.find<HTMLInputElement>('.time-input'); + await nextTick(); + expect(timeInput.element.value).toBe('22:46:20'); + }); it('time-picker format mm:HH:ss work', async () => { const wrapper = mount({ components: { DTimePicker }, template: `<d-time-picker v-model="vModelValue" format='mm:HH:ss'></d-time-picker>`, setup() { - const vModelValue = ref('23:30:00') + const vModelValue = ref('23:30:00'); return { vModelValue - } + }; } - }) + }); - const timeInput = wrapper.find<HTMLInputElement>('.time-input') - await nextTick() - expect(timeInput.element.value).toBe('30:23:00') - }) + const timeInput = wrapper.find<HTMLInputElement>('.time-input'); + await nextTick(); + expect(timeInput.element.value).toBe('30:23:00'); + }); it('time-picker format mm:ss work', async () => { const wrapper = mount({ components: { DTimePicker }, template: `<d-time-picker v-model="vModelValue" format='mm:ss'></d-time-picker>`, setup() { - const vModelValue = ref('23:30:00') + const vModelValue = ref('23:30:00'); return { vModelValue - } + }; } - }) + }); - const timeInput = wrapper.find<HTMLInputElement>('.time-input') - await nextTick() - expect(timeInput.element.value).toBe('30:00') - }) + const timeInput = wrapper.find<HTMLInputElement>('.time-input'); + await nextTick(); + expect(timeInput.element.value).toBe('30:00'); + }); it('time-picker format hh:mm work', async () => { const wrapper = mount({ components: { DTimePicker }, template: `<d-time-picker v-model="vModelValue" format='hh:mm'></d-time-picker>`, setup() { - const vModelValue = ref('23:30:00') + const vModelValue = ref('23:30:00'); return { vModelValue - } + }; } - }) + }); - const timeInput = wrapper.find<HTMLInputElement>('.time-input') - await nextTick() - expect(timeInput.element.value).toBe('23:30') - }) + const timeInput = wrapper.find<HTMLInputElement>('.time-input'); + await nextTick(); + expect(timeInput.element.value).toBe('23:30'); + }); it('time-picker slot customViewTemplate work', async () => { - const slotDemo = ref() + const slotDemo = ref(); const chooseTime = () => { const timeObj = { time: '21', type: 'mm' - } - slotDemo.value.chooseTime(timeObj) - } + }; + slotDemo.value.chooseTime(timeObj); + }; // 插槽内方法 -- 选择当前时间 const chooseNowFun = () => { - const date = new Date() - const hour = date.getHours() > 9 ? date.getHours() : '0' + date.getHours() - const minute = date.getMinutes() > 9 ? date.getMinutes() : '0' + date.getMinutes() - const second = date.getSeconds() > 9 ? date.getSeconds() : '0' + date.getSeconds() + const date = new Date(); + const hour = date.getHours() > 9 ? date.getHours() : '0' + date.getHours(); + const minute = date.getMinutes() > 9 ? date.getMinutes() : '0' + date.getMinutes(); + const second = date.getSeconds() > 9 ? date.getSeconds() : '0' + date.getSeconds(); const timeObj = { time: hour + ':' + minute + ':' + second - } - slotDemo.value.chooseTime(timeObj) + }; + slotDemo.value.chooseTime(timeObj); - return timeObj.time - } + return timeObj.time; + }; const wrapper = mount({ components: { DTimePicker }, @@ -188,17 +188,17 @@ describe('time-picker test', () => { chooseNowFun, chooseTime, slotDemo - } + }; } - }) - - const timeInput = wrapper.find<HTMLInputElement>('.time-input') - const slotBottomNow = wrapper.find<HTMLElement>('.slot-bottom-now') - const slotBottomOne = wrapper.find<HTMLElement>('.slot-bottom-one') - await slotBottomNow.trigger('click') - expect(timeInput.element.value).toBe(chooseNowFun()) - - await slotBottomOne.trigger('click') - expect(timeInput.element.value).toMatch(/21/) - }) -}) + }); + + const timeInput = wrapper.find<HTMLInputElement>('.time-input'); + const slotBottomNow = wrapper.find<HTMLElement>('.slot-bottom-now'); + const slotBottomOne = wrapper.find<HTMLElement>('.slot-bottom-one'); + await slotBottomNow.trigger('click'); + expect(timeInput.element.value).toBe(chooseNowFun()); + + await slotBottomOne.trigger('click'); + expect(timeInput.element.value).toMatch(/21/); + }); +}); diff --git a/packages/devui-vue/devui/time-picker/index.ts b/packages/devui-vue/devui/time-picker/index.ts index 85c682ab4d..3cf7bfe110 100644 --- a/packages/devui-vue/devui/time-picker/index.ts +++ b/packages/devui-vue/devui/time-picker/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import TimePicker from './src/time-picker' +import type { App } from 'vue'; +import TimePicker from './src/time-picker'; TimePicker.install = function(app: App): void { - app.component(TimePicker.name, TimePicker) -} + app.component(TimePicker.name, TimePicker); +}; -export { TimePicker } +export { TimePicker }; export default { title: 'TimePicker 时间选择器', category: '数据录入', status: '90%', // TODO: 组件若开发完成则填入"已完成",并删除该注释 install(app: App): void { - app.use(TimePicker as any) + app.use(TimePicker as any); } -} +}; diff --git a/packages/devui-vue/devui/time-picker/src/components/popup-line/composables/use-popup-line.ts b/packages/devui-vue/devui/time-picker/src/components/popup-line/composables/use-popup-line.ts index 93f8a55d9c..756f00008a 100644 --- a/packages/devui-vue/devui/time-picker/src/components/popup-line/composables/use-popup-line.ts +++ b/packages/devui-vue/devui/time-picker/src/components/popup-line/composables/use-popup-line.ts @@ -1,240 +1,240 @@ -import { Ref, ref } from 'vue' -import { ArrType } from '../../../types' +import { Ref, ref } from 'vue'; +import { ArrType } from '../../../types'; const usePopupLine =( - hourListRef:Array<ArrType>,minuteListRef:Array<ArrType>,secondListRef:Array<ArrType>, - minTime:string,maxTime:string,format:string,timeListDom:Ref, - ):any =>{ + hourListRef: Array<ArrType>,minuteListRef: Array<ArrType>,secondListRef: Array<ArrType>, + minTime: string,maxTime: string,format: string,timeListDom: Ref, +): any =>{ - const activeTime = ref('00:00:00') - const activeHour = ref('00') - const activeMinute = ref('00') - const activeSecond = ref('00') + const activeTime = ref('00:00:00'); + const activeHour = ref('00'); + const activeMinute = ref('00'); + const activeSecond = ref('00'); - const activeTimeFun = (e:any, item:ArrType, index:number)=>{ + const activeTimeFun = (e: any, item: ArrType, index: number)=>{ if(item.isDisabled){ - return false + return false; }else{ - setTimeActive(item,index) - e.target.parentElement.parentElement.scrollTop = index * 32 + setTimeActive(item,index); + e.target.parentElement.parentElement.scrollTop = index * 32; } - } + }; - const setTimeActive = (item:ArrType,index:number)=>{ + const setTimeActive = (item: ArrType,index: number)=>{ - let activeTimeList = [] - let acitveTimeValue = ref('') + let activeTimeList = []; + let acitveTimeValue = ref(''); if(item.flag == 'hour'){ - activeTimeList = hourListRef - acitveTimeValue = activeHour - getItemAstrict(item) + activeTimeList = hourListRef; + acitveTimeValue = activeHour; + getItemAstrict(item); }else if(item.flag == 'minute'){ - activeTimeList = minuteListRef - acitveTimeValue = activeMinute - getItemAstrict(item) + activeTimeList = minuteListRef; + acitveTimeValue = activeMinute; + getItemAstrict(item); }else if(item.flag == 'second'){ - activeTimeList = secondListRef - acitveTimeValue = activeSecond + activeTimeList = secondListRef; + acitveTimeValue = activeSecond; } activeTimeList.map((tiemItem,tiemeIndex)=>{ - tiemItem.isActive = index === tiemeIndex - }) - acitveTimeValue.value = activeTimeList[index].time + tiemItem.isActive = index === tiemeIndex; + }); + acitveTimeValue.value = activeTimeList[index].time; - activeTime.value = `${activeHour.value}:${activeMinute.value}:${activeSecond.value}` - + activeTime.value = `${activeHour.value}:${activeMinute.value}:${activeSecond.value}`; + if(activeTime.value < minTime){ - activeTime.value = minTime - resetTimeValue(minTime) + activeTime.value = minTime; + resetTimeValue(minTime); }else if(format == 'mm:ss' && `${activeMinute.value}:${activeSecond.value}` > maxTime.slice(3)){ - const newMinTime = minTime.slice(0,3) + maxTime.slice(3) - resetTimeValue(newMinTime) + const newMinTime = minTime.slice(0,3) + maxTime.slice(3); + resetTimeValue(newMinTime); }else if(activeTime.value > maxTime){ - activeTime.value = maxTime - resetTimeValue(maxTime) + activeTime.value = maxTime; + resetTimeValue(maxTime); } - } + }; // 获取最大值 最小值 - const getItemAstrict = (item:ArrType):void=>{ - let min ='00' - let max ='00' + const getItemAstrict = (item: ArrType): void=>{ + let min ='00'; + let max ='00'; - const minTimeHour = minTime.split(':')[0] - const minTimeMinute = minTime.split(':')[1] - const minTimeSecond = minTime.split(':')[2] + const minTimeHour = minTime.split(':')[0]; + const minTimeMinute = minTime.split(':')[1]; + const minTimeSecond = minTime.split(':')[2]; - const maxTimeHour = maxTime.split(':')[0] - const maxTimeMinute = maxTime.split(':')[1] - const maxTimeSecond = maxTime.split(':')[2] + const maxTimeHour = maxTime.split(':')[0]; + const maxTimeMinute = maxTime.split(':')[1]; + const maxTimeSecond = maxTime.split(':')[2]; if(item.flag == 'hour'){ if(item.time == minTimeHour){ - min = minTimeMinute - setItemAstrict(minuteListRef,min,max) - activeMinute.value < minTimeMinute && setItemAstrict(secondListRef,minTimeSecond,max) - }else if ( item.time == maxTimeHour){ - max = maxTimeMinute - setItemAstrict(minuteListRef,min,max) - setItemAstrict(secondListRef,min,maxTimeSecond) + min = minTimeMinute; + setItemAstrict(minuteListRef,min,max); + activeMinute.value < minTimeMinute && setItemAstrict(secondListRef,minTimeSecond,max); + }else if (item.time == maxTimeHour){ + max = maxTimeMinute; + setItemAstrict(minuteListRef,min,max); + setItemAstrict(secondListRef,min,maxTimeSecond); }else{ - setItemAstrict(minuteListRef,min,max) - setItemAstrict(secondListRef,min,max) + setItemAstrict(minuteListRef,min,max); + setItemAstrict(secondListRef,min,max); } } if(item.flag == 'minute' && format == 'mm:ss'){ if(item.time == minTimeMinute){ - min = minTimeSecond - setItemAstrict(secondListRef,min,max) + min = minTimeSecond; + setItemAstrict(secondListRef,min,max); }else if(item.time == maxTimeMinute){ - max = maxTimeSecond - setItemAstrict(secondListRef,min,max) + max = maxTimeSecond; + setItemAstrict(secondListRef,min,max); } else{ - setItemAstrict(secondListRef,min,max) + setItemAstrict(secondListRef,min,max); } }else if(item.flag == 'minute'){ if(activeHour.value == minTimeHour && item.time == minTimeMinute){ - min = minTimeSecond - setItemAstrict(secondListRef,min,max) + min = minTimeSecond; + setItemAstrict(secondListRef,min,max); }else if(activeHour.value == maxTimeHour && item.time == maxTimeMinute){ - max = maxTimeSecond - setItemAstrict(secondListRef,min,max) + max = maxTimeSecond; + setItemAstrict(secondListRef,min,max); } else{ - setItemAstrict(secondListRef,min,max) + setItemAstrict(secondListRef,min,max); } } - } + }; // 设置最大值 最小值 - const setItemAstrict = (timeArr:Array<ArrType>,min:string,max:string) =>{ + const setItemAstrict = (timeArr: Array<ArrType>,min: string,max: string) =>{ timeArr.map(itme=>{ if(min !='00' && itme.time < min){ - itme.isDisabled = true + itme.isDisabled = true; }else if(max !='00' && itme.time > max){ - itme.isDisabled = true + itme.isDisabled = true; }else{ - itme.isDisabled = false + itme.isDisabled = false; } - }) - } + }); + }; // 指定时间 - const resetTimeValue = (time:string)=>{ - const timeValueArr = time.split(':') - const minTiveArr = minTime.split(':') + const resetTimeValue = (time: string)=>{ + const timeValueArr = time.split(':'); + const minTiveArr = minTime.split(':'); - let hh = 0 - let mm = 0 - let ss = 0 + let hh = 0; + let mm = 0; + let ss = 0; if(format == 'hh:mm:ss'){ - hh = parseInt(timeValueArr[0]) - mm = parseInt(timeValueArr[1]) - ss = parseInt(timeValueArr[2]) + hh = parseInt(timeValueArr[0]); + mm = parseInt(timeValueArr[1]); + ss = parseInt(timeValueArr[2]); - timeListDom.value.children[0].lastElementChild.children[0].scrollTop = hh * 32 - timeListDom.value.children[1].lastElementChild.children[0].scrollTop = mm * 32 - timeListDom.value.children[2].lastElementChild.children[0].scrollTop = ss * 32 + timeListDom.value.children[0].lastElementChild.children[0].scrollTop = hh * 32; + timeListDom.value.children[1].lastElementChild.children[0].scrollTop = mm * 32; + timeListDom.value.children[2].lastElementChild.children[0].scrollTop = ss * 32; - activeHour.value = timeValueArr[0] - activeMinute.value = timeValueArr[1] - activeSecond.value = timeValueArr[2] + activeHour.value = timeValueArr[0]; + activeMinute.value = timeValueArr[1]; + activeSecond.value = timeValueArr[2]; - resetTimeActive(hourListRef,timeValueArr[0]) - resetTimeActive(minuteListRef,timeValueArr[1]) - resetTimeActive(secondListRef,timeValueArr[2]) + resetTimeActive(hourListRef,timeValueArr[0]); + resetTimeActive(minuteListRef,timeValueArr[1]); + resetTimeActive(secondListRef,timeValueArr[2]); - resetTimeAstrict(hourListRef,activeHour.value) - resetTimeAstrict(minuteListRef,activeMinute.value) + resetTimeAstrict(hourListRef,activeHour.value); + resetTimeAstrict(minuteListRef,activeMinute.value); } else if(format == 'mm:hh:ss'){ - hh = parseInt(timeValueArr[0]) - mm = parseInt(timeValueArr[1]) - ss = parseInt(timeValueArr[2]) + hh = parseInt(timeValueArr[0]); + mm = parseInt(timeValueArr[1]); + ss = parseInt(timeValueArr[2]); - timeListDom.value.children[0].lastElementChild.children[0].scrollTop = mm * 32 - timeListDom.value.children[1].lastElementChild.children[0].scrollTop = hh * 32 - timeListDom.value.children[2].lastElementChild.children[0].scrollTop = ss * 32 + timeListDom.value.children[0].lastElementChild.children[0].scrollTop = mm * 32; + timeListDom.value.children[1].lastElementChild.children[0].scrollTop = hh * 32; + timeListDom.value.children[2].lastElementChild.children[0].scrollTop = ss * 32; - activeHour.value = timeValueArr[0] - activeMinute.value = timeValueArr[1] - activeSecond.value = timeValueArr[2] + activeHour.value = timeValueArr[0]; + activeMinute.value = timeValueArr[1]; + activeSecond.value = timeValueArr[2]; - resetTimeActive(hourListRef,timeValueArr[0]) - resetTimeActive(minuteListRef,timeValueArr[1]) - resetTimeActive(secondListRef,timeValueArr[2]) + resetTimeActive(hourListRef,timeValueArr[0]); + resetTimeActive(minuteListRef,timeValueArr[1]); + resetTimeActive(secondListRef,timeValueArr[2]); - resetTimeAstrict(hourListRef,activeHour.value) - resetTimeAstrict(minuteListRef,activeMinute.value) + resetTimeAstrict(hourListRef,activeHour.value); + resetTimeAstrict(minuteListRef,activeMinute.value); }else if(format == 'hh:mm'){ - hh = parseInt(timeValueArr[0]) - mm = parseInt(timeValueArr[1]) + hh = parseInt(timeValueArr[0]); + mm = parseInt(timeValueArr[1]); - timeListDom.value.children[0].lastElementChild.children[0].scrollTop = hh * 32 - timeListDom.value.children[1].lastElementChild.children[0].scrollTop = mm * 32 + timeListDom.value.children[0].lastElementChild.children[0].scrollTop = hh * 32; + timeListDom.value.children[1].lastElementChild.children[0].scrollTop = mm * 32; - activeHour.value = timeValueArr[0] - activeMinute.value = timeValueArr[1] + activeHour.value = timeValueArr[0]; + activeMinute.value = timeValueArr[1]; - resetTimeActive(hourListRef,timeValueArr[0]) - resetTimeActive(minuteListRef,timeValueArr[1]) + resetTimeActive(hourListRef,timeValueArr[0]); + resetTimeActive(minuteListRef,timeValueArr[1]); - resetTimeAstrict(hourListRef,activeHour.value) + resetTimeAstrict(hourListRef,activeHour.value); }else if(format == 'mm:ss'){ - - mm = parseInt(timeValueArr[1]) - ss = parseInt(timeValueArr[2]) - timeListDom.value.children[0].lastElementChild.children[0].scrollTop = mm * 32 - timeListDom.value.children[1].lastElementChild.children[0].scrollTop = ss * 32 + mm = parseInt(timeValueArr[1]); + ss = parseInt(timeValueArr[2]); + + timeListDom.value.children[0].lastElementChild.children[0].scrollTop = mm * 32; + timeListDom.value.children[1].lastElementChild.children[0].scrollTop = ss * 32; - activeHour.value = minTiveArr[0] - activeMinute.value = timeValueArr[1] - activeSecond.value = timeValueArr[2] + activeHour.value = minTiveArr[0]; + activeMinute.value = timeValueArr[1]; + activeSecond.value = timeValueArr[2]; - resetTimeActive(minuteListRef,timeValueArr[1]) - resetTimeActive(secondListRef,timeValueArr[2]) + resetTimeActive(minuteListRef,timeValueArr[1]); + resetTimeActive(secondListRef,timeValueArr[2]); - resetTimeAstrict(minuteListRef,activeMinute.value) + resetTimeAstrict(minuteListRef,activeMinute.value); } - } + }; // 解决清空之后,再次打开 最大值最小值限制范围失效 - const resetTimeAstrict = (timeArr:Array<ArrType>,time:string) =>{ + const resetTimeAstrict = (timeArr: Array<ArrType>,time: string) =>{ timeArr.map(item=>{ if(item.time == time){ - getItemAstrict(item) - } - }) - } + getItemAstrict(item); + } + }); + }; // 指定选中 - const resetTimeActive = (timeArr:Array<ArrType>,itemValue:string) =>{ - timeArr.map( item =>{ - item.isActive = item.time === itemValue - }) - } + const resetTimeActive = (timeArr: Array<ArrType>,itemValue: string) =>{ + timeArr.map(item =>{ + item.isActive = item.time === itemValue; + }); + }; - // 暂时返回选中 时 分 秒 + // 暂时返回选中 时 分 秒 const getNewTime = ()=>{ - return { activeTime,activeHour,activeMinute,activeSecond } - } + return { activeTime,activeHour,activeMinute,activeSecond }; + }; // 回到顶部 const resetScrollTop = ()=>{ for (let i = 0; i < timeListDom.value.children.length; i++) { - timeListDom.value.children[i].lastElementChild.children[0].scrollTop = 0 + timeListDom.value.children[i].lastElementChild.children[0].scrollTop = 0; } - } + }; return{ activeTime, @@ -245,12 +245,11 @@ const usePopupLine =( resetTimeValue, getNewTime, resetScrollTop - } -} + }; +}; -export { +export { usePopupLine -} - +}; diff --git a/packages/devui-vue/devui/time-picker/src/components/popup-line/index.tsx b/packages/devui-vue/devui/time-picker/src/components/popup-line/index.tsx index d13669b254..4604036d01 100644 --- a/packages/devui-vue/devui/time-picker/src/components/popup-line/index.tsx +++ b/packages/devui-vue/devui/time-picker/src/components/popup-line/index.tsx @@ -1,9 +1,9 @@ -import { ref, defineComponent, onMounted } from 'vue' -import { usePopupLine } from './composables/use-popup-line' -import { ArrType } from '../../types' -import TimeScroll from '../time-scroll' +import { ref, defineComponent, onMounted } from 'vue'; +import { usePopupLine } from './composables/use-popup-line'; +import { ArrType } from '../../types'; +import TimeScroll from '../time-scroll'; -import './index.scss' +import './index.scss'; export default defineComponent({ @@ -37,7 +37,7 @@ export default defineComponent({ }, setup(props,ctx,){ - const timeListDom = ref<Element>() + const timeListDom = ref<Element>(); const { getNewTime, activeTimeFun, @@ -51,60 +51,60 @@ export default defineComponent({ props.maxTime, props.format, timeListDom, - ) + ); - const setOutoTime = (time:string)=>{ - resetTimeValue(time) - } + const setOutoTime = (time: string)=>{ + resetTimeValue(time); + }; - const TimeLi = (timeArr:Array<ArrType>):any=>{ + const TimeLi = (timeArr: Array<ArrType>): any=>{ return ( timeArr.map((item: ArrType, index: number) => { return ( <li - class={`time-li ${item.flag}Id-${index} ${item.isActive ? 'active-li' : ''} ${item.isDisabled ? 'disabled-li' : ''}`} - onClick={(e) => { activeTimeFun(e, item, index,) }} - > - <span>{item.time}</span> + class={`time-li ${item.flag}Id-${index} ${item.isActive ? 'active-li' : ''} ${item.isDisabled ? 'disabled-li' : ''}`} + onClick={(e) => { activeTimeFun(e, item, index,); }} + > + <span>{item.time}</span> </li> - ) - }) - ) - } + ); + }) + ); + }; - const TimeUl = (timeList:Array<ArrType>)=>{ + const TimeUl = (timeList: Array<ArrType>)=>{ return ( - <div class='time-item' style={{'flex':1}}> - <TimeScroll> - <ul class='time-ul'> - {TimeLi(timeList)} - </ul> - </TimeScroll> - </div> - ) - } + <div class='time-item' style={{'flex':1}}> + <TimeScroll> + <ul class='time-ul'> + {TimeLi(timeList)} + </ul> + </TimeScroll> + </div> + ); + }; const formatTimeUl = ()=>{ const timeList = { - 'hh':props.hourList, - 'mm':props.minuteList, - 'ss':props.secondList - } + 'hh':props.hourList, + 'mm':props.minuteList, + 'ss':props.secondList + }; + + const timeFormatArr = (props.format as string).split(':'); - const timeFormatArr = (props.format as string).split(':') - return( timeFormatArr.map((timeItme)=>{ return( TimeUl(timeList[timeItme]) - ) + ); }) - ) - } + ); + }; ctx.expose({ resetScrollTop,setOutoTime,getNewTime - }) + }); return ()=>{ return ( @@ -113,10 +113,8 @@ export default defineComponent({ formatTimeUl() } </div> - ) - } + ); + }; } -}) - +}); - \ No newline at end of file diff --git a/packages/devui-vue/devui/time-picker/src/components/time-popup/index.tsx b/packages/devui-vue/devui/time-picker/src/components/time-popup/index.tsx index 8be6354235..cfe0f9a419 100644 --- a/packages/devui-vue/devui/time-picker/src/components/time-popup/index.tsx +++ b/packages/devui-vue/devui/time-picker/src/components/time-popup/index.tsx @@ -1,9 +1,9 @@ import { defineComponent, reactive, ref,watch ,onMounted} from 'vue'; -import { initializeTimeData,setTimeAstrict } from '../../utils' -import TimeList from '../popup-line/index' +import { initializeTimeData,setTimeAstrict } from '../../utils'; +import TimeList from '../popup-line/index'; import { Button } from '../../../../button/index'; -import './index.scss' +import './index.scss'; export default defineComponent({ name:'DTimePopup', components:{ @@ -45,68 +45,68 @@ export default defineComponent({ }, emits:['subData'], setup(props,ctx){ - const popupDome = ref<Node>() - const timeListDom = ref() - const hourList = initializeTimeData('hour') - const minuteList = initializeTimeData('minute') - const secondList = initializeTimeData('second') + const popupDome = ref<Node>(); + const timeListDom = ref(); + const hourList = initializeTimeData('hour'); + const minuteList = initializeTimeData('minute'); + const secondList = initializeTimeData('second'); onMounted(()=>{ - setTimeAstrict(hourList,minuteList,secondList,props.minTime,props.maxTime,props.popupFormat) - }) + setTimeAstrict(hourList,minuteList,secondList,props.minTime,props.maxTime,props.popupFormat); + }); watch(()=>[props.showPopup,props.bindData],([showPopup,newTimeVal],[oldShowPopup,oldTimeVal])=>{ if(showPopup || newTimeVal != oldTimeVal){ - timeListDom.value.setOutoTime(newTimeVal) + timeListDom.value.setOutoTime(newTimeVal); }else{ - timeListDom.value.resetScrollTop() + timeListDom.value.resetScrollTop(); } - }) + }); const changTimeData = ()=>{ - return timeListDom.value.getNewTime() - } + return timeListDom.value.getNewTime(); + }; - const subDataFun = (e:MouseEvent)=>{ - e.stopPropagation() - ctx.emit('subData') - } + const subDataFun = (e: MouseEvent)=>{ + e.stopPropagation(); + ctx.emit('subData'); + }; ctx.expose({ changTimeData - }) + }); return()=>{ return( <> - <div ref={popupDome} - class={`devui-time-popup ${props.showPopup ? 'devui-show-time-popup' : ''}`} + <div ref={popupDome} + class={`devui-time-popup ${props.showPopup ? 'devui-show-time-popup' : ''}`} style={{'width': props.popupWidth + 'px','top':props.popupTop+'px','left':props.popupLeft+'px'}}> - <TimeList - ref={timeListDom} - hourList={hourList} - minuteList={minuteList} - secondList={secondList} - minTime={props.minTime} - maxTime={props.maxTime} - format={props.popupFormat} - /> - - <div class="devui-time-popup-btn" > - <div class='popup-slots'> - { - ctx.slots.default?.() - } - </div> - <div onClick={subDataFun}> - <Button variant="common">确定</Button> - </div> - + <TimeList + ref={timeListDom} + hourList={hourList} + minuteList={minuteList} + secondList={secondList} + minTime={props.minTime} + maxTime={props.maxTime} + format={props.popupFormat} + /> + + <div class="devui-time-popup-btn" > + <div class='popup-slots'> + { + ctx.slots.default?.() + } </div> + <div onClick={subDataFun}> + <Button variant="common">确定</Button> + </div> + + </div> </div> </> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/time-picker/src/components/time-scroll/composables/use-time-scroll.ts b/packages/devui-vue/devui/time-picker/src/components/time-scroll/composables/use-time-scroll.ts index 71234bdabe..1fe3de77ea 100644 --- a/packages/devui-vue/devui/time-picker/src/components/time-scroll/composables/use-time-scroll.ts +++ b/packages/devui-vue/devui/time-picker/src/components/time-scroll/composables/use-time-scroll.ts @@ -1,63 +1,63 @@ -import { ref } from 'vue' +import { ref } from 'vue'; -export default function useTimeScroll():any{ - const scrollBoxDom = ref() - const scrollContentDom = ref() - const scrollThumbDom = ref() - const scrollTrackDom = ref() +export default function useTimeScroll(): any{ + const scrollBoxDom = ref(); + const scrollContentDom = ref(); + const scrollThumbDom = ref(); + const scrollTrackDom = ref(); - const isDown = ref(false) + const isDown = ref(false); - // 获取滚动条 thumb高度 + // 获取滚动条 thumb高度 const getScrollHeight=()=>{ - const thumbHeight = (scrollContentDom.value.clientHeight / scrollContentDom.value.scrollHeight) * 100 - scrollThumbDom.value.style.height = thumbHeight + '%' - } - + const thumbHeight = (scrollContentDom.value.clientHeight / scrollContentDom.value.scrollHeight) * 100; + scrollThumbDom.value.style.height = thumbHeight + '%'; + }; + // 设置滚动条 thumb位置 const setVirtualScroll =()=>{ const thumbMoveY = (scrollContentDom.value.scrollTop * 100 / scrollContentDom.value.clientHeight); - scrollThumbDom.value.style.transform = `translateY(${thumbMoveY}%)` - } + scrollThumbDom.value.style.transform = `translateY(${thumbMoveY}%)`; + }; // 点击轨道 thumb滚动到相应位置 - const clickTrackFun = (e:MouseEvent)=>{ - const offsetNum = scrollTrackDom.value.getBoundingClientRect().top - e.clientY - const offset = Math.abs(offsetNum > 0 ? 0 : offsetNum) + const clickTrackFun = (e: MouseEvent)=>{ + const offsetNum = scrollTrackDom.value.getBoundingClientRect().top - e.clientY; + const offset = Math.abs(offsetNum > 0 ? 0 : offsetNum); const thumbCenter = scrollThumbDom.value.offsetHeight / 2; const thumbPosition = (offset - thumbCenter) * 100 / scrollContentDom.value.offsetHeight; scrollContentDom.value.scrollTop = (thumbPosition * scrollContentDom.value.scrollHeight / 100); - scrollContentDom.value.style.top = scrollContentDom.value.scrollTop + 'px' - } - + scrollContentDom.value.style.top = scrollContentDom.value.scrollTop + 'px'; + }; + // 鼠标拖到 const mouseDownThum = ()=>{ - isDown.value = true - scrollTrackDom.value.style.opacity = 1 - } + isDown.value = true; + scrollTrackDom.value.style.opacity = 1; + }; // 鼠标离开 - const mouseOutThum = (e:MouseEvent)=>{ - isDown.value = false - thumbMouseMove(e) - } - - const thumbMouseMove = (e:any)=>{ - const path = (e.composedPath && e.composedPath()) || e.path + const mouseOutThum = (e: MouseEvent)=>{ + isDown.value = false; + thumbMouseMove(e); + }; + + const thumbMouseMove = (e: any)=>{ + const path = (e.composedPath && e.composedPath()) || e.path; if(path.includes(scrollBoxDom.value) || isDown.value){ - scrollTrackDom.value.style.opacity = 1 + scrollTrackDom.value.style.opacity = 1; }else{ - scrollTrackDom.value.style.opacity = 0 + scrollTrackDom.value.style.opacity = 0; } - if( !isDown.value ) return - clickTrackFun(e) - } + if(!isDown.value) {return;} + clickTrackFun(e); + }; const getScrollWidth=()=>{ - const ua = navigator.userAgent - let marginRight = -20 + const ua = navigator.userAgent; + let marginRight = -20; if (ua.indexOf('Chrome') > -1) { - marginRight = -8 + marginRight = -8; }else{ const outer = document.createElement('div'); outer.className = 'devui-scrollbar-wrap'; @@ -79,14 +79,14 @@ export default function useTimeScroll():any{ marginRight = (widthNoScroll - widthWithScroll + 3) * -1; } - - return marginRight - } + + return marginRight; + }; return{ scrollThumbDom,scrollTrackDom,scrollContentDom,scrollBoxDom,isDown, getScrollHeight,setVirtualScroll,clickTrackFun,mouseDownThum,mouseOutThum,thumbMouseMove, getScrollWidth - } -} \ No newline at end of file + }; +} diff --git a/packages/devui-vue/devui/time-picker/src/components/time-scroll/index.tsx b/packages/devui-vue/devui/time-picker/src/components/time-scroll/index.tsx index 14aff80286..ace6878f42 100644 --- a/packages/devui-vue/devui/time-picker/src/components/time-scroll/index.tsx +++ b/packages/devui-vue/devui/time-picker/src/components/time-scroll/index.tsx @@ -1,8 +1,8 @@ -import { defineComponent, onBeforeUnmount, onMounted, onUnmounted } from 'vue' -import { TimePickerProps, timePickerProps } from '../../time-picker-types' -import useTimeScroll from './composables/use-time-scroll' +import { defineComponent, onBeforeUnmount, onMounted, onUnmounted } from 'vue'; +import { TimePickerProps, timePickerProps } from '../../time-picker-types'; +import useTimeScroll from './composables/use-time-scroll'; -import './index.scss' +import './index.scss'; export default defineComponent({ name:'DTimeScroll', @@ -20,37 +20,37 @@ export default defineComponent({ mouseOutThum, thumbMouseMove, getScrollWidth - }=useTimeScroll() - const marginRight = getScrollWidth() + }=useTimeScroll(); + const marginRight = getScrollWidth(); onMounted(()=>{ - getScrollWidth() - getScrollHeight() - scrollBoxDom.value.addEventListener('click',setVirtualScroll) - scrollContentDom.value.addEventListener('scroll',setVirtualScroll) - scrollThumbDom.value.addEventListener('mousedown',mouseDownThum) - document.addEventListener('mouseup',mouseOutThum) - document.addEventListener('mousemove',thumbMouseMove) - }) + getScrollWidth(); + getScrollHeight(); + scrollBoxDom.value.addEventListener('click',setVirtualScroll); + scrollContentDom.value.addEventListener('scroll',setVirtualScroll); + scrollThumbDom.value.addEventListener('mousedown',mouseDownThum); + document.addEventListener('mouseup',mouseOutThum); + document.addEventListener('mousemove',thumbMouseMove); + }); onBeforeUnmount(()=>{ - scrollBoxDom.value.removeEventListener('click',setVirtualScroll) - scrollContentDom.value.removeEventListener('scroll',setVirtualScroll) - scrollThumbDom.value.removeEventListener('mousedown',mouseDownThum) - }) + scrollBoxDom.value.removeEventListener('click',setVirtualScroll); + scrollContentDom.value.removeEventListener('scroll',setVirtualScroll); + scrollThumbDom.value.removeEventListener('mousedown',mouseDownThum); + }); onUnmounted(()=>{ - document.removeEventListener('mouseup',mouseOutThum) - document.removeEventListener('mousemove',thumbMouseMove) - }) + document.removeEventListener('mouseup',mouseOutThum); + document.removeEventListener('mousemove',thumbMouseMove); + }); return()=>{ return ( <> <div ref={scrollBoxDom} class="devui-scroll-box"> - <div ref={scrollContentDom} class={`box-content ${ isDown.value || !props.showAnimation ? 'box-content-behavior-auto':''}`} + <div ref={scrollContentDom} class={`box-content ${ isDown.value || !props.showAnimation ? 'box-content-behavior-auto':''}`} style={{'margin-right': marginRight + 'px'}}> - { - ctx.slots.default?.() - } + { + ctx.slots.default?.() + } </div> <div ref={scrollTrackDom} class="box-sroll" onClick={clickTrackFun}> @@ -58,7 +58,7 @@ export default defineComponent({ </div> </div> </> - ) - } + ); + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/time-picker/src/composables/use-time-picker.ts b/packages/devui-vue/devui/time-picker/src/composables/use-time-picker.ts index 4f66a8928e..e9851c1bd8 100644 --- a/packages/devui-vue/devui/time-picker/src/composables/use-time-picker.ts +++ b/packages/devui-vue/devui/time-picker/src/composables/use-time-picker.ts @@ -1,161 +1,161 @@ -import { Ref, ref } from 'vue' -import { TimeObj } from '../types' -import { getPositionFun } from '../utils' +import { Ref, ref } from 'vue'; +import { TimeObj } from '../types'; +import { getPositionFun } from '../utils'; export default function useTimePicker( - hh:Ref,mm:Ref,ss:Ref,minTime:string,maxTime:string,format:string, - autoOpen:boolean,disabled:boolean,value:string - ):any{ - const isActive = ref(false) - const showPopup = ref(false) - const devuiTimePicker = ref() - const inputDom = ref() - const left = ref(-100) - const top = ref(-100) - const timePopupDom = ref() - const timePickerValue = ref('') - const showClearIcon = ref(false) - const firsthandActiveTime = ref(`${hh.value}:${mm.value}:${ss.value}`) - const vModeValue = ref(value) + hh: Ref,mm: Ref,ss: Ref,minTime: string,maxTime: string,format: string, + autoOpen: boolean,disabled: boolean,value: string +): any{ + const isActive = ref(false); + const showPopup = ref(false); + const devuiTimePicker = ref(); + const inputDom = ref(); + const left = ref(-100); + const top = ref(-100); + const timePopupDom = ref(); + const timePickerValue = ref(''); + const showClearIcon = ref(false); + const firsthandActiveTime = ref(`${hh.value}:${mm.value}:${ss.value}`); + const vModeValue = ref(value); const getPopupPosition = ()=>{ - getPositionFun(devuiTimePicker.value,left,top) - } + getPositionFun(devuiTimePicker.value,left,top); + }; const clickVerifyFun = (e: any) => { - e.stopPropagation() - isActive.value = false - showPopup.value = false + e.stopPropagation(); + isActive.value = false; + showPopup.value = false; - if(disabled) return + if(disabled) {return;} - const path = (e.composedPath && e.composedPath()) || e.path - const inInputDom = path.includes(devuiTimePicker.value) - inInputDom && mouseInIputFun() - } + const path = (e.composedPath && e.composedPath()) || e.path; + const inInputDom = path.includes(devuiTimePicker.value); + inInputDom && mouseInIputFun(); + }; const mouseInIputFun = ()=>{ if(firsthandActiveTime.value == '00:00:00'){ - const vModelValueArr = value.split(':') - const minTimeValueArr = minTime.split(':') - const maxTimeValueArr = maxTime.split(':') + const vModelValueArr = value.split(':'); + const minTimeValueArr = minTime.split(':'); + const maxTimeValueArr = maxTime.split(':'); vModeValue.value == '' - ? vModeValue.value = '00:00:00' - : '' - - if( value > minTime && value < maxTime){ - firsthandActiveTime.value = value - setInputValue(vModelValueArr[0],vModelValueArr[1],vModelValueArr[2]) - }else if( value > maxTime ){ - firsthandActiveTime.value = maxTime - setInputValue(maxTimeValueArr[0],maxTimeValueArr[1],maxTimeValueArr[2]) + ? vModeValue.value = '00:00:00' + : ''; + + if(value > minTime && value < maxTime){ + firsthandActiveTime.value = value; + setInputValue(vModelValueArr[0],vModelValueArr[1],vModelValueArr[2]); + }else if(value > maxTime){ + firsthandActiveTime.value = maxTime; + setInputValue(maxTimeValueArr[0],maxTimeValueArr[1],maxTimeValueArr[2]); }else{ - firsthandActiveTime.value = minTime - setInputValue(minTimeValueArr[0],minTimeValueArr[1],minTimeValueArr[2]) + firsthandActiveTime.value = minTime; + setInputValue(minTimeValueArr[0],minTimeValueArr[1],minTimeValueArr[2]); } } - isActive.value = true - showPopup.value = true - } + isActive.value = true; + showPopup.value = true; + }; /** * 判断v-model 绑定的时间是否超出 最大值 最小值 范围 * 如果带有格式化 , 将执行格式化 - * */ + * */ const vModelIsBeyond = ()=>{ if(vModeValue.value != '' && vModeValue.value < minTime){ - vModeValue.value = minTime - }else if( vModeValue.value != '' && vModeValue.value > maxTime ){ - vModeValue.value = maxTime + vModeValue.value = minTime; + }else if(vModeValue.value != '' && vModeValue.value > maxTime){ + vModeValue.value = maxTime; } - const vModelValueArr = vModeValue.value.split(':') - vModeValue.value && setInputValue(vModelValueArr[0],vModelValueArr[1],vModelValueArr[2]) - - } - + const vModelValueArr = vModeValue.value.split(':'); + vModeValue.value && setInputValue(vModelValueArr[0],vModelValueArr[1],vModelValueArr[2]); - const getTimeValue = (e:MouseEvent)=>{ - e.stopPropagation() + }; + + + const getTimeValue = (e: MouseEvent)=>{ + e.stopPropagation(); if(showPopup.value){ - hh.value = timePopupDom.value.changTimeData().activeHour.value - mm.value = timePopupDom.value.changTimeData().activeMinute.value - ss.value = timePopupDom.value.changTimeData().activeSecond.value - firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}` - setInputValue(hh.value,mm.value,ss.value) + hh.value = timePopupDom.value.changTimeData().activeHour.value; + mm.value = timePopupDom.value.changTimeData().activeMinute.value; + ss.value = timePopupDom.value.changTimeData().activeSecond.value; + firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}`; + setInputValue(hh.value,mm.value,ss.value); } - } + }; - const setInputValue = (hh:string,mm:string,ss:string)=> { + const setInputValue = (hh: string,mm: string,ss: string)=> { if(format == 'hh:mm:ss'){ - vModeValue.value = `${hh}:${mm}:${ss}` + vModeValue.value = `${hh}:${mm}:${ss}`; }else if(format == 'mm:hh:ss'){ - vModeValue.value = `${mm}:${hh}:${ss}` + vModeValue.value = `${mm}:${hh}:${ss}`; }else if(format == 'hh:mm'){ - vModeValue.value = `${hh}:${mm}` + vModeValue.value = `${hh}:${mm}`; }else if(format == 'mm:ss'){ - vModeValue.value = `${mm}:${ss}` + vModeValue.value = `${mm}:${ss}`; } - } + }; - const clearAll = (e:MouseEvent)=>{ - e.stopPropagation() - showPopup.value = false + const clearAll = (e: MouseEvent)=>{ + e.stopPropagation(); + showPopup.value = false; if(minTime != '00:00:00'){ - const minTimeArr = minTime.split(':') - hh.value = minTimeArr[0] - mm.value = minTimeArr[1] - ss.value = minTimeArr[2] + const minTimeArr = minTime.split(':'); + hh.value = minTimeArr[0]; + mm.value = minTimeArr[1]; + ss.value = minTimeArr[2]; }else{ - hh.value = '00' - mm.value = '00' - ss.value = '00' + hh.value = '00'; + mm.value = '00'; + ss.value = '00'; } - firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}` - setInputValue(hh.value,mm.value,ss.value) - } + firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}`; + setInputValue(hh.value,mm.value,ss.value); + }; const isOutOpen =()=>{ if(autoOpen){ - - const timeArr = vModeValue.value.split(':') - hh.value = timeArr[0] - mm.value = timeArr[1] - ss.value = timeArr[2] - firsthandActiveTime.value = vModeValue.value + const timeArr = vModeValue.value.split(':'); + hh.value = timeArr[0]; + mm.value = timeArr[1]; + ss.value = timeArr[2]; + + firsthandActiveTime.value = vModeValue.value; - setInputValue(hh.value,mm.value,ss.value) + setInputValue(hh.value,mm.value,ss.value); - isActive.value = true - showPopup.value = autoOpen + isActive.value = true; + showPopup.value = autoOpen; } - } + }; // slot -- 选择时间 - const chooseTime = (slotTime:TimeObj) => { + const chooseTime = (slotTime: TimeObj) => { if (slotTime.type) { if (slotTime.type.toLowerCase() == 'hh') { - hh.value = slotTime.time + hh.value = slotTime.time; } else if (slotTime.type.toLowerCase() == 'mm') { - mm.value = slotTime.time + mm.value = slotTime.time; } else if (slotTime.type.toLowerCase() == 'ss') { - ss.value = slotTime.time + ss.value = slotTime.time; } - firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}` - setInputValue(hh.value,mm.value,ss.value) + firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}`; + setInputValue(hh.value,mm.value,ss.value); } else { - const timeArr = slotTime.time.split(':') - hh.value = timeArr[0] - mm.value = timeArr[1] - ss.value = timeArr[2] - firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}` - setInputValue(hh.value,mm.value,ss.value) + const timeArr = slotTime.time.split(':'); + hh.value = timeArr[0]; + mm.value = timeArr[1]; + ss.value = timeArr[2]; + firsthandActiveTime.value = `${hh.value}:${mm.value}:${ss.value}`; + setInputValue(hh.value,mm.value,ss.value); } - } + }; return { isActive, @@ -175,5 +175,5 @@ export default function useTimePicker( vModelIsBeyond, clearAll, chooseTime - } -} \ No newline at end of file + }; +} diff --git a/packages/devui-vue/devui/time-picker/src/time-picker-types.ts b/packages/devui-vue/devui/time-picker/src/time-picker-types.ts index 121d3fecc9..3e71cee67a 100644 --- a/packages/devui-vue/devui/time-picker/src/time-picker-types.ts +++ b/packages/devui-vue/devui/time-picker/src/time-picker-types.ts @@ -1,43 +1,43 @@ import { ExtractPropTypes, PropType } from 'vue'; export const timePickerProps = { - modelValue:{ - type: String, - default: '' - }, - placeholder: { - type: String, - default: '00:00:00' - }, - disabled: { - type: Boolean, - default: false - }, - timePickerWidth: { - type: Number, - default: 212 - }, - minTime: { - type: String, - default: '00:00:00' - // 默认时间优先级:minTime > modelValue - }, - maxTime: { - type: String, - default: '23:59:59' - }, - format:{ - type:String, - default:'hh:mm:ss' - }, - autoOpen:{ - type:Boolean, - default:false - }, - showAnimation:{ - type:Boolean, - default:true - } + modelValue:{ + type: String, + default: '' + }, + placeholder: { + type: String, + default: '00:00:00' + }, + disabled: { + type: Boolean, + default: false + }, + timePickerWidth: { + type: Number, + default: 212 + }, + minTime: { + type: String, + default: '00:00:00' + // 默认时间优先级:minTime > modelValue + }, + maxTime: { + type: String, + default: '23:59:59' + }, + format:{ + type:String, + default:'hh:mm:ss' + }, + autoOpen:{ + type:Boolean, + default:false + }, + showAnimation:{ + type:Boolean, + default:true + } } as const; export type TimePickerProps = ExtractPropTypes<typeof timePickerProps>; diff --git a/packages/devui-vue/devui/time-picker/src/time-picker.tsx b/packages/devui-vue/devui/time-picker/src/time-picker.tsx index 15be03e08c..cc0ddf26c4 100644 --- a/packages/devui-vue/devui/time-picker/src/time-picker.tsx +++ b/packages/devui-vue/devui/time-picker/src/time-picker.tsx @@ -1,10 +1,10 @@ -import { defineComponent, ref, onMounted, onUnmounted, watch } from 'vue' -import { TimePickerProps, timePickerProps } from './time-picker-types' -import { Icon } from '../../icon' -import useTimePicker from './composables/use-time-picker' -import TimePopup from './components/time-popup/index' +import { defineComponent, ref, onMounted, onUnmounted, watch } from 'vue'; +import { TimePickerProps, timePickerProps } from './time-picker-types'; +import { Icon } from '../../icon'; +import useTimePicker from './composables/use-time-picker'; +import TimePopup from './components/time-popup/index'; -import './time-picker.scss' +import './time-picker.scss'; export default defineComponent({ name: 'DTimePicker', @@ -13,12 +13,12 @@ export default defineComponent({ emits: ['selectedTimeChage','update:modelValue'], setup(props: TimePickerProps, ctx) { - const activeHour = ref('00') - const activeMinute = ref('00') - const activeSecond = ref('00') - const format = props.format.toLowerCase() + const activeHour = ref('00'); + const activeMinute = ref('00'); + const activeSecond = ref('00'); + const format = props.format.toLowerCase(); - const { + const { isActive, showPopup, devuiTimePicker, @@ -35,55 +35,55 @@ export default defineComponent({ timePopupDom, vModeValue, getPopupPosition - } = useTimePicker(activeHour,activeMinute,activeSecond,props.minTime,props.maxTime,format,props.autoOpen,props.disabled,props.modelValue) + } = useTimePicker(activeHour,activeMinute,activeSecond,props.minTime,props.maxTime,format,props.autoOpen,props.disabled,props.modelValue); - const selectedTimeChage = (e:MouseEvent) => { - isActive.value = false - showPopup.value = false - ctx.emit('selectedTimeChage', vModeValue.value) - } + const selectedTimeChage = (e: MouseEvent) => { + isActive.value = false; + showPopup.value = false; + ctx.emit('selectedTimeChage', vModeValue.value); + }; onMounted(() => { - getPopupPosition() - isOutOpen() - vModelIsBeyond() - document.addEventListener('click', clickVerifyFun) - document.addEventListener('click',getTimeValue) - document.addEventListener('scroll',getPopupPosition) - window.addEventListener('resize',getPopupPosition) - }) + getPopupPosition(); + isOutOpen(); + vModelIsBeyond(); + document.addEventListener('click', clickVerifyFun); + document.addEventListener('click',getTimeValue); + document.addEventListener('scroll',getPopupPosition); + window.addEventListener('resize',getPopupPosition); + }); onUnmounted(() => { - document.removeEventListener('click', clickVerifyFun) - document.removeEventListener('click',getTimeValue) - document.removeEventListener('scroll',getPopupPosition) - window.removeEventListener('resize',getPopupPosition) - }) + document.removeEventListener('click', clickVerifyFun); + document.removeEventListener('click',getTimeValue); + document.removeEventListener('scroll',getPopupPosition); + window.removeEventListener('resize',getPopupPosition); + }); - watch(vModeValue,(newValue:string)=>{ - ctx.emit('update:modelValue',vModeValue.value) + watch(vModeValue,(newValue: string)=>{ + ctx.emit('update:modelValue',vModeValue.value); if(newValue != props.minTime && newValue != '00:00'){ - showClearIcon.value = true + showClearIcon.value = true; }else{ - showClearIcon.value = false + showClearIcon.value = false; } - }) + }); ctx.expose({ clearAll,chooseTime - }) + }); return () => { return ( <> <div class={`devui-time-picker ${isActive.value ? 'time-picker-active' : ''} ${props.disabled ? 'picker-disabled' : ''}`} - ref={devuiTimePicker} - > - <TimePopup + ref={devuiTimePicker} + > + <TimePopup ref={timePopupDom} - showPopup={showPopup.value} - popupTop={top.value} - popupLeft={left.value} + showPopup={showPopup.value} + popupTop={top.value} + popupLeft={left.value} popupWidth={props.timePickerWidth} popupFormat={ props.format.toLowerCase() } minTime={props.minTime} @@ -105,7 +105,7 @@ export default defineComponent({ <div onClick={clearAll}> { showClearIcon.value - ? <Icon size="small" name="close" /> + ? <Icon size="small" name="close" /> :'' } </div> @@ -115,7 +115,7 @@ export default defineComponent({ </div> </div> </> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/time-picker/src/types.ts b/packages/devui-vue/devui/time-picker/src/types.ts index 8c02163b66..66abcd5488 100644 --- a/packages/devui-vue/devui/time-picker/src/types.ts +++ b/packages/devui-vue/devui/time-picker/src/types.ts @@ -1,14 +1,14 @@ export type timeType = 'hh' | 'HH' | 'mm' | 'MM' | 'ss' | 'SS'; export type TimeObj = { - time: string - type?: timeType -} + time: string; + type?: timeType; +}; export type ArrType = { - type:'hour' | 'minute' | 'seconde' - isActive:boolean - isDisabled:boolean - time:string - flag:string -} + type: 'hour' | 'minute' | 'seconde'; + isActive: boolean; + isDisabled: boolean; + time: string; + flag: string; +}; diff --git a/packages/devui-vue/devui/time-picker/src/utils.ts b/packages/devui-vue/devui/time-picker/src/utils.ts index 16260778dc..ad00642f25 100644 --- a/packages/devui-vue/devui/time-picker/src/utils.ts +++ b/packages/devui-vue/devui/time-picker/src/utils.ts @@ -1,21 +1,21 @@ -import { Ref , reactive} from 'vue' -import { ArrType } from './types' +import { Ref , reactive} from 'vue'; +import { ArrType } from './types'; /** - * 动态调整弹窗位置 - * @param element + * 动态调整弹窗位置 + * @param element * @returns { top , left } */ -export function getPositionFun(el:Element,left:Ref,top:Ref):any{ - const inputDom = el.getBoundingClientRect() - const button = window.innerHeight - (inputDom.top + 20) - if(button > inputDom.top + 20){ - left.value = inputDom.x - top.value = inputDom.top + 20 + 10 - }else{ - left.value = inputDom.x - top.value = inputDom.top - 316 - } +export function getPositionFun(el: Element,left: Ref,top: Ref): any{ + const inputDom = el.getBoundingClientRect(); + const button = window.innerHeight - (inputDom.top + 20); + if(button > inputDom.top + 20){ + left.value = inputDom.x; + top.value = inputDom.top + 20 + 10; + }else{ + left.value = inputDom.x; + top.value = inputDom.top - 316; + } } /** @@ -24,23 +24,23 @@ export function getPositionFun(el:Element,left:Ref,top:Ref):any{ * @returns Array<time> */ -export function initializeTimeData(type:string):any{ - const timeArr = reactive([]) - let arrLenght = 0 +export function initializeTimeData(type: string): any{ + const timeArr = reactive([]); + let arrLenght = 0; if(type == 'hour'){ - arrLenght = 24 + arrLenght = 24; }else{ - arrLenght = 60 + arrLenght = 60; } for (let i = 0; i < arrLenght; i++) { timeArr.push({ - time:i<10?'0'+i:i+'', - isActive:false, - flag:type, - isDisabled:false - }) + time:i<10?'0'+i:i+'', + isActive:false, + flag:type, + isDisabled:false + }); } - return timeArr + return timeArr; } /** @@ -52,44 +52,44 @@ export function initializeTimeData(type:string):any{ * @param farmat */ export const setTimeAstrict = ( - hourList:Array<ArrType>, - minuteList:Array<ArrType>, - secondList:Array<ArrType>, - minTime:string, - maxTime:string, - format:string):void=>{ + hourList: Array<ArrType>, + minuteList: Array<ArrType>, + secondList: Array<ArrType>, + minTime: string, + maxTime: string, + format: string): void=>{ - const maxTimeHour = maxTime.split(':')[0] - const maxTimeMinute = maxTime.split(':')[1] - const minTimeHour = minTime.split(':')[0] - const minTimeMinute = minTime.split(':')[1] - const minTimeSecond = minTime.split(':')[2] + const maxTimeHour = maxTime.split(':')[0]; + const maxTimeMinute = maxTime.split(':')[1]; + const minTimeHour = minTime.split(':')[0]; + const minTimeMinute = minTime.split(':')[1]; + const minTimeSecond = minTime.split(':')[2]; hourList.map((item,index)=>{ - if(item.time < minTimeHour || item.time > maxTimeHour ){ - item.isDisabled = true + if(item.time < minTimeHour || item.time > maxTimeHour){ + item.isDisabled = true; } - }) - + }); + // 如果为mm:ss格式,限制小时的选择范围 if(format == 'mm:ss'){ minuteList.map((item,index)=>{ - if(item.time < minTimeMinute || item.time > maxTimeMinute ){ - item.isDisabled = true + if(item.time < minTimeMinute || item.time > maxTimeMinute){ + item.isDisabled = true; } - }) + }); }else{ minuteList.map((item,index)=>{ - if(item.time < minTimeMinute ){ - item.isDisabled = true + if(item.time < minTimeMinute){ + item.isDisabled = true; } - }) + }); } secondList.map((item,index)=>{ - if(item.time < minTimeSecond ){ - item.isDisabled = true + if(item.time < minTimeSecond){ + item.isDisabled = true; } - }) -} + }); +}; diff --git a/packages/devui-vue/devui/timeline/__tests__/timeline.spec.ts b/packages/devui-vue/devui/timeline/__tests__/timeline.spec.ts index 6400b1ec26..25c6a5ac2f 100644 --- a/packages/devui-vue/devui/timeline/__tests__/timeline.spec.ts +++ b/packages/devui-vue/devui/timeline/__tests__/timeline.spec.ts @@ -1,6 +1,6 @@ import { mount } from '@vue/test-utils'; import DTimeline from '../src/timeline'; -import DTimelineItem from '../src/components/timeline-item' +import DTimelineItem from '../src/components/timeline-item'; describe('timeline test', () => { const wrapper = mount({ components: { DTimeline, DTimelineItem }, @@ -19,40 +19,40 @@ describe('timeline test', () => { </d-timeline> `, setup() { - return + return; } }); - const timeAxisItems = wrapper.findAll('.devui-timeline-item') + const timeAxisItems = wrapper.findAll('.devui-timeline-item'); it('should render correctly', async () => { - //渲染的dom元素是有这个class - expect(wrapper.classes()).toContain('devui-timeline') - //渲染正确子节点数 - expect(timeAxisItems.length).toBe(5) - //看时间是否正确 - expect(timeAxisItems[0].find('.devui-timeline-item-time').text()).toBe('2021-11-9') - //看内容是否正确 - expect(timeAxisItems[0].find('.devui-timeline-item-content').text()).toBe('测试1') - }) + // 渲染的dom元素是有这个class + expect(wrapper.classes()).toContain('devui-timeline'); + // 渲染正确子节点数 + expect(timeAxisItems.length).toBe(5); + // 看时间是否正确 + expect(timeAxisItems[0].find('.devui-timeline-item-time').text()).toBe('2021-11-9'); + // 看内容是否正确 + expect(timeAxisItems[0].find('.devui-timeline-item-content').text()).toBe('测试1'); + }); it('Custom content should be displayed', async () => { - //有自定义的时间节点 - expect(timeAxisItems[1].find('.devui-timeline-item-time div').html()).toBe('<div>2021-11-10</div>') - //有自定义的内容 - expect(timeAxisItems[1].find('.devui-timeline-item-content div').html()).toBe('<div>测试2</div>') - //显示自定义时间点 - expect(timeAxisItems[1].find('.devui-timeline-item-dot i').exists()).toBe(true) - //显示时间点间的附加元素 - expect(timeAxisItems[1].find('.devui-timeline-item-line-extra span').html()).toBe('<span>附加元素</span>') - }) + // 有自定义的时间节点 + expect(timeAxisItems[1].find('.devui-timeline-item-time div').html()).toBe('<div>2021-11-10</div>'); + // 有自定义的内容 + expect(timeAxisItems[1].find('.devui-timeline-item-content div').html()).toBe('<div>测试2</div>'); + // 显示自定义时间点 + expect(timeAxisItems[1].find('.devui-timeline-item-dot i').exists()).toBe(true); + // 显示时间点间的附加元素 + expect(timeAxisItems[1].find('.devui-timeline-item-line-extra span').html()).toBe('<span>附加元素</span>'); + }); it('type should be rendered correctly', async () => { - expect(timeAxisItems[0].find('.devui-timeline-item-dot').classes()).toContain('devui-timeline-item-type-primary') - expect(timeAxisItems[2].find('.devui-timeline-item-dot').classes()).toContain('devui-timeline-item-type-success') - expect(timeAxisItems[3].find('.devui-timeline-item-dot').classes()).toContain('devui-timeline-item-type-warning') - expect(timeAxisItems[4].find('.devui-timeline-item-dot').classes()).toContain('devui-timeline-item-type-error') + expect(timeAxisItems[0].find('.devui-timeline-item-dot').classes()).toContain('devui-timeline-item-type-primary'); + expect(timeAxisItems[2].find('.devui-timeline-item-dot').classes()).toContain('devui-timeline-item-type-success'); + expect(timeAxisItems[3].find('.devui-timeline-item-dot').classes()).toContain('devui-timeline-item-type-warning'); + expect(timeAxisItems[4].find('.devui-timeline-item-dot').classes()).toContain('devui-timeline-item-type-error'); - }) + }); it('position should be rendered correctly', async () => { @@ -67,22 +67,22 @@ describe('timeline test', () => { </d-timeline> `, setup() { - return + return; } }); - let timeAxisItems = wrapper.findAll('.devui-timeline-item') - //内容是否在正确的位置 - expect(timeAxisItems[0].find('.devui-timeline-item-data-left .devui-timeline-item-content').exists()).toBe(true) - expect(timeAxisItems[1].find('.devui-timeline-item-data-right .devui-timeline-item-content').exists()).toBe(true) - expect(timeAxisItems[2].find('.devui-timeline-item-data-right .devui-timeline-item-content').exists()).toBe(true) - //设置横向时间轴 - await wrapper.setProps({ direction: 'horizontal' }) - timeAxisItems = wrapper.findAll('.devui-timeline-item') - expect(timeAxisItems[0].find('.devui-timeline-item-data-bottom .devui-timeline-item-content').exists()).toBe(true) - expect(timeAxisItems[1].find('.devui-timeline-item-data-top .devui-timeline-item-content').exists()).toBe(true) - expect(timeAxisItems[3].find('.devui-timeline-item-data-top .devui-timeline-item-content').exists()).toBe(true) + let timeAxisItems = wrapper.findAll('.devui-timeline-item'); + // 内容是否在正确的位置 + expect(timeAxisItems[0].find('.devui-timeline-item-data-left .devui-timeline-item-content').exists()).toBe(true); + expect(timeAxisItems[1].find('.devui-timeline-item-data-right .devui-timeline-item-content').exists()).toBe(true); + expect(timeAxisItems[2].find('.devui-timeline-item-data-right .devui-timeline-item-content').exists()).toBe(true); + // 设置横向时间轴 + await wrapper.setProps({ direction: 'horizontal' }); + timeAxisItems = wrapper.findAll('.devui-timeline-item'); + expect(timeAxisItems[0].find('.devui-timeline-item-data-bottom .devui-timeline-item-content').exists()).toBe(true); + expect(timeAxisItems[1].find('.devui-timeline-item-data-top .devui-timeline-item-content').exists()).toBe(true); + expect(timeAxisItems[3].find('.devui-timeline-item-data-top .devui-timeline-item-content').exists()).toBe(true); - }) + }); it('time-position should be rendered correctly', async () => { const wrapper = mount({ @@ -94,16 +94,16 @@ describe('timeline test', () => { </d-timeline> `, setup() { - return + return; } }); - const timeAxisItems = wrapper.findAll('.devui-timeline-item') - //时间是否在正确的位置 - expect(timeAxisItems[0].find('.devui-timeline-item-data-left .devui-timeline-item-time').exists()).toBe(false) - expect(timeAxisItems[0].find('.devui-timeline-item-axis .devui-timeline-item-time').exists()).toBe(true) - expect(timeAxisItems[1].find('.devui-timeline-item-data-left .devui-timeline-item-time').exists()).toBe(true) - expect(timeAxisItems[1].find('.devui-timeline-item-axis .devui-timeline-item-time').exists()).toBe(false) - }) + const timeAxisItems = wrapper.findAll('.devui-timeline-item'); + // 时间是否在正确的位置 + expect(timeAxisItems[0].find('.devui-timeline-item-data-left .devui-timeline-item-time').exists()).toBe(false); + expect(timeAxisItems[0].find('.devui-timeline-item-axis .devui-timeline-item-time').exists()).toBe(true); + expect(timeAxisItems[1].find('.devui-timeline-item-data-left .devui-timeline-item-time').exists()).toBe(true); + expect(timeAxisItems[1].find('.devui-timeline-item-axis .devui-timeline-item-time').exists()).toBe(false); + }); it('line-style should be rendered correctly', async () => { const wrapper = mount({ @@ -118,14 +118,14 @@ describe('timeline test', () => { </d-timeline> `, setup() { - return + return; } }); - const timeAxisItemAxis = wrapper.findAll('.devui-timeline-item .devui-timeline-item-axis') - expect(timeAxisItemAxis[0].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-solid') - expect(timeAxisItemAxis[1].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-dashed') - expect(timeAxisItemAxis[2].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-dotted') - expect(timeAxisItemAxis[3].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-none') - expect(timeAxisItemAxis[4].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-none') - }) -}) + const timeAxisItemAxis = wrapper.findAll('.devui-timeline-item .devui-timeline-item-axis'); + expect(timeAxisItemAxis[0].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-solid'); + expect(timeAxisItemAxis[1].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-dashed'); + expect(timeAxisItemAxis[2].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-dotted'); + expect(timeAxisItemAxis[3].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-none'); + expect(timeAxisItemAxis[4].find('.devui-timeline-item-line').classes()).toContain('devui-timeline-item-line-style-none'); + }); +}); diff --git a/packages/devui-vue/devui/timeline/index.ts b/packages/devui-vue/devui/timeline/index.ts index 0219b52606..8fcd64ba65 100644 --- a/packages/devui-vue/devui/timeline/index.ts +++ b/packages/devui-vue/devui/timeline/index.ts @@ -1,21 +1,21 @@ -import type { App } from 'vue' -import Timeline from './src/timeline' -import TimelineItem from './src/components/timeline-item' +import type { App } from 'vue'; +import Timeline from './src/timeline'; +import TimelineItem from './src/components/timeline-item'; Timeline.install = function (app: App): void { - app.component(Timeline.name, Timeline) -} + app.component(Timeline.name, Timeline); +}; TimelineItem.install = function (app: App): void { - app.component(TimelineItem.name, TimelineItem) -} -export { Timeline, TimelineItem } + app.component(TimelineItem.name, TimelineItem); +}; +export { Timeline, TimelineItem }; export default { title: 'Timeline 时间轴', category: '数据展示', status: '100%', install(app: App): void { - app.use(Timeline as any) - app.use(TimelineItem as any) + app.use(Timeline as any); + app.use(TimelineItem as any); } -} +}; diff --git a/packages/devui-vue/devui/timeline/src/components/timeline-item/index.tsx b/packages/devui-vue/devui/timeline/src/components/timeline-item/index.tsx index d8a6224dfe..9496636707 100644 --- a/packages/devui-vue/devui/timeline/src/components/timeline-item/index.tsx +++ b/packages/devui-vue/devui/timeline/src/components/timeline-item/index.tsx @@ -1,7 +1,7 @@ -import {defineComponent, inject} from 'vue' -import type {TimelineRootType} from '../../timeline-types' -import DIcon from '../../../../icon/src/icon' -import {timeAxisItemProps, TimelineItemProps, Type} from './types' +import {defineComponent, inject} from 'vue'; +import type {TimelineRootType} from '../../timeline-types'; +import DIcon from '../../../../icon/src/icon'; +import {timeAxisItemProps, TimelineItemProps, Type} from './types'; export default defineComponent({ name: 'DTimelineItem', @@ -9,8 +9,8 @@ export default defineComponent({ props: timeAxisItemProps, emits: [], setup(props: TimelineItemProps, ctx) { - const timeAxis: TimelineRootType = inject('timeAxis') - const itemClass = 'devui-timeline-item' + const timeAxis: TimelineRootType = inject('timeAxis'); + const itemClass = 'devui-timeline-item'; const renderTime = () => { return ( <div class={`${itemClass}-time`}> @@ -20,46 +20,46 @@ export default defineComponent({ : props.time } </div> - ) - } + ); + }; const renderContent = () => { return ( <div class={`${itemClass}-content`}> {ctx.slots.default?.(props)} </div> - ) - } + ); + }; const renderPosition = (types: string[]) => { - //如果有设置position的话,就直接用position的内容 + // 如果有设置position的话,就直接用position的内容 if (types.includes(props.position)) { - return renderContent() + return renderContent(); } else { - //如果是horizontal直接返回时间 + // 如果是horizontal直接返回时间 if (timeAxis.props.direction === 'horizontal') { - return renderTime() + return renderTime(); } else { - //如果有设定time-position,则left显示在这 - return props.timePosition === 'left' ? renderTime() : '' + // 如果有设定time-position,则left显示在这 + return props.timePosition === 'left' ? renderTime() : ''; } } - } + }; const setTypeIcon = (type: Type) => { if (type === 'primary') { - return '' + return ''; } - return <i class={`icon-${type === 'success' ? 'right' : type}-o`}/> - } + return <i class={`icon-${type === 'success' ? 'right' : type}-o`}/>; + }; const renderDot = () => { if (ctx.slots.dot) { - return <div style={{color: props.dotColor}} class={`${itemClass}-dot`}> {ctx.slots.dot?.()}</div> + return <div style={{color: props.dotColor}} class={`${itemClass}-dot`}> {ctx.slots.dot?.()}</div>; } else { return (<div class={`${itemClass}-dot ${itemClass}-type-${props.type}`} - style={{borderColor: props.dotColor}} + style={{borderColor: props.dotColor}} > {setTypeIcon(props.type)} - </div>) + </div>); } - } + }; return () => { return ( @@ -73,7 +73,7 @@ export default defineComponent({ } {(timeAxis.props.direction === 'vertical' && props.timePosition === 'bottom') ? renderTime() : ''} <div class={`${itemClass}-line ${itemClass}-line-style-${props.lineStyle}`} - style={{borderColor: props.lineColor}} + style={{borderColor: props.lineColor}} > {ctx.slots.extra ? <div class={`${itemClass}-line-extra`}>{ctx.slots.extra()}</div> : ''} </div> @@ -83,7 +83,7 @@ export default defineComponent({ </div> </div> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/timeline/src/components/timeline-item/types.ts b/packages/devui-vue/devui/timeline/src/components/timeline-item/types.ts index f1c8ab1b65..b349f5e6a4 100644 --- a/packages/devui-vue/devui/timeline/src/components/timeline-item/types.ts +++ b/packages/devui-vue/devui/timeline/src/components/timeline-item/types.ts @@ -1,38 +1,38 @@ -import type { PropType, ExtractPropTypes } from 'vue' -import type { LineStyle,TimePosition } from '../../timeline-types' -export type Position = 'top' | 'bottom' | 'left' | 'right' -export type Type = 'primary' | 'success' | 'warning' | 'error' +import type { PropType, ExtractPropTypes } from 'vue'; +import type { LineStyle,TimePosition } from '../../timeline-types'; +export type Position = 'top' | 'bottom' | 'left' | 'right'; +export type Type = 'primary' | 'success' | 'warning' | 'error'; export const timeAxisItemProps = { time: { type: String, }, - //可选,自定义时间圈颜色 + // 可选,自定义时间圈颜色 dotColor: { type: String }, - //分界线的样式 + // 分界线的样式 lineStyle: { type: String as PropType<LineStyle>, default: 'solid' }, - //分界线的样式 + // 分界线的样式 lineColor: { type: String }, - //分界线的样式 + // 分界线的样式 position: { type: String as PropType<Position> }, - //设置时间位置 + // 设置时间位置 timePosition: { type: String as PropType<TimePosition>, default: 'left' }, - //时间点类型 + // 时间点类型 type: { type: String as PropType<Type>, default: 'primary' } -} as const +} as const; -export type TimelineItemProps = ExtractPropTypes<typeof timeAxisItemProps> +export type TimelineItemProps = ExtractPropTypes<typeof timeAxisItemProps>; diff --git a/packages/devui-vue/devui/timeline/src/timeline-types.ts b/packages/devui-vue/devui/timeline/src/timeline-types.ts index bcc7e67d1e..f1381cce69 100644 --- a/packages/devui-vue/devui/timeline/src/timeline-types.ts +++ b/packages/devui-vue/devui/timeline/src/timeline-types.ts @@ -1,35 +1,35 @@ -import type { PropType, ExtractPropTypes,SetupContext } from 'vue' -export type DataDirection = 'vertical' | 'horizontal' -export type Mode = 'normal' | 'alternative' -export type TimePosition = 'left' | 'bottom' -export type LineStyle = 'solid' | 'dashed' | 'dotted' | 'none' +import type { PropType, ExtractPropTypes,SetupContext } from 'vue'; +export type DataDirection = 'vertical' | 'horizontal'; +export type Mode = 'normal' | 'alternative'; +export type TimePosition = 'left' | 'bottom'; +export type LineStyle = 'solid' | 'dashed' | 'dotted' | 'none'; export const timeAxisProps = { - //设置时间轴方向 + // 设置时间轴方向 direction: { type: String as PropType<DataDirection>, default: 'vertical' }, - //设置居中 + // 设置居中 center: { type: Boolean, default: false }, - //设置排序方向 + // 设置排序方向 mode: { type: String as PropType<Mode>, default: 'normal' }, - //设置时间位置 + // 设置时间位置 timePosition: { type: String as PropType<TimePosition>, default: 'left' } -} as const +} as const; -export type TimelineProps = ExtractPropTypes<typeof timeAxisProps> +export type TimelineProps = ExtractPropTypes<typeof timeAxisProps>; export interface TimelineRootType { - ctx: SetupContext<any> - props: TimelineProps + ctx: SetupContext<any>; + props: TimelineProps; } diff --git a/packages/devui-vue/devui/timeline/src/timeline.tsx b/packages/devui-vue/devui/timeline/src/timeline.tsx index 47a2f71045..e29df6dd13 100644 --- a/packages/devui-vue/devui/timeline/src/timeline.tsx +++ b/packages/devui-vue/devui/timeline/src/timeline.tsx @@ -1,7 +1,7 @@ -import {defineComponent, Fragment, nextTick, onMounted, provide, reactive, ref, toRef, watch} from 'vue' -import {timeAxisProps, TimelineProps, TimelineRootType} from './timeline-types' -import TimelineItem from './components/timeline-item' -import './timeline.scss' +import {defineComponent, Fragment, nextTick, onMounted, provide, reactive, ref, toRef, watch} from 'vue'; +import {timeAxisProps, TimelineProps, TimelineRootType} from './timeline-types'; +import TimelineItem from './components/timeline-item'; +import './timeline.scss'; export default defineComponent({ name: 'DTimeline', @@ -9,90 +9,90 @@ export default defineComponent({ props: timeAxisProps, emits: [], setup(props: TimelineProps, ctx) { - provide<TimelineRootType>('timeAxis', {ctx, props}) + provide<TimelineRootType>('timeAxis', {ctx, props}); const timeAxis = ref<null | HTMLElement>(); const style = reactive({ marginLeft: '0px', height: 'auto' - }) + }); const setStyle = () => { - style.height = 'auto' - style.marginLeft = '0px' + style.height = 'auto'; + style.marginLeft = '0px'; if (props.direction === 'horizontal') { nextTick(() => { const el = timeAxis.value; if (props.center) { - //计算偏移量 - style.marginLeft = (el?.firstElementChild?.clientWidth || 0) / 2 + 'px' + // 计算偏移量 + style.marginLeft = (el?.firstElementChild?.clientWidth || 0) / 2 + 'px'; } - //算出最大高度 + // 算出最大高度 style.height = Math.max( - ...Array.from(el?.querySelectorAll('.devui-timeline-item-data-top')).map(el => el.clientHeight), - ...Array.from(el?.querySelectorAll('.devui-timeline-item-data-bottom')).map(el => el.clientHeight) - ) * 2 + ...Array.from(el?.querySelectorAll('.devui-timeline-item-data-top')).map(el => el.clientHeight), + ...Array.from(el?.querySelectorAll('.devui-timeline-item-data-bottom')).map(el => el.clientHeight) + ) * 2 + Math.max(...Array.from(el?.querySelectorAll('.devui-timeline-item-axis')).map(el => el.clientHeight)) - + 'px' + + 'px'; }); } - } + }; onMounted(() => { - setStyle() + setStyle(); }); watch(toRef(props, 'direction'), () => { - setStyle() - }) + setStyle(); + }); return () => { const renderItemPosition = (item, position?) => { return position ? <item position={position}/> - : <item/> - } + : <item/>; + }; const renderItem = () => { const slots: any[] = ctx.slots.default?.() ?? []; let children; if (slots.length === 1 && slots[0].type === Fragment) { - children = slots[0].children || [] + children = slots[0].children || []; } else { - children = slots + children = slots; } return children.map((item, index) => { - //默认隐藏最后一条线 + // 默认隐藏最后一条线 if ((index + 1) === children.length) { if (!item.props?.lineStyle && !item.props?.['line-style']) { - item = <item line-style="none"/> + item = <item line-style="none"/>; } } - //如果没有单独设置time-position属性,则以全局为准 + // 如果没有单独设置time-position属性,则以全局为准 if (!item.props?.timePosition && !item.props?.['time-position']) { - item = <item time-position={props.timePosition ? props.timePosition : 'left'}/> + item = <item time-position={props.timePosition ? props.timePosition : 'left'}/>; } if (props.direction === 'horizontal') { - //判断是否有自定义的位置信息,且是否正确 有,且正确直接用 - if (item.props?.position === 'top' || item.props?.position === 'bottom') return item - //判断是否需要交替 + // 判断是否有自定义的位置信息,且是否正确 有,且正确直接用 + if (item.props?.position === 'top' || item.props?.position === 'bottom') {return item;} + // 判断是否需要交替 if (props.mode === 'alternative') { - return renderItemPosition(item, index % 2 == 0 ? 'bottom' : 'top') + return renderItemPosition(item, index % 2 == 0 ? 'bottom' : 'top'); } else { - //不需要交替的直接给默认值 - return renderItemPosition(item, 'bottom') + // 不需要交替的直接给默认值 + return renderItemPosition(item, 'bottom'); } } else { - if (item.props?.position === 'left' || item.props?.position === 'right') return item + if (item.props?.position === 'left' || item.props?.position === 'right') {return item;} if (props.mode === 'alternative') { - return renderItemPosition(item, index % 2 == 0 ? 'left' : 'right') + return renderItemPosition(item, index % 2 == 0 ? 'left' : 'right'); } else { - return renderItemPosition(item, 'right') + return renderItemPosition(item, 'right'); } } - }) - } - //防止字段传入错误,导致显示错误 + }); + }; + // 防止字段传入错误,导致显示错误 const getDirection = () => { - return props.direction === 'horizontal' ? 'horizontal' : 'vertical' - } + return props.direction === 'horizontal' ? 'horizontal' : 'vertical'; + }; return ( <div @@ -102,7 +102,7 @@ export default defineComponent({ > {renderItem()} </div> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/tooltip/__tests__/tooltip.spec.ts b/packages/devui-vue/devui/tooltip/__tests__/tooltip.spec.ts index cf13e7a19d..2c31545eb8 100644 --- a/packages/devui-vue/devui/tooltip/__tests__/tooltip.spec.ts +++ b/packages/devui-vue/devui/tooltip/__tests__/tooltip.spec.ts @@ -1,175 +1,175 @@ import { mount } from '@vue/test-utils'; import Tooltip from '../src/tooltip'; import DButton from '../../button/src/button'; -import { Loading } from '../../loading/index' +import { Loading } from '../../loading/index'; import { nextTick } from 'vue'; let tooltipElement: HTMLElement; const globalOption = { - directives: { - dLoading: Loading - } -} + directives: { + dLoading: Loading + } +}; const defaultslot = { - default: '<d-button variant="common">tooltip</d-button>' -} + default: '<d-button variant="common">tooltip</d-button>' +}; describe('tooltip', () => { - beforeEach(() => { - jest.useFakeTimers(); - }) - describe('basic', () => { - it('should be create', async () => { - const wrapper = mount(Tooltip, { - props: { - content: 'content' - }, - slots: defaultslot, - global: globalOption - }) - await nextTick(); - tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; - expect(wrapper.find('.tooltip').exists()).toBe(true); - expect(wrapper.find('.tooltipcontent').text()).toBe('content'); - await wrapper.findComponent(DButton).trigger('mouseenter'); - jest.advanceTimersByTime(150); - await nextTick(); - tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; - expect(tooltipElement.style.opacity).toBe('1'); - await wrapper.findComponent(DButton).trigger('mouseleave'); - jest.advanceTimersByTime(150); - await nextTick(); - tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; - expect(tooltipElement.style.opacity).toBe('0'); - }) - it('position should be left', async () => { - const wrapper = mount(Tooltip, { - props: { - content: 'content', - position: 'left' - }, - slots: defaultslot, - global: globalOption, - attachTo: document.body - }) - await nextTick(); - await wrapper.findComponent(DButton).trigger('mouseenter'); - jest.advanceTimersByTime(100); - await nextTick(); - console.log(wrapper.element.childNodes); - const tooltipArrowElement = wrapper.element.querySelector('.arrow') as HTMLElement; - console.log(tooltipArrowElement); - expect(tooltipArrowElement.style.borderLeft).toBe('5px solid rgb(70, 77, 110)'); - wrapper.unmount(); - }) - it('position should be top', async () => { - const wrapper = mount(Tooltip, { - props: { - content: 'content', - position: 'top' - }, - slots: defaultslot, - global: globalOption, - attachTo: document.body - }) - await nextTick(); - await wrapper.findComponent(DButton).trigger('mouseenter'); - jest.advanceTimersByTime(150); - await nextTick(); - const tooltipArrowElement = wrapper.element.querySelector('.arrow') as HTMLElement; - console.log(tooltipArrowElement.style); - expect(tooltipArrowElement.style.borderTop).toBe('5px solid rgb(70, 77, 110)'); - wrapper.unmount(); - }) - it('position should be right', async () => { - const wrapper = mount(Tooltip, { - props: { - content: 'content', - position: 'right' - }, - slots: defaultslot, - global: globalOption, - attachTo: document.body - }) - await nextTick(); - await wrapper.findComponent(DButton).trigger('mouseenter'); - jest.advanceTimersByTime(150); - await nextTick(); - const tooltipArrowElement = wrapper.element.querySelector('.arrow') as HTMLElement; - console.log(tooltipArrowElement.style); - expect(tooltipArrowElement.style.borderRight).toBe('5px solid rgb(70, 77, 110)'); - wrapper.unmount(); - }) - it('position should be bottom', async () => { - const wrapper = mount(Tooltip, { - props: { - content: 'content', - position: 'bottom' - }, - slots: defaultslot, - global: globalOption, - attachTo: document.body - }) - await nextTick(); - await wrapper.findComponent(DButton).trigger('mouseenter'); - jest.advanceTimersByTime(150); - await nextTick(); - const tooltipArrowElement = wrapper.element.querySelector('.arrow') as HTMLElement; - console.log(tooltipArrowElement.style); - expect(tooltipArrowElement.style.borderBottom).toBe('5px solid rgb(70, 77, 110)'); - wrapper.unmount() - }) - }) - describe('delay time', () => { - it('test mouseEnterDelay', async () => { - const wrapper = mount(Tooltip, { - props: { - content: 'content', - mouseEnterDelay: '500' - }, - slots: defaultslot, - global: globalOption, - attachTo: document.body - }) - await nextTick(); - await wrapper.findComponent(DButton).trigger('mouseenter'); - jest.advanceTimersByTime(200); - await nextTick(); - tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; - expect(tooltipElement).toBe(null); - jest.advanceTimersByTime(300); - await nextTick(); - tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; - expect(tooltipElement.style.opacity).toBe('1'); - wrapper.unmount(); - }) - it('test mouseLeaveDelay', async () => { - const wrapper = mount(Tooltip, { - props: { - content: 'content', - mouseLeaveDelay: '1000' - }, - slots: defaultslot, - global: globalOption, - attachTo: document.body - }) - await nextTick(); - await wrapper.findComponent(DButton).trigger('mouseenter'); - jest.advanceTimersByTime(100); - await nextTick(); - tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; - expect(tooltipElement.style.opacity).toBe('1'); - await wrapper.findComponent(DButton).trigger('mouseleave'); - jest.advanceTimersByTime(500); - await nextTick(); - tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; - expect(tooltipElement.style.opacity).toBe('1'); - jest.advanceTimersByTime(500); - await nextTick(); - tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; - expect(tooltipElement).toBe(null); - }) + beforeEach(() => { + jest.useFakeTimers(); + }); + describe('basic', () => { + it('should be create', async () => { + const wrapper = mount(Tooltip, { + props: { + content: 'content' + }, + slots: defaultslot, + global: globalOption + }); + await nextTick(); + tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; + expect(wrapper.find('.tooltip').exists()).toBe(true); + expect(wrapper.find('.tooltipcontent').text()).toBe('content'); + await wrapper.findComponent(DButton).trigger('mouseenter'); + jest.advanceTimersByTime(150); + await nextTick(); + tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; + expect(tooltipElement.style.opacity).toBe('1'); + await wrapper.findComponent(DButton).trigger('mouseleave'); + jest.advanceTimersByTime(150); + await nextTick(); + tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; + expect(tooltipElement.style.opacity).toBe('0'); + }); + it('position should be left', async () => { + const wrapper = mount(Tooltip, { + props: { + content: 'content', + position: 'left' + }, + slots: defaultslot, + global: globalOption, + attachTo: document.body + }); + await nextTick(); + await wrapper.findComponent(DButton).trigger('mouseenter'); + jest.advanceTimersByTime(100); + await nextTick(); + console.log(wrapper.element.childNodes); + const tooltipArrowElement = wrapper.element.querySelector('.arrow') as HTMLElement; + console.log(tooltipArrowElement); + expect(tooltipArrowElement.style.borderLeft).toBe('5px solid rgb(70, 77, 110)'); + wrapper.unmount(); + }); + it('position should be top', async () => { + const wrapper = mount(Tooltip, { + props: { + content: 'content', + position: 'top' + }, + slots: defaultslot, + global: globalOption, + attachTo: document.body + }); + await nextTick(); + await wrapper.findComponent(DButton).trigger('mouseenter'); + jest.advanceTimersByTime(150); + await nextTick(); + const tooltipArrowElement = wrapper.element.querySelector('.arrow') as HTMLElement; + console.log(tooltipArrowElement.style); + expect(tooltipArrowElement.style.borderTop).toBe('5px solid rgb(70, 77, 110)'); + wrapper.unmount(); + }); + it('position should be right', async () => { + const wrapper = mount(Tooltip, { + props: { + content: 'content', + position: 'right' + }, + slots: defaultslot, + global: globalOption, + attachTo: document.body + }); + await nextTick(); + await wrapper.findComponent(DButton).trigger('mouseenter'); + jest.advanceTimersByTime(150); + await nextTick(); + const tooltipArrowElement = wrapper.element.querySelector('.arrow') as HTMLElement; + console.log(tooltipArrowElement.style); + expect(tooltipArrowElement.style.borderRight).toBe('5px solid rgb(70, 77, 110)'); + wrapper.unmount(); + }); + it('position should be bottom', async () => { + const wrapper = mount(Tooltip, { + props: { + content: 'content', + position: 'bottom' + }, + slots: defaultslot, + global: globalOption, + attachTo: document.body + }); + await nextTick(); + await wrapper.findComponent(DButton).trigger('mouseenter'); + jest.advanceTimersByTime(150); + await nextTick(); + const tooltipArrowElement = wrapper.element.querySelector('.arrow') as HTMLElement; + console.log(tooltipArrowElement.style); + expect(tooltipArrowElement.style.borderBottom).toBe('5px solid rgb(70, 77, 110)'); + wrapper.unmount(); + }); + }); + describe('delay time', () => { + it('test mouseEnterDelay', async () => { + const wrapper = mount(Tooltip, { + props: { + content: 'content', + mouseEnterDelay: '500' + }, + slots: defaultslot, + global: globalOption, + attachTo: document.body + }); + await nextTick(); + await wrapper.findComponent(DButton).trigger('mouseenter'); + jest.advanceTimersByTime(200); + await nextTick(); + tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; + expect(tooltipElement).toBe(null); + jest.advanceTimersByTime(300); + await nextTick(); + tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; + expect(tooltipElement.style.opacity).toBe('1'); + wrapper.unmount(); + }); + it('test mouseLeaveDelay', async () => { + const wrapper = mount(Tooltip, { + props: { + content: 'content', + mouseLeaveDelay: '1000' + }, + slots: defaultslot, + global: globalOption, + attachTo: document.body + }); + await nextTick(); + await wrapper.findComponent(DButton).trigger('mouseenter'); + jest.advanceTimersByTime(100); + await nextTick(); + tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; + expect(tooltipElement.style.opacity).toBe('1'); + await wrapper.findComponent(DButton).trigger('mouseleave'); + jest.advanceTimersByTime(500); + await nextTick(); + tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; + expect(tooltipElement.style.opacity).toBe('1'); + jest.advanceTimersByTime(500); + await nextTick(); + tooltipElement = wrapper.element.querySelector('.tooltip') as HTMLElement; + expect(tooltipElement).toBe(null); + }); - }) + }); -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts b/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts index 12d78fb110..66ea110398 100644 --- a/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts +++ b/packages/devui-vue/devui/transfer/__tests__/transfer.spec.ts @@ -1,88 +1,88 @@ import { mount } from '@vue/test-utils'; -import { ref, nextTick } from 'vue' +import { ref, nextTick } from 'vue'; import DCheckbox from '../../checkbox/src/checkbox'; import DTooltip from '../../tooltip/src/tooltip'; -import DTransfer from '../src/transfer' +import DTransfer from '../src/transfer'; const SOURCE_DATA = [ - { - key: '北京', - value: '北京', - disabled: false, - }, - { - key: '上海', - value: '上海', - disabled: true, - }, - { - key: '广州', - value: '广州', - disabled: true, - }, - { - key: '深圳', - value: '深圳', - disabled: false, - }, - { - key: '成都', - value: '成都', - disabled: false, - }, - { - key: '武汉', - value: '武汉', - disabled: false, - }, - { - key: '西安', - value: '西安', - disabled: false, - }, - { - key: '福建', - value: '福建', - disabled: false, - } -] + { + key: '北京', + value: '北京', + disabled: false, + }, + { + key: '上海', + value: '上海', + disabled: true, + }, + { + key: '广州', + value: '广州', + disabled: true, + }, + { + key: '深圳', + value: '深圳', + disabled: false, + }, + { + key: '成都', + value: '成都', + disabled: false, + }, + { + key: '武汉', + value: '武汉', + disabled: false, + }, + { + key: '西安', + value: '西安', + disabled: false, + }, + { + key: '福建', + value: '福建', + disabled: false, + } +]; const TARGET_DATA = [ - { - key: '南充', - value: '南充', - disabled: false, - }, - { - key: '广元', - value: '广元', - disabled: false, - }, - { - key: '绵阳', - value: '绵阳', - disabled: false, - }, - { - key: '大连', - value: '大连', - disabled: false, - }, - { - key: '重庆', - value: '重庆', - disabled: false, - } -] + { + key: '南充', + value: '南充', + disabled: false, + }, + { + key: '广元', + value: '广元', + disabled: false, + }, + { + key: '绵阳', + value: '绵阳', + disabled: false, + }, + { + key: '大连', + value: '大连', + disabled: false, + }, + { + key: '重庆', + value: '重庆', + disabled: false, + } +]; describe('d-transfer', () => { - it('d-transfer basic work', async () => { - const sourceOption = ref(SOURCE_DATA) - const targetOption = ref(TARGET_DATA) - const wrapper = mount({ - components: { - DTransfer - }, - template: ` + it('d-transfer basic work', async () => { + const sourceOption = ref(SOURCE_DATA); + const targetOption = ref(TARGET_DATA); + const wrapper = mount({ + components: { + DTransfer + }, + template: ` <d-transfer v-model="modelValues" :titles="titles" @@ -91,101 +91,101 @@ describe('d-transfer', () => { > </d-transfer> `, - setup() { - return { - modelValues: ref(['成都', '绵阳']), - titles: ref(['sourceHeader', 'targetHeader']), - source: sourceOption, - target: targetOption - } - } - }) + setup() { + return { + modelValues: ref(['成都', '绵阳']), + titles: ref(['sourceHeader', 'targetHeader']), + source: sourceOption, + target: targetOption + }; + } + }); - /** + /** * 测试穿梭框源是否正确渲染 start */ - expect(wrapper.find('.devui-transfer').exists()).toBeTruthy() - expect(wrapper.findAll('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').length).toBe(8) - expect(wrapper.findAll('.devui-transfer-target .devui-transfer-panel-body .devui-checkbox').length).toBe(5) - /** + expect(wrapper.find('.devui-transfer').exists()).toBeTruthy(); + expect(wrapper.findAll('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').length).toBe(8); + expect(wrapper.findAll('.devui-transfer-target .devui-transfer-panel-body .devui-checkbox').length).toBe(5); + /** * 测试穿梭框源是否正确渲染 end */ - /** + /** * 测试穿梭框源数据中disable start */ - const disableds = wrapper.findAll('.devui-transfer .devui-transfer-source .disabled') - expect(disableds.length).toBe(2) - expect(disableds.filter(item => ['上海', '广州'].includes(item.text())).length).toBe(2) - /** + const disableds = wrapper.findAll('.devui-transfer .devui-transfer-source .disabled'); + expect(disableds.length).toBe(2); + expect(disableds.filter(item => ['上海', '广州'].includes(item.text())).length).toBe(2); + /** * 测试穿梭框源数据中disable end */ - /** + /** * 测试穿梭框默认选中值 start */ - await nextTick() - const sourceChecked = wrapper.find('.devui-transfer-source .active') - expect(sourceChecked.text()).toBe('成都') - const targetChecked = wrapper.find('.devui-transfer-target .active') - expect(targetChecked.text()).toBe('绵阳') - /** + await nextTick(); + const sourceChecked = wrapper.find('.devui-transfer-source .active'); + expect(sourceChecked.text()).toBe('成都'); + const targetChecked = wrapper.find('.devui-transfer-target .active'); + expect(targetChecked.text()).toBe('绵阳'); + /** * 测试穿梭框默认选中值 end */ - /** + /** * 测试穿梭框左右穿梭 start */ - // 源按钮 - const leftButton = wrapper.find('.devui-transfer .devui-transfer-panel-operation-group-left button') - expect(leftButton) - expect(leftButton.attributes('disabled')).toEqual(undefined) - leftButton.trigger('click') - await nextTick() - expect(leftButton.attributes('disabled')).toEqual('') - // 目标按钮 - const rightButton = wrapper.find('.devui-transfer .devui-transfer-panel-operation-group-right button') - expect(rightButton) - expect(rightButton.attributes('disabled')).toEqual(undefined) - rightButton.trigger('click') - await nextTick() - expect(rightButton.attributes('disabled')).toEqual('') - /** + // 源按钮 + const leftButton = wrapper.find('.devui-transfer .devui-transfer-panel-operation-group-left button'); + expect(leftButton); + expect(leftButton.attributes('disabled')).toEqual(undefined); + leftButton.trigger('click'); + await nextTick(); + expect(leftButton.attributes('disabled')).toEqual(''); + // 目标按钮 + const rightButton = wrapper.find('.devui-transfer .devui-transfer-panel-operation-group-right button'); + expect(rightButton); + expect(rightButton.attributes('disabled')).toEqual(undefined); + rightButton.trigger('click'); + await nextTick(); + expect(rightButton.attributes('disabled')).toEqual(''); + /** * 测试穿梭框左右穿梭 end */ - /** + /** * 测试穿梭框左、右全选 start */ - // 源全选 - const sourceAllInput = wrapper.find('.devui-transfer-source .devui-transfer-panel-header-allChecked .devui-checkbox-input') - sourceAllInput.trigger('click') - await nextTick() - const newSourceAllInput = wrapper.find<HTMLInputElement>('.devui-transfer-source .devui-transfer-panel-header-allChecked .devui-checkbox-input') - expect(newSourceAllInput.element.checked).toBeTruthy() - // 目标全选 - const targetAllInput = wrapper.find('.devui-transfer-target .devui-transfer-panel-header-allChecked .devui-checkbox-input') - targetAllInput.trigger('click') - await nextTick() - const newTargetAllInput = wrapper.find<HTMLInputElement>('.devui-transfer-target .devui-transfer-panel-header-allChecked .devui-checkbox-input') - expect(newTargetAllInput.element.checked).toBeTruthy() - /** + // 源全选 + const sourceAllInput = wrapper.find('.devui-transfer-source .devui-transfer-panel-header-allChecked .devui-checkbox-input'); + sourceAllInput.trigger('click'); + await nextTick(); + const newSourceAllInput = wrapper.find<HTMLInputElement>('.devui-transfer-source .devui-transfer-panel-header-allChecked .devui-checkbox-input'); + expect(newSourceAllInput.element.checked).toBeTruthy(); + // 目标全选 + const targetAllInput = wrapper.find('.devui-transfer-target .devui-transfer-panel-header-allChecked .devui-checkbox-input'); + targetAllInput.trigger('click'); + await nextTick(); + const newTargetAllInput = wrapper.find<HTMLInputElement>('.devui-transfer-target .devui-transfer-panel-header-allChecked .devui-checkbox-input'); + expect(newTargetAllInput.element.checked).toBeTruthy(); + /** * 测试穿梭框左、右全选 end */ - }) + }); - it('d-transfer searching work', async () => { - const sourceOption = ref(SOURCE_DATA) - const targetOption = ref(TARGET_DATA) - const wrapper = mount({ - components: { - DTransfer - }, - template: ` + it('d-transfer searching work', async () => { + const sourceOption = ref(SOURCE_DATA); + const targetOption = ref(TARGET_DATA); + const wrapper = mount({ + components: { + DTransfer + }, + template: ` <d-transfer v-model="modelValues" :titles="titles" @@ -195,132 +195,131 @@ describe('d-transfer', () => { > </d-transfer> `, - setup() { - return { - modelValues: ref(['成都', '绵阳']), - titles: ref(['sourceHeader', 'targetHeader']), - source: sourceOption, - target: targetOption, - isSearch: ref(true) - } - } - }) + setup() { + return { + modelValues: ref(['成都', '绵阳']), + titles: ref(['sourceHeader', 'targetHeader']), + source: sourceOption, + target: targetOption, + isSearch: ref(true) + }; + } + }); - /** + /** * 测试搜索功能 start */ - // 源搜索功能 - expect(wrapper.find('.devui-transfer-source .devui-search').exists()).toBe(true) - const sourceSearch = wrapper.find<HTMLInputElement>('.devui-transfer-source .devui-search input[type="text"]') - const sourceSearchClear = wrapper.find('.devui-transfer-source .devui-search .devui-search__clear') - expect(sourceSearchClear.exists()).toBe(false) - sourceSearch.setValue('成都') - await nextTick() - expect(sourceSearch.element.value).toBe('成都') - expect(wrapper.find('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').text()).toBe('成都') - const newSourceSearchClear = wrapper.find('.devui-transfer-source .devui-search .devui-search__clear') - expect(newSourceSearchClear.exists()).toBe(true) - newSourceSearchClear.trigger('click') - await nextTick() - expect(wrapper.find<HTMLInputElement>('.devui-transfer-source .devui-search input[type="text"]').element.value).toBe('') + // 源搜索功能 + expect(wrapper.find('.devui-transfer-source .devui-search').exists()).toBe(true); + const sourceSearch = wrapper.find<HTMLInputElement>('.devui-transfer-source .devui-search input[type="text"]'); + const sourceSearchClear = wrapper.find('.devui-transfer-source .devui-search .devui-search__clear'); + expect(sourceSearchClear.exists()).toBe(false); + sourceSearch.setValue('成都'); + await nextTick(); + expect(sourceSearch.element.value).toBe('成都'); + expect(wrapper.find('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').text()).toBe('成都'); + const newSourceSearchClear = wrapper.find('.devui-transfer-source .devui-search .devui-search__clear'); + expect(newSourceSearchClear.exists()).toBe(true); + newSourceSearchClear.trigger('click'); + await nextTick(); + expect(wrapper.find<HTMLInputElement>('.devui-transfer-source .devui-search input[type="text"]').element.value).toBe(''); - // 目标搜索功能 - expect(wrapper.find('.devui-transfer-target .devui-search').exists()).toBe(true) - const targetSearch = wrapper.find<HTMLInputElement>('.devui-transfer-target .devui-search input[type="text"]') - const targetSearchClear = wrapper.find('.devui-transfer-target .devui-search .devui-search__clear') - expect(targetSearchClear.exists()).toBe(false) - targetSearch.setValue('广元') - await nextTick() - expect(targetSearch.element.value).toBe('广元') - expect(wrapper.find('.devui-transfer-target .devui-transfer-panel-body .devui-checkbox').text()).toBe('广元') - const newTargetSearchClear = wrapper.find('.devui-transfer-target .devui-search .devui-search__clear') - expect(newTargetSearchClear.exists()).toBe(true) - newTargetSearchClear.trigger('click') - await nextTick() - expect(wrapper.find<HTMLInputElement>('.devui-transfer-target .devui-search input[type="text"]').element.value).toBe('') - /** + // 目标搜索功能 + expect(wrapper.find('.devui-transfer-target .devui-search').exists()).toBe(true); + const targetSearch = wrapper.find<HTMLInputElement>('.devui-transfer-target .devui-search input[type="text"]'); + const targetSearchClear = wrapper.find('.devui-transfer-target .devui-search .devui-search__clear'); + expect(targetSearchClear.exists()).toBe(false); + targetSearch.setValue('广元'); + await nextTick(); + expect(targetSearch.element.value).toBe('广元'); + expect(wrapper.find('.devui-transfer-target .devui-transfer-panel-body .devui-checkbox').text()).toBe('广元'); + const newTargetSearchClear = wrapper.find('.devui-transfer-target .devui-search .devui-search__clear'); + expect(newTargetSearchClear.exists()).toBe(true); + newTargetSearchClear.trigger('click'); + await nextTick(); + expect(wrapper.find<HTMLInputElement>('.devui-transfer-target .devui-search input[type="text"]').element.value).toBe(''); + /** * 测试搜索功能 end */ - }) + }); - // it('d-transfer tooltips work', async () => { - // const sourceOption = ref(SOURCE_DATA) - // const targetOption = ref(TARGET_DATA) - // const wrapper = mount({ - // components: { - // DTransfer - // }, - // template: ` - // <d-transfer - // v-model="modelValues" - // :titles="titles" - // :sourceOption="source" - // :targetOption="target" - // :showTooltip="isShowTooltip" - // > - // </d-transfer> - // `, - // setup() { - // return { - // modelValues: ref(['成都', '绵阳']), - // titles: ref(['sourceHeader', 'targetHeader']), - // source: sourceOption, - // target: targetOption, - // isShowTooltip: ref(true) - // } - // } - // }) + // it('d-transfer tooltips work', async () => { + // const sourceOption = ref(SOURCE_DATA) + // const targetOption = ref(TARGET_DATA) + // const wrapper = mount({ + // components: { + // DTransfer + // }, + // template: ` + // <d-transfer + // v-model="modelValues" + // :titles="titles" + // :sourceOption="source" + // :targetOption="target" + // :showTooltip="isShowTooltip" + // > + // </d-transfer> + // `, + // setup() { + // return { + // modelValues: ref(['成都', '绵阳']), + // titles: ref(['sourceHeader', 'targetHeader']), + // source: sourceOption, + // target: targetOption, + // isShowTooltip: ref(true) + // } + // } + // }) - // /** - // * 测试穿梭框渲染 start - // */ - // expect(wrapper.find('.devui-transfer-source').exists()).toBe(true) - // expect(wrapper.find('.devui-transfer-target').exists()).toBe(true) - // expect(wrapper.findAll('.devui-transfer-source .devui-tooltip').length).toBe(8) - // expect(wrapper.findAll('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').length).toBe(8) - // /** - // * 测试穿梭框渲染 end - // */ + // /** + // * 测试穿梭框渲染 start + // */ + // expect(wrapper.find('.devui-transfer-source').exists()).toBe(true) + // expect(wrapper.find('.devui-transfer-target').exists()).toBe(true) + // expect(wrapper.findAll('.devui-transfer-source .devui-tooltip').length).toBe(8) + // expect(wrapper.findAll('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').length).toBe(8) + // /** + // * 测试穿梭框渲染 end + // */ - // /** - // * 测试穿梭框tooltip start - // */ - // expect(wrapper.find('.devui-transfer-source').exists()).toBe(true) - // expect(wrapper.find('.devui-transfer-target').exists()).toBe(true) - // expect(wrapper.findAll('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').length).toBe(8) - // expect(wrapper.findAll('.devui-transfer-target .devui-transfer-panel-body .devui-checkbox').length).toBe(5) - // const sourceTooltips = wrapper.findAll<HTMLDivElement>('.devui-transfer-source .devui-tooltip') - // const targetTooltips = wrapper.findAll('.devui-transfer-target .devui-tooltip') - // expect(sourceTooltips.length).toBe(8) - // expect(targetTooltips.length).toBe(5) - // expect(sourceTooltips[0].find('.tooltip').exists()).toBe(false) + // /** + // * 测试穿梭框tooltip start + // */ + // expect(wrapper.find('.devui-transfer-source').exists()).toBe(true) + // expect(wrapper.find('.devui-transfer-target').exists()).toBe(true) + // expect(wrapper.findAll('.devui-transfer-source .devui-transfer-panel-body .devui-checkbox').length).toBe(8) + // expect(wrapper.findAll('.devui-transfer-target .devui-transfer-panel-body .devui-checkbox').length).toBe(5) + // const sourceTooltips = wrapper.findAll<HTMLDivElement>('.devui-transfer-source .devui-tooltip') + // const targetTooltips = wrapper.findAll('.devui-transfer-target .devui-tooltip') + // expect(sourceTooltips.length).toBe(8) + // expect(targetTooltips.length).toBe(5) + // expect(sourceTooltips[0].find('.tooltip').exists()).toBe(false) - // const sourceBody = wrapper.find('.devui-transfer-source .devui-transfer-panel-body') - // const checkboxC = sourceBody.findComponent(DTooltip) - // const slotElement = checkboxC.find('.devui-checkbox-column-margin') - // slotElement.trigger('mouseenter') - // console.log(slotElement.classes()) - // await nextTick() - // console.log(checkboxC.find('.tooltip')) + // const sourceBody = wrapper.find('.devui-transfer-source .devui-transfer-panel-body') + // const checkboxC = sourceBody.findComponent(DTooltip) + // const slotElement = checkboxC.find('.devui-checkbox-column-margin') + // slotElement.trigger('mouseenter') + // console.log(slotElement.classes()) + // await nextTick() + // console.log(checkboxC.find('.tooltip')) + // /** + // * 测试穿梭框tooltip end + // */ + // }) - // /** - // * 测试穿梭框tooltip end - // */ - // }) - - it('d-transfer source drag work', async () => { - const sourceOption = ref(SOURCE_DATA) - const targetOption = ref(TARGET_DATA) - const wrapper = mount({ - components: { - DTransfer - }, - template: ` + it('d-transfer source drag work', async () => { + const sourceOption = ref(SOURCE_DATA); + const targetOption = ref(TARGET_DATA); + const wrapper = mount({ + components: { + DTransfer + }, + template: ` <d-transfer v-model="modelValues" :titles="titles" @@ -331,68 +330,68 @@ describe('d-transfer', () => { > </d-transfer> `, - setup() { - return { - modelValues: ref(['成都', '绵阳']), - titles: ref(['sourceHeader', 'targetHeader']), - source: sourceOption, - target: targetOption, - isSourceDroppable: ref(true) - } - } - }) + setup() { + return { + modelValues: ref(['成都', '绵阳']), + titles: ref(['sourceHeader', 'targetHeader']), + source: sourceOption, + target: targetOption, + isSourceDroppable: ref(true) + }; + } + }); - // /** - // * 测试穿梭框拖拽排序 start - // */ - // const startDragItemIndex = sourceOption.value.findIndex(item => item.value === '成都') - // const startDropItemIndex = sourceOption.value.findIndex(item => item.value === '上海') - // const dragItemValue = sourceOption.value[startDragItemIndex] - // const dropItemValue = sourceOption.value[startDropItemIndex] - // const dataSort = (target, dragItem, dropItem) => { - // const startIndex = target.findIndex(item => item.key === dragItem.key) - // const endIndex = target.findIndex(item => item.key === dropItem.key) - // target.splice(endIndex, 1, dragItem) - // target.splice(startIndex, 1, dropItem) - // } - // dataSort(sourceOption.value, dragItemValue, dropItemValue) - // await nextTick() - // const endDragItemIndex = sourceOption.value.findIndex(item => item.value === '成都') - // const endDropItemIndex = sourceOption.value.findIndex(item => item.value === '上海') - // // 4 1 // 1 4 - // /** - // * 测试穿梭框拖拽排序 end - // */ - /** + // /** + // * 测试穿梭框拖拽排序 start + // */ + // const startDragItemIndex = sourceOption.value.findIndex(item => item.value === '成都') + // const startDropItemIndex = sourceOption.value.findIndex(item => item.value === '上海') + // const dragItemValue = sourceOption.value[startDragItemIndex] + // const dropItemValue = sourceOption.value[startDropItemIndex] + // const dataSort = (target, dragItem, dropItem) => { + // const startIndex = target.findIndex(item => item.key === dragItem.key) + // const endIndex = target.findIndex(item => item.key === dropItem.key) + // target.splice(endIndex, 1, dragItem) + // target.splice(startIndex, 1, dropItem) + // } + // dataSort(sourceOption.value, dragItemValue, dropItemValue) + // await nextTick() + // const endDragItemIndex = sourceOption.value.findIndex(item => item.value === '成都') + // const endDropItemIndex = sourceOption.value.findIndex(item => item.value === '上海') + // // 4 1 // 1 4 + // /** + // * 测试穿梭框拖拽排序 end + // */ + /** * 测试穿梭框拖拽排序 start */ - const left = wrapper.find('.devui-transfer-source') - const leftTransfer = left.findComponent({ name: 'DTransferBase' }) - const leftOption = leftTransfer.props().sourceOption - const startDragItemIndex = leftOption.findIndex(item => item.value === '成都') - const startDropItemIndex = leftOption.findIndex(item => item.value === '上海') - expect(startDragItemIndex).toBe(4) - expect(startDropItemIndex).toBe(1) - leftTransfer.props().onDragend(leftOption[startDragItemIndex], leftOption[startDropItemIndex]) - await nextTick() - const endDragItemIndex = leftOption.findIndex(item => item.value === '成都') - const endDropItemIndex = leftOption.findIndex(item => item.value === '上海') - expect(endDragItemIndex).toBe(1) - expect(endDropItemIndex).toBe(4) - /** + const left = wrapper.find('.devui-transfer-source'); + const leftTransfer = left.findComponent({ name: 'DTransferBase' }); + const leftOption = leftTransfer.props().sourceOption; + const startDragItemIndex = leftOption.findIndex(item => item.value === '成都'); + const startDropItemIndex = leftOption.findIndex(item => item.value === '上海'); + expect(startDragItemIndex).toBe(4); + expect(startDropItemIndex).toBe(1); + leftTransfer.props().onDragend(leftOption[startDragItemIndex], leftOption[startDropItemIndex]); + await nextTick(); + const endDragItemIndex = leftOption.findIndex(item => item.value === '成都'); + const endDropItemIndex = leftOption.findIndex(item => item.value === '上海'); + expect(endDragItemIndex).toBe(1); + expect(endDropItemIndex).toBe(4); + /** * 测试穿梭框拖拽排序 end */ - }) + }); - it('d-transfer target drag work', async () => { - const sourceOption = ref(SOURCE_DATA) - const targetOption = ref(TARGET_DATA) - const wrapper = mount({ - components: { - DTransfer - }, - template: ` + it('d-transfer target drag work', async () => { + const sourceOption = ref(SOURCE_DATA); + const targetOption = ref(TARGET_DATA); + const wrapper = mount({ + components: { + DTransfer + }, + template: ` <d-transfer v-model="modelValues" :titles="titles" @@ -403,36 +402,36 @@ describe('d-transfer', () => { > </d-transfer> `, - setup() { - return { - modelValues: ref(['成都', '绵阳']), - titles: ref(['sourceHeader', 'targetHeader']), - source: sourceOption, - target: targetOption, - isSourceDroppable: ref(true) - } - } - }) + setup() { + return { + modelValues: ref(['成都', '绵阳']), + titles: ref(['sourceHeader', 'targetHeader']), + source: sourceOption, + target: targetOption, + isSourceDroppable: ref(true) + }; + } + }); - /** + /** * 测试穿梭框拖拽排序 start */ - const transfer = wrapper.findComponent({ name: 'DTransfer' }) - const rightTransfer = wrapper.find('.devui-transfer-target').findComponent({ name: 'DTransferBase' }) - const rightOption = transfer.props().targetOption - const startDragItemIndex = rightOption.findIndex(item => item.value === '大连') - const startDropItemIndex = rightOption.findIndex(item => item.value === '广元') - expect(startDragItemIndex).toBe(3) - expect(startDropItemIndex).toBe(1) - rightTransfer.props().onDragend(rightOption[startDragItemIndex], rightOption[startDropItemIndex]) - await nextTick() - const endDragItemIndex = rightOption.findIndex(item => item.value === '大连') - const endDropItemIndex = rightOption.findIndex(item => item.value === '广元') - expect(endDragItemIndex).toBe(3) - expect(endDropItemIndex).toBe(1) - /** + const transfer = wrapper.findComponent({ name: 'DTransfer' }); + const rightTransfer = wrapper.find('.devui-transfer-target').findComponent({ name: 'DTransferBase' }); + const rightOption = transfer.props().targetOption; + const startDragItemIndex = rightOption.findIndex(item => item.value === '大连'); + const startDropItemIndex = rightOption.findIndex(item => item.value === '广元'); + expect(startDragItemIndex).toBe(3); + expect(startDropItemIndex).toBe(1); + rightTransfer.props().onDragend(rightOption[startDragItemIndex], rightOption[startDropItemIndex]); + await nextTick(); + const endDragItemIndex = rightOption.findIndex(item => item.value === '大连'); + const endDropItemIndex = rightOption.findIndex(item => item.value === '广元'); + expect(endDragItemIndex).toBe(3); + expect(endDropItemIndex).toBe(1); + /** * 测试穿梭框拖拽排序 end */ - }) -}) + }); +}); diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-base.ts b/packages/devui-vue/devui/transfer/common/use-transfer-base.ts index d79f3b5011..bbe96d8132 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer-base.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer-base.ts @@ -1,146 +1,145 @@ -import { computed, ExtractPropTypes, PropType, ComputedRef } from 'vue' -import { IItem, TState, TResult } from '../types' -import { TransferProps } from './use-transfer' -import { transferCommon, transferDragFunctions } from './use-transfer-common' +import { computed, ExtractPropTypes, PropType, ComputedRef } from 'vue'; +import { IItem, TState, TResult } from '../types'; +import { TransferProps } from './use-transfer'; +import { transferCommon, transferDragFunctions } from './use-transfer-common'; -export type TransferOperationProps = ExtractPropTypes<typeof transferBaseProps> +export type TransferOperationProps = ExtractPropTypes<typeof transferBaseProps>; export const transferBaseProps = { - ...transferCommon, - ...transferDragFunctions, - sourceOption: { - type: Array as () => IItem[], - default(): Array<IItem> { - return [] - } - }, - targetOption: { - type: Array as () => IItem[], - default(): Array<IItem> { - return [] - } - }, - type: { - type: String, - default: (): string => 'source' - }, - title: { - type: String, - default: (): string => 'Source' - }, - search: { - type: Boolean, - default: (): boolean => false - }, - allChecked: { - type: Boolean, - default: (): boolean => false - }, - filter: { - type: String, - default: (): string => '' - }, - height: { - type: String, - default: (): string => '320px' - }, - alltargetState: { - type: Boolean, - default: (): boolean => false - }, - checkedNum: { - type: Number, - default: (): number => 0 - }, - checkedValues: { - type: Array, - default: (): string[] => [] - }, - allCount: { - type: Number, - default: (): number => 0 - }, - isSourceDroppable: { - type: Boolean, - default: (): boolean => false - }, - isTargetDroppable: { - type: Boolean, - default: (): boolean => false - }, - scopedSlots: { - type: Object - }, - onChangeAllSource: { - type: Function as unknown as () => ((val: boolean) => void) - }, - onChangeQuery: { - type: Function as PropType<(val: string) => void> - }, - onUpdateCheckeds: { - type: Function as PropType<(val: string[]) => void> - }, - onDragend: { - type: Function as unknown as () => ((dragItem: IItem, dropItem: IItem) => void) + ...transferCommon, + ...transferDragFunctions, + sourceOption: { + type: Array as () => IItem[], + default(): Array<IItem> { + return []; } -} + }, + targetOption: { + type: Array as () => IItem[], + default(): Array<IItem> { + return []; + } + }, + type: { + type: String, + default: (): string => 'source' + }, + title: { + type: String, + default: (): string => 'Source' + }, + search: { + type: Boolean, + default: (): boolean => false + }, + allChecked: { + type: Boolean, + default: (): boolean => false + }, + filter: { + type: String, + default: (): string => '' + }, + height: { + type: String, + default: (): string => '320px' + }, + alltargetState: { + type: Boolean, + default: (): boolean => false + }, + checkedNum: { + type: Number, + default: (): number => 0 + }, + checkedValues: { + type: Array, + default: (): string[] => [] + }, + allCount: { + type: Number, + default: (): number => 0 + }, + isSourceDroppable: { + type: Boolean, + default: (): boolean => false + }, + isTargetDroppable: { + type: Boolean, + default: (): boolean => false + }, + scopedSlots: { + type: Object + }, + onChangeAllSource: { + type: Function as unknown as () => ((val: boolean) => void) + }, + onChangeQuery: { + type: Function as PropType<(val: string) => void> + }, + onUpdateCheckeds: { + type: Function as PropType<(val: string[]) => void> + }, + onDragend: { + type: Function as unknown as () => ((dragItem: IItem, dropItem: IItem) => void) + } +}; -export type TransferBaseProps = ExtractPropTypes<typeof transferBaseProps> +export type TransferBaseProps = ExtractPropTypes<typeof transferBaseProps>; export const transferOperationProps = { - sourceDisabled: { - type: Boolean, - default: (): boolean => true - }, - targetDisabled: { - type: Boolean, - default: (): boolean => true - }, - onUpdateSourceData: { - type: Function as unknown as () => (() => void) - }, - onUpdateTargetData: { - type: Function as unknown as () => (() => void) - } -} + sourceDisabled: { + type: Boolean, + default: (): boolean => true + }, + targetDisabled: { + type: Boolean, + default: (): boolean => true + }, + onUpdateSourceData: { + type: Function as unknown as () => (() => void) + }, + onUpdateTargetData: { + type: Function as unknown as () => (() => void) + } +}; const getFilterData = (props, type: string): TResult => { - const newModel: string[] = []; - const data: IItem[] = type === 'source' ? props.sourceOption : props.targetOption - const resultData: IItem[] = data.map((item: IItem) => { - const checked = props.modelValue.some(cur => cur === item.value) - checked && newModel.push(item.value) - return item - }) - return { - model: newModel, - data: resultData - } -} - + const newModel: string[] = []; + const data: IItem[] = type === 'source' ? props.sourceOption : props.targetOption; + const resultData: IItem[] = data.map((item: IItem) => { + const checked = props.modelValue.some(cur => cur === item.value); + checked && newModel.push(item.value); + return item; + }); + return { + model: newModel, + data: resultData + }; +}; export const initState = (props: TransferProps, type: string): TState => { - const initModel: TResult = getFilterData(props, type); - const state: TState = { - data: initModel.data, - allChecked: false, - disabled: false, - checkedNum: initModel.model.length, - keyword: '', - checkedValues: initModel.model, - filterData: initModel.data - } - return state -} + const initModel: TResult = getFilterData(props, type); + const state: TState = { + data: initModel.data, + allChecked: false, + disabled: false, + checkedNum: initModel.model.length, + keyword: '', + checkedValues: initModel.model, + filterData: initModel.data + }; + return state; +}; export const TransferBaseClass = (props: TransferOperationProps): ComputedRef => { - return computed(() => { - return `devui-transfer-panel devui-transfer-${props.type}` - }) -} + return computed(() => { + return `devui-transfer-panel devui-transfer-${props.type}`; + }); +}; export const Query = ((props: TransferOperationProps): ComputedRef => { - return computed(() => props.filter) -}) + return computed(() => props.filter); +}); diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts b/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts index 1507a161ad..b7c4ec5675 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer-checkbox.ts @@ -1,17 +1,17 @@ -import { ExtractPropTypes } from 'vue' -import { IItem } from '../types' -import { transferCommon } from './use-transfer-common' +import { ExtractPropTypes } from 'vue'; +import { IItem } from '../types'; +import { transferCommon } from './use-transfer-common'; const transferCheckboxProps = { - ...transferCommon, - data: { - type: Object as () => IItem, - }, - id: { - type: Number - } -} + ...transferCommon, + data: { + type: Object as () => IItem, + }, + id: { + type: Number + } +}; -export type TransferCheckboxProps = ExtractPropTypes<typeof transferCheckboxProps> +export type TransferCheckboxProps = ExtractPropTypes<typeof transferCheckboxProps>; -export default transferCheckboxProps \ No newline at end of file +export default transferCheckboxProps; diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-common.ts b/packages/devui-vue/devui/transfer/common/use-transfer-common.ts index 0ad911eb31..72fde7ba8e 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer-common.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer-common.ts @@ -1,34 +1,34 @@ -import { PropType } from 'vue' -import { IItem } from '../types' +import { PropType } from 'vue'; +import { IItem } from '../types'; export const transferCommon = { - showTooltip: { - type: Boolean, - default: (): boolean => false - }, - tooltipPosition: { - type: String as PropType<'top' | 'right' | 'bottom' | 'left'>, - default: (): string => 'top' - } -} + showTooltip: { + type: Boolean, + default: (): boolean => false + }, + tooltipPosition: { + type: String as PropType<'top' | 'right' | 'bottom' | 'left'>, + default: (): string => 'top' + } +}; export const transferDragFunctions = { - onDragstart: { - type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) - }, - onDrop: { - type: Function as unknown as () => ((event: Event, dropItem: IItem) => void) - }, - onDragleave: { - type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) - }, - onDragover: { - type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) - }, - onDragenter: { - type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) - }, - onDragend: { - type: Function as unknown as () => ((event: Event, dropItem: IItem) => void) - } -} + onDragstart: { + type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) + }, + onDrop: { + type: Function as unknown as () => ((event: Event, dropItem: IItem) => void) + }, + onDragleave: { + type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) + }, + onDragover: { + type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) + }, + onDragenter: { + type: Function as unknown as () => ((event: Event, dragItem: IItem) => void) + }, + onDragend: { + type: Function as unknown as () => ((event: Event, dropItem: IItem) => void) + } +}; diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-drag.ts b/packages/devui-vue/devui/transfer/common/use-transfer-drag.ts index be1f9f88f6..766f9d41da 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer-drag.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer-drag.ts @@ -1,20 +1,20 @@ -import { PropType, ExtractPropTypes } from '@vue/runtime-core' -import { IItem } from '../types' -import { transferCommon, transferDragFunctions } from './use-transfer-common' +import { PropType, ExtractPropTypes } from '@vue/runtime-core'; +import { IItem } from '../types'; +import { transferCommon, transferDragFunctions } from './use-transfer-common'; const transferDragProps = { - ...transferCommon, - ...transferDragFunctions, - itemData: { - type: Object as PropType<IItem> - }, - id: { - type: Number, - default: (): number | null => null - }, + ...transferCommon, + ...transferDragFunctions, + itemData: { + type: Object as PropType<IItem> + }, + id: { + type: Number, + default: (): number | null => null + }, -} +}; -export type TransferDragProps = ExtractPropTypes<typeof transferDragProps> +export type TransferDragProps = ExtractPropTypes<typeof transferDragProps>; -export default transferDragProps \ No newline at end of file +export default transferDragProps; diff --git a/packages/devui-vue/devui/transfer/common/use-transfer-operation.ts b/packages/devui-vue/devui/transfer/common/use-transfer-operation.ts index c4eb000f66..5fb8b46d1f 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer-operation.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer-operation.ts @@ -1,22 +1,22 @@ export const transferOperationProps = { - sourceDisabled: { - type: Boolean, - default: (): boolean => true - }, - targetDisabled: { - type: Boolean, - default: (): boolean => true - }, - disabled: { - type: Boolean, - default: (): boolean => false - }, - onUpdateSourceData: { - type: Function as unknown as () => (() => void) - }, - onUpdateTargetData: { - type: Function as unknown as () => (() => void) - } -} + sourceDisabled: { + type: Boolean, + default: (): boolean => true + }, + targetDisabled: { + type: Boolean, + default: (): boolean => true + }, + disabled: { + type: Boolean, + default: (): boolean => false + }, + onUpdateSourceData: { + type: Function as unknown as () => (() => void) + }, + onUpdateTargetData: { + type: Function as unknown as () => (() => void) + } +}; diff --git a/packages/devui-vue/devui/transfer/common/use-transfer.ts b/packages/devui-vue/devui/transfer/common/use-transfer.ts index 566d8546bb..410bb12b3a 100644 --- a/packages/devui-vue/devui/transfer/common/use-transfer.ts +++ b/packages/devui-vue/devui/transfer/common/use-transfer.ts @@ -1,90 +1,89 @@ -import { ExtractPropTypes, PropType, SetupContext } from 'vue' -import { IItem, ITitles, IModel, TState } from '../types' -import { transferCommon } from './use-transfer-common' +import { ExtractPropTypes, PropType, SetupContext } from 'vue'; +import { IItem, ITitles, IModel, TState } from '../types'; +import { transferCommon } from './use-transfer-common'; export const transferProps = { - ...transferCommon, - sourceOption: { - type: Array as () => IItem[], - require: true, - default(): IItem[] { - return [] - } - }, - targetOption: { - type: Array as () => IItem[], - require: true, - default(): IItem[] { - return [] - } - }, - titles: { - type: Array as PropType<ITitles>, - default: () => (): ITitles[] => ['Source', 'Target'] - }, - modelValue: { - type: Array as PropType<string | number[]>, - default: () => (): IModel[] => [], - }, - height: { - type: String, - default: (): string => '320px' - }, - isSearch: { - type: Boolean, - default: (): boolean => false - }, - isSourceDroppable: { - type: Boolean, - default: (): boolean => false - }, - isTargetDroppable: { - type: Boolean, - default: (): boolean => false - }, - disabled: { - type: Boolean, - default: (): boolean => false - }, - beforeTransfer: { - type: Function as unknown as () => ((sourceOption: TState, targetOption: TState) => boolean | Promise<boolean>) - }, - slots: { - type: Object - }, - searching: { - type: Function as unknown as () => ((direction: string, keyword: string, targetOption: TState) => void) - }, - transferToSource: { - type: Function as unknown as () => ((sourceOption: TState, targetOption: TState) => void) - }, - transferToTarget: { - type: Function as unknown as () => ((sourceOption: TState, targetOption: TState) => void) - }, - transferring: { - type: Function as unknown as () => ((targetOption: TState) => void) - }, - afterTransfer: { - type: Function as unknown as () => ((targetOption: TState) => void) - }, - onDragend: { - type: Function as unknown as () => ((direction: string, dragItem: IItem, dropItem: IItem) => void) + ...transferCommon, + sourceOption: { + type: Array as () => IItem[], + require: true, + default(): IItem[] { + return []; } -} + }, + targetOption: { + type: Array as () => IItem[], + require: true, + default(): IItem[] { + return []; + } + }, + titles: { + type: Array as PropType<ITitles>, + default: () => (): ITitles[] => ['Source', 'Target'] + }, + modelValue: { + type: Array as PropType<string | number[]>, + default: () => (): IModel[] => [], + }, + height: { + type: String, + default: (): string => '320px' + }, + isSearch: { + type: Boolean, + default: (): boolean => false + }, + isSourceDroppable: { + type: Boolean, + default: (): boolean => false + }, + isTargetDroppable: { + type: Boolean, + default: (): boolean => false + }, + disabled: { + type: Boolean, + default: (): boolean => false + }, + beforeTransfer: { + type: Function as unknown as () => ((sourceOption: TState, targetOption: TState) => boolean | Promise<boolean>) + }, + slots: { + type: Object + }, + searching: { + type: Function as unknown as () => ((direction: string, keyword: string, targetOption: TState) => void) + }, + transferToSource: { + type: Function as unknown as () => ((sourceOption: TState, targetOption: TState) => void) + }, + transferToTarget: { + type: Function as unknown as () => ((sourceOption: TState, targetOption: TState) => void) + }, + transferring: { + type: Function as unknown as () => ((targetOption: TState) => void) + }, + afterTransfer: { + type: Function as unknown as () => ((targetOption: TState) => void) + }, + onDragend: { + type: Function as unknown as () => ((direction: string, dragItem: IItem, dropItem: IItem) => void) + } +}; export type TransferProps = ExtractPropTypes<typeof transferProps>; export const headerSlot = (ctx: SetupContext, name: string): unknown => { - return !ctx.slots[`${name}-header`] ? null : () => ctx.slots[`${name}-header`] && ctx.slots[`${name}-header`]() -} + return !ctx.slots[`${name}-header`] ? null : () => ctx.slots[`${name}-header`] && ctx.slots[`${name}-header`](); +}; export const bodySlot = (ctx: SetupContext, name: string): unknown => { - return !ctx.slots[`${name}-body`] ? null : () => ctx.slots[`${name}-body`] && ctx.slots[`${name}-body`]() -} + return !ctx.slots[`${name}-body`] ? null : () => ctx.slots[`${name}-body`] && ctx.slots[`${name}-body`](); +}; export const opeartionSlot = (ctx: SetupContext): unknown => { - return ctx.slots && ctx.slots.operation && ctx.slots.operation() || null -} - + return ctx.slots && ctx.slots.operation && ctx.slots.operation() || null; +}; diff --git a/packages/devui-vue/devui/transfer/index.ts b/packages/devui-vue/devui/transfer/index.ts index fb99c5b75d..2f0979b471 100644 --- a/packages/devui-vue/devui/transfer/index.ts +++ b/packages/devui-vue/devui/transfer/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Transfer from './src/transfer' +import type { App } from 'vue'; +import Transfer from './src/transfer'; Transfer.install = function (app: App) { - app.component(Transfer.name, Transfer) -} + app.component(Transfer.name, Transfer); +}; -export { Transfer } +export { Transfer }; export default { title: 'Transfer 穿梭框', category: '数据录入', status: '40%', install(app: App): void { - app.use(Transfer as any) + app.use(Transfer as any); } -} +}; diff --git a/packages/devui-vue/devui/transfer/src/transfer-base.tsx b/packages/devui-vue/devui/transfer/src/transfer-base.tsx index 29411f83f5..d8113e257b 100644 --- a/packages/devui-vue/devui/transfer/src/transfer-base.tsx +++ b/packages/devui-vue/devui/transfer/src/transfer-base.tsx @@ -1,163 +1,163 @@ -import { defineComponent, computed, ref, watch, SetupContext } from 'vue' -import { transferBaseProps, TransferBaseClass, TransferBaseProps } from '../common/use-transfer-base' -import DCheckbox from '../../checkbox/src/checkbox' -import DCheckboxGroup from '../../checkbox/src/checkbox-group' -import DSearch from '../../search/src/search' -import DTransferDrag from './transfer-drag-item' -import DTransfeCheckbox from './transfer-checkbox' +import { defineComponent, computed, ref, watch, SetupContext } from 'vue'; +import { transferBaseProps, TransferBaseClass, TransferBaseProps } from '../common/use-transfer-base'; +import DCheckbox from '../../checkbox/src/checkbox'; +import DCheckboxGroup from '../../checkbox/src/checkbox-group'; +import DSearch from '../../search/src/search'; +import DTransferDrag from './transfer-drag-item'; +import DTransfeCheckbox from './transfer-checkbox'; export default defineComponent({ - name: 'DTransferBase', - components: { - DSearch, - DCheckboxGroup, - DCheckbox, - DTransferDrag, - DTransfeCheckbox - }, - props: transferBaseProps, - setup(props: TransferBaseProps, ctx: SetupContext) { - /** data start **/ - const allHalfchecked = ref(false)//ref(props.allChecked) - const modelValues = computed(() => props.checkedValues as Array<string>) - const dragWrapClass = computed(() => { - const isDrag = props.isSourceDroppable || props.isTargetDroppable - return `devui-transfer-panel-body-list devui-transfer-panel-body-${isDrag ? '' : 'no'}drag` - }) - const searchQuery = computed(() => props.filter) - const baseClass = TransferBaseClass(props) - const dropItem = ref(null) + name: 'DTransferBase', + components: { + DSearch, + DCheckboxGroup, + DCheckbox, + DTransferDrag, + DTransfeCheckbox + }, + props: transferBaseProps, + setup(props: TransferBaseProps, ctx: SetupContext) { + /** data start **/ + const allHalfchecked = ref(false);// ref(props.allChecked) + const modelValues = computed(() => props.checkedValues as Array<string>); + const dragWrapClass = computed(() => { + const isDrag = props.isSourceDroppable || props.isTargetDroppable; + return `devui-transfer-panel-body-list devui-transfer-panel-body-${isDrag ? '' : 'no'}drag`; + }); + const searchQuery = computed(() => props.filter); + const baseClass = TransferBaseClass(props); + const dropItem = ref(null); - /** data end **/ + /** data end **/ - /** watch start **/ - watch( - () => props.checkedNum, - (nVal) => { - if (props.allChecked) { - allHalfchecked.value = !props.allChecked - } else { - allHalfchecked.value = nVal !== 0 - } - }, - { - immediate: true - } - ) - /** watch end **/ + /** watch start **/ + watch( + () => props.checkedNum, + (nVal) => { + if (props.allChecked) { + allHalfchecked.value = !props.allChecked; + } else { + allHalfchecked.value = nVal !== 0; + } + }, + { + immediate: true + } + ); + /** watch end **/ - /** methods start **/ - const updateSearchQuery = (val: string): void => ctx.emit('changeQuery', val) + /** methods start **/ + const updateSearchQuery = (val: string): void => ctx.emit('changeQuery', val); - const renderCheckboxGroup = () => { - return <DCheckboxGroup - modelValue={modelValues.value} - onChange={ - (values: string[]): void => ctx.emit('updateCheckeds', values) - }> - { - props.sourceOption.map((item, idx) => { - return <DTransfeCheckbox - data={item} - id={idx} - showTooltip={props.showTooltip} - tooltipPosition={props.tooltipPosition}> - </DTransfeCheckbox> - }) - } - </DCheckboxGroup> + const renderCheckboxGroup = () => { + return <DCheckboxGroup + modelValue={modelValues.value} + onChange={ + (values: string[]): void => ctx.emit('updateCheckeds', values) + }> + { + props.sourceOption.map((item, idx) => { + return <DTransfeCheckbox + data={item} + id={idx} + showTooltip={props.showTooltip} + tooltipPosition={props.tooltipPosition}> + </DTransfeCheckbox>; + }) } + </DCheckboxGroup>; + }; - const renderDragCheckboxGroup = () => { - return <DCheckboxGroup - modelValue={modelValues.value} - onChange={ - (values: string[]): void => ctx.emit('updateCheckeds', values) - }> - { - props.sourceOption.map((item, idx) => { - return <DTransferDrag - itemData={item} - id={idx} - showTooltip={props.showTooltip} - tooltipPosition={props.tooltipPosition} - onDrop={(event, item) => { - dropItem.value = item - }} - onDragend={(event, dragItem) => { - props.onDragend && props.onDragend(dragItem, dropItem.value) - }} /> - }) - } - </DCheckboxGroup> + const renderDragCheckboxGroup = () => { + return <DCheckboxGroup + modelValue={modelValues.value} + onChange={ + (values: string[]): void => ctx.emit('updateCheckeds', values) + }> + { + props.sourceOption.map((item, idx) => { + return <DTransferDrag + itemData={item} + id={idx} + showTooltip={props.showTooltip} + tooltipPosition={props.tooltipPosition} + onDrop={(event, item) => { + dropItem.value = item; + }} + onDragend={(event, dragItem) => { + props.onDragend && props.onDragend(dragItem, dropItem.value); + }} />; + }) } + </DCheckboxGroup>; + }; - /** methods start **/ + /** methods start **/ - return { - baseClass, - searchQuery, - dragWrapClass, - modelValues, - dropItem, - allHalfchecked, - updateSearchQuery, - renderCheckboxGroup, - renderDragCheckboxGroup - } - }, - render() { - const { - title, - baseClass, - checkedNum, - allChecked, - allHalfchecked, - sourceOption, - allCount, - updateSearchQuery, - search, - searchQuery, - dragWrapClass, - height, - isSourceDroppable, - isTargetDroppable, - renderCheckboxGroup, - renderDragCheckboxGroup - } = this + return { + baseClass, + searchQuery, + dragWrapClass, + modelValues, + dropItem, + allHalfchecked, + updateSearchQuery, + renderCheckboxGroup, + renderDragCheckboxGroup + }; + }, + render() { + const { + title, + baseClass, + checkedNum, + allChecked, + allHalfchecked, + sourceOption, + allCount, + updateSearchQuery, + search, + searchQuery, + dragWrapClass, + height, + isSourceDroppable, + isTargetDroppable, + renderCheckboxGroup, + renderDragCheckboxGroup + } = this; - return ( - <div class={baseClass}> - { - this.$slots.header ? this.$slots.header() : (<div class="devui-transfer-panel-header"> - <div class="devui-transfer-panel-header-allChecked"> - <DCheckbox - halfchecked={allHalfchecked} - modelValue={allChecked} - onChange={(value: boolean) => { - this.$emit('changeAllSource', value) - }}> - {title} - </DCheckbox> - </div> - <div class="devui-transfer-panel-header-num">{checkedNum}/{allCount}</div> - </div>) - } + return ( + <div class={baseClass}> + { + this.$slots.header ? this.$slots.header() : (<div class="devui-transfer-panel-header"> + <div class="devui-transfer-panel-header-allChecked"> + <DCheckbox + halfchecked={allHalfchecked} + modelValue={allChecked} + onChange={(value: boolean) => { + this.$emit('changeAllSource', value); + }}> + {title} + </DCheckbox> + </div> + <div class="devui-transfer-panel-header-num">{checkedNum}/{allCount}</div> + </div>) + } + { + this.$slots.body ? this.$slots.body() : + <div class="devui-transfer-panel-body"> + {search && <div class="devui-transfer-panel-body-search"> + <DSearch modelValue={searchQuery} onUpdate:modelValue={updateSearchQuery} /> + </div>} + <div class={dragWrapClass} style={{ height: height }}> { - this.$slots.body ? this.$slots.body() : - <div class="devui-transfer-panel-body"> - {search && <div class="devui-transfer-panel-body-search"> - <DSearch modelValue={searchQuery} onUpdate:modelValue={updateSearchQuery} /> - </div>} - <div class={dragWrapClass} style={{ height: height }}> - { - sourceOption.length ? - (isSourceDroppable || isTargetDroppable ? renderDragCheckboxGroup() : renderCheckboxGroup()) - : <div class="devui-transfer-panel-body-list-empty">无数据</div> - } - </div> - </div> + sourceOption.length ? + (isSourceDroppable || isTargetDroppable ? renderDragCheckboxGroup() : renderCheckboxGroup()) + : <div class="devui-transfer-panel-body-list-empty">无数据</div> } + </div> </div> - ) - } -}) \ No newline at end of file + } + </div> + ); + } +}); diff --git a/packages/devui-vue/devui/transfer/src/transfer-checkbox.tsx b/packages/devui-vue/devui/transfer/src/transfer-checkbox.tsx index 554277da83..3a67897ed3 100644 --- a/packages/devui-vue/devui/transfer/src/transfer-checkbox.tsx +++ b/packages/devui-vue/devui/transfer/src/transfer-checkbox.tsx @@ -1,42 +1,42 @@ -import { defineComponent } from 'vue' -import DCheckbox from '../../checkbox/src/checkbox' -import DTooltip from '../../tooltip/src/tooltip' -import transferCheckboxProps, { TransferCheckboxProps } from '../common/use-transfer-checkbox' +import { defineComponent } from 'vue'; +import DCheckbox from '../../checkbox/src/checkbox'; +import DTooltip from '../../tooltip/src/tooltip'; +import transferCheckboxProps, { TransferCheckboxProps } from '../common/use-transfer-checkbox'; export default defineComponent({ - name: 'DTransferCheckbox', - components: { - DCheckbox, - DTooltip - }, - props: transferCheckboxProps, - setup(props: TransferCheckboxProps) { - /** data start **/ - const renderCheckbox = () => { - return <DCheckbox - label={props.data.key} - value={props.data.value} - disabled={props.data.disabled} - class="devui-transfer-panel-body-list-item" - key={props.id}> - </DCheckbox> - } - /** data end **/ + name: 'DTransferCheckbox', + components: { + DCheckbox, + DTooltip + }, + props: transferCheckboxProps, + setup(props: TransferCheckboxProps) { + /** data start **/ + const renderCheckbox = () => { + return <DCheckbox + label={props.data.key} + value={props.data.value} + disabled={props.data.disabled} + class="devui-transfer-panel-body-list-item" + key={props.id}> + </DCheckbox>; + }; + /** data end **/ - /** watch start **/ - /** watch end **/ + /** watch start **/ + /** watch end **/ - /** methods start **/ - /** methods end **/ + /** methods start **/ + /** methods end **/ - return () => { - return ( - !props.showTooltip ? renderCheckbox() : - <DTooltip class="devui-transfer-panel-body-list-tooltip" - position={props.tooltipPosition} - content={props.data.key}>{renderCheckbox()} - </DTooltip> - ) - } - } -}) \ No newline at end of file + return () => { + return ( + !props.showTooltip ? renderCheckbox() : + <DTooltip class="devui-transfer-panel-body-list-tooltip" + position={props.tooltipPosition} + content={props.data.key}>{renderCheckbox()} + </DTooltip> + ); + }; + } +}); diff --git a/packages/devui-vue/devui/transfer/src/transfer-drag-item.tsx b/packages/devui-vue/devui/transfer/src/transfer-drag-item.tsx index bb104fd3c4..65fd944ada 100644 --- a/packages/devui-vue/devui/transfer/src/transfer-drag-item.tsx +++ b/packages/devui-vue/devui/transfer/src/transfer-drag-item.tsx @@ -1,134 +1,134 @@ -import { defineComponent, ref, onUnmounted } from 'vue' -import transferDragProps, { TransferDragProps } from '../common/use-transfer-drag' -import DTransfeCheckbox from './transfer-checkbox' -import '@devui-design/icons/icomoon/devui-icon.css' +import { defineComponent, ref, onUnmounted } from 'vue'; +import transferDragProps, { TransferDragProps } from '../common/use-transfer-drag'; +import DTransfeCheckbox from './transfer-checkbox'; +import '@devui-design/icons/icomoon/devui-icon.css'; export default defineComponent({ - name: 'DTransferDrag', - components: { - DTransfeCheckbox - }, - props: transferDragProps, - setup(props: TransferDragProps) { - /** data start **/ - const dragRef = ref(null) - const dragHighlight = ref(false) - const dragOverNodeKey = ref('') - const dropPosition = ref(null) - const dragTimer = ref(null) - /** data end **/ + name: 'DTransferDrag', + components: { + DTransfeCheckbox + }, + props: transferDragProps, + setup(props: TransferDragProps) { + /** data start **/ + const dragRef = ref(null); + const dragHighlight = ref(false); + const dragOverNodeKey = ref(''); + const dropPosition = ref(null); + const dragTimer = ref(null); + /** data end **/ - /** watch start **/ - /** watch end **/ + /** watch start **/ + /** watch end **/ - /** methods start **/ - /** + /** methods start **/ + /** * calcDropPosition: 根据event计算位置 * event: event对象 */ - const calcDropPosition = (event): number => { - const { clientY } = event; - const { top, bottom, height } = dragRef.value.getBoundingClientRect(); - const des = Math.max(height * 0.25, 2); + const calcDropPosition = (event): number => { + const { clientY } = event; + const { top, bottom, height } = dragRef.value.getBoundingClientRect(); + const des = Math.max(height * 0.25, 2); - if (clientY <= top + des) { - return -1; - } - if (clientY >= bottom - des) { - return 1; - } - return 0; - } - /** + if (clientY <= top + des) { + return -1; + } + if (clientY >= bottom - des) { + return 1; + } + return 0; + }; + /** * resetState: 重置属性 */ - const resetState = () => { - dragOverNodeKey.value = '' - dropPosition.value = null - dragHighlight.value = null - } - /** methods end **/ + const resetState = () => { + dragOverNodeKey.value = ''; + dropPosition.value = null; + dragHighlight.value = null; + }; + /** methods end **/ - /** 生命周期 start **/ - onUnmounted(() => { - clearTimeout(dragTimer.value) - }) - /** 生命周期 end **/ + /** 生命周期 start **/ + onUnmounted(() => { + clearTimeout(dragTimer.value); + }); + /** 生命周期 end **/ - return () => { - const state = dragOverNodeKey.value === props.itemData.key - return ( - <div class={{ - 'devui-transfer-panel-body-list-item': true, - 'devui-transfer-drag-dragging': dragHighlight.value, - 'devui-transfer-drag-over': state && dropPosition.value === 0, - 'devui-transfer–drag-over-top': state && dropPosition.value === -1, - 'devui-transfer–drag-over-bottom': state && dropPosition.value === 1, - }} - onDragenter={event => { - event.preventDefault(); - event.stopPropagation(); - clearTimeout(dragTimer.value) - const curDropPosition = calcDropPosition(event) - if (props.itemData.key === dragOverNodeKey.value && curDropPosition === 0) { - resetState() - return - } - dragTimer.value = setTimeout(() => { - dragOverNodeKey.value = props.itemData.key - dropPosition.value = curDropPosition - }, 0); - props.onDragenter && props.onDragenter(event, props.itemData) - }} - onDragover={event => { - event.preventDefault() - event.stopPropagation() - if (props.itemData.key === dragOverNodeKey.value) { - const curDropPosition = calcDropPosition(event) - if (curDropPosition === dropPosition.value) { - return - } - dropPosition.value = curDropPosition; - } - props.onDragover && props.onDragover(event, props.itemData) - }} - onDragleave={event => { - event.stopPropagation() - resetState() - props.onDragleave && props.onDragleave(event, props.itemData) - }} - onDrop={event => { - event.preventDefault() - event.stopPropagation() - resetState() - props.onDrop && props.onDrop(event, props.itemData) - }} - onDragend={event => { - event.stopPropagation() - props.onDragend && props.onDragend(event, props.itemData) - }}> - <div - class="devui-transfer-panel-body-list-drag" - draggable={true} - ref={dragRef} - onDragstart={event => { - event.stopPropagation() - dragHighlight.value = true - props.onDragstart && props.onDragstart(event, props.itemData) - }} - > - <span class="devui-transfer-panel-body-list-drag__icon"> - <d-icon name="drag-small" /> - </span> - <DTransfeCheckbox - data={props.itemData} - id={props.id} - showTooltip={props.showTooltip} - tooltipPosition={props.tooltipPosition}> - </DTransfeCheckbox> - </div> - </div> - ) - } - } -}) \ No newline at end of file + return () => { + const state = dragOverNodeKey.value === props.itemData.key; + return ( + <div class={{ + 'devui-transfer-panel-body-list-item': true, + 'devui-transfer-drag-dragging': dragHighlight.value, + 'devui-transfer-drag-over': state && dropPosition.value === 0, + 'devui-transfer–drag-over-top': state && dropPosition.value === -1, + 'devui-transfer–drag-over-bottom': state && dropPosition.value === 1, + }} + onDragenter={event => { + event.preventDefault(); + event.stopPropagation(); + clearTimeout(dragTimer.value); + const curDropPosition = calcDropPosition(event); + if (props.itemData.key === dragOverNodeKey.value && curDropPosition === 0) { + resetState(); + return; + } + dragTimer.value = setTimeout(() => { + dragOverNodeKey.value = props.itemData.key; + dropPosition.value = curDropPosition; + }, 0); + props.onDragenter && props.onDragenter(event, props.itemData); + }} + onDragover={event => { + event.preventDefault(); + event.stopPropagation(); + if (props.itemData.key === dragOverNodeKey.value) { + const curDropPosition = calcDropPosition(event); + if (curDropPosition === dropPosition.value) { + return; + } + dropPosition.value = curDropPosition; + } + props.onDragover && props.onDragover(event, props.itemData); + }} + onDragleave={event => { + event.stopPropagation(); + resetState(); + props.onDragleave && props.onDragleave(event, props.itemData); + }} + onDrop={event => { + event.preventDefault(); + event.stopPropagation(); + resetState(); + props.onDrop && props.onDrop(event, props.itemData); + }} + onDragend={event => { + event.stopPropagation(); + props.onDragend && props.onDragend(event, props.itemData); + }}> + <div + class="devui-transfer-panel-body-list-drag" + draggable={true} + ref={dragRef} + onDragstart={event => { + event.stopPropagation(); + dragHighlight.value = true; + props.onDragstart && props.onDragstart(event, props.itemData); + }} + > + <span class="devui-transfer-panel-body-list-drag__icon"> + <d-icon name="drag-small" /> + </span> + <DTransfeCheckbox + data={props.itemData} + id={props.id} + showTooltip={props.showTooltip} + tooltipPosition={props.tooltipPosition}> + </DTransfeCheckbox> + </div> + </div> + ); + }; + } +}); diff --git a/packages/devui-vue/devui/transfer/src/transfer-operation.tsx b/packages/devui-vue/devui/transfer/src/transfer-operation.tsx index 4815a47401..a0f1bdd4c3 100644 --- a/packages/devui-vue/devui/transfer/src/transfer-operation.tsx +++ b/packages/devui-vue/devui/transfer/src/transfer-operation.tsx @@ -1,28 +1,28 @@ import { defineComponent } from 'vue'; -import DButton from '../../button/src/button' -import { transferOperationProps } from '../common/use-transfer-operation' +import DButton from '../../button/src/button'; +import { transferOperationProps } from '../common/use-transfer-operation'; export default defineComponent({ - name: 'DTransferOperation', - components: { - DButton - }, - props: transferOperationProps, - setup(props, ctx) { - return () => { - return ctx.slots.operation && ctx.slots.operation() || <div class="devui-transfer-panel-operation"> - <div class="devui-transfer-panel-operation-group"> - <DButton - class="devui-transfer-panel-operation-group-left" - disabled={props.disabled ? props.disabled : props.sourceDisabled} - onClick={() => ctx.emit('updateSourceData')}> - <span class="icon-collapse"></span> - </DButton> - <DButton class="devui-transfer-panel-operation-group-right" disabled={props.disabled ? props.disabled : props.targetDisabled} onClick={() => ctx.emit('updateTargetData')}> - <span class="icon-chevron-right"></span> - </DButton> - </div> - </div> - } - } -}) \ No newline at end of file + name: 'DTransferOperation', + components: { + DButton + }, + props: transferOperationProps, + setup(props, ctx) { + return () => { + return ctx.slots.operation && ctx.slots.operation() || <div class="devui-transfer-panel-operation"> + <div class="devui-transfer-panel-operation-group"> + <DButton + class="devui-transfer-panel-operation-group-left" + disabled={props.disabled ? props.disabled : props.sourceDisabled} + onClick={() => ctx.emit('updateSourceData')}> + <span class="icon-collapse"></span> + </DButton> + <DButton class="devui-transfer-panel-operation-group-right" disabled={props.disabled ? props.disabled : props.targetDisabled} onClick={() => ctx.emit('updateTargetData')}> + <span class="icon-chevron-right"></span> + </DButton> + </div> + </div>; + }; + } +}); diff --git a/packages/devui-vue/devui/transfer/src/transfer.tsx b/packages/devui-vue/devui/transfer/src/transfer.tsx index 9fcf636bc0..2e5ee8595f 100644 --- a/packages/devui-vue/devui/transfer/src/transfer.tsx +++ b/packages/devui-vue/devui/transfer/src/transfer.tsx @@ -1,11 +1,11 @@ -import { defineComponent, reactive, watch, ref, SetupContext } from 'vue' -import { TState, IItem } from '../types' -import DTransferBase from './transfer-base' -import DTransferOperation from './transfer-operation' -import { initState } from '../common/use-transfer-base' -import { transferProps, TransferProps, headerSlot, bodySlot, opeartionSlot } from '../common/use-transfer' -import DCheckbox from '../../checkbox/src/checkbox' -import './transfer.scss' +import { defineComponent, reactive, watch, ref, SetupContext } from 'vue'; +import { TState, IItem } from '../types'; +import DTransferBase from './transfer-base'; +import DTransferOperation from './transfer-operation'; +import { initState } from '../common/use-transfer-base'; +import { transferProps, TransferProps, headerSlot, bodySlot, opeartionSlot } from '../common/use-transfer'; +import DCheckbox from '../../checkbox/src/checkbox'; +import './transfer.scss'; export default defineComponent({ name: 'DTransfer', @@ -17,8 +17,8 @@ export default defineComponent({ props: transferProps, setup(props: TransferProps, ctx: SetupContext) { /** data start **/ - let leftOptions = reactive<TState>(initState(props, 'source')) - let rightOptions = reactive<TState>(initState(props, 'target')) + let leftOptions = reactive<TState>(initState(props, 'source')); + let rightOptions = reactive<TState>(initState(props, 'target')); const origin = ref(null); /** data end **/ @@ -26,143 +26,143 @@ export default defineComponent({ watch( () => props.sourceOption, () => { - leftOptions = reactive<TState>(initState(props, 'source')) + leftOptions = reactive<TState>(initState(props, 'source')); } - ) + ); watch( () => props.targetOption, () => { - rightOptions = reactive<TState>(initState(props, 'target')) + rightOptions = reactive<TState>(initState(props, 'target')); } - ) + ); watch( () => leftOptions.keyword, (): void => { - searchFilterData(leftOptions) + searchFilterData(leftOptions); } - ) + ); watch( () => leftOptions.checkedValues, (values: string[]): void => { - leftOptions.checkedNum = values.length - setAllCheckedState(leftOptions, values) + leftOptions.checkedNum = values.length; + setAllCheckedState(leftOptions, values); }, { deep: true } - ) + ); watch( () => rightOptions.keyword, (): void => { - searchFilterData(rightOptions) + searchFilterData(rightOptions); }, - ) + ); watch( () => rightOptions.checkedValues, (values: string[]): void => { rightOptions.checkedNum = values.length; - setAllCheckedState(rightOptions, values) + setAllCheckedState(rightOptions, values); }, { deep: true } - ) + ); /** watch end **/ /** methods start **/ const setAllCheckedState = (source: TState, value: string[]): void => { if (origin.value === 'click') { - source.allChecked = false + source.allChecked = false; } else { - source.allChecked = value.length === source.data.filter(item => !item.disabled).length ? true : false + source.allChecked = value.length === source.data.filter(item => !item.disabled).length ? true : false; } - } + }; const updateFilterData = async (source: TState, target: TState, direction: string): Promise<void> => { if (isFunction('beforeTransfer')) { - const res: boolean = await props.beforeTransfer.call(null, source, target) + const res: boolean = await props.beforeTransfer.call(null, source, target); if (typeof res === 'boolean' && res === false) { - return + return; } } - const hasToSource = isFunction('transferToSource') - const hasToTarget = isFunction('transferToTarget') - const hasTransfering = isFunction('transferring') + const hasToSource = isFunction('transferToSource'); + const hasToTarget = isFunction('transferToTarget'); + const hasTransfering = isFunction('transferring'); if (hasToSource || hasToTarget) { - direction === 'right' && props.transferToSource.call(null, source, target) - direction === 'left' && props.transferToTarget.call(null, source, target) + direction === 'right' && props.transferToSource.call(null, source, target); + direction === 'left' && props.transferToTarget.call(null, source, target); } else { source.data = source.data.filter(item => { - const hasInclues = source.checkedValues.includes(item.value) - hasInclues && target.data.push(item) - return !hasInclues - }) + const hasInclues = source.checkedValues.includes(item.value); + hasInclues && target.data.push(item); + return !hasInclues; + }); } if (hasTransfering) { - props.transferring.call(null, target) + props.transferring.call(null, target); } - source.checkedValues = [] - target.disabled = !target.disabled - searchFilterData(source, target) - searchFilterData(target, source) - setOrigin('click') - isFunction('afterTransfer') && props.afterTransfer.call(null, target) - } + source.checkedValues = []; + target.disabled = !target.disabled; + searchFilterData(source, target); + searchFilterData(target, source); + setOrigin('click'); + isFunction('afterTransfer') && props.afterTransfer.call(null, target); + }; const changeAllSource = (source: TState, value: boolean): void => { - if (source.filterData.every(item => item.disabled)) return - source.allChecked = value + if (source.filterData.every(item => item.disabled)) {return;} + source.allChecked = value; if (value) { source.checkedValues = source.filterData.filter(item => !item.disabled) - .map(item => item.value) + .map(item => item.value); } else { - source.checkedValues = [] + source.checkedValues = []; } - setOrigin('change') - } + setOrigin('change'); + }; const updateLeftCheckeds = (values: string[]): void => { - leftOptions.checkedValues = values - setOrigin('change') - } + leftOptions.checkedValues = values; + setOrigin('change'); + }; const updateRightCheckeds = (values: string[]): void => { - rightOptions.checkedValues = values - setOrigin('change') - } + rightOptions.checkedValues = values; + setOrigin('change'); + }; const searchFilterData = (source: TState, target?: TState): void => { - source.filterData = source.data.filter(item => item.key.indexOf(source.keyword) !== -1) + source.filterData = source.data.filter(item => item.key.indexOf(source.keyword) !== -1); if (target) { - target.allChecked = false + target.allChecked = false; } - } + }; const setOrigin = (value: string): void => { - origin.value = value - } + origin.value = value; + }; const changeQueryHandle = (source: TState, direction: string, value: string): void => { if (props?.searching && typeof props.searching === 'function') { - props.searching.call(null, direction, value, source) - return + props.searching.call(null, direction, value, source); + return; } - source.keyword = value - } + source.keyword = value; + }; const isFunction = (type: string): boolean => { - return props[type] && typeof props[type] === 'function' - } + return props[type] && typeof props[type] === 'function'; + }; const dataSort = (target: TState, dragItem: IItem, dropItem: IItem, direction: string) => { - const startIndex = target.filterData.findIndex(item => item.key === dragItem.key) - const endIndex = target.filterData.findIndex(item => item.key === dropItem.key) - target.filterData.splice(endIndex, 1, dragItem) - target.filterData.splice(startIndex, 1, dropItem) - props.onDragend && props.onDragend(direction, dragItem, dropItem) - } + const startIndex = target.filterData.findIndex(item => item.key === dragItem.key); + const endIndex = target.filterData.findIndex(item => item.key === dropItem.key); + target.filterData.splice(endIndex, 1, dragItem); + target.filterData.splice(startIndex, 1, dropItem); + props.onDragend && props.onDragend(direction, dragItem, dropItem); + }; /** methods end **/ return () => { @@ -199,8 +199,8 @@ export default defineComponent({ disabled={props.disabled} sourceDisabled={rightOptions.checkedNum > 0 ? false : true} targetDisabled={leftOptions.checkedNum > 0 ? false : true} - onUpdateSourceData={() => { updateFilterData(rightOptions, leftOptions, 'left') }} - onUpdateTargetData={() => { updateFilterData(leftOptions, rightOptions, 'right') }} + onUpdateSourceData={() => { updateFilterData(rightOptions, leftOptions, 'left'); }} + onUpdateTargetData={() => { updateFilterData(leftOptions, rightOptions, 'right'); }} /> <DTransferBase v-slots={ @@ -227,7 +227,7 @@ export default defineComponent({ onChangeQuery={(value) => changeQueryHandle(rightOptions, 'right', value)} onDragend={(dragItem, dropItem) => dataSort(rightOptions, dragItem, dropItem, 'right')} /> - </div> - } + </div>; + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/transfer/types.ts b/packages/devui-vue/devui/transfer/types.ts index 3846d0da75..7de6e4ff82 100644 --- a/packages/devui-vue/devui/transfer/types.ts +++ b/packages/devui-vue/devui/transfer/types.ts @@ -1,32 +1,31 @@ export interface IItem { - key: string - value: string - disabled: boolean + key: string; + value: string; + disabled: boolean; } export interface ITitles { - [index: number]: string + [index: number]: string; } export interface IModel { - [index: number]: string | number + [index: number]: string | number; } export interface TState { - data: IItem[] - allChecked: boolean - checkedNum: number - keyword: string - checkedValues: string[] - filterData: IItem[] - disabled: boolean + data: IItem[]; + allChecked: boolean; + checkedNum: number; + keyword: string; + checkedValues: string[]; + filterData: IItem[]; + disabled: boolean; } export interface TResult { - model: string[] - data: IItem[] + model: string[]; + data: IItem[]; } - diff --git a/packages/devui-vue/devui/tree-select/__tests__/tree-select.spec.ts b/packages/devui-vue/devui/tree-select/__tests__/tree-select.spec.ts index f35fcbe2bf..650029c961 100644 --- a/packages/devui-vue/devui/tree-select/__tests__/tree-select.spec.ts +++ b/packages/devui-vue/devui/tree-select/__tests__/tree-select.spec.ts @@ -54,4 +54,4 @@ describe('tree-select', () => { expect(wrapper.classes()).toContain('devui-tree-select'); }); -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/devui/tree-select/hooks/use-clear.ts b/packages/devui-vue/devui/tree-select/hooks/use-clear.ts index f81d37dfb8..7cef9b0c4f 100644 --- a/packages/devui-vue/devui/tree-select/hooks/use-clear.ts +++ b/packages/devui-vue/devui/tree-select/hooks/use-clear.ts @@ -1,40 +1,40 @@ -import { computed } from 'vue' -import type { SetupContext, Ref } from 'vue' -import { TreeSelectProps } from '../src/tree-select-types' +import { computed } from 'vue'; +import type { SetupContext, Ref } from 'vue'; +import { TreeSelectProps } from '../src/tree-select-types'; export default function useClear(props: TreeSelectProps, ctx: SetupContext, data: Ref): any { const isClearable = computed<boolean>(() => { return !props.disabled && props.allowClear; - }) + }); const handleClearAll = (e: MouseEvent) => { - e.preventDefault() - e.stopPropagation() + e.preventDefault(); + e.stopPropagation(); if (props.multiple) { - ctx.emit('update:modelValue', []) - data.value = [] + ctx.emit('update:modelValue', []); + data.value = []; } else { - ctx.emit('update:modelValue', '') - data.value = '' + ctx.emit('update:modelValue', ''); + data.value = ''; } - } + }; const handleClearItem = (e: MouseEvent, item?: string) => { - e.preventDefault() - e.stopPropagation() + e.preventDefault(); + e.stopPropagation(); if (props.multiple) { - data.value.splice(data.value.indexOf(item), 1) - ctx.emit('update:modelValue', data.value) + data.value.splice(data.value.indexOf(item), 1); + ctx.emit('update:modelValue', data.value); } else { - ctx.emit('update:modelValue', []) - data.value = [] + ctx.emit('update:modelValue', []); + data.value = []; } - } + }; return { isClearable, handleClearAll, handleClearItem - } -} \ No newline at end of file + }; +} diff --git a/packages/devui-vue/devui/tree-select/hooks/use-select.ts b/packages/devui-vue/devui/tree-select/hooks/use-select.ts index 5acdb01efa..caf32e3ce9 100644 --- a/packages/devui-vue/devui/tree-select/hooks/use-select.ts +++ b/packages/devui-vue/devui/tree-select/hooks/use-select.ts @@ -1,72 +1,72 @@ -import { ref } from 'vue' -import { TreeSelectProps, TreeItem } from '../src/tree-select-types' +import { ref } from 'vue'; +import { TreeSelectProps, TreeItem } from '../src/tree-select-types'; export default function useSelect(props: TreeSelectProps): any { - const inputValue = ref<string | Array<string>>([]) - const selectedCache = new Set() + const inputValue = ref<string | Array<string>>([]); + const selectedCache = new Set(); const selectValue = (item: TreeItem) => { if(!props.multiple) { - inputValue.value = item.label + inputValue.value = item.label; } else { - item.checked = !item.checked - if(item.halfchecked) item.halfchecked = false - useCache(item) - searchUp(item) - searchDown(item) - inputValue.value = [...selectedCache] as string[] + item.checked = !item.checked; + if(item.halfchecked) {item.halfchecked = false;} + useCache(item); + searchUp(item); + searchDown(item); + inputValue.value = [...selectedCache] as string[]; } - } + }; const useCache = (item: TreeItem) => { - item.checked === true - ? selectedCache.add(item.label) - : (selectedCache.has(item.label) && selectedCache.delete(item.label)) - } + item.checked === true + ? selectedCache.add(item.label) + : (selectedCache.has(item.label) && selectedCache.delete(item.label)); + }; const searchUp = (item: TreeItem) => { - if(!item.parent) return - let state = '' - const checkedArr = item.parent.children.filter((el) => el.checked === true) + if(!item.parent) {return;} + let state = ''; + const checkedArr = item.parent.children.filter((el) => el.checked === true); switch(checkedArr.length) { - case 0: - state = 'none' - break; - case item.parent.children.length: - state = 'checked' - break - default: - state = 'halfchecked' - break + case 0: + state = 'none'; + break; + case item.parent.children.length: + state = 'checked'; + break; + default: + state = 'halfchecked'; + break; } if(state === 'checked') { - item.parent.checked = true - item.parent.halfchecked = false + item.parent.checked = true; + item.parent.halfchecked = false; } else if(state === 'halfchecked') { - item.parent.halfchecked = true - item.parent.checked = false + item.parent.halfchecked = true; + item.parent.checked = false; } else { - item.parent.checked = false - item.parent.halfchecked = false + item.parent.checked = false; + item.parent.halfchecked = false; } - useCache(item.parent) - searchUp(item.parent) - } + useCache(item.parent); + searchUp(item.parent); + }; const searchDown = (item: TreeItem) => { - if(!item.children) return + if(!item.children) {return;} item.children.forEach((el) => { - el.checked = item.checked - useCache(el) - searchDown(el) - }) - } + el.checked = item.checked; + useCache(el); + searchDown(el); + }); + }; return { inputValue, selectValue - } -} \ No newline at end of file + }; +} diff --git a/packages/devui-vue/devui/tree-select/hooks/use-toggle.ts b/packages/devui-vue/devui/tree-select/hooks/use-toggle.ts index 6be5a707c9..ee2d7e4e87 100644 --- a/packages/devui-vue/devui/tree-select/hooks/use-toggle.ts +++ b/packages/devui-vue/devui/tree-select/hooks/use-toggle.ts @@ -1,23 +1,23 @@ -import { ref } from 'vue' -import { TreeSelectProps, TreeItem } from '../src/tree-select-types' +import { ref } from 'vue'; +import { TreeSelectProps, TreeItem } from '../src/tree-select-types'; export default function useToggle(props: TreeSelectProps): any { - const visible = ref<boolean>(false) + const visible = ref<boolean>(false); const selectToggle = () => { - if(props.disabled) return - visible.value = !visible.value - } + if(props.disabled) {return;} + visible.value = !visible.value; + }; const treeToggle = (e: MouseEvent, item: TreeItem) => { - e.preventDefault() - e.stopPropagation() - item.opened = ! item.opened - } + e.preventDefault(); + e.stopPropagation(); + item.opened = ! item.opened; + }; return { visible, selectToggle, treeToggle, - } -} \ No newline at end of file + }; +} diff --git a/packages/devui-vue/devui/tree-select/index.ts b/packages/devui-vue/devui/tree-select/index.ts index 1c26922130..60a6edb5a5 100644 --- a/packages/devui-vue/devui/tree-select/index.ts +++ b/packages/devui-vue/devui/tree-select/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import TreeSelect from './src/tree-select' +import type { App } from 'vue'; +import TreeSelect from './src/tree-select'; TreeSelect.install = function(app: App): void { - app.component(TreeSelect.name, TreeSelect) -} + app.component(TreeSelect.name, TreeSelect); +}; -export { TreeSelect } +export { TreeSelect }; export default { title: 'TreeSelect 树形选择框', category: '数据录入', status: '20%', // TODO: 组件若开发完成则填入"已完成",并删除该注释 install(app: App): void { - app.use(TreeSelect as any) + app.use(TreeSelect as any); } -} +}; diff --git a/packages/devui-vue/devui/tree-select/src/tree-select-types.ts b/packages/devui-vue/devui/tree-select/src/tree-select-types.ts index 8aa6cf2ab6..a150866430 100644 --- a/packages/devui-vue/devui/tree-select/src/tree-select-types.ts +++ b/packages/devui-vue/devui/tree-select/src/tree-select-types.ts @@ -1,21 +1,21 @@ -import type { PropType, ExtractPropTypes } from 'vue' +import type { PropType, ExtractPropTypes } from 'vue'; export interface TreeItem { - id: number | string - label: string - parent?: TreeItem - children?: Array<TreeItem> - level?: number - loading?: boolean - opened?: boolean - checked?: boolean - halfchecked?: boolean - disabled?: boolean - - [prop: string]: any + id: number | string; + label: string; + parent?: TreeItem; + children?: Array<TreeItem>; + level?: number; + loading?: boolean; + opened?: boolean; + checked?: boolean; + halfchecked?: boolean; + disabled?: boolean; + + [prop: string]: any; } -export type TreeData = Array<TreeItem> +export type TreeData = Array<TreeItem>; export type ModelValue = number | string | Array<number | string>; @@ -64,6 +64,6 @@ export const treeSelectProps = { type: Function as PropType<(item: TreeItem, index: number) => void>, default: undefined, }, -} as const +} as const; -export type TreeSelectProps = ExtractPropTypes<typeof treeSelectProps> +export type TreeSelectProps = ExtractPropTypes<typeof treeSelectProps>; diff --git a/packages/devui-vue/devui/tree-select/src/tree-select.tsx b/packages/devui-vue/devui/tree-select/src/tree-select.tsx index 5c43c5b87f..29920538b4 100644 --- a/packages/devui-vue/devui/tree-select/src/tree-select.tsx +++ b/packages/devui-vue/devui/tree-select/src/tree-select.tsx @@ -1,16 +1,16 @@ -import './tree-select.scss' +import './tree-select.scss'; -import { defineComponent, toRefs, Transition } from 'vue' -import type { SetupContext } from 'vue' -import { treeSelectProps, TreeSelectProps, TreeItem } from './tree-select-types' -import { nodeMap, attributeExtension, className } from './utils' -import useToggle from '../hooks/use-toggle' -import useSelect from '../hooks/use-select' -import useClear from '../hooks/use-clear' -import IconOpen from '../assets/open.svg' -import IconClose from '../assets/close.svg' -import Checkbox from '../../checkbox/src/checkbox' -import ClickOutside from '../../shared/devui-directive/clickoutside' +import { defineComponent, toRefs, Transition } from 'vue'; +import type { SetupContext } from 'vue'; +import { treeSelectProps, TreeSelectProps, TreeItem } from './tree-select-types'; +import { nodeMap, attributeExtension, className } from './utils'; +import useToggle from '../hooks/use-toggle'; +import useSelect from '../hooks/use-select'; +import useClear from '../hooks/use-clear'; +import IconOpen from '../assets/open.svg'; +import IconClose from '../assets/close.svg'; +import Checkbox from '../../checkbox/src/checkbox'; +import ClickOutside from '../../shared/devui-directive/clickoutside'; export default defineComponent({ name: 'DTreeSelect', @@ -18,58 +18,58 @@ export default defineComponent({ props: treeSelectProps, emits: ['toggleChange', 'valueChange', 'update:modelValue'], setup(props: TreeSelectProps, ctx: SetupContext) { - const { treeData, placeholder, disabled, multiple, leafOnly, enableLabelization } = toRefs(props) - const { visible, selectToggle, treeToggle} = useToggle(props) - const { inputValue, selectValue } = useSelect(props) - const { isClearable, handleClearAll, handleClearItem} = useClear(props, ctx, inputValue) + const { treeData, placeholder, disabled, multiple, leafOnly, enableLabelization } = toRefs(props); + const { visible, selectToggle, treeToggle} = useToggle(props); + const { inputValue, selectValue } = useSelect(props); + const { isClearable, handleClearAll, handleClearItem} = useClear(props, ctx, inputValue); const clickNode = (item: TreeItem) => { if(!leafOnly.value) { - selectValue(item) - !multiple.value && selectToggle(item) + selectValue(item); + !multiple.value && selectToggle(item); } else { if(!item.children) { - selectValue(item) - !multiple.value && selectToggle(item) + selectValue(item); + !multiple.value && selectToggle(item); } } - } + }; const deleteNode = (e: MouseEvent, item: string) => { - handleClearItem(e, item) - selectValue(nodeMap.get(item)) - } + handleClearItem(e, item); + selectValue(nodeMap.get(item)); + }; const treeSelectCls = className('devui-tree-select', { 'devui-tree-select-open': visible.value, 'devui-tree-select-disabled': disabled.value, - }) + }); const treeSelectInputItem = className('devui-tree-select-value', { 'devui-tree-select-value-enableLabelization': enableLabelization.value - }) + }); const renderNode = (item) => ( - <div - class="devui-tree-select-item" + <div + class="devui-tree-select-item" style={{ paddingLeft: `${20 * (item.level - 1)}px` }} onClick={() => clickNode(item)} - > + > { item.children - ? item.opened - ? <IconOpen class="mr-xs" onClick={(e: MouseEvent) => treeToggle(e, item)}/> - : <IconClose class="mr-xs" onClick={(e: MouseEvent) => treeToggle(e, item)} /> + ? item.opened + ? <IconOpen class="mr-xs" onClick={(e: MouseEvent) => treeToggle(e, item)}/> + : <IconClose class="mr-xs" onClick={(e: MouseEvent) => treeToggle(e, item)} /> :<span>{'\u00A0\u00A0\u00A0'}</span> } - {ctx.slots.default - ? ctx.slots.default({ item }) - : multiple.value - ? item.halfchecked - ? <Checkbox label={item.label} halfchecked={item.halfchecked} /> - : <Checkbox label={item.label} checked={item.checked} /> - : (item.label)} + {ctx.slots.default + ? ctx.slots.default({ item }) + : multiple.value + ? item.halfchecked + ? <Checkbox label={item.label} halfchecked={item.halfchecked} /> + : <Checkbox label={item.label} checked={item.checked} /> + : (item.label)} </div> - ) + ); const renderTree = (treeData) => { return treeData.map(item => { @@ -79,16 +79,16 @@ export default defineComponent({ { renderNode(item) } { item.opened && renderTree(item.children) } </> - ) + ); } - return renderNode(item) - }) - } + return renderNode(item); + }); + }; return () => { return ( <div class={treeSelectCls} v-click-outside={() => visible.value = false}> - <div + <div class={isClearable.value ? 'devui-tree-select-clearable' : 'devui-tree-select-notclearable'} onClick={() => selectToggle()}> {/* <input @@ -100,23 +100,23 @@ export default defineComponent({ disabled={disabled} /> */} <div - class="devui-tree-select-input" - placeholder={placeholder.value}> - { multiple.value - ? inputValue.value.map((item) => ( - <div class={treeSelectInputItem}> - {item} - {enableLabelization.value - ? <d-icon name="close" onClick={(e: MouseEvent) => deleteNode(e, item)}/> - : <span>,</span>} - </div> - )) - : !Array.isArray(inputValue.value) && <div class={treeSelectInputItem}> + class="devui-tree-select-input" + placeholder={placeholder.value}> + { multiple.value + ? inputValue.value.map((item) => ( + <div class={treeSelectInputItem}> + {item} + {enableLabelization.value + ? <d-icon name="close" onClick={(e: MouseEvent) => deleteNode(e, item)}/> + : <span>,</span>} + </div> + )) + : !Array.isArray(inputValue.value) && <div class={treeSelectInputItem}> {inputValue.value} {enableLabelization.value && <d-icon name="close" onClick={(e: MouseEvent) => handleClearItem(e)}/>} </div> - } + } </div> <span onClick={(e: MouseEvent) => handleClearAll(e)} class="devui-tree-select-clear"> <d-icon name="close" /> @@ -131,7 +131,7 @@ export default defineComponent({ </div> </Transition> </div> - ) - } + ); + }; }, -}) +}); diff --git a/packages/devui-vue/devui/tree-select/src/utils.ts b/packages/devui-vue/devui/tree-select/src/utils.ts index ab4e3a4c2f..bad2bbb63a 100644 --- a/packages/devui-vue/devui/tree-select/src/utils.ts +++ b/packages/devui-vue/devui/tree-select/src/utils.ts @@ -1,28 +1,28 @@ -import { TreeData, TreeItem } from '../src/tree-select-types' +import { TreeData, TreeItem } from '../src/tree-select-types'; -export const nodeMap = new Map<string, TreeItem>() +export const nodeMap = new Map<string, TreeItem>(); export function attributeExtension(data: TreeData): any { data.forEach((el) => { - let level = 1 - el.level = level - nodeMap.set(el.label, el) - const nodeQueue = [] - nodeQueue.push(el) + let level = 1; + el.level = level; + nodeMap.set(el.label, el); + const nodeQueue = []; + nodeQueue.push(el); while(nodeQueue.length !== 0) { - const node = nodeQueue.shift() + const node = nodeQueue.shift(); if(node.children) { node.children.forEach((el) => { - el.level = level + 1 - el.parent = node - nodeMap.set(el.label, el) - nodeQueue.push(el) - }) + el.level = level + 1; + el.parent = node; + nodeMap.set(el.label, el); + nodeQueue.push(el); + }); } - level += 1 + level += 1; } - }) - return data + }); + return data; } /** @@ -33,7 +33,7 @@ export function attributeExtension(data: TreeData): any { */ export function className( classStr: string, - classOpt?: { [key: string]: boolean; } + classOpt?: { [key: string]: boolean } ): string { let classname = classStr; if (typeof classOpt === 'object') { diff --git a/packages/devui-vue/devui/tree/__tests__/tree.spec.ts b/packages/devui-vue/devui/tree/__tests__/tree.spec.ts index 08590ffe06..dcf13b0074 100644 --- a/packages/devui-vue/devui/tree/__tests__/tree.spec.ts +++ b/packages/devui-vue/devui/tree/__tests__/tree.spec.ts @@ -1,9 +1,9 @@ -import { mount, VueWrapper } from '@vue/test-utils' -import { ref, nextTick } from 'vue' -import DTree from '../src/tree' +import { mount, VueWrapper } from '@vue/test-utils'; +import { ref, nextTick } from 'vue'; +import DTree from '../src/tree'; describe('tree', () => { - let wrapper: VueWrapper<any> + let wrapper: VueWrapper<any>; beforeEach(() => { const data = ref([ @@ -148,7 +148,7 @@ describe('tree', () => { name: 'new child node' } } - ]) + ]); wrapper = mount({ components: { DTree }, @@ -158,30 +158,30 @@ describe('tree', () => { setup () { return { data, - } + }; } - }) - }) + }); + }); it('should render correctly', () => { - expect(wrapper.classes()).toContain('devui-tree') - expect(wrapper.element.childElementCount).toBe(6) - }) + expect(wrapper.classes()).toContain('devui-tree'); + expect(wrapper.element.childElementCount).toBe(6); + }); it('should expand and collapse correctly', async () => { - const firstNode = wrapper.get('.devui-tree-node:first-child') + const firstNode = wrapper.get('.devui-tree-node:first-child'); // 初始状态,节点是展开的 - expect(firstNode.classes()).toContain('devui-tree-node__open') - + expect(firstNode.classes()).toContain('devui-tree-node__open'); + // 点击之后,节点收起 - await wrapper.get('.devui-tree-node__folder:first-child').trigger('click') - await nextTick() - expect(firstNode.classes()).not.toContain('devui-tree-node__open') + await wrapper.get('.devui-tree-node__folder:first-child').trigger('click'); + await nextTick(); + expect(firstNode.classes()).not.toContain('devui-tree-node__open'); // 再次点击,节点展开 - await wrapper.get('.devui-tree-node__folder:first-child').trigger('click') - await nextTick() - expect(firstNode.classes()).toContain('devui-tree-node__open') - }) -}) + await wrapper.get('.devui-tree-node__folder:first-child').trigger('click'); + await nextTick(); + expect(firstNode.classes()).toContain('devui-tree-node__open'); + }); +}); diff --git a/packages/devui-vue/devui/tree/index.ts b/packages/devui-vue/devui/tree/index.ts index cae6212838..473c796ed9 100644 --- a/packages/devui-vue/devui/tree/index.ts +++ b/packages/devui-vue/devui/tree/index.ts @@ -1,17 +1,17 @@ -import type { App } from 'vue' -import Tree from './src/tree' +import type { App } from 'vue'; +import Tree from './src/tree'; Tree.install = function(app: App): void { - app.component(Tree.name, Tree) -} + app.component(Tree.name, Tree); +}; -export { Tree } +export { Tree }; export default { title: 'Tree 树', category: '数据展示', status: '20%', install(app: App): void { - app.use(Tree as any) + app.use(Tree as any); } -} +}; diff --git a/packages/devui-vue/devui/tree/src/composables/use-checked.ts b/packages/devui-vue/devui/tree/src/composables/use-checked.ts index b22d992788..ab2e4c73a9 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-checked.ts +++ b/packages/devui-vue/devui/tree/src/composables/use-checked.ts @@ -1,110 +1,110 @@ -import type { SetupContext, Ref } from 'vue' -import { unref, ref } from 'vue' +import type { SetupContext, Ref } from 'vue'; +import { unref, ref } from 'vue'; import { TreeItem, SelectType, ReverseTree, CheckableRelationType, -} from '../tree-types' -import { flatten } from '../util' +} from '../tree-types'; +import { flatten } from '../util'; export default function useChecked( cbr: Ref<CheckableRelationType>, ctx: SetupContext, data: any[] ) { - const selected = ref<SelectType>({}) - const flatData = flatten(data) + const selected = ref<SelectType>({}); + const flatData = flatten(data); const findPedigreeById = (id: string) => { - const treeData = data - let parentLevel: ReverseTree = {} - let childLevel: string[] = [] - let target = undefined + const treeData = data; + let parentLevel: ReverseTree = {}; + let childLevel: string[] = []; + let target = undefined; const ergodic = (curr: any[], parentNode: ReverseTree) => { curr.every(({ children, id: itemId }) => { if (target) { - return false + return false; } if (itemId === id) { - parentLevel = parentNode + parentLevel = parentNode; childLevel = Array.isArray(children) ? flatten(children).map(({ id: key }) => key) - : [] - target = itemId - return false + : []; + target = itemId; + return false; } if (Array.isArray(children)) { ergodic(children, { id: itemId, children: children.map(({ id: key }) => key), parent: parentNode, - }) + }); } - return true - }) - } - ergodic(treeData, {}) + return true; + }); + }; + ergodic(treeData, {}); return { parentLevel, childLevel, - } - } + }; + }; const generateParentObject = ( parentLevel: ReverseTree, isSelected: boolean, checkId: string ): SelectType => { - const state: SelectType = {} - const currentSelected = unref(selected) + const state: SelectType = {}; + const currentSelected = unref(selected); const ergodic = (currObj: ReverseTree, isOverflow = false) => { - const { id, children, parent } = currObj + const { id, children, parent } = currObj; if (!parent) { - return + return; } if (isSelected) { const optional = children.filter( (item) => !currentSelected[item] || currentSelected[item] === 'none' - ) + ); if (optional.length <= 1) { if (optional[0] === checkId) { - state[id] = 'select' + state[id] = 'select'; } else if (isOverflow) { - state[id] = 'half' + state[id] = 'half'; } } else { - state[id] = 'half' + state[id] = 'half'; } - ergodic(parent, state[id] === 'select') + ergodic(parent, state[id] === 'select'); } else { const optional = children.filter( (item) => currentSelected[item] && currentSelected[item] !== 'none' - ) + ); if (optional.length <= 1) { if (optional[0] === checkId || isOverflow) { - state[id] = 'none' + state[id] = 'none'; } } else { - state[id] = 'half' + state[id] = 'half'; } - ergodic(parent, state[id] === 'none') + ergodic(parent, state[id] === 'none'); } - } - ergodic(parentLevel) - return state - } + }; + ergodic(parentLevel); + return state; + }; const onNodeClick = (item: TreeItem) => { - const { id } = item - let currentSelected = Object.assign({}, unref(selected)) - const isSelected = currentSelected[id] === 'none' || !currentSelected[id] + const { id } = item; + let currentSelected = Object.assign({}, unref(selected)); + const isSelected = currentSelected[id] === 'none' || !currentSelected[id]; if (cbr.value === 'none') { currentSelected = Object.assign(currentSelected, { [id]: isSelected ? 'select' : 'none', - }) + }); } else if (cbr.value === 'both') { - const { parentLevel, childLevel } = findPedigreeById(id) + const { parentLevel, childLevel } = findPedigreeById(id); currentSelected = Object.assign( currentSelected, Object.fromEntries( @@ -112,33 +112,33 @@ export default function useChecked( ), generateParentObject(parentLevel, isSelected, id), { [id]: isSelected ? 'select' : 'none' } - ) + ); } else if (cbr.value === 'upward') { - const { parentLevel } = findPedigreeById(id) + const { parentLevel } = findPedigreeById(id); currentSelected = Object.assign( currentSelected, generateParentObject(parentLevel, isSelected, id), { [id]: isSelected ? 'select' : 'none' } - ) + ); } else if (cbr.value === 'downward') { - const { childLevel } = findPedigreeById(id) + const { childLevel } = findPedigreeById(id); currentSelected = Object.assign( currentSelected, Object.fromEntries( childLevel.map((key) => [key, isSelected ? 'select' : 'none']) ), { [id]: isSelected ? 'select' : 'none' } - ) + ); } - selected.value = currentSelected + selected.value = currentSelected; const currentSelectedItem = flatData.filter( ({ id }) => currentSelected[id] && currentSelected[id] !== 'none' - ) - ctx.emit('nodeSelected', currentSelectedItem) - } + ); + ctx.emit('nodeSelected', currentSelectedItem); + }; return { selected, onNodeClick, - } + }; } diff --git a/packages/devui-vue/devui/tree/src/composables/use-draggable.ts b/packages/devui-vue/devui/tree/src/composables/use-draggable.ts index 0089d14e84..dd8de3e442 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-draggable.ts +++ b/packages/devui-vue/devui/tree/src/composables/use-draggable.ts @@ -1,12 +1,12 @@ -import { reactive, ref, watch } from 'vue' -import type { Ref } from 'vue' -import { TreeItem, IDropType, Nullable } from '../tree-types' -import { cloneDeep } from 'lodash' +import { reactive, ref, watch } from 'vue'; +import type { Ref } from 'vue'; +import { TreeItem, IDropType, Nullable } from '../tree-types'; +import { cloneDeep } from 'lodash'; -const ACTIVE_NODE = 'devui-tree-node__content--value-wrapper' +const ACTIVE_NODE = 'devui-tree-node__content--value-wrapper'; interface DragState { - dropType?: 'prev' | 'next' | 'inner' - draggingNode?: Nullable<HTMLElement> + dropType?: 'prev' | 'next' | 'inner'; + draggingNode?: Nullable<HTMLElement>; } export default function useDraggable( @@ -19,150 +19,150 @@ export default function useDraggable( const dragState = reactive<DragState>({ dropType: null, draggingNode: null, - }) - const treeIdMapValue = ref({}) + }); + const treeIdMapValue = ref({}); watch( () => renderData.value, () => { - treeIdMapValue.value = renderData.value.reduce((acc, cur) => ({ ...acc, [cur.id]: cur }), {}) + treeIdMapValue.value = renderData.value.reduce((acc, cur) => ({ ...acc, [cur.id]: cur }), {}); }, { deep: true, immediate: true } - ) + ); const removeDraggingStyle = (target: Nullable<HTMLElement>) => { target .querySelector(`.${ACTIVE_NODE}`) - ?.classList.remove(...['prev', 'next', 'inner'].map((item) => `devui-drop-${item}`)) - } + ?.classList.remove(...['prev', 'next', 'inner'].map((item) => `devui-drop-${item}`)); + }; const checkIsParent = (childNodeId: number | string, parentNodeId: number | string) => { - const realParentId = treeIdMapValue.value[childNodeId].parentId + const realParentId = treeIdMapValue.value[childNodeId].parentId; if (realParentId === parentNodeId) { - return true + return true; } else if (realParentId !== undefined) { - return checkIsParent(realParentId, parentNodeId) + return checkIsParent(realParentId, parentNodeId); } else { - return false + return false; } - } + }; const handlerDropData = (dragNodeId: string | number, dropNodeId: string | number, dropType?: string) => { - const cloneData = cloneDeep(data.value) - let nowDragNode - let nowDropNode + const cloneData = cloneDeep(data.value); + let nowDragNode; + let nowDropNode; const findDragAndDropNode = (curr: TreeItem[]) => { - if (!Array.isArray(curr)) return + if (!Array.isArray(curr)) {return;} curr.every((item, index) => { if (nowDragNode && nowDropNode) { - return false + return false; } if (item.id === dragNodeId) { - nowDragNode = { target: curr, index, item } + nowDragNode = { target: curr, index, item }; } else if (item.id === dropNodeId) { - nowDropNode = { target: curr, index, item } + nowDropNode = { target: curr, index, item }; } if (!nowDragNode || !nowDropNode) { - findDragAndDropNode(item.children) + findDragAndDropNode(item.children); } - return true - }) - } - findDragAndDropNode(cloneData) + return true; + }); + }; + findDragAndDropNode(cloneData); if (nowDragNode && nowDropNode && dropType) { - const cloneDrapNode = cloneDeep(nowDragNode.target[nowDragNode.index]) + const cloneDrapNode = cloneDeep(nowDragNode.target[nowDragNode.index]); if (dropType === 'prev') { - nowDropNode.target.splice(nowDropNode.index, 0, cloneDrapNode) + nowDropNode.target.splice(nowDropNode.index, 0, cloneDrapNode); } else if (dropType === 'next') { - nowDropNode.target.splice(nowDropNode.index + 1, 0, cloneDrapNode) + nowDropNode.target.splice(nowDropNode.index + 1, 0, cloneDrapNode); } else if (dropType === 'inner') { - const children = nowDropNode.target[nowDropNode.index].children + const children = nowDropNode.target[nowDropNode.index].children; if (Array.isArray(children)) { - children.unshift(cloneDrapNode) + children.unshift(cloneDrapNode); } else { - nowDropNode.target[nowDropNode.index].children = [cloneDrapNode] + nowDropNode.target[nowDropNode.index].children = [cloneDrapNode]; } } - const targetIndex = nowDragNode.target.indexOf(nowDragNode.item) + const targetIndex = nowDragNode.target.indexOf(nowDragNode.item); if (targetIndex !== -1) { - nowDragNode.target.splice(targetIndex, 1) + nowDragNode.target.splice(targetIndex, 1); } - + } - - return cloneData - } + + return cloneData; + }; const onDragstart = (event: DragEvent, treeNode: TreeItem) => { - dragState.draggingNode = <Nullable<HTMLElement>>event.target + dragState.draggingNode = <Nullable<HTMLElement>>event.target; const data = { type: 'tree-node', nodeId: treeNode.id - } - event.dataTransfer.setData('Text', JSON.stringify(data)) - } + }; + event.dataTransfer.setData('Text', JSON.stringify(data)); + }; const onDragover = (event: DragEvent) => { if (draggable) { - event.preventDefault() - event.dataTransfer.dropEffect = 'move' + event.preventDefault(); + event.dataTransfer.dropEffect = 'move'; if (!node) { - return + return; } - const dropPrev = dropType.dropPrev - const dropNext = dropType.dropNext - const dropInner = dropType.dropInner + const dropPrev = dropType.dropPrev; + const dropNext = dropType.dropNext; + const dropInner = dropType.dropInner; - let innerDropType + let innerDropType; - const prevPercent = dropPrev ? (dropInner ? 0.25 : dropNext ? 0.45 : 1) : -1 - const nextPercent = dropNext ? (dropInner ? 0.75 : dropPrev ? 0.55 : 0) : 1 - const currentTarget = <Nullable<HTMLElement>>event.currentTarget - const targetPosition = currentTarget.getBoundingClientRect() - const distance = event.clientY - targetPosition.top + const prevPercent = dropPrev ? (dropInner ? 0.25 : dropNext ? 0.45 : 1) : -1; + const nextPercent = dropNext ? (dropInner ? 0.75 : dropPrev ? 0.55 : 0) : 1; + const currentTarget = <Nullable<HTMLElement>>event.currentTarget; + const targetPosition = currentTarget.getBoundingClientRect(); + const distance = event.clientY - targetPosition.top; if (distance < targetPosition.height * prevPercent) { - innerDropType = 'prev' + innerDropType = 'prev'; } else if (distance > targetPosition.height * nextPercent) { - innerDropType = 'next' + innerDropType = 'next'; } else if (dropInner) { - innerDropType = 'inner' + innerDropType = 'inner'; } else { - innerDropType = undefined + innerDropType = undefined; } - removeDraggingStyle(currentTarget) + removeDraggingStyle(currentTarget); if (innerDropType && innerDropType !== 'none') { - currentTarget.querySelector(`.${ACTIVE_NODE}`)?.classList.add(`devui-drop-${innerDropType}`) + currentTarget.querySelector(`.${ACTIVE_NODE}`)?.classList.add(`devui-drop-${innerDropType}`); } - dragState.dropType = innerDropType + dragState.dropType = innerDropType; } - } + }; const onDragleave = (event: DragEvent) => { - removeDraggingStyle(<Nullable<HTMLElement>>event.currentTarget) - } + removeDraggingStyle(<Nullable<HTMLElement>>event.currentTarget); + }; const onDrop = (event: DragEvent, dropNode: TreeItem) => { - removeDraggingStyle(<Nullable<HTMLElement>>event.currentTarget) + removeDraggingStyle(<Nullable<HTMLElement>>event.currentTarget); if (!draggable) { - return + return; } - event.preventDefault() - const transferDataStr = event.dataTransfer.getData('Text') + event.preventDefault(); + const transferDataStr = event.dataTransfer.getData('Text'); if (transferDataStr) { try { - const transferData = JSON.parse(transferDataStr) + const transferData = JSON.parse(transferDataStr); if (typeof transferData === 'object' && transferData.type === 'tree-node') { - const dragNodeId = transferData.nodeId - const isParent = checkIsParent(dropNode.id, dragNodeId) + const dragNodeId = transferData.nodeId; + const isParent = checkIsParent(dropNode.id, dragNodeId); if (dragNodeId === dropNode.id || isParent) { - return + return; } - let result + let result; if (dragState.dropType) { - result = handlerDropData(dragNodeId, dropNode.id, dragState.dropType) + result = handlerDropData(dragNodeId, dropNode.id, dragState.dropType); } - data.value = result + data.value = result; } } catch (e) { - console.error(e) + console.error(e); } } - } + }; return { onDragstart, @@ -170,5 +170,5 @@ export default function useDraggable( onDragleave, onDrop, dragState - } + }; } diff --git a/packages/devui-vue/devui/tree/src/composables/use-highlight.ts b/packages/devui-vue/devui/tree/src/composables/use-highlight.ts index 93f20dd56b..2305d42201 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-highlight.ts +++ b/packages/devui-vue/devui/tree/src/composables/use-highlight.ts @@ -1,37 +1,37 @@ -import { ref, Ref } from 'vue' +import { ref, Ref } from 'vue'; interface TypeHighlightClass { - [key: string]: 'active' | '' | 'devui-tree_isDisabledNode' + [key: string]: 'active' | '' | 'devui-tree_isDisabledNode'; } type TypeUseHighlightNode = () => { - nodeClassNameReflect: Ref<TypeHighlightClass> - handleClickOnNode: (index: string) => void - handleInitNodeClassNameReflect: (isDisabled: boolean, ...keys: Array<string>) => string -} + nodeClassNameReflect: Ref<TypeHighlightClass>; + handleClickOnNode: (index: string) => void; + handleInitNodeClassNameReflect: (isDisabled: boolean, ...keys: Array<string>) => string; +}; -const HIGHLIGHT_CLASS = 'active' -const IS_DISABLED_FLAG = 'devui-tree_isDisabledNode' +const HIGHLIGHT_CLASS = 'active'; +const IS_DISABLED_FLAG = 'devui-tree_isDisabledNode'; const useHighlightNode: TypeUseHighlightNode = () => { - const nodeClassNameReflectRef = ref<TypeHighlightClass>({}) - const prevActiveNodeKey = ref<string>('') + const nodeClassNameReflectRef = ref<TypeHighlightClass>({}); + const prevActiveNodeKey = ref<string>(''); const handleInit = (isDisabled = false, ...keys) => { - const key = keys.join('-') + const key = keys.join('-'); nodeClassNameReflectRef.value[key] = isDisabled ? IS_DISABLED_FLAG - : nodeClassNameReflectRef.value[key] || '' - return key - } + : nodeClassNameReflectRef.value[key] || ''; + return key; + }; const handleClick = (key) => { - if (nodeClassNameReflectRef.value[key] === IS_DISABLED_FLAG) return - if (prevActiveNodeKey.value === key) return - if (prevActiveNodeKey.value) nodeClassNameReflectRef.value[prevActiveNodeKey.value] = '' - nodeClassNameReflectRef.value[key] = HIGHLIGHT_CLASS - prevActiveNodeKey.value = key - } + if (nodeClassNameReflectRef.value[key] === IS_DISABLED_FLAG) {return;} + if (prevActiveNodeKey.value === key) {return;} + if (prevActiveNodeKey.value) {nodeClassNameReflectRef.value[prevActiveNodeKey.value] = '';} + nodeClassNameReflectRef.value[key] = HIGHLIGHT_CLASS; + prevActiveNodeKey.value = key; + }; return { nodeClassNameReflect: nodeClassNameReflectRef, handleClickOnNode: handleClick, handleInitNodeClassNameReflect: handleInit - } -} -export default useHighlightNode + }; +}; +export default useHighlightNode; diff --git a/packages/devui-vue/devui/tree/src/composables/use-lazy.ts b/packages/devui-vue/devui/tree/src/composables/use-lazy.ts index 7b7debd047..4301cbd81e 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-lazy.ts +++ b/packages/devui-vue/devui/tree/src/composables/use-lazy.ts @@ -1,64 +1,64 @@ -import { ref, Ref } from 'vue' -import { TreeData, TreeItem } from '../tree-types' +import { ref, Ref } from 'vue'; +import { TreeData, TreeItem } from '../tree-types'; interface TypeReflectValue { // 外部传入 - id: keyof TypeReflect // 懒加载节点 id - onGetNodeData: () => Promise<TreeData> // 懒加载获取数据函数, 当前是节点 children - renderLoading?: (id: string) => any // loadingTemplate 挂载 + id: keyof TypeReflect; // 懒加载节点 id + onGetNodeData: () => Promise<TreeData>; // 懒加载获取数据函数, 当前是节点 children + renderLoading?: (id: string) => any; // loadingTemplate 挂载 // useLazy 内部使用 - loadingTargetId?: string // loadingTemplate 挂载节点 id - dataSource?: TreeData // 懒加载数据 + loadingTargetId?: string; // loadingTemplate 挂载节点 id + dataSource?: TreeData; // 懒加载数据 } interface TypeReflect { - [key: string]: TypeReflectValue + [key: string]: TypeReflectValue; } -type TypeHandleInit = (item: TreeItem, value: TypeReflectValue) => void -type TypeGetLazyData = (key: keyof TypeReflect) => Promise<TreeItem> | any +type TypeHandleInit = (item: TreeItem, value: TypeReflectValue) => void; +type TypeGetLazyData = (key: keyof TypeReflect) => Promise<TreeItem> | any; type TypeUseLazy = () => { - lazyNodesReflect: Ref<TypeReflect> - handleInitLazyNodeReflect: TypeHandleInit - getLazyData: TypeGetLazyData -} + lazyNodesReflect: Ref<TypeReflect>; + handleInitLazyNodeReflect: TypeHandleInit; + getLazyData: TypeGetLazyData; +}; const useLazy: TypeUseLazy = () => { - const reflect = ref<TypeReflect>({}) + const reflect = ref<TypeReflect>({}); const handleInit: TypeHandleInit = (item, value) => { if (!item.isParent) { - return + return; } - const key = reflect.value[value.id]?.id.toString() + const key = reflect.value[value.id]?.id.toString(); if (!key) { reflect.value[value.id] = { ...value, loadingTargetId: `devui-tree_loadingTemplate-${value.id}`, dataSource: null - } + }; } - } + }; const getLazyData: TypeGetLazyData = async (key) => { - const ds = reflect.value[key] + const ds = reflect.value[key]; if (ds.dataSource) { - return ds.dataSource + return ds.dataSource; } - const handleLoading = reflect.value[key].renderLoading(reflect.value[key].loadingTargetId) + const handleLoading = reflect.value[key].renderLoading(reflect.value[key].loadingTargetId); try { - reflect.value[key].dataSource = await ds.onGetNodeData() + reflect.value[key].dataSource = await ds.onGetNodeData(); } catch(e) { - console.error(e) + console.error(e); } finally { - handleLoading.loadingInstance.close() + handleLoading.loadingInstance.close(); } - return reflect.value[key].dataSource - } + return reflect.value[key].dataSource; + }; return { lazyNodesReflect: reflect, handleInitLazyNodeReflect: handleInit, getLazyData, - } -} + }; +}; -export default useLazy +export default useLazy; diff --git a/packages/devui-vue/devui/tree/src/composables/use-merge-node.ts b/packages/devui-vue/devui/tree/src/composables/use-merge-node.ts index ff7a18c7e0..a5b6a6b455 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-merge-node.ts +++ b/packages/devui-vue/devui/tree/src/composables/use-merge-node.ts @@ -1,9 +1,9 @@ -import { Ref, ref, watch } from 'vue' -import { TreeItem } from '../tree-types' +import { Ref, ref, watch } from 'vue'; +import { TreeItem } from '../tree-types'; export default function useMergeNode(data: Ref<TreeItem[]>): any { const mergeObject = (treeItem, childName = 'children', labelName = 'label') => { - const { [childName]: children, [labelName]: label } = treeItem + const { [childName]: children, [labelName]: label } = treeItem; if ( Array.isArray(children) && children.length === 1 && @@ -14,10 +14,10 @@ export default function useMergeNode(data: Ref<TreeItem[]>): any { Object.assign({}, children[0], { [labelName]: `${label} \\ ${children[0][labelName]}` }) - ) + ); } - return treeItem - } + return treeItem; + }; const mergeNode = ( tree: Array<any>, @@ -26,30 +26,30 @@ export default function useMergeNode(data: Ref<TreeItem[]>): any { labelName = 'label' ): Array<any> => { return tree.map((item) => { - const { [childName]: children } = item + const { [childName]: children } = item; if (!Array.isArray(children) || !children.length) { - return Object.assign({}, item, { level: level + 1 }) + return Object.assign({}, item, { level: level + 1 }); } - let currentObject = item + let currentObject = item; if (children.length === 1) { - currentObject = mergeObject(item) + currentObject = mergeObject(item); } return Object.assign({}, currentObject, { [childName]: mergeNode(currentObject[childName], level + 1, childName, labelName), level: level + 1 - }) - }) - } - const mergeData = ref(mergeNode(data.value)) + }); + }); + }; + const mergeData = ref(mergeNode(data.value)); watch( () => data.value, () => { - mergeData.value = mergeNode(data.value) + mergeData.value = mergeNode(data.value); }, { deep: true } - ) + ); return { mergeData - } + }; } diff --git a/packages/devui-vue/devui/tree/src/composables/use-operate.tsx b/packages/devui-vue/devui/tree/src/composables/use-operate.tsx index 67b94de8e4..cf5168845c 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-operate.tsx +++ b/packages/devui-vue/devui/tree/src/composables/use-operate.tsx @@ -1,60 +1,60 @@ -import { ref, Ref } from 'vue' -import { TreeItem, TreeData } from '../tree-types' +import { ref, Ref } from 'vue'; +import { TreeItem, TreeData } from '../tree-types'; -type TypeID = TreeItem['id'] +type TypeID = TreeItem['id']; interface TypeOperator { - addable: boolean - editable: boolean - deletable: boolean - handleAdd: () => void - handleEdit: () => void - handleDelete: () => void + addable: boolean; + editable: boolean; + deletable: boolean; + handleAdd: () => void; + handleEdit: () => void; + handleDelete: () => void; } interface TypeOperateIconReflect { - id: TypeID - renderIcon: (data: TreeItem) => JSX.Element + id: TypeID; + renderIcon: (data: TreeItem) => JSX.Element; } interface TypeeditStatusReflect { - [id: TypeID]: boolean + [id: TypeID]: boolean; } interface TypeReturnUseOperate { - editStatusReflect: Ref<TypeeditStatusReflect> - operateIconReflect: Ref<Array<TypeOperateIconReflect>> - handleReflectIdToIcon: TypeHandleReflectIdToIcon + editStatusReflect: Ref<TypeeditStatusReflect>; + operateIconReflect: Ref<Array<TypeOperateIconReflect>>; + handleReflectIdToIcon: TypeHandleReflectIdToIcon; } -type TypeUseOperate = (treeData: Ref<TreeData>) => TypeReturnUseOperate -type TypeHandleReflectIdToIcon = (id: TypeID, operate: TypeOperator) => void +type TypeUseOperate = (treeData: Ref<TreeData>) => TypeReturnUseOperate; +type TypeHandleReflectIdToIcon = (id: TypeID, operate: TypeOperator) => void; const reflectIconWithHandle = (data: TreeItem, operator: TypeOperator): JSX.Element => { - const handleAdd = (payload: MouseEvent) => operator.handleAdd() - const handleEdit = (payload: MouseEvent) => operator.handleEdit() - const handleDelete = (payload: MouseEvent) => operator.handleDelete() + const handleAdd = (payload: MouseEvent) => operator.handleAdd(); + const handleEdit = (payload: MouseEvent) => operator.handleEdit(); + const handleDelete = (payload: MouseEvent) => operator.handleDelete(); return ( <> { operator.addable && <span class="op-icons icon icon-add" onClick={handleAdd}></span> } { operator.editable && <span class="op-icons icon icon-edit" onClick={handleEdit}></span> } { operator.deletable && <span class="op-icons icon icon-close" onClick={handleDelete}></span> } </> - ) -} + ); +}; const useOperate: TypeUseOperate = (treeData) => { - const operateIconReflect = ref<Array<TypeOperateIconReflect>>([]) - const editStatusReflect = ref<TypeeditStatusReflect>({}) - + const operateIconReflect = ref<Array<TypeOperateIconReflect>>([]); + const editStatusReflect = ref<TypeeditStatusReflect>({}); + const handleReflectIdToIcon: TypeHandleReflectIdToIcon = (id, operator) => { - const isNotExistedReflectItem = operateIconReflect.value.every(({ id: d }) => d != id) + const isNotExistedReflectItem = operateIconReflect.value.every(({ id: d }) => d != id); if (isNotExistedReflectItem) { - editStatusReflect.value[id] = false - operateIconReflect.value.push({ id, renderIcon: data => reflectIconWithHandle(data, operator) }) + editStatusReflect.value[id] = false; + operateIconReflect.value.push({ id, renderIcon: data => reflectIconWithHandle(data, operator) }); } - } + }; return { operateIconReflect, editStatusReflect, handleReflectIdToIcon, - } -} + }; +}; -export default useOperate +export default useOperate; diff --git a/packages/devui-vue/devui/tree/src/composables/use-toggle.ts b/packages/devui-vue/devui/tree/src/composables/use-toggle.ts index 91711a69eb..fcea0a9fe9 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-toggle.ts +++ b/packages/devui-vue/devui/tree/src/composables/use-toggle.ts @@ -1,4 +1,4 @@ -import { ref, Ref, watch } from 'vue' +import { ref, Ref, watch } from 'vue'; export default function useToggle(data: Ref<unknown>): any { const openedTree = (tree) => { @@ -6,25 +6,25 @@ export default function useToggle(data: Ref<unknown>): any { item.open ? acc.concat(item, openedTree(item.children)) : acc.concat(item) - ), []) - } + ), []); + }; - const openedData = ref(openedTree(data.value)) + const openedData = ref(openedTree(data.value)); watch( () => data.value, (d) => openedData.value = openedTree(d), { deep: true } - ) + ); const toggle = (target, item) => { - target.stopPropagation() - if (!item.children) return - item.open = !item.open - openedData.value = openedTree(data.value) - } + target.stopPropagation(); + if (!item.children) {return;} + item.open = !item.open; + openedData.value = openedTree(data.value); + }; return { openedData, toggle, - } + }; } diff --git a/packages/devui-vue/devui/tree/src/config.ts b/packages/devui-vue/devui/tree/src/config.ts index dbd834d3d8..9fb551b68d 100644 --- a/packages/devui-vue/devui/tree/src/config.ts +++ b/packages/devui-vue/devui/tree/src/config.ts @@ -6,4 +6,4 @@ export const CHECK_CONFIG = { select: { checked: true, }, -} +}; diff --git a/packages/devui-vue/devui/tree/src/tree-node-content.tsx b/packages/devui-vue/devui/tree/src/tree-node-content.tsx index 818a17170c..f8caa022ea 100644 --- a/packages/devui-vue/devui/tree/src/tree-node-content.tsx +++ b/packages/devui-vue/devui/tree/src/tree-node-content.tsx @@ -1,5 +1,5 @@ -import { defineComponent, inject, toRefs, watch, onUpdated, ref } from 'vue' -import { TreeRootType } from './tree-types' +import { defineComponent, inject, toRefs, watch, onUpdated, ref } from 'vue'; +import { TreeRootType } from './tree-types'; export default defineComponent({ name: 'DTreeNodeContent', @@ -14,38 +14,38 @@ export default defineComponent({ }, }, setup(props) { - const tree = inject<TreeRootType>('treeRoot') + const tree = inject<TreeRootType>('treeRoot'); - const getCurID = (id) => `devui-tree-node__input-${id}` + const getCurID = (id) => `devui-tree-node__input-${id}`; onUpdated(() => { - const target = document.querySelector(`#${getCurID(props.node.id)}`) as HTMLInputElement - target?.focus() - }) + const target = document.querySelector(`#${getCurID(props.node.id)}`) as HTMLInputElement; + target?.focus(); + }); return () => { - const { node, editStatusReflect } = toRefs(props) // 闭包 - const { disabled, label, id } = node.value // 闭包 + const { node, editStatusReflect } = toRefs(props); // 闭包 + const { disabled, label, id } = node.value; // 闭包 const handleChange = ({ target }) => { - node.value.label = target.value - } + node.value.label = target.value; + }; const handleBlur = () => { - editStatusReflect.value[id] = false - } + editStatusReflect.value[id] = false; + }; return tree.ctx.slots.default ? tree.ctx.slots.default({ node }) : <span class={['devui-tree-node__title', disabled && 'select-disabled']}> - { - editStatusReflect.value[id] - ? <input - id={getCurID(id)} - ref={ref} - value={label} - onChange={handleChange} - onBlur={handleBlur} - /> - : label - } - </span> - } + { + editStatusReflect.value[id] + ? <input + id={getCurID(id)} + ref={ref} + value={label} + onChange={handleChange} + onBlur={handleBlur} + /> + : label + } + </span>; + }; }, -}) +}); diff --git a/packages/devui-vue/devui/tree/src/tree-types.ts b/packages/devui-vue/devui/tree/src/tree-types.ts index e8951ba8cf..1309491b41 100644 --- a/packages/devui-vue/devui/tree/src/tree-types.ts +++ b/packages/devui-vue/devui/tree/src/tree-types.ts @@ -1,35 +1,35 @@ -import type { PropType, ExtractPropTypes, SetupContext } from 'vue' +import type { PropType, ExtractPropTypes, SetupContext } from 'vue'; export interface TreeItem { - id: string - label: string - isParent?: boolean - level?: number - open?: boolean - addable?: boolean - editable?: boolean - deletable?: boolean - children?: TreeData - [key: string]: any + id: string; + label: string; + isParent?: boolean; + level?: number; + open?: boolean; + addable?: boolean; + editable?: boolean; + deletable?: boolean; + children?: TreeData; + [key: string]: any; } export interface IDropType { - dropPrev?: boolean - dropNext?: boolean - dropInner?: boolean + dropPrev?: boolean; + dropNext?: boolean; + dropInner?: boolean; } export interface SelectType { - [key: string]: 'none' | 'half' | 'select' + [key: string]: 'none' | 'half' | 'select'; } export interface ReverseTree { - id?: string - children?: string[] - parent?: ReverseTree + id?: string; + children?: string[]; + parent?: ReverseTree; } -export type TreeData = Array<TreeItem> +export type TreeData = Array<TreeItem>; -export type CheckableRelationType = 'downward' | 'upward' | 'both' | 'none' +export type CheckableRelationType = 'downward' | 'upward' | 'both' | 'none'; export const treeProps = { data: { @@ -53,13 +53,13 @@ export const treeProps = { type: Object as PropType<IDropType>, default: () => ({}), }, -} as const +} as const; -export type TreeProps = ExtractPropTypes<typeof treeProps> +export type TreeProps = ExtractPropTypes<typeof treeProps>; -export type Nullable<T> = null | T +export type Nullable<T> = null | T; export interface TreeRootType { - ctx: SetupContext<any> - props: TreeProps + ctx: SetupContext<any>; + props: TreeProps; } diff --git a/packages/devui-vue/devui/tree/src/tree.tsx b/packages/devui-vue/devui/tree/src/tree.tsx index 41924cd8f4..b547cfa57d 100644 --- a/packages/devui-vue/devui/tree/src/tree.tsx +++ b/packages/devui-vue/devui/tree/src/tree.tsx @@ -1,40 +1,40 @@ -import { defineComponent, reactive, ref, toRefs, provide, unref } from 'vue' -import type { SetupContext } from 'vue' -import { treeProps, TreeProps, TreeItem, TreeRootType, Nullable } from './tree-types' -import { CHECK_CONFIG } from './config' -import { preCheckTree, deleteNode, getId } from './util' -import Loading from '../../loading/src/service' -import Checkbox from '../../checkbox/src/checkbox' -import useToggle from './composables/use-toggle' -import useMergeNode from './composables/use-merge-node' -import useHighlightNode from './composables/use-highlight' -import useChecked from './composables/use-checked' -import useLazy from './composables/use-lazy' -import useOperate from './composables/use-operate' -import useDraggable from './composables/use-draggable' -import IconOpen from './assets/open.svg' -import IconClose from './assets/close.svg' -import NodeContent from './tree-node-content' -import './tree.scss' +import { defineComponent, reactive, ref, toRefs, provide, unref } from 'vue'; +import type { SetupContext } from 'vue'; +import { treeProps, TreeProps, TreeItem, TreeRootType, Nullable } from './tree-types'; +import { CHECK_CONFIG } from './config'; +import { preCheckTree, deleteNode, getId } from './util'; +import Loading from '../../loading/src/service'; +import Checkbox from '../../checkbox/src/checkbox'; +import useToggle from './composables/use-toggle'; +import useMergeNode from './composables/use-merge-node'; +import useHighlightNode from './composables/use-highlight'; +import useChecked from './composables/use-checked'; +import useLazy from './composables/use-lazy'; +import useOperate from './composables/use-operate'; +import useDraggable from './composables/use-draggable'; +import IconOpen from './assets/open.svg'; +import IconClose from './assets/close.svg'; +import NodeContent from './tree-node-content'; +import './tree.scss'; export default defineComponent({ name: 'DTree', props: treeProps, emits: ['nodeSelected'], setup(props: TreeProps, ctx: SetupContext) { - const { data, checkable, draggable, dropType, checkableRelation: cbr } = toRefs(reactive({ ...props, data: preCheckTree(props.data) })) - const node = ref<Nullable<HTMLElement>>(null) - const { mergeData } = useMergeNode(data) - const { openedData, toggle } = useToggle(mergeData) - const { nodeClassNameReflect, handleInitNodeClassNameReflect, handleClickOnNode } = useHighlightNode() - const { lazyNodesReflect, handleInitLazyNodeReflect, getLazyData } = useLazy() - const { selected, onNodeClick } = useChecked(cbr, ctx, data.value) - const { editStatusReflect, operateIconReflect, handleReflectIdToIcon } = useOperate(data) + const { data, checkable, draggable, dropType, checkableRelation: cbr } = toRefs(reactive({ ...props, data: preCheckTree(props.data) })); + const node = ref<Nullable<HTMLElement>>(null); + const { mergeData } = useMergeNode(data); + const { openedData, toggle } = useToggle(mergeData); + const { nodeClassNameReflect, handleInitNodeClassNameReflect, handleClickOnNode } = useHighlightNode(); + const { lazyNodesReflect, handleInitLazyNodeReflect, getLazyData } = useLazy(); + const { selected, onNodeClick } = useChecked(cbr, ctx, data.value); + const { editStatusReflect, operateIconReflect, handleReflectIdToIcon } = useOperate(data); const { onDragstart, onDragover, onDragleave, onDrop } = useDraggable(draggable.value, dropType.value, node, openedData, data); - provide<TreeRootType>('treeRoot', { ctx, props }) + provide<TreeRootType>('treeRoot', { ctx, props }); const renderNode = (item: TreeItem) => { - const { id = '', disabled, open, isParent, level, children, addable, editable, deletable } = item + const { id = '', disabled, open, isParent, level, children, addable, editable, deletable } = item; handleReflectIdToIcon( id, { @@ -49,23 +49,23 @@ export default defineComponent({ addable, editable, deletable - } - item.open = true + }; + item.open = true; if (item.children && Array.isArray(item.children)) { - item.children.push(newItem) + item.children.push(newItem); } else { - item.children = [newItem] + item.children = [newItem]; } }, handleEdit: () => { - editStatusReflect.value[id] = !editStatusReflect.value[id] + editStatusReflect.value[id] = !editStatusReflect.value[id]; }, handleDelete: () => { - mergeData.value = deleteNode(id, mergeData.value) + mergeData.value = deleteNode(id, mergeData.value); }, } - ) - handleInitNodeClassNameReflect(disabled, id) + ); + handleInitNodeClassNameReflect(disabled, id); handleInitLazyNodeReflect(item, { id, onGetNodeData: async () => { @@ -81,9 +81,9 @@ export default defineComponent({ label: `It is a test Node-2 ID = ${id}`, level: item.level + 1 } - ]) - }, 4000) - }) + ]); + }, 4000); + }); }, renderLoading: (id) => { return Loading.open({ @@ -91,30 +91,30 @@ export default defineComponent({ message: '加载中...', positionType: 'relative', zIndex: 1, - }) + }); } - }) + }); const renderFoldIcon = (item: TreeItem) => { const handleClick = async (target: MouseEvent) => { if (item.isParent) { - item.children = await getLazyData(id) // item 按引用传递 + item.children = await getLazyData(id); // item 按引用传递 } - return toggle(target, item) - } + return toggle(target, item); + }; return ( <div class="devui-tree-node__folder" onClick={handleClick} > { isParent || children && children.length - ? open - ? <IconOpen class="mr-xs" /> - : <IconClose class="mr-xs" /> - : <span class="devui-tree-node__indent" /> + ? open + ? <IconOpen class="mr-xs" /> + : <IconClose class="mr-xs" /> + : <span class="devui-tree-node__indent" /> } </div> - - ) - } - const checkState = CHECK_CONFIG[selected.value[id] ?? 'none'] + + ); + }; + const checkState = CHECK_CONFIG[selected.value[id] ?? 'none']; return ( <div class={['devui-tree-node', open && 'devui-tree-node__open']} @@ -142,14 +142,14 @@ export default defineComponent({ </div> </div> </div> - ) - } + ); + }; return () => { return ( <div class="devui-tree"> { openedData.value.map(item => renderNode(item)) } </div> - ) - } + ); + }; } -}) +}); diff --git a/packages/devui-vue/devui/tree/src/util.ts b/packages/devui-vue/devui/tree/src/util.ts index c984e8167a..cac60d3a0f 100644 --- a/packages/devui-vue/devui/tree/src/util.ts +++ b/packages/devui-vue/devui/tree/src/util.ts @@ -1,64 +1,64 @@ -import { TreeData, TreeItem } from './tree-types' +import { TreeData, TreeItem } from './tree-types'; export const omit = (obj: unknown, key: string): unknown => { return Object.entries(obj) .filter(item => item[0] !== key) - .reduce((acc, item) => Object.assign({}, acc, { [item[0]]: item[1] }), {}) -} + .reduce((acc, item) => Object.assign({}, acc, { [item[0]]: item[1] }), {}); +}; export const flatten = (tree: Array<any>, key = 'children'): Array<any> => { return tree.reduce((acc, item) => ( !item[key] ? acc.concat(item) : acc.concat(item, flatten(item[key], key)) - ), []) -} + ), []); +}; /** * 用于设置 Tree Node 的 ID 属性 * 应用场景: 懒加载 loading 后元素定位 */ -const getRandomId = (): string => (Math.random() * 10 ** 9).toString().slice(0,8) +const getRandomId = (): string => (Math.random() * 10 ** 9).toString().slice(0,8); const preCheckNodeId = (d: TreeItem, postfixId?: string): TreeItem => { - const randomStr = getRandomId() - return { ...d, id: postfixId ? `${postfixId}_${randomStr}` : randomStr } -} + const randomStr = getRandomId(); + return { ...d, id: postfixId ? `${postfixId}_${randomStr}` : randomStr }; +}; export const getId = (id: string): string => { - const ids = id.split('_') - return [...ids.slice(0, ids.length), getRandomId()].join('_') -} + const ids = id.split('_'); + return [...ids.slice(0, ids.length), getRandomId()].join('_'); +}; /** * 用于 Tree Node 的数据格式检查 */ export const preCheckTree = (ds: TreeData, postfixId?: string): TreeData => { return ds.map(d => { - const dd = preCheckNodeId(d, postfixId) + const dd = preCheckNodeId(d, postfixId); if (!dd.parentId && postfixId) { - dd.parentId = postfixId + dd.parentId = postfixId; } return d.children ? { ...dd, children: preCheckTree(d.children, dd.id) - } : dd - }) -} + } : dd; + }); +}; const _deleteNode = (ids: Array<string>, data: Array<TreeItem>, index = 0): Array<TreeItem> => { - const curTargetId = ids.slice(0, index + 2).join('_') + const curTargetId = ids.slice(0, index + 2).join('_'); data.forEach(item => { if (item.id === ids.slice(0, index + 1).join('_')) { if (ids.length === index + 2) { - item.children = item.children.filter(({ id: d }) => d !== curTargetId) + item.children = item.children.filter(({ id: d }) => d !== curTargetId); } else { - item.children = _deleteNode(ids, item.children, index + 1) + item.children = _deleteNode(ids, item.children, index + 1); } } - }) - return data -} + }); + return data; +}; export const deleteNode = (id: string, data: Array<TreeItem>): Array<TreeItem> => { if (id.includes('_')) { - return _deleteNode(id.split('_'), data) + return _deleteNode(id.split('_'), data); } - return data.filter(({ id: d }) => d !== id) -} + return data.filter(({ id: d }) => d !== id); +}; diff --git a/packages/devui-vue/devui/upload/__tests__/upload.spec.ts b/packages/devui-vue/devui/upload/__tests__/upload.spec.ts index 6960223cf4..a566661648 100644 --- a/packages/devui-vue/devui/upload/__tests__/upload.spec.ts +++ b/packages/devui-vue/devui/upload/__tests__/upload.spec.ts @@ -1,13 +1,13 @@ -import { mount } from '@vue/test-utils' -import { ref, nextTick, reactive } from 'vue' -import DUpload from '../src/upload' +import { mount } from '@vue/test-utils'; +import { ref, nextTick, reactive } from 'vue'; +import DUpload from '../src/upload'; const getMockFile = (element: Element, files: File[]): void => { Object.defineProperty(element, 'files', { get() { - return files + return files; } - }) -} + }); +}; describe('upload', () => { it('should render correctly', () => { @@ -24,16 +24,16 @@ describe('upload', () => { setup() { const uploadOptions = reactive({ uri: 'http://localhost:4000/files/upload' - }) - const uploadedFiles = ref([]) + }); + const uploadedFiles = ref([]); return { uploadedFiles, uploadOptions - } + }; } - } - mount(TestComponent) - }) + }; + mount(TestComponent); + }); it('should work with `disabled` prop', () => { const TestComponent = { components: { @@ -49,19 +49,19 @@ describe('upload', () => { setup() { const uploadOptions = reactive({ uri: 'http://localhost:4000/files/upload' - }) - const uploadedFiles = ref([]) + }); + const uploadedFiles = ref([]); return { uploadedFiles, uploadOptions - } + }; } - } - const wrapper = mount(TestComponent) - expect(wrapper.find('.devui-input-group.disabled').exists()).toBe(true) - }) + }; + const wrapper = mount(TestComponent); + expect(wrapper.find('.devui-input-group.disabled').exists()).toBe(true); + }); it('should work with `before-upload auto-upload withoutBtn` prop', async () => { - const beforeUpload = jest.fn(async () => true) + const beforeUpload = jest.fn(async () => true); const TestComponent = { components: { @@ -79,32 +79,32 @@ describe('upload', () => { setup() { const uploadOptions = reactive({ uri: 'http://localhost:4000/files/upload' - }) - const uploadedFiles = ref([]) + }); + const uploadedFiles = ref([]); return { uploadedFiles, uploadOptions, beforeUpload - } + }; } - } - const wrapper = mount(TestComponent) - const uploadElment = wrapper.find('.devui-input-group') - await uploadElment.trigger('click') - await nextTick() - const input = document.getElementById('d-upload-temp') + }; + const wrapper = mount(TestComponent); + const uploadElment = wrapper.find('.devui-input-group'); + await uploadElment.trigger('click'); + await nextTick(); + const input = document.getElementById('d-upload-temp'); const fileList = [ new File(['test'], 'file.txt', { type: 'text/plain', lastModified: Date.now() }) - ] - getMockFile(input, fileList) - const evt = new Event('change') - await input.dispatchEvent(evt) - expect(beforeUpload).toHaveBeenCalled() - expect(wrapper.find('.devui-upload button').exists()).toBe(false) - }) + ]; + getMockFile(input, fileList); + const evt = new Event('change'); + await input.dispatchEvent(evt); + expect(beforeUpload).toHaveBeenCalled(); + expect(wrapper.find('.devui-upload button').exists()).toBe(false); + }); it('should work with `placeholderText uploadText` prop', async () => { const TestComponent = { components: { @@ -121,16 +121,16 @@ describe('upload', () => { setup() { const uploadOptions = reactive({ uri: 'http://localhost:4000/files/upload' - }) - const uploadedFiles = ref([]) + }); + const uploadedFiles = ref([]); return { uploadedFiles, uploadOptions - } + }; } - } - const wrapper = mount(TestComponent) - expect(wrapper.find('.devui-upload-placeholder').text()).toBe('select file') - expect(wrapper.find('.devui-upload button').text()).toBe('upload') - }) -}) + }; + const wrapper = mount(TestComponent); + expect(wrapper.find('.devui-upload-placeholder').text()).toBe('select file'); + expect(wrapper.find('.devui-upload button').text()).toBe('upload'); + }); +}); diff --git a/packages/devui-vue/devui/upload/src/composables/use-upload.ts b/packages/devui-vue/devui/upload/src/composables/use-upload.ts index 1275d9621c..883b4acc62 100644 --- a/packages/devui-vue/devui/upload/src/composables/use-upload.ts +++ b/packages/devui-vue/devui/upload/src/composables/use-upload.ts @@ -65,11 +65,11 @@ export const useUpload = () => { const upload = async ( oneFile? ): Promise< - | never - | { - file: File; - response: any; - }[] + | never + | { + file: File; + response: any; + }[] > => { let uploads: any[] = []; if (oneFile) { diff --git a/packages/devui-vue/docs/components/alert/index.md b/packages/devui-vue/docs/components/alert/index.md index e0fc685726..8159aef392 100644 --- a/packages/devui-vue/docs/components/alert/index.md +++ b/packages/devui-vue/docs/components/alert/index.md @@ -77,11 +77,11 @@ export default { ```vue <template> <div class="alert-demo-3"> - <d-alert type="success" :showIcon="false">success</d-alert> - <d-alert type="danger" :showIcon="false">danger</d-alert> - <d-alert type="warning" :showIcon="false">warning</d-alert> - <d-alert type="info" :showIcon="false">info</d-alert> - <d-alert type="simple" :showIcon="false">simple</d-alert> + <d-alert type="success" :show-icon="false">success</d-alert> + <d-alert type="danger" :show-icon="false">danger</d-alert> + <d-alert type="warning" :show-icon="false">warning</d-alert> + <d-alert type="info" :show-icon="false">info</d-alert> + <d-alert type="simple" :show-icon="false">simple</d-alert> </div> </template> <style> @@ -100,10 +100,10 @@ export default { | 属性 | 类型 | 默认 | 说明 | 跳转 Demo | | ----------- | ------------------------- | ------ | --------------------------------------- | --------------------------------- | | type | [`AlertType`](#AlertType) | 'info' | 必选,指定警告提示的样式 | [基本用法](#基本用法) | -| cssClass | `string` | -- | 可选,自定义 class 名 | +| css-class | `string` | -- | 可选,自定义 class 名 | | closeable | `boolean` | true | 可选,默认显示关闭按钮 | [基本用法](#可关闭的提示) | -| dismissTime | `number` | -- | 可选,自动关闭 alert 的延迟时间(`ms`) | -| showIcon | `boolean` | true | 可选,是否使用默认的类型图标 | [不使用默认图标](#不使用默认图标) | +| dismiss-time | `number` | -- | 可选,自动关闭 alert 的延迟时间(`ms`) | +| show-icon | `boolean` | true | 可选,是否使用默认的类型图标 | [不使用默认图标](#不使用默认图标) | ### d-alert 事件 diff --git a/packages/devui-vue/docs/components/anchor/demo.tsx b/packages/devui-vue/docs/components/anchor/demo.tsx index d87cc00cee..0d04660805 100644 --- a/packages/devui-vue/docs/components/anchor/demo.tsx +++ b/packages/devui-vue/docs/components/anchor/demo.tsx @@ -1,5 +1,5 @@ -import { defineComponent } from 'vue' - +import { defineComponent } from 'vue'; + export default defineComponent({ name: 'DAnchor', props: { @@ -8,28 +8,28 @@ export default defineComponent({ return () => { return ( <div v-d-anchor-box className="scrollTarget"> - <ul> - <li v-d-anchor-link="anchorlink-one">anchorlink-one</li> - <li v-d-anchor-link="anchorlink-two">anchorlink-two</li> - <li v-d-anchor-link="anchorlink-three">anchorlink-three</li> - <li v-d-anchor-link="anchorlink-four">anchorlink-four</li> - </ul> - <div> - <div v-d-anchor="anchorlink-one"> + <ul> + <li v-d-anchor-link="anchorlink-one">anchorlink-one</li> + <li v-d-anchor-link="anchorlink-two">anchorlink-two</li> + <li v-d-anchor-link="anchorlink-three">anchorlink-three</li> + <li v-d-anchor-link="anchorlink-four">anchorlink-four</li> + </ul> + <div> + <div v-d-anchor="anchorlink-one"> anchorlink-one - </div> - <div v-d-anchor="anchorlink-two"> + </div> + <div v-d-anchor="anchorlink-two"> anchorlink-two - </div> - <div v-d-anchor="anchorlink-three"> + </div> + <div v-d-anchor="anchorlink-three"> anchorlink-three - </div> - <div v-d-anchor="anchorlink-four"> + </div> + <div v-d-anchor="anchorlink-four"> anchorlink-four - </div> </div> </div> - ) - } + </div> + ); + }; } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/docs/components/icon/index.md b/packages/devui-vue/docs/components/icon/index.md index 12e1d4b653..3013476f4b 100644 --- a/packages/devui-vue/docs/components/icon/index.md +++ b/packages/devui-vue/docs/components/icon/index.md @@ -87,4 +87,4 @@ import "my-icon.css"; | name | `String` | -- | 必选,Icon 名称 | [基本用法](#基本用法) | | size | `String` | '16px' | 可选,图标大小 | [基本用法](#基本用法) | | color | `String` | '#252b3a' | 可选,图标颜色 | [基本用法](#基本用法) | -| classPrefix | `String` | 'icon' | 可选,自定义字体图标前缀 | [自定义字体图标](#自定义字体图标) | +| class-prefix | `String` | 'icon' | 可选,自定义字体图标前缀 | [自定义字体图标](#自定义字体图标) | diff --git a/packages/devui-vue/docs/components/panel/index.md b/packages/devui-vue/docs/components/panel/index.md index d43748a783..30545ed2de 100644 --- a/packages/devui-vue/docs/components/panel/index.md +++ b/packages/devui-vue/docs/components/panel/index.md @@ -12,13 +12,13 @@ ```vue <template> - <d-panel type="primary" :isCollapsed="true" :showAnimation="true"> + <d-panel type="primary" :is-collapsed="true" :show-animation="true"> <d-panel-header>Panel with foldable</d-panel-header> <d-panel-body>This is body</d-panel-body> </d-panel> <br /> <br /> - <d-panel :toggle="toggle" :isCollapsed="true" :showAnimation="true" :hasLeftPadding="false"> + <d-panel :toggle="toggle" :is-collapsed="true" :show-animation="true" :has-left-padding="false"> <d-panel-header> Panel has no left padding <em :class="`icon icon-chevron-${toggleState ? 'down' : 'up'}`"></em> @@ -27,7 +27,7 @@ </d-panel> <br /> <br /> - <d-panel :isCollapsed="true" :beforeToggle="beforeToggle"> + <d-panel :is-collapsed="true" :before-toggle="beforeToggle"> <d-panel-header>Panel with header and footer</d-panel-header> <d-panel-body>This is body</d-panel-body> <d-panel-footer>This is footer</d-panel-footer> @@ -60,29 +60,29 @@ export default defineComponent({ ```vue <template> - <d-panel type="info" :isCollapsed="true" :showAnimation="true"> + <d-panel type="info" :is-collapsed="true" :show-animation="true"> <d-panel-header>Panel with info Type</d-panel-header> <d-panel-body>This is body</d-panel-body> </d-panel> - <d-panel type="primary" :isCollapsed="true" :showAnimation="true"> + <d-panel type="primary" :is-collapsed="true" :show-animation="true"> <d-panel-header>Panel with Primary Type</d-panel-header> <d-panel-body>This is body</d-panel-body> </d-panel> <br /> <br /> - <d-panel type="success" :isCollapsed="true" :showAnimation="true"> + <d-panel type="success" :is-collapsed="true" :show-animation="true"> <d-panel-header>Panel with Success Type</d-panel-header> <d-panel-body>This is body</d-panel-body> </d-panel> <br /> <br /> - <d-panel type="warning" :isCollapsed="true" :showAnimation="true"> + <d-panel type="warning" :is-collapsed="true" :show-animation="true"> <d-panel-header>Panel with Warning Type</d-panel-header> <d-panel-body>This is body</d-panel-body> </d-panel> <br /> <br /> - <d-panel type="danger" :isCollapsed="true" :showAnimation="true"> + <d-panel type="danger" :is-collapsed="true" :show-animation="true"> <d-panel-header>Panel with danger Type</d-panel-header> <d-panel-body>This is body</d-panel-body> </d-panel> @@ -103,10 +103,10 @@ export default defineComponent({ <template> <d-panel type="primary" - :hasLeftPadding="padding" + :has-left-padding="padding" :toggle="handleToggle" - :beforeToggle="beforeToggle" - :showAnimation="showAnimation" + :before-toggle="beforeToggle" + :show-animation="showAnimation" > <d-panel-header> Panel with foldable @@ -157,7 +157,7 @@ export default defineComponent({ ### 动态切换 -我们以 hasLeftPadding 为例 +我们以 has-left-padding 为例 理论上所有的属性都可以动态切换 @@ -165,7 +165,7 @@ export default defineComponent({ ```vue <template> - <d-panel :hasLeftPadding="padding" :isCollapsed="true"> + <d-panel :has-left-padding="padding" :is-collapsed="true"> <d-panel-header>Panel with foldable</d-panel-header> <d-panel-body>This is body</d-panel-body> </d-panel> @@ -196,11 +196,11 @@ export default defineComponent({ | 参数 | 类型 | 默认 | 说明 | | :------------: | :---------------------------: | :-------: | :---------------------------------------------------------------------------------------------------------: | | type | PanelType | 'default' | 可选,面板的类型 | -| cssClass | string | -- | 可选,自定义 class 名 | -| isCollapsed | boolean | false | 可选,是否展开 | -| hasLeftPadding | boolean | true | 可选,是否显示左侧填充 | -| showAnimation | boolean | true | 可选,是否展示动画 | -| beforeToggle | Function\|Promise\|Observable | -- | 可选,面板折叠状态改变前的回调函数,返回 boolean 类型,返回 false 可以阻止面板改变折叠状态 根据条件阻止折叠 | +| css-class | string | -- | 可选,自定义 class 名 | +| is-collapsed | boolean | false | 可选,是否展开 | +| has-left-padding | boolean | true | 可选,是否显示左侧填充 | +| show-animation | boolean | true | 可选,是否展示动画 | +| before-toggle | Function\|Promise\|Observable | -- | 可选,面板折叠状态改变前的回调函数,返回 boolean 类型,返回 false 可以阻止面板改变折叠状态 根据条件阻止折叠 | | toggle | Function | -- | 可选,面板当前状态的回调函数,返回 boolean 类型,返回 false 代表面板被收起,返回 true 代表面板展开 | ### 接口&类型定义 diff --git a/packages/devui-vue/docs/vite.config.ts b/packages/devui-vue/docs/vite.config.ts index 6d2a00609e..84422a2154 100644 --- a/packages/devui-vue/docs/vite.config.ts +++ b/packages/devui-vue/docs/vite.config.ts @@ -1,7 +1,7 @@ -import path from 'path' -import { defineConfig } from 'vite' -import vueJsx from '@vitejs/plugin-vue-jsx' -import svgLoader from 'vite-svg-loader' +import path from 'path'; +import { defineConfig } from 'vite'; +import vueJsx from '@vitejs/plugin-vue-jsx'; +import svgLoader from 'vite-svg-loader'; export default defineConfig({ resolve: { @@ -22,4 +22,4 @@ export default defineConfig({ strict: false } } -}) \ No newline at end of file +}); diff --git a/packages/devui-vue/jest.config.js b/packages/devui-vue/jest.config.js index fb480498a9..fed80dbbd1 100644 --- a/packages/devui-vue/jest.config.js +++ b/packages/devui-vue/jest.config.js @@ -34,4 +34,4 @@ module.exports = { // The test environment that will be used for testing testEnvironment: 'jest-environment-jsdom', setupFiles: ['<rootDir>/jest.setup.js'], -} +}; diff --git a/packages/devui-vue/jest.setup.js b/packages/devui-vue/jest.setup.js index 88b32b6bfc..4f4932486d 100644 --- a/packages/devui-vue/jest.setup.js +++ b/packages/devui-vue/jest.setup.js @@ -1,14 +1,14 @@ -import { config } from '@vue/test-utils' -import Icon from './devui/icon/src/icon' -import Button from './devui/button/src/button' -import Progress from './devui/progress/src/progress' -import fileDropDirective from './devui/upload/src/file-drop-directive' +import { config } from '@vue/test-utils'; +import Icon from './devui/icon/src/icon'; +import Button from './devui/button/src/button'; +import Progress from './devui/progress/src/progress'; +import fileDropDirective from './devui/upload/src/file-drop-directive'; config.global.components = { 'd-icon': Icon, 'd-button': Button, 'd-progress': Progress, -} +}; config.global.directives = { FileDrop: fileDropDirective, -} +};