@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
package/dist/root/mountSatin.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { flushSync } from 'react-dom';
|
|
2
2
|
import { createRoot } from 'react-dom/client';
|
|
3
|
-
import {
|
|
3
|
+
import { prelaunchController, showLaunchFailure } from '../app/launchScreenRuntime.js';
|
|
4
4
|
/** Mount once from the app entry point, after resolving its initial screen.
|
|
5
|
-
*
|
|
5
|
+
* After managed styles load, the first commit runs synchronously so WebKit cannot defer it behind
|
|
6
6
|
* its launch presentation. Later updates retain React's normal scheduling.
|
|
7
7
|
* Do not call from a component or an effect, or suspend the initial screen.
|
|
8
8
|
*/
|
|
@@ -17,9 +17,29 @@ export function mountSatin(container, content, options) {
|
|
|
17
17
|
reportError(error);
|
|
18
18
|
},
|
|
19
19
|
});
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
let disposed = false;
|
|
21
|
+
const unmount = root.unmount.bind(root);
|
|
22
|
+
root.unmount = () => {
|
|
23
|
+
disposed = true;
|
|
24
|
+
unmount();
|
|
25
|
+
};
|
|
26
|
+
const commit = () => {
|
|
27
|
+
if (disposed)
|
|
28
|
+
return;
|
|
29
|
+
performance.mark('satin-mount-start');
|
|
30
|
+
flushSync(() => root.render(content));
|
|
31
|
+
performance.mark('satin-mount-committed');
|
|
32
|
+
};
|
|
33
|
+
// A glass renderer cannot measure or present an unstyled React tree. The
|
|
34
|
+
// independent head environment owns this wait, including any load failure.
|
|
35
|
+
if (document.querySelector('link[data-satin-style]')) {
|
|
36
|
+
void prelaunchController().stylesReady().then(commit, error => {
|
|
37
|
+
if (!disposed)
|
|
38
|
+
showLaunchFailure(error instanceof Error ? error.message : String(error));
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
else
|
|
42
|
+
commit();
|
|
23
43
|
return root;
|
|
24
44
|
}
|
|
25
45
|
/** An uncaught render or effect error unmounts the whole app. Without this the launch cover
|
|
@@ -27,34 +47,5 @@ export function mountSatin(container, content, options) {
|
|
|
27
47
|
* above the launch cover, with the same presentation as a failed launch. */
|
|
28
48
|
export function showAppFailure(error) {
|
|
29
49
|
performance.mark('satin-app-failed');
|
|
30
|
-
|
|
31
|
-
const panel = document.createElement('div');
|
|
32
|
-
panel.dataset.satinRole = 'chrome';
|
|
33
|
-
panel.dataset.satinLaunchError = 'true';
|
|
34
|
-
panel.dataset.satinAppFailure = 'true';
|
|
35
|
-
panel.setAttribute('role', 'alert');
|
|
36
|
-
panel.style.zIndex = String(launchErrorLayer);
|
|
37
|
-
const message = document.createElement('div');
|
|
38
|
-
message.className = 'satin-launch-error-message';
|
|
39
|
-
const title = document.createElement('h1');
|
|
40
|
-
title.textContent = 'App Failed to Start';
|
|
41
|
-
const detail = document.createElement('pre');
|
|
42
|
-
detail.style.whiteSpace = 'pre-wrap';
|
|
43
|
-
detail.style.overflowWrap = 'anywhere';
|
|
44
|
-
detail.textContent = error instanceof Error ? error.message : String(error);
|
|
45
|
-
const reload = document.createElement('button');
|
|
46
|
-
reload.type = 'button';
|
|
47
|
-
reload.textContent = 'Reload';
|
|
48
|
-
reload.addEventListener('click', () => window.location.reload());
|
|
49
|
-
message.append(title, detail, reload);
|
|
50
|
-
const icon = document.querySelector('#satin-launch-screen .satin-launch-icon img');
|
|
51
|
-
if (icon?.src) {
|
|
52
|
-
const image = document.createElement('img');
|
|
53
|
-
image.className = 'satin-launch-error-icon';
|
|
54
|
-
image.src = icon.src;
|
|
55
|
-
image.alt = '';
|
|
56
|
-
panel.append(image);
|
|
57
|
-
}
|
|
58
|
-
panel.append(message);
|
|
59
|
-
document.body.append(panel);
|
|
50
|
+
showLaunchFailure(error instanceof Error ? error.message : String(error), 'App Failed to Start');
|
|
60
51
|
}
|
|
@@ -22,5 +22,6 @@ export declare function useSatinLayoutRuntime(): Omit<SatinRuntime, 'metrics'> &
|
|
|
22
22
|
export declare function useSatinRuntime(): SatinRuntime;
|
|
23
23
|
/** Classes follow the layout viewport; keyboard occlusion and zoom do not select panes. */
|
|
24
24
|
export declare function useLayoutClass(): LayoutClass;
|
|
25
|
-
/**
|
|
25
|
+
/** Tells Satin the app has unsaved work while `unsaved` is true, so a pending app update waits
|
|
26
|
+
* instead of reloading over it. Edits in text fields are detected without this hook. */
|
|
26
27
|
export declare function useUnsavedChanges(unsaved: boolean): void;
|
|
@@ -19,7 +19,8 @@ export function useSatinRuntime() {
|
|
|
19
19
|
export function useLayoutClass() {
|
|
20
20
|
return useSatinLayoutRuntime().layoutClass;
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
22
|
+
/** Tells Satin the app has unsaved work while `unsaved` is true, so a pending app update waits
|
|
23
|
+
* instead of reloading over it. Edits in text fields are detected without this hook. */
|
|
23
24
|
export function useUnsavedChanges(unsaved) {
|
|
24
25
|
const { registerUnsavedChanges } = useSatinLayoutRuntime();
|
|
25
26
|
useEffect(() => {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
2
|
import type { ContentAlignment } from '../content/content.js';
|
|
3
|
-
/** `
|
|
3
|
+
/** The layered `content` and its alignment. The children set the frame. */
|
|
4
4
|
export type OverlayProps = Omit<HTMLAttributes<HTMLDivElement>, 'content'> & Readonly<{
|
|
5
5
|
alignment?: ContentAlignment;
|
|
6
6
|
content: ReactNode;
|
|
7
7
|
}>;
|
|
8
|
-
/**
|
|
8
|
+
/** Layers `content` over its children without changing their frame. Inside a `SafeAreaInset`, the
|
|
9
|
+
* overlay keeps to the reduced safe area and moves with the keyboard, like the composer. */
|
|
9
10
|
export declare function Overlay({ alignment, content, children, ...props }: OverlayProps): import("react").JSX.Element;
|
|
@@ -4,7 +4,8 @@ import { BottomInsetContext } from './SafeAreaInset.js';
|
|
|
4
4
|
// Overlay content is already inside the parent's reduced safe area. Its descendants consume
|
|
5
5
|
// only their own local insets and inherit the parent's keyboard transform.
|
|
6
6
|
const CONTENT_SCOPE = { consumed: true };
|
|
7
|
-
/**
|
|
7
|
+
/** Layers `content` over its children without changing their frame. Inside a `SafeAreaInset`, the
|
|
8
|
+
* overlay keeps to the reduced safe area and moves with the keyboard, like the composer. */
|
|
8
9
|
export function Overlay({ alignment = 'center', content, children, ...props }) {
|
|
9
10
|
const { geometry, consumed } = useContext(BottomInsetContext);
|
|
10
11
|
const layer = useRef(null);
|
|
@@ -5,21 +5,25 @@ export declare const BottomInsetContext: import("react").Context<{
|
|
|
5
5
|
consumed: boolean;
|
|
6
6
|
geometry?: ReturnType<typeof createBottomInsetGeometry>;
|
|
7
7
|
}>;
|
|
8
|
-
/** `
|
|
8
|
+
/** The edge a `SafeAreaInset` accessory sits on. `leading` and `trailing` follow the layout
|
|
9
|
+
* direction. */
|
|
9
10
|
export type SafeAreaInsetEdge = 'top' | 'bottom' | 'leading' | 'trailing';
|
|
10
11
|
/** The edge, the accessory (`content`) and its spacing; `children` is the content it insets. */
|
|
11
12
|
export type SafeAreaInsetProps = Omit<HTMLAttributes<HTMLDivElement>, 'content'> & Readonly<{
|
|
12
13
|
edge: SafeAreaInsetEdge;
|
|
13
14
|
content: ReactNode;
|
|
15
|
+
/** Room between the content and the accessory, in points. Defaults to the system spacing,
|
|
16
|
+
* 8 pt. */
|
|
14
17
|
spacing?: number;
|
|
15
18
|
}>;
|
|
16
19
|
/**
|
|
17
|
-
*
|
|
18
|
-
* area on its edge; a scroll view inside still
|
|
20
|
+
* Pins an accessory, such as a composer or a filter bar, to one edge of its content. The
|
|
21
|
+
* accessory takes room from the content's safe area on its edge; a scroll view inside still
|
|
22
|
+
* spans the whole frame and scrolls under it.
|
|
19
23
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* `--satin-inset-accessory-height
|
|
23
|
-
*
|
|
24
|
+
* At the bottom, content scrolls under the accessory and its last item stays clear of it. When
|
|
25
|
+
* the accessory resizes, the scroll inset changes in the same frame (through
|
|
26
|
+
* `--satin-inset-accessory-height`), so a composer that grows by a line keeps the newest message
|
|
27
|
+
* in view.
|
|
24
28
|
*/
|
|
25
29
|
export declare function SafeAreaInset({ edge, content, spacing, children, ...props }: SafeAreaInsetProps): import("react").JSX.Element;
|
|
@@ -10,13 +10,14 @@ export const BottomInsetContext = createContext({ consumed: false });
|
|
|
10
10
|
const SYSTEM_INSET_SPACING_PX = 8;
|
|
11
11
|
const ACCESSORY_INSET_SCOPE = { consumed: true };
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
* area on its edge; a scroll view inside still
|
|
13
|
+
* Pins an accessory, such as a composer or a filter bar, to one edge of its content. The
|
|
14
|
+
* accessory takes room from the content's safe area on its edge; a scroll view inside still
|
|
15
|
+
* spans the whole frame and scrolls under it.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* `--satin-inset-accessory-height
|
|
19
|
-
*
|
|
17
|
+
* At the bottom, content scrolls under the accessory and its last item stays clear of it. When
|
|
18
|
+
* the accessory resizes, the scroll inset changes in the same frame (through
|
|
19
|
+
* `--satin-inset-accessory-height`), so a composer that grows by a line keeps the newest message
|
|
20
|
+
* in view.
|
|
20
21
|
*/
|
|
21
22
|
export function SafeAreaInset({ edge, content, spacing = SYSTEM_INSET_SPACING_PX, children, ...props }) {
|
|
22
23
|
if (edge !== 'bottom')
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** A logical edge. `leading` and `trailing` follow the layout direction. */
|
|
2
2
|
export type Edge = 'top' | 'bottom' | 'leading' | 'trailing';
|
|
3
|
-
/**
|
|
3
|
+
/** Optional lengths per logical edge, in points. */
|
|
4
4
|
export type EdgeLengths = Readonly<Partial<Record<Edge, number>>>;
|
|
5
5
|
export type Lengths = Readonly<Record<Edge, number>>;
|
|
6
6
|
export declare const NO_LENGTHS: Lengths;
|
|
7
7
|
/** Safe-area padding the enclosing modifiers add to the next scroll view's content, per edge. */
|
|
8
8
|
export declare const SafeAreaPaddingContext: import("react").Context<Readonly<Record<Edge, number>>>;
|
|
9
|
-
/**
|
|
9
|
+
/** The content margins in effect for every scroll view below, per edge. */
|
|
10
10
|
export declare const ContentMarginsContext: import("react").Context<Readonly<Partial<Record<Edge, number>>>>;
|
|
11
11
|
/** The safe-area regions and edges an enclosing `IgnoresSafeArea` gives up. */
|
|
12
12
|
export declare const IgnoresSafeAreaContext: import("react").Context<{
|
|
@@ -2,7 +2,7 @@ import { createContext } from 'react';
|
|
|
2
2
|
export const NO_LENGTHS = { top: 0, bottom: 0, leading: 0, trailing: 0 };
|
|
3
3
|
/** Safe-area padding the enclosing modifiers add to the next scroll view's content, per edge. */
|
|
4
4
|
export const SafeAreaPaddingContext = createContext(NO_LENGTHS);
|
|
5
|
-
/**
|
|
5
|
+
/** The content margins in effect for every scroll view below, per edge. */
|
|
6
6
|
export const ContentMarginsContext = createContext({});
|
|
7
7
|
/** The safe-area regions and edges an enclosing `IgnoresSafeArea` gives up. */
|
|
8
8
|
export const IgnoresSafeAreaContext = createContext({ container: new Set(), keyboard: false });
|
|
@@ -15,7 +15,9 @@ export type DisplayCornerMetrics = Readonly<{
|
|
|
15
15
|
export declare function resolveDisplayCornerMetrics(display: DisplayGeometry): DisplayCornerMetrics;
|
|
16
16
|
/** Framework token for the screen containing this app. Display Zoom and unknown models fall back to zero. */
|
|
17
17
|
export declare function readDisplayCornerMetrics(): DisplayCornerMetrics;
|
|
18
|
-
/**
|
|
18
|
+
/** The corner radius of the device screen in points, or 0 when the model is unknown. It updates
|
|
19
|
+
* after rotation, window moves and pixel-ratio changes that fire a resize. */
|
|
19
20
|
export declare function useDisplayCornerRadius(): number;
|
|
20
|
-
/**
|
|
21
|
+
/** The corner radius for a shape inset evenly inside a rounded container, so the two corners stay
|
|
22
|
+
* concentric. The result never goes below 0; a negative or non-finite argument throws. */
|
|
21
23
|
export declare function concentricRadius(containerRadius: number, inset: number): number;
|
|
@@ -44,7 +44,8 @@ export function readDisplayCornerMetrics() {
|
|
|
44
44
|
scale: window.devicePixelRatio,
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
|
-
/**
|
|
47
|
+
/** The corner radius of the device screen in points, or 0 when the model is unknown. It updates
|
|
48
|
+
* after rotation, window moves and pixel-ratio changes that fire a resize. */
|
|
48
49
|
export function useDisplayCornerRadius() {
|
|
49
50
|
const [radius, setRadius] = useState(() => readDisplayCornerMetrics().radius);
|
|
50
51
|
useLayoutEffect(() => {
|
|
@@ -59,7 +60,8 @@ export function useDisplayCornerRadius() {
|
|
|
59
60
|
}, []);
|
|
60
61
|
return radius;
|
|
61
62
|
}
|
|
62
|
-
/**
|
|
63
|
+
/** The corner radius for a shape inset evenly inside a rounded container, so the two corners stay
|
|
64
|
+
* concentric. The result never goes below 0; a negative or non-finite argument throws. */
|
|
63
65
|
export function concentricRadius(containerRadius, inset) {
|
|
64
66
|
if (!Number.isFinite(containerRadius) ||
|
|
65
67
|
containerRadius < 0 ||
|
|
@@ -4,22 +4,23 @@ import { type HTMLAttributes, type ReactNode } from 'react';
|
|
|
4
4
|
export type { Edge, EdgeLengths } from './context.js';
|
|
5
5
|
/** A logical edge, an axis pair or all edges. */
|
|
6
6
|
export type EdgeSetMember = Edge | 'horizontal' | 'vertical' | 'all';
|
|
7
|
-
/**
|
|
7
|
+
/** One edge group or a list of them. */
|
|
8
8
|
export type EdgeSet = EdgeSetMember | readonly EdgeSetMember[];
|
|
9
|
-
/** The
|
|
9
|
+
/** The children and plain div attributes every layout wrapper takes. */
|
|
10
10
|
export type LayoutModifierProps = Omit<HTMLAttributes<HTMLDivElement>, 'children'> & Readonly<{
|
|
11
11
|
children?: ReactNode;
|
|
12
12
|
}>;
|
|
13
13
|
/** Which edges to pad, and by how much. */
|
|
14
14
|
export type SafeAreaPaddingProps = LayoutModifierProps & Readonly<{
|
|
15
|
-
/** Edges to pad. Defaults to all edges
|
|
15
|
+
/** Edges to pad. Defaults to all edges. */
|
|
16
16
|
edges?: EdgeSet;
|
|
17
17
|
/** Points. Defaults to the system padding, 16 pt. */
|
|
18
18
|
length?: number;
|
|
19
|
-
/**
|
|
19
|
+
/** A length per edge. Overrides `edges` and `length`. */
|
|
20
20
|
insets?: EdgeLengths;
|
|
21
21
|
}>;
|
|
22
|
-
/**
|
|
22
|
+
/** Grows the safe area of the content inside it. Scroll views keep their frame and inset their
|
|
23
|
+
* content; other content is padded. Nested padding adds up. */
|
|
23
24
|
export declare function SafeAreaPadding({ edges, length, insets, children, ...props }: SafeAreaPaddingProps): import("react").JSX.Element;
|
|
24
25
|
/** Which edges get a margin, how much, and whether it applies to content or indicators. */
|
|
25
26
|
export type ContentMarginsProps = LayoutModifierProps & Readonly<{
|
|
@@ -27,26 +28,29 @@ export type ContentMarginsProps = LayoutModifierProps & Readonly<{
|
|
|
27
28
|
/** Points. */
|
|
28
29
|
length: number;
|
|
29
30
|
/**
|
|
30
|
-
*
|
|
31
|
+
* What the margin applies to. `scrollContent` (and `automatic`) margins the content;
|
|
31
32
|
* `scrollIndicators` only moves the indicator, which Satin draws in the screen frame and does
|
|
32
33
|
* not inset, so it has no effect yet.
|
|
33
34
|
*/
|
|
34
35
|
placement?: 'automatic' | 'scrollContent' | 'scrollIndicators';
|
|
35
36
|
}>;
|
|
36
|
-
/** Sets margins for
|
|
37
|
+
/** Sets content margins for every scroll view inside it. A `List` takes a horizontal margin as its
|
|
38
|
+
* layout margin. The innermost value for each edge wins. */
|
|
37
39
|
export declare function ContentMargins({ edges, length, placement, children, ...props }: ContentMarginsProps): import("react").JSX.Element;
|
|
38
40
|
/** A `SafeAreaInset` limited to the top or bottom edge, with no spacing. */
|
|
39
41
|
export type SafeAreaBarProps = Omit<SafeAreaInsetProps, 'edge' | 'spacing'> & Readonly<{
|
|
40
42
|
edge: 'top' | 'bottom';
|
|
41
43
|
}>;
|
|
42
|
-
/**
|
|
44
|
+
/** A bar on the top or bottom edge that content scrolls under. It is a `SafeAreaInset` with no
|
|
45
|
+
* spacing and its own scroll-edge blur. */
|
|
43
46
|
export declare function SafeAreaBar({ edge, ...props }: SafeAreaBarProps): import("react").JSX.Element;
|
|
44
47
|
/** Which safe-area regions and edges the content ignores. */
|
|
45
48
|
export type IgnoresSafeAreaProps = LayoutModifierProps & Readonly<{
|
|
46
|
-
/** `
|
|
49
|
+
/** `container` (the bars and screen edges), `keyboard`, or `all`, the default. */
|
|
47
50
|
regions?: 'all' | 'container' | 'keyboard';
|
|
48
51
|
/** Defaults to all edges. */
|
|
49
52
|
edges?: EdgeSet;
|
|
50
53
|
}>;
|
|
51
|
-
/**
|
|
54
|
+
/** Lets content extend through the safe area on the chosen edges, for full-bleed backgrounds and
|
|
55
|
+
* media. The container edges and keyboard avoidance can be ignored separately. */
|
|
52
56
|
export declare function IgnoresSafeArea({ regions, edges, children, ...props }: IgnoresSafeAreaProps): import("react").JSX.Element;
|
|
@@ -29,7 +29,8 @@ function lengthsOf(edges, length, insets) {
|
|
|
29
29
|
trailing: set.has('trailing') ? amount : 0,
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
32
|
+
/** Grows the safe area of the content inside it. Scroll views keep their frame and inset their
|
|
33
|
+
* content; other content is padded. Nested padding adds up. */
|
|
33
34
|
export function SafeAreaPadding({ edges, length, insets, children, ...props }) {
|
|
34
35
|
const parent = useContext(SafeAreaPaddingContext);
|
|
35
36
|
const own = lengthsOf(edges, length, insets);
|
|
@@ -47,7 +48,8 @@ export function SafeAreaPadding({ edges, length, insets, children, ...props }) {
|
|
|
47
48
|
['--satin-padding-trailing']: `${own.trailing}px`,
|
|
48
49
|
}, "data-satin-safe-area-padding": "true", children: _jsx(SafeAreaPaddingContext, { value: total, children: children }) }));
|
|
49
50
|
}
|
|
50
|
-
/** Sets margins for
|
|
51
|
+
/** Sets content margins for every scroll view inside it. A `List` takes a horizontal margin as its
|
|
52
|
+
* layout margin. The innermost value for each edge wins. */
|
|
51
53
|
export function ContentMargins({ edges = 'all', length, placement = 'automatic', children, ...props }) {
|
|
52
54
|
const parent = useContext(ContentMarginsContext);
|
|
53
55
|
const set = edgesOf(edges);
|
|
@@ -57,11 +59,13 @@ export function ContentMargins({ edges = 'all', length, placement = 'automatic',
|
|
|
57
59
|
margins[edge] = length;
|
|
58
60
|
return (_jsx("div", { ...props, "data-satin-content-margins": "true", children: _jsx(ContentMarginsContext, { value: margins, children: children }) }));
|
|
59
61
|
}
|
|
60
|
-
/**
|
|
62
|
+
/** A bar on the top or bottom edge that content scrolls under. It is a `SafeAreaInset` with no
|
|
63
|
+
* spacing and its own scroll-edge blur. */
|
|
61
64
|
export function SafeAreaBar({ edge, ...props }) {
|
|
62
65
|
return _jsx(SafeAreaInset, { ...props, edge: edge, spacing: 0, "data-satin-safe-area-bar": edge });
|
|
63
66
|
}
|
|
64
|
-
/**
|
|
67
|
+
/** Lets content extend through the safe area on the chosen edges, for full-bleed backgrounds and
|
|
68
|
+
* media. The container edges and keyboard avoidance can be ignored separately. */
|
|
65
69
|
export function IgnoresSafeArea({ regions = 'all', edges = 'all', children, ...props }) {
|
|
66
70
|
const parent = useContext(IgnoresSafeAreaContext);
|
|
67
71
|
const set = edgesOf(edges);
|
|
@@ -15,9 +15,10 @@ import { TabActivityContext, TabRegistrationContext } from '../tabs/context.js';
|
|
|
15
15
|
import { SearchDrawer } from '../search/SearchDrawer.js';
|
|
16
16
|
import { ContentAdmission } from '../image/ContentAdmission.js';
|
|
17
17
|
import { SearchToolbarField } from '../search/SearchToolbarField.js';
|
|
18
|
+
import { readDeviceIdiom } from '../layout/deviceIdiom.js';
|
|
18
19
|
import { resolveSearchPlacement } from '../search/searchPlacement.js';
|
|
19
20
|
import { Children, createContext, forwardRef, isValidElement, useCallback, useContext, useImperativeHandle, useLayoutEffect, useRef, useState, useSyncExternalStore, } from 'react';
|
|
20
|
-
import { ScreenContext, SystemScrollRegistryContext, useScreenScrollRegistry, } from '../navigation/navigationContext.js';
|
|
21
|
+
import { NavigationPaneContext, ScreenContext, SystemScrollRegistryContext, useScreenScrollRegistry, } from '../navigation/navigationContext.js';
|
|
21
22
|
import { readScrollOffset } from './registry.js';
|
|
22
23
|
import { installScrollPressOwnership } from './pressOwnership.js';
|
|
23
24
|
/** Inside another scroll surface: never the screen's primary scroll view. */
|
|
@@ -151,8 +152,11 @@ export const ScrollSurface = forwardRef(function ScrollSurface({ axis = 'vertica
|
|
|
151
152
|
? (listNavigation?.searchable ?? chrome.searchable)
|
|
152
153
|
: undefined;
|
|
153
154
|
const tabbed = useContext(TabRegistrationContext) !== null;
|
|
155
|
+
const searchPane = useContext(NavigationPaneContext);
|
|
154
156
|
const searchPlacement = searchable
|
|
155
157
|
? resolveSearchPlacement(searchable.placement, {
|
|
158
|
+
idiom: readDeviceIdiom(),
|
|
159
|
+
pane: searchPane,
|
|
156
160
|
compact: chrome.horizontalSizeClass === 'compact',
|
|
157
161
|
bottomBarItems: chrome.hasBottomBar === true,
|
|
158
162
|
searchToolbarItem: chrome.searchToolbarItem !== undefined,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type HTMLAttributes } from 'react';
|
|
2
2
|
export declare const ScrollTargetContext: import("react").Context<((id: string, element: HTMLDivElement | null) => void) | null>;
|
|
3
|
-
/**
|
|
3
|
+
/** Marks content a vertical `ScrollView` can scroll to by `id`. */
|
|
4
4
|
export declare function ScrollTarget({ id, ...props }: HTMLAttributes<HTMLDivElement> & {
|
|
5
5
|
id: string;
|
|
6
6
|
}): import("react").JSX.Element;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useCallback, useContext } from 'react';
|
|
3
3
|
export const ScrollTargetContext = createContext(null);
|
|
4
|
-
/**
|
|
4
|
+
/** Marks content a vertical `ScrollView` can scroll to by `id`. */
|
|
5
5
|
export function ScrollTarget({ id, ...props }) {
|
|
6
6
|
const register = useContext(ScrollTargetContext);
|
|
7
7
|
if (!register)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** A logical edge of a scroll view. */
|
|
2
2
|
export type ScrollEdge = 'top' | 'bottom' | 'leading' | 'trailing';
|
|
3
3
|
/** One or more scroll edges, or all edges. */
|
|
4
4
|
export type ScrollEdgeSelection = ScrollEdge | 'all' | readonly ScrollEdge[];
|
|
5
|
-
/**
|
|
5
|
+
/** The material under bars at a scroll view's edge: `soft`, `hard` or `automatic`. */
|
|
6
6
|
export type ScrollEdgeEffectStyle = 'soft' | 'hard' | 'automatic';
|
|
7
7
|
/** Whether to hide scroll edge material, optionally for specific edges. */
|
|
8
8
|
export type ScrollEdgeEffectHidden = boolean | {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Where a scroll target lines up in the viewport: `top`, `center` or `bottom`. */
|
|
2
2
|
export type ScrollAnchor = 'top' | 'center' | 'bottom';
|
|
3
3
|
/** Vertical scroll geometry: the current viewport and content offset in points. */
|
|
4
4
|
export type VerticalScrollGeometry = Readonly<{
|
|
@@ -7,13 +7,15 @@ export type VerticalScrollGeometry = Readonly<{
|
|
|
7
7
|
containerHeight: number;
|
|
8
8
|
distanceToBottom: number;
|
|
9
9
|
}>;
|
|
10
|
-
/**
|
|
10
|
+
/** A controlled scroll position: the id of the target in view, its anchor and the callback that
|
|
11
|
+
* receives changes. */
|
|
11
12
|
export type ScrollPositionBinding = Readonly<{
|
|
12
13
|
id: string | null;
|
|
13
14
|
anchor?: ScrollAnchor;
|
|
14
15
|
onChange(id: string | null): void;
|
|
15
16
|
}>;
|
|
16
|
-
/**
|
|
17
|
+
/** The scroll view's position options: where it starts, whether it keeps visible content in
|
|
18
|
+
* place, a controlled position and a geometry callback. */
|
|
17
19
|
export type ScrollPositionOptions = Readonly<{
|
|
18
20
|
defaultScrollAnchor?: 'top' | 'bottom';
|
|
19
21
|
maintainVisibleContentPosition?: boolean;
|
package/dist/scroll/types.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type ScrollOffset = Readonly<{
|
|
|
6
6
|
y: number;
|
|
7
7
|
}>;
|
|
8
8
|
export type ScrollSnapshot = ReadonlyMap<string, ScrollOffset>;
|
|
9
|
-
/** Options for
|
|
9
|
+
/** Options for `scrollToTop`: whether to animate. */
|
|
10
10
|
export type ScrollToTopOptions = Readonly<{
|
|
11
11
|
animated?: boolean;
|
|
12
12
|
}>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import type { Searchable } from './searchable.js';
|
|
3
|
+
/** A column-owned field. Its host stays in this scroll surface, never a sibling pane. */
|
|
4
|
+
export declare function PadSearchDrawer({ configuration, scroller, }: {
|
|
5
|
+
configuration: Searchable;
|
|
6
|
+
scroller: RefObject<HTMLDivElement | null>;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { SearchToolbarField } from './SearchToolbarField.js';
|
|
4
|
+
/** A column-owned field. Its host stays in this scroll surface, never a sibling pane. */
|
|
5
|
+
export function PadSearchDrawer({ configuration, scroller, }) {
|
|
6
|
+
const [host, setHost] = useState(null);
|
|
7
|
+
return (_jsx("div", { ref: setHost, "data-satin-search-pad-drawer": "", "data-satin-search-toolbar-host": "", children: host && (_jsx(SearchToolbarField, { configuration: configuration, scroller: scroller, host: host, navigation: true, drawer: true })) }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Internal coordination between a retained search destination and its owning tab bar. */
|
|
2
|
+
export declare const PadSearchPresentationContext: import("react").Context<{
|
|
3
|
+
owner: string | null;
|
|
4
|
+
setOwner: (owner: string | null) => void;
|
|
5
|
+
} | null>;
|
|
6
|
+
export declare const PadSearchTabContext: import("react").Context<string | null>;
|
|
@@ -10,7 +10,7 @@ import { type Searchable } from './searchable.js';
|
|
|
10
10
|
* visual state of each part (FLIP), on the native springs (searchMotion.ts). A retarget mid-way
|
|
11
11
|
* starts from where everything is on screen, keeping the field's velocity.
|
|
12
12
|
*/
|
|
13
|
-
export declare function SearchDrawer(
|
|
13
|
+
export declare function SearchDrawer(props: {
|
|
14
14
|
configuration: Searchable;
|
|
15
15
|
scroller: RefObject<HTMLDivElement | null>;
|
|
16
16
|
}): import("react").JSX.Element;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { readDeviceIdiom } from '../layout/deviceIdiom.js';
|
|
3
|
+
import { PadSearchDrawer } from './PadSearchDrawer.js';
|
|
2
4
|
import { NavigationSearchRow, navigationSearchRowOf } from '../navigation/NavigationSearchRow.js';
|
|
3
5
|
import { animateElement } from '../motion/animate.js';
|
|
4
6
|
import { beginSearchBackdrop, endSearchBackdrop, refreshSearchBackdrop } from './searchBackdrop.js';
|
|
@@ -28,7 +30,10 @@ const TITLE_SELECTOR = ':scope > :is([data-satin-list-title], [data-satin-scroll
|
|
|
28
30
|
* visual state of each part (FLIP), on the native springs (searchMotion.ts). A retarget mid-way
|
|
29
31
|
* starts from where everything is on screen, keeping the field's velocity.
|
|
30
32
|
*/
|
|
31
|
-
export function SearchDrawer(
|
|
33
|
+
export function SearchDrawer(props) {
|
|
34
|
+
return readDeviceIdiom() === 'pad' ? (_jsx(PadSearchDrawer, { ...props })) : (_jsx(PhoneSearchDrawer, { ...props }));
|
|
35
|
+
}
|
|
36
|
+
function PhoneSearchDrawer({ configuration, scroller, }) {
|
|
32
37
|
validateSearchPresentation(configuration);
|
|
33
38
|
const liquid = useContext(MaterialEffectContext);
|
|
34
39
|
const navigator = useContext(NavigatorContext);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type RefObject, type ReactNode } from 'react';
|
|
2
|
+
/** Suggestions belong to their field, including when it lives in a split column. */
|
|
3
|
+
export declare function SearchSuggestionsPopover({ anchor, children, }: {
|
|
4
|
+
anchor: RefObject<HTMLElement | null>;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}): import("react").ReactPortal | null;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { GlassBackground } from '../glass/GlassEffect.js';
|
|
3
|
+
import { useSafeAreaMetrics } from '../safe-area/useSafeAreaMetrics.js';
|
|
4
|
+
import { useLayoutEffect, useState } from 'react';
|
|
5
|
+
import { createPortal } from 'react-dom';
|
|
6
|
+
/** Suggestions belong to their field, including when it lives in a split column. */
|
|
7
|
+
export function SearchSuggestionsPopover({ anchor, children, }) {
|
|
8
|
+
const metrics = useSafeAreaMetrics();
|
|
9
|
+
const [frame, setFrame] = useState();
|
|
10
|
+
useLayoutEffect(() => {
|
|
11
|
+
const element = anchor.current;
|
|
12
|
+
if (!element)
|
|
13
|
+
return;
|
|
14
|
+
const update = () => {
|
|
15
|
+
const rect = element.getBoundingClientRect();
|
|
16
|
+
const next = { left: Math.max(8, rect.left - 10), top: rect.bottom + 6, width: rect.width };
|
|
17
|
+
setFrame(previous => previous &&
|
|
18
|
+
previous.left === next.left &&
|
|
19
|
+
previous.top === next.top &&
|
|
20
|
+
previous.width === next.width
|
|
21
|
+
? previous
|
|
22
|
+
: next);
|
|
23
|
+
};
|
|
24
|
+
update();
|
|
25
|
+
const observer = new ResizeObserver(update);
|
|
26
|
+
observer.observe(element);
|
|
27
|
+
window.addEventListener('resize', update);
|
|
28
|
+
document.addEventListener('scroll', update, true);
|
|
29
|
+
return () => {
|
|
30
|
+
observer.disconnect();
|
|
31
|
+
window.removeEventListener('resize', update);
|
|
32
|
+
document.removeEventListener('scroll', update, true);
|
|
33
|
+
};
|
|
34
|
+
}, [anchor]);
|
|
35
|
+
if (!frame)
|
|
36
|
+
return null;
|
|
37
|
+
return createPortal(_jsxs("div", { "data-satin-search-popover": "", style: {
|
|
38
|
+
...frame,
|
|
39
|
+
maxHeight: Math.max(0, metrics.visualViewport.offsetTop + metrics.visualViewport.height - frame.top - 8),
|
|
40
|
+
overflowY: 'auto',
|
|
41
|
+
}, role: "list", "aria-label": "Suggestions", onPointerDown: event => event.preventDefault(), children: [_jsx(GlassBackground, { shape: { kind: 'roundedRectangle', cornerRadius: 28 } }), children] }), document.body);
|
|
42
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type RefObject } from 'react';
|
|
2
2
|
import type { Searchable } from './searchable.js';
|
|
3
|
-
export declare function SearchToolbarField({ configuration, scroller, host, navigation, }: {
|
|
3
|
+
export declare function SearchToolbarField({ configuration, scroller, host, navigation, drawer, }: {
|
|
4
4
|
configuration: Searchable;
|
|
5
5
|
scroller: RefObject<HTMLDivElement | null>;
|
|
6
6
|
host: HTMLElement;
|
|
7
7
|
navigation?: boolean;
|
|
8
|
+
drawer?: boolean;
|
|
8
9
|
}): import("react").JSX.Element;
|