@tamagui/select 1.0.1-beta.36 → 1.0.1-beta.39

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.
@@ -51,34 +51,41 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
51
51
  var Select_exports = {};
52
52
  __export(Select_exports, {
53
53
  Select: () => Select,
54
- SelectContent: () => SelectContent,
55
- SelectGroup: () => SelectGroup,
56
54
  SelectIcon: () => SelectIcon,
57
- SelectItem: () => SelectItem,
58
- SelectItemIndicator: () => SelectItemIndicator,
59
- SelectItemText: () => SelectItemText,
60
- SelectLabel: () => SelectLabel,
61
- SelectScrollDownButton: () => SelectScrollDownButton,
62
- SelectScrollUpButton: () => SelectScrollUpButton,
63
55
  SelectSeparator: () => SelectSeparator,
64
56
  SelectTrigger: () => SelectTrigger,
65
- SelectValue: () => SelectValue,
57
+ SelectViewportFrame: () => SelectViewportFrame,
66
58
  createSelectScope: () => createSelectScope
67
59
  });
68
60
  module.exports = __toCommonJS(Select_exports);
69
61
  var import_react_dom_interactions = require("@floating-ui/react-dom-interactions");
70
62
  var import_react_use_previous = require("@radix-ui/react-use-previous");
63
+ var import_button = require("@tamagui/button");
71
64
  var import_compose_refs = require("@tamagui/compose-refs");
72
65
  var import_core = require("@tamagui/core");
73
66
  var import_core2 = require("@tamagui/core");
74
67
  var import_create_context = require("@tamagui/create-context");
75
68
  var import_separator = require("@tamagui/separator");
76
69
  var import_stacks = require("@tamagui/stacks");
70
+ var import_text = require("@tamagui/text");
77
71
  var import_use_controllable_state = require("@tamagui/use-controllable-state");
78
72
  var React = __toESM(require("react"));
79
73
  var ReactDOM = __toESM(require("react-dom"));
80
- const OPEN_KEYS = [" ", "Enter", "ArrowUp", "ArrowDown"];
81
- const SELECTION_KEYS = [" ", "Enter"];
74
+ const isFirefox = typeof navigator !== "undefined" && navigator.userAgent.toLowerCase().includes("firefox");
75
+ if (isFirefox) {
76
+ document.body.classList.add("firefox");
77
+ }
78
+ function getVisualOffsetTop() {
79
+ return !/^((?!chrome|android).)*safari/i.test(navigator.userAgent) ? visualViewport.offsetTop : 0;
80
+ }
81
+ __name(getVisualOffsetTop, "getVisualOffsetTop");
82
+ const getSelectItemSize = /* @__PURE__ */ __name((val, { tokens }) => {
83
+ const padding = (0, import_core.getVariableValue)(tokens.size[val]);
84
+ return {
85
+ paddingHorizontal: padding / 2,
86
+ paddingVertical: padding / 4
87
+ };
88
+ }, "getSelectItemSize");
82
89
  const SELECT_NAME = "Select";
83
90
  const WINDOW_PADDING = 8;
84
91
  const SCROLL_ARROW_VELOCITY = 8;
@@ -87,61 +94,8 @@ const MIN_HEIGHT = 80;
87
94
  const FALLBACK_THRESHOLD = 16;
88
95
  const [createSelectContext, createSelectScope] = (0, import_create_context.createContextScope)(SELECT_NAME);
89
96
  const [SelectProvider, useSelectContext] = createSelectContext(SELECT_NAME);
90
- const Select = /* @__PURE__ */ __name((props) => {
91
- const {
92
- __scopeSelect,
93
- children,
94
- open: openProp,
95
- defaultOpen,
96
- onOpenChange,
97
- value: valueProp,
98
- defaultValue,
99
- onValueChange,
100
- dir: dir2,
101
- name,
102
- autoComplete
103
- } = props;
104
- const [open, setOpen] = (0, import_use_controllable_state.useControllableState)({
105
- prop: openProp,
106
- defaultProp: defaultOpen || false,
107
- onChange: onOpenChange
108
- });
109
- const [value, setValue] = (0, import_use_controllable_state.useControllableState)({
110
- prop: valueProp,
111
- defaultProp: defaultValue || "",
112
- onChange: onValueChange
113
- });
114
- const selectedIndexRef = React.useRef(null);
115
- const activeIndexRef = React.useRef(null);
116
- const prevActiveIndex = (0, import_react_use_previous.usePrevious)(activeIndex);
117
- const [showArrows, setShowArrows] = React.useState(false);
118
- const [scrollTop, setScrollTop] = React.useState(0);
119
- const [activeIndex, setActiveIndex] = React.useState(null);
120
- const [selectedIndex, setSelectedIndex] = React.useState(Math.max(0, listContentRef.current.indexOf(value)));
121
- (0, import_core.useIsomorphicLayoutEffect)(() => {
122
- selectedIndexRef.current = selectedIndex;
123
- activeIndexRef.current = activeIndex;
124
- });
125
- useEffect(() => {
126
- const frame = requestAnimationFrame(() => {
127
- setShowArrows(open);
128
- if (!open) {
129
- setScrollTop(0);
130
- setMiddlewareType("align");
131
- setActiveIndex(null);
132
- setControlledScrolling(false);
133
- }
134
- });
135
- return () => cancelAnimationFrame(frame);
136
- }, [open]);
137
- const showUpArrow = showArrows && scrollTop > SCROLL_ARROW_THRESHOLD;
138
- const showDownArrow = showArrows && floatingRef.current && scrollTop < floatingRef.current.scrollHeight - floatingRef.current.clientHeight - SCROLL_ARROW_THRESHOLD;
139
- return /* @__PURE__ */ React.createElement(SelectProvider, {
140
- scope: __scopeSelect,
141
- open
142
- }, children);
143
- }, "Select");
144
- Select.displayName = SELECT_NAME;
97
+ const OPEN_KEYS = [" ", "Enter", "ArrowUp", "ArrowDown"];
98
+ const SELECTION_KEYS = [" ", "Enter"];
145
99
  const TRIGGER_NAME = "SelectTrigger";
