conceptadev / conceptadev/mix

Chaining transform methods overrides instead of composing

Open
#893 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Dart
Stars
800
Forks
49
Avg merge
3h 39m
Merged PRs (30d)
22

Description

## Description

When chaining multiple transform methods on `BoxStyler` (e.g., `scale()` then `translate()`), the last transform completely replaces the previous one instead of composing them.

## Steps to Reproduce

```dart
final style = BoxStyler()
.scale(1)
.translate(0, 10);

Box(style: style, child: child);
```

## Expected Behavior

Both transforms should be applied: the box should be scaled **and** translated. The resulting `Matrix4` should be the composition (multiplication) of both transform matrices.

## Actual Behavior

Only the last transform (`translate`) is applied. The `scale` is silently discarded.

## Root Cause

Each transform method (defined in `TransformStyleMixin`) calls `transform(matrix)` which creates a new `BoxStyler` with that single `Matrix4` and merges it. During merge, `Prop.mergeProp()` correctly accumulates both Matrix4 sources. However, during resolution in `Prop.resolveProp()`, because `Matrix4` is not a `Mix` type, it falls into the **replacement strategy** (`resolvedValue = values.last`) instead of composing (multiplying) the matrices.

**Key code path:**
- `TransformStyleMixin.scale()` / `.translate()` → `transform(Matrix4)` → creates new styler and merges
- `Prop.mergeProp()` accumulates sources: `[scaleMatrix, translateMatrix]`
- `Prop.resolveProp()` resolves with `values.last` → only `translateMatrix` is returned

## Affected Methods

All transform helpers in `TransformStyleMixin` are affected when chained together:
- `scale()`
- `translate()`
- `rotate()`
- `skew()`

Any combination of two or more of these will result in only the last one being applied.

## Possible Solution

Stop using `Container`'s `transform` property for these operations. Instead, each transform method (`scale`, `translate`, `rotate`, `skew`) should use `wrap()` behind the scenes to apply the respective `ModifierMix. This way, each chained call adds its own independent `Modifier` widget in the widget tree, so they naturally compose without needing Matrix4 multiplication logic in the `Prop` resolution system.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start at TransformStyleMixin's scale(), translate(), rotate(), and skew() methods, then trace transform() into Prop.mergeProp() and Prop.resolveProp(). Reproduce the chained BoxStyler example and inspect the resulting widget or Matrix4 behavior. Done means every combination of chained transforms preserves and applies all transforms, with coverage for the affected helpers.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, flutter
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.