mana-swift-core/Sources/ManaTokens/Themes/ManaTheme.swift
Till JS 0c41c69065 bodensee = seepuls-Palette (Gletscherblau, Kalk, Aprikose)
gen:swift aus @mana/themes bodensee.css; Beschreibung in ManaTheme.

Sitzung: 79964fc4
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0111BCGu1WXLkJzY5CGKXdC6
2026-09-15 13:16:10 +02:00

264 lines
11 KiB
Swift

import SwiftUI
/// Eine der 21 Verein-Theme-Variants aus `mana/packages/themes`.
///
/// **Theme-Pass:** jede Variant ist die Signatur genau einer App (1:1,
/// 21 Apps ↔ 21 Themes) — es gibt seit 2026-06-03 keine Baseline-Variants
/// mehr.
///
/// Die Werte-Schicht (``ManaThemeColors``) wird per `colors`-Accessor
/// geliefert. Convenience-Properties (`background`, `foreground`, …)
/// erlauben Apps, ohne `.colors`-Indirektion zu schreiben:
///
/// ```swift
/// ManaTheme.lume.foreground // Convenience
/// ManaTheme.lume.colors.foreground // explizit
/// ```
///
/// Für User-Theme-Switching nutze ``SwiftUICore/View/manaTheme(_:)``
/// und lese im View per `@Environment(\.manaTheme)`.
public enum ManaTheme: String, CaseIterable, Sendable {
case mana
case paper
case kollekta
case lume
case twilight
case skylight
case bodensee
case pinnwand
case buchseite
case herbar
case frischgruen
case wegspur
case waldlichtung
case panel
case buehne
case kreisel
case garderobe
case wolke
case hoerweg
case spektrum
case schaenke
case stetig
case stimmig
case leinwand
/// Konkrete Token-Werte für diese Variant.
public var colors: ManaThemeColors {
switch self {
case .mana: return .mana
case .paper: return .paper
case .kollekta: return .kollekta
case .lume: return .lume
case .twilight: return .twilight
case .skylight: return .skylight
case .bodensee: return .bodensee
case .pinnwand: return .pinnwand
case .buchseite: return .buchseite
case .herbar: return .herbar
case .frischgruen: return .frischgruen
case .wegspur: return .wegspur
case .waldlichtung: return .waldlichtung
case .panel: return .panel
case .buehne: return .buehne
case .kreisel: return .kreisel
case .garderobe: return .garderobe
case .wolke: return .wolke
case .hoerweg: return .hoerweg
case .spektrum: return .spektrum
case .schaenke: return .schaenke
case .stetig: return .stetig
case .stimmig: return .stimmig
case .leinwand: return .leinwand
}
}
// MARK: Convenience-Accessors
public var background: Color { colors.background }
public var foreground: Color { colors.foreground }
public var surface: Color { colors.surface }
public var surfaceHover: Color { colors.surfaceHover }
public var muted: Color { colors.muted }
public var mutedForeground: Color { colors.mutedForeground }
public var border: Color { colors.border }
public var primary: Color { colors.primary }
public var primaryForeground: Color { colors.primaryForeground }
public var error: Color { colors.error }
public var success: Color { colors.success }
public var warning: Color { colors.warning }
// MARK: Präsentations-Metadaten
/// Kurzer Anzeige-Name (DE) für Theme-Picker. Spiegelt die
/// Variant-Tabelle in `mana/docs/THEMING.md`.
public var displayName: String {
switch self {
case .mana: return "mana"
case .paper: return "Papier"
case .kollekta: return "Kollekta"
case .lume: return "Lume"
case .twilight: return "Dämmerung"
case .skylight: return "Papier"
case .bodensee: return "Bodensee"
case .pinnwand: return "Pinnwand"
case .buchseite: return "Buchseite"
case .herbar: return "Herbar"
case .frischgruen: return "Frischgrün"
case .wegspur: return "Wegspur"
case .waldlichtung: return "Waldlichtung"
case .panel: return "Panel"
case .buehne: return "Bühne"
case .kreisel: return "Kreisel"
case .garderobe: return "Garderobe"
case .wolke: return "Wolke"
case .hoerweg: return "Hörweg"
case .spektrum: return "Spektrum"
case .schaenke: return "Schänke"
case .stetig: return "Stetig"
case .stimmig: return "Stimmig"
case .leinwand: return "Leinwand"
}
}
/// Einzeiliger Charakter (DE) — was die Variant ausmacht. Für
/// Untertitel in Theme-Pickern. Quelle: `mana/docs/THEMING.md`.
public var characterDescription: String {
switch self {
case .mana: return "Vereins-Orange, lebendig"
case .paper: return "Sepia, warm, lesefokussiert"
case .kollekta: return "Lila-Akzent, sammlerisch"
case .lume: return "Gold-Akzent, dunkel-elegant"
case .twilight: return "Indigo bis Violett, abendlich"
case .skylight: return "Warmes Papier, Tinte als Akzent"
case .bodensee: return "Gletscherblau, Kalk und Aprikose"
case .pinnwand: return "Beige + Orange, einladend"
case .buchseite: return "Pergament + Burgund, literarisch"
case .herbar: return "Tiefes Kräutergrün"
case .frischgruen: return "Helles, frisches Grün"
case .wegspur: return "Erdiges Outdoor-Grün"
case .waldlichtung: return "Luftiges Lichtungsgrün"
case .panel: return "Sattes Comic-Kobaltblau"
case .buehne: return "Dunkel mit Neon-Magenta"
case .kreisel: return "Verspieltes Violett"
case .garderobe: return "Gedämpftes Mauve, Mode"
case .wolke: return "Kühl-helles Wolkenblau"
case .hoerweg: return "Warmer Amber, erzählerisch"
case .spektrum: return "Lautes Magenta, Internet"
case .schaenke: return "Kerzenlicht-Schänke, Terrakotta-Rot"
case .stetig: return "Tiefes Jadegrün, beständig"
case .stimmig: return "Warmes Himbeer-Rosé, klangvoll"
case .leinwand: return "Kinematisches Türkis, Abendlicht"
}
}
// MARK: Theme-Pass — Unlock-Metadaten
/// Baseline-Konzept stillgelegt (2026-06-03) — jede Variant gehört jetzt
/// genau einer App. Bleibt als immer-`false`-Property aus Kompatibilität.
@available(*, deprecated, message: "Keine Baseline-Variants mehr — jede Variant hat eine signatureApp.")
public var isBaseline: Bool { false }
/// App-Slug, dessen Ausprobieren (Login) diese Signatur-Variant
/// freischaltet. Reverse-Map der App→Signatur-Zuordnung (THEME_PASS.md).
/// Slug = stabiler App-Key (gleich über web + native).
public var signatureApp: String {
switch self {
case .mana: return "hub"
case .schaenke: return "who"
case .stetig: return "stetick"
case .stimmig: return "stimmig"
case .leinwand: return "lumetour"
case .paper: return "pageta"
case .kollekta: return "kollekta"
case .bodensee: return "seepuls"
case .pinnwand: return "wunsch"
case .buchseite: return "zitare"
case .lume: return "memoro"
case .skylight: return "kartomo"
case .twilight: return "moodlit"
case .herbar: return "herbatrium"
case .frischgruen: return "nutriphi"
case .wegspur: return "viadocu"
case .waldlichtung: return "manawald"
case .panel: return "comicello"
case .buehne: return "mukke"
case .kreisel: return "kreisel"
case .garderobe: return "werdrobe"
case .wolke: return "uload"
case .hoerweg: return "audioguide"
case .spektrum: return "manameme"
}
}
/// Anzeige-Name der Signatur-App (DE) — für Locked-Hinweise + Button in
/// Theme-Pickern („Probier <Name>").
/// Quelle: `mana/apps/landing/src/content/apps/<slug>.md` (`name:`).
public var signatureAppName: String {
switch self {
case .mana: return "Hub"
case .schaenke: return "Who"
case .stetig: return "Stetick"
case .stimmig: return "Stimmig"
case .leinwand: return "LumeTour"
case .paper: return "Pageta"
case .kollekta: return "Kollekta"
case .bodensee: return "Seepuls"
case .pinnwand: return "Was fehlt?"
case .buchseite: return "Zitare"
case .lume: return "Memoro"
case .skylight: return "Kartomo"
case .twilight: return "Moodlit"
case .herbar: return "Herbatrium"
case .frischgruen: return "Nutriphi"
case .wegspur: return "Viadocu"
case .waldlichtung: return "Manawald"
case .panel: return "Comicello"
case .buehne: return "Mukke"
case .kreisel: return "Kreisel"
case .garderobe: return "Werdrobe"
case .wolke: return "uLoad"
case .hoerweg: return "Audioguide"
case .spektrum: return "ManaMeme"
}
}
/// Eigene Landingpage der Signatur-App — Ziel des „<Name> öffnen"-Buttons
/// bei gesperrter Variant. Bevorzugt die Apex-Domain (z. B. `kartomo.com`),
/// fällt auf `<slug>.mana.how` zurück, wo es keine eigene gibt.
/// Quelle: `mana/apps/landing/src/content/apps/<slug>.md` (`url:`).
public var signatureAppHomepage: URL? {
switch self {
case .mana: return URL(string: "https://hub.mana.how")
case .schaenke: return URL(string: "https://who.mana.how")
case .stetig: return URL(string: "https://stetick.mana.how")
case .stimmig: return URL(string: "https://stimmig.mana.how")
case .leinwand: return URL(string: "https://lumetour.mana.how")
case .paper: return URL(string: "https://pageta.com")
case .kollekta: return URL(string: "https://kollekta.mana.how")
case .bodensee: return URL(string: "https://seepuls.com")
case .pinnwand: return URL(string: "https://wunsch.mana.how")
case .buchseite: return URL(string: "https://zitare.com")
case .lume: return URL(string: "https://memoro.mana.how")
case .skylight: return URL(string: "https://kartomo.com")
case .twilight: return URL(string: "https://moodlit.mana.how")
case .herbar: return URL(string: "https://herbatrium.com")
case .frischgruen: return URL(string: "https://nutriphi.mana.how")
case .wegspur: return URL(string: "https://viadocu.mana.how")
case .waldlichtung: return URL(string: "https://manawald.mana.how")
case .panel: return URL(string: "https://comicello.com")
case .buehne: return URL(string: "https://mukke.mana.how")
case .kreisel: return URL(string: "https://kreisel.mana.how")
case .garderobe: return URL(string: "https://werdrobe.com")
case .wolke: return URL(string: "https://ulo.ad")
case .hoerweg: return URL(string: "https://audioguide.mana.how")
case .spektrum: return URL(string: "https://manameme.mana.how")
}
}
/// Ist diese Variant für den gegebenen Satz „ausprobierter" App-Slugs
/// freigeschaltet? Frei, sobald die zugehörige Signatur-App dabei ist.
public func isUnlocked(triedApps: Set<String>) -> Bool {
triedApps.contains(signatureApp)
}
}