Skip to content

fix: vanilla-extract/StyleX number units and full engine for .css.ts - #676

Closed
owjs3901 wants to merge 12 commits into
mainfrom
fix/vanilla-extract-full-engine-and-units
Closed

owjs3901 wants to merge 12 commits into
mainfrom
fix/vanilla-extract-full-engine-and-units

Conversation

@owjs3901

Copy link
Copy Markdown
Contributor

#675에 의존합니다. #675를 먼저 머지해 주세요. CI가 main 대상 PR에서만 돌기 때문에 base를 main으로 열었고, diff에는 #675 커밋 8개가 함께 보입니다. 이 PR의 변경은 마지막 4개 커밋입니다.

문제

  1. vanilla-extract·StyleX의 숫자가 Devup UI 스페이싱 스케일(×4)로 해석됨
    • VE style({ padding: 8 }) → padding: 32px (VE 원본은 8px)
    • StyleX fontSize: 16 → 64px, transitionDuration: 300 → 1200px
    • .css.ts가 아닌 일반 모듈에서 쓴 VE style() / globalStyle() / keyframes()도 똑같이 ×4가 적용됨
    • Devup 자체 unitless 목록이 좁아서 strokeWidth={2}가 8px, columns, zoom, orphans, column-count 등도 px로 바뀜
  2. Next 플러그인 .css.ts 정적 fast path의 비결정성
    • 프로덕션에서만 lite 엔진과 TS 정적 변환을 썼고, 개발 모드는 full(Boa)을 썼습니다. 같은 파일인데 클래스명과 export 순서가 달랐습니다.
    • 정적 변환은 리터럴만 쓴 style({...})만 처리할 수 있었습니다. vars, 템플릿 리터럴, createVar, 계산값은 결국 Boa가 필요합니다.

