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
+105
View File
@@ -0,0 +1,105 @@
import "package:flutter/widgets.dart";
import "package:google_fonts/google_fonts.dart";
import "package:garage_ui/theme/garage_theme.dart";
// The apps type scale. shadcn exposed a big Typography object; the GarageUI widgets
// only reach for the small set below. `small` is a size style, `medium`/`normal`
// are weight styles, and `mono` swaps the font family while inheriting the
// ambient size/weight unless a caller overrides them.
class Typography {
const Typography({
this.normal = const TextStyle(fontWeight: FontWeight.w400),
this.medium = const TextStyle(fontWeight: FontWeight.w500),
this.semiBold = const TextStyle(fontWeight: FontWeight.w600),
// `small` is the shared control font used by buttons, fields and selects.
// Prefer [Typography.forDensity] over setting this by hand - the size
// and line height belong to the density, and the whole control geometry
// chain hangs off them.
this.small = const TextStyle(
fontSize: 10,
height: 1.1,
fontWeight: FontWeight.w400,
),
});
/// Builds the control type from the density, so `small` can never drift from
/// the line box the control heights are derived from.
factory Typography.forDensity(Density density) => Typography(
small: TextStyle(
fontSize: density.fontSize,
height: density.lineHeight,
fontWeight: FontWeight.w400,
),
);
final TextStyle normal;
final TextStyle medium;
/// Emphasis above [medium] - section labels, a dialog's title. Was a
/// FontWeight.w600 literal in menu.dart, properties.dart and toast.dart.
final TextStyle semiBold;
final TextStyle small;
TextStyle sansStyle(TextStyle style) =>
GoogleFonts.geist(textStyle: style, fontWeight: style.fontWeight);
TextStyle get mono => GoogleFonts.geistMono();
TextStyle monoStyle(TextStyle style) =>
GoogleFonts.geistMono(textStyle: style, fontWeight: style.fontWeight);
}
// shadcn hung these little text helpers off every widget (usually a Text). they
// merge a style change over whatever DefaultTextStyle is in scope. sizes are
// multiplied by the theme scaling so they track the rest of the ui.
extension TextStyleExtension on Widget {
// sizes come off the density's text ladder, NOT a literal times scaling -
// see Density.textXs for why. scaling is left out on purpose: Density isn't
// scaled, and these have to stay in step with the control font.
Widget xSmall() => _StyledText(
child: this,
style: (t) => TextStyle(fontSize: t.density.textXs),
);
Widget small() => _StyledText(
child: this,
style: (t) => TextStyle(fontSize: t.density.textSm),
);
Widget large() => _StyledText(
child: this,
style: (t) => TextStyle(fontSize: t.density.textLg),
);
Widget medium() => _StyledText(
child: this,
style: (t) => const TextStyle(fontWeight: FontWeight.w500),
);
Widget semiBold() => _StyledText(
child: this,
style: (t) => const TextStyle(fontWeight: FontWeight.w600),
);
Widget bold() => _StyledText(
child: this,
style: (t) => const TextStyle(fontWeight: FontWeight.w700),
);
Widget muted() => _StyledText(
child: this,
style: (t) => TextStyle(color: t.colorScheme.mutedForeground),
);
}
typedef _StyleFromTheme = TextStyle Function(ThemeData theme);
class _StyledText extends StatelessWidget {
const _StyledText({required this.child, required this.style});
final Widget child;
final _StyleFromTheme style;
@override
Widget build(BuildContext context) {
final theme = GarageTheme.of(context);
return DefaultTextStyle.merge(style: style(theme), child: child);
}
}