Skip to content

Latest commit

 

History

History
1206 lines (766 loc) · 44.7 KB

CHANGELOG.md

File metadata and controls

1206 lines (766 loc) · 44.7 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Fixed

Added

Removed

Changed

Deprecated

Security

Documentation

Misc

Internal

Past Releases

4.0.0 - 2024-04-29

Added

  • AccessibilityElement.CustomContent now exposes previously internal methods for creating AXCustomContent objects.
  • Introduced a new Flow layout type, for creating flow layout based elements.

Changed

  • AttributedLabel now activates a single contained link when activated by accessible technologies.
  • AccessibilityElement.CustomContent.Importance.Regular renamed to Default.

3.1.0 - 2024-03-26

Fixed

  • Fixed a bug where AccessibilityBlocker would block accessibility when isBlocking is false.

Added

  • Added support for accessibility focus triggers to force VoiceOver to focus on any given element.
  • Added startTimestamp to BlueprintViewRenderMetrics. This represents the mach time in seconds at which the render started, from CACurrentMediaTime().

3.0.0 - 2024-02-21

Fixed

  • Fixed an issue where AttributedLabel would not properly handle tapping on links when a label was stretched.

Added

  • AccessibilityElement now supports providing arbitrary strings to assistive devices using the AXCustomContent protocol.

Removed

Changed

  • The behavior of name of ElementPreview has been change, affecting the SwiftUI previewName. Instead of including device or size information (i.e. sizeThatFits - \(name)), it now either defaults to the Xcode default if given an empty string, and shows only the name if name is non-empty.
  • Updated minimum deployment target from iOS 14 to iOS 15.

Internal

  • Updated CI to use M1 machines, Xcode 15.1, and Ruby 3.2.2.
  • Added iOS 17 snapshot images.
  • Bump Swift version to 5.9.
  • Update Ruby gems.

2.2.0 - 2023-09-22