수정

  • extractor
    • VE: JSON.stringify에 native replacer(pixelify)를 넘깁니다.
      • VE 규칙대로 0이 아닌 숫자에만 px를 붙입니다.
      • unitless 속성, --*/var( 키, 배열 인덱스, vars는 그대로 둡니다.
    • 일반 모듈의 VE style() / globalStyle() / keyframes()는 import 별칭 단계에서 숫자 리터럴을 "8px"로 치환합니다.
    • StyleX: getNumberSuffix를 동일하게 옮겼습니다.
      • unitless는 그대로, 시간 속성은 ms, 나머지는 px입니다.
      • 반올림은 Math.round(x*10000)/10000입니다.
      • 동적 인자는 길이·시간 속성에서만 ((v) => typeof v === "number" ? v + "px" : v)(arg)로 감쌉니다.
    • MAINTAIN_VALUE_PROPERTIES를 vanilla-extract의 unitless 목록으로 확장했습니다.
      • 추가: strokeWidth, columns, columnCount, zoom, orphans, widows, gridArea, borderImage*, maskBorder*, SVG opacity 계열 등
      • Devup 네이티브 prop에도 적용되는 동작 변경입니다. 예: strokeWidth={2}가 8px에서 2가 됩니다.
  • next-plugin
    • static-vanilla.ts와 관련 옵션을 제거했습니다. .css.ts가 있으면 항상 full 엔진을 씁니다(없으면 기존처럼 lite).
    • 측정: 첫 .css.ts에 약 +20ms, 이후 파일당 1ms 미만입니다.
  • docs
    • README 10곳의 lite fast path 설명을 교체했습니다.
    • VE/StyleX 마이그레이션 문서에 숫자 규칙을 추가했습니다.
    • API 문서(Box/Button/Center/Grid/VStack)의 "×4 예외" 목록과 SKILL.md를 갱신했습니다.
  • changepack: @devup-ui/wasm, @devup-ui/next-plugin Patch

테스트

  • 단위 테스트
    • test_vanilla_extract_numbers_follow_vanilla_extract_units
    • test_stylex_numbers_follow_stylex_units
    • test_style_to_json_adds_vanilla_extract_units
    • test_vanilla_extract_numbers_become_px_outside_stylesheets
    • test_js_number_literal
  • 스냅샷 28개를 갱신했습니다(VE는 px, StyleX는 px/ms, 동적 값은 IIFE).
  • cargo fmt / clippy -D warnings(기본 + lite wasm 타깃), cargo test --workspace 전부 통과
  • bun test 5231 pass, 100% 커버리지 / 회귀 테스트 6 pass / next-plugin tsc·eslint 통과
  • 재빌드한 wasm(full·lite)으로 직접 확인:
    • VE .css.ts: font-size:16px, padding:8px, line-height:1.5, column-count:3
    • 일반 모듈의 VE keyframes: width:10px
    • StyleX: transition-duration:300ms, 동적 height에 px IIFE 적용

참고

  • 미검증 후보(별도 이슈 후보): Emotion·styled-components 객체 스타일의 숫자, VE createVar/createContainer 이름의 파일 간 충돌 가능성

owjs3901 and others added 12 commits September 27, 2026 00:39
…cking

Boa's Context::default() reads std::time::Instant, which panics on wasm32-unknown-unknown without the js feature. Every .css.ts extraction crashed in the full WASM; the lite build is unaffected. Add a wasm-bindgen test and a bun regression that runs in CI.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…en-prefix rules

prefer-media-shorthand suggests _motionReduce, _print and the other media shorthands for _media entries and @media keys that spell out the same query. no-typography-token-prefix reports typography=$heading, which names no preset. Both are auto-fixable and part of the recommended config.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Media shorthand queries, at-rule key parsing, query normalization, media query combination (merge, never-match, nest) and the deterministic order at-rule blocks are emitted in. StyleSelector::At now carries its enclosing at-rules and owning file.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…xtract references

Nest _print, _media and @media keys with selectors in both directions (props, globalCss, template literals, Tailwind variants, StyleX conditions), apply typography conditionally, and keep responsive globalCss values in the base layer. vanilla-extract selectors, values and globalStyle now resolve references to styles, keyframes, fonts and themes, and createVar/fontFace/layer exports no longer shift onto each other.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Rules order by selector group before breakpoint level and at-rules follow every plain rule; globalCss and custom layers keep SELECTOR_ORDER instead of sorting selectors alphabetically. Adjacent rules with the same selector share one block, and a declaration written next to a conditional typography preset wins over it.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add _motionReduce, _motionSafe, _portrait, _landscape, _contrastMore, _contrastLess and _forcedColors, accept @media/@supports/@container keys, allow top-level at-rules in globalCss, and drop the never-matching _speech.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
typography takes the bare preset key, so the examples no longer write typography=$heading.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
… units

vanilla-extract styles add px to numbers (in .css.ts files and in style/globalStyle/keyframes calls of ordinary modules) and StyleX adds px/ms to static and dynamic numbers, instead of Devup UI's spacing scale. The unitless property list now matches vanilla-extract's, so strokeWidth, columns, zoom, orphans and similar keep bare numbers everywhere.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…gine

Remove the static .css.ts fast path so development and production builds evaluate stylesheets the same way and produce the same class names and CSS.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@github-actions

Copy link
Copy Markdown
Contributor

Changepacks

@devup-ui/wasm@1.0.81 → 1.0.82 - bindings/devup-ui-wasm/package.json

Patch

  • Fix at-rule composition and cascade: _print/_media/@media … nest correctly with selectors in both directions and inside globalCss, nested media queries merge (print and (…)), breakpoints put media types first, distribute query lists, and nest not … queries, and at-rules are emitted after all breakpoint values while pseudo selectors keep SELECTOR_ORDER across breakpoints. Add _motionReduce, _motionSafe, _portrait, _landscape, _contrastMore, _contrastLess and _forcedColors, remove the never-matching _speech, normalize query whitespace, support Emotion-style '@media …'/'&:hover' object keys, fix template literals losing declarations before @media or selectors around nested at-rules, apply typography conditionally under selectors, and drop stale global at-rules on re-extraction
  • Fix the full WASM build panicking on every vanilla-extract .css.ts file (Boa read the clock without its js feature), resolve vanilla-extract references to other styles, keyframes, fonts and themes in selectors, values and globalStyle, keep globalCss pseudo selectors in SELECTOR_ORDER across breakpoints, merge adjacent rules with the same selector, and let declarations written next to a conditional typography preset win over it. Add the prefer-media-shorthand and no-typography-token-prefix ESLint rules
  • Numbers in vanilla-extract and StyleX styles keep their library's meaning instead of Devup UI's spacing scale: vanilla-extract styles add px in .css.ts files and in style(), globalStyle() and keyframes() calls inside ordinary modules, StyleX adds px/ms to static values and to numbers passed to dynamic styles, and unitless properties such as columnCount, strokeWidth, orphans or zoom keep a bare number everywhere. The Next.js plugin now runs every .css.ts module on the full engine instead of a separate static fast path, so development and production builds produce the same output

@devup-ui/bun-plugin@1.0.20 → 1.0.21 - packages/bun-plugin/package.json

Patch

  • Auto-update: depends on '@devup-ui/wasm' via a local workspace dependency

@devup-ui/components@0.1.58 → 0.1.59 - packages/components/package.json

Patch

  • Auto-update: depends on '@devup-ui/react' via a local workspace dependency

@devup-ui/eslint-plugin@1.0.20 → 1.0.21 - packages/eslint-plugin/package.json

Patch

  • Fix the full WASM build panicking on every vanilla-extract .css.ts file (Boa read the clock without its js feature), resolve vanilla-extract references to other styles, keyframes, fonts and themes in selectors, values and globalStyle, keep globalCss pseudo selectors in SELECTOR_ORDER across breakpoints, merge adjacent rules with the same selector, and let declarations written next to a conditional typography preset win over it. Add the prefer-media-shorthand and no-typography-token-prefix ESLint rules

@devup-ui/next-plugin@1.0.88 → 1.0.89 - packages/next-plugin/package.json

Patch

  • Numbers in vanilla-extract and StyleX styles keep their library's meaning instead of Devup UI's spacing scale: vanilla-extract styles add px in .css.ts files and in style(), globalStyle() and keyframes() calls inside ordinary modules, StyleX adds px/ms to static values and to numbers passed to dynamic styles, and unitless properties such as columnCount, strokeWidth, orphans or zoom keep a bare number everywhere. The Next.js plugin now runs every .css.ts module on the full engine instead of a separate static fast path, so development and production builds produce the same output

@devup-ui/react@1.0.43 → 1.0.44 - packages/react/package.json

Patch

  • Fix at-rule composition and cascade: _print/_media/@media … nest correctly with selectors in both directions and inside globalCss, nested media queries merge (print and (…)), breakpoints put media types first, distribute query lists, and nest not … queries, and at-rules are emitted after all breakpoint values while pseudo selectors keep SELECTOR_ORDER across breakpoints. Add _motionReduce, _motionSafe, _portrait, _landscape, _contrastMore, _contrastLess and _forcedColors, remove the never-matching _speech, normalize query whitespace, support Emotion-style '@media …'/'&:hover' object keys, fix template literals losing declarations before @media or selectors around nested at-rules, apply typography conditionally under selectors, and drop stale global at-rules on re-extraction

@devup-ui/reset-css@1.0.30 → 1.0.31 - packages/reset-css/package.json

Patch

  • Auto-update: depends on '@devup-ui/react' via a local workspace dependency

@devup-ui/rsbuild-plugin@1.0.65 → 1.0.66 - packages/rsbuild-plugin/package.json

Patch

  • Auto-update: depends on '@devup-ui/wasm' via a local workspace dependency

@devup-ui/vite-plugin@1.0.71 → 1.0.72 - packages/vite-plugin/package.json

Patch

  • Auto-update: depends on '@devup-ui/wasm' via a local workspace dependency

@devup-ui/webpack-plugin@1.0.69 → 1.0.70 - packages/webpack-plugin/package.json

Patch

  • Auto-update: depends on '@devup-ui/wasm' via a local workspace dependency

@codecov

codecov Bot commented Sep 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
libs/css/src/at_rule.rs 100.00% <100.00%> (ø)
libs/css/src/lib.rs 100.00% <100.00%> (ø)
libs/css/src/style_selector.rs 100.00% <100.00%> (ø)
libs/css/src/theme_tokens.rs 100.00% <100.00%> (ø)
libs/extractor/src/css_utils.rs 100.00% <100.00%> (ø)
.../extractor/extract_global_style_from_expression.rs 100.00% <100.00%> (ø)
...tor/src/extractor/extract_style_from_expression.rs 100.00% <100.00%> (ø)
...tractor/src/extractor/extract_style_from_stylex.rs 100.00% <100.00%> (ø)
libs/extractor/src/import_alias_visit.rs 100.00% <100.00%> (ø)
libs/extractor/src/lib.rs 100.00% <100.00%> (ø)
... and 16 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@owjs3901

Copy link
Copy Markdown
Contributor Author

#681로 합쳤습니다. #676·#677·#678의 커밋을 main 위로 rebase한 종합 PR입니다.

@owjs3901 owjs3901 closed this Sep 29, 2026
owjs3901 added a commit that referenced this pull request Sep 30, 2026
…me values (#676, #677, #678) (#681)

* fix(extractor): give vanilla-extract and StyleX numbers their library units

vanilla-extract styles add px to numbers (in .css.ts files and in style/globalStyle/keyframes calls of ordinary modules) and StyleX adds px/ms to static and dynamic numbers, instead of Devup UI's spacing scale. The unitless property list now matches vanilla-extract's, so strokeWidth, columns, zoom, orphans and similar keep bare numbers everywhere.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(next-plugin): run every vanilla-extract stylesheet on the full engine

Remove the static .css.ts fast path so development and production builds evaluate stylesheets the same way and produce the same class names and CSS.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document library number units and the full vanilla-extract engine

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: add changepack for library number units and full engine

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): fix vanilla-extract evaluation and Emotion/styled-components object styles

vanilla-extract: name styles after the variable holding them instead of by call order, generate file-unique names for vars, containers, layers, fonts and theme variables, follow vanilla-extract's createVar/fallbackVar/createTheme/createGlobalTheme/contract/layer semantics, resolve styleVariants variants and transitive composition, and export plain values as data. Emotion and styled-components: numbers in object styles mean pixels, several style arguments or arrays merge, styled(tag, options) is a factory, and css() composes class names passed with rule objects. '@layer' records and a global '@layer' cover nested and responsive declarations, and typography presets yield to declarations written beside them.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(sheet): write layered rules like the others and let typography yield

Layered properties of any kind are written with the regular writer, one layer at a time, so a layer keeps breakpoints, selectors and at-rules. A typography atom skips the declarations its value lists as written beside it from the breakpoint they start at.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document library composition, vanilla-extract coverage and typography precedence

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: add changepack for compat, layer and typography fixes

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): build font faces without a branching loop

