Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .changeset/breezy-ghosts-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@devup-ui/reset-css": major
---

reset css
5 changes: 5 additions & 0 deletions .changeset/yummy-brooms-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@devup-ui/wasm": patch
---

Implement keyframe
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/landing/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ export default withMDX(
pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
output: 'export',
},
{ include: ['@devup-ui/components'] },
{ include: ['@devup-ui/components', '@devup-ui/reset-css'] },
),
)
4 changes: 2 additions & 2 deletions apps/landing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"@devup-ui/components": "workspace:*",
"@devup-ui/react": "workspace:*",
"@devup-ui/reset-css": "workspace:*",
"@mdx-js/loader": "^3.1.0",
"@mdx-js/react": "^3.1.0",
"@next/mdx": "^15.3.5",
Expand All @@ -24,8 +25,7 @@
"react-dom": "^19.1.0",
"react-markdown": "^10.1.0",
"react-syntax-highlighter": "^15.6.1",
"remark-gfm": "^4.0.1",
"sanitize.css": "^13.0.0"
"remark-gfm": "^4.0.1"
},
"devDependencies": {
"@devup-ui/next-plugin": "workspace:*",
Expand Down
9 changes: 0 additions & 9 deletions apps/landing/src/app/StarButton.css

This file was deleted.

16 changes: 12 additions & 4 deletions apps/landing/src/app/StarButton.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
'use client'

import './StarButton.css'

import { Center, css, Flex, Image, Text } from '@devup-ui/react'
import { Center, css, Flex, Image, keyframes, Text } from '@devup-ui/react'
import Link from 'next/link'
import { useEffect, useState } from 'react'

const spin = keyframes({
'0%': {
transform: 'rotate(0deg)',
},
'100%': {
transform: 'rotate(360deg)',
},
})

export default function StarButton() {
const [starCount, setStarCount] = useState<number | null>(null)

Expand Down Expand Up @@ -88,7 +95,8 @@ export default function StarButton() {
{starCount === null ? (
<Image
alt="Loading"
animation="spin 1s linear infinite"
animation="1s linear infinite"
animationName={spin}
boxSize="20px"
src="/spinner.svg"
/>
Expand Down
5 changes: 3 additions & 2 deletions apps/landing/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'sanitize.css'

import { css, globalCss, ThemeScript } from '@devup-ui/react'
import { resetCss } from '@devup-ui/reset-css'
import type { Metadata } from 'next'

import { Footer } from '../components/Footer'
Expand All @@ -24,6 +23,8 @@ export const metadata: Metadata = {
},
}

resetCss()

globalCss({
imports: ['https://cdn.jsdelivr.net/gh/joungkyun/font-d2coding/d2coding.css'],
table: {
Expand Down
30 changes: 29 additions & 1 deletion bindings/devup-ui-wasm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use css::class_map::{get_class_map, set_class_map};
use extractor::extract_style::ExtractStyleProperty;
use extractor::extract_style::extract_style_value::ExtractStyleValue;
use extractor::{ExtractOption, StyleProperty, extract};
use extractor::extract_style::style_property::StyleProperty;
use extractor::{ExtractOption, extract};
use once_cell::sync::Lazy;
use sheet::StyleSheet;
use std::collections::HashSet;
Expand Down Expand Up @@ -90,6 +92,32 @@ impl Output {
collected = true;
}
}

ExtractStyleValue::Keyframes(keyframes) => {
if sheet.add_keyframes(
&keyframes.extract().to_string(),
keyframes
.keyframes
.iter()
.map(|(key, value)| {
(
key.clone(),
value
.iter()
.map(|style| {
(
style.property().to_string(),
style.value().to_string(),
)
})
.collect::<Vec<(String, String)>>(),
)
})
.collect(),
) {
collected = true;
}
}
ExtractStyleValue::Css(cs) => {
if sheet.add_css(&cs.file, &cs.css) {
collected = true;
Expand Down
28 changes: 28 additions & 0 deletions libs/css/src/class_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,31 @@ pub fn set_class_map(map: HashMap<String, i32>) {
pub fn get_class_map() -> HashMap<String, i32> {
GLOBAL_CLASS_MAP.lock().unwrap().clone()
}

#[cfg(test)]
mod tests {
use serial_test::serial;

use super::*;

#[test]
#[serial]
fn test_set_and_get_class_map() {
let mut test_map = HashMap::new();
test_map.insert("test-key".to_string(), 42);
set_class_map(test_map.clone());
let got = get_class_map();
assert_eq!(got.get("test-key"), Some(&42));
}

#[test]
#[serial]
fn test_reset_class_map() {
let mut test_map = HashMap::new();
test_map.insert("reset-key".to_string(), 1);
set_class_map(test_map);
reset_class_map();
let got = get_class_map();
assert!(got.is_empty());
}
}
28 changes: 28 additions & 0 deletions libs/css/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ pub fn short_to_long(property: &str) -> String {
.unwrap_or_else(|| property.to_string())
}

pub fn keyframes_to_keyframes_name(keyframes: &str) -> String {
if is_debug() {
format!("k-{keyframes}")
} else {
let key = format!("k-{keyframes}");
let mut map = GLOBAL_CLASS_MAP.lock().unwrap();
map.get(&key).map(|v| format!("k{v}")).unwrap_or_else(|| {
let len = map.len();
map.insert(key, len as i32);
format!("k{}", map.len() - 1)
})
}
}

pub fn sheet_to_classname(
property: &str,
level: u8,
Expand Down Expand Up @@ -419,4 +433,18 @@ mod tests {
set_class_map(map);
assert_eq!(get_class_map().len(), 1);
}

#[test]
#[serial]
fn test_keyframes_to_keyframes_name() {
reset_class_map();
set_debug(false);
assert_eq!(keyframes_to_keyframes_name("spin"), "k0");
assert_eq!(keyframes_to_keyframes_name("spin"), "k0");
assert_eq!(keyframes_to_keyframes_name("spin2"), "k1");
reset_class_map();
set_debug(true);
assert_eq!(keyframes_to_keyframes_name("spin"), "k-spin");
assert_eq!(keyframes_to_keyframes_name("spin1"), "k-spin1");
}
}
34 changes: 0 additions & 34 deletions libs/extractor/src/css_type.rs

This file was deleted.

101 changes: 101 additions & 0 deletions libs/extractor/src/css_utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::BTreeMap;

use css::{style_selector::StyleSelector, utils::to_camel_case};

use crate::{
Expand Down Expand Up @@ -30,6 +32,37 @@ pub fn css_to_style<'a>(
.collect()
}

pub fn keyframes_to_keyframes_style<'a>(
keyframes: &str,
) -> BTreeMap<String, Vec<ExtractStyleProp<'a>>> {
let mut map = BTreeMap::new();
let mut input = keyframes;

while let Some(start) = input.find('{') {
let key = input[..start].trim().to_string();
let rest = &input[start + 1..];
if let Some(end) = rest.find('}') {
let block = &rest[..end];
let mut styles = css_to_style(block, 0, &None)
.into_iter()
.collect::<Vec<_>>();

styles.sort_by_key(|a| {
if let crate::ExtractStyleProp::Static(crate::ExtractStyleValue::Static(a)) = a {
a.property().to_string()
} else {
"".to_string()
}
});
map.insert(key, styles);
input = &rest[end + 1..];
} else {
break;
}
}
map
}

pub fn optimize_css_block(css: &str) -> String {
css.split("{")
.map(|s| s.trim().to_string())
Expand Down Expand Up @@ -143,4 +176,72 @@ mod tests {
expected_sorted.sort();
assert_eq!(result, expected_sorted);
}

#[rstest]
#[case(
"to {\nbackground-color:red;\n}\nfrom {\nbackground-color:blue;\n}",
vec![
("to", vec![("backgroundColor", "red")]),
("from", vec![("backgroundColor", "blue")]),
],
)]
#[case(
"0% { opacity: 0; }\n100% { opacity: 1; }",
vec![
("0%", vec![("opacity", "0")]),
("100%", vec![("opacity", "1")]),
],
)]
#[case(
"from { left: 0; }\nto { left: 100px; }",
vec![
("from", vec![("left", "0")]),
("to", vec![("left", "100px")]),
],
)]
#[case(
"50% { color: red; background: blue; }",
vec![
("50%", vec![("color", "red"), ("background", "blue")]),
],
)]
#[case(
"",
vec![],
)]
#[case(
"50% { color: red ; background: blue; }",
vec![
("50%", vec![("color", "red"), ("background", "blue")]),
],
)]
fn test_keyframes_to_keyframes_style(
#[case] input: &str,
#[case] expected: Vec<(&str, Vec<(&str, &str)>)>,
) {
let styles = keyframes_to_keyframes_style(input);
for (expected_key, expected_styles) in styles.iter() {
let styles = expected_styles;
let mut result: Vec<(&str, &str)> = styles
.iter()
.filter_map(|prop| {
if let crate::ExtractStyleProp::Static(crate::ExtractStyleValue::Static(st)) =
prop
{
Some((st.property(), st.value()))
} else {
None
}
})
.collect();
result.sort();
let mut expected_sorted = expected
.iter()
.find(|(k, _)| k == expected_key)
.map(|(_, v)| v.clone())
.unwrap();
expected_sorted.sort();
assert_eq!(result, expected_sorted);
}
}
}
4 changes: 3 additions & 1 deletion libs/extractor/src/extract_style/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ pub(super) static MAINTAIN_VALUE_PROPERTIES: phf::Set<&str> = phf_set! {
"gridRow",
"gridRowStart",
"gridRowEnd",
"animationIterationCount"
"animationIterationCount",
"tabSize",
"MozTabSize"
};
2 changes: 1 addition & 1 deletion libs/extractor/src/extract_style/extract_dynamic_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use css::{
style_selector::StyleSelector,
};

use crate::{StyleProperty, extract_style::ExtractStyleProperty};
use crate::extract_style::{ExtractStyleProperty, style_property::StyleProperty};

#[derive(Debug, PartialEq, Clone, Eq, Hash, Ord, PartialOrd)]
pub struct ExtractDynamicStyle {
Expand Down
Loading