UUI Component Util support data attributes

This commit is contained in:
ShinCurry
2020-08-14 16:55:28 +08:00
parent 1482496711
commit 9428b95d39
3 changed files with 104 additions and 2 deletions

View File

@@ -8,7 +8,7 @@
import React from 'react';
import { mapValues, pick, isString, omit, merge, clone, uniq, isEmpty } from 'lodash';
import { mapValues, pick, isString, omit, merge, clone, uniq, isEmpty, chain } from 'lodash';
import classNames from 'classnames';
import { mergeRefs } from '../utils/mergeRefs';
@@ -32,10 +32,16 @@ export interface NodeCustomizeChildrenProps {
extendChildrenBefore?: React.ReactNode;
extendChildrenAfter?: React.ReactNode;
}
export interface NodeCustomizeDataAttributesProps {
dataAttributes?: {
[key: string]: any;
};
}
export type NodeCustomizeProps =
& NodeCustomizeClassNameProps
& NodeCustomizeStyleProps
& NodeCustomizeChildrenProps
& NodeCustomizeDataAttributesProps
& React.RefAttributes<any>
// ---------------------------------------------------------------
@@ -88,6 +94,18 @@ function IntrinsicNode<T extends keyof JSX.IntrinsicElements, N extends string>(
})
return isEmpty(data) ? undefined : data
})()
const dataAttributes = (() => {
if (!customizeProps.customize?.dataAttributes) return {}
/**
* @reference https://www.w3.org/TR/2008/REC-xml-20081126/#NT-Name
* TODO: // fix regex for supporting unicode
*/
const validDataAttributesCharactersRegex = /^([A-Za-z0-9-])*$/
return chain(customizeProps.customize.dataAttributes)
.pickBy((v, k) => validDataAttributesCharactersRegex.test(k))
.mapKeys((v, k) => `data-${k}`)
.value()
})()
const children = (() => {
const noChildren = ['input', 'textarea', 'hr'].indexOf(tagName) !== -1
const isSelectOption = tagName === 'option'
@@ -150,6 +168,7 @@ function IntrinsicNode<T extends keyof JSX.IntrinsicElements, N extends string>(
return React.createElement(tagName, {
...omit(_props, 'children', 'ref', 'className', 'style'),
...mergedCallbackFunctions,
...dataAttributes,
ref,
className, style,
}, children)
@@ -242,6 +261,11 @@ export type UUIConvenienceProps = {
* @default none
*/
style?: React.CSSProperties;
/**
* React native support data-* attributes type,
* dont need to redeclare again convenience data attributes.
*/
}
export type UUIComponentProps<P, X extends { [key in string]?: keyof IntrinsicNodeT | FunctionComponentNodeT | ClassComponentNodeT }> = P & UUIConvenienceProps & UUIComponentCustomizeProps<X>
export type UUIFunctionComponentProps<T extends (...args: any) => any> = Parameters<T>[0]
@@ -369,7 +393,16 @@ function compileProps(props: any, options: any, ref: any): any {
) {
const rootCustomizeProps: any = (compiledProps.customize as any)['Root'] || {};
if (compiledProps.className) rootCustomizeProps.extendClassName = classNames(compiledProps.className, rootCustomizeProps.extendClassName);
if (compiledProps.style) rootCustomizeProps.extendStyle = Object.assign(compiledProps.style, rootCustomizeProps.extendStyle) as any;
if (compiledProps.style) rootCustomizeProps.extendStyle = Object.assign(compiledProps.style, rootCustomizeProps.extendStyle);
const dataAttributes = chain(compiledProps)
.pickBy((v, k) => k.startsWith('data-'))
.mapKeys((v, k) => k.replace('data-', ''))
.value();
if (!isEmpty(dataAttributes)) {
rootCustomizeProps.dataAttributes = Object.assign(dataAttributes, rootCustomizeProps.dataAttributes);
}
(compiledProps.customize as any)['Root'] = rootCustomizeProps;
}
compiledProps.ref = ref

View File

@@ -1,5 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`UUIComponent [dataAttributes] 1`] = `
<div
className="UUI-UUITestComponent-Root"
data-id="thisisamockid"
data-nativedata="nativedata"
>
<div
className="UUI-UUITestComponent-Node1"
data-abc-xyz="abcxyz"
/>
<div
className="UUI-UUITestComponent-Node2"
/>
</div>
`;
exports[`UUIComponent [special IntrinsicNodes children] 1`] = `
<div
className="UUI-UUITestComponent-Root"

View File

@@ -501,4 +501,57 @@ it('UUIComponent [refs]', () => {
expect(ref1.current).toBe(ref2.current);
expect(ref3.current).toBe(ref4.current);
})
/**
* UUI Component dataAttributes
*
* 测试 props.customize[Node].dataAttributes 是否被正确插入 DOM
*/
it('UUIComponent [dataAttributes]', () => {
const UUITestComponent = UUI.FunctionComponent({
name: 'UUITestComponent',
nodes: {
Root: 'div',
Node1: 'div',
Node2: 'div',
}
}, (props: {}, nodes) => {
const { Root, Node1, Node2 } = nodes
return (
<Root>
<Node1 />
<Node2 />
</Root>
)
})
const tree = renderer
.create(
<UUITestComponent
data-nativedata="nativedata"
customize={{
Root: {
dataAttributes: {
id: "thisisamockid",
}
},
Node1: {
dataAttributes: {
"abc-xyz": "abcxyz",
// TODO: fix unicode support
// "测试UNICODE": "测试 Unicode",
"test-@invalid-name": "invalid attribute name willnot inject into dom",
}
},
Node2: {
// keep empty
},
}}
/>
)
.toJSON();
expect(tree).toMatchSnapshot();
})