1111 * :style="'opacity: ' + (cond ? '0.5' : '1') + '; ...'"
1212 * :style="someStringProp"
1313 *
14- * Delegates to `style-to-js` (a ~1 KB inline-style parser built on
15- * `inline-style-parser`) invoked with `{ reactCompat: true }`. That single
16- * call subsumes both the declaration parse and the kebab→camel key
17- * conversion this helper used to perform by hand:
18- * - parses the gotchas a naive split-on-`;` misses — quoted strings with
19- * semicolons (`content: 'foo;bar'`), `url(data:…;base64,…)` data URIs,
20- * inline comments, `!important`;
21- * - camelCases keys, capitalizing vendor prefixes the way React/Solid
22- * style objects expect (`-webkit-mask` → `WebkitMask`) and passing CSS
23- * custom properties (`--foo`) through verbatim.
14+ * SOLID DIFFERENCE (LB6 SEAM 3) — a CSS STRING is passed through VERBATIM and
15+ * left for Solid's own `style()` runtime helper to apply. Solid applies an
16+ * object-form `style` by iterating keys into `CSSStyleDeclaration.setProperty(
17+ * key, value)`, which requires a KEBAB-case CSS property name — a camelCased
18+ * key (`paddingLeft`) is a silent no-op (verified against solid-js@1.9.x
19+ * `web.cjs` `style()`). Earlier this helper camelCased declarations (via
20+ * `style-to-js`'s `reactCompat: true`), so a dynamic `:style` returning
21+ * `'padding-left:1.75rem'` became `{ paddingLeft: '1.75rem' }` → DROPPED on
22+ * Solid (single-word props like `overflow` survived; the data-table expander
23+ * depth-indent `padding-left` did not). Solid's `style()` routes a STRING to
24+ * `node.style.cssText`, where the browser's own CSS parser handles every
25+ * declaration correctly — so passing the string through is both simpler and
26+ * strictly more correct than re-parsing into a camelCased object the Solid
27+ * runtime then mis-applies.
2428 *
25- * Replaced postcss (2026-06-04). postcss was the ONLY dependency these
26- * runtime packages leaked into a consumer bundle (~24 KB gzip) and it was
27- * reachable solely through this helper; style-to-js is ~1.5 KB gzip and
28- * produces byte-identical output for the inline-declaration subset. A
29- * differential test (`parseInlineStyle.parity.test.ts`) pins the new output
30- * to the prior postcss implementation, kept as the oracle in devDependencies.
31- *
32- * Crash-safety (SPEC-1): the runtime path has no diagnostic stream, so a
33- * parse failure must never escape as an exception — `style-to-js` throws on
34- * some malformed input, so the call is wrapped to degrade to `{}`.
29+ * An already-built style OBJECT (a `$computed` returning a CSS-custom-property
30+ * map such as `{ '--rozie-slider-fill-start': '50%' }`) is passed through
31+ * unchanged — Solid's `setProperty` handles custom properties regardless of
32+ * casing.
3533 *
3634 * @public — runtime API consumed by emitted .tsx files.
3735 */
3836import type { JSX } from 'solid-js' ;
39- import styleToJS from 'style-to-js' ;
4037
4138const KEBAB_TO_CAMEL_CACHE = new Map < string , string > ( ) ;
4239
@@ -48,9 +45,12 @@ const KEBAB_TO_CAMEL_CACHE = new Map<string, string>();
4845 * --custom-prop → --custom-prop (CSS custom properties pass through)
4946 * font-size → fontSize
5047 *
51- * Retained as a public export (and used by the differential parity test's
52- * oracle); the main `parseInlineStyle` path now gets key conversion from
53- * `style-to-js` directly.
48+ * Retained as a public kebab→camel utility. NOTE (LB6 SEAM 3): the
49+ * `parseInlineStyle` path no longer camelCases at all — a CSS string is handed
50+ * to Solid's `style()` (cssText) verbatim, so this helper is no longer on that
51+ * path. It stays exported for tooling / consumers that key a Solid style object
52+ * directly. (Solid's `setProperty` actually wants KEBAB keys, so prefer the raw
53+ * CSS property name for Solid style objects — this camelCaser is React-shaped.)
5454 */
5555export function toStyleObjectKey ( prop : string ) : string {
5656 const cached = KEBAB_TO_CAMEL_CACHE . get ( prop ) ;
@@ -81,28 +81,28 @@ export function toStyleObjectKey(prop: string): string {
8181 *
8282 * A dynamic `:style` binding's runtime value is NOT statically known to the
8383 * emitter, so this helper accepts the union the author may produce:
84- * - a CSS string (`'opacity: 0.5; color: red'`) → parsed via `style-to-js`;
84+ * - a CSS string (`'opacity: 0.5; color: red'`) → passed through VERBATIM so
85+ * Solid's `style()` helper applies it via `cssText` (LB6 SEAM 3);
8586 * - an already-built style object (a `$computed` returning a
8687 * CSS-custom-property map such as `{ '--rozie-slider-fill-start': '50%' }`,
8788 * or a plain style object) → passed through verbatim;
8889 * - `null` / `undefined` → `{}`.
8990 *
90- * Returning `JSX.CSSProperties` keeps the value assignable to Solid's `style`
91- * JSX prop, whose index signature permits CSS custom properties (`--x`).
92- * Returns `{}` for empty, whitespace-only, or unparseable input — never throws
93- * (see crash-safety note above).
91+ * The return type `string | JSX.CSSProperties` is exactly Solid's `style` JSX
92+ * prop type, so the emitted `style={parseInlineStyle(<expr>)}` is well-typed.
93+ * Returns `{}` for empty / whitespace-only input — never throws.
9494 */
9595export function parseInlineStyle (
9696 value : string | JSX . CSSProperties | Record < string , string | number > | null | undefined ,
97- ) : JSX . CSSProperties {
97+ ) : JSX . CSSProperties | string {
9898 if ( value == null ) return { } ;
9999 // Already an object (e.g. a CSS-custom-property map from a `$computed`) —
100100 // pass through; Solid's `style` prop accepts custom properties.
101101 if ( typeof value === 'object' ) return value as JSX . CSSProperties ;
102102 if ( value . length === 0 || / ^ \s * $ / . test ( value ) ) return { } ;
103- try {
104- return styleToJS ( value , { reactCompat : true } ) as JSX . CSSProperties ;
105- } catch {
106- return { } ;
107- }
103+ // A CSS string — hand it to Solid's `style()` runtime, which sets it via
104+ // `node.style.cssText`. The browser's CSS parser applies every (kebab-case)
105+ // declaration correctly, including multi-word props like `padding-left` that
106+ // a camelCased `setProperty` key would silently drop.
107+ return value ;
108108}
0 commit comments