// // Swiftfin is subject to the terms of the Mozilla Public // License, v2.0. If a copy of the MPL was not distributed with this // file, you can obtain one at https://mozilla.org/MPL/2.0/. // // Copyright (c) 2025 Jellyfin & Jellyfin Contributors // import SwiftUI extension Binding { func clamp(min: Value, max: Value) -> Binding where Value: Comparable { Binding( get: { Swift.min(Swift.max(wrappedValue, min), max) }, set: { wrappedValue = Swift.min(Swift.max($0, min), max) } ) } func coalesce(_ defaultValue: T) -> Binding where Value == T? { Binding( get: { wrappedValue ?? defaultValue }, set: { wrappedValue = $0 } ) } func contains(_ value: E) -> Binding where Value == [E] { Binding( get: { wrappedValue.contains(value) }, set: { shouldBeContained in if shouldBeContained { wrappedValue.append(value) } else { wrappedValue.removeAll { $0 == value } } } ) } func map(getter: @escaping (Value) -> V, setter: @escaping (V) -> Value) -> Binding { Binding( get: { getter(wrappedValue) }, set: { wrappedValue = setter($0) } ) } func min(_ minValue: Value) -> Binding where Value: Comparable { Binding( get: { Swift.max(wrappedValue, minValue) }, set: { wrappedValue = Swift.max($0, minValue) } ) } func negate() -> Binding where Value == Bool { map(getter: { !$0 }, setter: { $0 }) } } extension Binding where Value: RangeReplaceableCollection, Value.Element: Equatable { func contains(_ element: Value.Element) -> Binding { Binding( get: { wrappedValue.contains(element) }, set: { newValue in if newValue { if !wrappedValue.contains(element) { wrappedValue.append(element) } } else { wrappedValue.removeAll { $0 == element } } } ) } }