codex-flow 2.1.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. codex_flow/__init__.py +28 -0
  2. codex_flow/__main__.py +9 -0
  3. codex_flow/cli.py +242 -0
  4. codex_flow/data/LICENSE +21 -0
  5. codex_flow/data/README.en.md +303 -0
  6. codex_flow/data/README.md +305 -0
  7. codex_flow/data/VERSION +1 -0
  8. codex_flow/data/apps/chatgpt-mcp/README.md +86 -0
  9. codex_flow/data/apps/chatgpt-mcp/__init__.py +1 -0
  10. codex_flow/data/apps/chatgpt-mcp/adapter.py +458 -0
  11. codex_flow/data/apps/chatgpt-mcp/server.py +358 -0
  12. codex_flow/data/apps/chatgpt-mcp/widget.html +927 -0
  13. codex_flow/data/apps/macos-overlay/README.en.md +121 -0
  14. codex_flow/data/apps/macos-overlay/README.md +123 -0
  15. codex_flow/data/apps/macos-overlay/Sources/Controllers/OverlayRuntimeState.swift +126 -0
  16. codex_flow/data/apps/macos-overlay/Sources/Controllers/OverlayScreenGeometry.swift +82 -0
  17. codex_flow/data/apps/macos-overlay/Sources/Controllers/OverlayWindowController.swift +1052 -0
  18. codex_flow/data/apps/macos-overlay/Sources/Localization.swift +197 -0
  19. codex_flow/data/apps/macos-overlay/Sources/Models/TelemetryData.swift +1557 -0
  20. codex_flow/data/apps/macos-overlay/Sources/Services/AccountSnapshotService.swift +1101 -0
  21. codex_flow/data/apps/macos-overlay/Sources/Services/FlowPilotInstanceLock.swift +153 -0
  22. codex_flow/data/apps/macos-overlay/Sources/Services/IPCServer.swift +298 -0
  23. codex_flow/data/apps/macos-overlay/Sources/Services/TelemetryQueryEngine.swift +800 -0
  24. codex_flow/data/apps/macos-overlay/Sources/Services/TelemetryWatcher.swift +135 -0
  25. codex_flow/data/apps/macos-overlay/Sources/Services/UpdateService.swift +610 -0
  26. codex_flow/data/apps/macos-overlay/Sources/Views/AccountView.swift +610 -0
  27. codex_flow/data/apps/macos-overlay/Sources/Views/AnalyticsView.swift +566 -0
  28. codex_flow/data/apps/macos-overlay/Sources/Views/AutostartView.swift +293 -0
  29. codex_flow/data/apps/macos-overlay/Sources/Views/BubbleView.swift +317 -0
  30. codex_flow/data/apps/macos-overlay/Sources/Views/HistoryView.swift +1124 -0
  31. codex_flow/data/apps/macos-overlay/Sources/Views/HoverRevealText.swift +165 -0
  32. codex_flow/data/apps/macos-overlay/Sources/Views/InspectorSkillsToolsView.swift +121 -0
  33. codex_flow/data/apps/macos-overlay/Sources/Views/LogoView.swift +182 -0
  34. codex_flow/data/apps/macos-overlay/Sources/Views/SleekSwitch.swift +117 -0
  35. codex_flow/data/apps/macos-overlay/Sources/Views/StrategyModeView.swift +561 -0
  36. codex_flow/data/apps/macos-overlay/Sources/Views/SummaryView.swift +1273 -0
  37. codex_flow/data/apps/macos-overlay/Sources/Views/UpdateView.swift +352 -0
  38. codex_flow/data/apps/macos-overlay/Sources/main.swift +340 -0
  39. codex_flow/data/apps/macos-overlay/Tests/OverlayScreenGeometryTests.swift +163 -0
  40. codex_flow/data/apps/macos-overlay/Tests/TelemetryPhase1ContractTests.swift +357 -0
  41. codex_flow/data/apps/macos-overlay/Tests/TelemetryQueryEngineConcurrencyTests.swift +221 -0
  42. codex_flow/data/apps/macos-overlay/Tests/TelemetryQuotaSelectionTests.swift +158 -0
  43. codex_flow/data/apps/macos-overlay/Tests/TelemetryWorkerTokenTests.swift +122 -0
  44. codex_flow/data/apps/macos-overlay/build.sh +75 -0
  45. codex_flow/data/benchmark/corpus.json +103 -0
  46. codex_flow/data/benchmark/manifest.example.json +41 -0
  47. codex_flow/data/benchmark/manifest.schema.json +137 -0
  48. codex_flow/data/benchmark/prices/gpt-5.6-2026-08-30.json +5 -0
  49. codex_flow/data/benchmark/profiles.json +90 -0
  50. codex_flow/data/benchmark/schema.json +77 -0
  51. codex_flow/data/benchmark/tasks.json +50 -0
  52. codex_flow/data/completions/codex-flow.bash +34 -0
  53. codex_flow/data/completions/codex-flow.zsh +52 -0
  54. codex_flow/data/glama.json +6 -0
  55. codex_flow/data/install-release.ps1 +126 -0
  56. codex_flow/data/install-release.sh +155 -0
  57. codex_flow/data/install.ps1 +349 -0
  58. codex_flow/data/install.sh +362 -0
  59. codex_flow/data/policy/benchmark.toml +49 -0
  60. codex_flow/data/policy/defaults.toml +70 -0
  61. codex_flow/data/scripts/analyze-benchmark.py +510 -0
  62. codex_flow/data/scripts/benchmark-local.py +171 -0
  63. codex_flow/data/scripts/check-recommendation.py +277 -0
  64. codex_flow/data/scripts/doctor.py +449 -0
  65. codex_flow/data/scripts/generate-release-manifest.py +74 -0
  66. codex_flow/data/scripts/localization.py +192 -0
  67. codex_flow/data/scripts/manage-hooks.py +448 -0
  68. codex_flow/data/scripts/manage-instructions.py +389 -0
  69. codex_flow/data/scripts/manage-shell.py +151 -0
  70. codex_flow/data/scripts/materialize-corpus.py +193 -0
  71. codex_flow/data/scripts/menu.py +646 -0
  72. codex_flow/data/scripts/migrations/0001_update_settings.py +80 -0
  73. codex_flow/data/scripts/package-release.py +132 -0
  74. codex_flow/data/scripts/render-benchmark-report.py +292 -0
  75. codex_flow/data/scripts/run-benchmark.py +829 -0
  76. codex_flow/data/scripts/strategies/__init__.py +28 -0
  77. codex_flow/data/scripts/strategies/balanced.py +115 -0
  78. codex_flow/data/scripts/strategies/base.py +363 -0
  79. codex_flow/data/scripts/strategies/efficient.py +158 -0
  80. codex_flow/data/scripts/strategies/lifecycle_runtime.py +590 -0
  81. codex_flow/data/scripts/strategies/quality.py +209 -0
  82. codex_flow/data/scripts/strategies/speed.py +108 -0
  83. codex_flow/data/scripts/strategies/task_budget_runtime.py +644 -0
  84. codex_flow/data/scripts/strategies/task_phase_runtime.py +341 -0
  85. codex_flow/data/scripts/strategies/work_unit_runtime.py +421 -0
  86. codex_flow/data/scripts/strategy_runtime.py +1091 -0
  87. codex_flow/data/scripts/telemetry.py +400 -0
  88. codex_flow/data/scripts/telemetry_core/__init__.py +192 -0
  89. codex_flow/data/scripts/telemetry_core/app_server.py +1192 -0
  90. codex_flow/data/scripts/telemetry_core/collector.py +1247 -0
  91. codex_flow/data/scripts/telemetry_core/common.py +421 -0
  92. codex_flow/data/scripts/telemetry_core/latency.py +593 -0
  93. codex_flow/data/scripts/telemetry_core/query.py +427 -0
  94. codex_flow/data/scripts/telemetry_core/quota_ledger.py +598 -0
  95. codex_flow/data/scripts/telemetry_core/render.py +460 -0
  96. codex_flow/data/scripts/telemetry_core/repair.py +223 -0
  97. codex_flow/data/scripts/ui.py +266 -0
  98. codex_flow/data/scripts/update-homebrew-formula.py +146 -0
  99. codex_flow/data/scripts/update_runtime_config.py +134 -0
  100. codex_flow/data/scripts/updater.py +1718 -0
  101. codex_flow/data/smithery.yaml +18 -0
  102. codex_flow/data/templates/agents/worker-explorer.toml +24 -0
  103. codex_flow/data/templates/agents/worker-implementer.toml +49 -0
  104. codex_flow/data/templates/agents/worker-reviewer.toml +25 -0
  105. codex_flow/data/templates/flow-pilot-instructions.md +35 -0
  106. codex_flow/data/templates/skills/flow-pilot/SKILL.md +577 -0
  107. codex_flow/mcp.py +35 -0
  108. codex_flow-2.1.13.dist-info/METADATA +342 -0
  109. codex_flow-2.1.13.dist-info/RECORD +113 -0
  110. codex_flow-2.1.13.dist-info/WHEEL +5 -0
  111. codex_flow-2.1.13.dist-info/entry_points.txt +3 -0
  112. codex_flow-2.1.13.dist-info/licenses/LICENSE +21 -0
  113. codex_flow-2.1.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,165 @@