The loop left a region tarpaulin maps past the function on Linux; the output is unchanged.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): build font faces without closures

Tarpaulin's Linux report still attributed a line past the function to its closures; the output is unchanged.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): build the single font-face rule list without vec!

The vec! expansion is the region tarpaulin maps past the function on Linux; the output is unchanged.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): make declaring font faces infallible

Reading a rule list cannot fail, so the error path tarpaulin kept reporting as uncovered past the function is gone; the output is unchanged.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore(extractor): keep the font-face loop out of tarpaulin's report

Its output is asserted by test_font_faces; tarpaulin's Linux report maps the loop exit onto a line it never counts however the loop is written.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): declare font-face lists recursively

Shaped like compose so tarpaulin's Linux report maps its loop, and the coverage exclusion is gone again; the output is unchanged.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): build font-face rules without touching the collector

The callers store the rules, so the helper ends in its value; the output is unchanged.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): extract font faces through the library build

Tarpaulin merges the unit-test build and the library build that other targets link; the latter never ran the font-face helper, which left one region at zero. The helper is split into single-rule and list parts.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): keep custom property values verbatim

A number on a custom property was read as the spacing scale (--columns: 4 became 16px), which broke theme tokens and var() math. The vanilla-extract API now also runs through the library build in an integration test.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): cover a createVar declaration that cannot be read

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): fit the createVar signature on one line

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): split createVar into name and reference helpers

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): move the declared createVar branch into its own function

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(extractor): keep the declared createVar helper out of line

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): resolve placeholders through one selector function type

