@tamagui/select 1.0.1-beta.21 → 1.0.1-beta.211

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 +412 -390
  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 +403 -358
  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 +283 -271
  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 +618 -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 +753 -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,436 @@
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 } 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
- 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;
14
+ import { SELECT_NAME } from "./constants";
15
+ import { SelectProvider, createSelectContext, useSelectContext } from "./context";
16
+ import { SelectContent } from "./SelectContent";
17
+ import { SelectInlineImpl } from "./SelectImpl";
18
+ import { SelectScrollDownButton, SelectScrollUpButton } from "./SelectScrollButton";
19
+ import { SelectViewport } from "./SelectViewport";
20
+ import { useSelectBreakpointActive, useShowSelectSheet } from "./useSelectBreakpointActive";
82
21
  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();
22
+ const SelectTrigger = React.forwardRef(
23
+ (props, forwardedRef) => {
24
+ const {
25
+ __scopeSelect,
26
+ disabled = false,
27
+ "aria-labelledby": ariaLabelledby,
28
+ ...triggerProps
29
+ } = props;
30
+ const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
31
+ const labelledBy = ariaLabelledby;
32
+ return /* @__PURE__ */ jsx(ListItem, {
33
+ componentName: TRIGGER_NAME,
34
+ backgrounded: true,
35
+ radiused: true,
36
+ hoverTheme: true,
37
+ pressTheme: true,
38
+ focusTheme: true,
39
+ focusable: true,
40
+ borderWidth: 1,
41
+ size: context.size,
42
+ "aria-expanded": context.open,
43
+ "aria-autocomplete": "none",
44
+ "aria-labelledby": labelledBy,
45
+ dir: context.dir,
46
+ disabled,
47
+ "data-disabled": disabled ? "" : void 0,
48
+ ...triggerProps,
49
+ ref: forwardedRef,
50
+ ...process.env.TAMAGUI_TARGET === "web" && context.interactions ? context.interactions.getReferenceProps() : {
51
+ onPress() {
52
+ context.setOpen(!context.open);
53
+ }
120
54
  }
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
- });
55
+ });
56
+ }
57
+ );
136
58
  SelectTrigger.displayName = TRIGGER_NAME;
137
59
  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;
