@tamagui/select 1.2.8 → 1.2.10

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 (63) hide show
  1. package/dist/esm/BubbleSelect.mjs +25 -0
  2. package/dist/esm/BubbleSelect.mjs.map +7 -0
  3. package/dist/esm/Select.mjs +463 -0
  4. package/dist/esm/Select.mjs.map +7 -0
  5. package/dist/esm/SelectContent.mjs +31 -0
  6. package/dist/esm/SelectContent.mjs.map +7 -0
  7. package/dist/esm/SelectContent.native.mjs +7 -0
  8. package/dist/esm/SelectContent.native.mjs.map +7 -0
  9. package/dist/esm/SelectImpl.mjs +295 -0
  10. package/dist/esm/SelectImpl.mjs.map +7 -0
  11. package/dist/esm/SelectImpl.native.mjs +11 -0
  12. package/dist/esm/SelectImpl.native.mjs.map +7 -0
  13. package/dist/esm/SelectScrollButton.mjs +140 -0
  14. package/dist/esm/SelectScrollButton.mjs.map +7 -0
  15. package/dist/esm/SelectScrollButton.native.mjs +7 -0
  16. package/dist/esm/SelectScrollButton.native.mjs.map +7 -0
  17. package/dist/esm/SelectViewport.mjs +91 -0
  18. package/dist/esm/SelectViewport.mjs.map +7 -0
  19. package/dist/esm/SelectViewport.native.mjs +19 -0
  20. package/dist/esm/SelectViewport.native.mjs.map +7 -0
  21. package/dist/esm/constants.mjs +17 -0
  22. package/dist/esm/constants.mjs.map +7 -0
  23. package/dist/esm/context.mjs +16 -0
  24. package/dist/esm/context.mjs.map +7 -0
  25. package/dist/esm/index.mjs +3 -0
  26. package/dist/esm/index.mjs.map +7 -0
  27. package/dist/esm/types.mjs +1 -0
  28. package/dist/esm/types.mjs.map +7 -0
  29. package/dist/esm/useSelectBreakpointActive.mjs +18 -0
  30. package/dist/esm/useSelectBreakpointActive.mjs.map +7 -0
  31. package/dist/jsx/BubbleSelect.mjs +25 -0
  32. package/dist/jsx/BubbleSelect.mjs.map +7 -0
  33. package/dist/jsx/Select.mjs +427 -0
  34. package/dist/jsx/Select.mjs.map +7 -0
  35. package/dist/jsx/SelectContent.mjs +30 -0
  36. package/dist/jsx/SelectContent.mjs.map +7 -0
  37. package/dist/jsx/SelectContent.native.mjs +7 -0
  38. package/dist/jsx/SelectContent.native.mjs.map +7 -0
  39. package/dist/jsx/SelectImpl.mjs +287 -0
  40. package/dist/jsx/SelectImpl.mjs.map +7 -0
  41. package/dist/jsx/SelectImpl.native.mjs +10 -0
  42. package/dist/jsx/SelectImpl.native.mjs.map +7 -0
  43. package/dist/jsx/SelectScrollButton.mjs +126 -0
  44. package/dist/jsx/SelectScrollButton.mjs.map +7 -0
  45. package/dist/jsx/SelectScrollButton.native.mjs +7 -0
  46. package/dist/jsx/SelectScrollButton.native.mjs.map +7 -0
  47. package/dist/jsx/SelectViewport.mjs +83 -0
  48. package/dist/jsx/SelectViewport.mjs.map +7 -0
  49. package/dist/jsx/SelectViewport.native.mjs +18 -0
  50. package/dist/jsx/SelectViewport.native.mjs.map +7 -0
  51. package/dist/jsx/constants.mjs +17 -0
  52. package/dist/jsx/constants.mjs.map +7 -0
  53. package/dist/jsx/context.mjs +15 -0
  54. package/dist/jsx/context.mjs.map +7 -0
  55. package/dist/jsx/index.mjs +3 -0
  56. package/dist/jsx/index.mjs.map +7 -0
  57. package/dist/jsx/types.mjs +1 -0
  58. package/dist/jsx/types.mjs.map +7 -0
  59. package/dist/jsx/useSelectBreakpointActive.mjs +18 -0
  60. package/dist/jsx/useSelectBreakpointActive.mjs.map +7 -0
  61. package/package.json +16 -16
  62. package/types/context.d.ts +8 -2
  63. package/types/context.d.ts.map +1 -1