146
100
  const SelectTrigger = React.forwardRef((props, forwardedRef) => {
147
101
  const _a = props, {
@@ -154,298 +108,780 @@ const SelectTrigger = React.forwardRef((props, forwardedRef) => {
154
108
  "aria-labelledby"
155
109
  ]);
156
110
  const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
157
- const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, context.onTriggerChange);
158
- const getItems = useCollection(__scopeSelect);
159
- const handleOpen = /* @__PURE__ */ __name(() => {
160
- if (!disabled) {
161
- context.onOpenChange(true);
162
- resetTypeahead();
163
- }
164
- }, "handleOpen");
165
- return /* @__PURE__ */ React.createElement(Primitive.button, __spreadProps(__spreadValues({
166
- type: "button",
167
- role: "combobox",
168
- "aria-controls": context.contentId,
111
+ return /* @__PURE__ */ React.createElement(import_button.Button, __spreadValues(__spreadProps(__spreadValues({
112
+ componentName: TRIGGER_NAME,
169
113
  "aria-expanded": context.open,
170
114
  "aria-autocomplete": "none",
171
- dir: context.dir,
172
115
  disabled,
173
116
  "data-disabled": disabled ? "" : void 0
174
117
  }, triggerProps), {
175
- ref: composedRefs,
176
- onPointerDown: (0, import_core.composeEventHandlers)(triggerProps.onPointerDown, (event) => {
177
- ;
178
- event.target.releasePointerCapture(event.pointerId);
179
- if (event.button === 0 && event.ctrlKey === false) {
180
- handleOpen();
181
- context.triggerPointerDownPosRef.current = {
182
- x: Math.round(event.pageX),
183
- y: Math.round(event.pageY)
184
- };
185
- event.preventDefault();
186
- }
187
- }),
188
- onKeyDown: (0, import_core.composeEventHandlers)(triggerProps.onKeyDown, (event) => {
189
- const isTypingAhead = searchRef.current !== "";
190
- const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
191
- if (!isModifierKey && event.key.length === 1)
192
- handleTypeaheadSearch(event.key);
193
- if (isTypingAhead && event.key === " ")
194
- return;
195
- if (OPEN_KEYS.includes(event.key)) {
196
- handleOpen();
197
- event.preventDefault();
198
- }
199
- })
200
- }));
118
+ ref: forwardedRef
119
+ }), context.interactions.getReferenceProps()));
201
120
  });
202
121
  SelectTrigger.displayName = TRIGGER_NAME;
203
122
  const VALUE_NAME = "SelectValue";
204
- const SelectValue = React.forwardRef((props, forwardedRef) => {
205
- const _a = props, { __scopeSelect, className, style } = _a, valueProps = __objRest(_a, ["__scopeSelect", "className", "style"]);
206
- return /* @__PURE__ */ React.createElement(import_stacks.XStack, __spreadProps(__spreadValues({}, valueProps), {
207
- pointerEvents: "none"
208
- }));
123
+ const SelectValueFrame = (0, import_core.styled)(import_text.Paragraph, {
124
+ name: VALUE_NAME
209
125
  });
210
- const ICON_NAME = "SelectIcon";
211
- const SelectIcon = React.forwardRef((props, forwardedRef) => {
212
- const _a = props, { __scopeSelect, children } = _a, iconProps = __objRest(_a, ["__scopeSelect", "children"]);
213
- return /* @__PURE__ */ React.createElement(import_stacks.XStack, __spreadProps(__spreadValues({
214
- "aria-hidden": true
215
- }, iconProps), {
216
- ref: forwardedRef
217
- }), children || "\u25BC");
126
+ const SelectValue = SelectValueFrame.extractable(React.forwardRef(({ __scopeSelect, children, placeholder }, forwardedRef) => {
127
+ const context = useSelectContext(VALUE_NAME, __scopeSelect);
128
+ const { onValueNodeHasChildrenChange } = context;
129
+ const hasChildren = children !== void 0;
130
+ const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, context.onValueNodeChange);
131
+ React.useLayoutEffect(() => {
132
+ onValueNodeHasChildrenChange(hasChildren);
133
+ }, [onValueNodeHasChildrenChange, hasChildren]);
134
+ return /* @__PURE__ */ React.createElement(SelectValueFrame, {
135
+ ref: composedRefs,
136
+ pointerEvents: "none"
137
+ }, context.value === void 0 && placeholder !== void 0 ? placeholder : children);
138
+ }));
139
+ SelectValue.displayName = VALUE_NAME;
140
+ const SelectIcon = (0, import_core.styled)(import_stacks.XStack, {
141
+ name: "SelectIcon",
142
+ "aria-hidden": true,
143
+ children: /* @__PURE__ */ React.createElement(import_text.Paragraph, null, "\u25BC")
218
144
  });
219
- SelectIcon.displayName = ICON_NAME;
220
145
  const CONTENT_NAME = "SelectContent";
221
- const SelectContent = React.forwardRef((props, forwardedRef) => {
222
- const context = useSelectContext(CONTENT_NAME, props.__scopeSelect);
223
- return props.children;
146
+ const SelectContent = React.forwardRef(({ children, __scopeSelect }, forwardedRef) => {
147
+ const context = useSelectContext(CONTENT_NAME, __scopeSelect);
148
+ return /* @__PURE__ */ React.createElement(import_react_dom_interactions.FloatingPortal, null, context.open ? /* @__PURE__ */ React.createElement(import_react_dom_interactions.FloatingOverlay, {
149
+ lockScroll: true
150
+ }, children) : /* @__PURE__ */ React.createElement("div", {
151
+ style: { display: "none" }
152
+ }, children));
224
153
  });
225
- const GROUP_NAME = "SelectGroup";
226
- const [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
227
- const SelectGroup = React.forwardRef((props, forwardedRef) => {
228
- const _a = props, { __scopeSelect } = _a, groupProps = __objRest(_a, ["__scopeSelect"]);
229
- const groupId = (0, import_core2.useId)();
230
- return /* @__PURE__ */ React.createElement(SelectGroupContextProvider, {
231
- scope: __scopeSelect,
232
- id: groupId
233
- }, /* @__PURE__ */ React.createElement(Primitive.div, __spreadProps(__spreadValues({
234
- role: "group",
235
- "aria-labelledby": groupId
236
- }, groupProps), {
237
- ref: forwardedRef
238
- })));
154
+ const VIEWPORT_NAME = "SelectViewport";
155
+ const SelectViewportFrame = (0, import_core.styled)(import_stacks.ThemeableStack, {
156
+ name: VIEWPORT_NAME,
157
+ backgroundColor: "$background",
158
+ elevate: true,
159
+ variants: {
160
+ size: {
161
+ "...size": (val, { tokens }) => {
162
+ return {
163
+ borderRadius: tokens.size[val] ?? val
164
+ };
165
+ }
166
+ }
167
+ },
168
+ defaultVariants: {
169
+ size: "$2"
170
+ }
239
171
  });
240
- SelectGroup.displayName = GROUP_NAME;
241
- const LABEL_NAME = "SelectLabel";
242
- const SelectLabel = React.forwardRef((props, forwardedRef) => {
243
- const _a = props, { __scopeSelect } = _a, labelProps = __objRest(_a, ["__scopeSelect"]);
244
- const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
245
- return /* @__PURE__ */ React.createElement(Primitive.div, __spreadProps(__spreadValues({
246
- id: groupContext.id
247
- }, labelProps), {
248
- ref: forwardedRef
249
- }));
172
+ const SelectViewport = React.forwardRef((props, forwardedRef) => {
173
+ const _a = props, { __scopeSelect, children } = _a, viewportProps = __objRest(_a, ["__scopeSelect", "children"]);
174
+ const context = useSelectContext(VIEWPORT_NAME, __scopeSelect);
175
+ const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef);
176
+ const prevScrollTopRef = React.useRef(0);
177
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("style", {
178
+ dangerouslySetInnerHTML: {
179
+ __html: `[data-radix-select-viewport]{scrollbar-width:none;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;}[data-radix-select-viewport]::-webkit-scrollbar{display:none}`
180
+ }
181
+ }), /* @__PURE__ */ React.createElement(import_react_dom_interactions.FloatingFocusManager, {
182
+ context: context.floatingContext,
183
+ preventTabbing: true
184
+ }, /* @__PURE__ */ React.createElement("div", __spreadValues({}, context.interactions.getFloatingProps()), /* @__PURE__ */ React.createElement(SelectViewportFrame, __spreadProps(__spreadValues({
185
+ "data-radix-select-viewport": "",
186
+ role: "presentation"
187
+ }, viewportProps), {
188
+ ref: composedRefs
189
+ }), children))));
250
190
  });
251
- SelectLabel.displayName = LABEL_NAME;
191
+ SelectViewport.displayName = VIEWPORT_NAME;
252
192
  const ITEM_NAME = "SelectItem";
253
193
  const [SelectItemContextProvider, useSelectItemContext] = createSelectContext(ITEM_NAME);
194
+ const SelectItemFrame = (0, import_core.styled)(import_stacks.YStack, {
195
+ name: ITEM_NAME,
196
+ tag: "li",
197
+ role: "option",
198
+ width: "100%",
199
+ hoverStyle: {
200
+ backgroundColor: "$backgroundHover"
201
+ },
202
+ focusStyle: {
203
+ backgroundColor: "$backgroundFocus"
204
+ },
205
+ variants: {
206
+ size: {
207
+ "...size": getSelectItemSize
208
+ }
209
+ },
210
+ defaultVariants: {
211
+ size: "$4"
212
+ }
213
+ });
254
214
  const SelectItem = React.forwardRef((props, forwardedRef) => {
255
- const _a = props, { __scopeSelect, value, disabled = false, textValue: textValueProp } = _a, itemProps = __objRest(_a, ["__scopeSelect", "value", "disabled", "textValue"]);
215
+ const _a = props, {
216
+ __scopeSelect,
217
+ value,
218
+ disabled = false,
219
+ textValue: textValueProp,
220
+ index
221
+ } = _a, itemProps = __objRest(_a, [
222
+ "__scopeSelect",
223
+ "value",
224
+ "disabled",
225
+ "textValue",
226
+ "index"
227
+ ]);
256
228
  const context = useSelectContext(ITEM_NAME, __scopeSelect);
257
- const contentContext = useSelectContentContext(ITEM_NAME, __scopeSelect);
258
229
  const isSelected = context.value === value;
259
230
  const [textValue, setTextValue] = React.useState(textValueProp ?? "");
260
231
  const [isFocused, setIsFocused] = React.useState(false);
261
- const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, isSelected ? contentContext.onSelectedItemChange : void 0);
262
232
  const textId = (0, import_core2.useId)();
263
- const handleSelect = /* @__PURE__ */ __name(() => {
264
- if (!disabled) {
265
- context.onValueChange(value);
266
- context.onOpenChange(false);
233
+ const {
234
+ selectedIndex,
235
+ setSelectedIndex,
236
+ listRef,
237
+ open,
238
+ setOpen,
239
+ onChange,
240
+ activeIndex,
241
+ setActiveIndex,
242
+ dataRef
243
+ } = context;
244
+ const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, (node) => {
245
+ console.log("node", node);
246
+ if (node instanceof HTMLElement) {
247
+ listRef.current[index] = node;
248
+ }
249
+ });
250
+ const timeoutRef = React.useRef();
251
+ const [allowMouseUp, setAllowMouseUp] = React.useState(false);
252
+ function handleSelect() {
253
+ console.log("handling select!");
254
+ setSelectedIndex(index);
255
+ onChange(value);
256
+ setOpen(false);
257
+ }
258
+ __name(handleSelect, "handleSelect");
259
+ React.useEffect(() => {
260
+ clearTimeout(timeoutRef.current);
261
+ if (open) {
262
+ if (selectedIndex !== index) {
263
+ setAllowMouseUp(true);
264
+ } else {
265
+ timeoutRef.current = setTimeout(() => {
266
+ setAllowMouseUp(true);
267
+ }, 300);
268
+ }
269
+ } else {
270
+ setAllowMouseUp(false);
271
+ }
272
+ }, [open, index, setActiveIndex, selectedIndex]);
273
+ function handleKeyDown(event) {
274
+ console.log("item key down");
275
+ if (event.key === "Enter" || event.key === " " && !dataRef.current.typing) {
276
+ event.preventDefault();
277
+ handleSelect();
267
278
  }
268
- }, "handleSelect");
279
+ }
280
+ __name(handleKeyDown, "handleKeyDown");
281
+ const selectItemProps = context.interactions.getItemProps({
282
+ onClick: allowMouseUp ? handleSelect : void 0,
283
+ onMouseUp: allowMouseUp ? handleSelect : void 0,
284
+ onKeyDown: handleKeyDown
285
+ });
269
286
  return /* @__PURE__ */ React.createElement(SelectItemContextProvider, {
270
287
  scope: __scopeSelect,
271
288
  value,
272
- textId,
289
+ textId: textId || "",
273
290
  isSelected,
274
291
  onItemTextChange: React.useCallback((node) => {
275
- setTextValue((prevTextValue) => prevTextValue || ((node == null ? void 0 : node.textContent) ?? "").trim());
276
292
  }, [])
277
- }, /* @__PURE__ */ React.createElement(Collection.ItemSlot, {
278
- scope: __scopeSelect,
279
- value,
280
- disabled,
281
- textValue
282
- }, /* @__PURE__ */ React.createElement(Primitive.div, __spreadProps(__spreadValues({
283
- role: "option",
293
+ }, /* @__PURE__ */ React.createElement(SelectItemFrame, __spreadValues(__spreadValues({
294
+ ref: composedRefs,
284
295
  "aria-labelledby": textId,
285
296
  "aria-selected": isSelected && isFocused,
286
297
  "data-state": isSelected ? "active" : "inactive",
287
298
  "aria-disabled": disabled || void 0,
288
299
  "data-disabled": disabled ? "" : void 0,
289
300
  tabIndex: disabled ? void 0 : -1
290
- }, itemProps), {
291
- ref: composedRefs,
292
- onFocus: (0, import_core.composeEventHandlers)(itemProps.onFocus, () => setIsFocused(true)),
293
- onBlur: (0, import_core.composeEventHandlers)(itemProps.onBlur, () => setIsFocused(false)),
294
- onPointerUp: (0, import_core.composeEventHandlers)(itemProps.onPointerUp, handleSelect),
295
- onPointerMove: (0, import_core.composeEventHandlers)(itemProps.onPointerMove, (event) => {
296
- if (disabled) {
297
- contentContext.onItemLeave();
298
- } else {
299
- event.currentTarget.focus({ preventScroll: true });
300
- }
301
- }),
302
- onPointerLeave: (0, import_core.composeEventHandlers)(itemProps.onPointerLeave, (event) => {
303
- if (event.currentTarget === document.activeElement) {
304
- contentContext.onItemLeave();
305
- }
306
- }),
307
- onKeyDown: (0, import_core.composeEventHandlers)(itemProps.onKeyDown, (event) => {
308
- const isTypingAhead = contentContext.searchRef.current !== "";
309
- if (isTypingAhead && event.key === " ")
310
- return;
311
- if (SELECTION_KEYS.includes(event.key))
312
- handleSelect();
313
- if (event.key === " ")
314
- event.preventDefault();
315
- })
316
- }))));
301
+ }, itemProps), selectItemProps)));
317
302
  });
318
303
  SelectItem.displayName = ITEM_NAME;
319
304
  const ITEM_TEXT_NAME = "SelectItemText";
305
+ const SelectItemTextFrame = (0, import_core.styled)(import_text.Paragraph, {
306
+ name: ITEM_TEXT_NAME,
307
+ cursor: "default"
308
+ });
320
309
  const SelectItemText = React.forwardRef((props, forwardedRef) => {
321
- var _b;
322
310
  const _a = props, { __scopeSelect, className, style } = _a, itemTextProps = __objRest(_a, ["__scopeSelect", "className", "style"]);
323
311
  const context = useSelectContext(ITEM_TEXT_NAME, __scopeSelect);
324
- const contentContext = useSelectContentContext(ITEM_TEXT_NAME, __scopeSelect);
325
312
  const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
326
313
  const ref = React.useRef(null);
327
- const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, ref, itemContext.onItemTextChange, itemContext.isSelected ? contentContext.onSelectedItemTextChange : void 0);
328
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Primitive.span, __spreadProps(__spreadValues({
314
+ const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, ref, itemContext.onItemTextChange);
315
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(SelectItemTextFrame, __spreadProps(__spreadValues({
329
316
  id: itemContext.textId
330
317
  }, itemTextProps), {
331
318
  ref: composedRefs
332
- })), itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren ? ReactDOM.createPortal(itemTextProps.children, context.valueNode) : null, context.bubbleSelect ? ReactDOM.createPortal(/* @__PURE__ */ React.createElement("option", {
333
- value: itemContext.value
334
- }, (_b = ref.current) == null ? void 0 : _b.textContent), context.bubbleSelect) : null);
319
+ })), itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren ? ReactDOM.createPortal(itemTextProps.children, context.valueNode) : null);
335
320
  });
336
321
  SelectItemText.displayName = ITEM_TEXT_NAME;
337
322
  const ITEM_INDICATOR_NAME = "SelectItemIndicator";
323
+ const SelectItemIndicatorFrame = (0, import_core.styled)(import_stacks.XStack, {
324
+ name: ITEM_TEXT_NAME
325
+ });
338
326
  const SelectItemIndicator = React.forwardRef((props, forwardedRef) => {
339
327
  const _a = props, { __scopeSelect } = _a, itemIndicatorProps = __objRest(_a, ["__scopeSelect"]);
340
328
  const itemContext = useSelectItemContext(ITEM_INDICATOR_NAME, __scopeSelect);
341
- return itemContext.isSelected ? /* @__PURE__ */ React.createElement(Primitive.span, __spreadProps(__spreadValues({
329
+ return itemContext.isSelected ? /* @__PURE__ */ React.createElement(SelectItemIndicatorFrame, __spreadProps(__spreadValues({
342
330
  "aria-hidden": true
343
331
  }, itemIndicatorProps), {
344
332
  ref: forwardedRef
345
333
  })) : null;
346
334
  });
347
335
  SelectItemIndicator.displayName = ITEM_INDICATOR_NAME;
348
- const SCROLL_UP_BUTTON_NAME = "SelectScrollUpButton";
349
- const SelectScrollUpButton = React.forwardRef((props, forwardedRef) => {
350
- const contentContext = useSelectContentContext(SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
351
- const [canScrollUp, setCanScrollUp] = React.useState(false);
352
- const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, contentContext.onScrollButtonChange);
353
- return canScrollUp ? /* @__PURE__ */ React.createElement(SelectScrollButtonImpl, __spreadProps(__spreadValues({}, props), {
354
- ref: composedRefs,
355
- onAutoScroll: () => {
356
- const { viewport, selectedItem } = contentContext;
357
- if (viewport && selectedItem) {
358
- viewport.scrollTop = viewport.scrollTop - selectedItem.offsetHeight;
336
+ const GROUP_NAME = "SelectGroup";
337
+ const [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
338
+ const SelectGroupFrame = (0, import_core.styled)(import_stacks.YStack, {
339
+ name: GROUP_NAME,
340
+ width: "100%"
341
+ });
342
+ const SelectGroup = React.forwardRef((props, forwardedRef) => {
343
+ const _a = props, { __scopeSelect } = _a, groupProps = __objRest(_a, ["__scopeSelect"]);
344
+ const groupId = (0, import_core2.useId)();
345
+ return /* @__PURE__ */ React.createElement(SelectGroupContextProvider, {
346
+ scope: __scopeSelect,
347
+ id: groupId || ""
348
+ }, /* @__PURE__ */ React.createElement(SelectGroupFrame, __spreadProps(__spreadValues({
349
+ role: "group",
350
+ "aria-labelledby": groupId
351
+ }, groupProps), {
352
+ ref: forwardedRef
353
+ })));
354
+ });
355
+ SelectGroup.displayName = GROUP_NAME;
356
+ const LABEL_NAME = "SelectLabel";
357
+ const SelectLabelFrame = (0, import_core.styled)(SelectItemTextFrame, {
358
+ name: LABEL_NAME,
359
+ variants: {
360
+ size: {
361
+ "...size": (val, extras) => {
362
+ const size2 = getSelectItemSize(val, extras);
363
+ return __spreadProps(__spreadValues({}, size2), {
364
+ paddingTop: size2.paddingVertical * 4
365
+ });
359
366
  }
360
367
  }
361
- })) : null;
368
+ },
369
+ defaultVariants: {
370
+ size: "$4"
371
+ }
372
+ });
373
+ const SelectLabel = React.forwardRef((props, forwardedRef) => {
374
+ const _a = props, { __scopeSelect } = _a, labelProps = __objRest(_a, ["__scopeSelect"]);
375
+ const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
376
+ return /* @__PURE__ */ React.createElement(SelectLabelFrame, __spreadProps(__spreadValues({
377
+ id: groupContext.id
378
+ }, labelProps), {
379
+ ref: forwardedRef
380
+ }));
381
+ });
382
+ SelectLabel.displayName = LABEL_NAME;
383
+ const SCROLL_UP_BUTTON_NAME = "SelectScrollUpButton";
384
+ const SelectScrollUpButton = React.forwardRef((props, forwardedRef) => {
385
+ return /* @__PURE__ */ React.createElement(SelectScrollButtonImpl, __spreadProps(__spreadValues({
386
+ componentName: SCROLL_UP_BUTTON_NAME
387
+ }, props), {
388
+ dir: "up",
389
+ ref: forwardedRef
390
+ }));
362
391
  });
363
392
  SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME;
364
393
  const SCROLL_DOWN_BUTTON_NAME = "SelectScrollDownButton";
365
394
  const SelectScrollDownButton = React.forwardRef((props, forwardedRef) => {
366
- const contentContext = useSelectContentContext(SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
367
- const [canScrollDown, setCanScrollDown] = React.useState(false);
368
- const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, contentContext.onScrollButtonChange);
369
- return canScrollDown ? /* @__PURE__ */ React.createElement(SelectScrollButtonImpl, __spreadProps(__spreadValues({}, props), {
370
- ref: composedRefs,
371
- onAutoScroll: () => {
372
- const { viewport, selectedItem } = contentContext;
373
- if (viewport && selectedItem) {
374
- viewport.scrollTop = viewport.scrollTop + selectedItem.offsetHeight;
375
- }
376
- }
377
- })) : null;
395
+ return /* @__PURE__ */ React.createElement(SelectScrollButtonImpl, __spreadProps(__spreadValues({
396
+ componentName: SCROLL_DOWN_BUTTON_NAME
397
+ }, props), {
398
+ dir: "down",
399
+ ref: forwardedRef
400
+ }));
378
401
  });
379
402
  SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
380
403
  const SelectScrollButtonImpl = React.forwardRef((props, forwardedRef) => {
381
- const _a = props, { __scopeSelect, onAutoScroll } = _a, scrollIndicatorProps = __objRest(_a, ["__scopeSelect", "onAutoScroll"]);
382
- const contentContext = useSelectContentContext("SelectScrollButton", __scopeSelect);
383
- const autoScrollTimerRef = React.useRef(null);
404
+ var _c;
405
+ const _a = props, { __scopeSelect, dir, componentName } = _a, scrollIndicatorProps = __objRest(_a, ["__scopeSelect", "dir", "componentName"]);
406
+ const _b = useSelectContext(componentName, __scopeSelect), { floatingRef, increaseHeight, forceUpdate } = _b, context = __objRest(_b, ["floatingRef", "increaseHeight", "forceUpdate"]);
384
407
  const intervalRef = React.useRef();
385
408
  const loopingRef = React.useRef(false);
409
+ const isVisible = context[dir === "down" ? "canScrollDown" : "canScrollUp"];
386
410
  const { x, y, reference, floating, strategy, update, refs } = (0, import_react_dom_interactions.useFloating)({
387
411
  strategy: "fixed",
388
412
  placement: dir === "up" ? "top" : "bottom",
389
- middleware: [(0, import_react_dom_interactions.offset)(({ floating: floating2 }) => -floating2.height)]
413
+ middleware: [(0, import_react_dom_interactions.offset)(({ rects }) => -rects.floating.height)]
390
414
  });
391
- return /* @__PURE__ */ React.createElement(Primitive.div, __spreadProps(__spreadValues({
415
+ const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, floating);
416
+ React.useLayoutEffect(() => {
417
+ reference(floatingRef.current);
418
+ }, [reference, floatingRef.current]);
419
+ React.useEffect(() => {
420
+ if (!refs.reference.current || !refs.floating.current || !isVisible) {
421
+ return;
422
+ }
423
+ const cleanup = (0, import_react_dom_interactions.autoUpdate)(refs.reference.current, refs.floating.current, update, {
424
+ animationFrame: true
425
+ });
426
+ return () => {
427
+ clearInterval(intervalRef.current);
428
+ loopingRef.current = false;
429
+ cleanup();
430
+ };
431
+ }, [isVisible, update, refs.floating, refs.reference]);
432
+ if (!isVisible) {
433
+ return null;
434
+ }
435
+ const handleScrollArrowChange = /* @__PURE__ */ __name(() => {
436
+ const floating2 = floatingRef.current;
437
+ const isUp = dir === "up";
438
+ if (floating2) {
439
+ const value = isUp ? -SCROLL_ARROW_VELOCITY : SCROLL_ARROW_VELOCITY;
440
+ const multi = isUp && floating2.scrollTop <= SCROLL_ARROW_THRESHOLD * 2 || !isUp && floating2.scrollTop >= floating2.scrollHeight - floating2.clientHeight - SCROLL_ARROW_THRESHOLD * 2 ? 2 : 1;
441
+ floating2.scrollTop += multi * (isUp ? -SCROLL_ARROW_VELOCITY : SCROLL_ARROW_VELOCITY);
442
+ increaseHeight(floating2, multi === 2 ? value * 2 : value);
443
+ forceUpdate();
444
+ }
445
+ }, "handleScrollArrowChange");
446
+ return /* @__PURE__ */ React.createElement(import_stacks.YStack, __spreadProps(__spreadValues({
447
+ ref: composedRefs,
448
+ componentName,
392
449
  "aria-hidden": true
393
450
  }, scrollIndicatorProps), {
394
- ref: forwardedRef,
395
- style: __spreadValues({ flexShrink: 0 }, scrollIndicatorProps.style),
396
- onPointerMove: (0, import_core.composeEventHandlers)(scrollIndicatorProps.onPointerMove, () => {
397
- contentContext.onItemLeave();
398
- if (autoScrollTimerRef.current === null) {
399
- autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
451
+ position: strategy,
452
+ left: x || 0,
453
+ top: y || 0,
454
+ width: `calc(${(((_c = floatingRef.current) == null ? void 0 : _c.offsetWidth) ?? 0) - 2}px)`,
455
+ background: `linear-gradient(to ${dir === "up" ? "bottom" : "top"}, #29282b 50%, rgba(53, 54, 55, 0.01))`,
456
+ onPointerMove: () => {
457
+ if (!loopingRef.current) {
458
+ intervalRef.current = setInterval(handleScrollArrowChange, 1e3 / 60);
459
+ loopingRef.current = true;
400
460
  }
401
- }),
402
- onPointerLeave: (0, import_core.composeEventHandlers)(scrollIndicatorProps.onPointerLeave, () => {
403
- clearAutoScrollTimer();
404
- })
461
+ },
462
+ onPointerLeave: () => {
463
+ loopingRef.current = false;
464
+ clearInterval(intervalRef.current);
465
+ }
405
466
  }));
406
467
  });
407
- const SEPARATOR_NAME = "SelectSeparator";
408
- const SelectSeparator = import_separator.Separator;
409
- SelectSeparator.displayName = SEPARATOR_NAME;
410
- const BubbleSelect = React.forwardRef((props, forwardedRef) => {
411
- const _a = props, { value } = _a, selectProps = __objRest(_a, ["value"]);
412
- const ref = React.useRef(null);
413
- const composedRefs = (0, import_compose_refs.useComposedRefs)(forwardedRef, ref);
414
- const prevValue = (0, import_react_use_previous.usePrevious)(value);
468
+ const SelectSeparator = (0, import_core.styled)(import_separator.Separator, {
469
+ name: "SelectSeparator"
470
+ });
471
+ const Select = (0, import_core.withStaticProperties)((props) => {
472
+ const {
473
+ __scopeSelect,
474
+ children,
475
+ open: openProp,
476
+ defaultOpen,
477
+ onOpenChange,
478
+ value: valueProp,
479
+ defaultValue,
480
+ onValueChange,
481
+ dir,
482
+ name,
483
+ autoComplete
484
+ } = props;
485
+ const [open, setOpen] = (0, import_use_controllable_state.useControllableState)({
486
+ prop: openProp,
487
+ defaultProp: defaultOpen || false,
488
+ onChange: onOpenChange
489
+ });
490
+ const [value, setValue] = (0, import_use_controllable_state.useControllableState)({
491
+ prop: valueProp,
492
+ defaultProp: defaultValue || "",
493
+ onChange: onValueChange
494
+ });
495
+ const [activeIndex, setActiveIndex] = React.useState(null);
496
+ const selectedIndexRef = React.useRef(null);
497
+ const activeIndexRef = React.useRef(null);
498
+ const prevActiveIndex = (0, import_react_use_previous.usePrevious)(activeIndex);
499
+ const [showArrows, setShowArrows] = React.useState(false);
500
+ const [scrollTop, setScrollTop] = React.useState(0);
501
+ const listItemsRef = React.useRef([]);
502
+ const listContentRef = React.useRef([
503
+ "Select...",
504
+ ...React.Children.map(children, (child) => React.Children.map(React.isValidElement(child) && child.props.children, (child2) => child2.props.value)) ?? []
505
+ ]);
506
+ const [selectedIndex, setSelectedIndex] = React.useState(Math.max(0, listContentRef.current.indexOf(value)));
507
+ const [controlledScrolling, setControlledScrolling] = React.useState(false);
508
+ const [middlewareType, setMiddlewareType] = React.useState("align");
509
+ (0, import_core.useIsomorphicLayoutEffect)(() => {
510
+ selectedIndexRef.current = selectedIndex;
511
+ activeIndexRef.current = activeIndex;
512
+ });
415
513
  React.useEffect(() => {
416
- const select = ref.current;
417
- const selectProto = window.HTMLSelectElement.prototype;
418
- const descriptor = Object.getOwnPropertyDescriptor(selectProto, "value");
419
- const setValue = descriptor.set;
420
- if (prevValue !== value && setValue) {
421
- const event = new Event("change", { bubbles: true });
422
- setValue.call(select, value);
423
- select.dispatchEvent(event);
514
+ const frame = requestAnimationFrame(() => {
515
+ setShowArrows(open);
516
+ if (!open) {
517
+ setScrollTop(0);
518
+ setMiddlewareType("align");
519
+ setActiveIndex(null);
520
+ setControlledScrolling(false);
521
+ }
522
+ });
523
+ return () => {
524
+ cancelAnimationFrame(frame);
525
+ };
526
+ }, [open]);
527
+ function getFloatingPadding(floating2) {
528
+ var _a;
529
+ if (!floating2) {
530
+ return 0;
424
531
  }
425
- }, [prevValue, value]);
426
- return null;
427
- return /* @__PURE__ */ React.createElement(VisuallyHidden, {
428
- asChild: true
429
- }, /* @__PURE__ */ React.createElement("select", __spreadProps(__spreadValues({}, selectProps), {
430
- ref: composedRefs,
431
- defaultValue: value
432
- })));
532
+ return Number((_a = getComputedStyle(floating2).paddingLeft) == null ? void 0 : _a.replace("px", ""));
533
+ }
534
+ __name(getFloatingPadding, "getFloatingPadding");
535
+ const { x, y, reference, floating, strategy, context, refs, middlewareData, update } = (0, import_react_dom_interactions.useFloating)({
536
+ open,
537
+ onOpenChange: setOpen,
538
+ placement: "bottom",
539
+ middleware: middlewareType === "align" ? [
540
+ (0, import_react_dom_interactions.offset)(({ rects }) => {
541
+ const index = activeIndexRef.current ?? selectedIndexRef.current;
542
+ if (index == null) {
543
+ return 0;
544
+ }
545
+ const item = listItemsRef.current[index];
546
+ if (item == null) {
547
+ return 0;
548
+ }
549
+ const offsetTop = item.offsetTop;
550
+ const itemHeight = item.offsetHeight;
551
+ const height = rects.reference.height;
552
+ return -offsetTop - height - (itemHeight - height) / 2;
553
+ }),
554
+ {
555
+ name: "size",
556
+ async fn(args) {
557
+ var _a;
558
+ const {
559
+ elements: { floating: floating2 },
560
+ rects: { reference: reference2 },
561
+ middlewareData: middlewareData2
562
+ } = args;
563
+ const overflow = await (0, import_react_dom_interactions.detectOverflow)(args, {
564
+ padding: WINDOW_PADDING
565
+ });
566
+ const top = Math.max(0, overflow.top);
567
+ const bottom = Math.max(0, overflow.bottom);
568
+ const nextY = args.y + top;
569
+ if ((_a = middlewareData2.size) == null ? void 0 : _a.skip) {
570
+ return {
571
+ y: nextY,
572
+ data: {
573
+ y: middlewareData2.size.y
574
+ }
575
+ };
576
+ }
577
+ Object.assign(floating2.style, {
578
+ maxHeight: `${floating2.scrollHeight - Math.abs(top + bottom)}px`,
579
+ minWidth: `${reference2.width + getFloatingPadding(floating2) * 2}px`
580
+ });
581
+ return {
582
+ y: nextY,
583
+ data: {
584
+ y: top,
585
+ skip: true
586
+ },
587
+ reset: {
588
+ rects: true
589
+ }
590
+ };
591
+ }
592
+ }
593
+ ] : [
594
+ (0, import_react_dom_interactions.offset)(5),
595
+ (0, import_react_dom_interactions.flip)(),
596
+ (0, import_react_dom_interactions.size)({
597
+ apply({ rects, availableHeight, elements }) {
598
+ Object.assign(elements.floating.style, {
599
+ width: `${rects.reference.width}px`,
600
+ maxHeight: `${availableHeight}px`
601
+ });
602
+ },
603
+ padding: WINDOW_PADDING
604
+ })
605
+ ]
606
+ });
607
+ const floatingRef = refs.floating;
608
+ const forceUpdate = React.useReducer(() => ({}), {})[1];
609
+ const showUpArrow = showArrows && scrollTop > SCROLL_ARROW_THRESHOLD;
610
+ const showDownArrow = showArrows && floatingRef.current && scrollTop < floatingRef.current.scrollHeight - floatingRef.current.clientHeight - SCROLL_ARROW_THRESHOLD;
611
+ console.log("Select", {
612
+ activeIndex,
613
+ selectedIndex
614
+ });
615
+ const interactions = (0, import_react_dom_interactions.useInteractions)([
616
+ (0, import_react_dom_interactions.useClick)(context, { pointerDown: true }),
617
+ (0, import_react_dom_interactions.useRole)(context, { role: "listbox" }),
618
+ (0, import_react_dom_interactions.useDismiss)(context),
619
+ (0, import_react_dom_interactions.useListNavigation)(context, {
620
+ listRef: listItemsRef,
621
+ activeIndex,
622
+ selectedIndex,
623
+ onNavigate: setActiveIndex
624
+ }),
625
+ (0, import_react_dom_interactions.useTypeahead)(context, {
626
+ listRef: listContentRef,
627
+ onMatch: open ? setActiveIndex : setSelectedIndex,
628
+ selectedIndex,
629
+ activeIndex
630
+ })
631
+ ]);
632
+ const increaseHeight = React.useCallback((floating2, amount = 0) => {
633
+ if (middlewareType === "fallback") {
634
+ return;
635
+ }
636
+ const currentMaxHeight = Number(floating2.style.maxHeight.replace("px", ""));
637
+ const currentTop = Number(floating2.style.top.replace("px", ""));
638
+ const rect = floating2.getBoundingClientRect();
639
+ const rectTop = rect.top;
640
+ const rectBottom = rect.bottom;
641
+ const visualMaxHeight = visualViewport.height - WINDOW_PADDING * 2;
642
+ if (amount < 0 && selectedIndexRef.current != null && Math.round(rectBottom) < Math.round(visualViewport.height + getVisualOffsetTop() - WINDOW_PADDING)) {
643
+ floating2.style.maxHeight = `${Math.min(visualMaxHeight, currentMaxHeight - amount)}px`;
644
+ }
645
+ if (amount > 0 && Math.round(rectTop) > Math.round(WINDOW_PADDING - getVisualOffsetTop()) && floating2.scrollHeight > floating2.offsetHeight) {
646
+ const nextTop = Math.max(WINDOW_PADDING + getVisualOffsetTop(), currentTop - amount);
647
+ const nextMaxHeight = Math.min(visualMaxHeight, currentMaxHeight + amount);
648
+ Object.assign(floating2.style, {
649
+ maxHeight: `${nextMaxHeight}px`,
650
+ top: `${nextTop}px`
651
+ });
652
+ if (nextTop - WINDOW_PADDING > getVisualOffsetTop()) {
653
+ floating2.scrollTop -= nextMaxHeight - currentMaxHeight + getFloatingPadding(floating2);
654
+ }
655
+ return currentTop - nextTop;
656
+ }
657
+ }, [middlewareType]);
658
+ const touchPageYRef = React.useRef(null);
659
+ const handleWheel = React.useCallback((event) => {
660
+ var _a;
661
+ const pinching = event.ctrlKey;
662
+ const currentTarget = event.currentTarget;
663
+ function isWheelEvent(event2) {
664
+ return typeof event2.deltaY === "number";
665
+ }
666
+ __name(isWheelEvent, "isWheelEvent");
667
+ function isTouchEvent(event2) {
668
+ return event2.touches != null;
669
+ }
670
+ __name(isTouchEvent, "isTouchEvent");
671
+ if (Math.abs(((currentTarget == null ? void 0 : currentTarget.offsetHeight) ?? 0) - (visualViewport.height - WINDOW_PADDING * 2)) > 1 && !pinching) {
672
+ event.preventDefault();
673
+ } else if (isWheelEvent(event) && isFirefox) {
674
+ currentTarget.scrollTop += event.deltaY;
675
+ }
676
+ if (!pinching) {
677
+ let delta = 5;
678
+ if (isTouchEvent(event)) {
679
+ const currentPageY = touchPageYRef.current;
680
+ const pageY = (_a = event.touches[0]) == null ? void 0 : _a.pageY;
681
+ if (pageY != null) {
682
+ touchPageYRef.current = pageY;
683
+ if (currentPageY != null) {
684
+ delta = currentPageY - pageY;
685
+ }
686
+ }
687
+ }
688
+ increaseHeight(currentTarget, isWheelEvent(event) ? event.deltaY : delta);
689
+ setScrollTop(currentTarget.scrollTop);
690
+ forceUpdate();
691
+ }
692
+ }, [increaseHeight, forceUpdate]);
693
+ React.useEffect(() => {
694
+ function onTouchEnd() {
695
+ touchPageYRef.current = null;
696
+ }
697
+ __name(onTouchEnd, "onTouchEnd");
698
+ const floating2 = floatingRef.current;
699
+ if (open && floating2 && middlewareType === "align") {
700
+ floating2.addEventListener("wheel", handleWheel);
701
+ floating2.addEventListener("touchmove", handleWheel);
702
+ floating2.addEventListener("touchend", onTouchEnd, { passive: true });
703
+ return () => {
704
+ floating2.removeEventListener("wheel", handleWheel);
705
+ floating2.removeEventListener("touchmove", handleWheel);
706
+ floating2.removeEventListener("touchend", onTouchEnd);
707
+ };
708
+ }
709
+ }, [open, floatingRef, handleWheel, middlewareType]);
710
+ React.useEffect(() => {
711
+ window.addEventListener("resize", update);
712
+ return () => {
713
+ window.removeEventListener("resize", update);
714
+ };
715
+ }, [update]);
716
+ React.useLayoutEffect(() => {
717
+ var _a;
718
+ const floating2 = floatingRef.current;
719
+ if (open && controlledScrolling && floating2) {
720
+ const item = activeIndex != null ? listItemsRef.current[activeIndex] : selectedIndex != null ? listItemsRef.current[selectedIndex] : null;
721
+ if (item && prevActiveIndex != null) {
722
+ const itemHeight = ((_a = listItemsRef.current[prevActiveIndex]) == null ? void 0 : _a.offsetHeight) ?? 0;
723
+ const floatingHeight = floating2.offsetHeight;
724
+ const top = item.offsetTop;
725
+ const bottom = top + itemHeight;
726
+ if (top < floating2.scrollTop + 20) {
727
+ const diff = floating2.scrollTop - top + 20;
728
+ floating2.scrollTop -= diff;
729
+ if (activeIndex != selectedIndex && activeIndex != null) {
730
+ increaseHeight(floating2, -diff);
731
+ }
732
+ } else if (bottom > floatingHeight + floating2.scrollTop - 20) {
733
+ const diff = bottom - floatingHeight - floating2.scrollTop + 20;
734
+ floating2.scrollTop += diff;
735
+ if (activeIndex != selectedIndex && activeIndex != null) {
736
+ floating2.scrollTop -= increaseHeight(floating2, diff) ?? 0;
737
+ }
738
+ }
739
+ }
740
+ }
741
+ }, [
742
+ open,
743
+ controlledScrolling,
744
+ prevActiveIndex,
745
+ activeIndex,
746
+ selectedIndex,
747
+ floatingRef,
748
+ increaseHeight
749
+ ]);
750
+ React.useLayoutEffect(() => {
751
+ var _a;
752
+ const floating2 = refs.floating.current;
753
+ const reference2 = refs.reference.current;
754
+ if (open && floating2 && reference2 && floating2.offsetHeight < floating2.scrollHeight) {
755
+ const referenceRect = reference2.getBoundingClientRect();
756
+ if (middlewareType === "fallback") {
757
+ const item = listItemsRef.current[selectedIndex];
758
+ if (item) {
759
+ floating2.scrollTop = item.offsetTop - floating2.clientHeight + referenceRect.height;
760
+ }
761
+ return;
762
+ }
763
+ floating2.scrollTop = (_a = middlewareData.size) == null ? void 0 : _a.y;
764
+ const closeToBottom = visualViewport.height + getVisualOffsetTop() - referenceRect.bottom < FALLBACK_THRESHOLD;
765
+ const closeToTop = referenceRect.top < FALLBACK_THRESHOLD;
766
+ if (floating2.offsetHeight < MIN_HEIGHT || closeToTop || closeToBottom) {
767
+ setMiddlewareType("fallback");
768
+ }
769
+ }
770
+ }, [
771
+ open,
772
+ increaseHeight,
773
+ selectedIndex,
774
+ middlewareType,
775
+ refs.floating,
776
+ refs.reference,
777
+ middlewareData
778
+ ]);
779
+ React.useLayoutEffect(() => {
780
+ console.log("focusin", selectedIndex, listItemsRef.current[selectedIndex], listItemsRef.current);
781
+ if (open && selectedIndex != null) {
782
+ requestAnimationFrame(() => {
783
+ var _a;
784
+ (_a = listItemsRef.current[selectedIndex]) == null ? void 0 : _a.focus({ preventScroll: true });
785
+ });
786
+ }
787
+ }, [listItemsRef, selectedIndex, open]);
788
+ React.useEffect(() => {
789
+ const frame = requestAnimationFrame(() => {
790
+ setShowArrows(open);
791
+ if (!open) {
792
+ setScrollTop(0);
793
+ setMiddlewareType("align");
794
+ setActiveIndex(null);
795
+ setControlledScrolling(false);
796
+ }
797
+ });
798
+ return () => cancelAnimationFrame(frame);
799
+ }, [open]);
800
+ const [valueNode, setValueNode] = React.useState(null);
801
+ const [valueNodeHasChildren, setValueNodeHasChildren] = React.useState(false);
802
+ return /* @__PURE__ */ React.createElement(SelectProvider, {
803
+ scope: __scopeSelect,
804
+ increaseHeight,
805
+ forceUpdate,
806
+ floatingRef,
807
+ valueNode,
808
+ onValueNodeChange: setValueNode,
809
+ valueNodeHasChildren,
810
+ onValueNodeHasChildrenChange: setValueNodeHasChildren,
811
+ interactions: __spreadProps(__spreadValues({}, interactions), {
812
+ getReferenceProps() {
813
+ return interactions.getReferenceProps({
814
+ ref: reference,
815
+ className: "SelectTrigger",
816
+ onKeyDown(event) {
817
+ if (event.key === "Enter" || event.key === " " && !context.dataRef.current.typing) {
818
+ event.preventDefault();
819
+ setOpen(true);
820
+ }
821
+ }
822
+ });
823
+ },
824
+ getFloatingProps() {
825
+ return interactions.getFloatingProps({
826
+ ref: floating,
827
+ className: "Select",
828
+ style: {
829
+ position: strategy,
830
+ top: y ?? "",
831
+ left: x ?? ""
832
+ },
833
+ onPointerEnter() {
834
+ setControlledScrolling(false);
835
+ },
836
+ onPointerMove() {
837
+ setControlledScrolling(false);
838
+ },
839
+ onKeyDown() {
840
+ setControlledScrolling(true);
841
+ },
842
+ onScroll(event) {
843
+ setScrollTop(event.currentTarget.scrollTop);
844
+ }
845
+ });
846
+ }
847
+ }),
848
+ floatingContext: context,
849
+ activeIndex,
850
+ canScrollDown: !!showDownArrow,
851
+ canScrollUp: !!showUpArrow,
852
+ controlledScrolling: true,
853
+ dataRef: context.dataRef,
854
+ listRef: listItemsRef,
855
+ onChange: setValue,
856
+ selectedIndex: 0,
857
+ setActiveIndex,
858
+ setOpen,
859
+ setSelectedIndex,
860
+ value,
861
+ open
862
+ }, children);
863
+ }, {
864
+ Content: SelectContent,
865
+ Group: SelectGroup,
866
+ Icon: SelectIcon,
867
+ Item: SelectItem,
868
+ ItemIndicator: SelectItemIndicator,
869
+ ItemText: SelectItemText,
870
+ Label: SelectLabel,
871
+ ScrollDownButton: SelectScrollDownButton,
872
+ ScrollUpButton: SelectScrollUpButton,
873
+ Trigger: SelectTrigger,
874
+ Value: SelectValue,
875
+ Viewport: SelectViewport
433
876
  });
877
+ Select.displayName = SELECT_NAME;
434
878
  // Annotate the CommonJS export names for ESM import in node:
435
879
  0 && (module.exports = {
436
880
  Select,
437
- SelectContent,
438
- SelectGroup,
439
881
  SelectIcon,
440
- SelectItem,
441
- SelectItemIndicator,
442
- SelectItemText,
443
- SelectLabel,
444
- SelectScrollDownButton,
445
- SelectScrollUpButton,
446
882
  SelectSeparator,
447
883
  SelectTrigger,
448
- SelectValue,
884
+ SelectViewportFrame,
449
885
  createSelectScope
450
886
  });
451
887
  //# sourceMappingURL=Select.js.map