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
33 changes: 31 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,29 @@ jobs:
fi
echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT"

# Release notes come from CHANGELOG.md. A stable release must have its own dated section;
# a prerelease uses its section if present, otherwise the Unreleased section.
- name: Extract release notes from CHANGELOG.md
run: |
VERSION="${GITHUB_REF_NAME#v}"
if eng/changelog-section.sh "$VERSION" > release-notes.md; then
echo "Using the [$VERSION] section of CHANGELOG.md"
elif [[ "$VERSION" == *-* ]]; then
eng/changelog-section.sh Unreleased > release-notes.md
echo "Prerelease: using the [Unreleased] section of CHANGELOG.md"
else
echo "::error::CHANGELOG.md needs a '## [$VERSION] - <date>' section before $VERSION can be released."
exit 1
fi
printf '\n**Full changelog:** https://github.com/%s/blob/%s/CHANGELOG.md\n' "$GITHUB_REPOSITORY" "$GITHUB_REF_NAME" >> release-notes.md

- name: Upload release notes
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-notes
path: release-notes.md
if-no-files-found: error

# ─────────────────────────────────────────────────────────────────────────────
# 2. Pack KumikoUI.Core and KumikoUI.SkiaSharp (plain net10.0 — Linux is fine)
# ─────────────────────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -314,13 +337,19 @@ jobs:
done

# ── GitHub Release ─────────────────────────────────────────────────────
- name: Download release notes
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: release-notes
path: notes

