@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.
Files changed (309) hide show
  1. package/NOTICE +2 -2
  2. package/README.md +2 -3
  3. package/dist/acknowledgements/inventory.json +5 -5
  4. package/dist/actions/RowActions.d.ts +4 -4
  5. package/dist/actions/RowActions.js +93 -27
  6. package/dist/actions/fullSwipeContact.d.ts +73 -0
  7. package/dist/actions/fullSwipeContact.js +186 -0
  8. package/dist/actions/rowScrub.d.ts +7 -4
  9. package/dist/actions/rowScrub.js +39 -37
  10. package/dist/actions/types.d.ts +13 -7
  11. package/dist/app/InstallComponents.d.ts +4 -7
  12. package/dist/app/InstallComponents.js +7 -7
  13. package/dist/app/InstallationDiagnostics.d.ts +2 -1
  14. package/dist/app/InstallationDiagnostics.js +2 -1
  15. package/dist/app/appearance.d.ts +5 -3
  16. package/dist/app/appearance.js +5 -3
  17. package/dist/app/appearanceStore.d.ts +3 -2
  18. package/dist/app/buildInfo.d.ts +4 -4
  19. package/dist/app/buildInfo.js +2 -2
  20. package/dist/app/definition.d.ts +11 -3
  21. package/dist/app/definition.js +2 -0
  22. package/dist/app/head.d.ts +2 -1
  23. package/dist/app/head.js +13 -16
  24. package/dist/app/inlineCSP.d.ts +6 -0
  25. package/dist/app/inlineCSP.js +25 -0
  26. package/dist/app/install.d.ts +1 -0
  27. package/dist/app/install.js +5 -2
  28. package/dist/app/installCheck.js +32 -86
  29. package/dist/app/installContext.d.ts +10 -5
  30. package/dist/app/installContext.js +2 -0
  31. package/dist/app/installCustom.js +1 -0
  32. package/dist/app/installExperience.js +0 -60
  33. package/dist/app/installationFailure.d.ts +3 -2
  34. package/dist/app/installationFailure.js +1 -1
  35. package/dist/app/launchScreen.d.ts +6 -2
  36. package/dist/app/launchScreen.js +104 -1
  37. package/dist/app/launchScreenRuntime.d.ts +31 -4
  38. package/dist/app/launchScreenRuntime.js +150 -22
  39. package/dist/app/launchWatchdog.js +25 -65
  40. package/dist/app/platformScripts.js +11 -0
  41. package/dist/app/styles.d.ts +3 -0
  42. package/dist/app/styles.js +42 -0
  43. package/dist/app/viewportValue.d.ts +2 -1
  44. package/dist/app/vite.d.ts +4 -0
  45. package/dist/app/vite.js +22 -24
  46. package/dist/content/content.d.ts +35 -30
  47. package/dist/content/content.js +19 -16
  48. package/dist/content/layout.d.ts +10 -2
  49. package/dist/content/layout.js +4 -2
  50. package/dist/content/scaledMetric.d.ts +2 -1
  51. package/dist/content/scaledMetric.js +2 -1
  52. package/dist/controls/ColorPicker.d.ts +2 -4
  53. package/dist/controls/ColorPicker.js +2 -4
  54. package/dist/controls/DatePicker.d.ts +4 -4
  55. package/dist/controls/DatePicker.js +2 -2
  56. package/dist/controls/ProgressView.d.ts +4 -4
  57. package/dist/controls/ProgressView.js +1 -2
  58. package/dist/controls/civilDate.d.ts +1 -1
  59. package/dist/controls/civilDate.js +1 -1
  60. package/dist/data/database.d.ts +9 -8
  61. package/dist/data/database.js +4 -4
  62. package/dist/docs/components/file-importer.md +1 -1
  63. package/dist/docs/components/paste-button.md +1 -1
  64. package/dist/docs/components/photos-picker.md +1 -1
  65. package/dist/docs/components/share-link.md +1 -1
  66. package/dist/docs/limitations.md +1 -1
  67. package/dist/docs/push.md +3 -3
  68. package/dist/docs/reference.md +1888 -0
  69. package/dist/docs/tailwind.md +76 -0
  70. package/dist/docs/tokens.md +1 -1
  71. package/dist/gestures/GestureView.d.ts +3 -1
  72. package/dist/gestures/GestureView.js +2 -1
  73. package/dist/gestures/gesture.d.ts +22 -2
  74. package/dist/gestures/gesture.js +7 -2
  75. package/dist/glass/GlassEffect.d.ts +2 -1
  76. package/dist/glass/GlassEffect.js +2 -1
  77. package/dist/glass/GlassPresentation.d.ts +1 -0
  78. package/dist/glass/GlassPresentation.js +21 -4
  79. package/dist/glass/TabBar.js +23 -1
  80. package/dist/glass/errorAlert.js +2 -1
  81. package/dist/glass/errors.d.ts +3 -1
  82. package/dist/glass/fallback/runtime.d.ts +1 -0
  83. package/dist/glass/fallback/runtime.js +8 -1
  84. package/dist/glass/lens/controlLift.d.ts +1 -1
  85. package/dist/glass/lens/controlLift.js +1 -1
  86. package/dist/glass/lens/interactivePress.d.ts +2 -2
  87. package/dist/glass/lens/interactivePress.js +2 -2
  88. package/dist/glass/lens/menu-opening-native-fits.json +1 -1
  89. package/dist/glass/lens/menuContextFit.json +1 -1
  90. package/dist/glass/lens/menuDropFit.json +1 -1
  91. package/dist/glass/lens/menuField.d.ts +2 -2
  92. package/dist/glass/lens/menuField.js +3 -3
  93. package/dist/glass/lens/menuGlyphDropFit.json +1 -1
  94. package/dist/glass/lens/menuMorphFit.json +1 -1
  95. package/dist/glass/lens/menuMorphPhoneFit.json +1 -1
  96. package/dist/glass/lens/tabAccessoryMotion.d.ts +1 -1
  97. package/dist/glass/lens/tabSearchMember.d.ts +1 -1
  98. package/dist/glass/lens/tabSearchMember.js +1 -1
  99. package/dist/glass/liquidContext.d.ts +2 -0
  100. package/dist/glass/menuPresenter.d.ts +2 -0
  101. package/dist/glass/menuPresenter.js +1 -1
  102. package/dist/glass/regions.d.ts +3 -2
  103. package/dist/glass/regions.js +1 -1
  104. package/dist/glass/renderSpecs.d.ts +1 -0
  105. package/dist/glass/renderSpecs.js +1 -0
  106. package/dist/glass/shapeTrack.d.ts +1 -1
  107. package/dist/glass/submenuMotion.d.ts +1 -1
  108. package/dist/glass/submenuMotion.js +1 -1
  109. package/dist/glass/webgpu/controlRim.d.ts +29 -0
  110. package/dist/glass/webgpu/controlRim.js +68 -0
  111. package/dist/glass/webgpu/entry.worker.js +3 -6
  112. package/dist/glass/webgpu/frameClock.d.ts +6 -2
  113. package/dist/glass/webgpu/frameClock.js +9 -2
  114. package/dist/glass/webgpu/frameProbe.d.ts +1 -1
  115. package/dist/glass/webgpu/frameProbe.js +3 -3
  116. package/dist/glass/webgpu/passes.d.ts +2 -2
  117. package/dist/glass/webgpu/production.d.ts +1 -0
  118. package/dist/glass/webgpu/production.js +31 -1
  119. package/dist/glass/webgpu/raster.d.ts +18 -0
  120. package/dist/glass/webgpu/raster.js +105 -15
  121. package/dist/glass/webgpu/rasterMaterial.d.ts +4 -0
  122. package/dist/glass/webgpu/rasterMaterial.js +17 -1
  123. package/dist/glass/webgpu/rasterUniforms.js +9 -0
  124. package/dist/glass/webgpu/regionScene.d.ts +4 -1
  125. package/dist/glass/webgpu/regionScene.js +30 -1
  126. package/dist/glass/webgpu/renderer.js +23 -7
  127. package/dist/glass/webgpu/shaders.d.ts +2 -2
  128. package/dist/glass/webgpu/shaders.js +5 -1
  129. package/dist/haptics/SensoryButton.d.ts +4 -4
  130. package/dist/haptics/SensoryButton.js +3 -3
  131. package/dist/image/Image.d.ts +6 -3
  132. package/dist/image/Image.js +4 -3
  133. package/dist/image/asset.d.ts +2 -1
  134. package/dist/keyboard/adapter.d.ts +3 -4
  135. package/dist/keyboard/adapter.js +2 -2
  136. package/dist/keyboard/avoidance.d.ts +1 -1
  137. package/dist/keyboard/avoidance.js +1 -1
  138. package/dist/keyboard/geometry.d.ts +1 -1
  139. package/dist/keyboard/motion.d.ts +1 -1
  140. package/dist/keyboard/motion.js +1 -1
  141. package/dist/list-form/ListForm.d.ts +10 -9
  142. package/dist/list-form/ListForm.js +3 -3
  143. package/dist/list-form/ListItem.js +1 -1
  144. package/dist/list-form/RowLabel.d.ts +1 -1
  145. package/dist/list-form/RowLabel.js +1 -1
  146. package/dist/list-form/Slider.js +1 -1
  147. package/dist/list-form/editMotion.js +1 -1
  148. package/dist/list-form/editing.d.ts +10 -11
  149. package/dist/list-form/editing.js +5 -6
  150. package/dist/list-form/offsets.d.ts +2 -2
  151. package/dist/list-form/offsets.js +2 -2
  152. package/dist/media/react.d.ts +2 -1
  153. package/dist/media/react.js +2 -1
  154. package/dist/media/types.d.ts +6 -3
  155. package/dist/motion/TransitionView.d.ts +4 -2
  156. package/dist/motion/TransitionView.js +3 -2
  157. package/dist/motion/animationValue.d.ts +2 -2
  158. package/dist/motion/animationValue.js +9 -10
  159. package/dist/motion/matchedGeometry.d.ts +10 -9
  160. package/dist/motion/matchedGeometry.js +9 -9
  161. package/dist/motion/springTrack.d.ts +1 -2
  162. package/dist/motion/springTrack.js +10 -5
  163. package/dist/motion/transition.d.ts +4 -1
  164. package/dist/motion/transition.js +2 -0
  165. package/dist/navigation/DetailList.d.ts +1 -1
  166. package/dist/navigation/DetailList.js +1 -1
  167. package/dist/navigation/ScreenContainer.js +1 -1
  168. package/dist/navigation/Sidebar.d.ts +3 -1
  169. package/dist/navigation/Sidebar.js +1 -1
  170. package/dist/navigation/SidebarSymbol.d.ts +2 -1
  171. package/dist/navigation/SidebarSymbol.js +2 -1
  172. package/dist/navigation/chromeCurves.js +1 -1
  173. package/dist/navigation/navigationContext.d.ts +2 -1
  174. package/dist/navigation/navigationContext.js +2 -1
  175. package/dist/navigation/splitContext.d.ts +2 -1
  176. package/dist/navigation/splitContext.js +2 -1
  177. package/dist/navigation/toolbarMinimization.d.ts +4 -3
  178. package/dist/navigation/types.d.ts +8 -6
  179. package/dist/navigation/zoomGeometry.js +1 -1
  180. package/dist/navigation/zoomMotion.d.ts +1 -1
  181. package/dist/navigation/zoomMotion.js +2 -2
  182. package/dist/navigation/zoomTransition.js +3 -4
  183. package/dist/presentation/Presentation.d.ts +10 -9
  184. package/dist/presentation/Presentation.js +4 -3
  185. package/dist/presentation/model.d.ts +2 -1
  186. package/dist/presentation/presentationSource.js +1 -1
  187. package/dist/press/Pressable.d.ts +5 -1
  188. package/dist/press/Pressable.js +2 -0
  189. package/dist/press/stateMachine.d.ts +1 -1
  190. package/dist/public/Label.d.ts +2 -1
  191. package/dist/public/Label.js +2 -1
  192. package/dist/public/Screen.d.ts +4 -6
  193. package/dist/public/actions.d.ts +2 -1
  194. package/dist/public/actions.js +2 -1
  195. package/dist/public/buttonBorderShape.d.ts +2 -1
  196. package/dist/public/colors.d.ts +7 -4
  197. package/dist/public/colors.js +3 -2
  198. package/dist/public/controlStyle.d.ts +17 -14
  199. package/dist/public/controls.d.ts +29 -28
  200. package/dist/public/controls.js +25 -24
  201. package/dist/public/deviceActions.d.ts +6 -4
  202. package/dist/public/deviceActions.js +4 -2
  203. package/dist/public/environment.d.ts +16 -13
  204. package/dist/public/environment.js +11 -9
  205. package/dist/public/filePickers.d.ts +6 -4
  206. package/dist/public/filePickers.js +3 -2
  207. package/dist/public/glass.d.ts +8 -6
  208. package/dist/public/glass.js +2 -2
  209. package/dist/public/glassValue.d.ts +3 -4
  210. package/dist/public/glassValue.js +3 -4
  211. package/dist/public/keyboard.d.ts +4 -1
  212. package/dist/public/keyboard.js +2 -1
  213. package/dist/public/navigationTransition.d.ts +6 -6
  214. package/dist/public/navigationTransition.js +3 -3
  215. package/dist/public/presentation.d.ts +8 -7
  216. package/dist/public/presentation.js +5 -5
  217. package/dist/public/runtime.d.ts +9 -8
  218. package/dist/public/runtime.js +7 -7
  219. package/dist/public/scroll.d.ts +6 -3
  220. package/dist/public/scroll.js +3 -1
  221. package/dist/public/structure.d.ts +2 -2
  222. package/dist/public/toolbar.d.ts +15 -11
  223. package/dist/public/toolbar.js +13 -8
  224. package/dist/reachability/model.d.ts +4 -3
  225. package/dist/reachability/react.d.ts +4 -1
  226. package/dist/reachability/react.js +2 -1
  227. package/dist/root/SatinRoot.d.ts +3 -3
  228. package/dist/root/SatinRoot.js +12 -36
  229. package/dist/root/mountSatin.d.ts +1 -1
  230. package/dist/root/mountSatin.js +26 -35
  231. package/dist/root/runtimeContext.d.ts +2 -1
  232. package/dist/root/runtimeContext.js +2 -1
  233. package/dist/safe-area/Overlay.d.ts +3 -2
  234. package/dist/safe-area/Overlay.js +2 -1
  235. package/dist/safe-area/SafeAreaInset.d.ts +11 -7
  236. package/dist/safe-area/SafeAreaInset.js +10 -9
  237. package/dist/safe-area/context.d.ts +3 -3
  238. package/dist/safe-area/context.js +1 -1
  239. package/dist/safe-area/displayCorners.d.ts +4 -2
  240. package/dist/safe-area/displayCorners.js +4 -2
  241. package/dist/safe-area/modifiers.d.ts +14 -10
  242. package/dist/safe-area/modifiers.js +10 -6
  243. package/dist/safe-area/useSafeAreaMetrics.js +2 -2
  244. package/dist/scroll/ScrollSurface.d.ts +5 -5
  245. package/dist/scroll/ScrollSurface.js +6 -2
  246. package/dist/scroll/ScrollTarget.d.ts +1 -1
  247. package/dist/scroll/ScrollTarget.js +1 -1
  248. package/dist/scroll/edgePolicy.d.ts +2 -2
  249. package/dist/scroll/position.d.ts +5 -3
  250. package/dist/scroll/position.js +1 -1
  251. package/dist/scroll/screenGeometry.d.ts +1 -1
  252. package/dist/scroll/screenGeometry.js +1 -1
  253. package/dist/scroll/types.d.ts +1 -1
  254. package/dist/search/PadSearchDrawer.d.ts +7 -0
  255. package/dist/search/PadSearchDrawer.js +8 -0
  256. package/dist/search/PadSearchPresentationContext.d.ts +6 -0
  257. package/dist/search/PadSearchPresentationContext.js +4 -0
  258. package/dist/search/SearchDrawer.d.ts +1 -1
  259. package/dist/search/SearchDrawer.js +7 -2
  260. package/dist/search/SearchSuggestionsPopover.d.ts +6 -0
  261. package/dist/search/SearchSuggestionsPopover.js +42 -0
  262. package/dist/search/SearchToolbarField.d.ts +2 -1
  263. package/dist/search/SearchToolbarField.js +28 -7
  264. package/dist/search/padSearchBarMotion.d.ts +69 -0
  265. package/dist/search/padSearchBarMotion.js +73 -0
  266. package/dist/search/padSearchFieldSamples.json +491 -0
  267. package/dist/search/searchMotion.d.ts +1 -1
  268. package/dist/search/searchMotion.js +1 -1
  269. package/dist/search/searchPlacement.d.ts +3 -0
  270. package/dist/search/searchPlacement.js +7 -0
  271. package/dist/search/searchable.d.ts +14 -12
  272. package/dist/search/usePadSearchFieldMotion.d.ts +4 -0
  273. package/dist/search/usePadSearchFieldMotion.js +100 -0
  274. package/dist/search/useSearchPresentation.d.ts +2 -1
  275. package/dist/search/useSearchPresentation.js +24 -6
  276. package/dist/server.d.ts +4 -4
  277. package/dist/server.js +4 -4
  278. package/dist/shapes/corners.d.ts +3 -3
  279. package/dist/shapes/corners.js +2 -3
  280. package/dist/styles.css +8302 -8236
  281. package/dist/sw/vite.d.ts +4 -0
  282. package/dist/sw/vite.js +2 -0
  283. package/dist/symbols/Symbol.d.ts +7 -5
  284. package/dist/symbols/Symbol.js +5 -3
  285. package/dist/symbols/catalogue.d.ts +1 -1
  286. package/dist/symbols/types.d.ts +6 -4
  287. package/dist/tabs/TabSection.d.ts +3 -2
  288. package/dist/tabs/TabSection.js +2 -1
  289. package/dist/tabs/TabView.js +54 -51
  290. package/dist/tasks/useTask.d.ts +5 -4
  291. package/dist/tasks/useTask.js +4 -3
  292. package/dist/testing.d.ts +3 -2
  293. package/dist/testing.js +3 -2
  294. package/dist/text-input/TextEditor.js +7 -3
  295. package/dist/text-input/focusChain.d.ts +4 -3
  296. package/dist/text-input/focusChain.js +3 -2
  297. package/dist/text-input/kinds.d.ts +1 -1
  298. package/dist/web/WebView.d.ts +10 -3
  299. package/dist/web/WebView.js +3 -2
  300. package/dist/web/authentication.d.ts +12 -1
  301. package/dist/web/authentication.js +2 -1
  302. package/dist/web/openURL.d.ts +10 -4
  303. package/dist/web/openURL.js +4 -2
  304. package/dist/web/useWebAuthentication.d.ts +2 -1
  305. package/dist/web/useWebAuthentication.js +2 -1
  306. package/dist/zoom/Zoomable.d.ts +3 -3
  307. package/dist/zoom/Zoomable.js +2 -2
  308. package/package.json +4 -4
  309. 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({ configuration, scroller, }: {
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({ configuration, scroller, }) {
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
- * (SwiftUI's `displayMode: .always`) under an inline or inlineLarge title (native reference reference and reference
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 search = useSearchPresentation(configuration, inputRef);
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
- return (_jsxs(_Fragment, { children: [createPortal(ownsItem ? _jsx("div", { "data-satin-toolbar-item": "search", children: row }) : row, host), navigation && 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 && (_jsx("div", { "data-satin-search-suggestions": "", role: "list", "aria-label": "Suggestions", children: 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))) }))] }));
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
+ }