@tamagui/select 1.0.1-beta.18 → 1.0.1-beta.180

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.
Files changed (114) hide show
  1. package/dist/cjs/BubbleSelect.js +43 -0
  2. package/dist/cjs/BubbleSelect.js.map +7 -0
  3. package/dist/cjs/Select.js +413 -389
  4. package/dist/cjs/Select.js.map +3 -3
  5. package/dist/cjs/SelectContent.js +72 -0
  6. package/dist/cjs/SelectContent.js.map +7 -0
  7. package/dist/cjs/SelectContent.native.js +31 -0
  8. package/dist/cjs/SelectContent.native.js.map +7 -0
  9. package/dist/cjs/SelectImpl.js +286 -0
  10. package/dist/cjs/SelectImpl.js.map +7 -0
  11. package/dist/cjs/SelectScrollButton.js +157 -0
  12. package/dist/cjs/SelectScrollButton.js.map +7 -0
  13. package/dist/cjs/SelectScrollButton.native.js +32 -0
  14. package/dist/cjs/SelectScrollButton.native.js.map +7 -0
  15. package/dist/cjs/SelectViewport.js +126 -0
  16. package/dist/cjs/SelectViewport.js.map +7 -0
  17. package/dist/cjs/SelectViewport.native.js +41 -0
  18. package/dist/cjs/SelectViewport.native.js.map +7 -0
  19. package/dist/cjs/constants.js +47 -0
  20. package/dist/cjs/constants.js.map +7 -0
  21. package/dist/cjs/context.js +49 -0
  22. package/dist/cjs/context.js.map +7 -0
  23. package/dist/cjs/index.js +2 -0
  24. package/dist/cjs/index.js.map +2 -2
  25. package/dist/cjs/types.js +17 -0
  26. package/dist/cjs/types.js.map +7 -0
  27. package/dist/cjs/useSelectBreakpointActive.js +39 -0
  28. package/dist/cjs/useSelectBreakpointActive.js.map +7 -0
  29. package/dist/esm/BubbleSelect.js +24 -0
  30. package/dist/esm/BubbleSelect.js.map +7 -0
  31. package/dist/esm/Select.js +404 -357
  32. package/dist/esm/Select.js.map +3 -3
  33. package/dist/esm/SelectContent.js +48 -0
  34. package/dist/esm/SelectContent.js.map +7 -0
  35. package/dist/esm/SelectContent.native.js +7 -0
  36. package/dist/esm/SelectContent.native.js.map +7 -0
  37. package/dist/esm/SelectImpl.js +271 -0
  38. package/dist/esm/SelectImpl.js.map +7 -0
  39. package/dist/esm/SelectScrollButton.js +126 -0
  40. package/dist/esm/SelectScrollButton.js.map +7 -0
  41. package/dist/esm/SelectScrollButton.native.js +7 -0
  42. package/dist/esm/SelectScrollButton.native.js.map +7 -0
  43. package/dist/esm/SelectViewport.js +95 -0
  44. package/dist/esm/SelectViewport.js.map +7 -0
  45. package/dist/esm/SelectViewport.native.js +17 -0
  46. package/dist/esm/SelectViewport.native.js.map +7 -0
  47. package/dist/esm/constants.js +17 -0
  48. package/dist/esm/constants.js.map +7 -0
  49. package/dist/esm/context.js +21 -0
  50. package/dist/esm/context.js.map +7 -0
  51. package/dist/esm/index.js +1 -0
  52. package/dist/esm/index.js.map +2 -2
  53. package/dist/esm/types.js +1 -0
  54. package/dist/esm/types.js.map +7 -0
  55. package/dist/esm/useSelectBreakpointActive.js +14 -0
  56. package/dist/esm/useSelectBreakpointActive.js.map +7 -0
  57. package/dist/jsx/BubbleSelect.js +24 -0
  58. package/dist/jsx/BubbleSelect.js.map +7 -0
  59. package/dist/jsx/Select.js +284 -270
  60. package/dist/jsx/Select.js.map +7 -0
  61. package/dist/jsx/SelectContent.js +27 -0
  62. package/dist/jsx/SelectContent.js.map +7 -0
  63. package/dist/jsx/SelectContent.native.js +7 -0
  64. package/dist/jsx/SelectContent.native.js.map +7 -0
  65. package/dist/jsx/SelectImpl.js +244 -0
  66. package/dist/jsx/SelectImpl.js.map +7 -0
  67. package/dist/jsx/SelectScrollButton.js +99 -0
  68. package/dist/jsx/SelectScrollButton.js.map +7 -0
  69. package/dist/jsx/SelectScrollButton.native.js +7 -0
  70. package/dist/jsx/SelectScrollButton.native.js.map +7 -0
  71. package/dist/jsx/SelectViewport.js +72 -0
  72. package/dist/jsx/SelectViewport.js.map +7 -0
  73. package/dist/jsx/SelectViewport.native.js +13 -0
  74. package/dist/jsx/SelectViewport.native.js.map +7 -0
  75. package/dist/jsx/constants.js +17 -0
  76. package/dist/jsx/constants.js.map +7 -0
  77. package/dist/jsx/context.js +15 -0
  78. package/dist/jsx/context.js.map +7 -0
  79. package/dist/jsx/index.js +2 -0
  80. package/dist/jsx/index.js.map +7 -0
  81. package/dist/jsx/types.js +1 -0
  82. package/dist/jsx/types.js.map +7 -0
  83. package/dist/jsx/useSelectBreakpointActive.js +14 -0
  84. package/dist/jsx/useSelectBreakpointActive.js.map +7 -0
  85. package/package.json +26 -16
  86. package/src/BubbleSelect.tsx +46 -0
  87. package/src/Select.tsx +613 -0
  88. package/src/SelectContent.native.tsx +5 -0
  89. package/src/SelectContent.tsx +45 -0
  90. package/src/SelectImpl.tsx +342 -0
  91. package/src/SelectScrollButton.native.tsx +7 -0
  92. package/src/SelectScrollButton.tsx +168 -0
  93. package/src/SelectViewport.native.tsx +14 -0
  94. package/src/SelectViewport.tsx +104 -0
  95. package/src/constants.tsx +7 -0
  96. package/src/context.tsx +19 -0
  97. package/src/index.tsx +8 -0
  98. package/src/types.tsx +94 -0
  99. package/src/useSelectBreakpointActive.tsx +15 -0
  100. package/types/BubbleSelect.d.ts +2 -0
  101. package/types/Select.d.ts +750 -0
  102. package/types/SelectContent.d.ts +5 -0
  103. package/types/SelectContent.native.d.ts +4 -0
  104. package/types/SelectImpl.d.ts +9 -0
  105. package/types/SelectScrollButton.d.ts +6 -0
  106. package/types/SelectScrollButton.native.d.ts +4 -0
  107. package/types/SelectViewport.d.ts +127 -0
  108. package/types/SelectViewport.native.d.ts +7 -0
  109. package/types/constants.d.ts +8 -0
  110. package/types/context.d.ts +21 -0
  111. package/types/index.d.ts +2 -0
  112. package/types/types.d.ts +84 -0
  113. package/types/useSelectBreakpointActive.d.ts +4 -0
  114. package/types/index.d.ts.map +0 -1
