Skip to content

SwiftUI Components 2.1.0

Latest

Choose a tag to compare

@muhittincamdali muhittincamdali released this 14 Oct 23:49
· 8 commits to main since this release
16613df

Form validation, gestures and a contrast checker, merged from three of the author's packages
that are being archived: SwiftUI-Forms-Kit, SwiftUI-Gesture-Library and iOSUIComponents. The
code was rewritten for this package's style and tests rather than copied. No existing API
changed in a breaking way.

Added

  • Validation: Validator with required, minLength, maxLength, email, url, phone,
    digits, matches, equals, range, atLeast, atMost, notEmpty, count, custom
    and the combinators and, or and all; ValidationResult; ValidatedValue, which shows
    an error only after an edit or a submit; AsyncValidation, a debounced check that ignores
    answers for outdated values.
  • FormSchema, FormValue and SchemaForm: forms described in JSON, checked on decoding
    (duplicate ids, choices without options, impossible limits, invalid regular expressions,
    more fields, patterns or options than the size limits allow) and rendered with the package's
    fields. Every regular expression, in a schema or in Validator.matches, runs on
    NSRegularExpression with a 20 ms limit per match, a 1,000 UTF-16 code unit input limit and a
    100 ms budget per errors(in:) call.
  • StepFlow and MultiStepForm for forms split into steps.
  • Gestures: .onSwipe, .onSwipeSequence, .onEdgeSwipe, .transformable (pinch, rotate,
    drag and double-tap reset), .boundedDrag, ShapeDrawingPad and UnistrokeRecognizer
    (the $1 recognizer with $N's handling of straight lines), with the testable rules
    SwipeDirection, SwipeSequenceMatcher, EdgeSwipe, TransformState and DragBounds.
    Each gesture has an accessibility action.
  • ColorContrast: WCAG 2 contrast ratio and AA/AAA level for SwiftUI colors and hex codes.
  • FileUploadField.UploadedFile.url, public name, size and type, the
    FileUploadField.Rejection reasons and an onRejected callback.
  • Example app screens for the validated form, the JSON form and the gestures; a -sample
    launch argument that opens one of them; scripts/capture-example-screens.sh, which captures
    them on a simulator for the README; and the DocC articles "Validating Forms" and "Adding
    Gestures".

Changed

  • OTPField, SecurePINField and PinInput keep only ASCII digits (or ASCII letters and
    digits for PinInput(inputType: .alphanumeric)) and filter pasted text before cutting it
    to length, so "123-456" fills all six cells.
  • CreditCardInput's cardholder field prompts for "Name on card" instead of showing the sample
    name "John Doe".

Fixed

  • FileUploadField added made-up demo files instead of opening a file picker. It now opens
    the system file importer, accepts dropped files and enforces allowedTypes, maxFileSize
    and maxFiles.
  • PinInput with .numeric input undid its own length limit, so pasted text longer than
    length stayed in the binding and onComplete never ran; OTPField and SecurePINField
    could call onComplete twice for one paste.
  • PinInput(isSecure: true) masked the boxes but kept the PIN in a plain text field, where
    keyboard suggestions and VoiceOver could still reach it. It now uses a secure field, as
    SecurePINField does.
  • NaN, infinite or very large values no longer stop the app in ProgressCard,
    ProgressRingChart, CountdownTimer, Stopwatch, ProgressTimer, DurationPicker,
    ReorderableList, the toast, snackbar and banner durations, LoadingButton and
    VerticalMarqueeText. A zero or negative interval no longer makes a repeating animation
    spin.
  • Zero or negative counts no longer stop the app in DotLoader, SkeletonView,
    PageIndicator, ScrollingPageIndicator, CheckboxGroup, TimeSlotPicker, StatGrid,
    OTPField, SecurePINField, PinInput and PasscodeInput.
  • A maxRating below 1 in RatingInput and RatingDisplay, and a maxItems or maxVisible
    below 3 in BreadcrumbView and DropdownBreadcrumb, no longer stop the app; they are raised
    to those minimums.
  • A negative maxVisible in AvatarGroup or maxPoints in LiveSparklineChart no longer
    stops the app; it is treated as 0.
  • ReadingTimeText with a wordsPerMinute of 0 divided by zero; the speed is now at least 1.
  • A step that is zero, negative, NaN, infinite or larger than the range no longer stops the
    app in SliderField and SliderRatingInput, including SliderRatingInput(range: 5...5) with
    its default step; the slider then moves without steps. The same happens for a range that is
    not finite or holds more than 10,000 steps, such as 0...1e15 with a step of 1, which tried
    to allocate memory for every step. The pill and gradient SliderField styles count steps
    from the lower bound and stay inside the range.
  • PageIndicator's .numbers and .progress styles stopped the app for a currentPage of
    Int.max; the page number shown is now kept between 0 and the page count.
  • StepperButton stopped the app when a step passed Int.max or Int.min, for example a
    VoiceOver increment on a range ending at Int.max; such a step now leaves the value
    unchanged. A negative step no longer swaps what the two buttons do.
  • TexturedGlassCard drew one noise dot per ten square points without limit; it now draws at
    most 4,000.