@@ -0,0 +1,30 @@
1
+ import { FloatingOverlay, FloatingPortal } from "@floating-ui/react-dom-interactions";
2
+ import { Theme, useIsTouchDevice, useThemeName } from "@tamagui/core";
3
+ import { Dismissable } from "@tamagui/dismissable";
4
+ import { FocusScope } from "@tamagui/focus-scope";
5
+ import { useSelectContext } from "./context";
6
+ import { useShowSelectSheet } from "./useSelectBreakpointActive";
7
+ const CONTENT_NAME = "SelectContent";
8
+ const SelectContent = ({
9
+ children,
10
+ __scopeSelect,
11
+ zIndex = 1e3,
12
+ ...focusScopeProps
13
+ }) => {
14
+ const context = useSelectContext(CONTENT_NAME, __scopeSelect);
15
+ const themeName = useThemeName();
16
+ const showSheet = useShowSelectSheet(context);
17
+ const contents = <Theme forceClassName name={themeName}>{children}</Theme>;
18
+ const touch = useIsTouchDevice();
19
+ if (showSheet) {
20
+ if (!context.open) {
21
+ return null;
22
+ }
23
+ return <>{contents}</>;
24
+ }
25
+ return <FloatingPortal>{context.open ? <FloatingOverlay style={{ zIndex }} lockScroll={!touch}><FocusScope loop trapped {...focusScopeProps}><Dismissable>{contents}</Dismissable></FocusScope></FloatingOverlay> : <div style={{ display: "none" }}>{contents}</div>}</FloatingPortal>;
26
+ };
27
+ export {
28
+ SelectContent
29
+ };
30
+ //# sourceMappingURL=SelectContent.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/SelectContent.tsx"],
4
+ "sourcesContent": ["import { FloatingOverlay, FloatingPortal } from '@floating-ui/react-dom-interactions'\nimport { Theme, useIsTouchDevice, useThemeName } from '@tamagui/core'\nimport { Dismissable } from '@tamagui/dismissable'\nimport { FocusScope, FocusScopeProps } from '@tamagui/focus-scope'\n\nimport { useSelectContext } from './context'\nimport { SelectContentProps } from './types'\nimport { useShowSelectSheet } from './useSelectBreakpointActive'\n\n/* -------------------------------------------------------------------------------------------------\n * SelectContent\n * -----------------------------------------------------------------------------------------------*/\n\nconst CONTENT_NAME = 'SelectContent'\n\nexport const SelectContent = ({\n children,\n __scopeSelect,\n zIndex = 1000,\n ...focusScopeProps\n}: SelectContentProps & FocusScopeProps) => {\n const context = useSelectContext(CONTENT_NAME, __scopeSelect)\n const themeName = useThemeName()\n const showSheet = useShowSelectSheet(context)\n const contents = (\n <Theme forceClassName name={themeName}>\n {children}\n </Theme>\n )\n const touch = useIsTouchDevice()\n\n if (showSheet) {\n if (!context.open) {\n return null\n }\n return <>{contents}</>\n }\n\n return (\n <FloatingPortal>\n {context.open ? (\n <FloatingOverlay style={{ zIndex }} lockScroll={!touch}>\n <FocusScope loop trapped {...focusScopeProps}>\n <Dismissable>{contents}</Dismissable>\n </FocusScope>\n </FloatingOverlay>\n ) : (\n <div style={{ display: 'none' }}>{contents}</div>\n )}\n </FloatingPortal>\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB,sBAAsB;AAChD,SAAS,OAAO,kBAAkB,oBAAoB;AACtD,SAAS,mBAAmB;AAC5B,SAAS,kBAAmC;AAE5C,SAAS,wBAAwB;AAEjC,SAAS,0BAA0B;AAMnC,MAAM,eAAe;AAEd,MAAM,gBAAgB,CAAC;AAAA,EAC5B;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,GAAG;AACL,MAA4C;AAC1C,QAAM,UAAU,iBAAiB,cAAc,aAAa;AAC5D,QAAM,YAAY,aAAa;AAC/B,QAAM,YAAY,mBAAmB,OAAO;AAC5C,QAAM,WACJ,CAAC,MAAM,eAAe,MAAM,YACzB,SACH,EAFC;AAIH,QAAM,QAAQ,iBAAiB;AAE/B,MAAI,WAAW;AACb,QAAI,CAAC,QAAQ,MAAM;AACjB,aAAO;AAAA,IACT;AACA,WAAO,GAAG,SAAS;AAAA,EACrB;AAEA,SACE,CAAC,gBACE,QAAQ,OACP,CAAC,gBAAgB,OAAO,EAAE,OAAO,GAAG,YAAY,CAAC,OAC/C,CAAC,WAAW,KAAK,YAAY,iBAC3B,CAAC,aAAa,SAAS,EAAtB,YACH,EAFC,WAGH,EAJC,mBAMD,CAAC,IAAI,OAAO,EAAE,SAAS,OAAO,IAAI,SAAS,EAA1C,KAEL,EAVC;AAYL;",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ const SelectContent = ({ children }) => {
2
+ return children;
3
+ };
4
+ export {
5
+ SelectContent
6
+ };
7
+ //# sourceMappingURL=SelectContent.native.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/SelectContent.native.tsx"],
4
+ "sourcesContent": ["import { SelectContentProps } from './types'\n\nexport const SelectContent = ({ children }: SelectContentProps) => {\n return children\n}\n"],
5
+ "mappings": "AAEO,MAAM,gBAAgB,CAAC,EAAE,SAAS,MAA0B;AACjE,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,287 @@
1
+ import {
2
+ autoUpdate,
3
+ flip,
4
+ inner,
5
+ offset,
6
+ shift,
7
+ size,
8
+ useClick,
9
+ useDismiss,
10
+ useFloating,
11
+ useInnerOffset,
12
+ useInteractions,
13
+ useListNavigation,
14
+ useRole,
15
+ useTypeahead
16
+ } from "@floating-ui/react-dom-interactions";
17
+ import {
18
+ isClient,
19
+ isWeb,
20
+ useIsTouchDevice,
21
+ useIsomorphicLayoutEffect
22
+ } from "@tamagui/core";
23
+ import * as React from "react";
24
+ import { flushSync } from "react-dom";
25
+ import { SCROLL_ARROW_THRESHOLD, WINDOW_PADDING } from "./constants";
26
+ import { SelectProvider, useSelectContext } from "./context";
27
+ const SelectInlineImpl = (props) => {
28
+ const {
29
+ __scopeSelect,
30
+ children,
31
+ open = false,
32
+ selectedIndexRef,
33
+ listContentRef
34
+ } = props;
35
+ const selectContext = useSelectContext("SelectSheetImpl", __scopeSelect);
36
+ const {
37
+ setActiveIndex,
38
+ setOpen,
39
+ setSelectedIndex,
40
+ selectedIndex,
41
+ activeIndex,
42
+ forceUpdate
43
+ } = selectContext;
44
+ const [scrollTop, setScrollTop] = React.useState(0);
45
+ const touch = useIsTouchDevice();
46
+ const listItemsRef = React.useRef([]);
47
+ const overflowRef = React.useRef(null);
48
+ const upArrowRef = React.useRef(null);
49
+ const downArrowRef = React.useRef(null);
50
+ const allowSelectRef = React.useRef(false);
51
+ const allowMouseUpRef = React.useRef(true);
52
+ const selectTimeoutRef = React.useRef();
53
+ const state = React.useRef({
54
+ isMouseOutside: false
55
+ });
56
+ const [controlledScrolling, setControlledScrolling] = React.useState(false);
57
+ const [fallback, setFallback] = React.useState(false);
58
+ const [innerOffset, setInnerOffset] = React.useState(0);
59
+ const [blockSelection, setBlockSelection] = React.useState(false);
60
+ const floatingStyle = React.useRef({});
61
+ React.useEffect(() => {
62
+ const frame = requestAnimationFrame(() => {
63
+ if (!open) {
64
+ setScrollTop(0);
65
+ setFallback(false);
66
+ setActiveIndex(null);
67
+ setControlledScrolling(false);
68
+ }
69
+ });
70
+ return () => {
71
+ cancelAnimationFrame(frame);
72
+ };
73
+ }, [open, setActiveIndex]);
74
+ if (isWeb && isClient) {
75
+ React.useEffect(() => {
76
+ if (!open)
77
+ return;
78
+ const mouseUp = (e) => {
79
+ if (state.current.isMouseOutside) {
80
+ setOpen(false);
81
+ }
82
+ };
83
+ document.addEventListener("mouseup", mouseUp);
84
+ return () => {
85
+ document.removeEventListener("mouseup", mouseUp);
86
+ };
87
+ }, [open]);
88
+ }
89
+ const updateFloatingSize = size({
90
+ apply({
91
+ availableHeight,
92
+ rects: {
93
+ reference: { width }
94
+ }
95
+ }) {
96
+ floatingStyle.current = {
97
+ width,
98
+ maxHeight: availableHeight
99
+ };
100
+ },
101
+ padding: WINDOW_PADDING
102
+ });
103
+ const { x, y, reference, floating, strategy, context, refs } = useFloating({
104
+ open,
105
+ onOpenChange: setOpen,
106
+ whileElementsMounted: autoUpdate,
107
+ placement: "bottom-start",
108
+ middleware: fallback ? [
109
+ offset(5),
110
+ ...[
111
+ touch ? shift({ crossAxis: true, padding: WINDOW_PADDING }) : flip({ padding: WINDOW_PADDING })
112
+ ],
113
+ updateFloatingSize
114
+ ] : [
115
+ inner({
116
+ listRef: listItemsRef,
117
+ overflowRef,
118
+ index: selectedIndex,
119
+ offset: innerOffset,
120
+ onFallbackChange: setFallback,
121
+ padding: 10,
122
+ minItemsVisible: touch ? 10 : 4,
123
+ referenceOverflowThreshold: 20
124
+ }),
125
+ updateFloatingSize
126
+ ]
127
+ });
128
+ const floatingRef = refs.floating;
129
+ const showUpArrow = open && scrollTop > SCROLL_ARROW_THRESHOLD;
130
+ const showDownArrow = open && floatingRef.current && scrollTop < floatingRef.current.scrollHeight - floatingRef.current.clientHeight - SCROLL_ARROW_THRESHOLD;
131
+ const interactions = useInteractions([
132
+ useClick(context, { pointerDown: true }),
133
+ useDismiss(context, { outsidePointerDown: true }),
134
+ useRole(context, { role: "listbox" }),
135
+ useInnerOffset(context, {
136
+ enabled: !fallback,
137
+ onChange: setInnerOffset,
138
+ overflowRef
139
+ }),
140
+ useListNavigation(context, {
141
+ listRef: listItemsRef,
142
+ activeIndex,
143
+ selectedIndex,
144
+ onNavigate: setActiveIndex
145
+ }),
146
+ useTypeahead(context, {
147
+ listRef: listContentRef,
148
+ onMatch: open ? setActiveIndex : setSelectedIndex,
149
+ selectedIndex,
150
+ activeIndex
151
+ })
152
+ ]);
153
+ const interactionsContext = React.useMemo(() => {
154
+ return {
155
+ ...interactions,
156
+ getReferenceProps() {
157
+ return interactions.getReferenceProps({
158
+ ref: reference,
159
+ className: "SelectTrigger",
160
+ onKeyDown(event) {
161
+ if (event.key === "Enter" || event.key === " " && !context.dataRef.current.typing) {
162
+ event.preventDefault();
163
+ setOpen(true);
164
+ }
165
+ }
166
+ });
167
+ },
168
+ getFloatingProps(props2) {
169
+ return interactions.getFloatingProps({
170
+ ref: floating,
171
+ className: "Select",
172
+ ...props2,
173
+ style: {
174
+ position: strategy,
175
+ top: y ?? "",
176
+ left: x ?? "",
177
+ outline: 0,
178
+ scrollbarWidth: "none",
179
+ ...floatingStyle.current,
180
+ ...props2?.style
181
+ },
182
+ onPointerEnter() {
183
+ setControlledScrolling(false);
184
+ state.current.isMouseOutside = false;
185
+ },
186
+ onPointerLeave() {
187
+ state.current.isMouseOutside = true;
188
+ },
189
+ onPointerMove() {
190
+ state.current.isMouseOutside = false;
191
+ setControlledScrolling(false);
192
+ },
193
+ onKeyDown() {
194
+ setControlledScrolling(true);
195
+ },
196
+ onContextMenu(e) {
197
+ e.preventDefault();
198
+ },
199
+ onScroll(event) {
200
+ flushSync(() => setScrollTop(event.currentTarget.scrollTop));
201
+ }
202
+ });
203
+ }
204
+ };
205
+ }, [floating, y, x, interactions]);
206
+ useIsomorphicLayoutEffect(() => {
207
+ if (open) {
208
+ selectTimeoutRef.current = setTimeout(() => {
209
+ allowSelectRef.current = true;
210
+ }, 300);
211
+ return () => {
212
+ clearTimeout(selectTimeoutRef.current);
213
+ };
214
+ } else {
215
+ allowSelectRef.current = false;
216
+ allowMouseUpRef.current = true;
217
+ setInnerOffset(0);
218
+ setFallback(false);
219
+ setBlockSelection(false);
220
+ }
221
+ }, [open]);
222
+ useIsomorphicLayoutEffect(() => {
223
+ function onPointerDown(e) {
224
+ const target = e.target;
225
+ if (!(refs.floating.current?.contains(target) || upArrowRef.current?.contains(target) || downArrowRef.current?.contains(target))) {
226
+ setOpen(false);
227
+ setControlledScrolling(false);
228
+ }
229
+ }
230
+ if (open) {
231
+ document.addEventListener("pointerdown", onPointerDown);
232
+ return () => {
233
+ document.removeEventListener("pointerdown", onPointerDown);
234
+ };
235
+ }
236
+ }, [open, refs, setOpen]);
237
+ useIsomorphicLayoutEffect(() => {
238
+ if (open && controlledScrolling) {
239
+ if (activeIndex != null) {
240
+ listItemsRef.current[activeIndex]?.scrollIntoView({ block: "nearest" });
241
+ }
242
+ }
243
+ setScrollTop(refs.floating.current?.scrollTop ?? 0);
244
+ }, [open, refs, controlledScrolling, activeIndex]);
245
+ useIsomorphicLayoutEffect(() => {
246
+ if (open && fallback) {
247
+ if (selectedIndex != null) {
248
+ listItemsRef.current[selectedIndex]?.scrollIntoView({ block: "nearest" });
249
+ }
250
+ }
251
+ }, [open, fallback, selectedIndex]);
252
+ useIsomorphicLayoutEffect(() => {
253
+ if (refs.floating.current && fallback) {
254
+ refs.floating.current.style.maxHeight = "";
255
+ }
256
+ }, [refs, fallback]);
257
+ return <SelectProvider
258
+ scope={__scopeSelect}
259
+ {...selectContext}
260
+ setScrollTop={setScrollTop}
261
+ setInnerOffset={setInnerOffset}
262
+ floatingRef={floatingRef}
263
+ setValueAtIndex={(index, value) => {
264
+ listContentRef.current[index] = value;
265
+ }}
266
+ fallback={fallback}
267
+ interactions={interactionsContext}
268
+ floatingContext={context}
269
+ activeIndex={activeIndex}
270
+ canScrollDown={!!showDownArrow}
271
+ canScrollUp={!!showUpArrow}
272
+ controlledScrolling={controlledScrolling}
273
+ dataRef={context.dataRef}
274
+ listRef={listItemsRef}
275
+ blockSelection={blockSelection}
276
+ allowMouseUpRef={allowMouseUpRef}
277
+ upArrowRef={upArrowRef}
278
+ downArrowRef={downArrowRef}
279
+ selectTimeoutRef={selectTimeoutRef}
280
+ allowSelectRef={allowSelectRef}
281
+ >{children}</SelectProvider>;
282
+ };
283
+ const userAgent = typeof navigator !== "undefined" && navigator.userAgent || "";
284
+ export {
285
+ SelectInlineImpl
286
+ };
287
+ //# sourceMappingURL=SelectImpl.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/SelectImpl.tsx"],
4
+ "sourcesContent": ["import {\n SideObject,\n autoUpdate,\n flip,\n inner,\n offset,\n shift,\n size,\n useClick,\n useDismiss,\n useFloating,\n useInnerOffset,\n useInteractions,\n useListNavigation,\n useRole,\n useTypeahead,\n} from '@floating-ui/react-dom-interactions'\nimport {\n isClient,\n isWeb,\n useIsTouchDevice,\n useIsomorphicLayoutEffect,\n} from '@tamagui/core'\nimport * as React from 'react'\nimport { flushSync } from 'react-dom'\n\nimport { SCROLL_ARROW_THRESHOLD, WINDOW_PADDING } from './constants'\nimport { SelectProvider, useSelectContext } from './context'\nimport { SelectImplProps } from './types'\n\n// TODO use id for focusing from label\nexport const SelectInlineImpl = (props: SelectImplProps) => {\n const {\n __scopeSelect,\n children,\n open = false,\n selectedIndexRef,\n listContentRef,\n } = props\n\n const selectContext = useSelectContext('SelectSheetImpl', __scopeSelect)\n const {\n setActiveIndex,\n setOpen,\n setSelectedIndex,\n selectedIndex,\n activeIndex,\n forceUpdate,\n } = selectContext\n const [scrollTop, setScrollTop] = React.useState(0)\n const touch = useIsTouchDevice()\n\n const listItemsRef = React.useRef<Array<HTMLElement | null>>([])\n const overflowRef = React.useRef<null | SideObject>(null)\n const upArrowRef = React.useRef<HTMLDivElement | null>(null)\n const downArrowRef = React.useRef<HTMLDivElement | null>(null)\n const allowSelectRef = React.useRef(false)\n const allowMouseUpRef = React.useRef(true)\n const selectTimeoutRef = React.useRef<any>()\n const state = React.useRef({\n isMouseOutside: false,\n })\n\n const [controlledScrolling, setControlledScrolling] = React.useState(false)\n const [fallback, setFallback] = React.useState(false)\n const [innerOffset, setInnerOffset] = React.useState(0)\n const [blockSelection, setBlockSelection] = React.useState(false)\n const floatingStyle = React.useRef({})\n\n // Wait for scroll position to settle before showing arrows to prevent\n // interference with pointer events.\n React.useEffect(() => {\n const frame = requestAnimationFrame(() => {\n if (!open) {\n setScrollTop(0)\n setFallback(false)\n setActiveIndex(null)\n setControlledScrolling(false)\n }\n })\n return () => {\n cancelAnimationFrame(frame)\n }\n }, [open, setActiveIndex])\n\n // close when mouseup outside select\n if (isWeb && isClient) {\n React.useEffect(() => {\n if (!open) return\n const mouseUp = (e: MouseEvent) => {\n if (state.current.isMouseOutside) {\n setOpen(false)\n }\n }\n document.addEventListener('mouseup', mouseUp)\n return () => {\n document.removeEventListener('mouseup', mouseUp)\n }\n }, [open])\n }\n\n const updateFloatingSize = size({\n apply({\n availableHeight,\n rects: {\n reference: { width },\n },\n }) {\n floatingStyle.current = {\n width: width,\n maxHeight: availableHeight,\n }\n },\n padding: WINDOW_PADDING,\n })\n\n const { x, y, reference, floating, strategy, context, refs } = useFloating({\n open,\n onOpenChange: setOpen,\n whileElementsMounted: autoUpdate,\n placement: 'bottom-start',\n middleware: fallback\n ? [\n offset(5),\n ...[\n touch\n ? shift({ crossAxis: true, padding: WINDOW_PADDING })\n : flip({ padding: WINDOW_PADDING }),\n ],\n updateFloatingSize,\n ]\n : [\n inner({\n listRef: listItemsRef,\n overflowRef,\n index: selectedIndex,\n offset: innerOffset,\n onFallbackChange: setFallback,\n padding: 10,\n minItemsVisible: touch ? 10 : 4,\n referenceOverflowThreshold: 20,\n }),\n updateFloatingSize,\n ],\n })\n\n const floatingRef = refs.floating\n\n const showUpArrow = open && scrollTop > SCROLL_ARROW_THRESHOLD\n const showDownArrow =\n open &&\n floatingRef.current &&\n scrollTop <\n floatingRef.current.scrollHeight -\n floatingRef.current.clientHeight -\n SCROLL_ARROW_THRESHOLD\n\n const interactions = useInteractions([\n useClick(context, { pointerDown: true }),\n useDismiss(context, { outsidePointerDown: true }),\n useRole(context, { role: 'listbox' }),\n useInnerOffset(context, {\n enabled: !fallback,\n onChange: setInnerOffset,\n overflowRef,\n }),\n useListNavigation(context, {\n listRef: listItemsRef,\n activeIndex,\n selectedIndex,\n onNavigate: setActiveIndex,\n }),\n useTypeahead(context, {\n listRef: listContentRef,\n onMatch: open ? setActiveIndex : setSelectedIndex,\n selectedIndex,\n activeIndex,\n }),\n ])\n\n const interactionsContext = React.useMemo(() => {\n return {\n ...interactions,\n getReferenceProps() {\n return interactions.getReferenceProps({\n ref: reference,\n className: 'SelectTrigger',\n onKeyDown(event) {\n if (\n event.key === 'Enter' ||\n (event.key === ' ' && !context.dataRef.current.typing)\n ) {\n event.preventDefault()\n setOpen(true)\n }\n },\n })\n },\n getFloatingProps(props) {\n return interactions.getFloatingProps({\n ref: floating,\n className: 'Select',\n ...props,\n style: {\n position: strategy,\n top: y ?? '',\n left: x ?? '',\n outline: 0,\n scrollbarWidth: 'none',\n ...floatingStyle.current,\n ...props?.style,\n },\n onPointerEnter() {\n setControlledScrolling(false)\n state.current.isMouseOutside = false\n },\n onPointerLeave() {\n state.current.isMouseOutside = true\n },\n onPointerMove() {\n state.current.isMouseOutside = false\n setControlledScrolling(false)\n },\n onKeyDown() {\n setControlledScrolling(true)\n },\n onContextMenu(e) {\n e.preventDefault()\n },\n onScroll(event) {\n // In React 18, the ScrollArrows need to synchronously know this value to prevent\n // painting at the wrong time.\n flushSync(() => setScrollTop(event.currentTarget.scrollTop))\n },\n })\n },\n }\n }, [floating, y, x, interactions])\n\n // effects\n\n useIsomorphicLayoutEffect(() => {\n if (open) {\n selectTimeoutRef.current = setTimeout(() => {\n allowSelectRef.current = true\n }, 300)\n\n return () => {\n clearTimeout(selectTimeoutRef.current)\n }\n } else {\n allowSelectRef.current = false\n allowMouseUpRef.current = true\n setInnerOffset(0)\n setFallback(false)\n setBlockSelection(false)\n }\n }, [open])\n\n // Replacement for `useDismiss` as the arrows are outside of the floating\n // element DOM tree.\n useIsomorphicLayoutEffect(() => {\n function onPointerDown(e: PointerEvent) {\n const target = e.target as Node\n if (\n !(\n refs.floating.current?.contains(target) ||\n upArrowRef.current?.contains(target) ||\n downArrowRef.current?.contains(target)\n )\n ) {\n setOpen(false)\n setControlledScrolling(false)\n }\n }\n\n if (open) {\n document.addEventListener('pointerdown', onPointerDown)\n return () => {\n document.removeEventListener('pointerdown', onPointerDown)\n }\n }\n }, [open, refs, setOpen])\n\n // Scroll the `activeIndex` item into view only in \"controlledScrolling\"\n // (keyboard nav) mode.\n useIsomorphicLayoutEffect(() => {\n if (open && controlledScrolling) {\n if (activeIndex != null) {\n listItemsRef.current[activeIndex]?.scrollIntoView({ block: 'nearest' })\n }\n }\n\n setScrollTop(refs.floating.current?.scrollTop ?? 0)\n }, [open, refs, controlledScrolling, activeIndex])\n\n // Scroll the `selectedIndex` into view upon opening the floating element.\n useIsomorphicLayoutEffect(() => {\n if (open && fallback) {\n if (selectedIndex != null) {\n listItemsRef.current[selectedIndex]?.scrollIntoView({ block: 'nearest' })\n }\n }\n }, [open, fallback, selectedIndex])\n\n // Unset the height limiting for fallback mode. This gets executed prior to\n // the positioning call.\n useIsomorphicLayoutEffect(() => {\n if (refs.floating.current && fallback) {\n refs.floating.current.style.maxHeight = ''\n }\n }, [refs, fallback])\n\n // We set this to true by default so that events bubble to forms without JS (SSR)\n // const isFormControl = trigger ? Boolean(trigger.closest('form')) : true\n // const [bubbleSelect, setBubbleSelect] = React.useState<HTMLSelectElement | null>(null)\n // const triggerPointerDownPosRef = React.useRef<{ x: number; y: number } | null>(null)\n\n return (\n <SelectProvider\n scope={__scopeSelect}\n {...(selectContext as Required<typeof selectContext>)}\n setScrollTop={setScrollTop}\n setInnerOffset={setInnerOffset}\n floatingRef={floatingRef}\n setValueAtIndex={(index, value) => {\n listContentRef.current[index] = value\n }}\n fallback={fallback}\n interactions={interactionsContext}\n floatingContext={context}\n activeIndex={activeIndex}\n canScrollDown={!!showDownArrow}\n canScrollUp={!!showUpArrow}\n controlledScrolling={controlledScrolling}\n dataRef={context.dataRef}\n listRef={listItemsRef}\n blockSelection={blockSelection}\n allowMouseUpRef={allowMouseUpRef}\n upArrowRef={upArrowRef}\n downArrowRef={downArrowRef}\n selectTimeoutRef={selectTimeoutRef}\n allowSelectRef={allowSelectRef}\n >\n {children}\n {/* {isFormControl ? (\n <BubbleSelect\n ref={setBubbleSelect}\n aria-hidden\n tabIndex={-1}\n name={name}\n autoComplete={autoComplete}\n value={value}\n // enable form autofill\n onChange={(event) => setValue(event.target.value)}\n />\n ) : null} */}\n </SelectProvider>\n )\n}\n\n// Cross browser fixes for pinch-zooming/backdrop-filter \uD83D\uDE44\nconst userAgent = (typeof navigator !== 'undefined' && navigator.userAgent) || ''\n"],
5
+ "mappings": "AAAA;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,YAAY,WAAW;AACvB,SAAS,iBAAiB;AAE1B,SAAS,wBAAwB,sBAAsB;AACvD,SAAS,gBAAgB,wBAAwB;AAI1C,MAAM,mBAAmB,CAAC,UAA2B;AAC1D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,gBAAgB,iBAAiB,mBAAmB,aAAa;AACvE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,CAAC;AAClD,QAAM,QAAQ,iBAAiB;AAE/B,QAAM,eAAe,MAAM,OAAkC,CAAC,CAAC;AAC/D,QAAM,cAAc,MAAM,OAA0B,IAAI;AACxD,QAAM,aAAa,MAAM,OAA8B,IAAI;AAC3D,QAAM,eAAe,MAAM,OAA8B,IAAI;AAC7D,QAAM,iBAAiB,MAAM,OAAO,KAAK;AACzC,QAAM,kBAAkB,MAAM,OAAO,IAAI;AACzC,QAAM,mBAAmB,MAAM,OAAY;AAC3C,QAAM,QAAQ,MAAM,OAAO;AAAA,IACzB,gBAAgB;AAAA,EAClB,CAAC;AAED,QAAM,CAAC,qBAAqB,sBAAsB,IAAI,MAAM,SAAS,KAAK;AAC1E,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAS,KAAK;AACpD,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAS,CAAC;AACtD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAAS,KAAK;AAChE,QAAM,gBAAgB,MAAM,OAAO,CAAC,CAAC;AAIrC,QAAM,UAAU,MAAM;AACpB,UAAM,QAAQ,sBAAsB,MAAM;AACxC,UAAI,CAAC,MAAM;AACT,qBAAa,CAAC;AACd,oBAAY,KAAK;AACjB,uBAAe,IAAI;AACnB,+BAAuB,KAAK;AAAA,MAC9B;AAAA,IACF,CAAC;AACD,WAAO,MAAM;AACX,2BAAqB,KAAK;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,MAAM,cAAc,CAAC;AAGzB,MAAI,SAAS,UAAU;AACrB,UAAM,UAAU,MAAM;AACpB,UAAI,CAAC;AAAM;AACX,YAAM,UAAU,CAAC,MAAkB;AACjC,YAAI,MAAM,QAAQ,gBAAgB;AAChC,kBAAQ,KAAK;AAAA,QACf;AAAA,MACF;AACA,eAAS,iBAAiB,WAAW,OAAO;AAC5C,aAAO,MAAM;AACX,iBAAS,oBAAoB,WAAW,OAAO;AAAA,MACjD;AAAA,IACF,GAAG,CAAC,IAAI,CAAC;AAAA,EACX;AAEA,QAAM,qBAAqB,KAAK;AAAA,IAC9B,MAAM;AAAA,MACJ;AAAA,MACA,OAAO;AAAA,QACL,WAAW,EAAE,MAAM;AAAA,MACrB;AAAA,IACF,GAAG;AACD,oBAAc,UAAU;AAAA,QACtB;AAAA,QACA,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AAED,QAAM,EAAE,GAAG,GAAG,WAAW,UAAU,UAAU,SAAS,KAAK,IAAI,YAAY;AAAA,IACzE;AAAA,IACA,cAAc;AAAA,IACd,sBAAsB;AAAA,IACtB,WAAW;AAAA,IACX,YAAY,WACR;AAAA,MACE,OAAO,CAAC;AAAA,MACR,GAAG;AAAA,QACD,QACI,MAAM,EAAE,WAAW,MAAM,SAAS,eAAe,CAAC,IAClD,KAAK,EAAE,SAAS,eAAe,CAAC;AAAA,MACtC;AAAA,MACA;AAAA,IACF,IACA;AAAA,MACE,MAAM;AAAA,QACJ,SAAS;AAAA,QACT;AAAA,QACA,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,kBAAkB;AAAA,QAClB,SAAS;AAAA,QACT,iBAAiB,QAAQ,KAAK;AAAA,QAC9B,4BAA4B;AAAA,MAC9B,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACN,CAAC;AAED,QAAM,cAAc,KAAK;AAEzB,QAAM,cAAc,QAAQ,YAAY;AACxC,QAAM,gBACJ,QACA,YAAY,WACZ,YACE,YAAY,QAAQ,eAClB,YAAY,QAAQ,eACpB;AAEN,QAAM,eAAe,gBAAgB;AAAA,IACnC,SAAS,SAAS,EAAE,aAAa,KAAK,CAAC;AAAA,IACvC,WAAW,SAAS,EAAE,oBAAoB,KAAK,CAAC;AAAA,IAChD,QAAQ,SAAS,EAAE,MAAM,UAAU,CAAC;AAAA,IACpC,eAAe,SAAS;AAAA,MACtB,SAAS,CAAC;AAAA,MACV,UAAU;AAAA,MACV;AAAA,IACF,CAAC;AAAA,IACD,kBAAkB,SAAS;AAAA,MACzB,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,YAAY;AAAA,IACd,CAAC;AAAA,IACD,aAAa,SAAS;AAAA,MACpB,SAAS;AAAA,MACT,SAAS,OAAO,iBAAiB;AAAA,MACjC;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,QAAM,sBAAsB,MAAM,QAAQ,MAAM;AAC9C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,oBAAoB;AAClB,eAAO,aAAa,kBAAkB;AAAA,UACpC,KAAK;AAAA,UACL,WAAW;AAAA,UACX,UAAU,OAAO;AACf,gBACE,MAAM,QAAQ,WACb,MAAM,QAAQ,OAAO,CAAC,QAAQ,QAAQ,QAAQ,QAC/C;AACA,oBAAM,eAAe;AACrB,sBAAQ,IAAI;AAAA,YACd;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,MACA,iBAAiBA,QAAO;AACtB,eAAO,aAAa,iBAAiB;AAAA,UACnC,KAAK;AAAA,UACL,WAAW;AAAA,UACX,GAAGA;AAAA,UACH,OAAO;AAAA,YACL,UAAU;AAAA,YACV,KAAK,KAAK;AAAA,YACV,MAAM,KAAK;AAAA,YACX,SAAS;AAAA,YACT,gBAAgB;AAAA,YAChB,GAAG,cAAc;AAAA,YACjB,GAAGA,QAAO;AAAA,UACZ;AAAA,UACA,iBAAiB;AACf,mCAAuB,KAAK;AAC5B,kBAAM,QAAQ,iBAAiB;AAAA,UACjC;AAAA,UACA,iBAAiB;AACf,kBAAM,QAAQ,iBAAiB;AAAA,UACjC;AAAA,UACA,gBAAgB;AACd,kBAAM,QAAQ,iBAAiB;AAC/B,mCAAuB,KAAK;AAAA,UAC9B;AAAA,UACA,YAAY;AACV,mCAAuB,IAAI;AAAA,UAC7B;AAAA,UACA,cAAc,GAAG;AACf,cAAE,eAAe;AAAA,UACnB;AAAA,UACA,SAAS,OAAO;AAGd,sBAAU,MAAM,aAAa,MAAM,cAAc,SAAS,CAAC;AAAA,UAC7D;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,GAAG,CAAC,UAAU,GAAG,GAAG,YAAY,CAAC;AAIjC,4BAA0B,MAAM;AAC9B,QAAI,MAAM;AACR,uBAAiB,UAAU,WAAW,MAAM;AAC1C,uBAAe,UAAU;AAAA,MAC3B,GAAG,GAAG;AAEN,aAAO,MAAM;AACX,qBAAa,iBAAiB,OAAO;AAAA,MACvC;AAAA,IACF,OAAO;AACL,qBAAe,UAAU;AACzB,sBAAgB,UAAU;AAC1B,qBAAe,CAAC;AAChB,kBAAY,KAAK;AACjB,wBAAkB,KAAK;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAIT,4BAA0B,MAAM;AAC9B,aAAS,cAAc,GAAiB;AACtC,YAAM,SAAS,EAAE;AACjB,UACE,EACE,KAAK,SAAS,SAAS,SAAS,MAAM,KACtC,WAAW,SAAS,SAAS,MAAM,KACnC,aAAa,SAAS,SAAS,MAAM,IAEvC;AACA,gBAAQ,KAAK;AACb,+BAAuB,KAAK;AAAA,MAC9B;AAAA,IACF;AAEA,QAAI,MAAM;AACR,eAAS,iBAAiB,eAAe,aAAa;AACtD,aAAO,MAAM;AACX,iBAAS,oBAAoB,eAAe,aAAa;AAAA,MAC3D;AAAA,IACF;AAAA,EACF,GAAG,CAAC,MAAM,MAAM,OAAO,CAAC;AAIxB,4BAA0B,MAAM;AAC9B,QAAI,QAAQ,qBAAqB;AAC/B,UAAI,eAAe,MAAM;AACvB,qBAAa,QAAQ,WAAW,GAAG,eAAe,EAAE,OAAO,UAAU,CAAC;AAAA,MACxE;AAAA,IACF;AAEA,iBAAa,KAAK,SAAS,SAAS,aAAa,CAAC;AAAA,EACpD,GAAG,CAAC,MAAM,MAAM,qBAAqB,WAAW,CAAC;AAGjD,4BAA0B,MAAM;AAC9B,QAAI,QAAQ,UAAU;AACpB,UAAI,iBAAiB,MAAM;AACzB,qBAAa,QAAQ,aAAa,GAAG,eAAe,EAAE,OAAO,UAAU,CAAC;AAAA,MAC1E;AAAA,IACF;AAAA,EACF,GAAG,CAAC,MAAM,UAAU,aAAa,CAAC;AAIlC,4BAA0B,MAAM;AAC9B,QAAI,KAAK,SAAS,WAAW,UAAU;AACrC,WAAK,SAAS,QAAQ,MAAM,YAAY;AAAA,IAC1C;AAAA,EACF,GAAG,CAAC,MAAM,QAAQ,CAAC;AAOnB,SACE,CAAC;AAAA,IACC,OAAO;AAAA,QACF;AAAA,IACL,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,iBAAiB,CAAC,OAAO,UAAU;AACjC,qBAAe,QAAQ,KAAK,IAAI;AAAA,IAClC;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,eAAe,CAAC,CAAC;AAAA,IACjB,aAAa,CAAC,CAAC;AAAA,IACf,qBAAqB;AAAA,IACrB,SAAS,QAAQ;AAAA,IACjB,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAEf,SAaH,EAtCC;AAwCL;AAGA,MAAM,YAAa,OAAO,cAAc,eAAe,UAAU,aAAc;",
6
+ "names": ["props"]
7
+ }
@@ -0,0 +1,10 @@
1
+ const SelectInlineImpl = (props) => {
2
+ if (process.env.NODE_ENV === "development") {
3
+ console.warn("Sheet not implemented inline on native");
4
+ }
5
+ return <>{props.children}</>;
6
+ };
7
+ export {
8
+ SelectInlineImpl
9
+ };
10
+ //# sourceMappingURL=SelectImpl.native.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/SelectImpl.native.tsx"],
4
+ "sourcesContent": ["import { SelectImplProps } from './types'\n\n/**\n * TODO can just make it a sheet for native\n * later on can have `native` prop\n */\n\nexport const SelectInlineImpl = (props: SelectImplProps) => {\n if (process.env.NODE_ENV === 'development') {\n // eslint-disable-next-line no-console\n console.warn('Sheet not implemented inline on native')\n }\n return <>{props.children}</>\n}\n"],
5
+ "mappings": "AAOO,MAAM,mBAAmB,CAAC,UAA2B;AAC1D,MAAI,QAAQ,IAAI,aAAa,eAAe;AAE1C,YAAQ,KAAK,wCAAwC;AAAA,EACvD;AACA,SAAO,GAAG,MAAM,SAAS;AAC3B;",
6
+ "names": []
7
+ }
@@ -0,0 +1,126 @@
1
+ import { autoUpdate, offset, useFloating } from "@floating-ui/react-dom-interactions";
2
+ import { useComposedRefs } from "@tamagui/compose-refs";
3
+ import { useIsomorphicLayoutEffect } from "@tamagui/core";
4
+ import { YStack } from "@tamagui/stacks";
5
+ import * as React from "react";
6
+ import { flushSync } from "react-dom";
7
+ import { useSelectContext } from "./context";
8
+ const SCROLL_UP_BUTTON_NAME = "SelectScrollUpButton";
9
+ const SelectScrollUpButton = React.forwardRef((props, forwardedRef) => {
10
+ return <SelectScrollButtonImpl
11
+ componentName={SCROLL_UP_BUTTON_NAME}
12
+ {...props}
13
+ dir="up"
14
+ ref={forwardedRef}
15
+ />;
16
+ });
17
+ SelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME;
18
+ const SCROLL_DOWN_BUTTON_NAME = "SelectScrollDownButton";
19
+ const SelectScrollDownButton = React.forwardRef((props, forwardedRef) => {
20
+ return <SelectScrollButtonImpl
21
+ componentName={SCROLL_DOWN_BUTTON_NAME}
22
+ {...props}
23
+ dir="down"
24
+ ref={forwardedRef}
25
+ />;
26
+ });
27
+ SelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME;
28
+ const SelectScrollButtonImpl = React.memo(
29
+ React.forwardRef(
30
+ (props, forwardedRef) => {
31
+ const { __scopeSelect, dir, componentName, ...scrollIndicatorProps } = props;
32
+ const {
33
+ floatingRef,
34
+ forceUpdate,
35
+ open,
36
+ fallback,
37
+ setScrollTop,
38
+ setInnerOffset,
39
+ ...context
40
+ } = useSelectContext(componentName, __scopeSelect);
41
+ const [element, setElement] = React.useState(null);
42
+ const statusRef = React.useRef("idle");
43
+ const isVisible = context[dir === "down" ? "canScrollDown" : "canScrollUp"];
44
+ const frameRef = React.useRef();
45
+ const { x, y, reference, floating, strategy, update, refs } = useFloating({
46
+ open: open && isVisible,
47
+ strategy: "fixed",
48
+ placement: dir === "up" ? "top" : "bottom",
49
+ middleware: [offset(({ rects }) => -rects.floating.height)],
50
+ whileElementsMounted: (...args) => autoUpdate(...args, { animationFrame: true })
51
+ });
52
+ const composedRef = useComposedRefs(forwardedRef, floating);
53
+ if (floatingRef) {
54
+ if (open) {
55
+ if (element !== floatingRef.current) {
56
+ setElement(floatingRef.current);
57
+ reference(floatingRef.current);
58
+ requestAnimationFrame(update);
59
+ }
60
+ } else {
61
+ cancelAnimationFrame(frameRef.current);
62
+ }
63
+ }
64
+ useIsomorphicLayoutEffect(() => {
65
+ return () => {
66
+ cancelAnimationFrame(frameRef.current);
67
+ };
68
+ }, []);
69
+ if (!(isVisible && floatingRef)) {
70
+ return null;
71
+ }
72
+ const onScroll = (amount) => {
73
+ if (fallback) {
74
+ if (refs.floating.current) {
75
+ refs.floating.current.scrollTop -= amount;
76
+ flushSync(() => setScrollTop(refs.floating.current?.scrollTop ?? 0));
77
+ }
78
+ } else {
79
+ flushSync(() => setInnerOffset((value) => value - amount));
80
+ }
81
+ };
82
+ return <YStack
83
+ ref={composedRef}
84
+ componentName={componentName}
85
+ aria-hidden
86
+ {...scrollIndicatorProps}
87
+ zIndex={1e3}
88
+ position={strategy}
89
+ left={x || 0}
90
+ top={y || 0}
91
+ width={`calc(${(floatingRef?.current?.offsetWidth ?? 0) - 2}px)`}
92
+ onPointerEnter={() => {
93
+ statusRef.current = "active";
94
+ let prevNow = Date.now();
95
+ function frame() {
96
+ if (element) {
97
+ const currentNow = Date.now();
98
+ const msElapsed = currentNow - prevNow;
99
+ prevNow = currentNow;
100
+ const pixelsToScroll = msElapsed / 2;
101
+ const remainingPixels = dir === "up" ? element.scrollTop : element.scrollHeight - element.clientHeight - element.scrollTop;
102
+ const scrollRemaining = dir === "up" ? element.scrollTop - pixelsToScroll > 0 : element.scrollTop + pixelsToScroll < element.scrollHeight - element.clientHeight;
103
+ onScroll(
104
+ dir === "up" ? Math.min(pixelsToScroll, remainingPixels) : Math.max(-pixelsToScroll, -remainingPixels)
105
+ );
106
+ if (scrollRemaining) {
107
+ frameRef.current = requestAnimationFrame(frame);
108
+ }
109
+ }
110
+ }
111
+ cancelAnimationFrame(frameRef.current);
112
+ frameRef.current = requestAnimationFrame(frame);
113
+ }}
114
+ onPointerLeave={() => {
115
+ statusRef.current = "idle";
116
+ cancelAnimationFrame(frameRef.current);
117
+ }}
118
+ />;
119
+ }
120
+ )
121
+ );
122
+ export {
123
+ SelectScrollDownButton,
124
+ SelectScrollUpButton
125
+ };
126
+ //# sourceMappingURL=SelectScrollButton.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/SelectScrollButton.tsx"],
4
+ "sourcesContent": ["import { autoUpdate, offset, useFloating } from '@floating-ui/react-dom-interactions'\nimport { useComposedRefs } from '@tamagui/compose-refs'\nimport { TamaguiElement, useIsomorphicLayoutEffect } from '@tamagui/core'\nimport { YStack } from '@tamagui/stacks'\nimport * as React from 'react'\nimport { flushSync } from 'react-dom'\n\nimport { useSelectContext } from './context'\nimport {\n ScopedProps,\n SelectScrollButtonImplProps,\n SelectScrollButtonProps,\n} from './types'\n\n/* -------------------------------------------------------------------------------------------------\n * SelectScrollUpButton\n * -----------------------------------------------------------------------------------------------*/\n\nconst SCROLL_UP_BUTTON_NAME = 'SelectScrollUpButton'\n\nexport const SelectScrollUpButton = React.forwardRef<\n TamaguiElement,\n SelectScrollButtonProps\n>((props: ScopedProps<SelectScrollButtonProps>, forwardedRef) => {\n return (\n <SelectScrollButtonImpl\n componentName={SCROLL_UP_BUTTON_NAME}\n {...props}\n dir=\"up\"\n ref={forwardedRef}\n />\n )\n})\n\nSelectScrollUpButton.displayName = SCROLL_UP_BUTTON_NAME\n\n/* -------------------------------------------------------------------------------------------------\n * SelectScrollDownButton\n * -----------------------------------------------------------------------------------------------*/\n\nconst SCROLL_DOWN_BUTTON_NAME = 'SelectScrollDownButton'\n\nexport const SelectScrollDownButton = React.forwardRef<\n TamaguiElement,\n SelectScrollButtonProps\n>((props: ScopedProps<SelectScrollButtonProps>, forwardedRef) => {\n return (\n <SelectScrollButtonImpl\n componentName={SCROLL_DOWN_BUTTON_NAME}\n {...props}\n dir=\"down\"\n ref={forwardedRef}\n />\n )\n})\n\nSelectScrollDownButton.displayName = SCROLL_DOWN_BUTTON_NAME\n\ntype SelectScrollButtonImplElement = TamaguiElement\n\nconst SelectScrollButtonImpl = React.memo(\n React.forwardRef<SelectScrollButtonImplElement, SelectScrollButtonImplProps>(\n (props: ScopedProps<SelectScrollButtonImplProps>, forwardedRef) => {\n const { __scopeSelect, dir, componentName, ...scrollIndicatorProps } = props\n const {\n floatingRef,\n forceUpdate,\n open,\n fallback,\n setScrollTop,\n setInnerOffset,\n ...context\n } = useSelectContext(componentName, __scopeSelect)\n\n const [element, setElement] = React.useState<HTMLElement | null>(null)\n const statusRef = React.useRef<'idle' | 'active'>('idle')\n const isVisible = context[dir === 'down' ? 'canScrollDown' : 'canScrollUp']\n const frameRef = React.useRef<any>()\n\n const { x, y, reference, floating, strategy, update, refs } = useFloating({\n open: open && isVisible,\n strategy: 'fixed',\n placement: dir === 'up' ? 'top' : 'bottom',\n middleware: [offset(({ rects }) => -rects.floating.height)],\n whileElementsMounted: (...args) => autoUpdate(...args, { animationFrame: true }),\n })\n\n const composedRef = useComposedRefs(forwardedRef, floating)\n\n if (floatingRef) {\n if (open) {\n if (element !== floatingRef.current) {\n setElement(floatingRef.current)\n reference(floatingRef.current)\n requestAnimationFrame(update)\n }\n } else {\n cancelAnimationFrame(frameRef.current)\n }\n }\n\n useIsomorphicLayoutEffect(() => {\n return () => {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n cancelAnimationFrame(frameRef.current)\n }\n }, [])\n\n if (!(isVisible && floatingRef)) {\n return null\n }\n\n const onScroll = (amount: number) => {\n if (fallback) {\n if (refs.floating.current) {\n refs.floating.current.scrollTop -= amount\n flushSync(() => setScrollTop!(refs.floating.current?.scrollTop ?? 0))\n }\n } else {\n flushSync(() => setInnerOffset!((value) => value - amount))\n }\n }\n\n return (\n <YStack\n ref={composedRef}\n componentName={componentName}\n aria-hidden\n {...scrollIndicatorProps}\n zIndex={1000}\n // @ts-expect-error\n position={strategy}\n left={x || 0}\n top={y || 0}\n width={`calc(${(floatingRef?.current?.offsetWidth ?? 0) - 2}px)`}\n onPointerEnter={() => {\n statusRef.current = 'active'\n let prevNow = Date.now()\n\n function frame() {\n if (element) {\n const currentNow = Date.now()\n const msElapsed = currentNow - prevNow\n prevNow = currentNow\n\n const pixelsToScroll = msElapsed / 2\n\n const remainingPixels =\n dir === 'up'\n ? element.scrollTop\n : element.scrollHeight - element.clientHeight - element.scrollTop\n\n const scrollRemaining =\n dir === 'up'\n ? element.scrollTop - pixelsToScroll > 0\n : element.scrollTop + pixelsToScroll <\n element.scrollHeight - element.clientHeight\n\n onScroll(\n dir === 'up'\n ? Math.min(pixelsToScroll, remainingPixels)\n : Math.max(-pixelsToScroll, -remainingPixels)\n )\n\n if (scrollRemaining) {\n frameRef.current = requestAnimationFrame(frame)\n }\n }\n }\n\n cancelAnimationFrame(frameRef.current)\n frameRef.current = requestAnimationFrame(frame)\n }}\n onPointerLeave={() => {\n statusRef.current = 'idle'\n cancelAnimationFrame(frameRef.current)\n }}\n />\n )\n }\n )\n)\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ const SelectScrollUpButton = (_) => null;
2
+ const SelectScrollDownButton = (_) => null;
3
+ export {
4
+ SelectScrollDownButton,
5
+ SelectScrollUpButton
6
+ };
7
+ //# sourceMappingURL=SelectScrollButton.native.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/SelectScrollButton.native.tsx"],
4
+ "sourcesContent": ["import { ScopedProps, SelectScrollButtonProps } from './types'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport const SelectScrollUpButton = (_: ScopedProps<SelectScrollButtonProps>) => null\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport const SelectScrollDownButton = (_: ScopedProps<SelectScrollButtonProps>) =>\n null\n"],
5
+ "mappings": "AAGO,MAAM,uBAAuB,CAAC,MAA4C;AAG1E,MAAM,yBAAyB,CAAC,MACrC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,83 @@
1
+ import { FloatingFocusManager } from "@floating-ui/react-dom-interactions";
2
+ import { isWeb } from "@tamagui/core";
3
+ import { styled } from "@tamagui/core";
4
+ import { PortalItem } from "@tamagui/portal";
5
+ import { ThemeableStack } from "@tamagui/stacks";
6
+ import * as React from "react";
7
+ import { VIEWPORT_NAME } from "./constants";
8
+ import { ForwardSelectContext, useSelectContext } from "./context";
9
+ import { useSelectBreakpointActive } from "./useSelectBreakpointActive";
10
+ const SelectViewportFrame = styled(ThemeableStack, {
11
+ name: VIEWPORT_NAME,
12
+ backgroundColor: "$background",
13
+ elevate: true,
14
+ bordered: true,
15
+ overflow: "scroll",
16
+ userSelect: "none",
17
+ outlineWidth: 0,
18
+ variants: {
19
+ size: {
20
+ "...size": (val, { tokens }) => {
21
+ return {
22
+ borderRadius: tokens.radius[val] ?? val
23
+ };
24
+ }
25
+ }
26
+ },
27
+ defaultVariants: {
28
+ size: "$2"
29
+ }
30
+ });
31
+ const SelectViewport = React.forwardRef(
32
+ (props, forwardedRef) => {
33
+ const { __scopeSelect, children, disableScroll, ...viewportProps } = props;
34
+ const context = useSelectContext(VIEWPORT_NAME, __scopeSelect);
35
+ const breakpointActive = useSelectBreakpointActive(context.sheetBreakpoint);
36
+ if (breakpointActive || !isWeb) {
37
+ return <PortalItem hostName={`${context.scopeKey}SheetContents`}><ForwardSelectContext context={context}>{children}</ForwardSelectContext></PortalItem>;
38
+ }
39
+ if (!context.floatingContext) {
40
+ return null;
41
+ }
42
+ if (!context.open) {
43
+ return children;
44
+ }
45
+ const {
46
+ style: { scrollbarWidth, listStyleType, overflow, ...restStyle },
47
+ ...floatingProps
48
+ } = context.interactions.getFloatingProps();
49
+ return <>
50
+ {!disableScroll && <style
51
+ dangerouslySetInnerHTML={{
52
+ __html: selectViewportCSS
53
+ }}
54
+ />}
55
+ <FloatingFocusManager context={context.floatingContext}><SelectViewportFrame
56
+ size={context.size}
57
+ role="presentation"
58
+ {...viewportProps}
59
+ ref={forwardedRef}
60
+ {...floatingProps}
61
+ {...restStyle}
62
+ overflow={disableScroll ? void 0 : overflow}
63
+ >{children}</SelectViewportFrame></FloatingFocusManager>
64
+ </>;
65
+ }
66
+ );
67
+ SelectViewport.displayName = VIEWPORT_NAME;
68
+ const selectViewportCSS = `
69
+ .is_SelectViewport {
70
+ scrollbar-width: none;
71
+ -webkit-overflow-scrolling: touch;
72
+ overscroll-behavior: contain;
73
+ }
74
+
75
+ .is_SelectViewport::-webkit-scrollbar{
76
+ display:none
77
+ }
78
+ `;
79
+ export {
80
+ SelectViewport,
81
+ SelectViewportFrame
82
+ };
83
+ //# sourceMappingURL=SelectViewport.mjs.map