@yahoo/uds-mobile 2.21.2 → 2.23.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 +2 -0
- package/dist/bin/automated-config/dist/generated/generatedConfigs.mjs +3127 -452
- package/dist/bin/uds-mobile.mjs +7 -7
- package/dist/components/IconButton.cjs +24 -21
- package/dist/components/IconButton.js +25 -22
- package/dist/components/IconButton.js.map +1 -1
- package/dist/components/Select/Select.cjs +194 -0
- package/dist/components/Select/Select.d.cts +47 -0
- package/dist/components/Select/Select.d.cts.map +1 -0
- package/dist/components/Select/Select.d.ts +47 -0
- package/dist/components/Select/Select.d.ts.map +1 -0
- package/dist/components/Select/Select.js +194 -0
- package/dist/components/Select/Select.js.map +1 -0
- package/dist/components/Select/SelectContent.cjs +148 -0
- package/dist/components/Select/SelectContent.d.cts +31 -0
- package/dist/components/Select/SelectContent.d.cts.map +1 -0
- package/dist/components/Select/SelectContent.d.ts +31 -0
- package/dist/components/Select/SelectContent.d.ts.map +1 -0
- package/dist/components/Select/SelectContent.js +147 -0
- package/dist/components/Select/SelectContent.js.map +1 -0
- package/dist/components/Select/SelectItem.cjs +138 -0
- package/dist/components/Select/SelectItem.d.cts +24 -0
- package/dist/components/Select/SelectItem.d.cts.map +1 -0
- package/dist/components/Select/SelectItem.d.ts +24 -0
- package/dist/components/Select/SelectItem.d.ts.map +1 -0
- package/dist/components/Select/SelectItem.js +137 -0
- package/dist/components/Select/SelectItem.js.map +1 -0
- package/dist/components/Select/SelectTrigger.cjs +140 -0
- package/dist/components/Select/SelectTrigger.d.cts +13 -0
- package/dist/components/Select/SelectTrigger.d.cts.map +1 -0
- package/dist/components/Select/SelectTrigger.d.ts +13 -0
- package/dist/components/Select/SelectTrigger.d.ts.map +1 -0
- package/dist/components/Select/SelectTrigger.js +139 -0
- package/dist/components/Select/SelectTrigger.js.map +1 -0
- package/dist/components/Select/index.cjs +8 -0
- package/dist/components/Select/index.d.cts +5 -0
- package/dist/components/Select/index.d.ts +5 -0
- package/dist/components/Select/index.js +5 -0
- package/dist/components/Select/selectContext.cjs +22 -0
- package/dist/components/Select/selectContext.d.cts +12 -0
- package/dist/components/Select/selectContext.d.cts.map +1 -0
- package/dist/components/Select/selectContext.d.ts +12 -0
- package/dist/components/Select/selectContext.d.ts.map +1 -0
- package/dist/components/Select/selectContext.js +19 -0
- package/dist/components/Select/selectContext.js.map +1 -0
- package/dist/components/Select/selectItemTheme.cjs +39 -0
- package/dist/components/Select/selectItemTheme.d.cts +19 -0
- package/dist/components/Select/selectItemTheme.d.cts.map +1 -0
- package/dist/components/Select/selectItemTheme.d.ts +19 -0
- package/dist/components/Select/selectItemTheme.d.ts.map +1 -0
- package/dist/components/Select/selectItemTheme.js +39 -0
- package/dist/components/Select/selectItemTheme.js.map +1 -0
- package/dist/components/Select/types.cjs +1 -0
- package/dist/components/Select/types.d.cts +43 -0
- package/dist/components/Select/types.d.cts.map +1 -0
- package/dist/components/Select/types.d.ts +43 -0
- package/dist/components/Select/types.d.ts.map +1 -0
- package/dist/components/Select/types.js +1 -0
- package/dist/components/Switch.cjs +34 -12
- package/dist/components/Switch.d.cts.map +1 -1
- package/dist/components/Switch.d.ts.map +1 -1
- package/dist/components/Switch.js +36 -14
- package/dist/components/Switch.js.map +1 -1
- package/dist/components/UDSGestureProvider.cjs +4 -0
- package/dist/components/UDSGestureProvider.d.cts +3 -0
- package/dist/components/UDSGestureProvider.d.ts +3 -0
- package/dist/components/UDSGestureProvider.js +3 -0
- package/dist/components/UDSProvider.cjs +10 -5
- package/dist/components/UDSProvider.d.cts +15 -7
- package/dist/components/UDSProvider.d.cts.map +1 -1
- package/dist/components/UDSProvider.d.ts +15 -7
- package/dist/components/UDSProvider.d.ts.map +1 -1
- package/dist/components/UDSProvider.js +10 -6
- package/dist/components/UDSProvider.js.map +1 -1
- package/dist/components/internal/Overlay/OverlayPortal.js.map +1 -1
- package/dist/components/internal/Overlay/index.cjs +2 -0
- package/dist/components/internal/Overlay/index.d.cts +2 -1
- package/dist/components/internal/Overlay/index.d.ts +2 -1
- package/dist/components/internal/Overlay/index.js +2 -1
- package/dist/components/internal/Overlay/measureTrigger.cjs +35 -0
- package/dist/components/internal/Overlay/measureTrigger.d.cts +9 -0
- package/dist/components/internal/Overlay/measureTrigger.d.cts.map +1 -0
- package/dist/components/internal/Overlay/measureTrigger.d.ts +9 -0
- package/dist/components/internal/Overlay/measureTrigger.d.ts.map +1 -0
- package/dist/components/internal/Overlay/measureTrigger.js +36 -0
- package/dist/components/internal/Overlay/measureTrigger.js.map +1 -0
- package/dist/jest/mocks/styles.cjs +68 -10
- package/dist/jest/mocks/styles.d.cts +5 -2
- package/dist/jest/mocks/styles.d.cts.map +1 -1
- package/dist/jest/mocks/styles.d.ts +5 -2
- package/dist/jest/mocks/styles.d.ts.map +1 -1
- package/dist/jest/mocks/styles.js +66 -11
- package/dist/jest/mocks/styles.js.map +1 -1
- package/dist/jest/mocks/unistyles.cjs +16 -1
- package/dist/jest/mocks/unistyles.d.cts +56 -2
- package/dist/jest/mocks/unistyles.d.cts.map +1 -1
- package/dist/jest/mocks/unistyles.d.ts +56 -2
- package/dist/jest/mocks/unistyles.d.ts.map +1 -1
- package/dist/jest/mocks/unistyles.js +16 -1
- package/dist/jest/mocks/unistyles.js.map +1 -1
- package/dist/portal.cjs +1 -1
- package/dist/portal.js +1 -1
- package/dist/portal.js.map +1 -1
- package/dist/types/dist/index.d.cts +28 -1
- package/dist/types/dist/index.d.cts.map +1 -1
- package/dist/types/dist/index.d.ts +28 -1
- package/dist/types/dist/index.d.ts.map +1 -1
- package/generated/styles.cjs +125 -0
- package/generated/styles.d.ts +39 -0
- package/generated/styles.mjs +125 -0
- package/generated/unistyles.d.ts +108 -8
- package/package.json +21 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
|
+
import { HStack } from "../HStack.js";
|
|
3
|
+
import { Text } from "../Text.js";
|
|
4
|
+
import { InputHelpText } from "../InputHelpText.js";
|
|
5
|
+
import { VStack } from "../VStack.js";
|
|
6
|
+
import { useControllableState } from "../internal/Overlay/useControllableState.js";
|
|
7
|
+
import { SelectContext, SelectFieldContext } from "./selectContext.js";
|
|
8
|
+
import { SelectTrigger } from "./SelectTrigger.js";
|
|
9
|
+
import { memo, useCallback, useId, useMemo, useRef, useState } from "react";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { inputStyles } from "../../../generated/styles";
|
|
12
|
+
import { isFunction } from "lodash-es";
|
|
13
|
+
//#region src/components/Select/Select.tsx
|
|
14
|
+
/**
|
|
15
|
+
* **⚙️ A composable Select component**
|
|
16
|
+
*
|
|
17
|
+
* @description
|
|
18
|
+
* Select lets users pick one value from a list. Compose with `SelectContent` and
|
|
19
|
+
* `SelectItem`, similar to `Tabs` with `TabList` and `Tab`.
|
|
20
|
+
*
|
|
21
|
+
* @category Form
|
|
22
|
+
* @platform mobile
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* import { Select, SelectContent, SelectItem } from '@yahoo/uds-mobile/Select';
|
|
27
|
+
*
|
|
28
|
+
* <Select label="Country" placeholder="Select a country" defaultValue="us">
|
|
29
|
+
* <SelectContent>
|
|
30
|
+
* <SelectItem value="us">United States</SelectItem>
|
|
31
|
+
* <SelectItem value="ca">Canada</SelectItem>
|
|
32
|
+
* </SelectContent>
|
|
33
|
+
* </Select>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
const Select = memo(function Select({ label, helpText, helperTextIcon, placeholder, size = "md", disabled, required, hasError, readOnly, width = "100%", reduceMotion = false, startIcon, endIcon, value: valueProp, defaultValue = "", onChange, children, testID }) {
|
|
37
|
+
const uid = `uds-select-${useId()}`;
|
|
38
|
+
const triggerRef = useRef(null);
|
|
39
|
+
const [triggerRect, setTriggerRect] = useState(null);
|
|
40
|
+
const [highlightedValue, setHighlightedValue] = useState(null);
|
|
41
|
+
const itemsRef = useRef(/* @__PURE__ */ new Map());
|
|
42
|
+
const [, setItemsVersion] = useState(0);
|
|
43
|
+
const [value, setValue] = useControllableState({
|
|
44
|
+
value: valueProp,
|
|
45
|
+
defaultValue,
|
|
46
|
+
onChange
|
|
47
|
+
});
|
|
48
|
+
const [open, setOpen] = useControllableState({
|
|
49
|
+
defaultValue: false,
|
|
50
|
+
onChange: (nextOpen) => {
|
|
51
|
+
if (!nextOpen) setHighlightedValue(null);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
const registerItem = useCallback((itemValue, itemLabel) => {
|
|
55
|
+
if (itemsRef.current.get(itemValue) === itemLabel) return;
|
|
56
|
+
itemsRef.current.set(itemValue, itemLabel);
|
|
57
|
+
setItemsVersion((version) => version + 1);
|
|
58
|
+
}, []);
|
|
59
|
+
const unregisterItem = useCallback((itemValue) => {
|
|
60
|
+
if (!itemsRef.current.has(itemValue)) return;
|
|
61
|
+
itemsRef.current.delete(itemValue);
|
|
62
|
+
setItemsVersion((version) => version + 1);
|
|
63
|
+
}, []);
|
|
64
|
+
const getItemLabel = useCallback((itemValue) => itemsRef.current.get(itemValue), []);
|
|
65
|
+
const fieldContext = useMemo(() => ({
|
|
66
|
+
size,
|
|
67
|
+
disabled,
|
|
68
|
+
readOnly,
|
|
69
|
+
required,
|
|
70
|
+
hasError,
|
|
71
|
+
width,
|
|
72
|
+
reduceMotion,
|
|
73
|
+
placeholder,
|
|
74
|
+
uid
|
|
75
|
+
}), [
|
|
76
|
+
disabled,
|
|
77
|
+
hasError,
|
|
78
|
+
placeholder,
|
|
79
|
+
readOnly,
|
|
80
|
+
reduceMotion,
|
|
81
|
+
required,
|
|
82
|
+
size,
|
|
83
|
+
uid,
|
|
84
|
+
width
|
|
85
|
+
]);
|
|
86
|
+
const contextValue = useMemo(() => ({
|
|
87
|
+
value,
|
|
88
|
+
setValue,
|
|
89
|
+
open,
|
|
90
|
+
setOpen,
|
|
91
|
+
triggerRef,
|
|
92
|
+
triggerRect,
|
|
93
|
+
setTriggerRect,
|
|
94
|
+
registerItem,
|
|
95
|
+
unregisterItem,
|
|
96
|
+
getItemLabel,
|
|
97
|
+
highlightedValue,
|
|
98
|
+
setHighlightedValue,
|
|
99
|
+
field: fieldContext,
|
|
100
|
+
reduceMotion
|
|
101
|
+
}), [
|
|
102
|
+
fieldContext,
|
|
103
|
+
getItemLabel,
|
|
104
|
+
highlightedValue,
|
|
105
|
+
open,
|
|
106
|
+
reduceMotion,
|
|
107
|
+
registerItem,
|
|
108
|
+
setOpen,
|
|
109
|
+
setValue,
|
|
110
|
+
triggerRect,
|
|
111
|
+
unregisterItem,
|
|
112
|
+
value
|
|
113
|
+
]);
|
|
114
|
+
const valueState = value.length > 0 ? "filled" : "empty";
|
|
115
|
+
inputStyles.useVariants({
|
|
116
|
+
size,
|
|
117
|
+
value: valueState,
|
|
118
|
+
pressed: open,
|
|
119
|
+
readonly: readOnly,
|
|
120
|
+
invalid: hasError
|
|
121
|
+
});
|
|
122
|
+
const rootStyle = useMemo(() => [{
|
|
123
|
+
width,
|
|
124
|
+
opacity: disabled ? .5 : 1
|
|
125
|
+
}], [disabled, width]);
|
|
126
|
+
const labelContent = useMemo(() => {
|
|
127
|
+
if (!label) return null;
|
|
128
|
+
const content = isFunction(label) ? label() : label;
|
|
129
|
+
return /* @__PURE__ */ jsxs(HStack, {
|
|
130
|
+
columnGap: "1",
|
|
131
|
+
alignItems: "flex-end",
|
|
132
|
+
spacingBottom: "2",
|
|
133
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
134
|
+
style: inputStyles.label,
|
|
135
|
+
children: content
|
|
136
|
+
}), required && /* @__PURE__ */ jsx(Text, {
|
|
137
|
+
style: inputStyles.labelRequired,
|
|
138
|
+
children: "*"
|
|
139
|
+
})]
|
|
140
|
+
});
|
|
141
|
+
}, [
|
|
142
|
+
label,
|
|
143
|
+
required,
|
|
144
|
+
inputStyles.label,
|
|
145
|
+
inputStyles.labelRequired
|
|
146
|
+
]);
|
|
147
|
+
const helpTextContent = useMemo(() => {
|
|
148
|
+
if (!helpText) return null;
|
|
149
|
+
const content = isFunction(helpText) ? helpText() : helpText;
|
|
150
|
+
return /* @__PURE__ */ jsx(InputHelpText, {
|
|
151
|
+
startIcon: helperTextIcon,
|
|
152
|
+
size,
|
|
153
|
+
isFilled: valueState === "filled",
|
|
154
|
+
disabled,
|
|
155
|
+
readOnly,
|
|
156
|
+
hasError,
|
|
157
|
+
pressed: open,
|
|
158
|
+
children: content
|
|
159
|
+
});
|
|
160
|
+
}, [
|
|
161
|
+
disabled,
|
|
162
|
+
hasError,
|
|
163
|
+
helpText,
|
|
164
|
+
helperTextIcon,
|
|
165
|
+
open,
|
|
166
|
+
readOnly,
|
|
167
|
+
size,
|
|
168
|
+
valueState
|
|
169
|
+
]);
|
|
170
|
+
return /* @__PURE__ */ jsx(SelectContext.Provider, {
|
|
171
|
+
value: contextValue,
|
|
172
|
+
children: /* @__PURE__ */ jsx(SelectFieldContext.Provider, {
|
|
173
|
+
value: fieldContext,
|
|
174
|
+
children: /* @__PURE__ */ jsxs(VStack, {
|
|
175
|
+
testID,
|
|
176
|
+
style: rootStyle,
|
|
177
|
+
children: [
|
|
178
|
+
labelContent,
|
|
179
|
+
/* @__PURE__ */ jsx(SelectTrigger, {
|
|
180
|
+
startIcon,
|
|
181
|
+
endIcon
|
|
182
|
+
}),
|
|
183
|
+
helpTextContent,
|
|
184
|
+
children
|
|
185
|
+
]
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
Select.displayName = "Select";
|
|
191
|
+
//#endregion
|
|
192
|
+
export { Select };
|
|
193
|
+
|
|
194
|
+
//# sourceMappingURL=Select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Select.js","names":[],"sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import type { UniversalSelectProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { ReactNode } from 'react';\nimport { memo, useCallback, useId, useMemo, useRef, useState } from 'react';\nimport type { View } from 'react-native';\n\nimport { inputStyles } from '../../../generated/styles';\nimport { HStack } from '../HStack';\nimport type { IconSlotType } from '../IconSlot';\nimport { InputHelpText } from '../InputHelpText';\nimport { useControllableState } from '../internal/Overlay';\nimport { Text } from '../Text';\nimport { VStack } from '../VStack';\nimport { SelectContext, SelectFieldContext } from './selectContext';\nimport { SelectTrigger } from './SelectTrigger';\nimport type { SelectContextValue, SelectFieldContextValue } from './types';\n\ninterface SelectProps extends Omit<UniversalSelectProps<IconSlotType>, 'width'> {\n /** Placeholder text shown when no value is selected. */\n placeholder?: string;\n /** Selected value for controlled usage. */\n value?: string;\n /** Initial value for uncontrolled usage. @default '' */\n defaultValue?: string;\n /** Called when the selected value changes. */\n onChange?: (value: string) => void;\n /** Container width. @default '100%' */\n width?: number | `${number}%` | '100%';\n children?: ReactNode;\n testID?: string;\n}\n\n/**\n * **⚙️ A composable Select component**\n *\n * @description\n * Select lets users pick one value from a list. Compose with `SelectContent` and\n * `SelectItem`, similar to `Tabs` with `TabList` and `Tab`.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Select, SelectContent, SelectItem } from '@yahoo/uds-mobile/Select';\n *\n * <Select label=\"Country\" placeholder=\"Select a country\" defaultValue=\"us\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"ca\">Canada</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nconst Select = memo(function Select({\n label,\n helpText,\n helperTextIcon,\n placeholder,\n size = 'md',\n disabled,\n required,\n hasError,\n readOnly,\n width = '100%',\n reduceMotion = false,\n startIcon,\n endIcon,\n value: valueProp,\n defaultValue = '',\n onChange,\n children,\n testID,\n}: SelectProps) {\n const generatedId = useId();\n const uid = `uds-select-${generatedId}`;\n const triggerRef = useRef<View | null>(null);\n const [triggerRect, setTriggerRect] = useState<SelectContextValue['triggerRect']>(null);\n const [highlightedValue, setHighlightedValue] = useState<string | null>(null);\n const itemsRef = useRef(new Map<string, string>());\n const [, setItemsVersion] = useState(0);\n\n const [value, setValue] = useControllableState({\n value: valueProp,\n defaultValue,\n onChange,\n });\n\n const [open, setOpen] = useControllableState({\n defaultValue: false,\n onChange: (nextOpen) => {\n if (!nextOpen) {\n setHighlightedValue(null);\n }\n },\n });\n\n const registerItem = useCallback((itemValue: string, itemLabel: string) => {\n if (itemsRef.current.get(itemValue) === itemLabel) {\n return;\n }\n\n itemsRef.current.set(itemValue, itemLabel);\n setItemsVersion((version) => version + 1);\n }, []);\n\n const unregisterItem = useCallback((itemValue: string) => {\n if (!itemsRef.current.has(itemValue)) {\n return;\n }\n\n itemsRef.current.delete(itemValue);\n setItemsVersion((version) => version + 1);\n }, []);\n\n const getItemLabel = useCallback((itemValue: string) => itemsRef.current.get(itemValue), []);\n\n const fieldContext = useMemo<SelectFieldContextValue>(\n () => ({\n size,\n disabled,\n readOnly,\n required,\n hasError,\n width,\n reduceMotion,\n placeholder,\n uid,\n }),\n [disabled, hasError, placeholder, readOnly, reduceMotion, required, size, uid, width],\n );\n\n const contextValue = useMemo<SelectContextValue>(\n () => ({\n value,\n setValue,\n open,\n setOpen,\n triggerRef,\n triggerRect,\n setTriggerRect,\n registerItem,\n unregisterItem,\n getItemLabel,\n highlightedValue,\n setHighlightedValue,\n field: fieldContext,\n reduceMotion,\n }),\n [\n fieldContext,\n getItemLabel,\n highlightedValue,\n open,\n reduceMotion,\n registerItem,\n setOpen,\n setValue,\n triggerRect,\n unregisterItem,\n value,\n ],\n );\n\n const hasValue = value.length > 0;\n const valueState = hasValue ? 'filled' : 'empty';\n\n inputStyles.useVariants({\n size,\n value: valueState,\n pressed: open,\n readonly: readOnly,\n invalid: hasError,\n });\n\n const rootStyle = useMemo(() => [{ width, opacity: disabled ? 0.5 : 1 }], [disabled, width]);\n\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n\n const content = isFunction(label) ? label() : label;\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-end\" spacingBottom=\"2\">\n <Text style={inputStyles.label}>{content}</Text>\n {required && <Text style={inputStyles.labelRequired}>*</Text>}\n </HStack>\n );\n }, [label, required, inputStyles.label, inputStyles.labelRequired]);\n\n const helpTextContent = useMemo(() => {\n if (!helpText) {\n return null;\n }\n\n const content = isFunction(helpText) ? helpText() : helpText;\n return (\n <InputHelpText\n startIcon={helperTextIcon}\n size={size}\n isFilled={valueState === 'filled'}\n disabled={disabled}\n readOnly={readOnly}\n hasError={hasError}\n pressed={open}\n >\n {content}\n </InputHelpText>\n );\n }, [disabled, hasError, helpText, helperTextIcon, open, readOnly, size, valueState]);\n\n return (\n <SelectContext.Provider value={contextValue}>\n <SelectFieldContext.Provider value={fieldContext}>\n <VStack testID={testID} style={rootStyle}>\n {labelContent}\n\n <SelectTrigger startIcon={startIcon} endIcon={endIcon} />\n\n {helpTextContent}\n\n {children}\n </VStack>\n </SelectFieldContext.Provider>\n </SelectContext.Provider>\n );\n});\n\nSelect.displayName = 'Select';\n\nexport { Select, type SelectProps };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
|
|
4
|
+
const require_components_VStack = require("../VStack.cjs");
|
|
5
|
+
const require_components_internal_Overlay_useAnchoredPosition = require("../internal/Overlay/useAnchoredPosition.cjs");
|
|
6
|
+
const require_components_Popover_PopoverPortalLayer = require("../Popover/PopoverPortalLayer.cjs");
|
|
7
|
+
const require_components_Select_selectContext = require("./selectContext.cjs");
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let react_native = require("react-native");
|
|
10
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
11
|
+
let generated_styles = require("../../../generated/styles");
|
|
12
|
+
let react_native_reanimated = require("react-native-reanimated");
|
|
13
|
+
react_native_reanimated = require_runtime.__toESM(react_native_reanimated);
|
|
14
|
+
//#region src/components/Select/SelectContent.tsx
|
|
15
|
+
const DEFAULT_OFFSET = 4;
|
|
16
|
+
const DEFAULT_MAX_HEIGHT = 240;
|
|
17
|
+
const ANIMATION_DURATION = 200;
|
|
18
|
+
const OFFSCREEN_REGISTRY_STYLE = react_native.StyleSheet.create({ registry: {
|
|
19
|
+
position: "absolute",
|
|
20
|
+
top: 0,
|
|
21
|
+
left: 0,
|
|
22
|
+
width: 1,
|
|
23
|
+
height: 1,
|
|
24
|
+
opacity: 0,
|
|
25
|
+
overflow: "hidden",
|
|
26
|
+
zIndex: -1
|
|
27
|
+
} });
|
|
28
|
+
/**
|
|
29
|
+
* **▾ Select content panel**
|
|
30
|
+
*
|
|
31
|
+
* Floating listbox container for {@link SelectItem} options.
|
|
32
|
+
*/
|
|
33
|
+
const SelectContent = (0, react.memo)(function SelectContent({ children, size: _size = "default", variant: _variant = "default", keepOpenOnInteractOutside = false, maxHeight = DEFAULT_MAX_HEIGHT, gutter = DEFAULT_OFFSET, sameWidth = true, style, testID }) {
|
|
34
|
+
const { open, setOpen, triggerRect, reduceMotion } = require_components_Select_selectContext.useSelectContext();
|
|
35
|
+
const [contentSize, setContentSize] = (0, react.useState)({
|
|
36
|
+
width: 0,
|
|
37
|
+
height: 0
|
|
38
|
+
});
|
|
39
|
+
const [shouldRender, setShouldRender] = (0, react.useState)(open);
|
|
40
|
+
const dismiss = (0, react.useCallback)(() => {
|
|
41
|
+
if (keepOpenOnInteractOutside) return;
|
|
42
|
+
setOpen(false);
|
|
43
|
+
}, [keepOpenOnInteractOutside, setOpen]);
|
|
44
|
+
const { contentStyle, anchorReady, maxWidth: positionedMaxWidth } = require_components_internal_Overlay_useAnchoredPosition.useAnchoredPosition({
|
|
45
|
+
triggerRect,
|
|
46
|
+
contentSize,
|
|
47
|
+
placement: "bottom",
|
|
48
|
+
offset: gutter,
|
|
49
|
+
sameWidth,
|
|
50
|
+
width: sameWidth ? "trigger" : "content",
|
|
51
|
+
avoidCollisions: true,
|
|
52
|
+
collisionPadding: 12
|
|
53
|
+
});
|
|
54
|
+
const isPositionedOpen = open && anchorReady && contentSize.height > 0;
|
|
55
|
+
const progress = (0, react_native_reanimated.useDerivedValue)(() => (0, react_native_reanimated.withTiming)(isPositionedOpen ? 1 : 0, {
|
|
56
|
+
duration: reduceMotion ? 0 : ANIMATION_DURATION,
|
|
57
|
+
easing: react_native_reanimated.Easing.out(react_native_reanimated.Easing.ease)
|
|
58
|
+
}), [isPositionedOpen, reduceMotion]);
|
|
59
|
+
const animatedStyle = (0, react_native_reanimated.useAnimatedStyle)(() => ({
|
|
60
|
+
opacity: progress.value,
|
|
61
|
+
transform: [{ scale: .97 + progress.value * .03 }, { translateY: (1 - progress.value) * 8 }]
|
|
62
|
+
}));
|
|
63
|
+
const handleLayout = (0, react.useCallback)((event) => {
|
|
64
|
+
const { width, height } = event.nativeEvent.layout;
|
|
65
|
+
setContentSize({
|
|
66
|
+
width,
|
|
67
|
+
height
|
|
68
|
+
});
|
|
69
|
+
}, []);
|
|
70
|
+
(0, react.useEffect)(() => {
|
|
71
|
+
if (open) {
|
|
72
|
+
setShouldRender(true);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (reduceMotion) {
|
|
76
|
+
setShouldRender(false);
|
|
77
|
+
setContentSize({
|
|
78
|
+
width: 0,
|
|
79
|
+
height: 0
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const timeout = setTimeout(() => {
|
|
84
|
+
setShouldRender(false);
|
|
85
|
+
setContentSize({
|
|
86
|
+
width: 0,
|
|
87
|
+
height: 0
|
|
88
|
+
});
|
|
89
|
+
}, ANIMATION_DURATION);
|
|
90
|
+
return () => clearTimeout(timeout);
|
|
91
|
+
}, [open, reduceMotion]);
|
|
92
|
+
generated_styles.selectContentStyles.useVariants({});
|
|
93
|
+
const panelStyle = (0, react.useMemo)(() => react_native.StyleSheet.flatten([
|
|
94
|
+
generated_styles.selectContentStyles.root,
|
|
95
|
+
{
|
|
96
|
+
maxHeight,
|
|
97
|
+
maxWidth: positionedMaxWidth > 0 ? positionedMaxWidth : void 0,
|
|
98
|
+
overflow: "hidden",
|
|
99
|
+
zIndex: 1
|
|
100
|
+
},
|
|
101
|
+
style
|
|
102
|
+
]), [
|
|
103
|
+
maxHeight,
|
|
104
|
+
positionedMaxWidth,
|
|
105
|
+
generated_styles.selectContentStyles.root,
|
|
106
|
+
style
|
|
107
|
+
]);
|
|
108
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
|
|
109
|
+
accessibilityElementsHidden: true,
|
|
110
|
+
importantForAccessibility: "no-hide-descendants",
|
|
111
|
+
pointerEvents: "none",
|
|
112
|
+
style: OFFSCREEN_REGISTRY_STYLE.registry,
|
|
113
|
+
children
|
|
114
|
+
}) : null, open && shouldRender ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Popover_PopoverPortalLayer.PopoverPortalLayer, {
|
|
115
|
+
open,
|
|
116
|
+
dismissible: !keepOpenOnInteractOutside,
|
|
117
|
+
onDismiss: dismiss,
|
|
118
|
+
children: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
|
|
119
|
+
testID,
|
|
120
|
+
style: [
|
|
121
|
+
contentStyle,
|
|
122
|
+
animatedStyle,
|
|
123
|
+
{
|
|
124
|
+
overflow: "visible",
|
|
125
|
+
zIndex: 1e3
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
onLayout: handleLayout,
|
|
129
|
+
accessibilityRole: "menu",
|
|
130
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
|
|
131
|
+
style: panelStyle,
|
|
132
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ScrollView, {
|
|
133
|
+
keyboardShouldPersistTaps: "handled",
|
|
134
|
+
nestedScrollEnabled: true,
|
|
135
|
+
style: { maxHeight },
|
|
136
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_VStack.VStack, {
|
|
137
|
+
alignItems: "stretch",
|
|
138
|
+
justifyContent: "flex-start",
|
|
139
|
+
children
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
}) : null] });
|
|
145
|
+
});
|
|
146
|
+
SelectContent.displayName = "SelectContent";
|
|
147
|
+
//#endregion
|
|
148
|
+
exports.SelectContent = SelectContent;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
import { SelectContentSize, SelectContentVariant } from "./types.cjs";
|
|
3
|
+
import * as _$react from "react";
|
|
4
|
+
import { ReactNode } from "react";
|
|
5
|
+
import { StyleProp, ViewStyle } from "react-native";
|
|
6
|
+
|
|
7
|
+
//#region src/components/Select/SelectContent.d.ts
|
|
8
|
+
interface SelectContentProps {
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
size?: SelectContentSize;
|
|
11
|
+
variant?: SelectContentVariant;
|
|
12
|
+
/** When true, the panel stays open when the user taps outside. */
|
|
13
|
+
keepOpenOnInteractOutside?: boolean;
|
|
14
|
+
/** Maximum height of the options list in pixels. @default 240 */
|
|
15
|
+
maxHeight?: number;
|
|
16
|
+
/** Distance between the trigger and the content panel. @default 4 */
|
|
17
|
+
gutter?: number;
|
|
18
|
+
/** When true, the content panel matches the trigger width. @default true */
|
|
19
|
+
sameWidth?: boolean;
|
|
20
|
+
style?: StyleProp<ViewStyle>;
|
|
21
|
+
testID?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* **▾ Select content panel**
|
|
25
|
+
*
|
|
26
|
+
* Floating listbox container for {@link SelectItem} options.
|
|
27
|
+
*/
|
|
28
|
+
declare const SelectContent: _$react.NamedExoticComponent<SelectContentProps>;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { SelectContent, type SelectContentProps };
|
|
31
|
+
//# sourceMappingURL=SelectContent.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectContent.d.cts","names":[],"sources":["../../../src/components/Select/SelectContent.tsx"],"mappings":";;;;;;;UAmCU,kBAAA;EACR,QAAA,GAAW,SAAA;EACX,IAAA,GAAO,iBAAA;EACP,OAAA,GAAU,oBAAA;EAHgB;EAK1B,yBAAA;EAJW;EAMX,SAAA;EAJU;EAMV,MAAA;EAGQ;EADR,SAAA;EACA,KAAA,GAAQ,SAAA,CAAU,SAAA;EAClB,MAAA;AAAA;;;;;;cAQI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
import { SelectContentSize, SelectContentVariant } from "./types.js";
|
|
3
|
+
import * as _$react from "react";
|
|
4
|
+
import { ReactNode } from "react";
|
|
5
|
+
import { StyleProp, ViewStyle } from "react-native";
|
|
6
|
+
|
|
7
|
+
//#region src/components/Select/SelectContent.d.ts
|
|
8
|
+
interface SelectContentProps {
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
size?: SelectContentSize;
|
|
11
|
+
variant?: SelectContentVariant;
|
|
12
|
+
/** When true, the panel stays open when the user taps outside. */
|
|
13
|
+
keepOpenOnInteractOutside?: boolean;
|
|
14
|
+
/** Maximum height of the options list in pixels. @default 240 */
|
|
15
|
+
maxHeight?: number;
|
|
16
|
+
/** Distance between the trigger and the content panel. @default 4 */
|
|
17
|
+
gutter?: number;
|
|
18
|
+
/** When true, the content panel matches the trigger width. @default true */
|
|
19
|
+
sameWidth?: boolean;
|
|
20
|
+
style?: StyleProp<ViewStyle>;
|
|
21
|
+
testID?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* **▾ Select content panel**
|
|
25
|
+
*
|
|
26
|
+
* Floating listbox container for {@link SelectItem} options.
|
|
27
|
+
*/
|
|
28
|
+
declare const SelectContent: _$react.NamedExoticComponent<SelectContentProps>;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { SelectContent, type SelectContentProps };
|
|
31
|
+
//# sourceMappingURL=SelectContent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectContent.d.ts","names":[],"sources":["../../../src/components/Select/SelectContent.tsx"],"mappings":";;;;;;;UAmCU,kBAAA;EACR,QAAA,GAAW,SAAA;EACX,IAAA,GAAO,iBAAA;EACP,OAAA,GAAU,oBAAA;EAHgB;EAK1B,yBAAA;EAJW;EAMX,SAAA;EAJU;EAMV,MAAA;EAGQ;EADR,SAAA;EACA,KAAA,GAAQ,SAAA,CAAU,SAAA;EAClB,MAAA;AAAA;;;;;;cAQI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
|
+
import { VStack } from "../VStack.js";
|
|
3
|
+
import { useAnchoredPosition } from "../internal/Overlay/useAnchoredPosition.js";
|
|
4
|
+
import { PopoverPortalLayer } from "../Popover/PopoverPortalLayer.js";
|
|
5
|
+
import { useSelectContext } from "./selectContext.js";
|
|
6
|
+
import { memo, useCallback, useEffect, useMemo, useState } from "react";
|
|
7
|
+
import { ScrollView, StyleSheet, View } from "react-native";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { selectContentStyles } from "../../../generated/styles";
|
|
10
|
+
import Animated, { Easing, useAnimatedStyle, useDerivedValue, withTiming } from "react-native-reanimated";
|
|
11
|
+
//#region src/components/Select/SelectContent.tsx
|
|
12
|
+
const DEFAULT_OFFSET = 4;
|
|
13
|
+
const DEFAULT_MAX_HEIGHT = 240;
|
|
14
|
+
const ANIMATION_DURATION = 200;
|
|
15
|
+
const OFFSCREEN_REGISTRY_STYLE = StyleSheet.create({ registry: {
|
|
16
|
+
position: "absolute",
|
|
17
|
+
top: 0,
|
|
18
|
+
left: 0,
|
|
19
|
+
width: 1,
|
|
20
|
+
height: 1,
|
|
21
|
+
opacity: 0,
|
|
22
|
+
overflow: "hidden",
|
|
23
|
+
zIndex: -1
|
|
24
|
+
} });
|
|
25
|
+
/**
|
|
26
|
+
* **▾ Select content panel**
|
|
27
|
+
*
|
|
28
|
+
* Floating listbox container for {@link SelectItem} options.
|
|
29
|
+
*/
|
|
30
|
+
const SelectContent = memo(function SelectContent({ children, size: _size = "default", variant: _variant = "default", keepOpenOnInteractOutside = false, maxHeight = DEFAULT_MAX_HEIGHT, gutter = DEFAULT_OFFSET, sameWidth = true, style, testID }) {
|
|
31
|
+
const { open, setOpen, triggerRect, reduceMotion } = useSelectContext();
|
|
32
|
+
const [contentSize, setContentSize] = useState({
|
|
33
|
+
width: 0,
|
|
34
|
+
height: 0
|
|
35
|
+
});
|
|
36
|
+
const [shouldRender, setShouldRender] = useState(open);
|
|
37
|
+
const dismiss = useCallback(() => {
|
|
38
|
+
if (keepOpenOnInteractOutside) return;
|
|
39
|
+
setOpen(false);
|
|
40
|
+
}, [keepOpenOnInteractOutside, setOpen]);
|
|
41
|
+
const { contentStyle, anchorReady, maxWidth: positionedMaxWidth } = useAnchoredPosition({
|
|
42
|
+
triggerRect,
|
|
43
|
+
contentSize,
|
|
44
|
+
placement: "bottom",
|
|
45
|
+
offset: gutter,
|
|
46
|
+
sameWidth,
|
|
47
|
+
width: sameWidth ? "trigger" : "content",
|
|
48
|
+
avoidCollisions: true,
|
|
49
|
+
collisionPadding: 12
|
|
50
|
+
});
|
|
51
|
+
const isPositionedOpen = open && anchorReady && contentSize.height > 0;
|
|
52
|
+
const progress = useDerivedValue(() => withTiming(isPositionedOpen ? 1 : 0, {
|
|
53
|
+
duration: reduceMotion ? 0 : ANIMATION_DURATION,
|
|
54
|
+
easing: Easing.out(Easing.ease)
|
|
55
|
+
}), [isPositionedOpen, reduceMotion]);
|
|
56
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
57
|
+
opacity: progress.value,
|
|
58
|
+
transform: [{ scale: .97 + progress.value * .03 }, { translateY: (1 - progress.value) * 8 }]
|
|
59
|
+
}));
|
|
60
|
+
const handleLayout = useCallback((event) => {
|
|
61
|
+
const { width, height } = event.nativeEvent.layout;
|
|
62
|
+
setContentSize({
|
|
63
|
+
width,
|
|
64
|
+
height
|
|
65
|
+
});
|
|
66
|
+
}, []);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (open) {
|
|
69
|
+
setShouldRender(true);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (reduceMotion) {
|
|
73
|
+
setShouldRender(false);
|
|
74
|
+
setContentSize({
|
|
75
|
+
width: 0,
|
|
76
|
+
height: 0
|
|
77
|
+
});
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const timeout = setTimeout(() => {
|
|
81
|
+
setShouldRender(false);
|
|
82
|
+
setContentSize({
|
|
83
|
+
width: 0,
|
|
84
|
+
height: 0
|
|
85
|
+
});
|
|
86
|
+
}, ANIMATION_DURATION);
|
|
87
|
+
return () => clearTimeout(timeout);
|
|
88
|
+
}, [open, reduceMotion]);
|
|
89
|
+
selectContentStyles.useVariants({});
|
|
90
|
+
const panelStyle = useMemo(() => StyleSheet.flatten([
|
|
91
|
+
selectContentStyles.root,
|
|
92
|
+
{
|
|
93
|
+
maxHeight,
|
|
94
|
+
maxWidth: positionedMaxWidth > 0 ? positionedMaxWidth : void 0,
|
|
95
|
+
overflow: "hidden",
|
|
96
|
+
zIndex: 1
|
|
97
|
+
},
|
|
98
|
+
style
|
|
99
|
+
]), [
|
|
100
|
+
maxHeight,
|
|
101
|
+
positionedMaxWidth,
|
|
102
|
+
selectContentStyles.root,
|
|
103
|
+
style
|
|
104
|
+
]);
|
|
105
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [!open ? /* @__PURE__ */ jsx(View, {
|
|
106
|
+
accessibilityElementsHidden: true,
|
|
107
|
+
importantForAccessibility: "no-hide-descendants",
|
|
108
|
+
pointerEvents: "none",
|
|
109
|
+
style: OFFSCREEN_REGISTRY_STYLE.registry,
|
|
110
|
+
children
|
|
111
|
+
}) : null, open && shouldRender ? /* @__PURE__ */ jsx(PopoverPortalLayer, {
|
|
112
|
+
open,
|
|
113
|
+
dismissible: !keepOpenOnInteractOutside,
|
|
114
|
+
onDismiss: dismiss,
|
|
115
|
+
children: () => /* @__PURE__ */ jsx(Animated.View, {
|
|
116
|
+
testID,
|
|
117
|
+
style: [
|
|
118
|
+
contentStyle,
|
|
119
|
+
animatedStyle,
|
|
120
|
+
{
|
|
121
|
+
overflow: "visible",
|
|
122
|
+
zIndex: 1e3
|
|
123
|
+
}
|
|
124
|
+
],
|
|
125
|
+
onLayout: handleLayout,
|
|
126
|
+
accessibilityRole: "menu",
|
|
127
|
+
children: /* @__PURE__ */ jsx(View, {
|
|
128
|
+
style: panelStyle,
|
|
129
|
+
children: /* @__PURE__ */ jsx(ScrollView, {
|
|
130
|
+
keyboardShouldPersistTaps: "handled",
|
|
131
|
+
nestedScrollEnabled: true,
|
|
132
|
+
style: { maxHeight },
|
|
133
|
+
children: /* @__PURE__ */ jsx(VStack, {
|
|
134
|
+
alignItems: "stretch",
|
|
135
|
+
justifyContent: "flex-start",
|
|
136
|
+
children
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
}) : null] });
|
|
142
|
+
});
|
|
143
|
+
SelectContent.displayName = "SelectContent";
|
|
144
|
+
//#endregion
|
|
145
|
+
export { SelectContent };
|
|
146
|
+
|
|
147
|
+
//# sourceMappingURL=SelectContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectContent.js","names":["RNScrollView"],"sources":["../../../src/components/Select/SelectContent.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type { LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';\nimport { ScrollView as RNScrollView, StyleSheet, View } from 'react-native';\nimport Animated, {\n Easing,\n useAnimatedStyle,\n useDerivedValue,\n withTiming,\n} from 'react-native-reanimated';\n\nimport { selectContentStyles } from '../../../generated/styles';\nimport { useAnchoredPosition } from '../internal/Overlay';\nimport { PopoverPortalLayer } from '../Popover/PopoverPortalLayer';\nimport { VStack } from '../VStack';\nimport { useSelectContext } from './selectContext';\nimport type { SelectContentSize, SelectContentVariant } from './types';\n\nconst DEFAULT_OFFSET = 4;\nconst DEFAULT_MAX_HEIGHT = 240;\nconst ANIMATION_DURATION = 200;\n\nconst OFFSCREEN_REGISTRY_STYLE = StyleSheet.create({\n registry: {\n position: 'absolute',\n top: 0,\n left: 0,\n width: 1,\n height: 1,\n opacity: 0,\n overflow: 'hidden',\n zIndex: -1,\n },\n});\n\ninterface SelectContentProps {\n children?: ReactNode;\n size?: SelectContentSize;\n variant?: SelectContentVariant;\n /** When true, the panel stays open when the user taps outside. */\n keepOpenOnInteractOutside?: boolean;\n /** Maximum height of the options list in pixels. @default 240 */\n maxHeight?: number;\n /** Distance between the trigger and the content panel. @default 4 */\n gutter?: number;\n /** When true, the content panel matches the trigger width. @default true */\n sameWidth?: boolean;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\n/**\n * **▾ Select content panel**\n *\n * Floating listbox container for {@link SelectItem} options.\n */\nconst SelectContent = memo(function SelectContent({\n children,\n size: _size = 'default',\n variant: _variant = 'default',\n keepOpenOnInteractOutside = false,\n maxHeight = DEFAULT_MAX_HEIGHT,\n gutter = DEFAULT_OFFSET,\n sameWidth = true,\n style,\n testID,\n}: SelectContentProps) {\n const { open, setOpen, triggerRect, reduceMotion } = useSelectContext();\n const [contentSize, setContentSize] = useState({ width: 0, height: 0 });\n const [shouldRender, setShouldRender] = useState(open);\n\n const dismiss = useCallback(() => {\n if (keepOpenOnInteractOutside) {\n return;\n }\n\n setOpen(false);\n }, [keepOpenOnInteractOutside, setOpen]);\n\n const {\n contentStyle,\n anchorReady,\n maxWidth: positionedMaxWidth,\n } = useAnchoredPosition({\n triggerRect,\n contentSize,\n placement: 'bottom',\n offset: gutter,\n sameWidth,\n width: sameWidth ? 'trigger' : 'content',\n avoidCollisions: true,\n collisionPadding: 12,\n });\n\n const isPositionedOpen = open && anchorReady && contentSize.height > 0;\n const progress = useDerivedValue(\n () =>\n withTiming(isPositionedOpen ? 1 : 0, {\n duration: reduceMotion ? 0 : ANIMATION_DURATION,\n easing: Easing.out(Easing.ease),\n }),\n [isPositionedOpen, reduceMotion],\n );\n\n const animatedStyle = useAnimatedStyle(() => ({\n opacity: progress.value,\n transform: [{ scale: 0.97 + progress.value * 0.03 }, { translateY: (1 - progress.value) * 8 }],\n }));\n\n const handleLayout = useCallback((event: LayoutChangeEvent) => {\n const { width, height } = event.nativeEvent.layout;\n setContentSize({ width, height });\n }, []);\n\n useEffect(() => {\n if (open) {\n setShouldRender(true);\n return;\n }\n\n if (reduceMotion) {\n setShouldRender(false);\n setContentSize({ width: 0, height: 0 });\n return;\n }\n\n const timeout = setTimeout(() => {\n setShouldRender(false);\n setContentSize({ width: 0, height: 0 });\n }, ANIMATION_DURATION);\n\n return () => clearTimeout(timeout);\n }, [open, reduceMotion]);\n\n selectContentStyles.useVariants({});\n\n const panelStyle = useMemo(\n () =>\n StyleSheet.flatten([\n selectContentStyles.root,\n {\n maxHeight,\n maxWidth: positionedMaxWidth > 0 ? positionedMaxWidth : undefined,\n overflow: 'hidden',\n zIndex: 1,\n },\n style,\n ]) as ViewStyle,\n [maxHeight, positionedMaxWidth, selectContentStyles.root, style],\n );\n\n return (\n <>\n {!open ? (\n <View\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n pointerEvents=\"none\"\n style={OFFSCREEN_REGISTRY_STYLE.registry}\n >\n {children}\n </View>\n ) : null}\n\n {open && shouldRender ? (\n <PopoverPortalLayer\n open={open}\n dismissible={!keepOpenOnInteractOutside}\n onDismiss={dismiss}\n >\n {() => (\n <Animated.View\n testID={testID}\n style={[contentStyle, animatedStyle, { overflow: 'visible', zIndex: 1000 }]}\n onLayout={handleLayout}\n accessibilityRole=\"menu\"\n >\n <View style={panelStyle}>\n <RNScrollView\n keyboardShouldPersistTaps=\"handled\"\n nestedScrollEnabled\n style={{ maxHeight }}\n >\n <VStack alignItems=\"stretch\" justifyContent=\"flex-start\">\n {children}\n </VStack>\n </RNScrollView>\n </View>\n </Animated.View>\n )}\n </PopoverPortalLayer>\n ) : null}\n </>\n );\n});\n\nSelectContent.displayName = 'SelectContent';\n\nexport { SelectContent, type SelectContentProps };\n"],"mappings":"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"}
|