The Garage SDKs, in the open

garage_auth, garage_entitlements, garage_iap and garage_ui, moved out of
Garage-Services and Metro-Map-Maker into one public repo. MIT, one readme,
docs under docs/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013F4NWNvYcdeSgqbWMT1VQ7
This commit is contained in:
ImBenji
2026-09-23 18:49:21 +01:00
co-authored by Claude Opus 5.5
commit b269201919
117 changed files with 26944 additions and 0 deletions
+71
View File
@@ -0,0 +1,71 @@
// A label handed down to whatever control sits in a labelled row.
//
// Most controls in this app are not labelled at the call site — they sit in a
// PropertyRow (or a settings row) that already draws the name beside them, so
// a sighted user reads "Show grid" and then the box. A screen reader walking
// the tree gets the Text and the checkbox as two unrelated things, and the
// checkbox itself says nothing.
//
// The obvious fix — merging the whole row into one semantics node — falls over
// on rows holding more than one control (a Size row is two fields in a button
// group; merged, it becomes one unreadable blob). So instead the row publishes
// its label down the subtree and each control picks it up as a FALLBACK for
// its own semanticLabel. Explicit always wins.
import "package:flutter/widgets.dart";
class PropertyLabelScope extends InheritedWidget {
const PropertyLabelScope({
super.key,
required this.label,
required super.child,
});
final String label;
/// nearest enclosing row label, or null if this control isn't in one.
static String? maybeOf(BuildContext context) {
return context
.dependOnInheritedWidgetOfExactType<PropertyLabelScope>()
?.label;
}
@override
bool updateShouldNotify(PropertyLabelScope old) => label != old.label;
}
/// Resolves the label a control should announce: its own if it was given one,
/// otherwise the row it lives in. Returns null when neither exists, which is
/// the case a control should be given an explicit label to fix.
String? resolveSemanticLabel(BuildContext context, String? explicit) {
if (explicit != null) return explicit;
return PropertyLabelScope.maybeOf(context);
}
// Marks the control slot of a labelled row, so the controls inside it can stop
// asking the call site what they should look like.
//
// A property section is a docked surface: its rows sit ON a panel, not on the
// page. An outline field in there reads as floating - it draws its own border
// and background against a background that already has one. Secondary is the
// pairing that reads as docked, and it is the ONLY correct answer inside a
// row, which makes `variant:` at those call sites a parameter whose every
// value but one is a bug.
//
// So the row publishes the fact, and TextField/Select resolve against it. This
// is the same trick PropertyLabelScope plays one widget up - the row knows
// something the control cant see, and hands it down rather than making every
// call site repeat it. Unlike the label, though, this one is NOT a fallback:
// an explicit `variant:` inside a row loses. Thats the point.
class PropertySlotScope extends InheritedWidget {
const PropertySlotScope({super.key, required super.child});
/// true when this control sits in a property row's control slot.
static bool of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<PropertySlotScope>() !=
null;
}
@override
bool updateShouldNotify(PropertySlotScope old) => false;
}