@@ -1,391 +1,438 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
- import {
4
- offset,
5
- useFloating
6
- } from "@floating-ui/react-dom-interactions";
7
- import { usePrevious } from "@radix-ui/react-use-previous";
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
2
  import { useComposedRefs } from "@tamagui/compose-refs";
9
- import { composeEventHandlers, useIsomorphicLayoutEffect } from "@tamagui/core";
3
+ import { isWeb } from "@tamagui/core";
4
+ import { styled, useGet, useIsomorphicLayoutEffect, withStaticProperties } from "@tamagui/core";
10
5
  import { useId } from "@tamagui/core";
11
- import { createContextScope } from "@tamagui/create-context";
6
+ import { ListItem } from "@tamagui/list-item";
7
+ import { PortalHost } from "@tamagui/portal";
12
8
  import { Separator } from "@tamagui/separator";
13
- import { XStack } from "@tamagui/stacks";
9
+ import { ControlledSheet, SheetController } from "@tamagui/sheet";
10
+ import { XStack, YStack } from "@tamagui/stacks";
11
+ import { Paragraph } from "@tamagui/text";
14
12
  import { useControllableState } from "@tamagui/use-controllable-state";
15
13
  import * as React from "react";
16
14
  import * as ReactDOM from "react-dom";
17
- const OPEN_KEYS = [" ", "Enter", "ArrowUp", "ArrowDown"];
18
- const SELECTION_KEYS = [" ", "Enter"];
19
- const SELECT_NAME = "Select";
20
- const WINDOW_PADDING = 8;
21
- const SCROLL_ARROW_VELOCITY = 8;
22
- const SCROLL_ARROW_THRESHOLD = 8;
23
- const MIN_HEIGHT = 80;
24
- const FALLBACK_THRESHOLD = 16;
25
- const [createSelectContext, createSelectScope] = createContextScope(SELECT_NAME);
26
- const [SelectProvider, useSelectContext] = createSelectContext(SELECT_NAME);
27
- const Select = /* @__PURE__ */ __name((props) => {
28
- const {
29
- __scopeSelect,
30
- children,
31
- open: openProp,
32
- defaultOpen,
33
- onOpenChange,
34
- value: valueProp,
35
- defaultValue,
36
- onValueChange,
37
- dir: dir2,
38
- name,
39
- autoComplete
40
- } = props;
41
- const [open, setOpen] = useControllableState({
42
- prop: openProp,
43
- defaultProp: defaultOpen || false,
44
- onChange: onOpenChange
45
- });
46
- const [value, setValue] = useControllableState({
47
- prop: valueProp,
48
- defaultProp: defaultValue || "",
49
- onChange: onValueChange
50
- });
51
- const selectedIndexRef = React.useRef(null);
52
- const activeIndexRef = React.useRef(null);
53
- const prevActiveIndex = usePrevious(activeIndex);
54
- const [showArrows, setShowArrows] = React.useState(false);
55
- const [scrollTop, setScrollTop] = React.useState(0);
56
- const [activeIndex, setActiveIndex] = React.useState(null);
57
- const [selectedIndex, setSelectedIndex] = React.useState(Math.max(0, listContentRef.current.indexOf(value)));
58
- useIsomorphicLayoutEffect(() => {
59
- selectedIndexRef.current = selectedIndex;
60
- activeIndexRef.current = activeIndex;
61
- });
62
- useEffect(() => {
63
- const frame = requestAnimationFrame(() => {
64
- setShowArrows(open);
65
- if (!open) {
66
- setScrollTop(0);
67
- setMiddlewareType("align");
68
- setActiveIndex(null);
69
- setControlledScrolling(false);
70
- }
71
- });
72
- return () => cancelAnimationFrame(frame);
73
- }, [open]);
74
- const showUpArrow = showArrows && scrollTop > SCROLL_ARROW_THRESHOLD;
75
- const showDownArrow = showArrows && floatingRef.current && scrollTop < floatingRef.current.scrollHeight - floatingRef.current.clientHeight - SCROLL_ARROW_THRESHOLD;
76
- return /* @__PURE__ */ React.createElement(SelectProvider, {
77
- scope: __scopeSelect,
78
- open
79
- }, children);
80
- }, "Select");
81
- Select.displayName = SELECT_NAME;
15
+ import { SELECT_NAME } from "./constants";
16
+ import { SelectProvider, createSelectContext, useSelectContext } from "./context";
17
+ import { SelectContent } from "./SelectContent";
18
+ import { SelectInlineImpl } from "./SelectImpl";
19
+ import { SelectScrollDownButton, SelectScrollUpButton } from "./SelectScrollButton";
20
+ import { SelectViewport } from "./SelectViewport";
21
+ import { useSelectBreakpointActive, useShowSelectSheet } from "./useSelectBreakpointActive";
82
22
  const TRIGGER_NAME = "SelectTrigger";
