From 45eacb85edfa201d57ce4269c161a513a83283c1 Mon Sep 17 00:00:00 2001 From: Brandon Scott Date: Thu, 24 Nov 2022 14:54:21 -0500 Subject: [PATCH 1/4] Break out SelectorMap type, add support for recursive/nested selectors and add tests --- package.json | 2 +- src/index.tsx | 3 +- src/types/box-types.ts | 8 ++--- src/types/enhancers.ts | 8 +++-- test/enhance-props.ts | 70 ++++++++++++++++++++++++++++++++++++++++++ tools/story.tsx | 16 ++++++++++ 6 files changed, 97 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 5c955c8..ecc5d33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ui-box", - "version": "5.3.0", + "version": "5.3.0-dev", "description": "Blazing Fast React UI Primitive", "contributors": [ "Jeroen Ransijn (https://twitter.com/jeroen_ransijn)", diff --git a/src/index.tsx b/src/index.tsx index cd6677c..90ab9f0 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -7,7 +7,8 @@ export { default as splitProps } from './utils/split-props' export { default as splitBoxProps } from './utils/split-box-props' export { setClassNamePrefix } from './get-class-name' export { configureSafeHref } from './utils/safeHref' -export { BoxProps, BoxOwnProps, EnhancerProps, PropsOf, PolymorphicBoxProps, BoxComponent } from './types/box-types' +export { CssProps, BoxCssProps, EnhancerProps, SelectorMap } from './types/enhancers' +export { BoxProps, BoxOwnProps, PropsOf, PolymorphicBoxProps, BoxComponent } from './types/box-types' export { KeyframesPercentageKey, KeyframesPositionalKey, diff --git a/src/types/box-types.ts b/src/types/box-types.ts index 4fe7b1e..a1f9304 100644 --- a/src/types/box-types.ts +++ b/src/types/box-types.ts @@ -1,8 +1,6 @@ import React from 'react' import { EnhancerProps } from './enhancers' -export { EnhancerProps } - /** * @template T Object * @template K Union of keys (not necessarily present in T) @@ -48,6 +46,6 @@ export type PolymorphicBoxProps< /** * Convenience type for defining your own components that extend Box and pass-through props */ -export type BoxComponent

= < - E extends React.ElementType = D ->(props: PolymorphicBoxProps) => JSX.Element +export type BoxComponent

= ( + props: PolymorphicBoxProps +) => JSX.Element diff --git a/src/types/enhancers.ts b/src/types/enhancers.ts index 143c526..9bfc2ea 100644 --- a/src/types/enhancers.ts +++ b/src/types/enhancers.ts @@ -193,9 +193,11 @@ export type EnhancerProps = BoxCssProps & { * Hello world * */ - selectors?: { - [selector: string]: BoxCssProps - } + selectors?: SelectorMap +} + +export type SelectorMap = { + [selector: string]: BoxCssProps | SelectorMap } export type PropEnhancerValueType = string | number diff --git a/test/enhance-props.ts b/test/enhance-props.ts index 5adbab1..da0d432 100644 --- a/test/enhance-props.ts +++ b/test/enhance-props.ts @@ -85,3 +85,73 @@ test.serial('preserves style prop', t => { t.deepEqual(enhancedProps, expected) }) + +test.serial('converts styles in selectors to class name', t => { + const { className, enhancedProps } = enhanceProps({ + selectors: { + '&:hover': { + backgroundColor: 'blue' + } + } + }) + + t.deepEqual(className, 'ub-bg-clr_nfznl2') + t.deepEqual(enhancedProps, {}) +}) + +test.serial('injects selector styles', t => { + enhanceProps({ + selectors: { + '&:hover': { + backgroundColor: 'blue' + } + } + }) + + t.deepEqual( + styles.getAll(), + ` +.ub-bg-clr_nfznl2:hover { + background-color: blue; +}` + ) +}) + +test.serial('converts styles in nested selectors to class name', t => { + const { className, enhancedProps } = enhanceProps({ + selectors: { + '&[data-active]': { + selectors: { + '&:hover': { + backgroundColor: 'blue' + } + } + } + } + }) + + t.deepEqual(className, 'ub-bg-clr_nfznl2') + t.deepEqual(enhancedProps, {}) +}) + +test.serial('injects nested selector styles', t => { + enhanceProps({ + selectors: { + '&[data-active]': { + selectors: { + '&:hover': { + backgroundColor: 'blue' + } + } + } + } + }) + + t.deepEqual( + styles.getAll(), + ` +.ub-bg-clr_nfznl2[data-active]:hover { + background-color: blue; +}` + ) +}) diff --git a/tools/story.tsx b/tools/story.tsx index 18c038e..12db7aa 100644 --- a/tools/story.tsx +++ b/tools/story.tsx @@ -266,6 +266,22 @@ storiesOf('Box', module) + Nested selector - blue background when data-active=true, red background on hover + ) }) From 0c1588e42b6515cd56a607396059c08b0d29c9e7 Mon Sep 17 00:00:00 2001 From: Brandon Scott Date: Sat, 26 Nov 2022 11:56:26 -0500 Subject: [PATCH 2/4] Revert package.json change --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ecc5d33..5c955c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ui-box", - "version": "5.3.0-dev", + "version": "5.3.0", "description": "Blazing Fast React UI Primitive", "contributors": [ "Jeroen Ransijn (https://twitter.com/jeroen_ransijn)", From 6f26a31b406c14c3f08b66ca8a20299734cc5488 Mon Sep 17 00:00:00 2001 From: Brandon Scott Date: Sat, 26 Nov 2022 12:26:38 -0500 Subject: [PATCH 3/4] Tweak logic in enhanceProps function to allow direct nesting of selector keys to match SelectorMap typing expectation --- src/enhance-props.ts | 2 +- test/enhance-props.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/enhance-props.ts b/src/enhance-props.ts index 4e775c5..51c04da 100644 --- a/src/enhance-props.ts +++ b/src/enhance-props.ts @@ -27,7 +27,7 @@ export default function enhanceProps( let className: string = props.className || '' for (const [property, value] of propsMap) { - const isSelectorOrChildProp = property === SELECTORS_PROP || parentProperty === SELECTORS_PROP + const isSelectorOrChildProp = property === SELECTORS_PROP || parentProperty.length > 0 // Only attempt to process objects for the `selectors` prop or the individual selectors below it if (isObject(value) && isSelectorOrChildProp) { const prop = property === 'selectors' ? '' : property diff --git a/test/enhance-props.ts b/test/enhance-props.ts index da0d432..faee588 100644 --- a/test/enhance-props.ts +++ b/test/enhance-props.ts @@ -134,6 +134,21 @@ test.serial('converts styles in nested selectors to class name', t => { t.deepEqual(enhancedProps, {}) }) +test.serial("selectors can be nested without 'selectors' key", t => { + const { className, enhancedProps } = enhanceProps({ + selectors: { + '&[data-active]': { + '&:hover': { + backgroundColor: 'blue' + } + } + } + }) + + t.deepEqual(className, 'ub-bg-clr_nfznl2') + t.deepEqual(enhancedProps, {}) +}) + test.serial('injects nested selector styles', t => { enhanceProps({ selectors: { From 5c701717a92d4443cde6591914c8ccc1974bb6fd Mon Sep 17 00:00:00 2001 From: Brandon Scott Date: Sat, 26 Nov 2022 12:32:25 -0500 Subject: [PATCH 4/4] Update Box story to reflect simpler API without selectors object nest --- tools/story.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/story.tsx b/tools/story.tsx index 12db7aa..6ddbeea 100644 --- a/tools/story.tsx +++ b/tools/story.tsx @@ -274,10 +274,8 @@ storiesOf('Box', module) selectors={{ '[data-active=true]': { backgroundColor: 'blue', - selectors: { - '&:hover': { - backgroundColor: 'red' - } + '&:hover': { + backgroundColor: 'red' } } }}