Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
bba27a2
fix(parser): guard FileImage behind kIsWeb, declare platforms
anilcancakir Jun 7, 2026
bddc906
fix(parser): set max-w-prose to 512px fixed width
anilcancakir Jun 7, 2026
fa5bee8
fix(widgets): semanticLabel overrides child text, preserves activation
anilcancakir Jun 7, 2026
43542df
fix(parser): preserve null decoration in WindStyle.copyWith
anilcancakir Jun 7, 2026
df89ab2
fix(widgets): skip Container on shadow-none
anilcancakir Jun 7, 2026
90334b2
fix(dynamic): coerce malformed type/children in WDynamicRenderer
anilcancakir Jun 7, 2026
0732a58
feat(theme): value equality and hashCode for WindThemeData
anilcancakir Jun 7, 2026
609ead1
docs(widgets): document WInput controller/onChanged contract
anilcancakir Jun 7, 2026
270b75c
docs(debug): correct field-count comment in debug resolver
anilcancakir Jun 7, 2026
32b310f
docs: sync user-facing reference under doc/
anilcancakir Jun 7, 2026
b428390
docs(skill): sync wind-ui skill and references
anilcancakir Jun 7, 2026
5972954
docs: sync top-level overview and changelog
anilcancakir Jun 7, 2026
2f3fa9d
docs(ci): sync copilot and claude agent rules
anilcancakir Jun 7, 2026
5e44ffe
docs(example): dark pairs and realistic demo content
anilcancakir Jun 7, 2026
8b1a236
refactor(api): lock down public barrel, hide internal classes
anilcancakir Jun 7, 2026
9fa0af9
docs(widgets): add WKeyboardActions and WindAnimationWrapper referenc…
anilcancakir Jun 7, 2026
88f1b22
docs(example): add WKeyboardActions and WindAnimationWrapper demo pages
anilcancakir Jun 7, 2026
1ceb57b
docs(skill): list WKeyboardActions and WindAnimationWrapper in llms a…
anilcancakir Jun 7, 2026
2f981b1
docs: align max-w-prose references to 512px
anilcancakir Jun 7, 2026
a588f88
docs: align semanticLabel docs to override behavior
anilcancakir Jun 7, 2026
0ee5792
docs(changelog): log kIsWeb guard, max-w-prose 512, semanticLabel ove…
anilcancakir Jun 7, 2026
83501bc
docs(api): add dartdoc_options.yaml with GitHub source links
anilcancakir Jun 7, 2026
4e1f56c
docs(widgets): add See also cross-links to core widget DartDoc
anilcancakir Jun 7, 2026
23f423a
docs(widgets): fix broken Related Documentation links in wind-animati…
anilcancakir Jun 7, 2026
7504bc7
docs(changelog): correct removed parser class list to actual barrel e…
anilcancakir Jun 7, 2026
f052ecc
docs(widgets): document semanticLabel excludeSemantics caveat and tes…
anilcancakir Jun 7, 2026
642ff16
fix(debug): guard resolver against className-less W-widgets
anilcancakir Jun 8, 2026
2072b6b
refactor(api): rename DatePickerMode to WDatePickerMode
anilcancakir Jun 8, 2026
52042c9
feat(parser): self-* align-self alias and fix shrink-0 no-op
anilcancakir Jun 8, 2026
75feaab
docs(changelog): log live-QA fixes (resolver, WDatePickerMode, self-*…
anilcancakir Jun 8, 2026
4c7b102
fix(parser): revert shrink-0 flexFit mapping (preserve intrinsic size)
anilcancakir Jun 8, 2026
25ab1fd
docs: sync self-* alias, resolver robustness, brightness gotcha for 1…
anilcancakir Jun 8, 2026
aff50cf
fix(review): address PR #94 review feedback
anilcancakir Jun 8, 2026
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
4 changes: 2 additions & 2 deletions .claude/rules/dynamic.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Unknown action names are silently ignored (debugPrint only). Handler exceptions
## Known bugs (test-documented)

- **`WSelect<String>` + null value crash.** When `WSelect` receives simple string options and no initial `value`, the renderer infers `WSelect<String>`; the state-init expects non-nullable `String` and throws `type 'Null' is not a subtype of type 'String'`. The renderer's per-type catch path swallows it and emits the red error widget. Workaround for consumers: pass map-typed options or an explicit initial value. Out-of-scope follow-up to fix renderer-side.
- **`WDatePicker.onChange` asymmetry.** `_buildWDatePicker` uses `parseAction(props['onChange'])` (no `_value` injection) instead of `parseValueAction<DateTime>`. To get the selected date, callers must read `state.get(id)` from inside the action handler, not args. Inconsistent with WInput/WCheckbox/WSelect; documented for awareness.
- **`WDatePicker.onChange` API asymmetry (not a defect).** The renderer DOES write the selected date to state before dispatch (`state.set(id, date)` then the action callback). The asymmetry is delivery: because `_buildWDatePicker` uses `parseAction(props['onChange'])` rather than `parseValueAction<DateTime>`, the `DateTime` arrives via `state.get(id)`, not via the action `args._value`. Callers read the date from state inside the handler. Inconsistent with WInput/WCheckbox/WSelect, which inject `_value`; documented for awareness.

## Custom widgets via `builders`

Expand All @@ -89,7 +89,7 @@ Custom builders bypass the whitelist; they ARE the whitelist for their type. Use

## Custom icons via `customIcons`

`WIcon` inside JSON resolves icon names through `_parseIcon`. 25 built-in mappings (`home`, `star`, `person`, ...). Override or extend via `customIcons` map: `{ 'rocket': Icons.rocket_launch }`.
`WIcon` inside JSON resolves icon names through `_parseIcon`. 24 built-in mappings (`home`, `star`, `person`, ...). Override or extend via `customIcons` map: `{ 'rocket': Icons.rocket_launch }`.

## What never goes in `lib/src/dynamic/`

Expand Down
1 change: 1 addition & 0 deletions .claude/rules/parsers.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class FooParser implements WindParserInterface {
- `canParse(String className)` is O(1). Use `startsWith()` or a pre-compiled `static final RegExp`. No heavy logic.
- `parse` returns `styles.copyWith(...)` for every mutation. Never returns null. Never mutates the input list.
- The orchestrator's first-match-wins routing means `canParse` order matters: more specific prefixes register before more general ones. Registration is in `lib/src/parser/wind_parser.dart`'s `_parserMap` (a const map of const parser instances).
- `copyWith` does not fabricate an empty `BoxDecoration`. Pass `decoration:` only when setting a real visual box property (color, border, radius, shadow, gradient, image), so the downstream `decoration != null` Container gate stays honest.

## Last-class-wins semantics

Expand Down
6 changes: 6 additions & 0 deletions .claude/rules/widgets.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ When `styles.debug == false` (the default), every logger method is a no-op — o

When a new widget needs interaction state from a className prefix, follow `WDiv`'s pattern (`_buildImpl` inside a `Builder`); do not bypass `WAnchor`.

`WButton` / `WAnchor` accept `semanticLabel: String?`, forwarded to the `Semantics` node wrapping the interactive surface. New WAnchor-based widgets expose and forward it the same way (matters for icon-only controls with no visible text).

## className multi-line

For 3+ concerns in one className, use triple-quoted strings, one concern per line, grouping `dark:` pairs beside their light variants:
Expand All @@ -77,6 +79,10 @@ className: '''
''',
```

## Container elision

A `Container` is emitted only when `styles.decoration != null` OR a non-empty `boxShadow` / `ringShadow` exists. Padding-only, text-only, and `shadow-none` paths must stay Container-free. `WindStyle.copyWith` must NOT fabricate an empty `BoxDecoration`, or the `decoration != null` gate breaks and every styled widget grows a needless Container.

## What never goes in `lib/src/widgets/`

- Test helpers — those live in `test/`.
Expand Down
8 changes: 4 additions & 4 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ Utility-first Flutter UI plugin. Translates `className` strings (Tailwind syntax

```
lib/src/
├── widgets/ # 20 W-prefix widgets (WDiv, WText, WButton, WSvg, WDynamic...)
├── widgets/ # 22 W-prefix widgets (WDiv, WText, WButton, WSvg, WDynamic...)
├── parser/
│ ├── wind_parser.dart # Orchestrator — routes tokens to 17 parsers
│ ├── wind_parser.dart # Orchestrator — routes tokens to 19 parsers
│ ├── wind_style.dart # Immutable style value object (parse output)
│ ├── wind_context.dart # Theme + breakpoint + brightness + platform + states
│ └── parsers/ # 17 domain parsers (bg, border, flex, text, shadow...)
│ └── parsers/ # 19 domain parsers (bg, border, flex, text, shadow...)
├── theme/
│ ├── wind_theme.dart # WindTheme widget + WindThemeController
│ ├── wind_theme_data.dart # Config: colors, screens, spacing, fonts
Expand All @@ -23,7 +23,7 @@ lib/src/
└── utils/ # Extensions, helpers, color utils, logger
```

**Data flow:** `className` → WindParser.parse() → 17 parsers (first-match-wins) → WindStyle → Widget.build()
**Data flow:** `className` → WindParser.parse() → 19 parsers (first-match-wins) → WindStyle → Widget.build()

**Cache key:** className + breakpoint + brightness + platform + sorted states

Expand Down
10 changes: 5 additions & 5 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ How the package is organized internally. Companion to [README.md](README.md) (th

```
lib/src/
├── widgets/ # 20 user-facing W-prefix widgets (see .claude/rules/widgets.md)
├── widgets/ # 22 user-facing W-prefix widgets (see .claude/rules/widgets.md)
├── parser/
│ ├── wind_parser.dart # Orchestrator: first-match-wins routing to 17 parsers
│ ├── wind_parser.dart # Orchestrator: first-match-wins routing to 19 parsers
│ ├── wind_style.dart # Immutable value object (parse output)
│ ├── wind_context.dart # Theme + breakpoint + brightness + platform + states
│ └── parsers/ # 17 domain parsers (see .claude/rules/parsers.md)
│ └── parsers/ # 19 domain parsers (see .claude/rules/parsers.md)
├── theme/
│ ├── wind_theme.dart # WindTheme StatefulWidget + WindThemeController
│ ├── wind_theme_data.dart # 23 configurable fields; merges with defaults/
Expand All @@ -31,7 +31,7 @@ className: String
WindParser.parse(className, context, states:)
17 domain parsers (first match wins)
19 domain parsers (first match wins)
WindStyle (immutable value object)
Expand Down Expand Up @@ -60,7 +60,7 @@ WindTheme(

## Diagnostics bridge

Call `Wind.installDebugResolver()` inside `kDebugMode` to expose 6 fields (`className`, `breakpoint`, `brightness`, `platform`, `states`, `bgColor`, `textColor`) to any consumer of `WindDebugRegistry.current` (e.g., `fluttersdk_dusk` for E2E and any runtime inspector). Idempotent; gated by `kDebugMode` so release builds tree-shake it. There is no `WindDuskIntegration` class in v1.0 — replaced by this bridge via the `fluttersdk_wind_diagnostics_contracts` contract.
Call `Wind.installDebugResolver()` inside `kDebugMode` to expose 7 fields (`className`, `breakpoint`, `brightness`, `platform`, `states`, `bgColor`, `textColor`) to any consumer of `WindDebugRegistry.current` (e.g., `fluttersdk_dusk` for E2E and any runtime inspector). Idempotent; gated by `kDebugMode` so release builds tree-shake it. There is no `WindDuskIntegration` class in v1.0 — replaced by this bridge via the `fluttersdk_wind_diagnostics_contracts` contract.

## Widget API surface (invariants locked at 1.0.0)

Expand Down
24 changes: 19 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This project follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.

---

## [1.0.0] - 2026-05-27
## [1.0.0] - TBD

First stable release. wind is utility-first, Tailwind-syntax styling for Flutter; v1.0.0 is a complete rewrite of the 0.0.x line with a fresh API surface, a 19-parser pipeline with cached resolution, dark-mode pairs as a first-class contract, and a contracts-based debug bridge for external tooling. All public APIs follow Semantic Versioning 2.0.0 from this point forward.

Expand All @@ -30,37 +30,49 @@ First stable release. wind is utility-first, Tailwind-syntax styling for Flutter
- **CSS positioning utilities**: `relative`, `absolute`, `top-*`, `right-*`, `bottom-*`, `left-*`, `inset-*`, `inset-x-*`, `inset-y-*`, plus negative variants (`-top-*`, `-inset-*`) and arbitrary-px values (`top-[24px]`).
- **Child order utilities**: `order-0` through `order-12`, `order-first`, `order-last`, `order-none`, plus arbitrary `order-[n]` (including negatives) for reordering flex children without changing source order.
- **Reverse flex direction**: `flex-row-reverse` and `flex-col-reverse` flip the main-axis direction so `justify-start` mirrors per CSS semantics.
- **`self-*` align-self shorthand**: `self-start`, `self-end`, `self-center`, `self-stretch`, `self-auto`, `self-baseline` as aliases for the `align-self-*` long form, matching Tailwind's canonical class name.
- **Inline color props**: `WDiv.backgroundColor` and `WText.foregroundColor` for runtime-dynamic colors. Override any `bg-*` / `text-*` from className and stay out of the parser cache key.
- **`WBreakpoint` widget**: declarative per-breakpoint widget tree builder. Reach for it when className prefixes are not enough because the widget structure itself changes between breakpoints.
- **`WDynamic`**: JSON-driven widget tree renderer. 13 Wind types + 16 Flutter core types allowed by default, extensible via `builders:`, restrictable via `denyWidgets:`, with `customIcons:` for user-defined icon mappings (25 built-in glyphs). State binding by widget `id`, action dispatch via `WActionHandler`, max recursion depth 50.
- **Accessibility / Semantics** on 7 interactive widgets (`WAnchor`, `WButton`, `WInput`, `WFormInput`, `WCheckbox`, `WSelect`, `WDatePicker`): emit `Semantics` nodes with role + label, password fields mark `obscured`. Enables Playwright `getByRole` / `getByLabel` / `getByText` resolution against the Flutter web build. New optional `WInput.semanticLabel` parameter.
- **`WDynamic`**: JSON-driven widget tree renderer. 13 Wind types + 16 Flutter core types allowed by default, extensible via `builders:`, restrictable via `denyWidgets:`, with `customIcons:` for user-defined icon mappings (24 built-in glyphs). State binding by widget `id`, action dispatch via `WActionHandler`, max recursion depth 50.
- **Accessibility / Semantics** on 7 interactive widgets (`WAnchor`, `WButton`, `WInput`, `WFormInput`, `WCheckbox`, `WSelect`, `WDatePicker`): emit `Semantics` nodes with role + label, password fields mark `obscured`. Enables Playwright `getByRole` / `getByLabel` / `getByText` resolution against the Flutter web build. New optional `semanticLabel` parameters on `WInput`, `WButton`, and `WAnchor`; the button/anchor label gives icon-only controls an accessible name when there is no child text for `MergeSemantics` to absorb.
- **`Wind.installDebugResolver()`**: call inside `kDebugMode` to register a `WindDebugResolverImpl` against the new `fluttersdk_wind_diagnostics_contracts` bridge. Resolves 7 fields per Wind widget element: `className`, `breakpoint`, `brightness`, `platform`, `states`, conditional `bgColor`, conditional `textColor`. Consumed by `fluttersdk_dusk` for E2E snapshot capture and by any runtime inspector. Tree-shaken in release builds.
- **`wind-ui` skill v2.0.1 community pattern**: `skills/wind-ui/SKILL.md` section 15 plus `skills/wind-ui/references/community.md` add opt-in star + issue-report CTAs surfaced once per session after a verified Wind task or a genuine wind-side bug. Prose-permission only, never auto-executed, `gh auth status`-gated. (#89)
- **`wind-ui` skill v2.0.2 community pattern**: `skills/wind-ui/SKILL.md` section 15 plus `skills/wind-ui/references/community.md` add opt-in star + issue-report CTAs surfaced once per session after a verified Wind task or a genuine wind-side bug. Prose-permission only, never auto-executed, `gh auth status`-gated. (#89)

@coderabbitai coderabbitai Bot Jun 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Correct the wind-ui skill version in the 1.0.0 notes.

This bullet says v2.0.2, but the PR summary says the skill was bumped to v2.0.3; keeping this mismatched can mislead consumers during upgrade checks.

Based on learnings from the PR objectives (“skill bumped to v2.0.3”), the changelog version reference should match the shipped artifact.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` at line 39, Update the mismatched version string in the
CHANGELOG entry that currently reads "`wind-ui` skill v2.0.2 community pattern"
to reflect the shipped artifact version v2.0.3 so the changelog matches the PR
summary; locate the bullet containing "`skills/wind-ui/SKILL.md` section 15" /
"`skills/wind-ui/references/community.md`" and replace "v2.0.2" with "v2.0.3".

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changing this. The v2.0.2 here is correct: the community CTA pattern shipped in PR #89 at skill v2.0.2 (git history confirms the 2.0.1 -> 2.0.2 bump landed with that feature). The current 2.0.3 is an unrelated self-* doc bump in this PR. The bullet attributes the feature to its actual shipping version; raising it to 2.0.3 would misattribute it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anilcancakir, that's a clear and correct distinction — the bullet documents the version at which the community CTA feature shipped (#89, v2.0.1 → v2.0.2), not the current skill version. Attributing it to v2.0.3 would indeed misrepresent its origin. My comment was mistaken; the v2.0.2 here is accurate.


✏️ Learnings added
Learnt from: anilcancakir
Repo: fluttersdk/wind PR: 94
File: CHANGELOG.md:39-39
Timestamp: 2026-06-08T13:21:51.990Z
Learning: In `CHANGELOG.md` for the `fluttersdk/wind` project, skill version references in feature bullets (e.g., "`wind-ui` skill vX.Y.Z community pattern") are intentionally pinned to the version at which that specific feature shipped, not the latest skill version. For example, the community CTA pattern shipped in PR `#89` at skill v2.0.2 (a 2.0.1 → 2.0.2 bump), so the bullet correctly reads "v2.0.2" even when the skill has subsequently been bumped to v2.0.3 for unrelated changes. Do not flag these version references as mismatches against the current skill version.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: Applies to skills/wind-ui/**/*.md : Update `skills/wind-ui/SKILL.md` (trigger keywords, Core Laws, Layout Reality) and matching `skills/wind-ui/references/<topic>.md` when adding a new widget, parser token family, theme field, or breaking change to className semantics

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/instructions/parsers.instructions.md:0-0
Timestamp: 2026-05-26T21:58:29.735Z
Learning: Applies to lib/src/parser/**/*.dart : `WindStyle` is immutable — properties are nullable. Merge with existing: `pTop ?? styles.padding?.top ?? 0`

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-05-26T21:58:02.826Z
Learning: Update `skills/wind-ui/SKILL.md` when API or widget changes occur

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-05-26T21:58:02.826Z
Learning: Applies to lib/src/parser/wind_style.dart : Add new properties to `WindStyle` as immutable values using the `copyWith` method pattern

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: Applies to skills/wind-ui/SKILL.md : Bump `skills/wind-ui/SKILL.md` frontmatter version when API surface changes

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: Applies to README.md : Update `README.md` only for overview-worthy changes: new widget added to public roster, new top-level feature (theme field, parser token family, integration entry point), public API addition/removal. Skip internal refactors, test additions, doc fixes, and dependency tweaks

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/instructions/widgets.instructions.md:0-0
Timestamp: 2026-05-26T21:58:48.756Z
Learning: Applies to lib/src/widgets/**/*.dart : All widgets use `W` prefix: `WDiv`, `WButton`, `WText`, `WFormInput`, `WSvg`

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-05-26T21:58:02.826Z
Learning: Update `README.md` when new widgets, features, or API changes are introduced

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/instructions/widgets.instructions.md:0-0
Timestamp: 2026-05-26T21:58:48.756Z
Learning: Applies to lib/src/widgets/**/*.dart : Use `WindParser.parse(className, WindContext.of(context), states: states)` — always with context

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: Applies to CHANGELOG.md : Add every behavior-changing source change to `CHANGELOG.md` under the right semantic-version section (Unreleased or current version) and subsection (Added, Changed, Fixed, Removed, Quality, Security)

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: All code changes must trigger the post-change sync (five surfaces: doc/, example/lib/pages/, skills/wind-ui/, CHANGELOG.md, README.md) in the same change set before reporting work complete — skipping any surface is a bug


### Changed

- **BREAKING.** Complete API rewrite from 0.0.x. The legacy `lib/src/parsers/` (28 modules) and `lib/src/components/` (8 modules) directories were deleted and reimplemented under `lib/src/parser/parsers/` and `lib/src/widgets/`. Class names `WText`, `WDiv`, `WButton` are preserved but their constructor signatures, the className token set they accept, and theme integration differ. Not source-compatible with v0.
- **BREAKING.** Flutter SDK minimum raised from `>=3.3.0` to `>=3.27.0`. Dart SDK constraint set to `>=3.4.0 <4.0.0`.
- **BREAKING.** Parser cache is now always on. The opt-in `trackProvenance` flag on `WindParser.parse()` and the `WindStyle.resolvedVia` field are gone; debug-tooling consumers read widget state through `Wind.installDebugResolver()` and the `fluttersdk_wind_diagnostics_contracts` contract package instead.
- **BREAKING.** The public `DatePickerMode` enum is renamed to `WDatePickerMode`. The old name collided with Flutter Material's own `DatePickerMode`, forcing any consumer importing both `package:flutter/material.dart` and the wind barrel to `hide` one symbol. `WDatePicker` / `WFormDatePicker` `mode:` now takes `WDatePickerMode`.

### Removed

- **BREAKING.** `WindDuskIntegration` class and the `lib/dusk_integration.dart` sub-barrel. Replaced by `Wind.installDebugResolver()` from the main barrel.
- **BREAKING.** `fluttersdk_dusk` as a wind dependency at any level. Consumers needing Dusk for their own E2E add it to their own pubspec.
- **BREAKING.** `google_fonts` and `platform_info` dependencies. Consumers depending on them transitively must add explicit deps.
- **BREAKING.** `WindParser.parse(trackProvenance:)` parameter, `WindStyle.resolvedVia` field, and the `enableProvenance()` toggle. The contracts-based diagnostic bridge does not require provenance instrumentation.
- **BREAKING.** 13 internal parser classes (`AspectRatioParser`, `BackgroundParser`, `BorderParser`, `FlexboxGridParser`, `MarginParser`, `OpacityParser`, `OverflowParser`, `PaddingParser`, `RingParser`, `SizingParser`, `TextParser`, `TransitionParser`, `ZIndexParser`), `WindPlatformService`, `WindLogger`, `LogEntry`, `WDynamicRenderer`, and `WindDebugResolverImpl` are no longer exported from the public barrel (`package:fluttersdk_wind/fluttersdk_wind.dart`). These were always internal implementation details; any consumer referencing them by name must remove those references. The public widget and theme API is unaffected.

### Fixed

- Background image parser (`bg-[/abs/path]`): the `FileImage(File(...))` branch is now guarded by `kIsWeb`; on web, where `dart:io` `File` is unsupported, the image degrades gracefully (skipped) instead of throwing at runtime. Non-web behavior is unchanged. `pubspec.yaml` now declares explicit platform support (`android`, `ios`, `macos`, `web`, `linux`, `windows`) so pub.dev platform detection is not narrowed by the `dart:io` import graph.

@coderabbitai coderabbitai Bot Jun 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use canonical platform casing (macOS) in release notes.

Use macOS instead of macos for consistency with platform naming across docs and ecosystem conventions.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~58-~58: The operating system from Apple is written “macOS”.
Context: ...cit platform support (android, ios, macos, web, linux, windows) so pub.dev...

(MAC_OS)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` at line 58, Update the platform name casing in the release
notes by replacing the lowercase token "macos" with the canonical "macOS" in the
sentence describing declared platform support (the string listing `android`,
`ios`, `macos`, `web`, `linux`, `windows`) in CHANGELOG.md so it reads
`android`, `ios`, `macOS`, `web`, `linux`, `windows`; preserve all other
punctuation and wording.

Source: Linters/SAST tools

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipping. macos is the literal lowercase pubspec.yaml platform key (flutter: platforms: macos:), shown here as a backticked code identifier, not OS prose. macOS would not match the actual pubspec key.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anilcancakir — Good catch, you're right. The values are backtick-wrapped pubspec.yaml platform keys (android, ios, macos, web, linux, windows), where macos is the literal key name, not prose. Applying macOS casing there would create a mismatch with the actual manifest. My suggestion was incorrect here.


✏️ Learnings added
Learnt from: anilcancakir
Repo: fluttersdk/wind PR: 94
File: CHANGELOG.md:58-58
Timestamp: 2026-06-08T13:21:50.984Z
Learning: In the fluttersdk/wind repository, backticked platform identifiers in CHANGELOG.md (e.g., `android`, `ios`, `macos`, `web`, `linux`, `windows`) represent literal `pubspec.yaml` platform keys, not prose OS names. Do not flag `macos` as a casing issue in this context — it must remain lowercase to match the actual pubspec platform key.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/instructions/parsers.instructions.md:0-0
Timestamp: 2026-05-26T21:58:29.735Z
Learning: Applies to lib/src/parser/**/*.dart : `WindStyle` is immutable — properties are nullable. Merge with existing: `pTop ?? styles.padding?.top ?? 0`

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: example/CLAUDE.md:0-0
Timestamp: 2026-05-26T21:59:19.863Z
Learning: Applies to example/pubspec.yaml : Maintain `fluttersdk_wind: { path: ../ }` as a local path dependency in pubspec.yaml; do not bump to a pub.dev version

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: Applies to skills/wind-ui/**/*.md : Update `skills/wind-ui/SKILL.md` (trigger keywords, Core Laws, Layout Reality) and matching `skills/wind-ui/references/<topic>.md` when adding a new widget, parser token family, theme field, or breaking change to className semantics

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-05-26T21:58:02.826Z
Learning: Applies to lib/src/parser/wind_style.dart : Add new properties to `WindStyle` as immutable values using the `copyWith` method pattern

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: Applies to pubspec.yaml : Maintain Flutter >=3.27.0, Dart >=3.4.0; runtime dependencies: flutter_svg, fluttersdk_wind_diagnostics_contracts; no mockito, no state management library, no router

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/instructions/parsers.instructions.md:0-0
Timestamp: 2026-05-26T21:58:29.735Z
Learning: Applies to lib/src/parser/**/*.dart : Cache key = className + breakpoint + brightness + platform + sorted states. Call `WindParser.clearCache()` in tests

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-05-26T21:58:02.826Z
Learning: Applies to lib/src/parser/**/*.dart : Support arbitrary values using bracket syntax (e.g., `w-[200px]`, `text-[`#FF0000`]`)

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/instructions/parsers.instructions.md:0-0
Timestamp: 2026-05-26T21:58:29.735Z
Learning: Applies to lib/src/parser/**/*.dart : Every parser implements `WindParserInterface` with exactly two methods: `canParse()` and `parse()`

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: Applies to README.md : Update `README.md` only for overview-worthy changes: new widget added to public roster, new top-level feature (theme field, parser token family, integration entry point), public API addition/removal. Skip internal refactors, test additions, doc fixes, and dependency tweaks

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-05-26T21:58:02.826Z
Learning: Update `README.md` when new widgets, features, or API changes are introduced

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-05-26T21:58:02.826Z
Learning: Update `skills/wind-ui/SKILL.md` when API or widget changes occur

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: Applies to CHANGELOG.md : Add every behavior-changing source change to `CHANGELOG.md` under the right semantic-version section (Unreleased or current version) and subsection (Added, Changed, Fixed, Removed, Quality, Security)

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: Applies to skills/wind-ui/SKILL.md : Bump `skills/wind-ui/SKILL.md` frontmatter version when API surface changes

Learnt from: CR
Repo: fluttersdk/wind PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-27T21:52:14.303Z
Learning: All code changes must trigger the post-change sync (five surfaces: doc/, example/lib/pages/, skills/wind-ui/, CHANGELOG.md, README.md) in the same change set before reporting work complete — skipping any surface is a bug

- `max-w-prose`: corrected value from 1040 px (65 × 16, an incorrect approximation) to 512 px, matching the actual parser output. Docs and skill references updated accordingly.
- `WButton` / `WAnchor` `semanticLabel`: the `Semantics` node now sets `excludeSemantics: true` and lifts `onTap`/`onLongPress` onto itself when `semanticLabel` is set, so the label overrides any child text instead of concatenating with it under `MergeSemantics`, while activation is preserved.
- `Wind.installDebugResolver()`: the resolver no longer crashes on a className-less W-widget. `WindDebugResolverImpl.resolve` guarded its dynamic `className` read, so a bare `WAnchor` (or `WBreakpoint` / `WindAnimationWrapper` / `WKeyboardActions`) in the tree no longer throws `NoSuchMethodError` and abort the entire `fluttersdk_dusk` / telescope diagnostic snapshot.
- `WInput`: `px-*` horizontal padding now matches the requested value exactly; `OutlineInputBorder.gapPadding` is set to `0.0` so `px-3` produces a 12 px inset instead of 16 px. Multiline geometry unchanged. (#61)
- `WindParser.findAndGroupClasses`: duplicate tokens flow through to the parser pipeline so the documented last-class-wins contract holds on repeated overrides like `top-8 top-4 top-8`; previously `.toSet()` dropped the trailing occurrence.
- `WindParser.parse`: cache is bypassed in both directions (no read, no write) when `baseStyle` is non-null so per-call styles do not return stale cached entries or poison the cache slot for default-flag callers.
- `example/lib/routes.dart`: six widget routes (`/widgets/w-input-multiline`, `/widgets/w-input-search`, `/widgets/w-popover-alignment`, `/widgets/w-select_multi`, `/widgets/w-select_single`, `/widgets/w-text-transform`) renamed to snake_case to match their page-file basenames so live doc iframes at `wind.fluttersdk.com/preview/widgets/<key>` resolve. Two dead pages (`layout/grid_basic`, `layout/order`) without documentation references were removed.
- `BackgroundParser`: `bg-[#hex]` arbitrary-color backgrounds no longer also resolve to a bogus `AssetImage("assets/#hex")`. The image regex now excludes `#`-leading bracket values so a hex literal is parsed only as a color, eliminating a stray failed asset fetch on every arbitrary-hex background.
- `WindStyle.copyWith`: a padding-, margin-, or text-only style keeps `decoration == null` instead of fabricating an empty `BoxDecoration`. This stops `WDiv`/`WText` from wrapping a needless `Container` around non-decorated content. `shadow-none` likewise no longer forces a Container.
- `WDynamicRenderer`: malformed JSON degrades gracefully. A non-string `type` or non-list `children` is coerced defensively (routed through the whitelist / treated as no children) instead of throwing an implicit-downcast `TypeError` out of `build()`.
- `WindThemeData`: implements value-based `operator ==` and `hashCode`. The equality guards in `WindThemeController.setTheme` and `_WindThemeState.didUpdateWidget` now compare by value, so a fresh default `WindThemeData()` on a parent rebuild no longer clobbers a prior `toggleTheme()` choice or triggers spurious full-tree rebuilds.

### Quality

- 1,214 tests across 82 test files; line coverage 90.2% (CI gate enforces `>= 90%` via `./tool/coverage.sh 90`).
- 1,224 tests across 83 test files; line coverage 90.3% (CI gate enforces `>= 90%` via `./tool/coverage.sh 90`).
- New regression coverage in `test/parser/wind_parser_cache_test.dart` for the last-class-wins-on-duplicates and `baseStyle`-bypasses-cache contracts.
- New regression coverage for the arbitrary-hex background (`background_parser_test.dart`), `decoration`-stays-null contract (`wind_style_test.dart`), malformed-JSON graceful degradation (`w_dynamic_renderer_test.dart`), `WindThemeData` value equality (`wind_theme_data_test.dart`), and icon-only button Semantics label (`w_button_test.dart`).
- `tool/coverage.sh` portable threshold-aware lcov wrapper; GitHub Actions gate fails any PR dropping below 90%.
- Surgical `// coverage:ignore-line` pragmas only on lines structurally unreachable from `flutter test` (`kDebugMode` branches, `dart:io` `Platform.is*` branches not matching the CI host). Each pragma carries a one-line WHY comment.

Expand All @@ -71,3 +83,5 @@ Production deps: `flutter` (SDK), `flutter_svg ^2.0.0`, `fluttersdk_wind_diagnos
## Previous versions

The 1.0.0-alpha.1 through 1.0.0-alpha.10 release notes (Feb 2026 to May 2026) are preserved in git history and on the `v0` branch. The 0.0.x line is end-of-life; consumers pin to `^1.0.0` going forward.

[1.0.0]: https://github.com/fluttersdk/wind/releases/tag/1.0.0
Loading