Move compound-ios package into the project.

This commit is contained in:
Doug
2025-09-28 15:19:46 +01:00
committed by Doug
parent 9874d6fd84
commit ed73853c9b
80 changed files with 3658 additions and 25 deletions
@@ -0,0 +1,46 @@
//
// Copyright 2023, 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
@testable import Compound
import SwiftUI
import XCTest
final class DecorativeColorsTests: XCTestCase {
struct TestCase {
let input: String
private let webOutput: Int
// remember that web starts the index from 1 while we start from 0
var output: Int {
webOutput - 1
}
init(input: String, webOutput: Int) {
self.input = input
self.webOutput = webOutput
}
}
func testAvatarColorHash() {
// Match the tests with the web ones for consistency between the two platforms
// https://github.com/element-hq/compound-web/blob/4608dc807c9c904874eac67ff22be3213f4a261d/src/components/Avatar/Avatar.test.tsx#L62
let testCases: [TestCase] = [
.init(input: "@bob:example.org", webOutput: 4),
.init(input: "@alice:example.org", webOutput: 3),
.init(input: "@charlie:example.org", webOutput: 5),
.init(input: "@dan:example.org", webOutput: 4),
.init(input: "@elena:example.org", webOutput: 4),
.init(input: "@fanny:example.org", webOutput: 3)
]
for testCase in testCases {
XCTAssertEqual(Color.compound.decorativeColor(for: testCase.input), Color.compound.decorativeColors[testCase.output])
}
}
}
@@ -0,0 +1,104 @@
//
// Copyright 2023, 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
@testable import Compound
import SwiftUI
import XCTest
final class FontSizeTests: XCTestCase {
/// Test all system text styles to assert mapping between `Font` and `UIFont`.
func testTextStyle() throws {
let caption2FontSize = FontSize.reflecting(.caption2)
XCTAssertEqual(caption2FontSize?.value, 11)
XCTAssertEqual(caption2FontSize?.style, .caption2)
let captionFontSize = FontSize.reflecting(.caption)
XCTAssertEqual(captionFontSize?.value, 12)
XCTAssertEqual(captionFontSize?.style, .caption)
let footnoteFontSize = FontSize.reflecting(.footnote)
XCTAssertEqual(footnoteFontSize?.value, 13)
XCTAssertEqual(footnoteFontSize?.style, .footnote)
let subheadlineFontSize = FontSize.reflecting(.subheadline)
XCTAssertEqual(subheadlineFontSize?.value, 15)
XCTAssertEqual(subheadlineFontSize?.style, .subheadline)
let calloutFontSize = FontSize.reflecting(.callout)
XCTAssertEqual(calloutFontSize?.value, 16)
XCTAssertEqual(calloutFontSize?.style, .callout)
let bodyFontSize = FontSize.reflecting(.body)
XCTAssertEqual(bodyFontSize?.value, 17)
XCTAssertEqual(bodyFontSize?.style, .body)
let headlineFontSize = FontSize.reflecting(.headline)
XCTAssertEqual(headlineFontSize?.value, 17)
XCTAssertEqual(headlineFontSize?.style, .headline)
let title3FontSize = FontSize.reflecting(.title3)
XCTAssertEqual(title3FontSize?.value, 20)
XCTAssertEqual(title3FontSize?.style, .title3)
let title2FontSize = FontSize.reflecting(.title2)
XCTAssertEqual(title2FontSize?.value, 22)
XCTAssertEqual(title2FontSize?.style, .title2)
let titleFontSize = FontSize.reflecting(.title)
XCTAssertEqual(titleFontSize?.value, 28)
XCTAssertEqual(titleFontSize?.style, .title)
let largeTitleFontSize = FontSize.reflecting(.largeTitle)
XCTAssertEqual(largeTitleFontSize?.value, 34)
XCTAssertEqual(largeTitleFontSize?.style, .largeTitle)
}
func testModifiedTextStyle() {
let boldCaptionFontSize = FontSize.reflecting(.caption.bold())
XCTAssertEqual(boldCaptionFontSize?.value, 12)
XCTAssertEqual(boldCaptionFontSize?.style, .caption)
let styledTitle = Font.title.width(.compressed).bold().italic().monospaced()
let styledTitleFontSize = FontSize.reflecting(styledTitle)
XCTAssertEqual(styledTitleFontSize?.value, 28)
XCTAssertEqual(styledTitleFontSize?.style, .title)
}
func testSystemFont() {
let system21FontSize = FontSize.reflecting(.system(size: 21))
XCTAssertEqual(system21FontSize?.value, 21)
let boldSystem29FontSize = FontSize.reflecting(.system(size: 29).bold())
XCTAssertEqual(boldSystem29FontSize?.value, 29)
let styledSystem33 = Font.system(size: 33).width(.compressed).bold().italic().monospacedDigit()
let styledSystem33FontSize = FontSize.reflecting(styledSystem33)
XCTAssertEqual(styledSystem33FontSize?.value, 33)
}
func testCustomFont() {
let custom43FontSize = FontSize.reflecting(.custom("Baskerville", size: 43))
XCTAssertEqual(custom43FontSize?.value, 43)
XCTAssertEqual(custom43FontSize?.style, .body)
let styledCustom35 = Font.custom("Baskerville", size: 35).weight(.thin).monospaced().italic()
let styledCustom35FontSize = FontSize.reflecting(styledCustom35)
XCTAssertEqual(styledCustom35FontSize?.value, 35)
XCTAssertEqual(styledCustom35FontSize?.style, .body)
}
func testCustomFontWithTextStyle() {
let customTitle21FontSize = FontSize.reflecting(.custom("Baskerville", size: 21, relativeTo: .title))
XCTAssertEqual(customTitle21FontSize?.value, 21)
XCTAssertEqual(customTitle21FontSize?.style, .title)
let styledCustomFootnote15 = Font.custom("Baskerville", size: 15, relativeTo: .footnote).weight(.thin).monospaced().italic()
let styledCustomFootnote15FontSize = FontSize.reflecting(styledCustomFootnote15)
XCTAssertEqual(styledCustomFootnote15FontSize?.value, 15)
XCTAssertEqual(styledCustomFootnote15FontSize?.style, .footnote)
}
}
@@ -0,0 +1,112 @@
// Generated using Sourcery 2.2.6 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// swiftlint:disable all
// swiftformat:disable all
import XCTest
@testable import Compound
extension PreviewTests {
// MARK: - PreviewProvider
func testCompoundButtonStyle() async throws {
for (index, preview) in CompoundButtonStyle_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testCompoundIcon() async throws {
for (index, preview) in CompoundIcon_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testCompoundToggleStyle() async throws {
for (index, preview) in CompoundToggleStyle_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testListInlinePicker() async throws {
for (index, preview) in ListInlinePicker_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testListRowAccessory() async throws {
for (index, preview) in ListRowAccessory_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testListRowButtonStyle() async throws {
for (index, preview) in ListRowButtonStyle_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testListRowLabel() async throws {
for (index, preview) in ListRowLabel_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testListRowLoadingSelection() async throws {
for (index, preview) in ListRowLoadingSelection_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testListRowTrailingSection() async throws {
for (index, preview) in ListRowTrailingSection_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testListRow() async throws {
for (index, preview) in ListRow_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testListTextStyles() async throws {
for (index, preview) in ListTextStyles_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testScaledFrameModifier() async throws {
for (index, preview) in ScaledFrameModifier_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testScaledOffsetModifier() async throws {
for (index, preview) in ScaledOffsetModifier_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testScaledPaddingModifier() async throws {
for (index, preview) in ScaledPaddingModifier_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testSearchStyle() async throws {
for (index, preview) in SearchStyle_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
func testSendButton() async throws {
for (index, preview) in SendButton_Previews._allPreviews.enumerated() {
try await assertSnapshots(matching: preview, step: index)
}
}
}
// swiftlint:enable all
// swiftformat:enable all
@@ -0,0 +1,37 @@
//
// Copyright 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
@testable import Compound
import XCTest
class OverrideColorTests: XCTestCase {
func testSwiftUI() {
let colors = CompoundColors()
let tokens = CompoundColorTokens()
XCTAssertEqual(colors.textPrimary, tokens.textPrimary)
colors.override(\.textPrimary, with: .pink)
XCTAssertEqual(colors.textPrimary, .pink)
colors.override(\.textPrimary, with: nil)
XCTAssertEqual(colors.textPrimary, tokens.textPrimary)
}
func testUIKit() {
let colors = CompoundUIColors()
let tokens = CompoundUIColorTokens()
XCTAssertEqual(colors.textPrimary, tokens.textPrimary)
colors.override(\.textPrimary, with: .systemPink)
XCTAssertEqual(colors.textPrimary, .systemPink)
colors.override(\.textPrimary, with: nil)
XCTAssertEqual(colors.textPrimary, tokens.textPrimary)
}
}
@@ -0,0 +1,238 @@
//
// Copyright 2025 New Vector Ltd
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
//
import Combine
import SwiftUI
import XCTest
@testable import Compound
@testable import SnapshotTesting
@MainActor
class PreviewTests: XCTestCase {
private let deviceConfig: ViewImageConfig = .iPhoneX
private let simulatorDevice: String? = "iPhone14,6" // iPhone SE 3rd Generation
private let requiredOSVersion = (major: 18, minor: 5)
private let snapshotDevices = ["iPhone 16", "iPad"]
private var recordMode: SnapshotTestingConfiguration.Record = .missing
override func setUp() {
super.setUp()
if ProcessInfo().environment["RECORD_FAILURES"].map(Bool.init) == true {
recordMode = .failed
}
checkEnvironments()
UIView.setAnimationsEnabled(false)
}
/// Check environments to avoid problems with snapshots on different devices or OS.
private func checkEnvironments() {
if let simulatorDevice {
let deviceModel = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"]
guard deviceModel?.contains(simulatorDevice) ?? false else {
fatalError("\(deviceModel ?? "Unknown") is the wrong one. Switch to using \(simulatorDevice) for these tests.")
}
}
let osVersion = ProcessInfo().operatingSystemVersion
guard osVersion.majorVersion == requiredOSVersion.major, osVersion.minorVersion == requiredOSVersion.minor else {
fatalError("Switch to iOS \(requiredOSVersion) for these tests.")
}
guard !snapshotDevices.isEmpty else {
fatalError("Specify at least one snapshot device to test on.")
}
}
// MARK: - Snapshots
func assertSnapshots(matching preview: _Preview, testName: String = #function, step: Int) async throws {
let preferences = SnapshotPreferences()
let preferenceReadingView = preview.content
.onPreferenceChange(SnapshotPrecisionPreferenceKey.self) { preferences.precision = $0 }
.onPreferenceChange(SnapshotPerceptualPrecisionPreferenceKey.self) { preferences.perceptualPrecision = $0 }
// Render an image of the view in order to trigger the preference updates to occur.
let imageRenderer = ImageRenderer(content: preferenceReadingView)
_ = imageRenderer.uiImage
var sanitizedSuiteName = String(testName.suffix(testName.count - "test".count).dropLast(2))
sanitizedSuiteName = sanitizedSuiteName.prefix(1).lowercased() + sanitizedSuiteName.dropFirst()
for deviceName in snapshotDevices {
guard var device = PreviewDevice(rawValue: deviceName).snapshotDevice() else {
fatalError("Unknown device name: \(deviceName)")
}
// Ignore specific device safe area (using the workaround value to fix rendering issues).
device.safeArea = .one
// Ignore specific device display scale
let traits = UITraitCollection(displayScale: 2.0)
var testName = ""
if let displayName = preview.displayName {
testName = "\(displayName)-\(deviceName)-\(localeCode)"
} else {
testName = "\(deviceName)-\(localeCode)-\(step)"
}
let isScreen = switch preview.layout {
case .device: true
default: false
}
if let failure = assertSnapshots(matching: preview.content,
name: testName,
isScreen: isScreen,
device: device,
testName: sanitizedSuiteName,
traits: traits,
preferences: preferences) {
XCTFail(failure)
}
}
}
private var localeCode: String {
if UserDefaults.standard.bool(forKey: "NSDoubleLocalizedStrings") {
return "pseudo"
}
return languageCode + "-" + regionCode
}
private var languageCode: String {
Locale.current.language.languageCode?.identifier ?? ""
}
private var regionCode: String {
Locale.current.language.region?.identifier ?? ""
}
private func assertSnapshots(matching view: AnyView,
name: String?,
isScreen: Bool,
device: ViewImageConfig,
testName: String = #function,
traits: UITraitCollection = .init(),
preferences: SnapshotPreferences) -> String? {
let matchingView = isScreen ? AnyView(view) : AnyView(view
.frame(width: device.size?.width)
.fixedSize(horizontal: false, vertical: true)
)
return withSnapshotTesting(record: recordMode) {
verifySnapshot(of: matchingView,
as: .prefireImage(preferences: preferences,
layout: isScreen ? .device(config: device) : .sizeThatFits,
traits: traits),
named: name,
testName: testName)
}
}
private func wait(for duration: TimeInterval) {
let expectation = XCTestExpectation(description: "Wait")
DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
expectation.fulfill()
}
_ = XCTWaiter.wait(for: [expectation], timeout: duration + 1)
}
}
private class SnapshotPreferences: @unchecked Sendable {
var precision: Float = 1
var perceptualPrecision: Float = 1
var fulfillmentPublisher: AnyPublisher<Bool, Never>?
}
// MARK: - SnapshotTesting + Extensions
private extension PreviewDevice {
func snapshotDevice() -> ViewImageConfig? {
switch rawValue {
case "iPhone 16", "iPhone 15", "iPhone 14", "iPhone 13", "iPhone 12", "iPhone 11", "iPhone 10":
return .iPhoneX
case "iPhone 6", "iPhone 6s", "iPhone 7", "iPhone 8":
return .iPhone8
case "iPhone 6 Plus", "iPhone 6s Plus", "iPhone 8 Plus":
return .iPhone8Plus
case "iPhone SE (1st generation)", "iPhone SE (2nd generation)":
return .iPhoneSe
case "iPad":
return .iPad10_2
case "iPad Mini":
return .iPadMini
case "iPad Pro 11":
return .iPadPro11
case "iPad Pro 12.9":
return .iPadPro12_9
default: return nil
}
}
}
private extension Snapshotting where Value: SwiftUI.View, Format == UIImage {
static func prefireImage(drawHierarchyInKeyWindow: Bool = false,
preferences: SnapshotPreferences,
layout: SwiftUISnapshotLayout = .sizeThatFits,
traits: UITraitCollection = .init()) -> Snapshotting {
let config: ViewImageConfig
switch layout {
#if os(iOS) || os(tvOS)
case let .device(config: deviceConfig):
config = deviceConfig
#endif
case .sizeThatFits:
// Make sure to use the workaround safe area insets.
config = .init(safeArea: .one, size: nil, traits: traits)
case let .fixed(width: width, height: height):
let size = CGSize(width: width, height: height)
// Make sure to use the workaround safe area insets.
config = .init(safeArea: .one, size: size, traits: traits)
}
return SimplySnapshotting<UIImage>(pathExtension: "png", diffing: .prefireImage(preferences: preferences, scale: traits.displayScale))
.asyncPullback { view in
var config = config
let controller: UIViewController
if config.size != nil {
controller = UIHostingController(rootView: view)
} else {
let hostingController = UIHostingController(rootView: view)
let maxSize = CGSize.zero
config.size = hostingController.sizeThatFits(in: maxSize)
controller = hostingController
}
return snapshotView(config: config,
drawHierarchyInKeyWindow: drawHierarchyInKeyWindow,
traits: traits,
view: controller.view,
viewController: controller)
}
}
}
private extension Diffing where Value == UIImage {
static func prefireImage(preferences: SnapshotPreferences, scale: CGFloat?) -> Diffing {
lazy var originalDiffing = Diffing.image(precision: preferences.precision, perceptualPrecision: preferences.perceptualPrecision, scale: scale)
return Diffing(toData: { originalDiffing.toData($0) },
fromData: { originalDiffing.fromData($0) },
diff: { originalDiffing.diff($0, $1) })
}
}
private extension UIEdgeInsets {
/// A custom inset that prevents the snapshotting library from rendering the
/// origin at (10000, 10000) which breaks some of our views such as MessageText.
static var one: UIEdgeInsets { UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1) }
}
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1522abe037552d058d16a117a5aab3f8533b2a1f874c62fb3a467dbea5a75985
size 365301
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7495424229f590d4750e1263d942a84def528edba32bd2aee5ba805c9d9bd0bc
size 246031
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ae7bc39ec3c30e24d8ac88c8d606f778802f0d4444ca5c500de1d325614e4021
size 143736
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:19c50858911f09d89a9ac7655c12d3d411075e19ae637cc9c7af8d2d74bd6abb
size 95797
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4ded596557ccd9661dcf7b56bd45afec80bf4e70fe44b0b7f5fe82c554e09d54
size 270756
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7ade49dc268c8a7ff62cacbd4d648121fa1fd488ac4f3b32edbd04dfb2191a31
size 151126
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6513d85e4d4bd56b1e23e1e6120a1ad1a10f18ae9a216d10e93a0e8fdf024510
size 27001
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:732408e6893cb40b5a8e3a85ebe334fc74aab6edf7306b1af0fb87cc7ff7e797
size 18848
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fd5f836f60f9a8b075033402c00f13aaac04062572e42bbc1d1fec04c8505ff3
size 97606
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c3a2b451c5a074f5d6980d2be9376a41c5e19a3a35a0c503da02251a5079856e
size 50751
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2ac4f5f9eb71287f49783e7cf36900ac7c9ff70c54eb29eba55a1c1ad1762f20
size 91361
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f4c5095c685fc5b68ecb54245b18deeb6036d1f55547546919e1a1e33cb40315
size 49337
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3945f7af1ab1a55166b574f58688889b174289c25638de8acf8d9f78c2c9f75f
size 109376
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4bdc5025c6c745081e8e2766f54a148a568460ad18e139c0dea9939dff03319a
size 62084
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:01a4916af8da7fa798403e4678cd53f7f10352b5b1d87fef8594935bb61e4fe5
size 370719
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fba908f45758e56689c183c3636c2167cf389f1fb9a5c115276de9150949f1dd
size 250067
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f441c345728aff436af9f7aaf6c725cc6c303309915f63faac5726e4768ec495
size 115602
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7b38ad276f9d70ae600cbdb9ccc01861b584e30532f669895e009732838329ee
size 70069
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0c26d84c066dd85bccb5a5e7a08745803ba4de069493bbce5071b90c55d172cc
size 85789
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b1c2b14d75abcc6529963178e336a730bd899c4ca73b7b8e7f5589a25c2a2859
size 40657
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dccffd12a157f5456f479246044e043313c93e80edca6f822c72fc5b3b74b2f7
size 192255
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f94fc77bc6c85dd850148676053ce549a37486d44950254ce5a12497283bf278
size 135766
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8470bb9adc78c11996a13a21b954d338f911604bb1370c8484d4ace61c897bed
size 134850
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3a9530ae1b21201bf606b46223ff1717a55c464e2b3e262f2e07031a61e2f0fc
size 100075
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7de1fe2709765858fbdfbbee27796f6899ae4ec3130997637a1f521ed9cec2c3
size 92210
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b81ef4ef0f7c7f701323daa06fe202055de4a32087142fcb1410255a28e7fb06
size 49332
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cb82201cb06d09d1a3e3d3ac9b78b0a5686cd1aa08a15445a61116f42bcaf746
size 102895
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5122eab1e08d9f3207410669d7ff1076f02b7df91c1d3cc49356dc7fb10fb705
size 57230
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e9e66de21b08f5460d34a27026c7f80bf2fa30157920dd8576c222848b05408b
size 86910
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0b4a5b177ee1d57b7848eafed1d38a3768bf3310393802374244f76de48a82a2
size 40995
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:37c1b4ef394ebf21c35eb8dba7dd41cff59b264aec57de0fa8dcc0b368eec3b0
size 92691
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:73953b850cad43b8d09628143d3220441877bc3485dddaf734f14a3469778e8c
size 51105
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dee1d6e5f05fefaae3f2cdb8c5d7d942b23f3e5244a9c8589c6cfee1280c2b53
size 85357
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cc49e6cf9dd0490434ee5a189240fe9e45688e0843755ae681a89d35b716944e
size 44655
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f801b1baf3852a280e9edd8c21879f95c933b1f562fdf7db72b7dbcafc71925b
size 112184
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:721e0439a8ed8dbdc201cb618ddf157ac49dbf8f165a84cba932324b24f98252
size 69586
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1e410e13b6bfb668cc3593c746ef0bd48673ab32283630826130cabcc43d6f43
size 100011
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9cbb08c9fe6df9b564c93192aee5c655bf5c7ec69711fae822c7aea9e9a785a3
size 50053
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1ffa8d0056bb4cee07ad513405eb3b3903e21cfbd945866c354b7e67fbdffe19
size 92428
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dd3e0d853e76b65eab44bd0e52d0c468c4fcaf0f60021d74d68949628238acb5
size 49150
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fa1eadbbf0b7afd190fc65855ff81650216fb4bbc188802a93f210a9a2c2a896
size 79859
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7404a991f29fb33fe7d3d7fbcb102d2e89ed4975d6cb1e125e4448a03a885e8a
size 39549