resolve took impl Fn, so the always-selector caller got its own copy whose plain class-name branch never runs; CI coverage reported that branch as uncovered. A fn pointer keeps one copy. createVar returns to its original shape.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): resolve a style reference outside a selector through the library

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): support styled-components attrs and withConfig, and every styled import

styled.x.attrs(a).withConfig(c) now extracts like styled.x: withConfig is dropped and the attrs are merged over the props in order, objects spread and functions called with the props. A file importing styled from several libraries extracts all of them instead of only the last.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): keep dynamic values and layered classes in their layer

A dynamic value inside '@layer' now carries the layer, and the layer is part of the class and variable name key, so a layered declaration no longer shares a class (and loses its layer) with the same unlayered one.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(sheet): place dynamic rules of a layer inside it

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): compose conditional style parts per property

css(base, cond && over) and ternaries of rule objects now merge into per-property ternaries (color: cond ? 'blue' : 'red'), since the order of two atomic classes is decided by the stylesheet, not by composition. Conditional class parts join as cond ? cls : '' so a falsy part no longer prints 'false', and Emotion's number-to-px conversion reaches conditional branches.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(sheet): put conditional typography below direct declarations

The declarations of a conditional typography preset now sit in the typography layer nested in their own origin (t, oN.t, b.t), like the theme's typography classes. A declaration written directly therefore wins whenever it applies, including one that only applies on a condition, which yielding alone could not decide.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): load the modules a stylesheet imports

