@satinhq/kit 0.1.0-beta.3 → 0.1.0-beta.4

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 (240) hide show
  1. package/NOTICE +1 -1
  2. package/README.md +1 -2
  3. package/dist/acknowledgements/inventory.json +1 -1
  4. package/dist/actions/RowActions.d.ts +2 -2
  5. package/dist/actions/RowActions.js +91 -25
  6. package/dist/actions/fullSwipeContact.d.ts +73 -0
  7. package/dist/actions/fullSwipeContact.js +186 -0
  8. package/dist/actions/rowScrub.d.ts +7 -4
  9. package/dist/actions/rowScrub.js +39 -37
  10. package/dist/actions/types.d.ts +13 -7
  11. package/dist/app/InstallComponents.d.ts +4 -7
  12. package/dist/app/InstallComponents.js +7 -7
  13. package/dist/app/InstallationDiagnostics.d.ts +2 -1
  14. package/dist/app/InstallationDiagnostics.js +2 -1
  15. package/dist/app/appearance.d.ts +5 -3
  16. package/dist/app/appearance.js +5 -3
  17. package/dist/app/appearanceStore.d.ts +3 -2
  18. package/dist/app/buildInfo.d.ts +4 -4
  19. package/dist/app/buildInfo.js +2 -2
  20. package/dist/app/definition.d.ts +11 -3
  21. package/dist/app/definition.js +2 -0
  22. package/dist/app/head.d.ts +2 -1
  23. package/dist/app/head.js +13 -16
  24. package/dist/app/inlineCSP.d.ts +6 -0
  25. package/dist/app/inlineCSP.js +25 -0
  26. package/dist/app/install.d.ts +1 -0
  27. package/dist/app/install.js +5 -2
  28. package/dist/app/installCheck.js +32 -86
  29. package/dist/app/installContext.d.ts +10 -5
  30. package/dist/app/installContext.js +2 -0
  31. package/dist/app/installCustom.js +1 -0
  32. package/dist/app/installExperience.js +0 -60
  33. package/dist/app/installationFailure.d.ts +3 -2
  34. package/dist/app/installationFailure.js +1 -1
  35. package/dist/app/launchScreen.d.ts +6 -2
  36. package/dist/app/launchScreen.js +104 -1
  37. package/dist/app/launchScreenRuntime.d.ts +31 -4
  38. package/dist/app/launchScreenRuntime.js +150 -22
  39. package/dist/app/launchWatchdog.js +25 -65
  40. package/dist/app/platformScripts.js +11 -0
  41. package/dist/app/styles.d.ts +3 -0
  42. package/dist/app/styles.js +42 -0
  43. package/dist/app/viewportValue.d.ts +2 -1
  44. package/dist/app/vite.d.ts +4 -0
  45. package/dist/app/vite.js +22 -24
  46. package/dist/content/content.d.ts +35 -30
  47. package/dist/content/content.js +19 -16
  48. package/dist/content/layout.d.ts +10 -2
  49. package/dist/content/layout.js +4 -2
  50. package/dist/content/scaledMetric.d.ts +2 -1
  51. package/dist/content/scaledMetric.js +2 -1
  52. package/dist/controls/ColorPicker.d.ts +2 -4
  53. package/dist/controls/ColorPicker.js +2 -4
  54. package/dist/controls/DatePicker.d.ts +4 -4
  55. package/dist/controls/DatePicker.js +2 -2
  56. package/dist/controls/ProgressView.d.ts +4 -4
  57. package/dist/controls/ProgressView.js +1 -2
  58. package/dist/data/database.d.ts +9 -8
  59. package/dist/data/database.js +4 -4
  60. package/dist/docs/reference.md +982 -964
  61. package/dist/docs/tailwind.md +76 -0
  62. package/dist/docs/tokens.md +1 -1
  63. package/dist/gestures/GestureView.d.ts +3 -1
  64. package/dist/gestures/GestureView.js +2 -1
  65. package/dist/gestures/gesture.d.ts +22 -2
  66. package/dist/gestures/gesture.js +7 -2
  67. package/dist/glass/GlassEffect.d.ts +2 -1
  68. package/dist/glass/GlassEffect.js +2 -1
  69. package/dist/glass/GlassPresentation.d.ts +1 -0
  70. package/dist/glass/GlassPresentation.js +21 -4
  71. package/dist/glass/TabBar.js +23 -1
  72. package/dist/glass/errorAlert.js +2 -1
  73. package/dist/glass/errors.d.ts +3 -1
  74. package/dist/glass/fallback/runtime.d.ts +1 -0
  75. package/dist/glass/fallback/runtime.js +8 -1
  76. package/dist/glass/liquidContext.d.ts +2 -0
  77. package/dist/glass/menuPresenter.d.ts +2 -0
  78. package/dist/glass/regions.d.ts +2 -1
  79. package/dist/glass/renderSpecs.d.ts +1 -0
  80. package/dist/glass/renderSpecs.js +1 -0
  81. package/dist/glass/webgpu/controlRim.d.ts +29 -0
  82. package/dist/glass/webgpu/controlRim.js +68 -0
  83. package/dist/glass/webgpu/passes.d.ts +2 -2
  84. package/dist/glass/webgpu/production.d.ts +1 -0
  85. package/dist/glass/webgpu/production.js +27 -1
  86. package/dist/glass/webgpu/rasterUniforms.js +9 -0
  87. package/dist/glass/webgpu/shaders.d.ts +2 -2
  88. package/dist/glass/webgpu/shaders.js +5 -1
  89. package/dist/haptics/SensoryButton.d.ts +4 -4
  90. package/dist/haptics/SensoryButton.js +3 -3
  91. package/dist/image/Image.d.ts +6 -3
  92. package/dist/image/Image.js +4 -3
  93. package/dist/image/asset.d.ts +2 -1
  94. package/dist/keyboard/adapter.d.ts +3 -4
  95. package/dist/keyboard/geometry.d.ts +1 -1
  96. package/dist/list-form/ListForm.d.ts +8 -7
  97. package/dist/list-form/ListForm.js +2 -2
  98. package/dist/list-form/editing.d.ts +5 -6
  99. package/dist/list-form/editing.js +4 -5
  100. package/dist/list-form/offsets.d.ts +2 -2
  101. package/dist/list-form/offsets.js +2 -2
  102. package/dist/media/react.d.ts +2 -1
  103. package/dist/media/react.js +2 -1
  104. package/dist/media/types.d.ts +6 -3
  105. package/dist/motion/TransitionView.d.ts +4 -2
  106. package/dist/motion/TransitionView.js +3 -2
  107. package/dist/motion/animationValue.d.ts +1 -1
  108. package/dist/motion/matchedGeometry.d.ts +6 -5
  109. package/dist/motion/matchedGeometry.js +2 -1
  110. package/dist/motion/transition.d.ts +4 -1
  111. package/dist/motion/transition.js +2 -0
  112. package/dist/navigation/DetailList.d.ts +1 -1
  113. package/dist/navigation/DetailList.js +1 -1
  114. package/dist/navigation/Sidebar.d.ts +3 -1
  115. package/dist/navigation/Sidebar.js +1 -1
  116. package/dist/navigation/SidebarSymbol.d.ts +2 -1
  117. package/dist/navigation/SidebarSymbol.js +2 -1
  118. package/dist/navigation/navigationContext.d.ts +2 -1
  119. package/dist/navigation/navigationContext.js +2 -1
  120. package/dist/navigation/splitContext.d.ts +2 -1
  121. package/dist/navigation/splitContext.js +2 -1
  122. package/dist/navigation/toolbarMinimization.d.ts +4 -3
  123. package/dist/navigation/types.d.ts +7 -5
  124. package/dist/presentation/Presentation.d.ts +8 -7
  125. package/dist/presentation/Presentation.js +3 -2
  126. package/dist/presentation/model.d.ts +2 -1
  127. package/dist/press/Pressable.d.ts +5 -1
  128. package/dist/press/Pressable.js +2 -0
  129. package/dist/press/stateMachine.d.ts +1 -1
  130. package/dist/public/Label.d.ts +2 -1
  131. package/dist/public/Label.js +2 -1
  132. package/dist/public/Screen.d.ts +4 -6
  133. package/dist/public/actions.d.ts +2 -1
  134. package/dist/public/actions.js +2 -1
  135. package/dist/public/buttonBorderShape.d.ts +2 -1
  136. package/dist/public/colors.d.ts +7 -4
  137. package/dist/public/colors.js +3 -2
  138. package/dist/public/controlStyle.d.ts +17 -14
  139. package/dist/public/controls.d.ts +27 -26
  140. package/dist/public/controls.js +20 -19
  141. package/dist/public/deviceActions.d.ts +6 -4
  142. package/dist/public/deviceActions.js +4 -2
  143. package/dist/public/environment.d.ts +16 -13
  144. package/dist/public/environment.js +11 -9
  145. package/dist/public/filePickers.d.ts +6 -4
  146. package/dist/public/filePickers.js +3 -2
  147. package/dist/public/glass.d.ts +6 -3
  148. package/dist/public/glass.js +2 -1
  149. package/dist/public/glassValue.d.ts +3 -4
  150. package/dist/public/glassValue.js +3 -4
  151. package/dist/public/keyboard.d.ts +4 -1
  152. package/dist/public/keyboard.js +2 -1
  153. package/dist/public/navigationTransition.d.ts +5 -5
  154. package/dist/public/navigationTransition.js +2 -2
  155. package/dist/public/presentation.d.ts +8 -7
  156. package/dist/public/presentation.js +5 -5
  157. package/dist/public/runtime.d.ts +9 -8
  158. package/dist/public/runtime.js +7 -7
  159. package/dist/public/scroll.d.ts +6 -3
  160. package/dist/public/scroll.js +3 -1
  161. package/dist/public/structure.d.ts +2 -2
  162. package/dist/public/toolbar.d.ts +15 -11
  163. package/dist/public/toolbar.js +12 -7
  164. package/dist/reachability/model.d.ts +4 -3
  165. package/dist/reachability/react.d.ts +4 -1
  166. package/dist/reachability/react.js +2 -1
  167. package/dist/root/SatinRoot.d.ts +3 -3
  168. package/dist/root/SatinRoot.js +12 -36
  169. package/dist/root/mountSatin.d.ts +1 -1
  170. package/dist/root/mountSatin.js +26 -35
  171. package/dist/root/runtimeContext.d.ts +2 -1
  172. package/dist/root/runtimeContext.js +2 -1
  173. package/dist/safe-area/Overlay.d.ts +3 -2
  174. package/dist/safe-area/Overlay.js +2 -1
  175. package/dist/safe-area/SafeAreaInset.d.ts +11 -7
  176. package/dist/safe-area/SafeAreaInset.js +7 -6
  177. package/dist/safe-area/context.d.ts +3 -3
  178. package/dist/safe-area/context.js +1 -1
  179. package/dist/safe-area/displayCorners.d.ts +4 -2
  180. package/dist/safe-area/displayCorners.js +4 -2
  181. package/dist/safe-area/modifiers.d.ts +14 -10
  182. package/dist/safe-area/modifiers.js +8 -4
  183. package/dist/scroll/ScrollSurface.js +5 -1
  184. package/dist/scroll/ScrollTarget.d.ts +1 -1
  185. package/dist/scroll/ScrollTarget.js +1 -1
  186. package/dist/scroll/edgePolicy.d.ts +2 -2
  187. package/dist/scroll/position.d.ts +5 -3
  188. package/dist/scroll/types.d.ts +1 -1
  189. package/dist/search/PadSearchDrawer.d.ts +7 -0
  190. package/dist/search/PadSearchDrawer.js +8 -0
  191. package/dist/search/PadSearchPresentationContext.d.ts +6 -0
  192. package/dist/search/PadSearchPresentationContext.js +4 -0
  193. package/dist/search/SearchDrawer.d.ts +1 -1
  194. package/dist/search/SearchDrawer.js +6 -1
  195. package/dist/search/SearchSuggestionsPopover.d.ts +6 -0
  196. package/dist/search/SearchSuggestionsPopover.js +42 -0
  197. package/dist/search/SearchToolbarField.d.ts +2 -1
  198. package/dist/search/SearchToolbarField.js +28 -7
  199. package/dist/search/padSearchBarMotion.d.ts +69 -0
  200. package/dist/search/padSearchBarMotion.js +73 -0
  201. package/dist/search/padSearchFieldSamples.json +491 -0
  202. package/dist/search/searchPlacement.d.ts +3 -0
  203. package/dist/search/searchPlacement.js +7 -0
  204. package/dist/search/searchable.d.ts +14 -12
  205. package/dist/search/usePadSearchFieldMotion.d.ts +4 -0
  206. package/dist/search/usePadSearchFieldMotion.js +100 -0
  207. package/dist/search/useSearchPresentation.d.ts +2 -1
  208. package/dist/search/useSearchPresentation.js +23 -5
  209. package/dist/server.d.ts +4 -4
  210. package/dist/server.js +4 -4
  211. package/dist/shapes/corners.d.ts +3 -3
  212. package/dist/shapes/corners.js +1 -2
  213. package/dist/styles.css +8289 -8244
  214. package/dist/sw/vite.d.ts +4 -0
  215. package/dist/sw/vite.js +2 -0
  216. package/dist/symbols/Symbol.d.ts +7 -5
  217. package/dist/symbols/Symbol.js +5 -3
  218. package/dist/symbols/catalogue.d.ts +1 -1
  219. package/dist/symbols/types.d.ts +6 -4
  220. package/dist/tabs/TabSection.d.ts +3 -2
  221. package/dist/tabs/TabSection.js +2 -1
  222. package/dist/tabs/TabView.js +54 -51
  223. package/dist/tasks/useTask.d.ts +5 -4
  224. package/dist/tasks/useTask.js +4 -3
  225. package/dist/testing.d.ts +3 -2
  226. package/dist/testing.js +3 -2
  227. package/dist/text-input/focusChain.d.ts +4 -3
  228. package/dist/text-input/focusChain.js +3 -2
  229. package/dist/text-input/kinds.d.ts +1 -1
  230. package/dist/web/WebView.d.ts +10 -3
  231. package/dist/web/WebView.js +3 -2
  232. package/dist/web/authentication.d.ts +12 -1
  233. package/dist/web/authentication.js +2 -1
  234. package/dist/web/openURL.d.ts +10 -4
  235. package/dist/web/openURL.js +4 -2
  236. package/dist/web/useWebAuthentication.d.ts +2 -1
  237. package/dist/web/useWebAuthentication.js +2 -1
  238. package/dist/zoom/Zoomable.d.ts +3 -3
  239. package/dist/zoom/Zoomable.js +2 -2
  240. package/package.json +1 -1
