bleam 0.0.5 → 0.0.7

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.
Files changed (141) hide show
  1. package/dist/ai.cjs +4146 -0
  2. package/dist/ai.d.cts +535 -0
  3. package/dist/ai.d.ts +535 -0
  4. package/dist/ai.js +4102 -0
  5. package/dist/animated.cjs +286 -0
  6. package/dist/animated.d.cts +47 -0
  7. package/dist/animated.d.ts +47 -0
  8. package/dist/animated.js +281 -0
  9. package/dist/app.cjs +92 -0
  10. package/dist/app.d.cts +1 -2
  11. package/dist/app.d.ts +1 -2
  12. package/dist/app.js +93 -2
  13. package/dist/bundler.d.cts +1 -2
  14. package/dist/bundler.d.ts +1 -2
  15. package/dist/cli.cjs +1375 -71
  16. package/dist/cli.d.cts +89 -1
  17. package/dist/cli.d.ts +89 -1
  18. package/dist/cli.js +1373 -74
  19. package/dist/config-Bb6SULnR.cjs +46 -0
  20. package/dist/config-CfWa3q-k.js +28 -0
  21. package/dist/config-Cms0rvqg.d.ts +40 -0
  22. package/dist/config-CufOVJV3.d.cts +40 -0
  23. package/dist/config.cjs +4 -25
  24. package/dist/config.d.cts +2 -28
  25. package/dist/config.d.ts +2 -28
  26. package/dist/config.js +2 -24
  27. package/dist/crypto-BB92-Upx.js +7 -0
  28. package/dist/crypto-CT3VZ7lF.cjs +13 -0
  29. package/dist/crypto.cjs +2 -2
  30. package/dist/crypto.d.cts +6 -1
  31. package/dist/crypto.d.ts +8 -1
  32. package/dist/crypto.js +2 -2
  33. package/dist/dev-protocol.d.cts +16 -3
  34. package/dist/dev-protocol.d.ts +16 -3
  35. package/dist/dev-protocol.js +1 -2
  36. package/dist/files-Bo7h9fik.cjs +468 -0
  37. package/dist/files-Ds1wT8C2.js +445 -0
  38. package/dist/files-DwA7pzr3.d.cts +99 -0
  39. package/dist/files-VrkQlKIT.d.ts +99 -0
  40. package/dist/files.cjs +7 -0
  41. package/dist/files.d.cts +2 -0
  42. package/dist/files.d.ts +2 -0
  43. package/dist/files.js +4 -0
  44. package/dist/index.cjs +4 -5
  45. package/dist/index.d.cts +2 -3
  46. package/dist/index.d.ts +2 -3
  47. package/dist/index.js +2 -4
  48. package/dist/native-runtime-C85Nuc4F.js +10 -0
  49. package/dist/{native-runtime-CdeT0JyQ.cjs → native-runtime-CsXnXkQn.cjs} +1 -14
  50. package/dist/native-sqlite-xcGdamRD.js +64 -0
  51. package/dist/native-sqlite-yQLD5s9i.cjs +66 -0
  52. package/dist/platform.cjs +27 -0
  53. package/dist/platform.d.cts +39 -0
  54. package/dist/platform.d.ts +39 -0
  55. package/dist/platform.js +21 -0
  56. package/dist/runtime.d.cts +1 -7
  57. package/dist/runtime.d.ts +1 -7
  58. package/dist/schema-Bo5Jvqus.js +90 -0
  59. package/dist/schema-DOOjfXvs.d.ts +58 -0
  60. package/dist/schema-ENSMX_1t.d.cts +58 -0
  61. package/dist/schema-rQ13mrpD.cjs +102 -0
  62. package/dist/schema.cjs +4 -0
  63. package/dist/schema.d.cts +2 -0
  64. package/dist/schema.d.ts +2 -0
  65. package/dist/schema.js +3 -0
  66. package/dist/state-Bx0VlTlO.cjs +852 -0
  67. package/dist/state-CAwe-Vw1.js +767 -0
  68. package/dist/state.cjs +19 -0
  69. package/dist/state.d.cts +159 -0
  70. package/dist/state.d.ts +159 -0
  71. package/dist/state.js +6 -0
  72. package/dist/styles.cjs +742 -0
  73. package/dist/styles.d.cts +701 -0
  74. package/dist/styles.d.ts +701 -0
  75. package/dist/styles.js +739 -0
  76. package/dist/ui-1WepaMS4.d.cts +92 -0
  77. package/dist/ui-234Plg7Z.d.cts +92 -0
  78. package/dist/ui-BJmXhz9Q.d.ts +92 -0
  79. package/dist/ui-Dd7SXdbg.d.cts +92 -0
  80. package/dist/ui-Ds88eETu.d.ts +92 -0
  81. package/dist/ui-TaqnB5SP.d.ts +92 -0
  82. package/dist/ui-WQvnXL0W.d.ts +92 -0
  83. package/dist/ui.cjs +364 -0
  84. package/dist/ui.d.cts +2 -0
  85. package/dist/ui.d.ts +2 -0
  86. package/dist/ui.js +357 -0
  87. package/dist/window.cjs +596 -0
  88. package/dist/window.d.cts +63 -0
  89. package/dist/window.d.ts +63 -0
  90. package/dist/window.js +589 -0
  91. package/metro-config.cjs +18 -13
  92. package/package.json +57 -21
  93. package/templates/basic/app/index.tsx +133 -12
  94. package/templates/basic/app.config.ts +4 -2
  95. package/templates/foundation-models/app/index.tsx +32 -0
  96. package/templates/foundation-models/app.config.ts +5 -0
  97. package/templates/image-generation/app/index.tsx +39 -0
  98. package/templates/image-generation/app.config.ts +5 -0
  99. package/templates/state/app/index.tsx +30 -0
  100. package/templates/state/app.config.ts +5 -0
  101. package/dist/app.d.cts.map +0 -1
  102. package/dist/app.d.ts.map +0 -1
  103. package/dist/app.js.map +0 -1
  104. package/dist/bundler.d.cts.map +0 -1
  105. package/dist/bundler.d.ts.map +0 -1
  106. package/dist/cli.js.map +0 -1
  107. package/dist/config.d.cts.map +0 -1
  108. package/dist/config.d.ts.map +0 -1
  109. package/dist/config.js.map +0 -1
  110. package/dist/crypto-BNhWeXMj.cjs +0 -15
  111. package/dist/crypto-Bg8cD8wX.d.cts +0 -8
  112. package/dist/crypto-Bg8cD8wX.d.cts.map +0 -1
  113. package/dist/crypto-CCA_hvao.js +0 -11
  114. package/dist/crypto-CCA_hvao.js.map +0 -1
  115. package/dist/crypto-IOzbNoJD.d.ts +0 -8
  116. package/dist/crypto-IOzbNoJD.d.ts.map +0 -1
  117. package/dist/dev-protocol.d.cts.map +0 -1
  118. package/dist/dev-protocol.d.ts.map +0 -1
  119. package/dist/dev-protocol.js.map +0 -1
  120. package/dist/fs-BK7joD1g.js +0 -13
  121. package/dist/fs-BK7joD1g.js.map +0 -1
  122. package/dist/fs-CEhcjuN6.d.ts +0 -9
  123. package/dist/fs-CEhcjuN6.d.ts.map +0 -1
  124. package/dist/fs-CfE8CHf_.d.cts +0 -9
  125. package/dist/fs-CfE8CHf_.d.cts.map +0 -1
  126. package/dist/fs-DKHYTPua.cjs +0 -18
  127. package/dist/fs.cjs +0 -3
  128. package/dist/fs.d.cts +0 -2
  129. package/dist/fs.d.ts +0 -2
  130. package/dist/fs.js +0 -3
  131. package/dist/native-runtime-BoqybBBf.js +0 -18
  132. package/dist/native-runtime-BoqybBBf.js.map +0 -1
  133. package/dist/native.cjs +0 -132
  134. package/dist/native.d.cts +0 -64
  135. package/dist/native.d.cts.map +0 -1
  136. package/dist/native.d.ts +0 -64
  137. package/dist/native.d.ts.map +0 -1
  138. package/dist/native.js +0 -133
  139. package/dist/native.js.map +0 -1
  140. package/dist/runtime.d.cts.map +0 -1
  141. package/dist/runtime.d.ts.map +0 -1