A .css.ts file can now import other stylesheets and plain modules. Imports are resolved through a resolver the bundler supplies (extract_with_modules). A stylesheet is extracted the way the bundler extracts it and its output evaluated, so the names it exports are the ones its own CSS uses; other modules are run as they are. Every export form is supported, cycles are reported, the output keeps importing the stylesheets and side-effect imports it had, and the files read are returned as dependencies to watch.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): inline imported constants read by styles

With a module resolver, an import read in a style (props of the package's components, arguments of its functions) is looked up in its module; a string or number declared with const there (a literal, an as-const object's member, an alias, a re-export or a default export) replaces the read, so <Box color={PRIMARY} /> becomes a static class instead of a CSS variable. Only primitives are inlined and references are resolved by scope, so the output behaves the same; the modules read are returned as dependencies.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(wasm): resolve imports through setModuleResolver

setModuleResolver((specifier, importer) => ({ path, code })) lets codeExtract load the modules a file imports, and Output.dependencies lists the files it read for the bundler to watch.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(plugin-utils): add createModuleResolver

Resolves the imports of extracted files like the import graph does (relative paths, tsconfig paths, index files, and names like theme.css to theme.css.ts) and reads each module, naming it with the plugin's own toId so a module is extracted under the name the bundler uses.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(vite-plugin): load imported modules and watch them

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(webpack-plugin): load imported modules and depend on them

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(next-plugin): load imported modules and depend on them

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(rsbuild-plugin): load imported modules and depend on them

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(bun-plugin): load imported modules

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document module loading, imported constants and the new compatibility

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: add changepack for module loading and compatibility gaps

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): cover every path of imported constant inlining

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): compose || and ?? style parts and reject what cannot compose

left || right and left ?? right now compose like the other conditions: left as a class while it applies (only when it is a string, as the libraries skip other values), right per property otherwise. styled factories compose classes passed beside rule objects like css() does. Style arguments that cannot be composed at build time (a call, a spread, a computed key or a rule object replacing a value) are now a build error naming them instead of silently producing an empty class.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): evaluate import cycles like ES modules

A module is reserved before the modules it imports and exposes live bindings, so a cycle works when neither side reads the other before it is evaluated, and a read too early fails with a clear error naming the binding and module. Imports of a module still evaluating are read where they are used. A stylesheet loaded by another one reports its failure instead of falling back to plain extraction, and modules are parsed with their own source type (so .tsx and .js modules load).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): load CommonJS modules

A module without import or export that uses module, exports or require runs with its own module.exports; require of a literal path loads the module like an import, its keys become the exports, and the default follows bundler interop (the .default of a compiled ES module, module.exports otherwise).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): inline constants of CommonJS modules

exports.x = ..., module.exports.x = ... and module.exports = { ... } inline like export const, as long as the module assigns the property once (TypeScript's void 0 placeholders do not count), so a value that can change is never inlined. require() bindings are followed, and the default follows bundler interop.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(plugin-utils): resolve packages in createModuleResolver

Bare specifiers that no tsconfig path matches resolve in node_modules like a bundler: package exports (strings, arrays, conditions import > module > default > require > node, subpath maps with * patterns, null blocks), then module, main and index, including .cjs entries. Resolved files use their real path, as bundlers name symlinked installs.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): report an import cycle read too early instead of falling back

