diff --git a/.changeset/wacky-snails-show.md b/.changeset/wacky-snails-show.md new file mode 100644 index 00000000..1fdd1750 --- /dev/null +++ b/.changeset/wacky-snails-show.md @@ -0,0 +1,6 @@ +--- +'@devup-ui/wasm': patch +'@devup-ui/react': patch +--- + +Support selector with params diff --git a/Cargo.lock b/Cargo.lock index 0b6be0cd..03d3d50b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,9 +86,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.41" +version = "1.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9fe6cdbb24b6ade63616c0a0688e45bb56732262c158df3c0c4bea4ca47cb7" +checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2" dependencies = [ "find-msvc-tools", "shlex", @@ -175,7 +175,7 @@ dependencies = [ "encode_unicode", "libc", "once_cell", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -521,9 +521,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -1476,9 +1476,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", @@ -1487,25 +1487,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -1516,9 +1502,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1526,31 +1512,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-bindgen-test" -version = "0.3.54" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e381134e148c1062f965a42ed1f5ee933eef2927c3f70d1812158f711d39865" +checksum = "bfc379bfb624eb59050b509c13e77b4eb53150c350db69628141abce842f2373" dependencies = [ "js-sys", "minicov", @@ -1561,9 +1547,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.54" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b673bca3298fe582aeef8352330ecbad91849f85090805582400850f8270a2e8" +checksum = "085b2df989e1e6f9620c1311df6c996e83fe16f57792b272ce1e024ac16a90f1" dependencies = [ "proc-macro2", "quote", @@ -1572,9 +1558,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", @@ -1586,7 +1572,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -1604,15 +1590,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-targets" version = "0.52.6" diff --git a/bindings/devup-ui-wasm/Cargo.toml b/bindings/devup-ui-wasm/Cargo.toml index 179d3f84..e05d29f8 100644 --- a/bindings/devup-ui-wasm/Cargo.toml +++ b/bindings/devup-ui-wasm/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["cdylib", "rlib"] default = ["console_error_panic_hook"] [dependencies] -wasm-bindgen = "0.2.104" +wasm-bindgen = "0.2.105" extractor = { path = "../../libs/extractor" } sheet = { path = "../../libs/sheet" } css = { path = "../../libs/css" } @@ -26,13 +26,13 @@ css = { path = "../../libs/css" } # code size when deploying. console_error_panic_hook = { version = "0.1.7", optional = true } once_cell = "1.21.3" -js-sys = "0.3.81" +js-sys = "0.3.82" serde_json = "1.0.145" serde-wasm-bindgen = "0.6.5" bimap = { version = "0.6.3", features = ["serde"] } [dev-dependencies] -wasm-bindgen-test = "0.3.54" +wasm-bindgen-test = "0.3.55" serial_test = "3.2.0" insta = "1.43.2" rstest = "0.26.1" diff --git a/libs/css/src/lib.rs b/libs/css/src/lib.rs index 465b602f..acdbeaef 100644 --- a/libs/css/src/lib.rs +++ b/libs/css/src/lib.rs @@ -68,6 +68,19 @@ pub fn disassemble_property(property: &str) -> Vec { }) } +pub fn add_selector_params(selector: StyleSelector, params: &str) -> StyleSelector { + match selector { + StyleSelector::Selector(value) => StyleSelector::Selector(format!("{}({})", value, params)), + StyleSelector::Global(value, file) => { + StyleSelector::Global(format!("{}({})", value, params), file) + } + StyleSelector::Media { query, selector } => StyleSelector::Media { + query: query.to_string(), + selector: selector.map(|s| format!("{}({})", s, params)), + }, + } +} + pub fn get_enum_property_value(property: &str, value: &str) -> Option> { if let Some(map) = GLOBAL_ENUM_STYLE_PROPERTY.get(property) { if let Some(map) = map.get(value) { @@ -677,4 +690,32 @@ mod tests { assert_eq!(keyframes_to_keyframes_name("spin", None), "k-spin"); assert_eq!(keyframes_to_keyframes_name("spin1", None), "k-spin1"); } + + #[test] + fn test_add_selector_params() { + assert_eq!( + add_selector_params(StyleSelector::Selector("hover:is".to_string()), "test"), + StyleSelector::Selector("hover:is(test)".to_string()) + ); + assert_eq!( + add_selector_params( + StyleSelector::Global("&:is".to_string(), "file.ts".to_string()), + "test" + ), + StyleSelector::Global("&:is(test)".to_string(), "file.ts".to_string()) + ); + assert_eq!( + add_selector_params( + StyleSelector::Media { + query: "print".to_string(), + selector: Some("&:is".to_string()) + }, + "test" + ), + StyleSelector::Media { + query: "print".to_string(), + selector: Some("&:is(test)".to_string()) + } + ); + } } diff --git a/libs/extractor/src/extractor/extract_global_style_from_expression.rs b/libs/extractor/src/extractor/extract_global_style_from_expression.rs index b1988c38..70d8498e 100644 --- a/libs/extractor/src/extractor/extract_global_style_from_expression.rs +++ b/libs/extractor/src/extractor/extract_global_style_from_expression.rs @@ -10,7 +10,7 @@ use crate::{ extractor::{ GlobalExtractResult, extract_style_from_expression::extract_style_from_expression, }, - utils::get_string_by_literal_expression, + utils::{get_string_by_literal_expression, get_string_by_property_key}, }; use css::{ disassemble_property, @@ -19,7 +19,7 @@ use css::{ }; use oxc_ast::{ AstBuilder, - ast::{ArrayExpressionElement, Expression, ObjectPropertyKind, PropertyKey}, + ast::{ArrayExpressionElement, Expression, ObjectPropertyKind}, }; pub fn extract_global_style_from_expression<'a>( @@ -33,20 +33,7 @@ pub fn extract_global_style_from_expression<'a>( for p in obj.properties.iter_mut() { match p { ObjectPropertyKind::ObjectProperty(o) => { - if let Some(name) = if let PropertyKey::StaticIdentifier(ident) = &o.key { - Some(ident.name.to_string()) - } else if let PropertyKey::StringLiteral(s) = &o.key { - Some(s.value.to_string()) - } else if let PropertyKey::TemplateLiteral(t) = &o.key { - Some( - t.quasis - .iter() - .map(|q| q.value.raw.as_str()) - .collect::(), - ) - } else { - None - } { + if let Some(name) = get_string_by_property_key(&o.key) { if name == "imports" { if let Expression::ArrayExpression(arr) = &o.value { for p in arr.elements.iter() { @@ -108,11 +95,11 @@ pub fn extract_global_style_from_expression<'a>( .iter() .filter_map(|p| { if let ObjectPropertyKind::ObjectProperty(o) = p - && let PropertyKey::StaticIdentifier(ident) = &o.key + && let Some(property_name) = get_string_by_property_key(&o.key) && let Some(s) = get_string_by_literal_expression(&o.value) { Some( - disassemble_property(&ident.name) + disassemble_property(&property_name) .iter() .map(|p| { let v = if check_multi_css_optimize(p) { optimize_mutli_css_value(&s) } else { s.clone() }; diff --git a/libs/extractor/src/extractor/extract_keyframes_from_expression.rs b/libs/extractor/src/extractor/extract_keyframes_from_expression.rs index fd1f4766..4d8f72d4 100644 --- a/libs/extractor/src/extractor/extract_keyframes_from_expression.rs +++ b/libs/extractor/src/extractor/extract_keyframes_from_expression.rs @@ -5,10 +5,11 @@ use crate::{ ExtractResult, KeyframesExtractResult, extract_style_from_expression::extract_style_from_expression, }, + utils::get_string_by_property_key, }; use oxc_ast::{ AstBuilder, - ast::{Expression, ObjectPropertyKind, PropertyKey}, + ast::{Expression, ObjectPropertyKind}, }; pub fn extract_keyframes_from_expression<'a>( @@ -20,22 +21,7 @@ pub fn extract_keyframes_from_expression<'a>( if let Expression::ObjectExpression(obj) = expression { for p in obj.properties.iter_mut() { if let ObjectPropertyKind::ObjectProperty(o) = p - && let Some(name) = if let PropertyKey::StaticIdentifier(ident) = &o.key { - Some(ident.name.to_string()) - } else if let PropertyKey::StringLiteral(s) = &o.key { - Some(s.value.to_string()) - } else if let PropertyKey::TemplateLiteral(t) = &o.key { - Some( - t.quasis - .iter() - .map(|q| q.value.raw.as_str()) - .collect::(), - ) - } else if let PropertyKey::NumericLiteral(n) = &o.key { - Some(n.value.to_string()) - } else { - None - } + && let Some(name) = get_string_by_property_key(&o.key) { let ExtractResult { styles, .. } = extract_style_from_expression(ast_builder, None, &mut o.value, 0, &None); diff --git a/libs/extractor/src/extractor/extract_style_from_expression.rs b/libs/extractor/src/extractor/extract_style_from_expression.rs index a854aefa..ee6d97db 100644 --- a/libs/extractor/src/extractor/extract_style_from_expression.rs +++ b/libs/extractor/src/extractor/extract_style_from_expression.rs @@ -10,19 +10,19 @@ use crate::{ }, utils::{ expression_to_code, get_number_by_literal_expression, get_string_by_literal_expression, - is_same_expression, + get_string_by_property_key, is_same_expression, }, }; use css::{ - disassemble_property, get_enum_property_map, get_enum_property_value, + add_selector_params, disassemble_property, get_enum_property_map, get_enum_property_value, is_special_property::is_special_property, style_selector::StyleSelector, utils::to_kebab_case, }; use oxc_allocator::CloneIn; use oxc_ast::{ AstBuilder, ast::{ - BinaryOperator, Expression, LogicalOperator, ObjectPropertyKind, PropertyKey, - TemplateElementValue, UnaryOperator, + BinaryOperator, Expression, LogicalOperator, ObjectPropertyKind, TemplateElementValue, + UnaryOperator, }, }; use oxc_span::SPAN; @@ -50,9 +50,8 @@ pub fn extract_style_from_expression<'a>( let mut prop = obj.properties.remove(idx); if !match &mut prop { ObjectPropertyKind::ObjectProperty(prop) => { - if let PropertyKey::StaticIdentifier(ident) = &prop.key - && let name = ident.name.as_str() - && !is_special_property(name) + if let Some(name) = get_string_by_property_key(&prop.key) + && !is_special_property(&name) { let property_name = name.to_string(); for name in disassemble_property(&property_name) { @@ -562,8 +561,44 @@ pub fn extract_style_from_expression<'a>( } Expression::ObjectExpression(obj) => { let mut props = vec![]; + let params = obj.properties.iter().find_map(|p| { + if let ObjectPropertyKind::ObjectProperty(o) = p + && o.key.name().unwrap() == "params" + && selector.is_some() + && let Expression::ArrayExpression(array) = &o.value + { + let arr = array.elements.iter(); + Some( + arr.filter_map(|e| { + if let Some(e) = e.as_expression() + && let Some(s) = get_string_by_literal_expression(e) + && !s.is_empty() + { + Some(s) + } else { + None + } + }) + .collect::>() + .join(","), + ) + } else { + None + } + }); + + let selector = selector.clone().map(|s| { + if let Some(params) = params { + add_selector_params(s, ¶ms) + } else { + s + } + }); + for p in obj.properties.iter_mut() { - if let ObjectPropertyKind::ObjectProperty(o) = p { + if let ObjectPropertyKind::ObjectProperty(o) = p + && o.key.name().unwrap() != "params" + { for name in disassemble_property(&o.key.name().unwrap()) { props.extend( extract_style_from_expression( @@ -571,7 +606,7 @@ pub fn extract_style_from_expression<'a>( Some(&name), &mut o.value, level, - selector, + &selector, ) .styles, ); diff --git a/libs/extractor/src/extractor/extract_style_from_member_expression.rs b/libs/extractor/src/extractor/extract_style_from_member_expression.rs index 5a5c8b13..091e4f27 100644 --- a/libs/extractor/src/extractor/extract_style_from_member_expression.rs +++ b/libs/extractor/src/extractor/extract_style_from_member_expression.rs @@ -4,16 +4,16 @@ use crate::{ ExtractResult, extract_style_from_expression::{dynamic_style, extract_style_from_expression}, }, - utils::{get_number_by_literal_expression, get_string_by_literal_expression}, + utils::{ + get_number_by_literal_expression, get_string_by_literal_expression, + get_string_by_property_key, + }, }; use css::style_selector::StyleSelector; use oxc_allocator::CloneIn; use oxc_ast::{ AstBuilder, - ast::{ - ArrayExpressionElement, ComputedMemberExpression, Expression, ObjectPropertyKind, - PropertyKey, - }, + ast::{ArrayExpressionElement, ComputedMemberExpression, Expression, ObjectPropertyKind}, }; use oxc_span::SPAN; use std::collections::BTreeMap; @@ -113,8 +113,8 @@ pub(super) fn extract_style_from_member_expression<'a>( let mut etc = None; for p in obj.properties.iter_mut() { if let ObjectPropertyKind::ObjectProperty(o) = p { - if let PropertyKey::StaticIdentifier(ref pk) = o.key - && pk.name == k + if let Some(property_name) = get_string_by_property_key(&o.key) + && property_name == k { return ExtractResult { styles: extract_style_from_expression( @@ -154,12 +154,10 @@ pub(super) fn extract_style_from_member_expression<'a>( for p in obj.properties.iter_mut() { if let ObjectPropertyKind::ObjectProperty(o) = p - && let PropertyKey::StaticIdentifier(_) - | PropertyKey::NumericLiteral(_) - | PropertyKey::StringLiteral(_) = o.key + && let Some(property_name) = get_string_by_property_key(&o.key) { map.insert( - o.key.name().unwrap().to_string(), + property_name, Box::new(ExtractStyleProp::StaticArray( extract_style_from_expression( ast_builder, diff --git a/libs/extractor/src/lib.rs b/libs/extractor/src/lib.rs index 032a879d..94dbacb2 100644 --- a/libs/extractor/src/lib.rs +++ b/libs/extractor/src/lib.rs @@ -3720,6 +3720,9 @@ e(o, { className: "a", bg: variable, style: { color: "blue" }, ...props }) reset_class_map(); assert_debug_snapshot!(ToBTreeSet::from(extract("test.js", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),{Box,Text,Flex}=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(Box,{["_hover"]:{bg:"blue"},bg:"$text",color:"red",children:"hello"}),e.jsx(Text,{typography:`header`,children:"typo"}),e.jsx(Flex,{as:"section",mt:2,children:"section"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(), single_css: true, import_main_css: false }).unwrap())); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from(extract("test.js", r#""use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),{Box,Text,Flex}=require("@devup-ui/react");function t(){return e.jsxs("div",{children:[e.jsx(Box,{["_hover"]:{bg:"blue"},bg:"$text",[variable]:"red",children:"hello"})]})}exports.Lib=t;"#, ExtractOption { package: "@devup-ui/react".to_string(), css_dir: "@devup-ui/react".to_string(), single_css: true, import_main_css: false }).unwrap())); } #[test] @@ -7268,4 +7271,181 @@ keyframes({ .unwrap() )); } + + #[test] + #[serial] + fn extract_advenced_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_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: false + } + ) + .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_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: false + } + ) + .unwrap() + )); + + // empty + 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_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: false + } + ) + .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_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: false + } + ) + .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_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: false + } + ) + .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_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {globalCss} from '@devup-ui/core' + globalCss({ + "_is": { + params: ["test", variable], + _hover: { + bg: "blue" + }, + bg: "red" + } + }) + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: false + } + ) + .unwrap() + )); + + reset_class_map(); + assert_debug_snapshot!(ToBTreeSet::from( + extract( + "test.tsx", + r#"import {css} from '@devup-ui/core' + css({ + "_is": { + params: ["test"], + bg: "red" + } + }) + "#, + ExtractOption { + package: "@devup-ui/core".to_string(), + css_dir: "@devup-ui/core".to_string(), + single_css: false, + import_main_css: false + } + ) + .unwrap() + )); + } } diff --git a/libs/extractor/src/prop_modify_utils.rs b/libs/extractor/src/prop_modify_utils.rs index 96b3553b..90b0c977 100644 --- a/libs/extractor/src/prop_modify_utils.rs +++ b/libs/extractor/src/prop_modify_utils.rs @@ -1,6 +1,7 @@ use crate::ExtractStyleProp; use crate::gen_class_name::gen_class_names; use crate::gen_style::gen_styles; +use crate::utils::get_string_by_property_key; use oxc_allocator::CloneIn; use oxc_ast::AstBuilder; use oxc_ast::ast::JSXAttributeName::Identifier; @@ -27,8 +28,7 @@ pub fn modify_prop_object<'a>( let prop = props.remove(idx); match prop { ObjectPropertyKind::ObjectProperty(attr) => { - if let PropertyKey::StaticIdentifier(ident) = &attr.key { - let name = ident.name.as_str(); + if let Some(name) = get_string_by_property_key(&attr.key) { if name == "className" { class_name_prop = Some(attr.value.clone_in(ast_builder.allocator)); } else if name == "style" { @@ -430,10 +430,8 @@ pub fn convert_style_vars<'a>( let mut prop = obj.properties.remove(idx); if let ObjectPropertyKind::ObjectProperty(p) = &mut prop { - let name = if let PropertyKey::StaticIdentifier(ident) = &p.key { - Some(ident.name) - } else if let PropertyKey::StringLiteral(ident) = &p.key { - Some(ident.value) + let name = if let Some(name) = get_string_by_property_key(&p.key) { + Some(name) } else { obj.properties.insert( idx, diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-2.snap b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-2.snap new file mode 100644 index 00000000..f7c7d383 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_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{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "red", + level: 0, + selector: Some( + Selector( + "&:is(test,test2)", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui-0.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-3.snap b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-3.snap new file mode 100644 index 00000000..49d64257 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-3.snap @@ -0,0 +1,8 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: {}, + code: "
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-4.snap b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-4.snap new file mode 100644 index 00000000..0b7b4c40 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_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{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "blue", + level: 0, + selector: Some( + Selector( + "&:is():hover", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui-0.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-5.snap b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-5.snap new file mode 100644 index 00000000..87419994 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_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{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "blue", + level: 0, + selector: Some( + Selector( + "&:is():hover", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui-0.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-6.snap b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-6.snap new file mode 100644 index 00000000..75dbf5ce --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_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{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "blue", + level: 0, + selector: Some( + Selector( + "&:is(test):hover", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui-0.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-7.snap b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-7.snap new file mode 100644 index 00000000..4fcb372e --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-7.snap @@ -0,0 +1,41 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {globalCss} from '@devup-ui/core'\n globalCss({\n \"_is\": {\n params: [\"test\", variable],\n _hover: {\n bg: \"blue\"\n },\n bg: \"red\"\n }\n })\n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "blue", + level: 0, + selector: Some( + Global( + "*:is(test):hover", + "test.tsx", + ), + ), + style_order: Some( + 0, + ), + }, + ), + Static( + ExtractStaticStyle { + property: "background", + value: "red", + level: 0, + selector: Some( + Global( + "*:is(test)", + "test.tsx", + ), + ), + style_order: Some( + 0, + ), + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui-0.css\";\n;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-8.snap b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-8.snap new file mode 100644 index 00000000..f9e69e47 --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector-8.snap @@ -0,0 +1,22 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import {css} from '@devup-ui/core'\n css({\n \"_is\": {\n params: [\"test\"],\n bg: \"red\"\n }\n })\n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "red", + level: 0, + selector: Some( + Selector( + "&:is(test)", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui-0.css\";\n\"a-a\";\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector.snap b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_selector.snap new file mode 100644 index 00000000..67ab2c4d --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__extract_advenced_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{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: false, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "red", + level: 0, + selector: Some( + Selector( + "&:is(test)", + ), + ), + style_order: None, + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui-0.css\";\n
;\n", +} diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_wrong_global_css.snap b/libs/extractor/src/snapshots/extractor__tests__extract_wrong_global_css.snap index 826bfb86..ae6f23bf 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_wrong_global_css.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_wrong_global_css.snap @@ -1,8 +1,25 @@ --- source: libs/extractor/src/lib.rs -expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import { globalCss } from \"@devup-ui/core\";\nglobalCss({\n [1]: {\n bg: \"red\"\n }\n})\n\"#,\nExtractOption\n{ package: \"@devup-ui/core\".to_string(), css_file: None }).unwrap())" +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import { globalCss } from \"@devup-ui/core\";\nglobalCss({\n [1]: {\n bg: \"red\"\n }\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" --- ToBTreeSet { - styles: {}, - code: ";\n", + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "red", + level: 0, + selector: Some( + Global( + "1", + "test.tsx", + ), + ), + style_order: Some( + 0, + ), + }, + ), + }, + code: "import \"@devup-ui/core/devup-ui.css\";\n;\n", } diff --git a/libs/extractor/src/snapshots/extractor__tests__extract_wrong_keyframs.snap b/libs/extractor/src/snapshots/extractor__tests__extract_wrong_keyframs.snap index d012877d..b911c2f4 100644 --- a/libs/extractor/src/snapshots/extractor__tests__extract_wrong_keyframs.snap +++ b/libs/extractor/src/snapshots/extractor__tests__extract_wrong_keyframs.snap @@ -1,6 +1,6 @@ --- source: libs/extractor/src/lib.rs -expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import { keyframes } from \"@devup-ui/core\";\nkeyframes({\n from: { opacity: 0 },\n [true]: { opacity: 0.5 },\n to: { opacity: 1, color: dy }\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_file: None, single_css: true,import_main_css: false\n}).unwrap())" +expression: "ToBTreeSet::from(extract(\"test.tsx\",\nr#\"import { keyframes } from \"@devup-ui/core\";\nkeyframes({\n from: { opacity: 0 },\n [true]: { opacity: 0.5 },\n to: { opacity: 1, color: dy }\n})\n\"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" --- ToBTreeSet { styles: { @@ -25,6 +25,15 @@ ToBTreeSet { style_order: None, }, ], + "true": [ + ExtractStaticStyle { + property: "opacity", + value: ".5", + level: 0, + selector: None, + style_order: None, + }, + ], }, }, ), diff --git a/libs/extractor/src/snapshots/extractor__tests__style_variables-9.snap b/libs/extractor/src/snapshots/extractor__tests__style_variables-9.snap index 01e7f25d..5542eefe 100644 --- a/libs/extractor/src/snapshots/extractor__tests__style_variables-9.snap +++ b/libs/extractor/src/snapshots/extractor__tests__style_variables-9.snap @@ -1,8 +1,8 @@ --- 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())" +expression: "ToBTreeSet::from(extract(\"test.jsx\",\nr#\"import {Box} from '@devup-ui/core'\n \n \"#,\nExtractOption\n{\n package: \"@devup-ui/core\".to_string(), css_dir:\n \"@devup-ui/core\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" --- ToBTreeSet { styles: {}, - code: "
;\n", + code: "
;\n", } diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-6.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-6.snap index 162958c2..29f82ae9 100644 --- a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-6.snap +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-6.snap @@ -13,6 +13,19 @@ ToBTreeSet { style_order: None, }, ), + Static( + ExtractStaticStyle { + property: "background", + value: "blue", + level: 0, + selector: Some( + Selector( + "&:hover", + ), + ), + style_order: None, + }, + ), Static( ExtractStaticStyle { property: "color", @@ -46,5 +59,5 @@ ToBTreeSet { "header", ), }, - code: "\"use strict\";\nimport \"@devup-ui/react/devup-ui.css\";\nObject.defineProperty(exports, Symbol.toStringTag, { value: \"Module\" });\nconst e = require(\"react/jsx-runtime\"), { Box, Text, Flex } = require(\"@devup-ui/react\");\nfunction t() {\n\treturn e.jsxs(\"div\", { children: [\n\t\te.jsx(\"div\", {\n\t\t\t[\"_hover\"]: { bg: \"blue\" },\n\t\t\tchildren: \"hello\",\n\t\t\tclassName: \"a b\"\n\t\t}),\n\t\te.jsx(\"span\", {\n\t\t\tchildren: \"typo\",\n\t\t\tclassName: \"typo-header\"\n\t\t}),\n\t\te.jsx(\"section\", {\n\t\t\tchildren: \"section\",\n\t\t\tclassName: \"c d\"\n\t\t})\n\t] });\n}\nexports.Lib = t;\n", + code: "\"use strict\";\nimport \"@devup-ui/react/devup-ui.css\";\nObject.defineProperty(exports, Symbol.toStringTag, { value: \"Module\" });\nconst e = require(\"react/jsx-runtime\"), { Box, Text, Flex } = require(\"@devup-ui/react\");\nfunction t() {\n\treturn e.jsxs(\"div\", { children: [\n\t\te.jsx(\"div\", {\n\t\t\tchildren: \"hello\",\n\t\t\tclassName: \"a b c\"\n\t\t}),\n\t\te.jsx(\"span\", {\n\t\t\tchildren: \"typo\",\n\t\t\tclassName: \"typo-header\"\n\t\t}),\n\t\te.jsx(\"section\", {\n\t\t\tchildren: \"section\",\n\t\t\tclassName: \"d e\"\n\t\t})\n\t] });\n}\nexports.Lib = t;\n", } diff --git a/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-7.snap b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-7.snap new file mode 100644 index 00000000..fa95c4ba --- /dev/null +++ b/libs/extractor/src/snapshots/extractor__tests__support_transpile_cjs-7.snap @@ -0,0 +1,31 @@ +--- +source: libs/extractor/src/lib.rs +expression: "ToBTreeSet::from(extract(\"test.js\",\nr#\"\"use strict\";Object.defineProperty(exports,Symbol.toStringTag,{value:\"Module\"});const e=require(\"react/jsx-runtime\"),{Box,Text,Flex}=require(\"@devup-ui/react\");function t(){return e.jsxs(\"div\",{children:[e.jsx(Box,{[\"_hover\"]:{bg:\"blue\"},bg:\"$text\",[variable]:\"red\",children:\"hello\"})]})}exports.Lib=t;\"#,\nExtractOption\n{\n package: \"@devup-ui/react\".to_string(), css_dir:\n \"@devup-ui/react\".to_string(), single_css: true, import_main_css: false\n}).unwrap())" +--- +ToBTreeSet { + styles: { + Static( + ExtractStaticStyle { + property: "background", + value: "$text", + level: 0, + selector: None, + style_order: None, + }, + ), + Static( + ExtractStaticStyle { + property: "background", + value: "blue", + level: 0, + selector: Some( + Selector( + "&:hover", + ), + ), + style_order: None, + }, + ), + }, + code: "\"use strict\";\nimport \"@devup-ui/react/devup-ui.css\";\nObject.defineProperty(exports, Symbol.toStringTag, { value: \"Module\" });\nconst e = require(\"react/jsx-runtime\"), { Box, Text, Flex } = require(\"@devup-ui/react\");\nfunction t() {\n\treturn e.jsxs(\"div\", { children: [e.jsx(\"div\", {\n\t\t[variable]: \"red\",\n\t\tchildren: \"hello\",\n\t\tclassName: \"a b\"\n\t})] });\n}\nexports.Lib = t;\n", +} diff --git a/libs/extractor/src/utils.rs b/libs/extractor/src/utils.rs index c1e200a5..6e0a2603 100644 --- a/libs/extractor/src/utils.rs +++ b/libs/extractor/src/utils.rs @@ -1,5 +1,5 @@ use oxc_allocator::{Allocator, CloneIn}; -use oxc_ast::ast::{Expression, JSXAttributeValue, Statement}; +use oxc_ast::ast::{Expression, JSXAttributeValue, PropertyKey, Statement}; use oxc_codegen::Codegen; use oxc_parser::Parser; use oxc_span::{SPAN, SourceType}; @@ -111,6 +111,18 @@ pub(super) fn get_string_by_literal_expression(expr: &Expression) -> Option Option { + if let PropertyKey::StaticIdentifier(ident) = key { + Some(ident.name.to_string()) + } else if let Some(s) = key.as_expression() + && let Some(s) = get_string_by_literal_expression(s) + { + Some(s) + } else { + None + } +} + pub fn gcd(a: u32, b: u32) -> u32 { if b == 0 { a } else { gcd(b, a % b) } } diff --git a/libs/extractor/src/visit.rs b/libs/extractor/src/visit.rs index a71c0bbf..aaae4d37 100644 --- a/libs/extractor/src/visit.rs +++ b/libs/extractor/src/visit.rs @@ -24,7 +24,7 @@ use oxc_ast::ast::JSXAttributeItem::Attribute; use oxc_ast::ast::JSXAttributeName::Identifier; use oxc_ast::ast::{ Argument, BindingPatternKind, CallExpression, Expression, ImportDeclaration, - ImportOrExportKind, JSXAttributeValue, JSXChild, JSXElement, Program, PropertyKey, Statement, + ImportOrExportKind, JSXAttributeValue, JSXChild, JSXElement, Program, Statement, VariableDeclarator, WithClause, }; use oxc_ast_visit::VisitMut; @@ -34,7 +34,7 @@ use oxc_ast_visit::walk_mut::{ }; use strum::IntoEnumIterator; -use crate::utils::jsx_expression_to_number; +use crate::utils::{get_string_by_property_key, jsx_expression_to_number}; use oxc_ast::AstBuilder; use oxc_span::SPAN; use std::collections::{HashMap, HashSet}; @@ -392,13 +392,13 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { self.jsx_object = Some(ident.name.to_string()); } else if let BindingPatternKind::ObjectPattern(object) = &it.id.kind { for prop in &object.properties { - if let PropertyKey::StaticIdentifier(ident) = &prop.key + if let Some(name) = get_string_by_property_key(&prop.key) && let Some(k) = prop .value .get_binding_identifier() .map(|id| id.name.to_string()) { - self.jsx_imports.insert(k, ident.name.to_string()); + self.jsx_imports.insert(k, name); } } } @@ -407,7 +407,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { self.import_object = Some(ident.name.to_string()); } else if let BindingPatternKind::ObjectPattern(object) = &it.id.kind { for prop in &object.properties { - if let PropertyKey::StaticIdentifier(ident) = &prop.key + if let Some(name) = get_string_by_property_key(&prop.key) && let Ok(kind) = ExportVariableKind::try_from( prop.value .get_binding_identifier() @@ -415,7 +415,7 @@ impl<'a> VisitMut<'a> for DevupVisitor<'a> { .unwrap_or_default(), ) { - self.imports.insert(ident.name.to_string(), kind); + self.imports.insert(name, kind); } } } diff --git a/packages/eslint-plugin/src/rules/no-useless-responsive/index.ts b/packages/eslint-plugin/src/rules/no-useless-responsive/index.ts index dec11483..5cd1ccda 100644 --- a/packages/eslint-plugin/src/rules/no-useless-responsive/index.ts +++ b/packages/eslint-plugin/src/rules/no-useless-responsive/index.ts @@ -98,7 +98,7 @@ export const noUselessResponsive = createRule({ if ( devupContext && node.key.type === AST_NODE_TYPES.Identifier && - node.key.name === 'imports' + ['imports', 'params', 'fontFaces'].includes(node.key.name) ) { devupContext = null } diff --git a/packages/react/src/types/props/selector/index.ts b/packages/react/src/types/props/selector/index.ts index adf700b1..62bce9c2 100644 --- a/packages/react/src/types/props/selector/index.ts +++ b/packages/react/src/types/props/selector/index.ts @@ -1,10 +1,10 @@ -import type { Pseudos } from 'csstype' +import type { AdvancedPseudos, SimplePseudos } from 'csstype' import type { ResponsiveValue } from '../../responsive-value' import type { DevupTheme } from '../../theme' import type { DevupProps } from '../index' -type CamelCase = +export type CamelCase = S extends Lowercase ? S extends `${infer F}-${infer RF}${infer R}` ? `${F}${Uppercase}${CamelCase}` @@ -13,36 +13,62 @@ type CamelCase = type PascalCase = Capitalize> -export type SelectorProps = ResponsiveValue +export type SelectorProps = ResponsiveValue export type DevupThemeSelectorProps = keyof DevupTheme extends undefined - ? Partial> - : Partial}`, SelectorProps>> + ? Partial>> + : Partial< + Record<`_theme${PascalCase}`, SelectorProps> + > -export type NormalSelector = Exclude< - Pseudos, - `:-${string}` | `::-${string}` | `${string}()` -> -export type ExtractSelector = T extends `::${infer R}` +export type NormalizedSelector = Exclude +export type SimpleSelector = NormalizedSelector + +export type AdvancedSelector = NormalizedSelector + +export type ExtractSelector = T extends `::${infer R}` ? R : T extends `:${infer R}` ? R : never -export type CommonSelectorProps = { - [K in ExtractSelector as + +export type AdvancedSelectorProps = { + [K in ExtractSelector> as + | `_${CamelCase}` + | `_group${PascalCase}`]?: SimpleSelectorProps & + AdvancedSelectorProps & { + params: string[] + selectors?: Selectors + } +} + +export type MultipleSelectorProps = { + [K in ExtractSelector> as + | `_${CamelCase}` + | `_group${PascalCase}`]?: SelectorProps & { + params?: string[] + } +} + +export type SimpleSelectorProps = { + [K in ExtractSelector> as | `_${CamelCase}` - | `_group${PascalCase}`]?: SelectorProps + | `_group${PascalCase}`]?: SelectorProps } export type Selectors = Partial< Record< - (string & {}) | `&${NormalSelector}` | `_${CamelCase}`, - SelectorProps + | (string & {}) + | `&${SimpleSelector}` + | `_${CamelCase>}`, + SelectorProps > > -export interface DevupSelectorProps extends CommonSelectorProps { +export interface DevupSelectorProps + extends SimpleSelectorProps, + AdvancedSelectorProps { // media query - _print?: SelectorProps + _print?: SelectorProps selectors?: Selectors diff --git a/packages/react/src/utils/global-css.ts b/packages/react/src/utils/global-css.ts index 4264c8a5..b3dfcc72 100644 --- a/packages/react/src/utils/global-css.ts +++ b/packages/react/src/utils/global-css.ts @@ -1,23 +1,37 @@ import type { DevupCommonProps } from '../types/props' import type { + AdvancedSelector, + CamelCase, DevupThemeSelectorProps, ExtractSelector, - NormalSelector, + SimpleSelector, } from '../types/props/selector' import type { DevupSelectorProps } from '../types/props/selector' -type GlobalCssKeys = - | `*${NormalSelector | ''}` - | `${keyof HTMLElementTagNameMap}${NormalSelector | ''}` - | `${keyof SVGElementTagNameMap}${NormalSelector | ''}` - | `_${ExtractSelector}` - | (string & {}) +type GlobalCssKeys = + | `*${T}` + | `${keyof HTMLElementTagNameMap}${T}` + | `${keyof SVGElementTagNameMap}${T}` + | `_${CamelCase>}` type GlobalCssProps = { - [K in GlobalCssKeys]?: - | DevupCommonProps - | DevupSelectorProps - | DevupThemeSelectorProps + [K in GlobalCssKeys]?: DevupCommonProps & + DevupSelectorProps & + DevupThemeSelectorProps & { + params: string[] + } +} & { + [K in GlobalCssKeys< + Exclude + >]?: DevupCommonProps & + DevupSelectorProps & + DevupThemeSelectorProps & { + params?: string[] + } +} & { + [K in GlobalCssKeys | (string & {})]?: DevupCommonProps & + DevupSelectorProps & + DevupThemeSelectorProps } interface FontFaceProps {