craft-native 0.0.387 → 0.0.392

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7367,6 +7367,7 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
7367
7367
  }
7368
7368
  if options.keys.contains("backgroundColor") || options.keys.contains("navigationBarSolid") {
7369
7369
  applyNavigationBarAppearance()
7370
+ trackContentScrollView()
7370
7371
  }
7371
7372
  // Asked for after the bar was hidden for a bare root screen.
7372
7373
  if navigationBarHidden == nil, wantsNavigationBar, navigationController?.topViewController === self,
@@ -7589,7 +7590,14 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
7589
7590
  /// title collapses as it scrolls, and the bar's background follows it.
7590
7591
  private func trackContentScrollView() {
7591
7592
  guard let renderedRoot else { return }
7593
+ // UIKit can resize the root before nested flex wrappers lay out.
7594
+ // Resolve their frames before checking empty siblings or edges so
7595
+ // old child frames cannot toggle the root constraints each pass.
7596
+ rootStack.layoutIfNeeded()
7592
7597
  func find(_ node: RenderedNode) -> UIScrollView? {
7598
+ // Modal content belongs to a separate presentation. Hidden
7599
+ // branches must not steal tracking from the visible screen.
7600
+ guard node.type != "Modal", !node.view.isHidden else { return nil }
7593
7601
  if let scroll = node.view as? CraftNativeScrollView, scroll.isVertical, scroll.isScrollEnabled { return scroll }
7594
7602
  if let list = node.view as? CraftNativeFlatList, list.isScrollEnabled,
7595
7603
  (list.collectionViewLayout as? UICollectionViewFlowLayout)?.scrollDirection != .horizontal { return list }
@@ -7606,12 +7614,12 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
7606
7614
  return list.isScrollEnabled && (list.collectionViewLayout as? UICollectionViewFlowLayout)?.scrollDirection != .horizontal ? node : nil
7607
7615
  }
7608
7616
  guard paddingInsets(node.style).top == 0,
7609
- let first = node.children.first(where: { $0.type != "Modal" && !$0.view.isHidden }) else { return nil }
7617
+ let first = node.children.first(where: { $0.type != "Modal" && !$0.view.isHidden && $0.view.bounds.height > 0 }) else { return nil }
7610
7618
  return leading(first)
7611
7619
  }
7612
7620
  let scroll = find(renderedRoot)
7613
7621
  let leadingScroll = leading(renderedRoot)
7614
- // Only the screen's leading scroller draws beneath floating chrome.
7622
+ // The leading scroller may overflow beneath navigation chrome.
7615
7623
  // A bounded list inside a form must clip its rows to its viewport.
7616
7624
  if let leadingScroll, leadingScroll.style["overflow"] as? String != "hidden" {
7617
7625
  leadingScroll.view.clipsToBounds = false
@@ -7626,13 +7634,16 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
7626
7634
  let edgeToEdge = scroll != nil && (prefersLargeTitle == true || scroll === leadingScroll?.view)
7627
7635
  let fullEdgeToEdge = rootIsSafeAreaView
7628
7636
  let topEdgeToEdge = fullEdgeToEdge || edgeToEdge
7629
- // Only a leading vertical scroller that reaches the root's bottom
7630
- // can paint beneath a visible tab bar. A bounded list, fixed footer,
7631
- // plain screen or presented sheet must retain its safe-area bottom.
7637
+ // Bottom clearance does not depend on the leading-scroll rule for
7638
+ // navigation titles. Follow the visible scroller through wrappers,
7639
+ // even after a header or empty sibling. Its laid-out viewport must
7640
+ // reach the root's bottom; zero-size/hidden siblings do not shorten
7641
+ // it. A bounded list, fixed footer, plain screen or presented sheet
7642
+ // must retain its safe-area bottom.
7632
7643
  // Use UIKit's automatic inset for tab/accessory clearance, rather
7633
7644
  // than adding a second explicit inset (also owned by keyboard code).
7634
7645
  var tabbedScroll = false
7635
- if let scroll, scroll === leadingScroll?.view, scroll.bounds.height > 0,
7646
+ if let scroll, scroll.bounds.height > 0,
7636
7647
  let tabBar = tabBarController?.tabBar, !tabBar.isHidden, tabBar.alpha > 0,
7637
7648
  let window = view.window, tabBar.window === window,
7638
7649
  tabBar.convert(tabBar.bounds, to: view).intersects(view.bounds) {
@@ -7653,12 +7664,28 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
7653
7664
  rootLeadingToView?.isActive = fullEdgeToEdge
7654
7665
  rootTrailingToSafeArea?.isActive = !fullEdgeToEdge
7655
7666
  rootTrailingToView?.isActive = fullEdgeToEdge
7656
- scroll?.contentInsetAdjustmentBehavior = edgeToEdge ? .automatic : .never
7657
- guard scroll !== trackedScrollView else { return }
7658
- trackedScrollView = scroll
7659
- // The same primary vertical scroller drives the navigation bar and
7660
- // the system tab bar's scroll-edge/minimization behavior.
7661
- setContentScrollView(scroll, for: [.top, .bottom])
7667
+ scroll?.contentInsetAdjustmentBehavior = (edgeToEdge || tabbedScroll) ? .automatic : .never
7668
+ if scroll !== trackedScrollView {
7669
+ #if compiler(>=6.2)
7670
+ if #available(iOS 26.0, *) {
7671
+ trackedScrollView?.topEdgeEffect.isHidden = false
7672
+ trackedScrollView?.bottomEdgeEffect.isHidden = false
7673
+ }
7674
+ #endif
7675
+ trackedScrollView = scroll
7676
+ // Keep UIKit's title collapse, tab selection and minimization
7677
+ // tracking; only the full-width edge backdrop changes below.
7678
+ setContentScrollView(scroll, for: [.top, .bottom])
7679
+ }
7680
+ #if compiler(>=6.2)
7681
+ if #available(iOS 26.0, *) {
7682
+ // Floating button groups carry their own material. UIKit's
7683
+ // separate scroll-edge wash would cover the content behind
7684
+ // and beyond them even with a transparent bar appearance.
7685
+ scroll?.topEdgeEffect.isHidden = topEdgeToEdge && !navigationBarSolid
7686
+ scroll?.bottomEdgeEffect.isHidden = tabbedScroll
7687
+ }
7688
+ #endif
7662
7689
  }
7663
7690
 
7664
7691
  private func observeNativeEvents() {
package/dist/types.d.ts CHANGED
@@ -2397,5 +2397,9 @@ export interface MenubarState {
2397
2397
  hiddenSystemItemCount?: number;
2398
2398
  preserveSystemItems?: boolean;
2399
2399
  markerWidth?: number;
2400
+ /** Read-only access to the macOS 27 menu bar arrangement. */
2401
+ layoutAuthorized?: boolean;
2402
+ /** Saved native control position, or -1 before an arrangement is available. */
2403
+ layoutPosition?: number;
2400
2404
  error?: 'unavailable' | 'permissionRequired' | 'layoutUnavailable' | 'emptyGroup' | 'visibilityMismatch' | 'activationFailed' | 'activationTimeout' | null;
2401
2405
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "craft-native",
3
- "version": "0.0.387",
3
+ "version": "0.0.392",
4
4
  "type": "module",
5
5
  "description": "Build desktop apps with web languages - TypeScript SDK for Craft",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",