Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

treat hyphen as underscore in keys of styles #4810

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion reflex/components/tags/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def add_props(self, **kwargs: Optional[Any]) -> Tag:
"""
self.props.update(
{
format.to_camel_case(name, allow_hyphens=True): (
format.to_camel_case(name, treat_hyphens_as_underscores=False): (
prop
if types._isinstance(prop, (EventChain, Mapping))
else LiteralVar.create(prop)
Expand Down
7 changes: 5 additions & 2 deletions reflex/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,12 @@ def update_out_dict(
for key, value in style_dict.items():
keys = (
format_style_key(key)
if not isinstance(value, (dict, ObjectVar))
if not isinstance(value, (dict, ObjectVar, list))
or (
isinstance(value, Breakpoints)
and all(not isinstance(v, dict) for v in value.values())
)
or (isinstance(value, list) and all(not isinstance(v, dict) for v in value))
or (
isinstance(value, ObjectVar)
and not issubclass(get_origin(value._var_type) or value._var_type, dict)
Expand Down Expand Up @@ -237,7 +238,9 @@ def format_style_key(key: str) -> Tuple[str, ...]:
Returns:
Tuple of css style names corresponding to the key provided.
"""
key = format.to_camel_case(key, allow_hyphens=True)
if key.startswith("--"):
return (key,)
key = format.to_camel_case(key)
return STYLE_PROP_SHORTHAND_MAPPING.get(key, (key,))


Expand Down
11 changes: 5 additions & 6 deletions reflex/utils/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,25 +168,24 @@ def to_snake_case(text: str) -> str:
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower().replace("-", "_")


def to_camel_case(text: str, allow_hyphens: bool = False) -> str:
def to_camel_case(text: str, treat_hyphens_as_underscores: bool = True) -> str:
"""Convert a string to camel case.

The first word in the text is converted to lowercase and
the rest of the words are converted to title case, removing underscores.

Args:
text: The string to convert.
allow_hyphens: Whether to allow hyphens in the string.
treat_hyphens_as_underscores: Whether to allow hyphens in the string.

Returns:
The camel case string.
"""
char = "_" if allow_hyphens else "-_"
words = re.split(f"[{char}]", text.lstrip(char))
leading_underscores_or_hyphens = "".join(re.findall(rf"^[{char}]+", text))
char = "_" if not treat_hyphens_as_underscores else "-_"
words = re.split(f"[{char}]", text)
# Capitalize the first letter of each word except the first one
converted_word = words[0] + "".join(x.capitalize() for x in words[1:])
return leading_underscores_or_hyphens + converted_word
return converted_word


def to_title_case(text: str, sep: str = "") -> str:
Expand Down
2 changes: 1 addition & 1 deletion tests/units/components/markdown/test_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def test_create_map_fn_var_subclass(cls, fn_body, fn_args, explicit_return, expe
value, **props
)
},
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); let _language = match ? match[1] : ''; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <RadixThemesBox css={({ ["pre"] : ({ ["margin"] : "0", ["padding"] : "24px", ["background"] : "transparent", ["overflow-x"] : "auto", ["border-radius"] : "6px" }) })} {...props}><ShikiCode code={((Array.isArray(children)) ? children.join("\n") : children)} decorations={[]} language={_language} theme={((resolvedColorMode === "light") ? "one-light" : "one-dark-pro")} transformers={[]}/></RadixThemesBox> ); })""",
r"""(({node, inline, className, children, ...props}) => { const match = (className || '').match(/language-(?<lang>.*)/); let _language = match ? match[1] : ''; ; return inline ? ( <RadixThemesCode {...props}>{children}</RadixThemesCode> ) : ( <RadixThemesBox css={({ ["pre"] : ({ ["margin"] : "0", ["padding"] : "24px", ["background"] : "transparent", ["overflowX"] : "auto", ["borderRadius"] : "6px" }) })} {...props}><ShikiCode code={((Array.isArray(children)) ? children.join("\n") : children)} decorations={[]} language={_language} theme={((resolvedColorMode === "light") ? "one-light" : "one-dark-pro")} transformers={[]}/></RadixThemesBox> ); })""",
),
(
"h1",
Expand Down
2 changes: 1 addition & 1 deletion tests/units/components/test_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ def test_create_filters_none_props(test_component):

# Assert that the style prop is present in the component's props
assert str(component.style["color"]) == '"white"'
assert str(component.style["text-align"]) == '"center"'
assert str(component.style["textAlign"]) == '"center"'


@pytest.mark.parametrize(
Expand Down
10 changes: 5 additions & 5 deletions tests/units/utils/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,11 @@ def test_to_snake_case(input: str, output: str):
("kebab-case", "kebabCase"),
("kebab-case-two", "kebabCaseTwo"),
("snake_kebab-case", "snakeKebabCase"),
("_hover", "_hover"),
("-starts-with-hyphen", "-startsWithHyphen"),
("--starts-with-double-hyphen", "--startsWithDoubleHyphen"),
("_starts_with_underscore", "_startsWithUnderscore"),
("__starts_with_double_underscore", "__startsWithDoubleUnderscore"),
("_hover", "Hover"),
("-starts-with-hyphen", "StartsWithHyphen"),
("--starts-with-double-hyphen", "StartsWithDoubleHyphen"),
("_starts_with_underscore", "StartsWithUnderscore"),
("__starts_with_double_underscore", "StartsWithDoubleUnderscore"),
(":start-with-colon", ":startWithColon"),
(":-start-with-colon-dash", ":StartWithColonDash"),
],
Expand Down