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.
5.1.0 - 2024-11-25
- The
accessibilityIdentifier
can now be set onAttributedLabel
.
- Added release and changelog managements scripts to streamline releases.
5.0.1 - 2024-11-04
Flow
children now support a layoutpriority
, to specify if they should grow to use the extra space in a run.
- Bump CI Xcode version to 15.4.
5.0.0 - 2024-10-30
BlueprintView
has added preconditions to some methods to ensure they are only invoked on the main queue.
- Renamed deprecated function
accessibility(label:value:traits:hint:identifier:accessibilityFrameSize:)
todeprecated_accessibility(label:value:traits:hint:identifier:accessibilityFrameSize:)
.
4.3.0 - 2024-09-18
BlueprintView
will now pass through touches to views lower in the view hierarchy ifpassThroughTouches
is true.
- Moved
CornerStyle
out of theBox
namespace, and is now a root type inBlueprintUICommonControls
.Box.CornerStyle
is still available as a typealias.
4.2.1 - 2024-08-02
- Made public the
UIBezierPath
convenience init that uses aBox.CornerStyle
.
4.2.0 - 2024-06-25
Label
andAttributedLabel
now supportaccessibilityValue
.
4.1.2 - 2024-06-17
- Fix a bug in which newlines were preserved in accessibility labels.
4.1.1 - 2024-06-14
- Fixed a string range bug when a closed range should be half open.
4.1.0 - 2024-06-13
- Fixed a bug where
AttributedLabel
's accessibility utterance was not properly announcing links.
4.0.1 - 2024-06-04
- Fixed a bug where defining a
Box
with a.rounded
CornerStyle
withCorners
set to anything other than.all
would sometimes still round all of the corners.
4.0.0 - 2024-04-29
AccessibilityElement.CustomContent
now exposes previously internal methods for creatingAXCustomContent
objects.- Introduced a new
Flow
layout type, for creating flow layout based elements.
AttributedLabel
now activates a single contained link when activated by accessible technologies.AccessibilityElement.CustomContent.Importance.Regular
renamed toDefault
.
3.1.0 - 2024-03-26
- Fixed a bug where
AccessibilityBlocker
would block accessibility whenisBlocking
isfalse
.
- Added support for accessibility focus triggers to force VoiceOver to focus on any given element.
- Added
startTimestamp
toBlueprintViewRenderMetrics
. This represents the mach time in seconds at which the render started, fromCACurrentMediaTime()
.
3.0.0 - 2024-02-21
- Fixed an issue where
AttributedLabel
would not properly handle tapping on links when a label was stretched.
AccessibilityElement
now supports providing arbitrary strings to assistive devices using theAXCustomContent
protocol.
- The behavior of
name
ofElementPreview
has been change, affecting the SwiftUIpreviewName
. 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 thename
ifname
is non-empty. - Updated minimum deployment target from iOS 14 to iOS 15.
- 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 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 a
TintAdjustmentMode
element and.tintAdjustmentMode(:)
modifier for finer control of tint color during modal presentations.
2.1.0 - 2023-09-06
- 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.
- Lifecycle callbacks like
onAppear
andonDisappear
now occur outside of the layout pass; allowing, eg,onAppear
to safely trigger a re-render.
- 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
ConstrainedAspectRatio
measures correctly infitParent
andfillParent
modes when the proposed constraint has the same aspect ratio as the element's constraint.ConstrainedAspectRatio
adheres to the Caffeinated Layout contract when unconstrained infitParent
orfillParent
, by reportinginfinity
instead of falling back to the constrained element's size.
- Caffeinated Layout is enabled by default. You can disable it on a
BlueprintView
with thelayoutMode
property, or disable it globally by settingLayoutMode.default
.
ConstrainedAspectRatio
content modefillParent
is deprecated, due to having limited utility in Caffeinated Layout.
1.0.0 - 2023-04-18
- Restored documentation generation by executing the generate_docs.sh script with
bundle exec
to ensure gems are referenced properly.
-
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 thelayoutMode
property of aBlueprintView
.Caffeinated Layout is not enabled by default yet, but will be in a future release.
-
Added
layoutMode
toBlueprintViewRenderMetrics
to expose which layout mode was used to render a Blueprint view.
-
The
Layout
andSingleChildLayout
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.
- Updated jazzy gem (0.14.3).
- Updated cocoapods (1.12.0).
- Updated Ruby version (2.7).
0.50.0 - 2023-03-07
- The
Environment
will now automatically inherit forBlueprintView
instances nested insideUIViewElement
during measurement.
- Introduced
ElementContent.init(byMeasuring:)
, for use when yourElement
contains a nestedBlueprintView
, commonly used to implement stateful elements. This avoids detached measurements and improves performance.
- Renamed
BlueprintViewUpdateMetrics
toBlueprintViewRenderMetrics
. - Renamed
BlueprintViewRenderMetrics.measureDuration
tolayoutDuration
. - Renamed
BlueprintViewMetricsDelegate.blueprintView(_:completedUpdateWith:)
toblueprintView(_:completedRenderWith:)
. BlueprintViewRenderMetrics
values are now calculated usingCACurrentMediaTime
instead ofDate
.
- 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 uniqueContentStorage
type, which improves layout performance.
Image
'saspectFill
contentMode
now measures the same asaspectFit
to avoid aggressively taking up space when not necessary.
- Fixed unexpected measurement results that could occur from
Image
s using theaspectFit
contentMode
.
- Fix Catalyst version specifier in SPM package.
- Added
AccessibilityElement.CustomAction
to allow custom actions for use by assistive technologies. - Added
accessibilityCustomActions
property toLabel
andAttributedLabel
. UIViewElementContext
now passes through anenvironment
property, enabling environment-dependent measurements and layouts.
- 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
accessibilityHint
property forLabel
andAttributedLabel
.
- When stacks lay out with more
fixed
magnitude than is available for layout,flexible
items will no longer receive a negative width.
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.
- Improve
AttributedLabel
rendering performance.
- Fixed an issue where rounding was handled incorrectly for nested BlueprintViews.
- Added new logging option to expose aggregate measurements.
AccessibilityContainer
now omits accessibility elements where.accessibilityElementsHidden
istrue
.
Image
now provides an override to prevent VoiceOver from generating accessibility descriptions.
- Introduced an
Element.modify { ... }
conditional, to allow changing properties on an element.
-
Aligned
will now constrain its content to the provided layout frame. If you need content to exceed the layout frame, please useDecoration
. -
AccessibilityElement
will now only returnaccessibilityPath
for elements with a non-square corner style. This avoids needlessly changing AccessibilitySnapshot (https://github.com/cashapp/AccessibilitySnapshot) reference images.
- Introduced
accessibilityFrameCornerStyle
toAccessibilityElement
.
- Added
.grows
and.shrinks
toStackLayout.Child.Priority
, to allow for extra control over how flexible elements grow and shrink. AccessibilityBlocker
now takes in aBool
to control blocking, to avoid changing the element hierarchy to toggle if blocking is occurring.
- Added support for optionals in builders without unwrapping via
if let
. - Static constants on
Alignment
are now public (such asAlignment.topTrailing
).
AnimationAttributes
has gained a.default
option.LayoutTransition
has default values for itsAnimationAttributes
parameters.
- Added support for adjusting text spacing and sizing on
AttributedLabel
andLabel
when text does not fit within the provided layout rect.
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.
- Accessibility increment, decrement actions have been moved to associated values on the
AccessibilityElement.Trait
enum.
- Shadows on
Label
andAttributedLabel
- Accessibility increment, decrement and activate actions now available on
AccessibilityElement
Decorate
has a newaligned
positioning, that uses stack-styleAlignment
values and alignment guides.- The context vended to custom
Decorate
positions includes the decorated content size.
- The context vended to custom
Decorate
positions was renamed toPositionContext
, and thecontentFrame
property was replaced with acontentSize
.
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.
LayoutWriter.Context
now exposes the layout phase, to differ any calculations between measurement and layout.
- Fixed an issue where
AttributedLabel
andLabel
would not pass touches to super views when expected.
- 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 theAligned
initializer.
- The default line break mode for
Label
is nowbyTruncatingTail
, matching the default forUILabel
. (It was previouslybyWordWrapping
, 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
Label
andAttributedLabel
now correctly report theirUIAccessibilityTraits
.
0.35.0 - 2022-01-11
- Added the
EditingMenu
element, which allows showing aUIMenuController
(aka the system editing menu) on tap, long press, or based on a trigger.
Label.font
now defaults to using a font of sizeUIFont.labelFontSize
(17) instead ofUIFont.systemFontSize
.
0.34.0 - 2021-12-16
- Support
CALayerCornerCurve
forBox
corner styles. - Added
AttributedText
, which supports applying strongly-typed attributes to strings (much like theAttributedString
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 supportsURL
s orString
s. - 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 usesUIApplication.shared.open(_:options:completionHandler:)
. Customize link handling by providing aURLHandler
to the environment at the appropriate scope.AttributedLabel
also has a function for easily handling links with a closure using theonLinkTapped
method.
- Links can be added using the
0.33.3 - 2021-12-8
- Fixed an issue where
Box
did not implicitly animate its shadow.
- 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 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 an issue where
BlueprintView
would not size correctly when used with Auto Layout.
- Added an
ElementContent
variant whosemeasureFunction
takes in both aSizeConstraint
and anEnvironment
.
0.33.0 - 2021-11-18
- Allow measuring within an explicit
SizeConstraint
inGeometryProxy
. - Add an additional
stackLayoutChild(priority:)
method overload, for easier autocomplete when only customizing the layout priority.
- Values returned from
sizeThatFits
andsystemLayoutSizeFitting
are now cached.
0.32.0 - 2021-11-16
- Fixed an issue where the keyboard inset adjustment was incorrect in some cases.
- Fixed a retain cycle in
@FocusState
. (#285)
- Add support for
for...in
loops andavailable
checks to result builder APIs.
0.31.0 - 2021-11-09
intrinsicContentSize
is now cached.
- Improved error messages when using result builders with optional values.
0.30.0 - 2021-10-15
- Added a
Hidden
element and.hidden()
modifier for hiding elements. Overlay
now supports result builders.SegmentedControl
now supports result builders.
- Removed deprecated initializer from
AccessibilityElement
which was causing ambiguous initializer errors.
UserInteractionEnabled
has been moved fromBlueprintUICommonControls
intoBlueprintUI
. 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
-
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()
andgridRowChild()
.
let row = Row(alignment: .fill) { TestElement() TestElement2() .stackLayoutChild(priority: .fixed, alignmentGuide: { _ in 0 }, key: "two") }
- To declare one of these containers, simply include the elements inside the
-
The
accessibilityElement(...)
modifier has been added for wrapping anElement
in anAccessibilityElement
. Note that this will override all accessibility parameters of theElement
being wrapped, even if values are left unspecified or set tonil
. -
An initializer on
AccessibilityElement
that requires alabel
,value
, andtraits
. -
Overlay
supports keys for disambiguation between view updates. (#264)
-
BlueprintView
'sintrinsicContentSize
will now returnUIView.noIntrinsicMetric
if there is noelement
associated with it. -
TextField
'sbecomeActiveTrigger
andresignActiveTrigger
properties have been replaced with afocusBinding
for use with the new@FocusState
property wrapper.
- The
accessibility(...)
modifier has been deprecated. UseaccessibilityElement(...)
instead. - An initializer on
AccessibilityElement
that allowed all parameters to be unspecified. Use the initializer with required parameters instead. Overlay.add(_:)
deprecated in favor ofOverlay.add(key:child:)
.
0.28.1 - 2021-09-10
- 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)
- Lifecycle hooks are guaranteed to run after all views are updated. (#260)
0.28.0 - 2021-09-01
- Fixed an issue where
Label
andAttributedLabel
were not accessibility elements.
-
Label
AttributedLabel
andTextField
elements now support configuration of accessibility traits. -
The
Environment
is now automatically propagated through to nestedBlueprintViews
within a displayedElement
hierarchy. This means that if your view-backedElements
themselves contain aBlueprintView
(eg to manage their own state), that nested view will now automatically receive the correctEnvironment
acrossBlueprintView
boundaries. If you were previously manually propagatingEnvironment
values you may remove this code. If you would like to opt-out of this behavior; you can setview.automaticallyInheritsEnvironmentFromContainingBlueprintViews = false
on yourBlueprintView
. -
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 }
makeUIView()
onUIViewElement
is no longer a static function, to allow access to properties during view creation.
0.27.0 - 2021-06-22
- The signature of
Element.backingViewDescription(bounds: CGRect, subtreeExtent: CGRect?) -> ViewDescription?
has changed tobackingViewDescription(with context: ViewDescriptionContext) -> ViewDescription?
(#231). This is a large breaking change, but is worth it as it allows us to pass additional context tobackingViewDescription
in the future in a non-breaking way. TheViewDescriptionContext
contains thebounds
andsubtreeExtent
, as well as theEnvironment
the element is rendered in.
0.26.0 - 2021-06-02
- Add
ScrollTrigger
, which adds the ability set the content offset of aScrollView
- Add
UIViewElementContext
toUIViewElement.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
- Expose
contentInsetAdjustmentBehavior
onScrollView
.
0.24.0 - 2021-04-16
-
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
, aRow
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 childElement
s. -
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
.
- The layout system now uses a caching system to improve performance by eliminating redundant measurements. (#209)
0.23.0 - 2021-03-26
- Introduce
UserInteractionEnabled
, an element which conditionally enables user interaction of wrapped elements.
searchField
.userInteractionEnabled(canBeginSearch)
-
Change
ProxyElement
to directly return the content of a child. This significantly speeds up deeper element hierarchies that are made up of proxy elements, by reducing the duplicate calculation work that needs to be done to layout an element tree. -
Change backing view of
TransitionContainer
to not directly receive touches while still allowing subviews to do so.
0.22.0 - 2021-03-15
- Introduce
Decorate
to allow placing a decoration element in front or behind of anElement
, without affecting its layout. This is useful for rendering tap or selection states which should overflow the natural bounds of theElement
, similar to a shadow, or useful for adding a badge to anElement
.
0.21.0 - 2021-02-17
- Introduce conditionals on
Element
to allow you to perform inline checks likeif
,if let
, andmap
when buildingElement
trees.
- Introduce additional APIs on
Overlay
to ease conditional construction theOverlay
elements.
0.20.0 - 2021-01-12
- Add
Transformed
element to apply aCATransform3D
to a wrapped element.
0.19.1 - 2021-01-06
- Remove compile time validation from
Element
s, since it caused compile-time errors in certain cases when extensions andwhere
clauses were used.
0.19.0 - 2021-01-05
Ensure thatElement
s are a value type. This is generally assumed by Blueprint, but was previously not validated. This is only validated inDEBUG
builds, to avoid otherwise affecting performance.
- Add
LayoutWriter
, which makes creating custom / arbitrary layouts much simpler. You no longer need to define a customLayout
type; instead, you can just utilizeLayoutWriter
and configure and place your children within its builder initializer.
0.18.0 - 2020-12-08
- Add
AccessibilityContainer.identifier
([#180])
0.17.1 - 2020-10-30
-
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
-
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 support for iOS 10. Future releases will only support iOS 11 and later.
Row
alignmentsleading
andtrailing
are deprecated. Usetop
andbottom
instead. (#153)
0.16.0 - 2020-09-22
- Fixed
EqualStack
to properly constrain children when measuring. (#157)
-
Add a new
TransitionContainer.init
that supports further customization during initialization and has the same defaults asViewDescription
. (#155, #158) -
Add
transition(onAppear:onDisappear:onLayout)
andtransition(_:)
methods toElement
to describe transition animations. (#155, #158)
- Remove
GridLayout
; it's incomplete and was never really intended to be consumed widely. The intended replacement is puttingEqualStacks
inside of aColumn
, orRows
inside aColumn
.
TransitionContainer(wrapping:)
is deprecated. Use the newTransitionContainer(transitioning:)
instead. (#158)
- Removed some redundant work being done during rendering. (#154)
0.15.1 - 2020-09-16
- Fixes a crash that can occur in
Box
when specifying a corner radius and shadow. (#149)
0.15.0 - 2020-09-14
-
Add
addFixed(child:)
andaddFlexible(child:)
methods toStackElement
for adding children with a grow & shrink priority of 0.0 and 1.0 respectively. (#143) -
Add
capsule
case toBox.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
toAccessibilityElement
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)
BlueprintView
will calllayoutIfNeeded
on backing views during its layout pass. This allows backing views' subviews that are laid out duringlayoutSubviews
to participate in animations. (#139)
0.14.0 - 2020-08-12
-
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) }
- Default
ScrollView.delaysContentTouches
totrue
(#132)
- Set an explicit shadow path on
Box
(#137)
0.13.1 - 2020-07-30
-
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
-
Update the scroll indicator inset when adjusting the content inset.
-
Label
&AttributedLabel
use an internalUILabel
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 beUIScreen.main.scale
. These elements may not be measured correctly if they are placed on a screen other thanUIScreen.main
. (#120)
-
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
toLabel
andAttributedLabel
. (#120) -
Add
lineHeight
toLabel
for specifying custom line heights.AttributedLabel
has atextRectOffset
property to support this. (#120)
- Update Demo app to support more demo screen types.
0.12.2 - 2020-06-08
- Fix erroneous use of
frame
instead ofbounds
when laying outBlueprintView
.
- Add delaysContentTouches to the
ScrollView
element.
0.12.1 - 2020-06-05
- Use default environment when measuring
BlueprintView
.
0.12.0 - 2020-06-04
-
Add support for the iPhone SE 2 in
ElementPreview
. -
Added
tintColor
andcontentMode
into the initializer forImage
. (#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 extendingEnvironment
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
ConstrainedSize
to ensure that the measurement of its inner element respects theConstrainedSize
'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 support for
SwiftUI
-style element building withinBlueprintUI
andBlueprintUICommonControls
.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
- BlueprintView will align view frames to pixel boundaries after layout (#64).
0.9.2 - 2020-04-27
- 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
- Weak link
SwiftUI
so if an app is not already linkingSwiftUI
, it will build correctly.
0.9.0 - 2020-04-17
- Add support for previewing Blueprint elements in Xcode / SwiftUI previews.
- Add accessibilityIdentifier support to
AccessibilityElement
.
0.8.0 - 2020-04-03
- Properly measure the child of
ScrollView
to allow for unconstrained measurement. - Fix stack layout during underflow (#72)
- ScrollView can automatically adjust its content inset for the keyboard (#55)
- Improved element diffing (#56)
0.7.0 - 2020-03-30
- Xcode 11 and Swift 5.1 support (#67).
- Change how stack layouts are measured to resolve an issue where text would be truncated.
- Raise minimum deployment target from iOS 9.3 to iOS 10 (#66).
0.6.0 - 2020-02-24
- Add
keyboardDismissMode
property on ScrollView (#57). - Add
textAlignment
property on TextField (#53).
0.5.0 - 2020-01-24
- Prevent divide-by-zero when a stack contains zero-size elements (#52).
- Add
fill
alignment to Aligned (#42).
0.4.0 - 2019-12-04
- Public init on Aligned (#41).
- Guarantee that subviews are ordered the same as their associated elements (#32).
0.3.1 - 2019-11-15
- Do not run snapshot tests from CocoaPods (#40).
- Make tests with float comparisons more lenient for 32-bit (#35).
- Add Swift Package Manager support (#37).
- Add Getting Started section to README (#38).
0.3.0 - 2019-11-12
- Add Stack alignment options
justifyToStart
,justifyToCenter
, andjustifyToEnd
(#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).
- 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.