83
- const SelectTrigger = React.forwardRef((props, forwardedRef) => {
84
- const {
85
- __scopeSelect,
86
- disabled = false,
87
- "aria-labelledby": ariaLabelledby,
88
- ...triggerProps
89
- } = props;
90
- const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
91
- const composedRefs = useComposedRefs(forwardedRef, context.onTriggerChange);
92
- const getItems = useCollection(__scopeSelect);
93
- const handleOpen = /* @__PURE__ */ __name(() => {
94
- if (!disabled) {
95
- context.onOpenChange(true);
96
- resetTypeahead();
97
- }
98
- }, "handleOpen");
99
- return /* @__PURE__ */ React.createElement(Primitive.button, {
100
- type: "button",
101
- role: "combobox",
102
- "aria-controls": context.contentId,
103
- "aria-expanded": context.open,
104
- "aria-autocomplete": "none",
105
- dir: context.dir,
106
- disabled,
107
- "data-disabled": disabled ? "" : void 0,
108
- ...triggerProps,
109
- ref: composedRefs,
110
- onPointerDown: composeEventHandlers(triggerProps.onPointerDown, (event) => {
111
- ;
112
- event.target.releasePointerCapture(event.pointerId);
113
- if (event.button === 0 && event.ctrlKey === false) {
114
- handleOpen();
115
- context.triggerPointerDownPosRef.current = {
116
- x: Math.round(event.pageX),
117
- y: Math.round(event.pageY)
118
- };
119
- event.preventDefault();
23
+ const SelectTrigger = React.forwardRef(
24
+ (props, forwardedRef) => {
25
+ const {
26
+ __scopeSelect,
27
+ disabled = false,
28
+ "aria-labelledby": ariaLabelledby,
29
+ ...triggerProps
30
+ } = props;
31
+ const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
32
+ const labelledBy = ariaLabelledby;
33
+ return /* @__PURE__ */ jsx(ListItem, {
34
+ componentName: TRIGGER_NAME,
35
+ backgrounded: true,
36
+ radiused: true,
37
+ hoverTheme: true,
38
+ pressTheme: true,
39
+ focusTheme: true,
40
+ focusable: true,
41
+ borderWidth: 1,
42
+ size: context.size,
43
+ "aria-expanded": context.open,
44
+ "aria-autocomplete": "none",
45
+ "aria-labelledby": labelledBy,
46
+ dir: context.dir,
47
+ disabled,
48
+ "data-disabled": disabled ? "" : void 0,
49
+ ...triggerProps,
50
+ ref: forwardedRef,
51
+ ...process.env.TAMAGUI_TARGET === "web" && context.interactions ? context.interactions.getReferenceProps() : {
52
+ onPress() {
53
+ context.setOpen(!context.open);
54
+ }
120
55
  }
121
- }),
122
- onKeyDown: composeEventHandlers(triggerProps.onKeyDown, (event) => {
123
- const isTypingAhead = searchRef.current !== "";
124
- const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
125
- if (!isModifierKey && event.key.length === 1)
126
- handleTypeaheadSearch(event.key);
127
- if (isTypingAhead && event.key === " ")
128
- return;
129
- if (OPEN_KEYS.includes(event.key)) {
130
- handleOpen();
131
- event.preventDefault();
132
- }
133
- })
134
- });
135
- });
56
+ });
57
+ }
58
+ );
136
59
  SelectTrigger.displayName = TRIGGER_NAME;
137
60
  const VALUE_NAME = "SelectValue";
138
- const SelectValue = React.forwardRef((props, forwardedRef) => {
139
- const { __scopeSelect, className, style, ...valueProps } = props;
140
- return /* @__PURE__ */ React.createElement(XStack, {
141
- ...valueProps,
142
- pointerEvents: "none"
143
- });
144
- });
145
- const ICON_NAME = "SelectIcon";
146
- const SelectIcon = React.forwardRef((props, forwardedRef) => {
147
- const { __scopeSelect, children, ...iconProps } = props;
148
- return /* @__PURE__ */ React.createElement(XStack, {
149
- "aria-hidden": true,
150
- ...iconProps,
151
- ref: forwardedRef
152
- }, children || "\u25BC");
153
- });
154
- SelectIcon.displayName = ICON_NAME;
155
- const CONTENT_NAME = "SelectContent";
156
- const SelectContent = React.forwardRef((props, forwardedRef) => {
157
- const context = useSelectContext(CONTENT_NAME, props.__scopeSelect);
158
- return props.children;
61
+ const SelectValueFrame = styled(Paragraph, {
62
+ name: VALUE_NAME,
63
+ selectable: false
159
64
  });
160
- const GROUP_NAME = "SelectGroup";
161
- const [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
162
- const SelectGroup = React.forwardRef((props, forwardedRef) => {
163
- const { __scopeSelect, ...groupProps } = props;
164
- const groupId = useId();
165
- return /* @__PURE__ */ React.createElement(SelectGroupContextProvider, {
166
- scope: __scopeSelect,
167
- id: groupId
168
- }, /* @__PURE__ */ React.createElement(Primitive.div, {
169
- role: "group",
170
- "aria-labelledby": groupId,
171
- ...groupProps,
172
- ref: forwardedRef
173
- }));
174
- });
175
- SelectGroup.displayName = GROUP_NAME;
176
- const LABEL_NAME = "SelectLabel";
177
- const SelectLabel = React.forwardRef((props, forwardedRef) => {
178
- const { __scopeSelect, ...labelProps } = props;
179
- const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
180
- return /* @__PURE__ */ React.createElement(Primitive.div, {
181
- id: groupContext.id,
182
- ...labelProps,
183
- ref: forwardedRef
184
- });
65
+ const SelectValue = SelectValueFrame.extractable(
66
+ React.forwardRef(
67
+ ({ __scopeSelect, children: childrenProp, placeholder }, forwardedRef) => {
68
+ const context = useSelectContext(VALUE_NAME, __scopeSelect);
69
+ const { onValueNodeHasChildrenChange } = context;
70
+ const hasChildren = childrenProp !== void 0;
71
+ const composedRefs = useComposedRefs(forwardedRef, context.onValueNodeChange);
72
+ useIsomorphicLayoutEffect(() => {
73
+ onValueNodeHasChildrenChange(hasChildren);
74
+ }, [onValueNodeHasChildrenChange, hasChildren]);
75
+ const children = childrenProp ?? context.selectedItem;
76
+ return /* @__PURE__ */ jsx(SelectValueFrame, {
77
+ size: context.size,
78
+ ref: composedRefs,
79
+ pointerEvents: "none",
80
+ children: context.value === void 0 && placeholder !== void 0 ? placeholder : children
81
+ });
82
+ }
83
+ )
84
+ );
85
+ SelectValue.displayName = VALUE_NAME;
86
+ const SelectIcon = styled(XStack, {
87
+ name: "SelectIcon",
88
+ "aria-hidden": true,
89
+ children: /* @__PURE__ */ jsx(Paragraph, {
90
+ children: "\u25BC"
91
+ })
185
92
  });
186
- SelectLabel.displayName = LABEL_NAME;
187
93
  const ITEM_NAME = "SelectItem";
188
94
  const [SelectItemContextProvider, useSelectItemContext] = createSelectContext(ITEM_NAME);
189
- const SelectItem = React.forwardRef((props, forwardedRef) => {
190
- const { __scopeSelect, value, disabled = false, textValue: textValueProp, ...itemProps } = props;
191
- const context = useSelectContext(ITEM_NAME, __scopeSelect);
192
- const contentContext = useSelectContentContext(ITEM_NAME, __scopeSelect);
193
- const isSelected = context.value === value;
194
- const [textValue, setTextValue] = React.useState(textValueProp != null ? textValueProp : "");
195
- const [isFocused, setIsFocused] = React.useState(false);
196
- const composedRefs = useComposedRefs(forwardedRef, isSelected ? contentContext.onSelectedItemChange : void 0);
197
- const textId = useId();
198
- const handleSelect = /* @__PURE__ */ __name(() => {
199
- if (!disabled) {
200
- context.onValueChange(value);
201
- context.onOpenChange(false);
202
- }
203
- }, "handleSelect");
204
- return /* @__PURE__ */ React.createElement(SelectItemContextProvider, {
205
- scope: __scopeSelect,
206
- value,
207
- textId,
208
- isSelected,
209
- onItemTextChange: React.useCallback((node) => {
210
- setTextValue((prevTextValue) => {
211
- var _a;
212
- return prevTextValue || ((_a = node == null ? void 0 : node.textContent) != null ? _a : "").trim();
213
- });
214
- }, [])
215
- }, /* @__PURE__ */ React.createElement(Collection.ItemSlot, {
216
- scope: __scopeSelect,
217
- value,
218
- disabled,
219
- textValue
220
- }, /* @__PURE__ */ React.createElement(Primitive.div, {
221
- role: "option",
222
- "aria-labelledby": textId,
223
- "aria-selected": isSelected && isFocused,
224
- "data-state": isSelected ? "active" : "inactive",
225
- "aria-disabled": disabled || void 0,
226
- "data-disabled": disabled ? "" : void 0,
227
- tabIndex: disabled ? void 0 : -1,
228
- ...itemProps,
229
- ref: composedRefs,
230
- onFocus: composeEventHandlers(itemProps.onFocus, () => setIsFocused(true)),
231
- onBlur: composeEventHandlers(itemProps.onBlur, () => setIsFocused(false)),
232
- onPointerUp: composeEventHandlers(itemProps.onPointerUp, handleSelect),
233
- onPointerMove: composeEventHandlers(itemProps.onPointerMove, (event) => {
234
- if (disabled) {
235
- contentContext.onItemLeave();
236
- } else {
237
- event.currentTarget.focus({ preventScroll: true });
95
+ const SelectItem = React.forwardRef(
96
+ (props, forwardedRef) => {
97
+ const {
98
+ __scopeSelect,
99
+ value,
100
+ disabled = false,
101
+ textValue: textValueProp,
102
+ index,
103
+ ...itemProps
104
+ } = props;
105
+ const context = useSelectContext(ITEM_NAME, __scopeSelect);
106
+ const isSelected = context.value === value;
107
+ const textId = useId();
108
+ const {
109
+ selectedIndex,
110
+ setSelectedIndex,
111
+ listRef,
112
+ open,
113
+ setOpen,
114
+ onChange,
115
+ setActiveIndex,
116
+ allowMouseUpRef,
117
+ allowSelectRef,
118
+ setValueAtIndex,
119
+ selectTimeoutRef,
120
+ dataRef
121
+ } = context;
122
+ const composedRefs = useComposedRefs(forwardedRef, (node) => {
123
+ if (!isWeb)
124
+ return;
125
+ if (node instanceof HTMLElement) {
126
+ if (listRef) {
127
+ listRef.current[index] = node;
128
+ }
238
129
  }
239
- }),
240
- onPointerLeave: composeEventHandlers(itemProps.onPointerLeave, (event) => {
241
- if (event.currentTarget === document.activeElement) {
242
- contentContext.onItemLeave();
130
+ });
131
+ React.useEffect(() => {
132
+ setValueAtIndex(index, value);
133
+ }, [index, setValueAtIndex, value]);
134
+ function handleSelect() {
135
+ setSelectedIndex(index);
136
+ onChange(value);
137
+ setOpen(false);
138
+ }
139
+ const selectItemProps = context.interactions ? context.interactions.getItemProps({
140
+ onTouchStart() {
141
+ allowSelectRef.current = true;
142
+ allowMouseUpRef.current = false;
143
+ },
144
+ onKeyDown(event) {
145
+ if (event.key === "Enter" || event.key === " " && !(dataRef == null ? void 0 : dataRef.current.typing)) {
146
+ event.preventDefault();
147
+ handleSelect();
148
+ } else {
149
+ allowSelectRef.current = true;
150
+ }
151
+ },
152
+ onClick() {
153
+ if (allowSelectRef.current) {
154
+ setSelectedIndex(index);
155
+ setOpen(false);
156
+ }
157
+ },
158
+ onMouseUp() {
159
+ if (!allowMouseUpRef.current) {
160
+ return;
161
+ }
162
+ if (allowSelectRef.current) {
163
+ handleSelect();
164
+ }
165
+ clearTimeout(selectTimeoutRef.current);
166
+ selectTimeoutRef.current = setTimeout(() => {
167
+ allowSelectRef.current = true;
168
+ });
243
169
  }
244
- }),
245
- onKeyDown: composeEventHandlers(itemProps.onKeyDown, (event) => {
246
- const isTypingAhead = contentContext.searchRef.current !== "";
247
- if (isTypingAhead && event.key === " ")
248
- return;
249
- if (SELECTION_KEYS.includes(event.key))
250
- handleSelect();
251
- if (event.key === " ")
252
- event.preventDefault();
253
- })
254
- })));
255
- });
170
+ }) : {
171
+ onPress: handleSelect
172
+ };
173
+ return /* @__PURE__ */ jsx(SelectItemContextProvider, {
174
+ scope: __scopeSelect,
175
+ value,
176
+ textId: textId || "",
177
+ isSelected,
178
+ children: /* @__PURE__ */ jsx(ListItem, {
179
+ backgrounded: true,
180
+ pressTheme: true,
181
+ cursor: "",
182
+ focusTheme: true,
183
+ componentName: ITEM_NAME,
184
+ ref: composedRefs,
185
+ "aria-labelledby": textId,
186
+ "aria-selected": isSelected,
187
+ "data-state": isSelected ? "active" : "inactive",
188
+ "aria-disabled": disabled || void 0,
189
+ "data-disabled": disabled ? "" : void 0,
190
+ tabIndex: disabled ? void 0 : -1,
191
+ size: context.size,
192
+ ...itemProps,
193
+ ...selectItemProps
194
+ })
195
+ });
196
+ }
197
+ );
256
198
  SelectItem.displayName = ITEM_NAME;
257
199
  const ITEM_TEXT_NAME = "SelectItemText";
258
- const SelectItemText = React.forwardRef((props, forwardedRef) => {
259
- var _a;
260
- const { __scopeSelect, className, style, ...itemTextProps } = props;
261
- const context = useSelectContext(ITEM_TEXT_NAME, __scopeSelect);
262
- const contentContext = useSelectContentContext(ITEM_TEXT_NAME, __scopeSelect);
263
- const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
264
- const ref = React.useRef(null);
265
- const composedRefs = useComposedRefs(forwardedRef, ref, itemContext.onItemTextChange, itemContext.isSelected ? contentContext.onSelectedItemTextChange : void 0);
266
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Primitive.span, {
267
- id: itemContext.textId,
268
- ...itemTextProps,
269
- ref: composedRefs
270
- }), itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren ? ReactDOM.createPortal(itemTextProps.children, context.valueNode) : null, context.bubbleSelect ? ReactDOM.createPortal(/* @__PURE__ */ React.createElement("option", {
271
- value: itemContext.value
272
- }, (_a = ref.current) == null ? void 0 : _a.textContent), context.bubbleSelect) : null);
200
+ const SelectItemTextFrame = styled(Paragraph, {
201
+ name: ITEM_TEXT_NAME,
202
+ selectable: false
273
203
  });
204
+ const SelectItemText = React.forwardRef(
205
+ (props, forwardedRef) => {
206
+ const { __scopeSelect, className, ...itemTextProps } = props;
207
+ const context = useSelectContext(ITEM_TEXT_NAME, __scopeSelect);
208
+ const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
209
+ const ref = React.useRef(null);
210
+ const composedRefs = useComposedRefs(forwardedRef, ref);
211
+ const isSelected = itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren;
212
+ const contents = /* @__PURE__ */ jsx(SelectItemTextFrame, {
213
+ className,
214
+ size: context.size,
215
+ id: itemContext.textId,
216
+ ...itemTextProps,
217
+ ref: composedRefs
218
+ });
219
+ if (!isWeb) {
220
+ React.useEffect(() => {
221
+ if (isSelected) {
222
+ context.setSelectedItem(contents);
223
+ }
224
+ }, [isSelected]);
225
+ }
226
+ return /* @__PURE__ */ jsxs(Fragment, {
227
+ children: [
228
+ contents,
229
+ isWeb && isSelected ? ReactDOM.createPortal(itemTextProps.children, context.valueNode) : null
230
+ ]
231
+ });
232
+ }
233
+ );
274
234
  SelectItemText.displayName = ITEM_TEXT_NAME;
275
235
  const ITEM_INDICATOR_NAME = "SelectItemIndicator";
276
- const SelectItemIndicator = React.forwardRef((props, forwardedRef) => {
277
- const { __scopeSelect, ...itemIndicatorProps } = props;
278
- const itemContext = useSelectItemContext(ITEM_INDICATOR_NAME, __scopeSelect);
279
- return itemContext.isSelected ? /* @__PURE__ */ React.createElement(Primitive.span, {
280
- "aria-hidden": true,
281
- ...itemIndicatorProps,
282
- ref: forwardedRef
283
- }) : null;
236
+ const SelectItemIndicatorFrame = styled(XStack, {
237
+ name: ITEM_TEXT_NAME
284
238
  });
239
+ const SelectItemIndicator = React.forwardRef(
240
+ (props, forwardedRef) => {
241
+ const { __scopeSelect, ...itemIndicatorProps } = props;
242
+ const itemContext = useSelectItemContext(ITEM_INDICATOR_NAME, __scopeSelect);
243
+ return itemContext.isSelected ? /* @__PURE__ */ jsx(SelectItemIndicatorFrame, {
244
+ "aria-hidden": true,
245
+ ...itemIndicatorProps,
246
+ ref: forwardedRef
247
+ }) : null;
248
+ }
249
+ );
285
250
  SelectItemIndicator.displayName = ITEM_INDICATOR_NAME;
286
- const SCROLL_UP_BUTTON_NAME = "SelectScrollUpButton";
287
- const SelectScrollUpButton = React.forwardRef((props, forwardedRef) => {
288
- const contentContext = useSelectContentContext(SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
289
- const [canScrollUp, setCanScrollUp] = React.useState(false);
290
- const composedRefs = useComposedRefs(forwardedRef, contentContext.onScrollButtonChange);
291
- return canScrollUp ? /* @__PURE__ */ React.createElement(SelectScrollButtonImpl, {
292
- ...props,
293
- ref: composedRefs,
294
- onAutoScroll: () => {
295
- const { viewport, selectedItem } = contentContext;
296
- if (viewport && selectedItem) {
297
- viewport.scrollTop = viewport.scrollTop - selectedItem.offsetHeight;
298
- }
299
- }
300
- }) : null;
251
+ const GROUP_NAME = "SelectGroup";
252
+ const [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
253
+ const SelectGroupFrame = styled(YStack, {
254
+ name: GROUP_NAME,
255
+ width: "100%"
301
256
  });
302
- SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME;
303
- const SCROLL_DOWN_BUTTON_NAME = "SelectScrollDownButton";
304
- const SelectScrollDownButton = React.forwardRef((props, forwardedRef) => {
305
- const contentContext = useSelectContentContext(SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
306
- const [canScrollDown, setCanScrollDown] = React.useState(false);
307
- const composedRefs = useComposedRefs(forwardedRef, contentContext.onScrollButtonChange);
308
- return canScrollDown ? /* @__PURE__ */ React.createElement(SelectScrollButtonImpl, {
309
- ...props,
310
- ref: composedRefs,
311
- onAutoScroll: () => {
312
- const { viewport, selectedItem } = contentContext;
313
- if (viewport && selectedItem) {
314
- viewport.scrollTop = viewport.scrollTop + selectedItem.offsetHeight;
315
- }
316
- }
317
- }) : null;
257
+ const SelectGroup = React.forwardRef(
258
+ (props, forwardedRef) => {
259
+ const { __scopeSelect, ...groupProps } = props;
260
+ const groupId = useId();
261
+ return /* @__PURE__ */ jsx(SelectGroupContextProvider, {
262
+ scope: __scopeSelect,
263
+ id: groupId || "",
264
+ children: /* @__PURE__ */ jsx(SelectGroupFrame, {
265
+ role: "group",
266
+ "aria-labelledby": groupId,
267
+ ...groupProps,
268
+ ref: forwardedRef
269
+ })
270
+ });
271
+ }
272
+ );
273
+ SelectGroup.displayName = GROUP_NAME;
274
+ const LABEL_NAME = "SelectLabel";
275
+ const SelectLabel = React.forwardRef(
276
+ (props, forwardedRef) => {
277
+ const { __scopeSelect, ...labelProps } = props;
278
+ const context = useSelectContext(LABEL_NAME, __scopeSelect);
279
+ const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
280
+ return /* @__PURE__ */ jsx(ListItem, {
281
+ componentName: LABEL_NAME,
282
+ fontWeight: "800",
283
+ id: groupContext.id,
284
+ size: context.size,
285
+ ...labelProps,
286
+ ref: forwardedRef
287
+ });
288
+ }
289
+ );
290
+ SelectLabel.displayName = LABEL_NAME;
291
+ const SelectSeparator = styled(Separator, {
292
+ name: "SelectSeparator"
318
293
  });
319
- SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
320
- const SelectScrollButtonImpl = React.forwardRef((props, forwardedRef) => {
321
- const { __scopeSelect, onAutoScroll, ...scrollIndicatorProps } = props;
322
- const contentContext = useSelectContentContext("SelectScrollButton", __scopeSelect);
323
- const autoScrollTimerRef = React.useRef(null);
324
- const intervalRef = React.useRef();
325
- const loopingRef = React.useRef(false);
326
- const { x, y, reference, floating, strategy, update, refs } = useFloating({
327
- strategy: "fixed",
328
- placement: dir === "up" ? "top" : "bottom",
329
- middleware: [offset(({ floating: floating2 }) => -floating2.height)]
330
- });
331
- return /* @__PURE__ */ React.createElement(Primitive.div, {
332
- "aria-hidden": true,
333
- ...scrollIndicatorProps,
334
- ref: forwardedRef,
335
- style: { flexShrink: 0, ...scrollIndicatorProps.style },
336
- onPointerMove: composeEventHandlers(scrollIndicatorProps.onPointerMove, () => {
337
- contentContext.onItemLeave();
338
- if (autoScrollTimerRef.current === null) {
339
- autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
294
+ const SelectSheetController = (props) => {
295
+ const context = useSelectContext("SelectSheetController", props.__scopeSelect);
296
+ const showSheet = useShowSelectSheet(context);
297
+ const breakpointActive = useSelectBreakpointActive(context.sheetBreakpoint);
298
+ const getShowSheet = useGet(showSheet);
299
+ return /* @__PURE__ */ jsx(SheetController, {
300
+ onOpenChange: (val) => {
301
+ if (getShowSheet()) {
302
+ props.onOpenChange(val);
340
303
  }
341
- }),
342
- onPointerLeave: composeEventHandlers(scrollIndicatorProps.onPointerLeave, () => {
343
- clearAutoScrollTimer();
344
- })
304
+ },
305
+ open: context.open,
306
+ hidden: breakpointActive === false,
307
+ children: props.children
345
308
  });
346
- });
347
- const SEPARATOR_NAME = "SelectSeparator";
348
- const SelectSeparator = Separator;
349
- SelectSeparator.displayName = SEPARATOR_NAME;
350
- const BubbleSelect = React.forwardRef((props, forwardedRef) => {
351
- const { value, ...selectProps } = props;
352
- const ref = React.useRef(null);
353
- const composedRefs = useComposedRefs(forwardedRef, ref);
354
- const prevValue = usePrevious(value);
355
- React.useEffect(() => {
356
- const select = ref.current;
357
- const selectProto = window.HTMLSelectElement.prototype;
358
- const descriptor = Object.getOwnPropertyDescriptor(selectProto, "value");
359
- const setValue = descriptor.set;
360
- if (prevValue !== value && setValue) {
361
- const event = new Event("change", { bubbles: true });
362
- setValue.call(select, value);
363
- select.dispatchEvent(event);
364
- }
365
- }, [prevValue, value]);
366
- return null;
367
- return /* @__PURE__ */ React.createElement(VisuallyHidden, {
368
- asChild: true
369
- }, /* @__PURE__ */ React.createElement("select", {
370
- ...selectProps,
371
- ref: composedRefs,
372
- defaultValue: value
373
- }));
374
- });
309
+ };
310
+ const SHEET_CONTENTS_NAME = "SelectSheetContents";
311
+ const SelectSheetContents = ({ __scopeSelect }) => {
312
+ const context = useSelectContext(SHEET_CONTENTS_NAME, __scopeSelect);
313
+ return /* @__PURE__ */ jsx(PortalHost, {
314
+ name: `${context.scopeKey}SheetContents`
315
+ });
316
+ };
317
+ SelectSheetContents.displayName = SHEET_CONTENTS_NAME;
318
+ const SelectSheetImpl = (props) => {
319
+ return /* @__PURE__ */ jsx(Fragment, {
320
+ children: props.children
321
+ });
322
+ };
323
+ const Select = withStaticProperties(
324
+ (props) => {
325
+ const {
326
+ __scopeSelect,
327
+ children,
328
+ open: openProp,
329
+ defaultOpen,
330
+ onOpenChange,
331
+ value: valueProp,
332
+ defaultValue,
333
+ onValueChange,
334
+ size: sizeProp = "$4",
335
+ sheetBreakpoint = false,
336
+ dir
337
+ } = props;
338
+ const isSheet = useSelectBreakpointActive(sheetBreakpoint);
339
+ const SelectImpl = isSheet ? SelectSheetImpl : SelectInlineImpl;
340
+ const forceUpdate = React.useReducer(() => ({}), {})[1];
341
+ const [selectedItem, setSelectedItem] = React.useState(null);
342
+ const [open, setOpen] = useControllableState({
343
+ prop: openProp,
344
+ defaultProp: defaultOpen || false,
345
+ onChange: onOpenChange,
346
+ strategy: "most-recent-wins"
347
+ });
348
+ const [value, setValue] = useControllableState({
349
+ prop: valueProp,
350
+ defaultProp: defaultValue || "",
351
+ onChange: onValueChange,
352
+ strategy: "most-recent-wins"
353
+ });
354
+ const [activeIndex, setActiveIndex] = React.useState(null);
355
+ const selectedIndexRef = React.useRef(null);
356
+ const activeIndexRef = React.useRef(null);
357
+ const listContentRef = React.useRef([]);
358
+ const [selectedIndex, setSelectedIndex] = React.useState(
359
+ Math.max(0, listContentRef.current.indexOf(value))
360
+ );
361
+ const [valueNode, setValueNode] = React.useState(null);
362
+ const [valueNodeHasChildren, setValueNodeHasChildren] = React.useState(false);
363
+ useIsomorphicLayoutEffect(() => {
364
+ selectedIndexRef.current = selectedIndex;
365
+ activeIndexRef.current = activeIndex;
366
+ });
367
+ const id = useId();
368
+ const scopeKey = __scopeSelect ? Object.keys(__scopeSelect)[0] ?? id : id;
369
+ return /* @__PURE__ */ jsx(SelectProvider, {
370
+ dir,
371
+ blockSelection: false,
372
+ size: sizeProp,
373
+ fallback: false,
374
+ selectedItem,
375
+ setSelectedItem,
376
+ forceUpdate,
377
+ valueNode,
378
+ onValueNodeChange: setValueNode,
379
+ onValueNodeHasChildrenChange: setValueNodeHasChildren,
380
+ valueNodeHasChildren,
381
+ scopeKey,
382
+ sheetBreakpoint,
383
+ scope: __scopeSelect,
384
+ setValueAtIndex: (index, value2) => {
385
+ listContentRef.current[index] = value2;
386
+ },
387
+ activeIndex,
388
+ onChange: setValue,
389
+ selectedIndex,
390
+ setActiveIndex,
391
+ setOpen,
392
+ setSelectedIndex,
393
+ value,
394
+ open,
395
+ children: /* @__PURE__ */ jsx(SelectSheetController, {
396
+ onOpenChange: setOpen,
397
+ __scopeSelect,
398
+ children: /* @__PURE__ */ jsx(SelectImpl, {
399
+ activeIndexRef,
400
+ listContentRef,
401
+ selectedIndexRef,
402
+ ...props,
403
+ open,
404
+ value,
405
+ children
406
+ })
407
+ })
408
+ });
409
+ },
410
+ {
411
+ Content: SelectContent,
412
+ Group: SelectGroup,
413
+ Icon: SelectIcon,
414
+ Item: SelectItem,
415
+ ItemIndicator: SelectItemIndicator,
416
+ ItemText: SelectItemText,
417
+ Label: SelectLabel,
418
+ ScrollDownButton: SelectScrollDownButton,
419
+ ScrollUpButton: SelectScrollUpButton,
420
+ Trigger: SelectTrigger,
421
+ Value: SelectValue,
422
+ Viewport: SelectViewport,
423
+ SheetContents: SelectSheetContents,
424
+ Sheet: ControlledSheet
425
+ }
426
+ );
427
+ Select.displayName = SELECT_NAME;
375
428
  export {
376
429
  Select,
377
- SelectContent,
378
- SelectGroup,
430
+ SelectGroupFrame,
379
431
  SelectIcon,
380
432
  SelectItem,
381
- SelectItemIndicator,
382
- SelectItemText,
383
- SelectLabel,
384
- SelectScrollDownButton,
385
- SelectScrollUpButton,
433
+ SelectItemTextFrame,
386
434
  SelectSeparator,
387
- SelectTrigger,
388
- SelectValue,
389
- createSelectScope
435
+ SelectSheetContents,
436
+ SelectTrigger
390
437
  };
391
438
  //# sourceMappingURL=Select.js.map