fix: restore camelCase support in setPrefixedStyle - #1139
Conversation
setPrefixedStyle used CSSStyleDeclaration.setProperty, which only accepts kebab-case names. Every camelCase call site was therefore a silent no-op, including the transformOrigin write in CellEditorHandler that keeps the cell editor overlay aligned with the label when the graph is zoomed. The vendor prefixed write was dead for every input spelling: the prefix is built by capitalizing the first character, producing webkit-cased names such as WebkitTransformOrigin, which setProperty always discards. Restore the property assignment used by mxGraph, which accepts both spellings for the standard property and the webkit-cased name for the prefixed one. It requires a cast to compile, which is what commit 61648e4 was avoiding when it introduced the regression, so a comment now records why the assignment is deliberate. Both call sites are left untouched, as their existing camelCase arguments become correct again. Document in the JSDoc that camelCase is required to reach the vendor prefixed path, and cover the function with tests, including the kebab-case limitation and the per-browser prefixes. Fixes #1046
Walkthrough
ChangesPrefixed style assignment
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 41cd3090-674b-462d-aae6-62b808fb5122
📒 Files selected for processing (2)
packages/core/__tests__/util/styleUtils.test.tspackages/core/src/util/styleUtils.ts
CSS custom properties have no attribute on CSSStyleDeclaration, unlike standard properties which expose camel-cased, dashed and webkit-cased attributes. Assigning one only creates a JavaScript property and no CSS declaration, so switching this function to property assignment would have dropped support for calls such as setPrefixedStyle(style, '--overlay-offset', '10px'). That support does not come from mxGraph, which had the same limitation as the assignment. It appeared as a side effect of the switch to setProperty and has been available for four years, so it is preserved rather than silently removed. Route names starting with -- through setProperty and return early, since custom properties are never vendor prefixed.
|



Problem
setPrefixedStylewrites CSS properties withCSSStyleDeclaration.setProperty, which only accepts kebab-case names. Any camelCase name is lowercased, matches no known property, and is silently discarded.The reported symptom is the cell editor:
CellEditorHandlercallssetPrefixedStyle(this.textarea.style, 'transformOrigin', '0px 0px'), so the textarea never receives its transform origin and the editing overlay is visibly offset from the cell label at any zoom level other than 1x.The vendor prefixed write was broken too, for every input spelling. The prefix is built by capitalizing the first character of the name, which produces webkit-cased names such as
WebkitTransformOrigin. Those are CSSOM IDL attribute spellings, not CSS property names, sosetPropertydiscards them as well. Feeding the function a kebab-case name does not help either: it yields the meaninglessWebkitTransform-origin. Consequently the prefixed write inRubberBandHandler('transition') has also been dead, even though its standard write happens to work, single word names surviving the lowercasing intact.Root cause
Commit 61648e4, a large "Converting *Handlers into plugins. Keep resolving errors" refactor, changed exactly two lines of this function:
style[name] = valuedoes not compile here (TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'), so this was a type error being silenced during a mass refactor, not a deliberate API change. The kebab-case requirement was never chosen, and the JSDoc has kept documenting camelCase ever since.Fix
Restore the property assignment used by
mxGraph, with the cast that commit was avoiding:Property assignment reaches the CSSOM camel-cased, dashed and webkit-cased attributes, so both writes work again. A comment records why the assignment is deliberate, so it does not get "fixed" back to
setProperty.Both call sites are left untouched: their existing camelCase arguments become correct again, rather than needing to change.
CSS custom properties are the one case that must keep using
setProperty, so they get an early return before the prefix logic:Unlike standard properties, a custom property has no attribute on
CSSStyleDeclaration, so assigning one would create a JavaScript property and no CSS declaration at all, and it is never vendor prefixed. This capability is not inherited frommxGraph, which used assignment and had the same limitation: it appeared as a side effect of 61648e4, the very commit that introduced the bug fixed here. It has been available for four years, so it is preserved rather than silently removed.Vendor prefixing is deliberately kept rather than removed. It is very likely obsolete (
transform-originandtransitionhave been unprefixed for over a decade, the browser detection relies on user agent sniffing, and the project targets modern browsers only), but the impact on external consumers calling this exported utility for other properties is unknown, so removing it belongs in its own change.Documented limitation
The mangling only produces a valid name from camelCase input, which the JSDoc now states explicitly:
Tests
The function had no test coverage. 14 cases added in
packages/core/__tests__/util/styleUtils.test.ts, each written before the corresponding fix and confirmed to fail against the previous implementation (7 failures for the camelCase standard write plus every vendor prefixed write, then 3 more for the custom properties):RubberBandHandlerwritename.length > 0guard for an empty nameWebkitTransform-origin, so the JSDoc warning has an executable counterpartcssTextis exactly--overlay-offset: 10px;so a JavaScript property masquerading as a CSS declaration cannot passTwo implementation notes.
Client.IS_SFistrueby default under jsdom, so each test sets the browser flags explicitly instead of inheriting the environment; those flags are global mutable state, captured before any test runs and restored after each one. And jsdom implements no vendor prefixed CSS property, so a prefixed assignment lands as a plain JavaScript property on the declaration, which a helper reads. That is the only way this path is observable in jsdom, and it works precisely because the fix uses assignment rather thansetProperty.Validation
npm test -w packages/core: 535 tests passed, 60 suitesnpm run test-check -w packages/coreandtsc --noEmit: cleannpm run lint: clean✔️ Not covered by automated tests: the visual outcome. The tests prove
transform-originreaches the textarea style, not that the overlay aligns on screen. Manual check for a reviewer: open Storybook, zoom to a non-1x level, double-click a cell, and confirm the editor lines up with the label.Fixes #1046
Summary by CodeRabbit
Summary by CodeRabbit
Bug Fixes
Tests