AlarmBGLimitSection.swift 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // LoopFollow
  2. // AlarmBGLimitSection.swift
  3. import SwiftUI
  4. struct AlarmBGLimitSection: View {
  5. // ────────── Public API ──────────
  6. let header: String?
  7. let footer: String?
  8. let toggleText: String
  9. let pickerTitle: String
  10. let range: ClosedRange<Double>
  11. let defaultOnValue: Double
  12. @Binding var value: Double?
  13. // ────────────────────────────────
  14. init(
  15. header: String? = nil,
  16. footer: String? = nil,
  17. toggleText: String,
  18. pickerTitle: String,
  19. range: ClosedRange<Double>,
  20. defaultOnValue: Double? = nil,
  21. value: Binding<Double?>
  22. ) {
  23. self.header = header
  24. self.footer = footer
  25. self.toggleText = toggleText
  26. self.pickerTitle = pickerTitle
  27. self.range = range
  28. if let v = defaultOnValue, range.contains(v) {
  29. self.defaultOnValue = v
  30. } else {
  31. self.defaultOnValue = range.lowerBound
  32. }
  33. _value = value
  34. }
  35. // MARK: - Private bindings
  36. private var isOn: Binding<Bool> {
  37. Binding(
  38. get: { value != nil },
  39. set: { on in
  40. if on, value == nil { value = defaultOnValue }
  41. if !on { value = nil }
  42. }
  43. )
  44. }
  45. private var pickerValue: Binding<Double> {
  46. Binding(
  47. get: { value ?? defaultOnValue },
  48. set: { newVal in value = newVal }
  49. )
  50. }
  51. // MARK: - Body
  52. var body: some View {
  53. Section(
  54. header: header.map(Text.init),
  55. footer: footer.map(Text.init)
  56. ) {
  57. Toggle(toggleText, isOn: isOn)
  58. if isOn.wrappedValue {
  59. BGPicker(
  60. title: pickerTitle,
  61. range: range,
  62. value: pickerValue
  63. )
  64. }
  65. }
  66. }
  67. }