1
+ import SwiftUI
2
+ import Foundation
3
+
4
+ /// A compact text label that keeps the normal layout truncated, but reveals the
5
+ /// complete value in a small native popover after a short hover dwell.
6
+ ///
7
+ /// Privacy mode intentionally keeps the original text layout and applies the
8
+ /// same 4.5pt blur used by the earlier showcase pipeline. A drawing group bakes
9
+ /// the blur into an offscreen texture so AppKit-backed screenshots preserve the
10
+ /// visual mask instead of degrading it into placeholder bars.
11
+ public struct HoverRevealText: View {
12
+ public let text: String
13
+ public let fullText: String?
14
+ public let font: Font
15
+ public let foregroundColor: Color
16
+ public let lineLimit: Int?
17
+ public let truncationMode: Text.TruncationMode
18
+ public let privacyBlur: Bool
19
+ public let alignment: TextAlignment
20
+ public let popoverWidth: CGFloat
21
+
22
+ @State private var isPresented = false
23
+ @State private var hoverGeneration = 0
24
+
25
+ public init(
26
+ _ text: String,
27
+ font: Font = .system(size: 10),
28
+ foregroundColor: Color = .white,
29
+ lineLimit: Int? = 1,
30
+ truncationMode: Text.TruncationMode = .tail,
31
+ privacyBlur: Bool = false,
32
+ alignment: TextAlignment = .leading,
33
+ popoverWidth: CGFloat = 340,
34
+ fullText: String? = nil
35
+ ) {
36
+ self.text = text
37
+ self.fullText = fullText
38
+ self.font = font
39
+ self.foregroundColor = foregroundColor
40
+ self.lineLimit = lineLimit
41
+ self.truncationMode = truncationMode
42
+ self.privacyBlur = privacyBlur
43
+ self.alignment = alignment
44
+ self.popoverWidth = popoverWidth
45
+ }
46
+
47
+ public var body: some View {
48
+ Group {
49
+ if privacyBlur {
50
+ Text(text)
51
+ .font(font)
52
+ .foregroundColor(foregroundColor)
53
+ .lineLimit(lineLimit)
54
+ .truncationMode(truncationMode)
55
+ .multilineTextAlignment(alignment)
56
+ .blur(radius: 4.5)
57
+ .drawingGroup(opaque: false, colorMode: .linear)
58
+ .accessibilityLabel(Text("Private content"))
59
+ } else {
60
+ Text(text)
61
+ .font(font)
62
+ .foregroundColor(foregroundColor)
63
+ .lineLimit(lineLimit)
64
+ .truncationMode(truncationMode)
65
+ .multilineTextAlignment(alignment)
66
+ }
67
+ }
68
+ .contentShape(Rectangle())
69
+ .onHover(perform: handleSourceHover)
70
+ .popover(isPresented: $isPresented, arrowEdge: .bottom) {
71
+ ZStack {
72
+ Color(red: 0.055, green: 0.062, blue: 0.085)
73
+ .ignoresSafeArea()
74
+
75
+ ScrollView(.vertical, showsIndicators: true) {
76
+ expandedText
77
+ .font(font)
78
+ .foregroundColor(.white.opacity(0.92))
79
+ .multilineTextAlignment(.leading)
80
+ .textSelection(.enabled)
81
+ .fixedSize(horizontal: false, vertical: true)
82
+ .frame(maxWidth: .infinity, alignment: .leading)
83
+ .padding(10)
84
+ }
85
+ }
86
+ .frame(width: min(max(popoverWidth, 220), 520))
87
+ .frame(maxHeight: 260)
88
+ .background(Color(red: 0.055, green: 0.062, blue: 0.085))
89
+ .preferredColorScheme(.dark)
90
+ .onHover(perform: handlePopoverHover)
91
+ }
92
+ }
93
+
94
+ /// Native Foundation Markdown parsing keeps headings, lists, fenced code,
95
+ /// inline code, and links selectable without introducing a WebView or HTML.
96
+ /// A malformed value falls back to the exact source text. Link attributes
97
+ /// are retained only for http/https URLs so local files and script schemes
98
+ /// can never become clickable from telemetry.
99
+ @ViewBuilder
100
+ private var expandedText: some View {
101
+ let content = fullText ?? text
102
+ if let markdown = Self.parseMarkdown(content) {
103
+ Text(markdown)
104
+ } else {
105
+ Text(content)
106
+ }
107
+ }
108
+
109
+ private static func parseMarkdown(_ source: String) -> AttributedString? {
110
+ do {
111
+ var value = try AttributedString(
112
+ markdown: source,
113
+ options: .init(interpretedSyntax: .full)
114
+ )
115
+
116
+ for run in value.runs {
117
+ guard let link = run.link else { continue }
118
+ let scheme = link.scheme?.lowercased()
119
+ guard scheme == "http" || scheme == "https" else {
120
+ value[run.range].link = nil
121
+ continue
122
+ }
123
+ }
124
+ return value
125
+ } catch {
126
+ return nil
127
+ }
128
+ }
129
+
130
+ private func handleSourceHover(_ inside: Bool) {
131
+ hoverGeneration += 1
132
+ let generation = hoverGeneration
133
+
134
+ let content = fullText ?? text
135
+ guard !privacyBlur, !content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
136
+ isPresented = false
137
+ return
138
+ }
139
+
140
+ let delay = inside ? 0.22 : 0.25
141
+ DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
142
+ guard generation == hoverGeneration else { return }
143
+ withAnimation(.easeInOut(duration: 0.12)) {
144
+ isPresented = inside
145
+ }
146
+ }
147
+ }
148
+
149
+ private func handlePopoverHover(_ inside: Bool) {
150
+ hoverGeneration += 1
151
+ let generation = hoverGeneration
152
+
153
+ if inside {
154
+ isPresented = true
155
+ return
156
+ }
157
+
158
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.16) {
159
+ guard generation == hoverGeneration else { return }
160
+ withAnimation(.easeInOut(duration: 0.12)) {
161
+ isPresented = false
162
+ }
163
+ }
164
+ }
165
+ }
@@ -0,0 +1,121 @@
1
+ import SwiftUI
2
+
3
+ /// Keeps the existing Skills / MCP visibility in the refreshed Inspector while
4
+ /// using the same hover-to-reveal behavior as the rest of the app.
5
+ public struct InspectorSkillsToolsView: View {
6
+ public let run: TaskRun
7
+ @State private var expanded = false
8
+
9
+ public init(run: TaskRun) {
10
+ self.run = run
11
+ }
12
+
13
+ private var skills: [SkillUsage] { run.skillsUsed ?? [] }
14
+ private var tools: [ToolCallInfo] { run.toolsUsed ?? [] }
15
+
16
+ public var body: some View {
17
+ VStack(alignment: .leading, spacing: 6) {
18
+ Button {
19
+ withAnimation(.easeInOut(duration: 0.15)) {
20
+ expanded.toggle()
21
+ }
22
+ } label: {
23
+ HStack(spacing: 4) {
24
+ Image(systemName: "square.grid.2x2.fill")
25
+ .font(.system(size: 8))
26
+ .foregroundColor(.purple)
27
+ Text(L("Skills & Tools", "技能与工具"))
28
+ .font(.system(size: 8.8, weight: .bold, design: .rounded))
29
+ .foregroundColor(.white.opacity(0.7))
30
+ Spacer()
31
+ Text(L("\(skills.count) skills · \(tools.count) tools", "\(skills.count) 个技能 · \(tools.count) 个工具"))
32
+ .font(.system(size: 7.3, weight: .medium))
33
+ .foregroundColor(.white.opacity(0.38))
34
+ Image(systemName: expanded ? "chevron.up" : "chevron.down")
35
+ .font(.system(size: 7, weight: .bold))
36
+ .foregroundColor(.white.opacity(0.35))
37
+ }
38
+ .contentShape(Rectangle())
39
+ }
40
+ .buttonStyle(.plain)
41
+
42
+ if expanded {
43
+ if !skills.isEmpty {
44
+ compactSection(title: L("Skills", "技能"), icon: "sparkles", tint: .purple) {
45
+ ForEach(skills) { skill in
46
+ compactItem(
47
+ text: skill.name,
48
+ trailing: skill.count.map { "×\($0)" },
49
+ tint: .purple
50
+ )
51
+ }
52
+ }
53
+ }
54
+
55
+ if !tools.isEmpty {
56
+ compactSection(title: L("Tools", "工具"), icon: "wrench.and.screwdriver.fill", tint: .teal) {
57
+ ForEach(tools) { tool in
58
+ compactItem(
59
+ text: tool.displayName,
60
+ trailing: tool.count.map { "×\($0)" },
61
+ tint: tool.isMcp == true ? .cyan : .teal
62
+ )
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+ .padding(8)
69
+ .background(
70
+ RoundedRectangle(cornerRadius: 9)
71
+ .fill(Color.white.opacity(0.035))
72
+ .overlay(
73
+ RoundedRectangle(cornerRadius: 9)
74
+ .stroke(Color.white.opacity(0.07), lineWidth: 0.7)
75
+ )
76
+ )
77
+ }
78
+
79
+ private func compactSection<Content: View>(
80
+ title: String,
81
+ icon: String,
82
+ tint: Color,
83
+ @ViewBuilder content: () -> Content
84
+ ) -> some View {
85
+ VStack(alignment: .leading, spacing: 4) {
86
+ Label(title, systemImage: icon)
87
+ .font(.system(size: 7.6, weight: .semibold))
88
+ .foregroundColor(tint.opacity(0.85))
89
+
90
+ VStack(spacing: 3) {
91
+ content()
92
+ }
93
+ }
94
+ }
95
+
96
+ private func compactItem(text: String, trailing: String?, tint: Color) -> some View {
97
+ HStack(spacing: 5) {
98
+ Circle()
99
+ .fill(tint.opacity(0.85))
100
+ .frame(width: 4, height: 4)
101
+
102
+ HoverRevealText(
103
+ text,
104
+ font: .system(size: 8, weight: .medium, design: .monospaced),
105
+ foregroundColor: .white.opacity(0.68),
106
+ lineLimit: 1,
107
+ popoverWidth: 380
108
+ )
109
+ .frame(maxWidth: .infinity, alignment: .leading)
110
+
111
+ if let trailing {
112
+ Text(trailing)
113
+ .font(.system(size: 7.2, weight: .bold, design: .monospaced))
114
+ .foregroundColor(tint.opacity(0.75))
115
+ }
116
+ }
117
+ .padding(.horizontal, 6)
118
+ .padding(.vertical, 3)
119
+ .background(RoundedRectangle(cornerRadius: 6).fill(Color.white.opacity(0.022)))
120
+ }
121
+ }
@@ -0,0 +1,182 @@
1
+ import SwiftUI
2
+ import AppKit
3
+
4
+ public struct FlowPilotLogoView: View {
5
+ public var size: CGFloat
6
+ public var showGlow: Bool
7
+ public var withBolt: Bool
8
+ public var text: String
9
+
10
+ public init(
11
+ size: CGFloat = 256,
12
+ showGlow: Bool = true,
13
+ withBolt: Bool = true,
14
+ text: String = "FlowPilot"
15
+ ) {
16
+ self.size = size
17
+ self.showGlow = showGlow
18
+ self.withBolt = withBolt
19
+ self.text = text
20
+ }
21
+
22
+ private var circleDiameter: CGFloat { size * 0.76 }
23
+ private var beaconSize: CGFloat { circleDiameter * 0.138 }
24
+ private var sparklesSize: CGFloat { circleDiameter * 0.31 }
25
+ private var beaconOffset: CGFloat { circleDiameter * 0.35 }
26
+
27
+ public var body: some View {
28
+ ZStack {
29
+ // 1. Dark Frosted Glass Inner Body
30
+ Circle()
31
+ .fill(
32
+ RadialGradient(
33
+ colors: [
34
+ Color(red: 0.15, green: 0.17, blue: 0.24).opacity(0.96),
35
+ Color(red: 0.07, green: 0.08, blue: 0.12).opacity(0.98)
36
+ ],
37
+ center: .center,
38
+ startRadius: circleDiameter * 0.08,
39
+ endRadius: circleDiameter * 0.5
40
+ )
41
+ )
42
+ .overlay(
43
+ Circle()
44
+ .stroke(
45
+ LinearGradient(
46
+ colors: [
47
+ Color.white.opacity(0.28),
48
+ Color.white.opacity(0.08),
49
+ Color.cyan.opacity(0.20)
50
+ ],
51
+ startPoint: .topLeading,
52
+ endPoint: .bottomTrailing
53
+ ),
54
+ lineWidth: max(1.0, circleDiameter * 0.015)
55
+ )
56
+ )
57
+ .frame(width: circleDiameter, height: circleDiameter)
58
+
59
+ // 2. Dynamic Neon Rainbow Border Glow
60
+ Circle()
61
+ .strokeBorder(
62
+ AngularGradient(
63
+ colors: [
64
+ Color(red: 0.0, green: 0.85, blue: 1.0), // Cyan
65
+ Color(red: 0.35, green: 0.45, blue: 1.0), // Indigo
66
+ Color(red: 0.75, green: 0.35, blue: 0.95), // Purple
67
+ Color(red: 1.0, green: 0.35, blue: 0.65), // Pink
68
+ Color(red: 0.0, green: 0.9, blue: 0.75), // Teal
69
+ Color(red: 0.0, green: 0.85, blue: 1.0) // Cyan
70
+ ],
71
+ center: .center
72
+ ),
73
+ lineWidth: max(1.8, circleDiameter * 0.028)
74
+ )
75
+ .shadow(
76
+ color: Color.cyan.opacity(showGlow ? 0.75 : 0.0),
77
+ radius: max(3.0, circleDiameter * 0.06)
78
+ )
79
+ .shadow(
80
+ color: Color(red: 0.7, green: 0.3, blue: 0.9).opacity(showGlow ? 0.45 : 0.0),
81
+ radius: max(6.0, circleDiameter * 0.1)
82
+ )
83
+ .frame(width: circleDiameter, height: circleDiameter)
84
+
85
+ // 3. Central Content Stack
86
+ VStack(spacing: circleDiameter * 0.04) {
87
+ // Sparkles Hero Glyph
88
+ Image(systemName: "sparkles")
89
+ .font(.system(size: sparklesSize, weight: .bold))
90
+ .foregroundStyle(
91
+ LinearGradient(
92
+ colors: [
93
+ Color.white,
94
+ Color(red: 0.2, green: 0.85, blue: 1.0),
95
+ Color(red: 0.65, green: 0.4, blue: 0.95)
96
+ ],
97
+ startPoint: .topLeading,
98
+ endPoint: .bottomTrailing
99
+ )
100
+ )
101
+ .shadow(color: Color.cyan.opacity(0.8), radius: max(2.5, sparklesSize * 0.25))
102
+ .shadow(color: Color.purple.opacity(0.5), radius: max(5.0, sparklesSize * 0.4))
103
+ .offset(y: circleDiameter * 0.015)
104
+
105
+ // Bottom Pill Badge with "FlowPilot" (replacing token quantity)
106
+ HStack(spacing: circleDiameter * 0.025) {
107
+ if withBolt {
108
+ Image(systemName: "bolt.fill")
109
+ .font(.system(size: circleDiameter * 0.095, weight: .heavy))
110
+ .foregroundColor(Color(red: 0.2, green: 0.88, blue: 0.45))
111
+ .shadow(color: Color(red: 0.2, green: 0.88, blue: 0.45).opacity(0.8), radius: 2)
112
+ }
113
+
114
+ Text(text)
115
+ .font(.system(
116
+ size: withBolt ? circleDiameter * 0.112 : circleDiameter * 0.125,
117
+ weight: .heavy,
118
+ design: .rounded
119
+ ))
120
+ .foregroundColor(Color.white.opacity(0.98))
121
+ .shadow(color: Color.black.opacity(0.8), radius: 2, y: 1)
122
+ }
123
+ .padding(.horizontal, circleDiameter * 0.055)
124
+ .padding(.vertical, circleDiameter * 0.022)
125
+ .background(
126
+ Capsule()
127
+ .fill(Color(red: 0.04, green: 0.05, blue: 0.08).opacity(0.88))
128
+ )
129
+ .overlay(
130
+ Capsule()
131
+ .stroke(
132
+ LinearGradient(
133
+ colors: [
134
+ Color.white.opacity(0.35),
135
+ Color.cyan.opacity(0.35),
136
+ Color.white.opacity(0.12)
137
+ ],
138
+ startPoint: .topLeading,
139
+ endPoint: .bottomTrailing
140
+ ),
141
+ lineWidth: max(0.8, circleDiameter * 0.012)
142
+ )
143
+ )
144
+ .shadow(color: Color.black.opacity(0.6), radius: 4, y: 2)
145
+ }
146
+
147
+ // 4. Emerald Active Beacon Dot (Upper Right)
148
+ ZStack {
149
+ // Radiant beacon bloom
150
+ Circle()
151
+ .fill(Color(red: 0.2, green: 0.88, blue: 0.45).opacity(0.4))
152
+ .frame(width: beaconSize * 1.6, height: beaconSize * 1.6)
153
+ .blur(radius: beaconSize * 0.25)
154
+
155
+ // Solid beacon dot
156
+ Circle()
157
+ .fill(
158
+ RadialGradient(
159
+ colors: [
160
+ Color(red: 0.4, green: 1.0, blue: 0.65),
161
+ Color(red: 0.15, green: 0.82, blue: 0.4)
162
+ ],
163
+ center: .center,
164
+ startRadius: 0,
165
+ endRadius: beaconSize * 0.5
166
+ )
167
+ )
168
+ .frame(width: beaconSize, height: beaconSize)
169
+ .overlay(
170
+ Circle()
171
+ .stroke(Color(red: 0.05, green: 0.06, blue: 0.09), lineWidth: max(1.2, beaconSize * 0.16))
172
+ )
173
+ .shadow(
174
+ color: Color(red: 0.2, green: 0.88, blue: 0.45).opacity(0.95),
175
+ radius: max(3.0, beaconSize * 0.35)
176
+ )
177
+ }
178
+ .offset(x: beaconOffset, y: -beaconOffset)
179
+ }
180
+ .frame(width: size, height: size)
181
+ }
182
+ }
@@ -0,0 +1,117 @@
1
+ import SwiftUI
2
+
3
+ /// A modern, tactile switch toggle style tailored for dark glassmorphic overlays.
4
+ ///
5
+ /// Features a vibrant luminous track when active, a clean translucent dark glass
6
+ /// track when inactive, smooth spring physics, subtle depth drop-shadows, and
7
+ /// clear visual contrast in macOS dark mode.
8
+ public struct SleekSwitchToggleStyle: ToggleStyle {
9
+ public var tint: Color
10
+ public var width: CGFloat
11
+ public var height: CGFloat
12
+
13
+ public init(tint: Color = .cyan, width: CGFloat = 34, height: CGFloat = 19) {
14
+ self.tint = tint
15
+ self.width = width
16
+ self.height = height
17
+ }
18
+
19
+ public func makeBody(configuration: Configuration) -> some View {
20
+ SleekSwitchControl(configuration: configuration, tint: tint, width: width, height: height)
21
+ }
22
+ }
23
+
24
+ private struct SleekSwitchControl: View {
25
+ let configuration: ToggleStyle.Configuration
26
+ let tint: Color
27
+ let width: CGFloat
28
+ let height: CGFloat
29
+
30
+ @Environment(\.isEnabled) private var isEnabled
31
+ @State private var isHovered = false
32
+
33
+ private var knobSize: CGFloat { height - 4 }
34
+ private var travelDistance: CGFloat { width - knobSize - 4 }
35
+
36
+ var body: some View {
37
+ Button {
38
+ withAnimation(.spring(response: 0.24, dampingFraction: 0.72)) {
39
+ configuration.isOn.toggle()
40
+ }
41
+ } label: {
42
+ ZStack(alignment: .leading) {
43
+ // Background Track
44
+ Capsule(style: .continuous)
45
+ .fill(
46
+ configuration.isOn
47
+ ? LinearGradient(
48
+ colors: [tint, tint.opacity(0.82)],
49
+ startPoint: .topLeading,
50
+ endPoint: .bottomTrailing
51
+ )
52
+ : LinearGradient(
53
+ colors: [
54
+ Color.white.opacity(isHovered ? 0.16 : 0.11),
55
+ Color.white.opacity(isHovered ? 0.09 : 0.06)
56
+ ],
57
+ startPoint: .top,
58
+ endPoint: .bottom
59
+ )
60
+ )
61
+ .overlay(
62
+ Capsule(style: .continuous)
63
+ .stroke(
64
+ configuration.isOn
65
+ ? tint.opacity(0.55)
66
+ : Color.white.opacity(isHovered ? 0.18 : 0.12),
67
+ lineWidth: 0.8
68
+ )
69
+ )
70
+
71
+ // Active subtle ambient glow
72
+ if configuration.isOn {
73
+ Capsule(style: .continuous)
74
+ .stroke(tint.opacity(0.4), lineWidth: 1.5)
75
+ .blur(radius: 2)
76
+ }
77
+
78
+ // Knob
79
+ Circle()
80
+ .fill(
81
+ configuration.isOn
82
+ ? LinearGradient(
83
+ colors: [.white, Color(white: 0.94)],
84
+ startPoint: .top,
85
+ endPoint: .bottom
86
+ )
87
+ : LinearGradient(
88
+ colors: [
89
+ Color(white: isHovered ? 0.92 : 0.86),
90
+ Color(white: isHovered ? 0.82 : 0.76)
91
+ ],
92
+ startPoint: .top,
93
+ endPoint: .bottom
94
+ )
95
+ )
96
+ .frame(width: knobSize, height: knobSize)
97
+ .shadow(
98
+ color: Color.black.opacity(configuration.isOn ? 0.35 : 0.28),
99
+ radius: 2,
100
+ x: configuration.isOn ? -0.5 : 0.5,
101
+ y: 1
102
+ )
103
+ .padding(.leading, 2)
104
+ .offset(x: configuration.isOn ? travelDistance : 0)
105
+ .scaleEffect(isHovered ? 1.04 : 1.0)
106
+ }
107
+ .frame(width: width, height: height)
108
+ .contentShape(Capsule(style: .continuous))
109
+ }
110
+ .buttonStyle(.plain)
111
+ .opacity(isEnabled ? 1.0 : 0.42)
112
+ .onHover { isHovered = $0 }
113
+ .accessibilityElement(children: .combine)
114
+ .accessibilityValue(configuration.isOn ? "On" : "Off")
115
+ .accessibilityAddTraits(.isButton)
116
+ }
117
+ }