diff --git a/.changeset/large-poems-deny.md b/.changeset/large-poems-deny.md new file mode 100644 index 00000000..c11ae6b7 --- /dev/null +++ b/.changeset/large-poems-deny.md @@ -0,0 +1,6 @@ +--- +"@devup-ui/react": patch +"@devup-ui/wasm": patch +--- + +Support nested selector diff --git a/libs/extractor/src/lib.rs b/libs/extractor/src/lib.rs index 9bd42945..f9aa7ad3 100644 --- a/libs/extractor/src/lib.rs +++ b/libs/extractor/src/lib.rs @@ -1353,6 +1353,170 @@ import clsx from 'clsx' )); } + #[test] + #[serial] + fn extract_nested_selector() { + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap() + )); + } + #[test] #[serial] fn extract_conditional_selector() { @@ -2802,6 +2966,37 @@ import {Button} from '@devup/ui' )); } + #[test] + #[serial] + fn nested_theme_props() { + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.jsx", + r#"import {Box} from '@devup-ui/core' + + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_file: None + } + ) + .unwrap() + )); + } + #[test] #[serial] fn template_literal_props() { diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-2.snap b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-2.snap new file mode 100644 index 00000000..32839d06 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-2.snap @@ -0,0 +1,22 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "color", + value: "blue", + level: 0, + selector: Some( + Selector( + "&:hover::placeholder, &:hover:active", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-3.snap b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-3.snap new file mode 100644 index 00000000..e592a8ae --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-3.snap @@ -0,0 +1,35 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "color", + value: "blue", + level: 0, + selector: Some( + Selector( + "&:hover::placeholder, &:hover:active", + ), + ), + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "color", + value: "red", + level: 0, + selector: Some( + Selector( + "&:hover::placeholder", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-4.snap b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-4.snap new file mode 100644 index 00000000..4aea7d29 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-4.snap @@ -0,0 +1,22 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "color", + value: "red", + level: 0, + selector: Some( + Selector( + "&:hover::placeholder:active", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-5.snap b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-5.snap new file mode 100644 index 00000000..85af7854 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-5.snap @@ -0,0 +1,22 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "color", + value: "red", + level: 0, + selector: Some( + Selector( + "&::placeholder:active", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-6.snap b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-6.snap new file mode 100644 index 00000000..7522cf8c --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-6.snap @@ -0,0 +1,22 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "color", + value: "red", + level: 0, + selector: Some( + Selector( + "&::placeholder:active:hover", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-7.snap b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-7.snap new file mode 100644 index 00000000..dbff2f26 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector-7.snap @@ -0,0 +1,35 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "color", + value: "blue", + level: 0, + selector: Some( + Selector( + "&::placeholder:active:hover", + ), + ), + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "color", + value: "red", + level: 0, + selector: Some( + Selector( + "&::placeholder:active", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector.snap b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector.snap new file mode 100644 index 00000000..19ce0505 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_nested_selector.snap @@ -0,0 +1,22 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "color", + value: "red", + level: 0, + selector: Some( + Selector( + "&:hover::placeholder", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__nested_theme_props.snap b/libs/extractor/src/snapshots/extractor__tests__nested_theme_props.snap new file mode 100644 index 00000000..186162f1 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__nested_theme_props.snap @@ -0,0 +1,48 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.jsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "color", + value: "blue", + level: 0, + selector: Some( + Selector( + ":root[data-theme=dark] &:active", + ), + ), + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "color", + value: "green", + level: 0, + selector: Some( + Selector( + ":root[data-theme=dark] &:active::placeholder", + ), + ), + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "color", + value: "red", + level: 0, + selector: Some( + Selector( + ":root[data-theme=dark] &:hover", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n
;\n", +} diff --git a/libs/extractor/src/style_extractor.rs b/libs/extractor/src/style_extractor.rs index e3964609..82e3241c 100644 --- a/libs/extractor/src/style_extractor.rs +++ b/libs/extractor/src/style_extractor.rs @@ -273,11 +273,7 @@ pub fn extract_style_from_expression<'a>( level, Some( &if let Some(selector) = selector { - format!( - "{}{}", - selector.to_string().split("&").collect::>()[0], - name - ) + name.replace("&", &selector.to_string()) } else { name } diff --git a/packages/react/src/types/props/index.ts b/packages/react/src/types/props/index.ts index d3b03cf6..760f2f82 100644 --- a/packages/react/src/types/props/index.ts +++ b/packages/react/src/types/props/index.ts @@ -62,12 +62,12 @@ export interface DevupCommonProps DevupUiTransitionProps, DevupUiUiProps, DevupUiViewTransitionProps, + DevupSelectorProps, + DevupThemeSelectorProps, DevupUiSvgProps {} export interface DevupProps - extends DevupCommonProps, - DevupSelectorProps, - DevupThemeSelectorProps { + extends DevupCommonProps { as?: T styleVars?: Record }