60
+ const SelectValueFrame = styled(Paragraph, {
61
+ name: VALUE_NAME,
62
+ selectable: false
159
63
  });
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
- });
64
+ const SelectValue = SelectValueFrame.extractable(
65
+ React.forwardRef(
66
+ ({ __scopeSelect, children: childrenProp, placeholder }, forwardedRef) => {
67
+ const context = useSelectContext(VALUE_NAME, __scopeSelect);
68
+ const { onValueNodeHasChildrenChange } = context;
69
+ const composedRefs = useComposedRefs(forwardedRef, context.onValueNodeChange);
70
+ const children = childrenProp ?? context.selectedItem;
71
+ const hasChildren = !!children;
72
+ const selectValueChildren = context.value === void 0 && placeholder !== void 0 ? placeholder : children;
73
+ useIsomorphicLayoutEffect(() => {
74
+ onValueNodeHasChildrenChange(hasChildren);
75
+ }, [onValueNodeHasChildrenChange, hasChildren]);
76
+ return /* @__PURE__ */ jsx(SelectValueFrame, {
77
+ size: context.size,
78
+ ref: composedRefs,
79
+ pointerEvents: "none",
80
+ children: selectValueChildren
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 = Boolean(itemContext.isSelected && context.valueNode);
212
+ const contents = React.useMemo(
213
+ () => /* @__PURE__ */ jsx(SelectItemTextFrame, {
214
+ className,
215
+ size: context.size,
216
+ id: itemContext.textId,
217
+ ...itemTextProps,
218
+ ref: composedRefs
219
+ }),
220
+ [props, context.size, className, itemContext.textId]
221
+ );
222
+ React.useEffect(() => {
223
+ if (isSelected) {
224
+ context.setSelectedItem(contents);
225
+ }
226
+ }, [isSelected, contents]);
227
+ return /* @__PURE__ */ jsx(Fragment, {
228
+ children: contents
229
+ });
230
+ }
231
+ );
274
232
  SelectItemText.displayName = ITEM_TEXT_NAME;
275
233
  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;
234
+ const SelectItemIndicatorFrame = styled(XStack, {
235
+ name: ITEM_TEXT_NAME
284
236
  });
237
+ const SelectItemIndicator = React.forwardRef(
238
+ (props, forwardedRef) => {
239
+ const { __scopeSelect, ...itemIndicatorProps } = props;
240
+ const itemContext = useSelectItemContext(ITEM_INDICATOR_NAME, __scopeSelect);
241
+ return itemContext.isSelected ? /* @__PURE__ */ jsx(SelectItemIndicatorFrame, {
242
+ "aria-hidden": true,
243
+ ...itemIndicatorProps,
244
+ ref: forwardedRef
245
+ }) : null;
246
+ }
247
+ );
285
248
  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;
249
+ const GROUP_NAME = "SelectGroup";
250
+ const [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
251
+ const SelectGroupFrame = styled(YStack, {
252
+ name: GROUP_NAME,
253
+ width: "100%"
301
254
  });
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;
255
+ const SelectGroup = React.forwardRef(
256
+ (props, forwardedRef) => {
257
+ const { __scopeSelect, ...groupProps } = props;
258
+ const groupId = useId();
259
+ return /* @__PURE__ */ jsx(SelectGroupContextProvider, {
260
+ scope: __scopeSelect,
261
+ id: groupId || "",
262
+ children: /* @__PURE__ */ jsx(SelectGroupFrame, {
263
+ role: "group",
264
+ "aria-labelledby": groupId,
265
+ ...groupProps,
266
+ ref: forwardedRef
267
+ })
268
+ });
269
+ }
270
+ );
271
+ SelectGroup.displayName = GROUP_NAME;
272
+ const LABEL_NAME = "SelectLabel";
273
+ const SelectLabel = React.forwardRef(
274
+ (props, forwardedRef) => {
275
+ const { __scopeSelect, ...labelProps } = props;
276
+ const context = useSelectContext(LABEL_NAME, __scopeSelect);
277
+ const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
278
+ return /* @__PURE__ */ jsx(ListItem, {
279
+ componentName: LABEL_NAME,
280
+ fontWeight: "800",
281
+ id: groupContext.id,
282
+ size: context.size,
283
+ ...labelProps,
284
+ ref: forwardedRef
285
+ });
286
+ }
287
+ );
288
+ SelectLabel.displayName = LABEL_NAME;
289
+ const SelectSeparator = styled(Separator, {
290
+ name: "SelectSeparator"
318
291
  });
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);
292
+ const SelectSheetController = (props) => {
293
+ const context = useSelectContext("SelectSheetController", props.__scopeSelect);
294
+ const showSheet = useShowSelectSheet(context);
295
+ const breakpointActive = useSelectBreakpointActive(context.sheetBreakpoint);
296
+ const getShowSheet = useGet(showSheet);
297
+ return /* @__PURE__ */ jsx(SheetController, {
298
+ onOpenChange: (val) => {
299
+ if (getShowSheet()) {
300
+ props.onOpenChange(val);
340
301
  }
341
- }),
342
- onPointerLeave: composeEventHandlers(scrollIndicatorProps.onPointerLeave, () => {
343
- clearAutoScrollTimer();
344
- })
302
+ },
303
+ open: context.open,
304
+ hidden: breakpointActive === false,
305
+ children: props.children
345
306
  });
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
- });
307
+ };
308
+ const SHEET_CONTENTS_NAME = "SelectSheetContents";
309
+ const SelectSheetContents = ({ __scopeSelect }) => {
310
+ const context = useSelectContext(SHEET_CONTENTS_NAME, __scopeSelect);
311
+ return /* @__PURE__ */ jsx(PortalHost, {
312
+ name: `${context.scopeKey}SheetContents`
313
+ });
314
+ };
315
+ SelectSheetContents.displayName = SHEET_CONTENTS_NAME;
316
+ const SelectSheetImpl = (props) => {
317
+ return /* @__PURE__ */ jsx(Fragment, {
318
+ children: props.children
319
+ });
320
+ };
321
+ const Select = withStaticProperties(
322
+ (props) => {
323
+ const {
324
+ __scopeSelect,
325
+ children,
326
+ open: openProp,
327
+ defaultOpen,
328
+ onOpenChange,
329
+ value: valueProp,
330
+ defaultValue,
331
+ onValueChange,
332
+ size: sizeProp = "$4",
333
+ sheetBreakpoint = false,
334
+ dir
335
+ } = props;
336
+ const isSheet = useSelectBreakpointActive(sheetBreakpoint);
337
+ const SelectImpl = isSheet ? SelectSheetImpl : SelectInlineImpl;
338
+ const forceUpdate = React.useReducer(() => ({}), {})[1];
339
+ const [selectedItem, setSelectedItem] = React.useState(null);
340
+ const [open, setOpen] = useControllableState({
341
+ prop: openProp,
342
+ defaultProp: defaultOpen || false,
343
+ onChange: onOpenChange,
344
+ strategy: "most-recent-wins"
345
+ });
346
+ const [value, setValue] = useControllableState({
347
+ prop: valueProp,
348
+ defaultProp: defaultValue || "",
349
+ onChange: onValueChange,
350
+ strategy: "most-recent-wins"
351
+ });
352
+ const [activeIndex, setActiveIndex] = React.useState(null);
353
+ const selectedIndexRef = React.useRef(null);
354
+ const activeIndexRef = React.useRef(null);
355
+ const listContentRef = React.useRef([]);
356
+ const [selectedIndex, setSelectedIndex] = React.useState(
357
+ Math.max(0, listContentRef.current.indexOf(value))
358
+ );
359
+ const [valueNode, setValueNode] = React.useState(null);
360
+ const [valueNodeHasChildren, setValueNodeHasChildren] = React.useState(false);
361
+ useIsomorphicLayoutEffect(() => {
362
+ selectedIndexRef.current = selectedIndex;
363
+ activeIndexRef.current = activeIndex;
364
+ });
365
+ const id = useId();
366
+ const scopeKey = __scopeSelect ? Object.keys(__scopeSelect)[0] ?? id : id;
367
+ return /* @__PURE__ */ jsx(SelectProvider, {
368
+ dir,
369
+ blockSelection: false,
370
+ size: sizeProp,
371
+ fallback: false,
372
+ selectedItem,
373
+ setSelectedItem,
374
+ forceUpdate,
375
+ valueNode,
376
+ onValueNodeChange: setValueNode,
377
+ onValueNodeHasChildrenChange: setValueNodeHasChildren,
378
+ valueNodeHasChildren,
379
+ scopeKey,
380
+ sheetBreakpoint,
381
+ scope: __scopeSelect,
382
+ setValueAtIndex: (index, value2) => {
383
+ listContentRef.current[index] = value2;
384
+ },
385
+ activeIndex,
386
+ onChange: setValue,
387
+ selectedIndex,
388
+ setActiveIndex,
389
+ setOpen,
390
+ setSelectedIndex,
391
+ value,
392
+ open,
393
+ children: /* @__PURE__ */ jsx(SelectSheetController, {
394
+ onOpenChange: setOpen,
395
+ __scopeSelect,
396
+ children: /* @__PURE__ */ jsx(SelectImpl, {
397
+ activeIndexRef,
398
+ listContentRef,
399
+ selectedIndexRef,
400
+ ...props,
401
+ open,
402
+ value,
403
+ children
404
+ })
405
+ })
406
+ });
407
+ },
408
+ {
409
+ Content: SelectContent,
410
+ Group: SelectGroup,
411
+ Icon: SelectIcon,
412
+ Item: SelectItem,
413
+ ItemIndicator: SelectItemIndicator,
414
+ ItemText: SelectItemText,
415
+ Label: SelectLabel,
416
+ ScrollDownButton: SelectScrollDownButton,
417
+ ScrollUpButton: SelectScrollUpButton,
418
+ Trigger: SelectTrigger,
419
+ Value: SelectValue,
420
+ Viewport: SelectViewport,
421
+ SheetContents: SelectSheetContents,
422
+ Sheet: ControlledSheet
423
+ }
424
+ );
425
+ Select.displayName = SELECT_NAME;
375
426
  export {
376
427
  Select,
377
- SelectContent,
378
- SelectGroup,
428
+ SelectGroupFrame,
379
429
  SelectIcon,
380
430
  SelectItem,
381
- SelectItemIndicator,
382
- SelectItemText,
383
- SelectLabel,
384
- SelectScrollDownButton,
385
- SelectScrollUpButton,
431
+ SelectItemTextFrame,
386
432
  SelectSeparator,
387
- SelectTrigger,
388
- SelectValue,
389
- createSelectScope
433
+ SelectSheetContents,
434
+ SelectTrigger
390
435
  };
391
436
  //# sourceMappingURL=Select.js.map