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

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,301 +1,313 @@
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";
8
1
  import { useComposedRefs } from "@tamagui/compose-refs";
9
- import { composeEventHandlers, useIsomorphicLayoutEffect } from "@tamagui/core";
2
+ import { isWeb } from "@tamagui/core";
3
+ import { styled, useGet, useIsomorphicLayoutEffect, withStaticProperties } from "@tamagui/core";
10
4
  import { useId } from "@tamagui/core";
11
- import { createContextScope } from "@tamagui/create-context";
5
+ import { ListItem } from "@tamagui/list-item";
6
+ import { PortalHost } from "@tamagui/portal";
12
7
  import { Separator } from "@tamagui/separator";
13
- import { XStack } from "@tamagui/stacks";
8
+ import { ControlledSheet, SheetController } from "@tamagui/sheet";
9
+ import { XStack, YStack } from "@tamagui/stacks";
10
+ import { Paragraph } from "@tamagui/text";
14
11
  import { useControllableState } from "@tamagui/use-controllable-state";
15
12
  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 <SelectProvider scope={__scopeSelect} open={open}>{children}</SelectProvider>;
77
- }, "Select");
78
- Select.displayName = SELECT_NAME;
13
+ import { SELECT_NAME } from "./constants";
14
+ import { SelectProvider, createSelectContext, useSelectContext } from "./context";
15
+ import { SelectContent } from "./SelectContent";
16
+ import { SelectInlineImpl } from "./SelectImpl";
17
+ import { SelectScrollDownButton, SelectScrollUpButton } from "./SelectScrollButton";
18
+ import { SelectViewport } from "./SelectViewport";
19
+ import { useSelectBreakpointActive, useShowSelectSheet } from "./useSelectBreakpointActive";
79
20
  const TRIGGER_NAME = "SelectTrigger";
80
- const SelectTrigger = React.forwardRef((props, forwardedRef) => {
81
- const {
82
- __scopeSelect,
83
- disabled = false,
84
- "aria-labelledby": ariaLabelledby,
85
- ...triggerProps
86
- } = props;
87
- const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
88
- const composedRefs = useComposedRefs(forwardedRef, context.onTriggerChange);
89
- const getItems = useCollection(__scopeSelect);
90
- const handleOpen = /* @__PURE__ */ __name(() => {
91
- if (!disabled) {
92
- context.onOpenChange(true);
93
- resetTypeahead();
94
- }
95
- }, "handleOpen");
96
- return <Primitive.button type="button" role="combobox" aria-controls={context.contentId} aria-expanded={context.open} aria-autocomplete="none" dir={context.dir} disabled={disabled} data-disabled={disabled ? "" : void 0} {...triggerProps} ref={composedRefs} onPointerDown={composeEventHandlers(triggerProps.onPointerDown, (event) => {
97
- ;
98
- event.target.releasePointerCapture(event.pointerId);
99
- if (event.button === 0 && event.ctrlKey === false) {
100
- handleOpen();
101
- context.triggerPointerDownPosRef.current = {
102
- x: Math.round(event.pageX),
103
- y: Math.round(event.pageY)
104
- };
105
- event.preventDefault();
106
- }
107
- })} onKeyDown={composeEventHandlers(triggerProps.onKeyDown, (event) => {
108
- const isTypingAhead = searchRef.current !== "";
109
- const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
110
- if (!isModifierKey && event.key.length === 1)
111
- handleTypeaheadSearch(event.key);
112
- if (isTypingAhead && event.key === " ")
113
- return;
114
- if (OPEN_KEYS.includes(event.key)) {
115
- handleOpen();
116
- event.preventDefault();
117
- }
118
- })} />;
119
- });
21
+ const SelectTrigger = React.forwardRef(
22
+ (props, forwardedRef) => {
23
+ const {
24
+ __scopeSelect,
25
+ disabled = false,
26
+ "aria-labelledby": ariaLabelledby,
27
+ ...triggerProps
28
+ } = props;
29
+ const context = useSelectContext(TRIGGER_NAME, __scopeSelect);
30
+ const labelledBy = ariaLabelledby;
31
+ return <ListItem componentName={TRIGGER_NAME} backgrounded radiused hoverTheme pressTheme focusTheme focusable borderWidth={1} size={context.size} aria-expanded={context.open} aria-autocomplete="none" aria-labelledby={labelledBy} dir={context.dir} disabled={disabled} data-disabled={disabled ? "" : void 0} {...triggerProps} ref={forwardedRef} {...process.env.TAMAGUI_TARGET === "web" && context.interactions ? context.interactions.getReferenceProps() : {
32
+ onPress() {
33
+ context.setOpen(!context.open);
34
+ }
35
+ }} />;
36
+ }
37
+ );
120
38
  SelectTrigger.displayName = TRIGGER_NAME;
