From e8fbcd83fd07b5d2df0abe020fc8e2481332c1b2 Mon Sep 17 00:00:00 2001 From: vector Date: Fri, 1 Apr 2022 14:14:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20add=20css=20method=20for=20?= =?UTF-8?q?dom=20(#1959)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + packages/x6-common/__tests__/dom/attr.test.ts | 6 ++ packages/x6-common/__tests__/dom/css.test.ts | 19 +++++ .../x6-common/__tests__/dom/prefix.test.ts | 2 +- .../x6-common/__tests__/dom/style.test.ts | 2 +- packages/x6-common/src/dom/css.ts | 80 +++++++++++++++++++ packages/x6-common/src/dom/main.ts | 1 + packages/x6-common/src/dom/prefix.ts | 2 +- packages/x6-common/src/types.ts | 2 + tsconfig.json | 1 - 10 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 packages/x6-common/__tests__/dom/css.test.ts create mode 100644 packages/x6-common/src/dom/css.ts diff --git a/.gitignore b/.gitignore index 3c8e1992fb3..f6ec38f73b3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ dist *.pem !mock-cert.pem tmp +test \ No newline at end of file diff --git a/packages/x6-common/__tests__/dom/attr.test.ts b/packages/x6-common/__tests__/dom/attr.test.ts index 0155aad6373..183cd888ad3 100644 --- a/packages/x6-common/__tests__/dom/attr.test.ts +++ b/packages/x6-common/__tests__/dom/attr.test.ts @@ -131,6 +131,12 @@ describe('Dom', () => { const { id, ...attrs } = vel.attr() expect(attrs).toEqual({ foo: 'test', bar: '100' }) }) + + it('should work on html element', () => { + const div = document.createElement('div') + Dom.attr(div, 'data-id', '12') + expect(Dom.attr(div, 'data-id')).toEqual('12') + }) }) }) }) diff --git a/packages/x6-common/__tests__/dom/css.test.ts b/packages/x6-common/__tests__/dom/css.test.ts new file mode 100644 index 00000000000..dbfd9bd6765 --- /dev/null +++ b/packages/x6-common/__tests__/dom/css.test.ts @@ -0,0 +1,19 @@ +import { Vector } from '../../src/vector' +import { Dom } from '../../src/dom' + +describe('Dom', () => { + describe('css', () => { + it('should set right style property for element', () => { + const vel = Vector.create('rect') + const node = vel.node as Element + + Dom.css(node, { + stroke: 'red', + userDrag: 'auto', + }) + + expect(Dom.css(node, 'stroke')).toEqual('red') + expect(Dom.css(node, 'webkitUserDrag')).toEqual('auto') + }) + }) +}) diff --git a/packages/x6-common/__tests__/dom/prefix.test.ts b/packages/x6-common/__tests__/dom/prefix.test.ts index a035534f428..06245051d51 100644 --- a/packages/x6-common/__tests__/dom/prefix.test.ts +++ b/packages/x6-common/__tests__/dom/prefix.test.ts @@ -3,7 +3,7 @@ import { Dom } from '../../src/dom' describe('Dom', () => { describe('#prefix', () => { it('should return prefixed name with compatibility name', () => { - expect(Dom.getVendorPrefixedName('userDrag')).toBe('WebkitUserDrag') + expect(Dom.getVendorPrefixedName('userDrag')).toBe('webkitUserDrag') }) }) }) diff --git a/packages/x6-common/__tests__/dom/style.test.ts b/packages/x6-common/__tests__/dom/style.test.ts index 1e78a9de5e0..62faa51f227 100644 --- a/packages/x6-common/__tests__/dom/style.test.ts +++ b/packages/x6-common/__tests__/dom/style.test.ts @@ -7,7 +7,7 @@ describe('Dom', () => { Dom.setPrefixedStyle(style, 'userDrag', 'true') expect(style).toEqual({ userDrag: 'true', - WebkitUserDrag: 'true', + webkitUserDrag: 'true', }) }) diff --git a/packages/x6-common/src/dom/css.ts b/packages/x6-common/src/dom/css.ts new file mode 100644 index 00000000000..3c23851623e --- /dev/null +++ b/packages/x6-common/src/dom/css.ts @@ -0,0 +1,80 @@ +import { getVendorPrefixedName } from './prefix' + +const numericProps: { [prop: string]: true | undefined } = { + animationIterationCount: true, + columnCount: true, + flexGrow: true, + flexShrink: true, + fontWeight: true, + gridArea: true, + gridColumn: true, + gridColumnEnd: true, + gridColumnStart: true, + gridRow: true, + gridRowEnd: true, + gridRowStart: true, + lineHeight: true, + opacity: true, + order: true, + orphans: true, + widows: true, + zIndex: true, +} + +export function isCSSVariable(prop: string): boolean { + return /^--/.test(prop) +} + +export function computeStyle( + elem: Element, + prop: string, + isVariable?: boolean, +) { + const style: any = window.getComputedStyle(elem, null) + return isVariable + ? style.getPropertyValue(prop) || undefined + : style[prop] || (elem as any).style[prop] +} + +function getSuffixedValue(prop: string, value: number | string) { + return !numericProps[prop] && typeof value === 'number' ? `${value}px` : value +} + +export function css(elem: Element, prop: string): string | undefined +export function css(elem: Element, prop: string, value: number | string): void +export function css(elem: Element, prop: Record): void +export function css( + elem: Element, + prop: string | Record, + value?: number | string, +) { + if (typeof prop === 'string') { + const isVariable = isCSSVariable(prop) + + if (!isVariable) { + prop = getVendorPrefixedName(prop)! // eslint-disable-line + } + + if (value === undefined) { + return computeStyle(elem, prop, isVariable) + } + + if (!isVariable) { + value = getSuffixedValue(prop, value) // eslint-disable-line + } + + const style = (elem as any).style + if (isVariable) { + style.setProperty(prop, value) + } else { + style[prop] = value + } + + return + } + + // eslint-disable-next-line + for (const key in prop) { + css(elem, key, prop[key]) + } +} diff --git a/packages/x6-common/src/dom/main.ts b/packages/x6-common/src/dom/main.ts index 1cf873b1e62..56d88eee304 100644 --- a/packages/x6-common/src/dom/main.ts +++ b/packages/x6-common/src/dom/main.ts @@ -5,6 +5,7 @@ export * from './class' export * from './style' export * from './prefix' export * from './selection' +export * from './css' // svg // --- diff --git a/packages/x6-common/src/dom/prefix.ts b/packages/x6-common/src/dom/prefix.ts index d0296ca3144..9c46c64292c 100644 --- a/packages/x6-common/src/dom/prefix.ts +++ b/packages/x6-common/src/dom/prefix.ts @@ -4,7 +4,7 @@ function camelize(str: string) { } const memoized: { [key: string]: string | null } = {} -const prefixes = ['Webkit', 'ms', 'Moz', 'O'] +const prefixes = ['webkit', 'ms', 'moz', 'o'] const testStyle = document ? document.createElement('div').style : {} function getWithPrefix(name: string) { diff --git a/packages/x6-common/src/types.ts b/packages/x6-common/src/types.ts index 81ebc84d7af..26a90467d03 100644 --- a/packages/x6-common/src/types.ts +++ b/packages/x6-common/src/types.ts @@ -20,6 +20,8 @@ export interface Size { width: number height: number } + +export type Nilable = T | null | undefined export interface KeyValue { [key: string]: T } diff --git a/tsconfig.json b/tsconfig.json index 096a58b8ec5..0db9ecf3790 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,6 @@ "strictNullChecks": true, "resolveJsonModule": true, "experimentalDecorators": true, - "importsNotUsedAsValues": "error", "jsx": "react", "target": "es5", "lib": ["DOM", "ES2020"]