Skip to content

Commit afef14b

Browse files
committed
Bind a node's border weight
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0147gqWiq3xoEdAGwWSpq9JK
1 parent ffbf94b commit afef14b

3 files changed

Lines changed: 55 additions & 2 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
whether a mouse is over it as `${hovered}`, which it and the nodes inside
1515
it can bind for hover borders, fills and colors. The hold progress reaches
1616
the held node's own properties too.
17+
- `strokeWeight` can be bound, set by a condition or changed by an action,
18+
for a border that thickens when picked or hovered.
1719
- An expanded child whose bound `flex` is 0 takes no space, where it used to
1820
keep its design size.
1921

‎lib/src/transformers/passive_transformer_manager.dart‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ class PassiveNodeTransformerManager extends WidgetNodeTransformerManager {
179179

180180
/// Returns [node] with the style properties that conditions, bound
181181
/// variables or formulas, or set value actions give it at runtime: `fill`
182-
/// (a text's color for text nodes), `stroke`, `opacity`, `width` and
183-
/// `height`. Returns [node] itself when
182+
/// (a text's color for text nodes), `stroke`, `strokeWeight`, `opacity`,
183+
/// `width` and `height`. Returns [node] itself when
184184
/// nothing changes it.
185185
BaseNode applyStyleOverrides(BuildContext context, BaseNode node) {
186186
final ScopedValues scopedValues = ScopedValues.of(context);
@@ -208,6 +208,10 @@ class PassiveNodeTransformerManager extends WidgetNodeTransformerManager {
208208
for (final paint in geometry.strokes.skip(1)) paint.toJson(),
209209
];
210210
}
211+
final double? strokeWeight = value<double>('strokeWeight');
212+
if (strokeWeight != null && strokeWeight != geometry.strokeWeight) {
213+
patch['strokeWeight'] = math.max(0, strokeWeight).toDouble();
214+
}
211215
}
212216
if (node is TextNode) {
213217
// A text's fill is its color: it replaces the color of every span.

‎test/style_overrides_test.dart‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,51 @@ void main() {
149149
),
150150
);
151151
});
152+
153+
testWidgets('a bound strokeWeight thickens the border', (tester) async {
154+
final RectangleNode node = RectangleNode.fromJson({
155+
...RectangleNode(
156+
id: 'tile',
157+
name: 'Tile',
158+
basicBoxLocal: NodeBox(0, 0, 40, 40),
159+
strokes: [
160+
PaintModel.solid(id: 's', color: ColorRGB.fromHex('#FFC21A')),
161+
],
162+
strokeWeight: 1,
163+
).toJson(),
164+
'variables': {'strokeWeight': r'${= if(picked, 3, 1)}'},
165+
})..parentID = kRootNode;
166+
final manager = PassiveNodeTransformerManager(
167+
(id) => node,
168+
(context, bounds, pageID, layoutID, canvasID) => const SizedBox(),
169+
);
170+
final Observable<VariableData> picked = Observable(
171+
VariableData(
172+
id: 'picked',
173+
name: 'picked',
174+
type: VariableType.boolean,
175+
value: false,
176+
),
177+
);
178+
late double weight;
179+
Future<void> pump() => tester.pumpWidget(
180+
ChangeNotifierProvider<CodelesslyContext>.value(
181+
value: CodelesslyContext.empty()..variables['picked'] = picked,
182+
child: Builder(
183+
builder: (context) {
184+
weight = (manager.applyStyleOverrides(
185+
context,
186+
node,
187+
) as GeometryMixin).strokeWeight;
188+
return const SizedBox();
189+
},
190+
),
191+
),
192+
);
193+
await pump();
194+
expect(weight, 1);
195+
picked.set(picked.value.copyWith(value: true));
196+
await pump();
197+
expect(weight, 3);
198+
});
152199
}

0 commit comments

Comments
 (0)