@momo-kits/native-kits 0.168.1-beta.10 → 0.168.1-beta.11

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/CLAUDE.md CHANGED
@@ -82,6 +82,7 @@ Publishing is automated (`publish.sh` + GitLab CI on `[ci build]` / `main`). Do
82
82
  - Quick return header: glass headers and Animated headers (with a `ScrollState`) on the Duo side bar layout slide out with the content and back in on a reverse scroll; a half-shown header settles in or out once the scroll stops. The side bar is drawn apart from the header, so it stays put.
83
83
  - Overlays on Duo: popups cap at 440pt wide and the room between `duoTopInset` and the bottom inset (body scrolls, actions stay); modal centers inside that room; bottom sheet uses the window height, centers at width ≥ 600 and pads by side insets in landscape.
84
84
  - Font scale deliberately uses the short side (`min(w, h)`), unlike RN which reads the window width — landscape must not inflate every font.
85
+ - Font scale measures the **window**, never `UIScreen.main`: on iPhone Duo the main screen stays on one display while the window follows the one in use. Compose iOS `getScreenDimensions()` reads `LocalWindowInfo.containerSize` (recomposes on fold/unfold); SwiftUI `DesignSystemKits` KVO-observes each `UIWindowScene.effectiveGeometry` and republishes `windowShortSide`.
85
86
  - `StackScreen` pads content/footer/search/FAB by the side insets and provides an inset-consumed layout to its content; a bottom-tab root stays full width (tab bar + each tab's StackScreen handle insets). Grid columns use `contentWidth`.
86
87
 
87
88
  ## i18n / Localize (port of RN `Localize`)
@@ -36,6 +36,10 @@ public final class DesignSystemKits: ObservableObject {
36
36
 
37
37
  @Published private var configs = DesignSystemKitsConfigs()
38
38
  @Published public private(set) var osFontScale: CGFloat = DesignSystemKits.currentOsFontScale()
39
+ // AI-GENERATED START: republish the font scale when the window scene is resized (iPhone Duo fold/unfold)
40
+ @Published public private(set) var windowShortSide: CGFloat = DesignSystemKits.currentWindowShortSide()
41
+ private var geometryObservations: [ObjectIdentifier: NSKeyValueObservation] = [:]
42
+ // AI-GENERATED END: republish the font scale when the window scene is resized (iPhone Duo fold/unfold)
39
43
 
40
44
  private init() {
41
45
  NotificationCenter.default.addObserver(
@@ -44,6 +48,19 @@ public final class DesignSystemKits: ObservableObject {
44
48
  name: UIContentSizeCategory.didChangeNotification,
45
49
  object: nil
46
50
  )
51
+ // AI-GENERATED START: republish the font scale when the window scene is resized (iPhone Duo fold/unfold)
52
+ NotificationCenter.default.addObserver(
53
+ self,
54
+ selector: #selector(sceneDidActivate(_:)),
55
+ name: UIScene.didActivateNotification,
56
+ object: nil
57
+ )
58
+ onMain {
59
+ UIApplication.shared.connectedScenes
60
+ .compactMap { $0 as? UIWindowScene }
61
+ .forEach(self.observeGeometry(of:))
62
+ }
63
+ // AI-GENERATED END: republish the font scale when the window scene is resized (iPhone Duo fold/unfold)
47
64
  }
48
65
 
49
66
  public func setConfigs(_ configs: DesignSystemKitsConfigs) {
@@ -62,7 +79,10 @@ public final class DesignSystemKits: ObservableObject {
62
79
  FontScale(
63
80
  userScaleRate: configs.userScaleRate,
64
81
  useOSScaleRate: configs.useOSScaleRate,
65
- osFontScale: osFontScale
82
+ osFontScale: osFontScale,
83
+ // AI-GENERATED START: republish the font scale when the window scene is resized (iPhone Duo fold/unfold)
84
+ windowShortSide: windowShortSide
85
+ // AI-GENERATED END: republish the font scale when the window scene is resized (iPhone Duo fold/unfold)
66
86
  )
67
87
  }
68
88
 
@@ -72,6 +92,49 @@ public final class DesignSystemKits: ObservableObject {
72
92
  osFontScale = next
73
93
  }
74
94
 
95
+ // AI-GENERATED START: republish the font scale when the window scene is resized (iPhone Duo fold/unfold)
96
+ @objc private func sceneDidActivate(_ notification: Notification) {
97
+ guard let scene = notification.object as? UIWindowScene else { return }
98
+ observeGeometry(of: scene)
99
+ refreshWindowShortSide()
100
+ }
101
+
102
+ private func observeGeometry(of scene: UIWindowScene) {
103
+ guard #available(iOS 16.0, *) else { return }
104
+ let key = ObjectIdentifier(scene)
105
+ guard geometryObservations[key] == nil else { return }
106
+ geometryObservations[key] = scene.observe(\.effectiveGeometry, options: [.new]) { [weak self] _, _ in
107
+ // The window is resized after the scene geometry, so read it on the next turn.
108
+ DispatchQueue.main.async { self?.refreshWindowShortSide() }
109
+ }
110
+ }
111
+
112
+ private func refreshWindowShortSide() {
113
+ let next = Self.currentWindowShortSide()
114
+ guard next > 0, next != windowShortSide else { return }
115
+ windowShortSide = next
116
+ }
117
+
118
+ /// UIScreen.main stays on one display on iPhone Duo, so measure the foreground window instead.
119
+ static func currentWindowShortSide() -> CGFloat {
120
+ guard Thread.isMainThread else {
121
+ return min(UIScreen.main.bounds.width, UIScreen.main.bounds.height)
122
+ }
123
+ let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
124
+ let scene = scenes.first { $0.activationState == .foregroundActive } ?? scenes.first
125
+ let window = scene?.windows.first { $0.isKeyWindow } ?? scene?.windows.first
126
+ let size: CGSize
127
+ if let window, window.bounds.width > 0 {
128
+ size = window.bounds.size
129
+ } else if let scene {
130
+ size = scene.coordinateSpace.bounds.size
131
+ } else {
132
+ size = UIScreen.main.bounds.size
133
+ }
134
+ return min(size.width, size.height)
135
+ }
136
+ // AI-GENERATED END: republish the font scale when the window scene is resized (iPhone Duo fold/unfold)
137
+
75
138
  /// Same factor Compose's iOS `ProvideOsFontScale` derives from
76
139
  /// `UIFont.preferredFont(forTextStyle: .body).pointSize / 17`, so both iOS surfaces scale alike.
77
140
  static func currentOsFontScale() -> CGFloat {
@@ -19,11 +19,19 @@ public struct FontScale: Equatable {
19
19
  public let useOSScaleRate: Bool
20
20
  /// OS Dynamic Type factor at the time the snapshot was taken.
21
21
  public let osFontScale: CGFloat
22
+ // AI-GENERATED START: device scale from the app window, not UIScreen.main (fixed to one display on iPhone Duo)
23
+ public let windowShortSide: CGFloat
22
24
 
23
- public init(userScaleRate: CGFloat = 1, useOSScaleRate: Bool = true, osFontScale: CGFloat = 1) {
25
+ public init(
26
+ userScaleRate: CGFloat = 1,
27
+ useOSScaleRate: Bool = true,
28
+ osFontScale: CGFloat = 1,
29
+ windowShortSide: CGFloat? = nil
30
+ ) {
24
31
  self.userScaleRate = userScaleRate
25
32
  self.useOSScaleRate = useOSScaleRate
26
33
  self.osFontScale = osFontScale
34
+ self.windowShortSide = windowShortSide ?? DesignSystemKits.currentWindowShortSide()
27
35
  }
28
36
 
29
37
  /// `callAsFunction` so call sites keep reading like Compose's `scaleSize(16)`.
@@ -31,8 +39,8 @@ public struct FontScale: Equatable {
31
39
  guard useOSScaleRate else { return size * userScaleRate }
32
40
 
33
41
  // Short side, not width: landscape must not inflate every font (and so every popup's height).
34
- let bounds = UIScreen.main.bounds.size
35
- let deviceScale = min(bounds.width, bounds.height) / Self.defaultScreenSize
42
+ let deviceScale = windowShortSide / Self.defaultScreenSize
43
+ // AI-GENERATED END: device scale from the app window, not UIScreen.main (fixed to one display on iPhone Duo)
36
44
 
37
45
  var deviceScaled = size
38
46
  var osScaled = size
@@ -58,7 +66,10 @@ public struct FontScale: Equatable {
58
66
  return FontScale(
59
67
  userScaleRate: userScaleRate ?? self.userScaleRate,
60
68
  useOSScaleRate: useOSScaleRate ?? self.useOSScaleRate,
61
- osFontScale: osFontScale
69
+ osFontScale: osFontScale,
70
+ // AI-GENERATED START: keep the window size through context overrides
71
+ windowShortSide: windowShortSide
72
+ // AI-GENERATED END: keep the window size through context overrides
62
73
  )
63
74
  }
64
75
  }
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'MoMoUIKits'
3
- s.version = '0.167.1-beta.22'
3
+ s.version = '0.168.1-beta.11'
4
4
  s.summary = 'MoMoUIKits for iOS'
5
5
  s.homepage = 'https://momo.vn'
6
6
  s.license = { :type => 'MIT' }
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'MoMoUIKitsDemo'
3
- s.version = '0.167.1-beta.22'
3
+ s.version = '0.168.1-beta.11'
4
4
  s.summary = 'Demo browser for MoMoUIKits SwiftUI components'
5
5
  s.homepage = 'https://momo.vn'
6
6
  s.license = { :type => 'MIT' }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.168.1-beta.10",
3
+ "version": "0.168.1-beta.11",
4
4
  "private": false,
5
5
  "dependeNavigationncies": {},
6
6
  "devDependencies": {},