Fixed

  • Fixed a bug that could cause a crash or incorrect layout when an element with lazily resolved content (such as GeometryReader) generated a subtree that varied within a layout pass. (#468)

Added

  • Added a TintAdjustmentMode element and .tintAdjustmentMode(:) modifier for finer control of tint color during modal presentations.

2.1.0 - 2023-09-06

Fixed

  • Resolved a Swift 5.9 compilation warning: Forming 'UnsafeRawPointer' to a variable of type 'NSObject'; this is likely incorrect because 'NSObject' may contain an object reference.
  • KeyboardObserver has been updated to handle iOS 16.1+ changes that use the screen's coordinate space to report keyboard position. This can impact reported values when the app isn't full screen in Split View, Slide Over, and Stage Manager.

Changed

  • Lifecycle callbacks like onAppear and onDisappear now occur outside of the layout pass; allowing, eg, onAppear to safely trigger a re-render.

Internal

  • Update CI script to reference the xcodesorg/made/xcodes package for installing simulator runtimes.
  • Corrected a typo in AttributedLabel, which now exits paragraph style enumeration after encountering the first paragraph style. This is an optimization and not a functional change. The method continues to accept only a paragraph style which spans the length of the attributed string.

2.0.0 - 2023-05-02

Fixed

  • ConstrainedAspectRatio measures correctly in fitParent and fillParent modes when the proposed constraint has the same aspect ratio as the element's constraint.
  • ConstrainedAspectRatio adheres to the Caffeinated Layout contract when unconstrained in fitParent or fillParent, by reporting infinity instead of falling back to the constrained element's size.

Changed

  • Caffeinated Layout is enabled by default. You can disable it on a BlueprintView with the layoutMode property, or disable it globally by setting LayoutMode.default.

Deprecated

  • ConstrainedAspectRatio content mode fillParent is deprecated, due to having limited utility in Caffeinated Layout.

1.0.0 - 2023-04-18

Fixed

  • Restored documentation generation by executing the generate_docs.sh script with bundle exec to ensure gems are referenced properly.

Added

  • Introduced a new layout engine, Caffeinated Layout. Caffeinated Layout features a new API for custom layouts that is modeled after SwiftUI, and greatly improves performance.

    To enable Caffeinated Layout globally, set LayoutMode.default to .caffeinated. To enable it for a single view, set the layoutMode property of a BlueprintView.

    Caffeinated Layout is not enabled by default yet, but will be in a future release.

  • Added layoutMode to BlueprintViewRenderMetrics to expose which layout mode was used to render a Blueprint view.

Changed

  • The Layout and SingleChildLayout protocols have new methods to support Caffeinated Layout.

    To improve performance, Caffeinated Layout requires elements to adhere to a new contract for sizing behavior. Many elements can be easily adapted to the new API, but certain behaviors are no longer possible, particularly with regard to behavior when the size constraint is unconstrained.

    For more information about implementing these protocols and the sizing contract, see the Layout documentation.

Internal

  • Updated jazzy gem (0.14.3).
  • Updated cocoapods (1.12.0).
  • Updated Ruby version (2.7).

0.50.0 - 2023-03-07

Fixed

  • The Environment will now automatically inherit for BlueprintView instances nested inside UIViewElement during measurement.

Added

  • Introduced ElementContent.init(byMeasuring:), for use when your Element contains a nested BlueprintView, commonly used to implement stateful elements. This avoids detached measurements and improves performance.

Changed

  • Renamed BlueprintViewUpdateMetrics to BlueprintViewRenderMetrics.
  • Renamed BlueprintViewRenderMetrics.measureDuration to layoutDuration.
  • Renamed BlueprintViewMetricsDelegate.blueprintView(_:completedUpdateWith:) to blueprintView(_:completedRenderWith:).
  • BlueprintViewRenderMetrics values are now calculated using CACurrentMediaTime instead of Date.

Internal

  • Added an Internal section to the changelog. This section is intended to capture any notable non-public changes to the project.
  • ElementContent.init(child:) now utilizes a unique ContentStorage type, which improves layout performance.

Fixed

  • Image's aspectFill contentMode now measures the same as aspectFit to avoid aggressively taking up space when not necessary.

Fixed

  • Fixed unexpected measurement results that could occur from Images using the aspectFit contentMode.

Fixed

  • Fix Catalyst version specifier in SPM package.

Added

  • Added AccessibilityElement.CustomAction to allow custom actions for use by assistive technologies.
  • Added accessibilityCustomActions property to Label and AttributedLabel.
  • UIViewElementContext now passes through an environment property, enabling environment-dependent measurements and layouts.

Changed

  • Updated minimum deployment target from iOS 12 to iOS 14.
  • URLHandlerEnvironmentKey.defaultValue should now be a no-op in extensions.
  • Marks pod as APPLICATION_EXTENSION_API_ONLY

Added

  • accessibilityHint property for Label and AttributedLabel.

Fixed

  • When stacks lay out with more fixed magnitude than is available for layout, flexible items will no longer receive a negative width.

Changed

  • StackElement layouts have been optimized for the case of one fixed and one flexible element to improve performance. This also fixes issues as described in #265 in many cases.

Fixed

  • Improve AttributedLabel rendering performance.

Fixed

  • Fixed an issue where rounding was handled incorrectly for nested BlueprintViews.

Added

  • Added new logging option to expose aggregate measurements.

Fixed

  • AccessibilityContainer now omits accessibility elements where .accessibilityElementsHidden is true.

Added

  • Image now provides an override to prevent VoiceOver from generating accessibility descriptions.

Added

  • Introduced an Element.modify { ... } conditional, to allow changing properties on an element.

Changed

  • Aligned will now constrain its content to the provided layout frame. If you need content to exceed the layout frame, please use Decoration.

  • AccessibilityElement will now only return accessibilityPath for elements with a non-square corner style. This avoids needlessly changing AccessibilitySnapshot (https://github.com/cashapp/AccessibilitySnapshot) reference images.

Added

  • Introduced accessibilityFrameCornerStyle to AccessibilityElement.

Added

  • Added .grows and .shrinks to StackLayout.Child.Priority, to allow for extra control over how flexible elements grow and shrink.
  • AccessibilityBlocker now takes in a Bool to control blocking, to avoid changing the element hierarchy to toggle if blocking is occurring.

Added

  • Added support for optionals in builders without unwrapping via if let.
  • Static constants on Alignment are now public (such as Alignment.topTrailing).

Changed

  • AnimationAttributes has gained a .default option.
  • LayoutTransition has default values for its AnimationAttributes parameters.

Added

  • Added support for adjusting text spacing and sizing on AttributedLabel and Label when text does not fit within the provided layout rect.

Removed

  • MeasurementCachingKey has been removed – Blueprint has cached measurements per render pass for many releases, so this actually slowed down layouts due to additional allocations and cache checking. This is about a 5-10% performance improvement depending on the layout.

Changed

  • Accessibility increment, decrement actions have been moved to associated values on the AccessibilityElement.Trait enum.

Added

  • Shadows on Label and AttributedLabel
  • Accessibility increment, decrement and activate actions now available on AccessibilityElement
  • Decorate has a new aligned positioning, that uses stack-style Alignment values and alignment guides.
  • The context vended to custom Decorate positions includes the decorated content size.

Changed

  • The context vended to custom Decorate positions was renamed to PositionContext, and the contentFrame property was replaced with a contentSize.

Fixed

  • Decorate will now properly scale its base content to the full size of the rendered element, if the measured and laid out sizes differ.
  • Fixed an issue where AttributedLabel could cause a crash when voice over was enabled.

Added

  • LayoutWriter.Context now exposes the layout phase, to differ any calculations between measurement and layout.

Fixed

  • Fixed an issue where AttributedLabel and Label would not pass touches to super views when expected.

Fixed

  • Fixed an issue where AttributedLabel might not detect link taps in multi-line labels.
  • .aligned(vertically:horizontally:) now has the correct default values to match the Aligned initializer.

Changed

  • The default line break mode for Label is now byTruncatingTail, matching the default for UILabel. (It was previously byWordWrapping, which does not indicate that truncation occured.)
  • AttributedLabel will normalize certain line break modes based on the number of lines.

0.35.1 - 2022-01-13

Fixed

  • Label and AttributedLabel now correctly report their UIAccessibilityTraits.

0.35.0 - 2022-01-11

Added

  • Added the EditingMenu element, which allows showing a UIMenuController (aka the system editing menu) on tap, long press, or based on a trigger.

Changed

  • Label.font now defaults to using a font of size UIFont.labelFontSize (17) instead of UIFont.systemFontSize.

0.34.0 - 2021-12-16

Added

  • Support CALayerCornerCurve for Box corner styles.
  • Added AttributedText, which supports applying strongly-typed attributes to strings (much like the AttributedString type introduced in iOS 15).
  • Added support for links to AttributedLabel:
    • Links can be added using the link attribute of the attributed string. This attribute supports URLs or Strings.
    • The label also supports detecting certain types of data and links, much like UITextView. Use the linkDetectionTypes property to specify which types of data to detect.
    • Links are opened using the LinkHandler in the environment, which by default uses UIApplication.shared.open(_:options:completionHandler:). Customize link handling by providing a URLHandler to the environment at the appropriate scope. AttributedLabel also has a function for easily handling links with a closure using the onLinkTapped method.

0.33.3 - 2021-12-8

Fixed

  • Fixed an issue where Box did not implicitly animate its shadow.

Changed

  • Reverted scroll view keyboard inset behavior to the behavior in 0.30.0, since the recent changes were causing unexpected issues.

0.33.2 - 2021-11-30

Fixed

  • Fixed an issue where ScrollView did not adjust its content inset correctly when the keyboard height or content insets changed.

0.33.1 - 2021-11-22

Fixed

  • Fixed an issue where BlueprintView would not size correctly when used with Auto Layout.

Added

  • Added an ElementContent variant whose measureFunction takes in both a SizeConstraint and an Environment.

0.33.0 - 2021-11-18

Added

  • Allow measuring within an explicit SizeConstraint in GeometryProxy.
  • Add an additional stackLayoutChild(priority:) method overload, for easier autocomplete when only customizing the layout priority.

Changed

  • Values returned from sizeThatFits and systemLayoutSizeFitting are now cached.

0.32.0 - 2021-11-16

Fixed

  • Fixed an issue where the keyboard inset adjustment was incorrect in some cases.
  • Fixed a retain cycle in @FocusState. (#285)

Added

  • Add support for for...in loops and available checks to result builder APIs.

0.31.0 - 2021-11-09

Fixed

  • intrinsicContentSize is now cached.

Added

  • Improved error messages when using result builders with optional values.

0.30.0 - 2021-10-15

Added

  • Added a Hidden element and .hidden() modifier for hiding elements.
  • Overlay now supports result builders.
  • SegmentedControl now supports result builders.

Removed

  • Removed deprecated initializer from AccessibilityElement which was causing ambiguous initializer errors.

Changed

  • UserInteractionEnabled has been moved from BlueprintUICommonControls into BlueprintUI. It no longer has a backing view, and instead uses layout attributes to apply itself to elements. This change shouldn't affect consumers.

0.29.0 - 2021-09-21

Added

  • The @FocusState property wrapper can be used to manage focus of text fields. (#259)

    After binding a text field to a state, you can programmatically focus the field by setting the state value.

    struct LoginForm: ProxyElement {
        enum Field: Hashable {
            case username, password
        }
    
        @FocusState private var focusedField: Field?
    
        var elementRepresentation: Element {
            // This text field will be focused when `self.focusedField = .username`
            TextField(text: "")
                .focused(when: $focusedField, equals: .username)
        }
    }
  • Row, Column, EqualStack, and GridRow can now be initialized declaratively using result builders. ([#220])

    • To declare one of these containers, simply include the elements inside the ElementBuilder trailing closure.
    • To customize the container, pass values through the containers init or leave out to use the provided defaults parameters.
    • To customize one of the child element's container specific properties (key, priority, etc), tack on a corresponding modifier such as stackLayoutChild() and gridRowChild().
    let row = Row(alignment: .fill) {
      TestElement()
      TestElement2()
        .stackLayoutChild(priority: .fixed, alignmentGuide: { _ in 0 }, key: "two")
    }
  • The accessibilityElement(...) modifier has been added for wrapping an Element in an AccessibilityElement. Note that this will override all accessibility parameters of the Element being wrapped, even if values are left unspecified or set to nil.

  • An initializer on AccessibilityElement that requires a label, value, and traits.

  • Overlay supports keys for disambiguation between view updates. (#264)

Changed

  • BlueprintView's intrinsicContentSize will now return UIView.noIntrinsicMetric if there is no element associated with it.

  • TextField's becomeActiveTrigger and resignActiveTrigger properties have been replaced with a focusBinding for use with the new @FocusState property wrapper.

Deprecated

  • The accessibility(...) modifier has been deprecated. Use accessibilityElement(...) instead.
  • An initializer on AccessibilityElement that allowed all parameters to be unspecified. Use the initializer with required parameters instead.
  • Overlay.add(_:) deprecated in favor of Overlay.add(key:child:).

0.28.1 - 2021-09-10

Added

  • View-backed elements may opt-in to a frame rounding behavior that prioritizes preserving the frame size rather than the frame edges. This is primarily meant for text labels, to fix an issue where labels gain or lose a pixel in rounding and become wrapped or truncated incorrectly. (#257)

Changed

  • Lifecycle hooks are guaranteed to run after all views are updated. (#260)

0.28.0 - 2021-09-01

Fixed

  • Fixed an issue where Label and AttributedLabel were not accessibility elements.

Added

  • Label AttributedLabel and TextField elements now support configuration of accessibility traits.

  • The Environment is now automatically propagated through to nested BlueprintViews within a displayed Element hierarchy. This means that if your view-backed Elements themselves contain a BlueprintView (eg to manage their own state), that nested view will now automatically receive the correct Environment across BlueprintView boundaries. If you were previously manually propagating Environment values you may remove this code. If you would like to opt-out of this behavior; you can set view.automaticallyInheritsEnvironmentFromContainingBlueprintViews = false on your BlueprintView.

  • Lifecycle hooks. You can hook into lifecycle events when an element's visibility changes.

    element
      .onAppear {
        // runs when `element` appears
      }
      .onDisappear {
        // runs when `element` disappears
      }

Removed

Changed

0.27.0 - 2021-06-22

Changed

  • The signature of Element.backingViewDescription(bounds: CGRect, subtreeExtent: CGRect?) -> ViewDescription? has changed to backingViewDescription(with context: ViewDescriptionContext) -> ViewDescription? (#231). This is a large breaking change, but is worth it as it allows us to pass additional context to backingViewDescription in the future in a non-breaking way. The ViewDescriptionContext contains the bounds and subtreeExtent, as well as the Environment the element is rendered in.

0.26.0 - 2021-06-02

Added

  • Add ScrollTrigger, which adds the ability set the content offset of a ScrollView
  • Add UIViewElementContext to UIViewElement.updateUIView. The context currently has one property, isMeasuring, which tells you if the view being updated is the static measuring instance.

0.25.0 - 2021-05-5

Changed

0.24.0 - 2021-04-16

Added

  • Add Keyed element, which can be used to help differentiate elements during the diff and update process, eg to assist with proper animation transitions.

  • Introduce GridRow, a Row alternative suited for columnar layout. GridRow supports the following:

    • spacing
    • vertical alignment
    • children with absolutely-sized widths
    • children with proportionally-sized widths¹

    ¹Proportional width in this case always means "a proportion of available layout space after spacing and absolutely-sized children are laid out."

    Example:

    GridRow { row in
      row.spacing = 8
      row.verticalAlignment = .center
      row.add(width: .absolute(50), child: authorLabel)
      row.add(width: .proportional(0.75), child: bodyLabel)
      row.add(width: .proportional(0.25), child: dateLabel)
    }
  • Added support to LayoutWriter to allow specifying keys for child Elements.

  • Blueprint can now emit signpost logs during its render pass, which you can use for performance tuning. (#209)

    Signpost logs are disabled by default. To enable them, set BlueprintLogging.enabled = true.

Changed

  • The layout system now uses a caching system to improve performance by eliminating redundant measurements. (#209)

0.23.0 - 2021-03-26

Added

searchField
    .userInteractionEnabled(canBeginSearch)

Changed

0.22.0 - 2021-03-15

Added

  • Introduce Decorate to allow placing a decoration element in front or behind of an Element, without affecting its layout. This is useful for rendering tap or selection states which should overflow the natural bounds of the Element, similar to a shadow, or useful for adding a badge to an Element.

0.21.0 - 2021-02-17

Added

Changed

0.20.0 - 2021-01-12

Added

0.19.1 - 2021-01-06

Removed

0.19.0 - 2021-01-05

Fixed

  • Ensure that Elements are a value type. This is generally assumed by Blueprint, but was previously not validated. This is only validated in DEBUG builds, to avoid otherwise affecting performance.

Added

  • Add LayoutWriter, which makes creating custom / arbitrary layouts much simpler. You no longer need to define a custom Layout type; instead, you can just utilize LayoutWriter and configure and place your children within its builder initializer.

0.18.0 - 2020-12-08

Added

  • Add AccessibilityContainer.identifier ([#180])

0.17.1 - 2020-10-30

Fixed

  • Fixed an issue where view descriptions were applied with unintentional animations while creating backing views. This could happen if an element was added during a transition. (#175)

  • Fixed pull-to-refresh inset for iOS 13+. (#176)

0.17.0 - 2020-10-21

Added

  • Add alignment guides to stacks. (#153)

    Alignment guides let you fine-tune the cross axis alignment. You can specifying a guide value for any child in that element's coordinate space. Children are aligned relatively to each other so that the guide values line up, and then the content as a whole is aligned to the stack's bounds.

    In this example, the center of one element is aligned 10 points from the bottom of another element, and the contents are collectively aligned to the bottom of the row:

    Row { row in
        row.verticalAlignment = .bottom
    
        row.add(
            alignmentGuide: { d in d[VerticalAlignment.center] },
            child: element1
        )
    
        row.add(
            alignmentGuide: { d in d.height - 10 },
            child: element2
        )
    }

Removed

Deprecated

  • Row alignments leading and trailing are deprecated. Use top and bottom instead. (#153)

0.16.0 - 2020-09-22

Fixed

  • Fixed EqualStack to properly constrain children when measuring. (#157)

Added

  • Add a new TransitionContainer.init that supports further customization during initialization and has the same defaults as ViewDescription. (#155, #158)

  • Add transition(onAppear:onDisappear:onLayout) and transition(_:) methods to Element to describe transition animations. (#155, #158)

Removed

  • Remove GridLayout; it's incomplete and was never really intended to be consumed widely. The intended replacement is putting EqualStacks inside of a Column, or Rows inside a Column.

Deprecated

  • TransitionContainer(wrapping:) is deprecated. Use the new TransitionContainer(transitioning:) instead. (#158)

Misc

  • Removed some redundant work being done during rendering. (#154)

0.15.1 - 2020-09-16

Fixed

  • Fixes a crash that can occur in Box when specifying a corner radius and shadow. (#149)

0.15.0 - 2020-09-14

Added

  • Add addFixed(child:) and addFlexible(child:) methods to StackElement for adding children with a grow & shrink priority of 0.0 and 1.0 respectively. (#143)

  • Add capsule case to Box.CornerStyle (#145). This addition sugars the following pattern:

    GeometryReader { geometry in
      Box(cornerStyle: .rounded(geometry.constraint.height.maximum / 2.0))
    }

    into

    Box(cornerStyle: .capsule)
  • Add accessibilityFrameSize to AccessibilityElement for manually specifying a size for the frame rendered by Voice Over. (#144)

  • Add Opacity element for modifying the opacity of a wrapped element. (#147)

Changed

  • BlueprintView will call layoutIfNeeded on backing views during its layout pass. This allows backing views' subviews that are laid out during layoutSubviews to participate in animations. (#139)

0.14.0 - 2020-08-12

Added

  • Add textColor property on TextField (#133).

  • Add the windowSize environment key. (#134)

  • Add GeometryReader. (#135)

    This element allow you to compose elements whose contents depend on the amount of space available.

    Here is an example that dynamically chooses an image based on the width available:

    GeometryReader { (geometry) -> Element in
        let image: UIImage
        switch geometry.constraint.width.maximum {
        case ..<100:
            image = UIImage(named: "small")!
        case 100..<500:
            image = UIImage(named: "medium")!
        default:
            image = UIImage(named: "large")!
        }
        return Image(image: image)
    }

Changed

  • Default ScrollView.delaysContentTouches to true (#132)

Misc

  • Set an explicit shadow path on Box (#137)

0.13.1 - 2020-07-30

Added

  • Introduce AccessibilityContainer element for wrapping an element with multiple sub-elements that should be in a voice over container.

  • Add font property on TextField (#127).

0.13.0 - 2020-07-20

Fixed

  • Update the scroll indicator inset when adjusting the content inset.

  • Label & AttributedLabel use an internal UILabel for measurement. This fixes measurement when there is a line limit set. However, it also means that the screen scale cannot be specified and is always assumed to be UIScreen.main.scale. These elements may not be measured correctly if they are placed on a screen other than UIScreen.main. (#120)

Added

  • Introduce MeasurementCachingKey, to allow for elements to provide a way to cache their measurement during layout passes. This provides performance optimizations for elements whose layout and measurement is expensive to calculate.

  • Introduce UIViewElement to make wrapping self-sizing UIViews easier.

    You can now write a UIViewElement like this:

    struct Switch : UIViewElement
    {
      var isOn : Bool
    
      typealias UIViewType = UISwitch
    
      static func makeUIView() -> UISwitch {
          UISwitch()
      }
    
      func updateUIView(_ view: UISwitch) {
          view.isOn = self.isOn
      }
    }
    

    And the elements will be sized and presented correctly based on the view's sizeThatFits.

  • Add isAccessibilityElement to Label and AttributedLabel. (#120)

  • Add lineHeight to Label for specifying custom line heights. AttributedLabel has a textRectOffset property to support this. (#120)

Changed

0.12.2 - 2020-06-08

Fixed

Added

0.12.1 - 2020-06-05

Fixed

0.12.0 - 2020-06-04

Fixed

  • Removed layout rounding no longer needed since #64 (#95).

Added

  • Add support for the iPhone SE 2 in ElementPreview.

  • Added tintColor and contentMode into the initializer for Image. (#100)

  • Added an Empty element, to mirror EmptyView in SwiftUI. It is an element with no size and draws no content.

  • Environment (#101).

    You can now read and write values from an Environment that is automatically propagated down the element tree. You can use these values to dynamically build the contents of an element, without having to explicitly pass every value through the tree yourself.

    You can read these values with EnvironmentReader:

    struct Foo: ProxyElement {
        var elementRepresentation: Element {
            EnvironmentReader { environment -> Element in
                Label(text: "value from environment: \(environment.foo)")
            }
        }
    }

    And set them with AdaptedEnvironment:

    struct Bar: ProxyElement {
        var elementRepresentation: Element {
            ComplicatedElement()
                .adaptedEnvironment { environment in
                    environment.foo = "bar"
                }
        }
    }

    Several enviroment keys are available by default (#102):

    • calendar
    • display scale
    • layout direction
    • locale
    • safe area insets
    • time zone

    You can create your own by making a type that conforms to EnvironmentKey, and extending Environment with a new property:

    extension Environment {
        private enum FooKey: EnvironmentKey {
            static let defaultValue: String = "default value"
        }
    
        /// The current Foo that elements should use.
        public var foo: String {
            get { self[FooKey.self] }
            set { self[FooKey.self] = newValue }
        }
    }

0.11.0 - 2020-05-10

Fixed

  • Fixed ConstrainedSize to ensure that the measurement of its inner element respects the ConstrainedSize's maximum size, which matters for measuring elements which re-flow based on width, such as elements containing text.

  • Changed BlueprintView.sizeThatFits(:) to treat width and height separately when determining if measurement should be unconstrained in a given axis.

Added

  • Added support for SwiftUI-style element building within BlueprintUI and BlueprintUICommonControls.

    This allows you to replace this code:

    ScrollView(.fittingHeight) (
      wrapping: Box(
        backgroundColor .lightGrey,
        wrapping: Inset(
          uniformInset: 10.0,
          wrapping: ConstrainedSize(
            height: .atLeast(20.0),
            wrapping: Label(
              text: "Hello, world!"
            )
          )
        )
      )
    )

    With this code:

    Label(text: "Hello, World!")
      .constrainedTo(height: .atLeast(20.0))
      .inset(by: 20.0)
      .box(background: .lightGrey)
      .scrollable(.fittingHeight)

    Improving readability and conciseness of your elements.

0.10.0 - 2020-04-27

Added

  • BlueprintView will align view frames to pixel boundaries after layout (#64).

0.9.2 - 2020-04-27

Fixed

  • Don't try to build SwiftUI previews on 32 bit ARM devices – SwiftUI does not exist on these devices.

0.9.1 - 2020-04-17

Fixed

  • Weak link SwiftUI so if an app is not already linking SwiftUI, it will build correctly.

0.9.0 - 2020-04-17

Added

0.8.0 - 2020-04-03

Fixed

  • Properly measure the child of ScrollView to allow for unconstrained measurement.
  • Fix stack layout during underflow (#72)

Added

  • ScrollView can automatically adjust its content inset for the keyboard (#55)

Changed

  • Improved element diffing (#56)

0.7.0 - 2020-03-30

Added

  • Xcode 11 and Swift 5.1 support (#67).

Changed

Removed

  • Raise minimum deployment target from iOS 9.3 to iOS 10 (#66).

0.6.0 - 2020-02-24

Added

  • Add keyboardDismissMode property on ScrollView (#57).
  • Add textAlignment property on TextField (#53).

0.5.0 - 2020-01-24

Fixed

  • Prevent divide-by-zero when a stack contains zero-size elements (#52).

Added

  • Add fill alignment to Aligned (#42).

Documentation

  • Fix typos in the tutorial (#46).
  • Add docs to Overlay (#45).

0.4.0 - 2019-12-04

Fixed

  • Public init on Aligned (#41).

Changed

  • Guarantee that subviews are ordered the same as their associated elements (#32).

0.3.1 - 2019-11-15

Fixed

  • Do not run snapshot tests from CocoaPods (#40).
  • Make tests with float comparisons more lenient for 32-bit (#35).

Added

  • Add Swift Package Manager support (#37).

Documentation

  • Add Getting Started section to README (#38).

0.3.0 - 2019-11-12

Added

  • Add Stack alignment options justifyToStart, justifyToCenter, and justifyToEnd (#24).
  • Add ConstrainedAspectRatio element (#23).
  • Add EqualStack element (#26).
  • Add Rule element (#22).
  • Add Aligned element (#21).
  • Add a screen scale property to some elements (#18).
  • Swift 5 support (#15).

Changed

  • Reorder the parameters of ConstrainedSize, Inset, Button, and Tappapble, so that the wrapped element is the last parameter (#19).

0.2.2 - 2019-03-29

  • First stable release.