diff --git a/.changeset/core-audit-improvements.md b/.changeset/core-audit-improvements.md deleted file mode 100644 index 7c44a58..0000000 --- a/.changeset/core-audit-improvements.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -"@react-pixel-ui/core": minor ---- - -Core engine overhaul: real PNG compression, full CSS color support, gradient correctness, and graceful degradation. - -**Performance** - -- The PNG encoder now uses a built-in dependency-free DEFLATE (fixed Huffman + LZ77) instead of uncompressed stored blocks — generated data URLs are **30–100× smaller** (e.g. a 600×400 card went from ~78 KB to ~2.4 KB), with a stored-block fallback for incompressible data. -- `generatePixelArt` accepts `options.want: 'styles' | 'composite' | 'both'` so consumers skip generating the PNG they discard (~2× faster for gradient cases). Default `'both'` keeps backward compatibility. -- `generatePixelArt` results are cached in a small LRU keyed by inputs — hover/theme/re-render churn no longer regenerates identical art. Treat returned objects as immutable. - -**Color parsing** - -- All 148 CSS named colors are now supported (previously 14 — `lime`, `navy`, `teal`, `tomato`, `gold`, `rebeccapurple`, … no longer fail to parse). -- New: `color(srgb … )`, `color(srgb-linear …)`, and `color(display-p3 …)` — Chromium serializes computed `color-mix()` results as `color(srgb …)`, so `color-mix()` now works end-to-end through ``/`usePixelRef`. -- `rgb()`/`rgba()` patterns are anchored, so colors embedded in unsupported values (e.g. `conic-gradient(rgb(255,0,0), …)`) are no longer misparsed as a solid color. - -**Gradients** - -- Tailwind v4 interpolation hints are handled: `linear-gradient(to right in oklab, …)` no longer silently falls back to `to bottom`. -- Angle units `turn`, `rad`, and `grad` are converted correctly (previously only `deg` worked). -- Corner keywords (`to top right`, …) now resolve to the aspect-ratio-dependent "magic corner" angle per CSS spec via the new `resolveGradientAngle(gradient, width, height)` export, instead of a fixed 45° multiple. -- Double-position stops (`red 0% 50%`) expand into two stops, preserving hard color edges. -- Stops with `px` positions or one unparseable stop no longer corrupt the whole gradient (the `-1` position sentinel can no longer leak into sampling). - -**Correctness & safety** - -- `generatePixelShadow` no longer forces zero offsets to `pixelSize` — `box-shadow: 0 4px 0` stays a straight shadow instead of turning diagonal. Offsets snap to the nearest grid line; all-zero shadows are skipped entirely. -- `generateCompositePixelImage` keeps the interior **transparent** for border-only elements (previously it filled the content area with the border color), and returns `null` when a background is present but unparseable (`url()`, `conic-gradient()`, …) so consumers can leave the original styling untouched. -- `parseComputedStyles` resolves percentage `border-radius` (e.g. `border-radius: 50%` avatars) against the element size via a new optional `size` parameter, and handles elliptical two-value radii. -- `parseBoxShadow` detects the `inset` keyword anywhere in the serialization — real browsers put it at the END in computed styles, so inset shadows were previously converted into outer drop-shadows. Multiple shadows are split correctly and the first non-inset one is used. -- Every exported generator sanitizes `pixelSize` — `pixelSize: 0` no longer hangs the tab (infinite loop) or throws `RangeError`. - -**Packaging** - -- ESM consumers under `moduleResolution: node16/nodenext` now get the ESM declaration file (`index.d.mts`) via per-condition `exports` types — fixes the attw "Masquerading as CJS" failure and wrong CJS-interop type errors. diff --git a/.changeset/react-audit-improvements.md b/.changeset/react-audit-improvements.md deleted file mode 100644 index 1c0ba59..0000000 --- a/.changeset/react-audit-improvements.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -"@react-pixel-ui/react": minor ---- - -React layer fixes: stable DOM across re-measures, resize awareness, StrictMode-safe observers, working responsive mode, and API hardening. - -**``** - -- The drop-shadow wrapper no longer remounts the child DOM node on every re-measure (theme toggle, style change). Once a shadow wrapper exists it stays in the tree (`display: contents` while measuring), so uncontrolled `` values, focus, and selection survive. -- A `ResizeObserver` now watches the child: responsive/percentage-width elements re-measure when their size changes (stale absolute-px clip-paths are regenerated), and elements that mount at zero size (inside `display: none` tabs/accordions) get pixel art as soon as they become visible — previously they never did. -- Backgrounds the engine can't pixelate (`url()` images, `conic-gradient()`) are left untouched instead of being replaced with `background: none` + a transparent PNG (elements no longer go invisible or flash solid red). -- Author `box-shadow` is only cleared when it is actually replaced by a pixel shadow — inset-only shadows are preserved. - -**`usePixelRef`** - -- The style observer is created inside an effect instead of the ref callback. Under React 18 StrictMode (the Vite/Next dev default) the simulated remount previously disconnected the observer permanently, freezing all hover/focus/resize updates in development. -- Borderless elements with a `box-shadow` get their pixelated drop-shadow again — the hook only read `wrapperStyle.filter`, which the composer only sets when a border wrapper is needed, so shadows were silently deleted. When the element has no clip-path the filter now applies to the element itself instead of its parent. -- Same graceful-degradation behavior as `` for unparseable backgrounds. - -**``** - -- `responsive` mode actually works now: the component no longer pins its own measured fallback (`200×100`) as inline px width/height, which made the ResizeObserver only ever read back the forced size. Size the box with your own CSS (`style={{ width: '100%', height: 120 }}`) and the pixel art follows it. Measurement uses the border box. -- `className`, `style`, and other HTML props now consistently land on the **root** element (previously `style` landed on the inner content div when a border was used, so `margin` etc. silently did nothing). - -**``** - -- Unknown `variant` values fall back to `primary` with a dev warning instead of crashing with a `TypeError`. -- The rendered `