121
39
  const VALUE_NAME = "SelectValue";
122
- const SelectValue = React.forwardRef((props, forwardedRef) => {
123
- const { __scopeSelect, className, style, ...valueProps } = props;
124
- return <XStack {...valueProps} pointerEvents="none" />;
125
- });
126
- const ICON_NAME = "SelectIcon";
127
- const SelectIcon = React.forwardRef((props, forwardedRef) => {
128
- const { __scopeSelect, children, ...iconProps } = props;
129
- return <XStack aria-hidden {...iconProps} ref={forwardedRef}>{children || "\u25BC"}</XStack>;
130
- });
131
- SelectIcon.displayName = ICON_NAME;
132
- const CONTENT_NAME = "SelectContent";
133
- const SelectContent = React.forwardRef((props, forwardedRef) => {
134
- const context = useSelectContext(CONTENT_NAME, props.__scopeSelect);
135
- return props.children;
40
+ const SelectValueFrame = styled(Paragraph, {
41
+ name: VALUE_NAME,
42
+ selectable: false
136
43
  });
137
- const GROUP_NAME = "SelectGroup";
138
- const [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
139
- const SelectGroup = React.forwardRef((props, forwardedRef) => {
140
- const { __scopeSelect, ...groupProps } = props;
141
- const groupId = useId();
142
- return <SelectGroupContextProvider scope={__scopeSelect} id={groupId}><Primitive.div role="group" aria-labelledby={groupId} {...groupProps} ref={forwardedRef} /></SelectGroupContextProvider>;
143
- });
144
- SelectGroup.displayName = GROUP_NAME;
145
- const LABEL_NAME = "SelectLabel";
146
- const SelectLabel = React.forwardRef((props, forwardedRef) => {
147
- const { __scopeSelect, ...labelProps } = props;
148
- const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
149
- return <Primitive.div id={groupContext.id} {...labelProps} ref={forwardedRef} />;
44
+ const SelectValue = SelectValueFrame.extractable(
45
+ React.forwardRef(
46
+ ({ __scopeSelect, children: childrenProp, placeholder }, forwardedRef) => {
47
+ const context = useSelectContext(VALUE_NAME, __scopeSelect);
48
+ const { onValueNodeHasChildrenChange } = context;
49
+ const composedRefs = useComposedRefs(forwardedRef, context.onValueNodeChange);
50
+ const children = childrenProp ?? context.selectedItem;
51
+ const hasChildren = !!children;
52
+ const selectValueChildren = context.value === void 0 && placeholder !== void 0 ? placeholder : children;
53
+ useIsomorphicLayoutEffect(() => {
54
+ onValueNodeHasChildrenChange(hasChildren);
55
+ }, [onValueNodeHasChildrenChange, hasChildren]);
56
+ return <SelectValueFrame size={context.size} ref={composedRefs} pointerEvents="none">{selectValueChildren}</SelectValueFrame>;
57
+ }
58
+ )
59
+ );
60
+ SelectValue.displayName = VALUE_NAME;
61
+ const SelectIcon = styled(XStack, {
62
+ name: "SelectIcon",
63
+ "aria-hidden": true,
64
+ children: <Paragraph>{"\u25BC"}</Paragraph>
150
65
  });
151
- SelectLabel.displayName = LABEL_NAME;
152
66
  const ITEM_NAME = "SelectItem";
153
67
  const [SelectItemContextProvider, useSelectItemContext] = createSelectContext(ITEM_NAME);
154
- const SelectItem = React.forwardRef((props, forwardedRef) => {
155
- const { __scopeSelect, value, disabled = false, textValue: textValueProp, ...itemProps } = props;
156
- const context = useSelectContext(ITEM_NAME, __scopeSelect);
157
- const contentContext = useSelectContentContext(ITEM_NAME, __scopeSelect);
158
- const isSelected = context.value === value;
159
- const [textValue, setTextValue] = React.useState(textValueProp != null ? textValueProp : "");
160
- const [isFocused, setIsFocused] = React.useState(false);
161
- const composedRefs = useComposedRefs(forwardedRef, isSelected ? contentContext.onSelectedItemChange : void 0);
162
- const textId = useId();
163
- const handleSelect = /* @__PURE__ */ __name(() => {
164
- if (!disabled) {
165
- context.onValueChange(value);
166
- context.onOpenChange(false);
167
- }
168
- }, "handleSelect");
169
- return <SelectItemContextProvider scope={__scopeSelect} value={value} textId={textId} isSelected={isSelected} onItemTextChange={React.useCallback((node) => {
170
- setTextValue((prevTextValue) => {
171
- var _a;
172
- return prevTextValue || ((_a = node == null ? void 0 : node.textContent) != null ? _a : "").trim();
68
+ const SelectItem = React.forwardRef(
69
+ (props, forwardedRef) => {
70
+ const {
71
+ __scopeSelect,
72
+ value,
73
+ disabled = false,
74
+ textValue: textValueProp,
75
+ index,
76
+ ...itemProps
77
+ } = props;
78
+ const context = useSelectContext(ITEM_NAME, __scopeSelect);
79
+ const isSelected = context.value === value;
80
+ const textId = useId();
81
+ const {
82
+ selectedIndex,
83
+ setSelectedIndex,
84
+ listRef,
85
+ open,
86
+ setOpen,
87
+ onChange,
88
+ setActiveIndex,
89
+ allowMouseUpRef,
90
+ allowSelectRef,
91
+ setValueAtIndex,
92
+ selectTimeoutRef,
93
+ dataRef
94
+ } = context;
95
+ const composedRefs = useComposedRefs(forwardedRef, (node) => {
96
+ if (!isWeb)
97
+ return;
98
+ if (node instanceof HTMLElement) {
99
+ if (listRef) {
100
+ listRef.current[index] = node;
101
+ }
102
+ }
173
103
  });
174
- }, [])}><Collection.ItemSlot scope={__scopeSelect} value={value} disabled={disabled} textValue={textValue}><Primitive.div role="option" aria-labelledby={textId} aria-selected={isSelected && isFocused} data-state={isSelected ? "active" : "inactive"} aria-disabled={disabled || void 0} data-disabled={disabled ? "" : void 0} tabIndex={disabled ? void 0 : -1} {...itemProps} ref={composedRefs} onFocus={composeEventHandlers(itemProps.onFocus, () => setIsFocused(true))} onBlur={composeEventHandlers(itemProps.onBlur, () => setIsFocused(false))} onPointerUp={composeEventHandlers(itemProps.onPointerUp, handleSelect)} onPointerMove={composeEventHandlers(itemProps.onPointerMove, (event) => {
175
- if (disabled) {
176
- contentContext.onItemLeave();
177
- } else {
178
- event.currentTarget.focus({ preventScroll: true });
179
- }
180
- })} onPointerLeave={composeEventHandlers(itemProps.onPointerLeave, (event) => {
181
- if (event.currentTarget === document.activeElement) {
182
- contentContext.onItemLeave();
104
+ React.useEffect(() => {
105
+ setValueAtIndex(index, value);
106
+ }, [index, setValueAtIndex, value]);
107
+ function handleSelect() {
108
+ setSelectedIndex(index);
109
+ onChange(value);
110
+ setOpen(false);
183
111
  }
184
- })} onKeyDown={composeEventHandlers(itemProps.onKeyDown, (event) => {
185
- const isTypingAhead = contentContext.searchRef.current !== "";
186
- if (isTypingAhead && event.key === " ")
187
- return;
188
- if (SELECTION_KEYS.includes(event.key))
189
- handleSelect();
190
- if (event.key === " ")
191
- event.preventDefault();
192
- })} /></Collection.ItemSlot></SelectItemContextProvider>;
193
- });
112
+ const selectItemProps = context.interactions ? context.interactions.getItemProps({
113
+ onTouchStart() {
114
+ allowSelectRef.current = true;
115
+ allowMouseUpRef.current = false;
116
+ },
117
+ onKeyDown(event) {
118
+ if (event.key === "Enter" || event.key === " " && !dataRef?.current.typing) {
119
+ event.preventDefault();
120
+ handleSelect();
121
+ } else {
122
+ allowSelectRef.current = true;
123
+ }
124
+ },
125
+ onClick() {
126
+ if (allowSelectRef.current) {
127
+ setSelectedIndex(index);
128
+ setOpen(false);
129
+ }
130
+ },
131
+ onMouseUp() {
132
+ if (!allowMouseUpRef.current) {
133
+ return;
134
+ }
135
+ if (allowSelectRef.current) {
136
+ handleSelect();
137
+ }
138
+ clearTimeout(selectTimeoutRef.current);
139
+ selectTimeoutRef.current = setTimeout(() => {
140
+ allowSelectRef.current = true;
141
+ });
142
+ }
143
+ }) : {
144
+ onPress: handleSelect
145
+ };
146
+ return <SelectItemContextProvider scope={__scopeSelect} value={value} textId={textId || ""} isSelected={isSelected}><ListItem backgrounded pressTheme cursor="" focusTheme componentName={ITEM_NAME} ref={composedRefs} aria-labelledby={textId} aria-selected={isSelected} data-state={isSelected ? "active" : "inactive"} aria-disabled={disabled || void 0} data-disabled={disabled ? "" : void 0} tabIndex={disabled ? void 0 : -1} size={context.size} {...itemProps} {...selectItemProps} /></SelectItemContextProvider>;
147
+ }
148
+ );
194
149
  SelectItem.displayName = ITEM_NAME;
195
150
  const ITEM_TEXT_NAME = "SelectItemText";
196
- const SelectItemText = React.forwardRef((props, forwardedRef) => {
197
- var _a;
198
- const { __scopeSelect, className, style, ...itemTextProps } = props;
199
- const context = useSelectContext(ITEM_TEXT_NAME, __scopeSelect);
200
- const contentContext = useSelectContentContext(ITEM_TEXT_NAME, __scopeSelect);
201
- const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
202
- const ref = React.useRef(null);
203
- const composedRefs = useComposedRefs(forwardedRef, ref, itemContext.onItemTextChange, itemContext.isSelected ? contentContext.onSelectedItemTextChange : void 0);
204
- return <>
205
- <Primitive.span id={itemContext.textId} {...itemTextProps} ref={composedRefs} />
206
- {itemContext.isSelected && context.valueNode && !context.valueNodeHasChildren ? ReactDOM.createPortal(itemTextProps.children, context.valueNode) : null}
207
- {context.bubbleSelect ? ReactDOM.createPortal(<option value={itemContext.value}>{(_a = ref.current) == null ? void 0 : _a.textContent}</option>, context.bubbleSelect) : null}
208
- </>;
151
+ const SelectItemTextFrame = styled(Paragraph, {
152
+ name: ITEM_TEXT_NAME,
153
+ selectable: false
209
154
  });
155
+ const SelectItemText = React.forwardRef(
156
+ (props, forwardedRef) => {
157
+ const { __scopeSelect, className, ...itemTextProps } = props;
158
+ const context = useSelectContext(ITEM_TEXT_NAME, __scopeSelect);
159
+ const itemContext = useSelectItemContext(ITEM_TEXT_NAME, __scopeSelect);
160
+ const ref = React.useRef(null);
161
+ const composedRefs = useComposedRefs(forwardedRef, ref);
162
+ const isSelected = Boolean(itemContext.isSelected && context.valueNode);
163
+ const contents = React.useMemo(
164
+ () => <SelectItemTextFrame className={className} size={context.size} id={itemContext.textId} {...itemTextProps} ref={composedRefs} />,
165
+ [props, context.size, className, itemContext.textId]
166
+ );
167
+ React.useEffect(() => {
168
+ if (isSelected) {
169
+ context.setSelectedItem(contents);
170
+ }
171
+ }, [isSelected, contents]);
172
+ return <>{contents}</>;
173
+ }
174
+ );
210
175
  SelectItemText.displayName = ITEM_TEXT_NAME;
211
176
  const ITEM_INDICATOR_NAME = "SelectItemIndicator";
212
- const SelectItemIndicator = React.forwardRef((props, forwardedRef) => {
213
- const { __scopeSelect, ...itemIndicatorProps } = props;
214
- const itemContext = useSelectItemContext(ITEM_INDICATOR_NAME, __scopeSelect);
215
- return itemContext.isSelected ? <Primitive.span aria-hidden {...itemIndicatorProps} ref={forwardedRef} /> : null;
177
+ const SelectItemIndicatorFrame = styled(XStack, {
178
+ name: ITEM_TEXT_NAME
216
179
  });
180
+ const SelectItemIndicator = React.forwardRef(
181
+ (props, forwardedRef) => {
182
+ const { __scopeSelect, ...itemIndicatorProps } = props;
183
+ const itemContext = useSelectItemContext(ITEM_INDICATOR_NAME, __scopeSelect);
184
+ return itemContext.isSelected ? <SelectItemIndicatorFrame aria-hidden {...itemIndicatorProps} ref={forwardedRef} /> : null;
185
+ }
186
+ );
217
187
  SelectItemIndicator.displayName = ITEM_INDICATOR_NAME;
218
- const SCROLL_UP_BUTTON_NAME = "SelectScrollUpButton";
219
- const SelectScrollUpButton = React.forwardRef((props, forwardedRef) => {
220
- const contentContext = useSelectContentContext(SCROLL_UP_BUTTON_NAME, props.__scopeSelect);
221
- const [canScrollUp, setCanScrollUp] = React.useState(false);
222
- const composedRefs = useComposedRefs(forwardedRef, contentContext.onScrollButtonChange);
223
- return canScrollUp ? <SelectScrollButtonImpl {...props} ref={composedRefs} onAutoScroll={() => {
224
- const { viewport, selectedItem } = contentContext;
225
- if (viewport && selectedItem) {
226
- viewport.scrollTop = viewport.scrollTop - selectedItem.offsetHeight;
227
- }
228
- }} /> : null;
229
- });
230
- SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME;
231
- const SCROLL_DOWN_BUTTON_NAME = "SelectScrollDownButton";
232
- const SelectScrollDownButton = React.forwardRef((props, forwardedRef) => {
233
- const contentContext = useSelectContentContext(SCROLL_DOWN_BUTTON_NAME, props.__scopeSelect);
234
- const [canScrollDown, setCanScrollDown] = React.useState(false);
235
- const composedRefs = useComposedRefs(forwardedRef, contentContext.onScrollButtonChange);
236
- return canScrollDown ? <SelectScrollButtonImpl {...props} ref={composedRefs} onAutoScroll={() => {
237
- const { viewport, selectedItem } = contentContext;
238
- if (viewport && selectedItem) {
239
- viewport.scrollTop = viewport.scrollTop + selectedItem.offsetHeight;
240
- }
241
- }} /> : null;
188
+ const GROUP_NAME = "SelectGroup";
189
+ const [SelectGroupContextProvider, useSelectGroupContext] = createSelectContext(GROUP_NAME);
190
+ const SelectGroupFrame = styled(YStack, {
191
+ name: GROUP_NAME,
192
+ width: "100%"
242
193
  });
243
- SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
244
- const SelectScrollButtonImpl = React.forwardRef((props, forwardedRef) => {
245
- const { __scopeSelect, onAutoScroll, ...scrollIndicatorProps } = props;
246
- const contentContext = useSelectContentContext("SelectScrollButton", __scopeSelect);
247
- const autoScrollTimerRef = React.useRef(null);
248
- const intervalRef = React.useRef();
249
- const loopingRef = React.useRef(false);
250
- const { x, y, reference, floating, strategy, update, refs } = useFloating({
251
- strategy: "fixed",
252
- placement: dir === "up" ? "top" : "bottom",
253
- middleware: [offset(({ floating: floating2 }) => -floating2.height)]
254
- });
255
- return <Primitive.div aria-hidden {...scrollIndicatorProps} ref={forwardedRef} style={{ flexShrink: 0, ...scrollIndicatorProps.style }} onPointerMove={composeEventHandlers(scrollIndicatorProps.onPointerMove, () => {
256
- contentContext.onItemLeave();
257
- if (autoScrollTimerRef.current === null) {
258
- autoScrollTimerRef.current = window.setInterval(onAutoScroll, 50);
259
- }
260
- })} onPointerLeave={composeEventHandlers(scrollIndicatorProps.onPointerLeave, () => {
261
- clearAutoScrollTimer();
262
- })} />;
194
+ const SelectGroup = React.forwardRef(
195
+ (props, forwardedRef) => {
196
+ const { __scopeSelect, ...groupProps } = props;
197
+ const groupId = useId();
198
+ return <SelectGroupContextProvider scope={__scopeSelect} id={groupId || ""}><SelectGroupFrame role="group" aria-labelledby={groupId} {...groupProps} ref={forwardedRef} /></SelectGroupContextProvider>;
199
+ }
200
+ );
201
+ SelectGroup.displayName = GROUP_NAME;
202
+ const LABEL_NAME = "SelectLabel";
203
+ const SelectLabel = React.forwardRef(
204
+ (props, forwardedRef) => {
205
+ const { __scopeSelect, ...labelProps } = props;
206
+ const context = useSelectContext(LABEL_NAME, __scopeSelect);
207
+ const groupContext = useSelectGroupContext(LABEL_NAME, __scopeSelect);
208
+ return <ListItem componentName={LABEL_NAME} fontWeight="800" id={groupContext.id} size={context.size} {...labelProps} ref={forwardedRef} />;
209
+ }
210
+ );
211
+ SelectLabel.displayName = LABEL_NAME;
212
+ const SelectSeparator = styled(Separator, {
213
+ name: "SelectSeparator"
263
214
  });
264
- const SEPARATOR_NAME = "SelectSeparator";
265
- const SelectSeparator = Separator;
266
- SelectSeparator.displayName = SEPARATOR_NAME;
267
- const BubbleSelect = React.forwardRef((props, forwardedRef) => {
268
- const { value, ...selectProps } = props;
269
- const ref = React.useRef(null);
270
- const composedRefs = useComposedRefs(forwardedRef, ref);
271
- const prevValue = usePrevious(value);
272
- React.useEffect(() => {
273
- const select = ref.current;
274
- const selectProto = window.HTMLSelectElement.prototype;
275
- const descriptor = Object.getOwnPropertyDescriptor(selectProto, "value");
276
- const setValue = descriptor.set;
277
- if (prevValue !== value && setValue) {
278
- const event = new Event("change", { bubbles: true });
279
- setValue.call(select, value);
280
- select.dispatchEvent(event);
215
+ const SelectSheetController = (props) => {
216
+ const context = useSelectContext("SelectSheetController", props.__scopeSelect);
217
+ const showSheet = useShowSelectSheet(context);
218
+ const breakpointActive = useSelectBreakpointActive(context.sheetBreakpoint);
219
+ const getShowSheet = useGet(showSheet);
220
+ return <SheetController onOpenChange={(val) => {
221
+ if (getShowSheet()) {
222
+ props.onOpenChange(val);
281
223
  }
282
- }, [prevValue, value]);
283
- return null;
284
- return <VisuallyHidden asChild><select {...selectProps} ref={composedRefs} defaultValue={value} /></VisuallyHidden>;
285
- });
224
+ }} open={context.open} hidden={breakpointActive === false}>{props.children}</SheetController>;
225
+ };
226
+ const SHEET_CONTENTS_NAME = "SelectSheetContents";
227
+ const SelectSheetContents = ({ __scopeSelect }) => {
228
+ const context = useSelectContext(SHEET_CONTENTS_NAME, __scopeSelect);
229
+ return <PortalHost name={`${context.scopeKey}SheetContents`} />;
230
+ };
231
+ SelectSheetContents.displayName = SHEET_CONTENTS_NAME;
232
+ const SelectSheetImpl = (props) => {
233
+ return <>{props.children}</>;
234
+ };
235
+ const Select = withStaticProperties(
236
+ (props) => {
237
+ const {
238
+ __scopeSelect,
239
+ children,
240
+ open: openProp,
241
+ defaultOpen,
242
+ onOpenChange,
243
+ value: valueProp,
244
+ defaultValue,
245
+ onValueChange,
246
+ size: sizeProp = "$4",
247
+ sheetBreakpoint = false,
248
+ dir
249
+ } = props;
250
+ const isSheet = useSelectBreakpointActive(sheetBreakpoint);
251
+ const SelectImpl = isSheet ? SelectSheetImpl : SelectInlineImpl;
252
+ const forceUpdate = React.useReducer(() => ({}), {})[1];
253
+ const [selectedItem, setSelectedItem] = React.useState(null);
254
+ const [open, setOpen] = useControllableState({
255
+ prop: openProp,
256
+ defaultProp: defaultOpen || false,
257
+ onChange: onOpenChange,
258
+ strategy: "most-recent-wins"
259
+ });
260
+ const [value, setValue] = useControllableState({
261
+ prop: valueProp,
262
+ defaultProp: defaultValue || "",
263
+ onChange: onValueChange,
264
+ strategy: "most-recent-wins"
265
+ });
266
+ const [activeIndex, setActiveIndex] = React.useState(null);
267
+ const selectedIndexRef = React.useRef(null);
268
+ const activeIndexRef = React.useRef(null);
269
+ const listContentRef = React.useRef([]);
270
+ const [selectedIndex, setSelectedIndex] = React.useState(
271
+ Math.max(0, listContentRef.current.indexOf(value))
272
+ );
273
+ const [valueNode, setValueNode] = React.useState(null);
274
+ const [valueNodeHasChildren, setValueNodeHasChildren] = React.useState(false);
275
+ useIsomorphicLayoutEffect(() => {
276
+ selectedIndexRef.current = selectedIndex;
277
+ activeIndexRef.current = activeIndex;
278
+ });
279
+ const id = useId();
280
+ const scopeKey = __scopeSelect ? Object.keys(__scopeSelect)[0] ?? id : id;
281
+ return <SelectProvider dir={dir} blockSelection={false} size={sizeProp} fallback={false} selectedItem={selectedItem} setSelectedItem={setSelectedItem} forceUpdate={forceUpdate} valueNode={valueNode} onValueNodeChange={setValueNode} onValueNodeHasChildrenChange={setValueNodeHasChildren} valueNodeHasChildren={valueNodeHasChildren} scopeKey={scopeKey} sheetBreakpoint={sheetBreakpoint} scope={__scopeSelect} setValueAtIndex={(index, value2) => {
282
+ listContentRef.current[index] = value2;
283
+ }} activeIndex={activeIndex} onChange={setValue} selectedIndex={selectedIndex} setActiveIndex={setActiveIndex} setOpen={setOpen} setSelectedIndex={setSelectedIndex} value={value} open={open}><SelectSheetController onOpenChange={setOpen} __scopeSelect={__scopeSelect}><SelectImpl activeIndexRef={activeIndexRef} listContentRef={listContentRef} selectedIndexRef={selectedIndexRef} {...props} open={open} value={value}>{children}</SelectImpl></SelectSheetController></SelectProvider>;
284
+ },
285
+ {
286
+ Content: SelectContent,
287
+ Group: SelectGroup,
288
+ Icon: SelectIcon,
289
+ Item: SelectItem,
290
+ ItemIndicator: SelectItemIndicator,
291
+ ItemText: SelectItemText,
292
+ Label: SelectLabel,
293
+ ScrollDownButton: SelectScrollDownButton,
294
+ ScrollUpButton: SelectScrollUpButton,
295
+ Trigger: SelectTrigger,
296
+ Value: SelectValue,
297
+ Viewport: SelectViewport,
298
+ SheetContents: SelectSheetContents,
299
+ Sheet: ControlledSheet
300
+ }
301
+ );
302
+ Select.displayName = SELECT_NAME;
286
303
  export {
287
304
  Select,
288
- SelectContent,
289
- SelectGroup,
305
+ SelectGroupFrame,
290
306
  SelectIcon,
291
307
  SelectItem,
292
- SelectItemIndicator,
293
- SelectItemText,
294
- SelectLabel,
295
- SelectScrollDownButton,
296
- SelectScrollUpButton,
308
+ SelectItemTextFrame,
297
309
  SelectSeparator,
298
- SelectTrigger,
299
- SelectValue,
300
- createSelectScope
310
+ SelectSheetContents,
311
+ SelectTrigger
301
312
  };
313
+ //# sourceMappingURL=Select.js.map