@multiplatform.one/forms 7.80.0 → 7.81.1
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/dist/cjs/AdaptivePopup/index.cjs +2 -1
- package/dist/cjs/AdaptivePopup/index.native.js +2 -1
- package/dist/cjs/AdaptivePopup/index.native.js.map +1 -1
- package/dist/cjs/Button/index.cjs +12 -5
- package/dist/cjs/Button/index.native.js +14 -6
- package/dist/cjs/Button/index.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/PanelHeader.cjs +3 -8
- package/dist/cjs/FloatingPanel/PanelHeader.native.js +3 -8
- package/dist/cjs/FloatingPanel/PanelHeader.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/coverRect.cjs +0 -8
- package/dist/cjs/FloatingPanel/coverRect.native.js +0 -8
- package/dist/cjs/FloatingPanel/coverRect.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/echoContext.cjs +5 -27
- package/dist/cjs/FloatingPanel/echoContext.native.js +5 -28
- package/dist/cjs/FloatingPanel/echoContext.native.js.map +1 -1
- package/dist/cjs/FloatingPanel/index.cjs +49 -131
- package/dist/cjs/FloatingPanel/index.native.js +216 -135
- package/dist/cjs/FloatingPanel/index.native.js.map +1 -1
- package/dist/cjs/fields/Combobox/index.cjs +3 -10
- package/dist/cjs/fields/Combobox/index.native.js +3 -10
- package/dist/cjs/fields/Combobox/index.native.js.map +1 -1
- package/dist/cjs/fields/Select/InlineChoices.cjs +4 -8
- package/dist/cjs/fields/Select/InlineChoices.native.js +4 -8
- package/dist/cjs/fields/Select/InlineChoices.native.js.map +1 -1
- package/dist/cjs/fields/Select/index.cjs +65 -201
- package/dist/cjs/fields/Select/index.native.js +74 -209
- package/dist/cjs/fields/Select/index.native.js.map +1 -1
- package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.cjs +2 -2
- package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js +2 -2
- package/dist/cjs/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
- package/dist/cjs/index.cjs +4 -0
- package/dist/cjs/index.native.js +4 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/shared/CheckGlyph.cjs +40 -0
- package/dist/cjs/shared/CheckGlyph.native.js +44 -0
- package/dist/cjs/shared/CheckGlyph.native.js.map +1 -0
- package/dist/cjs/shared/checkedOnField.cjs +104 -0
- package/dist/cjs/shared/checkedOnField.native.js +117 -0
- package/dist/cjs/shared/checkedOnField.native.js.map +1 -0
- package/dist/cjs/shared/floatingList.cjs +12 -5
- package/dist/cjs/shared/floatingList.native.js +15 -7
- package/dist/cjs/shared/floatingList.native.js.map +1 -1
- package/dist/esm/AdaptivePopup/index.mjs +3 -2
- package/dist/esm/AdaptivePopup/index.mjs.map +1 -1
- package/dist/esm/AdaptivePopup/index.native.js +3 -2
- package/dist/esm/AdaptivePopup/index.native.js.map +1 -1
- package/dist/esm/Button/index.mjs +12 -5
- package/dist/esm/Button/index.mjs.map +1 -1
- package/dist/esm/Button/index.native.js +14 -6
- package/dist/esm/Button/index.native.js.map +1 -1
- package/dist/esm/FloatingPanel/PanelHeader.mjs +3 -8
- package/dist/esm/FloatingPanel/PanelHeader.mjs.map +1 -1
- package/dist/esm/FloatingPanel/PanelHeader.native.js +3 -8
- package/dist/esm/FloatingPanel/PanelHeader.native.js.map +1 -1
- package/dist/esm/FloatingPanel/coverRect.mjs +1 -8
- package/dist/esm/FloatingPanel/coverRect.mjs.map +1 -1
- package/dist/esm/FloatingPanel/coverRect.native.js +1 -8
- package/dist/esm/FloatingPanel/coverRect.native.js.map +1 -1
- package/dist/esm/FloatingPanel/echoContext.mjs +4 -24
- package/dist/esm/FloatingPanel/echoContext.mjs.map +1 -1
- package/dist/esm/FloatingPanel/echoContext.native.js +4 -25
- package/dist/esm/FloatingPanel/echoContext.native.js.map +1 -1
- package/dist/esm/FloatingPanel/index.mjs +53 -135
- package/dist/esm/FloatingPanel/index.mjs.map +1 -1
- package/dist/esm/FloatingPanel/index.native.js +180 -99
- package/dist/esm/FloatingPanel/index.native.js.map +1 -1
- package/dist/esm/fields/Combobox/index.mjs +4 -11
- package/dist/esm/fields/Combobox/index.mjs.map +1 -1
- package/dist/esm/fields/Combobox/index.native.js +4 -11
- package/dist/esm/fields/Combobox/index.native.js.map +1 -1
- package/dist/esm/fields/Select/InlineChoices.mjs +2 -6
- package/dist/esm/fields/Select/InlineChoices.mjs.map +1 -1
- package/dist/esm/fields/Select/InlineChoices.native.js +2 -6
- package/dist/esm/fields/Select/InlineChoices.native.js.map +1 -1
- package/dist/esm/fields/Select/index.mjs +68 -204
- package/dist/esm/fields/Select/index.mjs.map +1 -1
- package/dist/esm/fields/Select/index.native.js +77 -212
- package/dist/esm/fields/Select/index.native.js.map +1 -1
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.mjs +3 -3
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.mjs.map +1 -1
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js +3 -3
- package/dist/esm/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
- package/dist/esm/index.mjs +3 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +3 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/shared/CheckGlyph.mjs +15 -0
- package/dist/esm/shared/CheckGlyph.mjs.map +1 -0
- package/dist/esm/shared/CheckGlyph.native.js +16 -0
- package/dist/esm/shared/CheckGlyph.native.js.map +1 -0
- package/dist/esm/shared/checkedOnField.mjs +76 -0
- package/dist/esm/shared/checkedOnField.mjs.map +1 -0
- package/dist/esm/shared/checkedOnField.native.js +86 -0
- package/dist/esm/shared/checkedOnField.native.js.map +1 -0
- package/dist/esm/shared/floatingList.mjs +9 -5
- package/dist/esm/shared/floatingList.mjs.map +1 -1
- package/dist/esm/shared/floatingList.native.js +12 -7
- package/dist/esm/shared/floatingList.native.js.map +1 -1
- package/dist/jsx/AdaptivePopup/index.mjs +3 -2
- package/dist/jsx/AdaptivePopup/index.mjs.map +1 -1
- package/dist/jsx/AdaptivePopup/index.native.js +2 -1
- package/dist/jsx/AdaptivePopup/index.native.js.map +1 -1
- package/dist/jsx/Button/index.mjs +12 -5
- package/dist/jsx/Button/index.mjs.map +1 -1
- package/dist/jsx/Button/index.native.js +14 -6
- package/dist/jsx/Button/index.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/PanelHeader.mjs +3 -8
- package/dist/jsx/FloatingPanel/PanelHeader.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/PanelHeader.native.js +3 -8
- package/dist/jsx/FloatingPanel/PanelHeader.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/coverRect.mjs +1 -8
- package/dist/jsx/FloatingPanel/coverRect.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/coverRect.native.js +0 -8
- package/dist/jsx/FloatingPanel/coverRect.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/echoContext.mjs +4 -24
- package/dist/jsx/FloatingPanel/echoContext.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/echoContext.native.js +5 -28
- package/dist/jsx/FloatingPanel/echoContext.native.js.map +1 -1
- package/dist/jsx/FloatingPanel/index.mjs +53 -135
- package/dist/jsx/FloatingPanel/index.mjs.map +1 -1
- package/dist/jsx/FloatingPanel/index.native.js +216 -135
- package/dist/jsx/FloatingPanel/index.native.js.map +1 -1
- package/dist/jsx/fields/Combobox/index.mjs +4 -11
- package/dist/jsx/fields/Combobox/index.mjs.map +1 -1
- package/dist/jsx/fields/Combobox/index.native.js +3 -10
- package/dist/jsx/fields/Combobox/index.native.js.map +1 -1
- package/dist/jsx/fields/Select/InlineChoices.mjs +2 -6
- package/dist/jsx/fields/Select/InlineChoices.mjs.map +1 -1
- package/dist/jsx/fields/Select/InlineChoices.native.js +4 -8
- package/dist/jsx/fields/Select/InlineChoices.native.js.map +1 -1
- package/dist/jsx/fields/Select/index.mjs +68 -204
- package/dist/jsx/fields/Select/index.mjs.map +1 -1
- package/dist/jsx/fields/Select/index.native.js +74 -209
- package/dist/jsx/fields/Select/index.native.js.map +1 -1
- package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.mjs +3 -3
- package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.mjs.map +1 -1
- package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js +2 -2
- package/dist/jsx/fields/nativeDateTime/OsDateTimeSheet.native.js.map +1 -1
- package/dist/jsx/index.js +3 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +3 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +4 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/shared/CheckGlyph.mjs +15 -0
- package/dist/jsx/shared/CheckGlyph.mjs.map +1 -0
- package/dist/jsx/shared/CheckGlyph.native.js +44 -0
- package/dist/jsx/shared/CheckGlyph.native.js.map +1 -0
- package/dist/jsx/shared/checkedOnField.mjs +76 -0
- package/dist/jsx/shared/checkedOnField.mjs.map +1 -0
- package/dist/jsx/shared/checkedOnField.native.js +117 -0
- package/dist/jsx/shared/checkedOnField.native.js.map +1 -0
- package/dist/jsx/shared/floatingList.mjs +9 -5
- package/dist/jsx/shared/floatingList.mjs.map +1 -1
- package/dist/jsx/shared/floatingList.native.js +15 -7
- package/dist/jsx/shared/floatingList.native.js.map +1 -1
- package/package.json +8 -8
- package/src/AdaptivePopup/index.tsx +6 -3
- package/src/Button/Button.iconButton.spec.tsx +39 -0
- package/src/Button/index.tsx +20 -8
- package/src/FloatingPanel/FloatingPanel.iconCover.spec.tsx +279 -0
- package/src/FloatingPanel/FloatingPanel.menuFace.native.spec.tsx +78 -69
- package/src/FloatingPanel/FloatingPanel.seamlessCover.spec.tsx +12 -0
- package/src/FloatingPanel/PanelHeader.tsx +4 -12
- package/src/FloatingPanel/coverRect.ts +2 -15
- package/src/FloatingPanel/echoContext.ts +6 -40
- package/src/FloatingPanel/index.native.tsx +209 -144
- package/src/FloatingPanel/index.tsx +71 -187
- package/src/FloatingPanel/pointAnchor.spec.ts +1 -1
- package/src/FloatingPanel/pointAnchor.ts +4 -4
- package/src/FloatingPanel/sheetGrabber.spec.tsx +53 -0
- package/src/fields/Combobox/index.tsx +4 -9
- package/src/fields/Select/InlineChoices.tsx +2 -2
- package/src/fields/Select/Select.containingBlock.spec.tsx +131 -130
- package/src/fields/Select/Select.popUp.native.spec.tsx +276 -0
- package/src/fields/Select/Select.stories.tsx +26 -0
- package/src/fields/Select/index.tsx +84 -255
- package/src/fields/nativeDateTime/OsDateTimeSheet.tsx +3 -3
- package/src/index.ts +2 -1
- package/src/shared/CheckGlyph.tsx +12 -0
- package/src/shared/checkedOnField.ts +116 -0
- package/src/shared/floatingList.spec.tsx +154 -1
- package/src/shared/floatingList.tsx +18 -9
- package/types/AdaptivePopup/index.d.ts.map +1 -1
- package/types/Button/index.d.ts.map +1 -1
- package/types/FloatingPanel/PanelHeader.d.ts +1 -6
- package/types/FloatingPanel/PanelHeader.d.ts.map +1 -1
- package/types/FloatingPanel/coverRect.d.ts +2 -11
- package/types/FloatingPanel/coverRect.d.ts.map +1 -1
- package/types/FloatingPanel/echoContext.d.ts +5 -22
- package/types/FloatingPanel/echoContext.d.ts.map +1 -1
- package/types/FloatingPanel/index.d.ts +22 -9
- package/types/FloatingPanel/index.d.ts.map +1 -1
- package/types/FloatingPanel/index.native.d.ts +8 -1
- package/types/FloatingPanel/index.native.d.ts.map +1 -1
- package/types/FloatingPanel/pointAnchor.d.ts +4 -4
- package/types/fields/Combobox/index.d.ts.map +1 -1
- package/types/fields/Select/index.d.ts.map +1 -1
- package/types/index.d.ts +2 -1
- package/types/index.d.ts.map +1 -1
- package/types/shared/CheckGlyph.d.ts +10 -0
- package/types/shared/CheckGlyph.d.ts.map +1 -0
- package/types/shared/checkedOnField.d.ts +54 -0
- package/types/shared/checkedOnField.d.ts.map +1 -0
- package/types/shared/floatingList.d.ts +5 -2
- package/types/shared/floatingList.d.ts.map +1 -1
- package/dist/cjs/FloatingPanel/iconEcho.cjs +0 -106
- package/dist/cjs/FloatingPanel/iconEcho.native.js +0 -116
- package/dist/cjs/FloatingPanel/iconEcho.native.js.map +0 -1
- package/dist/esm/FloatingPanel/iconEcho.mjs +0 -79
- package/dist/esm/FloatingPanel/iconEcho.mjs.map +0 -1
- package/dist/esm/FloatingPanel/iconEcho.native.js +0 -86
- package/dist/esm/FloatingPanel/iconEcho.native.js.map +0 -1
- package/dist/jsx/FloatingPanel/iconEcho.mjs +0 -79
- package/dist/jsx/FloatingPanel/iconEcho.mjs.map +0 -1
- package/dist/jsx/FloatingPanel/iconEcho.native.js +0 -116
- package/dist/jsx/FloatingPanel/iconEcho.native.js.map +0 -1
- package/src/FloatingPanel/FloatingPanel.iconEcho.spec.tsx +0 -357
- package/src/FloatingPanel/iconEcho.tsx +0 -124
- package/types/FloatingPanel/iconEcho.d.ts +0 -29
- package/types/FloatingPanel/iconEcho.d.ts.map +0 -1
|
@@ -61,10 +61,25 @@
|
|
|
61
61
|
* OVERLAY_BREAKPOINT the sheet is the wrong form. The panel opens over its
|
|
62
62
|
* field the way the web float does (LC-105, LC-112), sized by `widthMode`;
|
|
63
63
|
* compact windows (iPhone, Slide Over) keep the sheet. `sheet` forces it.
|
|
64
|
+
*
|
|
65
|
+
* Pop-up (`popUp`, FZ-8655): a Select's menu face opens the way a macOS pop-up
|
|
66
|
+
* does, as the web's covering Select does. The rows are measured here, the
|
|
67
|
+
* caller reports the row that goes on the field, and `placeCheckedOnField`
|
|
68
|
+
* (shared with the web) places the panel. It's a touch list, so a panel keeps
|
|
69
|
+
* its box as it scrolls, as a UIMenu does, where a pointer's grows
|
|
70
|
+
* (`growOnScroll`).
|
|
64
71
|
*/
|
|
65
72
|
|
|
66
|
-
import {
|
|
73
|
+
import { CaretDownIcon, CaretUpIcon } from "@phosphor-icons/react";
|
|
74
|
+
import {
|
|
75
|
+
nativeAnimationConfig,
|
|
76
|
+
type MotionStop,
|
|
77
|
+
overlayScrim,
|
|
78
|
+
sheetGrabber,
|
|
79
|
+
sheetGrabberZone,
|
|
80
|
+
} from "@multiplatform.one/theme";
|
|
67
81
|
import {
|
|
82
|
+
type ComponentRef,
|
|
68
83
|
isValidElement,
|
|
69
84
|
type ReactNode,
|
|
70
85
|
useCallback,
|
|
@@ -88,15 +103,22 @@ import {
|
|
|
88
103
|
useWindowDimensions,
|
|
89
104
|
View as RNView,
|
|
90
105
|
type GestureResponderEvent,
|
|
106
|
+
type NativeScrollEvent,
|
|
107
|
+
type NativeSyntheticEvent,
|
|
91
108
|
} from "react-native";
|
|
92
109
|
import { SafeAreaInsetsContext, initialWindowMetrics } from "react-native-safe-area-context";
|
|
93
110
|
import {
|
|
94
111
|
Surface,
|
|
95
|
-
|
|
112
|
+
useGlyphColor,
|
|
96
113
|
useResolvedKnobs,
|
|
97
114
|
motionDurationMs,
|
|
98
115
|
} from "@multiplatform.one/theme";
|
|
99
|
-
import { View, YStack } from "tamagui";
|
|
116
|
+
import { getTokenValue, View, YStack } from "tamagui";
|
|
117
|
+
import {
|
|
118
|
+
placeCheckedOnField,
|
|
119
|
+
scrollArrowBand,
|
|
120
|
+
scrollArrowThreshold,
|
|
121
|
+
} from "../shared/checkedOnField";
|
|
100
122
|
import { useInsideOverlay, useOverlayZIndex } from "../shared/overlayStack";
|
|
101
123
|
import { OverlayWindow } from "../shared/OverlayWindow";
|
|
102
124
|
import { t } from "../shared/t";
|
|
@@ -105,12 +127,7 @@ import { useKeyboardInset } from "../shared/useKeyboardInset";
|
|
|
105
127
|
import type { FloatingPanelProps } from "./index";
|
|
106
128
|
import { MENU_MIN_WIDTH, resolveCompactFace } from "./compactFace";
|
|
107
129
|
import { echoOffset, type PanelWidth, panelWidthBox, screenBounds } from "./panelWidth";
|
|
108
|
-
import {
|
|
109
|
-
echoHeaderBox,
|
|
110
|
-
PanelEchoContext,
|
|
111
|
-
PanelIconEchoBoxContext,
|
|
112
|
-
PanelTriggerRadiusContext,
|
|
113
|
-
} from "./echoContext";
|
|
130
|
+
import { PanelEchoContext, PanelSheetContext, PanelTriggerRadiusContext } from "./echoContext";
|
|
114
131
|
import {
|
|
115
132
|
placeAtPoint,
|
|
116
133
|
placeBesideTrigger,
|
|
@@ -122,8 +139,7 @@ import {
|
|
|
122
139
|
import { RegularPanel } from "./RegularPanel";
|
|
123
140
|
import { panelViewportPadding, resolvePanelWidthMode } from "./useFloatingPanel";
|
|
124
141
|
import { TrailingActionOverlay, TriggerWithTrailingAction } from "./trailingAction";
|
|
125
|
-
import {
|
|
126
|
-
import { echoInCover, iconCoverRect } from "./coverRect";
|
|
142
|
+
import { iconCoverRect } from "./coverRect";
|
|
127
143
|
import {
|
|
128
144
|
IconButtonGroupSurfaceContext,
|
|
129
145
|
useIconButtonGroupSurface,
|
|
@@ -184,7 +200,8 @@ export function FloatingPanel({
|
|
|
184
200
|
triggerRow,
|
|
185
201
|
triggerEcho = true,
|
|
186
202
|
coverAlign = "start",
|
|
187
|
-
|
|
203
|
+
iconCover = false,
|
|
204
|
+
popUp,
|
|
188
205
|
anchorMode,
|
|
189
206
|
panelWidth = "content",
|
|
190
207
|
sheet,
|
|
@@ -193,7 +210,6 @@ export function FloatingPanel({
|
|
|
193
210
|
}: FloatingPanelProps) {
|
|
194
211
|
// The panel floats over the page: it never inherits a painted ancestor.
|
|
195
212
|
const { knobProps } = useResolvedKnobs({ painted: false });
|
|
196
|
-
const triggerSurface = SurfaceContext.useStyledContext();
|
|
197
213
|
const windowZIndex = useOverlayZIndex("sheet");
|
|
198
214
|
// A grouped trigger's capsule is its own: a panel's content never covers it.
|
|
199
215
|
const children = (
|
|
@@ -254,7 +270,7 @@ export function FloatingPanel({
|
|
|
254
270
|
const insideOverlay = useInsideOverlay();
|
|
255
271
|
const asMenu = isContextMenu
|
|
256
272
|
? compactFace === "menu"
|
|
257
|
-
: resolveCompactFace(compactFace, insideOverlay) === "menu";
|
|
273
|
+
: resolveCompactFace(compactFace, insideOverlay) === "menu" || (popUp != null && regular);
|
|
258
274
|
const asRegular = regular && !asMenu && !isContextMenu && sheet !== true;
|
|
259
275
|
const anchored = asMenu || asRegular;
|
|
260
276
|
const triggerRef = useRef<RNView | null>(null);
|
|
@@ -289,7 +305,7 @@ export function FloatingPanel({
|
|
|
289
305
|
} else {
|
|
290
306
|
setAnchor({ x: 0, y: 0, width: 0, height: 0 });
|
|
291
307
|
}
|
|
292
|
-
if (
|
|
308
|
+
if (iconCover && anchorMode !== "attach" && groupSurface) {
|
|
293
309
|
setGroup(undefined);
|
|
294
310
|
groupSurface.measure((plate) => {
|
|
295
311
|
if (live) setGroup(plate);
|
|
@@ -300,7 +316,7 @@ export function FloatingPanel({
|
|
|
300
316
|
return () => {
|
|
301
317
|
live = false;
|
|
302
318
|
};
|
|
303
|
-
}, [anchored, open,
|
|
319
|
+
}, [anchored, open, iconCover, anchorMode, groupSurface]);
|
|
304
320
|
|
|
305
321
|
const handleBackdropPress = useCallback(() => {
|
|
306
322
|
if (backdropArmed) close();
|
|
@@ -669,15 +685,11 @@ export function FloatingPanel({
|
|
|
669
685
|
Math.max(safeArea?.bottom ?? 0, keyboardInset) -
|
|
670
686
|
panelViewportPadding,
|
|
671
687
|
}}
|
|
672
|
-
echo={triggerEcho && !
|
|
688
|
+
echo={triggerEcho && !iconCover && !popUp ? (triggerRow ?? trigger) : null}
|
|
673
689
|
echoLabel={triggerA11y?.label}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
: null
|
|
678
|
-
}
|
|
679
|
-
iconEchoKind={iconEcho}
|
|
680
|
-
group={iconEcho && anchorMode !== "attach" ? (group ?? null) : null}
|
|
690
|
+
popUp={popUp}
|
|
691
|
+
iconCover={iconCover && anchorMode !== "attach"}
|
|
692
|
+
group={iconCover && anchorMode !== "attach" ? (group ?? null) : null}
|
|
681
693
|
coverAlign={anchorMode === "attach" ? "start" : coverAlign}
|
|
682
694
|
panelWidth={panelWidth}
|
|
683
695
|
triggerRadius={anchorMode === "attach" ? null : triggerRadius}
|
|
@@ -749,7 +761,7 @@ export function FloatingPanel({
|
|
|
749
761
|
accessibilityRole="button"
|
|
750
762
|
accessibilityLabel={t("Close")}
|
|
751
763
|
>
|
|
752
|
-
<View flex={1} backgroundColor=
|
|
764
|
+
<View flex={1} backgroundColor={overlayScrim} />
|
|
753
765
|
</Pressable>
|
|
754
766
|
{/*
|
|
755
767
|
Sheet sits above the absoluteFill backdrop in z-order (later sibling).
|
|
@@ -782,19 +794,23 @@ export function FloatingPanel({
|
|
|
782
794
|
{...knobProps.elevatedSurface}
|
|
783
795
|
borderBottomLeftRadius={0}
|
|
784
796
|
borderBottomRightRadius={0}
|
|
797
|
+
// A sheet spans the screen: only its top edge meets the page,
|
|
798
|
+
// so no side border gutters a full-width row (FZ-8557).
|
|
799
|
+
borderLeftWidth={0}
|
|
800
|
+
borderRightWidth={0}
|
|
801
|
+
borderBottomWidth={0}
|
|
785
802
|
maxHeight={maxHeight}
|
|
786
803
|
flexShrink={1}
|
|
787
804
|
minHeight={0}
|
|
788
805
|
// sheetFill opens at full sheet height (flexShrink keeps the
|
|
789
806
|
// keyboard from pushing the top of the sheet off-screen).
|
|
790
807
|
{...(sheetFill ? { height: maxHeight } : undefined)}
|
|
791
|
-
paddingTop="$2"
|
|
792
808
|
paddingBottom={sheetBottomPadding}
|
|
793
809
|
// VoiceOver escape gesture (two-finger Z) dismisses the sheet.
|
|
794
810
|
onAccessibilityEscape={close}
|
|
795
811
|
>
|
|
796
812
|
{/*
|
|
797
|
-
The grab ZONE, not just the
|
|
813
|
+
The grab ZONE, not just the 5pt pill: a 5pt tall target is
|
|
798
814
|
unhittable. The gesture lives here rather than on the whole
|
|
799
815
|
sheet so it never fights the ScrollView inside it, which is the
|
|
800
816
|
same division iOS uses.
|
|
@@ -803,14 +819,10 @@ export function FloatingPanel({
|
|
|
803
819
|
{...panResponder.panHandlers}
|
|
804
820
|
accessibilityRole="adjustable"
|
|
805
821
|
accessibilityLabel={t("Drag to resize")}
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
alignItems: "center",
|
|
809
|
-
paddingTop: 4,
|
|
810
|
-
paddingBottom: 12,
|
|
811
|
-
}}
|
|
822
|
+
testID="floating-panel-grabber"
|
|
823
|
+
style={sheetGrabberZone}
|
|
812
824
|
>
|
|
813
|
-
<View
|
|
825
|
+
<View {...sheetGrabber} />
|
|
814
826
|
</RNView>
|
|
815
827
|
<YStack
|
|
816
828
|
padding={framePadding}
|
|
@@ -819,8 +831,10 @@ export function FloatingPanel({
|
|
|
819
831
|
{...(sheetFill ? { flex: 1, minHeight: 0 } : undefined)}
|
|
820
832
|
>
|
|
821
833
|
<Surface size="$true">
|
|
822
|
-
|
|
823
|
-
|
|
834
|
+
<PanelSheetContext.Provider value>
|
|
835
|
+
{header}
|
|
836
|
+
{content}
|
|
837
|
+
</PanelSheetContext.Provider>
|
|
824
838
|
</Surface>
|
|
825
839
|
</YStack>
|
|
826
840
|
</YStack>
|
|
@@ -835,9 +849,9 @@ export function FloatingPanel({
|
|
|
835
849
|
|
|
836
850
|
/**
|
|
837
851
|
* The menu over its trigger (LC-112): measured once per open at its natural
|
|
838
|
-
* size, then placed on the trigger's window rect.
|
|
839
|
-
* trigger in the trigger's own box, and pressing it closes the menu, as
|
|
840
|
-
* web echo row does.
|
|
852
|
+
* size, then placed on the trigger's window rect. A field's first row repeats
|
|
853
|
+
* the trigger in the trigger's own box, and pressing it closes the menu, as
|
|
854
|
+
* the web echo row does. An icon trigger repeats nothing (Round 45).
|
|
841
855
|
*/
|
|
842
856
|
function TriggerMenuPanel({
|
|
843
857
|
anchor,
|
|
@@ -845,8 +859,8 @@ function TriggerMenuPanel({
|
|
|
845
859
|
bounds,
|
|
846
860
|
echo,
|
|
847
861
|
echoLabel,
|
|
848
|
-
|
|
849
|
-
|
|
862
|
+
popUp,
|
|
863
|
+
iconCover = false,
|
|
850
864
|
group = null,
|
|
851
865
|
coverAlign,
|
|
852
866
|
panelWidth,
|
|
@@ -862,9 +876,10 @@ function TriggerMenuPanel({
|
|
|
862
876
|
bounds: PanelBounds;
|
|
863
877
|
echo: ReactNode;
|
|
864
878
|
echoLabel?: string;
|
|
865
|
-
/** LC-112 (FZ-
|
|
866
|
-
|
|
867
|
-
|
|
879
|
+
/** LC-112 (FZ-8655): the row that sits on the trigger, a macOS pop-up. */
|
|
880
|
+
popUp?: FloatingPanelProps["popUp"];
|
|
881
|
+
/** LC-112 (FZ-8665): an icon trigger, covered at the surface it is seen on. */
|
|
882
|
+
iconCover?: boolean;
|
|
868
883
|
/** LC-112 (FZ-8550): the glass capsule a grouped trigger sits on. */
|
|
869
884
|
group?: IconButtonGroupPlate | null;
|
|
870
885
|
coverAlign: "start" | "auto";
|
|
@@ -877,12 +892,15 @@ function TriggerMenuPanel({
|
|
|
877
892
|
children: ReactNode;
|
|
878
893
|
}) {
|
|
879
894
|
const { knobProps } = useResolvedKnobs({ painted: false });
|
|
895
|
+
const glyphColor = useGlyphColor();
|
|
880
896
|
const [size, setSize] = useState<{ width: number; height: number } | null>(null);
|
|
897
|
+
const [contentHeight, setContentHeight] = useState<number | null>(null);
|
|
898
|
+
const [scrolled, setScrolled] = useState<{ up: boolean; down: boolean } | null>(null);
|
|
899
|
+
const scrollRef = useRef<ComponentRef<typeof RNScrollView>>(null);
|
|
900
|
+
const offsetRef = useRef(0);
|
|
881
901
|
// LC-112 (FZ-8480, FZ-8550): an icon trigger's panel covers the surface the
|
|
882
|
-
// trigger is seen on, its capsule or its press target
|
|
883
|
-
|
|
884
|
-
const cover = anchor && iconEcho != null ? iconCoverRect(anchor, group) : anchor;
|
|
885
|
-
const echoCover = anchor && cover && iconEcho != null ? echoInCover(anchor, cover) : null;
|
|
902
|
+
// trigger is seen on, its capsule or its press target.
|
|
903
|
+
const cover = anchor && iconCover ? iconCoverRect(anchor, group) : anchor;
|
|
886
904
|
// LC-112 width setting (FZ-8438 r3). `"content"` keeps the iOS pull-down's
|
|
887
905
|
// 250pt floor (FZ-8220), and no panel is narrower than an echoed trigger.
|
|
888
906
|
const room =
|
|
@@ -904,8 +922,31 @@ function TriggerMenuPanel({
|
|
|
904
922
|
echo: echo != null,
|
|
905
923
|
floor: Math.max(MENU_MIN_WIDTH, cover?.width ?? 0),
|
|
906
924
|
});
|
|
907
|
-
const
|
|
908
|
-
|
|
925
|
+
const borderWidth = Number(knobProps.elevatedSurface.borderWidth) || 0;
|
|
926
|
+
const framePaddingToken = getTokenValue(
|
|
927
|
+
framePadding as Parameters<typeof getTokenValue>[0],
|
|
928
|
+
"space",
|
|
929
|
+
);
|
|
930
|
+
const framePaddingPx = typeof framePaddingToken === "number" ? framePaddingToken : 0;
|
|
931
|
+
// LC-112 (FZ-8655): the web's macOS pop-up, from the rows measured here.
|
|
932
|
+
const band = scrollArrowBand(knobProps.menuRow.minHeight);
|
|
933
|
+
const fit =
|
|
934
|
+
anchor && popUp?.row && contentHeight != null
|
|
935
|
+
? placeCheckedOnField({
|
|
936
|
+
fieldTop: anchor.y,
|
|
937
|
+
fieldBottom: anchor.y + anchor.height,
|
|
938
|
+
rowTop: popUp.row.top + framePaddingPx,
|
|
939
|
+
rowHeight: popUp.row.height,
|
|
940
|
+
contentHeight,
|
|
941
|
+
boundsTop: bounds.top + borderWidth,
|
|
942
|
+
boundsBottom: bounds.bottom - borderWidth,
|
|
943
|
+
band,
|
|
944
|
+
})
|
|
945
|
+
: null;
|
|
946
|
+
const scrollTop = fit?.scrollTop ?? 0;
|
|
947
|
+
const scrolls = fit != null && contentHeight != null && fit.height < contentHeight;
|
|
948
|
+
const placed =
|
|
949
|
+
anchor && cover && size && (!popUp || fit)
|
|
909
950
|
? (attach ? placeBesideTrigger : placeOverTrigger)({
|
|
910
951
|
trigger: cover,
|
|
911
952
|
width: size.width,
|
|
@@ -913,23 +954,54 @@ function TriggerMenuPanel({
|
|
|
913
954
|
bounds: room,
|
|
914
955
|
rtl: I18nManager.isRTL,
|
|
915
956
|
align: coverAlign,
|
|
916
|
-
pinned:
|
|
957
|
+
pinned: iconCover,
|
|
917
958
|
})
|
|
918
959
|
: null;
|
|
960
|
+
const placement =
|
|
961
|
+
placed && fit
|
|
962
|
+
? { ...placed, top: fit.top - borderWidth, maxHeight: fit.height + 2 * borderWidth }
|
|
963
|
+
: placed;
|
|
964
|
+
useLayoutEffect(() => {
|
|
965
|
+
offsetRef.current = scrollTop;
|
|
966
|
+
if (scrollTop > 0) scrollRef.current?.scrollTo({ y: scrollTop, animated: false });
|
|
967
|
+
}, [scrollTop]);
|
|
968
|
+
const atRest = {
|
|
969
|
+
up: scrolls && scrollTop > scrollArrowThreshold,
|
|
970
|
+
down:
|
|
971
|
+
scrolls &&
|
|
972
|
+
fit != null &&
|
|
973
|
+
contentHeight != null &&
|
|
974
|
+
contentHeight - scrollTop - fit.height > scrollArrowThreshold,
|
|
975
|
+
};
|
|
976
|
+
const arrows = scrolled ?? atRest;
|
|
977
|
+
const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
978
|
+
if (!scrolls) return;
|
|
979
|
+
const { contentOffset, contentSize, layoutMeasurement } = event.nativeEvent;
|
|
980
|
+
offsetRef.current = contentOffset.y;
|
|
981
|
+
const up = contentOffset.y > scrollArrowThreshold;
|
|
982
|
+
const down =
|
|
983
|
+
contentSize.height - contentOffset.y - layoutMeasurement.height > scrollArrowThreshold;
|
|
984
|
+
setScrolled((prev) => (prev?.up === up && prev?.down === down ? prev : { up, down }));
|
|
985
|
+
};
|
|
986
|
+
// A band's tap turns the page, less a row, so nothing goes unseen.
|
|
987
|
+
const scrollPage = (direction: "up" | "down") => {
|
|
988
|
+
if (!fit) return;
|
|
989
|
+
const page = Math.max(band, fit.height - 2 * band - (popUp?.row?.height ?? 0));
|
|
990
|
+
const next = offsetRef.current + (direction === "up" ? -page : page);
|
|
991
|
+
scrollRef.current?.scrollTo({ y: Math.max(0, next), animated: true });
|
|
992
|
+
};
|
|
919
993
|
// LC-112 seamless cover: the menu is its trigger grown open, so it draws the
|
|
920
994
|
// trigger's corner arc at all four corners. A field reports its radius; an
|
|
921
995
|
// icon button with no echo is a circle or capsule, half its short side.
|
|
922
996
|
const half = cover ? Math.min(cover.width, cover.height) / 2 : undefined;
|
|
923
997
|
const radius =
|
|
924
|
-
group != null &&
|
|
998
|
+
group != null && iconCover
|
|
925
999
|
? Math.min(group.radius, half ?? group.radius)
|
|
926
1000
|
: triggerRadius != null && half != null
|
|
927
1001
|
? Math.min(triggerRadius, half)
|
|
928
1002
|
: coverAlign === "auto" && half
|
|
929
1003
|
? half
|
|
930
1004
|
: undefined;
|
|
931
|
-
const borderWidth = Number(knobProps.elevatedSurface.borderWidth) || 0;
|
|
932
|
-
const echoOverlays = iconEchoOverlays(iconEchoKind, placement?.up ?? false);
|
|
933
1005
|
// A panel slid along the screen (a `"screen"` or fixed width, or one pushed
|
|
934
1006
|
// back inside the margins) keeps its echo on the trigger.
|
|
935
1007
|
const echoShift =
|
|
@@ -943,7 +1015,11 @@ function TriggerMenuPanel({
|
|
|
943
1015
|
})
|
|
944
1016
|
: 0;
|
|
945
1017
|
return (
|
|
946
|
-
<RNView
|
|
1018
|
+
<RNView
|
|
1019
|
+
style={StyleSheet.absoluteFill}
|
|
1020
|
+
testID="floating-panel-menu-layer"
|
|
1021
|
+
accessibilityViewIsModal
|
|
1022
|
+
>
|
|
947
1023
|
<Pressable
|
|
948
1024
|
style={StyleSheet.absoluteFill}
|
|
949
1025
|
onPress={onBackdropPress}
|
|
@@ -1013,49 +1089,47 @@ function TriggerMenuPanel({
|
|
|
1013
1089
|
</RNView>
|
|
1014
1090
|
</Pressable>
|
|
1015
1091
|
) : null}
|
|
1016
|
-
{iconEcho != null && anchor && !placement?.up && !echoOverlays ? (
|
|
1017
|
-
<IconEchoBand
|
|
1018
|
-
anchor={anchor}
|
|
1019
|
-
cover={echoCover}
|
|
1020
|
-
shift={echoShift}
|
|
1021
|
-
borderWidth={borderWidth}
|
|
1022
|
-
edge="top"
|
|
1023
|
-
>
|
|
1024
|
-
{iconEcho}
|
|
1025
|
-
</IconEchoBand>
|
|
1026
|
-
) : null}
|
|
1027
1092
|
<RNScrollView
|
|
1093
|
+
ref={scrollRef}
|
|
1028
1094
|
style={{ flexGrow: 0, flexShrink: 1 }}
|
|
1029
1095
|
keyboardShouldPersistTaps="handled"
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
width: anchor.width,
|
|
1038
|
-
height: echoCover?.height ?? anchor.height,
|
|
1039
|
-
panelWidth: placement.width,
|
|
1040
|
-
rtl: I18nManager.isRTL,
|
|
1041
|
-
})
|
|
1042
|
-
: null
|
|
1096
|
+
{...(popUp
|
|
1097
|
+
? {
|
|
1098
|
+
contentOffset: { x: 0, y: scrollTop },
|
|
1099
|
+
scrollEnabled: scrolls,
|
|
1100
|
+
bounces: scrolls,
|
|
1101
|
+
onScroll: handleScroll,
|
|
1102
|
+
scrollEventThrottle: 16,
|
|
1043
1103
|
}
|
|
1044
|
-
|
|
1104
|
+
: null)}
|
|
1105
|
+
>
|
|
1106
|
+
<RNView
|
|
1107
|
+
testID="floating-panel-menu-content"
|
|
1108
|
+
collapsable={false}
|
|
1109
|
+
onLayout={popUp ? (e) => setContentHeight(e.nativeEvent.layout.height) : undefined}
|
|
1110
|
+
>
|
|
1111
|
+
<YStack padding={framePadding} gap={frameGap}>
|
|
1045
1112
|
{children}
|
|
1046
|
-
</
|
|
1047
|
-
</
|
|
1113
|
+
</YStack>
|
|
1114
|
+
</RNView>
|
|
1048
1115
|
</RNScrollView>
|
|
1049
|
-
{
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1116
|
+
{scrolls ? (
|
|
1117
|
+
<>
|
|
1118
|
+
<ScrollBand
|
|
1119
|
+
direction="up"
|
|
1120
|
+
band={band}
|
|
1121
|
+
visible={arrows.up}
|
|
1122
|
+
glyphColor={glyphColor}
|
|
1123
|
+
onPress={scrollPage}
|
|
1124
|
+
/>
|
|
1125
|
+
<ScrollBand
|
|
1126
|
+
direction="down"
|
|
1127
|
+
band={band}
|
|
1128
|
+
visible={arrows.down}
|
|
1129
|
+
glyphColor={glyphColor}
|
|
1130
|
+
onPress={scrollPage}
|
|
1131
|
+
/>
|
|
1132
|
+
</>
|
|
1059
1133
|
) : null}
|
|
1060
1134
|
</YStack>
|
|
1061
1135
|
</YStack>
|
|
@@ -1065,63 +1139,50 @@ function TriggerMenuPanel({
|
|
|
1065
1139
|
}
|
|
1066
1140
|
|
|
1067
1141
|
/**
|
|
1068
|
-
*
|
|
1069
|
-
*
|
|
1070
|
-
*
|
|
1071
|
-
* over the frame's border so it lands exactly where the trigger is.
|
|
1142
|
+
* A pop-up's scroll arrow on native (LC-112, FZ-8655): the web's opaque band in
|
|
1143
|
+
* the panel's own fill, half a menu row at a clipped edge, so a cut row hides
|
|
1144
|
+
* under it. A tap on it stays off the row beneath and turns the page.
|
|
1072
1145
|
*/
|
|
1073
|
-
function
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
children,
|
|
1146
|
+
function ScrollBand({
|
|
1147
|
+
direction,
|
|
1148
|
+
band,
|
|
1149
|
+
visible,
|
|
1150
|
+
glyphColor,
|
|
1151
|
+
onPress,
|
|
1080
1152
|
}: {
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
/** `"overlay"`: an X laid over the content's top corner, taking no height. */
|
|
1087
|
-
edge: "top" | "bottom" | "overlay";
|
|
1088
|
-
children: ReactNode;
|
|
1153
|
+
direction: "up" | "down";
|
|
1154
|
+
band: number;
|
|
1155
|
+
visible: boolean;
|
|
1156
|
+
glyphColor: string;
|
|
1157
|
+
onPress: (direction: "up" | "down") => void;
|
|
1089
1158
|
}) {
|
|
1090
|
-
const
|
|
1159
|
+
const { knobProps } = useResolvedKnobs({ painted: false });
|
|
1160
|
+
const Icon = direction === "up" ? CaretUpIcon : CaretDownIcon;
|
|
1161
|
+
if (!visible) return null;
|
|
1091
1162
|
return (
|
|
1092
|
-
<
|
|
1093
|
-
testID=
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
: {
|
|
1106
|
-
height: bandHeight,
|
|
1107
|
-
marginHorizontal: -borderWidth,
|
|
1108
|
-
...(edge === "top" ? { marginTop: -borderWidth } : { marginBottom: -borderWidth }),
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1163
|
+
<Pressable
|
|
1164
|
+
testID={`floating-panel-scroll-${direction}`}
|
|
1165
|
+
onPress={() => onPress(direction)}
|
|
1166
|
+
accessibilityElementsHidden
|
|
1167
|
+
importantForAccessibility="no-hide-descendants"
|
|
1168
|
+
style={{
|
|
1169
|
+
position: "absolute",
|
|
1170
|
+
start: 0,
|
|
1171
|
+
end: 0,
|
|
1172
|
+
height: band,
|
|
1173
|
+
zIndex: 1,
|
|
1174
|
+
...(direction === "up" ? { top: 0 } : { bottom: 0 }),
|
|
1175
|
+
}}
|
|
1111
1176
|
>
|
|
1112
|
-
<
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
marginTop: cover?.top ?? 0,
|
|
1118
|
-
alignItems: "flex-start",
|
|
1119
|
-
justifyContent: "flex-start",
|
|
1120
|
-
}}
|
|
1177
|
+
<View
|
|
1178
|
+
flex={1}
|
|
1179
|
+
alignItems="center"
|
|
1180
|
+
justifyContent="center"
|
|
1181
|
+
backgroundColor={knobProps.elevatedSurface.backgroundColor}
|
|
1121
1182
|
>
|
|
1122
|
-
{
|
|
1123
|
-
</
|
|
1124
|
-
</
|
|
1183
|
+
<Icon size={knobProps.controlIcon.width} color={glyphColor} />
|
|
1184
|
+
</View>
|
|
1185
|
+
</Pressable>
|
|
1125
1186
|
);
|
|
1126
1187
|
}
|
|
1127
1188
|
|
|
@@ -1159,7 +1220,11 @@ function PointPanel({
|
|
|
1159
1220
|
})
|
|
1160
1221
|
: null;
|
|
1161
1222
|
return (
|
|
1162
|
-
<RNView
|
|
1223
|
+
<RNView
|
|
1224
|
+
style={StyleSheet.absoluteFill}
|
|
1225
|
+
testID="floating-panel-point-layer"
|
|
1226
|
+
accessibilityViewIsModal
|
|
1227
|
+
>
|
|
1163
1228
|
<Pressable
|
|
1164
1229
|
style={StyleSheet.absoluteFill}
|
|
1165
1230
|
onPress={onBackdropPress}
|