@swiftbrowser/native 0.26.3 → 0.26.5

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/dist/run.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAA4D,KAAK,WAAW,EAA6B,MAAM,qBAAqB,CAAC;AAC5I,OAAO,KAAK,EAAM,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAI3D,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,sFAAsF;IACtF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,OAAO,IAAI,IAAI,CAAC;CACjB;AAaD,wBAAgB,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CA2EzE"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAA4D,KAAK,WAAW,EAA6B,MAAM,qBAAqB,CAAC;AAC5I,OAAO,KAAK,EAAM,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAI3D,MAAM,WAAW,UAAU;IACzB,wEAAwE;IACxE,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,sFAAsF;IACtF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC;IAC9C,OAAO,IAAI,IAAI,CAAC;CACjB;AAeD,wBAAgB,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CA6EzE"}
package/dist/run.js CHANGED
@@ -69,6 +69,9 @@ export function run(element, options = {}) {
69
69
  next.horizontalSizeClass = fields.horizontalSizeClass;
70
70
  if (fields.scenePhase)
71
71
  next.scenePhase = fields.scenePhase;
72
+ // Without this the tree's `usePlatform` said `ios` on a Mac.
73
+ if (fields.platform === 'ios' || fields.platform === 'macos')
74
+ next.platform = fields.platform;
72
75
  if (Object.keys(next).length > 0)
73
76
  root.setEnvironment(next);
74
77
  return;
package/dist/run.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swiftbrowser/native",
3
- "version": "0.26.3",
3
+ "version": "0.26.5",
4
4
  "type": "module",
5
5
  "description": "Run a @swiftbrowser/react app natively: the runtime a JavaScriptCore-hosted app needs (timers, console, fetch and the other web globals over the SwiftBrowser Native bridge), the `run` entry that renders into the native SwiftUI renderer, and the bundler that builds app.js for the Xcode target.",
6
6
  "repository": {
@@ -63,8 +63,8 @@
63
63
  },
64
64
  "dependencies": {
65
65
  "@babel/core": "^7.29.7",
66
- "@swiftbrowser/react": "0.26.3",
67
- "@swiftbrowser/web": "0.26.3",
66
+ "@swiftbrowser/react": "0.26.5",
67
+ "@swiftbrowser/web": "0.26.5",
68
68
  "esbuild": "^0.28.2",
69
69
  "react-refresh": "^0.17.0"
70
70
  },
package/src/run.ts CHANGED
@@ -36,6 +36,8 @@ interface EnvironmentFields {
36
36
  dynamicTypeSize?: string;
37
37
  horizontalSizeClass?: 'compact' | 'regular';
38
38
  scenePhase?: 'active' | 'inactive' | 'background';
39
+ /** The platform the app is drawn on (docs/notes/macos.md): `ios` or `macos`, from the native root view. */
40
+ platform?: 'ios' | 'macos';
39
41
  }
40
42
 
41
43
  /** The running app, when `run` was called (the dev loop calls it again on every save). */
@@ -91,6 +93,8 @@ export function run(element: ReactNode, options: RunOptions = {}): Running {
91
93
  if (fields.dynamicTypeSize) next.dynamicTypeSize = fields.dynamicTypeSize as Environment['dynamicTypeSize'];
92
94
  if (fields.horizontalSizeClass) next.horizontalSizeClass = fields.horizontalSizeClass;
93
95
  if (fields.scenePhase) next.scenePhase = fields.scenePhase;
96
+ // Without this the tree's `usePlatform` said `ios` on a Mac.
97
+ if (fields.platform === 'ios' || fields.platform === 'macos') next.platform = fields.platform;
94
98
  if (Object.keys(next).length > 0) root.setEnvironment(next);
95
99
  return;
96
100
  }
@@ -4,6 +4,8 @@ import SwiftBrowserProtocol
4
4
  import SwiftUI
5
5
  #if canImport(UIKit)
6
6
  import UIKit
7
+ #elseif canImport(AppKit)
8
+ import AppKit
7
9
  #endif
8
10
 
9
11
  // The protocol's value types as SwiftUI's. Names are SwiftUI's own (the shim
@@ -70,6 +72,39 @@ extension Color {
70
72
  case "systemGray6": return Color(uiColor: .systemGray6)
71
73
  default: break
72
74
  }
75
+ #elseif canImport(AppKit)
76
+ // AppKit has no UIKit system colors: each is its light and dark value,
77
+ // as the web renderer's Mac idiom draws it (the window, grouped and
78
+ // grouped cell backgrounds white and #1e1e1e there; the rest iOS's).
79
+ func dynamic(_ light: UInt32, _ dark: UInt32, _ lightAlpha: Double = 1, _ darkAlpha: Double = 1) -> Color {
80
+ func rgb(_ hex: UInt32, _ alpha: Double) -> NSColor {
81
+ NSColor(srgbRed: CGFloat((hex >> 16) & 0xff) / 255, green: CGFloat((hex >> 8) & 0xff) / 255, blue: CGFloat(hex & 0xff) / 255, alpha: alpha)
82
+ }
83
+ return Color(nsColor: NSColor(name: nil) { appearance in
84
+ appearance.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua ? rgb(dark, darkAlpha) : rgb(light, lightAlpha)
85
+ })
86
+ }
87
+ switch name {
88
+ case "systemBackground", "systemGroupedBackground", "secondarySystemGroupedBackground": return dynamic(0xffffff, 0x1e1e1e)
89
+ case "secondarySystemBackground": return dynamic(0xf2f2f7, 0x1c1c1e)
90
+ case "tertiarySystemGroupedBackground": return dynamic(0xf2f2f7, 0x2c2c2e)
91
+ case "tertiarySystemBackground": return dynamic(0xffffff, 0x2c2c2e)
92
+ case "tertiaryLabel": return dynamic(0x3c3c43, 0xebebf5, 0.3, 0.3)
93
+ case "quaternaryLabel": return dynamic(0x3c3c43, 0xebebf5, 0.18, 0.16)
94
+ case "placeholderText": return dynamic(0x3c3c43, 0xebebf5, 0.3, 0.3)
95
+ case "separator": return dynamic(0x3c3c43, 0x545458, 0.29, 0.6)
96
+ case "opaqueSeparator": return dynamic(0xc6c6c8, 0x38383a)
97
+ case "systemFill": return dynamic(0x787880, 0x787880, 0.2, 0.36)
98
+ case "secondarySystemFill": return dynamic(0x787880, 0x787880, 0.16, 0.32)
99
+ case "tertiarySystemFill": return dynamic(0x767680, 0x767680, 0.12, 0.24)
100
+ case "quaternarySystemFill": return dynamic(0x747480, 0x767680, 0.08, 0.18)
101
+ case "systemGray2": return dynamic(0xaeaeb2, 0x636366)
102
+ case "systemGray3": return dynamic(0xc7c7cc, 0x48484a)
103
+ case "systemGray4": return dynamic(0xd1d1d6, 0x3a3a3c)
104
+ case "systemGray5": return dynamic(0xe5e5ea, 0x2c2c2e)
105
+ case "systemGray6": return dynamic(0xf2f2f7, 0x1c1c1e)
106
+ default: break
107
+ }
73
108
  #else
74
109
  switch name {
75
110
  case "systemBackground", "secondarySystemGroupedBackground", "tertiarySystemBackground": return Color(white: 1)
@@ -81,4 +81,23 @@ private struct CapsuleGlass: ViewModifier {
81
81
  }
82
82
  }
83
83
  #endif
84
+
85
+ /// `.navigationSubtitle` (macOS 11, iOS 26): the screen's `subtitle`, under
86
+ /// the title in a Mac's title bar. The iOS build's SDK floor is older than
87
+ /// the modifier, so only a Mac (and the shim's round trip) draws it.
88
+ struct NavigationSubtitle: ViewModifier {
89
+ let subtitle: String?
90
+
91
+ func body(content: Content) -> some View {
92
+ #if os(macOS) || canImport(FoundationBridge)
93
+ if let subtitle, !subtitle.isEmpty {
94
+ content.navigationSubtitle(subtitle)
95
+ } else {
96
+ content
97
+ }
98
+ #else
99
+ content
100
+ #endif
101
+ }
102
+ }
84
103
  #endif
@@ -15,6 +15,9 @@ struct ListElement: View {
15
15
  let props = ListProps(props: node.props)
16
16
  let list = selectionList(props)
17
17
  let styled: AnyView = {
18
+ // A `Form` (the shim's and React's mark their list `form`): the
19
+ // system's form, which on a Mac is the columns style.
20
+ if props.form { return AnyView(Form { ListRowsView(children: node.children) }) }
18
21
  switch props.style {
19
22
  case "plain": return AnyView(list.listStyle(.plain))
20
23
  case "sidebar": return AnyView(list.listStyle(.sidebar))
@@ -28,7 +31,10 @@ struct ListElement: View {
28
31
  #endif
29
32
  }
30
33
  }()
31
- let refreshable = props.refreshable ? AnyView(styled.refreshable { app?.dispatch(.refresh(node.id)) }) : styled
34
+ // `.environment(\.defaultMinListRowHeight, _)` (the list's `minRowHeight`):
35
+ // a Mac app spaces a content list's rows like a sidebar's, 32.
36
+ let sized = props.minRowHeight.map { AnyView(styled.environment(\.defaultMinListRowHeight, CGFloat($0))) } ?? styled
37
+ let refreshable = props.refreshable ? AnyView(sized.refreshable { app?.dispatch(.refresh(node.id)) }) : sized
32
38
  #if os(iOS) || canImport(FoundationBridge)
33
39
  if let editing = props.editing {
34
40
  refreshable.environment(\.editMode, .constant(editing ? .active : .inactive))
@@ -145,6 +145,7 @@ struct NavigationScreenElement: View {
145
145
  let titled = content
146
146
  .modifier(KeyboardBarInset(toolbars: keyboardToolbars))
147
147
  .navigationTitle(props.title)
148
+ .modifier(NavigationSubtitle(subtitle: props.subtitle))
148
149
  .toolbar { ScreenToolbar(toolbars: shown) }
149
150
  .onAppear {
150
151
  // A pushed screen, appearing: its bar as it is now, until the push has settled.
@@ -337,6 +338,15 @@ struct NavigationLinkElement: View {
337
338
  let inList = Self.isListRow(node)
338
339
  let label = Group {
339
340
  if inList {
341
+ #if os(macOS)
342
+ // A Mac's link row has no chevron (macOS 26, as the web
343
+ // renderer's Mac idiom draws it).
344
+ HStack(spacing: 0) {
345
+ ChildrenView(node: node)
346
+ Spacer(minLength: 0)
347
+ }
348
+ .contentShape(Rectangle())
349
+ #else
340
350
  // The disclosure chevron in the trailing 22 points, as measured
341
351
  // against iOS's row: 13 pt semibold, 2 in from the content's edge
342
352
  // (the web renderer's LIST_CHEVRON_WIDTH reserves 20).
@@ -350,6 +360,7 @@ struct NavigationLinkElement: View {
350
360
  .padding(.trailing, 2)
351
361
  }
352
362
  .contentShape(Rectangle())
363
+ #endif
353
364
  } else {
354
365
  ChildrenView(node: node)
355
366
  }
@@ -175,11 +175,17 @@ public struct ListProps: Equatable, Sendable {
175
175
  public var editing: Bool?
176
176
  /// `List(selection:)` over a `Set`: several rows may be selected.
177
177
  public var multiSelect: Bool
178
+ /// A `Form`: drawn as one (on a Mac, the columns style).
179
+ public var form: Bool
180
+ /// `.environment(\.defaultMinListRowHeight, _)`: the rows at least this tall (a Mac app's content list, 32).
181
+ public var minRowHeight: Double?
178
182
  public init(props: JSONObject) {
179
183
  style = props.string("style") ?? "insetGrouped"
180
184
  refreshable = props.bool("refreshable") ?? false
181
185
  editing = props.bool("editing")
182
186
  multiSelect = props.bool("multiSelect") ?? false
187
+ form = props.bool("form") ?? false
188
+ minRowHeight = props.double("minRowHeight")
183
189
  }
184
190
  }
185
191
 
@@ -294,6 +300,8 @@ public struct ToggleProps: Equatable, Sendable {
294
300
 
295
301
  public struct NavScreenProps: Equatable, Sendable {
296
302
  public var title: String
303
+ /// `.navigationSubtitle`: under the title in a Mac's title bar.
304
+ public var subtitle: String?
297
305
  /// `automatic`, `large` or `inline`.
298
306
  public var displayMode: String
299
307
  /// 0 for the stack's root screen.
@@ -306,6 +314,7 @@ public struct NavScreenProps: Equatable, Sendable {
306
314
  public var statusBarHidden: Bool
307
315
  public init(props: JSONObject) {
308
316
  title = props.string("title") ?? ""
317
+ subtitle = props.string("subtitle")
309
318
  displayMode = props.string("displayMode") ?? "automatic"
310
319
  depth = props.int("depth") ?? 0
311
320
  toolbarRole = props.string("toolbarRole")
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/wasm/SwiftBrowserNative.wasm
3
- size: 50282598 bytes
4
- sha256: 36221c0c44b7bb993ff03090d3f241303c9b224b90b1b1dc398137d25926ba14
3
+ size: 50289339 bytes
4
+ sha256: 5249606957c30e9c98f3a1f3d51c42b6ae48bfb960b166de7cf8e42a6cfa9cb2