@@ -2,8 +2,8 @@ import { type ReactNode } from 'react';
2
2
  import type { NamespaceID } from '../motion/matchedGeometry.js';
3
3
  declare const brand: unique symbol;
4
4
  /**
5
- * `NavigationTransition`: how a pushed screen arrives and leaves. Give one to `Screen`'s
6
- * `navigationTransition`.
5
+ * How a pushed screen arrives and leaves: `automatic` (a slide) or `zoom`. Give one to
6
+ * `Screen`'s `navigationTransition`.
7
7
  */
8
8
  export type NavigationTransition = Readonly<{
9
9
  [brand]: true;
@@ -22,7 +22,7 @@ export declare const NavigationTransition: Readonly<{
22
22
  automatic: NavigationTransition;
23
23
  zoom: (options: ZoomTransitionOptions) => NavigationTransition;
24
24
  }>;
25
- /** Props of `MatchedTransitionSource`. */
25
+ /** The source's id and namespace, and the one element the screen zooms out of. */
26
26
  export type MatchedTransitionSourceProps = Readonly<{
27
27
  /** The id a `NavigationTransition.zoom` names as its `sourceID`. */
28
28
  id: string;
@@ -31,8 +31,8 @@ export type MatchedTransitionSourceProps = Readonly<{
31
31
  children: ReactNode;
32
32
  }>;
33
33
  /**
34
- * `matchedTransitionSource(id:in:)`: marks the view a zoom transition starts from and
35
- * returns to. A push zooms only while its source is on screen; otherwise it slides as usual.
34
+ * Marks the view a zoom transition starts from and returns to. A push zooms only while its
35
+ * source is on screen; otherwise it slides as usual.
36
36
  * @example
37
37
  * <MatchedTransitionSource id={album.id} in={albumZoom}>
38
38
  * <Image src={album.artwork} alt="" />
@@ -13,8 +13,8 @@ export const NavigationTransition = Object.freeze({
13
13
  zoom: ({ sourceID, in: namespace }) => Object.freeze({ [brand]: true, kind: 'zoom', sourceID, namespace }),
14
14
  });
15
15
  /**
16
- * `matchedTransitionSource(id:in:)`: marks the view a zoom transition starts from and
17
- * returns to. A push zooms only while its source is on screen; otherwise it slides as usual.
16
+ * Marks the view a zoom transition starts from and returns to. A push zooms only while its
17
+ * source is on screen; otherwise it slides as usual.
18
18
  * @example
19
19
  * <MatchedTransitionSource id={album.id} in={albumZoom}>
20
20
  * <Image src={album.artwork} alt="" />
@@ -1,6 +1,7 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { PresentationDetent } from '../presentation/model.js';
3
- /** Sheet's presentation binding, title, detents and drag behaviour. */
3
+ /** A sheet's presentation binding, title, detents and drag behaviour. Supplying `selection`
4
+ * requires `onSelectionChange`. */
4
5
  export type SheetProps = {
5
6
  isPresented: boolean;
6
7
  onPresentedChange(presented: boolean): void;
@@ -19,15 +20,15 @@ export type SheetProps = {
19
20
  onSelectionChange(detent: PresentationDetent): void;
20
21
  });
21
22
  /**
22
- * `sheet(isPresented:)`: a card over the current screen, with optional detents. It can
23
- * host its own `NavigationStack modal`. Keep `isPresented` in plain React state: presentations
24
- * start closed after a relaunch.
23
+ * A card that slides up over the current screen and can rest at several heights. It can host
24
+ * its own `NavigationStack modal`. Keep `isPresented` in plain React state: presentations start
25
+ * closed after a relaunch.
25
26
  *
26
27
  * @example
27
28
  * <Sheet isPresented={adding} onPresentedChange={setAdding} title="New Note">...</Sheet>
28
29
  */
29
30
  export declare function Sheet(props: SheetProps): import("react").JSX.Element;
30
- /** FullScreenCover's presentation binding and accessible title. */
31
+ /** A full-screen cover's presentation binding and accessible title. */
31
32
  export type FullScreenCoverProps = {
32
33
  isPresented: boolean;
33
34
  onPresentedChange(presented: boolean): void;
@@ -35,6 +36,6 @@ export type FullScreenCoverProps = {
35
36
  onDismiss?(): void;
36
37
  children: ReactNode;
37
38
  };
38
- /** `fullScreenCover`: an opaque presentation over the whole screen, closed through its
39
- * binding or `useDismiss()`. */
39
+ /** An opaque presentation that slides up over the whole screen. It has no interactive dismissal;
40
+ * close it through its binding or `useDismiss()`. */
40
41
  export declare function FullScreenCover(props: FullScreenCoverProps): import("react").JSX.Element;
@@ -2,9 +2,9 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { FullScreenCover as EngineFullScreenCover, Sheet as EngineSheet, } from '../presentation/Presentation.js';
3
3
  import { ModalPresentationContext } from './presentationContext.js';
4
4
  /**
5
- * `sheet(isPresented:)`: a card over the current screen, with optional detents. It can
6
- * host its own `NavigationStack modal`. Keep `isPresented` in plain React state: presentations
7
- * start closed after a relaunch.
5
+ * A card that slides up over the current screen and can rest at several heights. It can host
6
+ * its own `NavigationStack modal`. Keep `isPresented` in plain React state: presentations start
7
+ * closed after a relaunch.
8
8
  *
9
9
  * @example
10
10
  * <Sheet isPresented={adding} onPresentedChange={setAdding} title="New Note">...</Sheet>
@@ -14,8 +14,8 @@ export function Sheet(props) {
14
14
  throw new TypeError('Controlled sheet selection requires onSelectionChange.');
15
15
  return (_jsx(ModalPresentationContext, { value: true, children: _jsx(EngineSheet, { ...props }) }));
16
16
  }
17
- /** `fullScreenCover`: an opaque presentation over the whole screen, closed through its
18
- * binding or `useDismiss()`. */
17
+ /** An opaque presentation that slides up over the whole screen. It has no interactive dismissal;
18
+ * close it through its binding or `useDismiss()`. */
19
19
  export function FullScreenCover(props) {
20
20
  return (_jsx(ModalPresentationContext, { value: true, children: _jsx(EngineFullScreenCover, { ...props }) }));
21
21
  }
@@ -83,13 +83,13 @@ export declare function NavigationStack<R extends Routes = RegisteredRoutes, D =
83
83
  export type NavigationSplitViewProps<D = RegisteredNavigation> = {
84
84
  tab?: TabId<D>;
85
85
  };
86
- /** `NavigationSplitView`: the declared root becomes the sidebar and pushes become the
87
- * retained detail stack. It collapses to a plain stack at compact width. A `NavigationStack` never
88
- * splits by itself. */
86
+ /** Shows the declared root as a sidebar and pushes into a retained detail column. At compact
87
+ * width it collapses to a plain stack. A `NavigationStack` never splits by itself. */
89
88
  export declare function NavigationSplitView<D = RegisteredNavigation>(props: NavigationSplitViewProps<D>): import("react").JSX.Element;
90
89
  /** The typed parameter tuple accepted by push and replace. */
91
90
  export type NavigationArguments<P> = {} extends P ? [params?: P] : [params: P];
92
- /** The current stack's typed navigation actions. */
91
+ /** The actions `useNavigation` returns: `push`, `replace`, `pop`, `popToRoot` and
92
+ * `showAcknowledgements`, typed against the routes. */
93
93
  export interface Navigation<R extends Routes> {
94
94
  /** Opens the built-in credit and bundled licenses. Returns false when opted out or while a back gesture owns navigation. */
95
95
  showAcknowledgements(): boolean;
@@ -124,11 +124,12 @@ export type TabViewProps<D = RegisteredNavigation> = {
124
124
  export type TabProps<D = RegisteredNavigation> = {
125
125
  id: TabId<D>;
126
126
  };
127
- /** Render one declared tab's content; identities and root stacks come from defineNavigation. */
127
+ /** Renders one declared tab inside a `TabView`. Its id, label and root stack come from
128
+ * `defineNavigation`. */
128
129
  export declare function Tab<D = RegisteredNavigation>({ id }: TabProps<D>): import("react").JSX.Element;
129
130
  /**
130
- * `TabView`: renders the tabs from `defineNavigation`, each retaining its own stack, and
131
- * restores the selected tab with the scene. Pass `selection` and `onSelectionChange` to control it;
132
- * a controlled tab press only requests the change.
131
+ * Renders the tabs from `defineNavigation`. Each tab keeps its own stack, and the selected tab is
132
+ * restored with the scene. Pass `selection` and `onSelectionChange` to control it; a controlled
133
+ * tab press only requests the change.
133
134
  */
134
135
  export declare function TabView<D = RegisteredNavigation>(props: TabViewProps<D>): import("react").JSX.Element;
@@ -121,9 +121,8 @@ export function NavigationStack(props) {
121
121
  throw new Error('Primary roots belong in defineNavigation, not JSX');
122
122
  return props.modal ? _jsx(ModalStack, { ...props }) : _jsx(PrimaryStack, { tab: props.tab });
123
123
  }
124
- /** `NavigationSplitView`: the declared root becomes the sidebar and pushes become the
125
- * retained detail stack. It collapses to a plain stack at compact width. A `NavigationStack` never
126
- * splits by itself. */
124
+ /** Shows the declared root as a sidebar and pushes into a retained detail column. At compact
125
+ * width it collapses to a plain stack. A `NavigationStack` never splits by itself. */
127
126
  export function NavigationSplitView(props) {
128
127
  if ('root' in props || 'params' in props || 'modal' in props)
129
128
  throw new Error('NavigationSplitView uses a declared primary sidebar root');
@@ -206,7 +205,8 @@ export function useNavigation() {
206
205
  };
207
206
  }, [navigator, routes, app]);
208
207
  }
209
- /** Render one declared tab's content; identities and root stacks come from defineNavigation. */
208
+ /** Renders one declared tab inside a `TabView`. Its id, label and root stack come from
209
+ * `defineNavigation`. */
210
210
  export function Tab({ id }) {
211
211
  return _jsx(DeclaredTab, { id: id });
212
212
  }
@@ -219,9 +219,9 @@ function DeclaredTab({ id }) {
219
219
  return (_jsx(PrimaryTabContext, { value: id, children: Content ? _jsx(Content, {}) : _jsx(PrimaryStack, {}) }));
220
220
  }
221
221
  /**
222
- * `TabView`: renders the tabs from `defineNavigation`, each retaining its own stack, and
223
- * restores the selected tab with the scene. Pass `selection` and `onSelectionChange` to control it;
224
- * a controlled tab press only requests the change.
222
+ * Renders the tabs from `defineNavigation`. Each tab keeps its own stack, and the selected tab is
223
+ * restored with the scene. Pass `selection` and `onSelectionChange` to control it; a controlled
224
+ * tab press only requests the change.
225
225
  */
226
226
  export function TabView(props) {
227
227
  return _jsx(DeclaredTabView, { ...props });
@@ -4,14 +4,15 @@ import type { TaskAction } from '../tasks/useTask.js';
4
4
  import type { ScrollAnchor, ScrollPositionBinding, VerticalScrollGeometry } from '../scroll/position.js';
5
5
  import type { ScrollEdgeEffectHidden, ScrollEdgeEffectStyleSelection } from '../scroll/edgePolicy.js';
6
6
  import type { ScrollOffset, ScrollToTopOptions } from '../scroll/types.js';
7
- /** The current offset and imperative positioning of a scroll view. */
7
+ /** A scroll view's ref handle: its current offset, `scrollTo` a target and `scrollToTop`. */
8
8
  export interface ScrollViewHandle {
9
9
  readonly offset: ScrollOffset;
10
10
  /** Position a vertical ScrollTarget. Horizontal target positioning is unsupported. */
11
11
  scrollTo(id: string, anchor?: ScrollAnchor): boolean;
12
12
  scrollToTop(options?: ScrollToTopOptions): void;
13
13
  }
14
- /** Scroll policy. Target positioning, refresh and scalar geometry are vertical-only. */
14
+ /** A scroll view's id, axis, refresh action, keyboard dismissal, edge material and position
15
+ * options. Targets, refresh and geometry work only on the vertical axis. */
15
16
  export type ScrollViewProps = Omit<HTMLAttributes<HTMLDivElement>, 'id'> & {
16
17
  id: string;
17
18
  chain?: boolean;
@@ -34,5 +35,7 @@ export type ScrollViewProps = Omit<HTMLAttributes<HTMLDivElement>, 'id'> & {
34
35
  scrollPosition?: never;
35
36
  onScrollGeometryChange?: never;
36
37
  });
37
- /** A scroll surface with framework-owned restoration and native scrolling. */
38
+ /** A scrolling region, vertical by default. Inside a screen its `id` keys scroll restoration, so
39
+ * keep it stable. `refreshable` adds pull to refresh, and a ref handle scrolls to a
40
+ * `ScrollTarget`. */
38
41
  export declare const ScrollView: import("react").ForwardRefExoticComponent<ScrollViewProps & import("react").RefAttributes<ScrollViewHandle>>;
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from 'react';
3
3
  import { ScrollSurface } from '../scroll/ScrollSurface.js';
4
- /** A scroll surface with framework-owned restoration and native scrolling. */
4
+ /** A scrolling region, vertical by default. Inside a screen its `id` keys scroll restoration, so
5
+ * keep it stable. `refreshable` adds pull to refresh, and a ref handle scrolls to a
6
+ * `ScrollTarget`. */
5
7
  export const ScrollView = forwardRef(function ScrollView(props, ref) {
6
8
  return _jsx(ScrollSurface, { ...props, ref: ref });
7
9
  });
@@ -11,14 +11,14 @@ export type StackDeclaration<R extends Routes> = {
11
11
  params: RouteProps<R, K>;
12
12
  });
13
13
  }[keyof R['definitions'] & string];
14
- /** The tab declaration contract used by public app declarations. */
14
+ /** One tab in `defineNavigation`: its id, label, symbol or icon, and the root of its stack. */
15
15
  export type TabDeclaration<R extends Routes> = StackDeclaration<R> & {
16
16
  /** The tab's identity: typed by `TabId`, used by `TabView selection` and restoration. */
17
17
  id: string;
18
18
  label: string;
19
19
  icon?: ReactNode;
20
20
  symbol?: SymbolName;
21
- /** `Tab(role: .search)`: the separated search tab. */
21
+ /** `search` marks the search tab, drawn apart from the other tabs. */
22
22
  role?: 'search';
23
23
  /** Wraps the tab's stack, for per-tab providers. Render `<NavigationStack />` inside it. */
24
24
  content?: ComponentType;
@@ -4,7 +4,8 @@ import type { ToolbarSlot } from './screenChrome.js';
4
4
  export declare const BottomBarRegistrationContext: import("react").Context<(() => () => void) | null>;
5
5
  /** A `DefaultToolbarItem kind="search"` reports the element it holds in the bottom bar. */
6
6
  export declare const SearchToolbarItemContext: import("react").Context<((element: HTMLElement | null) => void) | null>;
7
- /** The supported toolbar placement names. */
7
+ /** A toolbar item's placement and content. `automatic` lets the bar choose; `bottomBar` puts it
8
+ * in the bottom toolbar. */
8
9
  export type ToolbarItemProps = {
9
10
  placement: 'subtitle' | 'largeTitle' | 'largeSubtitle' | 'principal' | 'topBarLeading' | 'topBarTrailing' | 'primaryAction' | 'confirmationAction' | 'cancellationAction' | 'automatic' | 'bottomBar';
10
11
  children?: ReactNode;
@@ -12,26 +13,29 @@ export type ToolbarItemProps = {
12
13
  export declare const ToolbarContext: import("react").Context<"group" | boolean>;
13
14
  export declare const ToolbarConfirmationContext: import("react").Context<boolean>;
14
15
  export declare const ToolbarSlotsContext: import("react").Context<Partial<Record<ToolbarSlot, HTMLDivElement | null>>>;
15
- /** Places one navigation or bottom-bar item. Adjacent actions share a glass capsule; ToolbarSpacer separates groups. */
16
+ /** Places one item in the navigation bar or the bottom toolbar. Adjacent actions share a glass
17
+ * capsule; a `ToolbarSpacer` separates groups. */
16
18
  export declare function ToolbarItem({ children, placement }: ToolbarItemProps): import("react").ReactPortal | null;
17
- /** Which system item to place, and where. */
19
+ /** Which system item to place, and where. Only `search` exists. */
18
20
  export type DefaultToolbarItemProps = {
19
- /** `DefaultToolbarItem(kind:)`. Only `search` is drawn. */
21
+ /** The system item. Only `search` is drawn. */
20
22
  kind: 'search';
21
23
  placement?: 'bottomBar' | 'automatic';
22
24
  };
23
- /** Places the screen search field among bottom-bar items. Requires Screen searchable. */
25
+ /** Places the screen's search field among its bottom toolbar items. The screen must be
26
+ * `searchable`. */
24
27
  export declare function DefaultToolbarItem({ kind }: DefaultToolbarItemProps): import("react").ReactPortal | null;
25
28
  /** The spacer's sizing and placement. */
26
29
  export type ToolbarSpacerProps = {
27
- /** `SpacerSizing`: `fixed` separates two items' glass by the standard 12 pt gap;
28
- * `flexible` (the default) takes the free space of the bar, like `ToolbarSpacer()`. */
30
+ /** `fixed` separates two items' glass by the standard 12 pt gap; `flexible`, the default,
31
+ * takes the free space of the bar. */
29
32
  sizing?: 'fixed' | 'flexible';
30
33
  placement?: ToolbarItemProps['placement'];
31
34
  };
32
- /** `ToolbarSpacer(_:placement:)`. Consecutive items of one placement share one glass
33
- * capsule; a spacer between them splits it. Place it directly in `toolbar`, next to the items. */
35
+ /** Splits toolbar items into separate glass capsules. Consecutive items of one placement share
36
+ * one capsule; a spacer between them splits it. Place it directly in `toolbar`, next to the
37
+ * items. */
34
38
  export declare function ToolbarSpacer({ sizing, placement, }: ToolbarSpacerProps): import("react").JSX.Element | null;
35
- /** `ToolbarItemGroup`: its items render as consecutive `ToolbarItem`s of the placement,
36
- * which share one glass capsule (iOS 26+ draws a group and adjacent items identically). */
39
+ /** Groups several items under one placement. They render as consecutive `ToolbarItem`s and share
40
+ * one glass capsule. */
37
41
  export declare function ToolbarItemGroup({ children, placement }: ToolbarItemProps): import("react").JSX.Element;
@@ -1,4 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { readDeviceIdiom } from '../layout/deviceIdiom.js';
2
3
  import { Children, createContext, isValidElement, useContext, useLayoutEffect, useState, } from 'react';
3
4
  import { createPortal } from 'react-dom';
4
5
  import { ToolbarMaterialContext } from '../glass/toolbarMaterialContext.js';
@@ -24,7 +25,8 @@ const toolbarPlacement = {
24
25
  bottomBar: 'bottom',
25
26
  };
26
27
  export const ToolbarSlotsContext = createContext({});
27
- /** Places one navigation or bottom-bar item. Adjacent actions share a glass capsule; ToolbarSpacer separates groups. */
28
+ /** Places one item in the navigation bar or the bottom toolbar. Adjacent actions share a glass
29
+ * capsule; a `ToolbarSpacer` separates groups. */
28
30
  export function ToolbarItem({ children, placement }) {
29
31
  const slots = useContext(ToolbarSlotsContext);
30
32
  const registerBottomBar = useContext(BottomBarRegistrationContext);
@@ -40,11 +42,13 @@ export function ToolbarItem({ children, placement }) {
40
42
  ? createPortal(_jsx("div", { "data-satin-toolbar-item": spacer ? 'spacer' : 'item', children: _jsx(ToolbarMaterialContext, { value: !['subtitle', 'largeTitle', 'largeSubtitle'].includes(slot), children: _jsx(ToolbarContext, { value: !['subtitle', 'largeTitle', 'largeSubtitle'].includes(slot), children: _jsx(ToolbarConfirmationContext, { value: placement === 'confirmationAction', children: children }) }) }) }), destination)
41
43
  : null;
42
44
  }
43
- /** Places the screen search field among bottom-bar items. Requires Screen searchable. */
45
+ /** Places the screen's search field among its bottom toolbar items. The screen must be
46
+ * `searchable`. */
44
47
  export function DefaultToolbarItem({ kind }) {
45
48
  const slots = useContext(ToolbarSlotsContext);
46
49
  const report = useContext(SearchToolbarItemContext);
47
- const destination = slots.bottom;
50
+ // iPad search is owned by the navigation column's trailing slot.
51
+ const destination = readDeviceIdiom() === 'pad' ? undefined : slots.bottom;
48
52
  const [element, setElement] = useState(null);
49
53
  useLayoutEffect(() => {
50
54
  report?.(element);
@@ -54,8 +58,9 @@ export function DefaultToolbarItem({ kind }) {
54
58
  ? createPortal(_jsx("div", { ref: setElement, "data-satin-toolbar-item": "search", "data-satin-search-toolbar-host": "" }), destination)
55
59
  : null;
56
60
  }
57
- /** `ToolbarSpacer(_:placement:)`. Consecutive items of one placement share one glass
58
- * capsule; a spacer between them splits it. Place it directly in `toolbar`, next to the items. */
61
+ /** Splits toolbar items into separate glass capsules. Consecutive items of one placement share
62
+ * one capsule; a spacer between them splits it. Place it directly in `toolbar`, next to the
63
+ * items. */
59
64
  export function ToolbarSpacer({ sizing = 'flexible', placement = 'automatic', }) {
60
65
  const slots = useContext(ToolbarSlotsContext);
61
66
  const inItem = useContext(ToolbarContext) !== false;
@@ -66,8 +71,8 @@ export function ToolbarSpacer({ sizing = 'flexible', placement = 'automatic', })
66
71
  const destination = slots[slot] ?? (slot === 'topBarLeading' ? slots.leading : undefined);
67
72
  return destination ? createPortal(spacer, destination) : null;
68
73
  }
69
- /** `ToolbarItemGroup`: its items render as consecutive `ToolbarItem`s of the placement,
70
- * which share one glass capsule (iOS 26+ draws a group and adjacent items identically). */
74
+ /** Groups several items under one placement. They render as consecutive `ToolbarItem`s and share
75
+ * one glass capsule. */
71
76
  export function ToolbarItemGroup({ children, placement }) {
72
77
  // gives confirmation actions separate capsules, even inside a group.
73
78
  if (placement === 'confirmationAction')
@@ -1,10 +1,10 @@
1
- /** The result of the app server reachability probe. */
1
+ /** Whether the app server answered: `reachable`, `server-unreachable` or `device-offline`. */
2
2
  export type ReachabilityStatus = 'device-offline' | 'server-unreachable' | 'reachable';
3
3
  /** The server probe result, including an unknown initial state. */
4
4
  export type ReachabilityStateStatus = ReachabilityStatus | 'unknown';
5
5
  /** Whether a destination remains usable without the app server. */
6
6
  export type ReachabilityRoutePolicy = 'local-first' | 'requires-server';
7
- /** The framework connectivity presentation to show for a failed probe. */
7
+ /** How Satin shows a failed probe: a `banner`, a `full-screen` offline view, or `none`. */
8
8
  export type ReachabilitySurface = 'banner' | 'full-screen' | 'none';
9
9
  /** The endpoint and deadlines used to probe the app server. */
10
10
  export interface ReachabilityProbeConfig {
@@ -66,7 +66,7 @@ export interface ReachabilityPresentation {
66
66
  readonly reason: Exclude<ReachabilityStatus, 'reachable'>;
67
67
  readonly surface: Exclude<ReachabilitySurface, 'none'>;
68
68
  }
69
- /** The connectivity state of an app that does not require an app server. */
69
+ /** The reachability state of an app that needs no app server. Its status is always `local`. */
70
70
  export interface LocalReachabilityState {
71
71
  readonly connectivity: 'local';
72
72
  readonly status: 'local';
@@ -82,6 +82,7 @@ export interface ServerReachabilityState {
82
82
  readonly route: string;
83
83
  readonly status: ReachabilityStateStatus;
84
84
  }
85
+ /** The full reachability state: local for apps without a server, or the server probe state. */
85
86
  export type ReachabilityState = LocalReachabilityState | ServerReachabilityState;
86
87
  export interface ReachabilityReduction {
87
88
  readonly commands: readonly ReachabilityCommand[];
@@ -1,5 +1,7 @@
1
1
  import { type ComponentType, type PropsWithChildren } from 'react';
2
2
  import type { ReachabilityProfile, ReachabilitySurface } from './model.js';
3
+ /** What the offline view shows: why the server is unavailable, how it is presented, and the
4
+ * recheck and back actions. */
3
5
  export interface OfflinePresentationProps {
4
6
  readonly reason: 'device-offline' | 'server-unreachable';
5
7
  readonly surface: Exclude<ReachabilitySurface, 'none'>;
@@ -12,7 +14,8 @@ export declare function ReachabilityProvider({ profile, offlinePresentation, chi
12
14
  profile: ReachabilityProfile;
13
15
  offlinePresentation?: ComponentType<OfflinePresentationProps>;
14
16
  }>): import("react").JSX.Element;
15
- /** The server status and visible offline presentation, with fetch and retry helpers. */
17
+ /** The app server's status and the offline view currently shown, with `fetch` and `recheck`
18
+ * helpers that feed the status. */
16
19
  export declare function useReachability(): {
17
20
  recheck: () => void;
18
21
  reportFetchOutcome: (outcome: 'response' | 'network-failure' | 'aborted') => void;
@@ -37,7 +37,8 @@ function useReachabilityController() {
37
37
  fetch: controller.fetch,
38
38
  };
39
39
  }
40
- /** The server status and visible offline presentation, with fetch and retry helpers. */
40
+ /** The app server's status and the offline view currently shown, with `fetch` and `recheck`
41
+ * helpers that feed the status. */
41
42
  export function useReachability() {
42
43
  const { state, ...commands } = useReachabilityController();
43
44
  return {
@@ -15,11 +15,11 @@ export type SatinRootProps = PropsWithChildren<Omit<HTMLAttributes<HTMLDivElemen
15
15
  /** Receives every renderer failure, including failures after launch. Release builds switch failed glass to the fallback material. */
16
16
  onGlassError?: (error: GlassError) => void;
17
17
  }>;
18
- /** A content-role wrapper's children and plain div attributes. */
18
+ /** The wrapped content and plain div attributes. */
19
19
  export type SelectableProps = PropsWithChildren<HTMLAttributes<HTMLDivElement>>;
20
20
  /** Re-enters app-chrome policy inside a Selectable region. */
21
21
  export declare function Chrome({ children, ...props }: SelectableProps): import("react").JSX.Element;
22
- /** `textSelection(.enabled)`: restores text selection and system callouts for
23
- * user-authored content, which app chrome otherwise suppresses. */
22
+ /** Lets the user select and copy the text inside it. App chrome turns text selection off
23
+ * everywhere else, so wrap user-authored content such as notes or messages. */
24
24
  export declare function Selectable({ children, ...props }: SelectableProps): import("react").JSX.Element;
25
25
  export declare function SatinRoot({ background: legacyBackground, app: suppliedApp, offlinePresentation, onAppShellReady, children, className, glassDisplacement, onGlassError, style, ...props }: SatinRootProps): import("react").JSX.Element;
@@ -1,15 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { MediaPlayerRoot } from '../media/react.js';
3
3
  import { useDisplayCornerRadius } from '../safe-area/displayCorners.js';
4
- import { retryFailedInstallation } from '../app/earlyWorker.js';
5
4
  import { installStatusBand } from '../app/statusBand.js';
6
5
  import { windowControlsBackInset } from '../safe-area/windowChrome.js';
7
- import { automaticGlassFallbackAllowed } from '../glass/failurePolicy.js';
8
6
  import { installGlassErrorAlert } from '../glass/errorAlert.js';
9
7
  import { reportGlassError, subscribeGlassErrors } from '../glass/errors.js';
10
8
  import { installKeyboardAdapter } from '../keyboard/adapter.js';
11
- import { launchErrorLayer } from '../app/launchScreen.js';
12
- import { setLaunchScreen, setLaunchProgress, showAppliedUpdate, completeLaunchProgress, } from '../app/launchScreenRuntime.js';
9
+ import { setLaunchScreen, showLaunchFailure, prelaunchController, setLaunchProgress, showAppliedUpdate, completeLaunchProgress, } from '../app/launchScreenRuntime.js';
13
10
  import { settingsChromeTokens } from '../settings/tokens.js';
14
11
  import { installViewportPolicy } from '../app/viewport.js';
15
12
  import { prepareOfflineBundle, prepareLaunchContent } from '../app/launch.js';
@@ -22,7 +19,7 @@ import { OrientationGuard } from '../app/OrientationGuard.js';
22
19
  import { getBuiltApp, useAppBackground, registerDefinedAppShell } from '../app/runtime.js';
23
20
  import { defineSatinApp } from '../app/definition.js';
24
21
  import { ReachabilityProvider } from '../reachability/react.js';
25
- import { createPortal, flushSync } from 'react-dom';
22
+ import { flushSync } from 'react-dom';
26
23
  import { AdaptiveTabsContext } from '../layout/adaptiveTabsContext.js';
27
24
  import { createLayoutClassState, reduceLayoutClass } from '../layout/layoutClass.js';
28
25
  import { lazy, Suspense, useEffect, useCallback, useLayoutEffect, useMemo, useRef, useState, } from 'react';
@@ -133,8 +130,8 @@ function installDocumentPolicy(root, background, tint) {
133
130
  export function Chrome({ children, ...props }) {
134
131
  return (_jsx("div", { ...props, "data-satin-role": "chrome", children: children }));
135
132
  }
136
- /** `textSelection(.enabled)`: restores text selection and system callouts for
137
- * user-authored content, which app chrome otherwise suppresses. */
133
+ /** Lets the user select and copy the text inside it. App chrome turns text selection off
134
+ * everywhere else, so wrap user-authored content such as notes or messages. */
138
135
  export function Selectable({ children, ...props }) {
139
136
  return (_jsx("div", { ...props, "data-satin-role": "content", children: children }));
140
137
  }
@@ -154,19 +151,15 @@ export function SatinRoot({ background: legacyBackground, app: suppliedApp, offl
154
151
  throw new Error('SatinRoot style.background is owned by the app definition.');
155
152
  }
156
153
  const [launch, setLaunch] = useState(app ? 'preparing' : 'ready');
157
- const [preparationError, setPreparationError] = useState('Check your connection and try again.');
158
154
  const downloadActivity = useRef(0);
159
155
  const downloadedBytes = useRef(0);
160
- const [launchAttempt, setLaunchAttempt] = useState(0);
156
+ const launchAttempt = 0;
161
157
  const [glassReady, setGlassReady] = useState(false);
162
158
  const [bundlePrepared, setBundlePrepared] = useState(import.meta.env.DEV || !app);
163
- const [glassError, setGlassError] = useState(null);
164
159
  const [glassFailed, setGlassFailed] = useState(false);
165
160
  useLayoutEffect(() => {
166
161
  installGlassErrorAlert();
167
162
  return subscribeGlassErrors(error => {
168
- if (!automaticGlassFallbackAllowed())
169
- setGlassError(error);
170
163
  // A renderer failure owns its visible error alert, never the app's
171
164
  // content/launch state. In particular, loss during resume cannot blank it.
172
165
  setGlassFailed(true);
@@ -203,8 +196,9 @@ export function SatinRoot({ background: legacyBackground, app: suppliedApp, offl
203
196
  // appearance/context recovery must not restore the logo or hide its content.
204
197
  const presentationPending = Boolean(app) && launch !== 'ready';
205
198
  useLayoutEffect(() => {
206
- setLaunchScreen(launch === 'preparing');
207
- }, [launch]);
199
+ if (app && launch !== 'failed')
200
+ setLaunchScreen(launch === 'preparing');
201
+ }, [app, launch]);
208
202
  const [preparedAttempt, setPreparedAttempt] = useState(null);
209
203
  useLayoutEffect(() => {
210
204
  performance.mark('satin-first-react-commit');
@@ -245,6 +239,7 @@ export function SatinRoot({ background: legacyBackground, app: suppliedApp, offl
245
239
  return ready;
246
240
  }),
247
241
  prepareLaunchContent(rootRef.current, contentPreparation.signal),
242
+ prelaunchController().stylesReady(),
248
243
  ]);
249
244
  if (cancelled || !bundleReady)
250
245
  return;
@@ -275,7 +270,7 @@ export function SatinRoot({ background: legacyBackground, app: suppliedApp, offl
275
270
  catch (error) {
276
271
  if (!cancelled) {
277
272
  performance.mark('satin-launch-preparation-failed');
278
- setPreparationError(error instanceof Error ? error.message : String(error));
273
+ showLaunchFailure(error instanceof Error ? error.message : String(error));
279
274
  setLaunch('failed');
280
275
  console.error('Satin launch failed', error);
281
276
  }
@@ -314,7 +309,7 @@ export function SatinRoot({ background: legacyBackground, app: suppliedApp, offl
314
309
  return armPreparationBudget(() => {
315
310
  const message = 'App preparation stopped making progress. Please try again.';
316
311
  performance.mark('satin-launch-preparation-timeout');
317
- setPreparationError(message);
312
+ showLaunchFailure(message);
318
313
  setLaunch('failed');
319
314
  console.error('Satin launch preparation timed out after 30 seconds of visible idle time.');
320
315
  }, () => downloadActivity.current);
@@ -493,24 +488,5 @@ export function SatinRoot({ background: legacyBackground, app: suppliedApp, offl
493
488
  return;
494
489
  return startDevFidelityAssertions(initialHistoryLength.current);
495
490
  }, []);
496
- return (_jsx(RuntimeContext, { value: runtime, children: _jsxs(MediaPlayerRoot, { onActivityChange: onMediaActivityChange, children: [_jsx("div", { ...props, ref: rootRef, className: className, "data-satin-role": "chrome", "data-satin-root": "true", "data-satin-launch": launch, "data-satin-presentation": presentationPending ? 'preparing' : 'ready', inert: launch !== 'ready' || presentationPending, "data-satin-layout-horizontal": nextLayout.layoutClass.horizontal, "data-satin-layout-vertical": nextLayout.layoutClass.vertical, style: geometryStyles, children: _jsx(AdaptiveTabsContext, { value: tabs, children: _jsx("div", { "data-satin-status-band-source": "scene", children: _jsxs(GlassMaterialRoot, { displacement: glassDisplacement, prepared: bundlePrepared, onLaunchReady: setGlassReady, children: [DeveloperMenu && app && launch === 'ready' ? (_jsx(Suspense, { fallback: null, children: _jsx(DeveloperMenu, {}) })) : null, app ? (_jsx(OrientationGuard, { app: app, width: metrics.safeFrame.width, height: metrics.safeFrame.height, children: _jsx(ReachabilityProvider, { profile: app, offlinePresentation: offlinePresentation, children: children }) })) : (children)] }) }) }) }), launch === 'failed'
497
- ? createPortal(_jsxs("div", { "data-satin-role": "chrome", "data-satin-launch-error": "true", "data-satin-glass-error": glassError ? true : undefined, role: "alert", style: { zIndex: launchErrorLayer }, children: [!glassError ? (_jsx("img", { className: "satin-launch-error-icon", src: document.querySelector('#satin-launch-screen .satin-launch-icon img')?.src ??
498
- app?.launchScreen?.icon ??
499
- app?.icons[0]?.src, alt: "" })) : null, _jsxs("div", { className: "satin-launch-error-message", children: [_jsx("h1", { children: glassError ? 'Glass Renderer Failed' : 'Unable to Open App' }), glassError ? (_jsx("pre", { style: { whiteSpace: 'pre-wrap', overflowWrap: 'anywhere' }, children: `${glassError.code} · ${glassError.stage}\n${glassError.message}${glassError.reason ? `\n${glassError.reason}` : ''}` })) : (_jsx("p", { children: preparationError })), _jsx("button", { type: "button", onClick: async () => {
500
- if (glassError) {
501
- window.location.reload();
502
- return;
503
- }
504
- try {
505
- if (app)
506
- await retryFailedInstallation(app.scope);
507
- }
508
- catch (error) {
509
- setPreparationError(error instanceof Error ? error.message : String(error));
510
- return;
511
- }
512
- setLaunch('preparing');
513
- setLaunchAttempt(value => value + 1);
514
- }, children: "Try Again" })] })] }), document.body)
515
- : null] }) }));
491
+ return (_jsx(RuntimeContext, { value: runtime, children: _jsx(MediaPlayerRoot, { onActivityChange: onMediaActivityChange, children: _jsx("div", { ...props, ref: rootRef, className: className, "data-satin-role": "chrome", "data-satin-root": "true", "data-satin-launch": launch, "data-satin-presentation": presentationPending ? 'preparing' : 'ready', inert: launch !== 'ready' || presentationPending, "data-satin-layout-horizontal": nextLayout.layoutClass.horizontal, "data-satin-layout-vertical": nextLayout.layoutClass.vertical, style: geometryStyles, children: _jsx(AdaptiveTabsContext, { value: tabs, children: _jsx("div", { "data-satin-status-band-source": "scene", children: _jsxs(GlassMaterialRoot, { displacement: glassDisplacement, prepared: bundlePrepared, onLaunchReady: setGlassReady, children: [DeveloperMenu && app && launch === 'ready' ? (_jsx(Suspense, { fallback: null, children: _jsx(DeveloperMenu, {}) })) : null, app ? (_jsx(OrientationGuard, { app: app, width: metrics.safeFrame.width, height: metrics.safeFrame.height, children: _jsx(ReachabilityProvider, { profile: app, offlinePresentation: offlinePresentation, children: children }) })) : (children)] }) }) }) }) }) }));
516
492
  }
@@ -1,7 +1,7 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import { type RootOptions } from 'react-dom/client';
3
3
  /** Mount once from the app entry point, after resolving its initial screen.
4
- * The first commit runs in this task so installed WebKit cannot defer it behind
4
+ * After managed styles load, the first commit runs synchronously so WebKit cannot defer it behind
5
5
  * its launch presentation. Later updates retain React's normal scheduling.
6
6
  * Do not call from a component or an effect, or suspend the initial screen.
7
7
  */