@@ -0,0 +1,63 @@
1
+ import { p as SymbolName } from "./ui-WQvnXL0W.js";
2
+ import * as react3 from "react";
3
+ import { ComponentType } from "react";
4
+ import { StyleProp, ViewStyle } from "react-native";
5
+
6
+ //#region src/chrome.d.ts
7
+ type HexColor = `#${string}`;
8
+ type WindowToolbarStyle = 'automatic' | 'unified' | 'unifiedCompact' | 'preference' | 'expanded';
9
+ type WindowTitleVisibility = 'visible' | 'hidden';
10
+ type WindowUserInterfaceStyle = 'automatic' | 'light' | 'dark';
11
+ type WindowProps = {
12
+ title?: string;
13
+ tint?: HexColor;
14
+ backgroundColor?: HexColor;
15
+ userInterfaceStyle?: WindowUserInterfaceStyle;
16
+ titleVisibility?: WindowTitleVisibility;
17
+ };
18
+ type ToolbarProps = {
19
+ toolbarStyle?: WindowToolbarStyle;
20
+ };
21
+ declare function Window(props: WindowProps): null;
22
+ declare function Toolbar(props: ToolbarProps): null;
23
+ //#endregion
24
+ //#region src/safe-area.d.ts
25
+ type SafeAreaInsets = {
26
+ top: number;
27
+ right: number;
28
+ bottom: number;
29
+ left: number;
30
+ };
31
+ declare function useSafeAreaInsets(): SafeAreaInsets;
32
+ //#endregion
33
+ //#region src/navigation.d.ts
34
+ type RouteName = string;
35
+ type ScreenComponent = ComponentType<Record<string, never>>;
36
+ type SidebarScreenConfig = ScreenComponent | {
37
+ screen: ScreenComponent;
38
+ title?: string;
39
+ symbol?: SymbolName;
40
+ };
41
+ type SidebarScreenMap = Record<RouteName, SidebarScreenConfig>;
42
+ type SidebarRouteState<Routes extends SidebarScreenMap> = {
43
+ name: Extract<keyof Routes, string>;
44
+ };
45
+ type SidebarNavigation<Routes extends SidebarScreenMap> = {
46
+ route: SidebarRouteState<Routes>;
47
+ navigate(name: Extract<keyof Routes, string>): void;
48
+ };
49
+ type SidebarNavigatorConfig<Routes extends SidebarScreenMap> = {
50
+ initialRouteName: Extract<keyof Routes, string>;
51
+ screens: Routes;
52
+ sidebarWidth?: number;
53
+ minimumSidebarWidth?: number;
54
+ maximumSidebarWidth?: number;
55
+ style?: StyleProp<ViewStyle>;
56
+ };
57
+ declare function createSidebarNavigator<const Routes extends SidebarScreenMap>(config: SidebarNavigatorConfig<Routes>): {
58
+ Navigator: () => react3.JSX.Element;
59
+ useNavigation: () => SidebarNavigation<Routes>;
60
+ useRoute: () => SidebarRouteState<Routes>;
61
+ };
62
+ //#endregion
63
+ export { type HexColor, type SafeAreaInsets, type SidebarNavigatorConfig, Toolbar, type ToolbarProps, Window, type WindowProps, type WindowTitleVisibility, type WindowToolbarStyle, type WindowUserInterfaceStyle, createSidebarNavigator, useSafeAreaInsets };
package/dist/window.js ADDED
@@ -0,0 +1,589 @@
1
+ import { t as ensureNativeScript } from "./native-runtime-C85Nuc4F.js";
2
+ import { createContext, createElement, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useState, useSyncExternalStore } from "react";
3
+ import { View } from "react-native";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+
6
+ //#region src/native-macos.ts
7
+ function macOSApplication() {
8
+ return ensureNativeScript().getClass("NSApplication")?.sharedApplication;
9
+ }
10
+ function createMacOSToolbar(identifier) {
11
+ const toolbarClass = ensureNativeScript().getClass("NSToolbar");
12
+ if (!toolbarClass) return;
13
+ try {
14
+ const toolbar = toolbarClass.alloc?.().initWithIdentifier?.(identifier);
15
+ if (toolbar) return toolbar;
16
+ } catch {}
17
+ try {
18
+ return toolbarClass.new?.();
19
+ } catch {}
20
+ }
21
+
22
+ //#endregion
23
+ //#region src/safe-area.ts
24
+ const emptyInsets = {
25
+ top: 0,
26
+ right: 0,
27
+ bottom: 0,
28
+ left: 0
29
+ };
30
+ const contributions = /* @__PURE__ */ new Map();
31
+ const listeners = /* @__PURE__ */ new Set();
32
+ let currentInsets = emptyInsets;
33
+ function mergeInsets() {
34
+ const nextInsets = { ...emptyInsets };
35
+ for (const contribution of contributions.values()) {
36
+ nextInsets.top += contribution.top ?? 0;
37
+ nextInsets.right += contribution.right ?? 0;
38
+ nextInsets.bottom += contribution.bottom ?? 0;
39
+ nextInsets.left += contribution.left ?? 0;
40
+ }
41
+ return nextInsets;
42
+ }
43
+ function areInsetsEqual(a, b) {
44
+ return a.top === b.top && a.right === b.right && a.bottom === b.bottom && a.left === b.left;
45
+ }
46
+ function emitIfChanged(nextInsets) {
47
+ if (areInsetsEqual(currentInsets, nextInsets)) return;
48
+ currentInsets = nextInsets;
49
+ for (const listener of listeners) listener();
50
+ }
51
+ function subscribe(listener) {
52
+ listeners.add(listener);
53
+ return () => {
54
+ listeners.delete(listener);
55
+ };
56
+ }
57
+ function snapshot() {
58
+ return currentInsets;
59
+ }
60
+ function setSafeAreaContribution(source, contribution) {
61
+ contributions.set(source, contribution);
62
+ emitIfChanged(mergeInsets());
63
+ }
64
+ function clearSafeAreaContribution(source) {
65
+ contributions.delete(source);
66
+ emitIfChanged(mergeInsets());
67
+ }
68
+ function useSafeAreaInsets() {
69
+ return useSyncExternalStore(subscribe, snapshot, snapshot);
70
+ }
71
+
72
+ //#endregion
73
+ //#region src/chrome.tsx
74
+ const toolbarStyleValues = {
75
+ automatic: 0,
76
+ expanded: 1,
77
+ preference: 2,
78
+ unified: 3,
79
+ unifiedCompact: 4
80
+ };
81
+ const toolbarSafeAreaHeights = {
82
+ automatic: 52,
83
+ expanded: 52,
84
+ preference: 52,
85
+ unified: 52,
86
+ unifiedCompact: 38
87
+ };
88
+ const toolbarSafeAreaSource = "toolbar";
89
+ const titleVisibilityValues = {
90
+ visible: 0,
91
+ hidden: 1
92
+ };
93
+ const userInterfaceStyleValues = {
94
+ automatic: 0,
95
+ light: 1,
96
+ dark: 2
97
+ };
98
+ function nativeRecord(value) {
99
+ if (!value || typeof value !== "object") return;
100
+ return value;
101
+ }
102
+ function macOSScene(value) {
103
+ return nativeRecord(value);
104
+ }
105
+ function macOSWindow(value) {
106
+ return nativeRecord(value);
107
+ }
108
+ function selectorTarget(value) {
109
+ return nativeRecord(value);
110
+ }
111
+ function setNativeValue(value, key, nextValue) {
112
+ const record = nativeRecord(value);
113
+ if (!record) return false;
114
+ record[key] = nextValue;
115
+ return true;
116
+ }
117
+ function colorFromHex(hex) {
118
+ const value = hex.trim().replace(/^#/, "");
119
+ const normalized = value.length === 3 ? value.split("").map((part) => `${part}${part}`).join("") : value;
120
+ if (!/^[\da-f]{6}$/i.test(normalized)) throw new Error(`Invalid color: ${hex}`);
121
+ const number = Number.parseInt(normalized, 16);
122
+ const red = (number >> 16 & 255) / 255;
123
+ const green = (number >> 8 & 255) / 255;
124
+ const blue = (number & 255) / 255;
125
+ return UIColor.colorWithRedGreenBlueAlpha(red, green, blue, 1);
126
+ }
127
+ function forEachNativeObject(collection, callback) {
128
+ const values = collection?.allObjects ?? collection;
129
+ if (Array.isArray(values)) {
130
+ values.forEach(callback);
131
+ return;
132
+ }
133
+ const iterableValues = values;
134
+ const count = Number(iterableValues?.count ?? 0);
135
+ for (let index = 0; index < count; index += 1) callback(iterableValues?.objectAtIndex?.(index));
136
+ }
137
+ function runOnUIWithRetry(apply) {
138
+ const run = () => ensureNativeScript().runOnUI(apply).catch(() => {});
139
+ run();
140
+ const timeout = setTimeout(() => {
141
+ run();
142
+ }, 250);
143
+ return () => {
144
+ clearTimeout(timeout);
145
+ };
146
+ }
147
+ function applyWindowTitle(title) {
148
+ const application = UIApplication.sharedApplication;
149
+ forEachNativeObject(application?.connectedScenes, (scene) => {
150
+ setNativeValue(scene, "title", title);
151
+ });
152
+ const appKitApplication = macOSApplication();
153
+ const appKitWindow = appKitApplication?.keyWindow ?? appKitApplication?.mainWindow;
154
+ if (appKitWindow) setNativeValue(appKitWindow, "title", title);
155
+ }
156
+ function clearRootView(window) {
157
+ const rootView = (macOSWindow(window)?.rootViewController)?.view;
158
+ if (!rootView) return;
159
+ setNativeValue(rootView, "backgroundColor", UIColor.clearColor);
160
+ setNativeValue(rootView, "opaque", false);
161
+ }
162
+ function forEachApplicationWindow(callback) {
163
+ const application = UIApplication.sharedApplication;
164
+ callback(application.keyWindow);
165
+ forEachNativeObject(application?.windows, callback);
166
+ forEachNativeObject(application?.connectedScenes, (scene) => {
167
+ callback(macOSScene(scene)?.keyWindow);
168
+ forEachNativeObject(macOSScene(scene)?.windows, callback);
169
+ });
170
+ }
171
+ function applyWindowTint(tint) {
172
+ const tintColor = colorFromHex(tint);
173
+ function applyTint(window) {
174
+ if (!window) return;
175
+ setNativeValue(window, "tintColor", tintColor);
176
+ clearRootView(window);
177
+ const rootView = (macOSWindow(window)?.rootViewController)?.view;
178
+ if (rootView) setNativeValue(rootView, "tintColor", tintColor);
179
+ }
180
+ forEachApplicationWindow(applyTint);
181
+ }
182
+ function applyWindowBackgroundColor(backgroundColor) {
183
+ const color = colorFromHex(backgroundColor);
184
+ forEachApplicationWindow((window) => {
185
+ if (!window) return;
186
+ setNativeValue(window, "backgroundColor", color);
187
+ clearRootView(window);
188
+ });
189
+ }
190
+ function applyWindowUserInterfaceStyle(userInterfaceStyle) {
191
+ const value = userInterfaceStyleValues[userInterfaceStyle];
192
+ forEachApplicationWindow((window) => {
193
+ if (!window) return;
194
+ setNativeValue(window, "overrideUserInterfaceStyle", value);
195
+ const rootViewController = macOSWindow(window)?.rootViewController;
196
+ if (rootViewController) setNativeValue(rootViewController, "overrideUserInterfaceStyle", value);
197
+ });
198
+ }
199
+ function applyWindowRootTransparency() {
200
+ forEachApplicationWindow((window) => {
201
+ if (window) clearRootView(window);
202
+ });
203
+ }
204
+ function invokeNativeValue(target, selector, ...values) {
205
+ const invoke = selectorTarget(target)?.invoke;
206
+ if (typeof invoke !== "function") return;
207
+ return invoke.call(target, selector, ...values);
208
+ }
209
+ function titlebarForScene(scene) {
210
+ try {
211
+ const titlebar = invokeNativeValue(scene, "titlebar");
212
+ if (titlebar) return titlebar;
213
+ } catch {}
214
+ try {
215
+ const target = selectorTarget(scene);
216
+ if (target?.valueForKey) {
217
+ const titlebar = target.valueForKey("titlebar");
218
+ if (titlebar) return titlebar;
219
+ }
220
+ } catch {}
221
+ return macOSScene(scene)?.titlebar;
222
+ }
223
+ function setNativeNumber(target, key, value) {
224
+ const selector = `set${key[0]?.toUpperCase()}${key.slice(1)}:`;
225
+ try {
226
+ if (invokeNativeValue(target, selector, value) !== void 0) return;
227
+ } catch {}
228
+ try {
229
+ if (setNativeValue(target, key, value)) return;
230
+ } catch {}
231
+ try {
232
+ const selector$1 = selectorTarget(target);
233
+ if (selector$1?.setValueForKey) {
234
+ selector$1.setValueForKey(NSNumber.numberWithInteger(value), key);
235
+ return;
236
+ }
237
+ } catch {}
238
+ }
239
+ function applyTitleVisibility(titleVisibility) {
240
+ if (!macOSApplication()) return;
241
+ const value = titleVisibilityValues[titleVisibility];
242
+ const application = UIApplication.sharedApplication;
243
+ forEachNativeObject(application?.connectedScenes, (scene) => {
244
+ const titlebar = titlebarForScene(scene);
245
+ if (!titlebar) return;
246
+ setNativeNumber(titlebar, "titleVisibility", value);
247
+ });
248
+ }
249
+ function toolbarForTitlebar(titlebar) {
250
+ let toolbar;
251
+ try {
252
+ toolbar = invokeNativeValue(titlebar, "toolbar");
253
+ } catch {}
254
+ try {
255
+ toolbar ??= titlebar.toolbar;
256
+ } catch {}
257
+ try {
258
+ if (!toolbar && titlebar.valueForKey) toolbar = titlebar.valueForKey("toolbar");
259
+ } catch {}
260
+ if (toolbar) return toolbar;
261
+ toolbar = createMacOSToolbar("BleamToolbar");
262
+ if (!toolbar) return;
263
+ try {
264
+ if (invokeNativeValue(titlebar, "setToolbar:", toolbar) !== void 0) return toolbar;
265
+ } catch {}
266
+ try {
267
+ if (setNativeValue(titlebar, "toolbar", toolbar)) return toolbar;
268
+ } catch {}
269
+ try {
270
+ if (titlebar.setValueForKey) {
271
+ titlebar.setValueForKey(toolbar, "toolbar");
272
+ return toolbar;
273
+ }
274
+ } catch {}
275
+ }
276
+ function applyToolbarStyle(toolbarStyle) {
277
+ if (!macOSApplication()) return;
278
+ const value = toolbarStyleValues[toolbarStyle];
279
+ const application = UIApplication.sharedApplication;
280
+ forEachNativeObject(application?.connectedScenes, (scene) => {
281
+ const titlebar = titlebarForScene(scene);
282
+ if (!titlebar) return;
283
+ toolbarForTitlebar(titlebar);
284
+ setNativeNumber(titlebar, "toolbarStyle", value);
285
+ });
286
+ }
287
+ function Window(props) {
288
+ const { title, tint, backgroundColor, userInterfaceStyle, titleVisibility } = props;
289
+ useLayoutEffect(() => {
290
+ return runOnUIWithRetry(() => {
291
+ applyWindowRootTransparency();
292
+ });
293
+ }, []);
294
+ useEffect(() => {
295
+ if (title === void 0) return;
296
+ ensureNativeScript().runOnUI(() => {
297
+ applyWindowTitle(title);
298
+ }).catch(() => {});
299
+ }, [title]);
300
+ useLayoutEffect(() => {
301
+ if (tint === void 0) return;
302
+ return runOnUIWithRetry(() => {
303
+ applyWindowTint(tint);
304
+ });
305
+ }, [tint]);
306
+ useLayoutEffect(() => {
307
+ if (backgroundColor === void 0) return;
308
+ return runOnUIWithRetry(() => {
309
+ applyWindowBackgroundColor(backgroundColor);
310
+ });
311
+ }, [backgroundColor]);
312
+ useLayoutEffect(() => {
313
+ if (userInterfaceStyle === void 0) return;
314
+ return runOnUIWithRetry(() => {
315
+ applyWindowUserInterfaceStyle(userInterfaceStyle);
316
+ });
317
+ }, [userInterfaceStyle]);
318
+ useEffect(() => {
319
+ if (titleVisibility === void 0) return;
320
+ ensureNativeScript().runOnUI(() => {
321
+ applyTitleVisibility(titleVisibility);
322
+ }).catch(() => {});
323
+ }, [titleVisibility]);
324
+ return null;
325
+ }
326
+ function Toolbar(props) {
327
+ const { toolbarStyle } = props;
328
+ useEffect(() => {
329
+ if (toolbarStyle === void 0) {
330
+ clearSafeAreaContribution(toolbarSafeAreaSource);
331
+ return;
332
+ }
333
+ setSafeAreaContribution(toolbarSafeAreaSource, { top: toolbarSafeAreaHeights[toolbarStyle] });
334
+ ensureNativeScript().runOnUI(() => {
335
+ applyToolbarStyle(toolbarStyle);
336
+ }).catch(() => {});
337
+ return () => {
338
+ clearSafeAreaContribution(toolbarSafeAreaSource);
339
+ };
340
+ }, [toolbarStyle]);
341
+ return null;
342
+ }
343
+
344
+ //#endregion
345
+ //#region src/navigation.tsx
346
+ const stateKey = Symbol.for("bleam.navigation.sidebar");
347
+ const sectionIdentifier = "sidebar";
348
+ const splitIdentifier = "bleam.navigation.sidebar.split";
349
+ const defaultMinimumSidebarWidth = 180;
350
+ const defaultSidebarWidth = 240;
351
+ const defaultMaximumSidebarWidth = 320;
352
+ const MissingContext = Symbol("MissingContext");
353
+ const sidebarSafeAreaSource = "sidebar";
354
+ function sidebarState() {
355
+ const globalState = globalThis;
356
+ globalState[stateKey] ??= {
357
+ items: [],
358
+ titleById: /* @__PURE__ */ new Map(),
359
+ symbolById: /* @__PURE__ */ new Map(),
360
+ sidebarWidth: defaultSidebarWidth,
361
+ minimumSidebarWidth: defaultMinimumSidebarWidth,
362
+ maximumSidebarWidth: defaultMaximumSidebarWidth
363
+ };
364
+ return globalState[stateKey];
365
+ }
366
+ function isClassAvailable(name) {
367
+ const nativeScript = ensureNativeScript();
368
+ return nativeScript.isClassAvailable?.(name) ?? Boolean(nativeScript.getClass(name));
369
+ }
370
+ function requiredNativeClassesAvailable() {
371
+ return [
372
+ "UISplitViewController",
373
+ "UICollectionLayoutListConfiguration",
374
+ "UICollectionViewCompositionalLayout",
375
+ "UICollectionView",
376
+ "UICollectionViewListCell",
377
+ "UICollectionViewCellRegistration",
378
+ "UICollectionViewDiffableDataSource",
379
+ "NSDiffableDataSourceSnapshot"
380
+ ].every(isClassAvailable);
381
+ }
382
+ function createSidebarController(state) {
383
+ const listConfiguration = UICollectionLayoutListConfiguration.alloc().initWithAppearance(UICollectionLayoutListAppearance.Sidebar);
384
+ listConfiguration.showsSeparators = false;
385
+ const layout = UICollectionViewCompositionalLayout.layoutWithListConfiguration(listConfiguration);
386
+ const collectionView = UICollectionView.alloc().initWithFrameCollectionViewLayout(CGRectZero, layout);
387
+ collectionView.backgroundColor = UIColor.clearColor;
388
+ collectionView.allowsMultipleSelection = false;
389
+ collectionView.allowsFocus = false;
390
+ collectionView.remembersLastFocusedIndexPath = false;
391
+ collectionView.selectionFollowsFocus = false;
392
+ const sidebarController = UIViewController.new();
393
+ sidebarController.title = "Sidebar";
394
+ sidebarController.view = collectionView;
395
+ const cellRegistration = UICollectionViewCellRegistration.registrationWithCellClassConfigurationHandler(UICollectionViewListCell, (cell, _indexPath, item) => {
396
+ const listCell = cell;
397
+ const content = listCell.defaultContentConfiguration();
398
+ const itemId = String(item);
399
+ const symbol = state.symbolById.get(itemId);
400
+ content.text = state.titleById.get(itemId) ?? itemId;
401
+ content.image = symbol ? UIImage.systemImageNamed(symbol) : null;
402
+ listCell.contentConfiguration = content;
403
+ listCell.accessories = [];
404
+ });
405
+ const dataSource = UICollectionViewDiffableDataSource.alloc().initWithCollectionViewCellProvider(collectionView, (nextCollectionView, indexPath, item) => nextCollectionView.dequeueConfiguredReusableCellWithRegistrationForIndexPathItem(cellRegistration, indexPath, item));
406
+ const delegate = ensureNativeScript().createDelegate(UICollectionViewDelegate, { collectionViewDidSelectItemAtIndexPath(_collectionView, indexPath) {
407
+ const item = state.items[indexPath.item];
408
+ if (!item) return;
409
+ state.selectedId = item.id;
410
+ state.emitSelect?.(item.id);
411
+ } });
412
+ collectionView.dataSource = dataSource;
413
+ collectionView.delegate = delegate;
414
+ state.sidebarViewController = sidebarController;
415
+ state.collectionView = collectionView;
416
+ state.dataSource = dataSource;
417
+ state.delegate = delegate;
418
+ state.cellRegistration = cellRegistration;
419
+ return sidebarController;
420
+ }
421
+ function isSidebarSplitController(viewController) {
422
+ if (!viewController) return false;
423
+ return viewController.restorationIdentifier === splitIdentifier && viewController.isKindOfClass(UISplitViewController);
424
+ }
425
+ function reuseExistingSidebarSplit(state, splitViewController) {
426
+ const contentViewController = splitViewController.viewControllerForColumn(UISplitViewControllerColumn.Secondary);
427
+ const sidebarController = createSidebarController(state);
428
+ splitViewController.minimumPrimaryColumnWidth = state.minimumSidebarWidth;
429
+ splitViewController.preferredPrimaryColumnWidth = state.sidebarWidth;
430
+ splitViewController.maximumPrimaryColumnWidth = state.maximumSidebarWidth;
431
+ splitViewController.setViewControllerForColumn(sidebarController, UISplitViewControllerColumn.Primary);
432
+ state.originalRootViewController = contentViewController;
433
+ state.splitViewController = splitViewController;
434
+ }
435
+ function installSidebarNavigator(state) {
436
+ if (state.splitViewController) return;
437
+ if (!requiredNativeClassesAvailable()) return;
438
+ const window = UIApplication.sharedApplication.keyWindow;
439
+ const rootViewController = window?.rootViewController;
440
+ if (!window || !rootViewController) return;
441
+ if (isSidebarSplitController(rootViewController)) {
442
+ reuseExistingSidebarSplit(state, rootViewController);
443
+ return;
444
+ }
445
+ const sidebarController = createSidebarController(state);
446
+ const splitViewController = UISplitViewController.alloc().initWithStyle(UISplitViewControllerStyle.DoubleColumn);
447
+ splitViewController.restorationIdentifier = splitIdentifier;
448
+ splitViewController.primaryBackgroundStyle = UISplitViewControllerBackgroundStyle.Sidebar;
449
+ splitViewController.preferredSplitBehavior = UISplitViewControllerSplitBehavior.Tile;
450
+ splitViewController.preferredDisplayMode = UISplitViewControllerDisplayMode.OneBesideSecondary;
451
+ splitViewController.displayModeButtonVisibility = UISplitViewControllerDisplayModeButtonVisibility.Always;
452
+ splitViewController.minimumPrimaryColumnWidth = state.minimumSidebarWidth;
453
+ splitViewController.preferredPrimaryColumnWidth = state.sidebarWidth;
454
+ splitViewController.maximumPrimaryColumnWidth = state.maximumSidebarWidth;
455
+ splitViewController.setViewControllerForColumn(sidebarController, UISplitViewControllerColumn.Primary);
456
+ splitViewController.setViewControllerForColumn(rootViewController, UISplitViewControllerColumn.Secondary);
457
+ state.originalRootViewController = rootViewController;
458
+ state.splitViewController = splitViewController;
459
+ window.rootViewController = splitViewController;
460
+ window.makeKeyAndVisible();
461
+ }
462
+ function applySidebarSnapshot(state) {
463
+ const { dataSource } = state;
464
+ if (!dataSource) return;
465
+ const snapshot$1 = NSDiffableDataSourceSnapshot.alloc().init();
466
+ snapshot$1.appendSectionsWithIdentifiers([sectionIdentifier]);
467
+ snapshot$1.appendItemsWithIdentifiersIntoSectionWithIdentifier(state.items.map((item) => item.id), sectionIdentifier);
468
+ dataSource.applySnapshotAnimatingDifferences(snapshot$1, true);
469
+ }
470
+ function applySidebarSelection(state) {
471
+ const { collectionView, selectedId } = state;
472
+ if (!collectionView || selectedId === void 0) return;
473
+ const itemIndex = state.items.findIndex((item) => item.id === selectedId);
474
+ if (itemIndex < 0) return;
475
+ const indexPath = NSIndexPath.indexPathForItemInSection(itemIndex, 0);
476
+ collectionView.selectItemAtIndexPathAnimatedScrollPosition(indexPath, false, UICollectionViewScrollPosition.None);
477
+ }
478
+ function applySidebarNavigator(props, ctx) {
479
+ const state = sidebarState();
480
+ state.items = props.items;
481
+ state.selectedId = props.selectedId;
482
+ state.emitSelect = props.onSelect ? (id) => ctx?.emit("onSelect", id) : void 0;
483
+ state.sidebarWidth = props.sidebarWidth ?? defaultSidebarWidth;
484
+ state.minimumSidebarWidth = props.minimumSidebarWidth ?? defaultMinimumSidebarWidth;
485
+ state.maximumSidebarWidth = props.maximumSidebarWidth ?? defaultMaximumSidebarWidth;
486
+ state.titleById = new Map(props.items.map((item) => [item.id, item.title]));
487
+ state.symbolById = new Map(props.items.filter((item) => Boolean(item.symbol)).map((item) => [item.id, item.symbol]));
488
+ installSidebarNavigator(state);
489
+ applySidebarSnapshot(state);
490
+ applySidebarSelection(state);
491
+ }
492
+ const NativeSidebarNavigator = ensureNativeScript().defineUIKitView({
493
+ name: "NativeSidebarNavigator",
494
+ layout: {
495
+ sizing: "fill",
496
+ defaultSize: {
497
+ width: 0,
498
+ height: 0
499
+ }
500
+ },
501
+ create(ctx) {
502
+ const view = UIView.new();
503
+ view.hidden = true;
504
+ applySidebarNavigator(ctx, ctx);
505
+ return view;
506
+ },
507
+ update(_view, props, _previousProps, ctx) {
508
+ applySidebarNavigator(props, ctx);
509
+ }
510
+ });
511
+ function screenComponent(config) {
512
+ return typeof config === "function" ? config : config.screen;
513
+ }
514
+ function screenTitle(name, config) {
515
+ return typeof config === "function" ? name : config.title ?? name;
516
+ }
517
+ function screenSymbol(config) {
518
+ return typeof config === "function" ? void 0 : config.symbol;
519
+ }
520
+ function createSidebarNavigator(config) {
521
+ const context = createContext(MissingContext);
522
+ const items = Object.entries(config.screens).map(([name, screen]) => ({
523
+ id: name,
524
+ title: screenTitle(name, screen),
525
+ symbol: screenSymbol(screen)
526
+ }));
527
+ const sidebarWidth = config.sidebarWidth ?? defaultSidebarWidth;
528
+ function useNavigatorContext() {
529
+ const value = useContext(context);
530
+ if (value === MissingContext) throw new Error("Expected a Bleam sidebar navigation context");
531
+ return value;
532
+ }
533
+ function Navigator() {
534
+ const [routeName, setRouteName] = useState(config.initialRouteName);
535
+ const navigate = useCallback((name) => {
536
+ if (name in config.screens) setRouteName(name);
537
+ }, []);
538
+ const route = useMemo(() => ({ name: routeName }), [routeName]);
539
+ const navigation = useMemo(() => ({
540
+ route,
541
+ navigate
542
+ }), [route, navigate]);
543
+ const value = useMemo(() => ({
544
+ route,
545
+ navigation
546
+ }), [route, navigation]);
547
+ const activeScreen = config.screens[routeName];
548
+ const ActiveScreen = activeScreen ? screenComponent(activeScreen) : void 0;
549
+ useEffect(() => {
550
+ setSafeAreaContribution(sidebarSafeAreaSource, { left: sidebarWidth });
551
+ return () => {
552
+ clearSafeAreaContribution(sidebarSafeAreaSource);
553
+ };
554
+ }, []);
555
+ return /* @__PURE__ */ jsx(context.Provider, {
556
+ value,
557
+ children: /* @__PURE__ */ jsxs(View, {
558
+ style: [{
559
+ flex: 1,
560
+ paddingLeft: sidebarWidth
561
+ }, config.style],
562
+ children: [/* @__PURE__ */ jsx(NativeSidebarNavigator, {
563
+ items,
564
+ selectedId: routeName,
565
+ sidebarWidth,
566
+ minimumSidebarWidth: config.minimumSidebarWidth,
567
+ maximumSidebarWidth: config.maximumSidebarWidth,
568
+ onSelect: (name) => {
569
+ if (name in config.screens) navigate(name);
570
+ }
571
+ }), ActiveScreen ? createElement(ActiveScreen, {}) : null]
572
+ })
573
+ });
574
+ }
575
+ function useNavigation() {
576
+ return useNavigatorContext().navigation;
577
+ }
578
+ function useRoute() {
579
+ return useNavigatorContext().route;
580
+ }
581
+ return {
582
+ Navigator,
583
+ useNavigation,
584
+ useRoute
585
+ };
586
+ }
587
+
588
+ //#endregion
589
+ export { Toolbar, Window, createSidebarNavigator, useSafeAreaInsets };
package/metro-config.cjs CHANGED
@@ -14,23 +14,28 @@ function getDefaultConfig(projectRoot) {
14
14
  const appRoot = process.env.BLEAM_PROJECT_ROOT ?? projectRoot
15
15
  const port = Number(process.env.BLEAM_DEV_PORT ?? 8081)
16
16
  const origin = process.env.BLEAM_DEV_ORIGIN ?? `http://localhost:${port}`
17
+ const platform = process.env.BLEAM_DEV_PLATFORM === 'ios' ? 'ios' : 'macos'
17
18
  const config = getExpoDefaultConfig(projectRoot)
18
19
  const upstreamEnhanceMiddleware = config.server.enhanceMiddleware
19
20
  const projectNodeModules = path.join(appRoot, 'node_modules')
20
21
  const runtimeNodeModules = path.dirname(packageRoot('react'))
21
- const nodeModulesPaths = Array.from(new Set([
22
- projectNodeModules,
23
- bleamNodeModules,
24
- runtimeNodeModules,
25
- ...(config.resolver.nodeModulesPaths ?? []),
26
- ]))
22
+ const nodeModulesPaths = Array.from(
23
+ new Set([
24
+ projectNodeModules,
25
+ bleamNodeModules,
26
+ runtimeNodeModules,
27
+ ...(config.resolver.nodeModulesPaths ?? []),
28
+ ]),
29
+ )
27
30
 
28
- config.watchFolders = Array.from(new Set([
29
- appRoot,
30
- __dirname,
31
- ...nodeModulesPaths,
32
- ...(config.watchFolders ?? []),
33
- ])).filter((directory) => fs.existsSync(directory))
31
+ config.watchFolders = Array.from(
32
+ new Set([
33
+ appRoot,
34
+ __dirname,
35
+ ...nodeModulesPaths,
36
+ ...(config.watchFolders ?? []),
37
+ ]),
38
+ ).filter((directory) => fs.existsSync(directory))
34
39
 
35
40
  config.resolver.nodeModulesPaths = nodeModulesPaths
36
41
 
@@ -55,7 +60,7 @@ function getDefaultConfig(projectRoot) {
55
60
  name: process.env.BLEAM_DEV_NAME ?? 'bleam-app',
56
61
  sdkVersion: process.env.BLEAM_DEV_SDK_VERSION ?? bleamVersion,
57
62
  runtimeVersion: process.env.BLEAM_DEV_RUNTIME_VERSION ?? bleamVersion,
58
- platform: 'macos',
63
+ platform,
59
64
  bundleUrl: `${origin}/.expo/.virtual-metro-entry.bundle?platform=ios&dev=true&minify=false&runModule=true`,
60
65
  dev: true,
61
66
  })