A stylesheet whose import cycle is read before it is evaluated fails as it does in ES modules (and in vanilla-extract) rather than falling back to plain extraction, whose output would still call the styling APIs.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document packages, CommonJS, import cycles and style composition errors

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): cover lazy default imports and reads without constants

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): reject runtime values without an element and place template interpolations

css(), globalCss(), keyframes() and stylex.create() now report a value known only at runtime instead of emitting an unset CSS variable or dropping it. Module-level consts inline without a resolver, with templates and arithmetic folded. Template interpolations are written into global and keyframes CSS, mixins compose their class, and unknown selector or property interpolations are build errors.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(next-plugin): keep the files an extraction read when it is prewarmed

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(eslint-plugin): accept constants the build inlines in css utils

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document runtime value errors, local constants and template interpolations

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): keep computed stylex keys runtime values and cover number strings

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(sheet): keep the important value dynamic now that local consts inline

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(sheet): cover a dynamic base style updating the base sheet

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(webpack-plugin): prewarm with the module resolver the loader uses

Without it, the prewarm extracted imported constants as CSS variables while the loader later emitted static classes, so a file merged into another file's CSS bucket could reference classes missing from the CSS webpack had already built.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): resolve imported StyleX values and locate every build error

StyleX defineVars, createThemeContract, defineConsts and createTheme values imported from another module resolve to the names that module generates, and every namespace or default StyleX import is recognized. A .css.ts file that throws while evaluated reports the exception when plain extraction would leave its calls uncompiled. Constant inlining builds scoping only when a style reads a name that may hold a constant. Build errors are reported together, in source order, as file:line:column, mapped back through the import alias rewrite.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document imported StyleX values, stylesheet evaluation errors and located build errors

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): support conditional StyleX variable and theme values

defineVars and createTheme values may be condition objects of default, @media, @supports and @container keys, optionally wrapped in types.*(). Each set of conditions becomes one block after the unconditional values, deeper conditions last so the more specific value wins. Importers resolve such variables to the same names, reading constant condition keys like [DARK] as the defining file does. A value that is not static is a build error instead of a silently missing variable.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document conditional StyleX variable and theme values

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): cover a spread in a StyleX variable condition

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): compute build-time style values and report every StyleX input it cannot read

Math.* calls over constants fold; a style value computed from constants runs through the full engine and becomes a static class. StyleX create/defineVars/defineConsts/createTheme/keyframes/positionTry/viewTransitionClass/include report spreads, computed keys and non-object arguments as located build errors, and props()/attrs() join styles compiled elsewhere at runtime.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(next-plugin): select the full engine when a file computes style values

The WASM bindings export hasBuildTimeValues, and selectWasmVariant loads the full engine when a candidate file has a style value only running the module computes.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document build-time computed values and StyleX build errors

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): cover build-time values and StyleX error branches

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): read constant objects, arrays and enums as styles and report styles it cannot read

Object, array and TypeScript enum constants, declared in the file or imported, are inlined where styles read them, a later property replacing an earlier one in style objects and among JSX props. A spread of an unknown object, a selector given a non-object, a computed key and a non-object globalCss/keyframes argument are build errors instead of silently missing; a single css()/styled argument composes as a class; a JSX literal spread keeps its non-style props; theme.colors[key] becomes a CSS variable; an index or key a spread may supply is read at runtime. The full engine computes values reached through a const or an import, spreads, shorthand properties, computed keys and conditions, standing in for the style packages and for modules it cannot load. Stylesheet evaluation no longer panics on TypeScript enums.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(next-plugin): detect computed style values after inlining constants

hasBuildTimeValues takes the import aliases and reads imported constants through the module resolver before deciding, so a file reading only constants keeps the lite engine and one reading a computed constant selects the full engine.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document constant style objects and styles the build cannot read

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): cover remaining build-time value and constant branches

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* feat(extractor): compose rules the module computes and map sources to the code as written

- css() and styled() compose a binding holding rules only running the module gives through the full engine; a class computed in its place is no longer read as CSS text

- build errors state what each engine accepts: constants, and with the full engine values computed from them

