diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index ca9a307dd..923908b49 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -306,3 +306,8 @@ export const initDirectivesForSSR: () => void = __SSR__ export * from '@vue/runtime-core' export * from './jsx' + +/** + * @internal + */ +export { type Style, setStyle } from './modules/style' diff --git a/packages/runtime-dom/src/modules/style.ts b/packages/runtime-dom/src/modules/style.ts index 383628a6a..d07f8b9a9 100644 --- a/packages/runtime-dom/src/modules/style.ts +++ b/packages/runtime-dom/src/modules/style.ts @@ -1,5 +1,5 @@ -import { capitalize, hyphenate, isArray, isString } from '@vue/shared' -import { camelize, warn } from '@vue/runtime-core' +import { camelize, capitalize, hyphenate, isArray, isString } from '@vue/shared' +import { warn } from '@vue/runtime-core' import { type VShowElement, vShowHidden, @@ -7,7 +7,7 @@ import { } from '../directives/vShow' import { CSS_VAR_TEXT } from '../helpers/useCssVars' -type Style = string | Record | null +export type Style = string | Record | null const displayRE = /(^|;)\s*display\s*:/ @@ -20,14 +20,14 @@ export function patchStyle(el: Element, prev: Style, next: Style): void { if (!isString(prev)) { for (const key in prev) { if (next[key] == null) { - setStyle(style, key, '') + setStyle(style, key, '', warn) } } } else { for (const prevStyle of prev.split(';')) { const key = prevStyle.slice(0, prevStyle.indexOf(':')).trim() if (next[key] == null) { - setStyle(style, key, '') + setStyle(style, key, '', warn) } } } @@ -36,7 +36,7 @@ export function patchStyle(el: Element, prev: Style, next: Style): void { if (key === 'display') { hasControlledDisplay = true } - setStyle(style, key, next[key]) + setStyle(style, key, next[key], warn) } } else { if (isCssString) { @@ -67,13 +67,14 @@ export function patchStyle(el: Element, prev: Style, next: Style): void { const semicolonRE = /[^\\];\s*$/ const importantRE = /\s*!important$/ -function setStyle( +export function setStyle( style: CSSStyleDeclaration, name: string, val: string | string[], -) { + warn: (msg: string, ...args: any[]) => void, +): void { if (isArray(val)) { - val.forEach(v => setStyle(style, name, v)) + val.forEach(v => setStyle(style, name, v, warn)) } else { if (val == null) val = '' if (__DEV__) { diff --git a/packages/runtime-vapor/src/dom/style.ts b/packages/runtime-vapor/src/dom/style.ts index 5ee233a0c..06deafa4c 100644 --- a/packages/runtime-vapor/src/dom/style.ts +++ b/packages/runtime-vapor/src/dom/style.ts @@ -1,11 +1,5 @@ -import { - camelize, - capitalize, - hyphenate, - isArray, - isString, - normalizeStyle, -} from '@vue/shared' +import { isString, normalizeStyle } from '@vue/shared' +import { type Style, setStyle as setStyleValue } from '@vue/runtime-dom' import { warn } from '../warning' import { recordPropMetadata } from '../componentMetadata' import { mergeInheritAttr } from './prop' @@ -19,10 +13,6 @@ export function setStyle(el: HTMLElement, value: any, root?: boolean): void { patchStyle(el, prev, value) } -// TODO copied from packages/runtime-dom/src/modules/style.ts - -type Style = string | Record | null - function patchStyle(el: Element, prev: Style, next: Style) { const style = (el as HTMLElement).style const isCssString = isString(next) @@ -30,13 +20,13 @@ function patchStyle(el: Element, prev: Style, next: Style) { if (prev && !isString(prev)) { for (const key in prev) { if (next[key] == null) { - setStyleValue(style, key, '') + setStyleValue(style, key, '', warn) } } } for (const key in next) { - setStyleValue(style, key, next[key]) + setStyleValue(style, key, next[key], warn) } } else { if (isCssString) { @@ -49,63 +39,3 @@ function patchStyle(el: Element, prev: Style, next: Style) { } } } - -const semicolonRE = /[^\\];\s*$/ -const importantRE = /\s*!important$/ - -function setStyleValue( - style: CSSStyleDeclaration, - name: string, - val: string | string[], -) { - if (isArray(val)) { - val.forEach(v => setStyleValue(style, name, v)) - } else { - if (val == null) val = '' - if (__DEV__) { - if (semicolonRE.test(val)) { - warn( - `Unexpected semicolon at the end of '${name}' style value: '${val}'`, - ) - } - } - if (name.startsWith('--')) { - // custom property definition - style.setProperty(name, val) - } else { - const prefixed = autoPrefix(style, name) - if (importantRE.test(val)) { - // !important - style.setProperty( - hyphenate(prefixed), - val.replace(importantRE, ''), - 'important', - ) - } else { - style[prefixed as any] = val - } - } - } -} - -const prefixes = ['Webkit', 'Moz', 'ms'] -const prefixCache: Record = {} - -function autoPrefix(style: CSSStyleDeclaration, rawName: string): string { - const cached = prefixCache[rawName] - if (cached) { - return cached - } - let name = camelize(rawName) - if (name !== 'filter' && name in style) { - return (prefixCache[rawName] = name) - } - name = capitalize(name) - for (let i = 0; i < prefixes.length; i++) { - const prefixed = prefixes[i] + name - if (prefixed in style) { - return (prefixCache[rawName] = prefixed) - } - } - return rawName -}