@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.
- package/NOTICE +1 -1
- package/README.md +1 -2
- package/dist/acknowledgements/inventory.json +1 -1
- package/dist/actions/RowActions.d.ts +2 -2
- package/dist/actions/RowActions.js +91 -25
- package/dist/actions/fullSwipeContact.d.ts +73 -0
- package/dist/actions/fullSwipeContact.js +186 -0
- package/dist/actions/rowScrub.d.ts +7 -4
- package/dist/actions/rowScrub.js +39 -37
- package/dist/actions/types.d.ts +13 -7
- package/dist/app/InstallComponents.d.ts +4 -7
- package/dist/app/InstallComponents.js +7 -7
- package/dist/app/InstallationDiagnostics.d.ts +2 -1
- package/dist/app/InstallationDiagnostics.js +2 -1
- package/dist/app/appearance.d.ts +5 -3
- package/dist/app/appearance.js +5 -3
- package/dist/app/appearanceStore.d.ts +3 -2
- package/dist/app/buildInfo.d.ts +4 -4
- package/dist/app/buildInfo.js +2 -2
- package/dist/app/definition.d.ts +11 -3
- package/dist/app/definition.js +2 -0
- package/dist/app/head.d.ts +2 -1
- package/dist/app/head.js +13 -16
- package/dist/app/inlineCSP.d.ts +6 -0
- package/dist/app/inlineCSP.js +25 -0
- package/dist/app/install.d.ts +1 -0
- package/dist/app/install.js +5 -2
- package/dist/app/installCheck.js +32 -86
- package/dist/app/installContext.d.ts +10 -5
- package/dist/app/installContext.js +2 -0
- package/dist/app/installCustom.js +1 -0
- package/dist/app/installExperience.js +0 -60
- package/dist/app/installationFailure.d.ts +3 -2
- package/dist/app/installationFailure.js +1 -1
- package/dist/app/launchScreen.d.ts +6 -2
- package/dist/app/launchScreen.js +104 -1
- package/dist/app/launchScreenRuntime.d.ts +31 -4
- package/dist/app/launchScreenRuntime.js +150 -22
- package/dist/app/launchWatchdog.js +25 -65
- package/dist/app/platformScripts.js +11 -0
- package/dist/app/styles.d.ts +3 -0
- package/dist/app/styles.js +42 -0
- package/dist/app/viewportValue.d.ts +2 -1
- package/dist/app/vite.d.ts +4 -0
- package/dist/app/vite.js +22 -24
- package/dist/content/content.d.ts +35 -30
- package/dist/content/content.js +19 -16
- package/dist/content/layout.d.ts +10 -2
- package/dist/content/layout.js +4 -2
- package/dist/content/scaledMetric.d.ts +2 -1
- package/dist/content/scaledMetric.js +2 -1
- package/dist/controls/ColorPicker.d.ts +2 -4
- package/dist/controls/ColorPicker.js +2 -4
- package/dist/controls/DatePicker.d.ts +4 -4
- package/dist/controls/DatePicker.js +2 -2
- package/dist/controls/ProgressView.d.ts +4 -4
- package/dist/controls/ProgressView.js +1 -2
- package/dist/data/database.d.ts +9 -8
- package/dist/data/database.js +4 -4
- package/dist/docs/reference.md +982 -964
- package/dist/docs/tailwind.md +76 -0
- package/dist/docs/tokens.md +1 -1
- package/dist/gestures/GestureView.d.ts +3 -1
- package/dist/gestures/GestureView.js +2 -1
- package/dist/gestures/gesture.d.ts +22 -2
- package/dist/gestures/gesture.js +7 -2
- package/dist/glass/GlassEffect.d.ts +2 -1
- package/dist/glass/GlassEffect.js +2 -1
- package/dist/glass/GlassPresentation.d.ts +1 -0
- package/dist/glass/GlassPresentation.js +21 -4
- package/dist/glass/TabBar.js +23 -1
- package/dist/glass/errorAlert.js +2 -1
- package/dist/glass/errors.d.ts +3 -1
- package/dist/glass/fallback/runtime.d.ts +1 -0
- package/dist/glass/fallback/runtime.js +8 -1
- package/dist/glass/liquidContext.d.ts +2 -0
- package/dist/glass/menuPresenter.d.ts +2 -0
- package/dist/glass/regions.d.ts +2 -1
- package/dist/glass/renderSpecs.d.ts +1 -0
- package/dist/glass/renderSpecs.js +1 -0
- package/dist/glass/webgpu/controlRim.d.ts +29 -0
- package/dist/glass/webgpu/controlRim.js +68 -0
- package/dist/glass/webgpu/passes.d.ts +2 -2
- package/dist/glass/webgpu/production.d.ts +1 -0
- package/dist/glass/webgpu/production.js +27 -1
- package/dist/glass/webgpu/rasterUniforms.js +9 -0
- package/dist/glass/webgpu/shaders.d.ts +2 -2
- package/dist/glass/webgpu/shaders.js +5 -1
- package/dist/haptics/SensoryButton.d.ts +4 -4
- package/dist/haptics/SensoryButton.js +3 -3
- package/dist/image/Image.d.ts +6 -3
- package/dist/image/Image.js +4 -3
- package/dist/image/asset.d.ts +2 -1
- package/dist/keyboard/adapter.d.ts +3 -4
- package/dist/keyboard/geometry.d.ts +1 -1
- package/dist/list-form/ListForm.d.ts +8 -7
- package/dist/list-form/ListForm.js +2 -2
- package/dist/list-form/editing.d.ts +5 -6
- package/dist/list-form/editing.js +4 -5
- package/dist/list-form/offsets.d.ts +2 -2
- package/dist/list-form/offsets.js +2 -2
- package/dist/media/react.d.ts +2 -1
- package/dist/media/react.js +2 -1
- package/dist/media/types.d.ts +6 -3
- package/dist/motion/TransitionView.d.ts +4 -2
- package/dist/motion/TransitionView.js +3 -2
- package/dist/motion/animationValue.d.ts +1 -1
- package/dist/motion/matchedGeometry.d.ts +6 -5
- package/dist/motion/matchedGeometry.js +2 -1
- package/dist/motion/transition.d.ts +4 -1
- package/dist/motion/transition.js +2 -0
- package/dist/navigation/DetailList.d.ts +1 -1
- package/dist/navigation/DetailList.js +1 -1
- package/dist/navigation/Sidebar.d.ts +3 -1
- package/dist/navigation/Sidebar.js +1 -1
- package/dist/navigation/SidebarSymbol.d.ts +2 -1
- package/dist/navigation/SidebarSymbol.js +2 -1
- package/dist/navigation/navigationContext.d.ts +2 -1
- package/dist/navigation/navigationContext.js +2 -1
- package/dist/navigation/splitContext.d.ts +2 -1
- package/dist/navigation/splitContext.js +2 -1
- package/dist/navigation/toolbarMinimization.d.ts +4 -3
- package/dist/navigation/types.d.ts +7 -5
- package/dist/presentation/Presentation.d.ts +8 -7
- package/dist/presentation/Presentation.js +3 -2
- package/dist/presentation/model.d.ts +2 -1
- package/dist/press/Pressable.d.ts +5 -1
- package/dist/press/Pressable.js +2 -0
- package/dist/press/stateMachine.d.ts +1 -1
- package/dist/public/Label.d.ts +2 -1
- package/dist/public/Label.js +2 -1
- package/dist/public/Screen.d.ts +4 -6
- package/dist/public/actions.d.ts +2 -1
- package/dist/public/actions.js +2 -1
- package/dist/public/buttonBorderShape.d.ts +2 -1
- package/dist/public/colors.d.ts +7 -4
- package/dist/public/colors.js +3 -2
- package/dist/public/controlStyle.d.ts +17 -14
- package/dist/public/controls.d.ts +27 -26
- package/dist/public/controls.js +20 -19
- package/dist/public/deviceActions.d.ts +6 -4
- package/dist/public/deviceActions.js +4 -2
- package/dist/public/environment.d.ts +16 -13
- package/dist/public/environment.js +11 -9
- package/dist/public/filePickers.d.ts +6 -4
- package/dist/public/filePickers.js +3 -2
- package/dist/public/glass.d.ts +6 -3
- package/dist/public/glass.js +2 -1
- package/dist/public/glassValue.d.ts +3 -4
- package/dist/public/glassValue.js +3 -4
- package/dist/public/keyboard.d.ts +4 -1
- package/dist/public/keyboard.js +2 -1
- package/dist/public/navigationTransition.d.ts +5 -5
- package/dist/public/navigationTransition.js +2 -2
- package/dist/public/presentation.d.ts +8 -7
- package/dist/public/presentation.js +5 -5
- package/dist/public/runtime.d.ts +9 -8
- package/dist/public/runtime.js +7 -7
- package/dist/public/scroll.d.ts +6 -3
- package/dist/public/scroll.js +3 -1
- package/dist/public/structure.d.ts +2 -2
- package/dist/public/toolbar.d.ts +15 -11
- package/dist/public/toolbar.js +12 -7
- package/dist/reachability/model.d.ts +4 -3
- package/dist/reachability/react.d.ts +4 -1
- package/dist/reachability/react.js +2 -1
- package/dist/root/SatinRoot.d.ts +3 -3
- package/dist/root/SatinRoot.js +12 -36
- package/dist/root/mountSatin.d.ts +1 -1
- package/dist/root/mountSatin.js +26 -35
- package/dist/root/runtimeContext.d.ts +2 -1
- package/dist/root/runtimeContext.js +2 -1
- package/dist/safe-area/Overlay.d.ts +3 -2
- package/dist/safe-area/Overlay.js +2 -1
- package/dist/safe-area/SafeAreaInset.d.ts +11 -7
- package/dist/safe-area/SafeAreaInset.js +7 -6
- package/dist/safe-area/context.d.ts +3 -3
- package/dist/safe-area/context.js +1 -1
- package/dist/safe-area/displayCorners.d.ts +4 -2
- package/dist/safe-area/displayCorners.js +4 -2
- package/dist/safe-area/modifiers.d.ts +14 -10
- package/dist/safe-area/modifiers.js +8 -4
- package/dist/scroll/ScrollSurface.js +5 -1
- package/dist/scroll/ScrollTarget.d.ts +1 -1
- package/dist/scroll/ScrollTarget.js +1 -1
- package/dist/scroll/edgePolicy.d.ts +2 -2
- package/dist/scroll/position.d.ts +5 -3
- package/dist/scroll/types.d.ts +1 -1
- package/dist/search/PadSearchDrawer.d.ts +7 -0
- package/dist/search/PadSearchDrawer.js +8 -0
- package/dist/search/PadSearchPresentationContext.d.ts +6 -0
- package/dist/search/PadSearchPresentationContext.js +4 -0
- package/dist/search/SearchDrawer.d.ts +1 -1
- package/dist/search/SearchDrawer.js +6 -1
- package/dist/search/SearchSuggestionsPopover.d.ts +6 -0
- package/dist/search/SearchSuggestionsPopover.js +42 -0
- package/dist/search/SearchToolbarField.d.ts +2 -1
- package/dist/search/SearchToolbarField.js +28 -7
- package/dist/search/padSearchBarMotion.d.ts +69 -0
- package/dist/search/padSearchBarMotion.js +73 -0
- package/dist/search/padSearchFieldSamples.json +491 -0
- package/dist/search/searchPlacement.d.ts +3 -0
- package/dist/search/searchPlacement.js +7 -0
- package/dist/search/searchable.d.ts +14 -12
- package/dist/search/usePadSearchFieldMotion.d.ts +4 -0
- package/dist/search/usePadSearchFieldMotion.js +100 -0
- package/dist/search/useSearchPresentation.d.ts +2 -1
- package/dist/search/useSearchPresentation.js +23 -5
- package/dist/server.d.ts +4 -4
- package/dist/server.js +4 -4
- package/dist/shapes/corners.d.ts +3 -3
- package/dist/shapes/corners.js +1 -2
- package/dist/styles.css +8289 -8244
- package/dist/sw/vite.d.ts +4 -0
- package/dist/sw/vite.js +2 -0
- package/dist/symbols/Symbol.d.ts +7 -5
- package/dist/symbols/Symbol.js +5 -3
- package/dist/symbols/catalogue.d.ts +1 -1
- package/dist/symbols/types.d.ts +6 -4
- package/dist/tabs/TabSection.d.ts +3 -2
- package/dist/tabs/TabSection.js +2 -1
- package/dist/tabs/TabView.js +54 -51
- package/dist/tasks/useTask.d.ts +5 -4
- package/dist/tasks/useTask.js +4 -3
- package/dist/testing.d.ts +3 -2
- package/dist/testing.js +3 -2
- package/dist/text-input/focusChain.d.ts +4 -3
- package/dist/text-input/focusChain.js +3 -2
- package/dist/text-input/kinds.d.ts +1 -1
- package/dist/web/WebView.d.ts +10 -3
- package/dist/web/WebView.js +3 -2
- package/dist/web/authentication.d.ts +12 -1
- package/dist/web/authentication.js +2 -1
- package/dist/web/openURL.d.ts +10 -4
- package/dist/web/openURL.js +4 -2
- package/dist/web/useWebAuthentication.d.ts +2 -1
- package/dist/web/useWebAuthentication.js +2 -1
- package/dist/zoom/Zoomable.d.ts +3 -3
- package/dist/zoom/Zoomable.js +2 -2
- 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
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
35
|
-
*
|
|
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
|
-
*
|
|
17
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
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
|
-
/**
|
|
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
|
}
|
package/dist/public/runtime.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
87
|
-
*
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
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;
|
package/dist/public/runtime.js
CHANGED
|
@@ -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
|
-
/**
|
|
125
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
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 });
|
package/dist/public/scroll.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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>>;
|
package/dist/public/scroll.js
CHANGED
|
@@ -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
|
|
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
|
-
/**
|
|
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
|
-
/** `
|
|
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;
|
package/dist/public/toolbar.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/** `
|
|
28
|
-
*
|
|
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
|
-
/**
|
|
33
|
-
* capsule; a spacer between them splits it. Place it directly in `toolbar`, next to the
|
|
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
|
-
/**
|
|
36
|
-
*
|
|
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;
|
package/dist/public/toolbar.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
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
|
-
/**
|
|
58
|
-
* capsule; a spacer between them splits it. Place it directly in `toolbar`, next to the
|
|
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
|
-
/**
|
|
70
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
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
|
|
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 {
|
package/dist/root/SatinRoot.d.ts
CHANGED
|
@@ -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
|
-
/**
|
|
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
|
-
/**
|
|
23
|
-
* user-authored content
|
|
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;
|
package/dist/root/SatinRoot.js
CHANGED
|
@@ -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 {
|
|
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 {
|
|
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
|
-
/**
|
|
137
|
-
* user-authored content
|
|
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
|
|
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
|
-
|
|
207
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
*
|
|
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
|
*/
|