- source maps point at the code as written through rewritten imports and computed values

- an imported stylesheet runs once per script it evaluates to, and each module is stripped of TypeScript once

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(next-plugin): check styled compositions when choosing the engine

A file composing a binding with styled.div(...) or styled(...)(...) may hold rules only the full engine computes, so the engine choice checks it too.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(eslint-plugin): accept values the build computes in css utils

css-utils-literal-only follows what the engines read: calls of imported or module-level functions and built-ins over constants, Math folds, arrays, conditions and computed members of constants pass, while Date, Math.random and functions only known at runtime are reported. The README documents the computed values and the engine each needs.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document composed computed rules, engine-specific build errors and source maps

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): keep runtime values as written and compute what elements take

- A runtime value an element holds is written as it is: it was optimized as CSS text, so a string passed to a function lost digits and --i became var(--i)

- await, new, assignments, sequences and tagged templates reach the element instead of being dropped; a function or class is reported

- globalCss() used as a value gives undefined instead of invalid code, and a runtime condition in globalCss(), keyframes() or <Global> is a build error instead of being dropped; a condition the build knows picks its branch

- With the full engine, JSX spreads, selector props and the spreads, selectors and computed keys of styled objects compute what the module computes, as do css(...parts) and a template argument of css()

- A namespace or object of known classes no longer runs the module or needs the full engine, and a stylesheet that loops forever fails instead of hanging

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(next-plugin): check JSX spreads and selector props when choosing the engine

An element spreading or selecting a binding may take styles only the full engine computes, so the engine choice checks those files too.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document computed element styles, known conditions and runtime values

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): place a dynamic as where the element stands and read impure spreads once

- A component with a non-literal as (as={Link}, as={cond ? 'a' : 'b'}) is replaced where it stands. In JSX children it replaced its parent element or a later expression and left the component, which throws at runtime, in the output; in lists it lost its key inside a fragment

- A spread whose value may change when read again (<Box {...register('email')} />, a hook) is evaluated once, with the props and children written before it in order, where it was evaluated for the spread, the className and the style

- A literal spread no longer reads a className or style it does not write

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): tell nested members of partly known objects apart and cover every read-once path

- css(tokens.nested.x) is computed when the build knows tokens.nested but not its x: a member chain is resolved through the constants the build knows, where only the first member was checked

- Tests cover reading once in children, attribute elements, generators and compiled jsx() calls, the purity of each expression kind, and the conditions globalCss() cannot switch

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(css,extractor): cover value whitespace and calls of partly known objects

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: note the dynamic as and read-once spread fixes in the changepack

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(next-plugin): always load @devup-ui/wasm

- Every build loads the one extraction engine instead of scanning the project at startup to choose between the lite and full engines, so a file added while the dev server runs is extracted like the others

- The static import graph and the prewarm file list are built where they were before the engine choice moved them ahead of loading WASM

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* refactor(wasm): build one engine and drop @devup-ui/wasm/lite

- Boa is a plain dependency of the extractor, sheet and WASM crates instead of the vanilla-extract feature, so every build evaluates stylesheets and computes style values

- @devup-ui/wasm builds one package: the lite build, its ./lite export and hasBuildTimeValues, which only chose between the engines, are gone

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: describe one extraction engine

- The docs, the css-utils-literal-only README and the changepacks no longer mention the lite engine, hasBuildTimeValues or an engine Next.js picks: every build computes style values the module computes

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: add changepack for removing the lite engine

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): stop reading changed objects and the build environment as constants

- An object, array or enum constant that code the build sees changes (a member assignment, delete, ++, push, sort, Object.assign, or handing it to a function the build does not know) is read at runtime: elements read its members as CSS variables, and css(), styled() and element spreads taking it whole are build errors naming where it is changed. Handing on a string or number it holds, or putting it in a top-level const nothing changes, keeps it constant

- The module declaring an imported constant and the modules re-exporting it are checked too, and values computed at build time do not read a changed binding

- Values computed at build time cannot read window, document, navigator, location, process or globalThis properties the build does not define, so the CSS never holds the build environment's answer

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document changed objects and the build environment

