@seed-design/lynx-react 0.7.1 → 0.9.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/lib/components/Accordion/Accordion.jsx +2 -2
- package/lib/components/ActionButton/ActionButton.jsx +1 -1
- package/lib/components/AlertDialog/AlertDialog.d.ts +64 -0
- package/lib/components/AlertDialog/AlertDialog.d.ts.map +1 -0
- package/lib/components/AlertDialog/AlertDialog.jsx +138 -0
- package/lib/components/AlertDialog/AlertDialog.namespace.d.ts +2 -0
- package/lib/components/AlertDialog/AlertDialog.namespace.d.ts.map +1 -0
- package/lib/components/AlertDialog/AlertDialog.namespace.js +17 -0
- package/lib/components/AlertDialog/index.d.ts +3 -0
- package/lib/components/AlertDialog/index.d.ts.map +1 -0
- package/lib/components/AppBar/AppBar.d.ts +14 -1
- package/lib/components/AppBar/AppBar.d.ts.map +1 -1
- package/lib/components/AppBar/AppBar.jsx +42 -16
- package/lib/components/AppBar/AppBar.namespace.d.ts +1 -1
- package/lib/components/AppBar/AppBar.namespace.d.ts.map +1 -1
- package/lib/components/AppBar/context.d.ts +2 -1
- package/lib/components/AppBar/context.d.ts.map +1 -1
- package/lib/components/AppBar/index.d.ts +1 -1
- package/lib/components/AppBar/index.d.ts.map +1 -1
- package/lib/components/AppBar/useAppBar.d.ts +2 -1
- package/lib/components/AppBar/useAppBar.d.ts.map +1 -1
- package/lib/components/AppBar/useAppBar.js +17 -15
- package/lib/components/AttachmentDisplay/AttachmentDisplay.d.ts +182 -0
- package/lib/components/AttachmentDisplay/AttachmentDisplay.d.ts.map +1 -0
- package/lib/components/AttachmentDisplay/AttachmentDisplay.jsx +444 -0
- package/lib/components/AttachmentDisplay/index.d.ts +2 -0
- package/lib/components/AttachmentDisplay/index.d.ts.map +1 -0
- package/lib/components/AttachmentInput/AttachmentInput.d.ts +179 -0
- package/lib/components/AttachmentInput/AttachmentInput.d.ts.map +1 -0
- package/lib/components/AttachmentInput/AttachmentInput.jsx +520 -0
- package/lib/components/AttachmentInput/index.d.ts +2 -0
- package/lib/components/AttachmentInput/index.d.ts.map +1 -0
- package/lib/components/BottomSheet/BottomSheet.d.ts +1 -1
- package/lib/components/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/lib/components/BottomSheet/BottomSheet.jsx +1 -7
- package/lib/components/Box/Box.d.ts +3 -3
- package/lib/components/Box/Box.d.ts.map +1 -1
- package/lib/components/Callout/Callout.jsx +2 -2
- package/lib/components/Checkbox/Checkbox.jsx +2 -2
- package/lib/components/Chip/Chip.jsx +2 -2
- package/lib/components/ChipTabs/ChipTabs.d.ts +41 -0
- package/lib/components/ChipTabs/ChipTabs.d.ts.map +1 -0
- package/lib/components/ChipTabs/ChipTabs.jsx +39 -0
- package/lib/components/ChipTabs/ChipTabs.namespace.d.ts +2 -0
- package/lib/components/ChipTabs/ChipTabs.namespace.d.ts.map +1 -0
- package/lib/components/ChipTabs/ChipTabs.namespace.js +13 -0
- package/lib/components/ChipTabs/index.d.ts +3 -0
- package/lib/components/ChipTabs/index.d.ts.map +1 -0
- package/lib/components/ContextualFloatingButton/ContextualFloatingButton.d.ts +18 -0
- package/lib/components/ContextualFloatingButton/ContextualFloatingButton.d.ts.map +1 -0
- package/lib/components/ContextualFloatingButton/ContextualFloatingButton.jsx +113 -0
- package/lib/components/ContextualFloatingButton/index.d.ts +2 -0
- package/lib/components/ContextualFloatingButton/index.d.ts.map +1 -0
- package/lib/components/Dialog/Dialog.d.ts +87 -0
- package/lib/components/Dialog/Dialog.d.ts.map +1 -0
- package/lib/components/Dialog/Dialog.jsx +147 -0
- package/lib/components/Dialog/Dialog.namespace.d.ts +2 -0
- package/lib/components/Dialog/Dialog.namespace.d.ts.map +1 -0
- package/lib/components/Dialog/Dialog.namespace.js +18 -0
- package/lib/components/Dialog/index.d.ts +3 -0
- package/lib/components/Dialog/index.d.ts.map +1 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.d.ts +23 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.d.ts.map +1 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.jsx +76 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.namespace.d.ts +2 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.namespace.d.ts.map +1 -0
- package/lib/components/FloatingActionButton/FloatingActionButton.namespace.js +10 -0
- package/lib/components/FloatingActionButton/index.d.ts +3 -0
- package/lib/components/FloatingActionButton/index.d.ts.map +1 -0
- package/lib/components/HelpBubble/HelpBubble.d.ts +67 -0
- package/lib/components/HelpBubble/HelpBubble.d.ts.map +1 -0
- package/lib/components/HelpBubble/HelpBubble.jsx +600 -0
- package/lib/components/HelpBubble/HelpBubble.namespace.d.ts +2 -0
- package/lib/components/HelpBubble/HelpBubble.namespace.d.ts.map +1 -0
- package/lib/components/HelpBubble/HelpBubble.namespace.js +18 -0
- package/lib/components/HelpBubble/index.d.ts +3 -0
- package/lib/components/HelpBubble/index.d.ts.map +1 -0
- package/lib/components/Icon/Icon.d.ts +1 -0
- package/lib/components/Icon/Icon.d.ts.map +1 -1
- package/lib/components/Icon/Icon.jsx +2 -1
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.d.ts +28 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.d.ts.map +1 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.jsx +37 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.d.ts +2 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.d.ts.map +1 -0
- package/lib/components/IdentityPlaceholder/IdentityPlaceholder.namespace.js +9 -0
- package/lib/components/IdentityPlaceholder/identity-placeholder-business.js +4 -0
- package/lib/components/IdentityPlaceholder/identity-placeholder-person.js +4 -0
- package/lib/components/IdentityPlaceholder/index.d.ts +3 -0
- package/lib/components/IdentityPlaceholder/index.d.ts.map +1 -0
- package/lib/components/InputButton/InputButton.d.ts +2 -0
- package/lib/components/InputButton/InputButton.d.ts.map +1 -1
- package/lib/components/InputButton/InputButton.jsx +40 -8
- package/lib/components/List/List.d.ts +1 -1
- package/lib/components/List/List.d.ts.map +1 -1
- package/lib/components/List/List.jsx +26 -12
- package/lib/components/Menu/Menu.d.ts.map +1 -1
- package/lib/components/Menu/Menu.jsx +15 -5
- package/lib/components/PageBanner/PageBanner.d.ts +3 -0
- package/lib/components/PageBanner/PageBanner.d.ts.map +1 -1
- package/lib/components/PageBanner/PageBanner.jsx +49 -11
- package/lib/components/QuantityPicker/QuantityPicker.d.ts +53 -0
- package/lib/components/QuantityPicker/QuantityPicker.d.ts.map +1 -0
- package/lib/components/QuantityPicker/QuantityPicker.jsx +282 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts +2 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts.map +1 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.js +11 -0
- package/lib/components/QuantityPicker/index.d.ts +3 -0
- package/lib/components/QuantityPicker/index.d.ts.map +1 -0
- package/lib/components/RadioGroup/RadioGroup.jsx +2 -2
- package/lib/components/ReactionButton/ReactionButton.d.ts +1 -1
- package/lib/components/ReactionButton/ReactionButton.d.ts.map +1 -1
- package/lib/components/ReactionButton/ReactionButton.jsx +22 -13
- package/lib/components/ScrollFog/ScrollFog.d.ts +41 -0
- package/lib/components/ScrollFog/ScrollFog.d.ts.map +1 -0
- package/lib/components/ScrollFog/ScrollFog.jsx +65 -0
- package/lib/components/ScrollFog/index.d.ts +2 -0
- package/lib/components/ScrollFog/index.d.ts.map +1 -0
- package/lib/components/SegmentedControl/SegmentedControl.jsx +2 -2
- package/lib/components/Select/Select.d.ts +112 -0
- package/lib/components/Select/Select.d.ts.map +1 -0
- package/lib/components/Select/Select.jsx +885 -0
- package/lib/components/Select/Select.namespace.d.ts +2 -0
- package/lib/components/Select/Select.namespace.d.ts.map +1 -0
- package/lib/components/Select/Select.namespace.js +23 -0
- package/lib/components/Select/index.d.ts +3 -0
- package/lib/components/Select/index.d.ts.map +1 -0
- package/lib/components/Skeleton/Skeleton.d.ts +15 -0
- package/lib/components/Skeleton/Skeleton.d.ts.map +1 -0
- package/lib/components/Skeleton/Skeleton.jsx +18 -0
- package/lib/components/Skeleton/index.d.ts +2 -0
- package/lib/components/Skeleton/index.d.ts.map +1 -0
- package/lib/components/Slider/Slider.d.ts +101 -0
- package/lib/components/Slider/Slider.d.ts.map +1 -0
- package/lib/components/Slider/Slider.jsx +573 -0
- package/lib/components/Slider/Slider.namespace.d.ts +2 -0
- package/lib/components/Slider/Slider.namespace.d.ts.map +1 -0
- package/lib/components/Slider/Slider.namespace.js +19 -0
- package/lib/components/Slider/Slider.utils.d.ts +19 -0
- package/lib/components/Slider/Slider.utils.d.ts.map +1 -0
- package/lib/components/Slider/Slider.utils.js +106 -0
- package/lib/components/Slider/index.d.ts +3 -0
- package/lib/components/Slider/index.d.ts.map +1 -0
- package/lib/components/Stack/Stack.d.ts +7 -9
- package/lib/components/Stack/Stack.d.ts.map +1 -1
- package/lib/components/SwipeableMenuSheet/SwipeableMenuSheet.d.ts.map +1 -1
- package/lib/components/SwipeableMenuSheet/SwipeableMenuSheet.jsx +22 -8
- package/lib/components/Switch/Switch.d.ts.map +1 -1
- package/lib/components/Switch/Switch.jsx +5 -3
- package/lib/components/Tabs/Tabs.d.ts +34 -2
- package/lib/components/Tabs/Tabs.d.ts.map +1 -1
- package/lib/components/Tabs/Tabs.jsx +186 -56
- package/lib/components/Tabs/Tabs.utils.d.ts +14 -1
- package/lib/components/Tabs/Tabs.utils.d.ts.map +1 -1
- package/lib/components/Tabs/Tabs.utils.js +24 -3
- package/lib/components/Tabs/index.d.ts +1 -1
- package/lib/components/Tabs/index.d.ts.map +1 -1
- package/lib/components/index.d.ts +14 -0
- package/lib/components/index.d.ts.map +1 -1
- package/lib/hooks/useControllableState.d.ts +1 -14
- package/lib/hooks/useControllableState.d.ts.map +1 -1
- package/lib/hooks/usePressTap.d.ts +1 -27
- package/lib/hooks/usePressTap.d.ts.map +1 -1
- package/lib/hooks/useSafeArea.d.ts +8 -4
- package/lib/hooks/useSafeArea.d.ts.map +1 -1
- package/lib/hooks/useSafeArea.js +22 -20
- package/lib/index.js +29 -6
- package/lib/{hooks/useControllableState.js → packages/lynx-react-headless/use-controllable-state/lib/index.js} +2 -3
- package/lib/{hooks/usePressTap.js → packages/lynx-react-headless/use-press-tap/lib/index.js} +13 -10
- package/lib/types.d.ts +1 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/utils/styled.d.ts +46 -6
- package/lib/utils/styled.d.ts.map +1 -1
- package/lib/utils/styled.js +19 -4
- package/package.json +9 -5
- package/src/components/AlertDialog/AlertDialog.namespace.ts +22 -0
- package/src/components/AlertDialog/AlertDialog.test.tsx +226 -0
- package/src/components/AlertDialog/AlertDialog.tsx +374 -0
- package/src/components/AlertDialog/index.ts +24 -0
- package/src/components/AppBar/AppBar.namespace.ts +1 -0
- package/src/components/AppBar/AppBar.test.tsx +252 -3
- package/src/components/AppBar/AppBar.tsx +108 -25
- package/src/components/AppBar/context.ts +3 -1
- package/src/components/AppBar/index.ts +1 -0
- package/src/components/AppBar/useAppBar.ts +21 -15
- package/src/components/AttachmentDisplay/AttachmentDisplay.tsx +886 -0
- package/src/components/AttachmentDisplay/index.ts +48 -0
- package/src/components/AttachmentInput/AttachmentInput.tsx +1001 -0
- package/src/components/AttachmentInput/index.ts +49 -0
- package/src/components/BottomSheet/BottomSheet.test.tsx +22 -7
- package/src/components/BottomSheet/BottomSheet.tsx +1 -19
- package/src/components/Box/Box.test.tsx +104 -0
- package/src/components/Box/Box.tsx +9 -6
- package/src/components/ChipTabs/ChipTabs.namespace.ts +14 -0
- package/src/components/ChipTabs/ChipTabs.tsx +119 -0
- package/src/components/ChipTabs/index.ts +16 -0
- package/src/components/ContextualFloatingButton/ContextualFloatingButton.test.tsx +63 -0
- package/src/components/ContextualFloatingButton/ContextualFloatingButton.tsx +232 -0
- package/src/components/ContextualFloatingButton/index.ts +4 -0
- package/src/components/Dialog/Dialog.namespace.ts +24 -0
- package/src/components/Dialog/Dialog.test.tsx +172 -0
- package/src/components/Dialog/Dialog.tsx +373 -0
- package/src/components/Dialog/index.ts +26 -0
- package/src/components/FloatingActionButton/FloatingActionButton.namespace.ts +8 -0
- package/src/components/FloatingActionButton/FloatingActionButton.test.tsx +59 -0
- package/src/components/FloatingActionButton/FloatingActionButton.tsx +207 -0
- package/src/components/FloatingActionButton/index.ts +10 -0
- package/src/components/HelpBubble/HelpBubble.namespace.ts +24 -0
- package/src/components/HelpBubble/HelpBubble.tsx +998 -0
- package/src/components/HelpBubble/index.ts +26 -0
- package/src/components/Icon/Icon.test.tsx +0 -3
- package/src/components/Icon/Icon.tsx +11 -1
- package/src/components/IdentityPlaceholder/IdentityPlaceholder.namespace.ts +6 -0
- package/src/components/IdentityPlaceholder/IdentityPlaceholder.tsx +103 -0
- package/src/components/IdentityPlaceholder/assets.d.ts +4 -0
- package/src/components/IdentityPlaceholder/identity-placeholder-business.webp +0 -0
- package/src/components/IdentityPlaceholder/identity-placeholder-person.webp +0 -0
- package/src/components/IdentityPlaceholder/index.ts +8 -0
- package/src/components/InputButton/InputButton.test.tsx +128 -1
- package/src/components/InputButton/InputButton.tsx +60 -9
- package/src/components/List/List.test.tsx +54 -2
- package/src/components/List/List.tsx +43 -10
- package/src/components/Menu/Menu.tsx +14 -4
- package/src/components/Menu/__tests__/Menu.test.tsx +34 -0
- package/src/components/PageBanner/PageBanner.test.tsx +110 -3
- package/src/components/PageBanner/PageBanner.tsx +83 -19
- package/src/components/QuantityPicker/QuantityPicker.namespace.ts +10 -0
- package/src/components/QuantityPicker/QuantityPicker.test.tsx +235 -0
- package/src/components/QuantityPicker/QuantityPicker.tsx +605 -0
- package/src/components/QuantityPicker/index.ts +14 -0
- package/src/components/ReactionButton/ReactionButton.feedback.test.tsx +50 -0
- package/src/components/ReactionButton/ReactionButton.test.tsx +5 -3
- package/src/components/ReactionButton/ReactionButton.tsx +20 -12
- package/src/components/ScrollFog/ScrollFog.test.tsx +222 -0
- package/src/components/ScrollFog/ScrollFog.tsx +172 -0
- package/src/components/ScrollFog/index.ts +1 -0
- package/src/components/Select/Select.namespace.ts +34 -0
- package/src/components/Select/Select.test.tsx +297 -0
- package/src/components/Select/Select.tsx +1483 -0
- package/src/components/Select/index.ts +39 -0
- package/src/components/Skeleton/Skeleton.test.tsx +64 -0
- package/src/components/Skeleton/Skeleton.tsx +45 -0
- package/src/components/Skeleton/index.ts +1 -0
- package/src/components/Slider/Slider.namespace.ts +26 -0
- package/src/components/Slider/Slider.test.tsx +260 -0
- package/src/components/Slider/Slider.tsx +897 -0
- package/src/components/Slider/Slider.utils.ts +167 -0
- package/src/components/Slider/index.ts +30 -0
- package/src/components/Stack/Stack.test.tsx +7 -0
- package/src/components/Stack/Stack.tsx +11 -10
- package/src/components/SwipeableMenuSheet/SwipeableMenuSheet.test.tsx +21 -1
- package/src/components/SwipeableMenuSheet/SwipeableMenuSheet.tsx +30 -7
- package/src/components/Switch/Switch.tsx +14 -13
- package/src/components/Tabs/Tabs.test.tsx +218 -1
- package/src/components/Tabs/Tabs.tsx +346 -75
- package/src/components/Tabs/Tabs.utils.ts +51 -1
- package/src/components/Tabs/index.ts +17 -1
- package/src/components/index.ts +14 -0
- package/src/hooks/useControllableState.ts +1 -43
- package/src/hooks/usePressTap.test.ts +23 -11
- package/src/hooks/usePressTap.ts +1 -60
- package/src/hooks/useSafeArea.test.ts +13 -1
- package/src/hooks/useSafeArea.ts +25 -23
- package/src/types.ts +1 -0
- package/src/utils/styled.ts +127 -9
|
@@ -5,6 +5,9 @@ import { list } from "@seed-design/lynx-css/recipes/list";
|
|
|
5
5
|
import { listHeader, type ListHeaderVariantProps } from "@seed-design/lynx-css/recipes/list-header";
|
|
6
6
|
import { listItem, type ListItemVariantProps } from "@seed-design/lynx-css/recipes/list-item";
|
|
7
7
|
|
|
8
|
+
import { ScaleFeedbackContentContext } from "../../contexts";
|
|
9
|
+
import { useScaleFeedback, type ScaleFeedbackTargetProps } from "../../hooks/useScaleFeedback";
|
|
10
|
+
import { mergeProps } from "../../utils/merge-props";
|
|
8
11
|
import { usePressTap } from "../../hooks/usePressTap";
|
|
9
12
|
import type {
|
|
10
13
|
LynxAccessibilityProps,
|
|
@@ -24,7 +27,10 @@ import {
|
|
|
24
27
|
} from "../RadioGroup/RadioGroup";
|
|
25
28
|
import { SwitchRoot, type SwitchRootProps, useSwitchContext } from "../Switch/Switch";
|
|
26
29
|
|
|
27
|
-
type PublicListItemVariantProps = Omit<
|
|
30
|
+
type PublicListItemVariantProps = Omit<
|
|
31
|
+
ListItemVariantProps,
|
|
32
|
+
"pressed" | "disabled" | "interactive"
|
|
33
|
+
>;
|
|
28
34
|
|
|
29
35
|
const { ClassNamesProvider, useClassNames } = createSlotRecipeContext(listItem);
|
|
30
36
|
|
|
@@ -91,12 +97,26 @@ interface ListItemSurfaceProps
|
|
|
91
97
|
LynxTouchProps {
|
|
92
98
|
disabled?: boolean;
|
|
93
99
|
pressed?: boolean;
|
|
100
|
+
scaleFeedbackTargetProps?: ScaleFeedbackTargetProps;
|
|
94
101
|
}
|
|
95
102
|
|
|
96
103
|
const ListItemSurface = React.forwardRef<unknown, ListItemSurfaceProps>((props, ref) => {
|
|
97
|
-
const {
|
|
104
|
+
const {
|
|
105
|
+
children,
|
|
106
|
+
className,
|
|
107
|
+
style,
|
|
108
|
+
disabled = false,
|
|
109
|
+
pressed = false,
|
|
110
|
+
scaleFeedbackTargetProps,
|
|
111
|
+
...restProps
|
|
112
|
+
} = props;
|
|
98
113
|
const [variantProps, nativeProps] = listItem.splitVariantProps(restProps);
|
|
99
|
-
const classes = listItem({
|
|
114
|
+
const classes = listItem({
|
|
115
|
+
...variantProps,
|
|
116
|
+
disabled,
|
|
117
|
+
pressed,
|
|
118
|
+
interactive: !!scaleFeedbackTargetProps,
|
|
119
|
+
});
|
|
100
120
|
|
|
101
121
|
return (
|
|
102
122
|
<ClassNamesProvider value={classes}>
|
|
@@ -110,14 +130,17 @@ const ListItemSurface = React.forwardRef<unknown, ListItemSurfaceProps>((props,
|
|
|
110
130
|
}}
|
|
111
131
|
>
|
|
112
132
|
<view
|
|
113
|
-
{...(ref ? { ref: ref as LynxViewRef } : {})}
|
|
114
|
-
{...nativeProps}
|
|
133
|
+
{...mergeProps(ref ? { ref: ref as LynxViewRef } : {}, nativeProps)}
|
|
115
134
|
className={clsx(classes.root, className)}
|
|
116
135
|
style={style}
|
|
117
136
|
>
|
|
118
137
|
<view className={classes.highlightedOverlay} accessibility-elements-hidden={true} />
|
|
119
138
|
<view className={classes.pressedOverlay} accessibility-elements-hidden={true} />
|
|
120
|
-
<view className={classes.layout}
|
|
139
|
+
<view className={classes.layout} {...scaleFeedbackTargetProps}>
|
|
140
|
+
<ScaleFeedbackContentContext.Provider value={!!scaleFeedbackTargetProps}>
|
|
141
|
+
{children}
|
|
142
|
+
</ScaleFeedbackContentContext.Provider>
|
|
143
|
+
</view>
|
|
121
144
|
</view>
|
|
122
145
|
</IconSlotProvider>
|
|
123
146
|
</ClassNamesProvider>
|
|
@@ -157,11 +180,17 @@ export const ListButtonItem = React.forwardRef<unknown, ListButtonItemProps>((pr
|
|
|
157
180
|
"accessibility-traits": accessibilityTraits,
|
|
158
181
|
...restProps
|
|
159
182
|
} = props;
|
|
160
|
-
const { pressed, ...pressHandlers } = usePressTap({
|
|
183
|
+
const { pressed, bindtouchstart, bindtouchend, bindtouchcancel, ...pressHandlers } = usePressTap({
|
|
161
184
|
disabled,
|
|
162
185
|
onTap: bindtap,
|
|
163
186
|
mainThreadOnTap,
|
|
164
187
|
});
|
|
188
|
+
const { scaleFeedbackTriggerProps, scaleFeedbackTargetProps } = useScaleFeedback({
|
|
189
|
+
disabled,
|
|
190
|
+
onTouchStart: bindtouchstart,
|
|
191
|
+
onTouchEnd: bindtouchend,
|
|
192
|
+
onTouchCancel: bindtouchcancel,
|
|
193
|
+
});
|
|
165
194
|
|
|
166
195
|
return (
|
|
167
196
|
<ListItemSurface
|
|
@@ -171,8 +200,8 @@ export const ListButtonItem = React.forwardRef<unknown, ListButtonItemProps>((pr
|
|
|
171
200
|
accessibility-element={accessibilityElement}
|
|
172
201
|
accessibility-role-description={accessibilityRoleDescription}
|
|
173
202
|
accessibility-traits={accessibilityTraits ?? (disabled ? "disabled" : "button")}
|
|
174
|
-
{
|
|
175
|
-
{...restProps}
|
|
203
|
+
scaleFeedbackTargetProps={scaleFeedbackTargetProps}
|
|
204
|
+
{...mergeProps(scaleFeedbackTriggerProps, pressHandlers, restProps)}
|
|
176
205
|
/>
|
|
177
206
|
);
|
|
178
207
|
});
|
|
@@ -193,6 +222,7 @@ function ListCheckboxItemSurface(props: ListCheckboxItemSurfaceProps) {
|
|
|
193
222
|
{...props}
|
|
194
223
|
disabled={context.disabled}
|
|
195
224
|
pressed={context.pressed}
|
|
225
|
+
scaleFeedbackTargetProps={context.scaleFeedbackTargetProps}
|
|
196
226
|
accessibility-element={props["accessibility-element"] ?? true}
|
|
197
227
|
accessibility-role-description={props["accessibility-role-description"] ?? "checkbox"}
|
|
198
228
|
accessibility-value={
|
|
@@ -254,6 +284,7 @@ function ListRadioItemSurface(props: ListRadioItemSurfaceProps) {
|
|
|
254
284
|
{...props}
|
|
255
285
|
disabled={context.disabled}
|
|
256
286
|
pressed={context.pressed}
|
|
287
|
+
scaleFeedbackTargetProps={context.scaleFeedbackTargetProps}
|
|
257
288
|
accessibility-element={props["accessibility-element"] ?? true}
|
|
258
289
|
accessibility-role-description={props["accessibility-role-description"] ?? "radio"}
|
|
259
290
|
accessibility-value={
|
|
@@ -277,12 +308,13 @@ export interface ListRadioItemProps
|
|
|
277
308
|
export const ListRadioItem = React.forwardRef<unknown, ListRadioItemProps>((props, ref) => {
|
|
278
309
|
const { children, className, style, disabled = false, value, ...restProps } = props;
|
|
279
310
|
const [variantProps, remainingProps] = listItem.splitVariantProps(restProps);
|
|
280
|
-
const [accessibilityProps] = splitAccessibilityProps(remainingProps);
|
|
311
|
+
const [accessibilityProps, radioProps] = splitAccessibilityProps(remainingProps);
|
|
281
312
|
const interactionRootClassName = listItem().interactionRoot;
|
|
282
313
|
|
|
283
314
|
return (
|
|
284
315
|
<RadioGroupItem
|
|
285
316
|
ref={ref}
|
|
317
|
+
{...radioProps}
|
|
286
318
|
value={value}
|
|
287
319
|
disabled={disabled}
|
|
288
320
|
className={interactionRootClassName}
|
|
@@ -315,6 +347,7 @@ function ListSwitchItemSurface(props: ListSwitchItemSurfaceProps) {
|
|
|
315
347
|
{...props}
|
|
316
348
|
disabled={context.disabled}
|
|
317
349
|
pressed={context.pressed}
|
|
350
|
+
scaleFeedbackTargetProps={context.scaleFeedbackTargetProps}
|
|
318
351
|
accessibility-element={props["accessibility-element"] ?? true}
|
|
319
352
|
accessibility-role-description={props["accessibility-role-description"] ?? "switch"}
|
|
320
353
|
accessibility-value={props["accessibility-value"] ?? (context.checked ? "켜짐" : "꺼짐")}
|
|
@@ -8,6 +8,8 @@ import { menuItem, type MenuItemVariantProps } from "@seed-design/lynx-css/recip
|
|
|
8
8
|
import { menu as menuVars } from "@seed-design/lynx-css/vars/component";
|
|
9
9
|
|
|
10
10
|
import { useControllableState } from "../../hooks/useControllableState";
|
|
11
|
+
import { useScaleFeedback } from "../../hooks/useScaleFeedback";
|
|
12
|
+
import { mergeProps } from "../../utils/merge-props";
|
|
11
13
|
import { usePressTap } from "../../hooks/usePressTap";
|
|
12
14
|
import type {
|
|
13
15
|
LynxAccessibilityProps,
|
|
@@ -38,6 +40,7 @@ type MenuClassNames = {
|
|
|
38
40
|
};
|
|
39
41
|
type MenuItemClassNames = {
|
|
40
42
|
root: string;
|
|
43
|
+
scaleContent: string;
|
|
41
44
|
pressedOverlay: string;
|
|
42
45
|
body: string;
|
|
43
46
|
label: string;
|
|
@@ -782,11 +785,17 @@ export const MenuItem = React.forwardRef<unknown, MenuItemProps>((props, ref) =>
|
|
|
782
785
|
},
|
|
783
786
|
[bindtap, context],
|
|
784
787
|
);
|
|
785
|
-
const { pressed, ...pressHandlers } = usePressTap({
|
|
788
|
+
const { pressed, bindtouchstart, bindtouchend, bindtouchcancel, ...pressHandlers } = usePressTap({
|
|
786
789
|
disabled,
|
|
787
790
|
onTap: handleTap,
|
|
788
791
|
mainThreadOnTap: mainThreadBindtap,
|
|
789
792
|
});
|
|
793
|
+
const { scaleFeedbackTriggerProps, scaleFeedbackTargetProps } = useScaleFeedback({
|
|
794
|
+
disabled,
|
|
795
|
+
onTouchStart: bindtouchstart,
|
|
796
|
+
onTouchEnd: bindtouchend,
|
|
797
|
+
onTouchCancel: bindtouchcancel,
|
|
798
|
+
});
|
|
790
799
|
const classes = menuItem({
|
|
791
800
|
...variantProps,
|
|
792
801
|
size: context.size,
|
|
@@ -812,11 +821,12 @@ export const MenuItem = React.forwardRef<unknown, MenuItemProps>((props, ref) =>
|
|
|
812
821
|
accessibility-label={accessibilityLabel}
|
|
813
822
|
accessibility-role-description="button"
|
|
814
823
|
accessibility-traits={disabled ? "disabled" : (accessibilityTraits ?? "button")}
|
|
815
|
-
{...nativeProps}
|
|
816
|
-
{...pressHandlers}
|
|
824
|
+
{...mergeProps(scaleFeedbackTriggerProps, pressHandlers, nativeProps)}
|
|
817
825
|
>
|
|
818
826
|
<view className={classes.pressedOverlay} accessibility-elements-hidden={true} />
|
|
819
|
-
{
|
|
827
|
+
<view className={classes.scaleContent} {...scaleFeedbackTargetProps}>
|
|
828
|
+
{children}
|
|
829
|
+
</view>
|
|
820
830
|
</view>
|
|
821
831
|
</IconSlotProvider>
|
|
822
832
|
</MenuItemClassNamesContext.Provider>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import { fireEvent, render } from "@lynx-js/react/testing-library";
|
|
3
|
+
import { describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { MenuRoot, MenuItem, MenuItemLabel } from "../Menu";
|
|
5
|
+
|
|
6
|
+
describe("Menu item feedback", () => {
|
|
7
|
+
it("scales the inner content while preserving item callbacks and disabled gating", () => {
|
|
8
|
+
const onTap = vi.fn();
|
|
9
|
+
const { getByText, rerender } = render(
|
|
10
|
+
<MenuRoot>
|
|
11
|
+
<MenuItem bindtap={onTap}>
|
|
12
|
+
<MenuItemLabel>Choose</MenuItemLabel>
|
|
13
|
+
</MenuItem>
|
|
14
|
+
</MenuRoot>,
|
|
15
|
+
);
|
|
16
|
+
const label = getByText("Choose") as HTMLElement;
|
|
17
|
+
const target = label.parentElement!;
|
|
18
|
+
const root = target.parentElement!;
|
|
19
|
+
expect(target).toHaveClass("seed-menu-item__scaleContent");
|
|
20
|
+
expect(target).toHaveAttribute("flatten", "false");
|
|
21
|
+
expect(target).not.toContainElement(root.querySelector(".seed-menu-item__pressedOverlay"));
|
|
22
|
+
fireEvent.tap(root);
|
|
23
|
+
expect(onTap).toHaveBeenCalledTimes(1);
|
|
24
|
+
rerender(
|
|
25
|
+
<MenuRoot>
|
|
26
|
+
<MenuItem disabled bindtap={onTap}>
|
|
27
|
+
<MenuItemLabel>Choose</MenuItemLabel>
|
|
28
|
+
</MenuItem>
|
|
29
|
+
</MenuRoot>,
|
|
30
|
+
);
|
|
31
|
+
fireEvent.tap((getByText("Choose") as HTMLElement).parentElement!.parentElement!);
|
|
32
|
+
expect(onTap).toHaveBeenCalledTimes(1);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import "@testing-library/jest-dom";
|
|
2
|
-
import
|
|
2
|
+
import * as React from "@lynx-js/react";
|
|
3
|
+
import { runOnBackground } from "@lynx-js/react";
|
|
4
|
+
import { fireEvent, render, waitSchedule } from "@lynx-js/react/testing-library";
|
|
3
5
|
import { describe, expect, it, vi } from "vitest";
|
|
4
6
|
|
|
5
7
|
import * as PageBanner from "./PageBanner.namespace";
|
|
@@ -87,6 +89,111 @@ describe("PageBanner", () => {
|
|
|
87
89
|
expect(onTap).toHaveBeenCalledTimes(1);
|
|
88
90
|
});
|
|
89
91
|
|
|
92
|
+
it("scales the actionable content group without its background or independent close button", () => {
|
|
93
|
+
render(
|
|
94
|
+
<PageBanner.Root bindtap={() => {}}>
|
|
95
|
+
<React.Fragment key="fragment-slots">
|
|
96
|
+
<view id="prefix" />
|
|
97
|
+
<PageBanner.Content>
|
|
98
|
+
<PageBanner.Description>Body</PageBanner.Description>
|
|
99
|
+
</PageBanner.Content>
|
|
100
|
+
<view id="suffix" />
|
|
101
|
+
<PageBanner.CloseButton accessibility-label="Close" />
|
|
102
|
+
</React.Fragment>
|
|
103
|
+
</PageBanner.Root>,
|
|
104
|
+
);
|
|
105
|
+
const root = getPageBannerRoot();
|
|
106
|
+
const target = root.querySelector(".seed-page-banner__scaleContent");
|
|
107
|
+
const close = root.querySelector(".seed-page-banner__closeButton");
|
|
108
|
+
expect(target).toHaveAttribute("flatten", "false");
|
|
109
|
+
expect(target?.parentElement).toBe(root);
|
|
110
|
+
expect(target?.querySelector("#prefix")).toBeTruthy();
|
|
111
|
+
expect(target?.querySelector("#suffix")).toBeTruthy();
|
|
112
|
+
expect(target?.contains(close)).toBe(false);
|
|
113
|
+
expect(close?.parentElement).toBe(root);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("measures the action text itself and prevents action taps from reaching the banner", () => {
|
|
117
|
+
const onBanner = vi.fn();
|
|
118
|
+
const onAction = vi.fn();
|
|
119
|
+
render(
|
|
120
|
+
<PageBanner.Root bindtap={onBanner}>
|
|
121
|
+
<PageBanner.Content>
|
|
122
|
+
<PageBanner.Button bindtap={onAction}>Action</PageBanner.Button>
|
|
123
|
+
</PageBanner.Content>
|
|
124
|
+
</PageBanner.Root>,
|
|
125
|
+
);
|
|
126
|
+
const root = getPageBannerRoot();
|
|
127
|
+
const action = root.querySelector(".seed-page-banner__button") as HTMLElement;
|
|
128
|
+
expect(action).toHaveAttribute("flatten", "false");
|
|
129
|
+
expect(action.parentElement).toHaveClass("seed-page-banner__content");
|
|
130
|
+
fireEvent.tap(action, { eventType: "catchEvent" });
|
|
131
|
+
expect(onAction).toHaveBeenCalledTimes(1);
|
|
132
|
+
expect(onBanner).not.toHaveBeenCalled();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("does not activate the banner when its independent close action is tapped", () => {
|
|
136
|
+
const onBanner = vi.fn();
|
|
137
|
+
const onDismiss = vi.fn();
|
|
138
|
+
render(
|
|
139
|
+
<PageBanner.Root open bindtap={onBanner} onDismiss={onDismiss}>
|
|
140
|
+
<PageBanner.Content>
|
|
141
|
+
<PageBanner.Description>Body</PageBanner.Description>
|
|
142
|
+
</PageBanner.Content>
|
|
143
|
+
<PageBanner.CloseButton accessibility-label="Close" />
|
|
144
|
+
</PageBanner.Root>,
|
|
145
|
+
);
|
|
146
|
+
const root = getPageBannerRoot();
|
|
147
|
+
fireEvent.tap(root.querySelector(".seed-page-banner__closeButton") as HTMLElement, {
|
|
148
|
+
eventType: "catchEvent",
|
|
149
|
+
});
|
|
150
|
+
expect(onDismiss).toHaveBeenCalledTimes(1);
|
|
151
|
+
expect(onBanner).not.toHaveBeenCalled();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("bridges banner feedback and preserves independent Main Thread handlers", async () => {
|
|
155
|
+
function Example({ report }: { report: () => void }) {
|
|
156
|
+
function handleTouch() {
|
|
157
|
+
"main thread";
|
|
158
|
+
runOnBackground(report)();
|
|
159
|
+
}
|
|
160
|
+
return (
|
|
161
|
+
<PageBanner.Root open bindtap={() => {}}>
|
|
162
|
+
<PageBanner.Content>
|
|
163
|
+
<PageBanner.Description>Body</PageBanner.Description>
|
|
164
|
+
</PageBanner.Content>
|
|
165
|
+
<PageBanner.CloseButton
|
|
166
|
+
accessibility-label="Close"
|
|
167
|
+
main-thread:bindtouchstart={handleTouch}
|
|
168
|
+
/>
|
|
169
|
+
</PageBanner.Root>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
const report = vi.fn();
|
|
173
|
+
const { container } = render(<Example report={report} />, {
|
|
174
|
+
enableMainThread: true,
|
|
175
|
+
enableBackgroundThread: true,
|
|
176
|
+
});
|
|
177
|
+
await waitSchedule();
|
|
178
|
+
const root = container.querySelector(".seed-page-banner__root");
|
|
179
|
+
const close = container.querySelector(".seed-page-banner__closeButton");
|
|
180
|
+
if (!root || !close) throw new Error("Expected banner and close button");
|
|
181
|
+
fireEvent.touchstart(close, { eventType: "catchEvent" });
|
|
182
|
+
await waitSchedule();
|
|
183
|
+
expect(report).toHaveBeenCalledTimes(1);
|
|
184
|
+
expect(root.className).toContain("__root--pressed_false");
|
|
185
|
+
expect(close.className).toContain("closeButtonPressed_true");
|
|
186
|
+
fireEvent.touchend(close, { eventType: "catchEvent" });
|
|
187
|
+
await waitSchedule();
|
|
188
|
+
expect(close.className).not.toContain("closeButtonPressed_true");
|
|
189
|
+
fireEvent.touchstart(root, {});
|
|
190
|
+
await waitSchedule();
|
|
191
|
+
expect(root.className).toContain("__root--pressed_true");
|
|
192
|
+
fireEvent.touchcancel(root, {});
|
|
193
|
+
await waitSchedule();
|
|
194
|
+
expect(root.className).toContain("__root--pressed_false");
|
|
195
|
+
});
|
|
196
|
+
|
|
90
197
|
it("dismisses an uncontrolled banner and composes the close tap handler", () => {
|
|
91
198
|
const onTap = vi.fn();
|
|
92
199
|
const onDismiss = vi.fn();
|
|
@@ -100,7 +207,7 @@ describe("PageBanner", () => {
|
|
|
100
207
|
const closeButton = getPageBannerRoot().querySelector(".seed-page-banner__closeButton");
|
|
101
208
|
if (!closeButton) throw new Error("Expected close button to exist.");
|
|
102
209
|
|
|
103
|
-
fireEvent.tap(closeButton);
|
|
210
|
+
fireEvent.tap(closeButton, { eventType: "catchEvent" });
|
|
104
211
|
|
|
105
212
|
expect(onTap).toHaveBeenCalledTimes(1);
|
|
106
213
|
expect(onDismiss).toHaveBeenCalledTimes(1);
|
|
@@ -119,7 +226,7 @@ describe("PageBanner", () => {
|
|
|
119
226
|
const closeButton = getPageBannerRoot().querySelector(".seed-page-banner__closeButton");
|
|
120
227
|
if (!closeButton) throw new Error("Expected close button to exist.");
|
|
121
228
|
|
|
122
|
-
fireEvent.tap(closeButton);
|
|
229
|
+
fireEvent.tap(closeButton, { eventType: "catchEvent" });
|
|
123
230
|
|
|
124
231
|
expect(onDismiss).toHaveBeenCalledTimes(1);
|
|
125
232
|
expect(getPageBannerRoot()).toBeInTheDocument();
|
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
} from "../../types";
|
|
17
17
|
import { createSlotRecipeContext } from "../../utils/create-slot-recipe-context";
|
|
18
18
|
import { IconSlotProvider } from "../Icon/Icon";
|
|
19
|
-
import {
|
|
19
|
+
import { toArray } from "../../utils/children";
|
|
20
20
|
import { mergeProps } from "../../utils/merge-props";
|
|
21
21
|
|
|
22
22
|
const { ClassNamesProvider, PropsProvider, useClassNames, useProps } =
|
|
@@ -48,6 +48,9 @@ function usePageBannerContext(consumer: string) {
|
|
|
48
48
|
* Differences from React Web:
|
|
49
49
|
* - Uses Lynx native `<view>` and `bindtap` instead of `asChild` and DOM events.
|
|
50
50
|
* - Does not provide a web focus ring.
|
|
51
|
+
* - Actionable banners group their children for Content Scale. Render CloseButton
|
|
52
|
+
* directly under Root (or in a Fragment) to exclude it from that group.
|
|
53
|
+
* A CloseButton hidden inside a custom component remains in the content group.
|
|
51
54
|
*/
|
|
52
55
|
export interface PageBannerRootProps
|
|
53
56
|
extends Omit<PageBannerVariantProps, "pressed" | "closeButtonPressed" | "interactive">,
|
|
@@ -94,6 +97,15 @@ export const PageBannerRoot = React.forwardRef<unknown, PageBannerRootProps>((pr
|
|
|
94
97
|
onTap: bindtap,
|
|
95
98
|
mainThreadOnTap: mainThreadBindtap,
|
|
96
99
|
});
|
|
100
|
+
const { scaleFeedbackTriggerProps, scaleFeedbackTargetProps } = useScaleFeedback({
|
|
101
|
+
disabled: !isInteractive,
|
|
102
|
+
onTouchStart: pressTap.bindtouchstart,
|
|
103
|
+
onTouchEnd: pressTap.bindtouchend,
|
|
104
|
+
onTouchCancel: pressTap.bindtouchcancel,
|
|
105
|
+
});
|
|
106
|
+
const childArray = flattenPageBannerChildren(children);
|
|
107
|
+
const closeButtons = childArray.filter(isPageBannerCloseButton);
|
|
108
|
+
const scaleChildren = childArray.filter((child) => !isPageBannerCloseButton(child));
|
|
97
109
|
const classNames = pageBanner({
|
|
98
110
|
...variantProps,
|
|
99
111
|
pressed: pressTap.pressed,
|
|
@@ -134,6 +146,7 @@ export const PageBannerRoot = React.forwardRef<unknown, PageBannerRootProps>((pr
|
|
|
134
146
|
{...mergeProps(
|
|
135
147
|
ref ? { ref: ref as LynxViewRef } : {},
|
|
136
148
|
isInteractive ? pressTap : {},
|
|
149
|
+
isInteractive ? scaleFeedbackTriggerProps : {},
|
|
137
150
|
nativeProps,
|
|
138
151
|
)}
|
|
139
152
|
accessibility-element={accessibilityElement ?? (isInteractive ? true : undefined)}
|
|
@@ -141,7 +154,16 @@ export const PageBannerRoot = React.forwardRef<unknown, PageBannerRootProps>((pr
|
|
|
141
154
|
className={clsx(classNames.root, className)}
|
|
142
155
|
style={style}
|
|
143
156
|
>
|
|
144
|
-
{
|
|
157
|
+
{isInteractive ? (
|
|
158
|
+
<>
|
|
159
|
+
<view {...scaleFeedbackTargetProps} className={classNames.scaleContent}>
|
|
160
|
+
{scaleChildren}
|
|
161
|
+
</view>
|
|
162
|
+
{closeButtons}
|
|
163
|
+
</>
|
|
164
|
+
) : (
|
|
165
|
+
children
|
|
166
|
+
)}
|
|
145
167
|
</view>
|
|
146
168
|
</IconSlotProvider>
|
|
147
169
|
</PropsProvider>
|
|
@@ -253,19 +275,26 @@ export const PageBannerButton = React.forwardRef<unknown, PageBannerButtonProps>
|
|
|
253
275
|
...nativeProps
|
|
254
276
|
} = props;
|
|
255
277
|
const classNames = useClassNames();
|
|
278
|
+
const { scaleFeedbackTriggerProps, scaleFeedbackTargetProps } = useScaleFeedback();
|
|
256
279
|
|
|
257
280
|
return (
|
|
258
|
-
<
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
281
|
+
<text
|
|
282
|
+
{...independentActionProps(
|
|
283
|
+
mergeProps(
|
|
284
|
+
ref ? { ref: ref as LynxTextRef } : {},
|
|
285
|
+
scaleFeedbackTriggerProps,
|
|
286
|
+
scaleFeedbackTargetProps,
|
|
287
|
+
nativeProps,
|
|
288
|
+
),
|
|
289
|
+
)}
|
|
290
|
+
accessibility-element={accessibilityElement}
|
|
291
|
+
accessibility-traits={accessibilityTraits}
|
|
292
|
+
className={clsx(classNames.button, className)}
|
|
293
|
+
style={style}
|
|
294
|
+
flatten={false}
|
|
295
|
+
>
|
|
296
|
+
{children}
|
|
297
|
+
</text>
|
|
269
298
|
);
|
|
270
299
|
});
|
|
271
300
|
PageBannerButton.displayName = "PageBannerButton";
|
|
@@ -326,12 +355,14 @@ export const PageBannerCloseButton = React.forwardRef<unknown, PageBannerCloseBu
|
|
|
326
355
|
return (
|
|
327
356
|
<IconSlotProvider value={iconSlotContextValue}>
|
|
328
357
|
<view
|
|
329
|
-
{...
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
358
|
+
{...independentActionProps(
|
|
359
|
+
mergeProps(
|
|
360
|
+
ref ? { ref: ref as LynxViewRef } : {},
|
|
361
|
+
pressTapHandlers,
|
|
362
|
+
scaleFeedbackTriggerProps,
|
|
363
|
+
scaleFeedbackTargetProps,
|
|
364
|
+
nativeProps,
|
|
365
|
+
),
|
|
335
366
|
)}
|
|
336
367
|
accessibility-element={accessibilityElement}
|
|
337
368
|
accessibility-label={accessibilityLabel}
|
|
@@ -347,3 +378,36 @@ export const PageBannerCloseButton = React.forwardRef<unknown, PageBannerCloseBu
|
|
|
347
378
|
},
|
|
348
379
|
);
|
|
349
380
|
PageBannerCloseButton.displayName = "PageBannerCloseButton";
|
|
381
|
+
|
|
382
|
+
function isPageBannerCloseButton(node: React.ReactNode) {
|
|
383
|
+
return React.isValidElement(node) && node.type === PageBannerCloseButton;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function flattenPageBannerChildren(children: React.ReactNode): React.ReactNode[] {
|
|
387
|
+
return toArray(children).flatMap((child) =>
|
|
388
|
+
React.isValidElement<{ children?: React.ReactNode }>(child) && child.type === React.Fragment
|
|
389
|
+
? flattenPageBannerChildren(child.props.children)
|
|
390
|
+
: [child],
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Native catch handlers keep independent actions from starting the banner's feedback or tap.
|
|
395
|
+
function independentActionProps(props: Record<string, unknown>) {
|
|
396
|
+
const result = { ...props };
|
|
397
|
+
for (const event of ["tap", "touchstart", "touchend", "touchcancel"]) {
|
|
398
|
+
const bind = `bind${event}`;
|
|
399
|
+
const catchKey = `catch${event}`;
|
|
400
|
+
const mainBind = `main-thread:${bind}`;
|
|
401
|
+
const mainCatch = `main-thread:${catchKey}`;
|
|
402
|
+
const caught = mergeProps(
|
|
403
|
+
{ [catchKey]: result[bind] ?? (() => {}) },
|
|
404
|
+
{ [catchKey]: result[catchKey] },
|
|
405
|
+
{ [mainCatch]: result[mainBind] },
|
|
406
|
+
{ [mainCatch]: result[mainCatch] },
|
|
407
|
+
);
|
|
408
|
+
delete result[bind];
|
|
409
|
+
delete result[mainBind];
|
|
410
|
+
Object.assign(result, caught);
|
|
411
|
+
}
|
|
412
|
+
return result;
|
|
413
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export {
|
|
2
|
+
QuantityPickerRoot as Root,
|
|
3
|
+
QuantityPickerDecrementButton as DecrementButton,
|
|
4
|
+
QuantityPickerValueDisplay as ValueDisplay,
|
|
5
|
+
QuantityPickerIncrementButton as IncrementButton,
|
|
6
|
+
type QuantityPickerRootProps as RootProps,
|
|
7
|
+
type QuantityPickerDecrementButtonProps as DecrementButtonProps,
|
|
8
|
+
type QuantityPickerValueDisplayProps as ValueDisplayProps,
|
|
9
|
+
type QuantityPickerIncrementButtonProps as IncrementButtonProps,
|
|
10
|
+
} from "./QuantityPicker";
|