# Runs for tag pushes and for manual runs against a tag (the only refs resolve-version accepts).
- name: Create GitHub Release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
with:
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }}
body_path: notes/release-notes.md
draft: false
prerelease: ${{ contains(github.ref_name, '-') }}
generate_release_notes: true
files: publish/*.nupkg
68 changes: 60 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,78 @@
# Changelog

All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
All notable changes to KumikoUI are documented in this file. All four packages (KumikoUI.Core, KumikoUI.SkiaSharp, KumikoUI.Maui, KumikoUI.Uno) share one version.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) as described in [docs/VERSIONING.md](docs/VERSIONING.md). Each release's section is also used as its GitHub release notes.

## [Unreleased]

### Added
- **KumikoUI.Uno**: a new package hosting the grid on the Uno Platform (Windows App SDK, desktop on Windows/macOS/Linux, WebAssembly, Android, iOS) with the same engine, rendering and features as KumikoUI.Maui, plus `KumikoFonts` for registering custom fonts from app assets, and the `SampleApp.Uno` sample.
- `DataGridStyle.PinBottomSummaryRows` (default `true`): `Position=Bottom` table summary rows are pinned to the bottom of the viewport as a fixed footer instead of scrolling after the last row. **Behaviour change** for existing users of bottom summaries; set it to `false` to restore the previous layout.

### Changed
- **Breaking:** minimum OS versions raised and unified across KumikoUI.Maui and KumikoUI.Uno: iOS 17.0 (was 15.0 on MAUI, 14.2 on Uno), Mac Catalyst 17.0 (was 15.0, which current Xcode toolchains reject), Android API 24 (was 21), Windows 10.0.19041 (was 10.0.17763 on MAUI). Defined once in `Directory.Build.props` and re-baselined at each .NET major.
- **Breaking:** SkiaSharp 4.153.1 (was 3.119.2) for KumikoUI.SkiaSharp, KumikoUI.Maui and KumikoUI.Uno, which changes the native SkiaSharp library in every consuming app. **Uno apps must set `<SkiaSharpVersion>4.153.1</SkiaSharpVersion>`** in their csproj: Uno.Sdk's implicit SkiaSharp packages default to 3.x, and the app must resolve the same major as KumikoUI. KumikoUI.Uno also references the SkiaSharp packages Uno's runtime pulls at 3.x (`SkiaSharp.Views`, `SkiaSharp.NativeAssets.Linux`, `SkiaSharp.Skottie`), so the whole graph resolves one major.
- **Breaking:** KumikoUI.Core, KumikoUI.SkiaSharp and every KumikoUI.Uno head now target .NET 10 (`net10.0`, `net10.0-*`); `net9.0` is dropped because .NET 9 support ends 2026-11-10. KumikoUI.Maui already targeted .NET 10. Apps must target .NET 10.
- Supply-chain hardening: Dependabot (NuGet and GitHub Actions, grouped weekly), CodeQL analysis, OpenSSF Scorecard, read-only workflow tokens by default, and every GitHub Action pinned to a commit SHA at its current major (checkout v7, setup-dotnet v6, upload-artifact v7, download-artifact v8, action-gh-release v3).
- Releases are gated: publishing requires approval in the `nuget-publish` environment and passing Core and Uno test suites; `main` and `v*` tags are protected by rulesets kept in `.github/settings/`. CI now runs on every pull request to `main`, including documentation-only changes, and no longer runs for `develop`.
- Package versions come from git tags (MinVer); project files no longer contain `<Version>1.0.0</Version>`, so a local `dotnet pack` now produces a prerelease such as `0.2.0-alpha.0.8` instead of a misleading `1.0.0`. Copyright metadata uses a fixed year, and symbol packages are produced by default.
- **Breaking:** minimum OS versions raised and unified across KumikoUI.Maui and KumikoUI.Uno: iOS 17.0 (was 15.0 on MAUI, 14.2 on Uno), Mac Catalyst 17.0 (was 15.0, which current Xcode toolchains reject), Android API 24 (was 21), Windows 10.0.19041 (was 10.0.17763 on MAUI). Defined once in `Directory.Build.props` and re-baselined at each .NET major.
- KumikoUI.Uno package description no longer claims a Mac Catalyst head (macOS is served by the desktop head).
- KumikoUI.Maui now declares an explicit minimum of `Microsoft.Maui.Controls` 10.0.20 instead of whatever MAUI version the build machine had installed.
- KumikoUI.Uno is built with Uno.Sdk 6.7.30 (was 6.5.31).
- **Breaking:** SkiaSharp 4.153.1 (was 3.119.2) for KumikoUI.SkiaSharp, KumikoUI.Maui and KumikoUI.Uno, which changes the native SkiaSharp library in every consuming app. **Uno apps must set `<SkiaSharpVersion>4.153.1</SkiaSharpVersion>`** in their csproj: Uno.Sdk's implicit SkiaSharp packages default to 3.x, and the app must resolve the same major as KumikoUI. KumikoUI.Uno also references the SkiaSharp packages Uno's runtime pulls at 3.x (`SkiaSharp.Views`, `SkiaSharp.NativeAssets.Linux`, `SkiaSharp.Skottie`), so the whole graph resolves one major.
- **Breaking:** KumikoUI.Core, KumikoUI.SkiaSharp and every KumikoUI.Uno head now target .NET 10 (`net10.0`, `net10.0-*`); `net9.0` is dropped because .NET 9 support ends 2026-11-10. KumikoUI.Maui already targeted .NET 10. Apps must target .NET 10.

### Added
- `DataGridStyle.PinBottomSummaryRows` (default `true`): `Position=Bottom` table summary rows are pinned to the bottom of the viewport as a fixed footer instead of scrolling after the last row. **Behaviour change** for existing users of bottom summaries; set it to `false` to restore the previous layout.

### Fixed
- An unknown font family now falls back to the default family in the requested weight and slant instead of producing a null typeface. Styled typefaces are resolved through `SKFontManager` with an explicit family, which SkiaSharp 4 needs to keep bold and italic.
- Taps on the pinned summary footer no longer select or edit the data row behind it; unpinned bottom summary rows are also reported as `HitRegion.TableSummaryRow`.
- Keyboard navigation keeps the current row fully visible between the header/frozen rows and the pinned footer, and accounts for the grouping panel and top summary rows (previously the scroll offset was counted twice).
- Row drag-handle grips no longer paint over the pinned summary footer.

## [0.1.10] - 2026-05-05

### Added
- `SkiaFontRegistrar`: register custom typefaces (for example CJK or icon fonts) and use them by family name in `GridFont`. Fixes Japanese text and icon fonts rendering garbled on Android (#5, #8).

### Fixed
- Sample: corrected the selection text colour property name in `IconFontCellRenderer`.

## [0.1.9] - 2026-05-04

### Added
- Per-column `EditTriggers` on `DataGridColumn`, overriding the grid-level triggers (#6, #7).

## [0.1.8] - 2026-05-03

### Added
- Action button columns: pill buttons in a cell with `ICommand` or callback support, activating on the first tap (#3).
- MIT licence and Contributor Covenant Code of Conduct.

## [0.1.7] - 2026-03-06

### Changed
- README: NuGet installation steps in Getting Started.

## [0.1.6] - 2026-03-06

### Changed
- NuGet package icon switched to PNG.

## [0.1.4] - 2026-03-05

### Added
- NuGet package icon.

## [0.1.3] - 2026-03-05

### Added
- First release on NuGet.org of KumikoUI.Core, KumikoUI.SkiaSharp and KumikoUI.Maui: a fully canvas-drawn DataGrid for .NET MAUI with virtual scrolling, text/numeric/boolean/date/combo/picker/image/template columns, sorting, Excel-style filtering, grouping with summaries, editing, selection, keyboard navigation, frozen columns and rows, row drag and drop, column resizing, theming and momentum scrolling.

Versions 0.1.1, 0.1.2 and 0.1.5 were tagged but never published to NuGet.org.

[Unreleased]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.10...HEAD
[0.1.10]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.9...v0.1.10
[0.1.9]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.8...v0.1.9
[0.1.8]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.7...v0.1.8
[0.1.7]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.6...v0.1.7
[0.1.6]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.4...v0.1.6
[0.1.4]: https://github.com/TheEightBot/KumikoUI/compare/v0.1.3...v0.1.4
[0.1.3]: https://github.com/TheEightBot/KumikoUI/releases/tag/v0.1.3
7 changes: 6 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,18 @@ Package versions come from git tags through [MinVer](https://github.com/adamralp
- Any other commit builds the next version as a prerelease, for example `0.2.0-alpha.0.8`: eight commits after the last tag. `MinVerMinimumMajorMinor` in `Directory.Build.props` sets the floor (currently 0.2).
- Clones need tags and history (`git fetch --tags`, no shallow clone) or MinVer falls back to `0.2.0-alpha.0`.

To release, push a version tag on a commit that is on `main`:
To release:

1. In [CHANGELOG.md](CHANGELOG.md), rename `## [Unreleased]` to `## [X.Y.Z] - YYYY-MM-DD`, add a fresh empty `## [Unreleased]` above it, and update the compare links at the bottom. Merge that through a pull request. Stable releases fail to publish without their section; prereleases fall back to `Unreleased`.
2. Push a version tag on that commit on `main`:

```bash
git tag v0.2.0
git push origin v0.2.0
```

The section becomes the GitHub release notes, and every package links to the CHANGELOG. Versioning rules (SemVer, lockstep packages, deprecation, support window) are in [docs/VERSIONING.md](docs/VERSIONING.md).

The publish workflow refuses to run unless the ref is a version tag, the tagged commit is on `main`, and MinVer computes the same version as the tag. It then runs the Core and Uno test suites and waits for approval in the `nuget-publish` environment before pushing to NuGet.org. Symbol packages (`.snupkg`) are produced for every package by default. Only admins can create `v*` tags.

## Making a change
Expand Down
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/TheEightBot/KumikoUI</PackageProjectUrl>
<PackageReleaseNotes>Release notes for every version: https://github.com/TheEightBot/KumikoUI/blob/main/CHANGELOG.md</PackageReleaseNotes>
<RepositoryUrl>https://github.com/TheEightBot/KumikoUI</RepositoryUrl>
<RepositoryType>git</RepositoryType>

Expand Down
41 changes: 41 additions & 0 deletions docs/VERSIONING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Versioning and support policy

## One version for all packages

KumikoUI.Core, KumikoUI.SkiaSharp, KumikoUI.Maui and KumikoUI.Uno are released together and always share the same version. Use the same version of every KumikoUI package in an app. Versions come from git tags (see [CONTRIBUTING.md](../CONTRIBUTING.md#versions-and-releases)).

## Semantic Versioning

KumikoUI follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html): `MAJOR.MINOR.PATCH[-prerelease]`.

| Change | Before 1.0 (`0.y.z`) | From 1.0 |
|---|---|---|
| Breaking change to public API or documented behaviour | minor (`0.2.0` → `0.3.0`) | major |
| New feature, backward compatible | minor or patch | minor |
| Bug fix, backward compatible | patch | patch |
| Raised minimum OS, .NET or SkiaSharp major | minor | major |

Before 1.0 the API is still settling: breaking changes can land in any minor release and are always listed under **Changed** with a **Breaking:** prefix in the [CHANGELOG](../CHANGELOG.md).

Prerelease versions (`1.0.0-preview.1`, `0.2.0-alpha.0.8`) carry no compatibility promise.

## What counts as public API

- Every public type and member in the four packages, including XAML-settable properties and events.
- Documented behaviour: defaults, event order, rendering and input semantics described in the README or XML docs.
- The supported platforms and minimum versions in the README.

Not covered: members marked internal or experimental, sample code, and pixel-exact rendering output (anti-aliasing can change with SkiaSharp updates).

From 1.0, the public surface is tracked with API analyzers and package validation, so an unintended breaking change fails the build.

## Deprecation

From 1.0, a public API is removed only after it has been marked `[Obsolete]` with a message pointing to the replacement for at least one minor release; removal happens in the next major. Behaviour changes that cannot be deprecated are called out in the CHANGELOG and, where possible, kept behind an opt-in setting for one minor release.

## Support window

- **.NET:** each KumikoUI major targets the current .NET LTS release (currently .NET 10, supported until November 2028). When .NET moves to a new LTS, the next KumikoUI major moves with it; the previous major gets security fixes for six months.
- **Minimum OS versions** are re-baselined at each .NET major release; see the README's "Supported platforms".
- **Fixes:** bug and security fixes ship in the latest minor of the current major. Before 1.0, only the latest release is supported (see [SECURITY.md](../SECURITY.md)).
- **SkiaSharp, .NET MAUI and Uno Platform:** KumikoUI moves to new majors of its dependencies in its own minor (before 1.0) or major (from 1.0) releases, and states the required versions in the CHANGELOG.
25 changes: 25 additions & 0 deletions eng/changelog-section.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# Prints the body of one CHANGELOG.md section, without its heading.
#
# eng/changelog-section.sh 0.2.0 # section "## [0.2.0] - <date>"
# eng/changelog-section.sh Unreleased # section "## [Unreleased]"
#
# Exits 1 if the section is missing or empty.
set -euo pipefail
version="${1:?usage: changelog-section.sh <version|Unreleased>}"
file="${2:-$(cd "$(dirname "$0")/.." && pwd)/CHANGELOG.md}"

body=$(awk -v v="$version" '
/^## \[/ {
if (found) exit
if (index($0, "## [" v "]") == 1) { found = 1; next }
}
/^\[[^]]+\]: / { if (found) exit } # link reference definitions at the end
found { print }
' "$file" | sed -e '/./,$!d' | sed -e ':a' -e '/^\n*$/{$d;N;ba' -e '}')

if [[ -z "${body//[[:space:]]/}" ]]; then
echo "CHANGELOG.md has no '## [$version]' section (or it is empty)." >&2
exit 1
fi
printf '%s\n' "$body"
Loading