- Objects, arrays and enums that visible code changes are read at runtime, taking one whole is a build error naming where it changes, and values computed at build time cannot read window, document, navigator, location, process or unknown globalThis properties

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: add changepack for changed objects and the build environment

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): cover spread arguments and the first argument Object functions change

- A spread argument of css() reading a changed binding is reported like any other argument, and the check for the argument Object.assign and friends change no longer hides in a match guard coverage cannot count

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): close the gaps in changed objects and build-environment values

- A changed object a namespace import or another object holds is a build error where css(), styled() or a spread takes it whole, where it was composed as a class; a value read from a changed object is never read as its declared value; CommonJS modules, element changes in for...of loops and forEach/map callbacks, and methods using this count as changes

- export default, module.exports, Object.freeze, Array.from, Object.keys and element props other than ref only read an object, so token objects stay static classes; a namespace import itself is never changed; notes tell a change from handing an object on and name the binding where it is changed

- Values computed at build time never read Intl or locale methods, directly or through variables and imports; a value reading a statement that threw or a module the build cannot load is not computed instead of taking a branch on a stand-in; a module checking the environment at its top still gives its other exports; console calls no longer stop a module or a .css.ts stylesheet; only the modules a computed value reads are loaded

- content, font-size-adjust and math-depth keep their numbers instead of scaling them to px

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(eslint-plugin): report constants the file changes in css-utils-literal-only

- A constant or an import the file changes through a member assignment, delete, ++, a destructuring target, a changing method or Object.assign is reported, as the build no longer reads it as written

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document what changes objects, the build environment and failed values

- Iteration, methods using this, CommonJS modules and namespace imports can change an object; export default, module.exports, Object.freeze and element props only read it; locale methods and Intl are unavailable, and nothing is computed from a failed statement or an unloadable module

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: add changepack for the runtime value gaps

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): only run build-time code whose result is certain

Values are computed from the file's own const, function and enum declarations with exact built-ins; imports are injected as the literals their modules declare and no other module runs. Uncertain code stays a CSS variable on elements and is a build error in css(), globalCss(), keyframes() and styled(). Constant conditions fold only where styles read them, objects holding booleans, undefined or functions are no longer taken as changed, times are milliseconds and counters keep their numbers.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(eslint-plugin): follow the strict build-time rules in css-utils-literal-only

Report calls of imported functions and of functions the build does not run, uncertain built-ins and members, changing elements in for...of loops and forEach/map callbacks, methods using this, and objects handed to unknown code, as the build decides them.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document the strict build-time rules and time units

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: add changepack for the strict build-time values

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): cover literal conditions and reads of partly known namespaces

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): read a member of a string a partly known namespace holds

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: leave the changepack of #675 as main has it

The Update Versions PR removes it once released, so a change here would conflict with that PR.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(extractor): read an array member of a partly known namespace

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): render what a dynamic as gives

undefined, null and false give the default element, a component or a member such as motion.div renders as named, a condition between names becomes an element for each, and any other value is read at runtime once, with the default element when it is empty. Member expressions rendered nothing, templates took their first part, lowercase variables became tags and lookups built every element. Build-time values read Math only through members with a known key and toString only called at once without a radix, so aliases no longer reach approximate functions.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(eslint-plugin): check every style argument and StyleX values in css-utils-literal-only

Values in every rule object and in the CSS text of css, globalCss, keyframes and createGlobalStyle are checked, tagged templates included, as are the StyleX functions devup-ui compiles; parts css() composes as classes stay unchecked, and styled() is left out as it keeps values as CSS variables. Aliases of Math and toString read other than called at once are reported, as the build reads them.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* docs: document dynamic as, styled values and times in .css.ts files

A dynamic as renders what it gives, styled() keeps uncertain values as CSS variables like elements, and a number for a time in a .css.ts file gets px as in vanilla-extract.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: add changepack for dynamic as and wider lint checks

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(extractor): read style results as values and never leave removed imports read

A const holding what keyframes() or css() gives is read by the other style APIs and computed selector keys; the package imported whole compiles; styled() renders any base; top-level aliases of compiled imports compile and are removed, other runtime reads of removed imports and unknown selectors keys are build errors.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* fix(eslint-plugin): read css() and keyframes() results held in a const as static

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* chore: add changepack for style results as values

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

* test(components): inline the spinner keyframes name as a static class

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant