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
37 changes: 0 additions & 37 deletions .changeset/core-audit-improvements.md

This file was deleted.

35 changes: 0 additions & 35 deletions .changeset/react-audit-improvements.md

This file was deleted.

33 changes: 33 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,38 @@
# @react-pixel-ui/core

## 2.2.0

### Minor Changes

- [#6](https://github.com/Todari/react-pixel-ui/pull/6) [`911fbb0`](https://github.com/Todari/react-pixel-ui/commit/911fbb0448c849451a5e697373ceb8767380d239) Thanks [@Todari](https://github.com/Todari)! - 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 `<Pixel>`/`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.

## 2.1.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@react-pixel-ui/core",
"version": "2.1.0",
"version": "2.2.0",
"description": "Core engine for @react-pixel-ui/react. Generates pixel art styles from CSS. Install @react-pixel-ui/react directly.",
"keywords": [
"pixel",
Expand Down
36 changes: 36 additions & 0 deletions packages/react/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
# @react-pixel-ui/react

## 2.2.0

### Minor Changes

- [#6](https://github.com/Todari/react-pixel-ui/pull/6) [`911fbb0`](https://github.com/Todari/react-pixel-ui/commit/911fbb0448c849451a5e697373ceb8767380d239) Thanks [@Todari](https://github.com/Todari)! - React layer fixes: stable DOM across re-measures, resize awareness, StrictMode-safe observers, working responsive mode, and API hardening.

**`<Pixel>`**
- 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 `<input>` 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 `<Pixel>` for unparseable backgrounds.

**`<PixelBox>`**
- `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).

**`<PixelButton>`**
- Unknown `variant` values fall back to `primary` with a dev warning instead of crashing with a `TypeError`.
- The rendered `<button>` defaults to `type="button"` so dropping it into a form no longer submits the form; an explicit `type` prop still wins.

**Misc**
- `PixelConfigProvider` no longer crashes when rendered without a `config` prop (it is now optional).
- `usePixelArt` memoizes by the radius values, so inline per-corner arrays (`borderRadius={[8,8,0,0]}`) no longer regenerate the art on every parent re-render; it also skips generating the unused composite PNG.
- `PixelBox`/`PixelButton` expose proper `displayName`s in React DevTools (no more `PixelBox2`).
- ESM consumers under `moduleResolution: node16/nodenext` get the ESM declaration file via per-condition `exports` types, and the `"use client"` banner no longer shifts source maps by one line.

### Patch Changes

- Updated dependencies [[`911fbb0`](https://github.com/Todari/react-pixel-ui/commit/911fbb0448c849451a5e697373ceb8767380d239)]:
- @react-pixel-ui/core@2.2.0

## 2.1.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@react-pixel-ui/react",
"version": "2.1.1",
"version": "2.2.0",
"description": "Wrap any element with <Pixel> and your CSS becomes pixel art. Tailwind, inline styles, CSS modules — all supported. No Canvas, SSR compatible.",
"keywords": [
"react",
Expand Down