@satinhq/kit 0.1.0-beta.2 → 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 +2 -2
- package/README.md +2 -3
- package/dist/acknowledgements/inventory.json +5 -5
- package/dist/actions/RowActions.d.ts +4 -4
- package/dist/actions/RowActions.js +93 -27
- 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/controls/civilDate.d.ts +1 -1
- package/dist/controls/civilDate.js +1 -1
- package/dist/data/database.d.ts +9 -8
- package/dist/data/database.js +4 -4
- package/dist/docs/components/file-importer.md +1 -1
- package/dist/docs/components/paste-button.md +1 -1
- package/dist/docs/components/photos-picker.md +1 -1
- package/dist/docs/components/share-link.md +1 -1
- package/dist/docs/limitations.md +1 -1
- package/dist/docs/push.md +3 -3
- package/dist/docs/reference.md +1888 -0
- 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/lens/controlLift.d.ts +1 -1
- package/dist/glass/lens/controlLift.js +1 -1
- package/dist/glass/lens/interactivePress.d.ts +2 -2
- package/dist/glass/lens/interactivePress.js +2 -2
- package/dist/glass/lens/menu-opening-native-fits.json +1 -1
- package/dist/glass/lens/menuContextFit.json +1 -1
- package/dist/glass/lens/menuDropFit.json +1 -1
- package/dist/glass/lens/menuField.d.ts +2 -2
- package/dist/glass/lens/menuField.js +3 -3
- package/dist/glass/lens/menuGlyphDropFit.json +1 -1
- package/dist/glass/lens/menuMorphFit.json +1 -1
- package/dist/glass/lens/menuMorphPhoneFit.json +1 -1
- package/dist/glass/lens/tabAccessoryMotion.d.ts +1 -1
- package/dist/glass/lens/tabSearchMember.d.ts +1 -1
- package/dist/glass/lens/tabSearchMember.js +1 -1
- package/dist/glass/liquidContext.d.ts +2 -0
- package/dist/glass/menuPresenter.d.ts +2 -0
- package/dist/glass/menuPresenter.js +1 -1
- package/dist/glass/regions.d.ts +3 -2
- package/dist/glass/regions.js +1 -1
- package/dist/glass/renderSpecs.d.ts +1 -0
- package/dist/glass/renderSpecs.js +1 -0
- package/dist/glass/shapeTrack.d.ts +1 -1
- package/dist/glass/submenuMotion.d.ts +1 -1
- package/dist/glass/submenuMotion.js +1 -1
- package/dist/glass/webgpu/controlRim.d.ts +29 -0
- package/dist/glass/webgpu/controlRim.js +68 -0
- package/dist/glass/webgpu/entry.worker.js +3 -6
- package/dist/glass/webgpu/frameClock.d.ts +6 -2
- package/dist/glass/webgpu/frameClock.js +9 -2
- package/dist/glass/webgpu/frameProbe.d.ts +1 -1
- package/dist/glass/webgpu/frameProbe.js +3 -3
- package/dist/glass/webgpu/passes.d.ts +2 -2
- package/dist/glass/webgpu/production.d.ts +1 -0
- package/dist/glass/webgpu/production.js +31 -1
- package/dist/glass/webgpu/raster.d.ts +18 -0
- package/dist/glass/webgpu/raster.js +105 -15
- package/dist/glass/webgpu/rasterMaterial.d.ts +4 -0
- package/dist/glass/webgpu/rasterMaterial.js +17 -1
- package/dist/glass/webgpu/rasterUniforms.js +9 -0
- package/dist/glass/webgpu/regionScene.d.ts +4 -1
- package/dist/glass/webgpu/regionScene.js +30 -1
- package/dist/glass/webgpu/renderer.js +23 -7
- 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/adapter.js +2 -2
- package/dist/keyboard/avoidance.d.ts +1 -1
- package/dist/keyboard/avoidance.js +1 -1
- package/dist/keyboard/geometry.d.ts +1 -1
- package/dist/keyboard/motion.d.ts +1 -1
- package/dist/keyboard/motion.js +1 -1
- package/dist/list-form/ListForm.d.ts +10 -9
- package/dist/list-form/ListForm.js +3 -3
- package/dist/list-form/ListItem.js +1 -1
- package/dist/list-form/RowLabel.d.ts +1 -1
- package/dist/list-form/RowLabel.js +1 -1
- package/dist/list-form/Slider.js +1 -1
- package/dist/list-form/editMotion.js +1 -1
- package/dist/list-form/editing.d.ts +10 -11
- package/dist/list-form/editing.js +5 -6
- 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 +2 -2
- package/dist/motion/animationValue.js +9 -10
- package/dist/motion/matchedGeometry.d.ts +10 -9
- package/dist/motion/matchedGeometry.js +9 -9
- package/dist/motion/springTrack.d.ts +1 -2
- package/dist/motion/springTrack.js +10 -5
- 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/ScreenContainer.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/chromeCurves.js +1 -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 +8 -6
- package/dist/navigation/zoomGeometry.js +1 -1
- package/dist/navigation/zoomMotion.d.ts +1 -1
- package/dist/navigation/zoomMotion.js +2 -2
- package/dist/navigation/zoomTransition.js +3 -4
- package/dist/presentation/Presentation.d.ts +10 -9
- package/dist/presentation/Presentation.js +4 -3
- package/dist/presentation/model.d.ts +2 -1
- package/dist/presentation/presentationSource.js +1 -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 +29 -28
- package/dist/public/controls.js +25 -24
- 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 +8 -6
- package/dist/public/glass.js +2 -2
- 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 +6 -6
- package/dist/public/navigationTransition.js +3 -3
- 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 +13 -8
- 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 +10 -9
- 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 +10 -6
- package/dist/safe-area/useSafeAreaMetrics.js +2 -2
- package/dist/scroll/ScrollSurface.d.ts +5 -5
- package/dist/scroll/ScrollSurface.js +6 -2
- 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/position.js +1 -1
- package/dist/scroll/screenGeometry.d.ts +1 -1
- package/dist/scroll/screenGeometry.js +1 -1
- 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 +7 -2
- 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/searchMotion.d.ts +1 -1
- package/dist/search/searchMotion.js +1 -1
- 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 +24 -6
- 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 +2 -3
- package/dist/styles.css +8302 -8236
- 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/TextEditor.js +7 -3
- 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 +4 -4
- package/dist/docs/swiftui-reference.md +0 -1895
|
@@ -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);
|
|
@@ -258,7 +263,7 @@ function pinProgress(drawer) {
|
|
|
258
263
|
}
|
|
259
264
|
/* How far the resting field has turned from its grey fill to glass. The field is glass from
|
|
260
265
|
* scroll 0 only when the drawer is fixed in the bar: an explicit `navigationBarDrawer` placement
|
|
261
|
-
*
|
|
266
|
+
* with persistent visibility under an inline or inlineLarge title (native reference reference and reference
|
|
262
267
|
* B/H, iOS 27.0: light 251 with a darker rim, dark 32 with a light rim). Under a large title the
|
|
263
268
|
* field belongs to the content header, and an automatic placement's drawer scrolls away with the
|
|
264
269
|
* content; both are a grey fill until content scrolls under the field (reference A/C/D/G: light 228-239,
|
|
@@ -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;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { usePadSearchFieldMotion } from './usePadSearchFieldMotion.js';
|
|
3
|
+
import { PadSearchPresentationContext, PadSearchTabContext, } from './PadSearchPresentationContext.js';
|
|
2
4
|
import { useContext, useLayoutEffect, useRef, useSyncExternalStore } from 'react';
|
|
5
|
+
import { readDeviceIdiom } from '../layout/deviceIdiom.js';
|
|
3
6
|
import { createPortal } from 'react-dom';
|
|
4
7
|
import { GlassBackground } from '../glass/GlassEffect.js';
|
|
5
8
|
import { MaterialEffectContext } from '../glass/liquidContext.js';
|
|
@@ -9,6 +12,7 @@ import { contactTarget, MENU_CONTACT_CLICK_WINDOW_MS, ownPhysicalContact, } from
|
|
|
9
12
|
import { focusFromFramework } from '../focus/programmaticFocus.js';
|
|
10
13
|
import { SymbolImage } from '../symbols/Symbol.js';
|
|
11
14
|
import { TextField } from '../text-input/TextField.js';
|
|
15
|
+
import { SearchSuggestionsPopover } from './SearchSuggestionsPopover.js';
|
|
12
16
|
import { SearchScopesBar } from './SearchScopesBar.js';
|
|
13
17
|
import { navigationChromeOf, ownBarParts, stackedOver, subscribeNever } from './searchChrome.js';
|
|
14
18
|
import { useSearchPresentation } from './useSearchPresentation.js';
|
|
@@ -24,20 +28,31 @@ import { useSearchPresentation } from './useSearchPresentation.js';
|
|
|
24
28
|
* placed among the bottom items. Suggestions stand in for the scroll view's content, as in the
|
|
25
29
|
* drawer. Presentation is not animated yet: native's motion is not measured (spec notes, reference).
|
|
26
30
|
*/
|
|
27
|
-
export function SearchToolbarField({ configuration, scroller, host, navigation = false, }) {
|
|
31
|
+
export function SearchToolbarField({ configuration, scroller, host, navigation = false, drawer = false, }) {
|
|
32
|
+
const tabSearch = useContext(PadSearchPresentationContext);
|
|
33
|
+
const searchTab = useContext(PadSearchTabContext);
|
|
34
|
+
const setSearchOwner = tabSearch?.setOwner;
|
|
28
35
|
const liquid = useContext(MaterialEffectContext);
|
|
29
36
|
const navigator = useContext(NavigatorContext);
|
|
30
37
|
const screenKey = useContext(ScreenContext)?.key;
|
|
31
38
|
const stacked = useSyncExternalStore(navigator?.subscribe ?? subscribeNever, () => stackedOver(navigator, screenKey, scroller.current));
|
|
32
39
|
const inputRef = useRef(null);
|
|
33
40
|
const rowRef = useRef(null);
|
|
34
|
-
const
|
|
41
|
+
const pad = navigation && readDeviceIdiom() === 'pad';
|
|
42
|
+
const search = useSearchPresentation(configuration, inputRef, pad);
|
|
35
43
|
const { presented } = search;
|
|
44
|
+
usePadSearchFieldMotion(rowRef, pad && !drawer, presented, searchTab !== null, liquid?.regions);
|
|
45
|
+
useLayoutEffect(() => {
|
|
46
|
+
if (!pad || !searchTab || !setSearchOwner || !presented || stacked)
|
|
47
|
+
return;
|
|
48
|
+
setSearchOwner(searchTab);
|
|
49
|
+
return () => setSearchOwner(null);
|
|
50
|
+
}, [pad, searchTab, setSearchOwner, presented, stacked]);
|
|
36
51
|
// The bar's title and items give way while search is presented; its back control too, unless a
|
|
37
52
|
// screen is stacked over this one (as the drawer, SearchDrawer.tsx).
|
|
38
53
|
useLayoutEffect(() => {
|
|
39
54
|
const element = scroller.current;
|
|
40
|
-
if (!element || navigation)
|
|
55
|
+
if (!element || (navigation && !drawer))
|
|
41
56
|
return;
|
|
42
57
|
element.toggleAttribute('data-satin-search-presented', presented);
|
|
43
58
|
const { header } = navigationChromeOf(element);
|
|
@@ -57,7 +72,7 @@ export function SearchToolbarField({ configuration, scroller, host, navigation =
|
|
|
57
72
|
part.removeAttribute('data-satin-search-presented');
|
|
58
73
|
header?.removeAttribute('data-satin-search-presented');
|
|
59
74
|
};
|
|
60
|
-
}, [presented, scroller, screenKey, stacked, navigation]);
|
|
75
|
+
}, [presented, scroller, screenKey, stacked, navigation, drawer]);
|
|
61
76
|
// The field moves with the keyboard on the keyboard's own curve (styles.css). Glass regions
|
|
62
77
|
// follow a moving element only when told: refresh them while it moves.
|
|
63
78
|
useLayoutEffect(() => {
|
|
@@ -93,16 +108,20 @@ export function SearchToolbarField({ configuration, scroller, host, navigation =
|
|
|
93
108
|
}, [liquid?.regions, presented]);
|
|
94
109
|
const prompt = configuration.prompt ?? 'Search';
|
|
95
110
|
const ownsItem = !host.hasAttribute('data-satin-search-toolbar-host');
|
|
96
|
-
const row = (_jsxs("div", { ref: rowRef, role: "search", "data-satin-search-toolbar": "", "data-satin-search-navigation": navigation || undefined, "data-satin-search-toolbar-presented": presented || undefined, children: [_jsxs("div", { "data-satin-search-toolbar-field": "", children: [_jsx(GlassBackground, { shape: "capsule" }), _jsx(SymbolImage, { name: "magnifyingglass", weight: "medium", "data-satin-search-toolbar-magnifier": "" }), _jsx(TextField, { ref: inputRef, label: prompt, labelVisibility: "hidden", variant: "plain", placeholder: prompt, kind: "search", submitLabel: "search", value: configuration.text, onChange: search.change, onFocus: search.present, onSubmit: search.submit, onKeyDown: event => {
|
|
111
|
+
const row = (_jsxs("div", { ref: rowRef, role: "search", "data-satin-search-toolbar": "", "data-satin-search-navigation": navigation || undefined, "data-satin-search-pad": pad || undefined, "data-satin-search-toolbar-presented": presented || undefined, children: [_jsxs("div", { "data-satin-search-toolbar-field": "", children: [_jsx(GlassBackground, { shape: "capsule" }), _jsx(SymbolImage, { name: "magnifyingglass", weight: "medium", "data-satin-search-toolbar-magnifier": "" }), _jsx(TextField, { ref: inputRef, label: prompt, labelVisibility: "hidden", variant: "plain", placeholder: prompt, kind: "search", submitLabel: "search", value: configuration.text, onChange: search.change, onFocus: search.present, onBlur: pad ? search.resign : undefined, onSubmit: search.submit, onKeyDown: event => {
|
|
97
112
|
if (event.key !== 'Escape' || event.nativeEvent.isComposing)
|
|
98
113
|
return;
|
|
99
114
|
event.preventDefault();
|
|
100
115
|
search.dismiss();
|
|
101
116
|
} }), configuration.text && (_jsx(Pressable, { iconOnly: true, "aria-label": "Clear text", "data-satin-search-toolbar-clear": "", onPress: () => {
|
|
117
|
+
if (pad && searchTab) {
|
|
118
|
+
search.dismiss();
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
102
121
|
search.change('');
|
|
103
122
|
if (inputRef.current)
|
|
104
123
|
focusFromFramework(inputRef.current);
|
|
105
|
-
}, children: _jsx(SymbolImage, { name: "xmark.circle.fill" }) }))] }), presented && (_jsxs(Pressable, { iconOnly: true, "aria-label": "Close", "data-satin-search-toolbar-close": "", "data-satin-glass-press": "true", onPress: () => {
|
|
124
|
+
}, children: _jsx(SymbolImage, { name: "xmark.circle.fill" }) }))] }), presented && !pad && (_jsxs(Pressable, { iconOnly: true, "aria-label": "Close", "data-satin-search-toolbar-close": "", "data-satin-glass-press": "true", onPress: () => {
|
|
106
125
|
// The touch ends here: WebKit's synthesized mouse events must not refocus the field
|
|
107
126
|
// that moves under the finger (as the drawer's close button).
|
|
108
127
|
ownPhysicalContact(contactTarget(), closeContactOwner, MENU_CONTACT_CLICK_WINDOW_MS, {
|
|
@@ -110,6 +129,8 @@ export function SearchToolbarField({ configuration, scroller, host, navigation =
|
|
|
110
129
|
});
|
|
111
130
|
search.dismiss();
|
|
112
131
|
}, children: [_jsx(GlassBackground, { shape: "circle", interactive: true }), _jsx(SymbolImage, { name: "xmark", weight: "medium" })] }))] }));
|
|
113
|
-
|
|
132
|
+
const suggestions = search.suggestions.map(suggestion => (_jsx(Pressable, { role: "listitem", feedback: "row", "data-satin-search-suggestion": "", onPress: () => search.complete(suggestion), children: suggestion.label ?? suggestion.text }, suggestion.id)));
|
|
133
|
+
return (_jsxs(_Fragment, { children: [createPortal(ownsItem ? (_jsx("div", { "data-satin-toolbar-item": "search", "data-satin-search-pad-item": pad || undefined, "data-satin-search-expanded": (pad && presented) || undefined, children: row })) : (row), host), navigation && (!pad || drawer) && configuration.scopes && presented && (_jsx("div", { "data-satin-search-navigation-scopes": "", "data-satin-search-presented": "", children: _jsx(SearchScopesBar, { scopes: configuration.scopes, presented: presented }) })), search.suggestions.length > 0 &&
|
|
134
|
+
(pad ? (_jsx(SearchSuggestionsPopover, { anchor: rowRef, children: suggestions })) : (_jsx("div", { "data-satin-search-suggestions": "", role: "list", "aria-label": "Suggestions", children: suggestions })))] }));
|
|
114
135
|
}
|
|
115
136
|
const closeContactOwner = {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { SurfaceRenderSpec } from '../glass/renderSpecs.js';
|
|
2
|
+
/** iPad, iPadOS 27.0 (24A437), reference. Activation fit from original video
|
|
3
|
+
* F742–751: omega 17.8734, critical damping, RMS 0.104 pt. Dismissal
|
|
4
|
+
* presentation-layer fit: omega 17.9118, zeta .9982, RMS .038 pt.
|
|
5
|
+
* Translation and effective opacity are one group track; scale remains 1. */
|
|
6
|
+
export declare const PAD_SEARCH_BAR_OMEGA = 17.9;
|
|
7
|
+
export declare const PAD_SEARCH_BAR_TRAVEL = 64;
|
|
8
|
+
export declare class PadSearchBarMotion {
|
|
9
|
+
private run?;
|
|
10
|
+
private animation?;
|
|
11
|
+
get active(): boolean;
|
|
12
|
+
sample(at: number): {
|
|
13
|
+
value: number;
|
|
14
|
+
velocity: number;
|
|
15
|
+
};
|
|
16
|
+
retarget(target: number, at: number): void;
|
|
17
|
+
start(element: HTMLElement, target: number, finalSpec: SurfaceRenderSpec | undefined, at?: number): {
|
|
18
|
+
at: number;
|
|
19
|
+
duration: number;
|
|
20
|
+
specs: {
|
|
21
|
+
touchLight?: import("../internal.js").GlassTouchLight;
|
|
22
|
+
excludeRegionIds?: readonly string[];
|
|
23
|
+
restHidden?: boolean;
|
|
24
|
+
occluder?: import("../internal.js").CapsuleShape;
|
|
25
|
+
prewarmTransparent?: boolean;
|
|
26
|
+
recipeMix?: number;
|
|
27
|
+
sheetOpaqueMix?: number;
|
|
28
|
+
popoverArrow?: import("../glass/regions.js").PopoverArrow;
|
|
29
|
+
variant?: import("../glass/lens/referenceProfiles.js").ReferenceVariant;
|
|
30
|
+
treatment?: 'sheet' | 'expandedSheet' | 'alert' | 'confirmation' | 'contextBackdrop' | 'contextPreview' | 'contextMenu';
|
|
31
|
+
tint?: import("../index.js").GlassTint;
|
|
32
|
+
memberHighlight?: Readonly<{
|
|
33
|
+
member: number;
|
|
34
|
+
amount: number;
|
|
35
|
+
light?: import("../internal.js").GlassTouchLight;
|
|
36
|
+
}>;
|
|
37
|
+
backdropExclusions?: readonly string[];
|
|
38
|
+
backdropMenuOverlay?: boolean;
|
|
39
|
+
blurSigmaCssPx?: number;
|
|
40
|
+
frameHeight: number;
|
|
41
|
+
frameWidth: number;
|
|
42
|
+
frameX: number;
|
|
43
|
+
id: import("../internal.js").SurfaceId;
|
|
44
|
+
materialMix: number;
|
|
45
|
+
materialProfile: 'chrome' | 'searchField' | 'menu';
|
|
46
|
+
menuTintMix?: number;
|
|
47
|
+
returningTrigger?: import("../internal.js").ReturningMenuTrigger;
|
|
48
|
+
radius: number;
|
|
49
|
+
sampleHeight: number;
|
|
50
|
+
sampleInsetX: number;
|
|
51
|
+
sampleInsetY: number;
|
|
52
|
+
sampleWidth: number;
|
|
53
|
+
shaderAperture: boolean;
|
|
54
|
+
shape: import("../internal.js").SurfaceShape;
|
|
55
|
+
tabSelection?: import("../internal.js").TabSelectionShape;
|
|
56
|
+
ink?: Readonly<{
|
|
57
|
+
atlas: Readonly<{
|
|
58
|
+
width: number;
|
|
59
|
+
height: number;
|
|
60
|
+
}>;
|
|
61
|
+
layers: readonly import("../glass/lens/menuField.js").MenuInkLayer[];
|
|
62
|
+
}>;
|
|
63
|
+
frameY: number;
|
|
64
|
+
opacity: number;
|
|
65
|
+
}[];
|
|
66
|
+
finished: Promise<void | Animation>;
|
|
67
|
+
};
|
|
68
|
+
dispose(): void;
|
|
69
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { animateElement, timelineStart } from '../motion/animate.js';
|
|
2
|
+
/** iPad, iPadOS 27.0 (24A437), reference. Activation fit from original video
|
|
3
|
+
* F742–751: omega 17.8734, critical damping, RMS 0.104 pt. Dismissal
|
|
4
|
+
* presentation-layer fit: omega 17.9118, zeta .9982, RMS .038 pt.
|
|
5
|
+
* Translation and effective opacity are one group track; scale remains 1. */
|
|
6
|
+
export const PAD_SEARCH_BAR_OMEGA = 17.9;
|
|
7
|
+
export const PAD_SEARCH_BAR_TRAVEL = 64;
|
|
8
|
+
export class PadSearchBarMotion {
|
|
9
|
+
run;
|
|
10
|
+
animation;
|
|
11
|
+
get active() {
|
|
12
|
+
return this.animation?.playState === 'running';
|
|
13
|
+
}
|
|
14
|
+
sample(at) {
|
|
15
|
+
const run = this.run;
|
|
16
|
+
if (!run)
|
|
17
|
+
return { value: 0, velocity: 0 };
|
|
18
|
+
const t = Math.max(0, at - run.at) / 1000;
|
|
19
|
+
const displacement = run.from - run.target;
|
|
20
|
+
const slope = run.velocity + PAD_SEARCH_BAR_OMEGA * displacement;
|
|
21
|
+
const decay = Math.exp(-PAD_SEARCH_BAR_OMEGA * t);
|
|
22
|
+
return {
|
|
23
|
+
value: run.target + (displacement + slope * t) * decay,
|
|
24
|
+
velocity: (slope - PAD_SEARCH_BAR_OMEGA * (displacement + slope * t)) * decay,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
retarget(target, at) {
|
|
28
|
+
const current = this.sample(at);
|
|
29
|
+
this.run = { at, from: current.value, target, velocity: current.velocity };
|
|
30
|
+
}
|
|
31
|
+
start(element, target, finalSpec, at = performance.now()) {
|
|
32
|
+
this.retarget(target, at);
|
|
33
|
+
this.animation?.cancel();
|
|
34
|
+
this.animation = undefined;
|
|
35
|
+
const reduced = matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
36
|
+
let duration = 0;
|
|
37
|
+
if (!reduced) {
|
|
38
|
+
do {
|
|
39
|
+
duration += 1000 / 60;
|
|
40
|
+
} while (duration < 2000 &&
|
|
41
|
+
(Math.abs(this.sample(at + duration).value - target) > 0.0015 ||
|
|
42
|
+
Math.abs(this.sample(at + duration).velocity) > 0.02));
|
|
43
|
+
}
|
|
44
|
+
const count = Math.max(1, Math.round(duration / (1000 / 60)));
|
|
45
|
+
const values = Array.from({ length: count + 1 }, (_, index) => reduced || index === count ? target : this.sample(at + (duration * index) / count).value);
|
|
46
|
+
const specs = finalSpec
|
|
47
|
+
? values.map(value => ({
|
|
48
|
+
...finalSpec,
|
|
49
|
+
frameY: finalSpec.frameY - PAD_SEARCH_BAR_TRAVEL * (value - target),
|
|
50
|
+
opacity: Math.max(0, Math.min(1, 1 - value)),
|
|
51
|
+
}))
|
|
52
|
+
: [];
|
|
53
|
+
const frames = values.map(value => ({
|
|
54
|
+
transform: `translateY(${-PAD_SEARCH_BAR_TRAVEL * (value - target)}px)`,
|
|
55
|
+
opacity: Math.max(0, Math.min(1, 1 - value)),
|
|
56
|
+
}));
|
|
57
|
+
if (duration) {
|
|
58
|
+
this.animation = animateElement(element, frames, { duration, easing: 'linear' });
|
|
59
|
+
this.animation.startTime = timelineStart(at);
|
|
60
|
+
}
|
|
61
|
+
else
|
|
62
|
+
this.run = { at, from: target, target, velocity: 0 };
|
|
63
|
+
return {
|
|
64
|
+
at,
|
|
65
|
+
duration,
|
|
66
|
+
specs,
|
|
67
|
+
finished: this.animation?.finished.catch(() => { }) ?? Promise.resolve(),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
dispose() {
|
|
71
|
+
this.animation?.cancel();
|
|
72
|
+
}
|
|
73
|
+
}
|