diff --git a/common/shared/package.json b/common/shared/package.json index 51a9465a35..c2f39eb223 100644 --- a/common/shared/package.json +++ b/common/shared/package.json @@ -33,7 +33,7 @@ "dependencies": { "@tsdown/css": "^0.22.14", "@typescript-eslint/parser": "^8.65.0", - "@vitest/coverage-istanbul": "^4.1.11", + "@vitest/coverage-istanbul": "^5.0.0", "autoprefixer": "^10.5.4", "eslint-plugin-better-tailwindcss": "^4.7.0", "eslint-plugin-header": "^3.1.1", @@ -48,7 +48,7 @@ "tailwindcss": "3.4.18", "tsdown": "^0.22.14", "unplugin-vue": "^7.2.0", - "vitest": "^4.1.11" + "vitest": "^5.0.0" }, "devDependencies": { "@univerjs/icons": "1.38.0", diff --git a/docs/NAMING_CONVENTION.md b/docs/NAMING_CONVENTION.md index e5de1aa4f7..4b6f7fd661 100644 --- a/docs/NAMING_CONVENTION.md +++ b/docs/NAMING_CONVENTION.md @@ -192,14 +192,14 @@ A package MUST NOT reference a key whose first segment is another package's name ```typescript // In @univerjs/sheets-filter // 🚫 references a key from the UI package -localeService.t('sheets-filter-ui.panel.empty') +localeService.t('sheets-filter-ui.panel.empty') // In @univerjs/sheets-filter-ui // 🚫 references a key from a common/utility package -localeService.t('sheets-ui.permission.dialog.filterErr') +localeService.t('sheets-ui.permission.dialog.filterErr') // ✅ sink the key into your own locale file -localeService.t('sheets-filter-ui.permission.filterErr') +localeService.t('sheets-filter-ui.permission.filterErr') ``` ### Namespace must be the single root key diff --git a/examples/package.json b/examples/package.json index 34f3fb0b67..504ca5ec5e 100644 --- a/examples/package.json +++ b/examples/package.json @@ -52,6 +52,6 @@ "tsx": "^4.22.4", "typescript": "^6.0.3", "vite": "^8.0.11", - "vitest": "^4.1.10" + "vitest": "^5.0.0" } } diff --git a/package.json b/package.json index 4b34c263b8..c849eb8b23 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "tailwindcss": "3.4.18", "turbo": "^2.10.8", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" }, "lint-staged": { "*": "eslint --fix" diff --git a/packages/action-recorder/package.json b/packages/action-recorder/package.json index 3aa2d65047..96632b9304 100644 --- a/packages/action-recorder/package.json +++ b/packages/action-recorder/package.json @@ -88,6 +88,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/core/package.json b/packages/core/package.json index 7a630ae72b..81b238ed3b 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -95,6 +95,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/data-validation/package.json b/packages/data-validation/package.json index f578d1f25e..60710f1e10 100644 --- a/packages/data-validation/package.json +++ b/packages/data-validation/package.json @@ -81,6 +81,6 @@ "@univerjs/sheets": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/design/.gitignore b/packages/design/.gitignore new file mode 100644 index 0000000000..d3df7912a3 --- /dev/null +++ b/packages/design/.gitignore @@ -0,0 +1 @@ +/src/helper/clsx.generated.ts diff --git a/packages/design/package.json b/packages/design/package.json index 478701ada0..701bec9667 100644 --- a/packages/design/package.json +++ b/packages/design/package.json @@ -61,6 +61,7 @@ "lib" ], "scripts": { + "prepare": "node scripts/generate-clsx.mts", "test": "vitest run", "test:watch": "vitest", "coverage": "vitest run --coverage", @@ -83,10 +84,8 @@ "@radix-ui/react-slot": "^1.3.3", "@univerjs/icons": "1.38.0", "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", "cmdk": "1.1.1", - "sonner": "^2.0.7", - "tailwind-merge": "2.6.0" + "sonner": "^2.0.7" }, "devDependencies": { "@testing-library/jest-dom": "6.9.1", @@ -95,9 +94,10 @@ "postcss": "^8.5.26", "react": "18.3.1", "react-dom": "18.3.1", + "tailwind-merge": "2.6.0", "tailwindcss": "3.4.18", "tailwindcss-animate": "^1.0.7", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/design/scripts/generate-clsx.mts b/packages/design/scripts/generate-clsx.mts new file mode 100644 index 0000000000..79b194bff7 --- /dev/null +++ b/packages/design/scripts/generate-clsx.mts @@ -0,0 +1,87 @@ +import type { Config } from 'tailwind-merge'; +import { readFileSync, writeFileSync } from 'node:fs'; +import { createRequire } from 'node:module'; +import { dirname, resolve } from 'node:path'; +import { getDefaultConfig, validators } from 'tailwind-merge'; + +type ClassGroup = Config['classGroups'][string]; + +const config = getDefaultConfig(); +const groupNames = Object.keys(config.classGroups); +const validatorNames = Object.keys(validators).sort() as Array; +const groupIds = new Map(groupNames.map((name, index) => [name, index + 1])); + +interface IRule { + literals: string[]; + validators: number; +} + +function visit(definitions: ClassGroup, prefix: string, rules: Map) { + const rule = rules.get(prefix) ?? { literals: [], validators: 0 }; + rules.set(prefix, rule); + for (const definition of definitions) { + if (typeof definition === 'string') { + rule.literals.push(definition); + } else if (typeof definition === 'function') { + if ('isThemeGetter' in definition) { + visit(definition(config.theme), prefix, rules); + continue; + } + + const validator = validatorNames.findIndex((name) => validators[name] === definition); + if (validator === -1) { + throw new Error(`Unknown Tailwind v3 validator: ${definition.name}`); + } + + rule.validators |= 1 << validator; + } else { + for (const [part, children] of Object.entries(definition)) { + visit(children, prefix + (prefix ? '-' : '') + part, rules); + } + } + } +} + +const classGroups = Object.values(config.classGroups).map((definitions) => { + const rules = new Map(); + visit(definitions, '', rules); + return Array.from(rules) + .filter(([, rule]) => rule.literals.length || rule.validators) + .map(([prefix, rule]) => `['${prefix}', ${rule.literals.length ? `'${rule.literals.join(' ')}'` : 'null'}, ${rule.validators}]`); +}); + +function serializeConflicts(conflicts: Record) { + return Object.entries(conflicts).map(([name, targets]) => + ` ${groupIds.get(name)}: [${targets!.map((target) => groupIds.get(target)).join(', ')}],` + ).join('\n'); +} + +const require = createRequire(import.meta.url); +const packageDir = resolve(dirname(require.resolve('tailwind-merge')), '..'); +const license = readFileSync(resolve(packageDir, 'LICENSE.md'), 'utf8').trim(); +const header = readFileSync(new URL('../src/helper/clsx.ts', import.meta.url), 'utf8').split('\n\n')[0]; +const output = `${header} + +// Generated by pnpm --filter @univerjs/design prepare. Do not edit. +// Complete tailwind-merge 2.6.0 / Tailwind CSS 3.4 rules; the runtime supplies the univer- prefix. +/*! +${license.split('\n').map((line) => ` *${line ? ` ${line}` : ''}`).join('\n')} + */ + +export const VALIDATOR_NAMES = [${validatorNames.map((name) => `'${name}'`).join(', ')}] as const; + +// Group IDs are one-based. Each rule contains a prefix, literal suffixes and a validator bitmask. +export const CLASS_GROUPS: ReadonlyArray> = [ +${classGroups.map((rules) => ` [${rules.join(', ')}],`).join('\n')} +]; + +export const CLASS_CONFLICTS: Record = { +${serializeConflicts(config.conflictingClassGroups)} +}; + +export const POSTFIX_CONFLICTS: Record = { +${serializeConflicts(config.conflictingClassGroupModifiers)} +}; +`; + +writeFileSync(new URL('../src/helper/clsx.generated.ts', import.meta.url), output); diff --git a/packages/design/src/helper/__tests__/clsx.spec.ts b/packages/design/src/helper/__tests__/clsx.spec.ts index 147519e8d2..4f5288e6ea 100644 --- a/packages/design/src/helper/__tests__/clsx.spec.ts +++ b/packages/design/src/helper/__tests__/clsx.spec.ts @@ -16,9 +16,24 @@ import { cva } from 'class-variance-authority'; import { describe, expect, it } from 'vitest'; + import { clsx } from '../clsx'; describe('clsx', () => { + it('flattens conditional values without caching mutable arrays or objects by identity', () => { + const active = { 'univer-h-8': false }; + const values = ['univer-h-6']; + const inputs = [values, active, [false, null, undefined, 0, Number.NaN, '', true, 7, 1n]]; + + expect(clsx(...inputs)).toBe('univer-h-6 7'); + active['univer-h-8'] = true; + expect(clsx(...inputs)).toBe('univer-h-8 7'); + values.push('univer-p-2'); + expect(clsx(...inputs)).toBe('univer-p-2 univer-h-8 7'); + expect(clsx()).toBe(''); + expect(clsx(' \n univer-p-2\t univer-p-4 ')).toBe('univer-p-4'); + }); + it('merges Univer-prefixed conflicting utilities', () => { expect(clsx('univer-h-6', 'univer-h-[78px]')).toBe('univer-h-[78px]'); expect(clsx('univer-px-3', 'univer-px-8')).toBe('univer-px-8'); @@ -37,4 +52,53 @@ describe('clsx', () => { expect(clsx(buttonVariants({ size: 'small', className: 'univer-h-[78px]' }))).toBe('univer-h-[78px]'); }); + + it.each([ + ['univer-pr-2 univer-px-4', 'univer-px-4'], + ['univer-px-4 univer-pr-2', 'univer-px-4 univer-pr-2'], + ['univer-p-2 univer-px-4', 'univer-p-2 univer-px-4'], + ['univer-px-4 univer-p-2', 'univer-p-2'], + ['univer-w-2 univer-h-4 univer-size-8', 'univer-size-8'], + ['univer-size-8 univer-w-2', 'univer-size-8 univer-w-2'], + ['-univer-m-2 univer-m-4', 'univer-m-4'], + ['univer-p-2 !univer-p-4 !univer-p-8', 'univer-p-2 !univer-p-8'], + ['univer-leading-8 univer-text-sm/6', 'univer-text-sm/6'], + ['univer-text-sm/6 univer-leading-8', 'univer-text-sm/6 univer-leading-8'], + ['univer-w-1/2 univer-w-3/4', 'univer-w-3/4'], + ['univer-bg-opacity-25 univer-bg-opacity-50 univer-bg-red-500/50', 'univer-bg-opacity-50 univer-bg-red-500/50'], + ['univer-text-opacity-25 univer-text-opacity-75', 'univer-text-opacity-75'], + ])('resolves directional and v3-specific conflicts: %s', (input, expected) => { + expect(clsx(input)).toBe(expected); + }); + + it.each([ + ['hover:focus:univer-p-2 focus:hover:univer-p-4', 'focus:hover:univer-p-4'], + ['hover:univer-p-2 focus:univer-p-4', 'hover:univer-p-2 focus:univer-p-4'], + ['dark:hover:!univer-p-2 hover:dark:!univer-p-4', 'hover:dark:!univer-p-4'], + ['[&:nth-child(2)]:univer-p-2 [&:nth-child(2)]:univer-p-4', '[&:nth-child(2)]:univer-p-4'], + ['hover:[&_a]:univer-p-2 [&_a]:hover:univer-p-4', 'hover:[&_a]:univer-p-2 [&_a]:hover:univer-p-4'], + ['group-hover/menu:univer-p-2 group-hover/menu:univer-p-4', 'group-hover/menu:univer-p-4'], + ['data-[state=open]:univer-p-2 data-[state=open]:univer-p-4', 'data-[state=open]:univer-p-4'], + ])('keeps variant scopes distinct: %s', (input, expected) => { + expect(clsx(input)).toBe(expected); + }); + + it.each([ + ['univer-text-[length:var(--size)] univer-text-[color:var(--color)]', 'univer-text-[length:var(--size)] univer-text-[color:var(--color)]'], + ['univer-bg-[url(https://example.com/a-b.svg)] univer-bg-red-500', 'univer-bg-[url(https://example.com/a-b.svg)] univer-bg-red-500'], + ['univer-bg-[size:20px_30px] univer-bg-cover', 'univer-bg-cover'], + ['univer-shadow-[0_1px_2px_black] univer-shadow-red-500', 'univer-shadow-[0_1px_2px_black] univer-shadow-red-500'], + ['[color:red] [color:blue] [background:red]', '[color:blue] [background:red]'], + ['hover:[--gutter:1rem] hover:[--gutter:2rem]', 'hover:[--gutter:2rem]'], + ['p-2 p-4 univer-custom univer-custom', 'p-2 p-4 univer-custom univer-custom'], + ['univer-p-unknown univer-p-2', 'univer-p-unknown univer-p-2'], + ['constructor toString __proto__ univer-constructor univer-toString', 'constructor toString __proto__ univer-constructor univer-toString'], + ])('recognizes arbitrary values and preserves external classes: %s', (input, expected) => { + expect(clsx(input)).toBe(expected); + }); + + it('handles the v3 leading important marker before a font-size/line-height postfix', () => { + expect(clsx('!univer-leading-8 !univer-text-sm/6')).toBe('!univer-text-sm/6'); + expect(clsx('!univer-text-red-500 !univer-text-sm/6')).toBe('!univer-text-red-500 !univer-text-sm/6'); + }); }); diff --git a/packages/design/src/helper/clsx.ts b/packages/design/src/helper/clsx.ts index 7cbf00ac85..cad2bc0a42 100644 --- a/packages/design/src/helper/clsx.ts +++ b/packages/design/src/helper/clsx.ts @@ -14,13 +14,256 @@ * limitations under the License. */ -/* eslint-disable no-restricted-imports */ -import type { ClassValue } from 'clsx'; -import { clsx as cn } from 'clsx'; -import { extendTailwindMerge } from 'tailwind-merge'; +import { CLASS_CONFLICTS, CLASS_GROUPS, POSTFIX_CONFLICTS, VALIDATOR_NAMES } from './clsx.generated'; -const twMerge = extendTailwindMerge({ prefix: 'univer-' }); +export type ClassValue = string | number | bigint | boolean | null | undefined | ClassValue[] | Record; -export function clsx(...inputs: ClassValue[]) { - return twMerge(cn(inputs)); +interface IClassToken { + id: number | string; + conflicts: readonly (number | string)[]; +} + +const arbitraryValue = /^\[(?:([a-z-]+):)?(.+)\]$/i; +const lengthValue = /\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/; +const colorValue = /^(rgba?|hsla?|hwb|(ok)?(lab|lch))\(.+\)$/; + +function isNumber(value: string) { + return Boolean(value) && !Number.isNaN(Number(value)); +} + +function isArbitrary(value: string, labels: string[], test: (value: string) => boolean = () => false) { + const match = arbitraryValue.exec(value); + return !!match && (match[1] ? labels.includes(match[1]) : test(match[2])); +} + +// Tailwind v3 validators, adapted from tailwind-merge 2.6.0. +// Its MIT license is included with the generated rules in clsx.generated.ts. +const validators: Record boolean> = { + isAny: () => true, + isArbitraryImage: (value) => isArbitrary(value, ['image', 'url'], (value) => /^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/.test(value)), + isArbitraryLength: (value) => isArbitrary(value, ['length'], (value) => lengthValue.test(value) && !colorValue.test(value)), + isArbitraryNumber: (value) => isArbitrary(value, ['number'], isNumber), + isArbitraryPosition: (value) => isArbitrary(value, ['position']), + isArbitraryShadow: (value) => isArbitrary(value, [], (value) => /^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/.test(value)), + isArbitrarySize: (value) => isArbitrary(value, ['length', 'size', 'percentage']), + isArbitraryValue: (value) => arbitraryValue.test(value), + isInteger: (value) => Boolean(value) && Number.isInteger(Number(value)), + isLength: (value) => isNumber(value) || ['px', 'full', 'screen'].includes(value) || /^\d+\/\d+$/.test(value), + isNumber, + isPercent: (value) => value.endsWith('%') && isNumber(value.slice(0, -1)), + isTshirtSize: (value) => /^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/.test(value), +}; + +const classValidators = VALIDATOR_NAMES.map((name) => validators[name]); +const classPatterns = new Map(); +const classGroups = new Map(); +const cache = new Map(); +const cacheKeys = cache.keys(); +const tokens = new Map(); +const tokenKeys = tokens.keys(); +const plainTokens: IClassToken[] = []; + +CLASS_GROUPS.forEach((rules, index) => { + for (const [prefix, literals, mask] of rules) { + if (literals !== null) { + for (const suffix of literals.split(' ')) { + classGroups.set(prefix + (prefix && suffix ? '-' : '') + suffix, index + 1); + } + } + if (mask) { + const patterns = classPatterns.get(prefix) ?? []; + patterns.push(index + 1, mask); + classPatterns.set(prefix, patterns); + } + } +}); + +function getClassGroup(className: string): number | string | undefined { + const positive = className.startsWith('-') ? className.slice(1) : className; + if (!positive.startsWith('univer-')) { + // Arbitrary properties are unprefixed in Tailwind v3, including in prefixed projects. + const property = /^\[([^:]+):.+\]$/.exec(className); + return property ? `arbitrary..${property[1]}` : undefined; + } + + const utility = positive.slice(7); + const exact = classGroups.get(utility); + if (exact !== undefined) { + return exact; + } + + // Longest prefix first preserves v3's precedence (e.g. border-x width before border color). + for (let end = utility.lastIndexOf('-'); end > 0; end = utility.lastIndexOf('-', end - 1)) { + const rules = classPatterns.get(utility.slice(0, end)); + if (!rules) { + continue; + } + + const value = utility.slice(end + 1); + for (let index = 0; index < rules.length; index += 2) { + // Visit only the validators present in the precompiled bitmask. + for (let mask = rules[index + 1]; mask; mask &= mask - 1) { + const validator = 31 - Math.clz32(mask & -mask); + if (classValidators[validator](value)) { + return rules[index]; + } + } + } + } +} + +function joinClasses(inputs: ClassValue[]): string { + let result = ''; + for (const value of inputs) { + if (!value) { + continue; + } + + let joined = ''; + if (typeof value === 'string' || typeof value === 'number') { + joined = String(value); + } else if (Array.isArray(value)) { + joined = joinClasses(value); + } else if (typeof value === 'object') { + for (const key in value) { + if (value[key]) { + result += (result ? ' ' : '') + key; + } + } + } + if (joined) { + result += (result ? ' ' : '') + joined; + } + } + return result; +} + +function parseClassName(original: string) { + const modifiers: string[] = []; + let sortable: string[] = []; + let depth = 0; + let start = 0; + let slash = -1; + + for (let position = 0; position < original.length; position++) { + const character = original[position]; + if (depth === 0 && character === ':') { + const modifier = original.slice(start, position); + if (modifier.startsWith('[')) { + modifiers.push(...sortable.sort(), modifier); + sortable = []; + } else { + sortable.push(modifier); + } + start = position + 1; + } else if (depth === 0 && character === '/') { + slash = position; + } else if (character === '[') { + depth++; + } else if (character === ']') { + depth--; + } + } + + const important = original[start] === '!'; + if (important) { + // Strip v3's leading ! before slicing / so text-sm/6 remains a font size, not a color. + start++; + } + + let hasPostfix = slash > start; + let group = getClassGroup(original.slice(start, hasPostfix ? slash : undefined)); + if (group === undefined && hasPostfix) { + group = getClassGroup(original.slice(start)); + hasPostfix = false; + } + + modifiers.push(...sortable.sort()); + return { group, hasPostfix, scope: `${modifiers.join(':')}|${important ? '!' : ''}` }; +} + +function getClassToken(original: string): IClassToken | null { + // Arbitrary values often change on every call; retaining them costs more than reusing their group. + const cacheable = original.indexOf('[') === -1; + if (cacheable) { + const cached = tokens.get(original); + if (cached !== undefined) { + return cached; + } + } + + let group: number | string | undefined; + let scope = '|'; + let hasPostfix = false; + if (original.indexOf(':') === -1 && original.indexOf('/') === -1) { + const important = original[0] === '!'; + group = getClassGroup(important ? original.slice(1) : original); + scope = important ? '|!' : '|'; + } else { + ({ group, scope, hasPostfix } = parseClassName(original)); + } + + const token = group === undefined ? null : createClassToken(group, scope, hasPostfix); + if (cacheable) { + if (tokens.size >= 2048) { + tokens.delete(tokenKeys.next().value!); + } + tokens.set(original, token); + } + return token; +} + +function createClassToken(group: number | string, scope: string, hasPostfix: boolean): IClassToken { + const plain = scope === '|' || scope === '|!'; + const offset = scope === '|!' ? CLASS_GROUPS.length : 0; + const id = plain && typeof group === 'number' ? group + offset : scope + group; + const postfix = hasPostfix && typeof group === 'number' ? POSTFIX_CONFLICTS[group] : undefined; + const cached = typeof id === 'number' && !postfix ? plainTokens[id] : undefined; + if (cached) { + return cached; + } + + const conflicts = typeof group === 'number' + ? [...(CLASS_CONFLICTS[group] ?? []), ...(postfix ?? [])].map((conflict) => plain ? conflict + offset : scope + conflict) + : []; + const token = { id, conflicts }; + if (typeof id === 'number' && !postfix) { + plainTokens[id] = token; + } + return token; +} + +/** Joins conditional classes and resolves Tailwind CSS v3 conflicts for the univer- prefix. */ +export function clsx(...inputs: ClassValue[]): string { + const classList = inputs.length === 1 && typeof inputs[0] === 'string' ? inputs[0] : joinClasses(inputs); + const cached = cache.get(classList); + if (cached !== undefined) { + return cached; + } + + const classes = classList.trim().split(/\s+/); + const conflicts = new Set(); + let result = ''; + + for (let index = classes.length - 1; index >= 0; index--) { + const original = classes[index]; + const token = getClassToken(original); + if (token) { + if (conflicts.has(token.id)) { + continue; + } + conflicts.add(token.id); + for (const conflict of token.conflicts) { + conflicts.add(conflict); + } + } + + result = original + (result ? ` ${result}` : ''); + } + + if (cache.size >= 1000) { + cache.delete(cacheKeys.next().value!); + } + cache.set(classList, result); + return result; } diff --git a/packages/docs-drawing-ui/package.json b/packages/docs-drawing-ui/package.json index da146f7280..0075491fb2 100644 --- a/packages/docs-drawing-ui/package.json +++ b/packages/docs-drawing-ui/package.json @@ -93,6 +93,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/docs-drawing/package.json b/packages/docs-drawing/package.json index 886f41ff3b..935feef162 100644 --- a/packages/docs-drawing/package.json +++ b/packages/docs-drawing/package.json @@ -83,6 +83,6 @@ "@univerjs-infra/shared": "workspace:*", "@univerjs/engine-render": "workspace:*", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/docs-find-replace/package.json b/packages/docs-find-replace/package.json index 3c4502857f..006c455ca3 100644 --- a/packages/docs-find-replace/package.json +++ b/packages/docs-find-replace/package.json @@ -79,6 +79,6 @@ "react": "18.3.1", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/docs-hyper-link-ui/package.json b/packages/docs-hyper-link-ui/package.json index b7762e6911..fe9303970c 100644 --- a/packages/docs-hyper-link-ui/package.json +++ b/packages/docs-hyper-link-ui/package.json @@ -91,6 +91,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/docs-hyper-link/package.json b/packages/docs-hyper-link/package.json index 54c2db38a3..43fa3d7a1e 100644 --- a/packages/docs-hyper-link/package.json +++ b/packages/docs-hyper-link/package.json @@ -69,6 +69,6 @@ "devDependencies": { "@univerjs-infra/shared": "workspace:*", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/docs-quick-insert-ui/package.json b/packages/docs-quick-insert-ui/package.json index 6e14e8d94e..25d1d15d64 100644 --- a/packages/docs-quick-insert-ui/package.json +++ b/packages/docs-quick-insert-ui/package.json @@ -93,6 +93,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/docs-thread-comment-ui/package.json b/packages/docs-thread-comment-ui/package.json index c94e44da9d..63d909c83b 100644 --- a/packages/docs-thread-comment-ui/package.json +++ b/packages/docs-thread-comment-ui/package.json @@ -93,6 +93,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/docs-thread-comment/package.json b/packages/docs-thread-comment/package.json index 284bebe763..f6572cc7ac 100644 --- a/packages/docs-thread-comment/package.json +++ b/packages/docs-thread-comment/package.json @@ -82,6 +82,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.10" + "vitest": "^5.0.0" } } diff --git a/packages/docs-ui/package.json b/packages/docs-ui/package.json index 662faeac5b..def888f57b 100644 --- a/packages/docs-ui/package.json +++ b/packages/docs-ui/package.json @@ -103,6 +103,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/docs-ui/src/views/DocLayoutProgress.tsx b/packages/docs-ui/src/views/DocLayoutProgress.tsx index 537bc227d2..4daab5a80c 100644 --- a/packages/docs-ui/src/views/DocLayoutProgress.tsx +++ b/packages/docs-ui/src/views/DocLayoutProgress.tsx @@ -14,6 +14,7 @@ * limitations under the License. */ +import type { LocaleKey } from '../locale/types'; import { LocaleService } from '@univerjs/core'; import { useDependency, useObservable } from '@univerjs/ui'; import { DocLayoutProgressService } from '../services/doc-layout-progress.service'; @@ -26,7 +27,7 @@ export function DocLayoutProgress() { } const { progress } = progressState; - const label = localeService.t('docs-ui.layout.progress'); + const label = localeService.t('docs-ui.layout.progress'); return (
- {localeService.t('docs-ui.layout.recovering')} + {localeService.t('docs-ui.layout.recovering')}
); } diff --git a/packages/docs/package.json b/packages/docs/package.json index 2476167a1c..715fdaf60b 100644 --- a/packages/docs/package.json +++ b/packages/docs/package.json @@ -87,6 +87,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/drawing-ui/package.json b/packages/drawing-ui/package.json index adce38c330..2746036199 100644 --- a/packages/drawing-ui/package.json +++ b/packages/drawing-ui/package.json @@ -88,6 +88,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/drawing/package.json b/packages/drawing/package.json index bda5d35abf..fca91c8eb0 100644 --- a/packages/drawing/package.json +++ b/packages/drawing/package.json @@ -74,6 +74,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/engine-formula/package.json b/packages/engine-formula/package.json index 67a840c243..46ad374307 100644 --- a/packages/engine-formula/package.json +++ b/packages/engine-formula/package.json @@ -93,6 +93,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/engine-render/package.json b/packages/engine-render/package.json index 3526a9ccf2..abcfc98095 100644 --- a/packages/engine-render/package.json +++ b/packages/engine-render/package.json @@ -80,6 +80,6 @@ "rxjs": "^7.8.2", "tsdown": "^0.22.14", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/find-replace/package.json b/packages/find-replace/package.json index 17e75c584c..afaffd6cfa 100644 --- a/packages/find-replace/package.json +++ b/packages/find-replace/package.json @@ -87,6 +87,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/network/package.json b/packages/network/package.json index bd4650825a..bd9a814347 100644 --- a/packages/network/package.json +++ b/packages/network/package.json @@ -84,6 +84,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/protocol/package.json b/packages/protocol/package.json index 2cd90f04d5..17c6fb5d12 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -70,6 +70,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/rpc-node/package.json b/packages/rpc-node/package.json index 9a21d209b0..ba990b0047 100644 --- a/packages/rpc-node/package.json +++ b/packages/rpc-node/package.json @@ -74,6 +74,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/rpc/package.json b/packages/rpc/package.json index 246e005ef8..1069b9fe07 100644 --- a/packages/rpc/package.json +++ b/packages/rpc/package.json @@ -73,6 +73,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-conditional-formatting-ui/package.json b/packages/sheets-conditional-formatting-ui/package.json index fa507c3ab6..59a86d977c 100644 --- a/packages/sheets-conditional-formatting-ui/package.json +++ b/packages/sheets-conditional-formatting-ui/package.json @@ -93,6 +93,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-conditional-formatting/package.json b/packages/sheets-conditional-formatting/package.json index 4e0f82bce9..fb47d86bae 100644 --- a/packages/sheets-conditional-formatting/package.json +++ b/packages/sheets-conditional-formatting/package.json @@ -96,6 +96,6 @@ "@univerjs/sheets-formula": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-crosshair-highlight/package.json b/packages/sheets-crosshair-highlight/package.json index b49f870f23..a198d5f895 100644 --- a/packages/sheets-crosshair-highlight/package.json +++ b/packages/sheets-crosshair-highlight/package.json @@ -100,6 +100,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-data-validation-ui/package.json b/packages/sheets-data-validation-ui/package.json index e6592b94e0..b1d913d5ba 100644 --- a/packages/sheets-data-validation-ui/package.json +++ b/packages/sheets-data-validation-ui/package.json @@ -94,6 +94,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-data-validation/package.json b/packages/sheets-data-validation/package.json index 5ad42ad8f2..eadccb4c3d 100644 --- a/packages/sheets-data-validation/package.json +++ b/packages/sheets-data-validation/package.json @@ -95,6 +95,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-drawing-ui/package.json b/packages/sheets-drawing-ui/package.json index b1381e7058..8fd31bb65d 100644 --- a/packages/sheets-drawing-ui/package.json +++ b/packages/sheets-drawing-ui/package.json @@ -105,6 +105,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-drawing/package.json b/packages/sheets-drawing/package.json index 14e0f30b6b..1592885e3d 100644 --- a/packages/sheets-drawing/package.json +++ b/packages/sheets-drawing/package.json @@ -83,6 +83,6 @@ "devDependencies": { "@univerjs-infra/shared": "workspace:*", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-filter-ui/package.json b/packages/sheets-filter-ui/package.json index 5b415a14ef..a78a0a539e 100644 --- a/packages/sheets-filter-ui/package.json +++ b/packages/sheets-filter-ui/package.json @@ -91,6 +91,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-filter/package.json b/packages/sheets-filter/package.json index d97f188f4a..27cf710abc 100644 --- a/packages/sheets-filter/package.json +++ b/packages/sheets-filter/package.json @@ -94,6 +94,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-find-replace/package.json b/packages/sheets-find-replace/package.json index f42b71145e..4baf6abf4f 100644 --- a/packages/sheets-find-replace/package.json +++ b/packages/sheets-find-replace/package.json @@ -88,6 +88,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-formula-ui/package.json b/packages/sheets-formula-ui/package.json index 0dfcb4d80d..d1993feb7d 100644 --- a/packages/sheets-formula-ui/package.json +++ b/packages/sheets-formula-ui/package.json @@ -104,6 +104,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-formula/package.json b/packages/sheets-formula/package.json index d478897d1c..6a56042fef 100644 --- a/packages/sheets-formula/package.json +++ b/packages/sheets-formula/package.json @@ -95,6 +95,6 @@ "@univerjs/engine-render": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-hyper-link-ui/package.json b/packages/sheets-hyper-link-ui/package.json index d51cd8c010..77e949cb5e 100644 --- a/packages/sheets-hyper-link-ui/package.json +++ b/packages/sheets-hyper-link-ui/package.json @@ -106,6 +106,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-hyper-link/package.json b/packages/sheets-hyper-link/package.json index 0364fcadf2..69c6acd759 100644 --- a/packages/sheets-hyper-link/package.json +++ b/packages/sheets-hyper-link/package.json @@ -93,6 +93,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-note-ui/package.json b/packages/sheets-note-ui/package.json index ca064d448b..ff143f4f6b 100644 --- a/packages/sheets-note-ui/package.json +++ b/packages/sheets-note-ui/package.json @@ -89,6 +89,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-note/package.json b/packages/sheets-note/package.json index 64c1c81c9c..afeb69f581 100644 --- a/packages/sheets-note/package.json +++ b/packages/sheets-note/package.json @@ -88,6 +88,6 @@ "@univerjs/network": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-numfmt-ui/package.json b/packages/sheets-numfmt-ui/package.json index c7f20b8478..33785b0ee1 100644 --- a/packages/sheets-numfmt-ui/package.json +++ b/packages/sheets-numfmt-ui/package.json @@ -91,6 +91,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-numfmt/package.json b/packages/sheets-numfmt/package.json index 08c7067f85..24d1c8cf38 100644 --- a/packages/sheets-numfmt/package.json +++ b/packages/sheets-numfmt/package.json @@ -86,6 +86,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-sort-ui/package.json b/packages/sheets-sort-ui/package.json index 5312c931ac..220ac7da3a 100644 --- a/packages/sheets-sort-ui/package.json +++ b/packages/sheets-sort-ui/package.json @@ -91,6 +91,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-sort/package.json b/packages/sheets-sort/package.json index e0a13659d6..144c3b8ec6 100644 --- a/packages/sheets-sort/package.json +++ b/packages/sheets-sort/package.json @@ -82,6 +82,6 @@ "devDependencies": { "@univerjs-infra/shared": "workspace:*", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-table-ui/package.json b/packages/sheets-table-ui/package.json index f4b31c3a1c..3cb9412f39 100644 --- a/packages/sheets-table-ui/package.json +++ b/packages/sheets-table-ui/package.json @@ -94,6 +94,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-table/package.json b/packages/sheets-table/package.json index 2b731cf1c9..4e49a96e5f 100644 --- a/packages/sheets-table/package.json +++ b/packages/sheets-table/package.json @@ -94,6 +94,6 @@ "@univerjs/sheets-formula": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-thread-comment-ui/package.json b/packages/sheets-thread-comment-ui/package.json index 7149900588..238cdd0f95 100644 --- a/packages/sheets-thread-comment-ui/package.json +++ b/packages/sheets-thread-comment-ui/package.json @@ -93,6 +93,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-thread-comment/package.json b/packages/sheets-thread-comment/package.json index d68fc98947..c910724fdd 100644 --- a/packages/sheets-thread-comment/package.json +++ b/packages/sheets-thread-comment/package.json @@ -87,6 +87,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets-ui/package.json b/packages/sheets-ui/package.json index 1158e74815..cebc2ca371 100644 --- a/packages/sheets-ui/package.json +++ b/packages/sheets-ui/package.json @@ -105,6 +105,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/sheets/package.json b/packages/sheets/package.json index 67ba26e1ce..cf6d9a3542 100644 --- a/packages/sheets/package.json +++ b/packages/sheets/package.json @@ -95,6 +95,6 @@ "@univerjs/network": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/slides-ui/package.json b/packages/slides-ui/package.json index 6dd32498f0..1037abf669 100644 --- a/packages/slides-ui/package.json +++ b/packages/slides-ui/package.json @@ -91,6 +91,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/slides/package.json b/packages/slides/package.json index db056baca0..d194c07924 100644 --- a/packages/slides/package.json +++ b/packages/slides/package.json @@ -74,6 +74,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index 15d9353dbf..8601f69918 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -69,6 +69,6 @@ "devDependencies": { "@univerjs-infra/shared": "workspace:*", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/thread-comment-ui/package.json b/packages/thread-comment-ui/package.json index 3e8aff673d..8b3af152b8 100644 --- a/packages/thread-comment-ui/package.json +++ b/packages/thread-comment-ui/package.json @@ -89,6 +89,6 @@ "rxjs": "^7.8.2", "tailwindcss": "3.4.18", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/thread-comment/package.json b/packages/thread-comment/package.json index 4b27988445..e7378ca3c7 100644 --- a/packages/thread-comment/package.json +++ b/packages/thread-comment/package.json @@ -84,6 +84,6 @@ "@univerjs-infra/shared": "workspace:*", "rxjs": "^7.8.2", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/ui-adapter-vue3/package.json b/packages/ui-adapter-vue3/package.json index 474360c585..4abd96c788 100644 --- a/packages/ui-adapter-vue3/package.json +++ b/packages/ui-adapter-vue3/package.json @@ -73,7 +73,7 @@ "devDependencies": { "@univerjs-infra/shared": "workspace:*", "typescript": "^6.0.3", - "vitest": "^4.1.11", + "vitest": "^5.0.0", "vue": "^3.5.40" } } diff --git a/packages/ui-adapter-web-component/package.json b/packages/ui-adapter-web-component/package.json index c3c47a34ec..9f67b95f83 100644 --- a/packages/ui-adapter-web-component/package.json +++ b/packages/ui-adapter-web-component/package.json @@ -70,6 +70,6 @@ "devDependencies": { "@univerjs-infra/shared": "workspace:*", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/ui/package.json b/packages/ui/package.json index f5afd53e8d..e78ba193ac 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -104,6 +104,6 @@ "tailwindcss": "3.4.18", "tailwindcss-animate": "^1.0.7", "typescript": "^6.0.3", - "vitest": "^4.1.11" + "vitest": "^5.0.0" } } diff --git a/packages/ui/src/views/menu/mobile/MobileMenuDrawer.tsx b/packages/ui/src/views/menu/mobile/MobileMenuDrawer.tsx index 834420562b..efa298e24a 100644 --- a/packages/ui/src/views/menu/mobile/MobileMenuDrawer.tsx +++ b/packages/ui/src/views/menu/mobile/MobileMenuDrawer.tsx @@ -15,6 +15,7 @@ */ import type { ComponentProps } from 'react'; +import type { LocaleKey } from '../../../locale/types'; import type { IMenuSchema } from '../../../services/menu/menu-manager.service'; import type { MobileDrawerSnap } from '../../components/mobile-drawer/MobileDrawer'; import { LocaleService } from '@univerjs/core'; @@ -62,7 +63,7 @@ function MobileMenuDrawerContent(props: IMobileMenuDrawerProps) {