panelui-native 0.84.0 → 0.86.0
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/README.md +17 -8
- package/lib/module/components/bottom-sheet/index.js +27 -15
- package/lib/module/components/bottom-sheet/index.js.map +1 -1
- package/lib/module/components/button/index.js +37 -16
- package/lib/module/components/button/index.js.map +1 -1
- package/lib/module/components/flip-card/index.js +338 -0
- package/lib/module/components/flip-card/index.js.map +1 -0
- package/lib/module/components/popover/index.js +3 -2
- package/lib/module/components/popover/index.js.map +1 -1
- package/lib/module/components/progress-button/index.js +83 -18
- package/lib/module/components/progress-button/index.js.map +1 -1
- package/lib/module/components/select/index.js +3 -2
- package/lib/module/components/select/index.js.map +1 -1
- package/lib/module/components/slider/index.js +16 -5
- package/lib/module/components/slider/index.js.map +1 -1
- package/lib/module/components/switch/index.js +28 -7
- package/lib/module/components/switch/index.js.map +1 -1
- package/lib/module/components/tabs/index.js +119 -28
- package/lib/module/components/tabs/index.js.map +1 -1
- package/lib/module/hooks/use-keyboard-avoidance.js +37 -6
- package/lib/module/hooks/use-keyboard-avoidance.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/native/index.js +7 -0
- package/lib/module/native/index.js.map +1 -1
- package/lib/module/native/native-host.js +62 -0
- package/lib/module/native/native-host.js.map +1 -0
- package/lib/module/primitives/glass.js +14 -0
- package/lib/module/primitives/glass.js.map +1 -1
- package/lib/module/providers/panel-ui-provider.js +35 -7
- package/lib/module/providers/panel-ui-provider.js.map +1 -1
- package/lib/typescript/src/components/bottom-sheet/index.d.ts.map +1 -1
- package/lib/typescript/src/components/button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/flip-card/index.d.ts +116 -0
- package/lib/typescript/src/components/flip-card/index.d.ts.map +1 -0
- package/lib/typescript/src/components/progress-button/index.d.ts +38 -0
- package/lib/typescript/src/components/progress-button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/slider/index.d.ts.map +1 -1
- package/lib/typescript/src/components/switch/index.d.ts +0 -4
- package/lib/typescript/src/components/switch/index.d.ts.map +1 -1
- package/lib/typescript/src/components/tabs/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native/index.d.ts +28 -11
- package/lib/typescript/src/native/index.d.ts.map +1 -1
- package/lib/typescript/src/native/native-host.d.ts +71 -0
- package/lib/typescript/src/native/native-host.d.ts.map +1 -0
- package/lib/typescript/src/primitives/glass.d.ts.map +1 -1
- package/lib/typescript/src/providers/panel-ui-provider.d.ts.map +1 -1
- package/package.json +11 -1
- package/src/components/bottom-sheet/index.tsx +31 -16
- package/src/components/button/index.tsx +36 -15
- package/src/components/flip-card/index.tsx +419 -0
- package/src/components/popover/index.tsx +3 -3
- package/src/components/progress-button/index.tsx +58 -18
- package/src/components/select/index.tsx +3 -3
- package/src/components/slider/index.tsx +28 -6
- package/src/components/switch/index.tsx +28 -7
- package/src/components/tabs/index.tsx +112 -31
- package/src/hooks/use-keyboard-avoidance.ts +39 -5
- package/src/index.ts +9 -0
- package/src/native/index.ts +35 -10
- package/src/native/native-host.tsx +75 -0
- package/src/primitives/glass.tsx +12 -0
- package/src/providers/panel-ui-provider.tsx +39 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/native/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/native/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The host every native control is mounted in, told which appearance to draw.
|
|
3
|
+
*
|
|
4
|
+
* A hosting controller resolves its colour scheme from the trait environment
|
|
5
|
+
* it is placed in, which is the system appearance — not the theme the app is
|
|
6
|
+
* running. Those are the same thing only by coincidence: an app in a dark
|
|
7
|
+
* theme on a phone set to light gets a light platform control beside dark
|
|
8
|
+
* content, and a theme changed at runtime leaves the control where it was,
|
|
9
|
+
* because nothing in the trait environment moved.
|
|
10
|
+
*
|
|
11
|
+
* So the appearance is passed rather than inferred. `colorScheme` is the one
|
|
12
|
+
* theme signal the platform toolkit accepts, and this is the single place it
|
|
13
|
+
* is given.
|
|
14
|
+
*
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const { Host, Switch: NativeSwitch } = nativeUI;
|
|
17
|
+
* <NativeHost host={Host} matchContents ignoreSafeArea="keyboard">
|
|
18
|
+
* <NativeSwitch value={on} onValueChange={setOn} />
|
|
19
|
+
* </NativeHost>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ## Why the host arrives as a prop
|
|
23
|
+
*
|
|
24
|
+
* There are two of them. The universal `Host` comes from `getNativeUI()` and
|
|
25
|
+
* the SwiftUI-only one from `getSwiftUI()`, and a caller has already resolved
|
|
26
|
+
* whichever it needs before it renders. Taking the component rather than
|
|
27
|
+
* resolving it again keeps this file free of the module bridge, which is what
|
|
28
|
+
* lets the bridge re-export it without the two importing each other.
|
|
29
|
+
*
|
|
30
|
+
* ## Why this is a component rather than a hook at each call site
|
|
31
|
+
*
|
|
32
|
+
* `useThemeMode` subscribes to theme changes, and a hook cannot be called
|
|
33
|
+
* conditionally — so reading it inside `Button` would put a subscription on
|
|
34
|
+
* every button in a list for a branch almost none of them take. Here the
|
|
35
|
+
* subscription exists only where a native host is actually mounted.
|
|
36
|
+
*/
|
|
37
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
38
|
+
/**
|
|
39
|
+
* What this renders the host with. A type alias rather than an interface, and
|
|
40
|
+
* that is load-bearing: only an alias gets an implicit index signature, which
|
|
41
|
+
* is what makes it assignable to the bridge's own `Host` prop type.
|
|
42
|
+
*/
|
|
43
|
+
type NativeHostRenderProps = {
|
|
44
|
+
children?: ReactNode;
|
|
45
|
+
colorScheme?: 'light' | 'dark';
|
|
46
|
+
matchContents?: boolean | {
|
|
47
|
+
vertical?: boolean;
|
|
48
|
+
horizontal?: boolean;
|
|
49
|
+
};
|
|
50
|
+
ignoreSafeArea?: 'all' | 'container' | 'keyboard';
|
|
51
|
+
style?: unknown;
|
|
52
|
+
};
|
|
53
|
+
export interface NativeHostProps {
|
|
54
|
+
/**
|
|
55
|
+
* The host component to render — `Host` from `getNativeUI()` for a portable
|
|
56
|
+
* control, or from `getSwiftUI()` for an iOS-only one.
|
|
57
|
+
*/
|
|
58
|
+
host: ComponentType<NativeHostRenderProps>;
|
|
59
|
+
children?: ReactNode;
|
|
60
|
+
/** Whether the host resizes itself to the platform content. */
|
|
61
|
+
matchContents?: boolean | {
|
|
62
|
+
vertical?: boolean;
|
|
63
|
+
horizontal?: boolean;
|
|
64
|
+
};
|
|
65
|
+
/** Which safe areas the host lets the platform inset its content for. */
|
|
66
|
+
ignoreSafeArea?: 'all' | 'container' | 'keyboard';
|
|
67
|
+
style?: unknown;
|
|
68
|
+
}
|
|
69
|
+
export declare function NativeHost({ host: Host, children, ...props }: NativeHostProps): import("react").JSX.Element;
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=native-host.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-host.d.ts","sourceRoot":"","sources":["../../../../src/native/native-host.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGtD;;;;GAIG;AACH,KAAK,qBAAqB,GAAG;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B,aAAa,CAAC,EAAE,OAAO,GAAG;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACvE,cAAc,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,IAAI,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IAC3C,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,OAAO,GAAG;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACvE,yEAAyE;IACzE,cAAc,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,+BAQ7E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glass.d.ts","sourceRoot":"","sources":["../../../../src/primitives/glass.tsx"],"names":[],"mappings":"AA6CA,OAAO,EAA8C,KAAK,SAAS,EAAkB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"glass.d.ts","sourceRoot":"","sources":["../../../../src/primitives/glass.tsx"],"names":[],"mappings":"AA6CA,OAAO,EAA8C,KAAK,SAAS,EAAkB,MAAM,cAAc,CAAC;AAK1G,iDAAiD;AACjD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAE/C;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAkDrE;;;;GAIG;AACH,eAAO,MAAM,QAAQ,SAAqB,CAAC;AAE3C,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,KAAK,CAAC,EACpB,OAAmB,EACnB,IAAI,EACJ,MAAM,EACN,iBAA6B,EAC7B,SAAS,EACT,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACT,EAAE,UAAU,+BAmCZ;yBA5Ce,KAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panel-ui-provider.d.ts","sourceRoot":"","sources":["../../../../src/providers/panel-ui-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"panel-ui-provider.d.ts","sourceRoot":"","sources":["../../../../src/providers/panel-ui-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAwDrE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,UAAiB,GAClB,EAAE,oBAAoB,+BAqBtB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "panelui-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.86.0",
|
|
4
4
|
"description": "High-performance React Native UI components for Expo. Semantic design tokens, powered by Uniwind (Tailwind v4) and Reanimated.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"module": "./lib/module/index.js",
|
|
@@ -32,6 +32,16 @@
|
|
|
32
32
|
"react-native": "./src/theme/use-theme.ts",
|
|
33
33
|
"default": "./lib/module/theme/use-theme.js"
|
|
34
34
|
},
|
|
35
|
+
"./icons": {
|
|
36
|
+
"types": "./lib/typescript/src/icons/index.d.ts",
|
|
37
|
+
"react-native": "./src/icons/index.tsx",
|
|
38
|
+
"default": "./lib/module/icons/index.js"
|
|
39
|
+
},
|
|
40
|
+
"./primitives/text": {
|
|
41
|
+
"types": "./lib/typescript/src/primitives/text.d.ts",
|
|
42
|
+
"react-native": "./src/primitives/text.tsx",
|
|
43
|
+
"default": "./lib/module/primitives/text.js"
|
|
44
|
+
},
|
|
35
45
|
"./primitives/animated-pressable": {
|
|
36
46
|
"types": "./lib/typescript/src/primitives/animated-pressable.d.ts",
|
|
37
47
|
"react-native": "./src/primitives/animated-pressable.tsx",
|
|
@@ -26,7 +26,6 @@ import Animated, {
|
|
|
26
26
|
FadeIn,
|
|
27
27
|
cancelAnimation,
|
|
28
28
|
interpolate,
|
|
29
|
-
SlideInDown,
|
|
30
29
|
runOnJS,
|
|
31
30
|
useAnimatedScrollHandler,
|
|
32
31
|
useAnimatedStyle,
|
|
@@ -38,7 +37,7 @@ import Animated, {
|
|
|
38
37
|
} from 'react-native-reanimated';
|
|
39
38
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
40
39
|
import { tv } from 'tailwind-variants';
|
|
41
|
-
import { getComposeModifiers, getNativeUI, getSwiftUIModifiers } from '../../native';
|
|
40
|
+
import { NativeHost, getComposeModifiers, getNativeUI, getSwiftUIModifiers } from '../../native';
|
|
42
41
|
import { XIcon } from '../../icons';
|
|
43
42
|
import { ModalPortal } from '../../primitives/portal';
|
|
44
43
|
import { Scrim } from '../../primitives/scrim';
|
|
@@ -75,12 +74,6 @@ const EXIT_SPRING = { duration: 380, dampingRatio: 1, overshootClamping: true }
|
|
|
75
74
|
const DISMISS_DISTANCE = 120;
|
|
76
75
|
const DISMISS_VELOCITY = 800;
|
|
77
76
|
|
|
78
|
-
/*
|
|
79
|
-
* Built once at module scope. A layout-animation builder constructed in render
|
|
80
|
-
* is a new object every commit, and the sheet re-renders while it is open.
|
|
81
|
-
*/
|
|
82
|
-
const ENTERING = SlideInDown.springify().dampingRatio(0.9).duration(420);
|
|
83
|
-
|
|
84
77
|
/**
|
|
85
78
|
* Where a flick would come to rest if it kept decelerating — Apple's
|
|
86
79
|
* exponential-decay form.
|
|
@@ -407,7 +400,21 @@ function BottomSheetContent({
|
|
|
407
400
|
const { height: screenHeight, width: screenWidth } = useWindowDimensions();
|
|
408
401
|
const reducedMotion = useReducedMotion();
|
|
409
402
|
const insets = useSafeAreaInsets();
|
|
410
|
-
|
|
403
|
+
/*
|
|
404
|
+
* Starts off screen, and the entrance is this value moving to zero.
|
|
405
|
+
*
|
|
406
|
+
* It used to start at rest and hand the travel to a `SlideInDown` layout
|
|
407
|
+
* animation, which is a different mechanism with a different owner: the
|
|
408
|
+
* backdrop is interpolated from `translateY`, so a sheet parked at that
|
|
409
|
+
* animation's initial offset while `translateY` read zero drew a fully opaque
|
|
410
|
+
* scrim over an empty screen. A layout animation that does not replay on a
|
|
411
|
+
* remount inside the portal — two sheets sharing a screen is enough — left it
|
|
412
|
+
* there for good, with no way back.
|
|
413
|
+
*
|
|
414
|
+
* Under reduced motion there is no travel to make, so it starts at rest and
|
|
415
|
+
* the scrim's fade carries the change on its own.
|
|
416
|
+
*/
|
|
417
|
+
const translateY = useSharedValue(reducedMotion ? 0 : screenHeight);
|
|
411
418
|
const closeTint = useCSSVariable('--color-muted-foreground');
|
|
412
419
|
// Read unconditionally, used only by the native branch: the platform draws
|
|
413
420
|
// that sheet's container, so a token can only reach it as a colour handed
|
|
@@ -456,10 +463,13 @@ function BottomSheetContent({
|
|
|
456
463
|
if (open) {
|
|
457
464
|
cancelAnimation(translateY);
|
|
458
465
|
if (!presented) {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
466
|
+
/*
|
|
467
|
+
* A fresh mount starts off screen and this effect's own re-run — it
|
|
468
|
+
* depends on `presented` — springs it up. Catching one that is still on
|
|
469
|
+
* screen must not reset it under the finger, so this only runs when the
|
|
470
|
+
* sheet had actually gone.
|
|
471
|
+
*/
|
|
472
|
+
translateY.value = reducedMotion ? 0 : screenHeight;
|
|
463
473
|
setPresented(true);
|
|
464
474
|
return;
|
|
465
475
|
}
|
|
@@ -700,7 +710,12 @@ function BottomSheetContent({
|
|
|
700
710
|
// sheet cannot measure RN views directly. Without it the sheet sizes to
|
|
701
711
|
// nothing and the content spills outside its container.
|
|
702
712
|
return (
|
|
703
|
-
<
|
|
713
|
+
<NativeHost
|
|
714
|
+
host={Host}
|
|
715
|
+
matchContents
|
|
716
|
+
ignoreSafeArea="keyboard"
|
|
717
|
+
style={{ position: 'absolute' }}
|
|
718
|
+
>
|
|
704
719
|
<NativeBottomSheet
|
|
705
720
|
isPresented={nativePresented}
|
|
706
721
|
onDismiss={onNativeDismiss}
|
|
@@ -734,7 +749,7 @@ function BottomSheetContent({
|
|
|
734
749
|
</BottomSheetContext.Provider>
|
|
735
750
|
</RNHostView>
|
|
736
751
|
</NativeBottomSheet>
|
|
737
|
-
</
|
|
752
|
+
</NativeHost>
|
|
738
753
|
);
|
|
739
754
|
}
|
|
740
755
|
|
|
@@ -774,7 +789,7 @@ function BottomSheetContent({
|
|
|
774
789
|
* state change still has to be legible, and it is the travel that
|
|
775
790
|
* setting is about.
|
|
776
791
|
*/
|
|
777
|
-
entering={reducedMotion ? FadeIn.duration(150) :
|
|
792
|
+
entering={reducedMotion ? FadeIn.duration(150) : undefined}
|
|
778
793
|
accessibilityViewIsModal
|
|
779
794
|
className={sheetVariants({ detached, className })}
|
|
780
795
|
{...props}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { Text, textChildren } from '../../primitives/text';
|
|
10
10
|
import { cn } from '../../utils/cn';
|
|
11
11
|
import { IconColorProvider } from '../../icons';
|
|
12
|
-
import { getNativeUI, getSwiftUIModifiers } from '../../native';
|
|
12
|
+
import { NativeHost, getNativeUI, getSwiftUIModifiers } from '../../native';
|
|
13
13
|
import { Spinner } from '../spinner';
|
|
14
14
|
|
|
15
15
|
const buttonVariants = tv({
|
|
@@ -233,13 +233,15 @@ export interface ButtonProps
|
|
|
233
233
|
/**
|
|
234
234
|
* Height given to the platform button, matching the styled scale above.
|
|
235
235
|
*
|
|
236
|
-
* It goes on the
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
* the box
|
|
241
|
-
*
|
|
242
|
-
*
|
|
236
|
+
* It goes on the host as well as on the button, and the host is the half that
|
|
237
|
+
* stops the jump. `matchContents` does not mean "size the host once" — it
|
|
238
|
+
* means the host keeps its React Native box equal to whatever SwiftUI most
|
|
239
|
+
* recently laid out, and a button laying itself out again is what a press is.
|
|
240
|
+
* So the box moved under the press, and everything below it moved with it.
|
|
241
|
+
*
|
|
242
|
+
* A height we already know is not a question worth asking the platform, so it
|
|
243
|
+
* is not asked: the host states it, and `matchContents` is narrowed to the
|
|
244
|
+
* axis that is genuinely unknown. See the host in the native branch below.
|
|
243
245
|
*/
|
|
244
246
|
const NATIVE_HEIGHT: Record<NonNullable<ButtonVariantProps['size']>, number> = {
|
|
245
247
|
sm: 36,
|
|
@@ -402,8 +404,31 @@ export const Button = forwardRef<View, ButtonProps>(
|
|
|
402
404
|
*/
|
|
403
405
|
const nativeContent = prominent ? '#ffffff' : contentColor;
|
|
404
406
|
|
|
407
|
+
/*
|
|
408
|
+
* The box React Native reserves for the platform button, stated rather
|
|
409
|
+
* than measured.
|
|
410
|
+
*
|
|
411
|
+
* An icon button is a square we chose, so both axes are known and the
|
|
412
|
+
* host is asked to match nothing. A labelled button's width is its
|
|
413
|
+
* text's and known only to the platform, so the height is stated and
|
|
414
|
+
* only the width is matched.
|
|
415
|
+
*
|
|
416
|
+
* Leaving both to `matchContents` is what made the button move on its
|
|
417
|
+
* first press: the host tracks SwiftUI's latest layout, and a pressed
|
|
418
|
+
* button lays out again.
|
|
419
|
+
*/
|
|
420
|
+
const hostFrame =
|
|
421
|
+
resolvedSize === 'icon'
|
|
422
|
+
? { width: NATIVE_ICON_FRAME, height: NATIVE_ICON_FRAME }
|
|
423
|
+
: { height: NATIVE_HEIGHT[resolvedSize ?? 'md'] };
|
|
424
|
+
|
|
405
425
|
return (
|
|
406
|
-
<
|
|
426
|
+
<NativeHost
|
|
427
|
+
host={Host}
|
|
428
|
+
matchContents={resolvedSize === 'icon' ? false : { horizontal: true }}
|
|
429
|
+
ignoreSafeArea="keyboard"
|
|
430
|
+
style={hostFrame}
|
|
431
|
+
>
|
|
407
432
|
<NativeButton
|
|
408
433
|
label={isStringLabel ? children : undefined}
|
|
409
434
|
// The platform only reads a symbol beside a label it drew itself,
|
|
@@ -421,11 +446,7 @@ export const Button = forwardRef<View, ButtonProps>(
|
|
|
421
446
|
* background around. The frame only has to be large enough to hold
|
|
422
447
|
* the result.
|
|
423
448
|
*/
|
|
424
|
-
style={
|
|
425
|
-
resolvedSize === 'icon'
|
|
426
|
-
? { width: NATIVE_ICON_FRAME, height: NATIVE_ICON_FRAME }
|
|
427
|
-
: { height: NATIVE_HEIGHT[resolvedSize ?? 'md'] }
|
|
428
|
-
}
|
|
449
|
+
style={hostFrame}
|
|
429
450
|
modifiers={nativeModifiers.length ? nativeModifiers : undefined}
|
|
430
451
|
onPress={props.onPress}
|
|
431
452
|
>
|
|
@@ -461,7 +482,7 @@ export const Button = forwardRef<View, ButtonProps>(
|
|
|
461
482
|
</RNHostView>
|
|
462
483
|
)}
|
|
463
484
|
</NativeButton>
|
|
464
|
-
</
|
|
485
|
+
</NativeHost>
|
|
465
486
|
);
|
|
466
487
|
}
|
|
467
488
|
|