@craft-native/ios 0.0.394 → 0.0.395

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@craft-native/ios",
3
- "version": "0.0.394",
3
+ "version": "0.0.395",
4
4
  "homepage": "https://github.com/craft-native/craft/tree/main/packages/ios#readme",
5
5
  "repository": {
6
6
  "type": "git",
@@ -188,6 +188,10 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
188
188
  private var recycleItem: ((String) -> Void)?
189
189
  private var removeItem: ((String) -> Void)?
190
190
  private var endReached: (() -> Void)?
191
+ /// The `fontFamily` the list's rows inherit from its ancestors. Rows are
192
+ /// reconfigured when only their node changes, so the screen redraws them
193
+ /// itself when this changes (`CraftNativeScreenController.reconcileFlatList`).
194
+ var inheritedFontFamily: String?
191
195
  var onScrollEvent: ((UIScrollView) -> Void)?
192
196
  /// Called as the visible rows move, for a screen that lays out around them.
193
197
  var onLayoutChanged: (() -> Void)?
@@ -5895,7 +5895,12 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
5895
5895
  let type: String
5896
5896
  let view: UIView
5897
5897
  var protocolId: String?
5898
+ /// The node's effective style: its own, plus the `fontFamily` it
5899
+ /// inherited when it sets none (see `reconcile`).
5898
5900
  var style: [String: Any] = [:]
5901
+ /// The nearest ancestor's `fontFamily` when this node was drawn, so a
5902
+ /// targeted update of this subtree inherits it without its ancestors.
5903
+ var inheritedFontFamily: String?
5899
5904
  var children: [RenderedNode] = []
5900
5905
  var widthConstraint: NSLayoutConstraint?
5901
5906
  var heightConstraint: NSLayoutConstraint?
@@ -8380,7 +8385,7 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
8380
8385
  // its parent's to swap in: a targeted update only redraws in
8381
8386
  // place, and the new view was made and never attached.
8382
8387
  guard canReuseView(document, previous: previous) else { return false }
8383
- let next = reconcile(document, identity: previous.identity, path: target, previous: previous)
8388
+ let next = reconcile(document, identity: previous.identity, path: target, previous: previous, inheritedFontFamily: previous.inheritedFontFamily)
8384
8389
  // A style patch is applied in place, layout included: the parent
8385
8390
  // reads the node's new layout style on its next pass.
8386
8391
  CraftNativeFlexLayout.invalidateAncestors(of: next.view)
@@ -8521,10 +8526,22 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
8521
8526
 
8522
8527
  /// `adopting`: `previous` is a recycled list row's root, whose views may
8523
8528
  /// show this row instead (`identity` is the new row's).
8524
- private func reconcile(_ node: [String: Any], identity: String, path: String, previous: RenderedNode?, adopting: Bool = false) -> RenderedNode {
8529
+ ///
8530
+ /// `inheritedFontFamily`: the nearest ancestor's `fontFamily`. As in CSS,
8531
+ /// a node that sets none (or `inherit`) takes it, and its children inherit
8532
+ /// in turn, so a brand face set on a screen's root reaches every label,
8533
+ /// button and input below it. It is written into the node's effective
8534
+ /// style, which every font computed from that style (Dynamic Type
8535
+ /// re-renders included) reads. With no ancestor family this costs one nil
8536
+ /// check and copies nothing.
8537
+ private func reconcile(_ node: [String: Any], identity: String, path: String, previous: RenderedNode?, adopting: Bool = false, inheritedFontFamily: String? = nil) -> RenderedNode {
8525
8538
  let type = canonicalType(node["type"] as? String ?? "View")
8526
8539
  let props = node["props"] as? [String: Any] ?? [:]
8527
- let style = node["style"] as? [String: Any] ?? [:]
8540
+ var style = node["style"] as? [String: Any] ?? [:]
8541
+ if let inheritedFontFamily {
8542
+ let own = style["fontFamily"] as? String
8543
+ if own == nil || own == "inherit" { style["fontFamily"] = inheritedFontFamily }
8544
+ }
8528
8545
  let events = node["events"] as? [String: String] ?? [:]
8529
8546
  let children = node["children"] as? [Any] ?? []
8530
8547
  let protocolId = node["id"] as? String
@@ -8545,6 +8562,7 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
8545
8562
  let result = current.view
8546
8563
  current.protocolId = protocolId
8547
8564
  current.style = style
8565
+ current.inheritedFontFamily = inheritedFontFamily
8548
8566
  let linkTarget = ["href", "to"].lazy.compactMap { props[$0] as? String }
8549
8567
  .first(where: { !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty })?
8550
8568
  .trimmingCharacters(in: .whitespacesAndNewlines)
@@ -9091,7 +9109,8 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
9091
9109
  parent: current,
9092
9110
  path: path,
9093
9111
  props: props,
9094
- events: events
9112
+ events: events,
9113
+ fontFamily: style["fontFamily"] as? String
9095
9114
  )
9096
9115
  default:
9097
9116
  let stack = result as! CraftNativeFlowView
@@ -9319,6 +9338,8 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
9319
9338
  let counts = Dictionary(keys.map { ($0, 1) }, uniquingKeysWith: +)
9320
9339
  let old = Dictionary(uniqueKeysWithValues: parent.children.map { ($0.identity, $0) })
9321
9340
  var next: [RenderedNode] = []
9341
+ // `style` is the parent's effective style, its inherited family included.
9342
+ let fontFamily = style["fontFamily"] as? String
9322
9343
 
9323
9344
  for (index, node) in nodes.enumerated() {
9324
9345
  let key = explicitKey(node, props: node["props"] as? [String: Any] ?? [:])
@@ -9331,7 +9352,7 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
9331
9352
  let identity = parent.identity.hasPrefix("list:") || parent.identity.hasPrefix("key:")
9332
9353
  ? "\(parent.identity)/\(localIdentity)"
9333
9354
  : localIdentity
9334
- let child = reconcile(node, identity: identity, path: "\(path).\(index)", previous: old[identity])
9355
+ let child = reconcile(node, identity: identity, path: "\(path).\(index)", previous: old[identity], inheritedFontFamily: fontFamily)
9335
9356
  next.append(child)
9336
9357
  }
9337
9358
  if (style["flexDirection"] as? String)?.hasSuffix("-reverse") == true { next.reverse() }
@@ -9376,7 +9397,8 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
9376
9397
  parent: RenderedNode,
9377
9398
  path: String,
9378
9399
  props: [String: Any],
9379
- events: [String: String]
9400
+ events: [String: String],
9401
+ fontFamily: String?
9380
9402
  ) {
9381
9403
  let listKey = ObjectIdentifier(list)
9382
9404
  let owner = parent.protocolId ?? path
@@ -9420,6 +9442,8 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
9420
9442
  0,
9421
9443
  Double(number(props["onEndReachedThreshold"]) ?? number(props["threshold"]) ?? 0.1)
9422
9444
  )
9445
+ let familyChanged = list.inheritedFontFamily != fontFamily
9446
+ let rowsDrawnBefore = familyChanged && flatListRows[listKey]?.isEmpty == false
9423
9447
  list.apply(
9424
9448
  nodes: children,
9425
9449
  horizontal: props["horizontal"] as? Bool == true,
@@ -9444,7 +9468,10 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
9444
9468
  identity: "list:\(identity)",
9445
9469
  path: "\(path).\(identity)",
9446
9470
  previous: previous,
9447
- adopting: adopting
9471
+ adopting: adopting,
9472
+ // Rows are drawn later, as they scroll in: each takes the
9473
+ // list's family from this render's closure.
9474
+ inheritedFontFamily: fontFamily
9448
9475
  )
9449
9476
  // A recycled row's handlers went when it was recycled.
9450
9477
  if let previous, previous.view !== next.view, !adopting {
@@ -9489,6 +9516,12 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
9489
9516
  list.setScrollTarget(props["scrollTarget"])
9490
9517
  list.alwaysBounceVertical = props["alwaysBounceVertical"] as? Bool ?? !horizontal
9491
9518
  list.alwaysBounceHorizontal = props["alwaysBounceHorizontal"] as? Bool ?? horizontal
9519
+ // A row redraws when its own node changes; an ancestor's new family
9520
+ // leaves every node as it was, so rows drawn before are redrawn here.
9521
+ if familyChanged {
9522
+ list.inheritedFontFamily = fontFamily
9523
+ if rowsDrawnBefore { list.refreshThemeDefaults() }
9524
+ }
9492
9525
  parent.children = []
9493
9526
  }
9494
9527